browsertime 15.2.0 → 16.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,6 +3,8 @@ Firefox Examples
3
3
 
4
4
  This page shows a few of the options specific to Firefox.
5
5
 
6
- browsertime https://www.sitespeed.io --firefox.binaryPath '/Applications/Firefox.app/Contents/MacOS/firefox-bin'
6
+ ```
7
+ browsertime https://www.sitespeed.io -b firefox --firefox.binaryPath '/Applications/Firefox.app/Contents/MacOS/firefox-bin'
8
+ ```
7
9
 
8
10
  - Path to custom Firefox binary (e.g. Firefox Nightly). On OS X, the path should be to the binary inside the app bundle. (e.g. /Applications/Firefox.app/Contents/MacOS/firefox-bin)
@@ -9,12 +9,14 @@ const path = require('path');
9
9
  const parseCpuTrace = require('../parseCpuTrace');
10
10
  const har = require('../har');
11
11
  const harBuilder = require('../../support/har');
12
+ const util = require('../../support/util');
12
13
  const webdriver = require('selenium-webdriver');
13
14
  const traceCategoriesParser = require('../traceCategoriesParser');
14
15
  const pathToFolder = require('../../support/pathToFolder');
15
16
  const ChromeDevtoolsProtocol = require('../chromeDevtoolsProtocol');
16
17
  const { Android } = require('../../android');
17
18
  const unlink = promisify(fs.unlink);
19
+ const rm = promisify(fs.rm);
18
20
 
