Move the three load-bearing prototype files from `tests/uat/prototype/`
to their production paths under `tests/uat/`, leaving the architectural
narrative (research findings, BLOCKER citations, falsification table
references) intact. No behavioral changes — A6 still PASSES 5/5 in ~7s
end-to-end from the new paths.
File moves (git mv preserves history):
- tests/uat/prototype/extension-page-harness.html
→ tests/uat/extension-page-harness.html
- tests/uat/prototype/extension-page-harness.ts
→ tests/uat/extension-page-harness.ts
- tests/uat/prototype/a6.test.ts
→ tests/uat/a6.test.ts
The `tests/uat/prototype/` directory is now empty (git does not track
empty directories; will not appear in subsequent `git status`).
Path-reference updates inside the moved files:
- tests/uat/extension-page-harness.html: `<p>` line referencing the
chrome-extension:// URL updated to drop `/prototype/`.
- tests/uat/extension-page-harness.ts: file-header docstring rewritten
to cite Plan 01-13 / Approach B / inheritance from c647f61. The
load-bearing architectural-finding comment block (MV3 SW dynamic-
import block falsification, Approach-B chrome.* surface summary)
is REWORDED but its semantic content + research citations are
PRESERVED — every load-bearing fact survives the rename.
- tests/uat/a6.test.ts:
* File-header rewritten to position the file as Plan 01-13's
standalone single-assertion entry point (preserves the future-
proof rationale: this entry stays around forever for fast TDD
iteration on A6 even after Wave 3 folds A6 into the orchestrator
harness.test.ts).
* REPO_ROOT resolvePath chain corrected from `..,..,..` to `..,..`
— the file is now two directory levels above the repo root
instead of three. Without this fix DIST_TEST_DIR would resolve
to a path one level above the actual repo root and
assertBundlePresent would throw. **VERIFIED by running the
driver: build path resolves correctly.**
* harnessUrl constant updated to drop `/prototype/` from the
chrome-extension://<id>/tests/uat/extension-page-harness.html
URL — must match the rollup emission path in dist-test/.
* Stdout labels updated: 'PROTOTYPE A6 result' → 'A6 result',
'Plan 01-11 PROTOTYPE — A6 ... feasibility test' → 'Plan 01-13
— A6 (Bug B canonical) standalone driver'. Inside the docstrings
the historical 'originally landed as 01-11 prototype' provenance
is preserved per the plan's contract.
vite.test.config.ts:
- `rollupOptions.input` renamed `prototype_harness` → `extension_page_harness`
pointing at the new production path. crxjs emits the harness HTML
to `dist-test/tests/uat/extension-page-harness.html` (verified by
`ls dist-test/tests/uat/`).
- The `modulePreload: { polyfill: false }` line is PRESERVED — this
is the CRITICAL SW FIX per 01-11-SUMMARY (disabling the polyfill
is what makes the test bundle's offscreen-side dynamic import work
without crashing in non-DOM contexts that incorrectly try to call
document.querySelector).
- File-header comment §4 and the inline `define.__MOKOSH_UAT__` comment
are PRESERVED — load-bearing rationale for the dedicated build-time
token (vs `import.meta.env.MODE === 'test'` which collides with
vitest).
Verification (all GREEN):
- `npm run build:test` — exit 0; dist-test/ emits
`tests/uat/extension-page-harness.html` and `assets/extension_page_harness-*.js`.
- `npx tsx tests/uat/a6.test.ts` — exits 0 with "A6 result: PASS";
5/5 checks GREEN (SETUP: badge becomes REC; A6.1 badge==''; A6.2
popup==''; A6.3 notif delta==0; A6.4 isRecording=false). End-to-end
runtime ~7s headless on this workstation.
- `npx tsc --noEmit` — exit 0 (root tsconfig + tests/uat/tsconfig.json).
- `npx vitest run` — 92/92 GREEN; the moves do not touch any vitest-
discovered files.
- `npm run build` — exit 0; Tier-1 grep gate stays GREEN
(the moves do not touch production code).
Wave 2 (next): build out `tests/uat/lib/{launch,assertions,harness-page-
driver}.ts` around the extension-page architecture; rewrite
`tests/uat/a6.test.ts` to use the shared lib (still PASSES 5/5).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
97 lines
5.1 KiB
TypeScript
97 lines
5.1 KiB
TypeScript
// vite.test.config.ts — Plan 01-11 two-bundle separation.
|
|
//
|
|
// Extends the production `./vite.config.ts` with the following delta knobs:
|
|
// 1. `mode: 'test'` — Vite statically replaces `import.meta.env.MODE`
|
|
// everywhere in the input source with the string literal `'test'`.
|
|
// 2. `define: { __MOKOSH_UAT__: 'true' }` — the dedicated build-time
|
|
// token gating the test-hook dynamic imports in
|
|
// src/background/index.ts + src/offscreen/recorder.ts (Plan 01-11
|
|
// Task 2). With this set to `true` the `if (__MOKOSH_UAT__)` branch
|
|
// becomes a live branch and Rollup KEEPS the dynamic imports;
|
|
// production builds (vite.config.ts sets it `false`) tree-shake
|
|
// them away (verified by the Tier-1 grep gate
|
|
// `tests/background/no-test-hooks-in-prod-bundle.test.ts`).
|
|
// 3. `build.outDir: 'dist-test'` + `emptyOutDir: true` — emit to a
|
|
// SEPARATE directory so a `npm run build` immediately after this
|
|
// build does not clobber. Puppeteer harness consumes this path via
|
|
// `puppeteer.launch({ enableExtensions: [<abs-path-to-dist-test>] })`.
|
|
// 4. `build.modulePreload: { polyfill: false }` — CRITICAL SW FIX.
|
|
// Vite's default module-preload polyfill calls
|
|
// `document.getElementsByTagName` + `document.querySelector` at
|
|
// module init in EVERY chunk that contains a dynamic import. The
|
|
// production bundle has no dynamic imports (the test-hook gate is
|
|
// dead code; tree-shaken). The test bundle HAS the dynamic
|
|
// `await import('../test-hooks/sw-hooks')` — so the preload
|
|
// polyfill gets included in the SW chunk. SWs have no DOM —
|
|
// `document` is undefined — and the polyfill throws on the very
|
|
// first await, killing the SW module init silently (no console
|
|
// output, just a dead worker). Disabling the polyfill removes the
|
|
// `document.*` references; modern Chrome (and our MV3 target ≥88)
|
|
// supports native dynamic import without the polyfill.
|
|
// Empirically verified: with the polyfill enabled, the test
|
|
// bundle's SW never reaches `Service Worker initializing` log;
|
|
// with it disabled, the SW initializes and chrome.runtime.onMessage
|
|
// handlers respond. See Plan 01-11 PROTOTYPE research session.
|
|
//
|
|
// Plan 01-13 Wave 1: the extension-internal harness page at
|
|
// `tests/uat/extension-page-harness.html` is added as a Rollup input
|
|
// so the test build emits it under that path in `dist-test/`. The
|
|
// Puppeteer driver navigates the in-browser tab to
|
|
// `chrome-extension://<id>/tests/uat/extension-page-harness.html` and
|
|
// invokes `window.__mokoshHarness.*` from the host side via CDP. The
|
|
// page itself has full chrome.* extension privileges (Approach B
|
|
// architectural anchor). Production builds (vite.config.ts) do NOT
|
|
// include this input — the page ships only in the test bundle.
|
|
//
|
|
// References:
|
|
// - Vite mergeConfig: https://vite.dev/guide/api-javascript.html#mergeconfig
|
|
// - Vite environment variables: https://vite.dev/guide/env-and-mode.html
|
|
// - Vite build.modulePreload: https://vite.dev/config/build-options.html#build-modulepreload
|
|
// - Rollup multi-entry inputs: https://rollupjs.org/configuration-options/#input
|
|
|
|
import { defineConfig, mergeConfig, type UserConfigExport } from 'vite';
|
|
import baseConfig from './vite.config';
|
|
|
|
const baseAsExport: UserConfigExport = baseConfig;
|
|
|
|
export default defineConfig(({ command, mode }) =>
|
|
mergeConfig(
|
|
typeof baseAsExport === 'function'
|
|
? baseAsExport({ command, mode, isPreview: false, isSsrBuild: false })
|
|
: baseAsExport,
|
|
{
|
|
mode: 'test',
|
|
// `define` performs a static text replacement at build time. We use a
|
|
// dedicated `__MOKOSH_UAT__` token (NOT `import.meta.env.MODE`) for the
|
|
// hook-import gate because vitest defaults its mode to 'test' too —
|
|
// gating on MODE would activate the hooks during unit tests and
|
|
// overwrite their vi.fn() mocks for chrome.notifications.create etc.
|
|
// The dedicated token is `false` everywhere except in this test bundle
|
|
// (Plan 01-11 RESEARCH §6 augmented — keeps Vite tree-shake semantics
|
|
// intact while sidestepping the vitest cross-contamination).
|
|
// Reference: https://vite.dev/config/shared-options.html#define
|
|
define: {
|
|
__MOKOSH_UAT__: 'true',
|
|
},
|
|
build: {
|
|
outDir: 'dist-test',
|
|
emptyOutDir: true,
|
|
// CRITICAL: see file header comment §4 — disables the
|
|
// document.*-using module preload polyfill that crashes SW init.
|
|
modulePreload: { polyfill: false },
|
|
rollupOptions: {
|
|
input: {
|
|
// Plan 01-13 Wave 1: emit the extension-internal harness
|
|
// page at its production path so it becomes reachable as
|
|
// chrome-extension://<id>/tests/uat/extension-page-harness.html
|
|
// The crxjs vite plugin will copy this HTML into dist-test/
|
|
// and rewrite the <script type="module" src> reference to
|
|
// the bundled chunk's hashed filename.
|
|
extension_page_harness: 'tests/uat/extension-page-harness.html',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
),
|
|
);
|