feedback7: watch-bonds' "after the own battle" test gets a real window — the guest's enemies spawn at twice their times (new fastServer hook SP_SLOW_SPAWNS, startRealServer fast.slowSpawns), the host fields its 萨尔贡 five without 菲莱 (the planner puts a zero-range guard on the road since PR #339 and she held the host's battle to 109 s of 110), and 返回战场 tolerates the battles ending; measured: at the scheduled times a leaker's walk outlasted the host by 5–11 s in 0.2.1 and 0.2.2 alike (the 0.2.2 full pass lost 返回战场 to 联防)

This commit is contained in:
sganggs committed 2026-10-09 00:52:08 +08:00
1 parent e5e3f05bb2
commit 9bacd9ad45
3 files changed
+40 -9

No files matched your search

+18 -7
View File
@@ -17,8 +17,8 @@
// the pair field → its first player's bonds (never its own), taps the second player's operator and its card's bond
// chip → the SECOND player's popup (the strip stays on the first), taps each pair player → their half + bonds, taps
// the lone field's player → that field and its player's bonds.
// After the own battle (2 humans + 1 idle AI from round 3, 1× combat): the host's battle ends first, the host watches a
// teammate still fighting → the strip shows that teammate's bonds with the observing pill "👁 name" + 返回战场; a
// After the own battle (2 humans + 1 idle AI from round 3, 1× combat, the guest's enemies spawning at twice their times):
// the host's battle ends first, the host watches a teammate still fighting → the strip shows that teammate's bonds with the observing pill "👁 name" + 返回战场; a
// reload keeps all three (the resent field is adopted — battle/observe.js resumedWatch); 返回战场 → the own bonds.
// Unit counterparts: test/ui/watch-bonds.test.js (selection logic incl. 联防), test/match/watch-bonds.test.js (views),
// test/match/observe.test.js (resumedWatch).
@@ -39,6 +39,10 @@ const GUEST_KIT = ['chess_char_1_03_a', 'chess_char_1_09_a']; // 惊蛰 (炎),
// the AI seats five 拉特兰 ones + 古米 (信仰搅拌机, 莫斯提马, 能天使, 空弦, 送葬人; 坚守) — different bonds on each strip
const UNITE_HOST_KIT = ['chess_char_4_23_a', 'chess_char_4_24_a', 'chess_char_3_06_a', 'chess_char_3_13_a', 'chess_char_1_12_a', 'chess_char_2_06_a'];
const BOT_KIT = ['chess_char_4_01_a', 'chess_char_4_02_a', 'chess_char_3_01_a', 'chess_char_3_21_a', 'chess_char_2_01_a', 'chess_char_1_10_a'];
// "after the own battle": the same host without 菲莱 — the layout planner behind fastServer's autoPlace puts a zero-range
// guard on a road tile first (PR #339, §27.35), where she holds the enemies and the host's battle could run 109 s of a
// 110 s round-3 limit (measured; 53–68 s without her)
const AFTER_HOST_KIT = UNITE_HOST_KIT.filter((id) => id !== 'chess_char_3_06_a');
/** The strip as shown: whose (data-owner), the bonds (data-bond) with their counts, the tag's text. */
const stripOf = (c) => c.page.evaluate(() => {
@@ -470,10 +474,12 @@ describe('DESIGN §20.15 — the bond strip shows the watched teammate\'s bonds
});
test('after the own battle: the watched teammate\'s bonds, kept through a reload with the observing pill + 返回战场 (desktop)', { timeout: 12 * 60 * 1000 }, async () => {
// the host's six 萨尔贡 operators end their battle early; the guest (no board) and the idle AI leak for the enemies'
// whole walk (combat at 1×: a window for the reload) — the host watches one of them, reloads, then goes back
// the host's five 萨尔贡 operators end their battle first; the guest (no board) leaks, and its enemies spawn at twice
// their times (fastServer SP_SLOW_SPAWNS), so its battle runs to the round's time limit — a window of 40 s and more
// for watching it and a reload (at the scheduled times a leaker's walk outlasted the host's battle by 5–11 s in 0.2.1
// and 0.2.2 alike, and the 0.2.2 full pass lost 返回战场 to 联防); the host watches the guest, reloads, then goes back
const srv = await startRealServer({ fast: { timerScale: 1, combatSpeed: 1, startRound: 3, idleBots: true, autoPlace: true,
kits: [UNITE_HOST_KIT, []] } });
kits: [AFTER_HOST_KIT, []], slowSpawns: '1:2' } });
const P = (await import('puppeteer-core')).default;
let host = null;
let guest = null;
@@ -539,8 +545,13 @@ describe('DESIGN §20.15 — the bond strip shows the watched teammate\'s bonds
for (const id of await pubBonds()) assert.ok(st.bonds.includes(id), `after the reload: ${name}'s ${id} on the strip (${JSON.stringify(st.bonds)})`);
await sleep(1500); // the phase banner of the fresh screen
await host.shot('reloaded');
// 返回战场 → the own bonds, untagged
await host.click('.chud__observe .chud__back', '返回战场');
// 返回战场 → the own bonds, untagged. The watched battle may end meanwhile — 联防 or the settlement takes the
// screen and the pill with it (the 0.2.2 full pass) — then the next round tries again
if (!(await host.click('.chud__observe .chud__back', '返回战场', { optional: true, timeout: 8000 }))) {
const phase = (await host.st()).phase;
if (phase !== 'COMBAT') { console.log(`round ${round}: the battles ended before 返回战场 (${phase}), next round`); continue; }
throw new Error('host: nothing clickable for .chud__observe .chud__back "返回战场" while the battle runs');
}
await host.page.waitForFunction(() => !document.querySelector('.gm__bonds .bstrip')?.getAttribute('data-owner'), { timeout: 8000 });
st = await stripOf(host);
assert.deepEqual([st.owner, st.observe], [null, null], 'back: own bonds, no observing pill');