19
21
  class Chromium {
20
22
  constructor(storageManager, options) {
@@ -408,7 +410,27 @@ class Chromium {
408
410
  /**
409
411
  * Before the browser is stopped/closed.
410
412
  */
411
- async afterBrowserStopped() {}
413
+ async afterBrowserStopped() {
414
+ // If we supply a user data dir on desktop, we want to clean up before each start
415
+ if (
416
+ this.chrome.args &&
417
+ this.chrome.cleanUserDataDir &&
418
+ !this.chrome.android
419
+ ) {
420
+ const args = util.toArray(this.chrome.args);
421
+ for (let arg of args) {
422
+ if (arg.includes('user-data-dir')) {
423
+ const userDataDir = arg.split('=')[1];
424
+ try {
425
+ await rm(userDataDir, { recursive: true });
426
+ log.info(`Deleted user data dir: ${userDataDir}`);
427
+ } catch (e) {
428
+ log.error(`Could not delete user data dir: ${userDataDir}`, e);
429
+ }
430
+ }
431
+ }
432
+ }
433
+ }
412
434
 
413
435
  async getHARs() {
414
436
  if (!this.skipHar) {
@@ -102,7 +102,7 @@ class Iteration {
102
102
  const engineDelegate = this.engineDelegate;
103
103
 
104
104
  try {
105
- if (!options.disableDNSFlush === true) {
105
+ if (options.flushDNS) {
106
106
  await flushDNS(options);
107
107
  }
108
108
  if (options.connectivity && options.connectivity.variance) {
@@ -287,6 +287,12 @@ module.exports.parseCommandLine = function parseCommandLine() {
287
287
  'Prevent Browsertime from setting its default options for Chrome',
288
288
  group: 'chrome'
289
289
  })
290
+ .option('chrome.cleanUserDataDir', {
291
+ type: 'boolean',
292
+ describe:
293
+ 'If you use --user-data-dir as an argument to Chrome and want to clean that directory between each iteration you should use --chrome.cleanUserDataDir true.',
294
+ group: 'chrome'
295
+ })
290
296
  .option('cpu', {
291
297
  type: 'boolean',
292
298
  describe:
@@ -634,6 +640,11 @@ module.exports.parseCommandLine = function parseCommandLine() {
634
640
  type: 'boolean',
635
641
  describe: 'Collect Contentful Speed Index when you run --visualMetrics.'
636
642
  })
643
+ .option('visualMetricsPortable', {
644
+ type: 'boolean',
645
+ describe:
646
+ 'Use the portable visual-metrics processing script (no ImageMagick dependencies).'
647
+ })
637
648
  .option('scriptInput.visualElements', {
638
649
  describe:
639
650
  'Include specific elements in visual elements. Give the element a name and select it with document.body.querySelector. Use like this: --scriptInput.visualElements name:domSelector see https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors. Add multiple instances to measure multiple elements. Visual Metrics will use these elements and calculate when they are visible and fully rendered.'
@@ -964,7 +975,7 @@ module.exports.parseCommandLine = function parseCommandLine() {
964
975
  })
965
976
  .option('block', {
966
977
  describe:
967
- 'Domain to block. Add multiple instances to add multiple domains that will be blocked. If you use Chrome you can also use --blockDomainsExcept (that is more performant). Works for Firefox and Chrome.'
978
+ 'Domain to block or URL or URL pattern to block. If you use Chrome you can also use --blockDomainsExcept (that is more performant). Works in Chrome/Edge. For Firefox you can only block domains.'
968
979
  })
969
980
  .option('percentiles', {
970
981
  type: 'array',
@@ -1106,6 +1117,12 @@ module.exports.parseCommandLine = function parseCommandLine() {
1106
1117
  describe:
1107
1118
  'Start gnirehtet and reverse tethering the traffic from your Android phone.'
1108
1119
  })
1120
+ .option('flushDNS', {
1121
+ type: 'boolean',
1122
+ default: false,
1123
+ describe:
1124
+ 'Flush DNS between runs, works on Mac OS and Linux. Your user needs sudo rights to be able to flush the DNS.'
1125
+ })
1109
1126
  .option('extension', {
1110
1127
  describe:
1111
1128
  'Path to a WebExtension to be installed in the browser. Note that --extension can be passed multiple times.'
@@ -14,7 +14,7 @@ module.exports = async function (options) {
14
14
  }
15
15
 
16
16
  if (process.platform === 'darwin') {
17
- log.debug('Flush DNS cache on MacOS');
17
+ log.info('Flush DNS cache on MacOS');
18
18
  await execa('sudo', ['killall', '-HUP', 'mDNSResponder'], {
19
19
  reject: false
20
20
  });
@@ -25,7 +25,7 @@ module.exports = async function (options) {
25
25
  reject: false
26
26
  });
27
27
  } else if (process.platform === 'linux') {
28
- log.debug('Flush DNS cache on Linux');
28
+ log.info('Flush DNS cache on Linux');
29
29
  await execa('sudo', ['systemd-resolve', '--flush-caches'], {
30
30
  reject: false
31
31
  });
@@ -6,6 +6,7 @@ const readdir = promisify(fs.readdir);
6
6
  const lstat = promisify(fs.lstat);
7
7
  const unlink = promisify(fs.unlink);
8
8
  const rmdir = promisify(fs.rmdir);
9
+ const copyFile = promisify(fs.copyFile);
9
10
  const rename = promisify(fs.rename);
10
11
  const readFile = promisify(fs.readFile);
11
12
  const filters = require('./filters');
@@ -15,6 +16,9 @@ module.exports = {
15
16
  async rename(old, newName) {
16
17
  return rename(old, newName);
17
18
  },
19
+ async copyFile(source, destination) {
20
+ return copyFile(source, destination);
21
+ },
18
22
  async removeFile(fileName) {
19
23
  return unlink(fileName);
20
24
  },
@@ -4,7 +4,7 @@ const execa = require('execa');
4
4
  const log = require('intel').getLogger('browsertime.video');
5
5
  const get = require('lodash.get');
6
6
  const path = require('path');
7
- const { readFile, removeFile } = require('../../../support/fileUtil');
7
+ const { readFile, removeFile, copyFile } = require('../../../support/fileUtil');
8
8
 
9
9
  const SCRIPT_PATH = path.join(
10
10
  __dirname,
@@ -16,9 +16,29 @@ const SCRIPT_PATH = path.join(
16
16
  'visualmetrics.py'
17
17
  );
18
18
 
19
+ const PORTABLE_SCRIPT_PATH = path.join(
20
+ __dirname,
21
+ '..',
22
+ '..',
23
+ '..',
24
+ '..',
25
+ 'browsertime',
26
+ 'visualmetrics-portable.py'
27
+ );
28
+
29
+ function getScript(options) {
30
+ if (options.visualMetricsPortable) {
31
+ return PORTABLE_SCRIPT_PATH;
32
+ }
33
+ return SCRIPT_PATH;
34
+ }
35
+
19
36
  module.exports = {
20
- async checkDependencies() {
21
- return execa(process.env.PYTHON || 'python', [SCRIPT_PATH, '--check']);
37
+ async checkDependencies(options) {
38
+ return execa(process.env.PYTHON || 'python', [
39
+ getScript(options),
40
+ '--check'
41
+ ]);
22
42
  },
23
43
  async run(
24
44
  videoPath,
@@ -46,7 +66,13 @@ module.exports = {
46
66
  '--renderignore',
47
67
  5,
48
68
  '--json',
49
- '--viewport'
69
+ '--viewport',
70
+ '--viewportretries',
71
+ 60,
72
+ '--viewportminheight',
73
+ 100,
74
+ '--viewportminwidth',
75
+ 100
50
76
  ];
51
77
 
52
78
  if (options.visualMetricsPerceptual) {
@@ -103,7 +129,7 @@ module.exports = {
103
129
  scriptArgs.push('-vvv');
104
130
  }
105
131
 
106
- scriptArgs.unshift(SCRIPT_PATH);
132
+ scriptArgs.unshift(getScript(options));
107
133
 
108
134
  log.debug('Running visualmetrics.py ' + scriptArgs.join(' '));
109
135
  log.info('Get visual metrics from the video');
@@ -123,6 +149,7 @@ module.exports = {
123
149
  return JSON.parse(result.stdout);
124
150
  } catch (e) {
125
151
  log.error('VisualMetrics failed to run', e);
152
+ await copyFile(videoPath, videoPath + '.failed.mp4');
126
153
  // If something goes wrong, dump the visual metrics log to our log
127
154
  const visualMetricLog = await readFile(visualMetricsLogFile);
128
155
  log.error('Log from VisualMetrics: %s', visualMetricLog);
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "description": "Browsertime",
3
- "version": "15.2.0",
3
+ "version": "16.0.0",
4
4
  "bin": "./bin/browsertime.js",
5
5
  "dependencies": {
6
6
  "@cypress/xvfb": "1.2.4",
7
7
  "@devicefarmer/adbkit": "2.11.3",
8
- "@sitespeed.io/chromedriver": "99.0.4844-51",
9
- "@sitespeed.io/edgedriver": "99.0.1150-25",
8
+ "@sitespeed.io/chromedriver": "100.0.4896-20",
9
+ "@sitespeed.io/edgedriver": "100.0.1185-29",
10
10
  "@sitespeed.io/geckodriver": "0.30.0",
11
11
  "@sitespeed.io/throttle": "3.0.0",
12
12
  "@sitespeed.io/tracium": "0.3.3",