refactor(state): fix code quality findings for nav panel store and prefs
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { getPrefs, setPrefs } from '../prefs';
|
||||
|
||||
describe('prefs', () => {
|
||||
@@ -14,6 +14,10 @@ describe('prefs', () => {
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
it('returns defaults when localStorage empty', () => {
|
||||
expect(getPrefs()).toEqual({
|
||||
storyOpenMode: 'auto',
|
||||
@@ -27,6 +31,42 @@ describe('prefs', () => {
|
||||
setPrefs({ storyOpenMode: 'manual', actionDetailMode: 'hover' });
|
||||
expect(getPrefs().storyOpenMode).toBe('manual');
|
||||
});
|
||||
|
||||
it('migrates v1 prefs to v2 if v2 does not exist', () => {
|
||||
const v1Prefs = {
|
||||
storyOpenMode: 'manual',
|
||||
actionDetailMode: 'hover',
|
||||
collapsedActionGroups: { 'some-group': true },
|
||||
};
|
||||
localStorage.setItem('idlegame:prefs:v1', JSON.stringify(v1Prefs));
|
||||
|
||||
const migratedPrefs = getPrefs();
|
||||
|
||||
expect(migratedPrefs).toEqual({
|
||||
storyOpenMode: 'manual',
|
||||
actionDetailMode: 'hover',
|
||||
collapsedActionGroups: { 'some-group': true },
|
||||
showEventLog: true,
|
||||
});
|
||||
|
||||
const rawV2 = localStorage.getItem('idlegame:prefs:v2');
|
||||
expect(rawV2).not.toBeNull();
|
||||
expect(JSON.parse(rawV2 ?? 'null')).toEqual(migratedPrefs);
|
||||
});
|
||||
|
||||
it('returns defaults and does not migrate if v1 prefs is invalid JSON', () => {
|
||||
localStorage.setItem('idlegame:prefs:v1', '{invalid-json}');
|
||||
|
||||
const prefs = getPrefs();
|
||||
expect(prefs).toEqual({
|
||||
storyOpenMode: 'auto',
|
||||
actionDetailMode: 'inline',
|
||||
collapsedActionGroups: {},
|
||||
showEventLog: true,
|
||||
});
|
||||
|
||||
expect(localStorage.getItem('idlegame:prefs:v2')).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('expanded prefs', () => {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { getPrefs } from '../prefs';
|
||||
import { useGameStore } from '../store';
|
||||
|
||||
describe('game store nav and prefs', () => {
|
||||
@@ -12,6 +13,15 @@ describe('game store nav and prefs', () => {
|
||||
store[key] = value;
|
||||
},
|
||||
});
|
||||
useGameStore.setState({
|
||||
activePanel: 'play',
|
||||
selectedStoryNodeId: null,
|
||||
prefs: getPrefs(),
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
it('has default activePanel and selectedStoryNodeId', () => {
|
||||
|
||||
+14
-1
@@ -21,7 +21,20 @@ export function getPrefs(): GamePrefs {
|
||||
if (typeof localStorage === 'undefined') return { ...DEFAULTS };
|
||||
try {
|
||||
const raw = localStorage.getItem(PREFS_KEY);
|
||||
if (!raw) return { ...DEFAULTS };
|
||||
if (!raw) {
|
||||
const rawV1 = localStorage.getItem('idlegame:prefs:v1');
|
||||
if (rawV1) {
|
||||
try {
|
||||
const parsedV1 = JSON.parse(rawV1);
|
||||
const migrated = { ...DEFAULTS, ...parsedV1 };
|
||||
localStorage.setItem(PREFS_KEY, JSON.stringify(migrated));
|
||||
return migrated;
|
||||
} catch {
|
||||
return { ...DEFAULTS };
|
||||
}
|
||||
}
|
||||
return { ...DEFAULTS };
|
||||
}
|
||||
return { ...DEFAULTS, ...JSON.parse(raw) };
|
||||
} catch {
|
||||
return { ...DEFAULTS };
|
||||
|
||||
+6
-6
@@ -69,13 +69,13 @@ export const useGameStore = create<GameStoreState>((set) => ({
|
||||
setSettingsOpen: (open) => set({ settingsOpen: open }),
|
||||
setActivePanel: (panel) => set({ activePanel: panel }),
|
||||
setSelectedStoryNodeId: (id) => set({ selectedStoryNodeId: id }),
|
||||
toggleActionGroupCollapsed: (groupKey) =>
|
||||
set((state) => {
|
||||
toggleActionGroupCollapsed: (groupKey) => {
|
||||
const currentPrefs = useGameStore.getState().prefs;
|
||||
const nextCollapsed = {
|
||||
...state.prefs.collapsedActionGroups,
|
||||
[groupKey]: !state.prefs.collapsedActionGroups[groupKey],
|
||||
...currentPrefs.collapsedActionGroups,
|
||||
[groupKey]: !currentPrefs.collapsedActionGroups[groupKey],
|
||||
};
|
||||
const prefs = persistPrefs({ collapsedActionGroups: nextCollapsed });
|
||||
return { prefs };
|
||||
}),
|
||||
set({ prefs });
|
||||
},
|
||||
}));
|
||||
|
||||
Reference in New Issue
Block a user