chore: support multiple merged reports (#22672)

This commit is contained in:
Yury Semikhatsky 2023-04-27 09:15:24 -07:00 committed by GitHub
parent e50e2e6bc9
commit 82670147b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 63 additions and 8 deletions

View File

@ -98,7 +98,7 @@ function addMergeReportsCommand(program: Command) {
}
});
command.option('-c, --config <file>', `Configuration file. Can be used to specify additional configuration for the output report.`);
command.option('--reporter <reporter>', 'Output report type', 'list');
command.option('--reporter <reporter...>', 'Output report type', 'list');
command.addHelpText('afterAll', `
Arguments [dir]:
Directory containing blob reports.
@ -178,10 +178,10 @@ async function mergeReports(reportDir: string | undefined, opts: { [key: string]
const configLoader = new ConfigLoader();
const config = await (configFile ? configLoader.loadConfigFile(configFile) : configLoader.loadEmptyConfig(process.cwd()));
const dir = path.resolve(process.cwd(), reportDir || 'playwright-report');
const dir = path.resolve(process.cwd(), reportDir || '');
if (!(await fs.promises.stat(dir)).isDirectory())
throw new Error('Directory does not exist: ' + dir);
await createMergedReport(config, dir, opts.reporter || 'list');
await createMergedReport(config, dir, opts.reporter || ['list']);
}
function overridesFromOptions(options: { [key: string]: any }): ConfigCLIOverrides {

View File

@ -29,6 +29,7 @@ import { TeleReporterReceiver, type JsonEvent, type JsonProject, type JsonSuite,
import { createReporters } from '../runner/reporters';
import { defaultReportFolder } from './html';
import { TeleReporterEmitter } from './teleEmitter';
import { Multiplexer } from './multiplexer';
type BlobReporterOptions = {
@ -104,7 +105,7 @@ export class BlobReporter extends TeleReporterEmitter {
}
}
export async function createMergedReport(config: FullConfigInternal, dir: string, reporterName?: string) {
export async function createMergedReport(config: FullConfigInternal, dir: string, reporterNames: string[]) {
const shardFiles = await sortedShardFiles(dir);
const resourceDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'playwright-report-'));
await fs.promises.mkdir(resourceDir, { recursive: true });
@ -113,10 +114,8 @@ export async function createMergedReport(config: FullConfigInternal, dir: string
const events = mergeEvents(shardReports);
patchAttachmentPaths(events, resourceDir);
reporterName ??= 'list';
const reporters = await createReporters(config, 'merge', [reporterName]);
const receiver = new TeleReporterReceiver(path.sep, reporters[0]);
const reporters = await createReporters(config, 'merge', reporterNames);
const receiver = new TeleReporterReceiver(path.sep, new Multiplexer(reporters));
for (const event of events)
await receiver.dispatch(event);
} finally {

View File

@ -310,4 +310,60 @@ test('preserve attachments', async ({ runInlineTest, mergeReports, showReport, p
await page.getByText('failing 1').click();
await expect(page.getByText('\'text-attachment\', { body: \'hi!\'')).toBeVisible();
});
test('multiple output reports', async ({ runInlineTest, mergeReports, showReport, page }) => {
test.slow();
const reportDir = test.info().outputPath('blob-report');
const files = {
'playwright.config.ts': `
module.exports = {
retries: 1,
reporter: [['blob', { outputDir: '${reportDir.replace(/\\/g, '/')}' }]]
};
`,
'a.test.js': `
import { test, expect } from '@playwright/test';
import fs from 'fs';
test('first', async ({}) => {
const attachmentPath = test.info().outputPath('foo.txt');
fs.writeFileSync(attachmentPath, 'hello!');
await test.info().attach('file-attachment', {path: attachmentPath});
console.log('console info');
console.error('console error');
});
test('failing 1', async ({}) => {
await test.info().attach('text-attachment', { body: 'hi!' });
expect(1).toBe(2);
});
test.skip('skipped 1', async ({}) => {});
`,
'b.test.js': `
import { test, expect } from '@playwright/test';
test('math 2', async ({}) => { });
test('failing 2', async ({}) => {
expect(1).toBe(2);
});
test.skip('skipped 2', async ({}) => {});
`
};
await runInlineTest(files, { shard: `1/2` });
const reportFiles = await fs.promises.readdir(reportDir);
reportFiles.sort();
expect(reportFiles).toEqual(['report-1-of-2.zip']);
const { exitCode, output } = await mergeReports(reportDir, { 'PW_TEST_DEBUG_REPORTERS': '1' }, { additionalArgs: ['--reporter', 'html', '--reporter', 'line'] });
expect(exitCode).toBe(0);
// Check that line reporter was called.
const text = stripAnsi(output);
expect(text).toContain('Running 3 tests using 1 worker');
expect(text).toContain('[1/3] a.test.js:5:11 first');
expect(text).toContain('a.test.js:13:11 failing 1 (retry #1)');
// Check html report presence.
await showReport();
await expect(page.getByText('first')).toBeVisible();
});