备份现场结果补录、图片修复与跳过文章功能
This commit is contained in:
1 parent
1e6504b4a2
commit
d157c179c8
20 files changed
+597
-47
No files matched your search
@@ -0,0 +1,106 @@
|
||||
'use strict';
|
||||
const {test}=require('node:test');
|
||||
const assert=require('node:assert/strict');
|
||||
const fs=require('node:fs');
|
||||
const path=require('node:path');
|
||||
const vm=require('node:vm');
|
||||
const flush=async()=>{for(let i=0;i<12;i++)await new Promise(resolve=>setImmediate(resolve));};
|
||||
|
||||
function fixture({holdImport=false,holdHeartbeat=false,rejectSkip=false}={}) {
|
||||
const handlers=new Map(),calls=[],navigations=[],storage=new Map(),timers=new Set();
|
||||
const job={id:'first',state:'preparing',title:'标题',source:'来源',fid:125,account:{uid:'123',name:'账号'}};
|
||||
const run={running:true,epoch:1,active:job.id,owner:'tab-a'};
|
||||
const body={innerHTML:'正文',innerText:'正文',querySelectorAll:()=>[]};
|
||||
const subject={value:''};let tick,finishImport,finishHeartbeat,rolledBack=false;
|
||||
class Event {constructor(type,options={}){this.type=type;Object.assign(this,options);}}
|
||||
const doc={
|
||||
body:{append(){}},createElement:()=>({style:{}}),
|
||||
querySelector(selector){
|
||||
if(selector==='#mumucms_username')return {childNodes:[{nodeType:3,textContent:'账号'}],href:'https://www.dww11.com/home.php?uid=123',querySelectorAll:()=>[]};
|
||||
if(selector==='#e_iframe')return {contentDocument:{body}};
|
||||
if(selector==='#subject')return subject;
|
||||
return null;
|
||||
},
|
||||
addEventListener(type,fn){if(!handlers.has(type))handlers.set(type,[]);handlers.get(type).push(fn);},
|
||||
dispatchEvent(event){for(const fn of handlers.get(event.type)||[])fn(event);}
|
||||
};
|
||||
const reply=(id,value,error)=>doc.dispatchEvent(new Event('dww11:local-response',{detail:JSON.stringify({id,value,error})}));
|
||||
doc.addEventListener('dww11:local-request',event=>{
|
||||
const {id,route,body}=JSON.parse(event.detail);calls.push({route,body});
|
||||
if(route==='heartbeat'&&holdHeartbeat&&calls.filter(x=>x.route==='heartbeat').length>1) {
|
||||
finishHeartbeat=()=>reply(id,run);return;
|
||||
}
|
||||
let value={};
|
||||
if(route==='heartbeat')value=run;
|
||||
if(route==='next')value={action:job.state==='preparing'?'prepare':'resume',job,run};
|
||||
if(route==='event')job.state=body.state;
|
||||
if(route==='skip') {
|
||||
if(rejectSkip){reply(id,null,'状态已改变');return;}
|
||||
job.state='skipped';run.active=null;run.epoch++;value={ok:true,fid:125,run};
|
||||
}
|
||||
if(route==='stop')run.running=false;
|
||||
reply(id,value);
|
||||
});
|
||||
let sequence=0;
|
||||
const context={document:doc,CustomEvent:Event,Node:{TEXT_NODE:3},URL,AbortController,
|
||||
crypto:{randomUUID:()=>sequence++===0?'tab-a':`request-${sequence}`},sessionStorage:{getItem:k=>storage.get(k),setItem:(k,v)=>storage.set(k,v),removeItem:k=>storage.delete(k)},
|
||||
location:{href:'https://www.dww11.com/forum.php?mod=post&action=newthread&fid=125',assign:url=>navigations.push(url)},
|
||||
setInterval:fn=>{tick=fn;},setTimeout:(fn,ms)=>{const t=setTimeout(fn,ms);timers.add(t);return t;},clearTimeout:t=>{clearTimeout(t);timers.delete(t);}
|
||||
};
|
||||
context.window={DWW11Importer:{stagePackage:async()=>({}),importPrepared:async({signal})=>{
|
||||
if(holdImport)await new Promise((resolve,reject)=>{finishImport=()=>{rolledBack=true;reject(signal.reason);};signal.addEventListener('abort',()=>{}, {once:true});});
|
||||
signal.throwIfAborted();subject.value='标题';return {attachmentOrder:[]};
|
||||
},verifyEditorImages:async()=>{}},DWW11Formatter:{format(){}}};
|
||||
vm.runInNewContext(fs.readFileSync(path.join(__dirname,'../browser/runner.js'),'utf8'),context);
|
||||
return {calls,navigations,job,run,storage,doc,Event,tick:()=>tick(),skip:()=>doc.dispatchEvent(new Event('dww11:skip-article')),
|
||||
finishImport:()=>finishImport(),finishHeartbeat:()=>finishHeartbeat(),rolledBack:()=>rolledBack,
|
||||
close:()=>{for(const t of timers)clearTimeout(t);}};
|
||||
}
|
||||
|
||||
test('跳过待审文章后打开全新编辑器,不再领取或提交旧稿',async()=>{
|
||||
const f=fixture();try{
|
||||
await flush();assert.equal(f.job.state,'awaiting_user_review');
|
||||
f.skip();f.skip();await flush();
|
||||
assert.equal(f.calls.filter(x=>x.route==='skip').length,1);
|
||||
assert.equal(f.job.state,'skipped');assert.equal(f.storage.has('auto-news-current'),false);
|
||||
assert.deepEqual(f.navigations,['https://www.dww11.com/forum.php?mod=post&action=newthread&fid=125']);
|
||||
const count=f.calls.length;await f.tick();assert.equal(f.calls.length,count);
|
||||
assert.equal(f.calls.some(x=>x.route==='accept'),false);
|
||||
}finally{f.close();}
|
||||
});
|
||||
|
||||
test('导入中跳过等待取消回滚,旧回调不会把任务改成异常',async()=>{
|
||||
const f=fixture({holdImport:true});try{
|
||||
await flush();assert.equal(f.job.state,'importing');f.skip();await flush();
|
||||
assert.equal(f.calls.some(x=>x.route==='skip'),false);assert.deepEqual(f.navigations,[]);
|
||||
f.finishImport();await flush();
|
||||
assert.equal(f.rolledBack(),true);assert.equal(f.job.state,'skipped');
|
||||
assert.equal(f.calls.some(x=>x.body.state==='needs_attention'),false);
|
||||
assert.equal(f.navigations.length,1);
|
||||
}finally{f.close();}
|
||||
});
|
||||
|
||||
test('跳过时忽略较早的轮询响应',async()=>{
|
||||
const f=fixture({holdHeartbeat:true});try{
|
||||
await flush();const pending=f.tick();await flush();f.skip();await flush();
|
||||
const before=f.calls.filter(x=>x.route==='next').length;
|
||||
f.finishHeartbeat();await pending;
|
||||
assert.equal(f.calls.filter(x=>x.route==='next').length,before);
|
||||
}finally{f.close();}
|
||||
});
|
||||
|
||||
test('人工发表后的任务不能直接跳过',async()=>{
|
||||
const f=fixture();try{
|
||||
await flush();f.doc.dispatchEvent(new f.Event('click',{isTrusted:true,target:{closest:()=>true}}));
|
||||
await flush();assert.equal(f.job.state,'user_submitting');f.skip();await flush();
|
||||
assert.equal(f.calls.some(x=>x.route==='skip'),false);assert.deepEqual(f.navigations,[]);
|
||||
}finally{f.close();}
|
||||
});
|
||||
|
||||
test('跳过请求失败时暂停且保留当前稿件',async()=>{
|
||||
const f=fixture({rejectSkip:true});try{
|
||||
await flush();f.skip();await flush();
|
||||
assert.equal(f.run.running,false);assert.equal(f.job.state,'awaiting_user_review');assert.deepEqual(f.navigations,[]);
|
||||
assert.equal(f.storage.has('auto-news-current'),true);
|
||||
}finally{f.close();}
|
||||
});
|
||||
Reference in new issue
Block a user