diff --git a/packages/playwright/src/isomorphic/teleReceiver.ts b/packages/playwright/src/isomorphic/teleReceiver.ts index d2cc5e5cd8413..da377b099fc17 100644 --- a/packages/playwright/src/isomorphic/teleReceiver.ts +++ b/packages/playwright/src/isomorphic/teleReceiver.ts @@ -220,7 +220,7 @@ export class TeleReporterReceiver { private _onTestBegin(testId: string, payload: JsonTestResultStart) { const test = this._tests.get(testId)!; if (this._options.clearPreviousResultsWhenTestBegins) - test._clearResults(); + test.results = []; const testResult = test._createTestResult(payload.id); testResult.retry = payload.retry; testResult.workerIndex = payload.workerIndex; @@ -234,7 +234,7 @@ export class TeleReporterReceiver { test.timeout = testEndPayload.timeout; test.expectedStatus = testEndPayload.expectedStatus; test.annotations = testEndPayload.annotations; - const result = test._resultsMap.get(payload.id)!; + const result = test.results.find(r => r._id === payload.id)!; result.duration = payload.duration; result.status = payload.status; result.errors = payload.errors; @@ -247,7 +247,7 @@ export class TeleReporterReceiver { private _onStepBegin(testId: string, resultId: string, payload: JsonTestStepStart) { const test = this._tests.get(testId)!; - const result = test._resultsMap.get(resultId)!; + const result = test.results.find(r => r._id === resultId)!; const parentStep = payload.parentStepId ? result._stepMap.get(payload.parentStepId) : undefined; const location = this._absoluteLocation(payload.location); @@ -262,7 +262,7 @@ export class TeleReporterReceiver { private _onStepEnd(testId: string, resultId: string, payload: JsonTestStepEnd) { const test = this._tests.get(testId)!; - const result = test._resultsMap.get(resultId)!; + const result = test.results.find(r => r._id === resultId)!; const step = result._stepMap.get(payload.id)!; step.duration = payload.duration; step.error = payload.error; @@ -276,7 +276,7 @@ export class TeleReporterReceiver { private _onStdIO(type: JsonStdIOType, testId: string | undefined, resultId: string | undefined, data: string, isBase64: boolean) { const chunk = isBase64 ? ((globalThis as any).Buffer ? Buffer.from(data, 'base64') : atob(data)) : data; const test = testId ? this._tests.get(testId) : undefined; - const result = test && resultId ? test._resultsMap.get(resultId) : undefined; + const result = test && resultId ? test.results.find(r => r._id === resultId) : undefined; if (type === 'stdout') { result?.stdout.push(chunk); this._reporter.onStdOut?.(chunk, test, result); @@ -478,8 +478,6 @@ export class TeleTestCase implements reporterTypes.TestCase { repeatEachIndex = 0; id: string; - _resultsMap = new Map(); - constructor(id: string, title: string, location: reporterTypes.Location, repeatEachIndex: number) { this.id = id; this.title = title; @@ -502,20 +500,9 @@ export class TeleTestCase implements reporterTypes.TestCase { return status === 'expected' || status === 'flaky' || status === 'skipped'; } - _clearResults() { - this.results = []; - this._resultsMap.clear(); - } - - _restoreResults(snapshot: Map) { - this.results = [...snapshot.values()]; - this._resultsMap = snapshot; - } - _createTestResult(id: string): TeleTestResult { - const result = new TeleTestResult(this.results.length); + const result = new TeleTestResult(this.results.length, id); this.results.push(result); - this._resultsMap.set(id, result); return result; } } @@ -566,11 +553,13 @@ export class TeleTestResult implements reporterTypes.TestResult { error: reporterTypes.TestResult['error']; _stepMap: Map = new Map(); + _id: string; private _startTime: number = 0; - constructor(retry: number) { + constructor(retry: number, id: string) { this.retry = retry; + this._id = id; } setStartTimeNumber(startTime: number) { diff --git a/packages/trace-viewer/src/ui/teleSuiteUpdater.ts b/packages/trace-viewer/src/ui/teleSuiteUpdater.ts index a2fbb4e39a02e..0d448ea172364 100644 --- a/packages/trace-viewer/src/ui/teleSuiteUpdater.ts +++ b/packages/trace-viewer/src/ui/teleSuiteUpdater.ts @@ -15,7 +15,6 @@ */ import { TeleReporterReceiver, TeleSuite } from '@testIsomorphic/teleReceiver'; -import type { TeleTestCase, TeleTestResult } from '@testIsomorphic/teleReceiver'; import { statusEx } from '@testIsomorphic/testTree'; import type { ReporterV2 } from 'playwright/src/reporters/reporterV2'; import type * as reporterTypes from 'playwright/types/testReporter'; @@ -42,7 +41,7 @@ export class TeleSuiteUpdater { private _lastRunReceiver: TeleReporterReceiver | undefined; private _lastRunTestCount = 0; private _options: TeleSuiteUpdaterOptions; - private _testResultsSnapshot: Map> | undefined; + private _testResultsSnapshot: Map | undefined; constructor(options: TeleSuiteUpdaterOptions) { this._receiver = new TeleReporterReceiver(this._createReporter(), { @@ -79,13 +78,11 @@ export class TeleSuiteUpdater { onBegin: (suite: reporterTypes.Suite) => { if (!this.rootSuite) this.rootSuite = suite as TeleSuite; - // As soon as new test tree is built add previous results. + // As soon as new test tree is built add previous results, before calling onUpdate + // to avoid flashing empty results in the UI. if (this._testResultsSnapshot) { - (this.rootSuite.allTests() as TeleTestCase[]).forEach(test => { - const results = this._testResultsSnapshot!.get(test.id); - if (results) - test._restoreResults(results); - }); + for (const test of this.rootSuite.allTests()) + test.results = this._testResultsSnapshot?.get(test.id) || test.results; this._testResultsSnapshot = undefined; } this.progress.total = this._lastRunTestCount; @@ -143,8 +140,8 @@ export class TeleSuiteUpdater { processListReport(report: any[]) { // Save test results and reset all projects, the results will be restored after // new project structure is built. - if (this.rootSuite) - this._testResultsSnapshot = new Map((this.rootSuite.allTests() as TeleTestCase[]).map(test => [test.id, test._resultsMap])); + const tests = this.rootSuite?.allTests() || []; + this._testResultsSnapshot = new Map(tests.map(test => [test.id, test.results])); this._receiver.reset(); for (const message of report) this._receiver.dispatch(message); diff --git a/packages/trace-viewer/src/ui/uiModeView.tsx b/packages/trace-viewer/src/ui/uiModeView.tsx index 93ae4d9577c94..9c067dbc8924b 100644 --- a/packages/trace-viewer/src/ui/uiModeView.tsx +++ b/packages/trace-viewer/src/ui/uiModeView.tsx @@ -261,7 +261,7 @@ export const UIModeView: React.FC<{}> = ({ { for (const test of testModel.rootSuite?.allTests() || []) { if (testIds.has(test.id)) { - (test as TeleTestCase)._clearResults(); + test.results = []; const result = (test as TeleTestCase)._createTestResult('pending'); (result as any)[statusEx] = 'scheduled'; } @@ -289,7 +289,7 @@ export const UIModeView: React.FC<{}> = ({ // Clear pending tests in case of interrupt. for (const test of testModel.rootSuite?.allTests() || []) { if (test.results[0]?.duration === -1) - (test as TeleTestCase)._clearResults(); + test.results = []; } setTestModel({ ...testModel }); setRunningState(undefined);