Files
makelore/tests/unit/remembered-password-persistence.test.ts

96 lines
3.0 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from 'vitest';
import { safeStorage } from 'electron';
const fakeStore = vi.hoisted(() => ({
options: null as Record<string, unknown> | null,
values: new Map<string, unknown>(),
}));
vi.mock('electron-store', () => ({
default: class FakeElectronStore {
constructor(options: Record<string, unknown>) {
fakeStore.options = options;
}
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('remembered password persistence', () => {
beforeEach(() => {
vi.resetModules();
fakeStore.options = null;
fakeStore.values.clear();
});
it('stores only an OS-encrypted Main record and restores the credentials', async () => {
const firstModule = await import('@electron/services/remembered-password');
await firstModule.initializeRememberedPassword({ secureStorage: safeStorage });
await expect(firstModule.updateRememberedPassword({
username: 'zhangsan',
password: 'plain-password',
})).resolves.toBe(true);
expect(fakeStore.options).toMatchObject({
name: 'remembered-password',
configFileMode: 0o600,
});
const serializedStore = JSON.stringify(Object.fromEntries(fakeStore.values));
expect(serializedStore).not.toContain('zhangsan');
expect(serializedStore).not.toContain('plain-password');
vi.resetModules();
const restoredModule = await import('@electron/services/remembered-password');
await restoredModule.initializeRememberedPassword({ secureStorage: safeStorage });
await expect(restoredModule.getRememberedPasswordState()).resolves.toEqual({
available: true,
credentials: {
username: 'zhangsan',
password: 'plain-password',
},
});
});
it('does not offer persistence without OS credential encryption', async () => {
const passwordModule = await import('@electron/services/remembered-password');
await passwordModule.initializeRememberedPassword();
await expect(passwordModule.updateRememberedPassword({
username: 'zhangsan',
password: 'plain-password',
})).resolves.toBe(false);
await expect(passwordModule.getRememberedPasswordState()).resolves.toEqual({
available: false,
credentials: null,
});
expect(fakeStore.options).toBeNull();
});
it('discards an unreadable record without permanently disabling the feature', async () => {
const passwordModule = await import('@electron/services/remembered-password');
const persistence = {
load: vi.fn().mockRejectedValue(new Error('credential cannot be decrypted')),
save: vi.fn().mockResolvedValue(undefined),
};
await passwordModule.initializeRememberedPassword({ persistence });
expect(persistence.save).toHaveBeenCalledWith(null);
await expect(passwordModule.getRememberedPasswordState()).resolves.toEqual({
available: true,
credentials: null,
});
});
});