mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
chore(blob): change file name to report{-suffix}{-shard}.zip (#24592)
This commit is contained in:
parent
be1e8e061e
commit
8e2f33673b
@ -49,3 +49,7 @@ export async function copyFileAndMakeWritable(from: string, to: string) {
|
||||
await fs.promises.copyFile(from, to);
|
||||
await fs.promises.chmod(to, 0o664);
|
||||
}
|
||||
|
||||
export function sanitizeForFilePath(s: string) {
|
||||
return s.replace(/[\x00-\x2C\x2E-\x2F\x3A-\x40\x5B-\x60\x7B-\x7F]+/g, '-');
|
||||
}
|
||||
|
||||
@ -19,10 +19,10 @@ import type { Page as PageEx } from 'playwright-core/lib/client/page';
|
||||
import type { Locator as LocatorEx } from 'playwright-core/lib/client/locator';
|
||||
import { currentTestInfo, currentExpectTimeout } from '../common/globals';
|
||||
import type { ImageComparatorOptions, Comparator } from 'playwright-core/lib/utils';
|
||||
import { getComparator } from 'playwright-core/lib/utils';
|
||||
import { getComparator, sanitizeForFilePath } from 'playwright-core/lib/utils';
|
||||
import type { PageScreenshotOptions } from 'playwright-core/types/types';
|
||||
import {
|
||||
addSuffixToFilePath, serializeError, sanitizeForFilePath,
|
||||
addSuffixToFilePath, serializeError,
|
||||
trimLongString, callLogText,
|
||||
expectTypes } from '../util';
|
||||
import { colors } from 'playwright-core/lib/utilsBundle';
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { ManualPromise, calculateSha1, createGuid, removeFolders } from 'playwright-core/lib/utils';
|
||||
import { ManualPromise, calculateSha1, createGuid, removeFolders, sanitizeForFilePath } from 'playwright-core/lib/utils';
|
||||
import { mime } from 'playwright-core/lib/utilsBundle';
|
||||
import { Readable } from 'stream';
|
||||
import type { EventEmitter } from 'events';
|
||||
@ -44,6 +44,7 @@ export class BlobReporter extends TeleReporterEmitter {
|
||||
private readonly _attachments: { originalPath: string, zipEntryPath: string }[] = [];
|
||||
private readonly _options: BlobReporterOptions;
|
||||
private readonly _salt: string;
|
||||
private _reportName!: string;
|
||||
|
||||
constructor(options: BlobReporterOptions) {
|
||||
super(message => this._messages.push(message), false);
|
||||
@ -62,6 +63,7 @@ export class BlobReporter extends TeleReporterEmitter {
|
||||
params: metadata
|
||||
});
|
||||
|
||||
this._reportName = this._computeReportName(config);
|
||||
super.onConfigure(config);
|
||||
}
|
||||
|
||||
@ -73,16 +75,14 @@ export class BlobReporter extends TeleReporterEmitter {
|
||||
await removeFolders([outputDir]);
|
||||
await fs.promises.mkdir(outputDir, { recursive: true });
|
||||
|
||||
const reportName = `report-${createGuid()}`;
|
||||
|
||||
const zipFile = new yazl.ZipFile();
|
||||
const zipFinishPromise = new ManualPromise<undefined>();
|
||||
const finishPromise = zipFinishPromise.catch(e => {
|
||||
throw new Error(`Failed to write report ${reportName + '.zip'}: ` + e.message);
|
||||
throw new Error(`Failed to write report ${this._reportName + '.zip'}: ` + e.message);
|
||||
});
|
||||
|
||||
(zipFile as any as EventEmitter).on('error', error => zipFinishPromise.reject(error));
|
||||
const zipFileName = path.join(outputDir, reportName + '.zip');
|
||||
const zipFileName = path.join(outputDir, this._reportName + '.zip');
|
||||
zipFile.outputStream.pipe(fs.createWriteStream(zipFileName)).on('close', () => {
|
||||
zipFinishPromise.resolve(undefined);
|
||||
}).on('error', error => zipFinishPromise.reject(error));
|
||||
@ -95,12 +95,23 @@ export class BlobReporter extends TeleReporterEmitter {
|
||||
|
||||
const lines = this._messages.map(m => JSON.stringify(m) + '\n');
|
||||
const content = Readable.from(lines);
|
||||
zipFile.addReadStream(content, reportName + '.jsonl');
|
||||
zipFile.addReadStream(content, this._reportName + '.jsonl');
|
||||
zipFile.end();
|
||||
|
||||
await finishPromise;
|
||||
}
|
||||
|
||||
private _computeReportName(config: FullConfig) {
|
||||
let reportName = 'report';
|
||||
if (process.env.PWTEST_BLOB_SUFFIX)
|
||||
reportName += sanitizeForFilePath(process.env.PWTEST_BLOB_SUFFIX);
|
||||
if (config.shard) {
|
||||
const paddedNumber = `${config.shard.current}`.padStart(`${config.shard.total}`.length, '0');
|
||||
reportName += `-${paddedNumber}`;
|
||||
}
|
||||
return reportName;
|
||||
}
|
||||
|
||||
override _serializeAttachments(attachments: TestResult['attachments']): JsonAttachment[] {
|
||||
return super._serializeAttachments(attachments).map(attachment => {
|
||||
if (!attachment.path)
|
||||
|
||||
@ -20,11 +20,11 @@ import path from 'path';
|
||||
import type { TransformCallback } from 'stream';
|
||||
import { Transform } from 'stream';
|
||||
import type { FullConfig, Suite } from '../../types/testReporter';
|
||||
import { HttpServer, assert, calculateSha1, copyFileAndMakeWritable, gracefullyProcessExitDoNotHang, removeFolders } from 'playwright-core/lib/utils';
|
||||
import { HttpServer, assert, calculateSha1, copyFileAndMakeWritable, gracefullyProcessExitDoNotHang, removeFolders, sanitizeForFilePath } from 'playwright-core/lib/utils';
|
||||
import type { JsonAttachment, JsonReport, JsonSuite, JsonTestCase, JsonTestResult, JsonTestStep } from './raw';
|
||||
import RawReporter from './raw';
|
||||
import { stripAnsiEscapes } from './base';
|
||||
import { resolveReporterOutputPath, sanitizeForFilePath } from '../util';
|
||||
import { resolveReporterOutputPath } from '../util';
|
||||
import type { Metadata } from '../../types/test';
|
||||
import type { ZipFile } from 'playwright-core/lib/zipBundle';
|
||||
import { yazl } from 'playwright-core/lib/zipBundle';
|
||||
|
||||
@ -229,7 +229,7 @@ function mergeEndEvents(endEvents: JsonEvent[]): JsonEvent {
|
||||
|
||||
async function sortedShardFiles(dir: string) {
|
||||
const files = await fs.promises.readdir(dir);
|
||||
return files.filter(file => file.startsWith('report-') && file.endsWith('.zip')).sort();
|
||||
return files.filter(file => file.startsWith('report') && file.endsWith('.zip')).sort();
|
||||
}
|
||||
|
||||
function printStatusToStdout(message: string) {
|
||||
|
||||
@ -17,8 +17,7 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import type { FullConfig, Location, Suite, TestCase, TestResult, TestStatus, TestStep } from '../../types/testReporter';
|
||||
import { assert } from 'playwright-core/lib/utils';
|
||||
import { sanitizeForFilePath } from '../util';
|
||||
import { assert, sanitizeForFilePath } from 'playwright-core/lib/utils';
|
||||
import { formatResultFailure } from './base';
|
||||
import { toPosixPath, serializePatterns } from './json';
|
||||
import { MultiMap } from 'playwright-core/lib/utils';
|
||||
|
||||
@ -23,7 +23,7 @@ import url from 'url';
|
||||
import { colors, debug, minimatch, parseStackTraceLine } from 'playwright-core/lib/utilsBundle';
|
||||
import type { TestInfoError } from './../types/test';
|
||||
import type { Location } from './../types/testReporter';
|
||||
import { calculateSha1, isRegExp, isString } from 'playwright-core/lib/utils';
|
||||
import { calculateSha1, isRegExp, isString, sanitizeForFilePath } from 'playwright-core/lib/utils';
|
||||
import type { RawStack } from 'playwright-core/lib/utils';
|
||||
|
||||
const PLAYWRIGHT_TEST_PATH = path.join(__dirname, '..');
|
||||
@ -195,10 +195,6 @@ export function expectTypes(receiver: any, types: string[], matcherName: string)
|
||||
}
|
||||
}
|
||||
|
||||
export function sanitizeForFilePath(s: string) {
|
||||
return s.replace(/[\x00-\x2C\x2E-\x2F\x3A-\x40\x5B-\x60\x7B-\x7F]+/g, '-');
|
||||
}
|
||||
|
||||
export function trimLongString(s: string, length = 100) {
|
||||
if (s.length <= length)
|
||||
return s;
|
||||
|
||||
@ -16,14 +16,14 @@
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { MaxTime, captureRawStack, createAfterActionTraceEventForStep, createBeforeActionTraceEventForStep, monotonicTime, zones } from 'playwright-core/lib/utils';
|
||||
import { MaxTime, captureRawStack, createAfterActionTraceEventForStep, createBeforeActionTraceEventForStep, monotonicTime, zones, sanitizeForFilePath } from 'playwright-core/lib/utils';
|
||||
import type { TestInfoError, TestInfo, TestStatus, FullProject, FullConfig } from '../../types/test';
|
||||
import type { AttachmentPayload, StepBeginPayload, StepEndPayload, WorkerInitParams } from '../common/ipc';
|
||||
import type { TestCase } from '../common/test';
|
||||
import { TimeoutManager } from './timeoutManager';
|
||||
import type { Annotation, FullConfigInternal, FullProjectInternal } from '../common/config';
|
||||
import type { Location } from '../../types/testReporter';
|
||||
import { getContainedPath, normalizeAndSaveAttachment, sanitizeForFilePath, serializeError, trimLongString } from '../util';
|
||||
import { getContainedPath, normalizeAndSaveAttachment, serializeError, trimLongString } from '../util';
|
||||
import type * as trace from '@trace/trace';
|
||||
|
||||
export interface TestStepInternal {
|
||||
|
||||
@ -381,7 +381,7 @@ test('merge into list report by default', async ({ runInlineTest, mergeReports }
|
||||
await runInlineTest(files, { shard: `${i + 1}/${totalShards}` }, { PWTEST_BLOB_DO_NOT_REMOVE: '1' });
|
||||
const reportFiles = await fs.promises.readdir(reportDir);
|
||||
reportFiles.sort();
|
||||
expect(reportFiles).toEqual([expect.stringMatching(/report-.*.zip/), expect.stringMatching(/report-.*.zip/), expect.stringMatching(/report-.*.zip/)]);
|
||||
expect(reportFiles).toEqual(['report-1.zip', 'report-2.zip', 'report-3.zip']);
|
||||
const { exitCode, output } = await mergeReports(reportDir, { PW_TEST_DEBUG_REPORTERS: '1', PW_TEST_DEBUG_REPORTERS_PRINT_STEPS: '1', PWTEST_TTY_WIDTH: '80' }, { additionalArgs: ['--reporter', 'list'] });
|
||||
expect(exitCode).toBe(0);
|
||||
|
||||
@ -460,7 +460,7 @@ test('should print progress', async ({ runInlineTest, mergeReports }) => {
|
||||
await runInlineTest(files, { shard: `2/2` }, { PWTEST_BLOB_DO_NOT_REMOVE: '1' });
|
||||
const reportFiles = await fs.promises.readdir(reportDir);
|
||||
reportFiles.sort();
|
||||
expect(reportFiles).toEqual([expect.stringMatching(/report-.*.zip/), expect.stringMatching(/report-.*.zip/)]);
|
||||
expect(reportFiles).toEqual(['report-1.zip', 'report-2.zip']);
|
||||
const { exitCode, output } = await mergeReports(reportDir, { PW_TEST_HTML_REPORT_OPEN: 'never' }, { additionalArgs: ['--reporter', 'html'] });
|
||||
expect(exitCode).toBe(0);
|
||||
|
||||
@ -511,7 +511,7 @@ test('preserve attachments', async ({ runInlineTest, mergeReports, showReport, p
|
||||
|
||||
const reportFiles = await fs.promises.readdir(reportDir);
|
||||
reportFiles.sort();
|
||||
expect(reportFiles).toEqual([expect.stringMatching(/report-.*.zip/)]);
|
||||
expect(reportFiles).toEqual(['report-1.zip']);
|
||||
const { exitCode } = await mergeReports(reportDir, { 'PW_TEST_HTML_REPORT_OPEN': 'never' }, { additionalArgs: ['--reporter', 'html'] });
|
||||
expect(exitCode).toBe(0);
|
||||
|
||||
@ -574,7 +574,7 @@ test('generate html with attachment urls', async ({ runInlineTest, mergeReports,
|
||||
|
||||
const reportFiles = await fs.promises.readdir(reportDir);
|
||||
reportFiles.sort();
|
||||
expect(reportFiles).toEqual([expect.stringMatching(/report-.*.zip/)]);
|
||||
expect(reportFiles).toEqual(['report-1.zip']);
|
||||
const { exitCode } = await mergeReports(reportDir, { 'PW_TEST_HTML_REPORT_OPEN': 'never' }, { additionalArgs: ['--reporter', 'html'] });
|
||||
expect(exitCode).toBe(0);
|
||||
|
||||
@ -648,7 +648,7 @@ test('resource names should not clash between runs', async ({ runInlineTest, sho
|
||||
|
||||
const reportFiles = await fs.promises.readdir(reportDir);
|
||||
reportFiles.sort();
|
||||
expect(reportFiles).toEqual([expect.stringMatching(/report-.*.zip/), expect.stringMatching(/report-.*.zip/)]);
|
||||
expect(reportFiles).toEqual(['report-1.zip', 'report-2.zip']);
|
||||
|
||||
const { exitCode } = await mergeReports(reportDir, {}, { additionalArgs: ['--reporter', 'html'] });
|
||||
expect(exitCode).toBe(0);
|
||||
@ -723,7 +723,7 @@ test('multiple output reports', async ({ runInlineTest, mergeReports, showReport
|
||||
|
||||
const reportFiles = await fs.promises.readdir(reportDir);
|
||||
reportFiles.sort();
|
||||
expect(reportFiles).toEqual([expect.stringMatching(/report-.*.zip/)]);
|
||||
expect(reportFiles).toEqual(['report-1.zip']);
|
||||
const { exitCode, output } = await mergeReports(reportDir, { 'PW_TEST_HTML_REPORT_OPEN': 'never' }, { additionalArgs: ['--reporter', 'html,line'] });
|
||||
expect(exitCode).toBe(0);
|
||||
|
||||
@ -784,7 +784,7 @@ test('multiple output reports based on config', async ({ runInlineTest, mergeRep
|
||||
|
||||
const reportFiles = await fs.promises.readdir(reportDir);
|
||||
reportFiles.sort();
|
||||
expect(reportFiles).toEqual([expect.stringMatching(/report-.*.zip/), expect.stringMatching(/report-.*.zip/)]);
|
||||
expect(reportFiles).toEqual(['report-1.zip', 'report-2.zip']);
|
||||
const { exitCode, output } = await mergeReports(reportDir, undefined, { additionalArgs: ['--config', test.info().outputPath('merged/playwright.config.ts')] });
|
||||
expect(exitCode).toBe(0);
|
||||
|
||||
@ -799,7 +799,7 @@ test('multiple output reports based on config', async ({ runInlineTest, mergeRep
|
||||
|
||||
// Check report presence.
|
||||
const mergedBlobReportFiles = await fs.promises.readdir(test.info().outputPath('merged/merged-blob'));
|
||||
expect(mergedBlobReportFiles).toEqual([expect.stringMatching(/report.*.zip/)]);
|
||||
expect(mergedBlobReportFiles).toEqual(['report.zip']);
|
||||
});
|
||||
|
||||
test('onError in the report', async ({ runInlineTest, mergeReports, showReport, page }) => {
|
||||
@ -930,7 +930,7 @@ test('preserve config fields', async ({ runInlineTest, mergeReports }) => {
|
||||
|
||||
const reportFiles = await fs.promises.readdir(reportDir);
|
||||
reportFiles.sort();
|
||||
expect(reportFiles).toEqual([expect.stringMatching(/report-.*.zip/), expect.stringMatching(/report-.*.zip/)]);
|
||||
expect(reportFiles).toEqual(['report-1.zip', 'report-3.zip']);
|
||||
const { exitCode } = await mergeReports(reportDir, {}, { additionalArgs: ['--reporter', test.info().outputPath('echo-reporter.js'), '-c', test.info().outputPath('merge.config.ts')] });
|
||||
expect(exitCode).toBe(0);
|
||||
const json = JSON.parse(fs.readFileSync(test.info().outputPath('config.json')).toString());
|
||||
@ -1087,7 +1087,7 @@ test('preserve steps in html report', async ({ runInlineTest, mergeReports, show
|
||||
await runInlineTest(files);
|
||||
const reportFiles = await fs.promises.readdir(reportDir);
|
||||
reportFiles.sort();
|
||||
expect(reportFiles).toEqual([expect.stringMatching(/report-.*.zip/)]);
|
||||
expect(reportFiles).toEqual(['report.zip']);
|
||||
// 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');
|
||||
@ -1146,7 +1146,12 @@ test('custom project suffix', async ({ runInlineTest, mergeReports }) => {
|
||||
`,
|
||||
};
|
||||
|
||||
await runInlineTest(files, undefined, { PWTEST_BLOB_SUFFIX: '-suffix' });
|
||||
await runInlineTest(files, { shard: `1/2` }, { PWTEST_BLOB_SUFFIX: '-suffix', PWTEST_BLOB_DO_NOT_REMOVE: '1' });
|
||||
await runInlineTest(files, { shard: `2/2` }, { PWTEST_BLOB_SUFFIX: '-suffix', PWTEST_BLOB_DO_NOT_REMOVE: '1' });
|
||||
|
||||
const reportFiles = await fs.promises.readdir(reportDir);
|
||||
reportFiles.sort();
|
||||
expect(reportFiles).toEqual(['report-suffix-1.zip', 'report-suffix-2.zip']);
|
||||
|
||||
const { exitCode, output } = await mergeReports(reportDir, {}, { additionalArgs: ['--reporter', test.info().outputPath('echo-reporter.js')] });
|
||||
expect(exitCode).toBe(0);
|
||||
@ -1235,7 +1240,7 @@ test('blob-report should include version', async ({ runInlineTest }) => {
|
||||
};
|
||||
await runInlineTest(files);
|
||||
const reportFiles = await fs.promises.readdir(reportDir);
|
||||
expect(reportFiles).toEqual([expect.stringMatching(/report-.*.zip/)]);
|
||||
expect(reportFiles).toEqual(['report.zip']);
|
||||
|
||||
await extractZip(test.info().outputPath('blob-report', reportFiles[0]), { dir: test.info().outputPath('blob-report') });
|
||||
const reportFile = test.info().outputPath('blob-report', reportFiles[0].replace(/\.zip$/, '.jsonl'));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user