browsertime 16.17.0 → 17.0.0-beta.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.
- package/CHANGELOG.md +44 -0
- package/bin/browsertime.js +43 -43
- package/bin/browsertimeWebPageReplay.js +10 -9
- package/browserscripts/pageinfo/generator.js +1 -1
- package/index.js +14 -13
- package/lib/android/gnirehtet.js +14 -15
- package/lib/android/index.js +92 -89
- package/lib/android/root.js +6 -9
- package/lib/chrome/chromeDevtoolsProtocol.js +46 -45
- package/lib/chrome/har.js +12 -13
- package/lib/chrome/longTaskMetrics.js +3 -5
- package/lib/chrome/parseCpuTrace.js +13 -10
- package/lib/chrome/settings/chromeAndroidOptions.js +1 -3
- package/lib/chrome/settings/chromeDesktopOptions.js +1 -3
- package/lib/chrome/settings/traceCategories.js +1 -3
- package/lib/chrome/traceCategoriesParser.js +35 -36
- package/lib/chrome/webdriver/builder.js +18 -26
- package/lib/chrome/webdriver/chromium.js +56 -46
- package/lib/chrome/webdriver/setupChromiumOptions.js +32 -27
- package/lib/connectivity/humble.js +13 -14
- package/lib/connectivity/index.js +74 -77
- package/lib/connectivity/trafficShapeParser.js +31 -35
- package/lib/core/engine/collector.js +22 -22
- package/lib/core/engine/command/addText.js +24 -27
- package/lib/core/engine/command/android.js +7 -11
- package/lib/core/engine/command/cache.js +3 -4
- package/lib/core/engine/command/chromeDevToolsProtocol.js +20 -20
- package/lib/core/engine/command/click.js +48 -49
- package/lib/core/engine/command/debug.js +3 -4
- package/lib/core/engine/command/javaScript.js +18 -19
- package/lib/core/engine/command/measure.js +31 -37
- package/lib/core/engine/command/meta.js +1 -4
- package/lib/core/engine/command/mouse/clickAndHold.js +36 -39
- package/lib/core/engine/command/mouse/contextClick.js +17 -18
- package/lib/core/engine/command/mouse/doubleClick.js +17 -19
- package/lib/core/engine/command/mouse/index.js +5 -9
- package/lib/core/engine/command/mouse/mouseMove.js +19 -23
- package/lib/core/engine/command/mouse/singleClick.js +15 -19
- package/lib/core/engine/command/navigation.js +12 -14
- package/lib/core/engine/command/screenshot.js +1 -4
- package/lib/core/engine/command/scroll.js +4 -7
- package/lib/core/engine/command/select.js +26 -26
- package/lib/core/engine/command/set.js +25 -23
- package/lib/core/engine/command/stopWatch.js +5 -8
- package/lib/core/engine/command/switch.js +18 -20
- package/lib/core/engine/command/util/lcpHighlightScript.js +1 -2
- package/lib/core/engine/command/util/lsHighlightScript.js +1 -2
- package/lib/core/engine/command/wait.js +18 -18
- package/lib/core/engine/index.js +81 -71
- package/lib/core/engine/iteration.js +83 -79
- package/lib/core/engine/run.js +5 -9
- package/lib/core/pageCompleteChecks/defaultPageCompleteCheck.js +1 -2
- package/lib/core/pageCompleteChecks/pageCompleteCheckByInactivity.js +1 -3
- package/lib/core/pageCompleteChecks/spaInactivity.js +1 -3
- package/lib/core/seleniumRunner.js +92 -100
- package/lib/core/webdriver/index.js +24 -21
- package/lib/edge/webdriver/builder.js +21 -26
- package/lib/extensionserver/httpServer.js +17 -21
- package/lib/extensionserver/index.js +8 -12
- package/lib/extensionserver/setup.js +12 -12
- package/lib/firefox/geckoProfiler.js +27 -21
- package/lib/firefox/getHAR.js +7 -8
- package/lib/firefox/memoryReport.js +9 -11
- package/lib/firefox/perfStats.js +5 -7
- package/lib/firefox/settings/disableSafeBrowsingPreferences.js +1 -3
- package/lib/firefox/settings/disableTrackingProtectionPreferences.js +1 -3
- package/lib/firefox/settings/firefoxPreferences.js +2 -4
- package/lib/firefox/settings/geckoProfilerDefaults.js +5 -9
- package/lib/firefox/webdriver/builder.js +66 -63
- package/lib/firefox/webdriver/firefox.js +43 -48
- package/lib/safari/webdriver/builder.js +4 -5
- package/lib/safari/webdriver/safari.js +4 -8
- package/lib/screenshot/defaults.js +1 -3
- package/lib/screenshot/index.js +24 -21
- package/lib/support/browserScript.js +65 -56
- package/lib/support/cli.js +120 -87
- package/lib/support/dns.js +6 -7
- package/lib/support/engineUtils.js +85 -38
- package/lib/support/errors.js +4 -13
- package/lib/support/fileUtil.js +81 -68
- package/lib/support/filters.js +15 -20
- package/lib/support/getViewPort.js +6 -7
- package/lib/support/har/index.js +208 -216
- package/lib/support/images/index.js +54 -26
- package/lib/support/logging.js +20 -17
- package/lib/support/pathToFolder.js +18 -23
- package/lib/support/preURL.js +5 -6
- package/lib/support/processes.js +4 -6
- package/lib/support/setResourceTimingBufferSize.js +2 -4
- package/lib/support/statistics.js +58 -56
- package/lib/support/stop.js +7 -8
- package/lib/support/storageManager.js +44 -44
- package/lib/support/tcpdump.js +22 -16
- package/lib/support/userTiming.js +7 -13
- package/lib/support/util.js +204 -224
- package/lib/support/xvfb.js +11 -13
- package/lib/video/defaults.js +6 -10
- package/lib/video/postprocessing/finetune/addTextToVideo.js +15 -15
- package/lib/video/postprocessing/finetune/convertFps.js +14 -8
- package/lib/video/postprocessing/finetune/getFont.js +7 -9
- package/lib/video/postprocessing/finetune/getTimingMetrics.js +19 -18
- package/lib/video/postprocessing/finetune/index.js +40 -36
- package/lib/video/postprocessing/finetune/removeOrange.js +10 -11
- package/lib/video/postprocessing/visualmetrics/extraMetrics.js +17 -13
- package/lib/video/postprocessing/visualmetrics/getVideoMetrics.js +12 -13
- package/lib/video/postprocessing/visualmetrics/visualMetrics.js +117 -128
- package/lib/video/screenRecording/android/recorder.js +12 -17
- package/lib/video/screenRecording/desktop/convert.js +13 -11
- package/lib/video/screenRecording/desktop/desktopRecorder.js +29 -24
- package/lib/video/screenRecording/desktop/ffmpegRecorder.js +60 -63
- package/lib/video/screenRecording/desktop/osx/getSPDisplaysDataType.js +4 -6
- package/lib/video/screenRecording/desktop/osx/getScreen.js +9 -10
- package/lib/video/screenRecording/firefox/firefoxWindowRecorder.js +54 -54
- package/lib/video/screenRecording/ios/convertToMp4.js +10 -11
- package/lib/video/screenRecording/ios/iosRecorder.js +23 -21
- package/lib/video/screenRecording/iosSimulator/convertToMp4.js +10 -11
- package/lib/video/screenRecording/iosSimulator/recorder.js +10 -9
- package/lib/video/screenRecording/recorder.js +8 -9
- package/lib/video/screenRecording/setOrangeBackground.js +5 -6
- package/lib/video/video.js +28 -34
- package/package.json +19 -17
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import intel from 'intel';
|
|
2
|
+
const log = intel.getLogger('browsertime.command.set');
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
class Set {
|
|
4
|
+
export default class Set {
|
|
6
5
|
constructor(browser) {
|
|
7
6
|
this.browser = browser;
|
|
8
7
|
}
|
|
@@ -19,10 +18,12 @@ class Set {
|
|
|
19
18
|
try {
|
|
20
19
|
const script = `document.querySelector('${selector}').innerHTML = '${html}';`;
|
|
21
20
|
await this.browser.runScript(script, 'CUSTOM');
|
|
22
|
-
} catch (
|
|
21
|
+
} catch (error) {
|
|
23
22
|
log.error('Could not set inner HTML %s for selector %s', html, selector);
|
|
24
|
-
log.verbose(
|
|
25
|
-
throw Error(
|
|
23
|
+
log.verbose(error);
|
|
24
|
+
throw new Error(
|
|
25
|
+
`Could not set inner HTML ${html} for selector ${selector}`
|
|
26
|
+
);
|
|
26
27
|
}
|
|
27
28
|
}
|
|
28
29
|
|
|
@@ -38,10 +39,10 @@ class Set {
|
|
|
38
39
|
try {
|
|
39
40
|
const script = `document.getElementById('${id}').innerHTML = '${html}';`;
|
|
40
41
|
await this.browser.runScript(script, 'CUSTOM');
|
|
41
|
-
} catch (
|
|
42
|
+
} catch (error) {
|
|
42
43
|
log.error('Could not set inner HTML %s for id %s', html, id);
|
|
43
|
-
log.verbose(
|
|
44
|
-
throw Error(`Could not set inner HTML ${html} for id ${id}`);
|
|
44
|
+
log.verbose(error);
|
|
45
|
+
throw new Error(`Could not set inner HTML ${html} for id ${id}`);
|
|
45
46
|
}
|
|
46
47
|
}
|
|
47
48
|
|
|
@@ -57,10 +58,12 @@ class Set {
|
|
|
57
58
|
try {
|
|
58
59
|
const script = `document.querySelector('${selector}').innerText = '${text}';`;
|
|
59
60
|
await this.browser.runScript(script, 'CUSTOM');
|
|
60
|
-
} catch (
|
|
61
|
+
} catch (error) {
|
|
61
62
|
log.error('Could not set inner text %s for selector %s', text, selector);
|
|
62
|
-
log.verbose(
|
|
63
|
-
throw Error(
|
|
63
|
+
log.verbose(error);
|
|
64
|
+
throw new Error(
|
|
65
|
+
`Could not set inner text ${text} for selector ${selector}`
|
|
66
|
+
);
|
|
64
67
|
}
|
|
65
68
|
}
|
|
66
69
|
|
|
@@ -76,10 +79,10 @@ class Set {
|
|
|
76
79
|
try {
|
|
77
80
|
const script = `document.getElementById('${id}').innerText = '${text}';`;
|
|
78
81
|
await this.browser.runScript(script, 'CUSTOM');
|
|
79
|
-
} catch (
|
|
82
|
+
} catch (error) {
|
|
80
83
|
log.error('Could not set inner text %s for id %s', text, id);
|
|
81
|
-
log.verbose(
|
|
82
|
-
throw Error(`Could not set inner text ${text} for id ${id}`);
|
|
84
|
+
log.verbose(error);
|
|
85
|
+
throw new Error(`Could not set inner text ${text} for id ${id}`);
|
|
83
86
|
}
|
|
84
87
|
}
|
|
85
88
|
|
|
@@ -95,10 +98,10 @@ class Set {
|
|
|
95
98
|
try {
|
|
96
99
|
const script = `document.querySelector('${selector}').value = '${value}';`;
|
|
97
100
|
await this.browser.runScript(script, 'CUSTOM');
|
|
98
|
-
} catch (
|
|
101
|
+
} catch (error) {
|
|
99
102
|
log.error('Could not set value %s for selector %s', value, selector);
|
|
100
|
-
log.verbose(
|
|
101
|
-
throw Error(`Could not set value ${value} for selector ${selector}`);
|
|
103
|
+
log.verbose(error);
|
|
104
|
+
throw new Error(`Could not set value ${value} for selector ${selector}`);
|
|
102
105
|
}
|
|
103
106
|
}
|
|
104
107
|
|
|
@@ -114,11 +117,10 @@ class Set {
|
|
|
114
117
|
try {
|
|
115
118
|
const script = `document.getElementById('${id}').value= '${value}';`;
|
|
116
119
|
await this.browser.runScript(script, 'CUSTOM');
|
|
117
|
-
} catch (
|
|
120
|
+
} catch (error) {
|
|
118
121
|
log.error('Could not set value %s for id %s', value, id);
|
|
119
|
-
log.verbose(
|
|
120
|
-
throw Error(`Could not set value ${value} for id ${id}`);
|
|
122
|
+
log.verbose(error);
|
|
123
|
+
throw new Error(`Could not set value ${value} for id ${id}`);
|
|
121
124
|
}
|
|
122
125
|
}
|
|
123
126
|
}
|
|
124
|
-
module.exports = Set;
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const log =
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class StopWatch {
|
|
1
|
+
import { performance } from 'node:perf_hooks';
|
|
2
|
+
import intel from 'intel';
|
|
3
|
+
const log = intel.getLogger('browsertime.command.stopwatch');
|
|
4
|
+
export class StopWatch {
|
|
7
5
|
constructor(name, measure) {
|
|
8
6
|
this.name = name;
|
|
9
7
|
this.measure = measure;
|
|
@@ -49,7 +47,7 @@ class StopWatch {
|
|
|
49
47
|
}
|
|
50
48
|
}
|
|
51
49
|
|
|
52
|
-
class Watch {
|
|
50
|
+
export default class Watch {
|
|
53
51
|
constructor(measure) {
|
|
54
52
|
this.measure = measure;
|
|
55
53
|
}
|
|
@@ -58,4 +56,3 @@ class Watch {
|
|
|
58
56
|
return new StopWatch(name, this.measure);
|
|
59
57
|
}
|
|
60
58
|
}
|
|
61
|
-
module.exports = Watch;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import intel from 'intel';
|
|
2
|
+
const log = intel.getLogger('browsertime.command.switch');
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
class Switch {
|
|
4
|
+
export default class Switch {
|
|
6
5
|
constructor(browser, pageCompleteCheck, navigate) {
|
|
7
6
|
this.browser = browser;
|
|
8
7
|
this.pageCompleteCheck = pageCompleteCheck;
|
|
@@ -17,10 +16,10 @@ class Switch {
|
|
|
17
16
|
const driver = this.browser.getDriver();
|
|
18
17
|
try {
|
|
19
18
|
await driver.switchTo().frame(id);
|
|
20
|
-
} catch (
|
|
19
|
+
} catch (error) {
|
|
21
20
|
log.error('Could not switch to frame with id %s ', id);
|
|
22
|
-
log.verbose(
|
|
23
|
-
throw Error(`Could not switch to frame with id ${id}`);
|
|
21
|
+
log.verbose(error);
|
|
22
|
+
throw new Error(`Could not switch to frame with id ${id}`);
|
|
24
23
|
}
|
|
25
24
|
}
|
|
26
25
|
|
|
@@ -32,10 +31,10 @@ class Switch {
|
|
|
32
31
|
const driver = this.browser.getDriver();
|
|
33
32
|
try {
|
|
34
33
|
await driver.switchTo().window(name);
|
|
35
|
-
} catch (
|
|
34
|
+
} catch (error) {
|
|
36
35
|
log.error('Could not switch to frame with name %s ', name);
|
|
37
|
-
log.verbose(
|
|
38
|
-
throw Error(`Could not switch to frame with name ${name}`);
|
|
36
|
+
log.verbose(error);
|
|
37
|
+
throw new Error(`Could not switch to frame with name ${name}`);
|
|
39
38
|
}
|
|
40
39
|
}
|
|
41
40
|
|
|
@@ -46,10 +45,10 @@ class Switch {
|
|
|
46
45
|
const driver = this.browser.getDriver();
|
|
47
46
|
try {
|
|
48
47
|
await driver.switchTo().parentFrame();
|
|
49
|
-
} catch (
|
|
48
|
+
} catch (error) {
|
|
50
49
|
log.error('Could not switch to parent frame');
|
|
51
|
-
log.verbose(
|
|
52
|
-
throw Error(`Could not switch to parent frame`);
|
|
50
|
+
log.verbose(error);
|
|
51
|
+
throw new Error(`Could not switch to parent frame`);
|
|
53
52
|
}
|
|
54
53
|
}
|
|
55
54
|
|
|
@@ -63,10 +62,10 @@ class Switch {
|
|
|
63
62
|
await this.navigate(url);
|
|
64
63
|
await this.browser.extraWait(this.pageCompleteCheck);
|
|
65
64
|
}
|
|
66
|
-
} catch (
|
|
65
|
+
} catch (error) {
|
|
67
66
|
log.error('Could not open new tab');
|
|
68
|
-
log.verbose(
|
|
69
|
-
throw Error('Could not open new tab');
|
|
67
|
+
log.verbose(error);
|
|
68
|
+
throw new Error('Could not open new tab');
|
|
70
69
|
}
|
|
71
70
|
|
|
72
71
|
return;
|
|
@@ -82,13 +81,12 @@ class Switch {
|
|
|
82
81
|
await this.navigate(url);
|
|
83
82
|
await this.browser.extraWait(this.pageCompleteCheck);
|
|
84
83
|
}
|
|
85
|
-
} catch (
|
|
84
|
+
} catch (error) {
|
|
86
85
|
log.error('Could not open new window');
|
|
87
|
-
log.verbose(
|
|
88
|
-
throw Error('Could not open new window');
|
|
86
|
+
log.verbose(error);
|
|
87
|
+
throw new Error('Could not open new window');
|
|
89
88
|
}
|
|
90
89
|
|
|
91
90
|
return;
|
|
92
91
|
}
|
|
93
92
|
}
|
|
94
|
-
module.exports = Switch;
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
const log = require('intel').getLogger('browsertime.command.wait');
|
|
1
|
+
import webdriver from 'selenium-webdriver';
|
|
2
|
+
import intel from 'intel';
|
|
3
|
+
const log = intel.getLogger('browsertime.command.wait');
|
|
5
4
|
const delay = ms => new Promise(res => setTimeout(res, ms));
|
|
6
5
|
|
|
7
|
-
class Wait {
|
|
6
|
+
export default class Wait {
|
|
8
7
|
constructor(browser, pageCompleteCheck) {
|
|
9
8
|
this.browser = browser;
|
|
10
9
|
this.pageCompleteCheck = pageCompleteCheck;
|
|
@@ -26,10 +25,10 @@ class Wait {
|
|
|
26
25
|
webdriver.until.elementLocated(webdriver.By.id(id)),
|
|
27
26
|
time
|
|
28
27
|
);
|
|
29
|
-
} catch (
|
|
28
|
+
} catch (error) {
|
|
30
29
|
log.error('Element by id %s was not located in %s ms', id, time);
|
|
31
|
-
log.verbose(
|
|
32
|
-
throw Error(`Element by id ${id} was not located in ${time} ms`);
|
|
30
|
+
log.verbose(error);
|
|
31
|
+
throw new Error(`Element by id ${id} was not located in ${time} ms`);
|
|
33
32
|
}
|
|
34
33
|
}
|
|
35
34
|
|
|
@@ -49,10 +48,12 @@ class Wait {
|
|
|
49
48
|
webdriver.until.elementLocated(webdriver.By.xpath(xpath)),
|
|
50
49
|
time
|
|
51
50
|
);
|
|
52
|
-
} catch (
|
|
51
|
+
} catch (error) {
|
|
53
52
|
log.error('Element by xpath %s was not located in %s ms', xpath, time);
|
|
54
|
-
log.verbose(
|
|
55
|
-
throw Error(
|
|
53
|
+
log.verbose(error);
|
|
54
|
+
throw new Error(
|
|
55
|
+
`Element by xpath ${xpath} was not located in ${time} ms`
|
|
56
|
+
);
|
|
56
57
|
}
|
|
57
58
|
}
|
|
58
59
|
|
|
@@ -72,14 +73,14 @@ class Wait {
|
|
|
72
73
|
webdriver.until.elementLocated(webdriver.By.css(selector)),
|
|
73
74
|
time
|
|
74
75
|
);
|
|
75
|
-
} catch (
|
|
76
|
+
} catch (error) {
|
|
76
77
|
log.error(
|
|
77
78
|
'Element by selector %s was not located in %s ms',
|
|
78
79
|
selector,
|
|
79
80
|
time
|
|
80
81
|
);
|
|
81
|
-
log.verbose(
|
|
82
|
-
throw Error(
|
|
82
|
+
log.verbose(error);
|
|
83
|
+
throw new Error(
|
|
83
84
|
`Element by selector ${selector} was not located in ${time} ms`
|
|
84
85
|
);
|
|
85
86
|
}
|
|
@@ -118,11 +119,10 @@ class Wait {
|
|
|
118
119
|
await driver.wait(() => {
|
|
119
120
|
return driver.executeScript(script);
|
|
120
121
|
}, time);
|
|
121
|
-
} catch (
|
|
122
|
+
} catch (error) {
|
|
122
123
|
log.error('Condition was not met', jsExpression, time);
|
|
123
|
-
log.verbose(
|
|
124
|
-
throw Error(`Condition ${jsExpression} was not met in ${time} ms`);
|
|
124
|
+
log.verbose(error);
|
|
125
|
+
throw new Error(`Condition ${jsExpression} was not met in ${time} ms`);
|
|
125
126
|
}
|
|
126
127
|
}
|
|
127
128
|
}
|
|
128
|
-
module.exports = Wait;
|
package/lib/core/engine/index.js
CHANGED
|
@@ -1,35 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
1
|
+
import { arch as _arch } from 'node:os';
|
|
2
|
+
import intel from 'intel';
|
|
3
|
+
import merge from 'lodash.merge';
|
|
4
|
+
import getPort, { portNumbers } from 'get-port';
|
|
5
|
+
import { execaCommand as command } from 'execa';
|
|
6
|
+
import get from 'lodash.get';
|
|
7
|
+
import StorageManager from '../../support/storageManager.js';
|
|
8
|
+
import Firefox from '../../firefox/webdriver/firefox.js';
|
|
9
|
+
import Chromium from '../../chrome/webdriver/chromium.js';
|
|
10
|
+
import Safari from '../../safari/webdriver/safari.js';
|
|
11
|
+
import {
|
|
12
|
+
addConnectivity,
|
|
13
|
+
removeConnectivity
|
|
14
|
+
} from '../../connectivity/index.js';
|
|
15
|
+
import { logResultLogLine } from '../../support/util.js';
|
|
16
|
+
import {
|
|
17
|
+
getFullyLoaded,
|
|
18
|
+
getMainDocumentTimings,
|
|
19
|
+
addExtraFieldsToHar
|
|
20
|
+
} from '../../support/har/index.js';
|
|
21
|
+
import XVFB from '../../support/xvfb.js';
|
|
22
|
+
import Gnirehtet from '../../android/gnirehtet.js';
|
|
23
|
+
import Iteration from './iteration.js';
|
|
24
|
+
import Collector from './collector.js';
|
|
25
|
+
import { Android, isAndroidConfigured } from '../../android/index.js';
|
|
26
|
+
import RootedDevice from '../../android/root.js';
|
|
27
|
+
import run from './run.js';
|
|
28
|
+
import { loadScript } from '../../support/engineUtils.js';
|
|
29
|
+
import IOSRecorder from '../../video/screenRecording/ios/iosRecorder.js';
|
|
30
|
+
const log = intel.getLogger('browsertime');
|
|
26
31
|
const defaults = {
|
|
27
32
|
scripts: [],
|
|
28
33
|
iterations: 3,
|
|
29
34
|
delay: 0,
|
|
30
35
|
videoParams: {}
|
|
31
36
|
};
|
|
32
|
-
|
|
33
37
|
const delay = ms => new Promise(res => setTimeout(res, ms));
|
|
34
38
|
|
|
35
39
|
function shouldDelay(index, total, delay) {
|
|
@@ -41,7 +45,7 @@ function shouldDelay(index, total, delay) {
|
|
|
41
45
|
* Create a new Browsertime Engine.
|
|
42
46
|
* @class
|
|
43
47
|
*/
|
|
44
|
-
class Engine {
|
|
48
|
+
export default class Engine {
|
|
45
49
|
constructor(options) {
|
|
46
50
|
this.options = merge({}, defaults, options);
|
|
47
51
|
if (log.isEnabledFor(log.DEBUG)) {
|
|
@@ -60,7 +64,7 @@ class Engine {
|
|
|
60
64
|
const options = this.options;
|
|
61
65
|
|
|
62
66
|
options.devToolsPort = await getPort({
|
|
63
|
-
port:
|
|
67
|
+
port: portNumbers(9222, 9350),
|
|
64
68
|
host: '127.0.0.1'
|
|
65
69
|
});
|
|
66
70
|
|
|
@@ -69,7 +73,7 @@ class Engine {
|
|
|
69
73
|
);
|
|
70
74
|
|
|
71
75
|
options.safariDriverPort = await getPort({
|
|
72
|
-
port:
|
|
76
|
+
port: portNumbers(1234, 2000),
|
|
73
77
|
host: '127.0.0.1'
|
|
74
78
|
});
|
|
75
79
|
|
|
@@ -80,7 +84,7 @@ class Engine {
|
|
|
80
84
|
|
|
81
85
|
await addConnectivity(options);
|
|
82
86
|
|
|
83
|
-
if (options
|
|
87
|
+
if (isAndroidConfigured(options)) {
|
|
84
88
|
const android = new Android(options);
|
|
85
89
|
await android._init();
|
|
86
90
|
this.android = android;
|
|
@@ -94,7 +98,7 @@ class Engine {
|
|
|
94
98
|
if (phoneState !== 'device') {
|
|
95
99
|
const message = `The phone ${android.id} state is ${phoneState}`;
|
|
96
100
|
log.error(message);
|
|
97
|
-
throw Error(message);
|
|
101
|
+
throw new Error(message);
|
|
98
102
|
}
|
|
99
103
|
|
|
100
104
|
if (options.androidPretestPowerPress) {
|
|
@@ -111,7 +115,7 @@ class Engine {
|
|
|
111
115
|
if (!connection) {
|
|
112
116
|
const message = `No internet connection for ${android.id}. Could not ping ${pingAddress}`;
|
|
113
117
|
log.error(message);
|
|
114
|
-
throw Error(message);
|
|
118
|
+
throw new Error(message);
|
|
115
119
|
}
|
|
116
120
|
}
|
|
117
121
|
|
|
@@ -124,7 +128,7 @@ class Engine {
|
|
|
124
128
|
const gotRoot = await android._runCommandAndGet(
|
|
125
129
|
'su - root -c "echo test"'
|
|
126
130
|
);
|
|
127
|
-
if (gotRoot.
|
|
131
|
+
if (gotRoot.includes('not found')) {
|
|
128
132
|
log.info('Your phone do not have su, is it really rooted?');
|
|
129
133
|
} else {
|
|
130
134
|
this.rooted = new RootedDevice(this.android);
|
|
@@ -135,25 +139,25 @@ class Engine {
|
|
|
135
139
|
if (options.androidBatteryTemperatureLimit) {
|
|
136
140
|
const maxTries = options.androidBatteryTemperatureMaxTries || 20;
|
|
137
141
|
let batteryTry = 0;
|
|
138
|
-
let
|
|
139
|
-
const
|
|
142
|
+
let temporary = await android.getTemperature();
|
|
143
|
+
const minTemporaryLimit = options.androidBatteryTemperatureLimit;
|
|
140
144
|
const waitTime =
|
|
141
145
|
(options.androidBatteryTemperatureWaitTimeInSeconds || 120) * 1000;
|
|
142
|
-
if (
|
|
146
|
+
if (temporary > minTemporaryLimit) {
|
|
143
147
|
do {
|
|
144
|
-
|
|
148
|
+
temporary = await android.getTemperature();
|
|
145
149
|
log.info(
|
|
146
150
|
'Battery temperature is %s, waiting it to go down under %s, will sleep for %s s',
|
|
147
|
-
|
|
148
|
-
|
|
151
|
+
temporary,
|
|
152
|
+
minTemporaryLimit,
|
|
149
153
|
waitTime / 1000
|
|
150
154
|
);
|
|
151
155
|
batteryTry++;
|
|
152
156
|
if (batteryTry === maxTries) {
|
|
153
157
|
log.error(
|
|
154
158
|
'Battery temperature (%s) never got under %s after %s tries.',
|
|
155
|
-
|
|
156
|
-
|
|
159
|
+
temporary,
|
|
160
|
+
minTemporaryLimit,
|
|
157
161
|
maxTries
|
|
158
162
|
);
|
|
159
163
|
if (options.androidBatteryTemperatureReboot) {
|
|
@@ -162,14 +166,17 @@ class Engine {
|
|
|
162
166
|
);
|
|
163
167
|
await android.reboot();
|
|
164
168
|
}
|
|
165
|
-
throw Error(
|
|
169
|
+
throw new Error(
|
|
166
170
|
'Battery temperature never got under the configured limit'
|
|
167
171
|
);
|
|
168
172
|
}
|
|
169
173
|
await delay(waitTime);
|
|
170
|
-
} while (
|
|
174
|
+
} while (temporary > minTemporaryLimit);
|
|
171
175
|
} else {
|
|
172
|
-
log.info(
|
|
176
|
+
log.info(
|
|
177
|
+
'Battery temperature is %s, lets start the tests',
|
|
178
|
+
temporary
|
|
179
|
+
);
|
|
173
180
|
}
|
|
174
181
|
}
|
|
175
182
|
|
|
@@ -182,17 +189,17 @@ class Engine {
|
|
|
182
189
|
if (options.safari && options.safari.useSimulator) {
|
|
183
190
|
// Start the simulator
|
|
184
191
|
try {
|
|
185
|
-
await
|
|
192
|
+
await command(
|
|
186
193
|
'open -a /Applications/Xcode.app/Contents/Developer/Applications/Simulator.app/',
|
|
187
194
|
{ shell: true }
|
|
188
195
|
);
|
|
189
196
|
await delay(4000);
|
|
190
|
-
} catch (
|
|
191
|
-
log.error('Could not start the Simulator.app',
|
|
192
|
-
throw
|
|
197
|
+
} catch (error) {
|
|
198
|
+
log.error('Could not start the Simulator.app', error);
|
|
199
|
+
throw error;
|
|
193
200
|
}
|
|
194
201
|
|
|
195
|
-
const { stdout } = await
|
|
202
|
+
const { stdout } = await command('xcrun simctl list devices -j', {
|
|
196
203
|
shell: true
|
|
197
204
|
});
|
|
198
205
|
|
|
@@ -205,7 +212,7 @@ class Engine {
|
|
|
205
212
|
log.info(
|
|
206
213
|
'Running test on %s simulator using %s',
|
|
207
214
|
this.iosSimulatorDeviceName,
|
|
208
|
-
|
|
215
|
+
_arch()
|
|
209
216
|
);
|
|
210
217
|
break;
|
|
211
218
|
}
|
|
@@ -223,23 +230,27 @@ class Engine {
|
|
|
223
230
|
asyncScriptsByCategory
|
|
224
231
|
) {
|
|
225
232
|
const options = this.options;
|
|
226
|
-
if (name
|
|
233
|
+
if (Array.isArray(name)) {
|
|
227
234
|
name = name[0];
|
|
228
235
|
}
|
|
229
236
|
const storageManager = new StorageManager(name, options);
|
|
230
237
|
let engineDelegate;
|
|
231
238
|
switch (options.browser) {
|
|
232
|
-
case 'firefox':
|
|
239
|
+
case 'firefox': {
|
|
233
240
|
engineDelegate = new Firefox(storageManager, options);
|
|
234
241
|
break;
|
|
235
|
-
|
|
242
|
+
}
|
|
243
|
+
case 'chrome': {
|
|
236
244
|
engineDelegate = new Chromium(storageManager, options);
|
|
237
245
|
break;
|
|
238
|
-
|
|
246
|
+
}
|
|
247
|
+
case 'edge': {
|
|
239
248
|
engineDelegate = new Chromium(storageManager, options);
|
|
240
249
|
break;
|
|
241
|
-
|
|
250
|
+
}
|
|
251
|
+
case 'safari': {
|
|
242
252
|
engineDelegate = new Safari(storageManager, options);
|
|
253
|
+
}
|
|
243
254
|
}
|
|
244
255
|
const iteration = new Iteration(
|
|
245
256
|
storageManager,
|
|
@@ -253,7 +264,7 @@ class Engine {
|
|
|
253
264
|
await engineDelegate.beforeBrowserStart(name, options);
|
|
254
265
|
const collector = new Collector(name, storageManager, options);
|
|
255
266
|
|
|
256
|
-
if (
|
|
267
|
+
if (isAndroidConfigured(options)) {
|
|
257
268
|
const model = await this.android.getMeta();
|
|
258
269
|
log.info(
|
|
259
270
|
'Run tests on %s [%s] using Android version %s',
|
|
@@ -301,12 +312,12 @@ class Engine {
|
|
|
301
312
|
|
|
302
313
|
// Backfill the fully loaded data that we extract from the HAR
|
|
303
314
|
if (!options.skipHar && extras.har) {
|
|
304
|
-
const fullyLoadedPerUrl =
|
|
315
|
+
const fullyLoadedPerUrl = getFullyLoaded(extras.har);
|
|
305
316
|
for (let data of fullyLoadedPerUrl) {
|
|
306
317
|
collector.addFullyLoaded(data.url, data.fullyLoaded);
|
|
307
318
|
}
|
|
308
319
|
// Add the timings from the main document
|
|
309
|
-
const timings =
|
|
320
|
+
const timings = getMainDocumentTimings(extras.har);
|
|
310
321
|
for (let timing of timings) {
|
|
311
322
|
collector.addMainDocumentTimings(timing.url, timing.timings);
|
|
312
323
|
}
|
|
@@ -317,7 +328,7 @@ class Engine {
|
|
|
317
328
|
// to make the HAR files better when we use them in
|
|
318
329
|
// compare.sitespeed.io
|
|
319
330
|
if (!options.skipHar && extras.har) {
|
|
320
|
-
|
|
331
|
+
addExtraFieldsToHar(totalResult, extras.har, options);
|
|
321
332
|
totalResult.har = extras.har;
|
|
322
333
|
|
|
323
334
|
// Backfill browser and version
|
|
@@ -334,7 +345,7 @@ class Engine {
|
|
|
334
345
|
try {
|
|
335
346
|
const vString = result.info.browser.userAgent.split('Version/')[1];
|
|
336
347
|
result.info.browser.version = vString.split(' ')[0];
|
|
337
|
-
} catch
|
|
348
|
+
} catch {
|
|
338
349
|
// Just swallow
|
|
339
350
|
}
|
|
340
351
|
}
|
|
@@ -345,13 +356,13 @@ class Engine {
|
|
|
345
356
|
try {
|
|
346
357
|
const vString = result.info.browser.userAgent.split('Firefox/')[1];
|
|
347
358
|
result.info.browser.version = vString;
|
|
348
|
-
} catch
|
|
359
|
+
} catch {
|
|
349
360
|
// Just swallow
|
|
350
361
|
}
|
|
351
362
|
}
|
|
352
363
|
}
|
|
353
364
|
|
|
354
|
-
|
|
365
|
+
logResultLogLine(totalResult);
|
|
355
366
|
|
|
356
367
|
if (failures.length > 0) {
|
|
357
368
|
// If we have a result
|
|
@@ -374,7 +385,7 @@ class Engine {
|
|
|
374
385
|
}
|
|
375
386
|
}
|
|
376
387
|
|
|
377
|
-
if (
|
|
388
|
+
if (isAndroidConfigured(options)) {
|
|
378
389
|
const model = await this.android.getMeta();
|
|
379
390
|
for (let result of totalResult) {
|
|
380
391
|
result.info.android = model;
|
|
@@ -386,7 +397,7 @@ class Engine {
|
|
|
386
397
|
result.info.ios = {
|
|
387
398
|
deviceName: this.iosSimulatorDeviceName + ' simulator',
|
|
388
399
|
deviceUDID: options.safari.deviceUDID,
|
|
389
|
-
arch:
|
|
400
|
+
arch: _arch()
|
|
390
401
|
};
|
|
391
402
|
}
|
|
392
403
|
}
|
|
@@ -407,15 +418,16 @@ class Engine {
|
|
|
407
418
|
const scripts = [];
|
|
408
419
|
let name;
|
|
409
420
|
for (let urlOrFile of urlOrFiles) {
|
|
410
|
-
if (typeof urlOrFile == 'string' && urlOrFile.
|
|
421
|
+
if (typeof urlOrFile == 'string' && urlOrFile.includes('http')) {
|
|
411
422
|
scripts.push(urlOrFile);
|
|
412
423
|
} else {
|
|
413
424
|
let script = urlOrFile;
|
|
414
|
-
if (urlOrFile
|
|
425
|
+
if (Array.isArray(urlOrFile)) {
|
|
415
426
|
script = urlOrFile[1];
|
|
416
427
|
}
|
|
417
428
|
|
|
418
|
-
script =
|
|
429
|
+
script = await loadScript(script, true);
|
|
430
|
+
|
|
419
431
|
if (script.setUp) {
|
|
420
432
|
if (!options.preScript) {
|
|
421
433
|
options.preScript = [];
|
|
@@ -464,8 +476,8 @@ class Engine {
|
|
|
464
476
|
|
|
465
477
|
if (options.safari && options.safari.useSimulator) {
|
|
466
478
|
try {
|
|
467
|
-
await
|
|
468
|
-
} catch
|
|
479
|
+
await command('pkill -x Simulator', { shell: true });
|
|
480
|
+
} catch {
|
|
469
481
|
log.error('Could not stop the iOS simulator');
|
|
470
482
|
}
|
|
471
483
|
}
|
|
@@ -477,5 +489,3 @@ class Engine {
|
|
|
477
489
|
return Promise.all([this.myXVFB.stop()]);
|
|
478
490
|
}
|
|
479
491
|
}
|
|
480
|
-
|
|
481
|
-
module.exports = Engine;
|