Files
Crystal/tests/radio-browser.spec.ts
kawaandClaude Opus 5.5 7c12c81a27
Checks / web (push) Successful in 2m38s
Private ROM checks / private-rom (push) Successful in 20m37s
Ring with trainers' calls, rematch them and play the radio (Closes #30)
Every registered trainer's callee and caller scripts run, with the
missing specials and commands (RandomPhoneWildMon, RandomUnseenWildMon,
swarms, gettrainerclassname, Kenji's break, the Blue Card and Buena's
password variables). Fight counts are saved, so rematches and gifts work
on every open map, and the daily reset clears the phone's flags.

Random calls follow CheckPhoneCall and the 20/10/5/3-minute call timer;
received calls ring twice with the caller's name, and calls play their
ringing, hang-up and no-signal sounds. Grass and fishing swarms use the
swarm tables.

The radio ports PlayRadioShow and every station frame by frame, with its
music: the Pokégear's radio card tunes by knob, house radios play through
MapRadio, and Buena's show takes the day's password for Blue Card points
that her receptionist exchanges for prizes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 11:10:02 +02:00

50 lines
2.2 KiB
TypeScript

import { test, expect, type Page } from "@playwright/test";
import { existsSync } from "node:fs";
import { resolve } from "node:path";
const romPath = resolve(
process.env.CRYSTAL_ROM_PATH ?? "Pokemon - Crystal Version (UE) (V1.1) [C][!].gbc",
);
test.beforeEach(() => test.skip(!existsSync(romPath), "Requires the local user ROM."));
async function start(page: Page) {
await page.route("**/src/game/runtime.ts", async (route) => {
const response = await route.fetch(),
source = await response.text();
const needle = "const world = new GameWorld(assets);";
expect(source).toContain(needle);
await route.fulfill({
response,
body: source.replace("this.world?.beginIntro();", "").replace(
needle,
`const { radioFixtureWorld } = await import('/tests/radio-fixture.ts'); const world = radioFixtureWorld(assets);`,
),
});
});
await page.goto("/");
await page.locator("#rom-file").setInputFiles(romPath);
await expect(page.locator("#status")).toContainText("verified");
await page.locator("#play").click();
}
test("the Pokégear's radio card tunes in Oak's Pokémon Talk and plays it", async ({ page }) => {
const errors: string[] = [];
page.on("pageerror", (error) => errors.push(error.message));
await start(page);
await page.keyboard.press("Enter");
await page.locator("#dialogue-choice").getByRole("option", { name: /^POKéGEAR/ }).click();
await expect(page.locator("#pokegear")).toBeVisible();
await page.keyboard.press("ArrowRight");
const radio = page.locator(".pokegear-radio");
await expect(radio).toBeVisible();
await expect(radio.locator(".pokegear-frequency")).toHaveText("FM 0.5");
for (let press = 0; press < 8; press++) await page.keyboard.press("ArrowUp");
await expect(radio.locator(".pokegear-frequency")).toHaveText("FM 4.5");
await expect(radio.locator("strong")).toContainText("Talk");
await expect(radio.locator(".pokegear-radio-text")).toContainText("MARY: PROF.OAK'S");
await expect(radio.locator(".pokegear-radio-text")).toContainText("TALK!", { timeout: 10_000 });
await page.keyboard.press("KeyZ");
await expect(page.locator("#pokegear")).toBeHidden();
expect(errors).toEqual([]);
});