Files
5chan/src/stores/__tests__/theme-store.test.ts
T

73 lines
2.2 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from 'vitest';
const testState = vi.hoisted(() => ({
entriesMock: vi.fn(async () => [] as Array<['nsfw' | 'sfw', string]>),
setItemMock: vi.fn(async () => undefined),
}));
vi.mock('@bitsocial/bitsocial-react-hooks/dist/lib/localforage-lru/index.js', () => ({
default: {
createInstance: () => ({
entries: testState.entriesMock,
setItem: testState.setItemMock,
}),
},
}));
const waitFor = async (predicate: () => boolean) => {
for (let i = 0; i < 20; i += 1) {
await Promise.resolve();
if (predicate()) {
return;
}
}
};
describe('useThemeStore', () => {
beforeEach(() => {
vi.resetModules();
testState.entriesMock.mockReset();
testState.entriesMock.mockResolvedValue([]);
testState.setItemMock.mockReset();
testState.setItemMock.mockResolvedValue(undefined);
});
it('loads stored themes on initialization', async () => {
testState.entriesMock.mockResolvedValue([
['nsfw', 'tomorrow'],
['sfw', 'photon'],
]);
const store = (await import('../use-theme-store')).default;
await waitFor(() => store.getState().themes.nsfw === 'tomorrow');
expect(store.getState().themes).toEqual({
nsfw: 'tomorrow',
sfw: 'photon',
});
expect(store.getState().currentTheme).toBeNull();
});
it('setTheme persists the updated theme and updates currentTheme', async () => {
const store = (await import('../use-theme-store')).default;
await waitFor(() => testState.entriesMock.mock.calls.length > 0);
await store.getState().setTheme('nsfw', 'photon');
expect(testState.setItemMock).toHaveBeenCalledWith('nsfw', 'photon');
expect(store.getState().themes.nsfw).toBe('photon');
expect(store.getState().currentTheme).toBe('photon');
});
it('getTheme can skip updating currentTheme when requested', async () => {
const store = (await import('../use-theme-store')).default;
await waitFor(() => testState.entriesMock.mock.calls.length > 0);
expect(store.getState().getTheme('sfw', false)).toBe('yotsuba-b');
expect(store.getState().currentTheme).toBeNull();
expect(store.getState().getTheme('sfw')).toBe('yotsuba-b');
expect(store.getState().currentTheme).toBe('yotsuba-b');
});
});