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,159 @@
/* global describe: true, test:true, expect:true */
import { albums as albumsReducer, initialState } from '~/reducers/albums';
import _ from 'lodash';
import {
GET_ALBUMS,
CREATE_ALBUM,
GET_ALBUMS_SUCCESS,
GET_ALBUMS_ERROR,
CREATE_ALBUM_ERROR,
GET_ALBUM_CONTENT,
GET_ALBUM_CONTENT_SUCCESS,
GET_ALBUM_CONTENT_ERROR,
CREATE_ALBUM_SUCCESS,
LOGOUT_SUCCESS,
} from '~/store/actionTypes';
import {
DEFAULT_ALBUM_NAME,
DEFAULT_ALBUM_TYPE,
} from '~/store/contentTypes';
describe('albums reducer', () => {
test('CASE 1: should return initial state', () => {
expect(albumsReducer(undefined, { type: 'Default' }))
.toEqual(initialState);
});
test('CASE 2: should return state with loading when type is GET_ALBUMS or CREATE_ALBUM', () => {
const expectedState = { ...initialState, meta: { ...initialState.meta, loading: true } };
expect(albumsReducer(initialState, { type: GET_ALBUMS })).toEqual(expectedState);
expect(albumsReducer(initialState, { type: CREATE_ALBUM })).toEqual(expectedState);
});
test('CASE 3: should return albums with meta property when type is GET_ALBUMS_SUCCESS', () => {
const albums = [{ id: 1 }, { id: 2 }];
const stateResult = albumsReducer(undefined, { type: GET_ALBUMS_SUCCESS, payload: { albums } });
expect(stateResult).toHaveProperty('albums');
expect(stateResult.albums).toHaveLength(albums.length);
stateResult.albums.forEach(album => {
expect(album).toHaveProperty('meta');
});
});
test('CASE 5: should return correct state when type is GET_ALBUMS_ERROR or CREATE_ALBUM_ERROR', () => {
const albumErr = new Error('getAlbumsError');
const expectedState = { ...initialState, meta: { error: albumErr, loading: false } };
expect(albumsReducer(initialState, {
type: GET_ALBUMS_ERROR,
payload: { error: albumErr },
})).toEqual(expectedState);
expect(albumsReducer(initialState, {
type: CREATE_ALBUM_ERROR,
payload: { error: albumErr },
})).toEqual(expectedState);
});
test('CASE 6: should return state with album loading to TRUE when type is GET_ALBUM_CONTENT', () => {
const albums = [{ id: 1 }, { id: 2 }];
const payload = {
albumId: 1,
};
const originalState = { ...initialState, albums, meta: { error: '' } };
const stateResult = albumsReducer({ ...originalState, albums, meta: { error: '' } }, {
type: GET_ALBUM_CONTENT,
payload,
});
const expectedStateAlbums = [
{ id: 1, meta: { error: '', loading: true } },
{ id: 2 },
];
expect(stateResult.albums).toEqual(expectedStateAlbums);
});
test('CASE 7: should return state with album content when type is GET_ALBUM_CONTENT_SUCCESS', () => {
const albums = [{ id: 1 }, { id: 2 }];
const content = [
{ id: 5 }, // photo id
{ id: 4 }, // photo id
];
const payload = {
albumId: 1,
content,
};
const originalState = { ...initialState, albums, meta: { error: '' } };
const stateResult = albumsReducer({ ...originalState, albums, meta: { error: '' } }, {
type: GET_ALBUM_CONTENT_SUCCESS,
payload,
});
expect(stateResult.albums[0]).toHaveProperty('content', _.orderBy(content, ['id'], ['desc']));
// expect(stateResult.albums[0]).toHaveProperty('cover');
// expect(stateResult.albums[0]).toHaveProperty('thumbs');
});
test('CASE 8: should return state with album error when type is GET_ALBUM_CONTENT_ERROR', () => {
const albums = [{ id: 1 }, { id: 2 }];
const albumErr = new Error('getAlbumsContentError');
const payload = {
albumId: 1,
error: albumErr,
};
const originalState = { ...initialState, albums, meta: { error: '' } };
const stateResult = albumsReducer({ ...originalState, albums, meta: { error: '' } }, {
type: GET_ALBUM_CONTENT_ERROR,
payload,
});
const expectedStateAlbums = [
{ id: 1, meta: { error: albumErr, loading: false } },
{ id: 2 },
];
expect(stateResult.albums).toEqual(expectedStateAlbums);
});
test('CASE 9: should add album on CREATE_ALBUM_SUCCESS with meta', () => {
const albums = [{ id: 2 }, { id: 3 }];
const payload = {
album: { id: 1 },
};
const originalState = { ...initialState, albums, meta: { error: '' } };
const stateResult = albumsReducer({ albums, ...originalState, meta: { error: '' } }, {
type: CREATE_ALBUM_SUCCESS,
payload,
});
const expectedStateAlbums = [
{ id: 1, meta: { error: '', loading: false } },
{ id: 2 },
{ id: 3 },
];
expect(stateResult.albums).toEqual(expectedStateAlbums);
});
test('CASE 10: should empty the state on LOGOUT_SUCCESS', () => {
const existingState = [{ id: 1 }, { id: 2 }];
expect(albumsReducer(existingState, { type: LOGOUT_SUCCESS }))
.toEqual(initialState);
});
test('CASE 11: should return albums with defaultAlbumId property when type is GET_ALBUMS_SUCCESS', () => {
const albums = [{ id: 1, name: DEFAULT_ALBUM_NAME, type: DEFAULT_ALBUM_TYPE }, { id: 2 }];
const stateResult = albumsReducer(undefined, { type: GET_ALBUMS_SUCCESS, payload: { albums } });
expect(stateResult).toHaveProperty('albums');
expect(stateResult).toHaveProperty('defaultAlbumId');
expect(stateResult.albums).toHaveLength(albums.length);
expect(stateResult.defaultAlbumId).toEqual(1);
stateResult.albums.forEach(album => {
expect(album).toHaveProperty('meta');
});
});
test('CASE 12: should return albums with defaultAlbumId 0 property when type is GET_ALBUMS_SUCCESS', () => {
const albums = [{ id: 1 }, { id: 2 }];
const stateResult = albumsReducer(undefined, { type: GET_ALBUMS_SUCCESS, payload: { albums } });
expect(stateResult).toHaveProperty('albums');
expect(stateResult).toHaveProperty('defaultAlbumId');
expect(stateResult.albums).toHaveLength(albums.length);
expect(stateResult.defaultAlbumId).toEqual(0);
stateResult.albums.forEach(album => {
expect(album).toHaveProperty('meta');
});
});
});

View File

@@ -0,0 +1,71 @@
/* global describe: true, test:true, expect:true */
import { app } from '~/reducers/app';
import {
CHANGE_APP_ROOT,
UPDATE_APP_STATE,
UPDATE_SHOW_NOTIFICATION,
ACCEPT_TNC_LICENSE,
ACCEPT_TNC_LICENSE_SUCCESS,
ACCEPT_TNC_LICENSE_ERROR,
} from '~/store/actionTypes';
describe('app reducer', () => {
test('CASE 1: should return initial state', () => {
const expectedState = {
root: 'splash',
sharedPlaylistOnboardingTutorialState: 0,
location: 'United States',
appStatus: 'active',
hasLoggedInOnce: false,
showNotification: false,
fromSplashScreen: false,
ssid: '',
config: {},
};
expect(app(undefined, { type: 'Default' }))
.toEqual(expectedState);
});
test('CASE 2: should return the correct state when actionType is `CHANGE_APP_ROOT` and payload is valid root', () => {
const expectedState = { root: 'home' };
expect(app({}, { type: CHANGE_APP_ROOT, payload: { root: 'home' } }))
.toEqual(expectedState);
});
test('CASE 3: should return the initial state when actionType is `CHANGE_APP_ROOT` and payload is not valid root', () => {
const expectedState = {};
expect(app({}, { type: CHANGE_APP_ROOT, payload: { root: 'something else' } }))
.toEqual(expectedState);
});
test('CASE 8: default should return the appStatus active', () => {
const expectedState = { appStatus: 'active' };
expect(app({ appStatus: 'active' }, { type: UPDATE_APP_STATE, payload: 'active' }))
.toEqual(expectedState);
});
test('CASE 9: default should return the showNotification false', () => {
const expectedState = { showNotification: false };
expect(app({ showNotification: false }, { type: UPDATE_SHOW_NOTIFICATION, payload: false }))
.toEqual(expectedState);
});
test('CASE 10: default should return the state ACCEPT_TNC_LICENSE', () => {
const expectedState = { config: { user_accepted_tnc: true } };
expect(app({ config: { user_accepted_tnc: true } }, { type: ACCEPT_TNC_LICENSE, payload: false }))
.toEqual(expectedState);
});
test('CASE 11: default should return the state ACCEPT_TNC_LICENSE_SUCCESS', () => {
const expectedState = { config: { user_accepted_tnc: true } };
expect(app({ config: { user_accepted_tnc: true } }, { type: ACCEPT_TNC_LICENSE_SUCCESS, payload: false }))
.toEqual(expectedState);
});
test('CASE 12: default should return the config error', () => {
const expectedState = { config: {} };
expect(app({ config: {} }, { type: ACCEPT_TNC_LICENSE_ERROR, payload: false }))
.toEqual(expectedState);
});
});

View File

