Skip to content

Collapse pnpm test scripts into a single helper invocation#93097

Merged
lukesandberg merged 3 commits into
canaryfrom
simplify_pnpm_scripts
Apr 21, 2026
Merged

Collapse pnpm test scripts into a single helper invocation#93097
lukesandberg merged 3 commits into
canaryfrom
simplify_pnpm_scripts

Conversation

@lukesandberg
Copy link
Copy Markdown
Contributor

@lukesandberg lukesandberg commented Apr 21, 2026

What?

Every pnpm test-* / pnpm testonly-* script in the root package.json is now a single direct invocation of a new scripts/run-jest.sh helper instead of chaining through several pnpm run + cross-env layers.

Why?

Each hop through pnpm run / cross-env spins up its own Node process and takes a few hundred milliseconds before anything useful happens. For example, pnpm test-dev-turbo used to walk through five layers:

test-dev-turbo
  -> pnpm run with-turbo pnpm test-dev-inner           (cross-env IS_TURBOPACK_TEST=1)
       -> pnpm test-dev-inner                          (cross-env NEXT_TEST_MODE=dev)
            -> pnpm testheadless                       (cross-env HEADLESS=true)
                 -> pnpm testonly
                      -> jest --runInBand

Measured overhead (same machine, same stubbed jest invocation — jest --version)

Chain Layers Median (ms) Range (ms)
jest --version (baseline, direct) 1 80 75–89
pnpm test-dev-turbo --version (new) pnpm → bash → jest 448 435–493
pnpm test-dev-turbo --version (old) pnpm → cross-env → pnpm → cross-env → pnpm → cross-env → pnpm → jest 2494 2462–2512

That's ~2 seconds per test invocation shaved off, and ~85% reduction in wrapper overhead (from ~2414 ms to ~368 ms). The remaining ~368 ms is essentially just one pnpm run startup, which is unavoidable while we keep the pnpm test-* entry points.

Real-world impact: for a ~72 s e2e test run this is ~3%, but for fast unit-test files (often <5 s) this is closer to 30-40%, and it adds up quickly in CI jobs that shell out to these scripts in a loop.

How?

  • New scripts/run-jest.sh parses named flags and execs jest directly:
    • --mode=<dev|start|deploy> → sets NEXT_TEST_MODE
    • --bundler=<webpack|turbo|rspack> → sets IS_WEBPACK_TEST=1 / IS_TURBOPACK_TEST=1 / NEXT_RSPACK=1 NEXT_TEST_USE_RSPACK=1
    • --experimental → sets __NEXT_CACHE_COMPONENTS=true __NEXT_EXPERIMENTAL_APP_NEW_SCROLL_HANDLER=true
    • --headless → sets HEADLESS=true
    • -- terminates flag parsing; everything after is forwarded verbatim to jest so existing workflows like pnpm test-dev-turbo path/to/foo.test.ts -t "pattern" keep working.
  • Every test-* / testonly-* entry in package.json (including testheadless) now reads like scripts/run-jest.sh --mode=dev --bundler=turbo --headless --. No more pnpm run / cross-env indirection at the top level.
  • Removed nine unused internal intermediates (test-dev-inner, test-dev-experimental-inner, test-start-inner, test-start-experimental-inner, test-deploy-inner, testonly-dev-inner, testonly-start-inner, testonly-deploy-inner, test-inner). These were only called by other package.json scripts and not referenced anywhere else in the repo.
  • Kept testonly, testheadless, and all public test-* / testonly-* names so AGENTS.md, contributing/core/testing.md, .conductor/, and .agents/skills/ work unchanged.
  • The with-webpack, with-turbo, with-rspack, and with-experimental prefix scripts remain for ad-hoc use; they are just no longer in the hot path of the test scripts.
  • scripts/run-jest.sh invokes a bare jest, which resolves via $PATH (pnpm prepends node_modules/.bin/ when running a package script). The helper is documented as only supported when invoked through a package runner.

Verification

Ran a small e2e test through the new chain in both dev+turbopack and start+webpack modes. Output confirms env vars propagate correctly (PASS Turbopack ... / PASS webpack ..., plus pnpm next --turbopack vs pnpm next start in the logs):

pnpm test-dev-turbo test/e2e/app-dir/_allow-underscored-root-directory/...
  -> PASS Turbopack ... 3 passed

pnpm test-start-webpack test/e2e/app-dir/_allow-underscored-root-directory/...
  -> PASS webpack ... 3 passed

CI is unaffected: every workflow invokes node run-tests.js ... directly, never through these pnpm scripts.

Each `pnpm test-*` script used to chain through several `pnpm run` +
`cross-env` hops (e.g. test-dev-turbo -> with-turbo -> test-dev-inner
-> testheadless -> testonly -> jest), adding a few hundred ms of
Node/pnpm startup per hop. Route every test script through a new
scripts/run-jest.sh that parses --mode/--bundler/--experimental/--headless
flags, exports the matching env vars, and execs jest directly.

Also drops the internal *-inner intermediates which are no longer needed.
Public script names (test-dev-turbo, testonly-start-webpack, testheadless,
testonly, etc.) are preserved so AGENTS.md and the contributing docs
continue to work unchanged.

Co-Authored-By: Claude <noreply@anthropic.com>
Comment thread scripts/run-jest.sh
Comment thread scripts/run-jest.sh
…est.sh.

Adds a comment explaining that the bare `jest` invocation in
scripts/run-jest.sh relies on being called from a pnpm/package-runner
script (which prepends node_modules/.bin to $PATH).

Also replaces the last `cross-env HEADLESS=true jest --runInBand`
(testheadless) with `scripts/run-jest.sh --headless --` so there are
no more cross-env hops in the test script chain.

Co-Authored-By: Claude <noreply@anthropic.com>
@lukesandberg lukesandberg marked this pull request as ready for review April 21, 2026 18:12
@lukesandberg lukesandberg requested a review from a team April 21, 2026 18:30
Comment thread scripts/run-jest.sh
@lukesandberg lukesandberg merged commit 0b08e2f into canary Apr 21, 2026
335 of 337 checks passed
Copy link
Copy Markdown
Contributor Author

Merge activity

@lukesandberg lukesandberg deleted the simplify_pnpm_scripts branch April 21, 2026 23:53
@github-actions github-actions Bot added the locked label May 6, 2026
@github-actions github-actions Bot locked as resolved and limited conversation to collaborators May 6, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants