const {chromium}=require('playwright-core'),fs=require('node:fs'),assert=require('node:assert/strict'); const root='D:/web/dj/integration-work/',base='http://127.0.0.1:18886'; (async()=>{ const browser=await chromium.launch({channel:'chrome',headless:true}); try{ const page=await browser.newPage({viewport:{width:1550,height:1050}}),errors=[]; page.on('pageerror',e=>errors.push(e.message)); // UI checks must never generate media or change application defaults. await page.route('**/api/**',async route=>{ const r=route.request();if(!['GET','HEAD'].includes(r.method())&&!new URL(r.url()).pathname.endsWith('/reference-images'))return route.abort(); if(r.method()==='POST')await new Promise(resolve=>setTimeout(resolve,500)); return route.continue(); }); async function open(){await page.goto(base+'/drama/6/episode/1',{waitUntil:'networkidle'});await page.getByRole('navigation').getByRole('button',{name:/^资产制作/}).click();} await open(); const refs=page.locator('[data-reference-asset="character:26"]').first(); await refs.locator('.reference-image').nth(1).waitFor(); assert.equal(await refs.locator('.reference-image').count(),2); assert.equal(await page.locator('[data-reference-asset="character:27"] .reference-image').count(),1); assert.equal(await page.locator('[data-reference-asset="scene:22"] .reference-image').count(),2); assert.equal(await page.locator('[data-reference-asset="prop:1"] .reference-image').count(),2); const card=page.locator('.character-asset-card').filter({has:refs}); const original=await card.locator('.character-portrait img').getAttribute('src'); await refs.locator('input[type=file]').setInputFiles([root+'hd-test-references/blue.png',root+'hd-test-references/green.png']); assert.equal(await refs.getByRole('button',{name:'保存中'}).isDisabled(),true); await refs.locator('.reference-image').nth(3).waitFor(); await refs.getByRole('button',{name:'添加参考图'}).waitFor(); await open();assert.equal(await refs.locator('.reference-image').count(),4); await refs.getByRole('button',{name:'预览参考图 1',exact:true}).click(); await page.locator('.image-viewer-overlay').waitFor(); await page.keyboard.press('Escape'); await page.locator('.image-viewer-overlay').waitFor({state:'hidden'}); for(const n of [4,3]){ await refs.getByRole('button',{name:'移除参考图 '+n,exact:true}).click(); await page.waitForFunction(({n})=>document.querySelectorAll('[data-reference-asset="character:26"] .reference-image').length===n-1,{n}); } await open();assert.equal(await refs.locator('.reference-image').count(),2); assert.equal(await card.locator('.character-portrait img').getAttribute('src'),original); assert.equal(await page.locator('[data-reference-asset="character:27"] .reference-image').count(),1); await refs.scrollIntoViewIfNeeded(); await page.screenshot({path:root+'asset-reference-ui.png'}); assert.deepEqual(errors,[]); console.log('PASS: all asset types, multiple uploads, busy lock, reload persistence, preview, removal and asset isolation'); }finally{await browser.close()} })().catch(e=>{console.error(e.stack);process.exit(1)});