mirror of
https://github.com/microsoft/playwright.git
synced 2024-12-11 12:33:45 +03:00
chore: call onEnd(result)
on InternalReporter (#23972)
Drive-by: fix watch mode not running global teardown.
This commit is contained in:
parent
a07626b804
commit
e28312ba63
@ -22,7 +22,6 @@ import { Suite } from '../common/test';
|
||||
import type { FullConfigInternal } from '../common/config';
|
||||
import { Multiplexer } from './multiplexer';
|
||||
import { prepareErrorStack, relativeFilePath } from './base';
|
||||
import { monotonicTime } from 'playwright-core/lib/utils';
|
||||
|
||||
type StdIOChunk = {
|
||||
chunk: string | Buffer;
|
||||
@ -34,7 +33,6 @@ export class InternalReporter {
|
||||
private _multiplexer: Multiplexer;
|
||||
private _deferred: { error?: TestError, stdout?: StdIOChunk, stderr?: StdIOChunk }[] | null = [];
|
||||
private _config!: FullConfigInternal;
|
||||
private _montonicStartTime: number = 0;
|
||||
|
||||
constructor(reporters: Reporter[]) {
|
||||
this._multiplexer = new Multiplexer(reporters);
|
||||
@ -45,7 +43,6 @@ export class InternalReporter {
|
||||
}
|
||||
|
||||
onBegin(config: FullConfig, suite: Suite) {
|
||||
this._montonicStartTime = monotonicTime();
|
||||
this._multiplexer.onBegin(config, suite);
|
||||
|
||||
const deferred = this._deferred!;
|
||||
@ -86,16 +83,15 @@ export class InternalReporter {
|
||||
this._multiplexer.onTestEnd(test, result);
|
||||
}
|
||||
|
||||
async onEnd() {
|
||||
this._config.config.metadata.totalTime = monotonicTime() - this._montonicStartTime;
|
||||
}
|
||||
|
||||
async onExit(result: FullResult) {
|
||||
async onEnd(result: FullResult) {
|
||||
if (this._deferred) {
|
||||
// onBegin was not reported, emit it.
|
||||
this.onBegin(this._config.config, new Suite('', 'root'));
|
||||
}
|
||||
await this._multiplexer.onEnd(result);
|
||||
}
|
||||
|
||||
async onExit() {
|
||||
await this._multiplexer.onExit();
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,8 @@ export class Runner {
|
||||
status = 'failed';
|
||||
if (status === 'passed' && taskStatus !== 'passed')
|
||||
status = taskStatus;
|
||||
await reporter.onExit({ status });
|
||||
await reporter.onEnd({ status });
|
||||
await reporter.onExit();
|
||||
|
||||
// Calling process.exit() might truncate large stdout/stderr output.
|
||||
// See https://github.com/nodejs/node/issues/6456.
|
||||
|
@ -29,6 +29,7 @@ import { collectProjectsAndTestFiles, createRootSuite, loadFileSuites, loadGloba
|
||||
import type { Matcher } from '../util';
|
||||
import type { Suite } from '../common/test';
|
||||
import { buildDependentProjects, buildTeardownToSetupsMap } from './projectUtils';
|
||||
import { monotonicTime } from 'playwright-core/lib/utils';
|
||||
|
||||
const removeFolderAsync = promisify(rimraf);
|
||||
const readDirAsync = promisify(fs.readdir);
|
||||
@ -91,10 +92,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!);
|
||||
return () => reporter.onEnd();
|
||||
});
|
||||
taskRunner.addTask('report begin', createReportBeginTask());
|
||||
for (const plugin of config.plugins)
|
||||
taskRunner.addTask('plugin begin', createPluginBeginTask(plugin));
|
||||
taskRunner.addTask('start workers', createWorkersTask());
|
||||
@ -105,13 +103,20 @@ function addRunTasks(taskRunner: TaskRunner<TestRun>, config: FullConfigInternal
|
||||
export function createTaskRunnerForList(config: FullConfigInternal, reporter: InternalReporter, mode: 'in-process' | 'out-of-process', options: { failOnLoadErrors: boolean }): TaskRunner<TestRun> {
|
||||
const taskRunner = new TaskRunner<TestRun>(reporter, config.config.globalTimeout);
|
||||
taskRunner.addTask('load tests', createLoadTask(mode, { ...options, filterOnly: false }));
|
||||
taskRunner.addTask('report begin', async ({ reporter, rootSuite }) => {
|
||||
reporter.onBegin(config.config, rootSuite!);
|
||||
return () => reporter.onEnd();
|
||||
});
|
||||
taskRunner.addTask('report begin', createReportBeginTask());
|
||||
return taskRunner;
|
||||
}
|
||||
|
||||
function createReportBeginTask(): Task<TestRun> {
|
||||
return async ({ config, reporter, rootSuite }) => {
|
||||
const montonicStartTime = monotonicTime();
|
||||
reporter.onBegin(config.config, rootSuite!);
|
||||
return async () => {
|
||||
config.config.metadata.totalTime = monotonicTime() - montonicStartTime;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
function createPluginSetupTask(plugin: TestRunnerPluginRegistration): Task<TestRun> {
|
||||
return async ({ config, reporter }) => {
|
||||
if (typeof plugin.factory === 'function')
|
||||
|
@ -72,7 +72,8 @@ class UIMode {
|
||||
reporter.onConfigure(this._config);
|
||||
const testRun = new TestRun(this._config, reporter);
|
||||
const { status, cleanup: globalCleanup } = await taskRunner.runDeferCleanup(testRun, 0);
|
||||
await reporter.onExit({ status });
|
||||
await reporter.onEnd({ status });
|
||||
await reporter.onExit();
|
||||
if (status !== 'passed') {
|
||||
await globalCleanup();
|
||||
return status;
|
||||
@ -168,7 +169,8 @@ class UIMode {
|
||||
clearCompilationCache();
|
||||
reporter.onConfigure(this._config);
|
||||
const status = await taskRunner.run(testRun, 0);
|
||||
await reporter.onExit({ status });
|
||||
await reporter.onEnd({ status });
|
||||
await reporter.onExit();
|
||||
|
||||
const projectDirs = new Set<string>();
|
||||
for (const p of this._config.projects)
|
||||
@ -192,7 +194,8 @@ class UIMode {
|
||||
reporter.onConfigure(this._config);
|
||||
const stop = new ManualPromise();
|
||||
const run = taskRunner.run(testRun, 0, stop).then(async status => {
|
||||
await reporter.onExit({ status });
|
||||
await reporter.onEnd({ status });
|
||||
await reporter.onExit();
|
||||
this._testRun = undefined;
|
||||
this._config.testIdMatcher = undefined;
|
||||
return status;
|
||||
|
@ -118,7 +118,11 @@ export async function runWatchModeLoop(config: FullConfigInternal): Promise<Full
|
||||
reporter.onConfigure(config);
|
||||
const { status, cleanup: globalCleanup } = await taskRunner.runDeferCleanup(testRun, 0);
|
||||
if (status !== 'passed')
|
||||
return await globalCleanup();
|
||||
await globalCleanup();
|
||||
await reporter.onEnd({ status });
|
||||
await reporter.onExit();
|
||||
if (status !== 'passed')
|
||||
return status;
|
||||
|
||||
// Prepare projects that will be watched, set up watcher.
|
||||
const failedTestIdCollector = new Set<string>();
|
||||
@ -248,7 +252,8 @@ export async function runWatchModeLoop(config: FullConfigInternal): Promise<Full
|
||||
}
|
||||
}
|
||||
|
||||
return result === 'passed' ? await globalCleanup() : result;
|
||||
const cleanupStatus = await globalCleanup();
|
||||
return result === 'passed' ? cleanupStatus : result;
|
||||
}
|
||||
|
||||
async function runChangedTests(config: FullConfigInternal, failedTestIdCollector: Set<string>, filesByProject: Map<FullProjectInternal, Set<string>>, title?: string) {
|
||||
@ -297,7 +302,8 @@ async function runTests(config: FullConfigInternal, failedTestIdCollector: Set<s
|
||||
status = 'failed';
|
||||
if (status === 'passed' && taskStatus !== 'passed')
|
||||
status = taskStatus;
|
||||
await reporter.onExit({ status });
|
||||
await reporter.onEnd({ status });
|
||||
await reporter.onExit();
|
||||
}
|
||||
|
||||
function affectedProjectsClosure(projectClosure: FullProjectInternal[], affected: FullProjectInternal[]): Set<FullProjectInternal> {
|
||||
|
@ -696,3 +696,27 @@ test('should run CT on indirect deps change ESM mode', async ({ runWatchTest, wr
|
||||
expect(testProcess.output).not.toContain(`src${path.sep}link.spec.tsx`);
|
||||
await testProcess.waitForOutput('Waiting for file changes.');
|
||||
});
|
||||
|
||||
test('should run global teardown before exiting', async ({ runWatchTest }) => {
|
||||
const testProcess = await runWatchTest({
|
||||
'playwright.config.ts': `
|
||||
export default {
|
||||
globalTeardown: './global-teardown.ts',
|
||||
};
|
||||
`,
|
||||
'global-teardown.ts': `
|
||||
export default async function() {
|
||||
console.log('running teardown');
|
||||
};
|
||||
`,
|
||||
'a.test.ts': `
|
||||
import { test, expect } from '@playwright/test';
|
||||
test('passes', async () => {
|
||||
});
|
||||
`,
|
||||
}, {});
|
||||
await testProcess.waitForOutput('a.test.ts:3:11 › passes');
|
||||
await testProcess.waitForOutput('Waiting for file changes.');
|
||||
testProcess.write('\x1B');
|
||||
await testProcess.waitForOutput('running teardown');
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user