/** * What a Playwright run executed, recorded for the next run's selection. * * The instrument is the one `@variance-authority/sense` already uses; only the * transport differs, which is the rule * [spec 0028](https://github.com/Variance-Authority/variance-authority/blob/main/docs/specs/0028-the-instrument.md) states. The adopter's * application build carries `testSelectionProbes()`, the page counts block * crossings, and this drains those counters around each observation. * * ## Why the owner is a file * * A story is a subject this tool shows one at a time, so it may be selected on * its own. A Playwright test is not: the runner's unit of execution is the spec * file, so attributing crossings to a title would record a distinction no * `--since` could spend. Every observation in one file joins that file, and the * file is what gets selected. */ import type { Page, TestInfo } from '@playwright/test'; import { type CasePrecondition, type EvaluatingPage, type PreconditionStanding } from '@variance-authority/sense/journal'; import type { Wire } from '@variance-authority/wire/listen'; import type { ExecutionRecording } from './execution-recording.js'; import { type ObservedTest } from './test-coordinate.js'; export { ownerOf, testOf, type ObservedTest } from './test-coordinate.js'; export type { ExecutionRecording } from './execution-recording.js'; /** One worker's accumulation, drained per observation and written once. */ export interface ExecutionRecorder { /** * Take everything one document has entered since the last drain — a page's, * or any frame's, since the application is not always the top document. * * `subject` names the individual test the window belongs to, for a run * recording cases. Without it the crossings join the file and nothing finer, * which is what selection reads either way. * * `line` is the test line whose statement ran since the drain before, for a * case whose file was cut: each region the window holds that the case has * not reached under an earlier line is charged to it. A case drained without * one carries no lines, and a region drained without one before its first is * ambient. */ readonly note: (page: EvaluatingPage, owner: string, subject?: ObservedTest, line?: number) => Promise; /** * Mint this execution's journey and put it on the page's context. * * One opaque id per attempt, not per subject: a flake and its retry are two * executions and the heads must be able to tell them apart. The browser * attaches it to every same-origin request — navigations, subresources, * `fetch` a library made with no `credentials` option, `sendBeacon`, a form * POST — so nothing in the application is touched to carry it. * * Returns the journey, so anything else that needs this execution named — the * `events` fixture, most of all — uses the one that is already on the context * rather than minting a second and overwriting the first. */ readonly join: (page: Page, owner: string, origin?: string, subject?: ObservedTest) => Promise; /** * The owner key for one test, against the root this recorder was given. * * Every half of the seam has to spell a file the same way or it is two * owners: one the crossings went to, one the verdict retired, and neither * complete. The root is the recorder's because the recorder is what writes, * and a configuration that set `root` meant it for the paths that land in * the index — not only for the ones the closing fold happens to compute. */ readonly owner: (testInfo: TestInfo) => string; /** * Say whether this owner's tests finished; an incomplete owner never excludes. * With the test, the case carries it too, as whether its journey stopped. * * `duration` is the milliseconds Playwright counted for the attempt, as * `testInfo.duration` holds them when the test's fixtures tear down. The file * and the case each sum their attempts; nothing here reads a clock. */ readonly mark: (owner: string, complete: boolean, subject?: ObservedTest, duration?: number) => void; /** * Keep one attempt's Eyes journal for its case, counted from 1, or without * one, that the attempt opened a journal. The record joins it to the case by * the id the index gives the case; see `case-scope.ts`. */ readonly eyes: (owner: string, subject: ObservedTest, attempt: number, journal?: Readonly>) => void; /** What the case has said so far, or nothing where no listener runs; see `arranged.ts`. */ readonly arranged: (owner: string, subject: ObservedTest) => readonly CasePrecondition[] | undefined; /** The checkout every path this recorder writes is named against. */ readonly root: string; /** Merge this worker's contribution into the index, or explain the silence. */ readonly close: () => Promise; } /** * Collect one worker's crossings. * * Workers are processes, and each one writes the shared index at teardown under * the lock `recordExecution` takes. Accumulating first is what keeps that * to one contended write per worker instead of one per assertion. */ export declare function createExecutionRecorder(recording?: ExecutionRecording, wire?: Wire, standing?: () => PreconditionStanding): ExecutionRecorder; //# sourceMappingURL=execution.d.ts.map