browsertime 16.8.0 → 16.9.1

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.
@@ -5,6 +5,7 @@ const get = require('lodash.get');
5
5
  module.exports = function (result, options) {
6
6
  let totalDurationFirstPaint = 0;
7
7
  let totalDurationFirstContentFulPaint = 0;
8
+ let totalDurationLargestContentFulPaint = 0;
8
9
  let totalDurationAfterLoadEventEnd = 0;
9
10
  let totalDuration = 0;
10
11
 
@@ -22,10 +23,16 @@ module.exports = function (result, options) {
22
23
  'browserScripts.timings.paintTiming.first-contentful-paint'
23
24
  );
24
25
 
26
+ const largestContentfulPaint = get(
27
+ result,
28
+ 'browserScripts.timings.largestContentfulPaint.renderTime'
29
+ ); // result.browserScripts.timings.largestContentfulPaint.loadTime;
30
+
25
31
  const loadEventEnd = get(result, 'browserScripts.timings.loadEventEnd');
26
32
 
27
33
  let longTasksBeforeFirstPaint = 0;
28
34
  let longTasksBeforeFirstContentfulPaint = 0;
35
+ let longTasksBeforeLargestContentfulPaint = 0;
29
36
  let longTasksAfterLoadEventEnd = 0;
30
37
  let lastLongTask = 0;
31
38
 
@@ -42,6 +49,10 @@ module.exports = function (result, options) {
42
49
  longTasksBeforeFirstContentfulPaint++;
43
50
  totalDurationFirstContentFulPaint += longTask.duration;
44
51
  }
52
+ if (largestContentfulPaint && longTask.startTime < largestContentfulPaint) {
53
+ longTasksBeforeLargestContentfulPaint++;
54
+ totalDurationLargestContentFulPaint += longTask.duration;
55
+ }
45
56
  if (
46
57
  firstContentfulPaint &&
47
58
  longTask.startTime > firstContentfulPaint &&
@@ -74,6 +85,10 @@ module.exports = function (result, options) {
74
85
  tasks: longTasksBeforeFirstContentfulPaint,
75
86
  totalDuration: totalDurationFirstContentFulPaint
76
87
  },
88
+ beforeLargestContentfulPaint: {
89
+ tasks: longTasksBeforeLargestContentfulPaint,
90
+ totalDuration: totalDurationLargestContentFulPaint
91
+ },
77
92
  afterLoadEventEnd: {
78
93
  tasks: longTasksAfterLoadEventEnd,
79
94
  totalDuration: totalDurationAfterLoadEventEnd
@@ -2,7 +2,6 @@
2
2
 
3
3
  const trafficShapeParser = require('./trafficShapeParser');
4
4
  const get = require('lodash.get');
5
- const throttle = require('@sitespeed.io/throttle');
6
5
  const log = require('intel').getLogger('browsertime.connectivity');
7
6
  const Humble = require('./humble');
8
7
 
@@ -56,6 +55,7 @@ module.exports = {
56
55
  profile.rtt
57
56
  );
58
57
  }
58
+ const throttle = await import('@sitespeed.io/throttle');
59
59
  if (setOnLocalHost) {
60
60
  return throttle.start({
61
61
  localhost: true,
@@ -91,6 +91,7 @@ module.exports = {
91
91
  }
92
92
  case 'throttle': {
93
93
  const setOnLocalHost = get(connectivity, 'throttle.localhost', false);
94
+ const throttle = await import('@sitespeed.io/throttle');
94
95
  return throttle.stop({ localhost: setOnLocalHost });
95
96
  }
96
97
  case 'humble': {
@@ -36,6 +36,7 @@ class Debug {
36
36
  );
37
37
  await delay(1000);
38
38
  }
39
+ log.info('Exit breakpoint and continue.');
39
40
  return this.browser.runScript(
40
41
  'window.browsertime.pause = false',
41
42
  'SET_PAUSE_STATUS'
@@ -101,5 +101,28 @@ class Wait {
101
101
  async byPageToComplete() {
102
102
  return this.browser.extraWait(this.pageCompleteCheck);
103
103
  }
104
+
105
+ /**
106
+ * Wait for an condition that will eventually return a truthy-value for maxTime.
107
+ * @param {string} jsExpression The js code condition to wait for
108
+ * @param {number} maxTime Max time to wait in ms
109
+ * @returns {Promise} Promise object represents when the expression becomes truthy or the time times out
110
+ * @throws Will throw an error if the condition returned false
111
+ */
112
+ async byCondition(jsExpression, maxTime) {
113
+ const driver = this.browser.getDriver();
114
+ const time = maxTime || 6000;
115
+
116
+ try {
117
+ const script = `return ${jsExpression}`;
118
+ await driver.wait(() => {
119
+ return driver.executeScript(script);
120
+ }, time);
121
+ } catch (e) {
122
+ log.error('Condition was not met', jsExpression, time);
123
+ log.verbose(e);
124
+ throw Error(`Condition ${jsExpression} was not met in ${time} ms`);
125
+ }
126
+ }
104
127
  }
105
128
  module.exports = Wait;
@@ -5,7 +5,11 @@ const merge = require('lodash.merge');
5
5
  const get = require('lodash.get');
6
6
  const { Condition } = require('selenium-webdriver/lib/webdriver');
7
7
  const { isAndroidConfigured } = require('../android');
8
- const { UrlLoadError, BrowserError } = require('../support/errors');
8
+ const {
9
+ UrlLoadError,
10
+ BrowserError,
11
+ TimeoutError
12
+ } = require('../support/errors');
9
13
  const builder = require('./webdriver');
10
14
  const getViewPort = require('../support/getViewPort');
11
15
  const defaultPageCompleteCheck = require('./pageCompleteChecks/defaultPageCompleteCheck');
@@ -18,7 +22,7 @@ const defaults = {
18
22
  pageLoad: 300000,
19
23
  script: 120000,
20
24
  logs: 90000,
21
- pageCompleteCheck: 300000
25
+ pageCompleteCheck: 60000
22
26
  },
23
27
  index: 0
24
28
  };
@@ -36,7 +40,7 @@ async function timeout(promise, ms, errorMessage) {
36
40
 
37
41
  return Promise.race([
38
42
  new Promise((resolve, reject) => {
39
- timer = setTimeout(reject, ms, new BrowserError(errorMessage));
43
+ timer = setTimeout(reject, ms, new TimeoutError(errorMessage));
40
44
  return timer;
41
45
  }),
42
46
  promise.then(value => {
@@ -182,20 +186,26 @@ class SeleniumRunner {
182
186
  `Running page complete check ${pageCompleteCheck} took too long`
183
187
  );
184
188
  } catch (e) {
185
- log.error(
186
- `Failed waiting on page ${
187
- url ? url : ''
188
- } to finished loading, timed out after ${pageCompleteCheckTimeout} ms`,
189
- e
190
- );
191
- throw new UrlLoadError(
192
- `Failed waiting on page ${
193
- url ? url : ''
194
- } to finished loading, timed out after ${pageCompleteCheckTimeout} ms `,
195
- {
196
- cause: e
197
- }
198
- );
189
+ if (e instanceof TimeoutError) {
190
+ log.info(
191
+ `The page did not finished loading in ${pageCompleteCheckTimeout} ms. You can adjust the timeout by setting the --maxLoadTime option (in ms).`
192
+ );
193
+ } else {
194
+ log.error(
195
+ `Failed waiting on page ${
196
+ url ? url : ''
197
+ } to finished loading, timed out after ${pageCompleteCheckTimeout} ms`,
198
+ e
199
+ );
200
+ throw new UrlLoadError(
201
+ `Failed waiting on page ${
202
+ url ? url : ''
203
+ } to finished loading, timed out after ${pageCompleteCheckTimeout} ms `,
204
+ {
205
+ cause: e
206
+ }
207
+ );
208
+ }
199
209
  }
200
210
  }
201
211
 
@@ -104,19 +104,6 @@ class Firefox {
104
104
  */
105
105
  async afterPageCompleteCheck(runner, index, url, alias) {
106
106
  const result = { url, alias };
107
- if (this.firefoxConfig.collectMozLog) {
108
- const files = await fileUtil.findFiles(this.baseDir, 'moz_log.txt');
109
- for (const file of files) {
110
- await rename(
111
- `${this.baseDir}/${file}`,
112
- path.join(
113
- this.baseDir,
114
- pathToFolder(result.url, this.options),
115
- `${file}-${index}.txt`
116
- )
117
- );
118
- }
119
- }
120
107
 
121
108
  if (this.android && this.options.androidPower) {
122
109
  result.power = await this.android.measurePowerUsage(
@@ -192,6 +179,20 @@ class Firefox {
192
179
 
193
180
  async postWork(index, results) {
194
181
  for (let i = 0; i < results.length; i++) {
182
+ if (this.firefoxConfig.collectMozLog) {
183
+ const files = await fileUtil.findFiles(this.baseDir, 'moz_log.txt');
184
+ for (const file of files) {
185
+ await rename(
186
+ `${this.baseDir}/${file}`,
187
+ path.join(
188
+ this.baseDir,
189
+ pathToFolder(results[i].url, this.options),
190
+ `${file}-${index}.txt`
191
+ )
192
+ );
193
+ }
194
+ }
195
+
195
196
  if (this.firefoxConfig.geckoProfiler && this.options.visualMetrics) {
196
197
  const profileFilename = `geckoProfile-${index}.json.gz`;
197
198
  const profileSubdir = pathToFolder(results[i].url, this.options);
@@ -162,7 +162,8 @@ module.exports.parseCommandLine = function parseCommandLine() {
162
162
  group: 'timeouts'
163
163
  })
164
164
  .option('timeouts.pageCompleteCheck', {
165
- default: 300000,
165
+ alias: 'maxLoadTime',
166
+ default: 120000,
166
167
  type: 'number',
167
168
  describe:
168
169
  'Timeout when waiting for page to complete loading, in milliseconds',
@@ -21,8 +21,16 @@ class UrlLoadError extends BrowsertimeError {
21
21
  }
22
22
  }
23
23
 
24
+ class TimeoutError extends BrowsertimeError {
25
+ constructor(message, url, extra) {
26
+ super(message, extra);
27
+ this.url = url;
28
+ }
29
+ }
30
+
24
31
  module.exports = {
25
32
  BrowsertimeError,
26
33
  BrowserError,
27
- UrlLoadError
34
+ UrlLoadError,
35
+ TimeoutError
28
36
  };
@@ -81,10 +81,6 @@ module.exports = {
81
81
  scriptArgs.push('--perceptual');
82
82
  }
83
83
 
84
- if (options.visualMetricsNotification) {
85
- scriptArgs.push('--notification');
86
- }
87
-
88
84
  if (options.visualMetricsContentful) {
89
85
  scriptArgs.push('--contentful');
90
86
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "description": "Browsertime",
3
- "version": "16.8.0",
3
+ "version": "16.9.1",
4
4
  "bin": "./bin/browsertime.js",
5
5
  "dependencies": {
6
6
  "@cypress/xvfb": "1.2.4",
@@ -8,7 +8,7 @@
8
8
  "@sitespeed.io/chromedriver": "102.0.5005-27",
9
9
  "@sitespeed.io/edgedriver": "101.0.1210-32",
10
10
  "@sitespeed.io/geckodriver": "0.31.0",
11
- "@sitespeed.io/throttle": "3.1.1",
11
+ "@sitespeed.io/throttle": "4.0.1",
12
12
  "@sitespeed.io/tracium": "0.3.3",
13
13
  "btoa": "1.2.1",
14
14
  "chrome-har": "0.13.0",