chore: split InternalReporter and Multiplexer (#22671)
The multiplexer will be reused in the blob report merger.
This commit is contained in:
parent
e809ecdc5d
commit
51aca72c35
|
|
@ -15,11 +15,11 @@
|
|||
*/
|
||||
|
||||
import type { FullConfig, Suite } from '../../types/testReporter';
|
||||
import type { Multiplexer } from '../reporters/multiplexer';
|
||||
import type { InternalReporter } from '../reporters/internalReporter';
|
||||
|
||||
export interface TestRunnerPlugin {
|
||||
name: string;
|
||||
setup?(config: FullConfig, configDir: string, reporter: Multiplexer): Promise<void>;
|
||||
setup?(config: FullConfig, configDir: string, reporter: InternalReporter): Promise<void>;
|
||||
babelPlugins?(): Promise<[string, any?][]>;
|
||||
begin?(suite: Suite): Promise<void>;
|
||||
end?(): Promise<void>;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import type { FullConfig } from '../../types/testReporter';
|
|||
import type { TestRunnerPlugin } from '.';
|
||||
import type { FullConfigInternal } from '../common/config';
|
||||
import { envWithoutExperimentalLoaderOptions } from '../util';
|
||||
import type { Multiplexer } from '../reporters/multiplexer';
|
||||
import type { InternalReporter } from '../reporters/internalReporter';
|
||||
|
||||
|
||||
export type WebServerPluginOptions = {
|
||||
|
|
@ -49,7 +49,7 @@ export class WebServerPlugin implements TestRunnerPlugin {
|
|||
private _processExitedPromise!: Promise<any>;
|
||||
private _options: WebServerPluginOptions;
|
||||
private _checkPortOnly: boolean;
|
||||
private _reporter?: Multiplexer;
|
||||
private _reporter?: InternalReporter;
|
||||
name = 'playwright:webserver';
|
||||
|
||||
constructor(options: WebServerPluginOptions, checkPortOnly: boolean) {
|
||||
|
|
@ -57,7 +57,7 @@ export class WebServerPlugin implements TestRunnerPlugin {
|
|||
this._checkPortOnly = checkPortOnly;
|
||||
}
|
||||
|
||||
public async setup(config: FullConfig, configDir: string, reporter: Multiplexer) {
|
||||
public async setup(config: FullConfig, configDir: string, reporter: InternalReporter) {
|
||||
this._reporter = reporter;
|
||||
this._isAvailable = getIsAvailableFunction(this._options.url, this._checkPortOnly, !!this._options.ignoreHTTPSErrors, this._reporter.onStdErr?.bind(this._reporter));
|
||||
this._options.cwd = this._options.cwd ? path.resolve(configDir, this._options.cwd) : configDir;
|
||||
|
|
@ -148,7 +148,7 @@ async function isPortUsed(port: number): Promise<boolean> {
|
|||
return await innerIsPortUsed('127.0.0.1') || await innerIsPortUsed('::1');
|
||||
}
|
||||
|
||||
async function isURLAvailable(url: URL, ignoreHTTPSErrors: boolean, onStdErr: Multiplexer['onStdErr']) {
|
||||
async function isURLAvailable(url: URL, ignoreHTTPSErrors: boolean, onStdErr: InternalReporter['onStdErr']) {
|
||||
let statusCode = await httpStatusCode(url, ignoreHTTPSErrors, onStdErr);
|
||||
if (statusCode === 404 && url.pathname === '/') {
|
||||
const indexUrl = new URL(url);
|
||||
|
|
@ -158,7 +158,7 @@ async function isURLAvailable(url: URL, ignoreHTTPSErrors: boolean, onStdErr: Mu
|
|||
return statusCode >= 200 && statusCode < 404;
|
||||
}
|
||||
|
||||
async function httpStatusCode(url: URL, ignoreHTTPSErrors: boolean, onStdErr: Multiplexer['onStdErr']): Promise<number> {
|
||||
async function httpStatusCode(url: URL, ignoreHTTPSErrors: boolean, onStdErr: InternalReporter['onStdErr']): Promise<number> {
|
||||
return new Promise(resolve => {
|
||||
debugWebServer(`HTTP GET: ${url}`);
|
||||
httpRequest({
|
||||
|
|
@ -191,7 +191,7 @@ async function waitFor(waitFn: () => Promise<boolean>, cancellationToken: { canc
|
|||
}
|
||||
}
|
||||
|
||||
function getIsAvailableFunction(url: string, checkPortOnly: boolean, ignoreHTTPSErrors: boolean, onStdErr: Multiplexer['onStdErr']) {
|
||||
function getIsAvailableFunction(url: string, checkPortOnly: boolean, ignoreHTTPSErrors: boolean, onStdErr: InternalReporter['onStdErr']) {
|
||||
const urlObject = new URL(url);
|
||||
if (!checkPortOnly)
|
||||
return () => isURLAvailable(urlObject, ignoreHTTPSErrors, onStdErr);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,121 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { FullConfig, TestCase, TestError, TestResult, FullResult, TestStep, Reporter } from '../../types/testReporter';
|
||||
import { Suite } from '../common/test';
|
||||
import type { FullConfigInternal } from '../common/config';
|
||||
import { addSnippetToError } from './base';
|
||||
import { Multiplexer } from './multiplexer';
|
||||
|
||||
type StdIOChunk = {
|
||||
chunk: string | Buffer;
|
||||
test?: TestCase;
|
||||
result?: TestResult;
|
||||
};
|
||||
|
||||
export class InternalReporter {
|
||||
private _multiplexer: Multiplexer;
|
||||
private _deferred: { error?: TestError, stdout?: StdIOChunk, stderr?: StdIOChunk }[] | null = [];
|
||||
private _config!: FullConfigInternal;
|
||||
|
||||
constructor(reporters: Reporter[]) {
|
||||
this._multiplexer = new Multiplexer(reporters);
|
||||
}
|
||||
|
||||
onConfigure(config: FullConfigInternal) {
|
||||
this._config = config;
|
||||
}
|
||||
|
||||
onBegin(config: FullConfig, suite: Suite) {
|
||||
this._multiplexer.onBegin(config, suite);
|
||||
|
||||
const deferred = this._deferred!;
|
||||
this._deferred = null;
|
||||
for (const item of deferred) {
|
||||
if (item.error)
|
||||
this.onError(item.error);
|
||||
if (item.stdout)
|
||||
this.onStdOut(item.stdout.chunk, item.stdout.test, item.stdout.result);
|
||||
if (item.stderr)
|
||||
this.onStdErr(item.stderr.chunk, item.stderr.test, item.stderr.result);
|
||||
}
|
||||
}
|
||||
|
||||
onTestBegin(test: TestCase, result: TestResult) {
|
||||
this._multiplexer.onTestBegin(test, result);
|
||||
}
|
||||
|
||||
onStdOut(chunk: string | Buffer, test?: TestCase, result?: TestResult) {
|
||||
if (this._deferred) {
|
||||
this._deferred.push({ stdout: { chunk, test, result } });
|
||||
return;
|
||||
}
|
||||
this._multiplexer.onStdOut(chunk, test, result);
|
||||
}
|
||||
|
||||
onStdErr(chunk: string | Buffer, test?: TestCase, result?: TestResult) {
|
||||
if (this._deferred) {
|
||||
this._deferred.push({ stderr: { chunk, test, result } });
|
||||
return;
|
||||
}
|
||||
|
||||
this._multiplexer.onStdErr(chunk, test, result);
|
||||
}
|
||||
|
||||
onTestEnd(test: TestCase, result: TestResult) {
|
||||
this._addSnippetToTestErrors(test, result);
|
||||
this._multiplexer.onTestEnd(test, result);
|
||||
}
|
||||
|
||||
async onEnd() { }
|
||||
|
||||
async onExit(result: FullResult) {
|
||||
if (this._deferred) {
|
||||
// onBegin was not reported, emit it.
|
||||
this.onBegin(this._config.config, new Suite('', 'root'));
|
||||
}
|
||||
await this._multiplexer.onEnd(result);
|
||||
await this._multiplexer.onExit();
|
||||
}
|
||||
|
||||
onError(error: TestError) {
|
||||
if (this._deferred) {
|
||||
this._deferred.push({ error });
|
||||
return;
|
||||
}
|
||||
addSnippetToError(this._config.config, error);
|
||||
this._multiplexer.onError(error);
|
||||
}
|
||||
|
||||
onStepBegin(test: TestCase, result: TestResult, step: TestStep) {
|
||||
this._multiplexer.onStepBegin(test, result, step);
|
||||
}
|
||||
|
||||
onStepEnd(test: TestCase, result: TestResult, step: TestStep) {
|
||||
this._addSnippetToStepError(test, step);
|
||||
this._multiplexer.onStepEnd(test, result, step);
|
||||
}
|
||||
|
||||
private _addSnippetToTestErrors(test: TestCase, result: TestResult) {
|
||||
for (const error of result.errors)
|
||||
addSnippetToError(this._config.config, error, test.location.file);
|
||||
}
|
||||
|
||||
private _addSnippetToStepError(test: TestCase, step: TestStep) {
|
||||
if (step.error)
|
||||
addSnippetToError(this._config.config, step.error, test.location.file);
|
||||
}
|
||||
}
|
||||
|
|
@ -15,47 +15,18 @@
|
|||
*/
|
||||
|
||||
import type { FullConfig, TestCase, TestError, TestResult, FullResult, TestStep, Reporter } from '../../types/testReporter';
|
||||
import { Suite } from '../common/test';
|
||||
import type { FullConfigInternal } from '../common/config';
|
||||
import { addSnippetToError } from './base';
|
||||
import type { Suite } from '../common/test';
|
||||
|
||||
type StdIOChunk = {
|
||||
chunk: string | Buffer;
|
||||
test?: TestCase;
|
||||
result?: TestResult;
|
||||
};
|
||||
|
||||
export class Multiplexer {
|
||||
export class Multiplexer implements Reporter {
|
||||
private _reporters: Reporter[];
|
||||
private _deferred: { error?: TestError, stdout?: StdIOChunk, stderr?: StdIOChunk }[] | null = [];
|
||||
private _config!: FullConfigInternal;
|
||||
|
||||
constructor(reporters: Reporter[]) {
|
||||
this._reporters = reporters;
|
||||
}
|
||||
|
||||
printsToStdio() {
|
||||
return this._reporters.some(r => r.printsToStdio ? r.printsToStdio() : true);
|
||||
}
|
||||
|
||||
onConfigure(config: FullConfigInternal) {
|
||||
this._config = config;
|
||||
}
|
||||
|
||||
onBegin(config: FullConfig, suite: Suite) {
|
||||
for (const reporter of this._reporters)
|
||||
wrap(() => reporter.onBegin?.(config, suite));
|
||||
|
||||
const deferred = this._deferred!;
|
||||
this._deferred = null;
|
||||
for (const item of deferred) {
|
||||
if (item.error)
|
||||
this.onError(item.error);
|
||||
if (item.stdout)
|
||||
this.onStdOut(item.stdout.chunk, item.stdout.test, item.stdout.result);
|
||||
if (item.stderr)
|
||||
this.onStdErr(item.stderr.chunk, item.stderr.test, item.stderr.result);
|
||||
}
|
||||
}
|
||||
|
||||
onTestBegin(test: TestCase, result: TestResult) {
|
||||
|
|
@ -64,76 +35,52 @@ export class Multiplexer {
|
|||
}
|
||||
|
||||
onStdOut(chunk: string | Buffer, test?: TestCase, result?: TestResult) {
|
||||
if (this._deferred) {
|
||||
this._deferred.push({ stdout: { chunk, test, result } });
|
||||
return;
|
||||
}
|
||||
for (const reporter of this._reporters)
|
||||
wrap(() => reporter.onStdOut?.(chunk, test, result));
|
||||
}
|
||||
|
||||
onStdErr(chunk: string | Buffer, test?: TestCase, result?: TestResult) {
|
||||
if (this._deferred) {
|
||||
this._deferred.push({ stderr: { chunk, test, result } });
|
||||
return;
|
||||
}
|
||||
|
||||
for (const reporter of this._reporters)
|
||||
wrap(() => reporter.onStdErr?.(chunk, test, result));
|
||||
}
|
||||
|
||||
onTestEnd(test: TestCase, result: TestResult) {
|
||||
this._addSnippetToTestErrors(test, result);
|
||||
for (const reporter of this._reporters)
|
||||
wrap(() => reporter.onTestEnd?.(test, result));
|
||||
}
|
||||
|
||||
async onEnd() { }
|
||||
|
||||
async onExit(result: FullResult) {
|
||||
if (this._deferred) {
|
||||
// onBegin was not reported, emit it.
|
||||
this.onBegin(this._config.config, new Suite('', 'root'));
|
||||
}
|
||||
|
||||
async onEnd(result: FullResult) {
|
||||
for (const reporter of this._reporters)
|
||||
await Promise.resolve().then(() => reporter.onEnd?.(result)).catch(e => console.error('Error in reporter', e));
|
||||
await wrapAsync(() => reporter.onEnd?.(result));
|
||||
}
|
||||
|
||||
async onExit() {
|
||||
for (const reporter of this._reporters)
|
||||
await Promise.resolve().then(() => reporter.onExit?.()).catch(e => console.error('Error in reporter', e));
|
||||
await wrapAsync(() => reporter.onExit?.());
|
||||
}
|
||||
|
||||
onError(error: TestError) {
|
||||
if (this._deferred) {
|
||||
this._deferred.push({ error });
|
||||
return;
|
||||
}
|
||||
addSnippetToError(this._config.config, error);
|
||||
for (const reporter of this._reporters)
|
||||
wrap(() => reporter.onError?.(error));
|
||||
}
|
||||
|
||||
onStepBegin(test: TestCase, result: TestResult, step: TestStep) {
|
||||
for (const reporter of this._reporters)
|
||||
wrap(() => (reporter as any).onStepBegin?.(test, result, step));
|
||||
wrap(() => reporter.onStepBegin?.(test, result, step));
|
||||
}
|
||||
|
||||
onStepEnd(test: TestCase, result: TestResult, step: TestStep) {
|
||||
this._addSnippetToStepError(test, step);
|
||||
for (const reporter of this._reporters)
|
||||
wrap(() => (reporter as any).onStepEnd?.(test, result, step));
|
||||
wrap(() => reporter.onStepEnd?.(test, result, step));
|
||||
}
|
||||
}
|
||||
|
||||
private _addSnippetToTestErrors(test: TestCase, result: TestResult) {
|
||||
for (const error of result.errors)
|
||||
addSnippetToError(this._config.config, error, test.location.file);
|
||||
async function wrapAsync(callback: () => void | Promise<void>) {
|
||||
try {
|
||||
await callback();
|
||||
} catch (e) {
|
||||
console.error('Error in reporter', e);
|
||||
}
|
||||
|
||||
private _addSnippetToStepError(test: TestCase, step: TestStep) {
|
||||
if (step.error)
|
||||
addSnippetToError(this._config.config, step.error, test.location.file);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function wrap(callback: () => void) {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import { ManualPromise } from 'playwright-core/lib/utils';
|
|||
import { WorkerHost } from './workerHost';
|
||||
import type { TestGroup } from './testGroups';
|
||||
import type { FullConfigInternal } from '../common/config';
|
||||
import type { Multiplexer } from '../reporters/multiplexer';
|
||||
import type { InternalReporter } from '../reporters/internalReporter';
|
||||
|
||||
type TestResultData = {
|
||||
result: TestResult;
|
||||
|
|
@ -46,14 +46,14 @@ export class Dispatcher {
|
|||
|
||||
private _testById = new Map<string, TestData>();
|
||||
private _config: FullConfigInternal;
|
||||
private _reporter: Multiplexer;
|
||||
private _reporter: InternalReporter;
|
||||
private _hasWorkerErrors = false;
|
||||
private _failureCount = 0;
|
||||
|
||||
private _extraEnvByProjectId: EnvByProjectId = new Map();
|
||||
private _producedEnvByProjectId: EnvByProjectId = new Map();
|
||||
|
||||
constructor(config: FullConfigInternal, reporter: Multiplexer) {
|
||||
constructor(config: FullConfigInternal, reporter: InternalReporter) {
|
||||
this._config = config;
|
||||
this._reporter = reporter;
|
||||
}
|
||||
|
|
@ -75,7 +75,7 @@ export class Dispatcher {
|
|||
for (const test of group.tests) {
|
||||
const result = test._appendTestResult();
|
||||
result.status = 'skipped';
|
||||
this._reporter.onTestBegin?.(test, result);
|
||||
this._reporter.onTestBegin(test, result);
|
||||
test.annotations = [...test._staticAnnotations];
|
||||
this._reportTestEnd(test, result);
|
||||
}
|
||||
|
|
@ -222,7 +222,7 @@ export class Dispatcher {
|
|||
result.parallelIndex = worker.parallelIndex;
|
||||
result.workerIndex = worker.workerIndex;
|
||||
result.startTime = new Date(params.startWallTime);
|
||||
this._reporter.onTestBegin?.(data.test, result);
|
||||
this._reporter.onTestBegin(data.test, result);
|
||||
worker.currentTestId = params.testId;
|
||||
};
|
||||
worker.addListener('testBegin', onTestBegin);
|
||||
|
|
@ -284,7 +284,7 @@ export class Dispatcher {
|
|||
};
|
||||
steps.set(params.stepId, step);
|
||||
(parentStep || result).steps.push(step);
|
||||
this._reporter.onStepBegin?.(data.test, result, step);
|
||||
this._reporter.onStepBegin(data.test, result, step);
|
||||
};
|
||||
worker.on('stepBegin', onStepBegin);
|
||||
|
||||
|
|
@ -298,14 +298,14 @@ export class Dispatcher {
|
|||
const { result, steps } = runData;
|
||||
const step = steps.get(params.stepId);
|
||||
if (!step) {
|
||||
this._reporter.onStdErr?.('Internal error: step end without step begin: ' + params.stepId, data.test, result);
|
||||
this._reporter.onStdErr('Internal error: step end without step begin: ' + params.stepId, data.test, result);
|
||||
return;
|
||||
}
|
||||
step.duration = params.wallTime - step.startTime.getTime();
|
||||
if (params.error)
|
||||
step.error = params.error;
|
||||
steps.delete(params.stepId);
|
||||
this._reporter.onStepEnd?.(data.test, result, step);
|
||||
this._reporter.onStepEnd(data.test, result, step);
|
||||
};
|
||||
worker.on('stepEnd', onStepEnd);
|
||||
|
||||
|
|
@ -342,7 +342,7 @@ export class Dispatcher {
|
|||
if (onlyStartedTests)
|
||||
return true;
|
||||
result = data.test._appendTestResult();
|
||||
this._reporter.onTestBegin?.(test, result);
|
||||
this._reporter.onTestBegin(test, result);
|
||||
}
|
||||
result.errors = [...errors];
|
||||
result.error = result.errors[0];
|
||||
|
|
@ -358,7 +358,7 @@ export class Dispatcher {
|
|||
// Let's just fail the test run.
|
||||
this._hasWorkerErrors = true;
|
||||
for (const error of params.fatalErrors)
|
||||
this._reporter.onError?.(error);
|
||||
this._reporter.onError(error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -410,7 +410,7 @@ export class Dispatcher {
|
|||
|
||||
// Emulate a "skipped" run, and drop this test from remaining.
|
||||
const result = test._appendTestResult();
|
||||
this._reporter.onTestBegin?.(test, result);
|
||||
this._reporter.onTestBegin(test, result);
|
||||
result.status = 'skipped';
|
||||
this._reportTestEnd(test, result);
|
||||
return false;
|
||||
|
|
@ -470,17 +470,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._hasWorkerErrors = true;
|
||||
for (const error of params.fatalErrors)
|
||||
this._reporter.onError?.(error);
|
||||
this._reporter.onError(error);
|
||||
});
|
||||
worker.on('exit', () => {
|
||||
const producedEnv = this._producedEnvByProjectId.get(testGroup.projectId) || {};
|
||||
|
|
@ -509,7 +509,7 @@ export class Dispatcher {
|
|||
private _reportTestEnd(test: TestCase, result: TestResult) {
|
||||
if (result.status !== 'skipped' && result.status !== test.expectedStatus)
|
||||
++this._failureCount;
|
||||
this._reporter.onTestEnd?.(test, result);
|
||||
this._reporter.onTestEnd(test, result);
|
||||
const maxFailures = this._config.config.maxFailures;
|
||||
if (maxFailures && this._failureCount === maxFailures)
|
||||
this.stop().catch(e => {});
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ import type { FullConfigInternal } from '../common/config';
|
|||
import { colors } from 'playwright-core/lib/utilsBundle';
|
||||
import { runWatchModeLoop } from './watchMode';
|
||||
import { runUIMode } from './uiMode';
|
||||
import { Multiplexer } from '../reporters/multiplexer';
|
||||
import { InternalReporter } from '../reporters/internalReporter';
|
||||
|
||||
export class Runner {
|
||||
private _config: FullConfigInternal;
|
||||
|
|
@ -69,7 +69,7 @@ export class Runner {
|
|||
// Legacy webServer support.
|
||||
webServerPluginsForConfig(config).forEach(p => config.plugins.push({ factory: p }));
|
||||
|
||||
const reporter = new Multiplexer(await createReporters(config, listOnly ? 'list' : 'run'));
|
||||
const reporter = new InternalReporter(await createReporters(config, listOnly ? 'list' : 'run'));
|
||||
const taskRunner = listOnly ? createTaskRunnerForList(config, reporter, 'in-process')
|
||||
: createTaskRunner(config, reporter);
|
||||
|
||||
|
|
|
|||
|
|
@ -19,20 +19,20 @@ import { ManualPromise, monotonicTime } from 'playwright-core/lib/utils';
|
|||
import type { FullResult, TestError } from '../../reporter';
|
||||
import { SigIntWatcher } from './sigIntWatcher';
|
||||
import { serializeError } from '../util';
|
||||
import type { Multiplexer } from '../reporters/multiplexer';
|
||||
import type { InternalReporter } from '../reporters/internalReporter';
|
||||
|
||||
type TaskTeardown = () => Promise<any> | undefined;
|
||||
export type Task<Context> = (context: Context, errors: TestError[]) => Promise<TaskTeardown | void> | undefined;
|
||||
|
||||
export class TaskRunner<Context> {
|
||||
private _tasks: { name: string, task: Task<Context> }[] = [];
|
||||
private _reporter: Multiplexer;
|
||||
private _reporter: InternalReporter;
|
||||
private _hasErrors = false;
|
||||
private _interrupted = false;
|
||||
private _isTearDown = false;
|
||||
private _globalTimeoutForError: number;
|
||||
|
||||
constructor(reporter: Multiplexer, globalTimeoutForError: number) {
|
||||
constructor(reporter: InternalReporter, globalTimeoutForError: number) {
|
||||
this._reporter = reporter;
|
||||
this._globalTimeoutForError = globalTimeoutForError;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import { promisify } from 'util';
|
|||
import { debug, rimraf } from 'playwright-core/lib/utilsBundle';
|
||||
import { Dispatcher, type EnvByProjectId } from './dispatcher';
|
||||
import type { TestRunnerPluginRegistration } from '../plugins';
|
||||
import type { Multiplexer } from '../reporters/multiplexer';
|
||||
import type { InternalReporter } from '../reporters/internalReporter';
|
||||
import { createTestGroups, type TestGroup } from '../runner/testGroups';
|
||||
import type { Task } from './taskRunner';
|
||||
import { TaskRunner } from './taskRunner';
|
||||
|
|
@ -44,7 +44,7 @@ export type Phase = {
|
|||
};
|
||||
|
||||
export class TestRun {
|
||||
readonly reporter: Multiplexer;
|
||||
readonly reporter: InternalReporter;
|
||||
readonly config: FullConfigInternal;
|
||||
rootSuite: Suite | undefined = undefined;
|
||||
readonly phases: Phase[] = [];
|
||||
|
|
@ -53,13 +53,13 @@ export class TestRun {
|
|||
projectType: Map<FullProjectInternal, 'top-level' | 'dependency'> = new Map();
|
||||
projectSuites: Map<FullProjectInternal, Suite[]> = new Map();
|
||||
|
||||
constructor(config: FullConfigInternal, reporter: Multiplexer) {
|
||||
constructor(config: FullConfigInternal, reporter: InternalReporter) {
|
||||
this.config = config;
|
||||
this.reporter = reporter;
|
||||
}
|
||||
}
|
||||
|
||||
export function createTaskRunner(config: FullConfigInternal, reporter: Multiplexer): TaskRunner<TestRun> {
|
||||
export function createTaskRunner(config: FullConfigInternal, reporter: InternalReporter): TaskRunner<TestRun> {
|
||||
const taskRunner = new TaskRunner<TestRun>(reporter, config.config.globalTimeout);
|
||||
addGlobalSetupTasks(taskRunner, config);
|
||||
taskRunner.addTask('load tests', createLoadTask('in-process', true));
|
||||
|
|
@ -67,13 +67,13 @@ export function createTaskRunner(config: FullConfigInternal, reporter: Multiplex
|
|||
return taskRunner;
|
||||
}
|
||||
|
||||
export function createTaskRunnerForWatchSetup(config: FullConfigInternal, reporter: Multiplexer): TaskRunner<TestRun> {
|
||||
export function createTaskRunnerForWatchSetup(config: FullConfigInternal, reporter: InternalReporter): TaskRunner<TestRun> {
|
||||
const taskRunner = new TaskRunner<TestRun>(reporter, 0);
|
||||
addGlobalSetupTasks(taskRunner, config);
|
||||
return taskRunner;
|
||||
}
|
||||
|
||||
export function createTaskRunnerForWatch(config: FullConfigInternal, reporter: Multiplexer, additionalFileMatcher?: Matcher): TaskRunner<TestRun> {
|
||||
export function createTaskRunnerForWatch(config: FullConfigInternal, reporter: InternalReporter, additionalFileMatcher?: Matcher): TaskRunner<TestRun> {
|
||||
const taskRunner = new TaskRunner<TestRun>(reporter, 0);
|
||||
taskRunner.addTask('load tests', createLoadTask('out-of-process', true, additionalFileMatcher));
|
||||
addRunTasks(taskRunner, config);
|
||||
|
|
@ -91,7 +91,7 @@ function addGlobalSetupTasks(taskRunner: TaskRunner<TestRun>, config: FullConfig
|
|||
function addRunTasks(taskRunner: TaskRunner<TestRun>, config: FullConfigInternal) {
|
||||
taskRunner.addTask('create phases', createPhasesTask());
|
||||
taskRunner.addTask('report begin', async ({ reporter, rootSuite }) => {
|
||||
reporter.onBegin?.(config.config, rootSuite!);
|
||||
reporter.onBegin(config.config, rootSuite!);
|
||||
return () => reporter.onEnd();
|
||||
});
|
||||
for (const plugin of config.plugins)
|
||||
|
|
@ -101,11 +101,11 @@ function addRunTasks(taskRunner: TaskRunner<TestRun>, config: FullConfigInternal
|
|||
return taskRunner;
|
||||
}
|
||||
|
||||
export function createTaskRunnerForList(config: FullConfigInternal, reporter: Multiplexer, mode: 'in-process' | 'out-of-process'): TaskRunner<TestRun> {
|
||||
export function createTaskRunnerForList(config: FullConfigInternal, reporter: InternalReporter, mode: 'in-process' | 'out-of-process'): TaskRunner<TestRun> {
|
||||
const taskRunner = new TaskRunner<TestRun>(reporter, config.config.globalTimeout);
|
||||
taskRunner.addTask('load tests', createLoadTask(mode, false));
|
||||
taskRunner.addTask('report begin', async ({ reporter, rootSuite }) => {
|
||||
reporter.onBegin?.(config.config, rootSuite!);
|
||||
reporter.onBegin(config.config, rootSuite!);
|
||||
return () => reporter.onEnd();
|
||||
});
|
||||
return taskRunner;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import { isUnderTest, ManualPromise } from 'playwright-core/lib/utils';
|
|||
import type { FullResult } from '../../reporter';
|
||||
import { clearCompilationCache, collectAffectedTestFiles, dependenciesForTestFile } from '../common/compilationCache';
|
||||
import type { FullConfigInternal } from '../common/config';
|
||||
import { Multiplexer } from '../reporters/multiplexer';
|
||||
import { InternalReporter } from '../reporters/internalReporter';
|
||||
import { TeleReporterEmitter } from '../reporters/teleEmitter';
|
||||
import { createReporters } from './reporters';
|
||||
import { TestRun, createTaskRunnerForList, createTaskRunnerForWatch, createTaskRunnerForWatchSetup } from './tasks';
|
||||
|
|
@ -65,7 +65,7 @@ class UIMode {
|
|||
}
|
||||
|
||||
async runGlobalSetup(): Promise<FullResult['status']> {
|
||||
const reporter = new Multiplexer([new ListReporter()]);
|
||||
const reporter = new InternalReporter([new ListReporter()]);
|
||||
const taskRunner = createTaskRunnerForWatchSetup(this._config, reporter);
|
||||
reporter.onConfigure(this._config);
|
||||
const testRun = new TestRun(this._config, reporter);
|
||||
|
|
@ -144,7 +144,7 @@ class UIMode {
|
|||
|
||||
private async _listTests() {
|
||||
const listReporter = new TeleReporterEmitter(e => this._dispatchEvent(e));
|
||||
const reporter = new Multiplexer([listReporter]);
|
||||
const reporter = new InternalReporter([listReporter]);
|
||||
this._config.cliListOnly = true;
|
||||
this._config.testIdMatcher = undefined;
|
||||
const taskRunner = createTaskRunnerForList(this._config, reporter, 'out-of-process');
|
||||
|
|
@ -169,7 +169,7 @@ class UIMode {
|
|||
|
||||
const reporters = await createReporters(this._config, 'ui');
|
||||
reporters.push(new TeleReporterEmitter(e => this._dispatchEvent(e)));
|
||||
const reporter = new Multiplexer(reporters);
|
||||
const reporter = new InternalReporter(reporters);
|
||||
const taskRunner = createTaskRunnerForWatch(this._config, reporter);
|
||||
const testRun = new TestRun(this._config, reporter);
|
||||
clearCompilationCache();
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
import readline from 'readline';
|
||||
import { createGuid, ManualPromise } from 'playwright-core/lib/utils';
|
||||
import type { FullConfigInternal, FullProjectInternal } from '../common/config';
|
||||
import { Multiplexer } from '../reporters/multiplexer';
|
||||
import { InternalReporter } from '../reporters/internalReporter';
|
||||
import { createFileMatcher, createFileMatcherFromArguments } from '../util';
|
||||
import type { Matcher } from '../util';
|
||||
import { TestRun, createTaskRunnerForWatch, createTaskRunnerForWatchSetup } from './tasks';
|
||||
|
|
@ -112,7 +112,7 @@ export async function runWatchModeLoop(config: FullConfigInternal): Promise<Full
|
|||
p.project.retries = 0;
|
||||
|
||||
// Perform global setup.
|
||||
const reporter = new Multiplexer([new ListReporter()]);
|
||||
const reporter = new InternalReporter([new ListReporter()]);
|
||||
const testRun = new TestRun(config, reporter);
|
||||
const taskRunner = createTaskRunnerForWatchSetup(config, reporter);
|
||||
reporter.onConfigure(config);
|
||||
|
|
@ -275,7 +275,7 @@ async function runTests(config: FullConfigInternal, failedTestIdCollector: Set<s
|
|||
title?: string,
|
||||
}) {
|
||||
printConfiguration(config, options?.title);
|
||||
const reporter = new Multiplexer([new ListReporter()]);
|
||||
const reporter = new InternalReporter([new ListReporter()]);
|
||||
const taskRunner = createTaskRunnerForWatch(config, reporter, options?.additionalFileMatcher);
|
||||
const testRun = new TestRun(config, reporter);
|
||||
clearCompilationCache();
|
||||
|
|
|
|||
Loading…
Reference in New Issue