31 lines
4.9 KiB
JavaScript
31 lines
4.9 KiB
JavaScript
// External URL smoke + real gameplay. Browser contexts are isolated from users.
|
|
const {chromium}=require('playwright'),fs=require('fs'),path=require('path'),assert=require('assert');
|
|
const base=process.argv[2],out=process.argv[3];if(!base||!out)throw Error('Expected external URL and artifact directory');
|
|
fs.mkdirSync(out,{recursive:true});
|
|
(async()=>{
|
|
const b=await chromium.launch({channel:'chrome',headless:true});
|
|
const context=await b.newContext({viewport:{width:640,height:1136}}),p=await context.newPage(),errors=[],failed=[];
|
|
p.on('pageerror',e=>errors.push(String(e)));p.on('response',r=>{if(r.status()>=400&&!r.url().endsWith('/favicon.ico'))failed.push({status:r.status(),url:r.url()})});
|
|
async function ready(page){await page.waitForFunction(()=>{if(!window.Laya?.stage)return false;function v(n){for(const c of n._components||[])if(c.playerNodes)window.g=c;for(const ch of n._children||[])v(ch)}v(Laya.stage);return window.g?.total>0&&!g.busy},undefined,{timeout:45000})}
|
|
async function click(name){const pt=await p.evaluate(name=>{const n=g.findUi(g.modal||g.chooseOverlay||g.hud,name);if(!n)throw Error(name);return n.localToGlobal(new Laya.Point(n.width/2,n.height/2))},name);await p.mouse.click(pt.x,pt.y)}
|
|
async function panel(name){await p.waitForFunction(n=>g.modal?.name===`panel_${n}`&&g.modal.getChildByName('panel_card').scaleX===1&&!g.modalClosing,name)}
|
|
await p.goto(new URL('?level=3',base).href,{waitUntil:'networkidle',timeout:45000});await ready(p);
|
|
const start=await p.evaluate(()=>({level:g.level,resource:g.currentResource,total:g.total,standing:g.standingWalkers.size,walls:g.boardWallEnabled}));assert.deepEqual(start,{level:3,resource:'level32',total:1976,standing:1976,walls:true});
|
|
await p.screenshot({path:path.join(out,'desktop-level3.png')});
|
|
await click('upgrade_button');await panel('速度升级');assert.equal(await p.evaluate(()=>g.findUi(g.modal,'level').text),'0');await click('btn_getfast');await p.waitForFunction(()=>g.fastLevel===1&&!g.adBusy);await panel('速度升级');assert.equal(await p.evaluate(()=>g.findUi(g.modal,'percentage').text),'10%');await p.screenshot({path:path.join(out,'external-upgrade.png')});await click('btn_close');await p.waitForFunction(()=>!g.modal);
|
|
await click('remove_button');await p.waitForFunction(()=>g.chooseOverlay&&!g.chooseMotion);await click('cancel_choose');await p.waitForFunction(()=>!g.chooseOverlay);assert.equal(await p.evaluate(()=>g.tools.remove),3);
|
|
for(const i of [0,1]){const pt=await p.evaluate(i=>g.laneHits[i].localToGlobal(new Laya.Point(42,60)),i);await p.mouse.click(pt.x,pt.y);await p.waitForTimeout(100)}
|
|
let frames=0;
|
|
for(let i=0;i<220;i++){await p.waitForTimeout(80);const s=await p.evaluate(()=>({conserved:g.board.flat().filter(c=>c!==7000).length+[...g.pendingPassengers.values()].reduce((n,v)=>n+v,0)-g.reservedPassengers.size+g.cleared===g.total,cleared:g.cleared,active:g.activeMoves}));assert(s.conserved);frames++;if(!s.active){assert.equal(s.cleared,60);break}if(i===219)throw Error('External boarding stalled')}
|
|
await p.screenshot({path:path.join(out,'external-boarded.png')});
|
|
const mobileContext=await b.newContext({viewport:{width:390,height:844},deviceScaleFactor:2,isMobile:true,hasTouch:true}),mobile=await mobileContext.newPage(),mobileErrors=[];
|
|
mobile.on('pageerror',e=>mobileErrors.push(String(e)));await mobile.goto(new URL('?level=3',base).href,{waitUntil:'networkidle',timeout:45000});await ready(mobile);
|
|
const target=await mobile.evaluate(()=>{const n=g.hudButtons.get('upgrade'),pt=n.localToGlobal(new Laya.Point(n.width/2,n.height/2)),rect=document.querySelector('canvas').getBoundingClientRect();return{x:rect.x+pt.x*rect.width/Laya.stage.width,y:rect.y+pt.y*rect.height/Laya.stage.height}});await mobile.touchscreen.tap(target.x,target.y);await mobile.waitForFunction(()=>g.modal?.name==='panel_速度升级'&&g.modal.getChildByName('panel_card').scaleX===1);await mobile.screenshot({path:path.join(out,'mobile-upgrade.png')});assert.deepEqual(mobileErrors,[]);
|
|
for(const file of ['/js/bootstrap.js','/resources/levels/main-manifest.json','/resources/levels/level32.json'])assert.equal((await p.request.get(new URL(file,base).href)).status(),200);
|
|
assert.equal((await p.request.get(new URL('/resources/original/v11/home/game.js',base).href)).status(),404);
|
|
assert.equal((await p.request.get(new URL('/js/iterations/pass1/Main.js',base).href)).status(),404);
|
|
assert.deepEqual(errors,[]);assert.deepEqual(failed,[]);
|
|
const result={base,https:true,start,desktop:'PASS',mobileTouch:'PASS',upgradeReward:'PASS',chooseCancel:'PASS',twoCars:{cleared:60,samples:frames,conserved:true},historicalVersionsAndCachedScriptsExcluded:true,errors,failed};fs.writeFileSync(path.join(out,'external-verification.json'),JSON.stringify(result,null,2));console.log(JSON.stringify(result,null,2));
|
|
await Promise.race([b.close(),new Promise(r=>setTimeout(r,3000))]);process.exit(0);
|
|
})().catch(e=>{console.error(e);process.exit(1)});
|