Initial commit of 001code-html Scratch frontend project.
Includes scratch-gui, scratch-vm, scratch-blocks, scratch-render, scratch-l10n, and deployment config. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
208
scratch-gui/test/unit/reducers/alerts-reducer.test.js
Normal file
208
scratch-gui/test/unit/reducers/alerts-reducer.test.js
Normal file
@@ -0,0 +1,208 @@
|
||||
// TODO: add tests of extension alerts
|
||||
|
||||
/* eslint-env jest */
|
||||
import {AlertTypes, AlertLevels} from '../../../src/lib/alerts/index.jsx';
|
||||
import alertsReducer, {
|
||||
closeAlert,
|
||||
closeAlertWithId,
|
||||
filterInlineAlerts,
|
||||
filterPopupAlerts,
|
||||
showStandardAlert
|
||||
} from '../../../src/reducers/alerts';
|
||||
|
||||
test('initialState', () => {
|
||||
let defaultState;
|
||||
/* alertsReducer(state, action) */
|
||||
expect(alertsReducer(defaultState, {type: 'anything'})).toBeDefined();
|
||||
expect(alertsReducer(defaultState, {type: 'anything'}).visible).toBe(true);
|
||||
expect(alertsReducer(defaultState, {type: 'anything'}).alertsList).toEqual([]);
|
||||
});
|
||||
|
||||
test('create one standard alert', () => {
|
||||
let defaultState;
|
||||
const action = showStandardAlert('creating');
|
||||
const resultState = alertsReducer(defaultState, action);
|
||||
expect(resultState.alertsList.length).toBe(1);
|
||||
expect(resultState.alertsList[0].alertId).toBe('creating');
|
||||
expect(resultState.alertsList[0].alertType).toBe(AlertTypes.STANDARD);
|
||||
expect(resultState.alertsList[0].level).toBe(AlertLevels.SUCCESS);
|
||||
});
|
||||
|
||||
test('add several standard alerts', () => {
|
||||
const initialState = {
|
||||
visible: true,
|
||||
alertsList: [
|
||||
{
|
||||
alertId: 'saving',
|
||||
alertType: AlertTypes.INLINE,
|
||||
level: AlertLevels.SUCCESS,
|
||||
content: null,
|
||||
iconURL: '/no_image_here.jpg'
|
||||
}
|
||||
]
|
||||
};
|
||||
const action = showStandardAlert('creating');
|
||||
let resultState = alertsReducer(initialState, action);
|
||||
resultState = alertsReducer(resultState, action);
|
||||
resultState = alertsReducer(resultState, action);
|
||||
expect(resultState.alertsList.length).toBe(1);
|
||||
expect(resultState.alertsList[0].alertType).toBe(AlertTypes.STANDARD);
|
||||
expect(resultState.alertsList[0].iconURL).not.toBe('/no_image_here.jpg');
|
||||
expect(resultState.alertsList[0].alertId).toBe('creating');
|
||||
});
|
||||
|
||||
test('create one inline alert message', () => {
|
||||
let defaultState;
|
||||
const action = showStandardAlert('saving');
|
||||
const resultState = alertsReducer(defaultState, action);
|
||||
expect(resultState.alertsList.length).toBe(1);
|
||||
expect(resultState.alertsList[0].alertId).toBe('saving');
|
||||
expect(resultState.alertsList[0].alertType).toBe(AlertTypes.INLINE);
|
||||
expect(resultState.alertsList[0].level).toBe(AlertLevels.INFO);
|
||||
});
|
||||
|
||||
test('can close alerts by index', () => {
|
||||
const initialState = {
|
||||
visible: true,
|
||||
alertsList: [
|
||||
{
|
||||
alertId: 'saving',
|
||||
alertType: AlertTypes.INLINE,
|
||||
level: AlertLevels.SUCCESS,
|
||||
content: null,
|
||||
iconURL: '/no_image_here.jpg'
|
||||
}
|
||||
]
|
||||
};
|
||||
const closeAction = closeAlert(0);
|
||||
let resultState = alertsReducer(initialState, closeAction);
|
||||
expect(resultState.alertsList.length).toBe(0);
|
||||
const createAction = showStandardAlert('creating');
|
||||
resultState = alertsReducer(resultState, createAction);
|
||||
expect(resultState.alertsList.length).toBe(1);
|
||||
resultState = alertsReducer(initialState, closeAction);
|
||||
expect(resultState.alertsList.length).toBe(0);
|
||||
resultState = alertsReducer(resultState, createAction);
|
||||
});
|
||||
|
||||
test('can close a single alert by id', () => {
|
||||
const initialState = {
|
||||
visible: true,
|
||||
alertsList: [
|
||||
{alertId: 'saving'},
|
||||
{alertId: 'creating'},
|
||||
{alertId: 'saving'},
|
||||
{alertId: 'saving'}
|
||||
]
|
||||
};
|
||||
const closeAction = closeAlertWithId('saving');
|
||||
let resultState = alertsReducer(initialState, closeAction);
|
||||
expect(resultState.alertsList.map(a => a.alertId)).toEqual([
|
||||
'creating', 'saving', 'saving'
|
||||
]);
|
||||
resultState = alertsReducer(resultState, closeAction);
|
||||
expect(resultState.alertsList.map(a => a.alertId)).toEqual([
|
||||
'creating', 'saving'
|
||||
]);
|
||||
resultState = alertsReducer(resultState, closeAction);
|
||||
expect(resultState.alertsList.map(a => a.alertId)).toEqual([
|
||||
'creating'
|
||||
]);
|
||||
resultState = alertsReducer(resultState, closeAction);
|
||||
expect(resultState.alertsList.map(a => a.alertId)).toEqual([
|
||||
'creating'
|
||||
]);
|
||||
});
|
||||
|
||||
test('related alerts can clear each other', () => {
|
||||
const initialState = {
|
||||
visible: true,
|
||||
alertsList: [
|
||||
{
|
||||
alertId: 'saving',
|
||||
alertType: AlertTypes.INLINE,
|
||||
level: AlertLevels.SUCCESS,
|
||||
content: null,
|
||||
iconURL: '/no_image_here.jpg'
|
||||
},
|
||||
{
|
||||
alertId: 'creating',
|
||||
alertType: AlertTypes.STANDARD,
|
||||
level: AlertLevels.SUCCESS,
|
||||
content: null,
|
||||
iconURL: '/no_image_here.jpg'
|
||||
}
|
||||
]
|
||||
};
|
||||
const action = showStandardAlert('saveSuccess');
|
||||
const resultState = alertsReducer(initialState, action);
|
||||
expect(resultState.alertsList.length).toBe(2);
|
||||
expect(resultState.alertsList[0].alertId).toBe('creating');
|
||||
expect(resultState.alertsList[1].alertId).toBe('saveSuccess');
|
||||
});
|
||||
|
||||
test('several related alerts can be cleared at once', () => {
|
||||
const initialState = {
|
||||
visible: true,
|
||||
alertsList: []
|
||||
};
|
||||
const createAction = showStandardAlert('creating');
|
||||
let resultState = alertsReducer(initialState, createAction);
|
||||
resultState = alertsReducer(resultState, createAction);
|
||||
resultState = alertsReducer(resultState, createAction);
|
||||
const createSuccessAction = showStandardAlert('createSuccess');
|
||||
resultState = alertsReducer(resultState, createSuccessAction);
|
||||
expect(resultState.alertsList.length).toBe(1);
|
||||
expect(resultState.alertsList[0].alertId).toBe('createSuccess');
|
||||
});
|
||||
|
||||
test('filterInlineAlerts only returns inline type alerts', () => {
|
||||
const alerts = [
|
||||
{
|
||||
alertId: 'extension',
|
||||
alertType: AlertTypes.EXTENSION
|
||||
},
|
||||
{
|
||||
alertId: 'inline',
|
||||
alertType: AlertTypes.INLINE
|
||||
},
|
||||
{
|
||||
alertId: 'standard',
|
||||
alertType: AlertTypes.STANDARD
|
||||
},
|
||||
{
|
||||
alertId: 'non-existent type',
|
||||
alertType: 'wirly-burly'
|
||||
}
|
||||
];
|
||||
|
||||
const filtered = filterInlineAlerts(alerts);
|
||||
expect(filtered.length).toEqual(1);
|
||||
expect(filtered[0].alertId).toEqual('inline');
|
||||
});
|
||||
|
||||
test('filterPopupAlerts returns standard and extension type alerts', () => {
|
||||
const alerts = [
|
||||
{
|
||||
alertId: 'extension',
|
||||
alertType: AlertTypes.EXTENSION
|
||||
},
|
||||
{
|
||||
alertId: 'inline',
|
||||
alertType: AlertTypes.INLINE
|
||||
},
|
||||
{
|
||||
alertId: 'standard',
|
||||
alertType: AlertTypes.STANDARD
|
||||
},
|
||||
{
|
||||
alertId: 'non-existent type',
|
||||
alertType: 'wirly-burly'
|
||||
}
|
||||
];
|
||||
|
||||
const filtered = filterPopupAlerts(alerts);
|
||||
expect(filtered.length).toEqual(2);
|
||||
expect(filtered[0].alertId).toEqual('extension');
|
||||
expect(filtered[1].alertId).toEqual('standard');
|
||||
});
|
||||
53
scratch-gui/test/unit/reducers/mode-reducer.test.js
Normal file
53
scratch-gui/test/unit/reducers/mode-reducer.test.js
Normal file
@@ -0,0 +1,53 @@
|
||||
/* eslint-env jest */
|
||||
import modeReducer from '../../../src/reducers/mode';
|
||||
|
||||
const SET_FULL_SCREEN = 'scratch-gui/mode/SET_FULL_SCREEN';
|
||||
const SET_PLAYER = 'scratch-gui/mode/SET_PLAYER';
|
||||
|
||||
test('initialState', () => {
|
||||
let defaultState;
|
||||
/* modeReducer(state, action) */
|
||||
expect(modeReducer(defaultState, {type: 'anything'})).toBeDefined();
|
||||
});
|
||||
|
||||
test('set full screen mode', () => {
|
||||
const previousState = {
|
||||
showBranding: false,
|
||||
isFullScreen: false,
|
||||
isPlayerOnly: false,
|
||||
hasEverEnteredEditor: true
|
||||
};
|
||||
const action = {
|
||||
type: SET_FULL_SCREEN,
|
||||
isFullScreen: true
|
||||
};
|
||||
const newState = {
|
||||
showBranding: false,
|
||||
isFullScreen: true,
|
||||
isPlayerOnly: false,
|
||||
hasEverEnteredEditor: true
|
||||
};
|
||||
/* modeReducer(state, action) */
|
||||
expect(modeReducer(previousState, action)).toEqual(newState);
|
||||
});
|
||||
|
||||
test('set player mode', () => {
|
||||
const previousState = {
|
||||
showBranding: false,
|
||||
isFullScreen: false,
|
||||
isPlayerOnly: false,
|
||||
hasEverEnteredEditor: true
|
||||
};
|
||||
const action = {
|
||||
type: SET_PLAYER,
|
||||
isPlayerOnly: true
|
||||
};
|
||||
const newState = {
|
||||
showBranding: false,
|
||||
isFullScreen: false,
|
||||
isPlayerOnly: true,
|
||||
hasEverEnteredEditor: true
|
||||
};
|
||||
/* modeReducer(state, action) */
|
||||
expect(modeReducer(previousState, action)).toEqual(newState);
|
||||
});
|
||||
302
scratch-gui/test/unit/reducers/monitor-layout-reducer.test.js
Normal file
302
scratch-gui/test/unit/reducers/monitor-layout-reducer.test.js
Normal file
@@ -0,0 +1,302 @@
|
||||
/* eslint-env jest */
|
||||
import monitorLayoutReducer, {
|
||||
addMonitorRect, moveMonitorRect,
|
||||
resizeMonitorRect, removeMonitorRect,
|
||||
getInitialPosition, PADDING, SCREEN_WIDTH, SCREEN_HEIGHT
|
||||
} from '../../../src/reducers/monitor-layout';
|
||||
|
||||
test('initialState', () => {
|
||||
let defaultState;
|
||||
|
||||
expect(monitorLayoutReducer(defaultState /* state */, {type: 'anything'} /* action */)).toBeDefined();
|
||||
expect(monitorLayoutReducer(defaultState /* state */, {type: 'anything'} /* action */).monitors).toBeDefined();
|
||||
expect(monitorLayoutReducer(defaultState /* state */, {type: 'anything'} /* action */).savedMonitorPositions)
|
||||
.toBeDefined();
|
||||
});
|
||||
|
||||
test('addMonitorRect', () => {
|
||||
let defaultState;
|
||||
const monitorId = 1;
|
||||
const monitorId2 = 2;
|
||||
const upperStart = {x: 100, y: 100};
|
||||
const lowerEnd = {x: 200, y: 200};
|
||||
|
||||
// Add a monitor rect
|
||||
const reduxState = monitorLayoutReducer(defaultState, addMonitorRect(monitorId, upperStart, lowerEnd));
|
||||
expect(reduxState.monitors[monitorId]).toBeDefined();
|
||||
expect(reduxState.monitors[monitorId].upperStart).toEqual(upperStart);
|
||||
expect(reduxState.monitors[monitorId].lowerEnd).toEqual(lowerEnd);
|
||||
// Add monitor rect doesn't save position
|
||||
expect(reduxState.savedMonitorPositions[monitorId]).toBeUndefined();
|
||||
const reduxState2 = monitorLayoutReducer(reduxState, moveMonitorRect(monitorId, 0, 0));
|
||||
|
||||
// Add a second monitor rect
|
||||
const reduxState3 = monitorLayoutReducer(reduxState2, addMonitorRect(monitorId2, upperStart, lowerEnd));
|
||||
expect(reduxState3.monitors[monitorId]).toBeDefined();
|
||||
expect(reduxState3.monitors[monitorId2]).toBeDefined();
|
||||
expect(reduxState3.monitors[monitorId2].upperStart).toEqual(upperStart);
|
||||
expect(reduxState3.monitors[monitorId2].lowerEnd).toEqual(lowerEnd);
|
||||
// Saved positions aren't changed by adding monitor
|
||||
expect(reduxState3.savedMonitorPositions).toEqual(reduxState2.savedMonitorPositions);
|
||||
});
|
||||
|
||||
test('addMonitorRectWithSavedPosition', () => {
|
||||
let defaultState;
|
||||
const monitorId = 1;
|
||||
const upperStart = {x: 100, y: 100};
|
||||
const lowerEnd = {x: 200, y: 200};
|
||||
|
||||
// Add a monitor rect
|
||||
const reduxState = monitorLayoutReducer(defaultState,
|
||||
addMonitorRect(monitorId, upperStart, lowerEnd, true /* savePosition */));
|
||||
expect(reduxState.monitors[monitorId]).toBeDefined();
|
||||
expect(reduxState.monitors[monitorId].upperStart).toEqual(upperStart);
|
||||
expect(reduxState.monitors[monitorId].lowerEnd).toEqual(lowerEnd);
|
||||
// Save position
|
||||
expect(reduxState.savedMonitorPositions[monitorId].x).toEqual(upperStart.x);
|
||||
expect(reduxState.savedMonitorPositions[monitorId].y).toEqual(upperStart.y);
|
||||
});
|
||||
|
||||
test('invalidRect', () => {
|
||||
let defaultState;
|
||||
const reduxState = monitorLayoutReducer(defaultState /* state */, {type: 'initialize'} /* action */);
|
||||
|
||||
// Problem: x end is before x start
|
||||
expect(
|
||||
monitorLayoutReducer(reduxState,
|
||||
addMonitorRect(1, {x: 100, y: 100}, {x: 10, y: 200})))
|
||||
.toEqual(reduxState);
|
||||
|
||||
// Problem: y end is before y start
|
||||
expect(
|
||||
monitorLayoutReducer(reduxState,
|
||||
addMonitorRect(1, {x: 100, y: 100}, {x: 200, y: 10})))
|
||||
.toEqual(reduxState);
|
||||
});
|
||||
|
||||
test('invalidAddMonitorRect', () => {
|
||||
let defaultState;
|
||||
const monitorId = 1;
|
||||
const upperStart = {x: 100, y: 100};
|
||||
const lowerEnd = {x: 200, y: 200};
|
||||
|
||||
// Add a monitor rect
|
||||
const reduxState = monitorLayoutReducer(defaultState, addMonitorRect(monitorId, upperStart, lowerEnd));
|
||||
// Try to add the same one
|
||||
expect(monitorLayoutReducer(reduxState, addMonitorRect(monitorId, upperStart, lowerEnd)))
|
||||
.toEqual(reduxState);
|
||||
});
|
||||
|
||||
test('moveMonitorRect', () => {
|
||||
let defaultState;
|
||||
const monitorId = 1;
|
||||
const monitorId2 = 2;
|
||||
const width = 102;
|
||||
const height = 101;
|
||||
const upperStart = {x: 100, y: 100};
|
||||
const lowerEnd = {x: upperStart.x + width, y: upperStart.y + height};
|
||||
const movedToPosition = {x: 0, y: 0};
|
||||
const movedToPosition2 = {x: 543, y: 2};
|
||||
|
||||
// Add a monitor rect and move it. Expect it to be in monitors state and saved positions.
|
||||
const reduxState = monitorLayoutReducer(defaultState, addMonitorRect(monitorId, upperStart, lowerEnd));
|
||||
const reduxState2 = monitorLayoutReducer(reduxState,
|
||||
moveMonitorRect(monitorId, movedToPosition.x, movedToPosition.y));
|
||||
expect(reduxState2.monitors[monitorId]).toBeDefined();
|
||||
expect(reduxState2.monitors[monitorId].upperStart).toEqual(movedToPosition);
|
||||
expect(reduxState2.monitors[monitorId].lowerEnd.x).toEqual(movedToPosition.x + width);
|
||||
expect(reduxState2.monitors[monitorId].lowerEnd.y).toEqual(movedToPosition.y + height);
|
||||
expect(reduxState2.savedMonitorPositions[monitorId]).toBeDefined();
|
||||
expect(reduxState2.savedMonitorPositions[monitorId].x).toEqual(movedToPosition.x);
|
||||
expect(reduxState2.savedMonitorPositions[monitorId].y).toEqual(movedToPosition.y);
|
||||
|
||||
// Add a second monitor rect and move it. Expect there to now be 2 saved positions.
|
||||
const reduxState3 = monitorLayoutReducer(reduxState2, addMonitorRect(monitorId2, upperStart, lowerEnd));
|
||||
const reduxState4 = monitorLayoutReducer(reduxState3,
|
||||
moveMonitorRect(monitorId2, movedToPosition2.x, movedToPosition2.y));
|
||||
expect(reduxState4.savedMonitorPositions[monitorId]).toEqual(reduxState2.savedMonitorPositions[monitorId]);
|
||||
expect(reduxState4.savedMonitorPositions[monitorId2].x).toEqual(movedToPosition2.x);
|
||||
expect(reduxState4.savedMonitorPositions[monitorId2].y).toEqual(movedToPosition2.y);
|
||||
});
|
||||
|
||||
test('invalidMoveMonitorRect', () => {
|
||||
let defaultState;
|
||||
let reduxState = monitorLayoutReducer(defaultState, {type: 'initialize'} /* action */);
|
||||
const monitorId = 1;
|
||||
|
||||
// Try to move a monitor rect that doesn't exist
|
||||
expect(monitorLayoutReducer(reduxState, moveMonitorRect(monitorId, 1 /* newX */, 1 /* newY */)))
|
||||
.toEqual(reduxState);
|
||||
|
||||
// Add the monitor to move
|
||||
reduxState = monitorLayoutReducer(reduxState, addMonitorRect(monitorId, {x: 100, y: 100}, {x: 200, y: 200}));
|
||||
|
||||
// Invalid newX
|
||||
expect(monitorLayoutReducer(reduxState, moveMonitorRect(monitorId, 'Oregon' /* newX */, 1 /* newY */)))
|
||||
.toEqual(reduxState);
|
||||
|
||||
// Invalid newY
|
||||
expect(monitorLayoutReducer(reduxState, moveMonitorRect(monitorId, 1 /* newX */)))
|
||||
.toEqual(reduxState);
|
||||
});
|
||||
|
||||
test('resizeMonitorRect', () => {
|
||||
let defaultState;
|
||||
const monitorId = 1;
|
||||
const upperStart = {x: 100, y: 100};
|
||||
const newWidth = 10;
|
||||
const newHeight = 20;
|
||||
|
||||
// Add a monitor rect and resize it
|
||||
const reduxState = monitorLayoutReducer(defaultState, addMonitorRect(monitorId, upperStart, {x: 200, y: 200}));
|
||||
const reduxState2 = monitorLayoutReducer(reduxState,
|
||||
resizeMonitorRect(monitorId, newWidth, newHeight));
|
||||
expect(reduxState2.monitors[monitorId]).toBeDefined();
|
||||
expect(reduxState2.monitors[monitorId].upperStart).toEqual(upperStart);
|
||||
expect(reduxState2.monitors[monitorId].lowerEnd.x).toEqual(upperStart.x + newWidth);
|
||||
expect(reduxState2.monitors[monitorId].lowerEnd.y).toEqual(upperStart.y + newHeight);
|
||||
// Saved positions aren't changed by resizing monitor
|
||||
expect(reduxState2.savedMonitorPositions).toEqual(reduxState.savedMonitorPositions);
|
||||
});
|
||||
|
||||
test('invalidResizeMonitorRect', () => {
|
||||
let defaultState;
|
||||
let reduxState = monitorLayoutReducer(defaultState, {type: 'initialize'} /* action */);
|
||||
const monitorId = 1;
|
||||
|
||||
// Try to resize a monitor rect that doesn't exist
|
||||
expect(monitorLayoutReducer(reduxState, resizeMonitorRect(monitorId, 1 /* newWidth */, 1 /* newHeight */)))
|
||||
.toEqual(reduxState);
|
||||
|
||||
// Add the monitor to resize
|
||||
reduxState = monitorLayoutReducer(reduxState, addMonitorRect(monitorId, {x: 100, y: 100}, {x: 200, y: 200}));
|
||||
|
||||
// Invalid newWidth
|
||||
expect(monitorLayoutReducer(reduxState, resizeMonitorRect(monitorId, 'Oregon' /* newWidth */, 1 /* newHeight */)))
|
||||
.toEqual(reduxState);
|
||||
|
||||
// Invalid newHeight
|
||||
expect(monitorLayoutReducer(reduxState, moveMonitorRect(monitorId, 1 /* newWidth */)))
|
||||
.toEqual(reduxState);
|
||||
|
||||
// newWidth < 0
|
||||
expect(monitorLayoutReducer(reduxState, resizeMonitorRect(monitorId, -1 /* newWidth */, 1 /* newHeight */)))
|
||||
.toEqual(reduxState);
|
||||
|
||||
// newHeight < 0
|
||||
expect(monitorLayoutReducer(reduxState, resizeMonitorRect(monitorId, 1 /* newWidth */, -1 /* newHeight */)))
|
||||
.toEqual(reduxState);
|
||||
});
|
||||
|
||||
test('removeMonitorRect', () => {
|
||||
let defaultState;
|
||||
const monitorId = 1;
|
||||
|
||||
// Add a monitor rect, move it, and remove it
|
||||
const reduxState = monitorLayoutReducer(defaultState, addMonitorRect(monitorId,
|
||||
{x: 100, y: 100},
|
||||
{x: 200, y: 200}
|
||||
));
|
||||
const reduxState2 = monitorLayoutReducer(reduxState, moveMonitorRect(monitorId, 0, 0));
|
||||
const reduxState3 = monitorLayoutReducer(reduxState2, removeMonitorRect(monitorId));
|
||||
expect(reduxState3.monitors[monitorId]).toBeUndefined();
|
||||
// Check that saved positions aren't changed by removing monitor
|
||||
expect(reduxState3.savedMonitorPositions).toEqual(reduxState2.savedMonitorPositions);
|
||||
});
|
||||
|
||||
test('invalidRemoveMonitorRect', () => {
|
||||
let defaultState;
|
||||
const reduxState = monitorLayoutReducer(defaultState, {type: 'initialize'} /* action */);
|
||||
|
||||
// Try to remove a monitor rect that doesn't exist
|
||||
expect(monitorLayoutReducer(reduxState, resizeMonitorRect(1)))
|
||||
.toEqual(reduxState);
|
||||
});
|
||||
|
||||
test('getInitialPosition_lineUpTopLeft', () => {
|
||||
let defaultState;
|
||||
const width = 100;
|
||||
const height = 200;
|
||||
// Add monitors to right and bottom, but there is a space in the top left
|
||||
let reduxState = monitorLayoutReducer(defaultState, addMonitorRect(1,
|
||||
{x: width + PADDING, y: 0},
|
||||
{x: 100, y: height}
|
||||
));
|
||||
reduxState = monitorLayoutReducer(defaultState, addMonitorRect(2,
|
||||
{x: 0, y: height + PADDING},
|
||||
{x: width, y: 100}
|
||||
));
|
||||
|
||||
// Check that the added monitor appears in the space
|
||||
const rect = getInitialPosition(reduxState, 3, width, height);
|
||||
expect(rect.upperStart).toBeDefined();
|
||||
expect(rect.lowerEnd).toBeDefined();
|
||||
expect(rect.lowerEnd.x - rect.upperStart.x).toEqual(width);
|
||||
expect(rect.lowerEnd.y - rect.upperStart.y).toEqual(height);
|
||||
expect(rect.upperStart.x).toEqual(PADDING);
|
||||
expect(rect.upperStart.y).toEqual(PADDING);
|
||||
});
|
||||
|
||||
test('getInitialPosition_savedPosition', () => {
|
||||
const monitorId = 1;
|
||||
const savedX = 100;
|
||||
const savedY = 200;
|
||||
const width = 7;
|
||||
const height = 8;
|
||||
const reduxState = {
|
||||
monitors: {},
|
||||
savedMonitorPositions: {[monitorId]: {x: savedX, y: savedY}}
|
||||
};
|
||||
|
||||
// Check that initial position uses saved state
|
||||
const rect = getInitialPosition(reduxState, monitorId, width, height);
|
||||
expect(rect.upperStart).toBeDefined();
|
||||
expect(rect.lowerEnd).toBeDefined();
|
||||
expect(rect.lowerEnd.x - rect.upperStart.x).toEqual(width);
|
||||
expect(rect.lowerEnd.y - rect.upperStart.y).toEqual(height);
|
||||
expect(rect.upperStart.x).toEqual(savedX);
|
||||
expect(rect.upperStart.y).toEqual(savedY);
|
||||
});
|
||||
|
||||
test('getInitialPosition_lineUpLeft', () => {
|
||||
let defaultState;
|
||||
const monitor1EndY = 60;
|
||||
// Add a monitor that takes up the upper left corner
|
||||
const reduxState = monitorLayoutReducer(defaultState, addMonitorRect(1, {x: 0, y: 0}, {x: 100, y: monitor1EndY}));
|
||||
|
||||
// Check that added monitor is under it and lines up left
|
||||
const rect = getInitialPosition(reduxState, 2, 20 /* width */, 20 /* height */);
|
||||
expect(rect.upperStart.y >= monitor1EndY + PADDING).toBeTruthy();
|
||||
});
|
||||
|
||||
test('getInitialPosition_lineUpTop', () => {
|
||||
let defaultState;
|
||||
const monitor1EndX = 100;
|
||||
// Add a monitor that takes up the whole left side
|
||||
const reduxState = monitorLayoutReducer(defaultState, addMonitorRect(1,
|
||||
{x: 0, y: 0},
|
||||
{x: monitor1EndX, y: SCREEN_HEIGHT}
|
||||
));
|
||||
|
||||
// Check that added monitor is to the right of it and lines up top
|
||||
const rect = getInitialPosition(reduxState, 2, 20 /* width */, 20 /* height */);
|
||||
expect(rect.upperStart.y).toEqual(PADDING);
|
||||
expect(rect.upperStart.x >= monitor1EndX + PADDING).toBeTruthy();
|
||||
});
|
||||
|
||||
test('getInitialPosition_noRoom', () => {
|
||||
let defaultState;
|
||||
const width = 7;
|
||||
const height = 8;
|
||||
// Add a monitor that takes up the whole screen
|
||||
const reduxState = monitorLayoutReducer(defaultState, addMonitorRect(1,
|
||||
{x: 0, y: 0},
|
||||
{x: SCREEN_WIDTH, y: SCREEN_HEIGHT}
|
||||
));
|
||||
|
||||
// Check that added monitor exists somewhere (we don't care where)
|
||||
const rect = getInitialPosition(reduxState, 2, width, height);
|
||||
expect(rect.upperStart).toBeDefined();
|
||||
expect(rect.lowerEnd.x - rect.upperStart.x).toEqual(width);
|
||||
expect(rect.lowerEnd.y - rect.upperStart.y).toEqual(height);
|
||||
});
|
||||
508
scratch-gui/test/unit/reducers/project-state-reducer.test.js
Normal file
508
scratch-gui/test/unit/reducers/project-state-reducer.test.js
Normal file
@@ -0,0 +1,508 @@
|
||||
/* eslint-env jest */
|
||||
import projectStateReducer, {
|
||||
LoadingState,
|
||||
autoUpdateProject,
|
||||
doneCreatingProject,
|
||||
doneUpdatingProject,
|
||||
manualUpdateProject,
|
||||
onFetchedProjectData,
|
||||
onLoadedProject,
|
||||
projectError,
|
||||
remixProject,
|
||||
requestNewProject,
|
||||
requestProjectUpload,
|
||||
saveProjectAsCopy,
|
||||
setProjectId
|
||||
} from '../../../src/reducers/project-state';
|
||||
|
||||
test('initialState', () => {
|
||||
let defaultState;
|
||||
/* projectStateReducer(state, action) */
|
||||
expect(projectStateReducer(defaultState, {type: 'anything'})).toBeDefined();
|
||||
expect(projectStateReducer(defaultState, {type: 'anything'}).error).toBe(null);
|
||||
expect(projectStateReducer(defaultState, {type: 'anything'}).projectData).toBe(null);
|
||||
expect(projectStateReducer(defaultState, {type: 'anything'}).projectId).toBe(null);
|
||||
expect(projectStateReducer(defaultState, {type: 'anything'}).loadingState).toBe(LoadingState.NOT_LOADED);
|
||||
});
|
||||
|
||||
test('doneCreatingProject for new project with projectId type string shows project with that id', () => {
|
||||
const initialState = {
|
||||
projectId: null,
|
||||
loadingState: LoadingState.CREATING_NEW
|
||||
};
|
||||
const action = doneCreatingProject('100', initialState.loadingState);
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.SHOWING_WITH_ID);
|
||||
expect(resultState.projectId).toBe('100');
|
||||
});
|
||||
|
||||
test('doneCreatingProject for new project with projectId type number shows project with id of type number', () => {
|
||||
const initialState = {
|
||||
projectId: null,
|
||||
loadingState: LoadingState.CREATING_NEW
|
||||
};
|
||||
const action = doneCreatingProject(100, initialState.loadingState);
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.SHOWING_WITH_ID);
|
||||
expect(resultState.projectId).toBe(100);
|
||||
});
|
||||
|
||||
test('doneCreatingProject for remix shows project with that id', () => {
|
||||
const initialState = {
|
||||
projectId: null,
|
||||
loadingState: LoadingState.REMIXING
|
||||
};
|
||||
const action = doneCreatingProject('100', initialState.loadingState);
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.SHOWING_WITH_ID);
|
||||
expect(resultState.projectId).toBe('100');
|
||||
});
|
||||
|
||||
test('doneCreatingProject for save as copy shows project with that id', () => {
|
||||
const initialState = {
|
||||
projectId: null,
|
||||
loadingState: LoadingState.CREATING_COPY
|
||||
};
|
||||
const action = doneCreatingProject('100', initialState.loadingState);
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.SHOWING_WITH_ID);
|
||||
expect(resultState.projectId).toBe('100');
|
||||
});
|
||||
|
||||
test('onFetchedProjectData with id loads project data into vm', () => {
|
||||
const initialState = {
|
||||
projectData: null,
|
||||
loadingState: LoadingState.FETCHING_WITH_ID
|
||||
};
|
||||
const action = onFetchedProjectData('1010101', initialState.loadingState);
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.LOADING_VM_WITH_ID);
|
||||
expect(resultState.projectData).toBe('1010101');
|
||||
});
|
||||
|
||||
test('onFetchedProjectData new loads project data into vm', () => {
|
||||
const initialState = {
|
||||
projectData: null,
|
||||
loadingState: LoadingState.FETCHING_NEW_DEFAULT
|
||||
};
|
||||
const action = onFetchedProjectData('1010101', initialState.loadingState);
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.LOADING_VM_NEW_DEFAULT);
|
||||
expect(resultState.projectData).toBe('1010101');
|
||||
});
|
||||
|
||||
// onLoadedProject: LOADING_VM_WITH_ID
|
||||
|
||||
test('onLoadedProject(LOADING_VM_WITH_ID, true, true) results in state SHOWING_WITH_ID', () => {
|
||||
const initialState = {
|
||||
projectId: '100',
|
||||
loadingState: LoadingState.LOADING_VM_WITH_ID
|
||||
};
|
||||
const action = onLoadedProject(initialState.loadingState, true, true);
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.SHOWING_WITH_ID);
|
||||
expect(resultState.projectId).toBe('100');
|
||||
});
|
||||
|
||||
test('onLoadedProject(LOADING_VM_WITH_ID, false, true) results in state SHOWING_WITH_ID', () => {
|
||||
const initialState = {
|
||||
projectId: '100',
|
||||
loadingState: LoadingState.LOADING_VM_WITH_ID
|
||||
};
|
||||
const action = onLoadedProject(initialState.loadingState, false, true);
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.SHOWING_WITH_ID);
|
||||
expect(resultState.projectId).toBe('100');
|
||||
});
|
||||
|
||||
// case where we started out viewing a project with a projectId, then
|
||||
// started to load another project; but loading fails. We go back to
|
||||
// showing the original project.
|
||||
test('onLoadedProject(LOADING_VM_WITH_ID, false, false), with project id, ' +
|
||||
'results in state SHOWING_WITH_ID', () => {
|
||||
const initialState = {
|
||||
projectId: '100',
|
||||
loadingState: LoadingState.LOADING_VM_WITH_ID
|
||||
};
|
||||
const action = onLoadedProject(initialState.loadingState, false, false);
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.SHOWING_WITH_ID);
|
||||
expect(resultState.projectId).toBe('100');
|
||||
});
|
||||
|
||||
// case where we started out viewing a project with default projectId, then
|
||||
// started to load one with an id, such as in standalone mode when user adds
|
||||
// '#PROJECT_ID_NUMBER' to the URI; but loading fails. We go back to
|
||||
// showing the original project.
|
||||
test('onLoadedProject(LOADING_VM_WITH_ID, false, false), with no project id, ' +
|
||||
'results in state SHOWING_WITHOUT_ID', () => {
|
||||
const initialState = {
|
||||
projectId: '0',
|
||||
loadingState: LoadingState.LOADING_VM_WITH_ID
|
||||
};
|
||||
const action = onLoadedProject(initialState.loadingState, false, false);
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.SHOWING_WITHOUT_ID);
|
||||
expect(resultState.projectId).toBe('0');
|
||||
});
|
||||
|
||||
// onLoadedProject: LOADING_VM_FILE_UPLOAD
|
||||
|
||||
test('onLoadedProject(LOADING_VM_FILE_UPLOAD, true, true) prepares to save', () => {
|
||||
const initialState = {
|
||||
projectId: '100',
|
||||
loadingState: LoadingState.LOADING_VM_FILE_UPLOAD
|
||||
};
|
||||
const action = onLoadedProject(initialState.loadingState, true, true);
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.AUTO_UPDATING);
|
||||
expect(resultState.projectId).toBe('100');
|
||||
});
|
||||
|
||||
test('onLoadedProject(LOADING_VM_FILE_UPLOAD, false, true) results in state SHOWING_WITHOUT_ID', () => {
|
||||
const initialState = {
|
||||
projectId: '0',
|
||||
loadingState: LoadingState.LOADING_VM_FILE_UPLOAD
|
||||
};
|
||||
const action = onLoadedProject(initialState.loadingState, false, true);
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.SHOWING_WITHOUT_ID);
|
||||
expect(resultState.projectId).toBe('0');
|
||||
});
|
||||
|
||||
test('onLoadedProject(LOADING_VM_FILE_UPLOAD, false, false), when we know project id, ' +
|
||||
'results in state SHOWING_WITH_ID', () => {
|
||||
const initialState = {
|
||||
projectId: '100',
|
||||
loadingState: LoadingState.LOADING_VM_FILE_UPLOAD
|
||||
};
|
||||
const action = onLoadedProject(initialState.loadingState, false, false);
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.SHOWING_WITH_ID);
|
||||
expect(resultState.projectId).toBe('100');
|
||||
});
|
||||
|
||||
test('onLoadedProject(LOADING_VM_FILE_UPLOAD, false, false), when we ' +
|
||||
'don\'t know project id, results in state SHOWING_WITHOUT_ID', () => {
|
||||
const initialState = {
|
||||
projectId: '0',
|
||||
loadingState: LoadingState.LOADING_VM_FILE_UPLOAD
|
||||
};
|
||||
const action = onLoadedProject(initialState.loadingState, false, false);
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.SHOWING_WITHOUT_ID);
|
||||
expect(resultState.projectId).toBe('0');
|
||||
});
|
||||
|
||||
// onLoadedProject: LOADING_VM_NEW_DEFAULT
|
||||
|
||||
test('onLoadedProject(LOADING_VM_NEW_DEFAULT, true, true) results in state SHOWING_WITHOUT_ID', () => {
|
||||
const initialState = {
|
||||
projectId: '0',
|
||||
loadingState: LoadingState.LOADING_VM_NEW_DEFAULT
|
||||
};
|
||||
const action = onLoadedProject(initialState.loadingState, true, true);
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.SHOWING_WITHOUT_ID);
|
||||
expect(resultState.projectId).toBe('0');
|
||||
});
|
||||
|
||||
test('onLoadedProject(LOADING_VM_NEW_DEFAULT, false, true) results in state SHOWING_WITHOUT_ID', () => {
|
||||
const initialState = {
|
||||
projectId: '0',
|
||||
loadingState: LoadingState.LOADING_VM_NEW_DEFAULT
|
||||
};
|
||||
const action = onLoadedProject(initialState.loadingState, false, true);
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.SHOWING_WITHOUT_ID);
|
||||
expect(resultState.projectId).toBe('0');
|
||||
});
|
||||
|
||||
test('onLoadedProject(LOADING_VM_NEW_DEFAULT, false, false) results in ERROR state', () => {
|
||||
const initialState = {
|
||||
projectId: '0',
|
||||
loadingState: LoadingState.LOADING_VM_NEW_DEFAULT
|
||||
};
|
||||
const action = onLoadedProject(initialState.loadingState, false, false);
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.ERROR);
|
||||
expect(resultState.projectId).toBe('0');
|
||||
});
|
||||
|
||||
// doneUpdatingProject
|
||||
|
||||
test('doneUpdatingProject with id results in state SHOWING_WITH_ID', () => {
|
||||
const initialState = {
|
||||
projectId: '100',
|
||||
loadingState: LoadingState.MANUAL_UPDATING
|
||||
};
|
||||
const action = doneUpdatingProject(initialState.loadingState);
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.SHOWING_WITH_ID);
|
||||
expect(resultState.projectId).toBe('100');
|
||||
});
|
||||
|
||||
test('doneUpdatingProject with id, before copy occurs, results in state CREATING_COPY', () => {
|
||||
const initialState = {
|
||||
projectId: '100',
|
||||
loadingState: LoadingState.UPDATING_BEFORE_COPY
|
||||
};
|
||||
const action = doneUpdatingProject(initialState.loadingState);
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.CREATING_COPY);
|
||||
expect(resultState.projectId).toBe('100');
|
||||
});
|
||||
|
||||
test('doneUpdatingProject with id, before new, results in state FETCHING_NEW_DEFAULT', () => {
|
||||
const initialState = {
|
||||
projectId: '100',
|
||||
loadingState: LoadingState.UPDATING_BEFORE_NEW
|
||||
};
|
||||
const action = doneUpdatingProject(initialState.loadingState);
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.FETCHING_NEW_DEFAULT);
|
||||
expect(resultState.projectId).toBe('0'); // resets id
|
||||
});
|
||||
|
||||
test('calling setProjectId, using with same id as already showing, ' +
|
||||
'results in state SHOWING_WITH_ID', () => {
|
||||
const initialState = {
|
||||
projectId: '100',
|
||||
loadingState: LoadingState.SHOWING_WITH_ID
|
||||
};
|
||||
const action = setProjectId('100');
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.SHOWING_WITH_ID);
|
||||
expect(resultState.projectId).toBe('100');
|
||||
});
|
||||
|
||||
test('calling setProjectId, using different id from project already showing, ' +
|
||||
'results in state FETCHING_WITH_ID', () => {
|
||||
const initialState = {
|
||||
projectId: 99,
|
||||
loadingState: LoadingState.SHOWING_WITH_ID
|
||||
};
|
||||
const action = setProjectId('100');
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.FETCHING_WITH_ID);
|
||||
expect(resultState.projectId).toBe('100');
|
||||
});
|
||||
|
||||
test('setProjectId, with same id as before, but not same type, ' +
|
||||
'results in FETCHING_WITH_ID because the two projectIds are not strictly equal', () => {
|
||||
const initialState = {
|
||||
projectId: '100',
|
||||
loadingState: LoadingState.SHOWING_WITH_ID
|
||||
};
|
||||
const action = setProjectId(100);
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.FETCHING_WITH_ID);
|
||||
expect(resultState.projectId).toBe(100);
|
||||
});
|
||||
|
||||
test('requestNewProject, when can\'t create/save, results in FETCHING_NEW_DEFAULT', () => {
|
||||
const initialState = {
|
||||
projectId: '0',
|
||||
loadingState: LoadingState.SHOWING_WITHOUT_ID
|
||||
};
|
||||
const action = requestNewProject(false);
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.FETCHING_NEW_DEFAULT);
|
||||
expect(resultState.projectId).toBe('0');
|
||||
});
|
||||
|
||||
test('requestNewProject, when can create/save, results in UPDATING_BEFORE_NEW ' +
|
||||
'(in order to save before fetching default project)', () => {
|
||||
const initialState = {
|
||||
projectId: '100',
|
||||
loadingState: LoadingState.SHOWING_WITH_ID
|
||||
};
|
||||
const action = requestNewProject(true);
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.UPDATING_BEFORE_NEW);
|
||||
expect(resultState.projectId).toBe('100');
|
||||
});
|
||||
|
||||
test('requestProjectUpload when project not loaded results in state LOADING_VM_FILE_UPLOAD', () => {
|
||||
const initialState = {
|
||||
projectId: null,
|
||||
loadingState: LoadingState.NOT_LOADED
|
||||
};
|
||||
const action = requestProjectUpload(initialState.loadingState);
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.LOADING_VM_FILE_UPLOAD);
|
||||
expect(resultState.projectId).toBe(null);
|
||||
});
|
||||
|
||||
test('requestProjectUpload when showing project with id results in state LOADING_VM_FILE_UPLOAD', () => {
|
||||
const initialState = {
|
||||
projectId: '100',
|
||||
loadingState: LoadingState.SHOWING_WITH_ID
|
||||
};
|
||||
const action = requestProjectUpload(initialState.loadingState);
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.LOADING_VM_FILE_UPLOAD);
|
||||
expect(resultState.projectId).toBe('100');
|
||||
});
|
||||
|
||||
test('requestProjectUpload when showing project without id results in state LOADING_VM_FILE_UPLOAD', () => {
|
||||
const initialState = {
|
||||
projectId: null,
|
||||
loadingState: LoadingState.SHOWING_WITHOUT_ID
|
||||
};
|
||||
const action = requestProjectUpload(initialState.loadingState);
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.LOADING_VM_FILE_UPLOAD);
|
||||
expect(resultState.projectId).toBe(null);
|
||||
});
|
||||
|
||||
test('manualUpdateProject should prepare to update', () => {
|
||||
const initialState = {
|
||||
projectId: '100',
|
||||
loadingState: LoadingState.SHOWING_WITH_ID
|
||||
};
|
||||
const action = manualUpdateProject();
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.MANUAL_UPDATING);
|
||||
expect(resultState.projectId).toBe('100');
|
||||
});
|
||||
|
||||
test('autoUpdateProject should prepare to update', () => {
|
||||
const initialState = {
|
||||
projectId: '100',
|
||||
loadingState: LoadingState.SHOWING_WITH_ID
|
||||
};
|
||||
const action = autoUpdateProject();
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.AUTO_UPDATING);
|
||||
expect(resultState.projectId).toBe('100');
|
||||
});
|
||||
|
||||
test('saveProjectAsCopy should save, before preparing to save as a copy', () => {
|
||||
const initialState = {
|
||||
projectId: '100',
|
||||
loadingState: LoadingState.SHOWING_WITH_ID
|
||||
};
|
||||
const action = saveProjectAsCopy();
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.UPDATING_BEFORE_COPY);
|
||||
expect(resultState.projectId).toBe('100');
|
||||
});
|
||||
|
||||
test('remixProject should prepare to remix', () => {
|
||||
const initialState = {
|
||||
projectId: '100',
|
||||
loadingState: LoadingState.SHOWING_WITH_ID
|
||||
};
|
||||
const action = remixProject();
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.REMIXING);
|
||||
expect(resultState.projectId).toBe('100');
|
||||
});
|
||||
|
||||
test('projectError from various states should show error', () => {
|
||||
const startStates = [
|
||||
LoadingState.AUTO_UPDATING,
|
||||
LoadingState.CREATING_NEW,
|
||||
LoadingState.FETCHING_NEW_DEFAULT,
|
||||
LoadingState.FETCHING_WITH_ID,
|
||||
LoadingState.LOADING_VM_NEW_DEFAULT,
|
||||
LoadingState.LOADING_VM_WITH_ID,
|
||||
LoadingState.MANUAL_UPDATING,
|
||||
LoadingState.REMIXING,
|
||||
LoadingState.CREATING_COPY,
|
||||
LoadingState.UPDATING_BEFORE_NEW
|
||||
];
|
||||
for (const startState of startStates) {
|
||||
const initialState = {
|
||||
error: null,
|
||||
projectId: '100',
|
||||
loadingState: startState
|
||||
};
|
||||
const action = projectError('Error string');
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.error).toEqual('Error string');
|
||||
expect(resultState.projectId).toBe('100');
|
||||
}
|
||||
});
|
||||
|
||||
test('fatal projectError should show error state', () => {
|
||||
const startStates = [
|
||||
LoadingState.FETCHING_NEW_DEFAULT,
|
||||
LoadingState.FETCHING_WITH_ID,
|
||||
LoadingState.LOADING_VM_NEW_DEFAULT,
|
||||
LoadingState.LOADING_VM_WITH_ID
|
||||
];
|
||||
for (const startState of startStates) {
|
||||
const initialState = {
|
||||
error: null,
|
||||
projectId: '100',
|
||||
loadingState: startState
|
||||
};
|
||||
const action = projectError('Error string');
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.ERROR);
|
||||
expect(resultState.projectId).toBe('100');
|
||||
}
|
||||
});
|
||||
|
||||
test('non-fatal projectError should show normal state', () => {
|
||||
const startStates = [
|
||||
LoadingState.AUTO_UPDATING,
|
||||
LoadingState.CREATING_COPY,
|
||||
LoadingState.MANUAL_UPDATING,
|
||||
LoadingState.REMIXING,
|
||||
LoadingState.UPDATING_BEFORE_NEW
|
||||
];
|
||||
for (const startState of startStates) {
|
||||
const initialState = {
|
||||
error: null,
|
||||
projectId: '100',
|
||||
loadingState: startState
|
||||
};
|
||||
const action = projectError('Error string');
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.SHOWING_WITH_ID);
|
||||
expect(resultState.projectId).toBe('100');
|
||||
}
|
||||
});
|
||||
|
||||
test('projectError when creating new while viewing project with id should ' +
|
||||
'go back to state SHOWING_WITH_ID', () => {
|
||||
const initialState = {
|
||||
error: null,
|
||||
loadingState: LoadingState.CREATING_NEW,
|
||||
projectId: '12345'
|
||||
};
|
||||
const action = projectError('Error string');
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.SHOWING_WITH_ID);
|
||||
expect(resultState.projectId).toBe('12345');
|
||||
});
|
||||
|
||||
test('projectError when creating new while logged out, looking at default project ' +
|
||||
'should go back to state SHOWING_WITHOUT_ID', () => {
|
||||
const initialState = {
|
||||
error: null,
|
||||
loadingState: LoadingState.CREATING_NEW,
|
||||
projectId: '0'
|
||||
};
|
||||
const action = projectError('Error string');
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.SHOWING_WITHOUT_ID);
|
||||
expect(resultState.projectId).toBe('0');
|
||||
});
|
||||
|
||||
test('projectError encountered while in state FETCHING_WITH_ID results in ' +
|
||||
'ERROR state', () => {
|
||||
const initialState = {
|
||||
error: null,
|
||||
projectId: null,
|
||||
loadingState: LoadingState.FETCHING_WITH_ID
|
||||
};
|
||||
const action = projectError('Error string');
|
||||
const resultState = projectStateReducer(initialState, action);
|
||||
expect(resultState.loadingState).toBe(LoadingState.ERROR);
|
||||
expect(resultState.projectId).toBe(null);
|
||||
expect(resultState.error).toEqual('Error string');
|
||||
});
|
||||
@@ -0,0 +1,25 @@
|
||||
/* eslint-env jest */
|
||||
import workspaceMetricsReducer, {updateMetrics} from '../../../src/reducers/workspace-metrics';
|
||||
|
||||
test('initialState', () => {
|
||||
let defaultState;
|
||||
/* workspaceMetricsReducer(state, action) */
|
||||
expect(workspaceMetricsReducer(defaultState, {type: 'anything'})).toBeDefined();
|
||||
expect(workspaceMetricsReducer(defaultState, {type: 'anything'})).toEqual({targets: {}});
|
||||
});
|
||||
|
||||
test('updateMetrics action creator', () => {
|
||||
let defaultState;
|
||||
const action = updateMetrics({
|
||||
targetID: 'abcde',
|
||||
scrollX: 225,
|
||||
scrollY: 315,
|
||||
scale: 1.25
|
||||
});
|
||||
const resultState = workspaceMetricsReducer(defaultState, action);
|
||||
expect(Object.keys(resultState.targets).length).toBe(1);
|
||||
expect(resultState.targets.abcde).toBeDefined();
|
||||
expect(resultState.targets.abcde.scrollX).toBe(225);
|
||||
expect(resultState.targets.abcde.scrollY).toBe(315);
|
||||
expect(resultState.targets.abcde.scale).toBe(1.25);
|
||||
});
|
||||
Reference in New Issue
Block a user