100 lines
3.3 KiB
TypeScript
100 lines
3.3 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
import { invokeIpc } from '@/lib/api-client';
|
|
import { useSettingsStore } from '@/stores/settings';
|
|
import { useUpdateStore } from '@/stores/update';
|
|
|
|
vi.mock('@/lib/api-client', () => ({
|
|
invokeIpc: vi.fn(),
|
|
}));
|
|
|
|
const invokeIpcMock = vi.mocked(invokeIpc);
|
|
const ipcOn = vi.mocked(window.electron.ipcRenderer.on);
|
|
|
|
describe('update store initialization', () => {
|
|
beforeEach(() => {
|
|
vi.useFakeTimers();
|
|
vi.clearAllMocks();
|
|
useSettingsStore.setState({
|
|
autoCheckUpdate: true,
|
|
autoDownloadUpdate: false,
|
|
});
|
|
useUpdateStore.setState({
|
|
status: 'idle',
|
|
currentVersion: '0.0.0',
|
|
updateInfo: null,
|
|
progress: null,
|
|
error: null,
|
|
isInitialized: false,
|
|
isInitializing: false,
|
|
autoInstallCountdown: null,
|
|
});
|
|
invokeIpcMock.mockImplementation(async (channel) => {
|
|
if (channel === 'update:version') return '0.9.1';
|
|
if (channel === 'update:status') return { status: 'idle' };
|
|
if (channel === 'update:check') {
|
|
return { success: true, status: { status: 'not-available' } };
|
|
}
|
|
return undefined;
|
|
});
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.clearAllTimers();
|
|
vi.useRealTimers();
|
|
});
|
|
|
|
it('initializes concurrent callers once and schedules one delayed startup check', async () => {
|
|
let resolveVersion!: (version: string) => void;
|
|
const versionPromise = new Promise<string>((resolve) => {
|
|
resolveVersion = resolve;
|
|
});
|
|
invokeIpcMock.mockImplementation(async (channel) => {
|
|
if (channel === 'update:version') return versionPromise;
|
|
if (channel === 'update:status') return { status: 'idle' };
|
|
if (channel === 'update:check') {
|
|
return { success: true, status: { status: 'not-available' } };
|
|
}
|
|
return undefined;
|
|
});
|
|
|
|
const first = useUpdateStore.getState().init();
|
|
const second = useUpdateStore.getState().init();
|
|
resolveVersion('0.9.1');
|
|
await Promise.all([first, second]);
|
|
|
|
expect(invokeIpcMock).toHaveBeenCalledWith('update:version');
|
|
expect(invokeIpcMock).toHaveBeenCalledWith('update:status');
|
|
expect(invokeIpcMock.mock.calls.filter(([channel]) => channel === 'update:version')).toHaveLength(1);
|
|
expect(invokeIpcMock.mock.calls.filter(([channel]) => channel === 'update:status')).toHaveLength(1);
|
|
expect(ipcOn).toHaveBeenCalledTimes(2);
|
|
expect(vi.getTimerCount()).toBe(1);
|
|
|
|
await vi.advanceTimersByTimeAsync(10_000);
|
|
|
|
expect(invokeIpcMock).toHaveBeenCalledWith('update:check');
|
|
});
|
|
|
|
it('does not schedule a startup check when automatic checks are disabled', async () => {
|
|
useSettingsStore.setState({ autoCheckUpdate: false });
|
|
|
|
await useUpdateStore.getState().init();
|
|
|
|
expect(ipcOn).toHaveBeenCalledTimes(2);
|
|
expect(vi.getTimerCount()).toBe(0);
|
|
await vi.advanceTimersByTimeAsync(10_000);
|
|
expect(invokeIpcMock).not.toHaveBeenCalledWith('update:check');
|
|
});
|
|
|
|
it('ignores later initialization calls without adding listeners or timers', async () => {
|
|
await useUpdateStore.getState().init();
|
|
|
|
expect(ipcOn).toHaveBeenCalledTimes(2);
|
|
expect(vi.getTimerCount()).toBe(1);
|
|
|
|
await useUpdateStore.getState().init();
|
|
|
|
expect(ipcOn).toHaveBeenCalledTimes(2);
|
|
expect(vi.getTimerCount()).toBe(1);
|
|
});
|
|
});
|