mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
feat(screenshot): create directories for screenshot file
This commit is contained in:
parent
0e9793c452
commit
dfa1f103af
@ -20,6 +20,7 @@ import { Protocol } from './protocol';
|
||||
import * as fs from 'fs';
|
||||
import * as util from 'util';
|
||||
import * as types from '../types';
|
||||
import { mkdirIfNeeded } from '../helper';
|
||||
|
||||
export function getExceptionMessage(exceptionDetails: Protocol.Runtime.ExceptionDetails): string {
|
||||
if (exceptionDetails.exception)
|
||||
@ -42,8 +43,10 @@ export async function releaseObject(client: CRSession, objectId: string) {
|
||||
export async function readProtocolStream(client: CRSession, handle: string, path: string | null): Promise<Buffer> {
|
||||
let eof = false;
|
||||
let fd: number | undefined;
|
||||
if (path)
|
||||
if (path) {
|
||||
await mkdirIfNeeded(path);
|
||||
fd = await util.promisify(fs.open)(path, 'w');
|
||||
}
|
||||
const bufs = [];
|
||||
while (!eof) {
|
||||
const response = await client.send('IO.read', {handle});
|
||||
|
@ -20,7 +20,7 @@ import * as util from 'util';
|
||||
import { Page } from './page';
|
||||
import { Events } from './events';
|
||||
import { Readable } from 'stream';
|
||||
import { assert } from './helper';
|
||||
import { assert, mkdirIfNeeded } from './helper';
|
||||
|
||||
export class Download {
|
||||
private _downloadsPath: string;
|
||||
@ -92,8 +92,7 @@ export class Download {
|
||||
|
||||
async _saveAs(downloadPath: string) {
|
||||
const fileName = path.join(this._downloadsPath, this._uuid);
|
||||
// This will harmlessly throw on windows if the dirname is the root directory.
|
||||
await util.promisify(fs.mkdir)(path.dirname(downloadPath), {recursive: true}).catch(() => {});
|
||||
await mkdirIfNeeded(downloadPath);
|
||||
await util.promisify(fs.copyFile)(fileName, downloadPath);
|
||||
}
|
||||
|
||||
|
@ -21,12 +21,14 @@ import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as removeFolder from 'rimraf';
|
||||
import * as util from 'util';
|
||||
import * as path from 'path';
|
||||
import * as types from './types';
|
||||
import { Progress } from './progress';
|
||||
import * as debug from 'debug';
|
||||
|
||||
const removeFolderAsync = util.promisify(removeFolder);
|
||||
const readFileAsync = util.promisify(fs.readFile.bind(fs));
|
||||
const mkdirAsync = util.promisify(fs.mkdir.bind(fs));
|
||||
|
||||
export type RegisteredListener = {
|
||||
emitter: EventEmitter;
|
||||
@ -353,6 +355,12 @@ export function getFromENV(name: string) {
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
export async function mkdirIfNeeded(filePath: string) {
|
||||
// This will harmlessly throw on windows if the dirname is the root directory.
|
||||
await mkdirAsync(path.dirname(filePath), {recursive: true}).catch(() => {});
|
||||
}
|
||||
|
||||
const escapeGlobChars = new Set(['/', '$', '^', '+', '.', '(', ')', '=', '!', '|']);
|
||||
|
||||
export const helper = Helper;
|
||||
|
@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { Events } from './events';
|
||||
import { assert, helper, Listener } from '../../helper';
|
||||
import { assert, helper, Listener, mkdirIfNeeded } from '../../helper';
|
||||
import { TimeoutSettings } from '../../timeoutSettings';
|
||||
import { BindingCallChannel, BindingCallInitializer, PageChannel, PageInitializer, PagePdfParams, FrameWaitForSelectorOptions, FrameDispatchEventOptions, FrameSetContentOptions, FrameGotoOptions, PageReloadOptions, PageGoBackOptions, PageGoForwardOptions, PageScreenshotOptions, FrameClickOptions, FrameDblclickOptions, FrameFillOptions, FrameFocusOptions, FrameTextContentOptions, FrameInnerTextOptions, FrameInnerHTMLOptions, FrameGetAttributeOptions, FrameHoverOptions, FrameSetInputFilesOptions, FrameTypeOptions, FramePressOptions, FrameCheckOptions, FrameUncheckOptions } from '../channels';
|
||||
import { parseError, serializeError } from '../serializers';
|
||||
@ -425,8 +425,10 @@ export class Page extends ChannelOwner<PageChannel, PageInitializer> {
|
||||
async screenshot(options: PageScreenshotOptions & { path?: string } = {}): Promise<Buffer> {
|
||||
return this._wrapApiCall('page.screenshot', async () => {
|
||||
const buffer = Buffer.from((await this._channel.screenshot(options)).binary, 'base64');
|
||||
if (options.path)
|
||||
if (options.path) {
|
||||
await mkdirIfNeeded(options.path);
|
||||
await fsWriteFileAsync(options.path, buffer);
|
||||
}
|
||||
return buffer;
|
||||
});
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ import * as fs from 'fs';
|
||||
import * as mime from 'mime';
|
||||
import * as util from 'util';
|
||||
import * as dom from './dom';
|
||||
import { assert, helper } from './helper';
|
||||
import { assert, helper, mkdirIfNeeded } from './helper';
|
||||
import { Page } from './page';
|
||||
import * as types from './types';
|
||||
import { rewriteErrorMessage } from './utils/stackTrace';
|
||||
@ -153,8 +153,10 @@ export class Screenshotter {
|
||||
if (shouldSetDefaultBackground)
|
||||
await this._page._delegate.setBackgroundColor();
|
||||
progress.throwIfAborted(); // Avoid side effects.
|
||||
if (options.path)
|
||||
if (options.path) {
|
||||
await mkdirIfNeeded(options.path);
|
||||
await util.promisify(fs.writeFile)(options.path, buffer);
|
||||
}
|
||||
if ((options as any).__testHookAfterScreenshot)
|
||||
await (options as any).__testHookAfterScreenshot();
|
||||
return buffer;
|
||||
|
@ -42,6 +42,14 @@ it.skip(!CHROMIUM)('should output a trace', async({browser, page, server, output
|
||||
expect(fs.existsSync(outputFile)).toBe(true);
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should create directories as needed', async({browser, page, server, tmpDir}) => {
|
||||
const filePath = path.join(tmpDir, 'these', 'are', 'directories');
|
||||
await (browser as ChromiumBrowser).startTracing(page, {screenshots: true, path: filePath});
|
||||
await page.goto(server.PREFIX + '/grid.html');
|
||||
await (browser as ChromiumBrowser).stopTracing();
|
||||
expect(fs.existsSync(filePath)).toBe(true);
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should run with custom categories if provided', async({browser, page, outputFile}) => {
|
||||
await (browser as ChromiumBrowser).startTracing(page, {path: outputFile, categories: ['disabled-by-default-v8.cpu_profiler.hires']});
|
||||
await (browser as ChromiumBrowser).stopTracing();
|
||||
|
@ -16,6 +16,9 @@
|
||||
*/
|
||||
import './base.fixture';
|
||||
import utils from './utils';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
|
||||
const { HEADLESS } = testOptions;
|
||||
|
||||
// Firefox headful produces a different image.
|
||||
@ -246,3 +249,19 @@ it.skip(ffheadful)('should work with iframe in shadow', async({page, server, gol
|
||||
await page.goto(server.PREFIX + '/grid-iframe-in-shadow.html');
|
||||
expect(await page.screenshot()).toMatchImage(golden('screenshot-iframe.png'));
|
||||
});
|
||||
|
||||
it('path option should work', async({page, server, golden, tmpDir}) => {
|
||||
await page.setViewportSize({width: 500, height: 500});
|
||||
await page.goto(server.PREFIX + '/grid.html');
|
||||
const outputPath = path.join(tmpDir, 'screenshot.png');
|
||||
await page.screenshot({path: outputPath});
|
||||
expect(await fs.promises.readFile(outputPath)).toMatchImage(golden('screenshot-sanity.png'));
|
||||
});
|
||||
|
||||
it('path option should create subdirectories', async({page, server, golden, tmpDir}) => {
|
||||
await page.setViewportSize({width: 500, height: 500});
|
||||
await page.goto(server.PREFIX + '/grid.html');
|
||||
const outputPath = path.join(tmpDir, 'these', 'are', 'directories', 'screenshot.png');
|
||||
await page.screenshot({path: outputPath});
|
||||
expect(await fs.promises.readFile(outputPath)).toMatchImage(golden('screenshot-sanity.png'));
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user