- 玩法一 数字一笔:规则库、求解器、26 关、竖屏触摸 Web 原型、测试 - 玩法二 连连气球:连消畅玩版核心、Web 原型、Cocos 球槽组件与导出脚本 - 玩法三 六边一笔:规则库、求解器、10 关 + 转墙实验包、Web 原型、测试 - 产品文档、UI 设计规范、各玩法 GDD / HANDOFF - 文档移除全部外部参考作引用;删除玩法二 v0 旧稿
55 lines
4.3 KiB
JavaScript
55 lines
4.3 KiB
JavaScript
const space = Number(process.env.GARDEN_SPACE);
|
|
if (!space || !process.env.GARDEN_QA_DIR) throw new Error('请设置 GARDEN_SPACE 与 GARDEN_QA_DIR,复用当前 QA 空间。');
|
|
const task = await taskSpace(space), page = task.page('p1');
|
|
const fs = await import('node:fs/promises');
|
|
const root = process.env.GARDEN_QA_DIR;
|
|
await page.reload();
|
|
await page.waitForFunction(() => !!window.__garden);
|
|
const saved = await page.evaluate(() => JSON.parse(localStorage.getItem('mode:02-connect-1234:v1')));
|
|
if (Object.keys(saved.levels).length !== 10) throw new Error('completion not persisted');
|
|
let before = await page.evaluate(() => window.__garden.snapshot());
|
|
const touchHint = async () => {
|
|
const data = await page.evaluate(() => {
|
|
const g=window.__garden, s=g.snapshot(), t=g.transform(), r=document.getElementById('board').getBoundingClientRect();
|
|
return { merges:s.stats.merges, points:g.hint().map(id=>{const b=s.balls.find(b=>b.id===id);return {x:r.left+t.x+b.x*t.scale,y:r.top+t.y+b.y*t.scale};})};
|
|
});
|
|
for (let i=0;i<data.points.length;i++) await page.cdp('Input.dispatchTouchEvent',{type:i?'touchMove':'touchStart',touchPoints:[{...data.points[i],id:0,radiusX:5,radiusY:5,force:1}]});
|
|
await page.cdp('Input.dispatchTouchEvent',{type:'touchEnd',touchPoints:[]});
|
|
await page.waitForFunction(n=>window.__garden.snapshot().stats.merges===n+1&&!window.__garden.animating(),data.merges,{timeout:5000});
|
|
};
|
|
await touchHint();
|
|
const after = await page.evaluate(() => window.__garden.snapshot());
|
|
await page.click('#undo');
|
|
if (JSON.stringify(await page.evaluate(()=>window.__garden.snapshot()))!==JSON.stringify(before)) throw new Error('undo not exact');
|
|
await touchHint();
|
|
if (JSON.stringify(await page.evaluate(()=>window.__garden.snapshot()))!==JSON.stringify(after)) throw new Error('redo not deterministic');
|
|
await page.click('#undo');
|
|
await page.click('#shuffle');
|
|
const shuffled = await page.evaluate(()=>window.__garden.snapshot());
|
|
if (shuffled.shuffles!==0 || shuffled.movesLeft!==before.movesLeft || JSON.stringify(shuffled.balls.map(b=>b.n).sort())!==JSON.stringify(before.balls.map(b=>b.n).sort())) throw new Error('shuffle mismatch');
|
|
await page.click('#undo');
|
|
if (JSON.stringify(await page.evaluate(()=>window.__garden.snapshot()))!==JSON.stringify(before)) throw new Error('shuffle undo mismatch');
|
|
await page.click('#levels'); await page.click('[data-action="endless"]');
|
|
await touchHint();
|
|
if ((await page.evaluate(()=>window.__garden.snapshot())).movesLeft!==-1) throw new Error('endless consumed move');
|
|
await page.click('#levels'); await page.click('[data-level="8"]');
|
|
const layouts=[];
|
|
for (const [width,height,mobile] of [[320,568,true],[360,740,true],[390,844,true],[430,932,true],[844,390,true],[1280,900,false]]) {
|
|
await page.cdp('Emulation.setDeviceMetricsOverride',{width,height,deviceScaleFactor:2,mobile});
|
|
await page.evaluate(()=>new Promise(resolve=>requestAnimationFrame(()=>requestAnimationFrame(resolve))));
|
|
const layout=await page.evaluate(()=>({width:innerWidth,height:innerHeight,overflow:document.documentElement.scrollWidth>innerWidth+1,bodyHeight:document.documentElement.scrollHeight,buttons:[...document.querySelectorAll('.tools button,.header-actions button')].map(b=>({id:b.id,w:b.getBoundingClientRect().width,h:b.getBoundingClientRect().height}))}));
|
|
if(layout.overflow)throw new Error(`horizontal overflow at ${width}`);
|
|
if(layout.buttons.some(b=>b.w<44||b.h<44))throw new Error(`small touch target at ${width}`);
|
|
layouts.push(layout);
|
|
if(width===320||width===1280)await page.screenshot({path:`${root}/${width===320?'mobile-320':'desktop'}.png`});
|
|
}
|
|
await page.cdp('Emulation.setDeviceMetricsOverride',{width:390,height:844,deviceScaleFactor:2,mobile:true});
|
|
await page.click('#help');
|
|
await page.waitForFunction(()=>!document.getElementById('sheet').getAnimations().some(a=>a.playState==='running'));
|
|
await page.screenshot({path:`${root}/mobile-help.png`});
|
|
await page.keyboard.press('Escape');
|
|
if(!(await page.evaluate(()=>document.getElementById('modal').hidden)))throw new Error('escape not closed');
|
|
await fs.writeFile(`${root}/layout.json`,JSON.stringify({checks:['刷新保留十关成绩','撤销精确恢复盘面及补球','重走结果确定一致','打乱保留数字和步数','撤销恢复打乱库存','自由模式无步数限制','帮助可用 Escape 关闭'],layouts},null,2));
|
|
console.log(JSON.stringify(layouts));
|
|
console.log(await page.snapshot());
|