'use strict'; const {chromium}=require('playwright'); const fs=require('node:fs'); const path=require('node:path'); const assert=require('node:assert/strict'); const ROOT=path.resolve(__dirname,'..'); const output=path.join(__dirname,'artifacts');fs.mkdirSync(output,{recursive:true}); (async()=>{ const browser=await chromium.launch({headless:true,executablePath:process.env.CHROME_PATH||'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'}); try{ const page=await browser.newPage({viewport:{width:1440,height:1100}}),errors=[]; page.on('pageerror',error=>errors.push(error.message)); await page.route('**/*',route=>new URL(route.request().url()).hostname==='127.0.0.1'?route.continue():route.abort()); await page.goto('http://127.0.0.1:8771/'); await page.getByText('原创导入测试稿',{exact:true}).waitFor(); await page.screenshot({path:path.join(output,'desktop.png'),fullPage:true}); await page.locator('#fid').fill('125');await page.locator('#minimum').fill('1');await page.locator('#maximum').fill('2');await page.locator('#interval').fill('10');await page.locator('#history-checked').check(); await page.getByRole('button',{name:'保存处理规则'}).click();await page.getByText('处理规则已保存',{exact:true}).waitFor(); await page.locator('#start').click();await page.getByText('流程运行中',{exact:true}).waitFor(); await page.locator('#stop').click();await page.getByText('流程已暂停',{exact:true}).waitFor(); await page.setViewportSize({width:390,height:844});await page.screenshot({path:path.join(output,'mobile.png'),fullPage:true}); assert.equal(await page.evaluate(()=>document.documentElement.scrollWidth>innerWidth),false,'mobile overflow'); assert.deepEqual(errors,[]);console.log('PASS local UI: configuration, start/stop, desktop/mobile layout'); await page.close(); const mock=await browser.newPage(); await mock.route('**/*',route=>route.fulfill({contentType:'text/html; charset=utf-8',body:'测试账号'})); await mock.goto('https://www.dww11.com/forum.php?mod=post&action=newthread&fid=125'); await mock.evaluate(()=>{ window.wysiwyg=1;window.events=[];window.clicks=0;window.formats=0; window.job={id:'fixture',state:'preparing',title:'测试标题',source:'测试来源',fid:125,account:{uid:'123',name:'测试账号'}}; window.flow={running:true,epoch:1,active:'fixture',config:{fid:125}}; document.querySelector('#postsubmit').addEventListener('click',()=>window.clicks++); window.DWW11Importer={stagePackage:async()=>({warnings:[]}),importPrepared:async()=>{ document.querySelector('#subject').value='测试标题'; document.querySelector('#e_iframe').contentDocument.body.innerHTML='

正文第一段

正文第二段

来源:测试来源,如有侵权,请联系删除。

'; return {images:{'a.gif':'1'},attachmentOrder:['1']}; }}; document.addEventListener('dww11:local-request',event=>{ const {id,route,body}=JSON.parse(event.detail);let value={}; window.events.push({route,body}); if(route==='heartbeat'){window.flow.owner=body.owner;value=window.flow;} if(route==='next')value={action:window.job.state==='preparing'?'prepare':'resume',job:window.job,run:window.flow}; if(route==='current')value={job:window.job,run:window.flow}; if(route==='event'){window.job.state=body.state;value={ok:true};} if(route==='stop'){window.flow.running=false;value=window.flow;} document.dispatchEvent(new CustomEvent('dww11:local-response',{detail:JSON.stringify({id,value})})); }); }); const importerCore=require('../browser/importer.js'); await mock.addScriptTag({content:'(()=>{'+importerCore.attachmentId.toString()+';'+importerCore.verifyEditorImages.toString()+';Object.assign(window.DWW11Importer,{attachmentId,verifyEditorImages});})();'}); await mock.addScriptTag({path:path.join(ROOT,'browser/formatter.js')}); await mock.addScriptTag({path:path.join(ROOT,'browser/runner.js')}); await mock.waitForFunction(()=>window.job.state==='awaiting_user_review'); await mock.waitForTimeout(2400); assert.equal(await mock.evaluate(()=>window.clicks),0,'runner must never publish'); assert.equal(await mock.evaluate(()=>document.querySelector('#e_iframe').contentDocument.body.querySelectorAll('[data-dww11-wx-source]').length),1); const before=await mock.evaluate(()=>document.querySelector('#e_iframe').contentDocument.body.innerHTML); await mock.evaluate(()=>window.DWW11Formatter.format('测试来源')); const after=await mock.evaluate(()=>document.querySelector('#e_iframe').contentDocument.body.innerHTML); assert.equal(after,before,'repeated formatting should be idempotent'); await mock.locator('#postsubmit').click(); await mock.waitForFunction(()=>window.job.state==='user_submitting'); await mock.evaluate(()=>history.pushState({},'', '/thread/999.html')); await mock.waitForFunction(()=>window.job.state==='submit_unknown'); assert.equal(await mock.evaluate(()=>window.flow.running),false); assert.equal(await mock.evaluate(()=>window.events.some(e=>e.route==='accept')),false,'unknown page must not count accepted'); assert.equal(await mock.evaluate(()=>window.clicks),1); console.log('PASS browser fixture: import/format, source uniqueness, repeated formatting, manual-only publish, unknown result stops'); await mock.close(); const ext=await browser.newPage(); await ext.route('**/*',route=>route.fulfill({contentType:'text/html; charset=utf-8',body:'
立即登录
'})); await ext.goto('https://www.dww11.com/'); await ext.evaluate(()=>{ window.routes=[];window.chrome.runtime={sendMessage:async message=>{ window.routes.push(message.route); if(message.route==='/hello')return {ok:true,data:{total:1,active:1,round:1,remaining:1,flow:null}}; if(message.route==='/start')return new Promise(resolve=>window.finishStart=()=>resolve({ok:true,data:{flow:{id:'test-run',phase:'logout',paused:false}}})); if(message.route==='/suspend')return {ok:true,data:{}}; throw new Error('Unexpected extension operation: '+message.route); }}; }); await ext.addScriptTag({path:path.join(ROOT,'../dww11-account-switch-browser-extension/content.js')}); await ext.waitForFunction(()=>JSON.parse(document.querySelector('#dww11-extension-panel').dataset.autoNewsState).idle); await ext.locator('#dww11-extension-next').click(); await ext.waitForFunction(()=>!!window.finishStart); await ext.evaluate(()=>{document.dispatchEvent(new CustomEvent('dww11:auto-stop'));window.finishStart();}); await ext.waitForFunction(()=>window.routes.includes('/suspend')); assert.equal(await ext.evaluate(()=>JSON.parse(document.querySelector('#dww11-extension-panel').dataset.autoNewsState).paused),true); assert.deepEqual(await ext.evaluate(()=>window.routes),['/hello','/start','/suspend']); console.log('PASS extension bridge: stop during pending start prevents login and persists pause'); await ext.close(); }finally{await browser.close();} })().catch(error=>{console.error(error);process.exitCode=1;});