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
|
@@ -29,9 +29,14 @@ const sizeMap = {
|
|
|
29
29
|
'iPhone 12 Pro': '390x844',
|
|
30
30
|
'iPhone 14 Pro': '430x932',
|
|
31
31
|
'iPhone 14 Pro Max': '430x932',
|
|
32
|
+
'Pixel 3': '394x786',
|
|
33
|
+
'Pixel 3 XL': '394x786',
|
|
34
|
+
'Pixel 4': '354x746',
|
|
32
35
|
'Pixel 5': '394x852',
|
|
33
36
|
'Pixel 7': '412x916',
|
|
37
|
+
'Moto G Power': '412x824',
|
|
34
38
|
'Samsung Galaxy S8+': '412x846',
|
|
39
|
+
'Samsung Galaxy S20 Ultra': '412x916',
|
|
35
40
|
'Samsung Galaxy A51/71': '412x914'
|
|
36
41
|
};
|
|
37
42
|
|
package/lib/support/har/index.js
CHANGED
|
@@ -61,7 +61,8 @@ function addExtrasToHAR(
|
|
|
61
61
|
visualMetricsData,
|
|
62
62
|
timings,
|
|
63
63
|
cpu,
|
|
64
|
-
googleWebVitals
|
|
64
|
+
googleWebVitals,
|
|
65
|
+
pageinfo
|
|
65
66
|
) {
|
|
66
67
|
const harPageTimings = harPage.pageTimings;
|
|
67
68
|
|
|
@@ -129,6 +130,41 @@ function addExtrasToHAR(
|
|
|
129
130
|
harPageTimings._domContentLoadedTime =
|
|
130
131
|
timings.pageTimings.domContentLoadedTime;
|
|
131
132
|
}
|
|
133
|
+
|
|
134
|
+
// Long-task ranges as a `_longTasks` extension on pageTimings. Each
|
|
135
|
+
// entry is `[startMs, endMs]`, the format consumed by WebPageTest-derived
|
|
136
|
+
// waterfall viewers (e.g. waterfall-tools). Tri-state presence semantic:
|
|
137
|
+
// a non-empty array draws individual blocked spans; an empty array
|
|
138
|
+
// signals "instrumented, observed nothing"; field absent means "parser
|
|
139
|
+
// can't instrument". Browsertime always instruments via PerformanceObserver
|
|
140
|
+
// when the page-info script runs, so always emit the array (possibly
|
|
141
|
+
// empty) when `pageinfo.longTask` exists.
|
|
142
|
+
if (pageinfo && Array.isArray(pageinfo.longTask)) {
|
|
143
|
+
harPageTimings._longTasks = pageinfo.longTask.map(t => [
|
|
144
|
+
Number(t.startTime),
|
|
145
|
+
Number(t.startTime + t.duration)
|
|
146
|
+
]);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// User-timing marks + measures as a `_userTimings` extension on
|
|
150
|
+
// pageTimings. Object keyed by entry name so a downstream waterfall
|
|
151
|
+
// renderer can paint each as a vertical line. Measures override marks
|
|
152
|
+
// on name collision.
|
|
153
|
+
const userTimings = timings && timings.userTimings;
|
|
154
|
+
if (
|
|
155
|
+
userTimings &&
|
|
156
|
+
((userTimings.marks && userTimings.marks.length > 0) ||
|
|
157
|
+
(userTimings.measures && userTimings.measures.length > 0))
|
|
158
|
+
) {
|
|
159
|
+
const map = {};
|
|
160
|
+
for (const mark of userTimings.marks || []) {
|
|
161
|
+
if (mark && mark.name) map[mark.name] = mark.startTime;
|
|
162
|
+
}
|
|
163
|
+
for (const measure of userTimings.measures || []) {
|
|
164
|
+
if (measure && measure.name) map[measure.name] = measure.startTime;
|
|
165
|
+
}
|
|
166
|
+
if (Object.keys(map).length > 0) harPageTimings._userTimings = map;
|
|
167
|
+
}
|
|
132
168
|
}
|
|
133
169
|
|
|
134
170
|
function addMetaToHAR(index, harPage, url, browserScript, options) {
|
|
@@ -354,7 +390,8 @@ export function addExtraFieldsToHar(totalResults, har, options) {
|
|
|
354
390
|
visualMetric,
|
|
355
391
|
browserScript.timings,
|
|
356
392
|
cpu,
|
|
357
|
-
googleWebVitals
|
|
393
|
+
googleWebVitals,
|
|
394
|
+
browserScript.pageinfo
|
|
358
395
|
);
|
|
359
396
|
}
|
|
360
397
|
harPageNumber++;
|
|
@@ -392,7 +429,8 @@ export function addExtraFieldsToHar(totalResults, har, options) {
|
|
|
392
429
|
visualMetric,
|
|
393
430
|
browserScript.timings,
|
|
394
431
|
cpu,
|
|
395
|
-
googleWebVitals
|
|
432
|
+
googleWebVitals,
|
|
433
|
+
browserScript.pageinfo
|
|
396
434
|
);
|
|
397
435
|
}
|
|
398
436
|
}
|
package/lib/support/usbPower.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
export async function loadUsbPowerProfiler() {
|
|
2
2
|
try {
|
|
3
3
|
// usb-power-profiling/usb-power-profiling.js exports a default, so we destructure it
|
|
4
|
-
const { default: usbPowerProfiler } =
|
|
5
|
-
'usb-power-profiling/usb-power-profiling.js'
|
|
6
|
-
);
|
|
4
|
+
const { default: usbPowerProfiler } =
|
|
5
|
+
await import('usb-power-profiling/usb-power-profiling.js');
|
|
7
6
|
return usbPowerProfiler;
|
|
8
7
|
} catch {
|
|
9
8
|
return;
|
|
@@ -39,6 +39,10 @@ export async function addTextToVideo(
|
|
|
39
39
|
fontSize = 32;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
if (options.safari && options.safari.ios) {
|
|
43
|
+
fontSize = 40;
|
|
44
|
+
}
|
|
45
|
+
|
|
42
46
|
arguments_.push(
|
|
43
47
|
'-vf',
|
|
44
48
|
`drawtext=${fontFile}x=w/2-(tw/2): y=H-h/10:fontcolor=white:fontsize=h/${fontSize}:box=1:boxcolor=0x000000AA:text='%{pts\\:hms}'${allTimingMetrics}`,
|
|
@@ -6,7 +6,7 @@ export function getFont(options) {
|
|
|
6
6
|
const systemFontFile = '/System/Library/Fonts/SFNSMono.ttf';
|
|
7
7
|
try {
|
|
8
8
|
if (existsSync(systemFontFile)) {
|
|
9
|
-
return systemFontFile
|
|
9
|
+
return `fontfile=${systemFontFile}:`;
|
|
10
10
|
}
|
|
11
11
|
return '';
|
|
12
12
|
} catch {
|
|
@@ -18,7 +18,7 @@ export function getFont(options) {
|
|
|
18
18
|
'/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf';
|
|
19
19
|
try {
|
|
20
20
|
if (existsSync(systemFontFile)) {
|
|
21
|
-
return systemFontFile
|
|
21
|
+
return `fontfile=${systemFontFile}:`;
|
|
22
22
|
}
|
|
23
23
|
return '';
|
|
24
24
|
} catch {
|
|
@@ -26,6 +26,6 @@ export function getFont(options) {
|
|
|
26
26
|
}
|
|
27
27
|
} else
|
|
28
28
|
return options.videoParams.fontPath
|
|
29
|
-
? options.videoParams.fontPath
|
|
29
|
+
? `fontfile=${options.videoParams.fontPath}:`
|
|
30
30
|
: '';
|
|
31
31
|
}
|
|
@@ -23,6 +23,10 @@ function get(metric, metricName, pos, options) {
|
|
|
23
23
|
fontSize = 32;
|
|
24
24
|
x = 10;
|
|
25
25
|
}
|
|
26
|
+
if (options.safari && options.safari.ios) {
|
|
27
|
+
fontSize = 40;
|
|
28
|
+
x = 12;
|
|
29
|
+
}
|
|
26
30
|
|
|
27
31
|
// H-h/8
|
|
28
32
|
return `drawtext=${fontFile}enable='between(t,${
|
|
@@ -78,6 +82,9 @@ export function getTimingMetrics(videoMetrics, timingMetrics, options) {
|
|
|
78
82
|
if (options.safari && options.safari.useSimulator) {
|
|
79
83
|
posOffset = 24;
|
|
80
84
|
}
|
|
85
|
+
if (options.safari && options.safari.ios) {
|
|
86
|
+
posOffset = 28;
|
|
87
|
+
}
|
|
81
88
|
|
|
82
89
|
for (let metricAndValue of metricsAndValues) {
|
|
83
90
|
text += ',' + get(metricAndValue.value, metricAndValue.name, pos, options);
|
|
@@ -72,15 +72,32 @@ export async function finetuneVideo(
|
|
|
72
72
|
|
|
73
73
|
if (options.videoParams.addTimer) {
|
|
74
74
|
const temporaryFile2 = path.join(videoDir, 'tmp2.mp4');
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
75
|
+
try {
|
|
76
|
+
await addTextToVideo(
|
|
77
|
+
temporaryFile,
|
|
78
|
+
temporaryFile2,
|
|
79
|
+
videoMetrics,
|
|
80
|
+
timingMetrics,
|
|
81
|
+
options
|
|
82
|
+
);
|
|
83
|
+
await rename(temporaryFile2, videoPath);
|
|
84
|
+
await unlink(temporaryFile);
|
|
85
|
+
} catch (error) {
|
|
86
|
+
// Most commonly hit when the local ffmpeg lacks the drawtext
|
|
87
|
+
// filter (e.g. homebrew's stripped ffmpeg 8 build without
|
|
88
|
+
// libfreetype). Save the un-overlaid video so the rest of the
|
|
89
|
+
// run still produces useful output.
|
|
90
|
+
log.warn(
|
|
91
|
+
'Could not add text overlay to video, saving without metric labels. %s',
|
|
92
|
+
error.shortMessage || error.message
|
|
93
|
+
);
|
|
94
|
+
await rename(temporaryFile, videoPath);
|
|
95
|
+
try {
|
|
96
|
+
await unlink(temporaryFile2);
|
|
97
|
+
} catch {
|
|
98
|
+
// tmp2 may not exist if ffmpeg never opened the output
|
|
99
|
+
}
|
|
100
|
+
}
|
|
84
101
|
} else {
|
|
85
102
|
await rename(temporaryFile, videoPath);
|
|
86
103
|
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import { getLogger } from '@sitespeed.io/log';
|
|
4
|
+
|
|
5
|
+
const log = getLogger('browsertime.video');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Records the screen of an iOS device connected via USB.
|
|
9
|
+
*
|
|
10
|
+
* Uses the ios-capture server process that was started by the
|
|
11
|
+
* Safari delegate in beforeBrowserStart(). The server accepts
|
|
12
|
+
* START/STOP commands via stdin to control recording per iteration.
|
|
13
|
+
*/
|
|
14
|
+
export class IOSDeviceRecorder {
|
|
15
|
+
constructor(options, baseDir) {
|
|
16
|
+
this.options = options;
|
|
17
|
+
this.baseDir = baseDir;
|
|
18
|
+
this.responseBuffer = '';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Start recording to a temporary file.
|
|
23
|
+
*/
|
|
24
|
+
async start() {
|
|
25
|
+
const captureProcess = this.options._iosCaptureProcess;
|
|
26
|
+
if (!captureProcess) {
|
|
27
|
+
log.error('ios-capture server not running');
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Set up response listener if not already done
|
|
32
|
+
if (!this._listeningForResponses) {
|
|
33
|
+
captureProcess.stdout.on('data', data => {
|
|
34
|
+
this.responseBuffer += data.toString();
|
|
35
|
+
});
|
|
36
|
+
this._listeningForResponses = true;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const tmpVideo = path.join(this.baseDir, 'ios-tmp-video.mp4');
|
|
40
|
+
this.tmpVideo = tmpVideo;
|
|
41
|
+
|
|
42
|
+
captureProcess.stdin.write(`START ${tmpVideo}\n`);
|
|
43
|
+
|
|
44
|
+
// Wait for RECORDING response
|
|
45
|
+
await this._waitForResponse('RECORDING', 10_000);
|
|
46
|
+
log.debug('iOS recording started');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Stop the current recording and move the video to the destination.
|
|
51
|
+
*/
|
|
52
|
+
async stop(destination) {
|
|
53
|
+
log.debug('Stop iOS device recorder');
|
|
54
|
+
|
|
55
|
+
const captureProcess = this.options._iosCaptureProcess;
|
|
56
|
+
if (captureProcess) {
|
|
57
|
+
captureProcess.stdin.write('STOP\n');
|
|
58
|
+
await this._waitForResponse('STOPPED', 10_000);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Wait for ffmpeg to finish writing
|
|
62
|
+
await new Promise(r => setTimeout(r, 1000));
|
|
63
|
+
|
|
64
|
+
if (!destination) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
await fs.promises.rename(this.tmpVideo, destination);
|
|
70
|
+
} catch {
|
|
71
|
+
try {
|
|
72
|
+
await fs.promises.copyFile(this.tmpVideo, destination);
|
|
73
|
+
await fs.promises.unlink(this.tmpVideo);
|
|
74
|
+
} catch (error) {
|
|
75
|
+
log.error('Could not move video: %s', error.message);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
log.debug('Video saved to %s', destination);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Wait for a specific response from ios-capture stdout.
|
|
84
|
+
*/
|
|
85
|
+
async _waitForResponse(expected, timeoutMs) {
|
|
86
|
+
const start = Date.now();
|
|
87
|
+
while (Date.now() - start < timeoutMs) {
|
|
88
|
+
if (this.responseBuffer.includes(expected)) {
|
|
89
|
+
const index = this.responseBuffer.indexOf(expected);
|
|
90
|
+
this.responseBuffer = this.responseBuffer
|
|
91
|
+
.slice(index + expected.length)
|
|
92
|
+
.trim();
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
if (this.responseBuffer.includes('ERROR')) {
|
|
96
|
+
const errorMsg = this.responseBuffer.trim();
|
|
97
|
+
this.responseBuffer = '';
|
|
98
|
+
throw new Error(`ios-capture error: ${errorMsg}`);
|
|
99
|
+
}
|
|
100
|
+
await new Promise(r => setTimeout(r, 100));
|
|
101
|
+
}
|
|
102
|
+
log.error(
|
|
103
|
+
'Timeout waiting for "%s" from ios-capture (buffer: %s)',
|
|
104
|
+
expected,
|
|
105
|
+
this.responseBuffer
|
|
106
|
+
);
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -3,7 +3,7 @@ import { AndroidRecorder } from './android/recorder.js';
|
|
|
3
3
|
import { DesktopRecorder } from './desktop/desktopRecorder.js';
|
|
4
4
|
import { FirefoxWindowRecorder } from './firefox/firefoxWindowRecorder.js';
|
|
5
5
|
import { IOSSimulatorRecorder } from './iosSimulator/recorder.js';
|
|
6
|
-
import {
|
|
6
|
+
import { IOSDeviceRecorder } from './ios/iosDeviceRecorder.js';
|
|
7
7
|
|
|
8
8
|
export function getRecorder(options, browser, baseDir) {
|
|
9
9
|
if (
|
|
@@ -27,7 +27,7 @@ export function getRecorder(options, browser, baseDir) {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
if (options.browser === 'safari' && options.safari && options.safari.ios) {
|
|
30
|
-
return new
|
|
30
|
+
return new IOSDeviceRecorder(options, baseDir);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
return new DesktopRecorder(options);
|
|
@@ -6,6 +6,9 @@ export async function setOrangeBackground(driver) {
|
|
|
6
6
|
// We tried other ways for Android (access an orange page)
|
|
7
7
|
// That works fine ... but break scripts
|
|
8
8
|
// https://github.com/sitespeedio/browsertime/issues/802
|
|
9
|
+
// Wait for document.body to exist before trying to add the orange overlay
|
|
10
|
+
await driver.wait(until.elementsLocated(By.css('body')));
|
|
11
|
+
|
|
9
12
|
const orangeScript = `
|
|
10
13
|
(function() {
|
|
11
14
|
const orange = document.createElement('div');
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "browsertime",
|
|
3
3
|
"description": "Get performance metrics from your web page using Browsertime.",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "27.0.1",
|
|
5
5
|
"bin": "./bin/browsertime.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"types": "./types/scripting.d.ts",
|
|
@@ -13,31 +13,31 @@
|
|
|
13
13
|
"@sitespeed.io/log": "1.0.0",
|
|
14
14
|
"@sitespeed.io/throttle": "5.0.1",
|
|
15
15
|
"@sitespeed.io/tracium": "0.3.3",
|
|
16
|
-
"chrome-har": "1.
|
|
16
|
+
"chrome-har": "1.2.1",
|
|
17
17
|
"chrome-remote-interface": "0.33.3",
|
|
18
|
-
"execa": "9.6.
|
|
18
|
+
"execa": "9.6.1",
|
|
19
19
|
"fast-stats": "0.0.7",
|
|
20
20
|
"ff-test-bidi-har-export": "0.0.22",
|
|
21
21
|
"lodash.merge": "4.6.2",
|
|
22
|
-
"selenium-webdriver": "4.
|
|
22
|
+
"selenium-webdriver": "4.43.0",
|
|
23
23
|
"yargs": "18.0.0"
|
|
24
24
|
},
|
|
25
25
|
"optionalDependencies": {
|
|
26
|
-
"jimp": "1.6.
|
|
26
|
+
"jimp": "1.6.1",
|
|
27
27
|
"usb-power-profiling": "1.6.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@types/selenium-webdriver": "4.35.
|
|
30
|
+
"@types/selenium-webdriver": "4.35.5",
|
|
31
31
|
"ava": "6.4.1",
|
|
32
|
-
"clean-jsdoc-theme": "4.3.
|
|
32
|
+
"clean-jsdoc-theme": "4.3.2",
|
|
33
33
|
"eslint": "9.37.0",
|
|
34
34
|
"eslint-config-prettier": "10.1.8",
|
|
35
|
-
"eslint-plugin-prettier": "5.5.
|
|
35
|
+
"eslint-plugin-prettier": "5.5.5",
|
|
36
36
|
"eslint-plugin-unicorn": "61.0.2",
|
|
37
37
|
"jsdoc": "4.0.5",
|
|
38
|
-
"prettier": "3.
|
|
39
|
-
"serve": "14.2.
|
|
40
|
-
"serve-handler": "6.1.
|
|
38
|
+
"prettier": "3.8.3",
|
|
39
|
+
"serve": "14.2.6",
|
|
40
|
+
"serve-handler": "6.1.7",
|
|
41
41
|
"typescript": "5.9.3"
|
|
42
42
|
},
|
|
43
43
|
"engines": {
|
|
@@ -4,65 +4,94 @@
|
|
|
4
4
|
* @hideconstructor
|
|
5
5
|
*/
|
|
6
6
|
export class AddText {
|
|
7
|
-
constructor(browser: any);
|
|
7
|
+
constructor(browser: any, options: any);
|
|
8
8
|
/**
|
|
9
9
|
* @private
|
|
10
10
|
*/
|
|
11
11
|
private browser;
|
|
12
|
+
/**
|
|
13
|
+
* @private
|
|
14
|
+
*/
|
|
15
|
+
private options;
|
|
16
|
+
/**
|
|
17
|
+
* @private
|
|
18
|
+
*/
|
|
19
|
+
private _waitForElement;
|
|
20
|
+
/**
|
|
21
|
+
* @private
|
|
22
|
+
*/
|
|
23
|
+
private _getUrl;
|
|
24
|
+
/**
|
|
25
|
+
* Adds text to an element using a unified selector string.
|
|
26
|
+
* Supports CSS selectors (default), and prefix-based strategies:
|
|
27
|
+
* 'id:myId', 'xpath://input', 'name:email', 'class:input-field'.
|
|
28
|
+
*
|
|
29
|
+
* @async
|
|
30
|
+
* @param {string} selector - The selector string. CSS by default, or use a prefix.
|
|
31
|
+
* @param {string} text - The text string to add.
|
|
32
|
+
* @returns {Promise<void>} A promise that resolves when the text has been added.
|
|
33
|
+
* @throws {Error} Throws an error if the element is not found.
|
|
34
|
+
*/
|
|
35
|
+
run(selector: string, text: string): Promise<void>;
|
|
12
36
|
/**
|
|
13
37
|
* Adds text to an element identified by its ID.
|
|
14
38
|
*
|
|
15
39
|
* @async
|
|
40
|
+
* @private
|
|
16
41
|
* @example commands.addText.byId('mytext', 'id');
|
|
17
42
|
* @param {string} text - The text string to add.
|
|
18
43
|
* @param {string} id - The ID of the element.
|
|
19
44
|
* @returns {Promise<void>} A promise that resolves when the text has been added.
|
|
20
45
|
* @throws {Error} Throws an error if the element is not found.
|
|
21
46
|
*/
|
|
22
|
-
byId
|
|
47
|
+
private byId;
|
|
23
48
|
/**
|
|
24
49
|
* Adds text to an element identified by its XPath.
|
|
25
50
|
*
|
|
26
51
|
* @async
|
|
52
|
+
* @private
|
|
27
53
|
* @example commands.addText.byXpath('mytext', 'xpath');
|
|
28
54
|
* @param {string} text - The text string to add.
|
|
29
55
|
* @param {string} xpath - The XPath of the element.
|
|
30
56
|
* @returns {Promise<void>} A promise that resolves when the text has been added.
|
|
31
57
|
* @throws {Error} Throws an error if the element is not found.
|
|
32
58
|
*/
|
|
33
|
-
byXpath
|
|
59
|
+
private byXpath;
|
|
34
60
|
/**
|
|
35
61
|
* Adds text to an element identified by its CSS selector.
|
|
36
62
|
*
|
|
37
63
|
* @async
|
|
64
|
+
* @private
|
|
38
65
|
* @example commands.addText.bySelector('mytext', 'selector');
|
|
39
66
|
* @param {string} text - The text string to add.
|
|
40
67
|
* @param {string} selector - The CSS selector of the element.
|
|
41
68
|
* @returns {Promise<void>} A promise that resolves when the text has been added.
|
|
42
69
|
* @throws {Error} Throws an error if the element is not found.
|
|
43
70
|
*/
|
|
44
|
-
bySelector
|
|
71
|
+
private bySelector;
|
|
45
72
|
/**
|
|
46
73
|
* Adds text to an element identified by its class name.
|
|
47
74
|
*
|
|
48
75
|
* @async
|
|
76
|
+
* @private
|
|
49
77
|
* @example commands.addText.byClassName('mytext', 'className');
|
|
50
78
|
* @param {string} text - The text string to add.
|
|
51
79
|
* @param {string} className - The class name of the element.
|
|
52
80
|
* @returns {Promise<void>} A promise that resolves when the text has been added.
|
|
53
81
|
* @throws {Error} Throws an error if the element is not found.
|
|
54
82
|
*/
|
|
55
|
-
byClassName
|
|
83
|
+
private byClassName;
|
|
56
84
|
/**
|
|
57
85
|
* Adds text to an element identified by its name attribute.
|
|
58
86
|
*
|
|
59
87
|
* @async
|
|
88
|
+
* @private
|
|
60
89
|
* @example commands.addText.byName('mytext', 'name');
|
|
61
90
|
* @param {string} text - The text string to add.
|
|
62
91
|
* @param {string} name - The name attribute of the element.
|
|
63
92
|
* @returns {Promise<void>} A promise that resolves when the text has been added.
|
|
64
93
|
* @throws {Error} Throws an error if the element is not found.
|
|
65
94
|
*/
|
|
66
|
-
byName
|
|
95
|
+
private byName;
|
|
67
96
|
}
|
|
68
97
|
//# sourceMappingURL=addText.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"addText.d.ts","sourceRoot":"","sources":["../../../../lib/core/engine/command/addText.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"addText.d.ts","sourceRoot":"","sources":["../../../../lib/core/engine/command/addText.js"],"names":[],"mappings":"AAMA;;;;GAIG;AACH;IACE,wCASC;IARC;;OAEG;IACH,gBAAsB;IACtB;;OAEG;IACH,gBAAsB;IAGxB;;OAEG;IACH,wBAKC;IAED;;OAEG;IACH,gBAMC;IAED;;;;;;;;;;OAUG;IACH,cALW,MAAM,QACN,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAkBzB;IAED;;;;;;;;;;OAUG;IACH,aAoBC;IAED;;;;;;;;;;OAUG;IACH,gBAoBC;IAED;;;;;;;;;;OAUG;IACH,mBAsBC;IAED;;;;;;;;;;OAUG;IACH,oBAsBC;IAED;;;;;;;;;;OAUG;IACH,eAsBC;CACF"}
|