feat: add advanced context actions and optional translation
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { DEFAULT_SETTINGS } from '../lib/defaults.js';
|
||||
const { initializeMenus } = await import('../background/menus.js').catch(()=>({}));
|
||||
function event(){const listeners=[];return {addListener:f=>listeners.push(f),emit:async(...args)=>{for(const f of listeners)await f(...args);}};}
|
||||
function fixture(mode='advanced') {
|
||||
let settings={...DEFAULT_SETTINGS,contextMenuMode:mode};
|
||||
const items=new Map(), launches=[];let refreshes=0;
|
||||
const browser={runtime:{},storage:{onChanged:event()},menus:{onShown:event(),onHidden:event(),onClicked:event(),
|
||||
removeAll:async()=>items.clear(),create:(item,callback)=>{items.set(item.id,{...item});callback();},
|
||||
update:async(id,patch)=>{assert.ok(items.has(id));Object.assign(items.get(id),patch);},refresh:async()=>{refreshes++;}}};
|
||||
const ready=initializeMenus({browser,load:async()=>({...settings}),onAction:async request=>launches.push(request)});
|
||||
return {browser,items,launches,ready,get refreshes(){return refreshes;},set settings(value){settings={...settings,...value};}};
|
||||
}
|
||||
test('mode controls roots, live preferences rebuild, context-only onShown needs no host permission',async()=>{
|
||||
assert.equal(typeof initializeMenus,'function');
|
||||
const f=fixture('off');await f.ready;assert.equal(f.items.size,0);
|
||||
f.settings={contextMenuMode:'simple'};await f.browser.storage.onChanged.emit({contextMenuMode:{}},'sync');
|
||||
assert.equal(f.items.size,1);assert.equal([...f.items.values()][0].parentId,undefined);
|
||||
f.settings={contextMenuMode:'advanced'};await f.browser.storage.onChanged.emit({contextMenuMode:{}},'sync');
|
||||
assert.equal([...f.items.values()].filter(i=>!i.parentId).length,1);
|
||||
await f.browser.menus.onShown.emit({contexts:['selection','link'],editable:false});
|
||||
assert.deepEqual([...f.items.values()].filter(i=>i.parentId&&i.visible&&i.type!=='separator').map(i=>i.title),['Ask normally','Explain','Summarize','Debug code']);
|
||||
await f.browser.menus.onShown.emit({contexts:['link'],editable:false});
|
||||
assert.deepEqual([...f.items.values()].filter(i=>i.parentId&&i.visible).map(i=>i.title),['Ask about this link','Review link safety']);
|
||||
assert.ok(f.refreshes>=2);
|
||||
});
|
||||
test('click revalidates context and action, preserves source/settings snapshot',async()=>{
|
||||
assert.equal(typeof initializeMenus,'function');
|
||||
const f=fixture();await f.ready;
|
||||
await f.browser.menus.onClicked.emit({menuItemId:'ask-chatgpt:debug',selectionText:'code',linkUrl:'https://example.com'});
|
||||
assert.equal(f.launches.length,1);assert.equal(f.launches[0].actionId,'debug');assert.equal(f.launches[0].source,'code');
|
||||
f.settings={promptTemplate:'changed'};assert.equal(f.launches[0].settings.promptTemplate,'{query}');
|
||||
await f.browser.menus.onClicked.emit({menuItemId:'ask-chatgpt:debug',linkUrl:'https://example.com'});
|
||||
await f.browser.menus.onClicked.emit({menuItemId:'ask-chatgpt:translate',selectionText:'code'});
|
||||
await f.browser.menus.onClicked.emit({menuItemId:'unknown',selectionText:'code'});
|
||||
assert.equal(f.launches.length,1);
|
||||
});
|
||||
test('translation rebuilds with literal label and rapid preference updates settle',async()=>{
|
||||
assert.equal(typeof initializeMenus,'function');
|
||||
const f=fixture();await f.ready;
|
||||
f.settings={showTranslate:true,translationMode:'preferred',translationLanguage:'A & B'};
|
||||
await f.browser.storage.onChanged.emit({showTranslate:{}},'sync');
|
||||
assert.equal(f.items.get('ask-chatgpt:translate').title,'Translate to A && B');
|
||||
f.settings={contextMenuMode:'off'};
|
||||
const a=f.browser.storage.onChanged.emit({contextMenuMode:{}},'sync');
|
||||
f.settings={contextMenuMode:'simple'};
|
||||
await Promise.all([a,f.browser.storage.onChanged.emit({contextMenuMode:{}},'sync')]);
|
||||
assert.equal(f.items.size,1);
|
||||
});
|
||||
Reference in New Issue
Block a user