chore(har): attach resources for .zip hars (#14938)

This commit is contained in:
Pavel Feldman 2022-06-16 17:27:25 -08:00 committed by GitHub
parent 2e646ef92a
commit be64e9ce66
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 17 additions and 36 deletions

View File

@ -593,7 +593,7 @@ Logger sink for Playwright logging.
- `omitContent` ?<[boolean]> Optional setting to control whether to omit request content from the HAR. Defaults to
`false`. Deprecated, use `content` policy instead.
- `content` ?<[HarContentPolicy]<"omit"|"embed"|"attach">> Optional setting to control resource content management. If `omit` is specified, content is not persisted. If `attach` is specified, resources are persistet as separate files and all of these files are archived along with the HAR file. Defaults to `embed`, which stores content inline the HAR file as per HAR specification.
- `path` <[path]> Path on the filesystem to write the HAR file to. If the file name ends with `.zip`, the har file is archived. Content `attach` will also enforce `zip` compression.
- `path` <[path]> Path on the filesystem to write the HAR file to. If the file name ends with `.zip`, `attach` mode is used by default.
- `urlFilter` ?<[string]|[RegExp]> A glob or regex pattern to filter requests that are stored in the HAR. When a [`option: baseURL`] via the context options was provided and the passed URL is a path, it gets merged via the [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor.
Enables [HAR](http://www.softwareishard.com/blog/har-12-spec) recording for all pages into `recordHar.path` file. If not

View File

@ -383,7 +383,7 @@ function prepareRecordHarOptions(options: BrowserContextOptions['recordHar']): c
return;
return {
path: options.path,
content: options.content || (options.omitContent ? 'omit' : 'embed'),
content: options.content || (options.omitContent ? 'omit' : undefined),
urlGlob: isString(options.urlFilter) ? options.urlFilter : undefined,
urlRegexSource: isRegExp(options.urlFilter) ? options.urlFilter.source : undefined,
urlRegexFlags: isRegExp(options.urlFilter) ? options.urlFilter.flags : undefined,

View File

@ -265,7 +265,7 @@ export type SerializedError = {
export type RecordHarOptions = {
path: string,
content: 'embed' | 'attach' | 'omit',
content?: 'embed' | 'attach' | 'omit',
urlGlob?: string,
urlRegexSource?: string,
urlRegexFlags?: string,

View File

@ -226,7 +226,7 @@ RecordHarOptions:
properties:
path: string
content:
type: enum
type: enum?
literals:
- embed
- attach

View File

@ -155,7 +155,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
});
scheme.RecordHarOptions = tObject({
path: tString,
content: tEnum(['embed', 'attach', 'omit']),
content: tOptional(tEnum(['embed', 'attach', 'omit'])),
urlGlob: tOptional(tString),
urlRegexSource: tOptional(tString),
urlRegexFlags: tOptional(tString),

View File

@ -37,13 +37,15 @@ export class HarRecorder {
constructor(context: BrowserContext, options: channels.RecordHarOptions) {
this._artifact = new Artifact(context, path.join(context._browser.options.artifactsDir, `${createGuid()}.har`));
const urlFilterRe = options.urlRegexSource !== undefined && options.urlRegexFlags !== undefined ? new RegExp(options.urlRegexSource, options.urlRegexFlags) : undefined;
const expectsZip = options.path.endsWith('.zip');
const content = options.content || (expectsZip ? 'attach' : 'embed');
this._tracer = new HarTracer(context, this, {
content: options.content || 'embed',
content,
waitForContentOnStop: true,
skipScripts: false,
urlFilter: urlFilterRe ?? options.urlGlob,
});
this._zipFile = options.content === 'attach' || options.path.endsWith('.zip') ? new yazl.ZipFile() : null;
this._zipFile = content === 'attach' || expectsZip ? new yazl.ZipFile() : null;
this._tracer.start();
}

View File

@ -10651,8 +10651,7 @@ export interface BrowserType<Unused = {}> {
content?: "omit"|"embed"|"attach";
/**
* Path on the filesystem to write the HAR file to. If the file name ends with `.zip`, the har file is archived. Content
* `attach` will also enforce `zip` compression.
* Path on the filesystem to write the HAR file to. If the file name ends with `.zip`, `attach` mode is used by default.
*/
path: string;
@ -11868,8 +11867,7 @@ export interface AndroidDevice {
content?: "omit"|"embed"|"attach";
/**
* Path on the filesystem to write the HAR file to. If the file name ends with `.zip`, the har file is archived. Content
* `attach` will also enforce `zip` compression.
* Path on the filesystem to write the HAR file to. If the file name ends with `.zip`, `attach` mode is used by default.
*/
path: string;
@ -13468,8 +13466,7 @@ export interface Browser extends EventEmitter {
content?: "omit"|"embed"|"attach";
/**
* Path on the filesystem to write the HAR file to. If the file name ends with `.zip`, the har file is archived. Content
* `attach` will also enforce `zip` compression.
* Path on the filesystem to write the HAR file to. If the file name ends with `.zip`, `attach` mode is used by default.
*/
path: string;
@ -14284,8 +14281,7 @@ export interface Electron {
content?: "omit"|"embed"|"attach";
/**
* Path on the filesystem to write the HAR file to. If the file name ends with `.zip`, the har file is archived. Content
* `attach` will also enforce `zip` compression.
* Path on the filesystem to write the HAR file to. If the file name ends with `.zip`, `attach` mode is used by default.
*/
path: string;
@ -16133,8 +16129,7 @@ export interface BrowserContextOptions {
content?: "omit"|"embed"|"attach";
/**
* Path on the filesystem to write the HAR file to. If the file name ends with `.zip`, the har file is archived. Content
* `attach` will also enforce `zip` compression.
* Path on the filesystem to write the HAR file to. If the file name ends with `.zip`, `attach` mode is used by default.
*/
path: string;

View File

@ -275,30 +275,14 @@ it('should include content @smoke', async ({ contextFactory, server }, testInfo)
expect(log.entries[2].response.content.compression).toBe(0);
});
it('should include content in zip', async ({ contextFactory, server }, testInfo) => {
it('should use attach mode for zip extension', async ({ contextFactory, server }, testInfo) => {
const { page, getZip } = await pageWithHar(contextFactory, testInfo, { outputPath: 'test.har.zip' });
await page.goto(server.PREFIX + '/har.html');
await page.evaluate(() => fetch('/pptr.png').then(r => r.arrayBuffer()));
const zip = await getZip();
const log = JSON.parse(zip.get('har.har').toString())['log'] as Log;
expect(log.entries[0].response.content.encoding).toBe(undefined);
expect(log.entries[0].response.content.mimeType).toBe('text/html; charset=utf-8');
expect(log.entries[0].response.content.text).toContain('HAR Page');
expect(log.entries[0].response.content.size).toBeGreaterThanOrEqual(96);
expect(log.entries[0].response.content.compression).toBe(0);
expect(log.entries[1].response.content.encoding).toBe(undefined);
expect(log.entries[1].response.content.mimeType).toBe('text/css; charset=utf-8');
expect(log.entries[1].response.content.text).toContain('pink');
expect(log.entries[1].response.content.size).toBeGreaterThanOrEqual(37);
expect(log.entries[1].response.content.compression).toBe(0);
expect(log.entries[2].response.content.encoding).toBe('base64');
expect(log.entries[2].response.content.mimeType).toBe('image/png');
expect(Buffer.from(log.entries[2].response.content.text, 'base64').byteLength).toBeGreaterThan(0);
expect(log.entries[2].response.content.size).toBeGreaterThanOrEqual(6000);
expect(log.entries[2].response.content.compression).toBe(0);
expect(log.entries[0].response.content.text).toBe(undefined);
expect(zip.get('75841480e2606c03389077304342fac2c58ccb1b.html').toString()).toContain('HAR Page');
});
it('should omit content', async ({ contextFactory, server }, testInfo) => {