Introduce page.tracing (#181)
This patch introduces page.tracing, which allows to start and stop trace recording for a page. The trace could be then saved to file.
This commit is contained in:
parent
0218960713
commit
bd72e40e73
27
docs/api.md
27
docs/api.md
@ -54,6 +54,7 @@
|
||||
+ [page.setUserAgent(userAgent)](#pagesetuseragentuseragent)
|
||||
+ [page.setViewport(viewport)](#pagesetviewportviewport)
|
||||
+ [page.title()](#pagetitle)
|
||||
+ [page.tracing](#pagetracing)
|
||||
+ [page.type(text, options)](#pagetypetext-options)
|
||||
+ [page.uploadFile(selector, ...filePaths)](#pageuploadfileselector-filepaths)
|
||||
+ [page.url()](#pageurl)
|
||||
@ -71,6 +72,9 @@
|
||||
+ [mouse.down([options])](#mousedownoptions)
|
||||
+ [mouse.move(x, y)](#mousemovex-y)
|
||||
+ [mouse.up([options])](#mouseupoptions)
|
||||
* [class: Tracing](#class-tracing)
|
||||
+ [tracing.start([options])](#tracingstartoptions)
|
||||
+ [tracing.stop(path)](#tracingstoppath)
|
||||
* [class: Dialog](#class-dialog)
|
||||
+ [dialog.accept([promptText])](#dialogacceptprompttext)
|
||||
+ [dialog.dismiss()](#dialogdismiss)
|
||||
@ -638,6 +642,9 @@ In case of multiple pages in one browser, each page can have its own viewport si
|
||||
|
||||
Shortcut for [page.mainFrame().title()](#frametitle).
|
||||
|
||||
#### page.tracing
|
||||
- returns: <[Tracing]>
|
||||
|
||||
#### page.type(text, options)
|
||||
- `text` <[string]> A text to type into a focused element.
|
||||
- `options` <[Object]>
|
||||
@ -827,6 +834,25 @@ Dispatches a `mousemove` event.
|
||||
|
||||
Dispatches a `mouseup` event.
|
||||
|
||||
### class: Tracing
|
||||
|
||||
You can use [`tracing.start`](#tracingstartoptions) and [`tracing.stop`](#tracingstoppath) to create a trace file which can be opened in Chrome DevTools or [timeline viewer](https://chromedevtools.github.io/timeline-viewer/).
|
||||
|
||||
```js
|
||||
await page.tracing.start();
|
||||
await page.navigate('https://www.google.com');
|
||||
await page.tracing.stop('trace.json');
|
||||
```
|
||||
|
||||
#### tracing.start([options])
|
||||
- `options` <[Object]>
|
||||
- `screenshots` <[boolean]> captures screenshots in the trace.
|
||||
- returns: <[Promise]>
|
||||
|
||||
#### tracing.stop(path)
|
||||
- `path` <[string]> A path to write the trace file to.
|
||||
- returns: <[Promise]>
|
||||
|
||||
### class: Dialog
|
||||
|
||||
[Dialog] objects are dispatched by page via the ['dialog'](#event-dialog) event.
|
||||
@ -1194,3 +1220,4 @@ If changed, the request url will be modified in a way that's not observable by p
|
||||
[Mouse]: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#class-mouse "Mouse"
|
||||
[Map]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map "Map"
|
||||
[selector]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors "selector"
|
||||
[Tracing]: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#class-tracing "Tracing"
|
||||
|
@ -23,6 +23,7 @@ let Dialog = require('./Dialog');
|
||||
let EmulationManager = require('./EmulationManager');
|
||||
let FrameManager = require('./FrameManager');
|
||||
let {Keyboard, Mouse} = require('./Input');
|
||||
let Tracing = require('./Tracing');
|
||||
let helper = require('./helper');
|
||||
|
||||
class Page extends EventEmitter {
|
||||
@ -61,6 +62,7 @@ class Page extends EventEmitter {
|
||||
this._frameManager = new FrameManager(client, this._mouse);
|
||||
this._networkManager = new NetworkManager(client);
|
||||
this._emulationManager = new EmulationManager(client);
|
||||
this._tracing = new Tracing(client);
|
||||
/** @type {!Map<string, function>} */
|
||||
this._inPageCallbacks = new Map();
|
||||
this._ignoreHTTPSErrors = ignoreHTTPSErrors;
|
||||
@ -98,6 +100,13 @@ class Page extends EventEmitter {
|
||||
return this._keyboard;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {!Tracing}
|
||||
*/
|
||||
get tracing() {
|
||||
return this._tracing;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {!Array<!Frame>}
|
||||
*/
|
||||
|
85
lib/Tracing.js
Normal file
85
lib/Tracing.js
Normal file
@ -0,0 +1,85 @@
|
||||
/**
|
||||
* Copyright 2017 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
const fs = require('fs');
|
||||
const helper = require('./helper');
|
||||
|
||||
class Tracing {
|
||||
/**
|
||||
* @param {!Connection} client
|
||||
*/
|
||||
constructor(client) {
|
||||
this._client = client;
|
||||
this._recording = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object=} options
|
||||
*/
|
||||
async start(options = {}) {
|
||||
console.assert(!this._recording, 'Cannot start recording trace while already recording trace.');
|
||||
|
||||
const categoriesArray = [
|
||||
'-*', 'devtools.timeline', 'v8.execute', 'disabled-by-default-devtools.timeline',
|
||||
'disabled-by-default-devtools.timeline.frame', 'toplevel',
|
||||
'blink.console', 'blink.user_timing', 'latencyInfo', 'disabled-by-default-devtools.timeline.stack',
|
||||
'disabled-by-default-v8.cpu_profiler'
|
||||
];
|
||||
|
||||
if (options.screenshots)
|
||||
categoriesArray.push('disabled-by-default-devtools.screenshot');
|
||||
|
||||
this._recording = true;
|
||||
await this._client.send('Tracing.start', {
|
||||
transferMode: 'ReturnAsStream',
|
||||
categories: categoriesArray.join(',')
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} path
|
||||
*/
|
||||
async stop(path) {
|
||||
let fulfill;
|
||||
let contentPromise = new Promise(x => fulfill = x);
|
||||
this._client.once('Tracing.tracingComplete', event => {
|
||||
this._readStream(event.stream, path).then(fulfill);
|
||||
});
|
||||
await this._client.send('Tracing.end');
|
||||
this._recording = false;
|
||||
return contentPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} handle
|
||||
* @param {string=} path
|
||||
* @return {!Promise}
|
||||
*/
|
||||
async _readStream(handle, path) {
|
||||
let eof = false;
|
||||
let file = fs.openSync(path, 'w');
|
||||
while (!eof) {
|
||||
let response = await this._client.send('IO.read', {handle});
|
||||
eof = response.eof;
|
||||
if (path)
|
||||
fs.writeSync(file, response.data);
|
||||
}
|
||||
fs.closeSync(file);
|
||||
await this._client.send('IO.close', {handle});
|
||||
}
|
||||
}
|
||||
helper.tracePublicAPI(Tracing);
|
||||
|
||||
module.exports = Tracing;
|
26
test/test.js
26
test/test.js
@ -1481,6 +1481,32 @@ describe('Page', function() {
|
||||
await Promise.all(pages.map(page => page.close()));
|
||||
}));
|
||||
});
|
||||
|
||||
describe('Tracing', function() {
|
||||
let outputFile = path.join(__dirname, 'assets', 'trace.json');
|
||||
afterEach(function() {
|
||||
fs.unlinkSync(outputFile);
|
||||
});
|
||||
it('should output a trace', SX(async function() {
|
||||
await page.tracing.start({screenshots: true});
|
||||
await page.navigate(PREFIX + '/grid.html');
|
||||
await page.tracing.stop(outputFile);
|
||||
expect(fs.existsSync(outputFile)).toBe(true);
|
||||
}));
|
||||
it('should throw if tracing on two pages', SX(async function() {
|
||||
await page.tracing.start();
|
||||
let newPage = await browser.newPage();
|
||||
let error = null;
|
||||
try {
|
||||
await newPage.tracing.start();
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
await newPage.close();
|
||||
expect(error).toBeTruthy();
|
||||
await page.tracing.stop(outputFile);
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
if (process.env.COVERAGE) {
|
||||
|
@ -40,6 +40,7 @@ const EXCLUDE_METHODS = new Set([
|
||||
'InterceptedRequest.constructor',
|
||||
'Keyboard.constructor',
|
||||
'Mouse.constructor',
|
||||
'Tracing.constructor',
|
||||
'Page.constructor',
|
||||
'Page.create',
|
||||
'Request.constructor',
|
||||
|
Loading…
Reference in New Issue
Block a user