XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
import http from 'node:http';
import path from 'node:path';
import {readFile,writeFile} from 'node:fs/promises';

export default async function ({page,outputDir}) {
  const root=path.resolve('XFEEDToolBox/Assets/Galnet');
  const slides=JSON.parse(await readFile('artifacts/news-carousel/live-slides.json','utf8')).map(s=>({...s,image:'/space.png'}));
  const errors=[];page.on('pageerror',error=>errors.push(error.message));
  const require=(condition,message)=>{if(!condition)throw new Error(message);};
  const server=http.createServer(async(req,res)=>{
    try {
      const target=path.resolve(root,'.'+new URL(req.url,'http://localhost').pathname);
      if(!target.startsWith(root+path.sep)){res.writeHead(403).end();return;}
      const type={'.html':'text/html; charset=utf-8','.js':'text/javascript; charset=utf-8','.css':'text/css; charset=utf-8','.png':'image/png','.svg':'image/svg+xml','.woff2':'font/woff2'}[path.extname(target)]||'application/octet-stream';
      res.writeHead(200,{'Content-Type':type}).end(await readFile(target));
    } catch {if(!res.headersSent)res.writeHead(404);res.end();}
  });
  await new Promise(resolve=>server.listen(0,'127.0.0.1',resolve));
  try {
    await page.setViewportSize({width:3000,height:400});
    await page.goto(`http://127.0.0.1:${server.address().port}/index.html`,{waitUntil:'load'});
    const observed=await page.locator('#progress').evaluate(e=>({width:e.getBoundingClientRect().width,transform:getComputedStyle(e).transform}));
    await page.evaluate(slides=>window.galnet.setSlides(slides),slides);
    await page.mouse.move(-10,-10);
    const frames=await page.evaluate(()=>new Promise(resolve=>{
      const samples=[];
      function tick(time){samples.push({time,scale:new DOMMatrixReadOnly(getComputedStyle(document.getElementById('progress')).transform).a});if(samples.length<60)requestAnimationFrame(tick);else resolve(samples);}
      requestAnimationFrame(tick);
    }));
    const moving=frames.slice(1).filter((frame,i)=>frame.scale>frames[i].scale).length;
    require(moving>=frames.length*.85,`Progress moved on only ${moving}/${frames.length} frames.`);
    await page.screenshot({path:path.join(outputDir,'continuous-progress.png')});
    const beforeUpdate=await page.evaluate(()=>window.galnet.inspect().progress);
    await page.evaluate(slides=>window.galnet.setSlides(slides.map(s=>({...s,teaser:s.teaser+' '}))),slides);
    require(await page.evaluate(()=>window.galnet.inspect().progress)>=beforeUpdate,'A content/translation update reset the animation.');
    await page.locator('#carousel').hover();
    await page.waitForTimeout(50);
    const hover=await page.evaluate(()=>window.galnet.inspect().progress);
    await page.waitForTimeout(320);
    require(await page.evaluate(()=>window.galnet.inspect().progress)===hover,'Hover did not freeze the same animation timeline.');
    await page.mouse.move(-10,-10);await page.waitForTimeout(120);
    require(await page.evaluate(()=>window.galnet.inspect().progress)>hover,'Leaving hover did not resume from the same position.');
    await page.evaluate(()=>window.galnet.setActive(false));await page.waitForTimeout(50);
    const inactive=await page.evaluate(()=>window.galnet.inspect().progress);
    await page.waitForTimeout(180);
    require(await page.evaluate(()=>window.galnet.inspect().progress)===inactive,'Inactive page advanced the timeline.');
    await page.evaluate(()=>window.galnet.setActive(true));
    await page.getByRole('button',{name:'暂停自动轮播',exact:true}).click();
    require(await page.evaluate(()=>window.galnet.inspect().paused),'Pause button failed.');
    await page.getByRole('button',{name:'下一条新闻',exact:true}).click();
    require(await page.evaluate(()=>window.galnet.inspect().progress)===0,'Manual navigation did not immediately reset the bar.');
    await page.getByRole('button',{name:'继续自动轮播',exact:true}).click();
    await page.evaluate(()=>document.activeElement?.blur());await page.mouse.move(-10,-10);
    const index=await page.evaluate(()=>window.galnet.inspect().index);
    await page.waitForFunction(index=>window.galnet.inspect().index!==index,index,{timeout:10000});
    require(await page.evaluate(()=>window.galnet.inspect().progress)<800,'Automatic navigation did not restart the timeline.');
    await page.evaluate(()=>window.galnet.setActive(false));
    await page.screenshot({path:path.join(outputDir,'after-advance.png')});
    require(errors.length===0,errors.join('\n'));
    const report={passed:true,viewportWidth:3000,observedBeforeData:observed,sampledFrames:frames.length,movingFrames:moving,translationUpdatePreservesProgress:true,hoverPauseAndResume:true,inactivePagePauses:true,pauseButton:true,manualReset:true,automaticAdvance:true,errors,networkScope:'Local fixture and bundled assets only',gameCallsInvoked:false,frames};
    await writeFile(path.join(outputDir,'progress-report.json'),JSON.stringify(report,null,2));
    console.log(JSON.stringify({...report,frames:undefined}));
  } finally {await new Promise(resolve=>server.close(resolve));}
}