74 lines
4.3 KiB
JavaScript
74 lines
4.3 KiB
JavaScript
'use strict';
|
|
// Isolated UI regression: all requests use fixture data, never the user's queue.
|
|
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,'..');
|
|
(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:1000}}),errors=[],requests=[];
|
|
page.on('pageerror',error=>errors.push(error.message));
|
|
const data={run:{running:false,active:'active',config:{},reason:'已暂停',batch:null},clients:[],
|
|
jobs:['a','b','active'].map(id=>({id,title:'测试文章 '+id,original_title:'测试文章 '+id,image_count:0,source:'测试来源',state:id==='active'?'awaiting_user_review':'queued'})),
|
|
download:{status:'idle',saved:0,target:0,skipped:0,failed:0,logs:[]}};
|
|
let failRemoval=false;
|
|
await page.route('**/*',async route=>{
|
|
const url=new URL(route.request().url());
|
|
if(url.hostname!=='queue.test')return route.abort();
|
|
if(url.pathname==='/api/session')return route.fulfill({json:{token:'fixture'}});
|
|
if(url.pathname==='/api/state')return route.fulfill({json:data});
|
|
if(url.pathname==='/api/remove'){
|
|
const body=route.request().postDataJSON();requests.push(body);
|
|
if(failRemoval)return route.fulfill({status:400,json:{error:'模拟移除失败'}});
|
|
data.jobs=data.jobs.filter(job=>!body.ids.includes(job.id));
|
|
return route.fulfill({json:{ok:true,removed:body.ids.length}});
|
|
}
|
|
const files={'/':'index.html','/app.js':'app.js','/style.css':'style.css'};
|
|
if(files[url.pathname])return route.fulfill({path:path.join(ROOT,'static',files[url.pathname])});
|
|
return route.abort();
|
|
});
|
|
await page.goto('http://queue.test/');
|
|
await page.waitForFunction(()=>document.querySelectorAll('.job-select').length===3);
|
|
const box=id=>page.locator(`.job-select[value="${id}"]`);
|
|
assert.equal(await page.locator('#remove-selected').isDisabled(),true);
|
|
assert.equal(await box('active').isDisabled(),true);
|
|
await box('a').check();
|
|
assert.equal(await page.locator('#select-all').evaluate(el=>el.indeterminate),true);
|
|
await page.evaluate(()=>refresh());
|
|
assert.equal(await box('a').isChecked(),true,'polling preserves selection');
|
|
page.once('dialog',dialog=>dialog.dismiss());
|
|
await page.locator('#remove-selected').click();
|
|
assert.equal(requests.length,0,'cancel does not delete');
|
|
failRemoval=true;
|
|
page.once('dialog',dialog=>dialog.accept());
|
|
await page.locator('#remove-selected').click();
|
|
await page.getByText('模拟移除失败',{exact:true}).waitFor();
|
|
assert.equal(await box('a').isChecked(),true,'failure preserves selection');
|
|
failRemoval=false;
|
|
page.once('dialog',dialog=>dialog.accept());
|
|
await page.locator('#remove-selected').click();
|
|
await page.waitForFunction(()=>document.querySelectorAll('.job-select').length===2);
|
|
assert.deepEqual(requests.at(-1),{ids:['a']});
|
|
assert.equal(await box('b').count(),1,'unselected article remains');
|
|
await page.locator('#select-all').check();
|
|
assert.equal(await box('b').isChecked(),true);
|
|
assert.equal(await box('active').isChecked(),false);
|
|
data.run.running=true;await page.evaluate(()=>refresh());
|
|
assert.equal(await page.locator('#remove-selected').isDisabled(),true,'running flow blocks removal');
|
|
data.run.running=false;data.run.active=null;await page.evaluate(()=>refresh());
|
|
await page.locator('#select-all').check();
|
|
await page.setViewportSize({width:390,height:844});
|
|
assert.equal(await page.evaluate(()=>document.documentElement.scrollWidth>innerWidth),false,'mobile has no horizontal overflow');
|
|
page.once('dialog',dialog=>dialog.accept());
|
|
await page.locator('#remove-selected').click();
|
|
await page.locator('#empty').waitFor({state:'visible'});
|
|
assert.equal(await page.locator('#total').textContent(),'0');
|
|
assert.equal(await page.locator('#select-all').isDisabled(),true);
|
|
assert.equal(await page.locator('#remove-selected').isDisabled(),true);
|
|
assert.deepEqual(errors,[]);
|
|
console.log('PASS queue UI: selection, polling, cancellation, failure, selected deletion, protected task, running state, select all, empty state, mobile layout');
|
|
}finally{await browser.close();}
|
|
})().catch(error=>{console.error(error);process.exitCode=1;});
|