diff --git a/desktop-client/state.js b/desktop-client/state.js new file mode 100644 index 0000000..511519d --- /dev/null +++ b/desktop-client/state.js @@ -0,0 +1,23 @@ +const initialState = Object.freeze({ + title: '', + artist: '', + album: '', + albumArt: '', + isPlaying: false, + progress: 0, + duration: 0, +}); + +function mergeState(current, update) { + return { + title: update.title ?? current.title, + artist: update.artist ?? current.artist, + album: update.album ?? current.album, + albumArt: update.albumArt ?? current.albumArt, + isPlaying: update.isPlaying ?? current.isPlaying, + progress: update.progress ?? current.progress, + duration: update.duration ?? current.duration, + }; +} + +module.exports = { initialState, mergeState }; diff --git a/desktop-client/tests/state.test.js b/desktop-client/tests/state.test.js new file mode 100644 index 0000000..9c9f3b6 --- /dev/null +++ b/desktop-client/tests/state.test.js @@ -0,0 +1,47 @@ +const test = require('node:test'); +const assert = require('node:assert/strict'); +const { initialState, mergeState } = require('../state'); + +test('initialState has the expected shape', () => { + assert.deepEqual(initialState, { + title: '', + artist: '', + album: '', + albumArt: '', + isPlaying: false, + progress: 0, + duration: 0, + }); +}); + +test('mergeState applies a single field update', () => { + const next = mergeState(initialState, { title: 'Foo' }); + assert.equal(next.title, 'Foo'); +}); + +test('mergeState preserves fields not present in the update', () => { + const current = { ...initialState, title: 'Old', artist: 'Bar' }; + const next = mergeState(current, { title: 'New' }); + assert.equal(next.artist, 'Bar'); +}); + +test('mergeState treats undefined fields as no-change', () => { + const current = { ...initialState, isPlaying: true }; + const next = mergeState(current, { isPlaying: undefined }); + assert.equal(next.isPlaying, true); +}); + +test('mergeState applies false as a real value (not a no-change)', () => { + const current = { ...initialState, isPlaying: true }; + const next = mergeState(current, { isPlaying: false }); + assert.equal(next.isPlaying, false); +}); + +test('mergeState does not mutate inputs', () => { + const current = { ...initialState }; + const update = { title: 'X' }; + const before = { ...current }; + mergeState(current, update); + assert.deepEqual(current, before); + assert.deepEqual(update, { title: 'X' }); +});