Skip to content
Snippets Groups Projects
Commit f659dfbc authored by Paul Kaplan's avatar Paul Kaplan
Browse files

Move the started flag to the vmStatus reducer

parent 59df9b6c
No related branches found
No related tags found
No related merge requests found
...@@ -20,7 +20,7 @@ class Controls extends React.Component { ...@@ -20,7 +20,7 @@ class Controls extends React.Component {
if (e.shiftKey) { if (e.shiftKey) {
this.props.vm.setTurboMode(!this.props.turbo); this.props.vm.setTurboMode(!this.props.turbo);
} else { } else {
if (!this.props.vm.started) { if (!this.props.isStarted) {
this.props.vm.start(); this.props.vm.start();
} }
this.props.vm.greenFlag(); this.props.vm.greenFlag();
...@@ -41,6 +41,7 @@ class Controls extends React.Component { ...@@ -41,6 +41,7 @@ class Controls extends React.Component {
render () { render () {
const { const {
vm, // eslint-disable-line no-unused-vars vm, // eslint-disable-line no-unused-vars
isStarted, // eslint-disable-line no-unused-vars
projectRunning, projectRunning,
turbo, turbo,
...props ...props
...@@ -58,12 +59,14 @@ class Controls extends React.Component { ...@@ -58,12 +59,14 @@ class Controls extends React.Component {
} }
Controls.propTypes = { Controls.propTypes = {
isStarted: PropTypes.bool.isRequired,
projectRunning: PropTypes.bool.isRequired, projectRunning: PropTypes.bool.isRequired,
turbo: PropTypes.bool.isRequired, turbo: PropTypes.bool.isRequired,
vm: PropTypes.instanceOf(VM) vm: PropTypes.instanceOf(VM)
}; };
const mapStateToProps = state => ({ const mapStateToProps = state => ({
isStarted: state.scratchGui.vmStatus.running,
projectRunning: state.scratchGui.vmStatus.running, projectRunning: state.scratchGui.vmStatus.running,
turbo: state.scratchGui.vmStatus.turbo turbo: state.scratchGui.vmStatus.turbo
}); });
......
...@@ -8,7 +8,7 @@ import {connect} from 'react-redux'; ...@@ -8,7 +8,7 @@ import {connect} from 'react-redux';
import {updateTargets} from '../reducers/targets'; import {updateTargets} from '../reducers/targets';
import {updateBlockDrag} from '../reducers/block-drag'; import {updateBlockDrag} from '../reducers/block-drag';
import {updateMonitors} from '../reducers/monitors'; import {updateMonitors} from '../reducers/monitors';
import {setRunningState, setTurboState} from '../reducers/vm-status'; import {setRunningState, setTurboState, setStartedState} from '../reducers/vm-status';
import {showExtensionAlert} from '../reducers/alerts'; import {showExtensionAlert} from '../reducers/alerts';
import {updateMicIndicator} from '../reducers/mic-indicator'; import {updateMicIndicator} from '../reducers/mic-indicator';
...@@ -39,6 +39,7 @@ const vmListenerHOC = function (WrappedComponent) { ...@@ -39,6 +39,7 @@ const vmListenerHOC = function (WrappedComponent) {
this.props.vm.on('TURBO_MODE_OFF', this.props.onTurboModeOff); this.props.vm.on('TURBO_MODE_OFF', this.props.onTurboModeOff);
this.props.vm.on('PROJECT_RUN_START', this.props.onProjectRunStart); this.props.vm.on('PROJECT_RUN_START', this.props.onProjectRunStart);
this.props.vm.on('PROJECT_RUN_STOP', this.props.onProjectRunStop); this.props.vm.on('PROJECT_RUN_STOP', this.props.onProjectRunStop);
this.props.vm.on('RUNTIME_STARTED', this.props.onRuntimeStarted);
this.props.vm.on('PERIPHERAL_DISCONNECT_ERROR', this.props.onShowExtensionAlert); this.props.vm.on('PERIPHERAL_DISCONNECT_ERROR', this.props.onShowExtensionAlert);
this.props.vm.on('MIC_LISTENING', this.props.onMicListeningUpdate); this.props.vm.on('MIC_LISTENING', this.props.onMicListeningUpdate);
...@@ -110,6 +111,7 @@ const vmListenerHOC = function (WrappedComponent) { ...@@ -110,6 +111,7 @@ const vmListenerHOC = function (WrappedComponent) {
onTargetsUpdate, onTargetsUpdate,
onProjectRunStart, onProjectRunStart,
onProjectRunStop, onProjectRunStop,
onRuntimeStarted,
onTurboModeOff, onTurboModeOff,
onTurboModeOn, onTurboModeOn,
onShowExtensionAlert, onShowExtensionAlert,
...@@ -128,6 +130,7 @@ const vmListenerHOC = function (WrappedComponent) { ...@@ -128,6 +130,7 @@ const vmListenerHOC = function (WrappedComponent) {
onMonitorsUpdate: PropTypes.func.isRequired, onMonitorsUpdate: PropTypes.func.isRequired,
onProjectRunStart: PropTypes.func.isRequired, onProjectRunStart: PropTypes.func.isRequired,
onProjectRunStop: PropTypes.func.isRequired, onProjectRunStop: PropTypes.func.isRequired,
onRuntimeStarted: PropTypes.func.isRequired,
onShowExtensionAlert: PropTypes.func.isRequired, onShowExtensionAlert: PropTypes.func.isRequired,
onTargetsUpdate: PropTypes.func.isRequired, onTargetsUpdate: PropTypes.func.isRequired,
onTurboModeOff: PropTypes.func.isRequired, onTurboModeOff: PropTypes.func.isRequired,
...@@ -158,6 +161,7 @@ const vmListenerHOC = function (WrappedComponent) { ...@@ -158,6 +161,7 @@ const vmListenerHOC = function (WrappedComponent) {
}, },
onProjectRunStart: () => dispatch(setRunningState(true)), onProjectRunStart: () => dispatch(setRunningState(true)),
onProjectRunStop: () => dispatch(setRunningState(false)), onProjectRunStop: () => dispatch(setRunningState(false)),
onRuntimeStarted: () => dispatch(setStartedState(true)),
onTurboModeOn: () => dispatch(setTurboState(true)), onTurboModeOn: () => dispatch(setTurboState(true)),
onTurboModeOff: () => dispatch(setTurboState(false)), onTurboModeOff: () => dispatch(setTurboState(false)),
onShowExtensionAlert: data => { onShowExtensionAlert: data => {
......
...@@ -33,9 +33,8 @@ const vmManagerHOC = function (WrappedComponent) { ...@@ -33,9 +33,8 @@ const vmManagerHOC = function (WrappedComponent) {
this.props.vm.setCompatibilityMode(true); this.props.vm.setCompatibilityMode(true);
this.props.vm.initialized = true; this.props.vm.initialized = true;
} }
if (!this.props.isPlayerOnly && !this.props.vm.started) { if (!this.props.isPlayerOnly && !this.props.isStarted) {
this.props.vm.start(); this.props.vm.start();
this.props.vm.started = true;
} }
} }
componentDidUpdate (prevProps) { componentDidUpdate (prevProps) {
...@@ -46,9 +45,8 @@ const vmManagerHOC = function (WrappedComponent) { ...@@ -46,9 +45,8 @@ const vmManagerHOC = function (WrappedComponent) {
this.loadProject(); this.loadProject();
} }
// Start the VM if entering editor mode with an unstarted vm // Start the VM if entering editor mode with an unstarted vm
if (!this.props.isPlayerOnly && !this.props.vm.started) { if (!this.props.isPlayerOnly && !this.props.isStarted) {
this.props.vm.start(); this.props.vm.start();
this.props.vm.started = true;
} }
} }
loadProject () { loadProject () {
...@@ -65,6 +63,7 @@ const vmManagerHOC = function (WrappedComponent) { ...@@ -65,6 +63,7 @@ const vmManagerHOC = function (WrappedComponent) {
/* eslint-disable no-unused-vars */ /* eslint-disable no-unused-vars */
fontsLoaded, fontsLoaded,
loadingState, loadingState,
isStarted,
onError: onErrorProp, onError: onErrorProp,
onLoadedProject: onLoadedProjectProp, onLoadedProject: onLoadedProjectProp,
projectData, projectData,
...@@ -105,7 +104,8 @@ const vmManagerHOC = function (WrappedComponent) { ...@@ -105,7 +104,8 @@ const vmManagerHOC = function (WrappedComponent) {
projectData: state.scratchGui.projectState.projectData, projectData: state.scratchGui.projectState.projectData,
projectId: state.scratchGui.projectState.projectId, projectId: state.scratchGui.projectState.projectId,
loadingState: loadingState, loadingState: loadingState,
isPlayerOnly: state.scratchGui.mode.isPlayerOnly isPlayerOnly: state.scratchGui.mode.isPlayerOnly,
isStarted: state.scratchGui.vmStatus.started
}; };
}; };
......
const SET_RUNNING_STATE = 'scratch-gui/vm-status/SET_RUNNING_STATE'; const SET_RUNNING_STATE = 'scratch-gui/vm-status/SET_RUNNING_STATE';
const SET_TURBO_STATE = 'scratch-gui/vm-status/SET_TURBO_STATE'; const SET_TURBO_STATE = 'scratch-gui/vm-status/SET_TURBO_STATE';
const SET_STARTED_STATE = 'scratch-gui/vm-status/SET_STARTED_STATE';
const initialState = { const initialState = {
running: false, running: false,
started: false,
turbo: false turbo: false
}; };
const reducer = function (state, action) { const reducer = function (state, action) {
if (typeof state === 'undefined') state = initialState; if (typeof state === 'undefined') state = initialState;
switch (action.type) { switch (action.type) {
case SET_STARTED_STATE:
return Object.assign({}, state, {
started: action.started
});
case SET_RUNNING_STATE: case SET_RUNNING_STATE:
return Object.assign({}, state, { return Object.assign({}, state, {
running: action.running running: action.running
...@@ -22,6 +28,14 @@ const reducer = function (state, action) { ...@@ -22,6 +28,14 @@ const reducer = function (state, action) {
} }
}; };
const setStartedState = function (started) {
return {
type: SET_STARTED_STATE,
started: started
};
};
const setRunningState = function (running) { const setRunningState = function (running) {
return { return {
type: SET_RUNNING_STATE, type: SET_RUNNING_STATE,
...@@ -40,5 +54,6 @@ export { ...@@ -40,5 +54,6 @@ export {
reducer as default, reducer as default,
initialState as vmStatusInitialState, initialState as vmStatusInitialState,
setRunningState, setRunningState,
setStartedState,
setTurboState setTurboState
}; };
...@@ -17,7 +17,8 @@ describe('VMManagerHOC', () => { ...@@ -17,7 +17,8 @@ describe('VMManagerHOC', () => {
store = mockStore({ store = mockStore({
scratchGui: { scratchGui: {
projectState: {}, projectState: {},
mode: {} // Mocked by using override props in tests when needed mode: {},
vmStatus: {}
} }
}); });
vm = new VM(); vm = new VM();
...@@ -31,6 +32,7 @@ describe('VMManagerHOC', () => { ...@@ -31,6 +32,7 @@ describe('VMManagerHOC', () => {
mount( mount(
<WrappedComponent <WrappedComponent
isPlayerOnly isPlayerOnly
isStarted={false}
store={store} store={store}
vm={vm} vm={vm}
/> />
...@@ -40,8 +42,7 @@ describe('VMManagerHOC', () => { ...@@ -40,8 +42,7 @@ describe('VMManagerHOC', () => {
expect(vm.initialized).toBe(true); expect(vm.initialized).toBe(true);
// But vm should not be started automatically // But vm should not be started automatically
expect(vm.start.mock.calls.length).toBe(0); expect(vm.start).not.toHaveBeenCalled();
expect(vm.started).not.toBe(true);
}); });
test('when it mounts in editor mode, the vm is initialized and started', () => { test('when it mounts in editor mode, the vm is initialized and started', () => {
const Component = () => (<div />); const Component = () => (<div />);
...@@ -49,6 +50,7 @@ describe('VMManagerHOC', () => { ...@@ -49,6 +50,7 @@ describe('VMManagerHOC', () => {
mount( mount(
<WrappedComponent <WrappedComponent
isPlayerOnly={false} isPlayerOnly={false}
isStarted={false}
store={store} store={store}
vm={vm} vm={vm}
/> />
...@@ -57,17 +59,16 @@ describe('VMManagerHOC', () => { ...@@ -57,17 +59,16 @@ describe('VMManagerHOC', () => {
expect(vm.setCompatibilityMode.mock.calls.length).toBe(1); expect(vm.setCompatibilityMode.mock.calls.length).toBe(1);
expect(vm.initialized).toBe(true); expect(vm.initialized).toBe(true);
expect(vm.start.mock.calls.length).toBe(1); expect(vm.start).toHaveBeenCalled();
expect(vm.started).toBe(true);
}); });
test('if it mounts with an initialized vm, it does not reinitialize the vm but will start it', () => { test('if it mounts with an initialized vm, it does not reinitialize the vm but will start it', () => {
const Component = () => <div />; const Component = () => <div />;
const WrappedComponent = vmManagerHOC(Component); const WrappedComponent = vmManagerHOC(Component);
vm.initialized = true; vm.initialized = true;
vm.started = false;
mount( mount(
<WrappedComponent <WrappedComponent
isPlayerOnly={false} isPlayerOnly={false}
isStarted={false}
store={store} store={store}
vm={vm} vm={vm}
/> />
...@@ -76,28 +77,44 @@ describe('VMManagerHOC', () => { ...@@ -76,28 +77,44 @@ describe('VMManagerHOC', () => {
expect(vm.setCompatibilityMode.mock.calls.length).toBe(0); expect(vm.setCompatibilityMode.mock.calls.length).toBe(0);
expect(vm.initialized).toBe(true); expect(vm.initialized).toBe(true);
expect(vm.start.mock.calls.length).toBe(1); expect(vm.start).toHaveBeenCalled();
expect(vm.started).toBe(true);
}); });
test('if it mounts without starting the VM, it can be started by switching to editor mode', () => { test('if it mounts without starting the VM, it can be started by switching to editor mode', () => {
const Component = () => <div />; const Component = () => <div />;
const WrappedComponent = vmManagerHOC(Component); const WrappedComponent = vmManagerHOC(Component);
vm.initialized = true; vm.initialized = true;
vm.started = false;
const mounted = mount( const mounted = mount(
<WrappedComponent <WrappedComponent
isPlayerOnly isPlayerOnly
isStarted={false}
store={store} store={store}
vm={vm} vm={vm}
/> />
); );
expect(vm.start.mock.calls.length).toBe(0); expect(vm.start).not.toHaveBeenCalled();
mounted.setProps({ mounted.setProps({
isPlayerOnly: false isPlayerOnly: false
}); });
expect(vm.start.mock.calls.length).toBe(1); expect(vm.start).toHaveBeenCalled();
expect(vm.started).toBe(true); });
test('if it mounts with an initialized and started VM, it does not start again', () => {
const Component = () => <div />;
const WrappedComponent = vmManagerHOC(Component);
vm.initialized = true;
const mounted = mount(
<WrappedComponent
isPlayerOnly
isStarted
store={store}
vm={vm}
/>
);
expect(vm.start).not.toHaveBeenCalled();
mounted.setProps({
isPlayerOnly: false
});
expect(vm.start).not.toHaveBeenCalled();
}); });
test('if the isLoadingWithId prop becomes true, it loads project data into the vm', () => { test('if the isLoadingWithId prop becomes true, it loads project data into the vm', () => {
vm.loadProject = jest.fn(() => Promise.resolve()); vm.loadProject = jest.fn(() => Promise.resolve());
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment