Add persistent full-course mute option

This commit is contained in:
2026-10-10 17:00:50 +08:00
parent 8023a802f1
commit 281ab20018
7 changed files with 161 additions and 25 deletions
+6 -4
View File
@@ -13,10 +13,12 @@ function detail(overrides = {}) {
{id: RID, name: '视频一', type: 'VIDEO', sortNo: 1, completed: false, playable: true},
{id: '2093583972926885888', name: '视频二', type: 'VIDEO', sortNo: 2, completed: false, playable: true}], ...overrides};
}
function harness({sessionEntries=[]}={}) {
function harness({sessionEntries=[],storageEntries=[]}={}) {
let now = 100000;
class TestDate extends Date { static now() { return now; } }
const storage = new Map(), session = new Map(sessionEntries), selectors = new Map();
const storage = new Map(storageEntries), session = new Map(sessionEntries), selectors = new Map();
const mutations=[];
class TestMutationObserver {constructor(callback){mutations.push(callback);}observe(){}}
function eventSurface(){
const listeners=new Map();
return {addEventListener(type,fn,options){const list=listeners.get(type)||[];list.push({fn,capture:options===true||!!options?.capture});listeners.set(type,list);},
@@ -35,7 +37,7 @@ function harness({sessionEntries=[]}={}) {
window.self = window.top = window;
const context = {window, document, XMLHttpRequest: XHR, location: {
href: `https://icampus.yunyinsh.com/course/#/my-course/learn?id=${ID}`, hash: `#/my-course/learn?id=${ID}`, reload(){this.reloadCount=(this.reloadCount||0)+1;}},
URL, URLSearchParams, Date: TestDate, crypto: {randomUUID: () => 'test-owner'}, TextDecoder,Event:TestEvent,
URL, URLSearchParams, Date: TestDate, crypto: {randomUUID: () => 'test-owner'}, TextDecoder,Event:TestEvent,MutationObserver:TestMutationObserver,
localStorage: {getItem: k => storage.get(k) ?? null, setItem: (k,v) => storage.set(k,v), removeItem: k => storage.delete(k)},
sessionStorage: {getItem:k=>session.get(k)??null,setItem:(k,v)=>session.set(k,v),removeItem:k=>session.delete(k)},
setInterval() {}};
@@ -59,7 +61,7 @@ function harness({sessionEntries=[]}={}) {
classList: {contains: () => i === 0}, querySelector: () => ({textContent: name}), click() { ++this.clicks; }}));
selectors.set('button.resource-item', buttons);
api.receive({id: ID, tail: ''}, {bizCode: 0, data: detail()}, 200);
return {api, video, buttons, context, window, pending, selectors, storage, session, advance(ms) { now += ms; }};
return {api, video, buttons, context, window, pending, selectors, storage, session, mutate(){for(const callback of mutations)callback();}, advance(ms) { now += ms; }};
}
module.exports = {harness, detail, ID, RID};
if (require.main === module) (async () => {