mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
feat(report): add show-report option (#8895)
This commit is contained in:
parent
f8c0f0d637
commit
bb33b8923e
84
package-lock.json
generated
84
package-lock.json
generated
@ -37,6 +37,7 @@
|
||||
"mime": "^2.4.6",
|
||||
"minimatch": "^3.0.3",
|
||||
"ms": "^2.1.2",
|
||||
"open": "^8.2.1",
|
||||
"pirates": "^4.0.1",
|
||||
"pixelmatch": "^5.2.1",
|
||||
"pngjs": "^5.0.0",
|
||||
@ -3829,6 +3830,14 @@
|
||||
"integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/define-lazy-prop": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
|
||||
"integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/define-properties": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
|
||||
@ -6157,6 +6166,20 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-docker": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
|
||||
"integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
|
||||
"bin": {
|
||||
"is-docker": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/is-extendable": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
|
||||
@ -7421,6 +7444,33 @@
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/open": {
|
||||
"version": "8.2.1",
|
||||
"resolved": "https://registry.npmjs.org/open/-/open-8.2.1.tgz",
|
||||
"integrity": "sha512-rXILpcQlkF/QuFez2BJDf3GsqpjGKbkUUToAIGo9A0Q6ZkoSGogZJulrUdwRkrAsoQvoZsrjCYt8+zblOk7JQQ==",
|
||||
"dependencies": {
|
||||
"define-lazy-prop": "^2.0.0",
|
||||
"is-docker": "^2.1.1",
|
||||
"is-wsl": "^2.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/open/node_modules/is-wsl": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
|
||||
"integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
|
||||
"dependencies": {
|
||||
"is-docker": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/optionator": {
|
||||
"version": "0.9.1",
|
||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
|
||||
@ -8894,7 +8944,6 @@
|
||||
},
|
||||
"node_modules/socksv5/node_modules/ipv6": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ipv6/-/ipv6-3.1.1.tgz",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
@ -8913,7 +8962,6 @@
|
||||
},
|
||||
"node_modules/socksv5/node_modules/ipv6/node_modules/sprintf": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/sprintf/-/sprintf-0.1.3.tgz",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"engines": {
|
||||
@ -13727,6 +13775,11 @@
|
||||
"integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==",
|
||||
"dev": true
|
||||
},
|
||||
"define-lazy-prop": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
|
||||
"integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og=="
|
||||
},
|
||||
"define-properties": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
|
||||
@ -15651,6 +15704,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"is-docker": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
|
||||
"integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="
|
||||
},
|
||||
"is-extendable": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
|
||||
@ -16677,6 +16735,26 @@
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"open": {
|
||||
"version": "8.2.1",
|
||||
"resolved": "https://registry.npmjs.org/open/-/open-8.2.1.tgz",
|
||||
"integrity": "sha512-rXILpcQlkF/QuFez2BJDf3GsqpjGKbkUUToAIGo9A0Q6ZkoSGogZJulrUdwRkrAsoQvoZsrjCYt8+zblOk7JQQ==",
|
||||
"requires": {
|
||||
"define-lazy-prop": "^2.0.0",
|
||||
"is-docker": "^2.1.1",
|
||||
"is-wsl": "^2.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"is-wsl": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
|
||||
"integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
|
||||
"requires": {
|
||||
"is-docker": "^2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"optionator": {
|
||||
"version": "0.9.1",
|
||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
|
||||
@ -17860,7 +17938,6 @@
|
||||
"dependencies": {
|
||||
"ipv6": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ipv6/-/ipv6-3.1.1.tgz",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@ -17871,7 +17948,6 @@
|
||||
"dependencies": {
|
||||
"sprintf": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/sprintf/-/sprintf-0.1.3.tgz",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
}
|
||||
|
@ -69,6 +69,7 @@
|
||||
"mime": "^2.4.6",
|
||||
"minimatch": "^3.0.3",
|
||||
"ms": "^2.1.2",
|
||||
"open": "^8.2.1",
|
||||
"pirates": "^4.0.1",
|
||||
"pixelmatch": "^5.2.1",
|
||||
"pngjs": "^5.0.0",
|
||||
|
@ -237,8 +237,10 @@ if (!process.env.PW_CLI_TARGET_LANG) {
|
||||
|
||||
if (playwrightTestPackagePath) {
|
||||
require(playwrightTestPackagePath).addTestCommand(program);
|
||||
if (process.env.PW_EXPERIMENTAL)
|
||||
if (process.env.PW_EXPERIMENTAL) {
|
||||
require(playwrightTestPackagePath).addGenerateHtmlCommand(program);
|
||||
require(playwrightTestPackagePath).addShowHtmlCommand(program);
|
||||
}
|
||||
} else {
|
||||
const command = program.command('test').allowUnknownOption(true);
|
||||
command.description('Run tests with Playwright Test. Available in @playwright/test package.');
|
||||
|
@ -16,15 +16,17 @@
|
||||
|
||||
/* eslint-disable no-console */
|
||||
|
||||
import * as commander from 'commander';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import commander from 'commander';
|
||||
import fs from 'fs';
|
||||
import open from 'open';
|
||||
import path from 'path';
|
||||
import type { Config } from './types';
|
||||
import { Runner, builtInReporters, BuiltInReporter } from './runner';
|
||||
import { stopProfiling, startProfiling } from './profiler';
|
||||
import { FilePatternFilter } from './util';
|
||||
import { Loader } from './loader';
|
||||
import { HtmlBuilder } from './html/htmlBuilder';
|
||||
import { HttpServer } from '../utils/httpServer';
|
||||
|
||||
const defaultTimeout = 30000;
|
||||
const defaultReporter: BuiltInReporter = process.env.CI ? 'dot' : 'list';
|
||||
@ -84,23 +86,12 @@ export function addTestCommand(program: commander.CommanderStatic) {
|
||||
}
|
||||
|
||||
export function addGenerateHtmlCommand(program: commander.CommanderStatic) {
|
||||
const command = program.command('generate-html');
|
||||
const command = program.command('generate-report');
|
||||
command.description('Generate HTML report');
|
||||
command.option('-c, --config <file>', `Configuration file, or a test directory with optional "${tsConfig}"/"${jsConfig}"`);
|
||||
command.option('--output <dir>', `Folder for output artifacts (default: "playwright-report")`, 'playwright-report');
|
||||
command.action(async opts => {
|
||||
const output = opts.output;
|
||||
delete opts.output;
|
||||
const loader = await createLoader(opts);
|
||||
const outputFolders = new Set(loader.projects().map(p => p.config.outputDir));
|
||||
const reportFiles = new Set<string>();
|
||||
for (const outputFolder of outputFolders) {
|
||||
const reportFolder = path.join(outputFolder, 'report');
|
||||
const files = fs.readdirSync(reportFolder).filter(f => f.endsWith('.report'));
|
||||
for (const file of files)
|
||||
reportFiles.add(path.join(reportFolder, file));
|
||||
}
|
||||
new HtmlBuilder([...reportFiles], output, loader.fullConfig().rootDir);
|
||||
await generateHTMLReport(opts);
|
||||
}).on('--help', () => {
|
||||
console.log('');
|
||||
console.log('Examples:');
|
||||
@ -109,6 +100,46 @@ export function addGenerateHtmlCommand(program: commander.CommanderStatic) {
|
||||
});
|
||||
}
|
||||
|
||||
export function addShowHtmlCommand(program: commander.CommanderStatic) {
|
||||
const command = program.command('show-report');
|
||||
command.description('Show HTML report for last run');
|
||||
command.option('-c, --config <file>', `Configuration file, or a test directory with optional "${tsConfig}"/"${jsConfig}"`);
|
||||
command.option('--output <dir>', `Folder for output artifacts (default: "playwright-report")`, 'playwright-report');
|
||||
command.action(async opts => {
|
||||
const output = await generateHTMLReport(opts);
|
||||
const server = new HttpServer();
|
||||
server.routePrefix('/', (request, response) => {
|
||||
let relativePath = request.url!;
|
||||
if (relativePath === '/')
|
||||
relativePath = '/index.html';
|
||||
const absolutePath = path.join(output, ...relativePath.split('/'));
|
||||
return server.serveFile(response, absolutePath);
|
||||
});
|
||||
open(await server.start());
|
||||
}).on('--help', () => {
|
||||
console.log('');
|
||||
console.log('Examples:');
|
||||
console.log('');
|
||||
console.log(' $ show-report');
|
||||
});
|
||||
}
|
||||
|
||||
async function generateHTMLReport(opts: any): Promise<string> {
|
||||
const output = opts.output;
|
||||
delete opts.output;
|
||||
const loader = await createLoader(opts);
|
||||
const outputFolders = new Set(loader.projects().map(p => p.config.outputDir));
|
||||
const reportFiles = new Set<string>();
|
||||
for (const outputFolder of outputFolders) {
|
||||
const reportFolder = path.join(outputFolder, 'report');
|
||||
const files = fs.readdirSync(reportFolder).filter(f => f.endsWith('.report'));
|
||||
for (const file of files)
|
||||
reportFiles.add(path.join(reportFolder, file));
|
||||
}
|
||||
new HtmlBuilder([...reportFiles], output, loader.fullConfig().rootDir);
|
||||
return output;
|
||||
}
|
||||
|
||||
async function createLoader(opts: { [key: string]: any }): Promise<Loader> {
|
||||
if (opts.browser) {
|
||||
const browserOpt = opts.browser.toLowerCase();
|
||||
|
@ -50,7 +50,7 @@ export const Report: React.FC = () => {
|
||||
|
||||
return <div className='hbox'>
|
||||
<SplitView sidebarSize={300} orientation='horizontal' sidebarIsFirst={true}>
|
||||
<TestCaseView testId={testId}></TestCaseView>
|
||||
<TestCaseView key={testId?.testId} testId={testId}></TestCaseView>
|
||||
<div className='suite-tree-column'>
|
||||
<div className='tab-strip'>{
|
||||
(['Failing', 'All'] as Filter[]).map(item => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user