Files
shanhe-puzzle/tests/container-layout.mjs
T

11 lines
4.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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();