14 lines
4.4 KiB
JavaScript
14 lines
4.4 KiB
JavaScript
import {chooseProvince,setDifficulty} from './helpers.mjs';
|
||
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');}
|
||
const bounds=()=>p.locator('.atlas-scene').boundingBox(),national=await bounds();
|
||
for(const code of [null,'330000','110000','500000','710000','810000','820000']){await chooseProvince(p,code);await p.waitForTimeout(300);await safe();assert.deepEqual(await bounds(),national,'全国和省区的地图外框必须完全一致');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'),scene:rect('.atlas-scene'),actions:rect('.atlas-actions'),footer:rect('footer')};});assert.ok(fit.header.bottom<=fit.scene.top+1,JSON.stringify({sample,fit}));assert.ok(fit.scene.bottom<=fit.actions.top+1,JSON.stringify({sample,fit}));assert.ok(fit.actions.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,'两版主体地图必须可见');assert.ok(await p.locator('#reference .atlas-land').count()>1,'真实地区形状已绘制');}
|
||
await p.locator('#difficulty-settings').tap();await safe();await p.locator('[data-speed="2"]').tap();await p.locator('[data-bounce="2"]').tap();const dialog=await p.locator('#modal').evaluate(e=>({scroll:e.scrollHeight,client:e.clientHeight}));assert.ok(dialog.scroll<=dialog.client+1,JSON.stringify({sample,dialog}));await p.getByRole('button',{name:'完成设置',exact:true}).tap();assert.deepEqual(await bounds(),national,'设置弹窗关闭后地图外框不移动');
|
||
await p.screenshot({path:'artifacts/container-entry-'+sample.width+'.png'});await chooseProvince(p,'330000');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();
|