import type { FullConfig, FullResult, Reporter, Suite, TestCase, TestResult } from "@playwright/test/reporter"; import type { Formatter } from "./writeFileWithPrettier"; export interface LogsReporterOptions { /** Directory where log files are written on test failure */ logsFolder: string; /** Directory where HAR files are moved on test failure (temp HAR deleted on pass) */ harsFolder?: string; /** Workspace root used by createLogFile to locate prettier.config.mjs */ nxRoot: string; /** Prettier formatter instance */ formatter: Formatter; } /** * Custom Playwright reporter that writes redacted log files on test failure * and manages HAR file cleanup (retain on failure, delete on pass). */ export declare class LogsReporter implements Reporter { private readonly logsFolder; private readonly harsFolder; private readonly nxRoot; private readonly formatter; /** * Promises of in-flight log file writes from `onTestEnd`. `createLogFile` * formats with Prettier (async) and writes via `writeFileSync`; Playwright * may finish the run before those formats settle, so we track them here and * await them in `onEnd` to surface formatter errors and ensure files exist * by the time the process exits. */ private readonly pendingWrites; /** @param options - Reporter configuration options */ constructor(options: LogsReporterOptions); /** Creates the logs folder before the run begins. */ onBegin(_config: FullConfig, _suite: Suite): void; /** Writes a redacted log file on test failure and manages HAR file retention. */ onTestEnd(test: TestCase, result: TestResult): void; /** * Awaits in-flight log writes started in `onTestEnd` before the reporter * signals completion. Without this, Playwright may exit before Prettier * settles, leaving partial or missing log files and swallowing formatter * errors. */ onEnd(_result: FullResult): Promise; /** Returns false so Playwright adds its own terminal reporter alongside this one. */ printsToStdio(): boolean; /** * Scrubs Playwright's `error-context.md` failure attachment in place. * * On failure Playwright writes an `error-context.md` under `test-results/` * (uploaded as a CI artifact) that embeds the failing assertion's *received* * value and a page/aria snapshot. The `login()` slow path navigates to * `/auth/manager-classic#session_token=...`, so this file carries a live Okta * session token — and would carry the password if it ever surfaced in an * assertion's received value. It is neither a trace, HAR, nor a stdout log, so * the other redaction passes miss it entirely; scrub it here. Best-effort: * redaction never fails the reporter. */ private redactErrorContext; private getResultTracePath; /** * Persists (on failure) or cleans up (always) the per-test HAR recorded by the * `harRecording` fixture. * * The raw HAR is recorded to a deterministic temp path outside `outputDir` * (see `harRecordingPath`). `recordHar` only flushes it when the browser * context closes — and on a hard timeout that close completes during * Playwright's *native* context teardown, after the fixture's own teardown has * bounded out. Because `onTestEnd` runs after all teardown, the file is * reliably present here regardless of how late the close flushed: this is what * makes a hard-timeout HAR survive (the earlier `testInfo.attach` seam ran too * early on that path and lost it). On failure we redact (the HAR carries * Authorization/Cookie and request/response bodies) and move it into the shared * `hars/` artifacts folder; in every case we delete the raw temp source via * `finally` so an unredacted HAR never lingers on disk, even if redaction throws. */ private persistHar; } export default LogsReporter;