test(ext/shared): cover StateHost registration + reset (Plan C Phase 1)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
adlee-was-taken
2026-05-30 21:47:05 -04:00
parent 3f2e43753d
commit 31ed5c0384

View File

@@ -0,0 +1,92 @@
import { beforeEach, describe, expect, it, vi } from 'vitest';
import {
registerHost,
__resetHostForTests,
getState,
setState,
navigate,
sendMessage,
} from '../state';
import type { StateHost } from '../state';
import type { PopupState } from '../popup-state';
function makeHost(initial?: Partial<PopupState>): StateHost {
let state: PopupState = {
view: 'list',
entries: [],
selectedId: null,
selectedItem: null,
selectedIndex: 0,
searchQuery: '',
activeGroup: null,
error: null,
loading: false,
capturedTabId: null,
capturedUrl: '',
newType: null,
vaultSettings: null,
generatorDefaults: null,
historyItemId: null,
...initial,
};
return {
getState: () => state,
setState: (partial) => { state = { ...state, ...partial }; },
navigate: vi.fn(),
sendMessage: vi.fn().mockResolvedValue({ ok: true }),
escapeHtml: (s) => s,
popOutToTab: vi.fn(),
isInTab: () => false,
openVaultTab: vi.fn(),
};
}
describe('shared/state', () => {
beforeEach(() => {
__resetHostForTests();
});
it('register-then-getState round-trips', () => {
const host = makeHost({ view: 'detail' });
registerHost(host);
expect(getState().view).toBe('detail');
});
it('double-register throws', () => {
registerHost(makeHost());
expect(() => registerHost(makeHost())).toThrow(/already registered/);
});
it('__resetHostForTests clears the singleton', () => {
registerHost(makeHost());
__resetHostForTests();
expect(() => getState()).toThrow(/No state host/);
});
it('getState without host throws', () => {
expect(() => getState()).toThrow(/No state host/);
});
it('setState merges partial state', () => {
const host = makeHost();
registerHost(host);
setState({ loading: true });
expect(getState().loading).toBe(true);
});
it('navigate delegates to host', () => {
const host = makeHost();
registerHost(host);
navigate('settings');
expect(host.navigate).toHaveBeenCalledWith('settings', undefined);
});
it('sendMessage delegates to host', async () => {
const host = makeHost();
registerHost(host);
const resp = await sendMessage({ type: 'is_unlocked' });
expect(host.sendMessage).toHaveBeenCalledWith({ type: 'is_unlocked' });
expect(resp).toEqual({ ok: true });
});
});