fix(test runner): route more errors to reporter (#10263)
For example, top-level errors in files or global setup issues.
This commit is contained in:
parent
d97fe4e2af
commit
4bb123d4b7
|
|
@ -20,7 +20,7 @@ import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { promisify } from 'util';
|
import { promisify } from 'util';
|
||||||
import { Dispatcher, TestGroup } from './dispatcher';
|
import { Dispatcher, TestGroup } from './dispatcher';
|
||||||
import { createFileMatcher, createTitleMatcher, FilePatternFilter, monotonicTime } from './util';
|
import { createFileMatcher, createTitleMatcher, FilePatternFilter, monotonicTime, serializeError } from './util';
|
||||||
import { TestCase, Suite } from './test';
|
import { TestCase, Suite } from './test';
|
||||||
import { Loader } from './loader';
|
import { Loader } from './loader';
|
||||||
import { FullResult, Reporter, TestError } from '../types/testReporter';
|
import { FullResult, Reporter, TestError } from '../types/testReporter';
|
||||||
|
|
@ -97,18 +97,27 @@ export class Runner {
|
||||||
|
|
||||||
async run(list: boolean, filePatternFilters: FilePatternFilter[], projectNames?: string[]): Promise<FullResult> {
|
async run(list: boolean, filePatternFilters: FilePatternFilter[], projectNames?: string[]): Promise<FullResult> {
|
||||||
this._reporter = await this._createReporter(list);
|
this._reporter = await this._createReporter(list);
|
||||||
const config = this._loader.fullConfig();
|
try {
|
||||||
const globalDeadline = config.globalTimeout ? config.globalTimeout + monotonicTime() : 0;
|
const config = this._loader.fullConfig();
|
||||||
const { result, timedOut } = await raceAgainstDeadline(this._run(list, filePatternFilters, projectNames), globalDeadline);
|
const globalDeadline = config.globalTimeout ? config.globalTimeout + monotonicTime() : 0;
|
||||||
if (timedOut) {
|
const { result, timedOut } = await raceAgainstDeadline(this._run(list, filePatternFilters, projectNames), globalDeadline);
|
||||||
const actualResult: FullResult = { status: 'timedout' };
|
if (timedOut) {
|
||||||
if (this._didBegin)
|
const actualResult: FullResult = { status: 'timedout' };
|
||||||
await this._reporter.onEnd?.(actualResult);
|
if (this._didBegin)
|
||||||
else
|
await this._reporter.onEnd?.(actualResult);
|
||||||
this._reporter.onError?.(createStacklessError(`Timed out waiting ${config.globalTimeout / 1000}s for the entire test run`));
|
else
|
||||||
return actualResult;
|
this._reporter.onError?.(createStacklessError(`Timed out waiting ${config.globalTimeout / 1000}s for the entire test run`));
|
||||||
|
return actualResult;
|
||||||
|
}
|
||||||
|
return result!;
|
||||||
|
} catch (e) {
|
||||||
|
const result: FullResult = { status: 'failed' };
|
||||||
|
try {
|
||||||
|
this._reporter.onError?.(serializeError(e));
|
||||||
|
} catch (ignored) {
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
return result!;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async _run(list: boolean, testFileReFilters: FilePatternFilter[], projectNames?: string[]): Promise<FullResult> {
|
async _run(list: boolean, testFileReFilters: FilePatternFilter[], projectNames?: string[]): Promise<FullResult> {
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,9 @@ class Reporter {
|
||||||
onStdErr() {}
|
onStdErr() {}
|
||||||
onTestEnd(test, result) {}
|
onTestEnd(test, result) {}
|
||||||
onTimeout() {}
|
onTimeout() {}
|
||||||
onError() {}
|
onError(error) {
|
||||||
|
console.log('\\n%%got error: ' + error.message);
|
||||||
|
}
|
||||||
onEnd() {
|
onEnd() {
|
||||||
console.log('\\n%%end');
|
console.log('\\n%%end');
|
||||||
}
|
}
|
||||||
|
|
@ -405,6 +407,77 @@ test('should show nice stacks for locators', async ({ runInlineTest }) => {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should report forbid-only error to reporter', async ({ runInlineTest }) => {
|
||||||
|
const result = await runInlineTest({
|
||||||
|
'reporter.ts': smallReporterJS,
|
||||||
|
'playwright.config.ts': `
|
||||||
|
module.exports = {
|
||||||
|
reporter: './reporter',
|
||||||
|
};
|
||||||
|
`,
|
||||||
|
'a.test.ts': `
|
||||||
|
pwt.test.only('pass', () => {});
|
||||||
|
`
|
||||||
|
}, { 'reporter': '', 'forbid-only': true });
|
||||||
|
|
||||||
|
expect(result.exitCode).toBe(1);
|
||||||
|
expect(result.output).toContain(`%%got error: =====================================\n --forbid-only found a focused test.`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should report no-tests error to reporter', async ({ runInlineTest }) => {
|
||||||
|
const result = await runInlineTest({
|
||||||
|
'reporter.ts': smallReporterJS,
|
||||||
|
'playwright.config.ts': `
|
||||||
|
module.exports = {
|
||||||
|
reporter: './reporter',
|
||||||
|
};
|
||||||
|
`
|
||||||
|
}, { 'reporter': '' });
|
||||||
|
|
||||||
|
expect(result.exitCode).toBe(1);
|
||||||
|
expect(result.output).toContain(`%%got error: =================\n no tests found.`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should report require error to reporter', async ({ runInlineTest }) => {
|
||||||
|
const result = await runInlineTest({
|
||||||
|
'reporter.ts': smallReporterJS,
|
||||||
|
'playwright.config.ts': `
|
||||||
|
module.exports = {
|
||||||
|
reporter: './reporter',
|
||||||
|
};
|
||||||
|
`,
|
||||||
|
'a.spec.js': `
|
||||||
|
throw new Error('Oh my!');
|
||||||
|
`,
|
||||||
|
}, { 'reporter': '' });
|
||||||
|
|
||||||
|
expect(result.exitCode).toBe(1);
|
||||||
|
expect(result.output).toContain(`%%got error: Oh my!`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should report global setup error to reporter', async ({ runInlineTest }) => {
|
||||||
|
const result = await runInlineTest({
|
||||||
|
'reporter.ts': smallReporterJS,
|
||||||
|
'playwright.config.ts': `
|
||||||
|
module.exports = {
|
||||||
|
reporter: './reporter',
|
||||||
|
globalSetup: './globalSetup',
|
||||||
|
};
|
||||||
|
`,
|
||||||
|
'globalSetup.ts': `
|
||||||
|
module.exports = () => {
|
||||||
|
throw new Error('Oh my!');
|
||||||
|
};
|
||||||
|
`,
|
||||||
|
'a.spec.js': `
|
||||||
|
pwt.test('test', () => {});
|
||||||
|
`,
|
||||||
|
}, { 'reporter': '' });
|
||||||
|
|
||||||
|
expect(result.exitCode).toBe(1);
|
||||||
|
expect(result.output).toContain(`%%got error: Oh my!`);
|
||||||
|
});
|
||||||
|
|
||||||
function stripEscapedAscii(str: string) {
|
function stripEscapedAscii(str: string) {
|
||||||
return str.replace(/\\u00[a-z0-9][a-z0-9]\[[^m]+m/g, '');
|
return str.replace(/\\u00[a-z0-9][a-z0-9]\[[^m]+m/g, '');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue