browsertime 26.3.2 → 27.0.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.
- package/CHANGELOG.md +72 -0
- package/README.md +1 -1
- package/browserscripts/timings/softNavigations.js +94 -0
- package/lib/chrome/har.js +36 -5
- package/lib/chrome/settings/chromeAndroidOptions.js +2 -1
- package/lib/chrome/webdriver/chromium.js +40 -1
- package/lib/chrome/webdriver/setupChromiumOptions.js +86 -31
- package/lib/core/engine/collector.js +340 -317
- package/lib/core/engine/command/addText.js +93 -12
- package/lib/core/engine/command/click.js +268 -139
- package/lib/core/engine/command/commandHelper.js +45 -0
- package/lib/core/engine/command/cookie.js +85 -0
- package/lib/core/engine/command/element.js +37 -2
- package/lib/core/engine/command/javaScript.js +14 -24
- package/lib/core/engine/command/measure/screenshots.js +114 -0
- package/lib/core/engine/command/measure/video.js +85 -0
- package/lib/core/engine/command/measure.js +104 -180
- package/lib/core/engine/command/mouse/clickAndHold.js +6 -3
- package/lib/core/engine/command/mouse/contextClick.js +56 -4
- package/lib/core/engine/command/mouse/doubleClick.js +49 -1
- package/lib/core/engine/command/mouse/mouseMove.js +50 -1
- package/lib/core/engine/command/mouse/singleClick.js +165 -129
- package/lib/core/engine/command/navigation.js +6 -6
- package/lib/core/engine/command/select.js +95 -3
- package/lib/core/engine/command/selectorParser.js +58 -0
- package/lib/core/engine/command/set.js +55 -1
- package/lib/core/engine/command/wait.js +41 -2
- package/lib/core/engine/commands.js +550 -42
- package/lib/core/engine/index.js +206 -150
- package/lib/core/engine/iteration.js +277 -137
- package/lib/firefox/networkManager.js +22 -30
- package/lib/firefox/webdriver/builder.js +14 -0
- package/lib/safari/har.js +131 -0
- package/lib/safari/native/ios-capture +0 -0
- package/lib/safari/native/ios-capture.m +340 -0
- package/lib/safari/safariInspectorClient.js +322 -0
- package/lib/safari/webdriver/safari.js +303 -13
- package/lib/safari/webkitToCdpAdapter.js +241 -0
- package/lib/support/cli.js +13 -0
- package/lib/support/engineUtils.js +16 -5
- package/lib/support/getViewPort.js +5 -0
- package/lib/support/har/index.js +41 -3
- package/lib/support/usbPower.js +2 -3
- package/lib/video/postprocessing/finetune/addTextToVideo.js +4 -0
- package/lib/video/postprocessing/finetune/getFont.js +3 -3
- package/lib/video/postprocessing/finetune/getTimingMetrics.js +7 -0
- package/lib/video/postprocessing/finetune/index.js +26 -9
- package/lib/video/screenRecording/ios/iosDeviceRecorder.js +109 -0
- package/lib/video/screenRecording/recorder.js +2 -2
- package/lib/video/screenRecording/setOrangeBackground.js +3 -0
- package/package.json +11 -11
- package/types/core/engine/command/addText.d.ts +35 -6
- package/types/core/engine/command/addText.d.ts.map +1 -1
- package/types/core/engine/command/click.d.ts +87 -16
- package/types/core/engine/command/click.d.ts.map +1 -1
- package/types/core/engine/command/commandHelper.d.ts +16 -0
- package/types/core/engine/command/commandHelper.d.ts.map +1 -0
- package/types/core/engine/command/cookie.d.ts +65 -0
- package/types/core/engine/command/cookie.d.ts.map +1 -0
- package/types/core/engine/command/element.d.ts +19 -1
- package/types/core/engine/command/element.d.ts.map +1 -1
- package/types/core/engine/command/javaScript.d.ts +4 -0
- package/types/core/engine/command/javaScript.d.ts.map +1 -1
- package/types/core/engine/command/measure/screenshots.d.ts +15 -0
- package/types/core/engine/command/measure/screenshots.d.ts.map +1 -0
- package/types/core/engine/command/measure/video.d.ts +26 -0
- package/types/core/engine/command/measure/video.d.ts.map +1 -0
- package/types/core/engine/command/measure.d.ts +59 -33
- package/types/core/engine/command/measure.d.ts.map +1 -1
- package/types/core/engine/command/mouse/clickAndHold.d.ts.map +1 -1
- package/types/core/engine/command/mouse/contextClick.d.ts +28 -4
- package/types/core/engine/command/mouse/contextClick.d.ts.map +1 -1
- package/types/core/engine/command/mouse/doubleClick.d.ts +24 -4
- package/types/core/engine/command/mouse/doubleClick.d.ts.map +1 -1
- package/types/core/engine/command/mouse/mouseMove.d.ts +30 -5
- package/types/core/engine/command/mouse/mouseMove.d.ts.map +1 -1
- package/types/core/engine/command/mouse/singleClick.d.ts +50 -13
- package/types/core/engine/command/mouse/singleClick.d.ts.map +1 -1
- package/types/core/engine/command/navigation.d.ts +3 -3
- package/types/core/engine/command/select.d.ts +45 -8
- package/types/core/engine/command/select.d.ts.map +1 -1
- package/types/core/engine/command/selectorParser.d.ts +20 -0
- package/types/core/engine/command/selectorParser.d.ts.map +1 -0
- package/types/core/engine/command/set.d.ts +34 -7
- package/types/core/engine/command/set.d.ts.map +1 -1
- package/types/core/engine/command/wait.d.ts +29 -6
- package/types/core/engine/command/wait.d.ts.map +1 -1
- package/types/core/engine/commands.d.ts +296 -28
- package/types/core/engine/commands.d.ts.map +1 -1
- package/types/support/engineUtils.d.ts.map +1 -1
- package/types/support/getViewPort.d.ts.map +1 -1
- package/types/support/usbPower.d.ts.map +1 -1
- package/types/video/postprocessing/finetune/addTextToVideo.d.ts.map +1 -1
- package/types/video/postprocessing/finetune/getTimingMetrics.d.ts.map +1 -1
- package/types/video/postprocessing/finetune/index.d.ts.map +1 -1
- package/types/video/screenRecording/ios/iosDeviceRecorder.d.ts +28 -0
- package/types/video/screenRecording/ios/iosDeviceRecorder.d.ts.map +1 -0
- package/types/video/screenRecording/recorder.d.ts +2 -2
- package/types/video/screenRecording/recorder.d.ts.map +1 -1
- package/types/video/screenRecording/setOrangeBackground.d.ts.map +1 -1
- package/types/video/video.d.ts +1 -1
- package/types/video/video.d.ts.map +1 -1
- package/visualmetrics/visualmetrics-portable.py +136 -136
- package/lib/video/screenRecording/ios/convertToMp4.js +0 -22
- package/lib/video/screenRecording/ios/iosRecorder.js +0 -68
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { getLogger } from '@sitespeed.io/log';
|
|
2
|
+
const log = getLogger('browsertime.command.cookie');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Provides functionality to manage browser cookies.
|
|
6
|
+
*
|
|
7
|
+
* @class
|
|
8
|
+
* @hideconstructor
|
|
9
|
+
*/
|
|
10
|
+
export class Cookie {
|
|
11
|
+
constructor(browser) {
|
|
12
|
+
/**
|
|
13
|
+
* @private
|
|
14
|
+
*/
|
|
15
|
+
this.driver = browser.getDriver();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Gets all cookies for the current page.
|
|
20
|
+
*
|
|
21
|
+
* @async
|
|
22
|
+
* @returns {Promise<Array>} An array of cookie objects.
|
|
23
|
+
*/
|
|
24
|
+
async getAll() {
|
|
25
|
+
return this.driver.manage().getCookies();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Gets a specific cookie by name.
|
|
30
|
+
*
|
|
31
|
+
* @async
|
|
32
|
+
* @param {string} name - The name of the cookie.
|
|
33
|
+
* @returns {Promise<Object|undefined>} The cookie object, or undefined if not found.
|
|
34
|
+
*/
|
|
35
|
+
async get(name) {
|
|
36
|
+
try {
|
|
37
|
+
return await this.driver.manage().getCookie(name);
|
|
38
|
+
} catch {
|
|
39
|
+
// Cookie not found
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Sets a cookie.
|
|
45
|
+
*
|
|
46
|
+
* @async
|
|
47
|
+
* @param {string} name - The name of the cookie.
|
|
48
|
+
* @param {string} value - The value of the cookie.
|
|
49
|
+
* @param {Object} [options] - Optional cookie properties.
|
|
50
|
+
* @param {string} [options.domain] - The domain the cookie is visible to.
|
|
51
|
+
* @param {string} [options.path] - The cookie path.
|
|
52
|
+
* @param {boolean} [options.secure] - Whether the cookie is secure.
|
|
53
|
+
* @param {boolean} [options.httpOnly] - Whether the cookie is HTTP only.
|
|
54
|
+
* @param {Date} [options.expiry] - When the cookie expires.
|
|
55
|
+
* @returns {Promise<void>}
|
|
56
|
+
*/
|
|
57
|
+
async set(name, value, options = {}) {
|
|
58
|
+
const cookie = { name, value, ...options };
|
|
59
|
+
log.debug('Setting cookie %s', name);
|
|
60
|
+
return this.driver.manage().addCookie(cookie);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Deletes a specific cookie by name.
|
|
65
|
+
*
|
|
66
|
+
* @async
|
|
67
|
+
* @param {string} name - The name of the cookie to delete.
|
|
68
|
+
* @returns {Promise<void>}
|
|
69
|
+
*/
|
|
70
|
+
async delete(name) {
|
|
71
|
+
log.debug('Deleting cookie %s', name);
|
|
72
|
+
return this.driver.manage().deleteCookie(name);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Deletes all cookies for the current page.
|
|
77
|
+
*
|
|
78
|
+
* @async
|
|
79
|
+
* @returns {Promise<void>}
|
|
80
|
+
*/
|
|
81
|
+
async deleteAll() {
|
|
82
|
+
log.debug('Deleting all cookies');
|
|
83
|
+
return this.driver.manage().deleteAllCookies();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
// We disable these because they are needed for code completion
|
|
2
2
|
/* eslint no-unused-vars: "off" */
|
|
3
|
-
import { By, WebElement } from 'selenium-webdriver';
|
|
3
|
+
import webdriver, { By, WebElement } from 'selenium-webdriver';
|
|
4
4
|
/**
|
|
5
5
|
* This class provides a way to get hokld of Seleniums WebElements.
|
|
6
6
|
* @class
|
|
7
7
|
* @hideconstructor
|
|
8
8
|
*/
|
|
9
9
|
export class Element {
|
|
10
|
-
constructor(browser) {
|
|
10
|
+
constructor(browser, options) {
|
|
11
11
|
/**
|
|
12
12
|
* @private
|
|
13
13
|
*/
|
|
14
14
|
this.driver = browser.getDriver();
|
|
15
|
+
/**
|
|
16
|
+
* @private
|
|
17
|
+
*/
|
|
18
|
+
this.options = options;
|
|
15
19
|
}
|
|
16
20
|
|
|
17
21
|
/**
|
|
@@ -63,4 +67,35 @@ export class Element {
|
|
|
63
67
|
async getByName(name) {
|
|
64
68
|
return this.driver.findElement(By.name(name));
|
|
65
69
|
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Finds an element using a CSS selector, with optional waiting and visibility check.
|
|
73
|
+
*
|
|
74
|
+
* @param {string} selector - The CSS selector of the element.
|
|
75
|
+
* @param {Object} [options] - Options for finding the element.
|
|
76
|
+
* @param {number} [options.timeout] - Maximum time in milliseconds to wait for the element. Defaults to the configured --timeouts.elementWait value.
|
|
77
|
+
* @param {boolean} [options.visible=false] - If true, waits for the element to be visible, not just present.
|
|
78
|
+
* @returns {Promise<WebElement>} A promise that resolves to the WebElement found.
|
|
79
|
+
* @throws {Error} Throws an error if the element is not found within the timeout.
|
|
80
|
+
*/
|
|
81
|
+
async find(selector, options = {}) {
|
|
82
|
+
const timeout = options.timeout ?? this.options?.timeouts?.elementWait ?? 0;
|
|
83
|
+
const visible = options.visible ?? false;
|
|
84
|
+
const locator = By.css(selector);
|
|
85
|
+
|
|
86
|
+
if (timeout > 0) {
|
|
87
|
+
const element = await this.driver.wait(
|
|
88
|
+
webdriver.until.elementLocated(locator),
|
|
89
|
+
timeout
|
|
90
|
+
);
|
|
91
|
+
if (visible) {
|
|
92
|
+
await this.driver.wait(
|
|
93
|
+
webdriver.until.elementIsVisible(element),
|
|
94
|
+
timeout
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
return element;
|
|
98
|
+
}
|
|
99
|
+
return this.driver.findElement(locator);
|
|
100
|
+
}
|
|
66
101
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getLogger } from '@sitespeed.io/log';
|
|
2
|
+
import { executeCommand } from './commandHelper.js';
|
|
2
3
|
const log = getLogger('browsertime.command.javascript');
|
|
3
4
|
/**
|
|
4
5
|
* Provides functionality to execute JavaScript code in the context of the current page.
|
|
@@ -19,6 +20,14 @@ export class JavaScript {
|
|
|
19
20
|
this.pageCompleteCheck = pageCompleteCheck;
|
|
20
21
|
}
|
|
21
22
|
|
|
23
|
+
/**
|
|
24
|
+
* @private
|
|
25
|
+
*/
|
|
26
|
+
async _andWait(baseMethod, ...args) {
|
|
27
|
+
await baseMethod.apply(this, args);
|
|
28
|
+
return this.browser.extraWait(this.pageCompleteCheck);
|
|
29
|
+
}
|
|
30
|
+
|
|
22
31
|
/**
|
|
23
32
|
* Executes a JavaScript script.
|
|
24
33
|
*
|
|
@@ -28,14 +37,9 @@ export class JavaScript {
|
|
|
28
37
|
* @throws {Error} Throws an error if the JavaScript cannot be executed.
|
|
29
38
|
*/
|
|
30
39
|
async run(js) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
} catch (error) {
|
|
35
|
-
log.error('Could not run JavaScript %s ', js);
|
|
36
|
-
log.verbose(error);
|
|
37
|
-
throw new Error(`Could not run JavaScript ${js}`);
|
|
38
|
-
}
|
|
40
|
+
return executeCommand(log, 'Could not run JavaScript %s', js, () =>
|
|
41
|
+
this.browser.runScript(js, 'CUSTOM')
|
|
42
|
+
);
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
/**
|
|
@@ -47,14 +51,7 @@ export class JavaScript {
|
|
|
47
51
|
* @throws {Error} Throws an error if the JavaScript cannot be executed.
|
|
48
52
|
*/
|
|
49
53
|
async runAndWait(js) {
|
|
50
|
-
|
|
51
|
-
await this.browser.runScript(js, 'CUSTOM');
|
|
52
|
-
return this.browser.extraWait(this.pageCompleteCheck);
|
|
53
|
-
} catch (error) {
|
|
54
|
-
log.error('Could not run JavaScript %s ', js);
|
|
55
|
-
log.verbose(error);
|
|
56
|
-
throw new Error(`Could not run JavaScript ${js}`);
|
|
57
|
-
}
|
|
54
|
+
return this._andWait(this.run, js);
|
|
58
55
|
}
|
|
59
56
|
|
|
60
57
|
/**
|
|
@@ -88,14 +85,7 @@ export class JavaScript {
|
|
|
88
85
|
* @throws {Error} Throws an error if the privileged JavaScript cannot be executed.
|
|
89
86
|
*/
|
|
90
87
|
async runPrivilegedAndWait(js) {
|
|
91
|
-
|
|
92
|
-
await this.browser.runPrivilegedScript(js, 'CUSTOM PRIVILEGED');
|
|
93
|
-
return this.browser.extraWait(this.pageCompleteCheck);
|
|
94
|
-
} catch (error) {
|
|
95
|
-
log.error('Could not run privileged JavaScript %s ', js);
|
|
96
|
-
log.verbose(error);
|
|
97
|
-
throw error;
|
|
98
|
-
}
|
|
88
|
+
return this._andWait(this.runPrivileged, js);
|
|
99
89
|
}
|
|
100
90
|
|
|
101
91
|
/**
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { getLogger } from '@sitespeed.io/log';
|
|
2
|
+
import { lcpHighlightScript as highlightLargestContentfulPaint } from '../util/lcpHighlightScript.js';
|
|
3
|
+
import { clsHighlightScript as highlightLS } from '../util/lsHighlightScript.js';
|
|
4
|
+
const log = getLogger('browsertime.command.measure');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Handles screenshot capture during measurement collection.
|
|
8
|
+
* @class
|
|
9
|
+
* @private
|
|
10
|
+
*/
|
|
11
|
+
export class MeasureScreenshots {
|
|
12
|
+
constructor(browser, screenshotManager, options) {
|
|
13
|
+
this.browser = browser;
|
|
14
|
+
this.screenshotManager = screenshotManager;
|
|
15
|
+
this.options = options;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async afterPageCompleteCheck(url, index) {
|
|
19
|
+
if (!this.options.screenshot) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
log.info('Take after page complete check screenshot');
|
|
23
|
+
try {
|
|
24
|
+
const screenshot = await this.browser.takeScreenshot(url);
|
|
25
|
+
await this.screenshotManager.save(
|
|
26
|
+
'afterPageCompleteCheck',
|
|
27
|
+
screenshot,
|
|
28
|
+
url,
|
|
29
|
+
index
|
|
30
|
+
);
|
|
31
|
+
} catch {
|
|
32
|
+
// not getting screenshots shouldn't result in a failed test.
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async layoutShift(url, index) {
|
|
37
|
+
if (!this.options.screenshotLS) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const supportLS = await this.browser.runScript(
|
|
42
|
+
`
|
|
43
|
+
const supported = PerformanceObserver.supportedEntryTypes;
|
|
44
|
+
if (!supported || supported.indexOf('layout-shift') === -1) {
|
|
45
|
+
return false;
|
|
46
|
+
} else return true;
|
|
47
|
+
`,
|
|
48
|
+
'SUPPORT_LS'
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
if (!supportLS) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
log.info('Take cumulative layout shift screenshot');
|
|
56
|
+
await this.browser.runScript(highlightLS, 'HIGHLIGHT_LS', {
|
|
57
|
+
color: this.options.screenshotLSColor || 'red',
|
|
58
|
+
limit: this.options.screenshotLSLimit || 0.01
|
|
59
|
+
});
|
|
60
|
+
const screenshot = await this.browser.takeScreenshot(url);
|
|
61
|
+
await this.screenshotManager.save('layoutShift', screenshot, url, index);
|
|
62
|
+
const lsScriptClean = `
|
|
63
|
+
const c = document.getElementById("browsertime-ls");
|
|
64
|
+
if (c) c.remove();
|
|
65
|
+
`;
|
|
66
|
+
await this.browser.runScript(lsScriptClean, 'CLEAN_LS');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async largestContentfulPaint(url, index) {
|
|
70
|
+
if (!this.options.screenshotLCP) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const supportLCP = await this.browser.runScript(
|
|
75
|
+
`
|
|
76
|
+
const supported = PerformanceObserver.supportedEntryTypes;
|
|
77
|
+
if (!supported || supported.indexOf('largest-contentful-paint') === -1) {
|
|
78
|
+
return false;
|
|
79
|
+
} else return true;
|
|
80
|
+
`,
|
|
81
|
+
'SUPPORT_LCP'
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
if (!supportLCP) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
log.info('Take largest contentful paint screenshot');
|
|
89
|
+
try {
|
|
90
|
+
const lcpScriptClean = `
|
|
91
|
+
const c = document.getElementById("browsertime-lcp");
|
|
92
|
+
if (c) c.remove();
|
|
93
|
+
`;
|
|
94
|
+
const message = await this.browser.runScript(
|
|
95
|
+
highlightLargestContentfulPaint,
|
|
96
|
+
'HIGHLIGHT_LCP',
|
|
97
|
+
this.options.screenshotLCPColor || 'red'
|
|
98
|
+
);
|
|
99
|
+
if (message != '') {
|
|
100
|
+
log.info(message);
|
|
101
|
+
}
|
|
102
|
+
const screenshot = await this.browser.takeScreenshot(url);
|
|
103
|
+
await this.screenshotManager.save(
|
|
104
|
+
'largestContentfulPaint',
|
|
105
|
+
screenshot,
|
|
106
|
+
url,
|
|
107
|
+
index
|
|
108
|
+
);
|
|
109
|
+
await this.browser.runScript(lcpScriptClean, 'CLEAN_LCP');
|
|
110
|
+
} catch (error) {
|
|
111
|
+
log.error('Could not get LCP screenshot', error);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { Video } from '../../../../video/video.js';
|
|
2
|
+
import { setOrangeBackground } from '../../../../video/screenRecording/setOrangeBackground.js';
|
|
3
|
+
import { isAndroidConfigured } from '../../../../android/index.js';
|
|
4
|
+
import { getProperty } from '../../../../support/util.js';
|
|
5
|
+
const delay = ms => new Promise(res => setTimeout(res, ms));
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Handles video recording during measurement.
|
|
9
|
+
* @class
|
|
10
|
+
* @private
|
|
11
|
+
*/
|
|
12
|
+
export class MeasureVideo {
|
|
13
|
+
constructor(storageManager, browser, videos, options) {
|
|
14
|
+
this.storageManager = storageManager;
|
|
15
|
+
this.browser = browser;
|
|
16
|
+
this.videos = videos;
|
|
17
|
+
this.options = options;
|
|
18
|
+
this.recordVideo = options.visualMetrics || options.video;
|
|
19
|
+
this.ANDROID_DELAY_TIME = getProperty(
|
|
20
|
+
options,
|
|
21
|
+
'orangeAndroidDelayTime',
|
|
22
|
+
2000
|
|
23
|
+
);
|
|
24
|
+
this.IOS_DELAY_TIME = getProperty(options, 'orangeIosDelayTime', 1000);
|
|
25
|
+
this.DESKTOP_DELAY_TIME = getProperty(
|
|
26
|
+
options,
|
|
27
|
+
'orangeDesktopDelayTime',
|
|
28
|
+
800
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async start(numberOfMeasuredPages, index) {
|
|
33
|
+
this.video = new Video(this.storageManager, this.options, this.browser);
|
|
34
|
+
|
|
35
|
+
if (this.options.firefox && this.options.firefox.windowRecorder) {
|
|
36
|
+
// The Firefox window recorder will only record subsequent
|
|
37
|
+
// changes after recording has begun. So the orange frame needs
|
|
38
|
+
// to come after we start recording.
|
|
39
|
+
await this.video.record(numberOfMeasuredPages, index);
|
|
40
|
+
await setOrangeBackground(this.browser.getDriver(), this.options);
|
|
41
|
+
} else {
|
|
42
|
+
await setOrangeBackground(this.browser.getDriver(), this.options);
|
|
43
|
+
await this.video.record(numberOfMeasuredPages, index);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Give ffmpeg/video on phone time to settle
|
|
47
|
+
if (isAndroidConfigured(this.options)) {
|
|
48
|
+
return delay(this.ANDROID_DELAY_TIME);
|
|
49
|
+
} else if (this.options.safari && this.options.safari.ios) {
|
|
50
|
+
return delay(this.IOS_DELAY_TIME);
|
|
51
|
+
} else if (this.options.safari && this.options.safari.useSimulator) {
|
|
52
|
+
return delay(this.IOS_DELAY_TIME);
|
|
53
|
+
} else {
|
|
54
|
+
return delay(this.DESKTOP_DELAY_TIME);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async stop(url) {
|
|
59
|
+
if (this.recordVideo && !this.options.videoParams.debug) {
|
|
60
|
+
await this.video.stop(url);
|
|
61
|
+
this.videos.push(this.video);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
getRecordingMetadata() {
|
|
66
|
+
if (
|
|
67
|
+
this.recordVideo &&
|
|
68
|
+
!this.options.videoParams.debug &&
|
|
69
|
+
this.video &&
|
|
70
|
+
this.video.getRecordingStartTime()
|
|
71
|
+
) {
|
|
72
|
+
return {
|
|
73
|
+
recordingStartTime: Number.parseFloat(
|
|
74
|
+
this.video.getRecordingStartTime()
|
|
75
|
+
),
|
|
76
|
+
timeToFirstFrame: Number.parseInt(this.video.getTimeToFirstFrame(), 10)
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
shouldRecord() {
|
|
83
|
+
return this.recordVideo && !this.options.videoParams.debug;
|
|
84
|
+
}
|
|
85
|
+
}
|