import { beforeEach, describe, expect, it, vi } from 'vitest'; const fakeStore = vi.hoisted(() => ({ options: null as Record | null, values: new Map(), constructorError: null as Error | null, })); vi.mock('electron-store', () => ({ default: class FakeElectronStore { constructor(options: Record) { fakeStore.options = options; if (fakeStore.constructorError && options.clearInvalidConfig !== true) { throw fakeStore.constructorError; } } get(key: string) { return fakeStore.values.get(key); } set(key: string, value: unknown) { fakeStore.values.set(key, value); } delete(key: string) { fakeStore.values.delete(key); } }, })); describe('Works Square encrypted session persistence', () => { beforeEach(() => { vi.resetModules(); fakeStore.options = null; fakeStore.values.clear(); fakeStore.constructorError = null; }); it('stores one encrypted Main-only record and restores it', async () => { const firstModule = await import('@electron/services/works-square-session'); await firstModule.initializeWorksSquareSession(); firstModule.storeWorksSquareSession({ accessToken: 'plain-access-token', refreshToken: 'plain-refresh-token', expiresAt: Date.now() + 3600_000, lastActiveAt: Date.now(), }); await firstModule.flushWorksSquareSessionPersistence(); expect(fakeStore.options).toMatchObject({ name: 'works-square-session', configFileMode: 0o600, }); const serializedStore = JSON.stringify(Object.fromEntries(fakeStore.values)); expect(serializedStore).not.toContain('plain-access-token'); expect(serializedStore).not.toContain('plain-refresh-token'); vi.resetModules(); const restoredModule = await import('@electron/services/works-square-session'); await expect(restoredModule.initializeWorksSquareSession()).resolves.toMatchObject({ accessToken: 'plain-access-token', canRefresh: true, }); }); it('preserves a temporarily unreadable record until explicit reauthorization discards it', async () => { const record = { version: 1, authBase: 'https://biz.nianxx.cn/auth/', ciphertext: Buffer.from('encrypted:not-json', 'utf8').toString('base64'), }; fakeStore.values.set('record', record); const sessionModule = await import('@electron/services/works-square-session'); await expect(sessionModule.initializeWorksSquareSession()).resolves.toBeNull(); expect(fakeStore.values.get('record')).toEqual(record); expect(sessionModule.getWorksSquareSessionRestoreStatus()).toBe('unavailable'); await expect(sessionModule.discardUnrestorableWorksSquareSession()).resolves.toBe(true); expect(fakeStore.values.has('record')).toBe(false); expect(sessionModule.getWorksSquareSessionRestoreStatus()).toBe('ready'); }); it('discards malformed store config without aborting Main startup', async () => { fakeStore.constructorError = new SyntaxError('Unexpected token in JSON'); const sessionModule = await import('@electron/services/works-square-session'); await expect(sessionModule.initializeWorksSquareSession()).resolves.toBeNull(); expect(fakeStore.options).toMatchObject({ name: 'works-square-session', configFileMode: 0o600, clearInvalidConfig: true, }); expect(sessionModule.getWorksSquareSessionRestoreStatus()).toBe('ready'); expect(sessionModule.consumeWorksSquareStartupRuntimeCleanupRequired()).toBe(true); }); });