Dev harness: source HMR loop + force-reload (#3, #9) #19

Open
orchestrator wants to merge 3 commits from wip/issue-03 into integration/wave2
Member

Per #3 and #9.

  • s/dev [consumer-cwd] [exclude...] serves the testrunner from source with Vite HMR, rooted at the consumer, reusing the @srhazi/gooey-test/vite plugin for discovery and aliasing the lib to source.
  • #9: import.meta.hot force-reload guard for lib changes (plus ES2020 tsconfig for import.meta; published bundle unaffected).
  • dev/verify-hmr.mjs probe asserts the run summary is identical before/after a reload.

Verification

  • HMR 7/7 against gooey-identity (523/20): tsx + scss hot-update, lib force-reload, and all tests re-run after each reload.
  • Answer to the lead's plugin+reload question: yes — with the plugin present, a reload re-runs the whole suite; the dev harness registers its own plugin (never the consumer's config), and headless strips duplicate plugins.

Closes #3, #9

Base: integration/wave2 is the integration point this branch was based on, so this PR's diff shows only this issue's changes.

Per #3 and #9. - `s/dev [consumer-cwd] [exclude...]` serves the testrunner **from source with Vite HMR**, rooted at the consumer, reusing the `@srhazi/gooey-test/vite` plugin for discovery and aliasing the lib to source. - #9: `import.meta.hot` force-reload guard for lib changes (plus ES2020 tsconfig for `import.meta`; published bundle unaffected). - `dev/verify-hmr.mjs` probe asserts the run summary is identical before/after a reload. ## Verification - HMR **7/7** against gooey-identity (523/20): tsx + scss hot-update, lib force-reload, and **all tests re-run** after each reload. - Answer to the lead's plugin+reload question: yes — with the plugin present, a reload re-runs the whole suite; the dev harness registers its own plugin (never the consumer's config), and headless strips duplicate plugins. Closes #3, #9 > **Base:** `integration/wave2` is the integration point this branch was based on, so this PR's diff shows **only this issue's changes**.
Adds a dev-only Vite harness (`s/dev [consumer-cwd] [exclude-glob ...]`) that
serves the testrunner from source (`src/testrunner/dev.ts`) with Vite HMR while
discovering the consumer's tests via the `@srhazi/gooey-test/vite` plugin.

- `dev/vite.config.ts` roots Vite at the consumer, aliases
  `@srhazi/gooey-test` to `src/lib`, and defines gooey's dev globals.
- `dev/dev-runner.ts` serves the source runner HTML + sandbox through Vite's
  HTML pipeline (so iframes get `/@vite/client`).
- `src/testrunner/dev.ts` + `dev-manifest.ts` wire the plugin's
  `virtual:gooey-test/manifest` into the runner and pull the library into the
  runner's import graph.
- #9: `src/lib/test.ts` force-reloads on change via `import.meta.hot`; the
  `vite/client` reference lives in `src/vite-env.d.ts` so it never leaks into
  the published types; tsconfig module/lib/target bumped to ES2020.
- `s/dist` silences the expected esbuild `empty-import-meta` warning (targets
  unchanged).
- `dev/verify-hmr.mjs` is a Playwright probe; README documents the loop.

Verified against 2026/gooey-identity: 523 tests / 20 files pass; editing
src/testrunner/*.scss hot-updates, *.tsx reloads, and src/lib/test.ts
force-reloads (5/5 checks).
- verify-hmr.mjs: restore every edit in a finally block, plus process-exit and
  signal restorers, so a timeout/throw can't leave probe markers in source.
  The SCSS check now asserts in-place HMR (CSS applied AND no reload) instead of
  accepting any update, so it can't pass on a full-reload regression.
- tsconfig.json: exclude src/testrunner/dev.ts and dev-manifest.ts from the
  declaration build so they no longer emit dist/tsc/testrunner/dev*.d.ts into
  the published package.
- dev/vite.config.ts: drop the unnecessary gooeyTest entry override (the
  dev-runner middleware is registered first and wins), and split excludes on
  newlines so a glob containing a comma survives.
- src/lib/test.ts: correct the #9 comment — it is an explicit force-reload
  guard matching issue #9, not what enables the reload.
- README: note the harness does not load the consumer's vite.config and
  document the GOOEY_TEST_DEV_* overrides.

Verified: build clean; no dev .d.ts emitted; verify-hmr 5/5 on the repo and on
gooey-identity (523 tests / 20 files); comma-in-glob exclusion end-to-end.
The probe now asserts the run summary is identical before/after each reload
(src/testrunner/*.tsx and the #9 src/lib force-reload): status, total, passed
and files count must match. Previously it only checked that a reload happened.

Verified: 7/7 against the repo (22/22), gooey-identity (523/523 in 20 files),
and a plugin-configured fixture consumer (5/5 in 2 files).
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin wip/issue-03:wip/issue-03
git switch wip/issue-03

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch integration/wave2
git merge --no-ff wip/issue-03
git switch wip/issue-03
git rebase integration/wave2
git switch integration/wave2
git merge --ff-only wip/issue-03
git switch wip/issue-03
git rebase integration/wave2
git switch integration/wave2
git merge --no-ff wip/issue-03
git switch integration/wave2
git merge --squash wip/issue-03
git switch integration/wave2
git merge --ff-only wip/issue-03
git switch integration/wave2
git merge wip/issue-03
git push origin integration/wave2
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
legend/gooey-test!19
No description provided.