diff --git a/game_frontend/src/components/GameView/__snapshots__/index.test.js.snap b/game_frontend/src/components/GameView/__snapshots__/index.test.js.snap
index 5ca89bf74..119536fad 100644
--- a/game_frontend/src/components/GameView/__snapshots__/index.test.js.snap
+++ b/game_frontend/src/components/GameView/__snapshots__/index.test.js.snap
@@ -60,7 +60,7 @@ exports[` shows loading bar whilst game is loading 1`] = `
/>
{
return (
diff --git a/game_frontend/src/components/IDEEditor/__snapshots__/index.test.js.snap b/game_frontend/src/components/IDEEditor/__snapshots__/index.test.js.snap
index 16deb5dc8..ebbb6890a 100644
--- a/game_frontend/src/components/IDEEditor/__snapshots__/index.test.js.snap
+++ b/game_frontend/src/components/IDEEditor/__snapshots__/index.test.js.snap
@@ -47,16 +47,12 @@ exports[` matches snapshot 1`] = `
width="100%"
wrapEnabled={false}
/>
-
-
- Run Code
-
+ isCodeOnServerDifferent={true}
+ whenClicked={[MockFunction]}
+ />
`;
@@ -70,576 +66,3 @@ exports[` renders correctly 1`] = `
className="c0"
/>
`;
-
-exports[` matches snapshot 1`] = `
-.c0 {
- margin-right: 8px;
-}
-
-
-`;
-
-exports[` matches snapshot 1`] = `
-.c0.c0 {
- position: absolute;
- right: 24px;
- bottom: 24px;
- z-index: 5;
-}
-
-
-`;
diff --git a/game_frontend/src/components/IDEEditor/index.js b/game_frontend/src/components/IDEEditor/index.js
index 5785d5b6d..f8fa817b7 100644
--- a/game_frontend/src/components/IDEEditor/index.js
+++ b/game_frontend/src/components/IDEEditor/index.js
@@ -7,15 +7,14 @@ import 'brace/snippets/python'
import 'brace/ext/language_tools'
import PropTypes from 'prop-types'
import { withTheme } from '@material-ui/core/styles'
-import Button from '@material-ui/core/Button'
-import PlayIcon from 'components/icons/Play'
+import RunCodeButton from 'components/RunCodeButton'
export const IDEEditorLayout = styled.div`
position: relative;
grid-area: ide-editor;
`
-export const RunCodeButton = styled(Button)`
+export const PositionedRunCodeButton = styled(RunCodeButton)`
&& {
position: absolute;
right: ${props => props.theme.spacing.unit * 3}px;
@@ -24,11 +23,11 @@ export const RunCodeButton = styled(Button)`
}
`
-export const MarginedPlayIcon = styled(PlayIcon)`
- margin-right: ${props => props.theme.spacing.unit}px;
-`
-
export class IDEEditor extends PureComponent {
+ isCodeOnServerDifferent () {
+ return this.props.code !== this.props.codeOnServer
+ }
+
render () {
return (
@@ -53,14 +52,12 @@ export class IDEEditor extends PureComponent {
tabSize: 2,
fontFamily: this.props.theme.additionalVariables.typography.code.fontFamily
}} />
-
- Run Code
-
+ whenClicked={this.props.postCode} />
)
}
@@ -68,10 +65,12 @@ export class IDEEditor extends PureComponent {
IDEEditor.propTypes = {
code: PropTypes.string,
+ codeOnServer: PropTypes.string,
getCode: PropTypes.func,
editorChanged: PropTypes.func,
theme: PropTypes.object,
- postCode: PropTypes.func
+ postCode: PropTypes.func,
+ runCodeButtonStatus: PropTypes.object
}
export default withTheme()(IDEEditor)
diff --git a/game_frontend/src/components/IDEEditor/index.test.js b/game_frontend/src/components/IDEEditor/index.test.js
index 88483a52b..136e71143 100644
--- a/game_frontend/src/components/IDEEditor/index.test.js
+++ b/game_frontend/src/components/IDEEditor/index.test.js
@@ -1,7 +1,8 @@
/* eslint-env jest */
import React from 'react'
-import { IDEEditor, IDEEditorLayout, MarginedPlayIcon, RunCodeButton } from 'components/IDEEditor'
+import { IDEEditor, IDEEditorLayout } from 'components/IDEEditor'
import createShallowWithTheme from 'testHelpers/createShallow'
+import { Avatar } from '@material-ui/core'
describe('', () => {
it('matches snapshot', () => {
@@ -16,7 +17,7 @@ describe('', () => {
expect(component).toMatchSnapshot()
})
- it('calls the postCode function in props when Post code button is pressed', () => {
+ it('does not call post code as button is intially disabled', () => {
const postCode = jest.fn()
const props = {
postCode
@@ -25,7 +26,7 @@ describe('', () => {
const component = createShallowWithTheme(, 'dark')
component.find('#post-code-button').simulate('click')
- expect(postCode).toBeCalled()
+ expect(postCode).not.toBeCalled()
})
})
@@ -35,19 +36,3 @@ describe('', () => {
expect(tree).toMatchSnapshot()
})
})
-
-describe('', () => {
- it('matches snapshot', () => {
- const component = createShallowWithTheme(, 'dark')
-
- expect(component).toMatchSnapshot()
- })
-})
-
-describe('', () => {
- it('matches snapshot', () => {
- const component = createShallowWithTheme(, 'dark')
-
- expect(component).toMatchSnapshot()
- })
-})
diff --git a/game_frontend/src/components/RunCodeButton/__snapshots__/index.test.js.snap b/game_frontend/src/components/RunCodeButton/__snapshots__/index.test.js.snap
new file mode 100644
index 000000000..212643f06
--- /dev/null
+++ b/game_frontend/src/components/RunCodeButton/__snapshots__/index.test.js.snap
@@ -0,0 +1,892 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[` matches snapshot 1`] = `
+.c0 {
+ margin-right: 8px;
+}
+
+
+`;
+
+exports[` matches snapshot 1`] = `
+.c0 {
+ margin-right: 8px;
+}
+
+
+`;
+
+exports[` matches snapshot 1`] = `
+.c0 {
+ margin-right: 8px;
+}
+
+
+`;
+
+exports[` becomes disabled when code is the same as the server 1`] = `
+
+
+
+`;
+
+exports[` becomes enabled when code is different from the server 1`] = `
+
+
+
+`;
+
+exports[` renders with a done status 1`] = `
+
+
+
+`;
+
+exports[` renders with a normal status 1`] = `
+
+
+
+`;
+
+exports[` renders with a updating status 1`] = `
+
+
+
+`;
+
+exports[` shows an error when a timeout is detected 1`] = `
+
+
+
+`;
diff --git a/game_frontend/src/components/RunCodeButton/index.js b/game_frontend/src/components/RunCodeButton/index.js
new file mode 100644
index 000000000..69d5f442c
--- /dev/null
+++ b/game_frontend/src/components/RunCodeButton/index.js
@@ -0,0 +1,117 @@
+import styled from 'styled-components'
+import React, { Component } from 'react'
+import { connect } from 'react-redux'
+import PropTypes from 'prop-types'
+import Button from '@material-ui/core/Button'
+import PlayIcon from 'components/icons/Play'
+import BugIcon from 'components/icons/Bug'
+import { CircularProgress } from '@material-ui/core'
+import CheckCircle from 'components/icons/CheckCircle'
+
+export const MarginedPlayIcon = styled(PlayIcon)`
+ margin-right: ${props => props.theme.spacing.unit}px;
+`
+
+export const MarginedCircularProgress = styled(CircularProgress)`
+ margin-right: ${props => props.theme.spacing.unit}px;
+`
+
+export const MarginedCheckCircle = styled(CheckCircle)`
+ margin-right: ${props => props.theme.spacing.unit}px;
+`
+
+export const MarginedBugIcon = styled(BugIcon)`
+ margin-right: ${props => props.theme.spacing.unit}px;
+`
+
+export const RunCodeButtonStatus = Object.freeze({
+ normal: 'normal',
+ updating: 'updating',
+ done: 'done'
+})
+
+export class RunCodeButton extends Component {
+ shouldButtonBeDisabled () {
+ if (this.props.timeoutStatus) {
+ return false
+ } else {
+ if (this.props.runCodeButtonStatus.status === RunCodeButtonStatus.done) {
+ return false
+ }
+ return !this.props.isCodeOnServerDifferent ||
+ this.props.runCodeButtonStatus.status === RunCodeButtonStatus.updating
+ }
+ }
+
+ shouldButtonBeClickable () {
+ return (!(this.shouldButtonBeDisabled() && this.props.runCodeButtonStatus === RunCodeButtonStatus.done) ||
+ !this.props.timeoutStatus)
+ }
+
+ renderContent (status) {
+ if (this.props.timeoutStatus) {
+ return (
+ <>
+ Error
+ >
+ )
+ } else {
+ switch (status) {
+ case RunCodeButtonStatus.normal:
+ return (
+ <>
+ Run Code
+ >
+ )
+ case RunCodeButtonStatus.updating:
+ return (
+ <>
+ Updating
+ >
+ )
+ case RunCodeButtonStatus.done:
+ return (
+ <>
+ Done
+ >
+ )
+ }
+ }
+ }
+
+ render () {
+ return (
+
+ )
+ }
+}
+
+RunCodeButton.propTypes = {
+ whenClicked: PropTypes.func,
+ runCodeButtonStatus: PropTypes.shape({
+ status: PropTypes.oneOf([
+ RunCodeButtonStatus.normal,
+ RunCodeButtonStatus.updating,
+ RunCodeButtonStatus.done]
+ )
+ }),
+ isCodeOnServerDifferent: PropTypes.bool,
+ className: PropTypes.string
+}
+
+const mapStateToProps = state => ({
+ timeoutStatus: state.game.timeoutStatus
+})
+
+export default connect(mapStateToProps)(RunCodeButton)
diff --git a/game_frontend/src/components/RunCodeButton/index.test.js b/game_frontend/src/components/RunCodeButton/index.test.js
new file mode 100644
index 000000000..6da1d4863
--- /dev/null
+++ b/game_frontend/src/components/RunCodeButton/index.test.js
@@ -0,0 +1,108 @@
+/* eslint-env jest */
+import React from 'react'
+import RunCodeButton, { MarginedCheckCircle, MarginedCircularProgress, MarginedPlayIcon, RunCodeButtonStatus } from 'components/RunCodeButton'
+import createShallowWithTheme from 'testHelpers/createShallow'
+
+describe('', () => {
+ it('renders with a normal status', () => {
+ const props = {
+ whenClicked: jest.fn(),
+ runCodeButtonStatus: {
+ status: RunCodeButtonStatus.normal
+ }
+ }
+
+ const component = createShallowWithTheme(, 'dark')
+
+ expect(component).toMatchSnapshot()
+ })
+
+ it('renders with a updating status', () => {
+ const props = {
+ whenClicked: jest.fn(),
+ runCodeButtonStatus: {
+ status: RunCodeButtonStatus.updating
+ }
+ }
+
+ const component = createShallowWithTheme(, 'dark')
+
+ expect(component).toMatchSnapshot()
+ })
+
+ it('renders with a done status', () => {
+ const props = {
+ whenClicked: jest.fn(),
+ runCodeButtonStatus: {
+ status: RunCodeButtonStatus.done
+ }
+ }
+
+ const component = createShallowWithTheme(, 'dark')
+
+ expect(component).toMatchSnapshot()
+ })
+
+ it('becomes enabled when code is different from the server', () => {
+ const props = {
+ whenClicked: jest.fn(),
+ runCodeButtonStatus: {
+ status: RunCodeButtonStatus.normal
+ },
+ isCodeOnServerDifferent: true
+ }
+
+ const component = createShallowWithTheme(, 'dark')
+
+ expect(component).toMatchSnapshot()
+ })
+
+ it('becomes disabled when code is the same as the server', () => {
+ const props = {
+ whenClicked: jest.fn(),
+ runCodeButtonStatus: {
+ status: RunCodeButtonStatus.normal
+ },
+ isCodeOnServerDifferent: false
+ }
+
+ const component = createShallowWithTheme(, 'dark')
+
+ expect(component).toMatchSnapshot()
+ })
+
+ it('shows an error when a timeout is detected', () => {
+ const props = {
+ whenClicked: jest.fn(),
+ timeoutStatus: true
+ }
+
+ const component = createShallowWithTheme(, 'dark')
+
+ expect(component).toMatchSnapshot()
+ })
+})
+
+describe('', () => {
+ it('matches snapshot', () => {
+ const component = createShallowWithTheme(, 'dark')
+
+ expect(component).toMatchSnapshot()
+ })
+})
+
+describe('', () => {
+ it('matches snapshot', () => {
+ const component = createShallowWithTheme(, 'dark')
+
+ expect(component).toMatchSnapshot()
+ })
+})
+
+describe('', () => {
+ it('matches snapshot', () => {
+ const component = createShallowWithTheme(, 'dark')
+
+ expect(component).toMatchSnapshot()
+ })
+})
diff --git a/game_frontend/src/containers/IDE/index.js b/game_frontend/src/containers/IDE/index.js
index 428aaec45..c3cd8a7f1 100644
--- a/game_frontend/src/containers/IDE/index.js
+++ b/game_frontend/src/containers/IDE/index.js
@@ -9,23 +9,17 @@ import { MuiThemeProvider } from '@material-ui/core/styles'
import { ThemeProvider as StyledComponentsThemeProvider } from 'styled-components'
export class IDE extends Component {
- static propTypes = {
- code: PropTypes.string,
- postCode: PropTypes.func,
- getCode: PropTypes.func,
- editorChanged: PropTypes.func,
- logs: PropTypes.arrayOf(PropTypes.object)
- }
-
render () {
return (
@@ -35,8 +29,10 @@ export class IDE extends Component {
}
const mapStateToProps = state => ({
- code: state.editor.code,
- logs: state.consoleLog.logs
+ code: state.editor.code.code,
+ codeOnServer: state.editor.code.codeOnServer,
+ logs: state.consoleLog.logs,
+ runCodeButtonStatus: state.editor.runCodeButton
})
const mapDispatchToProps = {
@@ -45,4 +41,13 @@ const mapDispatchToProps = {
postCode: editorActions.postCodeRequest
}
+IDE.propTypes = {
+ code: PropTypes.string,
+ postCode: PropTypes.func,
+ getCode: PropTypes.func,
+ editorChanged: PropTypes.func,
+ logs: PropTypes.arrayOf(PropTypes.object),
+ runCodeButtonStatus: PropTypes.object
+}
+
export default connect(mapStateToProps, mapDispatchToProps)(IDE)
diff --git a/game_frontend/src/index.js b/game_frontend/src/index.js
index 58f0f9799..e08681d6d 100644
--- a/game_frontend/src/index.js
+++ b/game_frontend/src/index.js
@@ -2,15 +2,16 @@ import '@babel/polyfill'
import React from 'react'
import { render } from 'react-dom'
+import WebFont from 'webfontloader'
import { MuiThemeProvider } from '@material-ui/core/styles'
import { ThemeProvider as StyledComponentsThemeProvider } from 'styled-components'
import { darkTheme } from 'theme'
-import { Provider } from 'react-redux'
-import GamePage from './components/GamePage'
+import { Provider } from 'react-redux'
import configureStore from './redux/store'
-import WebFont from 'webfontloader'
+import GamePage from './components/GamePage'
+import { RunCodeButtonStatus } from 'components/RunCodeButton'
WebFont.load({
typekit: {
@@ -20,14 +21,20 @@ WebFont.load({
const initialState = {
editor: {
- code: ''
+ code: {
+ code: ''
+ },
+ runCodeButton: {
+ status: RunCodeButtonStatus.normal
+ }
},
game: {
connectionParameters: {
game_id: getGameIDFromURL() || 1
},
gameDataLoaded: false,
- showSnackbarForAvatarUpdated: false
+ showSnackbarForAvatarUpdated: false,
+ timeoutStatus: false
},
consoleLog: {
logs: []
diff --git a/game_frontend/src/redux/features/Editor/epics.js b/game_frontend/src/redux/features/Editor/epics.js
index 0cf77aaa2..2f990d7a1 100644
--- a/game_frontend/src/redux/features/Editor/epics.js
+++ b/game_frontend/src/redux/features/Editor/epics.js
@@ -27,7 +27,7 @@ const postCodeEpic = (action$, state$, { api }) =>
ofType(types.POST_CODE_REQUEST),
api.post(
`/aimmo/api/code/${state$.value.game.connectionParameters.game_id}/`,
- () => ({ code: state$.value.editor.code })
+ () => ({ code: state$.value.editor.code.code })
),
map(response => actions.postCodeReceived()),
catchError(error => of({
diff --git a/game_frontend/src/redux/features/Editor/epics.test.js b/game_frontend/src/redux/features/Editor/epics.test.js
index 651cc61b5..4acd3ef4e 100644
--- a/game_frontend/src/redux/features/Editor/epics.test.js
+++ b/game_frontend/src/redux/features/Editor/epics.test.js
@@ -80,7 +80,7 @@ describe('postCodeEpic', () => {
}
},
editor: {
- code: code
+ code: { code }
}
}
diff --git a/game_frontend/src/redux/features/Editor/reducers.js b/game_frontend/src/redux/features/Editor/reducers.js
index 1fc28abb0..4ff5e4cfe 100644
--- a/game_frontend/src/redux/features/Editor/reducers.js
+++ b/game_frontend/src/redux/features/Editor/reducers.js
@@ -1,16 +1,54 @@
+import { combineReducers } from 'redux'
import types from './types'
+import { gameTypes } from 'features/Game'
+import { RunCodeButtonStatus } from 'components/RunCodeButton'
-const editorReducer = (state = {}, action) => {
+const codeReducer = (state = {}, action) => {
switch (action.type) {
case types.GET_CODE_SUCCESS:
+ return {
+ ...state,
+ code: action.payload.code,
+ codeOnServer: action.payload.code
+ }
case types.CHANGE_CODE:
return {
...state,
code: action.payload.code
}
+ case types.POST_CODE_SUCCESS:
+ return {
+ ...state,
+ codeOnServer: state.code
+ }
+ default:
+ return state
+ }
+}
+
+const runCodeButtonReducer = (state = {}, action) => {
+ switch (action.type) {
+ case types.POST_CODE_REQUEST:
+ return {
+ ...state,
+ status: RunCodeButtonStatus.updating
+ }
+ case gameTypes.SOCKET_FEEDBACK_AVATAR_UPDATED:
+ return {
+ ...state,
+ status: RunCodeButtonStatus.done
+ }
+ case gameTypes.SNACKBAR_FOR_AVATAR_FEEDBACK_SHOWN:
+ return {
+ ...state,
+ status: RunCodeButtonStatus.normal
+ }
default:
return state
}
}
-export default editorReducer
+export default combineReducers({
+ code: codeReducer,
+ runCodeButton: runCodeButtonReducer
+})
diff --git a/game_frontend/src/redux/features/Editor/reducers.test.js b/game_frontend/src/redux/features/Editor/reducers.test.js
index 5284b8394..339a996e2 100644
--- a/game_frontend/src/redux/features/Editor/reducers.test.js
+++ b/game_frontend/src/redux/features/Editor/reducers.test.js
@@ -1,15 +1,25 @@
/* eslint-env jest */
import editorReducer from './reducers'
import actions from './actions'
+import { actions as gameActions } from 'features/Game'
+import { RunCodeButtonStatus } from 'components/RunCodeButton'
describe('editorReducer', () => {
it('should return the initial state', () => {
- expect(editorReducer(undefined, {})).toEqual({})
+ const initialState = {
+ code: {},
+ runCodeButton: {}
+ }
+ expect(editorReducer(undefined, {})).toEqual(initialState)
})
it('should handle GET_CODE_SUCCESS', () => {
const expectedState = {
- code: 'class Avatar'
+ code: {
+ code: 'class Avatar',
+ codeOnServer: 'class Avatar'
+ },
+ runCodeButton: {}
}
const action = actions.getCodeReceived('class Avatar')
expect(editorReducer({}, action)).toEqual(expectedState)
@@ -17,9 +27,50 @@ describe('editorReducer', () => {
it('should handle CHANGE_CODE', () => {
const expectedState = {
- code: 'class Avatar'
+ code: {
+ code: 'class Avatar'
+ },
+ runCodeButton: {}
}
const action = actions.changeCode('class Avatar')
expect(editorReducer({}, action)).toEqual(expectedState)
})
})
+
+describe('runCodeButtonReducer', () => {
+ it('should set the button status to updating when the code is sent to the server', () => {
+ const expectedState = {
+ code: {},
+ runCodeButton: {
+ status: RunCodeButtonStatus.updating
+ }
+ }
+
+ const action = actions.postCodeRequest()
+ expect(editorReducer({}, action)).toEqual(expectedState)
+ })
+
+ it('should set the button status to done when the avatar is updated', () => {
+ const expectedState = {
+ code: {},
+ runCodeButton: {
+ status: RunCodeButtonStatus.done
+ }
+ }
+
+ const action = gameActions.socketFeedbackAvatarUpdated()
+ expect(editorReducer({}, action)).toEqual(expectedState)
+ })
+
+ it('should set the button status to normal when the snackbar has been shown', () => {
+ const expectedState = {
+ code: {},
+ runCodeButton: {
+ status: RunCodeButtonStatus.normal
+ }
+ }
+
+ const action = gameActions.snackbarForAvatarUpdatedShown()
+ expect(editorReducer({}, action)).toEqual(expectedState)
+ })
+})
diff --git a/game_frontend/src/redux/features/Game/actions.js b/game_frontend/src/redux/features/Game/actions.js
index 221f81bda..8a2e8a9fa 100644
--- a/game_frontend/src/redux/features/Game/actions.js
+++ b/game_frontend/src/redux/features/Game/actions.js
@@ -81,6 +81,10 @@ const gameDataLoaded = () => (
}
)
+const setTimeout = () => ({
+ type: types.SET_TIMEOUT
+})
+
export default {
socketConnectToGameRequest,
sendGameStateFail,
@@ -92,5 +96,6 @@ export default {
unitySendAvatarIDFail,
socketFeedbackAvatarUpdated,
snackbarForAvatarUpdatedShown,
- gameDataLoaded
+ gameDataLoaded,
+ setTimeout
}
diff --git a/game_frontend/src/redux/features/Game/epics.js b/game_frontend/src/redux/features/Game/epics.js
index c11a0c64c..7726f9f23 100644
--- a/game_frontend/src/redux/features/Game/epics.js
+++ b/game_frontend/src/redux/features/Game/epics.js
@@ -1,9 +1,16 @@
import actions from './actions'
import types from './types'
import { of } from 'rxjs'
-import { map, mergeMap, catchError, switchMap, first, mapTo } from 'rxjs/operators'
+import { map, mergeMap, catchError, switchMap, first, mapTo, debounceTime } from 'rxjs/operators'
import { ofType } from 'redux-observable'
+const timeoutEpic = (action$) =>
+ action$.pipe(
+ ofType(types.SOCKET_GAME_STATE_RECEIVED),
+ debounceTime(12000),
+ map(action => actions.setTimeout())
+ )
+
const getConnectionParametersEpic = (action$, state$, { api: { get } }) => action$.pipe(
ofType(types.SOCKET_CONNECT_TO_GAME_REQUEST),
mergeMap(action =>
@@ -62,5 +69,6 @@ export default {
connectToGameEpic,
gameLoadedEpic,
sendGameStateEpic,
- sendAvatarIDEpic
+ sendAvatarIDEpic,
+ timeoutEpic
}
diff --git a/game_frontend/src/redux/features/Game/reducers.js b/game_frontend/src/redux/features/Game/reducers.js
index cc68604bc..b2f4f83ae 100644
--- a/game_frontend/src/redux/features/Game/reducers.js
+++ b/game_frontend/src/redux/features/Game/reducers.js
@@ -2,10 +2,16 @@ import types from './types'
const gameReducer = (state = {}, action) => {
switch (action.type) {
+ case types.SET_TIMEOUT:
+ return {
+ ...state,
+ timeoutStatus: true
+ }
case types.SOCKET_GAME_STATE_RECEIVED:
return {
...state,
- gameState: action.payload.gameState
+ gameState: action.payload.gameState,
+ timeoutStatus: false
}
case types.SOCKET_FEEDBACK_AVATAR_UPDATED:
return {
diff --git a/game_frontend/src/redux/features/Game/reducers.test.js b/game_frontend/src/redux/features/Game/reducers.test.js
index 847aa4e87..23481efc6 100644
--- a/game_frontend/src/redux/features/Game/reducers.test.js
+++ b/game_frontend/src/redux/features/Game/reducers.test.js
@@ -12,7 +12,8 @@ describe('gameReducer', () => {
gameState: {
id: 1
},
- initialState: 'someValue'
+ initialState: 'someValue',
+ timeoutStatus: false
}
const action = actions.socketGameStateReceived({ id: 1 })
expect(gameReducer({ initialState: 'someValue' }, action)).toEqual(expectedState)
diff --git a/game_frontend/src/redux/features/Game/types.js b/game_frontend/src/redux/features/Game/types.js
index ac513f783..2c6059580 100644
--- a/game_frontend/src/redux/features/Game/types.js
+++ b/game_frontend/src/redux/features/Game/types.js
@@ -17,6 +17,8 @@ const SNACKBAR_FOR_AVATAR_FEEDBACK_SHOWN = 'features/Game/SNACKBAR_FOR_AVATAR_FE
const GAME_DATA_LOADED = 'features/Game/GAME_DATA_LOADED'
+const SET_TIMEOUT = 'features/Game/TIMEOUT'
+
export default {
SOCKET_CONNECT_TO_GAME_REQUEST,
SOCKET_CONNECT_TO_GAME_FAIL,
@@ -29,5 +31,6 @@ export default {
UNITY_SEND_AVATAR_ID_FAIL,
SOCKET_FEEDBACK_AVATAR_UPDATED,
SNACKBAR_FOR_AVATAR_FEEDBACK_SHOWN,
- GAME_DATA_LOADED
+ GAME_DATA_LOADED,
+ SET_TIMEOUT
}
diff --git a/version.txt b/version.txt
index 7486fdbc5..8adc70fdd 100644
--- a/version.txt
+++ b/version.txt
@@ -1 +1 @@
-0.7.2
+0.8.0
\ No newline at end of file