test(studio): launch real-Chrome tests like the e2e launcher, bounded by the test budget (#5134)

* test(studio): launch real-Chrome tests like the e2e launcher, bounded by the test budget

* test(studio): share the real-Chrome page setup between the two runtime tests

* test(studio): keep the real-Chrome test helper with the other test helpers
This commit is contained in:
Miguel Ángel
2026-10-07 00:25:18 +00:00
committed by GitHub
parent 11e684d305
commit 1825c37268
3 changed files with 38 additions and 39 deletions
@@ -1,18 +1,14 @@
// @vitest-environment happy-dom
// Real Chrome with the built runtime: its seek, not a plain GSAP seek, decides what a saved edit shows.
import { readFileSync } from "node:fs";
import { createRequire } from "node:module";
import { gsap } from "gsap";
import { parseGsapScriptAcorn } from "@hyperframes/parsers/gsap-parser-acorn";
import { replaceTweenWithKeyframesInScript } from "@hyperframes/parsers/gsap-writer-acorn";
import puppeteer from "puppeteer-core";
import { expect, it, vi } from "vitest";
import { findSystemChrome } from "../../vite.browser";
import { launchTestChrome, showWithRuntime } from "../../tests/chromeTestUtils";
import type { DomEditSelection } from "../components/editor/domEditingTypes";
import { usePlayerStore } from "../player/store/playerStore";
import { planValueEdit } from "./gsapValueAtPlayhead";
const require = createRequire(import.meta.url);
vi.setConfig({ testTimeout: 60_000 });
const SRC = `var tl = gsap.timeline({ paused: true });
@@ -49,25 +45,10 @@ const page = (script: string) => `<!doctype html><html><body>
it("a drag on a fromTo's start shows the dropped x there once the runtime seeks", async () => {
const written = writeDrag(90, 2);
const executablePath = findSystemChrome();
if (!executablePath) throw new Error("no Chrome found: set HYPERFRAMES_BROWSER_PATH");
const browser = await puppeteer.launch({
executablePath,
headless: true,
args: ["--no-sandbox"],
});
const browser = await launchTestChrome();
try {
const tab = await browser.newPage();
await tab.setRequestInterception(true);
// Only the GSAP script is served; anything else is refused, never fetched.
tab.on("request", (request) =>
request.url().endsWith("/gsap.min.js")
? request.respond({ body: readFileSync(require.resolve("gsap/dist/gsap.min.js"), "utf8") })
: request.abort("blockedbyclient"),
);
await tab.setContent(page(written), { waitUntil: "load" });
await tab.evaluate(readFileSync(require.resolve("@hyperframes/core/runtime"), "utf8"));
await tab.waitForFunction(() => "__player" in window);
await showWithRuntime(tab, page(written));
const shown = await tab.evaluate(() => {
const w = window as unknown as {
__player: { seek(t: number): void };
@@ -1,16 +1,14 @@
// Real Chrome: the box GSAP and a stylesheet translate produce together is what no DOM emulation computes.
import { mkdtempSync, readFileSync } from "node:fs";
import { createRequire } from "node:module";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { fileURLToPath } from "node:url";
import puppeteer, { type Browser } from "puppeteer-core";
import type { Browser } from "puppeteer-core";
import { build, type Plugin } from "esbuild";
import { afterAll, beforeAll, expect, it, vi } from "vitest";
import { findSystemChrome } from "../../vite.browser";
import { launchTestChrome, showWithRuntime } from "../../tests/chromeTestUtils";
import { writeFixture } from "../../tests/e2e/edit-accuracy/grid.mjs";
const require = createRequire(import.meta.url);
const CROP = "inset(0px 40px 0px 0px)";
// Real Chrome on a loaded Windows runner exceeds Vitest's 5s test and 10s hook defaults.
vi.setConfig({ testTimeout: 60_000, hookTimeout: 60_000 });
@@ -44,9 +42,7 @@ async function bundle(file: string, name: string): Promise<string> {
}
beforeAll(async () => {
const executablePath = findSystemChrome();
if (!executablePath) throw new Error("no Chrome found: set HYPERFRAMES_BROWSER_PATH");
browser = await puppeteer.launch({ executablePath, headless: true, args: ["--no-sandbox"] });
browser = await launchTestChrome();
undoBundle = await bundle("./gsapUndoRestore.ts", "hfUndo");
softReloadBundle = await bundle("./gsapSoftReload.ts", "hfSoftReload");
});
@@ -62,16 +58,7 @@ async function openCase(spec: Spec, moduleBundle: string) {
const restored = readFileSync(join(dir, "index.html"), "utf8");
const page = await browser.newPage();
await page.setViewport({ width: 1920, height: 1080 });
await page.setRequestInterception(true);
// Only the fixture's GSAP CDN script is served; anything else is refused, never fetched.
page.on("request", (request) =>
request.url().endsWith("/gsap.min.js")
? request.respond({ body: readFileSync(require.resolve("gsap/dist/gsap.min.js"), "utf8") })
: request.abort("blockedbyclient"),
);
await page.setContent(restored, { waitUntil: "load" });
await page.evaluate(readFileSync(require.resolve("@hyperframes/core/runtime"), "utf8"));
await page.waitForFunction(() => "__player" in window);
await showWithRuntime(page, restored);
await page.evaluate(moduleBundle);
await page.evaluate(
(time) => (window as unknown as { __player: { seek(t: number): void } }).__player.seek(time),
+31
View File
@@ -0,0 +1,31 @@
import { readFileSync } from "node:fs";
import { createRequire } from "node:module";
import puppeteer, { type Browser, type Page } from "puppeteer-core";
import { findSystemChrome } from "../vite.browser";
const require = createRequire(import.meta.url);
/** Headless Chrome with the e2e launcher's flags; the test's own timeout bounds the launch. */
export async function launchTestChrome(): Promise<Browser> {
const executablePath = findSystemChrome();
if (!executablePath) throw new Error("no Chrome found: set HYPERFRAMES_BROWSER_PATH");
return puppeteer.launch({
executablePath,
headless: true,
args: ["--no-sandbox", "--disable-dev-shm-usage", "--disable-gpu"],
timeout: 0,
});
}
/** Shows `html` with the HyperFrames runtime; only its GSAP CDN script is served, nothing is fetched. */
export async function showWithRuntime(page: Page, html: string): Promise<void> {
await page.setRequestInterception(true);
page.on("request", (request) =>
request.url().endsWith("/gsap.min.js")
? request.respond({ body: readFileSync(require.resolve("gsap/dist/gsap.min.js"), "utf8") })
: request.abort("blockedbyclient"),
);
await page.setContent(html, { waitUntil: "load" });
await page.evaluate(readFileSync(require.resolve("@hyperframes/core/runtime"), "utf8"));
await page.waitForFunction(() => "__player" in window);
}