| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531 |
- import {
- ActionClientListUpdated,
- ActionStateSetLocal,
- ActionStateSetRemote,
- ActionTypeLocal,
- ActionTypeRemote,
- masterSet,
- nameSet,
- playPaused,
- seeked,
- songInfoFetched,
- stateSet,
- } from '../actions';
- import { Song } from '../types';
- import { MusicPlayer } from '../types/state';
- import { globalReducer, initialState, nullPlayer } from './reducer';
- import { GlobalState } from './types';
- describe(globalReducer.name, () => {
- describe(ActionTypeRemote.StateSet, () => {
- describe('when the client is master', () => {
- const stateMaster: GlobalState = {
- ...initialState,
- player: {
- ...nullPlayer,
- master: 'some-master-client',
- currentTime: 31,
- seekTime: -1,
- },
- myClientName: 'some-master-client',
- };
- describe('and the action came from a different client', () => {
- const actionFromOtherClient: ActionStateSetRemote = {
- type: ActionTypeRemote.StateSet,
- fromClient: 'other-client',
- payload: {
- songId: 123,
- playing: true,
- currentTime: 75,
- seekTime: 87,
- master: 'some-master-client',
- queue: [],
- },
- };
- it('should update the state, including seekTime', () => {
- expect.assertions(1);
- const result = globalReducer(stateMaster, actionFromOtherClient);
- expect(result.player).toStrictEqual<MusicPlayer>({
- songId: 123,
- playing: true,
- currentTime: 75,
- seekTime: 87,
- master: 'some-master-client',
- queue: [],
- });
- });
- });
- describe('and the action came from ourselves', () => {
- const actionFromOurselves: ActionStateSetRemote = {
- type: ActionTypeRemote.StateSet,
- fromClient: 'some-master-client',
- payload: {
- songId: 123,
- playing: true,
- currentTime: 75,
- seekTime: 87,
- master: 'some-master-client',
- queue: [],
- },
- };
- it('should update the state, except the seekTime', () => {
- expect.assertions(1);
- const result = globalReducer(stateMaster, actionFromOurselves);
- expect(result.player).toStrictEqual<MusicPlayer>({
- songId: 123,
- playing: true,
- currentTime: 75,
- seekTime: -1,
- master: 'some-master-client',
- queue: [],
- });
- });
- });
- describe('but will no longer be master', () => {
- const actionToSlave: ActionStateSetRemote = {
- type: ActionTypeRemote.StateSet,
- fromClient: 'other-client',
- payload: {
- songId: 123,
- playing: true,
- currentTime: 75,
- seekTime: 87,
- master: 'other-master-client',
- queue: [],
- },
- };
- it('should update the state, setting seekTime to -1', () => {
- expect.assertions(1);
- const result = globalReducer(stateMaster, actionToSlave);
- expect(result.player).toStrictEqual<MusicPlayer>({
- songId: 123,
- playing: true,
- currentTime: 75,
- seekTime: -1,
- master: 'other-master-client',
- queue: [],
- });
- });
- });
- });
- describe('when the client is a slave', () => {
- const stateSlave: GlobalState = {
- ...initialState,
- player: {
- ...initialState.player,
- master: 'some-master-client',
- },
- myClientName: 'my-client',
- };
- describe.each`
- case | fromClient
- ${'the master client'} | ${'some-master-client'}
- ${'a different client'} | ${'other-client'}
- `('and the action came from $case', ({ fromClient }) => {
- const action: ActionStateSetRemote = {
- type: ActionTypeRemote.StateSet,
- fromClient,
- payload: {
- songId: 123,
- playing: true,
- currentTime: 75,
- seekTime: 87,
- master: 'some-master-client',
- queue: [],
- },
- };
- it('should set the player state, except seekTime', () => {
- expect.assertions(1);
- const result = globalReducer(stateSlave, action);
- expect(result.player).toStrictEqual<MusicPlayer>({
- songId: 123,
- playing: true,
- currentTime: 75,
- seekTime: -1,
- master: 'some-master-client',
- queue: [],
- });
- });
- });
- describe('but will be set to master', () => {
- const actionToMaster: ActionStateSetRemote = {
- type: ActionTypeRemote.StateSet,
- fromClient: 'other-client',
- payload: {
- songId: 123,
- playing: true,
- currentTime: 75,
- seekTime: 87,
- master: 'my-client',
- queue: [],
- },
- };
- it('should set the player state, including seekTime', () => {
- expect.assertions(1);
- const result = globalReducer(stateSlave, actionToMaster);
- expect(result.player).toStrictEqual<MusicPlayer>({
- songId: 123,
- playing: true,
- currentTime: 75,
- seekTime: 87,
- master: 'my-client',
- queue: [],
- });
- });
- });
- });
- });
- describe(ActionTypeRemote.ClientListUpdated, () => {
- const action: ActionClientListUpdated = {
- type: ActionTypeRemote.ClientListUpdated,
- payload: [
- {
- name: 'client1-ab54x',
- lastPing: 1665912239,
- },
- {
- name: 'client1-ab54x',
- lastPing: 1665912262,
- },
- ],
- };
- it('should update the client list', () => {
- expect.assertions(1);
- const result = globalReducer(initialState, action);
- expect(result.clientList).toStrictEqual(action.payload);
- });
- });
- describe(ActionTypeLocal.NameSet, () => {
- it('should set the name', () => {
- expect.assertions(1);
- expect(globalReducer(initialState, nameSet('foo')).myClientName).toBe('foo');
- });
- });
- describe(ActionTypeLocal.StateSet, () => {
- const action = stateSet({
- songId: 123,
- playing: true,
- currentTime: 75,
- seekTime: 87,
- master: 'some-master-client',
- });
- describe('when the client is master', () => {
- const stateMaster: GlobalState = {
- ...initialState,
- player: {
- ...nullPlayer,
- master: 'some-master-client',
- currentTime: 31,
- seekTime: -1,
- },
- myClientName: 'some-master-client',
- };
- it('should set the player state optimistically', () => {
- expect.assertions(1);
- const result = globalReducer(stateMaster, action);
- expect(result.player).toStrictEqual<MusicPlayer>({
- songId: 123,
- playing: true,
- currentTime: 75,
- seekTime: 87,
- master: 'some-master-client',
- queue: [],
- });
- });
- describe('when the state update is partial', () => {
- const actionPartial: ActionStateSetLocal = stateSet({
- songId: 3,
- playing: true,
- });
- it('should update the given part of the state', () => {
- expect.assertions(1);
- const result = globalReducer(stateMaster, actionPartial);
- expect(result.player).toStrictEqual<MusicPlayer>({
- ...nullPlayer,
- master: 'some-master-client',
- currentTime: 31,
- seekTime: -1,
- songId: 3,
- playing: true,
- });
- });
- });
- });
- describe('when the client is a slave', () => {
- const stateSlave: GlobalState = {
- ...initialState,
- player: {
- ...initialState.player,
- master: 'some-master-client',
- },
- myClientName: 'my-client',
- };
- it('should not update the state optimistically', () => {
- expect.assertions(1);
- const result = globalReducer(stateSlave, action);
- expect(result.player).toBe(stateSlave.player);
- });
- describe('but will be master', () => {
- const actionToMaster = stateSet({
- master: 'my-client',
- });
- it('should set the seekTime to the currentTime value', () => {
- expect.assertions(1);
- const result = globalReducer(stateSlave, actionToMaster);
- expect(result.player.seekTime).toBe(stateSlave.player.currentTime);
- });
- });
- });
- });
- describe(ActionTypeLocal.Seeked, () => {
- const action = seeked(173);
- describe('when the client is master', () => {
- const stateMaster: GlobalState = {
- ...initialState,
- player: {
- songId: 123,
- playing: true,
- currentTime: 31,
- seekTime: -1,
- master: 'some-master-client',
- queue: [],
- },
- myClientName: 'some-master-client',
- };
- it('should set the seek time', () => {
- expect.assertions(1);
- const result = globalReducer(stateMaster, action);
- expect(result.player).toStrictEqual<MusicPlayer>({
- songId: 123,
- playing: true,
- currentTime: 31,
- seekTime: 173,
- master: 'some-master-client',
- queue: [],
- });
- });
- });
- describe('when the client is a slave', () => {
- const stateSlave: GlobalState = {
- ...initialState,
- player: {
- ...initialState.player,
- seekTime: 101,
- master: 'some-master-client',
- },
- myClientName: 'my-client',
- };
- it('should not update the player', () => {
- expect.assertions(1);
- const result = globalReducer(stateSlave, action);
- expect(result.player).toBe(stateSlave.player);
- });
- });
- });
- describe(ActionTypeLocal.MasterSet, () => {
- const action = masterSet();
- const stateBefore: GlobalState = {
- ...initialState,
- myClientName: 'my-client',
- player: {
- songId: 174,
- playing: true,
- master: 'some-master-client',
- currentTime: 13,
- seekTime: -1,
- queue: [],
- },
- };
- it('should set the master player to the current client', () => {
- expect.assertions(1);
- const result = globalReducer(stateBefore, action);
- expect(result.player.master).toBe('my-client');
- });
- it('should seek to the current time', () => {
- expect.assertions(1);
- const result = globalReducer(stateBefore, action);
- expect(result.player.seekTime).toBe(13);
- });
- it('should pause the client', () => {
- expect.assertions(1);
- const result = globalReducer(stateBefore, action);
- expect(result.player.playing).toBe(false);
- });
- describe('when a particular client is given in the action', () => {
- const actionToOtherClient = masterSet('other-client');
- it('should set the master player to the given client', () => {
- expect.assertions(2);
- const result = globalReducer(stateBefore, actionToOtherClient);
- expect(result.player.master).toBe('other-client');
- expect(result.player.seekTime).toBe(stateBefore.player.currentTime);
- });
- it('should not pause the client', () => {
- expect.assertions(1);
- const result = globalReducer(stateBefore, actionToOtherClient);
- expect(result.player.playing).toBe(true);
- });
- });
- });
- describe(ActionTypeLocal.PlayPaused, () => {
- const action = playPaused();
- describe('when the current client is master', () => {
- const stateMaster: GlobalState = {
- ...initialState,
- myClientName: 'my-client',
- player: {
- ...nullPlayer,
- master: 'my-client',
- },
- };
- describe('when playing', () => {
- const statePlaying: GlobalState = {
- ...stateMaster,
- player: {
- ...stateMaster.player,
- songId: 123,
- playing: true,
- },
- };
- it('should set playing=false', () => {
- expect.assertions(1);
- const result = globalReducer(statePlaying, action);
- expect(result.player).toStrictEqual<MusicPlayer>({
- ...stateMaster.player,
- songId: 123,
- playing: false,
- });
- });
- });
- describe('when not playing', () => {
- const statePaused: GlobalState = {
- ...stateMaster,
- player: {
- ...stateMaster.player,
- songId: 123,
- playing: false,
- },
- };
- it('should set playing=true', () => {
- expect.assertions(1);
- const result = globalReducer(statePaused, action);
- expect(result.player).toStrictEqual<MusicPlayer>({
- ...stateMaster.player,
- songId: 123,
- playing: true,
- });
- });
- });
- });
- describe('when the current client is a slave', () => {
- const stateSlave: GlobalState = {
- ...initialState,
- myClientName: 'my-client',
- player: {
- ...initialState.player,
- songId: 123,
- playing: true,
- master: 'some-master-client',
- },
- };
- it('should not update the state optimistically', () => {
- expect.assertions(1);
- const result = globalReducer(stateSlave, action);
- expect(result.player).toBe(stateSlave.player);
- });
- });
- });
- describe(ActionTypeLocal.SongInfoFetched, () => {
- const song: Song = {
- id: 123,
- track: 17,
- title: 'Some song',
- artist: 'Some artist',
- album: 'Some album',
- time: 214,
- };
- const action = songInfoFetched(song);
- it('should set the song info in state', () => {
- expect.assertions(1);
- const result = globalReducer(initialState, action);
- expect(result.songInfo).toStrictEqual<Song>(song);
- });
- describe('when set to replace the current song', () => {
- const actionReplace = songInfoFetched(song, true);
- it('should play the given song from the start', () => {
- expect.assertions(4);
- const result = globalReducer(initialState, actionReplace);
- expect(result.songInfo).toStrictEqual<Song>(song);
- expect(result.player.playing).toBe(true);
- expect(result.player.songId).toBe(song.id);
- expect(result.player.seekTime).toBe(0);
- });
- });
- });
- });
|