feat(html): automatically use console reporter with html (#9559)
This commit is contained in:
parent
3e054e9ad6
commit
99f3389b3b
|
|
@ -261,10 +261,9 @@ Running 124 tests using 6 workers
|
||||||
### HTML reporter
|
### HTML reporter
|
||||||
|
|
||||||
HTML reporter produces a self-contained folder that contains report for the test run that can be served as a web page.
|
HTML reporter produces a self-contained folder that contains report for the test run that can be served as a web page.
|
||||||
It is usually used together with some terminal reporter like `dot` or `line`.
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npx playwright test --reporter=html,dot
|
npx playwright test --reporter=html
|
||||||
```
|
```
|
||||||
|
|
||||||
By default, report is written into the `playwright-report` folder in the current working directory. One can override
|
By default, report is written into the `playwright-report` folder in the current working directory. One can override
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,11 @@ export class BaseReporter implements Reporter {
|
||||||
fileDurations = new Map<string, number>();
|
fileDurations = new Map<string, number>();
|
||||||
monotonicStartTime: number = 0;
|
monotonicStartTime: number = 0;
|
||||||
private printTestOutput = !process.env.PWTEST_SKIP_TEST_OUTPUT;
|
private printTestOutput = !process.env.PWTEST_SKIP_TEST_OUTPUT;
|
||||||
|
protected _omitFailures: boolean;
|
||||||
|
|
||||||
|
constructor(options: { omitFailures?: boolean } = {}) {
|
||||||
|
this._omitFailures = options.omitFailures || false;
|
||||||
|
}
|
||||||
|
|
||||||
onBegin(config: FullConfig, suite: Suite) {
|
onBegin(config: FullConfig, suite: Suite) {
|
||||||
this.monotonicStartTime = monotonicTime();
|
this.monotonicStartTime = monotonicTime();
|
||||||
|
|
@ -113,7 +118,6 @@ export class BaseReporter implements Reporter {
|
||||||
|
|
||||||
protected generateSummaryMessage({ skipped, expected, unexpected, flaky }: TestSummary) {
|
protected generateSummaryMessage({ skipped, expected, unexpected, flaky }: TestSummary) {
|
||||||
const tokens: string[] = [];
|
const tokens: string[] = [];
|
||||||
tokens.push('');
|
|
||||||
if (unexpected.length) {
|
if (unexpected.length) {
|
||||||
tokens.push(colors.red(` ${unexpected.length} failed`));
|
tokens.push(colors.red(` ${unexpected.length} failed`));
|
||||||
for (const test of unexpected)
|
for (const test of unexpected)
|
||||||
|
|
@ -169,7 +173,7 @@ export class BaseReporter implements Reporter {
|
||||||
epilogue(full: boolean) {
|
epilogue(full: boolean) {
|
||||||
const summary = this.generateSummary();
|
const summary = this.generateSummary();
|
||||||
const summaryMessage = this.generateSummaryMessage(summary);
|
const summaryMessage = this.generateSummaryMessage(summary);
|
||||||
if (full && summary.failuresToPrint.length)
|
if (full && summary.failuresToPrint.length && !this._omitFailures)
|
||||||
this._printFailures(summary.failuresToPrint);
|
this._printFailures(summary.failuresToPrint);
|
||||||
this._printSlowTests();
|
this._printSlowTests();
|
||||||
this._printSummary(summaryMessage);
|
this._printSummary(summaryMessage);
|
||||||
|
|
@ -191,9 +195,11 @@ export class BaseReporter implements Reporter {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private _printSummary(summary: string){
|
private _printSummary(summary: string) {
|
||||||
console.log('');
|
if (summary.trim()) {
|
||||||
console.log(summary);
|
console.log('');
|
||||||
|
console.log(summary);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
willRetry(test: TestCase): boolean {
|
willRetry(test: TestCase): boolean {
|
||||||
|
|
|
||||||
|
|
@ -31,11 +31,9 @@ type GitHubLogOptions = Partial<{
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
class GitHubLogger {
|
class GitHubLogger {
|
||||||
private _isGitHubAction: boolean = !!process.env.GITHUB_ACTION;
|
|
||||||
|
|
||||||
private _log(message: string, type: GitHubLogType = 'notice', options: GitHubLogOptions = {}) {
|
private _log(message: string, type: GitHubLogType = 'notice', options: GitHubLogOptions = {}) {
|
||||||
if (this._isGitHubAction)
|
message = message.replace(/\n/g, '%0A');
|
||||||
message = message.replace(/\n/g, '%0A');
|
|
||||||
const configs = Object.entries(options)
|
const configs = Object.entries(options)
|
||||||
.map(([key, option]) => `${key}=${option}`)
|
.map(([key, option]) => `${key}=${option}`)
|
||||||
.join(',');
|
.join(',');
|
||||||
|
|
|
||||||
|
|
@ -129,13 +129,11 @@ class HtmlReporter {
|
||||||
if (!stats.ok && !process.env.CI && !process.env.PWTEST_SKIP_TEST_OUTPUT) {
|
if (!stats.ok && !process.env.CI && !process.env.PWTEST_SKIP_TEST_OUTPUT) {
|
||||||
await showHTMLReport(reportFolder);
|
await showHTMLReport(reportFolder);
|
||||||
} else {
|
} else {
|
||||||
console.log('');
|
|
||||||
console.log('');
|
console.log('');
|
||||||
console.log('All tests passed. To open last HTML report run:');
|
console.log('All tests passed. To open last HTML report run:');
|
||||||
console.log(colors.cyan(`
|
console.log(colors.cyan(`
|
||||||
npx playwright show-report
|
npx playwright show-report
|
||||||
`));
|
`));
|
||||||
console.log('');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,8 @@ class LineReporter extends BaseReporter {
|
||||||
const width = process.stdout.columns! - 1;
|
const width = process.stdout.columns! - 1;
|
||||||
const title = `[${++this._current}/${this._total}] ${formatTestTitle(this.config, test)}`.substring(0, width);
|
const title = `[${++this._current}/${this._total}] ${formatTestTitle(this.config, test)}`.substring(0, width);
|
||||||
process.stdout.write(`\u001B[1A\u001B[2K${title}\n`);
|
process.stdout.write(`\u001B[1A\u001B[2K${title}\n`);
|
||||||
if (!this.willRetry(test) && (test.outcome() === 'flaky' || test.outcome() === 'unexpected')) {
|
|
||||||
|
if (!this._omitFailures && !this.willRetry(test) && (test.outcome() === 'flaky' || test.outcome() === 'unexpected')) {
|
||||||
process.stdout.write(`\u001B[1A\u001B[2K`);
|
process.stdout.write(`\u001B[1A\u001B[2K`);
|
||||||
console.log(formatFailure(this.config, test, {
|
console.log(formatFailure(this.config, test, {
|
||||||
index: ++this._failures
|
index: ++this._failures
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,8 @@ class ListReporter extends BaseReporter {
|
||||||
private readonly _liveTerminal: string | boolean | undefined;
|
private readonly _liveTerminal: string | boolean | undefined;
|
||||||
private readonly _ttyWidthForTest: number;
|
private readonly _ttyWidthForTest: number;
|
||||||
|
|
||||||
constructor() {
|
constructor(options: { omitFailures?: boolean } = {}) {
|
||||||
super();
|
super(options);
|
||||||
this._ttyWidthForTest = parseInt(process.env.PWTEST_TTY_WIDTH || '', 10);
|
this._ttyWidthForTest = parseInt(process.env.PWTEST_TTY_WIDTH || '', 10);
|
||||||
this._liveTerminal = process.stdout.isTTY || process.env.PWTEST_SKIP_TEST_OUTPUT || !!this._ttyWidthForTest;
|
this._liveTerminal = process.stdout.isTTY || process.env.PWTEST_SKIP_TEST_OUTPUT || !!this._ttyWidthForTest;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,13 @@ export class Runner {
|
||||||
html: HtmlReporter,
|
html: HtmlReporter,
|
||||||
};
|
};
|
||||||
const reporters: Reporter[] = [];
|
const reporters: Reporter[] = [];
|
||||||
|
const reporterConfig = this._loader.fullConfig().reporter;
|
||||||
|
if (reporterConfig.length === 1 && reporterConfig[0][0] === 'html') {
|
||||||
|
// For html reporter, add a line/dot report for convenience.
|
||||||
|
// Important to put html last because it stalls onEnd.
|
||||||
|
reporterConfig.unshift([process.stdout.isTTY && !process.env.CI ? 'line' : 'dot', { omitFailures: true }]);
|
||||||
|
}
|
||||||
|
|
||||||
for (const r of this._loader.fullConfig().reporter) {
|
for (const r of this._loader.fullConfig().reporter) {
|
||||||
const [name, arg] = r;
|
const [name, arg] = r;
|
||||||
if (name in defaultReporters) {
|
if (name in defaultReporters) {
|
||||||
|
|
|
||||||
|
|
@ -31,30 +31,13 @@ test('print GitHub annotations for success', async ({ runInlineTest }) => {
|
||||||
expect(1 + 1).toBe(2);
|
expect(1 + 1).toBe(2);
|
||||||
});
|
});
|
||||||
`
|
`
|
||||||
}, { reporter: 'github' }, { GITHUB_ACTION: 'true' });
|
}, { reporter: 'github' });
|
||||||
const text = stripAscii(result.output);
|
const text = stripAscii(result.output);
|
||||||
expect(text).not.toContain('::error');
|
expect(text).not.toContain('::error');
|
||||||
expect(text).toContain('::notice title=🎭 Playwright Run Summary::%0A 1 passed');
|
expect(text).toContain('::notice title=🎭 Playwright Run Summary:: 1 passed');
|
||||||
expect(result.exitCode).toBe(0);
|
expect(result.exitCode).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('print GitHub annotations with newline if not in CI', async ({ runInlineTest }) => {
|
|
||||||
const result = await runInlineTest({
|
|
||||||
'a.test.js': `
|
|
||||||
const { test } = pwt;
|
|
||||||
test('example1', async ({}) => {
|
|
||||||
expect(1 + 1).toBe(2);
|
|
||||||
});
|
|
||||||
`
|
|
||||||
}, { reporter: 'github' }, { GITHUB_ACTION: '' });
|
|
||||||
const text = stripAscii(result.output);
|
|
||||||
expect(text).not.toContain('::error');
|
|
||||||
expect(text).toContain(`::notice title=🎭 Playwright Run Summary::
|
|
||||||
1 passed `);
|
|
||||||
expect(result.exitCode).toBe(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
test('print GitHub annotations for failed tests', async ({ runInlineTest }, testInfo) => {
|
test('print GitHub annotations for failed tests', async ({ runInlineTest }, testInfo) => {
|
||||||
const result = await runInlineTest({
|
const result = await runInlineTest({
|
||||||
'a.test.js': `
|
'a.test.js': `
|
||||||
|
|
@ -63,7 +46,7 @@ test('print GitHub annotations for failed tests', async ({ runInlineTest }, test
|
||||||
expect(1 + 1).toBe(3);
|
expect(1 + 1).toBe(3);
|
||||||
});
|
});
|
||||||
`
|
`
|
||||||
}, { retries: 3, reporter: 'github' }, { GITHUB_ACTION: 'true', GITHUB_WORKSPACE: process.cwd() });
|
}, { retries: 3, reporter: 'github' }, { GITHUB_WORKSPACE: process.cwd() });
|
||||||
const text = stripAscii(result.output);
|
const text = stripAscii(result.output);
|
||||||
const testPath = relativeFilePath(testInfo.outputPath('a.test.js'));
|
const testPath = relativeFilePath(testInfo.outputPath('a.test.js'));
|
||||||
expect(text).toContain(`::error file=${testPath},title=a.test.js:6:7 › example,line=7,col=23:: 1) a.test.js:6:7 › example =======================================================================%0A%0A Retry #1`);
|
expect(text).toContain(`::error file=${testPath},title=a.test.js:6:7 › example,line=7,col=23:: 1) a.test.js:6:7 › example =======================================================================%0A%0A Retry #1`);
|
||||||
|
|
@ -72,7 +55,6 @@ test('print GitHub annotations for failed tests', async ({ runInlineTest }, test
|
||||||
expect(result.exitCode).toBe(1);
|
expect(result.exitCode).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
test('print GitHub annotations for slow tests', async ({ runInlineTest }) => {
|
test('print GitHub annotations for slow tests', async ({ runInlineTest }) => {
|
||||||
const result = await runInlineTest({
|
const result = await runInlineTest({
|
||||||
'playwright.config.ts': `
|
'playwright.config.ts': `
|
||||||
|
|
@ -86,9 +68,9 @@ test('print GitHub annotations for slow tests', async ({ runInlineTest }) => {
|
||||||
await new Promise(f => setTimeout(f, 200));
|
await new Promise(f => setTimeout(f, 200));
|
||||||
});
|
});
|
||||||
`
|
`
|
||||||
}, { retries: 3, reporter: 'github' }, { GITHUB_ACTION: 'true', GITHUB_WORKSPACE: '' });
|
}, { retries: 3, reporter: 'github' }, { GITHUB_WORKSPACE: '' });
|
||||||
const text = stripAscii(result.output);
|
const text = stripAscii(result.output);
|
||||||
expect(text).toContain('::warning title=Slow Test,file=a.test.js::a.test.js took');
|
expect(text).toContain('::warning title=Slow Test,file=a.test.js::a.test.js took');
|
||||||
expect(text).toContain('::notice title=🎭 Playwright Run Summary::%0A 1 passed');
|
expect(text).toContain('::notice title=🎭 Playwright Run Summary:: 1 passed');
|
||||||
expect(result.exitCode).toBe(0);
|
expect(result.exitCode).toBe(0);
|
||||||
});
|
});
|
||||||
Loading…
Reference in a new issue