mirror of
https://github.com/yaklang/yaklang-chrome-extension.git
synced 2026-09-23 19:51:53 +08:00
64 lines
2.9 KiB
TypeScript
64 lines
2.9 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
const fixture = vi.hoisted(() => ({
|
|
updatedListeners: [] as Array<(tabId: number, change: { url?: string; title?: string; status?: string }) => void>,
|
|
historyListeners: [] as Array<(details: { tabId: number; frameId: number }) => void>,
|
|
fragmentListeners: [] as Array<(details: { tabId: number; frameId: number }) => void>,
|
|
removedListeners: [] as Array<(tabId: number) => void>,
|
|
tabs: new Map<number, { id: number; url: string; title: string }>(),
|
|
sendMessage: vi.fn(async () => undefined),
|
|
}));
|
|
|
|
vi.mock('wxt/browser', () => ({
|
|
browser: {
|
|
tabs: {
|
|
get: vi.fn(async (tabId: number) => {
|
|
const tab = fixture.tabs.get(tabId);
|
|
if (!tab) throw new Error('missing tab');
|
|
return tab;
|
|
}),
|
|
sendMessage: fixture.sendMessage,
|
|
onUpdated: { addListener: vi.fn((listener: typeof fixture.updatedListeners[number]) => fixture.updatedListeners.push(listener)) },
|
|
onRemoved: { addListener: vi.fn((listener: typeof fixture.removedListeners[number]) => fixture.removedListeners.push(listener)) },
|
|
},
|
|
webNavigation: {
|
|
onHistoryStateUpdated: { addListener: vi.fn((listener: typeof fixture.historyListeners[number]) => fixture.historyListeners.push(listener)) },
|
|
onReferenceFragmentUpdated: { addListener: vi.fn((listener: typeof fixture.fragmentListeners[number]) => fixture.fragmentListeners.push(listener)) },
|
|
},
|
|
},
|
|
}));
|
|
|
|
import { initializeFloatingPanelLifecycle } from './lifecycle';
|
|
|
|
describe('floating panel lifecycle relay', () => {
|
|
beforeEach(() => {
|
|
vi.useFakeTimers();
|
|
fixture.tabs.clear();
|
|
fixture.sendMessage.mockClear();
|
|
});
|
|
|
|
it('coalesces SPA URL and title changes into the current main-frame snapshot', async () => {
|
|
initializeFloatingPanelLifecycle();
|
|
fixture.tabs.set(8, { id: 8, url: 'https://example.test/account/2', title: 'Account 2' });
|
|
for (const listener of fixture.historyListeners) listener({ tabId: 8, frameId: 0 });
|
|
for (const listener of fixture.updatedListeners) listener(8, { title: 'Account 2' });
|
|
await vi.advanceTimersByTimeAsync(41);
|
|
|
|
expect(fixture.sendMessage).toHaveBeenCalledTimes(1);
|
|
expect(fixture.sendMessage).toHaveBeenCalledWith(8, {
|
|
action: 'floating.tab.changed',
|
|
payload: { tabId: 8, title: 'Account 2', url: 'https://example.test/account/2' },
|
|
}, { frameId: 0 });
|
|
});
|
|
|
|
it('ignores sub-frame navigation and cancels pending work when a tab closes', async () => {
|
|
initializeFloatingPanelLifecycle();
|
|
fixture.tabs.set(9, { id: 9, url: 'https://example.test/', title: 'Fixture' });
|
|
for (const listener of fixture.fragmentListeners) listener({ tabId: 9, frameId: 2 });
|
|
for (const listener of fixture.updatedListeners) listener(9, { url: 'https://example.test/#new' });
|
|
for (const listener of fixture.removedListeners) listener(9);
|
|
await vi.advanceTimersByTimeAsync(100);
|
|
expect(fixture.sendMessage).not.toHaveBeenCalled();
|
|
});
|
|
});
|