| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- const test = require('node:test');
- const assert = require('node:assert/strict');
- const fs = require('node:fs');
- test('background imports tab runtime module', () => {
- const source = fs.readFileSync('background.js', 'utf8');
- assert.match(source, /background\/tab-runtime\.js/);
- });
- test('tab runtime module exposes a factory', () => {
- const source = fs.readFileSync('background/tab-runtime.js', 'utf8');
- const globalScope = {};
- const api = new Function('self', `${source}; return self.MultiPageBackgroundTabRuntime;`)(globalScope);
- assert.equal(typeof api?.createTabRuntime, 'function');
- });
- test('tab runtime waitForTabComplete waits until tab status becomes complete', async () => {
- const source = fs.readFileSync('background/tab-runtime.js', 'utf8');
- const globalScope = {};
- const api = new Function('self', `${source}; return self.MultiPageBackgroundTabRuntime;`)(globalScope);
- let getCalls = 0;
- const runtime = api.createTabRuntime({
- LOG_PREFIX: '[test]',
- addLog: async () => {},
- buildLocalhostCleanupPrefix: () => '',
- chrome: {
- tabs: {
- get: async () => {
- getCalls += 1;
- return {
- id: 9,
- url: 'https://example.com',
- status: getCalls >= 3 ? 'complete' : 'loading',
- };
- },
- query: async () => [],
- },
- },
- getSourceLabel: (source) => source || 'unknown',
- getState: async () => ({ tabRegistry: {}, sourceLastUrls: {} }),
- matchesSourceUrlFamily: () => false,
- normalizeLocalCpaStep9Mode: () => 'submit',
- parseUrlSafely: () => null,
- registerTab: async () => {},
- setState: async () => {},
- shouldBypassStep9ForLocalCpa: () => false,
- throwIfStopped: () => {},
- });
- const result = await runtime.waitForTabComplete(9, {
- timeoutMs: 2000,
- retryDelayMs: 1,
- });
- assert.equal(result?.status, 'complete');
- assert.equal(getCalls, 3);
- });
- test('tab runtime waitForTabComplete aborts promptly when stop is requested', async () => {
- const source = fs.readFileSync('background/tab-runtime.js', 'utf8');
- const globalScope = {};
- const api = new Function('self', `${source}; return self.MultiPageBackgroundTabRuntime;`)(globalScope);
- let throwCalls = 0;
- const runtime = api.createTabRuntime({
- LOG_PREFIX: '[test]',
- addLog: async () => {},
- chrome: {
- tabs: {
- get: async () => ({
- id: 9,
- url: 'https://example.com',
- status: 'loading',
- }),
- query: async () => [],
- },
- },
- getSourceLabel: (sourceName) => sourceName || 'unknown',
- getState: async () => ({ tabRegistry: {}, sourceLastUrls: {} }),
- matchesSourceUrlFamily: () => false,
- setState: async () => {},
- throwIfStopped: () => {
- throwCalls += 1;
- if (throwCalls >= 2) {
- throw new Error('Flow stopped.');
- }
- },
- });
- await assert.rejects(
- runtime.waitForTabComplete(9, {
- timeoutMs: 2000,
- retryDelayMs: 1,
- }),
- /Flow stopped\./
- );
- });
- test('tab runtime reuses an existing matching tab when registry was cleared', async () => {
- const source = fs.readFileSync('background/tab-runtime.js', 'utf8');
- const globalScope = {};
- const api = new Function('self', `${source}; return self.MultiPageBackgroundTabRuntime;`)(globalScope);
- const tabs = [
- {
- id: 21,
- url: 'https://mail.phplife.net/?_task=mail&_mbox=INBOX',
- status: 'complete',
- active: false,
- },
- ];
- let state = { tabRegistry: {}, sourceLastUrls: {} };
- let createCalls = 0;
- const runtime = api.createTabRuntime({
- LOG_PREFIX: '[test]',
- addLog: async () => {},
- chrome: {
- tabs: {
- get: async (tabId) => {
- const tab = tabs.find((item) => item.id === tabId);
- if (!tab) {
- throw new Error('tab not found');
- }
- return { ...tab };
- },
- query: async () => tabs.map((tab) => ({ ...tab })),
- update: async (tabId, updates) => {
- const tab = tabs.find((item) => item.id === tabId);
- Object.assign(tab, updates);
- return { ...tab };
- },
- create: async () => {
- createCalls += 1;
- throw new Error('should not create a new tab');
- },
- remove: async () => {},
- },
- },
- getSourceLabel: (sourceName) => sourceName || 'unknown',
- getState: async () => state,
- matchesSourceUrlFamily: (sourceName, candidateUrl, referenceUrl) => (
- sourceName === 'mail-phplife' && candidateUrl === referenceUrl
- ),
- setState: async (updates) => {
- state = { ...state, ...updates };
- },
- throwIfStopped: () => {},
- });
- const tabId = await runtime.reuseOrCreateTab(
- 'mail-phplife',
- 'https://mail.phplife.net/?_task=mail&_mbox=INBOX'
- );
- assert.equal(tabId, 21);
- assert.equal(createCalls, 0);
- assert.equal(state.tabRegistry['mail-phplife']?.tabId, 21);
- });
|