☕️ Classic, reliable, trusted test framework for Node.js and the browser
# AGENTS.md
Agent onboarding for the `mochajs/mocha` repository.
> **Trust this file first.** If you are unsure about command order, use the sequences below before trying alternatives.
## Instruction precedence and execution defaults
- Use `AGENTS.md` as the primary repository playbook for agent work.
- Use `.github/copilot-instructions.md` as the short compatibility layer for tools that prefer it.
- If prose and executable configuration disagree on command details, trust `package.json` scripts and `.github/workflows/*.yml`.
- Prefer repository `npm` scripts over ad hoc shell pipelines.
- If the current tool environment cannot edit files or run commands, provide copy-ready patch/command text and clearly mark validation as not run.
## Mission and scope
- Keep changes minimal and targeted.
- Preserve compatibility (Mocha is highly depended-upon and semver-sensitive).
- Never edit generated artifacts directly.
- Validate locally with the smallest command set that matches your change.
## Environment prerequisites
- Node.js: `^20.19.0 || >=22.12.0` (prefer Node 22 locally)
- npm (do not use pnpm/yarn for this repo)
- Google Chrome (required for browser tests)
## Repository map (quick)
- `lib/` — core runtime (runner, suite, hooks, reporters, CLI internals)
- `bin/` — CLI entrypoints (`mocha`)
- `test/` — unit, integration, node-only, browser-specific, smoke
- `docs/` — Astro/Starlight docs app with separate lockfile/scripts
- `mocha.js` / `mocha.js.map` — browser bundle outputs (generated)
- `.github/workflows/` — CI job matrix and script partitioning
## Generated files and do-not-edit rules
- **Do not edit** `mocha.js` or `mocha.js.map` by hand.
- These are generated via `npm run build` (Rollup).
- `npm run clean` removes generated bundle artifacts.
## Verified command runbooks
Run from repository root unless noted.
### Bootstrap
1. `npm install`
2. (Docs work only) `cd docs && npm install`
For clean CI reproduction on a fresh checkout, prefer `npm ci --ignore-scripts`; use `npm install` for normal local bootstrap.
### Fast sanity (recommended before/after focused edits)
1. `npm run clean`
2. `npm run build`
3. `npm run tsc`
4. `npm run test-smoke`
5. Targeted tests relevant to changed area (see below)
### Targeted tests
- Unit/core: `npm run test-node:unit`
- Integration: `npm run test-node:integration`
- Interfaces: `npm run test-node:interfaces`
- Reporters: `npm run test-node:reporters`
- Browser subset: `npm run test-browser -- --grep bdd`
- Full browser path: `npm run test-browser` (includes clean + build)
### Validation routing
- Instruction/docs-only edits: no runtime checks required unless behavior claims changed.
- Browser or reporter changes: `npm run clean` → `npm run build` → browser validation.
- CLI or node runtime changes: `npm run test-smoke` plus the closest `test-node:*` suite.
- Type/signature changes: `npm run tsc`.
- Workflow or script changes: mirror the affected `package.json` script or workflow job locally when practical.
### Full local gate (closest to CI intent)
1. `npm run format:check`
2. `npm run lint`
3. `npm run test-node`
4. `npm run test-browser`
5. `npm run tsc`
## Critical command-order gotchas
- Browser tests depend on built bundle artifacts.
- If you run `clean`, you **must** run `build` before invoking `playwright test` directly, or the page will 404 on `/mocha.js`.
- `test-browser` script is safer than calling `playwright test` directly because it includes `clean build`.
## CI parity notes
Main workflow: `.github/workflows/mocha.yml`
CI partitions checks into separate jobs:
- `format:check`
- `lint`
- `test-smoke` (Node 20/22/24)
- `test-node:*` matrix (interfaces/unit/integration/jsapi/requires/reporters/only)
- browser tests (`test-browser` with ChromeHeadless)
- `tsc`
Reusable execution details in `.github/workflows/npm-script.yml`:
- Uses `npm ci --ignore-scripts`
- Default Node 22 unless overridden
- `NODE_OPTIONS=--trace-warnings`
- Optional coverage upload via Codecov
## Transient validation issues and environment drift
During onboarding or after dependency refresh, you may encounter validation failures that reflect local environment or ecosystem drift rather than a persistent repository bug.
Common patterns include:
- Lint commands (for example, `npm run lint:code`) failing because new or stricter rules turn warnings into errors (such as via `--max-warnings 0`). Inspect the reported rule and location before changing lint configuration or adding suppressions.
- Docs-related workflows where documentation generation succeeds but a subsequent static site or bundler step (for example, `astro build`) fails with runtime errors originating in third-party dependencies.
Treat these as potential environment/version drift signals. Do not resolve them by broadly weakening checks (for example, relaxing lint strictness or skipping build steps) unless explicitly requested in the task.
## Change strategy for agents
- Prefer smallest reproducible command to validate your specific edit first.
- Add/adjust tests with behavior changes; do not change unrelated tests.
- Avoid broad dependency upgrades unless task explicitly requests it.
- If touching browser behavior, always include at least one browser test run.
- If touching CLI or node runtime behavior, include smoke + targeted node suite.
### CJS to ESM migration conventions (runtime code)
- Scope: prioritize runtime modules under `lib/`; do not include test fixtures unless explicitly requested.
- For ESM modules, prefer **named exports** over `export default`.
- When consuming ESM from CJS via `require()`, import named bindings from the namespace object:
- Use `const { SomeName } = require("./file.mjs");`
- Avoid `require("./file.mjs").default` for runtime modules.
- Keep PRs small and reviewable (roughly <=100 changed lines when practical).
- After each migration slice, update all direct runtime call sites in the same PR to avoid mixed import patterns.
## Docs subsystem notes (`docs/`)
- Separate package and lockfile.
- Script chain in `docs/package.json`:
- `generate` fetches supporter metadata/assets
- `build` runs `astro check && astro build`
- `docs` script reinstalls root+docs deps, then generate+build
- Docs output can be very noisy (many supporter image fetch logs).
## High-signal troubleshooting
- Never claim a check passed unless you actually ran it.
- If blocked, report the exact command, working directory, and first meaningful error.
- Missing Chrome / browser launch failures: ensure local Chrome installed and available.
- Browser path errors after cleanup: rerun `npm run build`.
- Strange lint failures after dependency changes: rerun on clean install (`npm ci`), inspect warning-as-error output first.
- Unexpected CI mismatch: mirror exact script from workflow rather than invoking custom command combinations.