@hapi/lab is a comprehensive test utility framework specifically designed for Node.js applications. It provides advanced testing capabilities including test runners, assertion libraries, code coverage analysis, memory leak detection, and TypeScript support with a simple, modern API based on async/await.
npm install @hapi/labconst Lab = require('@hapi/lab');
const { experiment, test, before, after } = exports.lab = Lab.script();For TypeScript:
import * as Lab from '@hapi/lab';
const lab = Lab.script();
const { describe, it, before } = lab;
export { lab };const Code = require('@hapi/code');
const Lab = require('@hapi/lab');
const { expect } = Code;
const { experiment, test, before, after } = exports.lab = Lab.script();
experiment('Math operations', () => {
test('addition works correctly', () => {
expect(1 + 1).to.equal(2);
});
test('async operations supported', async () => {
const result = await Promise.resolve(42);
expect(result).to.equal(42);
});
});@hapi/lab is built around several key components:
Core functionality for creating test scripts and organizing tests into experiments with setup/teardown hooks.
function script(options?: ScriptOptions): Script;
interface ScriptOptions {
schedule?: boolean;
cli?: CliOptions;
}
interface Script {
experiment: Experiment;
describe: Experiment;
suite: Experiment;
test: Test;
it: Test;
before: Setup;
after: Setup;
beforeEach: Setup;
afterEach: Setup;
}Programmatic test execution with comprehensive reporting and analysis capabilities.
function execute(scripts: Script | Script[], options?: ExecutionOptions, reporter?: Reporter): Promise<Notebook>;
function report(scripts: Script | Script[], options?: ExecutionOptions): Promise<Notebook>;
interface Notebook {
ms: number;
tests: TestResult[];
failures: number;
errors: any[];
coverage?: CoverageReport;
leaks?: LeakReport;
types?: TypesReport;
}Integration point for external assertion libraries, populated by the CLI
-a// Set by CLI --assert option, provides expect and fail functions to scripts
assertions: object | null;Advanced code coverage analysis with instrumentation and multiple report formats.
interface Coverage {
instrument(options: CoverageOptions): Promise<void>;
analyze(options: CoverageOptions): Promise<CoverageReport>;
}Global variable leak detection to ensure test isolation and prevent memory leaks.
interface Leaks {
detect(customGlobals?: string[], options?: LeakOptions): Promise<LeakReport>;
}Comprehensive TypeScript support including type validation and test execution.
interface Types {
expect: TypeExpect;
validate(options?: TypeOptions): Promise<TypesReport>;
}
interface TypeExpect {
type<T>(value: T): void;
error<T = any>(value: T): void;
}Full-featured CLI with extensive configuration options for all aspects of test execution.
interface Cli {
run(): Promise<{ code: number }>;
}interface TestOptions {
skip?: boolean;
only?: boolean;
timeout?: number;
plan?: number;
retry?: number | boolean;
}
interface Flags {
readonly context: Record<string, any>;
mustCall<T extends (...args: any[]) => any>(func: T, count: number): T;
note(note: string): void;
onCleanup?: Action;
onUncaughtException?: ErrorHandler;
onUnhandledRejection?: ErrorHandler;
}
interface Action {
(flags: Flags): Promise<any> | void;
}
interface Setup {
(action: Action): void;
(options: TestOptions, action: Action): void;
}
interface Experiment {
(title: string, content: () => void): void;
(title: string, options: Omit<TestOptions, 'plan'>, content: () => void): void;
only(title: string, content: () => void): void;
only(title: string, options: Omit<TestOptions, 'plan'>, content: () => void): void;
skip(title: string, content: () => void): void;
skip(title: string, options: Omit<TestOptions, 'plan'>, content: () => void): void;
}
interface Test {
(title: string, test: Action): void;
(title: string, options: TestOptions, test: Action): void;
only(title: string, test: Action): void;
only(title: string, options: TestOptions, test: Action): void;
skip(title: string, test: Action): void;
skip(title: string, options: TestOptions, test: Action): void;
}
interface ErrorHandler {
(err: Error): void;
}