fix(html-reporter): file-browser friendly extensions (#14943)

Fixes #14904.

This is done to make looking at the raw contents of the report
friendlier when using a file browser. However, it should be noted, the
public API of the HTML Reporter makes no guarantees of its contents
structure/layout/naming-conventions.
This commit is contained in:
Ross Wollman 2022-06-17 08:09:49 -07:00 committed by GitHub
parent 6fa5532ce1
commit b9114f9cbc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 2 deletions

View File

@ -27,10 +27,11 @@ import { removeFolders } from 'playwright-core/lib/utils/fileUtils';
import type { JsonAttachment, JsonReport, JsonSuite, JsonTestCase, JsonTestResult, JsonTestStep } from './raw';
import RawReporter from './raw';
import { stripAnsiEscapes } from './base';
import { getPackageJsonPath } from '../util';
import { getPackageJsonPath, sanitizeForFilePath } from '../util';
import type { FullConfigInternal, Metadata } from '../types';
import type { ZipFile } from 'playwright-core/lib/zipBundle';
import { yazl } from 'playwright-core/lib/zipBundle';
import { mime } from 'playwright-core/lib/utilsBundle';
export type Stats = {
total: number;
@ -463,7 +464,8 @@ class HtmlBuilder {
}
fs.mkdirSync(path.join(this._reportFolder, 'data'), { recursive: true });
const sha1 = calculateSha1(a.body) + '.dat';
const extension = sanitizeForFilePath(path.extname(a.name).replace(/^\./, '')) || mime.getExtension(a.contentType) || 'dat';
const sha1 = calculateSha1(a.body) + '.' + extension;
fs.writeFileSync(path.join(this._reportFolder, 'data', sha1), a.body);
return {
name: a.name,

View File

@ -15,6 +15,7 @@
*/
import fs from 'fs';
import path from 'path';
import { test as baseTest, expect, createImage } from './playwright-test-fixtures';
import type { HttpServer } from '../../packages/playwright-core/lib/utils/httpServer';
import { startHtmlReportServer } from '../../packages/playwright-test/lib/reporters/html';
@ -591,6 +592,33 @@ test('should render text attachments as text', async ({ runInlineTest, page, sho
await expect(page.locator('.attachment-body')).toHaveText(['foo', '{"foo":1}', 'utf16 encoded']);
});
test('should use file-browser friendly extensions for buffer attachments based on contentType', async ({ runInlineTest }, testInfo) => {
const result = await runInlineTest({
'a.test.js': `
const { test } = pwt;
test('passing', async ({ page }, testInfo) => {
await testInfo.attach('screenshot', { body: await page.screenshot(), contentType: 'image/png' });
await testInfo.attach('some-pdf', { body: Buffer.from('foo'), contentType: 'application/pdf' });
await testInfo.attach('madeup-contentType', { body: Buffer.from('bar'), contentType: 'madeup' });
await testInfo.attach('screenshot-that-already-has-an-extension-with-madeup.png', { body: Buffer.from('a'), contentType: 'madeup' });
await testInfo.attach('screenshot-that-already-has-an-extension-with-correct-contentType.png', { body: Buffer.from('c'), contentType: 'image/png' });
await testInfo.attach('example.ext with spaces', { body: Buffer.from('b'), contentType: 'madeup' });
});
`,
}, { reporter: 'dot,html' }, { PW_TEST_HTML_REPORT_OPEN: 'never' });
expect(result.exitCode).toBe(0);
const files = await fs.promises.readdir(path.join(testInfo.outputPath('playwright-report'), 'data'));
expect(new Set(files)).toEqual(new Set([
'f6aa9785bc9c7b8fd40c3f6ede6f59112a939527.png', // screenshot
'0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33.pdf', // some-pdf
'62cdb7020ff920e5aa642c3d4066950dd1f01f4d.dat', // madeup-contentType
'86f7e437faa5a7fce15d1ddcb9eaeaea377667b8.png', // screenshot-that-already-has-an-extension-with-madeup.png
'84a516841ba77a5b4648de2cd0dfcb30ea46dbb4.png', // screenshot-that-already-has-an-extension-with-correct-contentType.png
'e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98.ext-with-spaces', // example.ext with spaces
]));
});
test('should strikethough textual diff', async ({ runInlineTest, showReport, page }) => {
const result = await runInlineTest({
'helper.ts': `