From a33ffa3a1529c12f63a0af4862376c4cf027dac8 Mon Sep 17 00:00:00 2001 From: kawa Date: Sat, 3 Oct 2026 18:20:30 +0200 Subject: [PATCH] Make synthetic browser checks independent of private files and timing (#45) --- tests/browser.spec.ts | 10 +++------- tests/native-browser.spec.ts | 34 ++++++++++++++++++++++++++-------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/tests/browser.spec.ts b/tests/browser.spec.ts index dc55713..05d7e43 100644 --- a/tests/browser.spec.ts +++ b/tests/browser.spec.ts @@ -90,11 +90,9 @@ test("actual WASM executes an original cartridge, reads input and round-trips st const emulator = new BinjgbEmulator((error) => { throw error; }); - const wait = () => new Promise((resolve) => setTimeout(resolve, 180)); await emulator.load(new Uint8Array(bytes), canvas); - emulator.play(); - await wait(); - emulator.pause(); + // Advance emulated frames independently of the CI browser's animation rate. + emulator.advanceFrames(12); const before = emulator.exportBattery(); const state = emulator.captureState(); const pixels = canvas.getContext("2d")!.getImageData(0, 0, 160, 144).data; @@ -102,9 +100,7 @@ test("actual WASM executes an original cartridge, reads input and round-trips st for (let i = 0; i < pixels.length; i += 4) colors.add(`${pixels[i]},${pixels[i + 1]},${pixels[i + 2]}`); emulator.setButton("a", true); - emulator.play(); - await wait(); - emulator.pause(); + emulator.advanceFrames(12); const pressed = emulator.exportBattery()[0]; emulator.restoreState(state); const restored = emulator.exportBattery()[0]; diff --git a/tests/native-browser.spec.ts b/tests/native-browser.spec.ts index 4252f06..448cd5d 100644 --- a/tests/native-browser.spec.ts +++ b/tests/native-browser.spec.ts @@ -1,7 +1,14 @@ import { test, expect } from "@playwright/test"; -import { existsSync, readFileSync, writeFileSync } from "node:fs"; +import { + existsSync, + mkdirSync, + mkdtempSync, + readFileSync, + rmSync, + writeFileSync, +} from "node:fs"; import { createHash } from "node:crypto"; -import { resolve } from "node:path"; +import { basename, join, resolve } from "node:path"; import { CrystalAssets } from "../src/game/rom/assets"; import { generatePartyMon } from "../src/game/party/pokemon"; import { GameWorld } from "../src/game/world/world"; @@ -420,12 +427,23 @@ test("walks from New Bark Town onto Route 29 after receiving a starter", async ( test("development server does not serve ROMs or the private reference checkout", async ({ request, }) => { - for (const path of [ - "/Pokemon%20-%20Crystal%20Version%20(UE)%20(V1.1)%20%5BC%5D%5B!%5D.gbc", - "/.reference/pokecrystal/README.md", - ]) { - const response = await request.get(path); - expect([403, 404]).toContain(response.status()); + // Missing paths can return Vite's HTML fallback. Exercise real files using + // disposable synthetic content, without depending on a private checkout. + const directory = mkdtempSync(resolve(".ci-private-")); + try { + mkdirSync(join(directory, ".reference")); + for (const file of ["fixture.gbc", ".reference/README.md"]) { + writeFileSync(join(directory, file), "Synthetic private-file test fixture"); + for (const path of [ + `/${basename(directory)}/${file}`, + `/@fs/${join(directory, file)}`, + ]) { + const response = await request.get(path); + expect(response.status(), path).toBe(403); + } + } + } finally { + rmSync(directory, { recursive: true, force: true }); } });