CtrlK
BlogDocsLog inGet started
Tessl Logo

testland/js-unit-tests

JavaScript/TypeScript unit testing with Jest and Vitest as co-primary frameworks - install, config (`jest.config.js` / `vite.config.ts` test block), mocking (`jest.fn`/`jest.mock`/`jest.spyOn`, `vi.fn`/`vi.mock`/`vi.spyOn`, `__mocks__/`, fake timers), coverage (Istanbul/babel vs v8 providers, `coverageThreshold` gating), watch mode, and CI (`jest --ci`, `vitest run`, JUnit XML). Includes framework choice (Vite project → Vitest, otherwise Jest; always match an existing convention), test-authoring conventions (framework detection from package.json + config files, ESM vs CJS, no fabricated exports), and references for Mocha maintenance, Jasmine/Karma-to-Jest migration via jest-codemods, and deep Jest/Vitest coverage analysis. Use for any JS/TS unit-test task: setting up a framework, writing or mocking tests, gating coverage, or wiring CI.

93

Quality

93%

Does it follow best practices?

Impact

Average score across 10 eval scenarios

SecuritybySnyk

Passed

No findings from the security scan

Overview
Quality
Evals
Security
Files

mocha.mdreferences/

Mocha - pluggable JS test runner (maintenance reference)

Companion reference for js-unit-tests. Consult when maintaining a legacy Mocha codebase, or when a library/tooling project prefers a minimal pluggable runner over Jest/Vitest's batteries-included model. For new projects, prefer Jest or Vitest (see the Choosing section of SKILL.md).

Per mochajs.org:

Mocha is the original mainstream JS test runner. Distinguishing features:

  • Pluggable: assertions (Chai / Node assert), mocking (Sinon), coverage (nyc / c8) are separate libraries - pick what you need.
  • Two interfaces: BDD (describe/it, default) and TDD (suite/test).
  • Reporter ecosystem: spec, json, html, tap, dot, mocha-junit-reporter.
  • Parallel mode (Mocha 8+): --parallel flag for multi-process runs.

Install and first test

npm install --save-dev mocha
npm install --save-dev chai sinon nyc   # typical peers
// test/sum.test.js
const { expect } = require('chai');
const { sum } = require('../src/sum');

describe('sum', () => {
  it('adds 1 + 2 to equal 3', () => {
    expect(sum(1, 2)).to.equal(3);
  });
});

Wire "test": "mocha" in package.json. Default test glob: ./test/*.{js,cjs,mjs} plus ./test/**/*.spec.js. Node's built-in node:assert works too when zero extra deps matter.

.mocharc.json configuration

Config files: .mocharc.json, .mocharc.js, .mocharc.yaml, or a mocha key in package.json:

{
  "spec": ["test/**/*.spec.js"],
  "recursive": true,
  "require": ["ts-node/register", "./test/setup.js"],
  "reporter": "spec",
  "timeout": 5000,
  "parallel": true,
  "jobs": 4,
  "ui": "bdd",
  "extension": ["js", "ts"]
}

Key options: parallel + jobs (multi-process, Mocha 8+); ui: 'bdd' (default) vs 'tdd'; recursive (nested test dirs); require (preload TS support / setup).

Async patterns

Per mocha, three approaches - callback (done), returned promise, and async/await (preferred):

it('async/await', async () => {
  const result = await doAsyncWork();
  expect(result).to.equal(42);
});

The async function MUST return (or await) - otherwise the promise's rejection isn't surfaced to Mocha and tests pass-by-accident.

Hooks, exclusivity, and skipping

before / after (once per describe block) and beforeEach / afterEach (per test) all accept async bodies. it.only / describe.only run exclusively; it.skip / xit skip. Forbid committed .only via eslint-plugin-mocha's mocha/no-exclusive-tests rule.

Coverage with nyc / c8

{
  "extends": "@istanbuljs/nyc-config-typescript",
  "all": true,
  "check-coverage": true,
  "branches": 80, "lines": 80, "functions": 80, "statements": 80,
  "include": ["src/**/*.{js,ts}"],
  "reporter": ["text", "lcov", "html"]
}

Run nyc mocha (Istanbul instrumentation), or c8 mocha (Node's built-in V8 coverage; faster, no instrumentation). check-coverage + thresholds make the run fail below the floor.

Parallel mode and root hooks

Per parallel mode (Mocha 8+): mocha --parallel --jobs 4. Tests must be independent - shared state across describe blocks breaks parallel runs.

Root hooks stop working in parallel mode. "Each test file gets its own instance of Mocha", so a root hook defined in file A "will not be present" in file B (mocha-par). The serial-era pattern - --file ./test/setup.js installing a top-level before - does not carry over. Two supported replacements (root hook plugins):

// test/hooks.js - loaded with `mocha --require test/hooks.js`
export const mochaHooks = {
  beforeEach() { /* runs in every worker, before every test */ },
};

// once per run, not per worker ([global fixtures][mocha-gf]):
export const mochaGlobalSetup = async () => { /* seed */ };
export const mochaGlobalTeardown = async () => { /* tear down */ };

CI integration

- run: npm ci
- run: npx mocha --reporter mocha-junit-reporter --reporter-option mochaFile=./test-results/junit.xml
# Or with coverage:
- run: npx c8 --reporter lcov mocha
- uses: codecov/codecov-action@v4
  with: { files: ./coverage/lcov.info }

mocha-junit-reporter emits JUnit XML for junit-xml-analysis (qa-test-reporting).

Anti-patterns

Anti-patternWhy it failsFix
Forget return / await on async test bodyRejection silently passes the testAlways return or await
Commit .only accidentallyCI runs only one testmocha/no-exclusive-tests lint rule
--parallel with a shared root beforeHooks run inconsistently per-processRoot hook plugins / global fixtures
Mix BDD + TDD interfacesReader confusionPick one in .mocharc.json ui:
Skip check-coverage in nycCoverage gates not enforcedEnable + set thresholds

Limitations

  • No bundled assertions / mocking / coverage - more setup vs Jest/Vitest.
  • Watch mode less polished than Vitest's; snapshots need third-party mocha-chai-jest-snapshot.
  • ESM support workable but historically rough; pin a recent Mocha version.

References

  • mocha - official site; mochajs.org/api - API reference
  • chaijs.com - Chai assertions; sinonjs.org - Sinon mocking
  • istanbul.js.org / github.com/bcoe/c8 - coverage tools
  • github.com/michaelleeallen/mocha-junit-reporter - JUnit XML reporter

SKILL.md

tile.json