class JUnitReporter
implements Reporter

JUnit XML reporter — an additive artifact reporter, not a stdout format. Enabled with --junit[=<path>], it accumulates a <testcase> per testEnd and writes the document at run end, while whichever --reporter is active keeps owning stdout. That split matters: CI wants a readable log and a machine-readable file, and it's what --coverage=lcov already does for coverage artifacts.

Cases live on the instance (not on context), and the instance is shared across concurrent groups, so one document covers the whole run. onRunStart resets it for watch reruns.

import type { ReporterContext } from './types.ts';

import type { TestDetails } from './types.ts';

// Defined, not invoked: onRunEnd writes junit.xml to disk.
async function example(context: ReporterContext, details: TestDetails) {
  const reporter = new JUnitReporter();
  reporter.onRunStart();
  reporter.onTestEnd(context, details); // one <testcase> recorded
  await reporter.onRunEnd(context, { durationMs: 40 }); // document written to outputPath(context)
}

Methods

onRunEnd(
context: ReporterContext,
_info: RunEndInfo
): Promise<void>

Serializes the accumulated cases and writes the XML document to disk.

import type { ReporterContext } from './types.ts';

// Defined, not invoked: writes the XML document to disk.
async function example(reporter: JUnitReporter, context: ReporterContext) {
  await reporter.onRunEnd(context, { durationMs: 40 });
  // "# wrote JUnit report to tmp/junit.xml" on the run's output
}
onRunStart(): void

Drops cases from any previous run so watch reruns start clean.

const reporter = new JUnitReporter();
reporter.onRunStart(); // cases recorded by a previous watch-mode run are gone
onTestEnd(
context: ReporterContext,
details: TestDetails
): void

Accumulates one <testcase>; the document is written once at run end.

import type { ReporterContext } from './types.ts';

const reporter = new JUnitReporter();
reporter.onTestEnd({} as ReporterContext, { status: 'passed', fullName: ['Math', 'adds'], runtime: 2 });
// recorded as <testcase name="adds" classname="Math"/> (context is only read for failures)
xml(): string

The XML document as it stands. onRunEnd writes exactly this to disk; the JS API reads it back so a caller can ship the report somewhere other than the filesystem.

const reporter = new JUnitReporter();
reporter.xml().startsWith('<?xml'); // true — an empty but well-formed document

Usage

import { JUnitReporter } from "lib/reporters/junit.ts";