completion

This commit is contained in:
2025-08-06 13:49:11 +08:00
commit c2d7317897
684 changed files with 92987 additions and 0 deletions

View File

@@ -0,0 +1,438 @@
/* global describe: true, test:true, expect:true */
import { frames as framesReducer, initialState } from '~/reducers/frames';
import Factory from 'helper/factories/api';
import {
GET_FRAMES,
GET_FRAMES_SUCCESS,
GET_FRAMES_ERROR,
LOGOUT_SUCCESS,
GET_FRAME_STATE_SUCCESS,
GET_FRAME_STATE_ERROR,
SET_CURRENT_FRAME_PLAYLIST,
GET_FRAMES_STATUS_SUCCESS,
SET_FRAME_POWER_STATE_SUCCESS,
SET_CURRENT_FRAME,
UPDATE_FRAME_PLAYLIST_ASSIGNMENT,
GET_FRAME_STATE,
UNPAIR_FRAME,
UNPAIR_FRAME_SUCCESS,
UNPAIR_FRAME_ERROR,
} from '~/store/actionTypes';
import { FRAME_ORIENTATION, FRAME_POWER } from '~/store/frameConstants';
describe('frames reducer', () => {
test('CASE 1: should return initial state', () => {
expect(framesReducer(undefined, { type: 'Default' }))
.toEqual(initialState);
});
test('CASE 2: should return state with meta set to loading when type is GET_FRAMES', () => {
const frames = [{ id: 1 }, { id: 2 }];
const expectedState = { ...initialState, meta: { ...initialState.meta, loading: true } };
const stateResult = framesReducer(initialState, {
type: GET_FRAMES, payload: { frames },
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 3a: should return with removed frame with existing frameState when type is GET_FRAMES_SUCCESS', () => {
const frames = [{
id: 1,
}];
const currentState = {
framePreventPlaylistAssignChange: {},
frames: ['1ea790afd4c67c77', 'U6XYMRIEWBJ82RLL'].map((f, i) => (
{ id: i, ...Factory.build('FrameState', { frameId: f }) })),
};
const meta = { loading: false, error: '' };
const specs = { 'W08A-01': { colors: [], photo: {} } };
const stateResult = framesReducer(currentState, {
type: GET_FRAMES_SUCCESS, payload: { frames, specs },
});
expect(stateResult.frames[0]).toHaveProperty('meta', meta);
expect(stateResult.frames[0]).toHaveProperty('orientation');
expect(stateResult.frames[0]).toHaveProperty('power');
expect(stateResult.frames).toHaveLength(frames.length);
});
test('CASE 3b: should return with added frame with existing frameState and needUpdate as true when type is GET_FRAMES_SUCCESS', () => {
const frames = [
{ id: 1, softwareVersion: '5.0.0' },
{ id: 2 },
{ id: 3 },
];
const currentState = {
framePreventPlaylistAssignChange: {},
frames: ['1ea790afd4c67c77', 'U6XYMRIEWBJ82RLL'].map((f, i) => (
{ id: i, softwareVersion: '5.0.0', ...Factory.build('FrameState', { frameId: f }) })),
};
const meta = { loading: false, error: '' };
const specs = { 'W08A-01': { colors: [], photo: {}, minVersionSupported: '6.0.0' } };
const stateResult = framesReducer(currentState, {
type: GET_FRAMES_SUCCESS, payload: { frames, specs },
});
expect(stateResult.frames[0]).toHaveProperty('meta', meta);
expect(stateResult.frames[0]).toHaveProperty('orientation');
expect(stateResult.frames[0]).toHaveProperty('power');
expect(stateResult.frames[0]).toHaveProperty('needUpdate', true);
expect(stateResult.frames).toHaveLength(frames.length);
});
test('CASE 3c: should return with added frame with existing frameState and needUpdate set to false when type is GET_FRAMES_SUCCESS and checkEnabled is false', () => {
const frames = [
{ id: 1, softwareVersion: '5.0.0' },
{ id: 2 },
{ id: 3 },
];
const currentState = {
framePreventPlaylistAssignChange: {},
frames: ['1ea790afd4c67c77', 'U6XYMRIEWBJ82RLL'].map((f, i) => (
{ id: i, softwareVersion: '5.0.0', ...Factory.build('FrameState', { frameId: f }) })),
};
const meta = { loading: false, error: '' };
const specs = { 'W08A-01': { colors: [], photo: {}, minVersionSupported: '6.0.0' } };
const stateResult = framesReducer(currentState, {
type: GET_FRAMES_SUCCESS, payload: { frames, specs, checkEnabled: false },
});
expect(stateResult.frames[0]).toHaveProperty('meta', meta);
expect(stateResult.frames[0]).toHaveProperty('orientation');
expect(stateResult.frames[0]).toHaveProperty('power');
expect(stateResult.frames[0]).toHaveProperty('needUpdate', false);
expect(stateResult.frames).toHaveLength(frames.length);
});
test('CASE 5: should return state with error and loading = `false` when type is GET_FRAMES_ERROR', () => {
const error = new Error('getFramesError');
const expectedState = {
...initialState,
meta:
{ ...initialState.meta, error, loading: false },
};
const stateResult = framesReducer(initialState, {
type: GET_FRAMES_ERROR, payload: { error },
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 6: should empty the state on LOGOUT_SUCCESS', () => {
const existingState = [{ id: 1 }, { id: 2 }];
expect(framesReducer(existingState, { type: LOGOUT_SUCCESS }))
.toEqual(initialState);
});
test('CASE 7a: should return state with frameState on GET_FRAME_STATE_SUCCESS', () => {
const playlistId = 321;
const existingState = { framePreventPlaylistPlayingChange: {}, framePreventPowerChange: {}, frames: [{ id: 1, frameId: '1ea790afd4c67c77', playlists: [{ id: playlistId }] }, { id: 2 }] };
const expectedState = {
framePreventPlaylistPlayingChange: {},
framePreventPowerChange: {},
frames: [
{
id: 1,
frameId: '1ea790afd4c67c77',
orientation: FRAME_ORIENTATION.LANDSCAPE,
slideshow: playlistId,
playlists: [{ id: playlistId }],
power: 'on',
},
{ id: 2 },
],
meta: { stateLoading: false, error: '' },
};
const frameState = Factory.build('FrameState', { frameId: existingState.frames[0].frameId, slideshow: { value: playlistId } });
expect(framesReducer(existingState, { type: GET_FRAME_STATE_SUCCESS, payload: { frameState } }))
.toEqual(expectedState);
});
test('CASE 7b: should return state with slideshow=`-1` on GET_FRAME_STATE_SUCCESS when playlist is no longer assigned', () => {
const playlistId = 321;
const existingState = { framePreventPlaylistPlayingChange: {}, framePreventPowerChange: {}, frames: [{ id: 1, frameId: '1ea790afd4c67c77', playlists: [] }, { id: 2 }] };
const expectedState = {
framePreventPlaylistPlayingChange: {},
framePreventPowerChange: {},
frames: [
{
id: 1,
frameId: '1ea790afd4c67c77',
orientation: FRAME_ORIENTATION.LANDSCAPE,
slideshow: -1,
playlists: [],
power: 'on',
},
{ id: 2 },
],
meta: { stateLoading: false, error: '' },
};
const frameState = Factory.build('FrameState', { frameId: existingState.frames[0].frameId, slideshow: { value: playlistId } });
expect(framesReducer(existingState, { type: GET_FRAME_STATE_SUCCESS, payload: { frameState } }))
.toEqual(expectedState);
});
test('CASE 7c: should return state with slideshow=`-1` on GET_FRAME_STATE_SUCCESS when frameState.slideshow is `null`', () => {
const playlistId = 'null';
const existingState = { framePreventPlaylistPlayingChange: {}, framePreventPowerChange: {}, frames: [{ id: 1, frameId: '1ea790afd4c67c77', playlists: [] }, { id: 2 }] };
const expectedState = {
framePreventPlaylistPlayingChange: {},
framePreventPowerChange: {},
frames: [
{
id: 1,
frameId: '1ea790afd4c67c77',
orientation: FRAME_ORIENTATION.LANDSCAPE,
slideshow: -1,
playlists: [],
power: 'on',
},
{ id: 2 },
],
meta: { stateLoading: false, error: '' },
};
const frameState = Factory.build('FrameState', { frameId: existingState.frames[0].frameId, slideshow: { value: playlistId } });
expect(framesReducer(existingState, { type: GET_FRAME_STATE_SUCCESS, payload: { frameState } }))
.toEqual(expectedState);
});
test('CASE 8: should return state with corrent frame playlist on SET_CURRENT_FRAME_PLAYLIST', () => {
const existingState = {
frames: [
{
id: 1,
frameId: '1ea790afd4c67c77',
orientation: FRAME_ORIENTATION.LANDSCAPE,
slideshow: 123,
power: 'on',
},
{ id: 2 },
],
};
const payload = {
framePk: 1,
playlistId: 234,
};
expect(framesReducer(existingState, { type: SET_CURRENT_FRAME_PLAYLIST, payload }).frames[0])
.toHaveProperty('slideshow', 234);
});
test('CASE 9: should return state with correct frameState on GET_FRAMES_STATUS_SUCCESS', () => {
const framesStatus = {
frames: [
{ lastSeen: null, lastConnected: null, framePk: 17544 },
{ lastSeen: 1535338881548, lastConnected: 1535338819374, framePk: 18122 },
{
connected: true, lastSeen: 1539065938946, lastConnected: 1539065965182, framePk: 18429,
},
{
connected: true, lastSeen: 1539066031822, lastConnected: 1539066063638, framePk: 18438,
},
],
};
const currentState = {
frames: [17544, 18122, 18429, 18438, 18433].map((f) => (
{ id: f, ...Factory.build('FrameState') })),
};
const payload = { framesStatus };
const newState = framesReducer(currentState, { type: GET_FRAMES_STATUS_SUCCESS, payload });
expect(newState.frames)
.toEqual(expect.arrayContaining(framesStatus.frames.map(() =>
expect.objectContaining({ online: expect.any(Boolean) }))));
});
test('CASE 10: should return state with frameState on SET_FRAME_POWER_STATE_SUCCESS', () => {
const emptyObject = {};
const currentState = {
framePreventPowerChange: { 1: true },
};
const payload = { framePk: 1, powerState: FRAME_POWER.OFF };
const newState = framesReducer(currentState, { type: SET_FRAME_POWER_STATE_SUCCESS, payload });
expect(newState)
.toHaveProperty('framePreventPowerChange', emptyObject);
});
test('CASE 11: should return currentFrameId set to the payload.id when action is SET_CURRENT_FRAME', () => {
const currentState = {
frames: [
{ id: 1 },
{ id: 2 },
],
currentFrameId: 2,
};
const payload = { id: 1 };
const newState = framesReducer(currentState, { type: SET_CURRENT_FRAME, payload });
expect(newState)
.toHaveProperty('currentFrameId', 1);
});
test('CASE 12: should return state with loading = `false` on GET_FRAME_STATE_ERROR', () => {
const currentState = {
framePreventPlaylistAssignChange: {},
framePreventPlaylistPlayingChange: {},
framePreventPowerChange: {},
frames: [],
currentFrameId: 0,
meta: {
loading: true,
stateLoading: false,
statusLoading: false,
error: '',
},
};
const newState = framesReducer(initialState, { type: GET_FRAME_STATE_ERROR });
expect(newState)
.toEqual(currentState);
});
test('CASE 13a: should return state with updated playlists when operation = `add` on UPDATE_FRAME_PLAYLIST_ASSIGNMENT', () => {
const frameIds = [17544, 18122, 18429, 18438, 18433];
const currentState = {
frames: frameIds.map((f) => (
Factory.build('Frame', { id: f })
)),
currentFrameId: 0,
meta: { loading: false, error: '' },
};
const playlistIds = [103];
const payload = { frameIds, playlistIds, operation: 'add' };
const newState = framesReducer(
currentState,
{ type: UPDATE_FRAME_PLAYLIST_ASSIGNMENT, payload },
);
expect(newState.frames)
.toEqual(expect.arrayContaining([
expect.objectContaining({
playlists: [
{ id: expect.any(Number) },
{ id: expect.any(Number) },
{ id: expect.any(Number) },
],
})]));
});
test('CASE 13b: should return state with removed playlists when operation = `remove` on UPDATE_FRAME_PLAYLIST_ASSIGNMENT', () => {
const frameIds = [17544, 18122, 18429, 18438, 18433];
const currentState = {
frames: frameIds.map((f) => (
Factory.build('Frame', { id: f })
)),
currentFrameId: 0,
meta: { loading: false, error: '' },
};
const playlistIds = [currentState.frames[0].playlists[0].id];
const payload = { frameIds, playlistIds, operation: 'remove' };
const newState = framesReducer(
currentState,
{ type: UPDATE_FRAME_PLAYLIST_ASSIGNMENT, payload },
);
expect(newState.frames)
.toEqual(expect.arrayContaining([
expect.objectContaining({
playlists: [
{ id: expect.any(Number) },
],
})]));
});
test('CASE 13c: should return state with new playlists when operation is not specified on UPDATE_FRAME_PLAYLIST_ASSIGNMENT', () => {
const frameIds = [17544, 18122, 18429, 18438, 18433];
const currentState = {
frames: frameIds.map((f) => (
Factory.build('Frame', { id: f })
)),
currentFrameId: 0,
meta: { loading: false, error: '' },
};
const playlistIds = [111];
const payload = { frameIds, playlistIds };
const newState = framesReducer(
currentState,
{ type: UPDATE_FRAME_PLAYLIST_ASSIGNMENT, payload },
);
expect(newState.frames)
.toEqual(expect.arrayContaining([
expect.objectContaining({
playlists: [
{ id: playlistIds[0] },
],
})]));
});
test('CASE 14: should return state loading = `false` when action is GET_FRAME_STATE', () => {
const frameIds = [17544, 18122, 18429, 18438, 18433];
const currentState = {
frames: frameIds.map((f) => (
Factory.build('Frame', { id: f })
)),
currentFrameId: 0,
meta: { error: '' },
};
const newState = framesReducer(
currentState,
{ type: GET_FRAME_STATE },
);
expect(newState.meta)
.toEqual({ stateLoading: true, error: '' });
});
test('CASE 15: should return state loading = `true` when action is UNPAIR_FRAME', () => {
const frameIds = [17544, 18122, 18429, 18438, 18433];
const currentState = {
frames: frameIds.map((f) => (
Factory.build('Frame', { id: f })
)),
currentFrameId: 0,
meta: { error: '' },
};
const newState = framesReducer(
currentState,
{ type: UNPAIR_FRAME },
);
expect(newState.meta)
.toEqual({ loading: true, error: '' });
});
test('CASE 16: should return state loading = `false` when action is UNPAIR_FRAME_SUCCESS', () => {
const frameIds = [17544, 18122, 18429, 18438, 18433];
const specs = { 'W08A-01': { colors: [], photo: {} } };
const currentState = {
frames: frameIds.map((f) => (
Factory.build('Frame', { id: f })
)),
specs,
currentFrameId: 0,
meta: { error: '', loading: false },
};
const newState = framesReducer(
currentState,
{ type: UNPAIR_FRAME_SUCCESS, payload: { framePk: 0 } },
);
expect(newState.meta)
.toEqual({ loading: false, error: '' });
});
test('CASE 17: should return state loading = `false` error message when action is UNPAIR_FRAME_ERROR', () => {
const error = 'unpair frame error';
const frameIds = [17544, 18122, 18429, 18438, 18433];
const currentState = {
frames: frameIds.map((f) => (
Factory.build('Frame', { id: f })
)),
currentFrameId: 0,
meta: { error: '' },
};
const newState = framesReducer(
currentState,
{ type: UNPAIR_FRAME_ERROR, payload: { error } },
);
expect(newState.meta)
.toEqual({ loading: false, error });
});
});