Files
shanhe-puzzle/tests/container-layout.mjs
T
codex-bot 4845826deb
Shanhe source and offline package checks / verify (pull_request) Failing after 5s
feat: sync Shanhe 2.2 source and add remote package verification
2026-11-01 17:13:46 +08:00

14 lines
4.4 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 {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();