Adds an end-to-end test that drives File→Open in pcbnew, injects
the .kicad_pcb and .kicad_pro files into MEMFS at the dialog's
default starting directory, drives the menu + filename text input
+ Enter accept path, and screenshots the loaded board. Parametrized
for both kicad/demos/microwave (RF polygon footprints) and
kicad/demos/pic_programmer (full multi-IC layout).
Without the rtree fix bumped in via the kicad submodule, the load
would abort on every PCB at rtree.h:1771 Classify; the test asserts
no [RTREE-DIAG] line and no Aborted(. The post-load clipboard
RuntimeError in __asyncjs__js_clipboardHasText is a separate,
pre-existing wasm-port limitation that we explicitly do not regress
on here.
- tests/kicad/load-pcb.spec.ts: serial-mode parametrized spec
- tests/kicad/load-pcb-probe.spec.ts: one-shot diagnostic probe
for inspecting wxFileDialog state on the canvas
- tests/kicad/utils/fs-inject.ts: FS.writeFile bridge from Node fs
- tests/kicad/utils/board-ready.ts: poll-for-no-dialogs readiness
- tests/baseline-screenshots/load-pcb-*.png: 6 baselines covering
both demos at pcbnew-ready / dialog-open / loaded states
- features/.../rtree-debug-findings.md: full diagnosis trail with
an upstream-reportable summary the maintainer can lift verbatim
- kicad submodule bumped to 07d8130d44 (shape_poly_set rtree fix)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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>
Update wxwidgets submodule with fix for consecutive modal dialog crashes.
The fix prevents overlapping Asyncify operations that caused "indirect call
to null" and "func is not a function" errors when a second modal was
triggered immediately after the first one completed.
Also includes:
- docs: Clarify build script order and descriptions in CLAUDE.md
- refactor(test): Remove debug logging from wizard test
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Test now correctly finds "Finish" button on last wizard page
- Added CLAUDE.md note about running e2e tests via npm scripts
- Simplified test to click through wizard with proper button detection
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add testLogger fixture parameter to the first test so the logging
fixture lifecycle runs and writes console output to logs/kicad/pcbnew/.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Chrome headless crashes on ARM Mac due to a known Chromium bug where
SwiftShader WebGL is disabled on ARM architecture (issues #1416283,
#338414704). Firefox headless works reliably using native Metal.
Changes:
- Use Firefox as default for npm run test:kicad (headless)
- Use Chrome with --headed flag for npm run test:kicad:headed
- Add viewport size and increase timeout for KiCad WASM
- Simplify pcbnew.spec.ts test assertions
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Check HasAlpha() before calling InitAlpha() to avoid assertion failure
- Skip useless test that only checked for no JS exceptions
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- wxWidgets logs: tests/logs/wxwidgets/<test-file>/
- KiCad logs: tests/logs/kicad/<test-file>/
- Global setup now cleans all log subdirectories recursively
- Added globalSetup to KiCad playwright config
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- npm run test:kicad now auto-runs setup script first
- Create separate playwright-kicad.config.ts for KiCad tests
- Fix kicad spec to use web server instead of file:// paths
- Remove duplicate pcbnew.html/wasm from tests/kicad/
(proper files are in tests/apps/kicad/)
Test separation:
- npm test: runs only wxWidgets tests (tests/e2e/)
- npm run test:kicad: runs only KiCad tests (tests/kicad/)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>