11 lines
4.2 KiB
JavaScript
11 lines
4.2 KiB
JavaScript
import {chromium} from 'playwright';import assert from 'node:assert/strict';import fs from 'node:fs';
|
||
const browser=await chromium.launch({executablePath:'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',headless:true});const errors=[],results=[];
|
||
for(const sample of [{width:360,height:800,top:24,bottom:48},{width:320,height:568,top:44,bottom:34},{width:390,height:844,top:44,bottom:34},{width:740,height:390,top:24,bottom:24}]){
|
||
const context=await browser.newContext({viewport:{width:sample.width,height:sample.height},isMobile:true,hasTouch:true});const p=await context.newPage();p.on('pageerror',e=>errors.push(e.message));await p.goto('http://localhost:4173');await p.addStyleTag({content:':root{--safe-area-inset-top:'+sample.top+'px;--safe-area-inset-bottom:'+sample.bottom+'px}'});await p.evaluate(()=>dispatchEvent(new Event('resize')));
|
||
await p.evaluate(top=>{const div=document.createElement('div');div.id='host-overlay';div.style.cssText='position:fixed;top:'+top+'px;left:0;right:0;height:56px;z-index:10000;pointer-events:none';div.innerHTML='<span style="position:absolute;left:12px;top:4px;width:42px;height:42px;border-radius:50%;background:#aab0a4;color:white;font:28px/42px sans-serif;text-align:center;pointer-events:auto">‹</span><span style="position:absolute;right:12px;top:4px;width:86px;height:42px;border-radius:24px;background:#aab0a4;color:white;font:22px/42px sans-serif;text-align:center;pointer-events:auto">♙ ↗</span>';document.body.appendChild(div);},sample.top);
|
||
async function safe(){const bad=await p.locator('button:visible').evaluateAll((buttons,limit)=>buttons.filter(b=>b.getBoundingClientRect().top<limit-1).map(b=>({id:b.id,y:b.getBoundingClientRect().top})),sample.top+56);assert.deepEqual(bad,[],JSON.stringify(sample)+' button blocked by native toolbar');assert.ok(await p.evaluate(()=>document.documentElement.scrollHeight<=innerHeight+1),JSON.stringify(sample)+' page overflow');}
|
||
for(const mode of ['province','city']){await p.locator('[data-mode="'+mode+'"]').tap();await p.waitForTimeout(400);await safe();const fit=await p.evaluate(()=>{const rect=s=>{const r=document.querySelector(s).getBoundingClientRect();return {top:r.top,bottom:r.bottom};};return {header:rect('.header'),setup:rect('.setup'),map:rect('.entry-map'),footer:rect('footer')};});assert.ok(fit.header.bottom<=fit.setup.top+1,JSON.stringify({sample,fit}));assert.ok(fit.setup.bottom<=fit.footer.top+1,JSON.stringify({sample,fit}));const map=await p.locator('#reference').boundingBox();assert.ok(map&&map.height>=90&&map.width>=100,'两版地图预览必须可见');if(sample.width<600){assert.ok(fit.header.bottom<=fit.map.top+1,JSON.stringify({sample,fit}));assert.ok(fit.map.bottom<=fit.setup.top+1,JSON.stringify({sample,fit}));}assert.ok(await p.locator('#reference').evaluate(c=>{const data=c.getContext('2d').getImageData(0,0,c.width,c.height).data;let count=0;const colors=new Set([0xc3d4b4,0xe3c78f,0xd2b5a5,0xb5cbd0,0xd2c69d,0xb1c5a0,0xd9bca6,0xbdc7ac,0xd7c5c5,0xbfd0ba]);for(let i=0;i<data.length;i+=4)if(data[i+3]>200&&colors.has((data[i]<<16)|(data[i+1]<<8)|data[i+2]))count++;return count>300;}),'地图实际绘制像素而非空画布');}
|
||
await p.screenshot({path:'artifacts/container-entry-'+sample.width+'.png'});await p.locator('#province-picker').tap();await safe();await p.locator('[data-province="330000"]').tap();await p.locator('#start').tap();await p.waitForTimeout(300);await safe();await p.screenshot({path:'artifacts/container-game-'+sample.width+'.png'});await p.locator('#pause').tap();await safe();await p.getByRole('button',{name:'结束旅程',exact:true}).tap();await safe();await p.screenshot({path:'artifacts/container-result-'+sample.width+'.png'});await p.locator('#result-back').tap();await safe();results.push({sample,passed:true});await context.close();
|
||
}
|
||
assert.deepEqual(errors,[]);fs.writeFileSync('artifacts/container-layout-report.json',JSON.stringify({scope:'Modern browser with simulated host toolbar and safe areas; real container verification pending',results,errors},null,2));console.log('四种手机尺寸:模拟平台角落按钮遮挡下,入口/地级选择/游戏/暂停/成绩均可操作、无页面溢出、面板与页脚不重叠');await browser.close();
|