chore: make tracing zero config (#6859)
This commit is contained in:
parent
837ee08a53
commit
b2143a951b
|
|
@ -7,41 +7,40 @@ Playwright script runs.
|
|||
Start with specifying the folder traces will be stored in:
|
||||
|
||||
```js
|
||||
const browser = await chromium.launch({ traceDir: 'traces' });
|
||||
const browser = await chromium.launch();
|
||||
const context = await browser.newContext();
|
||||
await context.tracing.start({ name: 'trace', screenshots: true, snapshots: true });
|
||||
await context.tracing.start({ screenshots: true, snapshots: true });
|
||||
const page = await context.newPage();
|
||||
await page.goto('https://playwright.dev');
|
||||
await context.tracing.stop({ path: 'trace.zip' });
|
||||
```
|
||||
|
||||
```java
|
||||
Browser browser = chromium.launch(new BrowserType.LaunchOptions().setTraceDir("trace"));
|
||||
Browser browser = chromium.launch();
|
||||
BrowserContext context = browser.newContext();
|
||||
context.tracing.start(page, new Tracing.StartOptions()
|
||||
.setName("trace")
|
||||
.setScreenshots(true)
|
||||
.setSnapshots(true);
|
||||
Page page = context.newPage();
|
||||
page.goto("https://playwright.dev");
|
||||
context.tracing.stop(new Tracing.StopOptions()
|
||||
.setSaveAs(Paths.get("trace.zip")));
|
||||
.setPath(Paths.get("trace.zip")));
|
||||
```
|
||||
|
||||
```python async
|
||||
browser = await chromium.launch(traceDir='traces')
|
||||
browser = await chromium.launch()
|
||||
context = await browser.new_context()
|
||||
await context.tracing.start(name="trace", screenshots=True, snapshots=True)
|
||||
await context.tracing.start(screenshots=True, snapshots=True)
|
||||
await page.goto("https://playwright.dev")
|
||||
await context.tracing.stop(save_as = "trace.zip")
|
||||
await context.tracing.stop(path = "trace.zip")
|
||||
```
|
||||
|
||||
```python sync
|
||||
browser = chromium.launch(traceDir='traces')
|
||||
browser = chromium.launch()
|
||||
context = browser.new_context()
|
||||
context.tracing.start(name="trace", screenshots=True, snapshots=True)
|
||||
context.tracing.start(screenshots=True, snapshots=True)
|
||||
page.goto("https://playwright.dev")
|
||||
context.tracing.stop(save_as = "trace.zip")
|
||||
context.tracing.stop(path = "trace.zip")
|
||||
```
|
||||
|
||||
## async method: Tracing.start
|
||||
|
|
@ -49,43 +48,41 @@ context.tracing.stop(save_as = "trace.zip")
|
|||
Start tracing.
|
||||
|
||||
```js
|
||||
await context.tracing.start({ name: 'trace', screenshots: true, snapshots: true });
|
||||
await context.tracing.start({ screenshots: true, snapshots: true });
|
||||
const page = await context.newPage();
|
||||
await page.goto('https://playwright.dev');
|
||||
await context.tracing.stop();
|
||||
await context.tracing.export('trace.zip');
|
||||
await context.tracing.stop({ path: 'trace.zip' });
|
||||
```
|
||||
|
||||
```java
|
||||
context.tracing.start(page, new Tracing.StartOptions()
|
||||
.setName("trace")
|
||||
.setScreenshots(true)
|
||||
.setSnapshots(true);
|
||||
Page page = context.newPage();
|
||||
page.goto('https://playwright.dev');
|
||||
context.tracing.stop();
|
||||
context.tracing.export(Paths.get("trace.zip")))
|
||||
context.tracing.stop(new Tracing.StopOptions()
|
||||
.setPath(Paths.get("trace.zip")));
|
||||
```
|
||||
|
||||
```python async
|
||||
await context.tracing.start(name="trace", screenshots=True, snapshots=True)
|
||||
await page.goto("https://playwright.dev")
|
||||
await context.tracing.stop()
|
||||
await context.tracing.export("trace.zip")
|
||||
await context.tracing.stop(path = "trace.zip")
|
||||
```
|
||||
|
||||
```python sync
|
||||
context.tracing.start(name="trace", screenshots=True, snapshots=True)
|
||||
page.goto("https://playwright.dev")
|
||||
context.tracing.stop()
|
||||
context.tracing.export("trace.zip")
|
||||
context.tracing.stop(path = "trace.zip")
|
||||
```
|
||||
|
||||
### option: Tracing.start.name
|
||||
- `name` <[string]>
|
||||
|
||||
If specified, the trace is going to be saved into the file with the
|
||||
given name inside the [`option: traceDir`] folder specified in [`method: BrowserType.launch`].
|
||||
given name inside the [`option: tracesDir`] folder specified in [`method: BrowserType.launch`].
|
||||
|
||||
### option: Tracing.start.screenshots
|
||||
- `screenshots` <[boolean]>
|
||||
|
|
|
|||
|
|
@ -675,9 +675,9 @@ Logger sink for Playwright logging.
|
|||
Maximum time in milliseconds to wait for the browser instance to start. Defaults to `30000` (30 seconds). Pass `0` to
|
||||
disable timeout.
|
||||
|
||||
## browser-option-tracedir
|
||||
## browser-option-tracesdir
|
||||
* langs: js, python, java
|
||||
- `traceDir` <[path]>
|
||||
- `tracesDir` <[path]>
|
||||
|
||||
If specified, traces are saved into this directory.
|
||||
|
||||
|
|
@ -708,4 +708,4 @@ Slows down Playwright operations by the specified amount of milliseconds. Useful
|
|||
- %%-browser-option-ignoredefaultargs-%%
|
||||
- %%-browser-option-proxy-%%
|
||||
- %%-browser-option-timeout-%%
|
||||
- %%-browser-option-tracedir-%%
|
||||
- %%-browser-option-tracesdir-%%
|
||||
|
|
|
|||
|
|
@ -107,10 +107,8 @@ class ConnectedBrowserDispatcher extends Dispatcher<Browser, channels.BrowserIni
|
|||
}
|
||||
|
||||
async newContext(params: channels.BrowserNewContextParams, metadata: CallMetadata): Promise<channels.BrowserNewContextResult> {
|
||||
if (params.recordVideo) {
|
||||
// TODO: we should create a separate temp directory or accept a launchServer parameter.
|
||||
params.recordVideo.dir = this._object.options.downloadsPath!;
|
||||
}
|
||||
if (params.recordVideo)
|
||||
params.recordVideo.dir = this._object.options.artifactsDir;
|
||||
const context = await this._object.newContext(params);
|
||||
this._contexts.add(context);
|
||||
context._setSelectors(this._selectors);
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ export type BrowserTypeLaunchParams = {
|
|||
password?: string,
|
||||
},
|
||||
downloadsPath?: string,
|
||||
traceDir?: string,
|
||||
tracesDir?: string,
|
||||
chromiumSandbox?: boolean,
|
||||
firefoxUserPrefs?: any,
|
||||
slowMo?: number,
|
||||
|
|
@ -263,7 +263,7 @@ export type BrowserTypeLaunchOptions = {
|
|||
password?: string,
|
||||
},
|
||||
downloadsPath?: string,
|
||||
traceDir?: string,
|
||||
tracesDir?: string,
|
||||
chromiumSandbox?: boolean,
|
||||
firefoxUserPrefs?: any,
|
||||
slowMo?: number,
|
||||
|
|
@ -291,7 +291,7 @@ export type BrowserTypeLaunchPersistentContextParams = {
|
|||
password?: string,
|
||||
},
|
||||
downloadsPath?: string,
|
||||
traceDir?: string,
|
||||
tracesDir?: string,
|
||||
chromiumSandbox?: boolean,
|
||||
sdkLanguage: string,
|
||||
noDefaultViewport?: boolean,
|
||||
|
|
@ -362,7 +362,7 @@ export type BrowserTypeLaunchPersistentContextOptions = {
|
|||
password?: string,
|
||||
},
|
||||
downloadsPath?: string,
|
||||
traceDir?: string,
|
||||
tracesDir?: string,
|
||||
chromiumSandbox?: boolean,
|
||||
noDefaultViewport?: boolean,
|
||||
viewport?: {
|
||||
|
|
|
|||
|
|
@ -249,7 +249,7 @@ LaunchOptions:
|
|||
username: string?
|
||||
password: string?
|
||||
downloadsPath: string?
|
||||
traceDir: string?
|
||||
tracesDir: string?
|
||||
chromiumSandbox: boolean?
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
|
|||
password: tOptional(tString),
|
||||
})),
|
||||
downloadsPath: tOptional(tString),
|
||||
traceDir: tOptional(tString),
|
||||
tracesDir: tOptional(tString),
|
||||
chromiumSandbox: tOptional(tBoolean),
|
||||
firefoxUserPrefs: tOptional(tAny),
|
||||
slowMo: tOptional(tNumber),
|
||||
|
|
@ -200,7 +200,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
|
|||
password: tOptional(tString),
|
||||
})),
|
||||
downloadsPath: tOptional(tString),
|
||||
traceDir: tOptional(tString),
|
||||
tracesDir: tOptional(tString),
|
||||
chromiumSandbox: tOptional(tBoolean),
|
||||
sdkLanguage: tString,
|
||||
noDefaultViewport: tOptional(tBoolean),
|
||||
|
|
|
|||
|
|
@ -265,7 +265,9 @@ export class AndroidDevice extends SdkObject {
|
|||
isChromium: true,
|
||||
slowMo: 0,
|
||||
persistent: { ...options, noDefaultViewport: true },
|
||||
downloadsPath: undefined,
|
||||
artifactsDir: '',
|
||||
downloadsPath: '',
|
||||
tracesDir: '',
|
||||
browserProcess: new ClankBrowserProcess(androidBrowser),
|
||||
proxy: options.proxy,
|
||||
protocolLogger: helper.debugProtocolLogger(),
|
||||
|
|
|
|||
|
|
@ -42,8 +42,9 @@ export type BrowserOptions = PlaywrightOptions & {
|
|||
name: string,
|
||||
isChromium: boolean,
|
||||
channel?: string,
|
||||
downloadsPath?: string,
|
||||
traceDir?: string,
|
||||
artifactsDir: string;
|
||||
downloadsPath: string,
|
||||
tracesDir: string,
|
||||
headful?: boolean,
|
||||
persistent?: types.BrowserContextOptions, // Undefined means no persistent context.
|
||||
browserProcess: BrowserProcess,
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ import { CallMetadata, SdkObject } from './instrumentation';
|
|||
const mkdirAsync = util.promisify(fs.mkdir);
|
||||
const mkdtempAsync = util.promisify(fs.mkdtemp);
|
||||
const existsAsync = (path: string): Promise<boolean> => new Promise(resolve => fs.stat(path, err => resolve(!err)));
|
||||
const DOWNLOADS_FOLDER = path.join(os.tmpdir(), 'playwright_downloads-');
|
||||
const ARTIFACTS_FOLDER = path.join(os.tmpdir(), 'playwright-artifacts-');
|
||||
|
||||
export abstract class BrowserType extends SdkObject {
|
||||
private _name: registry.BrowserName;
|
||||
|
|
@ -97,7 +97,7 @@ export abstract class BrowserType extends SdkObject {
|
|||
async _innerLaunch(progress: Progress, options: types.LaunchOptions, persistent: types.BrowserContextOptions | undefined, protocolLogger: types.ProtocolLogger, userDataDir?: string): Promise<Browser> {
|
||||
options.proxy = options.proxy ? normalizeProxySettings(options.proxy) : undefined;
|
||||
const browserLogsCollector = new RecentLogsCollector();
|
||||
const { browserProcess, downloadsPath, transport } = await this._launchProcess(progress, options, !!persistent, browserLogsCollector, userDataDir);
|
||||
const { browserProcess, artifactsDir, transport } = await this._launchProcess(progress, options, !!persistent, browserLogsCollector, userDataDir);
|
||||
if ((options as any).__testHookBeforeCreateBrowser)
|
||||
await (options as any).__testHookBeforeCreateBrowser();
|
||||
const browserOptions: BrowserOptions = {
|
||||
|
|
@ -108,14 +108,15 @@ export abstract class BrowserType extends SdkObject {
|
|||
slowMo: options.slowMo,
|
||||
persistent,
|
||||
headful: !options.headless,
|
||||
downloadsPath,
|
||||
artifactsDir,
|
||||
downloadsPath: (options.downloadsPath || artifactsDir)!,
|
||||
tracesDir: (options.tracesDir || artifactsDir)!,
|
||||
browserProcess,
|
||||
customExecutablePath: options.executablePath,
|
||||
proxy: options.proxy,
|
||||
protocolLogger,
|
||||
browserLogsCollector,
|
||||
wsEndpoint: options.useWebSocket ? (transport as WebSocketTransport).wsEndpoint : undefined,
|
||||
traceDir: options.traceDir,
|
||||
};
|
||||
if (persistent)
|
||||
validateBrowserContextOptions(persistent, browserOptions);
|
||||
|
|
@ -127,7 +128,7 @@ export abstract class BrowserType extends SdkObject {
|
|||
return browser;
|
||||
}
|
||||
|
||||
private async _launchProcess(progress: Progress, options: types.LaunchOptions, isPersistent: boolean, browserLogsCollector: RecentLogsCollector, userDataDir?: string): Promise<{ browserProcess: BrowserProcess, downloadsPath: string, transport: ConnectionTransport }> {
|
||||
private async _launchProcess(progress: Progress, options: types.LaunchOptions, isPersistent: boolean, browserLogsCollector: RecentLogsCollector, userDataDir?: string): Promise<{ browserProcess: BrowserProcess, artifactsDir: string, transport: ConnectionTransport }> {
|
||||
const {
|
||||
ignoreDefaultArgs,
|
||||
ignoreAllDefaultArgs,
|
||||
|
|
@ -141,19 +142,13 @@ export abstract class BrowserType extends SdkObject {
|
|||
const env = options.env ? envArrayToObject(options.env) : process.env;
|
||||
|
||||
const tempDirectories = [];
|
||||
const ensurePath = async (tmpPrefix: string, pathFromOptions?: string) => {
|
||||
let dir;
|
||||
if (pathFromOptions) {
|
||||
dir = pathFromOptions;
|
||||
await mkdirAsync(pathFromOptions, { recursive: true });
|
||||
} else {
|
||||
dir = await mkdtempAsync(tmpPrefix);
|
||||
tempDirectories.push(dir);
|
||||
}
|
||||
return dir;
|
||||
};
|
||||
// TODO: add downloadsPath to newContext().
|
||||
const downloadsPath = await ensurePath(DOWNLOADS_FOLDER, options.downloadsPath);
|
||||
if (options.downloadsPath)
|
||||
await mkdirAsync(options.downloadsPath, { recursive: true });
|
||||
if (options.tracesDir)
|
||||
await mkdirAsync(options.tracesDir, { recursive: true });
|
||||
|
||||
const artifactsDir = await mkdtempAsync(ARTIFACTS_FOLDER);
|
||||
tempDirectories.push(artifactsDir);
|
||||
|
||||
if (!userDataDir) {
|
||||
userDataDir = await mkdtempAsync(path.join(os.tmpdir(), `playwright_${this._name}dev_profile-`));
|
||||
|
|
@ -252,7 +247,7 @@ export abstract class BrowserType extends SdkObject {
|
|||
const stdio = launchedProcess.stdio as unknown as [NodeJS.ReadableStream, NodeJS.WritableStream, NodeJS.WritableStream, NodeJS.WritableStream, NodeJS.ReadableStream];
|
||||
transport = new PipeTransport(stdio[3], stdio[4]);
|
||||
}
|
||||
return { browserProcess, downloadsPath, transport };
|
||||
return { browserProcess, artifactsDir, transport };
|
||||
}
|
||||
|
||||
async connectOverCDP(metadata: CallMetadata, endpointURL: string, options: { slowMo?: number, sdkLanguage: string }, timeout?: number): Promise<Browser> {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,10 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
import util from 'util';
|
||||
import { CRBrowser } from './crBrowser';
|
||||
import { Env } from '../processLauncher';
|
||||
import { kBrowserCloseMessageId } from './crConnection';
|
||||
|
|
@ -25,7 +28,7 @@ import { ConnectionTransport, ProtocolRequest, WebSocketTransport } from '../tra
|
|||
import { CRDevTools } from './crDevTools';
|
||||
import { BrowserOptions, BrowserProcess, PlaywrightOptions } from '../browser';
|
||||
import * as types from '../types';
|
||||
import { debugMode, headersArrayToObject } from '../../utils/utils';
|
||||
import { debugMode, headersArrayToObject, removeFolders } from '../../utils/utils';
|
||||
import { RecentLogsCollector } from '../../utils/debugLogger';
|
||||
import { ProgressController } from '../progress';
|
||||
import { TimeoutSettings } from '../../utils/timeoutSettings';
|
||||
|
|
@ -34,6 +37,9 @@ import { CallMetadata } from '../instrumentation';
|
|||
import { findChromiumChannel } from './findChromiumChannel';
|
||||
import http from 'http';
|
||||
|
||||
const mkdtempAsync = util.promisify(fs.mkdtemp);
|
||||
const ARTIFACTS_FOLDER = path.join(os.tmpdir(), 'playwright-artifacts-');
|
||||
|
||||
export class Chromium extends BrowserType {
|
||||
private _devtools: CRDevTools | undefined;
|
||||
|
||||
|
|
@ -58,12 +64,17 @@ export class Chromium extends BrowserType {
|
|||
let headersMap: { [key: string]: string; } | undefined;
|
||||
if (options.headers)
|
||||
headersMap = headersArrayToObject(options.headers, false);
|
||||
|
||||
const artifactsDir = await mkdtempAsync(ARTIFACTS_FOLDER);
|
||||
|
||||
const chromeTransport = await WebSocketTransport.connect(progress, await urlToWSEndpoint(endpointURL), headersMap);
|
||||
const browserProcess: BrowserProcess = {
|
||||
close: async () => {
|
||||
await removeFolders([ artifactsDir ]);
|
||||
await chromeTransport.closeAndWait();
|
||||
},
|
||||
kill: async () => {
|
||||
await removeFolders([ artifactsDir ]);
|
||||
await chromeTransport.closeAndWait();
|
||||
}
|
||||
};
|
||||
|
|
@ -76,6 +87,9 @@ export class Chromium extends BrowserType {
|
|||
browserProcess,
|
||||
protocolLogger: helper.debugProtocolLogger(),
|
||||
browserLogsCollector,
|
||||
artifactsDir,
|
||||
downloadsPath: artifactsDir,
|
||||
tracesDir: artifactsDir
|
||||
};
|
||||
return await CRBrowser.connect(chromeTransport, browserOptions);
|
||||
}, TimeoutSettings.timeout({timeout}));
|
||||
|
|
|
|||
|
|
@ -279,7 +279,7 @@ export class CRBrowserContext extends BrowserContext {
|
|||
async _initialize() {
|
||||
assert(!Array.from(this._browser._crPages.values()).some(page => page._browserContext === this));
|
||||
const promises: Promise<any>[] = [ super._initialize() ];
|
||||
if (this._browser.options.downloadsPath) {
|
||||
if (this._browser.options.name !== 'electron') {
|
||||
promises.push(this._browser._session.send('Browser.setDownloadBehavior', {
|
||||
behavior: this._options.acceptDownloads ? 'allowAndName' : 'deny',
|
||||
browserContextId: this._browserContextId,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,10 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import * as os from 'os';
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
import util from 'util';
|
||||
import { CRBrowser, CRBrowserContext } from '../chromium/crBrowser';
|
||||
import { CRConnection, CRSession } from '../chromium/crConnection';
|
||||
import { CRExecutionContext } from '../chromium/crExecutionContext';
|
||||
|
|
@ -34,6 +37,9 @@ import { RecentLogsCollector } from '../../utils/debugLogger';
|
|||
import { internalCallMetadata, SdkObject } from '../instrumentation';
|
||||
import * as channels from '../../protocol/channels';
|
||||
|
||||
const mkdtempAsync = util.promisify(fs.mkdtemp);
|
||||
const ARTIFACTS_FOLDER = path.join(os.tmpdir(), 'playwright-artifacts-');
|
||||
|
||||
export class ElectronApplication extends SdkObject {
|
||||
static Events = {
|
||||
Close: 'close',
|
||||
|
|
@ -119,6 +125,8 @@ export class Electron extends SdkObject {
|
|||
electronArguments.push('--no-sandbox');
|
||||
}
|
||||
|
||||
const artifactsDir = await mkdtempAsync(ARTIFACTS_FOLDER);
|
||||
|
||||
const browserLogsCollector = new RecentLogsCollector();
|
||||
const { launchedProcess, gracefullyClose, kill } = await launchProcess({
|
||||
executablePath: options.executablePath || require('electron/index.js'),
|
||||
|
|
@ -130,7 +138,7 @@ export class Electron extends SdkObject {
|
|||
},
|
||||
stdio: 'pipe',
|
||||
cwd: options.cwd,
|
||||
tempDirectories: [],
|
||||
tempDirectories: [ artifactsDir ],
|
||||
attemptToGracefullyClose: () => app!.close(),
|
||||
handleSIGINT: true,
|
||||
handleSIGTERM: true,
|
||||
|
|
@ -174,6 +182,9 @@ export class Electron extends SdkObject {
|
|||
browserProcess,
|
||||
protocolLogger: helper.debugProtocolLogger(),
|
||||
browserLogsCollector,
|
||||
artifactsDir,
|
||||
downloadsPath: artifactsDir,
|
||||
tracesDir: artifactsDir,
|
||||
};
|
||||
const browser = await CRBrowser.connect(chromeTransport, browserOptions);
|
||||
app = new ElectronApplication(this, browser, nodeConnection);
|
||||
|
|
|
|||
|
|
@ -158,15 +158,13 @@ export class FFBrowserContext extends BrowserContext {
|
|||
assert(!this._ffPages().length);
|
||||
const browserContextId = this._browserContextId;
|
||||
const promises: Promise<any>[] = [ super._initialize() ];
|
||||
if (this._browser.options.downloadsPath) {
|
||||
promises.push(this._browser._connection.send('Browser.setDownloadOptions', {
|
||||
browserContextId,
|
||||
downloadOptions: {
|
||||
behavior: this._options.acceptDownloads ? 'saveToDisk' : 'cancel',
|
||||
downloadsDir: this._browser.options.downloadsPath,
|
||||
},
|
||||
}));
|
||||
}
|
||||
promises.push(this._browser._connection.send('Browser.setDownloadOptions', {
|
||||
browserContextId,
|
||||
downloadOptions: {
|
||||
behavior: this._options.acceptDownloads ? 'saveToDisk' : 'cancel',
|
||||
downloadsDir: this._browser.options.downloadsPath,
|
||||
},
|
||||
}));
|
||||
if (this._options.viewport) {
|
||||
const viewport = {
|
||||
viewportSize: { width: this._options.viewport.width, height: this._options.viewport.height },
|
||||
|
|
|
|||
|
|
@ -49,6 +49,10 @@ export class TraceSnapshotter extends EventEmitter implements SnapshotterDelegat
|
|||
await this._snapshotter.start();
|
||||
}
|
||||
|
||||
async stop(): Promise<void> {
|
||||
await this._snapshotter.stop();
|
||||
}
|
||||
|
||||
async dispose() {
|
||||
this._snapshotter.dispose();
|
||||
await this._writeArtifactChain;
|
||||
|
|
|
|||
|
|
@ -48,23 +48,23 @@ export class Tracing implements InstrumentationListener {
|
|||
private _resourcesDir: string;
|
||||
private _sha1s: string[] = [];
|
||||
private _started = false;
|
||||
private _traceDir: string | undefined;
|
||||
private _tracesDir: string | undefined;
|
||||
|
||||
constructor(context: BrowserContext) {
|
||||
this._context = context;
|
||||
this._traceDir = context._browser.options.traceDir;
|
||||
this._resourcesDir = path.join(this._traceDir || '', 'resources');
|
||||
this._tracesDir = context._browser.options.tracesDir;
|
||||
this._resourcesDir = path.join(this._tracesDir, 'resources');
|
||||
this._snapshotter = new TraceSnapshotter(this._context, this._resourcesDir, traceEvent => this._appendTraceEvent(traceEvent));
|
||||
}
|
||||
|
||||
async start(options: TracerOptions): Promise<void> {
|
||||
// context + page must be the first events added, this method can't have awaits before them.
|
||||
if (!this._traceDir)
|
||||
if (!this._tracesDir)
|
||||
throw new Error('Tracing directory is not specified when launching the browser');
|
||||
if (this._started)
|
||||
throw new Error('Tracing has already been started');
|
||||
this._started = true;
|
||||
this._traceFile = path.join(this._traceDir, (options.name || createGuid()) + '.trace');
|
||||
this._traceFile = path.join(this._tracesDir, (options.name || createGuid()) + '.trace');
|
||||
|
||||
this._appendEventChain = mkdirIfNeeded(this._traceFile);
|
||||
const event: trace.ContextCreatedTraceEvent = {
|
||||
|
|
@ -91,6 +91,7 @@ export class Tracing implements InstrumentationListener {
|
|||
if (!this._started)
|
||||
return;
|
||||
this._started = false;
|
||||
await this._snapshotter.stop();
|
||||
this._context.instrumentation.removeListener(this);
|
||||
helper.removeEventListeners(this._eventListeners);
|
||||
for (const { sdkObject, metadata } of this._pendingCalls.values())
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ export class TraceViewer {
|
|||
private _server: HttpServer;
|
||||
private _browserName: string;
|
||||
|
||||
constructor(traceDir: string, browserName: string) {
|
||||
constructor(tracesDir: string, browserName: string) {
|
||||
this._browserName = browserName;
|
||||
const resourcesDir = path.join(traceDir, 'resources');
|
||||
const resourcesDir = path.join(tracesDir, 'resources');
|
||||
|
||||
// Served by TraceServer
|
||||
// - "/tracemodel" - json with trace model.
|
||||
|
|
@ -51,9 +51,9 @@ export class TraceViewer {
|
|||
// - "/snapshot/pageId/..." - actual snapshot html.
|
||||
// - "/snapshot/service-worker.js" - service worker that intercepts snapshot resources
|
||||
// and translates them into "/resources/<resourceId>".
|
||||
const actionTraces = fs.readdirSync(traceDir).filter(name => name.endsWith('.trace'));
|
||||
const actionTraces = fs.readdirSync(tracesDir).filter(name => name.endsWith('.trace'));
|
||||
const debugNames = actionTraces.map(name => {
|
||||
const tracePrefix = path.join(traceDir, name.substring(0, name.indexOf('.trace')));
|
||||
const tracePrefix = path.join(tracesDir, name.substring(0, name.indexOf('.trace')));
|
||||
return path.basename(tracePrefix);
|
||||
});
|
||||
|
||||
|
|
@ -71,7 +71,7 @@ export class TraceViewer {
|
|||
|
||||
const traceModelHandler: ServerRouteHandler = (request, response) => {
|
||||
const debugName = request.url!.substring('/context/'.length);
|
||||
const tracePrefix = path.join(traceDir, debugName);
|
||||
const tracePrefix = path.join(tracesDir, debugName);
|
||||
snapshotStorage.clear();
|
||||
response.statusCode = 200;
|
||||
response.setHeader('Content-Type', 'application/json');
|
||||
|
|
|
|||
|
|
@ -274,7 +274,7 @@ type LaunchOptionsBase = {
|
|||
chromiumSandbox?: boolean,
|
||||
slowMo?: number,
|
||||
useWebSocket?: boolean,
|
||||
traceDir?: string,
|
||||
tracesDir?: string,
|
||||
};
|
||||
export type LaunchOptions = LaunchOptionsBase & {
|
||||
firefoxUserPrefs?: { [key: string]: string | number | boolean },
|
||||
|
|
|
|||
|
|
@ -213,13 +213,11 @@ export class WKBrowserContext extends BrowserContext {
|
|||
assert(!this._wkPages().length);
|
||||
const browserContextId = this._browserContextId;
|
||||
const promises: Promise<any>[] = [ super._initialize() ];
|
||||
if (this._browser.options.downloadsPath) {
|
||||
promises.push(this._browser._browserSession.send('Playwright.setDownloadBehavior', {
|
||||
behavior: this._options.acceptDownloads ? 'allow' : 'deny',
|
||||
downloadPath: this._browser.options.downloadsPath,
|
||||
browserContextId
|
||||
}));
|
||||
}
|
||||
promises.push(this._browser._browserSession.send('Playwright.setDownloadBehavior', {
|
||||
behavior: this._options.acceptDownloads ? 'allow' : 'deny',
|
||||
downloadPath: this._browser.options.downloadsPath,
|
||||
browserContextId
|
||||
}));
|
||||
if (this._options.ignoreHTTPSErrors)
|
||||
promises.push(this._browser._browserSession.send('Playwright.setIgnoreCertificateErrors', { browserContextId, ignore: true }));
|
||||
if (this._options.locale)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ import { baseTest, CommonWorkerFixtures } from './baseTest';
|
|||
const mkdtempAsync = util.promisify(fs.mkdtemp);
|
||||
|
||||
type PlaywrightWorkerOptions = {
|
||||
traceDir: LaunchOptions['traceDir'];
|
||||
tracesDir: LaunchOptions['tracesDir'];
|
||||
executablePath: LaunchOptions['executablePath'];
|
||||
proxy: LaunchOptions['proxy'];
|
||||
args: LaunchOptions['args'];
|
||||
|
|
@ -53,7 +53,7 @@ type PlaywrightTestFixtures = {
|
|||
export type PlaywrightOptions = PlaywrightWorkerOptions & PlaywrightTestOptions;
|
||||
|
||||
export const playwrightFixtures: folio.Fixtures<PlaywrightTestOptions & PlaywrightTestFixtures, PlaywrightWorkerOptions & PlaywrightWorkerFixtures, {}, CommonWorkerFixtures> = {
|
||||
traceDir: [ undefined, { scope: 'worker' } ],
|
||||
tracesDir: [ undefined, { scope: 'worker' } ],
|
||||
executablePath: [ undefined, { scope: 'worker' } ],
|
||||
proxy: [ undefined, { scope: 'worker' } ],
|
||||
args: [ undefined, { scope: 'worker' } ],
|
||||
|
|
@ -63,12 +63,12 @@ export const playwrightFixtures: folio.Fixtures<PlaywrightTestOptions & Playwrig
|
|||
await run(playwright[browserName]);
|
||||
}, { scope: 'worker' } ],
|
||||
|
||||
browserOptions: [async ({ headless, channel, executablePath, traceDir, proxy, args }, run) => {
|
||||
browserOptions: [async ({ headless, channel, executablePath, tracesDir, proxy, args }, run) => {
|
||||
await run({
|
||||
headless,
|
||||
channel,
|
||||
executablePath,
|
||||
traceDir,
|
||||
tracesDir,
|
||||
proxy,
|
||||
args,
|
||||
handleSIGINT: false,
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ for (const browserName of browserNames) {
|
|||
channel,
|
||||
video,
|
||||
executablePath,
|
||||
traceDir: process.env.PWTRACE ? path.join(outputDir, 'trace') : undefined,
|
||||
tracesDir: process.env.PWTRACE ? path.join(outputDir, 'trace') : undefined,
|
||||
coverageName: browserName,
|
||||
},
|
||||
define: { test: pageTest, fixtures: pageFixtures },
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ export class RemoteServer {
|
|||
args: browserOptions.args,
|
||||
headless: browserOptions.headless,
|
||||
channel: browserOptions.channel,
|
||||
traceDir: browserOptions.traceDir,
|
||||
tracesDir: browserOptions.tracesDir,
|
||||
handleSIGINT: true,
|
||||
handleSIGTERM: true,
|
||||
handleSIGHUP: true,
|
||||
|
|
|
|||
|
|
@ -14,20 +14,10 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import path from 'path';
|
||||
import { expect, contextTest as test, browserTest } from './config/browserTest';
|
||||
import yauzl from 'yauzl';
|
||||
import removeFolder from 'rimraf';
|
||||
import jpeg from 'jpeg-js';
|
||||
|
||||
const traceDir = path.join(__dirname, '..', 'test-results', 'trace-' + process.env.FOLIO_WORKER_INDEX);
|
||||
test.use({ traceDir });
|
||||
|
||||
test.beforeEach(async ({ browserName, headless }) => {
|
||||
test.fixme(browserName === 'chromium' && !headless, 'Chromium screencast on headed has a min width issue');
|
||||
await new Promise(f => removeFolder(traceDir, f));
|
||||
});
|
||||
|
||||
test('should collect trace', async ({ context, page, server, browserName }, testInfo) => {
|
||||
await context.tracing.start({ name: 'test', screenshots: true, snapshots: true });
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
|
|
|
|||
19
types/types.d.ts
vendored
19
types/types.d.ts
vendored
|
|
@ -7235,7 +7235,7 @@ export interface BrowserType<Unused = {}> {
|
|||
/**
|
||||
* If specified, traces are saved into this directory.
|
||||
*/
|
||||
traceDir?: string;
|
||||
tracesDir?: string;
|
||||
|
||||
/**
|
||||
* Specific user agent to use in this context.
|
||||
|
|
@ -7424,7 +7424,7 @@ export interface BrowserType<Unused = {}> {
|
|||
/**
|
||||
* If specified, traces are saved into this directory.
|
||||
*/
|
||||
traceDir?: string;
|
||||
tracesDir?: string;
|
||||
}): Promise<BrowserServer>;
|
||||
|
||||
/**
|
||||
|
|
@ -10604,9 +10604,9 @@ export interface Touchscreen {
|
|||
* Start with specifying the folder traces will be stored in:
|
||||
*
|
||||
* ```js
|
||||
* const browser = await chromium.launch({ traceDir: 'traces' });
|
||||
* const browser = await chromium.launch();
|
||||
* const context = await browser.newContext();
|
||||
* await context.tracing.start({ name: 'trace', screenshots: true, snapshots: true });
|
||||
* await context.tracing.start({ screenshots: true, snapshots: true });
|
||||
* const page = await context.newPage();
|
||||
* await page.goto('https://playwright.dev');
|
||||
* await context.tracing.stop({ path: 'trace.zip' });
|
||||
|
|
@ -10618,19 +10618,18 @@ export interface Tracing {
|
|||
* Start tracing.
|
||||
*
|
||||
* ```js
|
||||
* await context.tracing.start({ name: 'trace', screenshots: true, snapshots: true });
|
||||
* await context.tracing.start({ screenshots: true, snapshots: true });
|
||||
* const page = await context.newPage();
|
||||
* await page.goto('https://playwright.dev');
|
||||
* await context.tracing.stop();
|
||||
* await context.tracing.export('trace.zip');
|
||||
* await context.tracing.stop({ path: 'trace.zip' });
|
||||
* ```
|
||||
*
|
||||
* @param options
|
||||
*/
|
||||
start(options?: {
|
||||
/**
|
||||
* If specified, the trace is going to be saved into the file with the given name inside the `traceDir` folder specified in
|
||||
* [browserType.launch([options])](https://playwright.dev/docs/api/class-browsertype#browsertypelaunchoptions).
|
||||
* If specified, the trace is going to be saved into the file with the given name inside the `tracesDir` folder specified
|
||||
* in [browserType.launch([options])](https://playwright.dev/docs/api/class-browsertype#browsertypelaunchoptions).
|
||||
*/
|
||||
name?: string;
|
||||
|
||||
|
|
@ -11343,7 +11342,7 @@ export interface LaunchOptions {
|
|||
/**
|
||||
* If specified, traces are saved into this directory.
|
||||
*/
|
||||
traceDir?: string;
|
||||
tracesDir?: string;
|
||||
}
|
||||
|
||||
export interface ConnectOverCDPOptions {
|
||||
|
|
|
|||
Loading…
Reference in a new issue