@@ -0,0 +1,122 @@
/* global describe: true, test:true, expect:true */
import {
avatar as avatarReducer,
initialState,
} from '~/reducers/avatar';
import {
GET_AVATAR_UPLOADPOLICY,
GET_AVATAR_UPLOADPOLICY_SUCCESS,
GET_AVATAR_UPLOADPOLICY_ERROR,
GET_AVATAR,
GET_AVATAR_SUCCESS,
GET_AVATAR_ERROR,
ACTIVATE_AVATAR,
ACTIVATE_AVATAR_SUCCESS,
ACTIVATE_AVATAR_ERROR,
DELETE_AVATAR,
DELETE_AVATAR_SUCCESS,
DELETE_AVATAR_ERROR,
} from '~/store/actionTypes';
describe('avatar reducer', () => {
test('CASE 1: should return initial state', () => {
expect(avatarReducer(undefined, { type: 'Default' }))
.toEqual(initialState);
});
test('CASE 2: should return state with meta set to loading when type is GET_AVATAR', () => {
const expectedState = { ...initialState, meta: { ...initialState.meta, loading: true } };
const stateResult = avatarReducer(initialState, {
type: GET_AVATAR, payload: {},
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 3: should return state with meta set to loading when type is ACTIVATE_AVATAR', () => {
const expectedState = { ...initialState, meta: { ...initialState.meta, loading: true } };
const stateResult = avatarReducer(initialState, {
type: ACTIVATE_AVATAR, payload: {},
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 4: should return state with meta set to loading when type is GET_AVATAR_UPLOADPOLICY', () => {
const expectedState = { ...initialState, meta: { ...initialState.meta, loading: true } };
const stateResult = avatarReducer(initialState, {
type: GET_AVATAR_UPLOADPOLICY, payload: {},
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 5: should return state with meta set to loading when type is DELETE_AVATAR', () => {
const expectedState = { ...initialState, meta: { ...initialState.meta, loading: true } };
const stateResult = avatarReducer(initialState, {
type: DELETE_AVATAR, payload: {},
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 6: should return state with error when type is GET_AVATAR_ERROR', () => {
const error = new Error('getAvatarError');
const expectedState = { ...initialState, meta: { ...initialState.meta, error } };
const stateResult = avatarReducer(initialState, {
type: GET_AVATAR_ERROR, payload: { error },
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 6: should return state with error when type is ACTIVATE_AVATAR_ERROR', () => {
const error = new Error('activateAvatarError');
const expectedState = { ...initialState, meta: { ...initialState.meta, error } };
const stateResult = avatarReducer(initialState, {
type: ACTIVATE_AVATAR_ERROR, payload: { error },
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 8: should return state with error when type is GET_AVATAR_UPLOADPOLICY_ERROR', () => {
const error = new Error('getUploadPolicyAvatarError');
const expectedState = { ...initialState, meta: { ...initialState.meta, error } };
const stateResult = avatarReducer(initialState, {
type: GET_AVATAR_UPLOADPOLICY_ERROR, payload: { error },
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 9: should return state with error when type is DELETE_AVATAR_ERROR', () => {
const error = new Error('deleteAvatarError');
const expectedState = { ...initialState, meta: { ...initialState.meta, error } };
const stateResult = avatarReducer(initialState, {
type: DELETE_AVATAR_ERROR, payload: { error },
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 10: should return state with meta set to loading when type is GET_AVATAR_SUCCESS', () => {
const payload = { uri: undefined };
const meta = { loading: false, error: '' };
const stateResult = avatarReducer(initialState, {
type: GET_AVATAR_SUCCESS, payload,
});
expect(stateResult.source).toEqual(payload);
expect(stateResult).toHaveProperty('meta', meta);
});
test('CASE 11: should return state with meta set to loading when type is ACTIVATE_AVATAR_SUCCESS', () => {
const payload = { uri: undefined };
const meta = { loading: false, error: '' };
const stateResult = avatarReducer(initialState, {
type: ACTIVATE_AVATAR_SUCCESS, payload,
});
expect(stateResult.source).toEqual(payload);
expect(stateResult).toHaveProperty('meta', meta);
});
test('CASE 12: should return state with meta set to loading when type is GET_AVATAR_UPLOADPOLICY_SUCCESS', () => {
const payload = { };
const meta = { loading: false, error: '' };
const stateResult = avatarReducer(initialState, {
type: GET_AVATAR_UPLOADPOLICY_SUCCESS, payload,
});
expect(stateResult.uploadPolicy).toEqual(payload);
expect(stateResult).toHaveProperty('meta', meta);
});
test('CASE 13: should return state with meta set to loading when type is DELETE_AVATAR_SUCCESS', () => {
const payload = { };
const meta = { loading: false, error: '' };
const stateResult = avatarReducer(initialState, {
type: DELETE_AVATAR_SUCCESS, payload,
});
expect(stateResult).toEqual(initialState);
expect(stateResult).toHaveProperty('meta', meta);
});
});

View File

@@ -0,0 +1,74 @@
/* global describe: true, test:true, expect:true */
import { framePairing as framePairingReducer, initialState } from '~/reducers/framePairing';
import {
FRAME_DISCOVER_START,
FRAME_DISCOVER_STARTED_SUCCESS,
FRAME_DISCOVER_ERROR,
FRAME_DISCOVER_SUCCESS,
} from '~/store/actionTypes';
describe('framePairing reducer', () => {
test('CASE 1: should return initial state', () => {
expect(framePairingReducer(undefined, { type: 'Default' }))
.toEqual(initialState);
});
test('CASE 2: should return state with loading when type is FRAME_DISCOVER_START or FRAME_DISCOVER_STARTED_SUCCESS', () => {
const expectedState = { ...initialState, meta: { ...initialState.meta, loading: true } };
expect(framePairingReducer(initialState, {
type: FRAME_DISCOVER_START,
})).toEqual(expectedState);
expect(framePairingReducer(initialState, {
type: FRAME_DISCOVER_STARTED_SUCCESS,
})).toEqual(expectedState);
});
test('CASE 3: should return frames with meta property when type is FRAME_DISCOVER_SUCCESS', () => {
const services = [{
txt: {
serialNumber: '',
model: 1,
},
},
{
txt: {
serialNumber: '',
model: 2,
},
}];
const specs = {
1: {
name: '',
colors: [1, 2],
photo: [
'',
'',
],
},
2: {
name: '',
colors: [1, 2],
photo: [
'',
'',
],
},
};
const stateResult = framePairingReducer(undefined, {
type: FRAME_DISCOVER_SUCCESS,
payload: { services, specs },
});
expect(stateResult).toHaveProperty('frames');
expect(stateResult.frames).toHaveLength(services.length);
expect(stateResult).toHaveProperty('meta');
});
test('CASE 5: should return correct state when type is FRAME_DISCOVER_ERROR', () => {
const err = new Error('discoverFrameErr');
const expectedState = { ...initialState, meta: { error: err, loading: false } };
expect(framePairingReducer(initialState, {
type: FRAME_DISCOVER_ERROR,
payload: { error: err },
})).toEqual(expectedState);
});
});

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

View File

@@ -0,0 +1,83 @@
/* global describe: true, test:true, expect:true */
import { initialState, friendActivities } from '~/reducers/friendActivities';
import {
GET_COMMENTS_SUCCESS,
DELETE_ACTIVITY_PHOTO,
DELETE_ACTIVITY_PHOTO_ERROR,
DELETE_ACTIVITY_PHOTO_SUCCESS,
} from '~/store/actionTypes';
import Factory from 'helper/factories/api';
describe('friendActivities reducer', () => {
test('CASE 1: should return initial state', () => {
expect(friendActivities(undefined, { type: 'Default' }))
.toEqual(initialState);
});
test('CASE 2a: should return with comments when comment is related to the friend and actionType is GET_COMMENTS_SUCCESS', () => {
const friend = { username: 'friend@mynixplay.com' };
const originalState = {
friend,
nextTimestamp: 0,
activities: [],
};
const comments = Factory.buildList('Comment', 2, { friend: friend.username });
const payload = { comments };
const newState = friendActivities(originalState, { type: GET_COMMENTS_SUCCESS, payload });
expect(newState.mediaViewer.comments)
.toHaveLength(2);
});
test('CASE 2b: should return without comments when comment is not related to the friend and actionType is GET_COMMENTS_SUCCESS', () => {
const friend = { username: 'friend@mynixplay.com' };
const originalState = {
friend,
nextTimestamp: 0,
activities: [],
};
const comments = Factory.buildList('Comment', 2, { friend: 'other@mynixplay.com' });
const payload = { comments };
const newState = friendActivities(originalState, { type: GET_COMMENTS_SUCCESS, payload });
expect(newState.mediaViewer.comments)
.toHaveLength(0);
});
test('CASE 3: friendActivities should update meta loading state when type is DELETE_ACTIVITY_PHOTO', (s3Key = '', albumId = '', timestamp = '', friend = '') => {
const existingState = { ...initialState, meta: { loading: true, error: '' } };
const stateResult = friendActivities(existingState, {
type: DELETE_ACTIVITY_PHOTO,
payload: {
s3Key,
albumId,
timestamp,
friend,
},
});
expect(stateResult).toEqual(existingState);
});
test('CASE 4: friendActivities should update meta loading state when type is DELETE_ACTIVITY_PHOTO_ERROR', () => {
const existingState = { ...initialState, actions: { submitting: false, error: '' } };
const stateResult = friendActivities(existingState, {
type: DELETE_ACTIVITY_PHOTO_ERROR,
payload: {
error: '',
},
});
expect(stateResult).toEqual(existingState);
});
test('CASE 5: friendActivities should update meta loading state when type is DELETE_ACTIVITY_PHOTO_SUCCESS', (s3Key = '', albumId = '', timestamp = '', friend = '') => {
const existingState = { ...initialState, meta: { loading: false, error: '' } };
const stateResult = friendActivities(existingState, {
type: DELETE_ACTIVITY_PHOTO_SUCCESS,
payload: {
s3Key,
albumId,
timestamp,
friend,
},
});
expect(stateResult).toEqual(existingState);
});
});

View File

@@ -0,0 +1,187 @@
/* global describe: true, test:true, expect:true */
import {
friends as friendsReducer,
initialState,
initAddFriend,
addFriend as addFriendReducer,
} from '~/reducers/friends';
import {
GET_FRIENDS,
GET_FRIENDS_SUCCESS,
GET_FRIENDS_ERROR,
UPDATE_SEEN_TIMESTAMP_SUCCESS,
LOGOUT_SUCCESS,
UPDATE_ADD_FRIEND,
ACCEPT_FRIEND_INVITE_SUCCESS,
ACCEPT_FRIEND_INVITE_ERROR,
REJECT_FRIEND_INVITE_SUCCESS,
REJECT_FRIEND_INVITE_ERROR,
RESET_ADD_FRIEND_ERROR,
RESET_ADD_FRIEND_PLAYLIST,
} from '~/store/actionTypes';
describe('friends reducer', () => {
test('CASE 1: should return initial state', () => {
expect(friendsReducer(undefined, { type: 'Default' }))
.toEqual(initialState);
});
test('CASE 2: should return state with meta set to loading when type is GET_FRIENDS', () => {
const expectedState = { ...initialState, meta: { ...initialState.meta, loading: true } };
const stateResult = friendsReducer(initialState, {
type: GET_FRIENDS, payload: {},
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 3: should return state with meta set to loading when type is GET_FRIENDS_SUCCESS', () => {
const friends = [{ username: '1', activity: { timestamp: 0 } }, { username: '2', activity: { timestamp: 0 } }];
const invites = [{ requester: '1' }, { requester: '2' }];
const meta = { loading: false, error: '' };
const stateResult = friendsReducer(initialState, {
type: GET_FRIENDS_SUCCESS, payload: { friends: { friends, invites } },
});
expect(stateResult.friends).toEqual([]);
expect(stateResult.invites[0]).toHaveProperty('meta', meta);
});
test('CASE 4: should return state with error when type is GET_FRIENDS_ERROR', () => {
const error = new Error('getFriendsError');
const expectedState = { ...initialState, meta: { ...initialState.meta, error } };
const stateResult = friendsReducer(initialState, {
type: GET_FRIENDS_ERROR, payload: { error },
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 5: should return state when type is UPDATE_SEEN_TIMESTAMP_SUCCESS', () => {
const meta = { loading: false, error: '' };
const stateResult = friendsReducer(initialState, { type: UPDATE_SEEN_TIMESTAMP_SUCCESS });
expect(stateResult).toHaveProperty('meta', meta);
});
test('CASE 6: should return state with loading = false when type is ACCEPT_FRIEND_INVITE_SUCCESS', () => {
const meta = { loading: false, error: '' };
const stateResult = friendsReducer(initialState, { type: ACCEPT_FRIEND_INVITE_SUCCESS });
expect(stateResult).toHaveProperty('meta', meta);
});
test('CASE 7: should return state with loading = false when type is ACCEPT_FRIEND_INVITE_ERROR', () => {
const meta = { loading: false, error: '' };
const stateResult = friendsReducer(initialState, { type: ACCEPT_FRIEND_INVITE_ERROR, payload: { error: '' } });
expect(stateResult).toHaveProperty('meta', meta);
});
test('CASE 8: should return state with loading = false when type is REJECT_FRIEND_INVITE_SUCCESS', () => {
const meta = { loading: false, error: '' };
const stateResult = friendsReducer(initialState, { type: REJECT_FRIEND_INVITE_SUCCESS });
expect(stateResult).toHaveProperty('meta', meta);
});
test('CASE 9: should return state with loading = false when type is REJECT_FRIEND_INVITE_ERROR', () => {
const meta = { loading: false, error: '' };
const stateResult = friendsReducer(initialState, { type: REJECT_FRIEND_INVITE_ERROR, payload: { error: '' } });
expect(stateResult).toHaveProperty('meta', meta);
});
test('CASE 10: should empty the state on LOGOUT_SUCCESS', () => {
const existingState = {};
expect(friendsReducer(existingState, { type: LOGOUT_SUCCESS }))
.toEqual(initialState);
});
test('CASE 11: addFriend should return initial state', () => {
expect(addFriendReducer(undefined, { type: 'Default' }))
.toEqual(initAddFriend);
});
test('CASE 12: addFriend should return state when type is UPDATE_ADD_FRIEND', () => {
const stateResult = friendsReducer(initAddFriend, {
type: UPDATE_ADD_FRIEND,
payload: {
lookupKey: '',
friendName: '',
playlistId: -1,
hasError: '',
isNewPlaylist: 0,
popCount: 2,
},
});
expect(stateResult).toEqual(initAddFriend);
});
test('CASE 13: addFriend should update error state when type is UPDATE_ADD_FRIEND', (hasError = '') => {
const {
lookupKey,
friendName,
playlistId,
isNewPlaylist,
} = initAddFriend;
const stateResult = friendsReducer(initAddFriend, {
type: RESET_ADD_FRIEND_ERROR,
payload: {
lookupKey,
friendName,
playlistId,
hasError,
isNewPlaylist,
},
});
expect(stateResult).toEqual(initAddFriend);
});
test('CASE 14: addFriend should update error state when type is RESET_ADD_FRIEND_ERROR', (hasError = '') => {
const stateResult = friendsReducer(initAddFriend, {
type: RESET_ADD_FRIEND_ERROR,
payload: { hasError },
});
expect(stateResult).toEqual(initAddFriend);
});
test('CASE 15: addFriend should update error state when type is RESET_ADD_FRIEND_PLAYLIST', (isNewPlaylist = 0) => {
const stateResult = friendsReducer(initAddFriend, {
type: RESET_ADD_FRIEND_PLAYLIST,
payload: { isNewPlaylist },
});
expect(stateResult).toEqual(initAddFriend);
});
test('CASE 16: Badge should be true when a new friend invite has been added to state GET_FRIENDS_SUCCESS', () => {
const existingState = { ...initialState, invites: [{ requester: '1' }, { requester: '2' }] };
const friends = {
invites: [{ requester: '1' }, { requester: '3' }],
friends: [{ username: '1', activity: { timestamp: 0 } }],
};
const stateResult = friendsReducer(existingState, {
type: GET_FRIENDS_SUCCESS,
payload: { friends },
});
expect(stateResult).toHaveProperty('isBadged', true);
});
test('CASE 17: Badge should be true when a new friend invite GET_FRIENDS_SUCCESS', () => {
const existingState = { ...initialState, invites: [{ requester: '1' }, { requester: '2' }] };
const friends = {
invites: [{ requester: '1' }],
friends: [{ username: '1', activity: { timestamp: 0 } }],
};
const stateResult = friendsReducer(existingState, {
type: GET_FRIENDS_SUCCESS,
payload: { friends },
});
expect(stateResult).toHaveProperty('isBadged', false);
});
test('CASE 18: Badge should be true when a friend gets a new activity', () => {
const existingState = { ...initialState, invites: [], friends: [{ username: '1', activity: { timestamp: 1 } }] };
const friends = {
invites: [],
friends: [{ username: '1', activity: { timestamp: 2 } }],
};
const stateResult = friendsReducer(existingState, {
type: GET_FRIENDS_SUCCESS,
payload: { friends },
});
expect(stateResult).toHaveProperty('isBadged', false);
});
});

View File

@@ -0,0 +1,37 @@
/* global describe: true, test:true, expect:true */
import { fujifilmCategories as fujifilmCategoriesReducer, initialState } from '~/reducers/fujifilmCategories';
import {
GET_FUJIFILM_CHILD_CATEGORY_PROPDUCTS_SUCCESS,
} from '~/store/actionTypes';
describe('fujifilmCategories reducer', () => {
test('CASE 1: should return initial state', () => {
expect(fujifilmCategoriesReducer(undefined, { type: 'Default' }))
.toEqual(initialState);
});
test('CASE 2: should return correct state when type is GET_FUJIFILM_CHILD_CATEGORY_PROPDUCTS_SUCCESS', () => {
const categoryId = 1;
const products = [{
ProductCode: '1',
}, {
ProductCode: '2',
}];
const serviceType = 'MailOrder';
const childCategoryProducts = {
1: [{
ProductCode: '1',
}, {
ProductCode: '2',
}],
};
const stateResult = fujifilmCategoriesReducer(initialState, {
type: GET_FUJIFILM_CHILD_CATEGORY_PROPDUCTS_SUCCESS,
payload: { categoryId, products, serviceType },
});
expect(stateResult).toHaveProperty('childCategoryProducts');
expect(stateResult.childCategoryProducts).toEqual(childCategoryProducts);
expect(stateResult).toHaveProperty('meta');
});
});

View File

@@ -0,0 +1,335 @@
/* global describe: true, test:true, expect:true */
import { google as googleReducer, initialState } from '~/reducers/google';
import {
SET_GOOGLE_INFO,
GET_GOOGLE_TOKEN,
GET_GOOGLE_TOKEN_SUCCESS,
LOGOUT_SUCCESS,
LOGOUT_FROM_GOOGLE_SUCCESS,
GET_GOOGLE_TOKEN_ERROR,
GET_GOOGLE_ALBUMS,
GET_GOOGLE_CATEGORIES,
GET_GOOGLE_ALBUMS_ERROR,
GET_GOOGLE_CATEGORIES_ERROR,
GET_GOOGLE_ALBUMS_SUCCESS,
GET_GOOGLE_CATEGORIES_SUCCESS,
GET_DYNAMIC_PLAYLISTS_ERROR,
GET_DYNAMIC_PLAYLISTS_SUCCESS,
GET_GOOGLE_ALBUM_CONTENT_SUCCESS,
} from '~/store/actionTypes';
import Factory from 'helper/factories/google';
describe('google reducer', () => {
test('CASE 1: should return initial state', () => {
expect(googleReducer(undefined, { type: 'Default' }))
.toEqual(initialState);
});
test('CASE 2: should return state with Google info set when type is SET_GOOGLE_INFO', () => {
const googleInfo = {
email: 'user@gmail.com',
photo: 'https://lh4.googleusercontent.com/photo.jpg',
idToken: '{idToken}',
id: '{id}',
familyName: '{lastName}',
serverAuthCode: '{serverAuthCode}',
accessToken: '{accessToken}',
givenName: '{firstName}',
accessTokenExpirationDate: 3260.7057960033417,
name: '{firstName} {lastName}',
};
const expectedState = { ...initialState, auth: googleInfo };
const stateResult = googleReducer(initialState, {
type: SET_GOOGLE_INFO, payload: googleInfo,
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 3: should return state with meta set when type is GET_GOOGLE_TOKEN', () => {
const expectedState = initialState;
const stateResult = googleReducer(initialState, {
type: GET_GOOGLE_TOKEN,
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 4: should return state with Google set when type is GET_GOOGLE_TOKEN_SUCCESS', () => {
const googleInfo = {
email: 'user@gmail.com',
photo: 'https://lh4.googleusercontent.com/photo.jpg',
idToken: '{idToken}',
id: '{id}',
familyName: '{lastName}',
serverAuthCode: '{serverAuthCode}',
accessToken: '{accessToken}',
givenName: '{firstName}',
accessTokenExpirationDate: 3260.7057960033417,
name: '{firstName} {lastName}',
};
const googleToken = { googleId: googleInfo.email, valid: true };
const expectedState = {
...initialState,
auth: googleInfo,
};
const stateResult = googleReducer({ ...initialState, auth: googleInfo }, {
type: GET_GOOGLE_TOKEN_SUCCESS,
payload: { googleToken },
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 5: should return state with Google unset when type is GET_GOOGLE_TOKEN_SUCCESS and server Token is invalid', () => {
const googleInfo = {
email: 'user@gmail.com',
photo: 'https://lh4.googleusercontent.com/photo.jpg',
idToken: '{idToken}',
id: '{id}',
familyName: '{lastName}',
serverAuthCode: '{serverAuthCode}',
accessToken: '{accessToken}',
givenName: '{firstName}',
accessTokenExpirationDate: 3260.7057960033417,
name: '{firstName} {lastName}',
};
const googleToken = { googleId: googleInfo.email, valid: false };
const expectedState = {
...initialState,
auth: {},
};
const stateResult = googleReducer({ ...initialState, auth: googleInfo }, {
type: GET_GOOGLE_TOKEN_SUCCESS,
payload: { googleToken },
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 6: should return state with Google unset when type is GET_GOOGLE_TOKEN_SUCCESS and server Token is valid but googleId does not match the email', () => {
const googleInfo = {
email: 'user@gmail.com',
photo: 'https://lh4.googleusercontent.com/photo.jpg',
idToken: '{idToken}',
id: '{id}',
familyName: '{lastName}',
serverAuthCode: '{serverAuthCode}',
accessToken: '{accessToken}',
givenName: '{firstName}',
accessTokenExpirationDate: 3260.7057960033417,
name: '{firstName} {lastName}',
};
const googleToken = { googleId: 'other@gmail.com', valid: true };
const expectedState = {
...initialState,
auth: {},
};
const stateResult = googleReducer({ ...initialState, auth: googleInfo }, {
type: GET_GOOGLE_TOKEN_SUCCESS,
payload: { googleToken },
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 7: should return state with meta loading set to false when actionType is GET_GOOGLE_TOKEN_ERROR', () => {
const expectedState = initialState;
const stateResult = googleReducer(initialState, {
type: GET_GOOGLE_TOKEN_ERROR,
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 7: should return initialState when actionType is LOGOUT_FROM_GOOGLE_SUCCESS', () => {
const stateResult = googleReducer(initialState, {
type: LOGOUT_FROM_GOOGLE_SUCCESS,
});
expect(stateResult).toEqual(initialState);
});
test('CASE 8: should return initialState when actionType is LOGOUT_SUCCESS', () => {
const stateResult = googleReducer(initialState, {
type: LOGOUT_SUCCESS,
});
expect(stateResult).toEqual(initialState);
});
test('CASE 9: should return loading for albums set to true when actionType is GET_GOOGLE_ALBUMS', () => {
const expectedState = {
...initialState,
meta: { loading: { ...initialState.meta.loading, albums: true } },
};
const stateResult = googleReducer(initialState, {
type: GET_GOOGLE_ALBUMS,
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 10: should return loading for categories set to true when actionType is GET_GOOGLE_CATEGORIES', () => {
const expectedState = {
...initialState,
meta: { loading: { ...initialState.meta.loading, categories: true } },
};
const stateResult = googleReducer(initialState, {
type: GET_GOOGLE_CATEGORIES,
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 11: should return loading for categories set to false when actionType is GET_GOOGLE_ALBUMS_ERROR', () => {
const expectedState = {
...initialState,
meta: { loading: { ...initialState.meta.loading, categories: false } },
};
const stateResult = googleReducer(initialState, {
type: GET_GOOGLE_ALBUMS_ERROR,
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 12: should return loading for categories set to false when actionType is GET_GOOGLE_CATEGORIES_ERROR', () => {
const expectedState = {
...initialState,
meta: { loading: { ...initialState.meta.loading, categories: false } },
};
const stateResult = googleReducer(initialState, {
type: GET_GOOGLE_CATEGORIES_ERROR,
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 12: should return albums with alreadySynced set correctly when actionType is GET_GOOGLE_ALBUMS_SUCCESS', () => {
const googleId = 'user@gmail.com';
const playlists = Factory.buildList('DynamicPlaylist', 4, { googleId });
const albums = Factory.buildList('GoogleAlbum', 2);
const prevState = {
auth: { email: googleId },
categories: [],
albums: [],
allPhotos: {},
playlists,
meta: { loading: { albums: false, categories: false } },
};
const expectedState = {
...prevState,
meta: { loading: { ...initialState.meta.loading, categories: false } },
albums: [
{ title: 'Album 1', id: 'album1', alreadySynced: true },
{ title: 'Album 2', id: 'album2', alreadySynced: true },
],
allPhotos: {},
};
const stateResult = googleReducer(prevState, {
type: GET_GOOGLE_ALBUMS_SUCCESS,
payload: albums,
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 13: should return categories with alreadySynced set correctly when actionType is GET_GOOGLE_CATEGORIES_SUCCESS', () => {
const googleId = 'user@gmail.com';
const playlists = Factory.buildList('DynamicPlaylist', 4, { googleId });
const categories = [
{ id: 'ANIMAL' },
{ id: 'PEOPLE' },
{ id: 'LANDSCAPE' },
];
const prevState = {
auth: { email: googleId },
categories: [],
albums: [],
playlists,
meta: { loading: { albums: false, categories: false } },
};
const expectedState = {
...prevState,
meta: { loading: { ...initialState.meta.loading, categories: false } },
categories: [
{ id: 'ANIMAL', alreadySynced: true },
{ id: 'PEOPLE', alreadySynced: true },
{ id: 'LANDSCAPE' },
],
allPhotos: { alreadySynced: false },
};
const stateResult = googleReducer(prevState, {
type: GET_GOOGLE_CATEGORIES_SUCCESS,
payload: { categories, allPhotos: {} },
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 14: should return alreadySynced set correctly when actionType is GET_DYNAMIC_PLAYLISTS_SUCCESS', () => {
const googleId = 'user@gmail.com';
const playlists = Factory.buildList('DynamicPlaylist', 4, { googleId });
const albums = Factory.buildList('GoogleAlbum', 2);
const categories = [
{ id: 'ANIMAL' },
{ id: 'PEOPLE' },
{ id: 'LANDSCAPE' },
];
const prevState = {
auth: { email: googleId },
categories,
albums,
playlists: [],
meta: { loading: { albums: false, categories: false } },
allPhotos: {},
};
const expectedState = {
...prevState,
meta: { loading: { albums: false, categories: false } },
categories: [
{ id: 'ANIMAL', alreadySynced: true },
{ id: 'PEOPLE', alreadySynced: true },
{ id: 'LANDSCAPE' },
],
albums,
playlists,
allPhotos: { alreadySynced: false },
};
const stateResult = googleReducer(prevState, {
type: GET_DYNAMIC_PLAYLISTS_SUCCESS,
payload: { google: playlists },
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 15: should return categories with alreadySynced set correctly when actionType is GET_DYNAMIC_PLAYLISTS_ERROR', () => {
const stateResult = googleReducer(initialState, {
type: GET_DYNAMIC_PLAYLISTS_ERROR,
});
expect(stateResult).toEqual(initialState);
});
test('CASE 16: should return album with mediaItems set correctly when actionType is GET_GOOGLE_ALBUM_CONTENT_SUCCESS', () => {
const googleId = 'user@gmail.com';
const playlists = Factory.buildList('DynamicPlaylist', 4, { googleId });
const albums = Factory.buildList('GoogleAlbum', 1);
const prevState = {
auth: { email: googleId },
albums,
playlists,
meta: { loading: { albums: false, categories: false } },
};
const payload = {
title: albums[0].title,
id: albums[0].id,
mediaItems: [
{ id: 'AGj1epUmh4wiG3g2bKOKDoclVoRTsE-_STHFhWdUdhvR142wa0wx4-y-rb9mYq2363Cr0_Gid19iJw4' },
{ id: 'AGj1epWNpu29AtPtEyX3ICRDLOcxyUxhCt45UG1C4swn1me84xFxculsQDCJaclsC3mBeX54MBM7HL8' },
{ id: 'AGj1epWAvBQE-WStq6wzHkv-4oW28J154cd5SU4KDCUTL-XB9hJdxyT7GCaOLett4qVyRXFFmYHpYJ4' },
],
};
const expectedState = {
...prevState,
meta: { loading: { albums: false, categories: false } },
albums: [payload],
playlists,
};
const stateResult = googleReducer(prevState, {
type: GET_GOOGLE_ALBUM_CONTENT_SUCCESS, payload,
});
expect(stateResult).toEqual(expectedState);
});
});

View File

@@ -0,0 +1,17 @@
/* global describe: true, test:true, expect:true */
import { locale } from '~/reducers/locale';
import { CHANGE_LOCALE } from '~/store/actionTypes';
describe('locale reducer', () => {
test('CASE 1: should return initial state', () => {
const expectedState = { locale: 'en' };
expect(locale(undefined, { type: 'Default' }))
.toEqual(expectedState);
});
test('CASE 2: should return correct state when action is `CHANGE_LOCALE`', () => {
const expectedState = { locale: 'de' };
expect(locale(undefined, { type: CHANGE_LOCALE, payload: { locale: 'de' } }))
.toEqual(expectedState);
});
});

View File

@@ -0,0 +1,121 @@
/* global describe: true, test:true, expect:true */
import { photoPrint as photoPrintReducer, initialState } from '~/reducers/photoPrint';
import {
PLACE_PHOTO_PRINT_ORDER,
PLACE_PHOTO_PRINT_ORDER_SUCCESS,
PLACE_PHOTO_PRINT_ORDER_ERROR,
SET_PHOTOS_TO_QUEUE,
SET_PHOTOS_TO_QUEUE_SUCCESS,
SET_PHOTOS_TO_QUEUE_ERROR,
REMOVE_PHOTO_FROM_QUEUE,
REMOVE_PHOTO_FROM_QUEUE_SUCCESS,
REMOVE_PHOTO_FROM_QUEUE_ERROR,
} from '~/store/actionTypes';
describe('photoPrint reducer', () => {
test('CASE 1: should return initial state', () => {
expect(photoPrintReducer(undefined, { type: 'Default' }))
.toEqual(initialState);
});
test('CASE 2: should return state with loading when type is PLACE_PHOTO_PRINT_ORDER, SET_PHOTOS_TO_QUEUE or REMOVE_PHOTO_FROM_QUEUE', () => {
const expectedState = { ...initialState, meta: { ...initialState.meta, loading: true } };
expect(photoPrintReducer(initialState, { type: PLACE_PHOTO_PRINT_ORDER })).toEqual(expectedState);
expect(photoPrintReducer(initialState, { type: SET_PHOTOS_TO_QUEUE })).toEqual(expectedState);
expect(photoPrintReducer(initialState, { type: REMOVE_PHOTO_FROM_QUEUE })).toEqual(expectedState);
});
test('CASE 4: should return correct state when type is PLACE_PHOTO_PRINT_ORDER_SUCCESS', () => {
const expectedState = { ...initialState, meta: { ...initialState.meta, loading: false }, orderNumbers: ['1234567'] };
expect(photoPrintReducer(
initialState,
{
type: PLACE_PHOTO_PRINT_ORDER_SUCCESS,
payload: {
orderNumber: '1234567',
},
},
)).toEqual(expectedState);
});
test('CASE 5: should return correct state when type is REMOVE_PHOTO_FROM_QUEUE_SUCCESS', () => {
const images = ['image1', 'image2', 'image3'];
const expectedState = {
...initialState,
images,
count: 3,
meta: {
...initialState.meta,
loading: false,
},
};
expect(photoPrintReducer(
initialState,
{
type: REMOVE_PHOTO_FROM_QUEUE_SUCCESS,
payload: {
images,
},
},
)).toEqual(expectedState);
});
test('CASE 6: should return correct state when type is SET_PHOTOS_TO_QUEUE_SUCCESS', () => {
const images = ['image1', 'image2', 'image3'];
const expectedState = {
...initialState,
images,
count:
3,
meta:
{
...initialState.meta,
loading:
false,
},
};
expect(photoPrintReducer(
initialState,
{
type: SET_PHOTOS_TO_QUEUE_SUCCESS,
payload: {
images,
},
},
)).toEqual(expectedState);
});
test('CASE 7: should return error state when type is PLACE_PHOTO_PRINT_ORDER_ERROR', () => {
const error = new Error('Error');
const expectedState = { ...initialState, meta: { ...initialState.meta, loading: false, error } };
expect(photoPrintReducer(
initialState,
{
type: PLACE_PHOTO_PRINT_ORDER_ERROR,
payload: { error },
},
)).toEqual(expectedState);
});
test('CASE 8: should return error state when type is SET_PHOTOS_TO_QUEUE_ERROR', () => {
const error = new Error('Error');
const expectedState = { ...initialState, meta: { ...initialState.meta, loading: false, error } };
expect(photoPrintReducer(
initialState,
{
type: SET_PHOTOS_TO_QUEUE_ERROR,
payload: { error },
},
)).toEqual(expectedState);
});
test('CASE 9: should return error state when type is REMOVE_PHOTO_FROM_QUEUE_ERROR', () => {
const error = new Error('Error');
const expectedState = { ...initialState, meta: { ...initialState.meta, loading: false, error } };
expect(photoPrintReducer(
initialState,
{
type: REMOVE_PHOTO_FROM_QUEUE_ERROR,
payload: { error },
},
)).toEqual(expectedState);
});
});

View File

@@ -0,0 +1,339 @@
/* global describe: true, test:true, expect:true */
import { playlists as playlistsReducer, initialState } from '~/reducers/playlists';
import {
GET_PLAYLISTS,
GET_PLAYLISTS_SUCCESS,
GET_PLAYLISTS_ERROR,
GET_PLAYLIST_CONTENT,
GET_PLAYLIST_CONTENT_SUCCESS,
GET_PLAYLIST_CONTENT_ERROR,
LOGOUT_SUCCESS,
CREATE_DYNAMIC_PLAYLIST_SUCCESS,
GET_DYNAMIC_PLAYLISTS_SUCCESS,
UPLOAD_ITEM_STARTED,
UPLOAD_ITEMS_SUCCESS,
UPLOAD_ITEMS_ERROR,
PLAYLIST_PROCESSING_STARTED,
PLAYLIST_PROCESSING_DONE,
UPLOAD_SUCCESS,
UPLOAD_ALL_CANCELLED,
} from '~/store/actionTypes';
import Factory from 'helper/factories/api';
describe('playlists reducer', () => {
test('CASE 1: should return initial state', () => {
expect(playlistsReducer(undefined, { type: 'Default' }))
.toEqual(initialState);
});
test('CASE 2: should return state with meta set to loading when type is GET_PLAYLISTS', () => {
const playlists = [{ id: 1 }, { id: 2 }];
const expectedState = { ...initialState, meta: { ...initialState.meta, loading: false } };
const stateResult = playlistsReducer(initialState, {
type: GET_PLAYLISTS, payload: { playlists },
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 3a: should return state with playlist content merged with dynamic playlist when type is GET_PLAYLISTS_SUCCESS', () => {
const playlists = Factory.buildList('Playlist', 6);
const googleId = 'someone@gmail.com';
const dynamicPlaylists = playlists.map(playlist => Factory.build('GoogleDynamicPlaylist', { playlistId: playlist.id, googleId }));
const statePlaylists = playlists.map((item) => ({ ...item, slides: [{ url: 'url' }] }));
const originalState = {
...initialState, playlists: statePlaylists, dynamicPlaylists,
};
const stateResult = playlistsReducer(originalState, {
type: GET_PLAYLISTS_SUCCESS, payload: { playlists },
});
expect(stateResult.playlists).toEqual(expect.arrayContaining([expect.objectContaining({
name: expect.any(String),
googleId: expect.any(String),
status: expect.any(String),
slides: expect.any(Array),
dynamicPlaylistName: expect.any(String),
lastSynced: expect.any(String),
})]));
});
test('CASE 3b: should return state with playlist content merged with dynamic playlist when type is GET_PLAYLISTS_SUCCESS', () => {
const playlists = Factory.buildList('Playlist', 1);
const googleId = 'someone@gmail.com';
const dynamicPlaylists = playlists.map(playlist => Factory.build('GoogleDynamicPlaylist', { playlistId: playlist.id, googleId }));
const originalState = { ...initialState, dynamicPlaylists };
const stateResult = playlistsReducer(originalState, {
type: GET_PLAYLISTS_SUCCESS, payload: { playlists },
});
expect(stateResult.playlists).toEqual(expect.arrayContaining([expect.objectContaining({
name: expect.any(String),
googleId: expect.any(String),
status: expect.any(String),
dynamicPlaylistName: expect.any(String),
lastSynced: expect.any(String),
googleCollectionType: expect.any(String),
})]));
});
test('CASE 3c: should return state with playlist content merged with dynamic playlist when type is GET_PLAYLISTS_SUCCESS', () => {
const playlists = Factory.buildList('Playlist', 1);
const googleId = 'someone@gmail.com';
const dynamicPlaylists = playlists.map(playlist => Factory.build('GoogleDynamicPlaylist', { playlistId: playlist.id, googleId }));
const statePlaylists = playlists.map((item) => ({ ...item, slides: [{ url: 'url' }] }));
const originalState = {
...initialState, playlists: statePlaylists, dynamicPlaylists,
};
const count = Math.floor((Math.random() * 500) + 1);
const thumbs = [0, 1, 2].map(item => ({ src: `https://loremflickr.com/1024/768/cats?asdf=${item}`, rotation: 0, orientation: 1 }));
const stateResult = playlistsReducer(originalState, {
type: GET_PLAYLISTS_SUCCESS, payload: { playlists: [{ ...playlists[0], count, thumbs }] },
});
// The count and thumbs properties should be overridden by the new playlists data
expect(stateResult.playlists[0].count).toEqual(count);
expect(stateResult.playlists[0].thumbs).toEqual(thumbs);
});
test('CASE 4: should return state with error when type is GET_PLAYLISTS_ERROR', () => {
const error = new Error('getPlaylistError');
const expectedState = { ...initialState, meta: { ...initialState.meta, error } };
const stateResult = playlistsReducer(initialState, {
type: GET_PLAYLISTS_ERROR, payload: { error },
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 5: should return state with meta set to loading when type is GET_PLAYLIST_CONTENT', () => {
const playlists = [
{ id: 1 },
{ id: 2 },
];
const originalState = { ...initialState, playlists };
const payload = { playlistId: 1 };
const expectedState = {
...initialState,
playlists: [{
id: 1,
meta: { error: '', loading: true },
},
{ id: 2 }],
meta: { error: '', loading: false, uploading: false },
};
const stateResult = playlistsReducer(originalState, {
type: GET_PLAYLIST_CONTENT, payload,
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 6a: should return state with playlist content set when type is GET_PLAYLIST_CONTENT_SUCCESS', () => {
const playlists = [
{ id: 1 },
];
const originalState = { ...initialState, playlists };
const payload = {
playlistId: 1,
playlist: { name: 'PL one', slides: [] },
offset: 0,
};
const stateResult = playlistsReducer(originalState, {
type: GET_PLAYLIST_CONTENT_SUCCESS, payload,
});
expect(stateResult.playlists[0]).toHaveProperty('name', payload.playlist.name);
expect(stateResult.playlists[0]).toHaveProperty('slides');
// expect(stateResult.playlists[0]).toHaveProperty('thumbs');
});
test('CASE 6b: GET_PLAYLIST_CONTENT_SUCCESS should combine playlist slides if offset is > 0', () => {
const initialSlides = ['a', 'b', 'c'];
const nextSlides = ['d', 'e', 'f'];
const playlists = [
{
id: 1, slides: initialSlides, pictureCount: 6, offset: 3,
},
];
const originalState = { ...initialState, playlists };
const payload = {
playlistId: 1,
playlist: {
name: 'PL one',
slides: nextSlides,
offset: 5,
pictureCount: 6,
},
startOffset: 3,
endOffset: 6,
};
const stateResult = playlistsReducer(originalState, {
type: GET_PLAYLIST_CONTENT_SUCCESS, payload,
});
expect(stateResult.playlists[0]).toHaveProperty('slides', [...initialSlides, ...nextSlides]);
});
test('CASE 7: should return state error when type is GET_PLAYLIST_CONTENT_ERROR', () => {
const playlists = [
{ id: 1, meta: { error: '', loading: true } },
{ id: 2, meta: { error: '', loading: false } },
];
const originalState = { ...initialState, playlists };
// console.log({ originalState: JSON.stringify(originalState) });
const error = new Error('getPlaylistError');
const payload = {
playlistId: 1,
error,
};
const expectedState = {
...initialState,
playlists: [{
id: 1,
meta: { error, loading: false },
},
{ id: 2, meta: { error: '', loading: false } }],
meta: { error: '', loading: false, uploading: false },
};
const stateResult = playlistsReducer(originalState, {
type: GET_PLAYLIST_CONTENT_ERROR, payload,
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 9: should empty the state on LOGOUT_SUCCESS', () => {
const existingState = [{ id: 1 }, { id: 2 }];
expect(playlistsReducer(existingState, { type: LOGOUT_SUCCESS }))
.toEqual(initialState);
});
test('CASE 10: should current state on CREATE_DYNAMIC_PLAYLIST_SUCCESS', () => {
const existingState = [{ id: 1 }, { id: 2 }];
expect(playlistsReducer(existingState, { type: CREATE_DYNAMIC_PLAYLIST_SUCCESS }))
.toEqual(existingState);
});
test('CASE 11: should return state with dynamicPlaylist set when type is GET_DYNAMIC_PLAYLISTS_SUCCESS', () => {
const playlists = Factory.buildList('Playlist', 6);
const googleId = 'someone@gmail.com';
const dynamicPlaylists = playlists.map(playlist => Factory.build('GoogleDynamicPlaylist', { playlistId: playlist.id, googleId }));
const originalState = { ...initialState, playlists };
const stateResult = playlistsReducer(originalState, {
type: GET_DYNAMIC_PLAYLISTS_SUCCESS, payload: { google: dynamicPlaylists },
});
expect(stateResult.playlists).toEqual(expect.arrayContaining([expect.objectContaining({
name: expect.any(String),
googleId: expect.any(String),
status: expect.any(String),
dynamicPlaylistName: expect.any(String),
lastSynced: expect.any(String),
})]));
expect(stateResult.dynamicPlaylists).toEqual(dynamicPlaylists);
});
test('CASE 12: should return state with upload state set when type is UPLOAD_ITEM_STARTED', () => {
const expectedState = { ...initialState, meta: { ...initialState.meta, uploading: true } };
const stateResult = playlistsReducer(initialState, {
type: UPLOAD_ITEM_STARTED,
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 13: should return state with upload state set when type is UPLOAD_ITEMS_SUCCESS or UPLOAD_ITEMS_ERROR', () => {
const expectedState = { ...initialState, meta: { ...initialState.meta, uploading: false } };
const stateResult = playlistsReducer(initialState, {
type: UPLOAD_ITEMS_SUCCESS,
});
expect(stateResult).toEqual(expectedState);
const expectedState2 = { ...initialState, meta: { ...initialState.meta, uploading: false } };
const stateResult2 = playlistsReducer(initialState, {
type: UPLOAD_ITEMS_ERROR,
});
expect(stateResult2).toEqual(expectedState2);
});
test('CASE 14: should return state with trackerId set when type is PLAYLIST_PROCESSING_STARTED', () => {
const playlists = [
{ id: 1, meta: { error: '', loading: true } },
{ id: 2, meta: { error: '', loading: false } },
{ id: 3, meta: { error: '', loading: true } },
];
const originalState = { ...initialState, playlists };
const playlistsWithTracker = [
{ id: 1, trackerId: 'a74d2e06f17e2893017431375b416b76', meta: { error: '', loading: true } },
{ id: 2, meta: { error: '', loading: false } },
{ id: 3, trackerId: '5b0e992791ed43ca79928eed54ca0b4f', meta: { error: '', loading: true } },
];
const expectedState = { ...originalState, playlists: playlistsWithTracker };
const stateResult = playlistsReducer(originalState, {
type: PLAYLIST_PROCESSING_STARTED,
payload: {
data: [
{ receiver: '1', trackerId: 'a74d2e06f17e2893017431375b416b76' },
{ receiver: '3', trackerId: '5b0e992791ed43ca79928eed54ca0b4f' },
],
},
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 15: should return state without trackerId set when type is PLAYLIST_PROCESSING_DONE', () => {
const playlists = [
{ id: 1, trackerId: 'a74d2e06f17e2893017431375b416b76', meta: { error: '', loading: true } },
{ id: 2, meta: { error: '', loading: false } },
{ id: 3, trackerId: '5b0e992791ed43ca79928eed54ca0b4f', meta: { error: '', loading: true } },
];
const originalState = { ...initialState, playlists };
const playlistsWithTracker = [
{ id: 1, trackerId: 'a74d2e06f17e2893017431375b416b76', meta: { error: '', loading: true } },
{ id: 2, meta: { error: '', loading: false } },
{ id: 3, meta: { error: '', loading: true } },
];
const expectedState = { ...originalState, playlists: playlistsWithTracker };
const stateResult = playlistsReducer(originalState, {
type: PLAYLIST_PROCESSING_DONE,
payload: {
playlistId: 3, trackerId: '5b0e992791ed43ca79928eed54ca0b4f',
},
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 16: should return state with meta.uploading set to false when type is UPLOAD_SUCCESS', () => {
const playlists = [
{ id: 1, meta: { error: '', uploading: true } },
{ id: 2, meta: { error: '', uploading: false } },
{ id: 3, meta: { error: '', uploading: true } },
];
const originalState = { ...initialState, playlists };
const stateResult = playlistsReducer(originalState, {
type: UPLOAD_SUCCESS,
});
stateResult.playlists.forEach((item) => {
expect(item.meta).toHaveProperty('uploading', false);
});
});
test('CASE 17: should return state with no trackerId and meta.uploading set to false when type is UPLOAD_ITEMS_ERROR or UPLOAD_ALL_CANCELLED', () => {
const playlists = [
{ id: 1, trackerId: 'a74d2e06f17e2893017431375b416b76', meta: { error: '', uploading: true } },
{ id: 2, meta: { error: '', uploading: false } },
{ id: 3, meta: { error: '', uploading: true } },
];
const originalState = { ...initialState, playlists };
const stateResult = playlistsReducer(originalState, {
type: UPLOAD_ALL_CANCELLED,
});
stateResult.playlists.forEach((item) => {
expect(item.meta).toHaveProperty('uploading', false);
expect(item).not.toHaveProperty('trackerId');
});
});
});

View File

@@ -0,0 +1,41 @@
/* global describe: true, test:true, expect:true */
import { receivers as receiversReducer, initialState } from '~/reducers/receivers';
import {
GET_RECEIVERS_TOKEN,
GET_RECEIVERS_TOKEN_SUCCESS,
GET_RECEIVERS_TOKEN_ERROR,
} from '~/store/actionTypes';
describe('receivers reducer', () => {
test('CASE 1: should return initial state', () => {
expect(receiversReducer(undefined, { type: 'Default' }))
.toEqual(initialState);
});
test('CASE 2: should return state with meta set to loading when type is GET_RECEIVERS_TOKEN', () => {
const receiversToken = { meta: { error: '', loading: true }, receiversToken: '' };
const expectedState = { ...initialState, meta: { ...initialState.meta, loading: true } };
const stateResult = receiversReducer(initialState, {
type: GET_RECEIVERS_TOKEN, payload: receiversToken,
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 3: should return state with meta set to loading when type is GET_RECEIVERS_TOKEN_SUCCESS', () => {
const receiversToken = { meta: { error: '', loading: false }, receiversToken: { meta: { error: '', loading: false } } };
const expectedState = { ...initialState, receiversToken: { meta: { error: '', loading: false } } };
const stateResult = receiversReducer(initialState, {
type: GET_RECEIVERS_TOKEN_SUCCESS, payload: receiversToken,
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 4: should return state with error when type is GET_RECEIVERS_TOKEN_ERROR', () => {
const error = { meta: { error: '', loading: false }, receiversToken: '' };
const expectedState = { ...initialState };
const stateResult = receiversReducer(initialState, {
type: GET_RECEIVERS_TOKEN_ERROR, payload: error,
});
expect(stateResult).toEqual(expectedState);
});
});

View File

@@ -0,0 +1,34 @@
/* global describe: true, test:true, expect:true */
import { settings as settingsReducer, initialState } from '~/reducers/settings';
import {
GET_SETTINGS_SUCCESS,
SET_SETTINGS_SUCCESS,
LOGOUT_SUCCESS,
} from '~/store/actionTypes';
describe('settings reducer', () => {
test('CASE 1: should return initial state', () => {
expect(settingsReducer(undefined, { type: 'Default' }))
.toEqual(initialState);
});
test('CASE 2: should empty the state on LOGOUT_SUCCESS', () => {
expect(settingsReducer({ languageCode: 'en' }, { type: LOGOUT_SUCCESS }))
.toEqual(initialState);
});
test('CASE 3: should return settings on GET_SETTINGS_SUCCESS', () => {
const settings = { autoAcceptFriend: true, defaultPlaylistId: 123 };
const expectedState = { ...initialState, ...settings };
expect(settingsReducer(undefined, { type: GET_SETTINGS_SUCCESS, payload: { settings } }))
.toEqual(expectedState);
});
test('CASE 3: should return settings on SET_SETTINGS_SUCCESS', () => {
const settings = { defaultPlaylistId: 123 };
const existingState = { autoAcceptFriend: false, defaultPlaylistId: -1 };
const expectedState = { ...existingState, ...settings };
expect(settingsReducer(existingState, { type: SET_SETTINGS_SUCCESS, payload: { settings } }))
.toEqual(expectedState);
});
});

View File

@@ -0,0 +1,140 @@
/* global describe: true, test:true, expect:true */
import {
shareExtension as shareExtReducer,
initialState,
} from '~/reducers/shareExtension';
import {
SET_SHARE_EXT,
DEFAULT_SHARE_EXT,
LOGOUT_SUCCESS,
GET_SHARE_EXT_DATA,
GET_SHARE_EXT_DATA_SUCCESS,
GET_SHARE_EXT_DATA_ERROR,
} from '~/store/actionTypes';
describe('shareExtension reducer', () => {
test('CASE 1: should return initial state', () => {
expect(shareExtReducer(undefined, { type: 'Default' }))
.toEqual(initialState);
});
test('CASE 2: should empty the state on LOGOUT_SUCCESS', () => {
expect(shareExtReducer({}, { type: LOGOUT_SUCCESS }))
.toEqual(initialState);
});
test('CASE 3: should return share extension on DEFAULT_SHARE_EXT', () => {
const expectedState = { ...initialState };
expect(shareExtReducer(undefined, { type: DEFAULT_SHARE_EXT, payload: { } }))
.toEqual(expectedState);
});
test('CASE 4: should return share extension on SET_SHARE_EXT', () => {
const albumId = 123;
const shareExtension = { albumId };
const expectedState = { ...initialState, ...shareExtension };
expect(shareExtReducer(initialState, { type: SET_SHARE_EXT, payload: { albumId } }))
.toEqual(expectedState);
});
test('CASE 5: should return share extension on GET_SHARE_EXT_DATA', () => {
const shareExtension = { images: [], meta: { loading: true, error: '' } };
const expectedState = { ...initialState, ...shareExtension };
expect(shareExtReducer(initialState, { type: GET_SHARE_EXT_DATA, payload: { props1: '', props2: [] } }))
.toEqual(expectedState);
});
test('CASE 6: should return share extension on GET_SHARE_EXT_DATA_SUCCESS', () => {
const images = [
{
meta: { loading: false, error: '' },
fullFilePath: '/data/user/0/com.creedon.Nixplay.qa/cache/IMG_8246.JPG',
uri: 'file:///data/user/0/com.creedon.Nixplay.qa/cache/IMG_8246.JPG',
type: 'jpg',
fileSize: '27209639',
caption: '',
mime: 'jpg',
fileName: 'IMG_8246.JPG',
id: 'id1',
},
{
meta: { loading: false, error: '' },
fullFilePath: '/data/user/0/com.creedon.Nixplay.qa/cache/IMG_8244.JPG',
uri: 'file:///data/user/0/com.creedon.Nixplay.qa/cache/IMG_8244.JPG',
type: 'jpg',
fileSize: '54096296',
caption: '',
mime: 'jpg',
fileName: 'IMG_8244.JPG',
id: 'id2',
}];
const shareExtension = { images, meta: { loading: false, error: '' } };
const expectedState = { ...initialState, ...shareExtension };
expect(shareExtReducer(initialState, { type: GET_SHARE_EXT_DATA_SUCCESS, payload: { images } }))
.toEqual(expectedState);
});
test('CASE 7: should return share extension on GET_SHARE_EXT_DATA_ERROR', () => {
const shareExtension = { images: [], meta: { loading: false, error: 'error' } };
const expectedState = { ...initialState, ...shareExtension };
expect(shareExtReducer(initialState, { type: GET_SHARE_EXT_DATA_ERROR, payload: { error: 'error' } }))
.toEqual(expectedState);
});
test('CASE 8: should return update caption share extension on GET_SHARE_EXT_DATA_SUCCESS SET_SHARE_EXT', () => {
const images = [
{
meta: { loading: false, error: '' },
fullFilePath: '/data/user/0/com.creedon.Nixplay.qa/cache/IMG_8246.JPG',
uri: 'file:///data/user/0/com.creedon.Nixplay.qa/cache/IMG_8246.JPG',
type: 'jpg',
fileSize: '27209639',
caption: '',
mime: 'jpg',
fileName: 'IMG_8246.JPG',
id: 'id1',
},
{
meta: { loading: false, error: '' },
fullFilePath: '/data/user/0/com.creedon.Nixplay.qa/cache/IMG_8244.JPG',
uri: 'file:///data/user/0/com.creedon.Nixplay.qa/cache/IMG_8244.JPG',
type: 'jpg',
fileSize: '54096296',
caption: '',
mime: 'jpg',
fileName: 'IMG_8244.JPG',
id: 'id2',
}];
const shareExtension = { images, meta: { loading: false, error: '' } };
const expectedState = { ...initialState, ...shareExtension };
expect(shareExtReducer(initialState, { type: GET_SHARE_EXT_DATA_SUCCESS, payload: { images } }))
.toEqual(expectedState);
const images2 = [
{
meta: { loading: false, error: '' },
fullFilePath: '/data/user/0/com.creedon.Nixplay.qa/cache/IMG_8246.JPG',
uri: 'file:///data/user/0/com.creedon.Nixplay.qa/cache/IMG_8246.JPG',
type: 'jpg',
fileSize: '27209639',
caption: 'caption1',
mime: 'jpg',
fileName: 'IMG_8246.JPG',
id: 'id1',
},
{
meta: { loading: false, error: '' },
fullFilePath: '/data/user/0/com.creedon.Nixplay.qa/cache/IMG_8244.JPG',
uri: 'file:///data/user/0/com.creedon.Nixplay.qa/cache/IMG_8244.JPG',
type: 'jpg',
fileSize: '54096296',
caption: 'caption2',
mime: 'jpg',
fileName: 'IMG_8244.JPG',
id: 'id2',
}];
const expectedState2 = { ...initialState, ...shareExtension, images: images2 };
expect(shareExtReducer(initialState, { type: SET_SHARE_EXT, payload: { images: images2 } }))
.toEqual(expectedState2);
});
});

View File

@@ -0,0 +1,223 @@
/* global describe: true, test:true, expect:true */
/* eslint-disable max-len */
import { upload as uploadReducer, initialState } from '~/reducers/upload';
import {
UPLOAD_ITEM_STARTED,
UPLOAD_SUCCESS,
UPLOAD_ITEMS,
UPLOAD_ITEMS_STATE_CHANGED,
UPLOAD_ITEMS_ERROR,
} from '~/store/actionTypes';
import {
UPLOAD_STATUS_COMPLETED,
UPLOAD_STATUS_UPLOADING,
UPLOAD_STATUS_ERROR,
} from '~/lib/uploaders/constants';
describe('Upload reducer', () => {
test('CASE 1: should return initial state', () => {
expect(uploadReducer(undefined, { type: 'Default' }))
.toEqual(initialState);
});
test('CASE 2: should return new state with items when type is UPLOAD_ITEMS', () => {
const items = [{ uri: '1.jpg' }, { uri: '2.jpg' }];
const stateResult = uploadReducer(undefined, { type: UPLOAD_ITEMS, payload: { items } });
expect(stateResult).toHaveProperty('items');
expect(stateResult.items).toHaveLength(items.length);
stateResult.items.forEach(item => {
expect(item).toHaveProperty('meta');
});
});
test('CASE 3: should return state with loading when type is UPLOAD_ITEM_STARTED', () => {
const expectedState = { ...initialState, meta: { ...initialState.meta, loading: true } };
expect(uploadReducer(initialState, { type: UPLOAD_ITEM_STARTED })).toEqual(expectedState);
});
test('CASE 4: should return empty items with meta property when type is UPLOAD_SUCCESS', () => {
const expectedState = {
items: [],
meta: {
error: '',
status: UPLOAD_STATUS_COMPLETED,
loading: false,
elapsed: 0,
},
receivers: [],
};
expect(uploadReducer(initialState, { type: UPLOAD_SUCCESS })).toEqual(expectedState);
});
test('CASE 5: should return items with meta property when type is UPLOAD_ITEMS_STATE_CHANGED', () => {
// add pending items
const items = [{ fullFilePath: '1.jpg' }, { fullFilePath: '2.jpg' }];
const item = { fullFilePath: '1.jpg', progress: 1 };
const pendingItemState = uploadReducer(initialState, { type: UPLOAD_ITEMS, payload: { items } });
const stateResult = uploadReducer(
pendingItemState,
{
type: UPLOAD_ITEMS_STATE_CHANGED,
payload: {
item,
elapsed: 1,
},
},
);
const expectedState = {
items: [{
fullFilePath: '1.jpg',
meta: {
progress: 1,
error: '',
status: UPLOAD_STATUS_UPLOADING,
loading: true,
},
}, {
fullFilePath: '2.jpg',
meta: {
progress: 0.0,
error: '',
status: UPLOAD_STATUS_UPLOADING,
loading: true,
},
}],
meta: {
error: '',
status: UPLOAD_STATUS_UPLOADING,
loading: true,
elapsed: 1,
},
};
stateResult.items.forEach(i => {
expect(i).toHaveProperty('meta');
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 6: should return correct state when type is UPLOAD_ITEMS_ERROR', () => {
const items = [{ fullFilePath: '1.jpg' }, { fullFilePath: '2.jpg' }];
const item = { fullFilePath: '1.jpg', error: 'error' };
const pendingItemState = uploadReducer(initialState, { type: UPLOAD_ITEMS, payload: { items } });
const stateResult = uploadReducer(
pendingItemState,
{
type: UPLOAD_ITEMS_ERROR,
payload: {
item,
error: item.error,
},
},
);
const expectedState = {
items: [],
meta: {
error: 'error',
status: UPLOAD_STATUS_ERROR,
loading: false,
elapsed: 0,
},
};
expect(stateResult).toEqual(expectedState);
});
// test('CASE 6: should return state with album loading to TRUE when type is GET_ALBUM_CONTENT', () => {
// const albums = [{ id: 1 }, { id: 2 }];
// const payload = {
// albumId: 1,
// };
// const originalState = { ...initialState, albums, meta: { error: '' } };
// const stateResult = uploadReducer({ ...originalState, albums, meta: { error: '' } }, {
// type: GET_ALBUM_CONTENT,
// payload,
// });
// const expectedState = {
// albums: [{
// id: 1,
// meta: { error: '', loading: true },
// },
// { id: 2 }],
// meta: { error: '' },
// };
// expect(stateResult).toEqual(expectedState);
// });
// test('CASE 7: should return state with album content when type is GET_ALBUM_CONTENT_SUCCESS', () => {
// const albums = [{ id: 1 }, { id: 2 }];
// const content = {
// name: 'album name',
// photos: [
// { id: 4 },
// { id: 5 },
// ],
// };
// const payload = {
// albumId: 1,
// content,
// };
// const originalState = { ...initialState, albums, meta: { error: '' } };
// const stateResult = uploadReducer({ ...originalState, albums, meta: { error: '' } }, {
// type: GET_ALBUM_CONTENT_SUCCESS,
// payload,
// });
// const expectedState = {
// albums: [{
// id: 1,
// content,
// meta: { error: '', loading: false },
// },
// { id: 2 }],
// meta: { error: '' },
// };
// expect(stateResult).toEqual(expectedState);
// });
// test('CASE 8: should return state with album error when type is GET_ALBUM_CONTENT_ERROR', () => {
// const albums = [{ id: 1 }, { id: 2 }];
// const albumErr = new Error('getAlbumsContentError');
// const payload = {
// albumId: 1,
// error: albumErr,
// };
// const originalState = { ...initialState, albums, meta: { error: '' } };
// const stateResult = uploadReducer({ ...originalState, albums, meta: { error: '' } }, {
// type: GET_ALBUM_CONTENT_ERROR,
// payload,
// });
// const expectedState = {
// albums: [{
// id: 1,
// meta: { error: albumErr, loading: false },
// },
// { id: 2 }],
// meta: { error: '' },
// };
// expect(stateResult).toEqual(expectedState);
// });
// test('CASE 9: should return state with album error when type is CREATE_ALBUM_SUCCESS', () => {
// const albums = [{ id: 1 }, { id: 2 }];
// const payload = {
// album: { id: 3 },
// };
// const originalState = { ...initialState, albums, meta: { error: '' } };
// const stateResult = uploadReducer({ ...originalState, albums, meta: { error: '' } }, {
// type: CREATE_ALBUM_SUCCESS,
// payload,
// });
// const expectedState = {
// albums: [
// { id: 1 },
// { id: 2 },
// { id: 3, meta: { error: '', loading: false } },
// ],
// meta: { error: '', loading: false },
// };
// expect(stateResult).toEqual(expectedState);
// });
// test('CASE 10: should empty the state on LOGOUT_SUCCESS', () => {
// const existingState = [{ id: 1 }, { id: 2 }];
// expect(uploadReducer(existingState, { type: LOGOUT_SUCCESS }))
// .toEqual(initialState);
// });
});

View File

@@ -0,0 +1,73 @@
/* global describe: true, test:true, expect:true */
import { user } from '~/reducers/user';
import {
SUBMIT_LOGIN_SUCCESS,
LOGOUT_SUCCESS,
} from '~/store/actionTypes';
describe('user reducer', () => {
test('CASE 1: should return initial state', () => {
const expectedState = {
checkUserStorage: false,
showLanguageChangedDialog: false,
enableLanguageDiscrepancyPopup: false,
displayUploadDialogue: true,
showStorageFull: false,
showLanguageDiscrepancy: false,
meta: { loading: false, error: '' },
isFullStoragePopup: false,
todo: {
avatar: {
avatarChanged: true,
tutorialDismissed: false,
},
},
};
expect(user(undefined, {}))
.toEqual(expectedState);
});
test('CASE 2: should return correct state when actionType is `SUBMIT_LOGIN_SUCCESS`', () => {
const expectedState = {
token: 'token',
username: 'username',
email: 'email@email.com',
firstName: 'first',
lastName: 'last',
checkUserStorage: true,
meta: { loading: false, error: '' },
isFullStoragePopup: false,
todo: {
avatar: {
avatarChanged: true,
tutorialDismissed: false,
},
},
};
expect(user({}, { type: SUBMIT_LOGIN_SUCCESS, payload: { user: expectedState } }))
.toEqual(expectedState);
});
test('CASE 3: should return correct state when actionType is `LOGOUT_SUCCESS`', () => {
const enableLanguageDiscrepancyPopup = false;
const expectedState = {
checkUserStorage: false,
displayUploadDialogue: true,
showLanguageChangedDialog: false,
enableLanguageDiscrepancyPopup,
showStorageFull: false,
showLanguageDiscrepancy: false,
meta: { loading: false, error: '' },
isFullStoragePopup: false,
todo: {
avatar: {
avatarChanged: true,
tutorialDismissed: false,
},
},
};
expect(user({ enableLanguageDiscrepancyPopup }, { type: LOGOUT_SUCCESS, payload: { user: expectedState } }))
.toEqual(expectedState);
});
});

View File

@@ -0,0 +1,62 @@
/* global describe: true, test:true, expect:true */
import {
userActivities as userActivitiesReducer,
initialState,
} from '~/reducers/userActivities';
import {
GET_USER_ACTIVITIES,
GET_USER_ACTIVITIES_SUCCESS,
GET_USER_ACTIVITIES_ERROR,
SET_SHOWN_MEDIA_STATUS,
LOGOUT_SUCCESS,
} from '~/store/actionTypes';
describe('user activities reducer', () => {
test('CASE 1: should return initial state', () => {
expect(userActivitiesReducer(undefined, { type: 'Default' }))
.toEqual(initialState);
});
test('CASE 2: should return state with meta set to loading when type is GET_USER_ACTIVITIES', () => {
const expectedState = { ...initialState, meta: { ...initialState.meta, loading: true, error: '' } };
const stateResult = userActivitiesReducer(initialState, {
type: GET_USER_ACTIVITIES, payload: {},
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 3: should return state with meta set to loading when type is GET_USER_ACTIVITIES_SUCCESS', () => {
const activities = [{ mediaExchange: {} }];
const meta = { loading: false, error: '' };
const stateResult = userActivitiesReducer(initialState, {
type: GET_USER_ACTIVITIES_SUCCESS, payload: { activities: { activities } },
});
expect(stateResult).toHaveProperty('meta', meta);
});
test('CASE 4: should return state with error when type is GET_USER_ACTIVITIES_ERROR', () => {
const error = new Error('getFriendsError');
const expectedState = {
...initialState,
meta: { ...initialState.meta, error, loading: false },
};
const stateResult = userActivitiesReducer(initialState, {
type: GET_USER_ACTIVITIES_ERROR, payload: { error },
});
expect(stateResult).toEqual(expectedState);
});
test('CASE 5: should update isShown state when type is SET_SHOWN_MEDIA_STATUS', (isShown = false) => {
const stateResult = userActivitiesReducer(initialState, {
type: SET_SHOWN_MEDIA_STATUS,
payload: { isShown },
});
expect(stateResult).toEqual(initialState);
});
test('CASE 6: should empty the state on LOGOUT_SUCCESS', () => {
const existingState = {};
expect(userActivitiesReducer(existingState, { type: LOGOUT_SUCCESS }))
.toEqual(initialState);
});
});