mirror of
				https://github.com/microsoft/playwright.git
				synced 2025-06-26 21:40:17 +00:00 
			
		
		
		
	chore(tracing): expose tracing api (#6523)
This commit is contained in:
		
							parent
							
								
									460cc31941
								
							
						
					
					
						commit
						21cb726b7d
					
				@ -975,6 +975,9 @@ The file path to save the storage state to. If [`option: path`] is a relative pa
 | 
				
			|||||||
current working directory. If no path is provided, storage
 | 
					current working directory. If no path is provided, storage
 | 
				
			||||||
state is still returned, but won't be saved to the disk.
 | 
					state is still returned, but won't be saved to the disk.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## property: BrowserContext.tracing
 | 
				
			||||||
 | 
					- type: <[Tracing]>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## async method: BrowserContext.unroute
 | 
					## async method: BrowserContext.unroute
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Removes a route created with [`method: BrowserContext.route`]. When [`param: handler`] is not specified, removes all
 | 
					Removes a route created with [`method: BrowserContext.route`]. When [`param: handler`] is not specified, removes all
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										72
									
								
								docs/src/api/class-tracing.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								docs/src/api/class-tracing.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,72 @@
 | 
				
			|||||||
 | 
					# class: Tracing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Tracing object for collecting test traces that can be opened using
 | 
				
			||||||
 | 
					Playwright CLI.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## async method: Tracing.export
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Export trace into the file with the given name. Should be called after the
 | 
				
			||||||
 | 
					tracing has stopped.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### param: Tracing.export.path
 | 
				
			||||||
 | 
					- `path` <[path]>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					File to save the trace into.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## async method: Tracing.start
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Start tracing.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```js
 | 
				
			||||||
 | 
					await context.tracing.start({ name: 'trace', 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');
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```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")))
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```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")
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```python sync
 | 
				
			||||||
 | 
					context.tracing.start(name="trace" screenshots=True snapshots=True)
 | 
				
			||||||
 | 
					page.goto("https://playwright.dev")
 | 
				
			||||||
 | 
					context.tracing.stop()
 | 
				
			||||||
 | 
					context.tracing.export("trace.zip")
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### option: Tracing.start.name
 | 
				
			||||||
 | 
					- `name` <[string]>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If specified, the trace is going to be saved into the file with the
 | 
				
			||||||
 | 
					given name.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### option: Tracing.start.screenshots
 | 
				
			||||||
 | 
					- `screenshots` <[boolean]>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Whether to capture screenshots during tracing. Screenshots are used to build
 | 
				
			||||||
 | 
					a timeline preview.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### option: Tracing.start.snapshots
 | 
				
			||||||
 | 
					- `snapshots` <[boolean]>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Whether to capture DOM snapshot on every action.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## async method: Tracing.stop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Stop tracing.
 | 
				
			||||||
@ -159,21 +159,25 @@ commandWithOpenOptions('pdf <url> <filename>', 'save page as pdf',
 | 
				
			|||||||
  console.log('  $ pdf https://example.com example.pdf');
 | 
					  console.log('  $ pdf https://example.com example.pdf');
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (process.env.PWTRACE) {
 | 
					program
 | 
				
			||||||
  program
 | 
					    .command('show-trace [trace]')
 | 
				
			||||||
      .command('show-trace [trace]')
 | 
					    .option('-b, --browser <browserType>', 'browser to use, one of cr, chromium, ff, firefox, wk, webkit', 'chromium')
 | 
				
			||||||
      .option('--resources <dir>', 'load resources from shared folder')
 | 
					    .description('Show trace viewer')
 | 
				
			||||||
      .description('Show trace viewer')
 | 
					    .action(function(trace, command) {
 | 
				
			||||||
      .action(function(trace, command) {
 | 
					      if (command.browser === 'cr')
 | 
				
			||||||
        showTraceViewer(trace, command.resources).catch(logErrorAndExit);
 | 
					        command.browser = 'chromium';
 | 
				
			||||||
      }).on('--help', function() {
 | 
					      if (command.browser === 'ff')
 | 
				
			||||||
        console.log('');
 | 
					        command.browser = 'firefox';
 | 
				
			||||||
        console.log('Examples:');
 | 
					      if (command.browser === 'wk')
 | 
				
			||||||
        console.log('');
 | 
					        command.browser = 'webkit';
 | 
				
			||||||
        console.log('  $ show-trace --resources=resources trace/file.trace');
 | 
					      showTraceViewer(trace, command.browser).catch(logErrorAndExit);
 | 
				
			||||||
        console.log('  $ show-trace trace/directory');
 | 
					    }).on('--help', function() {
 | 
				
			||||||
      });
 | 
					      console.log('');
 | 
				
			||||||
}
 | 
					      console.log('Examples:');
 | 
				
			||||||
 | 
					      console.log('');
 | 
				
			||||||
 | 
					      console.log('  $ show-trace --resources=resources trace/file.trace');
 | 
				
			||||||
 | 
					      console.log('  $ show-trace trace/directory');
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (process.argv[2] === 'run-driver')
 | 
					if (process.argv[2] === 'run-driver')
 | 
				
			||||||
  runDriver();
 | 
					  runDriver();
 | 
				
			||||||
 | 
				
			|||||||
@ -35,6 +35,7 @@ export { JSHandle } from './jsHandle';
 | 
				
			|||||||
export { Request, Response, Route, WebSocket } from './network';
 | 
					export { Request, Response, Route, WebSocket } from './network';
 | 
				
			||||||
export { Page } from './page';
 | 
					export { Page } from './page';
 | 
				
			||||||
export { Selectors } from './selectors';
 | 
					export { Selectors } from './selectors';
 | 
				
			||||||
 | 
					export { Tracing } from './tracing';
 | 
				
			||||||
export { Video } from './video';
 | 
					export { Video } from './video';
 | 
				
			||||||
export { Worker } from './worker';
 | 
					export { Worker } from './worker';
 | 
				
			||||||
export { CDPSession } from './cdpSession';
 | 
					export { CDPSession } from './cdpSession';
 | 
				
			||||||
 | 
				
			|||||||
@ -50,7 +50,7 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel,
 | 
				
			|||||||
    sdkLanguage: 'javascript'
 | 
					    sdkLanguage: 'javascript'
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  readonly _tracing: Tracing;
 | 
					  readonly tracing: Tracing;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  readonly _backgroundPages = new Set<Page>();
 | 
					  readonly _backgroundPages = new Set<Page>();
 | 
				
			||||||
  readonly _serviceWorkers = new Set<Worker>();
 | 
					  readonly _serviceWorkers = new Set<Worker>();
 | 
				
			||||||
@ -69,7 +69,7 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel,
 | 
				
			|||||||
    if (parent instanceof Browser)
 | 
					    if (parent instanceof Browser)
 | 
				
			||||||
      this._browser = parent;
 | 
					      this._browser = parent;
 | 
				
			||||||
    this._isChromium = this._browser?._name === 'chromium';
 | 
					    this._isChromium = this._browser?._name === 'chromium';
 | 
				
			||||||
    this._tracing = new Tracing(this);
 | 
					    this.tracing = new Tracing(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this._channel.on('bindingCall', ({binding}) => this._onBinding(BindingCall.from(binding)));
 | 
					    this._channel.on('bindingCall', ({binding}) => this._onBinding(BindingCall.from(binding)));
 | 
				
			||||||
    this._channel.on('close', () => this._onClose());
 | 
					    this._channel.on('close', () => this._onClose());
 | 
				
			||||||
 | 
				
			|||||||
@ -14,18 +14,19 @@
 | 
				
			|||||||
 * limitations under the License.
 | 
					 * limitations under the License.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import * as api from '../../types/types';
 | 
				
			||||||
import * as channels from '../protocol/channels';
 | 
					import * as channels from '../protocol/channels';
 | 
				
			||||||
import { Artifact } from './artifact';
 | 
					import { Artifact } from './artifact';
 | 
				
			||||||
import { BrowserContext } from './browserContext';
 | 
					import { BrowserContext } from './browserContext';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class Tracing {
 | 
					export class Tracing implements api.Tracing {
 | 
				
			||||||
  private _context: BrowserContext;
 | 
					  private _context: BrowserContext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  constructor(channel: BrowserContext) {
 | 
					  constructor(channel: BrowserContext) {
 | 
				
			||||||
    this._context = channel;
 | 
					    this._context = channel;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async start(options: { snapshots?: boolean, screenshots?: boolean } = {}) {
 | 
					  async start(options: { name?: string, snapshots?: boolean, screenshots?: boolean } = {}) {
 | 
				
			||||||
    await this._context._wrapApiCall('tracing.start', async (channel: channels.BrowserContextChannel) => {
 | 
					    await this._context._wrapApiCall('tracing.start', async (channel: channels.BrowserContextChannel) => {
 | 
				
			||||||
      return await channel.tracingStart(options);
 | 
					      return await channel.tracingStart(options);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
				
			|||||||
@ -226,7 +226,7 @@ export type BrowserTypeLaunchParams = {
 | 
				
			|||||||
    password?: string,
 | 
					    password?: string,
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  downloadsPath?: string,
 | 
					  downloadsPath?: string,
 | 
				
			||||||
  _traceDir?: string,
 | 
					  traceDir?: string,
 | 
				
			||||||
  chromiumSandbox?: boolean,
 | 
					  chromiumSandbox?: boolean,
 | 
				
			||||||
  firefoxUserPrefs?: any,
 | 
					  firefoxUserPrefs?: any,
 | 
				
			||||||
  slowMo?: number,
 | 
					  slowMo?: number,
 | 
				
			||||||
@ -251,7 +251,7 @@ export type BrowserTypeLaunchOptions = {
 | 
				
			|||||||
    password?: string,
 | 
					    password?: string,
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  downloadsPath?: string,
 | 
					  downloadsPath?: string,
 | 
				
			||||||
  _traceDir?: string,
 | 
					  traceDir?: string,
 | 
				
			||||||
  chromiumSandbox?: boolean,
 | 
					  chromiumSandbox?: boolean,
 | 
				
			||||||
  firefoxUserPrefs?: any,
 | 
					  firefoxUserPrefs?: any,
 | 
				
			||||||
  slowMo?: number,
 | 
					  slowMo?: number,
 | 
				
			||||||
@ -279,7 +279,7 @@ export type BrowserTypeLaunchPersistentContextParams = {
 | 
				
			|||||||
    password?: string,
 | 
					    password?: string,
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  downloadsPath?: string,
 | 
					  downloadsPath?: string,
 | 
				
			||||||
  _traceDir?: string,
 | 
					  traceDir?: string,
 | 
				
			||||||
  chromiumSandbox?: boolean,
 | 
					  chromiumSandbox?: boolean,
 | 
				
			||||||
  sdkLanguage: string,
 | 
					  sdkLanguage: string,
 | 
				
			||||||
  noDefaultViewport?: boolean,
 | 
					  noDefaultViewport?: boolean,
 | 
				
			||||||
@ -349,7 +349,7 @@ export type BrowserTypeLaunchPersistentContextOptions = {
 | 
				
			|||||||
    password?: string,
 | 
					    password?: string,
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  downloadsPath?: string,
 | 
					  downloadsPath?: string,
 | 
				
			||||||
  _traceDir?: string,
 | 
					  traceDir?: string,
 | 
				
			||||||
  chromiumSandbox?: boolean,
 | 
					  chromiumSandbox?: boolean,
 | 
				
			||||||
  noDefaultViewport?: boolean,
 | 
					  noDefaultViewport?: boolean,
 | 
				
			||||||
  viewport?: {
 | 
					  viewport?: {
 | 
				
			||||||
 | 
				
			|||||||
@ -260,7 +260,7 @@ LaunchOptions:
 | 
				
			|||||||
        username: string?
 | 
					        username: string?
 | 
				
			||||||
        password: string?
 | 
					        password: string?
 | 
				
			||||||
    downloadsPath: string?
 | 
					    downloadsPath: string?
 | 
				
			||||||
    _traceDir: string?
 | 
					    traceDir: string?
 | 
				
			||||||
    chromiumSandbox: boolean?
 | 
					    chromiumSandbox: boolean?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -172,7 +172,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
 | 
				
			|||||||
      password: tOptional(tString),
 | 
					      password: tOptional(tString),
 | 
				
			||||||
    })),
 | 
					    })),
 | 
				
			||||||
    downloadsPath: tOptional(tString),
 | 
					    downloadsPath: tOptional(tString),
 | 
				
			||||||
    _traceDir: tOptional(tString),
 | 
					    traceDir: tOptional(tString),
 | 
				
			||||||
    chromiumSandbox: tOptional(tBoolean),
 | 
					    chromiumSandbox: tOptional(tBoolean),
 | 
				
			||||||
    firefoxUserPrefs: tOptional(tAny),
 | 
					    firefoxUserPrefs: tOptional(tAny),
 | 
				
			||||||
    slowMo: tOptional(tNumber),
 | 
					    slowMo: tOptional(tNumber),
 | 
				
			||||||
@ -197,7 +197,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
 | 
				
			|||||||
      password: tOptional(tString),
 | 
					      password: tOptional(tString),
 | 
				
			||||||
    })),
 | 
					    })),
 | 
				
			||||||
    downloadsPath: tOptional(tString),
 | 
					    downloadsPath: tOptional(tString),
 | 
				
			||||||
    _traceDir: tOptional(tString),
 | 
					    traceDir: tOptional(tString),
 | 
				
			||||||
    chromiumSandbox: tOptional(tBoolean),
 | 
					    chromiumSandbox: tOptional(tBoolean),
 | 
				
			||||||
    sdkLanguage: tString,
 | 
					    sdkLanguage: tString,
 | 
				
			||||||
    noDefaultViewport: tOptional(tBoolean),
 | 
					    noDefaultViewport: tOptional(tBoolean),
 | 
				
			||||||
 | 
				
			|||||||
@ -115,7 +115,7 @@ export abstract class BrowserType extends SdkObject {
 | 
				
			|||||||
      protocolLogger,
 | 
					      protocolLogger,
 | 
				
			||||||
      browserLogsCollector,
 | 
					      browserLogsCollector,
 | 
				
			||||||
      wsEndpoint: options.useWebSocket ? (transport as WebSocketTransport).wsEndpoint : undefined,
 | 
					      wsEndpoint: options.useWebSocket ? (transport as WebSocketTransport).wsEndpoint : undefined,
 | 
				
			||||||
      traceDir: options._traceDir,
 | 
					      traceDir: options.traceDir,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    if (persistent)
 | 
					    if (persistent)
 | 
				
			||||||
      validateBrowserContextOptions(persistent, browserOptions);
 | 
					      validateBrowserContextOptions(persistent, browserOptions);
 | 
				
			||||||
 | 
				
			|||||||
@ -243,24 +243,11 @@ function rootScript() {
 | 
				
			|||||||
  pointElement.style.margin = '-10px 0 0 -10px';
 | 
					  pointElement.style.margin = '-10px 0 0 -10px';
 | 
				
			||||||
  pointElement.style.zIndex = '2147483647';
 | 
					  pointElement.style.zIndex = '2147483647';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let current = document.createElement('iframe');
 | 
					  const iframe = document.createElement('iframe');
 | 
				
			||||||
  document.body.appendChild(current);
 | 
					  document.body.appendChild(iframe);
 | 
				
			||||||
  let next = document.createElement('iframe');
 | 
					 | 
				
			||||||
  document.body.appendChild(next);
 | 
					 | 
				
			||||||
  next.style.visibility = 'hidden';
 | 
					 | 
				
			||||||
  const onload = () => {
 | 
					 | 
				
			||||||
    const temp = current;
 | 
					 | 
				
			||||||
    current = next;
 | 
					 | 
				
			||||||
    next = temp;
 | 
					 | 
				
			||||||
    current.style.visibility = 'visible';
 | 
					 | 
				
			||||||
    next.style.visibility = 'hidden';
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
  current.onload = onload;
 | 
					 | 
				
			||||||
  next.onload = onload;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  (window as any).showSnapshot = async (url: string, options: { point?: Point } = {}) => {
 | 
					  (window as any).showSnapshot = async (url: string, options: { point?: Point } = {}) => {
 | 
				
			||||||
    await showPromise;
 | 
					    await showPromise;
 | 
				
			||||||
    next.src = url;
 | 
					    iframe.src = url;
 | 
				
			||||||
    if (options.point) {
 | 
					    if (options.point) {
 | 
				
			||||||
      pointElement.style.left = options.point.x + 'px';
 | 
					      pointElement.style.left = options.point.x + 'px';
 | 
				
			||||||
      pointElement.style.top = options.point.y + 'px';
 | 
					      pointElement.style.top = options.point.y + 'px';
 | 
				
			||||||
 | 
				
			|||||||
@ -31,10 +31,11 @@ const fsReadFileAsync = util.promisify(fs.readFile.bind(fs));
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class TraceViewer {
 | 
					class TraceViewer {
 | 
				
			||||||
  private _server: HttpServer;
 | 
					  private _server: HttpServer;
 | 
				
			||||||
 | 
					  private _browserName: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  constructor(traceDir: string, resourcesDir?: string) {
 | 
					  constructor(traceDir: string, browserName: string) {
 | 
				
			||||||
    if (!resourcesDir)
 | 
					    this._browserName = browserName;
 | 
				
			||||||
      resourcesDir = path.join(traceDir, 'resources');
 | 
					    const resourcesDir = path.join(traceDir, 'resources');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Served by TraceServer
 | 
					    // Served by TraceServer
 | 
				
			||||||
    // - "/tracemodel" - json with trace model.
 | 
					    // - "/tracemodel" - json with trace model.
 | 
				
			||||||
@ -124,7 +125,7 @@ class TraceViewer {
 | 
				
			|||||||
    ];
 | 
					    ];
 | 
				
			||||||
    if (isUnderTest())
 | 
					    if (isUnderTest())
 | 
				
			||||||
      args.push(`--remote-debugging-port=0`);
 | 
					      args.push(`--remote-debugging-port=0`);
 | 
				
			||||||
    const context = await traceViewerPlaywright.chromium.launchPersistentContext(internalCallMetadata(), '', {
 | 
					    const context = await traceViewerPlaywright[this._browserName as 'chromium'].launchPersistentContext(internalCallMetadata(), '', {
 | 
				
			||||||
      // TODO: store language in the trace.
 | 
					      // TODO: store language in the trace.
 | 
				
			||||||
      sdkLanguage: 'javascript',
 | 
					      sdkLanguage: 'javascript',
 | 
				
			||||||
      args,
 | 
					      args,
 | 
				
			||||||
@ -144,7 +145,7 @@ class TraceViewer {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export async function showTraceViewer(traceDir: string, resourcesDir?: string) {
 | 
					export async function showTraceViewer(traceDir: string, browserName: string) {
 | 
				
			||||||
  const traceViewer = new TraceViewer(traceDir, resourcesDir);
 | 
					  const traceViewer = new TraceViewer(traceDir, browserName);
 | 
				
			||||||
  await traceViewer.show();
 | 
					  await traceViewer.show();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -272,7 +272,7 @@ type LaunchOptionsBase = {
 | 
				
			|||||||
  chromiumSandbox?: boolean,
 | 
					  chromiumSandbox?: boolean,
 | 
				
			||||||
  slowMo?: number,
 | 
					  slowMo?: number,
 | 
				
			||||||
  useWebSocket?: boolean,
 | 
					  useWebSocket?: boolean,
 | 
				
			||||||
  _traceDir?: string,
 | 
					  traceDir?: string,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
export type LaunchOptions = LaunchOptionsBase & {
 | 
					export type LaunchOptions = LaunchOptionsBase & {
 | 
				
			||||||
  firefoxUserPrefs?: { [key: string]: string | number | boolean },
 | 
					  firefoxUserPrefs?: { [key: string]: string | number | boolean },
 | 
				
			||||||
 | 
				
			|||||||
@ -56,7 +56,7 @@ class PlaywrightEnv {
 | 
				
			|||||||
  async beforeAll(args: CommonArgs & PlaywrightEnvOptions, workerInfo: folio.WorkerInfo): Promise<PlaywrightWorkerArgs> {
 | 
					  async beforeAll(args: CommonArgs & PlaywrightEnvOptions, workerInfo: folio.WorkerInfo): Promise<PlaywrightWorkerArgs> {
 | 
				
			||||||
    this._browserType = args.playwright[args.browserName];
 | 
					    this._browserType = args.playwright[args.browserName];
 | 
				
			||||||
    this._browserOptions = {
 | 
					    this._browserOptions = {
 | 
				
			||||||
      _traceDir: args.traceDir,
 | 
					      traceDir: args.traceDir,
 | 
				
			||||||
      channel: args.browserChannel,
 | 
					      channel: args.browserChannel,
 | 
				
			||||||
      headless: !args.headful,
 | 
					      headless: !args.headful,
 | 
				
			||||||
      handleSIGINT: false,
 | 
					      handleSIGINT: false,
 | 
				
			||||||
 | 
				
			|||||||
@ -41,7 +41,7 @@ class PageEnv {
 | 
				
			|||||||
  async beforeAll(args: AllOptions & CommonArgs, workerInfo: folio.WorkerInfo) {
 | 
					  async beforeAll(args: AllOptions & CommonArgs, workerInfo: folio.WorkerInfo) {
 | 
				
			||||||
    this._browser = await args.playwright[args.browserName].launch({
 | 
					    this._browser = await args.playwright[args.browserName].launch({
 | 
				
			||||||
      ...args.launchOptions,
 | 
					      ...args.launchOptions,
 | 
				
			||||||
      _traceDir: args.traceDir,
 | 
					      traceDir: args.traceDir,
 | 
				
			||||||
      channel: args.browserChannel,
 | 
					      channel: args.browserChannel,
 | 
				
			||||||
      headless: !args.headful,
 | 
					      headless: !args.headful,
 | 
				
			||||||
      handleSIGINT: false,
 | 
					      handleSIGINT: false,
 | 
				
			||||||
 | 
				
			|||||||
@ -132,9 +132,9 @@ it.describe('snapshots', () => {
 | 
				
			|||||||
    await previewPage.evaluate(snapshotId => {
 | 
					    await previewPage.evaluate(snapshotId => {
 | 
				
			||||||
      (window as any).showSnapshot(snapshotId);
 | 
					      (window as any).showSnapshot(snapshotId);
 | 
				
			||||||
    }, `${snapshot.snapshot().pageId}?name=snapshot${counter}`);
 | 
					    }, `${snapshot.snapshot().pageId}?name=snapshot${counter}`);
 | 
				
			||||||
    while (previewPage.frames().length < 4)
 | 
					    while (previewPage.frames().length < 3)
 | 
				
			||||||
      await new Promise(f => previewPage.once('frameattached', f));
 | 
					      await new Promise(f => previewPage.once('frameattached', f));
 | 
				
			||||||
    const button = await previewPage.frames()[3].waitForSelector('button');
 | 
					    const button = await previewPage.frames()[2].waitForSelector('button');
 | 
				
			||||||
    expect(await button.textContent()).toBe('Hello iframe');
 | 
					    expect(await button.textContent()).toBe('Hello iframe');
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -29,13 +29,13 @@ test.beforeEach(async ({ browserName, headful }) => {
 | 
				
			|||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test('should collect trace', async ({ context, page, server, browserName }, testInfo) => {
 | 
					test('should collect trace', async ({ context, page, server, browserName }, testInfo) => {
 | 
				
			||||||
  await (context as any)._tracing.start({ name: 'test', screenshots: true, snapshots: true });
 | 
					  await (context as any).tracing.start({ name: 'test', screenshots: true, snapshots: true });
 | 
				
			||||||
  await page.goto(server.EMPTY_PAGE);
 | 
					  await page.goto(server.EMPTY_PAGE);
 | 
				
			||||||
  await page.setContent('<button>Click</button>');
 | 
					  await page.setContent('<button>Click</button>');
 | 
				
			||||||
  await page.click('"Click"');
 | 
					  await page.click('"Click"');
 | 
				
			||||||
  await page.close();
 | 
					  await page.close();
 | 
				
			||||||
  await (context as any)._tracing.stop();
 | 
					  await (context as any).tracing.stop();
 | 
				
			||||||
  await (context as any)._tracing.export(testInfo.outputPath('trace.zip'));
 | 
					  await (context as any).tracing.export(testInfo.outputPath('trace.zip'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const { events } = await parseTrace(testInfo.outputPath('trace.zip'));
 | 
					  const { events } = await parseTrace(testInfo.outputPath('trace.zip'));
 | 
				
			||||||
  expect(events[0].type).toBe('context-metadata');
 | 
					  expect(events[0].type).toBe('context-metadata');
 | 
				
			||||||
@ -51,13 +51,13 @@ test('should collect trace', async ({ context, page, server, browserName }, test
 | 
				
			|||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test('should collect trace', async ({ context, page, server }, testInfo) => {
 | 
					test('should collect trace', async ({ context, page, server }, testInfo) => {
 | 
				
			||||||
  await (context as any)._tracing.start({ name: 'test' });
 | 
					  await (context as any).tracing.start({ name: 'test' });
 | 
				
			||||||
  await page.goto(server.EMPTY_PAGE);
 | 
					  await page.goto(server.EMPTY_PAGE);
 | 
				
			||||||
  await page.setContent('<button>Click</button>');
 | 
					  await page.setContent('<button>Click</button>');
 | 
				
			||||||
  await page.click('"Click"');
 | 
					  await page.click('"Click"');
 | 
				
			||||||
  await page.close();
 | 
					  await page.close();
 | 
				
			||||||
  await (context as any)._tracing.stop();
 | 
					  await (context as any).tracing.stop();
 | 
				
			||||||
  await (context as any)._tracing.export(testInfo.outputPath('trace.zip'));
 | 
					  await (context as any).tracing.export(testInfo.outputPath('trace.zip'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const { events } = await parseTrace(testInfo.outputPath('trace.zip'));
 | 
					  const { events } = await parseTrace(testInfo.outputPath('trace.zip'));
 | 
				
			||||||
  expect(events.some(e => e.type === 'frame-snapshot')).toBeFalsy();
 | 
					  expect(events.some(e => e.type === 'frame-snapshot')).toBeFalsy();
 | 
				
			||||||
@ -65,18 +65,18 @@ test('should collect trace', async ({ context, page, server }, testInfo) => {
 | 
				
			|||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test('should collect two traces', async ({ context, page, server }, testInfo) => {
 | 
					test('should collect two traces', async ({ context, page, server }, testInfo) => {
 | 
				
			||||||
  await (context as any)._tracing.start({ name: 'test1', screenshots: true, snapshots: true });
 | 
					  await (context as any).tracing.start({ name: 'test1', screenshots: true, snapshots: true });
 | 
				
			||||||
  await page.goto(server.EMPTY_PAGE);
 | 
					  await page.goto(server.EMPTY_PAGE);
 | 
				
			||||||
  await page.setContent('<button>Click</button>');
 | 
					  await page.setContent('<button>Click</button>');
 | 
				
			||||||
  await page.click('"Click"');
 | 
					  await page.click('"Click"');
 | 
				
			||||||
  await (context as any)._tracing.stop();
 | 
					  await (context as any).tracing.stop();
 | 
				
			||||||
  await (context as any)._tracing.export(testInfo.outputPath('trace1.zip'));
 | 
					  await (context as any).tracing.export(testInfo.outputPath('trace1.zip'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  await (context as any)._tracing.start({ name: 'test2', screenshots: true, snapshots: true });
 | 
					  await (context as any).tracing.start({ name: 'test2', screenshots: true, snapshots: true });
 | 
				
			||||||
  await page.dblclick('"Click"');
 | 
					  await page.dblclick('"Click"');
 | 
				
			||||||
  await page.close();
 | 
					  await page.close();
 | 
				
			||||||
  await (context as any)._tracing.stop();
 | 
					  await (context as any).tracing.stop();
 | 
				
			||||||
  await (context as any)._tracing.export(testInfo.outputPath('trace2.zip'));
 | 
					  await (context as any).tracing.export(testInfo.outputPath('trace2.zip'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    const { events } = await parseTrace(testInfo.outputPath('trace1.zip'));
 | 
					    const { events } = await parseTrace(testInfo.outputPath('trace1.zip'));
 | 
				
			||||||
@ -127,15 +127,15 @@ for (const params of [
 | 
				
			|||||||
    const previewHeight = params.height * scale;
 | 
					    const previewHeight = params.height * scale;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const context = await contextFactory({ viewport: { width: params.width, height: params.height }});
 | 
					    const context = await contextFactory({ viewport: { width: params.width, height: params.height }});
 | 
				
			||||||
    await (context as any)._tracing.start({ name: 'test', screenshots: true, snapshots: true });
 | 
					    await (context as any).tracing.start({ name: 'test', screenshots: true, snapshots: true });
 | 
				
			||||||
    const page = await context.newPage();
 | 
					    const page = await context.newPage();
 | 
				
			||||||
    // Make sure we have a chance to paint.
 | 
					    // Make sure we have a chance to paint.
 | 
				
			||||||
    for (let i = 0; i < 10; ++i) {
 | 
					    for (let i = 0; i < 10; ++i) {
 | 
				
			||||||
      await page.setContent('<body style="box-sizing: border-box; width: 100%; height: 100%; margin:0; background: red; border: 50px solid blue"></body>');
 | 
					      await page.setContent('<body style="box-sizing: border-box; width: 100%; height: 100%; margin:0; background: red; border: 50px solid blue"></body>');
 | 
				
			||||||
      await page.evaluate(() => new Promise(requestAnimationFrame));
 | 
					      await page.evaluate(() => new Promise(requestAnimationFrame));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    await (context as any)._tracing.stop();
 | 
					    await (context as any).tracing.stop();
 | 
				
			||||||
    await (context as any)._tracing.export(testInfo.outputPath('trace.zip'));
 | 
					    await (context as any).tracing.export(testInfo.outputPath('trace.zip'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const { events, resources } = await parseTrace(testInfo.outputPath('trace.zip'));
 | 
					    const { events, resources } = await parseTrace(testInfo.outputPath('trace.zip'));
 | 
				
			||||||
    const frames = events.filter(e => e.type === 'screencast-frame');
 | 
					    const frames = events.filter(e => e.type === 'screencast-frame');
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										48
									
								
								types/types.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										48
									
								
								types/types.d.ts
									
									
									
									
										vendored
									
									
								
							@ -5455,6 +5455,8 @@ export interface BrowserContext {
 | 
				
			|||||||
    }>;
 | 
					    }>;
 | 
				
			||||||
  }>;
 | 
					  }>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  tracing: Tracing;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * Removes a route created with
 | 
					   * Removes a route created with
 | 
				
			||||||
   * [browserContext.route(url, handler)](https://playwright.dev/docs/api/class-browsercontext#browsercontextrouteurl-handler).
 | 
					   * [browserContext.route(url, handler)](https://playwright.dev/docs/api/class-browsercontext#browsercontextrouteurl-handler).
 | 
				
			||||||
@ -10264,6 +10266,52 @@ export interface Touchscreen {
 | 
				
			|||||||
  tap(x: number, y: number): Promise<void>;
 | 
					  tap(x: number, y: number): Promise<void>;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Tracing object for collecting test traces that can be opened using Playwright CLI.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export interface Tracing {
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Export trace into the file with the given name. Should be called after the tracing has stopped.
 | 
				
			||||||
 | 
					   * @param path File to save the trace into.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  export(path: string): Promise<void>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Start tracing.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * ```js
 | 
				
			||||||
 | 
					   * await context.tracing.start({ name: 'trace', 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');
 | 
				
			||||||
 | 
					   * ```
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param options
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  start(options?: {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * If specified, the trace is going to be saved into the file with the given name.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    name?: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Whether to capture screenshots during tracing. Screenshots are used to build a timeline preview.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    screenshots?: boolean;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Whether to capture DOM snapshot on every action.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    snapshots?: boolean;
 | 
				
			||||||
 | 
					  }): Promise<void>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Stop tracing.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  stop(): Promise<void>;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * When browser context is created with the `recordVideo` option, each page has a video object associated with it.
 | 
					 * When browser context is created with the `recordVideo` option, each page has a video object associated with it.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user