Skip to content

Commit

Permalink
cherry-pick(#26413): fix(merge): allow reports with same name as input (
Browse files Browse the repository at this point in the history
  • Loading branch information
yury-s authored Aug 10, 2023
1 parent eed73de commit 9a5172e
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 1 deletion.
25 changes: 24 additions & 1 deletion packages/playwright-test/src/reporters/merge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,15 +110,17 @@ async function extractAndParseReports(dir: string, shardFiles: string[], interna
const shardEvents: { file: string, localPath: string, metadata: BlobReportMetadata, parsedEvents: JsonEvent[] }[] = [];
await fs.promises.mkdir(path.join(dir, 'resources'), { recursive: true });

const reportNames = new UniqueFileNameGenerator();
for (const file of shardFiles) {
const absolutePath = path.join(dir, file);
printStatus(`extracting: ${relativeFilePath(absolutePath)}`);
const zipFile = new ZipFile(absolutePath);
const entryNames = await zipFile.entries();
for (const entryName of entryNames.sort()) {
const fileName = path.join(dir, entryName);
let fileName = path.join(dir, entryName);
const content = await zipFile.read(entryName);
if (entryName.endsWith('.jsonl')) {
fileName = reportNames.makeUnique(fileName);
const parsedEvents = parseCommonEvents(content);
// Passing reviver to JSON.parse doesn't work, as the original strings
// keep beeing used. To work around that we traverse the parsed events
Expand Down Expand Up @@ -285,6 +287,27 @@ function printStatusToStdout(message: string) {
process.stdout.write(`${message}\n`);
}

class UniqueFileNameGenerator {
private _usedNames = new Set<string>();

makeUnique(name: string): string {
if (!this._usedNames.has(name)) {
this._usedNames.add(name);
return name;
}
const extension = path.extname(name);
name = name.substring(0, name.length - extension.length);
let index = 0;
while (true) {
const candidate = `${name}-${++index}${extension}`;
if (!this._usedNames.has(candidate)) {
this._usedNames.add(candidate);
return candidate;
}
}
}
}

class IdsPatcher {
constructor(private _stringPool: StringInternPool, private _reportName: string | undefined, private _salt: string) {
}
Expand Down
48 changes: 48 additions & 0 deletions tests/playwright-test/reporter-blob.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1324,3 +1324,51 @@ test('merge-reports should throw if report version is from the future', async ({
expect(output).toContain(`Error: Blob report report-2.zip was created with a newer version of Playwright.`);

});

test('should merge blob reports with same name', async ({ runInlineTest, mergeReports, showReport, page }) => {
const files = {
'playwright.config.ts': `
module.exports = {
retries: 1,
reporter: 'blob'
};
`,
'a.test.js': `
import { test, expect } from '@playwright/test';
test('math 1', async ({}) => {
expect(1 + 1).toBe(2);
});
test('failing 1', async ({}) => {
expect(1).toBe(2);
});
test('flaky 1', async ({}) => {
expect(test.info().retry).toBe(1);
});
test.skip('skipped 1', async ({}) => {});
`,
'b.test.js': `
import { test, expect } from '@playwright/test';
test('math 2', async ({}) => {
expect(1 + 1).toBe(2);
});
test('failing 2', async ({}) => {
expect(1).toBe(2);
});
test.skip('skipped 2', async ({}) => {});
`
};
await runInlineTest(files);
const reportZip = test.info().outputPath('blob-report', 'report.zip');
const allReportsDir = test.info().outputPath('all-blob-reports');
await fs.promises.cp(reportZip, path.join(allReportsDir, 'report-1.zip'));
await fs.promises.cp(reportZip, path.join(allReportsDir, 'report-2.zip'));

const { exitCode } = await mergeReports(allReportsDir, { 'PW_TEST_HTML_REPORT_OPEN': 'never' }, { additionalArgs: ['--reporter', 'html'] });
expect(exitCode).toBe(0);
await showReport();
await expect(page.locator('.subnav-item:has-text("All") .counter')).toHaveText('14');
await expect(page.locator('.subnav-item:has-text("Passed") .counter')).toHaveText('4');
await expect(page.locator('.subnav-item:has-text("Failed") .counter')).toHaveText('4');
await expect(page.locator('.subnav-item:has-text("Flaky") .counter')).toHaveText('2');
await expect(page.locator('.subnav-item:has-text("Skipped") .counter')).toHaveText('4');
});

0 comments on commit 9a5172e

Please sign in to comment.