This commit is contained in:
parent
eed73de573
commit
9a5172e6c1
|
|
@ -110,15 +110,17 @@ async function extractAndParseReports(dir: string, shardFiles: string[], interna
|
||||||
const shardEvents: { file: string, localPath: string, metadata: BlobReportMetadata, parsedEvents: JsonEvent[] }[] = [];
|
const shardEvents: { file: string, localPath: string, metadata: BlobReportMetadata, parsedEvents: JsonEvent[] }[] = [];
|
||||||
await fs.promises.mkdir(path.join(dir, 'resources'), { recursive: true });
|
await fs.promises.mkdir(path.join(dir, 'resources'), { recursive: true });
|
||||||
|
|
||||||
|
const reportNames = new UniqueFileNameGenerator();
|
||||||
for (const file of shardFiles) {
|
for (const file of shardFiles) {
|
||||||
const absolutePath = path.join(dir, file);
|
const absolutePath = path.join(dir, file);
|
||||||
printStatus(`extracting: ${relativeFilePath(absolutePath)}`);
|
printStatus(`extracting: ${relativeFilePath(absolutePath)}`);
|
||||||
const zipFile = new ZipFile(absolutePath);
|
const zipFile = new ZipFile(absolutePath);
|
||||||
const entryNames = await zipFile.entries();
|
const entryNames = await zipFile.entries();
|
||||||
for (const entryName of entryNames.sort()) {
|
for (const entryName of entryNames.sort()) {
|
||||||
const fileName = path.join(dir, entryName);
|
let fileName = path.join(dir, entryName);
|
||||||
const content = await zipFile.read(entryName);
|
const content = await zipFile.read(entryName);
|
||||||
if (entryName.endsWith('.jsonl')) {
|
if (entryName.endsWith('.jsonl')) {
|
||||||
|
fileName = reportNames.makeUnique(fileName);
|
||||||
const parsedEvents = parseCommonEvents(content);
|
const parsedEvents = parseCommonEvents(content);
|
||||||
// Passing reviver to JSON.parse doesn't work, as the original strings
|
// Passing reviver to JSON.parse doesn't work, as the original strings
|
||||||
// keep beeing used. To work around that we traverse the parsed events
|
// keep beeing used. To work around that we traverse the parsed events
|
||||||
|
|
@ -285,6 +287,27 @@ function printStatusToStdout(message: string) {
|
||||||
process.stdout.write(`${message}\n`);
|
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 {
|
class IdsPatcher {
|
||||||
constructor(private _stringPool: StringInternPool, private _reportName: string | undefined, private _salt: string) {
|
constructor(private _stringPool: StringInternPool, private _reportName: string | undefined, private _salt: string) {
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.`);
|
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');
|
||||||
|
});
|
||||||
Loading…
Reference in a new issue