pcbjam/tests/playwright-kicad.config.ts

249 lines
11 KiB
TypeScript
Raw Normal View History

import { defineConfig, devices } from "@playwright/test";
import { execSync } from "child_process";
import * as fs from "fs";
import * as path from "path";
const PORT_FILE = path.join(__dirname, ".test-port");
// NOTE: Chrome headless crashes on ARM Mac due to SwiftShader WebGL bug
// (Chromium issues #1416283, #338414704). Firefox headless works reliably.
// Use --project=firefox for headless, --project=chromium for headed debugging.
2026-06-04 13:20:55 +02:00
// Resolve the static-server port for this run.
//
// This config file is re-imported by EVERY Playwright process: the main runner
// (which launches the webServer) and each worker process (which calls
// page.goto(baseURL)). They must all agree on one port. Playwright also
// *recreates* a worker mid-run after a test times out or crashes — and that new
// worker re-imports this config.
//
// The previous heuristic ("reuse .test-port if it's <60s old, else pick a new
// free port") broke exactly there: once a run passed the 60s mark, a recreated
// worker treated the file as stale, picked a DIFFERENT free port, and every
// subsequent page.goto hit a dead port (NS_ERROR_CONNECTION_REFUSED) because the
// webServer was still listening on the original port. A single timing-out test
// (e.g. eeschema-load) thus cascaded into ~all later tests failing.
//
// Fix: drop the time window entirely. The main runner always picks a fresh port
// and writes it; workers always reuse whatever the main runner wrote. The main
// runner is the only process whose argv carries the `test` command (workers are
// forked with an empty argv), and it imports this config — and so writes the
// file — before any worker is spawned.
function resolvePort(): number {
const isMainRunner = process.argv.slice(2).includes("test");
2026-06-04 13:20:55 +02:00
if (!isMainRunner) {
try {
const existing = parseInt(fs.readFileSync(PORT_FILE, "utf-8").trim(), 10);
2026-06-04 13:20:55 +02:00
if (existing > 0 && existing < 65536) {
return existing;
}
2026-06-04 13:20:55 +02:00
} catch {
// No readable port file — fall through. Shouldn't happen in a worker,
// since the main runner writes the file before spawning workers.
}
}
const port = findFreePort();
fs.writeFileSync(PORT_FILE, port.toString());
return port;
}
function findFreePort(): number {
try {
const result = execSync(
"python3 -c \"import socket; s=socket.socket(); s.bind(('',0)); print(s.getsockname()[1]); s.close()\"",
{ encoding: "utf-8", timeout: 5000 }
);
return parseInt(result.trim());
} catch {
return 9000 + Math.floor(Math.random() * 1000);
}
}
2026-06-04 13:20:55 +02:00
const port = resolvePort();
feat(wasm): kicad_editor — merge the pcbnew+eeschema kifaces into ONE bundle (Part 2) All four editors (PCB / Footprint / Schematic / Symbol) are now runtime --frame choices of a single kicad_editor.wasm (178 MB at -O1 vs 147+82 separate; shared wx/common/boost linked once). One editor per page load, as before; frames pcb / fpedit / sch / symedit. - wasm/editor/: the merged executable target (single_top + both kiface library sets, whole-archive pcbcommon) + the safety-net focus-walk Kiface() dispatch TU. Gated by KICAD_WASM_MERGED_EDITOR (kicad submodule bump carries the fork side: per-engine Kiface/getter binding + ODR renames + dual-kiface launcher). - wasm/bindings/: per-editor collab entries renamed pcbCollab*/schCollab* (JS names unchanged); duplicate kicadOpenFile/kicadCollabOnSave + shared-name registrations guarded behind KICAD_MERGED_EMBIND; new kicad_editor_embind.cpp registers each shared JS name once, dispatching on the live frame. - Build: kicad_editor app (build wrapper, target case arms, 3-object embind compile with the ABI-critical flags, STUB_APP=pcbnew); docker/build.sh "all" = kicad_editor calculator pl_editor gerbview (pcbnew/eeschema stay as explicit debug apps); scripts/kicad/audit-merged-symbols.sh = repeatable ODR-collision audit (run on kicad bumps). - Frontend: Bundle type (bundle ≠ tool); TOOL_BUNDLE maps all four editors to kicad_editor; explicit --frame tokens for pcbnew (pcb) and eeschema (sch); publish list = the 4 real bundles. - Tests/CI: five harnesses load kicad_editor.js with explicit frame tokens; PCBNEW_FAMILY_SPECS renamed BIG_MODULE_SPECS + the 8 eeschema-family specs (they now boot the merged module — SpiderMonkey x86 CI OOM routing); frame-runtime spec covers all four frames from the one bundle. Validated so far: frame-runtime 4/4 (each frame boots with the right title, no aborts, no duplicate embind registration); 24-spec merged-module regression green; 3D raytracer renders. Known pre-existing failure: 3d-viewer title-bar drag deadlock, fixed on main by 7630c7e (2N+8 pthread pre-warm) — picked up by the follow-up rebase. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 14:48:11 +02:00
// The merged kicad_editor wasm (~190M+ debug build; pcbnew+eeschema engines in one
// image since editor-unification Part 2) exceeds SpiderMonkey's per-process code
// budget on x86-64 CI even with the baseline-only JIT (run 27343416511:
// "InternalError: out of memory" at instantiation; the same module compiles
feat(wasm): kicad_editor — merge the pcbnew+eeschema kifaces into ONE bundle (Part 2) All four editors (PCB / Footprint / Schematic / Symbol) are now runtime --frame choices of a single kicad_editor.wasm (178 MB at -O1 vs 147+82 separate; shared wx/common/boost linked once). One editor per page load, as before; frames pcb / fpedit / sch / symedit. - wasm/editor/: the merged executable target (single_top + both kiface library sets, whole-archive pcbcommon) + the safety-net focus-walk Kiface() dispatch TU. Gated by KICAD_WASM_MERGED_EDITOR (kicad submodule bump carries the fork side: per-engine Kiface/getter binding + ODR renames + dual-kiface launcher). - wasm/bindings/: per-editor collab entries renamed pcbCollab*/schCollab* (JS names unchanged); duplicate kicadOpenFile/kicadCollabOnSave + shared-name registrations guarded behind KICAD_MERGED_EMBIND; new kicad_editor_embind.cpp registers each shared JS name once, dispatching on the live frame. - Build: kicad_editor app (build wrapper, target case arms, 3-object embind compile with the ABI-critical flags, STUB_APP=pcbnew); docker/build.sh "all" = kicad_editor calculator pl_editor gerbview (pcbnew/eeschema stay as explicit debug apps); scripts/kicad/audit-merged-symbols.sh = repeatable ODR-collision audit (run on kicad bumps). - Frontend: Bundle type (bundle ≠ tool); TOOL_BUNDLE maps all four editors to kicad_editor; explicit --frame tokens for pcbnew (pcb) and eeschema (sch); publish list = the 4 real bundles. - Tests/CI: five harnesses load kicad_editor.js with explicit frame tokens; PCBNEW_FAMILY_SPECS renamed BIG_MODULE_SPECS + the 8 eeschema-family specs (they now boot the merged module — SpiderMonkey x86 CI OOM routing); frame-runtime spec covers all four frames from the one bundle. Validated so far: frame-runtime 4/4 (each frame boots with the right title, no aborts, no duplicate embind registration); 24-spec merged-module regression green; 3D raytracer renders. Known pre-existing failure: 3d-viewer title-bar drag deadlock, fixed on main by 7630c7e (2N+8 pthread pre-warm) — picked up by the follow-up rebase. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 14:48:11 +02:00
// on arm64, whose denser code fits). V8 handles it, so on CI every spec that
// boots the merged module — i.e. ALL FOUR editors — runs on bundled Chromium
// (the 'chromium-ci' project) and firefox skips them. Firefox keeps the small
// separate bundles (pl_editor / calculator / gerbview).
const BIG_MODULE_SPECS = [
"**/pcbnew.spec.ts",
"**/pcbnew-collab.spec.ts",
"**/load-pcb.spec.ts",
"**/load-pcb-probe.spec.ts",
2026-06-15 11:52:17 +02:00
// Specs added 2026-06-11..06-13 that boot pcbnew (pcbnew.html /
// pcbnew-collab.html). Without routing here they ran on Firefox in CI and
// timed out at instantiation (the SpiderMonkey/x86 code-budget OOM above).
feat(wasm): kicad_editor — merge the pcbnew+eeschema kifaces into ONE bundle (Part 2) All four editors (PCB / Footprint / Schematic / Symbol) are now runtime --frame choices of a single kicad_editor.wasm (178 MB at -O1 vs 147+82 separate; shared wx/common/boost linked once). One editor per page load, as before; frames pcb / fpedit / sch / symedit. - wasm/editor/: the merged executable target (single_top + both kiface library sets, whole-archive pcbcommon) + the safety-net focus-walk Kiface() dispatch TU. Gated by KICAD_WASM_MERGED_EDITOR (kicad submodule bump carries the fork side: per-engine Kiface/getter binding + ODR renames + dual-kiface launcher). - wasm/bindings/: per-editor collab entries renamed pcbCollab*/schCollab* (JS names unchanged); duplicate kicadOpenFile/kicadCollabOnSave + shared-name registrations guarded behind KICAD_MERGED_EMBIND; new kicad_editor_embind.cpp registers each shared JS name once, dispatching on the live frame. - Build: kicad_editor app (build wrapper, target case arms, 3-object embind compile with the ABI-critical flags, STUB_APP=pcbnew); docker/build.sh "all" = kicad_editor calculator pl_editor gerbview (pcbnew/eeschema stay as explicit debug apps); scripts/kicad/audit-merged-symbols.sh = repeatable ODR-collision audit (run on kicad bumps). - Frontend: Bundle type (bundle ≠ tool); TOOL_BUNDLE maps all four editors to kicad_editor; explicit --frame tokens for pcbnew (pcb) and eeschema (sch); publish list = the 4 real bundles. - Tests/CI: five harnesses load kicad_editor.js with explicit frame tokens; PCBNEW_FAMILY_SPECS renamed BIG_MODULE_SPECS + the 8 eeschema-family specs (they now boot the merged module — SpiderMonkey x86 CI OOM routing); frame-runtime spec covers all four frames from the one bundle. Validated so far: frame-runtime 4/4 (each frame boots with the right title, no aborts, no duplicate embind registration); 24-spec merged-module regression green; 3D raytracer renders. Known pre-existing failure: 3d-viewer title-bar drag deadlock, fixed on main by 7630c7e (2N+8 pthread pre-warm) — picked up by the follow-up rebase. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 14:48:11 +02:00
// appearance/roundtrip/save-hook are parametrized across pl_editor/eeschema/
// pcbnew; routing the whole file moves the small-bundle variants to chromium-ci
// too (they boot fine on V8) — only the browser changes, not whether they run.
"**/appearance.spec.ts",
"**/contextmenu-scrollbar-pcbnew.spec.ts",
"**/dark-mode.spec.ts",
"**/items-bridge.spec.ts",
"**/roundtrip.spec.ts",
"**/save-hook.spec.ts",
// boots pcbnew.html — must run on V8 (chromium-ci); on Firefox/x86 CI the
// ~190M module OOMs at instantiation and #canvas never appears (run 27626037849).
"**/pcbnew-move.spec.ts",
// 3D viewer specs boot pcbnew.html (3D-enabled build) — same V8 routing.
"**/3d-viewer.spec.ts",
// Isolated (own file → own worker) so its heavy single load isn't degraded by the
// Worker accumulation of the other 3D-viewer tests sharing a process (see the file header).
"**/3d-viewer-deadlock.spec.ts",
"**/3d-viewer-models.spec.ts",
"**/footprint-3d-preview.spec.ts",
feat(wasm): kicad_editor — merge the pcbnew+eeschema kifaces into ONE bundle (Part 2) All four editors (PCB / Footprint / Schematic / Symbol) are now runtime --frame choices of a single kicad_editor.wasm (178 MB at -O1 vs 147+82 separate; shared wx/common/boost linked once). One editor per page load, as before; frames pcb / fpedit / sch / symedit. - wasm/editor/: the merged executable target (single_top + both kiface library sets, whole-archive pcbcommon) + the safety-net focus-walk Kiface() dispatch TU. Gated by KICAD_WASM_MERGED_EDITOR (kicad submodule bump carries the fork side: per-engine Kiface/getter binding + ODR renames + dual-kiface launcher). - wasm/bindings/: per-editor collab entries renamed pcbCollab*/schCollab* (JS names unchanged); duplicate kicadOpenFile/kicadCollabOnSave + shared-name registrations guarded behind KICAD_MERGED_EMBIND; new kicad_editor_embind.cpp registers each shared JS name once, dispatching on the live frame. - Build: kicad_editor app (build wrapper, target case arms, 3-object embind compile with the ABI-critical flags, STUB_APP=pcbnew); docker/build.sh "all" = kicad_editor calculator pl_editor gerbview (pcbnew/eeschema stay as explicit debug apps); scripts/kicad/audit-merged-symbols.sh = repeatable ODR-collision audit (run on kicad bumps). - Frontend: Bundle type (bundle ≠ tool); TOOL_BUNDLE maps all four editors to kicad_editor; explicit --frame tokens for pcbnew (pcb) and eeschema (sch); publish list = the 4 real bundles. - Tests/CI: five harnesses load kicad_editor.js with explicit frame tokens; PCBNEW_FAMILY_SPECS renamed BIG_MODULE_SPECS + the 8 eeschema-family specs (they now boot the merged module — SpiderMonkey x86 CI OOM routing); frame-runtime spec covers all four frames from the one bundle. Validated so far: frame-runtime 4/4 (each frame boots with the right title, no aborts, no duplicate embind registration); 24-spec merged-module regression green; 3D raytracer renders. Known pre-existing failure: 3d-viewer title-bar drag deadlock, fixed on main by 7630c7e (2N+8 pthread pre-warm) — picked up by the follow-up rebase. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 14:48:11 +02:00
// Parametrized over the library editors — both cases now boot the merged module.
"**/frame-runtime.spec.ts",
feat(wasm): kicad_editor — merge the pcbnew+eeschema kifaces into ONE bundle (Part 2) All four editors (PCB / Footprint / Schematic / Symbol) are now runtime --frame choices of a single kicad_editor.wasm (178 MB at -O1 vs 147+82 separate; shared wx/common/boost linked once). One editor per page load, as before; frames pcb / fpedit / sch / symedit. - wasm/editor/: the merged executable target (single_top + both kiface library sets, whole-archive pcbcommon) + the safety-net focus-walk Kiface() dispatch TU. Gated by KICAD_WASM_MERGED_EDITOR (kicad submodule bump carries the fork side: per-engine Kiface/getter binding + ODR renames + dual-kiface launcher). - wasm/bindings/: per-editor collab entries renamed pcbCollab*/schCollab* (JS names unchanged); duplicate kicadOpenFile/kicadCollabOnSave + shared-name registrations guarded behind KICAD_MERGED_EMBIND; new kicad_editor_embind.cpp registers each shared JS name once, dispatching on the live frame. - Build: kicad_editor app (build wrapper, target case arms, 3-object embind compile with the ABI-critical flags, STUB_APP=pcbnew); docker/build.sh "all" = kicad_editor calculator pl_editor gerbview (pcbnew/eeschema stay as explicit debug apps); scripts/kicad/audit-merged-symbols.sh = repeatable ODR-collision audit (run on kicad bumps). - Frontend: Bundle type (bundle ≠ tool); TOOL_BUNDLE maps all four editors to kicad_editor; explicit --frame tokens for pcbnew (pcb) and eeschema (sch); publish list = the 4 real bundles. - Tests/CI: five harnesses load kicad_editor.js with explicit frame tokens; PCBNEW_FAMILY_SPECS renamed BIG_MODULE_SPECS + the 8 eeschema-family specs (they now boot the merged module — SpiderMonkey x86 CI OOM routing); frame-runtime spec covers all four frames from the one bundle. Validated so far: frame-runtime 4/4 (each frame boots with the right title, no aborts, no duplicate embind registration); 24-spec merged-module regression green; 3D raytracer renders. Known pre-existing failure: 3d-viewer title-bar drag deadlock, fixed on main by 7630c7e (2N+8 pthread pre-warm) — picked up by the follow-up rebase. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 14:48:11 +02:00
// eeschema family: since Part 2 these boot the SAME merged kicad_editor module
// (eeschema.html / symbol_editor.html load kicad_editor.js) — same V8 routing.
"**/eeschema.spec.ts",
"**/eeschema-collab.spec.ts",
"**/eeschema-crosshair.spec.ts",
"**/eeschema-load.spec.ts",
"**/eeschema-subschema.spec.ts",
"**/eeschema-ui.spec.ts",
"**/eeschema-url-regex.spec.ts",
"**/symbol_editor.spec.ts",
// Cross-face probe: schematic session lazily starts the PCB kiface (Preferences).
"**/xface-probe.spec.ts",
feat(wasm): occ-split — lazy occ_service worker; kicad_editor drops OCC (−31%) Move OpenCASCADE out of the merged editor image into occ_service: a separate emscripten module (-sASYNCIFY=0, MODULARIZE, in-container -Oz finalize, 2N+8 pre-warmed pthread pool) booted lazily in a dedicated Web Worker on the first STEP export or STEP/IGES model parse. kicad_editor.wasm ~190 MB -> 130 MB; sessions that never touch OCC never fetch its 57 MB. STEP export works in the browser for the first time: the unchanged desktop dialog runs EXPORTER_STEP, whose wasm shadow suspends into globalThis.occService and the export bytes go straight to a browser download (never entering the editor heap). STEP/IGES 3D models parse in the worker via the oce shadow (S3D WriteCache/ReadCache wire). - wasm/occ-service/: service CMake target (hooked from the kicad fork's top-level CMakeLists, wasm/editor pattern), embind entry (occExport/occLoadModel), wxConfig pre-js. - wasm/stubs/{exporter_step,oce_plugin}_stub.cpp: EM_ASYNC_JS worker bridges (callee-shadowing; no caller #ifdefs). - web/standalone: provider installed whenever the kicad_editor bundle boots (cross-face safe); ONE shared worker-boot source occ-worker.js (vite ?raw; the e2e stub reads the same file) — blob worker with locateFile absolutized against the glue URL; export download-name guard. - deps: OCC builds with RapidJSON so its glTF/GLB writer exists — pinned to the vcpkg master snapshot 2025-02-26 (24b5e7a8b27f), the same code official KiCad consumes via vcpkg.json's opencascade[rapidjson]; rapidjson's latest tag (v1.1.0, 2016) is ill-formed under modern clang. - tests: occ-export dialog e2e (lazy-fetch boundary + STEP download bytes), occ-probe incl. a 9-format matrix (step/stpz/brep/xao/ply/stl/glb/u3d/pdf), 3d-viewer-models hard-asserts the worker parse; occ provider stub installed ambiently by the kicad fixtures. Validated against desktop kicad-cli 10.0.4: geometric exact equality (bbox delta 0 um, volume delta 0.0000%) for STEP/GLB/STL/BREP/STPZ across three boards and option sweeps — with desktop OCC 7.9 vs wasm OCC 7.8; PLY/XAO/PDF structurally equal; U3D same-size (quantizer float LSBs differ). Full kicad e2e green on Firefox and Chromium; standalone verified end to end (lazy fetch only on the Export click; export.step 60,628 B ISO-10303-21; loadModel 700 KB STEP -> 569 KB scenegraph cache). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 12:39:58 +02:00
// OCC split: occ-export boots pcbnew.html (the merged module) and drives the
// export dialog through the occ_service worker — same V8 routing. occ-probe
// only boots the (small) occ_service module but shares the harness page.
"**/occ-export.spec.ts",
"**/occ-probe.spec.ts",
test(ysync): repro tests for review bugs 01-07 + v2 items-wire e2e port (miss 11) The 2026-07-02 sync review (docs/features/ysync-review, ysync-review branch) found 7 bugs and that the two-tab e2e only exercised the DEAD legacy scalar wire. This lands plan doc 15 in full; results + empirical findings in doc 16. - tests/collab/browser-entry-v2.ts (+build.mjs): the PRODUCTION v2 stack bundled for e2e (connectKicadDoc + attachKicadCollab, kdoc_* keys), with in-page renderActiveDoc/singleSeedRender/driftReport helpers and yjs forced to ONE copy (the two web pnpm workspaces otherwise bundle two instanceof-incompatible instances). - tests/kicad/ysync-two-tab.spec.ts: pl_editor green baseline (A↔B edits, ITEM-level drift silence) + divergent-uuid adopt; bug-01 pcb/ee fresh-room repros (Chromium-only: two kicad_editor tabs exceed Firefox's per-process wasm budget); bug-06 concurrent-seed race; bug-03 Y-half. - tests/kicad/ysync-repros-{pcbnew,eeschema}.spec.ts: bugs 02/03/05 + the bug-04 matrix (anchor-centred fp rotation, pad resize, endpoint drag, symbol rotation, Value-field edit), each with green landed-preconditions; the "local move emits" controls double as headless-emit probes — GREEN on both tools, so every emit-dependent repro is a live test.fail. - wasm/bindings: 7 local-edit test hooks via real commits (CallAfter+COROUTINE) — TestRemoveItem/TestRotateItem (both tools, dispatched in the merged image), TestSetPadSize/TestMoveEndpoint (pcbnew), TestSetFieldText (eeschema). - web/standalone ysync-repros.test.ts: bug-01 units (C++-faithful fake gating emit on ensureBridge) + bug-07a/b (stale DOWN hook, real sheet-manager gap). - web/pcbjam-shared bump: bug-03/06 unit repros. Convention: every repro asserts the CORRECT behavior and is expected-fail (test.fail/it.fails) naming its bug doc; a fix flips it to "unexpected pass", forcing marker removal — the repro becomes the regression test. Every expected failure verified (JSON reporter) to fail at its documented assert. Suite state: 39 passed / 0 failed / 0 flaky / 5 skipped (2 firefox guards, 2 pre-existing legacy two-tab skips, 1 pre-existing roundtrip fixme). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DPfrVhfYgPPgtawjSssZfn
2026-07-03 12:43:35 +02:00
// ysync v2-wire repros/coverage: the two-tab file boots pcbnew + eeschema
// (pl_editor cases ride along — only the browser changes), the repro files
// boot pcbnew-collab.html / eeschema.html — same V8 routing.
"**/ysync-two-tab.spec.ts",
"**/ysync-repros-pcbnew.spec.ts",
"**/ysync-repros-eeschema.spec.ts",
];
// Runtime-perf specs run ONLY on the Chromium 'perf' project below: they need
// CDP CPU throttling (Chromium-only) and pcbnew needs V8. Excluded from the
// firefox/chromium projects so they don't double-run there.
const PERF_SPECS = ["**/*-perf.spec.ts"];
const appsDir = "apps";
export default defineConfig({
globalSetup: "./global-setup.ts",
testDir: "./kicad",
// See playwright.config.ts: keep CI's outputDir cleanup off test-results/ so the kicad +
// perf runs don't wipe the accumulated screenshots.
outputDir: process.env.CI ? "pw-artifacts/kicad" : "test-results",
fullyParallel: true,
forbidOnly: !!process.env.CI,
// 1 local retry absorbs the known under-parallel-load flakes (same rationale
// as playwright.config.ts): the load-pcb post-load clipboard crash that can
// close the page on Firefox, and the calculator first-run-wizard timing race.
retries: process.env.CI ? 2 : 1,
fix(e2e): rescope the 3D fixes for the webgl-era viewer (rebased onto main) The 3d-webgl merge (kicad eb13ff3bdc: the viewer now defaults to the real OpenGL renderer via wasm/gl1, and occ-split moves STEP parsing into the occ_service worker) made the raytracer-era orchestration on this branch moot — main's chromium-ci phase is green at 15-way parallelism (28666407570 / 28698861536). Drop what no longer earns its complexity, keep the diagnostics, fix main's live flake, and make the deadlock spec test what it was written for. - REVERT the chromium-ci-3d serial project, the two-phase test:kicad:ci, the SwiftShader GPU-process flags, and the resize-drag/models skips: config and package.json are byte-for-byte back to main's shape. The raytracer contention they guarded is no longer on the CI path. - FIX main's live flake: run 28698861536 is green only via retry (3d-viewer.spec:26 flaky) and 28666407570's deadlock red sampled an ALL-ZERO pixel signature — the viewer's first frame lags the canvas's creation on software WebGL under parallel load, and sampling too early reads an all-black backbuffer. New waitForThreeDRender() gates render assertions on actual pixels (1s-interval full-frame CPU reads) instead of fixed sleeps, used by 3d-viewer.spec:26 and the models render tail. - KEEP the storm-proofed samplers (one full-frame getImageData on a willReadFrequently canvas replacing 256 per-pixel GPU round-trips per sample — the "GPU stall due to ReadPixels" trigger) and the logThreeDDiag instrumentation: engine-independent, and they de-risk every remaining software-GL pixel read. - models spec: bridge assertions stay front-loaded (the protocol regression signal is independent of the render); the occ_service parse verdict is now POLLED — it lands async relative to the bridge ensures, so asserting it immediately raced the worker; the render tail runs again everywhere. (The pre-webgl raytracer+models renderer-death documented in a17f3be does not affect the OpenGL default path — the raytracer-toggle+models combination remains untested product surface, tracked outside this branch.) - deadlock spec: the deadlock it guards is raytracer-specific and the viewer now defaults to OpenGL — on the GL engine it either passes vacuously (fast renders make every liveness assertion trivial, 28698861536) or fails on the black first frame (28666407570). It now flips the engine via the "Use raytracing" toolbar toggle (loud assert if the toggle moved) and cross-checks engagement by requiring the canvas pixels to CHANGE after the flip with no input in between (the raytraced frame is lit differently; a GL re-render reproduces identical pixels; heap growth is unusable — mimalloc satisfies the raytracer from freed arena pages). That guard immediately caught a REAL defect: on the webgl-era wasm build the toggle is INERT (the click lands and "Reload time" updates, but the canvas never changes — suspects: DoRePaint's silent catch(runtime_error) freezing the canvas after a raytracer Redraw throw, or ToggleRaytracing writing m_boardAdapter.m_Cfg while RenderEngineChanged() reads GetAppSettings<…>(), possibly different instances in the merged bundle). The spec is therefore test.skip-annotated as a KNOWN ISSUE with the full engine-force machinery in place — unskipping it self-validates the product fix. The CI-skip also stays (raytracer liveness needs real-GPU pacing; the Worker-boot deadlock mechanism is covered on CI by the standalone wx harnesses). - 180s viewer-open waits kept as pure CI headroom (never slow a passing run). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 11:37:27 +02:00
// Run parallel workers on CI too (Playwright default ≈ 50% of cores), same as
// local — the serial CI run was the dominant wall-clock cost. Cap (e.g. '50%'
// or a fixed count) if contention OOMs/flakes; retries:2 covers transient.
workers: undefined,
reporter: "html",
timeout: 180000, // KiCad WASM needs more time to load (3 minutes)
use: {
baseURL: `http://localhost:${port}`,
trace: "retain-on-failure",
screenshot: "only-on-failure",
},
projects: [
{
// Firefox is the default for headless testing (works on ARM Mac)
name: "firefox",
// Perf specs always run on the dedicated 'perf' project, never here. On CI
feat(wasm): kicad_editor — merge the pcbnew+eeschema kifaces into ONE bundle (Part 2) All four editors (PCB / Footprint / Schematic / Symbol) are now runtime --frame choices of a single kicad_editor.wasm (178 MB at -O1 vs 147+82 separate; shared wx/common/boost linked once). One editor per page load, as before; frames pcb / fpedit / sch / symedit. - wasm/editor/: the merged executable target (single_top + both kiface library sets, whole-archive pcbcommon) + the safety-net focus-walk Kiface() dispatch TU. Gated by KICAD_WASM_MERGED_EDITOR (kicad submodule bump carries the fork side: per-engine Kiface/getter binding + ODR renames + dual-kiface launcher). - wasm/bindings/: per-editor collab entries renamed pcbCollab*/schCollab* (JS names unchanged); duplicate kicadOpenFile/kicadCollabOnSave + shared-name registrations guarded behind KICAD_MERGED_EMBIND; new kicad_editor_embind.cpp registers each shared JS name once, dispatching on the live frame. - Build: kicad_editor app (build wrapper, target case arms, 3-object embind compile with the ABI-critical flags, STUB_APP=pcbnew); docker/build.sh "all" = kicad_editor calculator pl_editor gerbview (pcbnew/eeschema stay as explicit debug apps); scripts/kicad/audit-merged-symbols.sh = repeatable ODR-collision audit (run on kicad bumps). - Frontend: Bundle type (bundle ≠ tool); TOOL_BUNDLE maps all four editors to kicad_editor; explicit --frame tokens for pcbnew (pcb) and eeschema (sch); publish list = the 4 real bundles. - Tests/CI: five harnesses load kicad_editor.js with explicit frame tokens; PCBNEW_FAMILY_SPECS renamed BIG_MODULE_SPECS + the 8 eeschema-family specs (they now boot the merged module — SpiderMonkey x86 CI OOM routing); frame-runtime spec covers all four frames from the one bundle. Validated so far: frame-runtime 4/4 (each frame boots with the right title, no aborts, no duplicate embind registration); 24-spec merged-module regression green; 3D raytracer renders. Known pre-existing failure: 3d-viewer title-bar drag deadlock, fixed on main by 7630c7e (2N+8 pthread pre-warm) — picked up by the follow-up rebase. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 14:48:11 +02:00
// every merged-module (kicad_editor) spec moves to chromium-ci (see
// BIG_MODULE_SPECS).
testIgnore: [
...PERF_SPECS,
feat(wasm): kicad_editor — merge the pcbnew+eeschema kifaces into ONE bundle (Part 2) All four editors (PCB / Footprint / Schematic / Symbol) are now runtime --frame choices of a single kicad_editor.wasm (178 MB at -O1 vs 147+82 separate; shared wx/common/boost linked once). One editor per page load, as before; frames pcb / fpedit / sch / symedit. - wasm/editor/: the merged executable target (single_top + both kiface library sets, whole-archive pcbcommon) + the safety-net focus-walk Kiface() dispatch TU. Gated by KICAD_WASM_MERGED_EDITOR (kicad submodule bump carries the fork side: per-engine Kiface/getter binding + ODR renames + dual-kiface launcher). - wasm/bindings/: per-editor collab entries renamed pcbCollab*/schCollab* (JS names unchanged); duplicate kicadOpenFile/kicadCollabOnSave + shared-name registrations guarded behind KICAD_MERGED_EMBIND; new kicad_editor_embind.cpp registers each shared JS name once, dispatching on the live frame. - Build: kicad_editor app (build wrapper, target case arms, 3-object embind compile with the ABI-critical flags, STUB_APP=pcbnew); docker/build.sh "all" = kicad_editor calculator pl_editor gerbview (pcbnew/eeschema stay as explicit debug apps); scripts/kicad/audit-merged-symbols.sh = repeatable ODR-collision audit (run on kicad bumps). - Frontend: Bundle type (bundle ≠ tool); TOOL_BUNDLE maps all four editors to kicad_editor; explicit --frame tokens for pcbnew (pcb) and eeschema (sch); publish list = the 4 real bundles. - Tests/CI: five harnesses load kicad_editor.js with explicit frame tokens; PCBNEW_FAMILY_SPECS renamed BIG_MODULE_SPECS + the 8 eeschema-family specs (they now boot the merged module — SpiderMonkey x86 CI OOM routing); frame-runtime spec covers all four frames from the one bundle. Validated so far: frame-runtime 4/4 (each frame boots with the right title, no aborts, no duplicate embind registration); 24-spec merged-module regression green; 3D raytracer renders. Known pre-existing failure: 3d-viewer title-bar drag deadlock, fixed on main by 7630c7e (2N+8 pthread pre-warm) — picked up by the follow-up rebase. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 14:48:11 +02:00
...(process.env.CI ? BIG_MODULE_SPECS : []),
],
use: {
...devices["Desktop Firefox"],
viewport: { width: 1280, height: 720 },
fix(e2e): make the firefox kicad suite pass on GPU-less CI runners CI runs (Hetzner 27329612719, Ubicloud 27330989479) failed 22/41 identically, in two buckets, both firefox-environment issues (the suite is firefox-only: test:kicad -> --project=firefox): 1. No WebGL: headless Firefox can't create ANY GL context on a GPU-less VM (blocklist bypass still dies with FEATURE_FAILURE_WEBGL_EXHAUSTED_DRIVERS), so the GAL canvas failed and an error dialog blocked every UI flow. Fix: run headed under xvfb (GLX + Mesa llvmpipe software GL) with webgl.force-enabled — workflows now wrap the e2e step in xvfb-run. 2. pcbnew wasm OOM: the ~190M module OOMs Firefox's optimizing wasm JIT at compile ("InternalError: out of memory") and the app never boots. Fix: javascript.options.wasm_optimizingjit=false (baseline-only compile). Both prefs are CI-gated in playwright-kicad.config.ts; local runs keep stock behavior. Boot got slower (baseline JIT), so the wizard helpers now wait for the registry to have actual UI ENTRIES (the registry OBJECT exists pre-boot) instead of clicking into a fixed 10x500ms window. Validated in a local docker repro of the CI env (playwright:v1.57.0 image, no GPU): pl_editor canvas, gerbview wizard+canvas, and pcbnew wizard (on a properly asyncified 187M module) all pass; before the fix they reproduced the exact CI signatures. Known-fail left on CI: zoom-cursor — the zoom-in anchors at ~ -P in headed Firefox (screen-vs-client coordinate mix-up in the wheel->GAL path, headed mode only); marked test.fixme(CI) pending a wx-wasm-layer investigation. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 13:22:29 +02:00
// CI-only prefs: GPU-less CI VMs hit two Firefox blockers (identical on
// Hetzner ccx53 and ubicloud-standard-30, runs 27329612719/27330989479).
// Gated on CI so local runs keep stock Firefox behavior.
...(process.env.CI
? {
// Headless Firefox cannot create any GL context on the GPU-less CI
// VMs (blocklist bypass still ends in FEATURE_FAILURE_WEBGL_EXHAUSTED_
// DRIVERS) — run headed under Xvfb instead, where GLX + Mesa llvmpipe
// provides software WebGL. CI invokes the suite via `xvfb-run`.
headless: false,
launchOptions: {
firefoxUserPrefs: {
// Skip the no-GPU blocklist ("AllowWebgl2:false restricts
// context creation") so the GAL canvas gets a WebGL context.
"webgl.force-enabled": true,
feat(wasm): kicad_editor — merge the pcbnew+eeschema kifaces into ONE bundle (Part 2) All four editors (PCB / Footprint / Schematic / Symbol) are now runtime --frame choices of a single kicad_editor.wasm (178 MB at -O1 vs 147+82 separate; shared wx/common/boost linked once). One editor per page load, as before; frames pcb / fpedit / sch / symedit. - wasm/editor/: the merged executable target (single_top + both kiface library sets, whole-archive pcbcommon) + the safety-net focus-walk Kiface() dispatch TU. Gated by KICAD_WASM_MERGED_EDITOR (kicad submodule bump carries the fork side: per-engine Kiface/getter binding + ODR renames + dual-kiface launcher). - wasm/bindings/: per-editor collab entries renamed pcbCollab*/schCollab* (JS names unchanged); duplicate kicadOpenFile/kicadCollabOnSave + shared-name registrations guarded behind KICAD_MERGED_EMBIND; new kicad_editor_embind.cpp registers each shared JS name once, dispatching on the live frame. - Build: kicad_editor app (build wrapper, target case arms, 3-object embind compile with the ABI-critical flags, STUB_APP=pcbnew); docker/build.sh "all" = kicad_editor calculator pl_editor gerbview (pcbnew/eeschema stay as explicit debug apps); scripts/kicad/audit-merged-symbols.sh = repeatable ODR-collision audit (run on kicad bumps). - Frontend: Bundle type (bundle ≠ tool); TOOL_BUNDLE maps all four editors to kicad_editor; explicit --frame tokens for pcbnew (pcb) and eeschema (sch); publish list = the 4 real bundles. - Tests/CI: five harnesses load kicad_editor.js with explicit frame tokens; PCBNEW_FAMILY_SPECS renamed BIG_MODULE_SPECS + the 8 eeschema-family specs (they now boot the merged module — SpiderMonkey x86 CI OOM routing); frame-runtime spec covers all four frames from the one bundle. Validated so far: frame-runtime 4/4 (each frame boots with the right title, no aborts, no duplicate embind registration); 24-spec merged-module regression green; 3D raytracer renders. Known pre-existing failure: 3d-viewer title-bar drag deadlock, fixed on main by 7630c7e (2N+8 pthread pre-warm) — picked up by the follow-up rebase. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 14:48:11 +02:00
// kicad_editor.wasm (~190M+) OOMs the optimizing wasm JIT at compile
// time ("InternalError: out of memory") and the app never boots.
// Baseline-only compilation trades runtime speed for a compile
// that fits in memory.
"javascript.options.wasm_optimizingjit": false,
},
},
}
: {}),
},
},
{
wip: nested-asyncify fix, wxAuiToolBar registration, tests, research docs Main-repo side of a multi-part WIP covering the KiCad WASM tool-selection and nested-Asyncify work. Submodule commits are in kicad@f6e9239aaa (libcontext hygiene) and wxwidgets@bb80f91e8b (auibar registration + dialog diagnostics). ## scripts/common/inject-dyncall-shims.sh Wrap Asyncify.handleSleep / allocateData to save-and-restore Asyncify.currData around each EM_ASYNC_JS sleep. This fixes the nested Asyncify collision where a fiber swap that fired during a modal's event loop clobbered currData, and the modal's later doRewind used the fiber's buffer and hit "RuntimeError: index out of bounds". Root cause documented as Emscripten Issue #9153 (wontfix upstream). Diagnostic-rewind logging (forcedBottomOfCallStack, callStack traces) is retained to help future debugging of Asyncify state corruption. ## tests/ - tests/playwright-kicad.config.ts: add `channel: 'chrome'` for the chromium project so --project=chromium --headed uses system Chrome (real GPU) instead of SwiftShader on ARM Mac. Also switch trace to retain-on-failure + screenshot on-failure for easier E2E debugging. - tests/kicad/pcbnew.spec.ts: replace `tool.checked` assertions with a label-suffix check (`[checked]`) since our auibar registration encodes checked state in the label (no schema change to the registry). - tests/apps/Makefile.wasm: add `coroutine-nested` build target + include it in the all: list. - tests/apps/standalone/coroutine/: kicad_coroutine_harness.h + test app reproducing KiCad COROUTINE semantics against real libcontext. - tests/apps/standalone/coroutine-nested/: nested_test.cpp reproduces the EM_ASYNC_JS-modal + fiber-swap nesting bug in isolation. 8 scenarios from baseline_modal_alone through nested_fibers_inside_modal. - tests/e2e/coroutine.spec.ts + coroutine-nested.spec.ts: Playwright specs that load the standalone apps and assert all case cases pass via [COROUTINE_TEST] SUMMARY log parsing. ## research/ and features/browser-tools/ Three background docs capturing the investigation trajectory: - features/browser-tools/0001-kicad-wasm-tool-activation-investigation.md Early investigation: why tools don't activate; initial dynCall-empty- callback hypothesis. - features/browser-tools/0002-wasm-coroutine-deep-dive.md Deep dive on Asyncify internals, fiber API, QEMU's coroutine-wasm reference implementation. - features/browser-tools/0003-wxauitoolbar-registration-fix.md The narrow fix: why wxAuiToolBar needs a registration block, where to add it, what the fallback plan is. - research/threading_1.md: corrected root-cause analysis after reading runtime logs — nested-Asyncify currData collision, Emscripten #9153. - research/threading_2.md: extended research on alternative approaches (JSPI/WasmFX/state-machines) and why they don't help here. ## Submodule pointer updates kicad: f6e9239aaa (wip: libcontext WASM hygiene cleanup) wxwidgets: bb80f91e8b (wip: wxAuiToolBar element-registry registration + dialog diagnostics) ## Open threads not yet in scope - Firefox/Chrome divergent behavior: "indirect call signature mismatch" traps in Firefox vs renderer crash in system Chrome (tracked in plans/peaceful-hugging-pnueli.md and the research docs). - E2E pixel-diff for Draw Lines fails because the test's diff region does not cover where the line is actually drawn; tool activation works, the line is visible in test-results/pcbnew-draw-lines-02-after-drawing.png. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 13:58:16 +02:00
// Uses the SYSTEM-installed Google Chrome (not the Playwright-bundled
// Chromium) so WebGL runs on the real GPU instead of SwiftShader.
// The bundled Chromium fails with canvas hidden on ARM Mac because of
// Chromium issues #1416283, #338414704 (SwiftShader WebGL bug).
// Run via: npm run test:kicad:headed
name: "chromium",
testIgnore: PERF_SPECS,
use: {
channel: "chrome",
viewport: { width: 1280, height: 720 },
},
},
{
feat(wasm): kicad_editor — merge the pcbnew+eeschema kifaces into ONE bundle (Part 2) All four editors (PCB / Footprint / Schematic / Symbol) are now runtime --frame choices of a single kicad_editor.wasm (178 MB at -O1 vs 147+82 separate; shared wx/common/boost linked once). One editor per page load, as before; frames pcb / fpedit / sch / symedit. - wasm/editor/: the merged executable target (single_top + both kiface library sets, whole-archive pcbcommon) + the safety-net focus-walk Kiface() dispatch TU. Gated by KICAD_WASM_MERGED_EDITOR (kicad submodule bump carries the fork side: per-engine Kiface/getter binding + ODR renames + dual-kiface launcher). - wasm/bindings/: per-editor collab entries renamed pcbCollab*/schCollab* (JS names unchanged); duplicate kicadOpenFile/kicadCollabOnSave + shared-name registrations guarded behind KICAD_MERGED_EMBIND; new kicad_editor_embind.cpp registers each shared JS name once, dispatching on the live frame. - Build: kicad_editor app (build wrapper, target case arms, 3-object embind compile with the ABI-critical flags, STUB_APP=pcbnew); docker/build.sh "all" = kicad_editor calculator pl_editor gerbview (pcbnew/eeschema stay as explicit debug apps); scripts/kicad/audit-merged-symbols.sh = repeatable ODR-collision audit (run on kicad bumps). - Frontend: Bundle type (bundle ≠ tool); TOOL_BUNDLE maps all four editors to kicad_editor; explicit --frame tokens for pcbnew (pcb) and eeschema (sch); publish list = the 4 real bundles. - Tests/CI: five harnesses load kicad_editor.js with explicit frame tokens; PCBNEW_FAMILY_SPECS renamed BIG_MODULE_SPECS + the 8 eeschema-family specs (they now boot the merged module — SpiderMonkey x86 CI OOM routing); frame-runtime spec covers all four frames from the one bundle. Validated so far: frame-runtime 4/4 (each frame boots with the right title, no aborts, no duplicate embind registration); 24-spec merged-module regression green; 3D raytracer renders. Known pre-existing failure: 3d-viewer title-bar drag deadlock, fixed on main by 7630c7e (2N+8 pthread pre-warm) — picked up by the follow-up rebase. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 14:48:11 +02:00
// CI-only carrier for the merged-module specs (see BIG_MODULE_SPECS):
// Playwright-bundled Chromium, headless, software WebGL via SwiftShader
// (fine on x86 Linux; the SwiftShader bug above is ARM-Mac-specific).
// --enable-unsafe-swiftshader: newer Chromium refuses software WebGL in
// headless without it.
name: "chromium-ci",
fix(e2e): rescope the 3D fixes for the webgl-era viewer (rebased onto main) The 3d-webgl merge (kicad eb13ff3bdc: the viewer now defaults to the real OpenGL renderer via wasm/gl1, and occ-split moves STEP parsing into the occ_service worker) made the raytracer-era orchestration on this branch moot — main's chromium-ci phase is green at 15-way parallelism (28666407570 / 28698861536). Drop what no longer earns its complexity, keep the diagnostics, fix main's live flake, and make the deadlock spec test what it was written for. - REVERT the chromium-ci-3d serial project, the two-phase test:kicad:ci, the SwiftShader GPU-process flags, and the resize-drag/models skips: config and package.json are byte-for-byte back to main's shape. The raytracer contention they guarded is no longer on the CI path. - FIX main's live flake: run 28698861536 is green only via retry (3d-viewer.spec:26 flaky) and 28666407570's deadlock red sampled an ALL-ZERO pixel signature — the viewer's first frame lags the canvas's creation on software WebGL under parallel load, and sampling too early reads an all-black backbuffer. New waitForThreeDRender() gates render assertions on actual pixels (1s-interval full-frame CPU reads) instead of fixed sleeps, used by 3d-viewer.spec:26 and the models render tail. - KEEP the storm-proofed samplers (one full-frame getImageData on a willReadFrequently canvas replacing 256 per-pixel GPU round-trips per sample — the "GPU stall due to ReadPixels" trigger) and the logThreeDDiag instrumentation: engine-independent, and they de-risk every remaining software-GL pixel read. - models spec: bridge assertions stay front-loaded (the protocol regression signal is independent of the render); the occ_service parse verdict is now POLLED — it lands async relative to the bridge ensures, so asserting it immediately raced the worker; the render tail runs again everywhere. (The pre-webgl raytracer+models renderer-death documented in a17f3be does not affect the OpenGL default path — the raytracer-toggle+models combination remains untested product surface, tracked outside this branch.) - deadlock spec: the deadlock it guards is raytracer-specific and the viewer now defaults to OpenGL — on the GL engine it either passes vacuously (fast renders make every liveness assertion trivial, 28698861536) or fails on the black first frame (28666407570). It now flips the engine via the "Use raytracing" toolbar toggle (loud assert if the toggle moved) and cross-checks engagement by requiring the canvas pixels to CHANGE after the flip with no input in between (the raytraced frame is lit differently; a GL re-render reproduces identical pixels; heap growth is unusable — mimalloc satisfies the raytracer from freed arena pages). That guard immediately caught a REAL defect: on the webgl-era wasm build the toggle is INERT (the click lands and "Reload time" updates, but the canvas never changes — suspects: DoRePaint's silent catch(runtime_error) freezing the canvas after a raytracer Redraw throw, or ToggleRaytracing writing m_boardAdapter.m_Cfg while RenderEngineChanged() reads GetAppSettings<…>(), possibly different instances in the merged bundle). The spec is therefore test.skip-annotated as a KNOWN ISSUE with the full engine-force machinery in place — unskipping it self-validates the product fix. The CI-skip also stays (raytracer liveness needs real-GPU pacing; the Worker-boot deadlock mechanism is covered on CI by the standalone wx harnesses). - 180s viewer-open waits kept as pure CI headroom (never slow a passing run). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 11:37:27 +02:00
testMatch: BIG_MODULE_SPECS,
fix(ci): serialize the heavy 3D-viewer e2e specs (dedicated chromium-ci-3d project) The three heavy 3D-viewer specs (3d-viewer, 3d-viewer-deadlock, 3d-viewer-models) crashed on CI (run 28604015154): "Target crashed", "browser has been closed", and a black frozen canvas. Each boots the 3D-enabled pcbnew build, which pre-warms ~hardwareConcurrency*2+8 (~68 on the 30-core VM) Web Workers AND runs a multi-threaded CPU raytracer over SwiftShader software-WebGL. Under fullyParallel the three spec FILES run in separate browser processes concurrently, and the simultaneous raytrace tabs exhaust the shared GPU process's ~16 live-WebGL-context limit / renderer memory. The pool pre-warm (the deadlock fix, 7630c7e) is correct and present in the tested binary; per-file isolation prevented in-process Worker accumulation but NOT this cross-process concurrency — the gap these specs' first CI exposure hit. Fix (test-orchestration only; no wasm/submodule changes): - Route the three specs to a dedicated `chromium-ci-3d` Playwright project (own outputDir=pw-artifacts/kicad-3d so its failure traces survive the later perf run's wipe; the existing tests/pw-artifacts/** upload already captures it). - test:kicad:ci runs it as a SECOND `playwright test` pass with --workers=1, so at most one raytrace tab is alive at a time (the environment in which a single 3D load is reliably green — docs/features/3d-raytracer/README.md §7). An exit-code-aggregating sequencer runs both phases and fails if either fails (no silent skip of the 3D pass). - Cap phase-1 CI workers to 12 as headroom under the WebGL-context cap. - Log a resource-diagnostic snapshot (hardwareConcurrency, pthread pool, GL-canvas count, wasm/JS heap) before each 3D interaction so any recurrence is attributable. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 10:49:23 +02:00
use: {
...devices["Desktop Chrome"],
viewport: { width: 1280, height: 720 },
launchOptions: {
args: ["--enable-unsafe-swiftshader"],
},
},
},
{
// Runtime-perf specs (*-perf.spec.ts): bundled Chromium for CDP CPU throttling.
// Bundled (not system Chrome) because system Chrome paces rAF oddly under CDP
// throttle (FPS rose with throttle). --enable-unsafe-swiftshader lets it use
// software WebGL headless on CI; harmless with a real GPU locally. Add --headed
// locally for real-GPU FPS numbers.
name: "perf",
testMatch: PERF_SPECS,
use: {
...devices["Desktop Chrome"],
viewport: { width: 1280, height: 720 },
launchOptions: { args: ["--enable-unsafe-swiftshader"] },
},
},
],
webServer: {
command: `npx serve ${appsDir} -p ${port} -c ../serve.json`,
port: port,
reuseExistingServer: !process.env.CI,
},
});