Skip to content

fix(build): keep test files out of the page globs and the bundle - #328

Merged
antosubash merged 2 commits into
mainfrom
fix/exclude-test-files-from-page-globs
Sep 11, 2026
Merged

antosubash merged 2 commits into
mainfrom
fix/exclude-test-files-from-page-globs

Conversation

@antosubash

Copy link
Copy Markdown
Owner

Summary

pages/**/*.tsx matched *.test.tsx at both glob sites — the host's host/client_app/pages.ts and the module globs the manifest generator emits. Two consequences:

  1. The Inertia resolver registered a phantom page (Error.test), which is also why it showed up in the resolvable-pages list.
  2. Vite followed the import into the production build, shipping the test file and dragging @testing-library into a vendor chunk.

Found while auditing browser console output on an unrelated branch: the only console.log calls in the entire production bundle turned out to be testing-library's (screen.debug, logTestingPlaygroundURL).

Impact

Measured on one branch with only the glob differing, so the numbers are attributable:

before after
vendor chunk 1,073 kB (gzip 310 kB) 555 kB (gzip 175 kB)
total build 1,848 kB raw 1,328 kB raw
test files in bundle 3 (.js, .br, .gz) 0
files containing console.log 2 0

Every visitor was downloading roughly 135 kB gzipped of test tooling.

The fix

Both glob sites now exclude *.test.tsx and *.spec.tsx, anchored on the same base as the include — Vite resolves a negation relative to the importing file just like the include, so an exclusion written against a different base silently matches nothing. The scaffold template gets the same treatment, so newly-scaffolded apps don't inherit the bug.

Excluding the file from the page glob does not stop it being a test. Vitest has its own include pattern and still runs Error.test.tsx — 5 tests, and the suite total is unchanged at 463.

The glob rule moves into a new page_globs.py: adding the negations pushed manifest.py to 302 lines, over the 300-line cap, and per CLAUDE.md the rule is to split by responsibility rather than squeeze. Glob semantics is genuinely separate from writing the four generated files. manifest.py re-exports _glob_pattern_for so its caller and tests are unaffected.

Tests

Three new tests in test_manifest.py, all of which fail without the fix:

  • the module glob emits an include plus !…test.tsx / !…spec.tsx negations
  • the negations are anchored on the same relative base as the include (the silent-no-op trap above)
  • the host's hand-written glob in pages.ts carries the same negations — the two must agree on TEST_FILE_SUFFIXES, and nothing else would catch them drifting apart

Verification

make lint green · 2979 pytest · 463 vitest · clean rebuild confirms 0 test files and 0 console.log in host/static/dist.

Test plan

  • Reviewer confirms CI is green
  • Reviewer runs npm run build --workspace host/client_app and confirms no *.test.* in host/static/dist/assets/
  • Reviewer runs npx vitest run host/client_app/pages/Error.test.tsx and sees it still pass

https://claude.ai/code/session_01CwgTb8hULSfHoW2DrFrQAW

`pages/**/*.tsx` matched `*.test.tsx` at both glob sites — the host's
pages.ts and the module globs the manifest generator emits. Two
consequences: the resolver registered a phantom page ("Error.test"), and
Vite followed the import into the production build, shipping the test
file and dragging @testing-library into a vendor chunk.

Measured on one branch with only the glob differing:

  vendor chunk   1,073 kB -> 555 kB   (gzip 310 -> 175 kB)
  total build    1,848 kB -> 1,328 kB raw
  test files in the bundle    3 -> 0
  files with console.log      2 -> 0

Every visitor was downloading ~135 kB gzipped of test tooling, and those
were the only console.log calls in the whole production build.

Excluding the file from the *page* glob does not stop it being a test:
vitest has its own include pattern and still runs Error.test.tsx (5
tests; 463 total unchanged).

The glob rule moves to page_globs.py — adding the negations pushed
manifest.py to 302 lines, over the cap, and glob semantics is a separate
responsibility from writing the four generated files.

Claude-Session: https://claude.ai/code/session_01CwgTb8hULSfHoW2DrFrQAW
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 10, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
🔒 Security Review Completed 2026-09-10T21:33:56.551897Z fa69fc8 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Sep 10, 2026

Copy link
Copy Markdown

Deploying simple-module-python with  Cloudflare Pages  Cloudflare Pages

Latest commit: bf84179
Status: ✅  Deploy successful!
Preview URL: https://84884d80.simple-module-python.pages.dev
Branch Preview URL: https://fix-exclude-test-files-from.simple-module-python.pages.dev

View logs

Extend the test-file exclusion to the two places the review found it
missing:

- make doctor's SM003 orphan-page check (collect_tsx_pages) globbed
  pages/**/*.tsx with no exclusion, so a colocated Browse.test.tsx — the
  exact pattern the Vite glob now supports — was reported as an orphan
  page. The suffix list is duplicated rather than imported: hosting
  depends on core, so importing hosting.page_globs here would invert
  the layering. Regression test covers .test.tsx and .spec.tsx.
- A scaffold test now ties the CLI's pages.ts template to the host's
  checked-in pages.ts, so the two cannot drift apart silently.

Deferred, deliberately: vite.config.ts optimizeDeps.entries still globs
pages/**/*.tsx for the dev-server dependency crawler. It is dev-only,
never reaches the production bundle, and the proper fix touches four
files (host + scaffold vite.config.ts and module-assets.ts) — a
follow-up, not part of this fix.

Claude-Session: https://claude.ai/code/session_01CwgTb8hULSfHoW2DrFrQAW
@antosubash

Copy link
Copy Markdown
Owner Author

Ran the full review → QA → verify pipeline on this branch. One commit added: bf841799.

Review found two places the original fix had missed the same pattern:

  1. make doctor's SM003 orphan-page check globbed pages/**/*.tsx with no exclusion — so the colocated Browse.test.tsx pattern this PR now supports for Vite would have produced a false "orphan page" warning from the doctor. Fixed in core/diagnostics/_pages.py, with the suffix list duplicated rather than imported (hosting depends on core; importing the other way would invert the layering). Regression test covers .test.tsx and .spec.tsx; a second test ties the CLI's pages.ts template to the host's checked-in copy so they can't drift apart silently.
  2. optimizeDeps.entries in vite.config.ts still globs test files for the dev-server dependency scan. Deliberately deferred: pass 2 re-investigated and refuted it as a production concern — build.rollupOptions.input is main.tsx alone, so it can't touch the shipped bundle — and the proper fix spans four files (host + scaffold vite.config.ts and module-assets.ts). Follow-up, not part of this fix.

QA proved no real page was lost, which is the one way a glob negation can go wrong: asked Vite directly for its resolved sets — host glob 7 → 6 (only Error.test.tsx removed), module globs 89 page files with 0 test files. The Error page (whose test sibling was the excluded file) renders in full on a 404; Landing/Dashboard/Audit log/Settings all mount with 0 application console errors; 44/44 e2e.

Verify: rebased on main clean · lint green · 2981 pytest · 463 vitest · clean rebuild: 0 test files, 0 console.log in the bundle.

@antosubash
antosubash merged commit 923ab4c into main Sep 11, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant