fix: preserve steps in merged report (#23120)

This commit is contained in:
Yury Semikhatsky 2023-05-18 09:38:49 -07:00 committed by GitHub
parent acdb71878e
commit a1fc8ff07d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 72 additions and 17 deletions

View File

@ -28,7 +28,7 @@ export type JsonConfig = Pick<FullConfig, 'configFile' | 'globalTimeout' | 'maxF
listOnly: boolean;
};
export type MergeReporterConfig = Pick<FullConfig, 'configFile' | 'reportSlowTests' | 'quiet' >;
export type MergeReporterConfig = Pick<FullConfig, 'configFile' | 'quiet' | 'reportSlowTests' | 'rootDir' >;
export type JsonPattern = {
s?: string;
@ -171,7 +171,7 @@ export class TeleReporterReceiver {
}
private _onBegin(config: JsonConfig, projects: JsonProject[]) {
this._rootDir = config.rootDir;
this._rootDir = this._reportConfig?.rootDir || config.rootDir;
for (const project of projects) {
let projectSuite = this._rootSuite.suites.find(suite => suite.project()!.id === project.id);
if (!projectSuite) {
@ -247,6 +247,8 @@ export class TeleReporterReceiver {
};
if (parentStep)
parentStep.steps.push(step);
else
result.steps.push(step);
result.stepMap.set(payload.id, step);
this._reporter.onStepBegin?.(test, result, step);
}
@ -286,6 +288,7 @@ export class TeleReporterReceiver {
const result = { ...baseFullConfig, ...config };
if (this._reportConfig) {
result.configFile = this._reportConfig.configFile;
result.rootDir = this._reportConfig.rootDir;
result.reportSlowTests = this._reportConfig.reportSlowTests;
result.quiet = this._reportConfig.quiet;
}

View File

@ -16,7 +16,7 @@
import fs from 'fs';
import path from 'path';
import type { FullConfig, ReporterDescription } from '../../types/test';
import type { ReporterDescription } from '../../types/test';
import type { FullResult } from '../../types/testReporter';
import type { FullConfigInternal } from '../common/config';
import { TeleReporterReceiver, type JsonEvent, type JsonProject, type JsonSuite, type JsonTestResultEnd, type JsonConfig } from '../isomorphic/teleReceiver';
@ -25,7 +25,7 @@ import { Multiplexer } from './multiplexer';
export async function createMergedReport(config: FullConfigInternal, dir: string, reporterDescriptions: ReporterDescription[], resolvePaths: boolean) {
const shardFiles = await sortedShardFiles(dir);
const events = await mergeEvents(dir, shardFiles, config.config);
const events = await mergeEvents(dir, shardFiles);
if (resolvePaths)
patchAttachmentPaths(events, dir);
@ -53,7 +53,7 @@ function parseEvents(reportJsonl: string): JsonEvent[] {
return reportJsonl.toString().split('\n').filter(line => line.length).map(line => JSON.parse(line)) as JsonEvent[];
}
async function mergeEvents(dir: string, shardReportFiles: string[], reportConfig: FullConfig) {
async function mergeEvents(dir: string, shardReportFiles: string[]) {
const events: JsonEvent[] = [];
const beginEvents: JsonEvent[] = [];
const endEvents: JsonEvent[] = [];
@ -69,10 +69,10 @@ async function mergeEvents(dir: string, shardReportFiles: string[], reportConfig
events.push(event);
}
}
return [mergeBeginEvents(beginEvents, reportConfig), ...events, mergeEndEvents(endEvents), { method: 'onExit', params: undefined }];
return [mergeBeginEvents(beginEvents), ...events, mergeEndEvents(endEvents), { method: 'onExit', params: undefined }];
}
function mergeBeginEvents(beginEvents: JsonEvent[], reportConfig: FullConfig): JsonEvent {
function mergeBeginEvents(beginEvents: JsonEvent[]): JsonEvent {
if (!beginEvents.length)
throw new Error('No begin events found');
const projects: JsonProject[] = [];

View File

@ -47,10 +47,11 @@ const test = baseTest.extend<{
if (options.additionalArgs)
command.push(...options.additionalArgs);
const cwd = options.cwd ? path.resolve(test.info().outputDir, options.cwd) : test.info().outputDir;
const testProcess = childProcess({
command,
env: cleanEnv(env),
cwd: test.info().outputDir,
cwd,
});
const { exitCode } = await testProcess.exited;
return { exitCode, output: testProcess.output.toString() };
@ -409,14 +410,12 @@ test('preserve attachments', async ({ runInlineTest, mergeReports, showReport, p
await showReport();
// Check file attachment.
await page.getByText('first').click();
await expect(page.getByText('file-attachment')).toBeVisible();
// Check file attachment content.
const popupPromise = page.waitForEvent('popup');
await page.getByText('file-attachment').click();
// Check file attachment.
await page.getByRole('link', { name: 'file-attachment' }).click();
const popup = await popupPromise;
// Check file attachment content.
await expect(popup.locator('body')).toHaveText('hello!');
await popup.close();
await page.goBack();
@ -484,15 +483,14 @@ test('generate html with attachment urls', async ({ runInlineTest, mergeReports,
return oldSeveFile.call(server, req, res, filePath);
};
// Check file attachment.
await page.goto(`${server.PREFIX}/index.html`);
await page.getByText('first').click();
await expect(page.getByText('file-attachment')).toBeVisible();
// Check file attachment content.
const popupPromise = page.waitForEvent('popup');
await page.getByText('file-attachment').click();
// Check file attachment.
await page.getByRole('link', { name: 'file-attachment' }).click();
const popup = await popupPromise;
// Check file attachment content.
await expect(popup.locator('body')).toHaveText('hello!');
await popup.close();
await page.goBack();
@ -846,4 +844,58 @@ test('preserve config fields', async ({ runInlineTest, mergeReports }) => {
expect(json.reportSlowTests).toEqual(mergeConfig.reportSlowTests);
expect(json.configFile).toEqual(test.info().outputPath('merge.config.ts'));
expect(json.quiet).toEqual(mergeConfig.quiet);
});
test('preserve steps in html report', async ({ runInlineTest, mergeReports, showReport, page }) => {
test.slow();
const reportDir = test.info().outputPath('blob-report');
const files = {
'playwright.config.ts': `
module.exports = {
reporter: [['blob']]
};
`,
'tests/a.test.js': `
import { test, expect } from '@playwright/test';
test.beforeAll(() => {
expect(1).toBe(1);
})
test('test 1', async ({}) => {
await test.step('my step', async () => {
expect(2).toBe(2);
});
});
`,
};
await runInlineTest(files);
const reportFiles = await fs.promises.readdir(reportDir);
reportFiles.sort();
expect(reportFiles).toEqual([expect.stringMatching(/report-.*.jsonl/), 'resources']);
// Run merger in a different directory to make sure relative paths will not be resolved
// relative to the current directory.
const mergeCwd = test.info().outputPath('foo');
await fs.promises.mkdir(mergeCwd, { recursive: true });
const { exitCode, output } = await mergeReports(reportDir, { 'PW_TEST_HTML_REPORT_OPEN': 'never' }, { additionalArgs: ['--reporter', 'html'], cwd: mergeCwd });
expect(exitCode).toBe(0);
expect(output).toContain('To open last HTML report run:');
await showReport();
await expect(page.locator('.subnav-item:has-text("All") .counter')).toHaveText('1');
await expect(page.locator('.subnav-item:has-text("Passed") .counter')).toHaveText('1');
await page.getByRole('link', { name: 'test 1' }).click();
await page.getByText('Before Hooks').click();
await page.getByText('beforeAll hook').click();
await expect(page.getByText('expect.toBe')).toBeVisible();
// Collapse hooks.
await page.getByText('Before Hooks').click();
await expect(page.getByText('expect.toBe')).not.toBeVisible();
// Check that 'my step' location is relative.
await expect(page.getByText('— tests/a.test.js:7')).toBeVisible();
await page.getByText('my step').click();
await expect(page.getByText('expect.toBe')).toBeVisible();
});