import type { Emitter } from '../testing/emitter.js'; import type { Runner } from '../runner/runner.js'; import type { TestEndNode, SuiteEndNode, GroupEndNode, TestStartNode, RunnerSummary, RunnerEndNode, GroupStartNode, SuiteStartNode, RunnerStartNode, RunnerListNode, BaseReporterOptions, RunnerEvents, WithCorrelation, CorrelationIds, FileEndNode, FileStartNode } from '../types.js'; import type { NormalizedConfig } from '../runner/types.js'; export type { TestEndNode, SuiteEndNode, GroupEndNode, TestStartNode, RunnerSummary, RunnerEndNode, GroupStartNode, SuiteStartNode, RunnerStartNode, RunnerListNode, BaseReporterOptions, } from '../types.js'; /** * Abstract BaseReporter class serving as the foundation for creating custom test reporters in Lupa. * * It handles the boilerplate of connecting to the event emitter, tracking current execution state * (suite, group, file), and provides a set of empty lifecycle methods designed to be overridden. * It also includes utilities for formatting the summary, aggregating errors, and rendering * beautifully styled error stacks and test results. * * @example * ```ts * export class MyCustomReporter extends BaseReporter { * protected onTestEnd(payload: TestEndNode) { * if (payload.hasError) { * console.log(`Failed: ${payload.title}`) * } else { * console.log(`Passed: ${payload.title}`) * } * } * } * ``` */ export declare abstract class BaseReporter { runner?: Runner; config?: NormalizedConfig; protected options: BaseReporterOptions; constructor(options?: BaseReporterOptions); /** * Returns the runner instance * * @throws Error if the runner is not initialized */ protected getRunnerOrThrow(): Runner; /** * Pretty prints the aggregates */ protected printAggregates(summary: RunnerSummary): void; /** * Check if running with multiple browsers */ protected isMultipleBrowsers(): boolean; /** * Get formatted browser name from browser ID */ protected getBrowserName(browserId?: string): string | undefined; /** * Aggregates errors tree to a flat array */ protected aggregateErrors(summary: RunnerSummary): { phase: string; title: string; error: Error; }[]; /** * Pretty print errors */ protected printErrors(summary: RunnerSummary): Promise; /** * Pretty print import errors */ protected printImportErrors(summary: RunnerSummary): Promise; /** * Invoked when an individual test begins execution. * * @example * ```ts * protected onTestStart(node: WithCorrelation) { * console.log(`Starting test: ${node.title}`) * } * ``` * @param node The test start node */ protected onTestStart?(node: WithCorrelation): void; /** * Invoked when an individual test completes, regardless of success or failure. * You can inspect `node.hasError`, `node.isSkipped`, or `node.isTodo` to determine the outcome. * * @example * ```ts * protected onTestEnd(node: WithCorrelation) { * const duration = String(node.duration).padStart(4, ' ') * if (node.hasError) { * console.log(`[FAILED] ${duration}ms - ${node.title}`) * } else { * console.log(`[PASSED] ${duration}ms - ${node.title}`) * } * } * ``` * @param node The test end node */ protected onTestEnd?(node: WithCorrelation): void; /** * Invoked when a test group (created via `test.group()`) begins execution. * * @example * ```ts * protected onGroupStart(node: WithCorrelation) { * console.log(`\n▶ Group: ${node.title}`) * } * ``` * @param node The group start node */ protected onGroupStart?(node: WithCorrelation): void; /** * Invoked when a test group completes execution. * * @example * ```ts * protected onGroupEnd(node: WithCorrelation) { * console.log(`End of group: ${node.title}`) * } * ``` * @param node The group end node */ protected onGroupEnd?(node: WithCorrelation): void; /** * Invoked when a test suite begins execution. * * @example * ```ts * protected onSuiteStart(node: WithCorrelation) { * console.log(`\n=== Suite: ${node.name} ===`) * } * ``` * @param node The suite start node */ protected onSuiteStart?(node: WithCorrelation): void; /** * Invoked when a test suite completes execution. * * @example * ```ts * protected onSuiteEnd(node: WithCorrelation) { * if (node.hasError) { * console.log(`Suite ${node.name} encountered errors.`) * } * } * ``` * @param node The suite end node */ protected onSuiteEnd?(node: WithCorrelation): void; /** * Invoked once when the entire runner initiates execution. * Useful for setting up initial console outputs, tracking start times, or initializing external services. * * @example * ```ts * protected async start(node: RunnerStartNode & Partial) { * console.clear() * console.log('Test run started...') * } * ``` * @param node The runner start node */ protected start?(node: RunnerStartNode & Partial): Promise | void; /** * Invoked once when the runner completely finishes execution. * This is the ideal place to invoke `this.printSummary()` or finalize external telemetry connections. * * @example * ```ts * protected async end(node: RunnerEndNode) { * const summary = this.getRunnerOrThrow().getSummary() * await this.printSummary(summary) * } * ``` * @param node The runner end node */ protected end?(node: RunnerEndNode): Promise | void; /** * Invoked when the runner is in list mode and dumps the test tree. * * @example * ```ts * protected onRunnerList(node: RunnerListNode) { * console.log(`Runner list: ${node.tree.size}`) * } * ``` * @param node The runner list node */ protected onRunnerList?(node: RunnerListNode): void; /** * Invoked when an import error happens. * * @example * ```ts * protected onImportError(node: RunnerEvents['runner:import_error']) { * console.log(`Import Error: ${node.file}`) * } * ``` * @param node The import error node */ protected onImportError?(node: RunnerEvents['runner:import_error']): void; /** * Invoked when a test file starts being processed. * * @example * ```ts * protected onFileStart(node: WithCorrelation) { * console.log(`Processing file: ${node.file}`) * } * ``` * @param node The file start node */ protected onFileStart?(node: WithCorrelation): void; /** * Invoked when a test file finished all tests execution. * * @example * ```ts * protected onFileEnd(node: WithCorrelation) { * console.log(`Finished processing file: ${node.file}`) * } * ``` * @param node The file end node */ protected onFileEnd?(node: WithCorrelation): void; /** * Print tests summary */ protected printSummary(summary: RunnerSummary): Promise; /** * Invoked by the tests runner when tests are about to start */ boot(runner: Runner, emitter: Emitter, config: NormalizedConfig): void; /** * Invoked when the browser runner emits a console log event during test execution. * This allows the reporter to capture and render runtime browser logs. * * @example * ```ts * protected onBrowserLog(payload: RunnerEvents['browser:log']) { * if (payload.type === 'error') { * console.error(`[BROWSER ERROR in ${payload.file}]`, ...payload.messages) * } * } * ``` */ protected onBrowserLog(payload: RunnerEvents['browser:log']): void; }