mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-05 00:14:18 +00:00
77 lines
3.2 KiB
TypeScript
77 lines
3.2 KiB
TypeScript
// @vitest-environment node
|
|
import { describe, expect, it } from 'vitest';
|
|
import { DEFAULT_SCOPE } from '../area';
|
|
import { mailArea } from '../mail';
|
|
import type { StorageAdapter } from '../storage';
|
|
import { StoreHost, type HostStorage } from '../worker/host';
|
|
import { FAKE_SESSION } from './helpers/fake-jmap';
|
|
import { openMemoryStore } from './helpers/node-adapter';
|
|
|
|
const KEY = 'a'.repeat(64);
|
|
|
|
class FakeStorage implements HostStorage {
|
|
readonly dbs = new Map<string, StorageAdapter>();
|
|
removed: string[] = [];
|
|
files(): string[] {
|
|
return [...this.dbs.keys()];
|
|
}
|
|
async open(file: string): Promise<StorageAdapter> {
|
|
let db = this.dbs.get(file);
|
|
if (!db) {
|
|
db = openMemoryStore();
|
|
this.dbs.set(file, db);
|
|
}
|
|
// The host closes a database; the "file" stays for the next open.
|
|
return { ...db, exec: db.exec.bind(db), run: db.run.bind(db), all: db.all.bind(db), get: db.get.bind(db), transaction: db.transaction.bind(db), close() {} };
|
|
}
|
|
remove(file: string): boolean {
|
|
this.removed.push(file);
|
|
this.dbs.delete(`${file}-journal`);
|
|
return this.dbs.delete(file);
|
|
}
|
|
}
|
|
|
|
function host(storage: FakeStorage): StoreHost {
|
|
return new StoreHost({ areas: [mailArea], storage, emit: () => {}, needAuth: () => {} });
|
|
}
|
|
|
|
const params = (file: string, session: unknown = FAKE_SESSION, account = 'a') => ({
|
|
account, file, keyHex: KEY, session, scope: DEFAULT_SCOPE, invertedKeywordSort: null, auth: null,
|
|
}) as Parameters<StoreHost['openAccount']>[0];
|
|
|
|
describe('opening an account', () => {
|
|
it('says it was created, also after a first try with no session', async () => {
|
|
const storage = new FakeStorage();
|
|
await expect(host(storage).openAccount(params('/a1.db', null))).rejects.toThrow('No session');
|
|
expect(storage.files()).toEqual([]);
|
|
const running = host(storage);
|
|
expect(await running.openAccount(params('/a1.db'))).toEqual({ created: true });
|
|
await running.closeAll();
|
|
expect(await host(storage).openAccount(params('/a1.db', null))).toEqual({ created: false });
|
|
});
|
|
});
|
|
|
|
describe('removing an account', () => {
|
|
it('tells every tab, once the file is gone', async () => {
|
|
const storage = new FakeStorage();
|
|
const events: unknown[] = [];
|
|
const running = new StoreHost({ areas: [mailArea], storage, emit: (event) => events.push({ event, file: storage.files().length }), needAuth: () => {} });
|
|
await running.openAccount(params('/a1.db'));
|
|
events.length = 0;
|
|
await running.removeAccount('a', '/a1.db');
|
|
expect(events).toContainEqual({ event: { type: 'removed', account: 'a' }, file: 0 });
|
|
});
|
|
});
|
|
|
|
describe('a scope from another tab', () => {
|
|
it('reaches the engine over the channel call', async () => {
|
|
const storage = new FakeStorage();
|
|
const running = host(storage);
|
|
await running.openAccount(params('/a1.db'));
|
|
await running.call('setScope', { account: 'a', scope: { ...DEFAULT_SCOPE, days: 7 } });
|
|
const stored = storage.dbs.get('/a1.db')!.get<{ v: string }>("SELECT v FROM meta WHERE k = 'scope'");
|
|
expect(JSON.parse(String(stored?.v)).days).toBe(7);
|
|
await expect(running.call('setScope', { account: 'nobody', scope: DEFAULT_SCOPE })).rejects.toMatchObject({ name: 'StoreAccountClosedError' });
|
|
});
|
|
});
|