mocha-chain
Chain Mocha hooks so each one passes typed context to the next, instead of sharing nullable variables between them.
import { expect } from 'chai';
import { beforeEach, suite } from 'mocha-chain';
suite('Counter', () => {
const withCounter = beforeEach(() => ({ counter: new Counter() }));
withCounter.test('starts at zero', ({ counter }) => { expect(counter.increment()).to.equal(1);
});
});counter is a Counter in every test, never Counter | undefined, and each test gets a new one.
Features
- Typed context: a hook returns an object, and the hooks and tests chained to it receive it as their first parameter, merged with what earlier hooks returned.
- Isolated tests: each test gets a shallow copy of the context, from hooks that ran for it.
- Just Mocha: every function calls Mocha's own, so
this.timeout(),.only(),.skip(), retries and reporters all work, and native Mocha calls can be mixed in. - Catches misplaced tests: a test or hook declared inside another test or hook throws, where Mocha would silently ignore it.
- Teardown with the same context:
afterEachandafterreceive what setup returned, so cleanup is typed too. - For Vitest too: vitest-chain is the same API for Vitest.
Compared to
- Plain Mocha: a
letvariable assigned inbeforeEachmust be typedT | undefined, and asserted non-null in every test. See Why mocha-chain. - mocha-typescript and similar class-based wrappers give tests typed fields through decorators and class instances. mocha-chain keeps Mocha's functional style, and needs no decorators.
- Vitest's test context (
test.extend) types fixtures for Vitest. vitest-chain brings the hook-based style to Vitest instead.
Related
Packages
- vitest-chain
The same hook chaining for Vitest, with typed context alongside Vitest’s own test context.
- pg-dolly
A fresh Postgres database for every test, cloned from a template built once from your schema’s SQL, safe next to dev data and across parallel runs.
Used in demos
- Read-through cache
BentoCache on Valkey: a memory tier kept in sync, stale-while-revalidate, one load per key across instances, and sharding over several nodes with weighted rendezvous hashing.
- OpenAPI
A notes API from spec to database: an OpenAPI 3.1 document built from Juniper schemas, genever types for a typed client and a Hono server that validates every request and response, and Drizzle on Postgres with a database per test.
- MCP server
Making the notes API easy for AI agents that connect to services: tools shaped for tasks, an OAuth resource server with step-up scopes, and token exchange to call the API as the agent’s user.
- CLI for agents
Making the notes API easy for AI agents with a shell: one short command per task, logging in once from the API’s URL, with tokens, refresh and errors handled inside.
- Dev OAuth server
oidc-provider as a local authorization server: the real OAuth 2.1 flow with a fake login, so the other demos test their auth end to end.