A simple yet powerful testing framework for Node.js backend applications and libraries
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Built-in reporters and reporter creation for test output formatting and result reporting.
Creates a detailed, human-readable spec-style test output with hierarchical display of suites, groups, and tests.
/**
* Create an instance of the spec reporter
* @param options - Optional reporter configuration
* @returns Named reporter contract
*/
function spec(options?: BaseReporterOptions): NamedReporterContract;
interface BaseReporterOptions {
/** Maximum number of stack trace frames to display */
framesMaxLimit?: number;
}
interface NamedReporterContract {
name: string;
handler: (...args: any[]) => ReporterContract;
}Usage Examples:
import { configure } from "@japa/runner";
import { spec } from "@japa/runner/reporters";
configure({
files: ["tests/**/*.spec.ts"],
reporters: {
activated: ["spec"],
list: [spec()],
},
});
// With custom options
configure({
files: ["tests/**/*.spec.ts"],
reporters: {
activated: ["detailed-spec"],
list: [
{
...spec({ framesMaxLimit: 20 }),
name: "detailed-spec",
},
],
},
});Creates a minimalist dot-style output where each test is represented by a single character (. for pass, x for fail).
/**
* Create an instance of the dot reporter
* @param options - Optional reporter configuration
* @returns Named reporter contract
*/
function dot(options?: BaseReporterOptions): NamedReporterContract;Usage Examples:
import { configure } from "@japa/runner";
import { dot } from "@japa/runner/reporters";
configure({
files: ["tests/**/*.spec.ts"],
reporters: {
activated: ["dot"],
list: [dot()],
},
});
// Multiple reporters
configure({
files: ["tests/**/*.spec.ts"],
reporters: {
activated: ["dot", "spec"],
list: [dot(), spec()],
},
});Creates newline-delimited JSON output for programmatic consumption and integration with external tools.
/**
* Create an instance of the ndjson reporter
* @param options - Optional reporter configuration
* @returns Named reporter contract
*/
function ndjson(options?: BaseReporterOptions): NamedReporterContract;Usage Examples:
import { configure } from "@japa/runner";
import { ndjson } from "@japa/runner/reporters";
configure({
files: ["tests/**/*.spec.ts"],
reporters: {
activated: ["ndjson"],
list: [ndjson()],
},
});
// Useful for CI/CD pipelines
configure({
files: ["tests/**/*.spec.ts"],
reporters: {
activated: ["ndjson", "spec"],
list: [
ndjson({ framesMaxLimit: 5 }),
spec(),
],
},
});Creates GitHub Actions-compatible output with annotations and formatted messages for CI/CD integration.
/**
* Create an instance of the github reporter
* @param options - Optional reporter configuration
* @returns Named reporter contract
*/
function github(options?: BaseReporterOptions): NamedReporterContract;Usage Examples:
import { configure } from "@japa/runner";
import { github } from "@japa/runner/reporters";
// GitHub Actions CI configuration
configure({
files: ["tests/**/*.spec.ts"],
reporters: {
activated: ["github"],
list: [github()],
},
});
// Combination for local development and CI
const isCI = process.env.CI === "true";
configure({
files: ["tests/**/*.spec.ts"],
reporters: {
activated: isCI ? ["github"] : ["spec"],
list: [
github(),
spec(),
],
},
});Create custom reporters for specialized output formats or integrations.
interface ReporterContract {
name: string;
handler: (runner: Runner, emitter: Emitter) => void;
}
interface Runner {
getSummary(): RunnerSummary;
onSuite(callback: (suite: Suite) => void): void;
}
interface Emitter {
on(event: string, callback: (...args: any[]) => void): void;
emit(event: string, ...args: any[]): void;
}Usage Examples:
import { configure } from "@japa/runner";
// Custom JSON file reporter
const jsonFileReporter = {
name: "json-file",
handler: (runner, emitter) => {
const results: any[] = [];
emitter.on("test:end", (payload) => {
results.push({
title: payload.title,
duration: payload.duration,
hasError: payload.hasError,
errors: payload.errors,
});
});
emitter.on("runner:end", () => {
const fs = require("fs");
fs.writeFileSync("test-results.json", JSON.stringify(results, null, 2));
});
},
};
// Custom Slack reporter
const slackReporter = {
name: "slack",
handler: (runner, emitter) => {
emitter.on("runner:end", async () => {
const summary = runner.getSummary();
if (summary.hasError) {
await sendSlackNotification(`Tests failed: ${summary.failedCount} failures`);
}
});
},
};
configure({
files: ["tests/**/*.spec.ts"],
reporters: {
activated: ["spec", "json-file", "slack"],
list: [
spec(),
jsonFileReporter,
slackReporter,
],
},
});Configure multiple reporters to run simultaneously for different output needs.
Usage Examples:
import { configure } from "@japa/runner";
import { spec, dot, ndjson, github } from "@japa/runner/reporters";
// Development environment
configure({
files: ["tests/**/*.spec.ts"],
reporters: {
activated: ["spec"],
list: [spec({ framesMaxLimit: 10 })],
},
});
// CI environment
configure({
files: ["tests/**/*.spec.ts"],
reporters: {
activated: ["github", "ndjson"],
list: [
github(),
ndjson(),
],
},
});
// Complete setup with environment detection
const isDevelopment = process.env.NODE_ENV === "development";
const isCI = process.env.CI === "true";
let activeReporters: string[];
if (isDevelopment) {
activeReporters = ["spec"];
} else if (isCI) {
activeReporters = ["github", "ndjson"];
} else {
activeReporters = ["dot"];
}
configure({
files: ["tests/**/*.spec.ts"],
reporters: {
activated: activeReporters,
list: [
spec({ framesMaxLimit: 15 }),
dot(),
ndjson({ framesMaxLimit: 5 }),
github(),
],
},
});interface NamedReporterContract {
name: string;
handler: (...args: any[]) => ReporterContract;
}
interface ReporterContract {
name: string;
handler: (runner: Runner, emitter: Emitter) => void;
}
interface BaseReporterOptions {
framesMaxLimit?: number;
}interface RunnerSummary {
hasError: boolean;
aggregates: {
passed: number;
failed: number;
skipped: number;
todo: number;
total: number;
};
failureTree: Array<{
name: string;
errors: Array<{
phase: string;
error: Error;
}>;
children: Array<{
name: string;
errors: Array<{
phase: string;
error: Error;
}>;
}>;
}>;
}Common events emitted by the test runner that reporters can listen to:
// Runner events
"runner:start" | "runner:end"
// Suite events
"suite:start" | "suite:end"
// Group events
"group:start" | "group:end"
// Test events
"test:start" | "test:end"