import test from 'node:test';
import assert from 'node:assert/strict';
import { wrapScriptCode, getTabButtons, clickTabButton } from '../src/utils/userScripts.js';
const runWrapped = async code => {
let resolveDone;
const done = new Promise(resolve => { resolveDone = resolve; });
globalThis.__resolve_done = resolveDone;
new Function(wrapScriptCode(`${code}\nglobalThis.__resolve_done();`))();
await done;
delete globalThis.__resolve_done;
return globalThis.__OpenScriptButtons;
};
test('OpenScript.button registers, clicks, and removes popup buttons', async () => {
const clicks = [];
globalThis.__clicks = clicks;
try {
const registry = await runWrapped(`
OpenScript.button('Settings', () => globalThis.__clicks.push('settings'));
const remove = OpenScript.button('Temp', () => globalThis.__clicks.push('temp'));
globalThis.__remove = remove;
`);
assert.deepEqual(registry.list(), [{ id: 1, label: 'Settings' }, { id: 2, label: 'Temp' }]);
assert.equal(registry.click(1), true);
await new Promise(resolve => setTimeout(resolve, 5));
assert.deepEqual(clicks, ['settings']);
globalThis.__remove();
assert.deepEqual(registry.list(), [{ id: 1, label: 'Settings' }]);
assert.equal(registry.click(2), false);
} finally {
delete globalThis.__clicks;
delete globalThis.__remove;
delete globalThis.__OpenScriptButtons;
delete globalThis.OpenScript;
delete globalThis.env;
}
});
test('OpenScript.button rejects missing click handlers', async () => {
let resolveDone;
const done = new Promise(resolve => { resolveDone = resolve; });
globalThis.__resolve_done = resolveDone;
try {
new Function(wrapScriptCode(`
try { OpenScript.button('Broken'); } catch (error) { globalThis.__resolve_done(error); }
`))();
const error = await done;
assert.equal(error.name, 'TypeError');
} finally {
delete globalThis.__resolve_done;
delete globalThis.__OpenScriptButtons;
delete globalThis.OpenScript;
delete globalThis.env;
}
});
test('getTabButtons queries enabled script worlds and clickTabButton targets the document', async () => {
const originalChrome = globalThis.chrome;
const calls = [];
globalThis.chrome = {
userScripts: {
execute: async injection => {
calls.push(injection);
if (injection.worldId === 'broken') throw new Error('Cannot access a chrome:// URL');
if (injection.js[0].code.includes('.click(')) return [{ documentId: 'doc1', result: true }];
return injection.worldId === 'a'
? [{ documentId: 'doc1', result: [{ id: 1, label: 'Settings' }] }]
: [{ documentId: 'doc1', result: undefined }];
},
},
};
try {
const buttons = await getTabButtons(7, [
{ id: 'a', enabled: true },
{ id: 'b', enabled: true },
{ id: 'off', enabled: false },
{ id: 'broken', enabled: true },
]);
assert.deepEqual(buttons, { a: [{ id: 1, label: 'Settings', documentId: 'doc1' }] });
assert.deepEqual(calls.map(c => c.worldId), ['a', 'b', 'broken']);
assert.deepEqual(calls[0].target, { tabId: 7 });
assert.equal(await clickTabButton(7, 'a', buttons.a[0]), true);
assert.deepEqual(calls.at(-1).target, { tabId: 7, documentIds: ['doc1'] });
assert.equal(calls.at(-1).worldId, 'a');
assert.match(calls.at(-1).js[0].code, /__OpenScriptButtons\?\.click\(1\)/);
} finally {
globalThis.chrome = originalChrome;
}
});