84 lines
6.3 KiB
JavaScript
84 lines
6.3 KiB
JavaScript
'use strict';
|
|
const assert=require('node:assert/strict');
|
|
const {panelPosition}=require('./icampus-study-helper.user.js');
|
|
const {harness}=require('./study-helper.test.cjs');
|
|
const KEY='icampus.study.v1.panel';
|
|
let passed=0;
|
|
async function test(name,fn){await fn();passed++;console.log(`PASS ${name}`);}
|
|
function mount(h){
|
|
const nodes=new Map();
|
|
const panel={querySelector(s){if(!nodes.has(s))nodes.set(s,{textContent:'',value:'all',checked:true});return nodes.get(s);}};
|
|
const host={style:{},attachShadow:()=>panel,getBoundingClientRect(){return {
|
|
left:parseFloat(this.style.left)||16,top:parseFloat(this.style.top)||100,
|
|
width:nodes.get('[data-main-panel]')?.hidden?240:322,height:nodes.get('[data-main-panel]')?.hidden?44:620};}};
|
|
h.context.window.innerWidth=1400;h.context.window.innerHeight=900;
|
|
h.context.document.body={append(){}};h.context.document.createElement=()=>host;h.api.mount();
|
|
return {nodes,host};
|
|
}
|
|
function pointer(id,x,y,target={closest:()=>null}){return {pointerId:id,clientX:x,clientY:y,button:0,isPrimary:true,target,preventDefault(){}};}
|
|
(async()=>{
|
|
await test('collapse and expand preserve active playback, intent and options',()=>{
|
|
const h=harness(),{nodes}=mount(h);h.api.begin();h.api.track(h.video);
|
|
nodes.get('[data-collapse]').onclick();assert.equal(nodes.get('[data-main-panel]').hidden,true);assert.equal(nodes.get('[data-expand]').hidden,false);
|
|
assert.equal(h.api.state.running,true);assert.equal(h.api.state.armed,true);assert.equal(h.video.pauseCount,0);
|
|
nodes.get('[data-expand]').onclick({detail:0});assert.equal(nodes.get('[data-main-panel]').hidden,false);assert.equal(h.api.state.running,true);
|
|
});
|
|
await test('dragging the title changes and stores position',()=>{
|
|
const h=harness(),{nodes,host}=mount(h),handle=nodes.get('[data-drag-handle]');
|
|
handle.onpointerdown(pointer(1,20,104));handle.onpointermove(pointer(1,220,204));handle.onpointerup(pointer(1,220,204));
|
|
assert.equal(host.style.left,'216px');assert.equal(host.style.top,'200px');
|
|
assert.deepEqual(JSON.parse(h.storage.get(KEY)),{x:216,y:200,collapsed:false});
|
|
});
|
|
await test('dragged compact button remains collapsed and a later click expands',()=>{
|
|
const h=harness(),{nodes}=mount(h);nodes.get('[data-collapse]').onclick();const compact=nodes.get('[data-expand]');
|
|
compact.onpointerdown(pointer(1,20,104));compact.onpointermove(pointer(1,120,204));compact.onpointerup(pointer(1,120,204));
|
|
compact.onclick({detail:1});assert.equal(nodes.get('[data-main-panel]').hidden,true);
|
|
compact.onpointerdown(pointer(2,120,204));compact.onpointerup(pointer(2,120,204));compact.onclick({detail:1});
|
|
assert.equal(nodes.get('[data-main-panel]').hidden,false);
|
|
});
|
|
await test('refresh restores compact state and saved position',()=>{
|
|
const h=harness(),{nodes}=mount(h);const header=nodes.get('[data-drag-handle]');
|
|
header.onpointerdown(pointer(1,20,104));header.onpointermove(pointer(1,220,204));header.onpointerup(pointer(1,220,204));nodes.get('[data-collapse]').onclick();
|
|
const restarted=harness({storageEntries:[...h.storage]}),ui=mount(restarted);
|
|
assert.equal(ui.nodes.get('[data-main-panel]').hidden,true);assert.equal(ui.host.style.left,'216px');assert.equal(ui.host.style.top,'200px');
|
|
assert.equal(restarted.api.state.armed,false);
|
|
});
|
|
await test('resize keeps the header and expanded panel inside the smaller viewport',()=>{
|
|
const h=harness(),{nodes,host}=mount(h);const header=nodes.get('[data-drag-handle]');
|
|
header.onpointerdown(pointer(1,20,104));header.onpointermove(pointer(1,1000,250));header.onpointerup(pointer(1,1000,250));
|
|
h.window.innerWidth=400;h.window.innerHeight=700;h.window.dispatchEvent({type:'resize'});
|
|
assert.equal(host.style.left,'70px');assert.equal(host.style.top,'72px');
|
|
});
|
|
await test('tiny movements and button presses do not start a drag or change settings',()=>{
|
|
const h=harness(),{nodes,host}=mount(h),header=nodes.get('[data-drag-handle]');
|
|
const before={...host.style};header.onpointerdown(pointer(1,20,104));header.onpointermove(pointer(1,21,105));header.onpointerup(pointer(1,21,105));
|
|
assert.equal(host.style.left,before.left);assert.equal(h.storage.has(KEY),false);
|
|
header.onpointerdown(pointer(2,20,104,{closest:()=>({})}));header.onpointermove(pointer(2,500,500));header.onpointerup(pointer(2,500,500));
|
|
assert.equal(host.style.left,before.left);assert.equal(h.api.state.armed,false);
|
|
});
|
|
await test('cancelled pointer capture allows the next drag to work',()=>{
|
|
const h=harness(),{nodes,host}=mount(h),header=nodes.get('[data-drag-handle]');
|
|
header.onpointerdown(pointer(1,20,104));header.onpointercancel(pointer(1,20,104));
|
|
header.onpointerdown(pointer(2,20,104));header.onpointermove(pointer(2,120,104));header.onpointerup(pointer(2,120,104));
|
|
assert.equal(host.style.left,'116px');
|
|
});
|
|
await test('invalid and off-screen preferences safely fall back or clamp',()=>{
|
|
const invalid=harness({storageEntries:[[KEY,'broken json']]});assert.equal(mount(invalid).nodes.get('[data-main-panel]').hidden,false);
|
|
const outside=harness({storageEntries:[[KEY,JSON.stringify({x:100000,y:-100,collapsed:false})]]});const ui=mount(outside);
|
|
assert.equal(ui.host.style.left,'1070px');assert.equal(ui.host.style.top,'8px');
|
|
assert.deepEqual(panelPosition(NaN,Infinity,322,620,1400,900),{x:16,y:16});
|
|
});
|
|
await test('compact status reflects waiting and cancellation',()=>{
|
|
const h=harness(),{nodes}=mount(h);nodes.get('[data-start]').onclick();nodes.get('[data-collapse]').onclick();
|
|
h.api.park('等待网络');assert.equal(nodes.get('[data-mini-state]').textContent,'等待恢复');
|
|
assert.match(nodes.get('[data-expand]').title,/等待网络/);h.api.stop();assert.equal(nodes.get('[data-mini-state]').textContent,'未启动');
|
|
});
|
|
await test('blocked local storage does not prevent collapsing or dragging',()=>{
|
|
const h=harness(),{nodes,host}=mount(h);h.context.localStorage.setItem=()=>{throw new Error('blocked');};
|
|
nodes.get('[data-collapse]').onclick();const compact=nodes.get('[data-expand]');
|
|
compact.onpointerdown(pointer(1,20,104));compact.onpointermove(pointer(1,120,204));compact.onpointerup(pointer(1,120,204));
|
|
assert.equal(nodes.get('[data-main-panel]').hidden,true);assert.equal(host.style.left,'116px');
|
|
});
|
|
console.log(`${passed} panel control tests passed.`);
|
|
})().catch(e=>{console.error(e);process.exitCode=1;});
|