/* 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 }); }); });