import assert from 'node:assert/strict'; import {writeFile} from 'node:fs/promises'; const task=await taskSpace(4),page=task.page('p1'); const dir='/Users/wukaibing/Grok/number-swipe/modes/02-connect-1234/docs/qa-v2'; await page.goto('http://localhost:8002'); const opening=await page.evaluate(()=>({state:window.__balloons.snapshot(),hint:window.__balloons.hint()})); await page.goto('http://localhost:8003'); await page.waitForFunction(()=>document.querySelector('#app').dataset.mode==='flow',undefined,{timeout:5000}); const key='mode:02-connect-1234:balloons-v2'; const backup=await page.evaluate(k=>({v2:localStorage.getItem(k),v1:localStorage.getItem('mode:02-connect-1234:v1')}),key); assert.equal(await page.evaluate(()=>typeof window.__balloons),'undefined'); await page.evaluate(()=>{window.qaErrors=[];addEventListener('error',e=>window.qaErrors.push(e.message));addEventListener('unhandledrejection',e=>window.qaErrors.push(String(e.reason)));}); const coords=await page.evaluate(data=>{const r=document.querySelector('#board').getBoundingClientRect(),s=Math.min(r.width/360,r.height/416);return data.hint.map(id=>{const b=data.state.balls.find(b=>b.id===id);return{x:r.left+(r.width-360*s)/2+b.x*s,y:r.top+(r.height-416*s)/2+b.y*s,id:0};});},opening); for(let i=0;idocument.querySelector('#app').dataset.animating==='false',undefined,{timeout:7000}); const result=await page.evaluate(()=>({turns:Number(document.querySelector('#app').dataset.turns),score:document.querySelector('#score').textContent,errors:window.qaErrors,debugExposed:typeof window.__balloons!=='undefined'})); assert.equal(result.turns,1);assert(Number(result.score.replaceAll(',',''))>0);assert.deepEqual(result.errors,[]); await page.screenshot({path:dir+'/production-merge.png'}); await page.reload();assert.equal(await page.evaluate(()=>document.querySelector('#best-score').textContent),result.score); await page.click('#help'); await page.waitForFunction(()=>document.querySelector('#sheet').getAnimations().every(a=>a.playState==='finished'),undefined,{timeout:3000}); await page.screenshot({path:dir+'/help.png'});await page.click('button[aria-label="关闭面板"]'); // 仅恢复本次正式包验收前的 v2 纪录;保留其它存档。 await page.evaluate(({key,v2})=>{if(v2===null)localStorage.removeItem(key);else localStorage.setItem(key,v2);},{key,v2:backup.v2}); assert.equal(await page.evaluate(()=>localStorage.getItem('mode:02-connect-1234:v1')),backup.v1); await page.reload(); await page.screenshot({path:dir+'/mobile.png'}); await page.cdp('Emulation.setDeviceMetricsOverride',{width:1280,height:900,deviceScaleFactor:2,mobile:false}); await page.waitForFunction(()=>innerWidth===1280,undefined,{timeout:3000});await page.screenshot({path:dir+'/desktop.png'}); await page.cdp('Emulation.setDeviceMetricsOverride',{width:390,height:844,deviceScaleFactor:2,mobile:true}); await page.waitForFunction(()=>innerWidth===390,undefined,{timeout:3000}); await writeFile(dir+'/production.json',JSON.stringify({...result,persistence:true,originalRecordRestored:true,legacyRecordPreserved:true,url:await page.url()},null,2)+'\n'); console.log({...result,persistence:true,originalRecordRestored:true,url:await page.url()});