webpack/webpack
Jest is the only runner and it must be invoked through the `test:base` wrapper, which supplies `--experimental-vm-modules` (bare jest crashes the ESM and test262 suites). Coverage is broad and integration-first: ~2,257 leaf `configCases/` directories, 148 `*.unittest.js` files, 144 `statsCases/`, 37 `hotCases/`, 23 `watchCases/`, 44 `benchmarkCases/`, plus four upstream spec corpora pulled in as git submodules. The same `configCases/` corpus is re-run under ~20 option variants declared in one file, and again under `cache.type: "filesystem"` by `ConfigCacheTestCases`, which is what makes cache correctness a tested property rather than a hope. The main gaps are environment-dependent: browser tiers, Deno/Bun runtimes and spec corpora only run where their prerequisites exist, and three `lib/*Minify.js` files are explicitly excluded from coverage instrumentation.
- `jest.config.js` matches five patterns (`test/*.test.js`, `*.basictest.js`, `*.longtest.js`, `unitCases/*.unittest.js`, `specCases/*.spectest.js`), uses a custom `testEnvironment` (`test/harness/patch-node-env.js`), a custom `snapshotResolver`, a 30s default timeout and `forceExit`.
- Three `minify` entry points are deliberately excluded from coverage — `lib/css/cssMinify.js`, `lib/html/htmlMinify.js`, `lib/javascript/jsMinify.js` — because they are serialized to the minimizer worker pool as source and instrumentation counters would not resolve there.
- The suite is built from thin shims over four drivers: `test/*.test.js`/`*.basictest.js`/`*.longtest.js` each call `describeCases(config)` from `test/templates/{TestCases,ConfigTestCases,HotTestCases,WatchTestCases}.js` — e.g. `ConfigTestCases.basictest.js` is five lines.
- The option-set matrix lives in one file, `test/templates/variants.js`: `normal`, `development`, `production`, `production-global-used`, `module` (target node14 + `module: true`), `hot`, nine devtool variants, `minimized-source-map`, and `cache-pack` — one `test/` shim per entry because jest parallelizes per file.
- Scale: 2,257 leaf directories under `test/configCases/` across 107 categories, 148 files in `test/unitCases/`, 144 `statsCases/`, 37 `hotCases/`, 23 `watchCases/`, 44 `benchmarkCases/`, 4 `typesCases/` and 1 `memoryLimitCases/`.
- Cache correctness is enforced by re-running the whole config corpus: `ConfigCacheTestCases.basictest.js` runs every `configCases/` case with `cache.type: "filesystem"` and fails on `Pack got invalid because of write to: <identifier>`, so a class missing `makeSerializable` surfaces as a test failure rather than as a user's slow rebuild.
- Spec conformance is imported wholesale via four git submodules under `test/external/` — test262, html5lib-tests, WPT (~161k files, shallow-cloned) and css-parsing-tests — each with its own `specCases/*.spectest.js` runner and its own CI job.
- acorn's own corpus is vendored rather than submoduled (`test/fixtures/acorn-corpus.json`) because acorn's npm tarball ships no tests; `test/unitCases/WebpackParser.unittest.js` both replays it against webpack's parser and regenerates it under `WEBPACK_UPDATE_ACORN_CORPUS=1`.
- Non-Node runtimes are covered by dedicated wrappers: `test:base:deno` runs jest under Deno with an explicit permission list and an import map, `test:base:bun` runs it under `bun --bun --smol --workerThreads` with a preload file, both routed through `test/harness/runtimeCrashReporter.js`.
- Assertion helpers are centralized in `test/helpers/` (40+ files): `checkArrayExpectation` for per-case `errors.js`/`warnings.js`, `deprecationTracking`/`expectNoDeprecations`, `FakeDocument`/`createFakeWorker`/`createFakeWorklet` for browser-API simulation, and `launchBrowser` for the syntax-equivalence tiers.
- CI gates the expensive suites on three cheap ones — `integration`, `test262`, `parser`, `syntax-equivalence`, the Deno/Bun matrix and the benchmark shards all declare `needs: [lint, basic, unit]`, so a red lint leaves most of the run reporting `skipped` rather than a result.
- The integration matrix retries once before failing (`yarn cover:integration:${part} --ci … || yarn cover:integration:${part} --ci … -f`) and only uploads coverage on the non-legacy Node versions, so Node 10/12/14/16/18/20 legs run `test:integration` without instrumentation.
- Beyond correctness, CI runs measuring suites as separate workflows: `benchmarks.yml` (sharded CodSpeed runs over `test/benchmarkCases/`), `code-size.yml` (`test:size` diffed against main's uploaded report), `deep-imports.yml` (`find-deep-imports:check` against the recorded `tooling/deep-webpack-imports.json`) and `examples.yml`.
- Printer invariants are a standalone gate: the `invariants` job runs `yarn test:invariants` (`compare-css-tools.js --invariants` and `compare-html-tools.js --invariants`) on every PR, and also installs all three comparison corpora so a Dependabot bump that breaks an install reds on its own PR.
- Type checking is tested as five separate `tsc` projects (`tsconfig.json` for `lib`, plus `tsconfig.types.test.json`, `tsconfig.types.benchmark.json`, `tsconfig.hot.json`, `tsconfig.module.test.json`) with `strict: true` and `checkJs: true` over JSDoc, and `tsconfig.validation.json` re-checks against an older TypeScript in CI.