forked from phenom/healer-man
103 lines
6.4 KiB
JavaScript
103 lines
6.4 KiB
JavaScript
const { chromium } = require('C:/Users/phenom/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/playwright');
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
const assert = require('node:assert/strict');
|
|
|
|
const out = path.resolve('playtest-artifacts/dungeon-race');
|
|
fs.mkdirSync(out, { recursive: true });
|
|
const base = process.env.RACE_TEST_URL || 'http://127.0.0.1:5173';
|
|
|
|
(async () => {
|
|
const browser = await chromium.launch({ channel: 'msedge', headless: true });
|
|
const page = await browser.newPage({ viewport: { width: 1280, height: 800 } });
|
|
const errors = [];
|
|
page.on('pageerror', (error) => errors.push(error.message));
|
|
try {
|
|
await page.goto(base, { waitUntil: 'domcontentloaded', timeout: 120_000 });
|
|
await page.getByRole('button', { name: /Play offline/ }).click();
|
|
await page.getByRole('button', { name: /Create character/ }).click();
|
|
await page.getByRole('button', { name: /Customize & name/ }).click();
|
|
await page.getByLabel('Character name').fill('RaceTester');
|
|
await page.getByRole('button', { name: /Create character/ }).click();
|
|
await page.getByRole('button', { name: /Continue|Enter world/ }).first().click({ force: true });
|
|
await page.getByRole('button', { name: 'Continue', exact: true }).click();
|
|
await page.locator('.main-menu-screen').waitFor();
|
|
await page.getByRole('button', { name: /Dungeon Race/ }).click();
|
|
await page.locator('.dungeon-race-screen').waitFor();
|
|
await page.screenshot({ path: path.join(out, '01-setup-desktop.png') });
|
|
assert.equal(await page.getByRole('button', { name: 'Offline practice' }).getAttribute('aria-pressed'), 'true');
|
|
await page.locator('.dungeon-race-screen__setup select').first()
|
|
.selectOption('bite-sized-stormwind-stockade');
|
|
await page.getByRole('button', { name: 'Start practice' }).click();
|
|
await page.locator('.game-shell').waitFor({ timeout: 120_000 });
|
|
await page.locator('.dungeon-race-hud').waitFor({ timeout: 120_000 });
|
|
await page.locator('.dungeon-boss-intro').waitFor({ state: 'visible', timeout: 120_000 });
|
|
await page.locator('.dungeon-boss-intro').waitFor({ state: 'hidden', timeout: 120_000 });
|
|
await page.locator('.dungeon-race-countdown').waitFor({ state: 'visible', timeout: 30_000 });
|
|
await page.locator('.dungeon-race-countdown').waitFor({ state: 'hidden', timeout: 30_000 });
|
|
await page.screenshot({ path: path.join(out, '02-active-desktop.png') });
|
|
const state = await page.evaluate(async () => {
|
|
const { useDungeonRaceStore } = await import('/src/app/dungeonRaceStore.ts');
|
|
const { useGameStore } = await import('/src/game/store.ts');
|
|
const race = useDungeonRaceStore.getState();
|
|
return { mode: race.mode, status: race.status, inGame: race.inGame,
|
|
dungeonId: race.dungeonId, activeDungeonId: useGameStore.getState().activeDungeonId,
|
|
opponentSeats: race.opponent?.type === 'bot' ? race.opponent.roster.length : 0 };
|
|
});
|
|
assert.equal(state.mode, 'practice');
|
|
assert.equal(state.status, 'active');
|
|
assert.equal(state.inGame, true);
|
|
assert.equal(state.opponentSeats, 5);
|
|
assert.equal(state.activeDungeonId, state.dungeonId);
|
|
await page.evaluate(async () => {
|
|
const { useDungeonRaceStore } = await import('/src/app/dungeonRaceStore.ts');
|
|
const race = useDungeonRaceStore.getState();
|
|
useDungeonRaceStore.setState({ startAt: Date.now() - race.opponent.finishMs - 1000, result: null });
|
|
useDungeonRaceStore.getState().tick();
|
|
});
|
|
await page.locator('.dungeon-race-toast--loss').waitFor();
|
|
assert.equal(await page.locator('.game-shell').count(), 1);
|
|
await page.screenshot({ path: path.join(out, '03-loss-continues-desktop.png') });
|
|
await page.setViewportSize({ width: 960, height: 540 });
|
|
await page.screenshot({ path: path.join(out, '04-loss-thor-size.png') });
|
|
const card = await page.evaluate(async () => {
|
|
const { useCombatStore } = await import('/src/game/combatStore.ts');
|
|
const { BOSS_CARD_CATALOG } = await import('/src/game/bossCardCatalog.ts');
|
|
const definition = BOSS_CARD_CATALOG.find((entry) => entry.dungeons.some((dungeon) => dungeon.id === 'stormwind-stockade'));
|
|
const mob = Object.values(useCombatStore.getState().mobs)[0];
|
|
if (!definition || !mob) throw new Error(`Boss-card fixture is unavailable: definition=${Boolean(definition)} mob=${Boolean(mob)}.`);
|
|
const before = useCombatStore.getState().bossCards.counts[definition.key]?.normal ?? 0;
|
|
useCombatStore.setState((state) => ({ mobs: { ...state.mobs,
|
|
[mob.id]: { ...mob, name: definition.name, boss: true, dead: true, hasLoot: true,
|
|
looted: false, despawned: false, pendingLoot: [],
|
|
bossCardDrop: { bossKey: definition.key, spawnId: mob.id,
|
|
claimId: `${Date.now()}:1`, rarities: ['normal'] } } } }));
|
|
const looted = useCombatStore.getState().lootMob(mob.id);
|
|
return { looted, before, after: useCombatStore.getState().bossCards.counts[definition.key]?.normal ?? 0 };
|
|
});
|
|
console.log('Post-loss boss-card result:', card);
|
|
assert.equal(card.after, card.before + 1);
|
|
await page.waitForTimeout(300);
|
|
await page.screenshot({ path: path.join(out, '05-card-after-loss-fixture.png') });
|
|
await page.keyboard.press('Escape');
|
|
await page.getByRole('dialog', { name: 'Paused' }).getByRole('button', { name: 'Main menu' }).click();
|
|
await page.locator('.main-menu-screen').waitFor();
|
|
const afterExit = await page.evaluate(async () => {
|
|
const { useDungeonRaceStore } = await import('/src/app/dungeonRaceStore.ts');
|
|
const race = useDungeonRaceStore.getState();
|
|
return { mode: race.mode, inGame: race.inGame, matchId: race.matchId };
|
|
});
|
|
assert.deepEqual(afterExit, { mode: null, inGame: false, matchId: null });
|
|
await page.getByRole('button', { name: /Dungeon Race/ }).click();
|
|
await page.getByRole('button', { name: 'Start practice' }).click();
|
|
await page.locator('.game-shell').waitFor({ timeout: 120_000 });
|
|
await page.locator('.dungeon-race-hud').waitFor({ timeout: 120_000 });
|
|
assert.deepEqual(errors, []);
|
|
console.log(JSON.stringify({ ok: true, state, card, afterExit, screenshots: out }, null, 2));
|
|
} catch (error) {
|
|
await page.screenshot({ path: path.join(out, 'failure.png') });
|
|
console.error((await page.locator('body').innerText()).slice(0, 5000));
|
|
throw error;
|
|
} finally { await browser.close(); }
|
|
})().catch((error) => { console.error(error); process.exitCode = 1; });
|