From b5d968fa0e3acb052de4eab5952f6efb668d9111 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Tue, 10 Sep 2024 06:08:54 -0700 Subject: [PATCH] chore: make ReporterV2 a partial interface (#32532) This makes it easier to write reporters by avoding empty methods. --- .../playwright/src/isomorphic/teleReceiver.ts | 4 +- .../src/isomorphic/teleSuiteUpdater.ts | 12 ++---- packages/playwright/src/reporters/base.ts | 16 -------- packages/playwright/src/reporters/dot.ts | 4 -- packages/playwright/src/reporters/empty.ts | 38 +------------------ packages/playwright/src/reporters/github.ts | 2 +- packages/playwright/src/reporters/html.ts | 21 +++++----- .../src/reporters/internalReporter.ts | 26 ++++++------- packages/playwright/src/reporters/json.ts | 19 ++++++---- packages/playwright/src/reporters/junit.ts | 17 +++++---- packages/playwright/src/reporters/line.ts | 13 ++----- packages/playwright/src/reporters/list.ts | 14 ++----- packages/playwright/src/reporters/markdown.ts | 2 +- .../playwright/src/reporters/multiplexer.ts | 26 ++++++------- .../playwright/src/reporters/reporterV2.ts | 24 ++++++------ .../playwright/src/reporters/teleEmitter.ts | 3 -- packages/playwright/src/runner/dispatcher.ts | 24 ++++++------ packages/playwright/src/runner/reporters.ts | 29 +++++++------- packages/playwright/src/runner/tasks.ts | 2 +- .../trace-viewer/src/ui/uiModeTraceView.tsx | 2 +- 20 files changed, 114 insertions(+), 184 deletions(-) diff --git a/packages/playwright/src/isomorphic/teleReceiver.ts b/packages/playwright/src/isomorphic/teleReceiver.ts index 6391f8a64c..0c4408096d 100644 --- a/packages/playwright/src/isomorphic/teleReceiver.ts +++ b/packages/playwright/src/isomorphic/teleReceiver.ts @@ -133,12 +133,12 @@ export class TeleReporterReceiver { public isListing = false; private _rootSuite: TeleSuite; private _options: TeleReporterReceiverOptions; - private _reporter: Partial; + private _reporter: ReporterV2; private _tests = new Map(); private _rootDir!: string; private _config!: reporterTypes.FullConfig; - constructor(reporter: Partial, options: TeleReporterReceiverOptions = {}) { + constructor(reporter: ReporterV2, options: TeleReporterReceiverOptions = {}) { this._rootSuite = new TeleSuite('', 'root'); this._options = options; this._reporter = reporter; diff --git a/packages/playwright/src/isomorphic/teleSuiteUpdater.ts b/packages/playwright/src/isomorphic/teleSuiteUpdater.ts index ef1c2dbb3e..6f86c50147 100644 --- a/packages/playwright/src/isomorphic/teleSuiteUpdater.ts +++ b/packages/playwright/src/isomorphic/teleSuiteUpdater.ts @@ -77,6 +77,7 @@ export class TeleSuiteUpdater { // To work around that, have a dedicated per-run receiver that will only have // suite for a single test run, and hence will have correct total. this._lastRunReceiver = new TeleReporterReceiver({ + version: () => 'v2', onBegin: (suite: reporterTypes.Suite) => { this._lastRunTestCount = suite.allTests().length; this._lastRunReceiver = undefined; @@ -127,20 +128,13 @@ export class TeleSuiteUpdater { onError: (error: reporterTypes.TestError) => this._handleOnError(error), - printsToStdio: () => { - return false; - }, - - onStdOut: () => { }, - onStdErr: () => { }, - onExit: () => { }, - onStepBegin: () => { }, - onStepEnd: () => { }, + printsToStdio: () => false, }; } processGlobalReport(report: any[]) { const receiver = new TeleReporterReceiver({ + version: () => 'v2', onConfigure: (c: reporterTypes.FullConfig) => { this.config = c; }, diff --git a/packages/playwright/src/reporters/base.ts b/packages/playwright/src/reporters/base.ts index c9ce2f7bcd..e0aa7fa04e 100644 --- a/packages/playwright/src/reporters/base.ts +++ b/packages/playwright/src/reporters/base.ts @@ -123,9 +123,6 @@ export class BaseReporter implements ReporterV2 { (result as any)[kOutputSymbol].push(output); } - onTestBegin(test: TestCase, result: TestResult): void { - } - onTestEnd(test: TestCase, result: TestResult) { if (result.status !== 'skipped' && result.status !== test.expectedStatus) ++this._failureCount; @@ -146,19 +143,6 @@ export class BaseReporter implements ReporterV2 { this.result = result; } - onStepBegin(test: TestCase, result: TestResult, step: TestStep): void { - } - - onStepEnd(test: TestCase, result: TestResult, step: TestStep): void { - } - - async onExit() { - } - - printsToStdio() { - return true; - } - protected fitToScreen(line: string, prefix?: string): string { if (!ttyWidth) { // Guard against the case where we cannot determine available width. diff --git a/packages/playwright/src/reporters/dot.ts b/packages/playwright/src/reporters/dot.ts index 05d2da1e4e..169af3b1e7 100644 --- a/packages/playwright/src/reporters/dot.ts +++ b/packages/playwright/src/reporters/dot.ts @@ -20,10 +20,6 @@ import type { FullResult, TestCase, TestResult, Suite, TestError } from '../../t class DotReporter extends BaseReporter { private _counter = 0; - override printsToStdio() { - return true; - } - override onBegin(suite: Suite) { super.onBegin(suite); console.log(this.generateStartingMessage()); diff --git a/packages/playwright/src/reporters/empty.ts b/packages/playwright/src/reporters/empty.ts index 09bd63668c..3bab9bda0f 100644 --- a/packages/playwright/src/reporters/empty.ts +++ b/packages/playwright/src/reporters/empty.ts @@ -15,49 +15,15 @@ */ import type { ReporterV2 } from './reporterV2'; -import type { FullConfig, TestCase, TestError, TestResult, FullResult, TestStep, Suite } from '../../types/testReporter'; class EmptyReporter implements ReporterV2 { - onConfigure(config: FullConfig) { - } - - onBegin(suite: Suite) { - } - - onTestBegin(test: TestCase, result: TestResult) { - } - - onStdOut(chunk: string | Buffer, test?: TestCase, result?: TestResult) { - } - - onStdErr(chunk: string | Buffer, test?: TestCase, result?: TestResult) { - } - - onTestEnd(test: TestCase, result: TestResult) { - } - - async onEnd(result: FullResult) { - } - - async onExit() { - } - - onError(error: TestError) { - } - - onStepBegin(test: TestCase, result: TestResult, step: TestStep) { - } - - onStepEnd(test: TestCase, result: TestResult, step: TestStep) { + version(): 'v2' { + return 'v2'; } printsToStdio() { return false; } - - version(): 'v2' { - return 'v2'; - } } export default EmptyReporter; diff --git a/packages/playwright/src/reporters/github.ts b/packages/playwright/src/reporters/github.ts index 85bd4f8525..dc03677714 100644 --- a/packages/playwright/src/reporters/github.ts +++ b/packages/playwright/src/reporters/github.ts @@ -59,7 +59,7 @@ class GitHubLogger { export class GitHubReporter extends BaseReporter { githubLogger = new GitHubLogger(); - override printsToStdio() { + printsToStdio() { return false; } diff --git a/packages/playwright/src/reporters/html.ts b/packages/playwright/src/reporters/html.ts index 7b279a70a1..fd1fb0cbdf 100644 --- a/packages/playwright/src/reporters/html.ts +++ b/packages/playwright/src/reporters/html.ts @@ -30,7 +30,7 @@ import type { ZipFile } from 'playwright-core/lib/zipBundle'; import { yazl } from 'playwright-core/lib/zipBundle'; import { mime } from 'playwright-core/lib/utilsBundle'; import type { HTMLReport, Stats, TestAttachment, TestCase, TestCaseSummary, TestFile, TestFileSummary, TestResult, TestStep } from '@html-reporter/types'; -import EmptyReporter from './empty'; +import type { ReporterV2 } from './reporterV2'; type TestEntry = { testCase: TestCase; @@ -55,7 +55,7 @@ type HtmlReporterOptions = { _isTestServer?: boolean; }; -class HtmlReporter extends EmptyReporter { +class HtmlReporter implements ReporterV2 { private config!: FullConfig; private suite!: Suite; private _options: HtmlReporterOptions; @@ -68,19 +68,22 @@ class HtmlReporter extends EmptyReporter { private _topLevelErrors: TestError[] = []; constructor(options: HtmlReporterOptions) { - super(); this._options = options; } - override printsToStdio() { + version(): 'v2' { + return 'v2'; + } + + printsToStdio() { return false; } - override onConfigure(config: FullConfig) { + onConfigure(config: FullConfig) { this.config = config; } - override onBegin(suite: Suite) { + onBegin(suite: Suite) { const { outputFolder, open, attachmentsBaseURL, host, port } = this._resolveOptions(); this._outputFolder = outputFolder; this._open = open; @@ -122,18 +125,18 @@ class HtmlReporter extends EmptyReporter { return !!relativePath && !relativePath.startsWith('..') && !path.isAbsolute(relativePath); } - override onError(error: TestError): void { + onError(error: TestError): void { this._topLevelErrors.push(error); } - override async onEnd(result: FullResult) { + async onEnd(result: FullResult) { const projectSuites = this.suite.suites; await removeFolders([this._outputFolder]); const builder = new HtmlBuilder(this.config, this._outputFolder, this._attachmentsBaseURL); this._buildResult = await builder.build(this.config.metadata, projectSuites, result, this._topLevelErrors); } - override async onExit() { + async onExit() { if (process.env.CI || !this._buildResult) return; const { ok, singleTestId } = this._buildResult; diff --git a/packages/playwright/src/reporters/internalReporter.ts b/packages/playwright/src/reporters/internalReporter.ts index 392a8d9374..3526f89e0d 100644 --- a/packages/playwright/src/reporters/internalReporter.ts +++ b/packages/playwright/src/reporters/internalReporter.ts @@ -23,7 +23,7 @@ import type { ReporterV2 } from './reporterV2'; import { monotonicTime } from 'playwright-core/lib/utils'; import { Multiplexer } from './multiplexer'; -export class InternalReporter { +export class InternalReporter implements ReporterV2 { private _reporter: ReporterV2; private _didBegin = false; private _config!: FullConfig; @@ -42,29 +42,29 @@ export class InternalReporter { this._config = config; this._startTime = new Date(); this._monotonicStartTime = monotonicTime(); - this._reporter.onConfigure(config); + this._reporter.onConfigure?.(config); } onBegin(suite: Suite) { this._didBegin = true; - this._reporter.onBegin(suite); + this._reporter.onBegin?.(suite); } onTestBegin(test: TestCase, result: TestResult) { - this._reporter.onTestBegin(test, result); + this._reporter.onTestBegin?.(test, result); } onStdOut(chunk: string | Buffer, test?: TestCase, result?: TestResult) { - this._reporter.onStdOut(chunk, test, result); + this._reporter.onStdOut?.(chunk, test, result); } onStdErr(chunk: string | Buffer, test?: TestCase, result?: TestResult) { - this._reporter.onStdErr(chunk, test, result); + this._reporter.onStdErr?.(chunk, test, result); } onTestEnd(test: TestCase, result: TestResult) { this._addSnippetToTestErrors(test, result); - this._reporter.onTestEnd(test, result); + this._reporter.onTestEnd?.(test, result); } async onEnd(result: { status: FullResult['status'] }) { @@ -72,7 +72,7 @@ export class InternalReporter { // onBegin was not reported, emit it. this.onBegin(new Suite('', 'root')); } - return await this._reporter.onEnd({ + return await this._reporter.onEnd?.({ ...result, startTime: this._startTime!, duration: monotonicTime() - this._monotonicStartTime!, @@ -80,25 +80,25 @@ export class InternalReporter { } async onExit() { - await this._reporter.onExit(); + await this._reporter.onExit?.(); } onError(error: TestError) { addLocationAndSnippetToError(this._config, error); - this._reporter.onError(error); + this._reporter.onError?.(error); } onStepBegin(test: TestCase, result: TestResult, step: TestStep) { - this._reporter.onStepBegin(test, result, step); + this._reporter.onStepBegin?.(test, result, step); } onStepEnd(test: TestCase, result: TestResult, step: TestStep) { this._addSnippetToStepError(test, step); - this._reporter.onStepEnd(test, result, step); + this._reporter.onStepEnd?.(test, result, step); } printsToStdio() { - return this._reporter.printsToStdio(); + return this._reporter.printsToStdio ? this._reporter.printsToStdio() : true; } private _addSnippetToTestErrors(test: TestCase, result: TestResult) { diff --git a/packages/playwright/src/reporters/json.ts b/packages/playwright/src/reporters/json.ts index 62a625db5d..e2b7ddf872 100644 --- a/packages/playwright/src/reporters/json.ts +++ b/packages/playwright/src/reporters/json.ts @@ -20,41 +20,44 @@ import type { FullConfig, TestCase, Suite, TestResult, TestError, TestStep, Full import { formatError, prepareErrorStack, resolveOutputFile } from './base'; import { MultiMap, toPosixPath } from 'playwright-core/lib/utils'; import { getProjectId } from '../common/config'; -import EmptyReporter from './empty'; +import type { ReporterV2 } from './reporterV2'; type JSONOptions = { outputFile?: string, configDir: string, }; -class JSONReporter extends EmptyReporter { +class JSONReporter implements ReporterV2 { config!: FullConfig; suite!: Suite; private _errors: TestError[] = []; private _resolvedOutputFile: string | undefined; constructor(options: JSONOptions) { - super(); this._resolvedOutputFile = resolveOutputFile('JSON', options)?.outputFile; } - override printsToStdio() { + version(): 'v2' { + return 'v2'; + } + + printsToStdio() { return !this._resolvedOutputFile; } - override onConfigure(config: FullConfig) { + onConfigure(config: FullConfig) { this.config = config; } - override onBegin(suite: Suite) { + onBegin(suite: Suite) { this.suite = suite; } - override onError(error: TestError): void { + onError(error: TestError): void { this._errors.push(error); } - override async onEnd(result: FullResult) { + async onEnd(result: FullResult) { await outputReport(this._serializeReport(result), this._resolvedOutputFile); } diff --git a/packages/playwright/src/reporters/junit.ts b/packages/playwright/src/reporters/junit.ts index 61cf7e8e99..befd652e4b 100644 --- a/packages/playwright/src/reporters/junit.ts +++ b/packages/playwright/src/reporters/junit.ts @@ -18,8 +18,8 @@ import fs from 'fs'; import path from 'path'; import type { FullConfig, FullResult, Suite, TestCase } from '../../types/testReporter'; import { formatFailure, resolveOutputFile, stripAnsiEscapes } from './base'; -import EmptyReporter from './empty'; import { getAsBooleanFromENV } from 'playwright-core/lib/utils'; +import type { ReporterV2 } from './reporterV2'; type JUnitOptions = { outputFile?: string, @@ -29,7 +29,7 @@ type JUnitOptions = { configDir: string, }; -class JUnitReporter extends EmptyReporter { +class JUnitReporter implements ReporterV2 { private config!: FullConfig; private configDir: string; private suite!: Suite; @@ -42,27 +42,30 @@ class JUnitReporter extends EmptyReporter { private includeProjectInTestName = false; constructor(options: JUnitOptions) { - super(); this.stripANSIControlSequences = getAsBooleanFromENV('PLAYWRIGHT_JUNIT_STRIP_ANSI', !!options.stripANSIControlSequences); this.includeProjectInTestName = getAsBooleanFromENV('PLAYWRIGHT_JUNIT_INCLUDE_PROJECT_IN_TEST_NAME', !!options.includeProjectInTestName); this.configDir = options.configDir; this.resolvedOutputFile = resolveOutputFile('JUNIT', options)?.outputFile; } - override printsToStdio() { + version(): 'v2' { + return 'v2'; + } + + printsToStdio() { return !this.resolvedOutputFile; } - override onConfigure(config: FullConfig) { + onConfigure(config: FullConfig) { this.config = config; } - override onBegin(suite: Suite) { + onBegin(suite: Suite) { this.suite = suite; this.timestamp = new Date(); } - override async onEnd(result: FullResult) { + async onEnd(result: FullResult) { const children: XMLEntry[] = []; for (const projectSuite of this.suite.suites) { for (const fileSuite of projectSuite.suites) diff --git a/packages/playwright/src/reporters/line.ts b/packages/playwright/src/reporters/line.ts index 7d875d0f31..af4c786e16 100644 --- a/packages/playwright/src/reporters/line.ts +++ b/packages/playwright/src/reporters/line.ts @@ -23,10 +23,6 @@ class LineReporter extends BaseReporter { private _lastTest: TestCase | undefined; private _didBegin = false; - override printsToStdio() { - return true; - } - override onBegin(suite: Suite) { super.onBegin(suite); const startingMessage = this.generateStartingMessage(); @@ -66,20 +62,17 @@ class LineReporter extends BaseReporter { console.log(); } - override onTestBegin(test: TestCase, result: TestResult) { - super.onTestBegin(test, result); + onTestBegin(test: TestCase, result: TestResult) { ++this._current; this._updateLine(test, result, undefined); } - override onStepBegin(test: TestCase, result: TestResult, step: TestStep) { - super.onStepBegin(test, result, step); + onStepBegin(test: TestCase, result: TestResult, step: TestStep) { if (step.category === 'test.step') this._updateLine(test, result, step); } - override onStepEnd(test: TestCase, result: TestResult, step: TestStep) { - super.onStepEnd(test, result, step); + onStepEnd(test: TestCase, result: TestResult, step: TestStep) { if (step.category === 'test.step') this._updateLine(test, result, step.parent); } diff --git a/packages/playwright/src/reporters/list.ts b/packages/playwright/src/reporters/list.ts index f87a7d4fe8..8704bfe104 100644 --- a/packages/playwright/src/reporters/list.ts +++ b/packages/playwright/src/reporters/list.ts @@ -39,10 +39,6 @@ class ListReporter extends BaseReporter { this._printSteps = getAsBooleanFromENV('PLAYWRIGHT_LIST_PRINT_STEPS', options.printSteps); } - override printsToStdio() { - return true; - } - override onBegin(suite: Suite) { super.onBegin(suite); const startingMessage = this.generateStartingMessage(); @@ -52,9 +48,7 @@ class ListReporter extends BaseReporter { } } - override onTestBegin(test: TestCase, result: TestResult) { - super.onTestBegin(test, result); - + onTestBegin(test: TestCase, result: TestResult) { const index = String(this._resultIndex.size + 1); this._resultIndex.set(result, index); @@ -88,8 +82,7 @@ class ListReporter extends BaseReporter { return stepIndex; } - override onStepBegin(test: TestCase, result: TestResult, step: TestStep) { - super.onStepBegin(test, result, step); + onStepBegin(test: TestCase, result: TestResult, step: TestStep) { if (step.category !== 'test.step') return; const testIndex = this._resultIndex.get(result) || ''; @@ -108,8 +101,7 @@ class ListReporter extends BaseReporter { } } - override onStepEnd(test: TestCase, result: TestResult, step: TestStep) { - super.onStepEnd(test, result, step); + onStepEnd(test: TestCase, result: TestResult, step: TestStep) { if (step.category !== 'test.step') return; diff --git a/packages/playwright/src/reporters/markdown.ts b/packages/playwright/src/reporters/markdown.ts index a32d7bda42..fe8c83cdd4 100644 --- a/packages/playwright/src/reporters/markdown.ts +++ b/packages/playwright/src/reporters/markdown.ts @@ -34,7 +34,7 @@ class MarkdownReporter extends BaseReporter { this._options = options; } - override printsToStdio() { + printsToStdio() { return false; } diff --git a/packages/playwright/src/reporters/multiplexer.ts b/packages/playwright/src/reporters/multiplexer.ts index bfd91f3350..b666128ab4 100644 --- a/packages/playwright/src/reporters/multiplexer.ts +++ b/packages/playwright/src/reporters/multiplexer.ts @@ -31,37 +31,37 @@ export class Multiplexer implements ReporterV2 { onConfigure(config: FullConfig) { for (const reporter of this._reporters) - wrap(() => reporter.onConfigure(config)); + wrap(() => reporter.onConfigure?.(config)); } onBegin(suite: Suite) { for (const reporter of this._reporters) - wrap(() => reporter.onBegin(suite)); + wrap(() => reporter.onBegin?.(suite)); } onTestBegin(test: TestCase, result: TestResult) { for (const reporter of this._reporters) - wrap(() => reporter.onTestBegin(test, result)); + wrap(() => reporter.onTestBegin?.(test, result)); } onStdOut(chunk: string | Buffer, test?: TestCase, result?: TestResult) { for (const reporter of this._reporters) - wrap(() => reporter.onStdOut(chunk, test, result)); + wrap(() => reporter.onStdOut?.(chunk, test, result)); } onStdErr(chunk: string | Buffer, test?: TestCase, result?: TestResult) { for (const reporter of this._reporters) - wrap(() => reporter.onStdErr(chunk, test, result)); + wrap(() => reporter.onStdErr?.(chunk, test, result)); } onTestEnd(test: TestCase, result: TestResult) { for (const reporter of this._reporters) - wrap(() => reporter.onTestEnd(test, result)); + wrap(() => reporter.onTestEnd?.(test, result)); } async onEnd(result: FullResult) { for (const reporter of this._reporters) { - const outResult = await wrapAsync(() => reporter.onEnd(result)); + const outResult = await wrapAsync(() => reporter.onEnd?.(result)); if (outResult?.status) result.status = outResult.status; } @@ -70,28 +70,28 @@ export class Multiplexer implements ReporterV2 { async onExit() { for (const reporter of this._reporters) - await wrapAsync(() => reporter.onExit()); + await wrapAsync(() => reporter.onExit?.()); } onError(error: TestError) { for (const reporter of this._reporters) - wrap(() => reporter.onError(error)); + wrap(() => reporter.onError?.(error)); } onStepBegin(test: TestCase, result: TestResult, step: TestStep) { for (const reporter of this._reporters) - wrap(() => reporter.onStepBegin(test, result, step)); + wrap(() => reporter.onStepBegin?.(test, result, step)); } onStepEnd(test: TestCase, result: TestResult, step: TestStep) { for (const reporter of this._reporters) - wrap(() => reporter.onStepEnd(test, result, step)); + wrap(() => reporter.onStepEnd?.(test, result, step)); } printsToStdio(): boolean { return this._reporters.some(r => { - let prints = true; - wrap(() => prints = r.printsToStdio()); + let prints = false; + wrap(() => prints = r.printsToStdio ? r.printsToStdio() : true); return prints; }); } diff --git a/packages/playwright/src/reporters/reporterV2.ts b/packages/playwright/src/reporters/reporterV2.ts index 3d640f97c3..2cdffdfe12 100644 --- a/packages/playwright/src/reporters/reporterV2.ts +++ b/packages/playwright/src/reporters/reporterV2.ts @@ -17,18 +17,18 @@ import type { FullConfig, TestCase, TestError, TestResult, FullResult, TestStep, Reporter, Suite } from '../../types/testReporter'; export interface ReporterV2 { - onConfigure(config: FullConfig): void; - onBegin(suite: Suite): void; - onTestBegin(test: TestCase, result: TestResult): void; - onStdOut(chunk: string | Buffer, test?: TestCase, result?: TestResult): void; - onStdErr(chunk: string | Buffer, test?: TestCase, result?: TestResult): void; - onTestEnd(test: TestCase, result: TestResult): void; - onEnd(result: FullResult): Promise<{ status?: FullResult['status'] } | undefined | void> | void; - onExit(): void | Promise; - onError(error: TestError): void; - onStepBegin(test: TestCase, result: TestResult, step: TestStep): void; - onStepEnd(test: TestCase, result: TestResult, step: TestStep): void; - printsToStdio(): boolean; + onConfigure?(config: FullConfig): void; + onBegin?(suite: Suite): void; + onTestBegin?(test: TestCase, result: TestResult): void; + onStdOut?(chunk: string | Buffer, test?: TestCase, result?: TestResult): void; + onStdErr?(chunk: string | Buffer, test?: TestCase, result?: TestResult): void; + onTestEnd?(test: TestCase, result: TestResult): void; + onEnd?(result: FullResult): Promise<{ status?: FullResult['status'] } | undefined | void> | void; + onExit?(): void | Promise; + onError?(error: TestError): void; + onStepBegin?(test: TestCase, result: TestResult, step: TestStep): void; + onStepEnd?(test: TestCase, result: TestResult, step: TestStep): void; + printsToStdio?(): boolean; version(): 'v2'; } diff --git a/packages/playwright/src/reporters/teleEmitter.ts b/packages/playwright/src/reporters/teleEmitter.ts index 670a8c16c8..f56178114d 100644 --- a/packages/playwright/src/reporters/teleEmitter.ts +++ b/packages/playwright/src/reporters/teleEmitter.ts @@ -145,9 +145,6 @@ export class TeleReporterEmitter implements ReporterV2 { }); } - async onExit() { - } - printsToStdio() { return false; } diff --git a/packages/playwright/src/runner/dispatcher.ts b/packages/playwright/src/runner/dispatcher.ts index ad44ce453e..4e971f2475 100644 --- a/packages/playwright/src/runner/dispatcher.ts +++ b/packages/playwright/src/runner/dispatcher.ts @@ -198,17 +198,17 @@ export class Dispatcher { worker.on('stdOut', (params: TestOutputPayload) => { const { chunk, test, result } = handleOutput(params); result?.stdout.push(chunk); - this._reporter.onStdOut(chunk, test, result); + this._reporter.onStdOut?.(chunk, test, result); }); worker.on('stdErr', (params: TestOutputPayload) => { const { chunk, test, result } = handleOutput(params); result?.stderr.push(chunk); - this._reporter.onStdErr(chunk, test, result); + this._reporter.onStdErr?.(chunk, test, result); }); worker.on('teardownErrors', (params: TeardownErrorsPayload) => { this._failureTracker.onWorkerError(); for (const error of params.fatalErrors) - this._reporter.onError(error); + this._reporter.onError?.(error); }); worker.on('exit', () => { const producedEnv = this._producedEnvByProjectId.get(testGroup.projectId) || {}; @@ -257,7 +257,7 @@ class JobDispatcher { result.parallelIndex = this._parallelIndex; result.workerIndex = this._workerIndex; result.startTime = new Date(params.startWallTime); - this._reporter.onTestBegin(test, result); + this._reporter.onTestBegin?.(test, result); this._currentlyRunning = { test, result }; } @@ -323,7 +323,7 @@ class JobDispatcher { }; steps.set(params.stepId, step); (parentStep || result).steps.push(step); - this._reporter.onStepBegin(test, result, step); + this._reporter.onStepBegin?.(test, result, step); } private _onStepEnd(params: StepEndPayload) { @@ -335,14 +335,14 @@ class JobDispatcher { const { result, steps, test } = data; const step = steps.get(params.stepId); if (!step) { - this._reporter.onStdErr('Internal error: step end without step begin: ' + params.stepId, test, result); + this._reporter.onStdErr?.('Internal error: step end without step begin: ' + params.stepId, test, result); return; } step.duration = params.wallTime - step.startTime.getTime(); if (params.error) step.error = params.error; steps.delete(params.stepId); - this._reporter.onStepEnd(test, result, step); + this._reporter.onStepEnd?.(test, result, step); } private _onAttach(params: AttachmentPayload) { @@ -368,7 +368,7 @@ class JobDispatcher { result = runData.result; } else { result = test._appendTestResult(); - this._reporter.onTestBegin(test, result); + this._reporter.onTestBegin?.(test, result); } result.errors = [...errors]; result.error = result.errors[0]; @@ -392,7 +392,7 @@ class JobDispatcher { // Let's just fail the test run. this._failureTracker.onWorkerError(); for (const error of errors) - this._reporter.onError(error); + this._reporter.onError?.(error); } } @@ -526,7 +526,7 @@ class JobDispatcher { if (allTestsSkipped && !this._failureTracker.hasReachedMaxFailures()) { for (const test of this._job.tests) { const result = test._appendTestResult(); - this._reporter.onTestBegin(test, result); + this._reporter.onTestBegin?.(test, result); result.status = 'skipped'; this._reportTestEnd(test, result); } @@ -540,13 +540,13 @@ class JobDispatcher { } private _reportTestEnd(test: TestCase, result: TestResult) { - this._reporter.onTestEnd(test, result); + this._reporter.onTestEnd?.(test, result); const hadMaxFailures = this._failureTracker.hasReachedMaxFailures(); this._failureTracker.onTestEnd(test, result); if (this._failureTracker.hasReachedMaxFailures()) { this._stopCallback(); if (!hadMaxFailures) - this._reporter.onError({ message: colors.red(`Testing stopped early after ${this._failureTracker.maxFailures()} maximum allowed failures.`) }); + this._reporter.onError?.({ message: colors.red(`Testing stopped early after ${this._failureTracker.maxFailures()} maximum allowed failures.`) }); } } } diff --git a/packages/playwright/src/runner/reporters.ts b/packages/playwright/src/runner/reporters.ts index 4a2b3f970e..2f7b16f2a6 100644 --- a/packages/playwright/src/runner/reporters.ts +++ b/packages/playwright/src/runner/reporters.ts @@ -67,7 +67,7 @@ export async function createReporters(config: FullConfigInternal, mode: 'list' | reporters.push(wrapReporterAsV2(new reporterConstructor(runOptions))); } - const someReporterPrintsToStdio = reporters.some(r => r.printsToStdio()); + const someReporterPrintsToStdio = reporters.some(r => r.printsToStdio ? r.printsToStdio() : true); if (reporters.length && !someReporterPrintsToStdio) { // Add a line/dot/list-mode reporter for convenience. // Important to put it first, just in case some other reporter stalls onEnd. @@ -92,16 +92,15 @@ interface ErrorCollectingReporter extends ReporterV2 { export function createErrorCollectingReporter(writeToConsole?: boolean): ErrorCollectingReporter { const errors: TestError[] = []; - const reporterV2 = wrapReporterAsV2({ + return { + version: () => 'v2', onError(error: TestError) { errors.push(error); if (writeToConsole) process.stdout.write(formatError(error, colors.enabled).message + '\n'); - } - }); - const reporter = reporterV2 as ErrorCollectingReporter; - reporter.errors = () => errors; - return reporter; + }, + errors: () => errors, + }; } function reporterOptions(config: FullConfigInternal, mode: 'list' | 'test' | 'merge', isTestServer: boolean) { @@ -132,14 +131,18 @@ function computeCommandHash(config: FullConfigInternal) { return parts.join('-'); } -class ListModeReporter extends EmptyReporter { +class ListModeReporter implements ReporterV2 { private config!: FullConfig; - override onConfigure(config: FullConfig) { + version(): 'v2' { + return 'v2'; + } + + onConfigure(config: FullConfig) { this.config = config; } - override onBegin(suite: Suite): void { + onBegin(suite: Suite): void { // eslint-disable-next-line no-console console.log(`Listing tests:`); const tests = suite.allTests(); @@ -157,12 +160,8 @@ class ListModeReporter extends EmptyReporter { console.log(`Total: ${tests.length} ${tests.length === 1 ? 'test' : 'tests'} in ${files.size} ${files.size === 1 ? 'file' : 'files'}`); } - override onError(error: TestError) { + onError(error: TestError) { // eslint-disable-next-line no-console console.error('\n' + formatError(error, false).message); } - - override printsToStdio(): boolean { - return true; - } } diff --git a/packages/playwright/src/runner/tasks.ts b/packages/playwright/src/runner/tasks.ts index 6b8c9f7464..8281cc3d39 100644 --- a/packages/playwright/src/runner/tasks.ts +++ b/packages/playwright/src/runner/tasks.ts @@ -159,7 +159,7 @@ export function createTaskRunnerForClearCache(config: FullConfigInternal, report function createReportBeginTask(): Task { return { setup: async (reporter, { rootSuite }) => { - reporter.onBegin(rootSuite!); + reporter.onBegin?.(rootSuite!); }, teardown: async ({}) => {}, }; diff --git a/packages/trace-viewer/src/ui/uiModeTraceView.tsx b/packages/trace-viewer/src/ui/uiModeTraceView.tsx index 8027005812..48fd59e3ca 100644 --- a/packages/trace-viewer/src/ui/uiModeTraceView.tsx +++ b/packages/trace-viewer/src/ui/uiModeTraceView.tsx @@ -91,7 +91,7 @@ export const TraceView: React.FC<{ if (pollTimer.current) clearTimeout(pollTimer.current); }; - }, [outputDir, item, setModel, counter, setCounter]); + }, [outputDir, item, setModel, counter, setCounter, pathSeparator]); return