browsertime 26.3.2 → 27.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.
Files changed (105) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/README.md +1 -1
  3. package/browserscripts/timings/softNavigations.js +94 -0
  4. package/lib/chrome/har.js +36 -5
  5. package/lib/chrome/settings/chromeAndroidOptions.js +2 -1
  6. package/lib/chrome/webdriver/chromium.js +39 -0
  7. package/lib/chrome/webdriver/setupChromiumOptions.js +86 -31
  8. package/lib/core/engine/collector.js +340 -317
  9. package/lib/core/engine/command/addText.js +93 -12
  10. package/lib/core/engine/command/click.js +239 -139
  11. package/lib/core/engine/command/commandHelper.js +45 -0
  12. package/lib/core/engine/command/cookie.js +85 -0
  13. package/lib/core/engine/command/element.js +37 -2
  14. package/lib/core/engine/command/javaScript.js +14 -24
  15. package/lib/core/engine/command/measure/screenshots.js +114 -0
  16. package/lib/core/engine/command/measure/video.js +85 -0
  17. package/lib/core/engine/command/measure.js +104 -180
  18. package/lib/core/engine/command/mouse/clickAndHold.js +6 -3
  19. package/lib/core/engine/command/mouse/contextClick.js +56 -4
  20. package/lib/core/engine/command/mouse/doubleClick.js +49 -1
  21. package/lib/core/engine/command/mouse/mouseMove.js +50 -1
  22. package/lib/core/engine/command/mouse/singleClick.js +165 -129
  23. package/lib/core/engine/command/navigation.js +6 -6
  24. package/lib/core/engine/command/select.js +95 -3
  25. package/lib/core/engine/command/selectorParser.js +58 -0
  26. package/lib/core/engine/command/set.js +55 -1
  27. package/lib/core/engine/command/wait.js +41 -2
  28. package/lib/core/engine/commands.js +550 -42
  29. package/lib/core/engine/index.js +206 -150
  30. package/lib/core/engine/iteration.js +269 -137
  31. package/lib/firefox/networkManager.js +22 -30
  32. package/lib/firefox/webdriver/builder.js +14 -0
  33. package/lib/safari/har.js +131 -0
  34. package/lib/safari/native/ios-capture +0 -0
  35. package/lib/safari/native/ios-capture.m +340 -0
  36. package/lib/safari/safariInspectorClient.js +322 -0
  37. package/lib/safari/webdriver/safari.js +303 -13
  38. package/lib/safari/webkitToCdpAdapter.js +241 -0
  39. package/lib/support/cli.js +13 -0
  40. package/lib/support/engineUtils.js +16 -5
  41. package/lib/support/getViewPort.js +5 -0
  42. package/lib/support/har/index.js +41 -3
  43. package/lib/support/usbPower.js +2 -3
  44. package/lib/video/postprocessing/finetune/addTextToVideo.js +4 -0
  45. package/lib/video/postprocessing/finetune/getFont.js +3 -3
  46. package/lib/video/postprocessing/finetune/getTimingMetrics.js +7 -0
  47. package/lib/video/postprocessing/finetune/index.js +26 -9
  48. package/lib/video/screenRecording/ios/iosDeviceRecorder.js +109 -0
  49. package/lib/video/screenRecording/recorder.js +2 -2
  50. package/lib/video/screenRecording/setOrangeBackground.js +3 -0
  51. package/package.json +11 -11
  52. package/types/core/engine/command/addText.d.ts +35 -6
  53. package/types/core/engine/command/addText.d.ts.map +1 -1
  54. package/types/core/engine/command/click.d.ts +87 -16
  55. package/types/core/engine/command/click.d.ts.map +1 -1
  56. package/types/core/engine/command/commandHelper.d.ts +16 -0
  57. package/types/core/engine/command/commandHelper.d.ts.map +1 -0
  58. package/types/core/engine/command/cookie.d.ts +65 -0
  59. package/types/core/engine/command/cookie.d.ts.map +1 -0
  60. package/types/core/engine/command/element.d.ts +19 -1
  61. package/types/core/engine/command/element.d.ts.map +1 -1
  62. package/types/core/engine/command/javaScript.d.ts +4 -0
  63. package/types/core/engine/command/javaScript.d.ts.map +1 -1
  64. package/types/core/engine/command/measure/screenshots.d.ts +15 -0
  65. package/types/core/engine/command/measure/screenshots.d.ts.map +1 -0
  66. package/types/core/engine/command/measure/video.d.ts +26 -0
  67. package/types/core/engine/command/measure/video.d.ts.map +1 -0
  68. package/types/core/engine/command/measure.d.ts +59 -33
  69. package/types/core/engine/command/measure.d.ts.map +1 -1
  70. package/types/core/engine/command/mouse/clickAndHold.d.ts.map +1 -1
  71. package/types/core/engine/command/mouse/contextClick.d.ts +28 -4
  72. package/types/core/engine/command/mouse/contextClick.d.ts.map +1 -1
  73. package/types/core/engine/command/mouse/doubleClick.d.ts +24 -4
  74. package/types/core/engine/command/mouse/doubleClick.d.ts.map +1 -1
  75. package/types/core/engine/command/mouse/mouseMove.d.ts +30 -5
  76. package/types/core/engine/command/mouse/mouseMove.d.ts.map +1 -1
  77. package/types/core/engine/command/mouse/singleClick.d.ts +50 -13
  78. package/types/core/engine/command/mouse/singleClick.d.ts.map +1 -1
  79. package/types/core/engine/command/navigation.d.ts +3 -3
  80. package/types/core/engine/command/select.d.ts +45 -8
  81. package/types/core/engine/command/select.d.ts.map +1 -1
  82. package/types/core/engine/command/selectorParser.d.ts +20 -0
  83. package/types/core/engine/command/selectorParser.d.ts.map +1 -0
  84. package/types/core/engine/command/set.d.ts +34 -7
  85. package/types/core/engine/command/set.d.ts.map +1 -1
  86. package/types/core/engine/command/wait.d.ts +29 -6
  87. package/types/core/engine/command/wait.d.ts.map +1 -1
  88. package/types/core/engine/commands.d.ts +296 -28
  89. package/types/core/engine/commands.d.ts.map +1 -1
  90. package/types/support/engineUtils.d.ts.map +1 -1
  91. package/types/support/getViewPort.d.ts.map +1 -1
  92. package/types/support/usbPower.d.ts.map +1 -1
  93. package/types/video/postprocessing/finetune/addTextToVideo.d.ts.map +1 -1
  94. package/types/video/postprocessing/finetune/getTimingMetrics.d.ts.map +1 -1
  95. package/types/video/postprocessing/finetune/index.d.ts.map +1 -1
  96. package/types/video/screenRecording/ios/iosDeviceRecorder.d.ts +28 -0
  97. package/types/video/screenRecording/ios/iosDeviceRecorder.d.ts.map +1 -0
  98. package/types/video/screenRecording/recorder.d.ts +2 -2
  99. package/types/video/screenRecording/recorder.d.ts.map +1 -1
  100. package/types/video/screenRecording/setOrangeBackground.d.ts.map +1 -1
  101. package/types/video/video.d.ts +1 -1
  102. package/types/video/video.d.ts.map +1 -1
  103. package/visualmetrics/visualmetrics-portable.py +136 -136
  104. package/lib/video/screenRecording/ios/convertToMp4.js +0 -22
  105. package/lib/video/screenRecording/ios/iosRecorder.js +0 -68
@@ -1,5 +1,7 @@
1
- import { By } from 'selenium-webdriver';
1
+ import webdriver, { By } from 'selenium-webdriver';
2
2
  import { getLogger } from '@sitespeed.io/log';
3
+ import { executeCommand } from './commandHelper.js';
4
+ import { parseSelector } from './selectorParser.js';
3
5
  const log = getLogger('browsertime.command.addText');
4
6
 
5
7
  /**
@@ -8,17 +10,71 @@ const log = getLogger('browsertime.command.addText');
8
10
  * @hideconstructor
9
11
  */
10
12
  export class AddText {
11
- constructor(browser) {
13
+ constructor(browser, options) {
12
14
  /**
13
15
  * @private
14
16
  */
15
17
  this.browser = browser;
18
+ /**
19
+ * @private
20
+ */
21
+ this.options = options;
22
+ }
23
+
24
+ /**
25
+ * @private
26
+ */
27
+ async _waitForElement(driver, locator) {
28
+ const timeout = this.options?.timeouts?.elementWait ?? 0;
29
+ if (timeout > 0) {
30
+ await driver.wait(webdriver.until.elementLocated(locator), timeout);
31
+ }
32
+ }
33
+
34
+ /**
35
+ * @private
36
+ */
37
+ async _getUrl() {
38
+ try {
39
+ return ` on ${await this.browser.getDriver().getCurrentUrl()}`;
40
+ } catch {
41
+ return '';
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Adds text to an element using a unified selector string.
47
+ * Supports CSS selectors (default), and prefix-based strategies:
48
+ * 'id:myId', 'xpath://input', 'name:email', 'class:input-field'.
49
+ *
50
+ * @async
51
+ * @param {string} selector - The selector string. CSS by default, or use a prefix.
52
+ * @param {string} text - The text string to add.
53
+ * @returns {Promise<void>} A promise that resolves when the text has been added.
54
+ * @throws {Error} Throws an error if the element is not found.
55
+ */
56
+ async run(selector, text) {
57
+ const { locator, description } = parseSelector(selector);
58
+ return executeCommand(
59
+ log,
60
+ 'Could not add text %s to %s',
61
+ description,
62
+ async () => {
63
+ const driver = this.browser.getDriver();
64
+ await this._waitForElement(driver, locator);
65
+ const element = await driver.findElement(locator);
66
+ await element.clear();
67
+ return element.sendKeys(text);
68
+ },
69
+ this.browser
70
+ );
16
71
  }
17
72
 
18
73
  /**
19
74
  * Adds text to an element identified by its ID.
20
75
  *
21
76
  * @async
77
+ * @private
22
78
  * @example commands.addText.byId('mytext', 'id');
23
79
  * @param {string} text - The text string to add.
24
80
  * @param {string} id - The ID of the element.
@@ -28,11 +84,14 @@ export class AddText {
28
84
  async byId(text, id) {
29
85
  const driver = this.browser.getDriver();
30
86
  try {
31
- const element = await driver.findElement(By.id(id));
87
+ const locator = By.id(id);
88
+ await this._waitForElement(driver, locator);
89
+ const element = await driver.findElement(locator);
32
90
  // make sure we clear it
33
91
  await element.clear();
34
92
  return element.sendKeys(text);
35
93
  } catch (error) {
94
+ const url = await this._getUrl();
36
95
  log.error(
37
96
  'Could not add text %s to id %s error:%s',
38
97
  text,
@@ -40,7 +99,7 @@ export class AddText {
40
99
  error.message
41
100
  );
42
101
  log.verbose(error);
43
- throw new Error(`Could not add text ${text} to id ${id}`);
102
+ throw new Error(`Could not add text ${text} to id ${id}${url}`);
44
103
  }
45
104
  }
46
105
 
@@ -48,6 +107,7 @@ export class AddText {
48
107
  * Adds text to an element identified by its XPath.
49
108
  *
50
109
  * @async
110
+ * @private
51
111
  * @example commands.addText.byXpath('mytext', 'xpath');
52
112
  * @param {string} text - The text string to add.
53
113
  * @param {string} xpath - The XPath of the element.
@@ -57,11 +117,14 @@ export class AddText {
57
117
  async byXpath(text, xpath) {
58
118
  const driver = this.browser.getDriver();
59
119
  try {
60
- const element = await driver.findElement(By.xpath(xpath));
120
+ const locator = By.xpath(xpath);
121
+ await this._waitForElement(driver, locator);
122
+ const element = await driver.findElement(locator);
61
123
  // make sure we clear it
62
124
  await element.clear();
63
125
  return element.sendKeys(text);
64
126
  } catch (error) {
127
+ const url = await this._getUrl();
65
128
  log.error(
66
129
  'Could not add text %s to xpath %s error: %s',
67
130
  text,
@@ -69,7 +132,7 @@ export class AddText {
69
132
  error.message
70
133
  );
71
134
  log.verbose(error);
72
- throw new Error(`Could not add text ${text} to xpath ${xpath}`);
135
+ throw new Error(`Could not add text ${text} to xpath ${xpath}${url}`);
73
136
  }
74
137
  }
75
138
 
@@ -77,6 +140,7 @@ export class AddText {
77
140
  * Adds text to an element identified by its CSS selector.
78
141
  *
79
142
  * @async
143
+ * @private
80
144
  * @example commands.addText.bySelector('mytext', 'selector');
81
145
  * @param {string} text - The text string to add.
82
146
  * @param {string} selector - The CSS selector of the element.
@@ -86,11 +150,14 @@ export class AddText {
86
150
  async bySelector(text, selector) {
87
151
  const driver = this.browser.getDriver();
88
152
  try {
89
- const element = await driver.findElement(By.css(selector));
153
+ const locator = By.css(selector);
154
+ await this._waitForElement(driver, locator);
155
+ const element = await driver.findElement(locator);
90
156
  // make sure we clear it
91
157
  await element.clear();
92
158
  return element.sendKeys(text);
93
159
  } catch (error) {
160
+ const url = await this._getUrl();
94
161
  log.error(
95
162
  'Could not add text %s to selector %s error: %s',
96
163
  text,
@@ -98,7 +165,9 @@ export class AddText {
98
165
  error.message
99
166
  );
100
167
  log.verbose(error);
101
- throw new Error(`Could not add text ${text} to selector ${selector}`);
168
+ throw new Error(
169
+ `Could not add text ${text} to selector ${selector}${url}`
170
+ );
102
171
  }
103
172
  }
104
173
 
@@ -106,6 +175,7 @@ export class AddText {
106
175
  * Adds text to an element identified by its class name.
107
176
  *
108
177
  * @async
178
+ * @private
109
179
  * @example commands.addText.byClassName('mytext', 'className');
110
180
  * @param {string} text - The text string to add.
111
181
  * @param {string} className - The class name of the element.
@@ -115,11 +185,14 @@ export class AddText {
115
185
  async byClassName(text, className) {
116
186
  const driver = this.browser.getDriver();
117
187
  try {
118
- const element = await driver.findElement(By.className(className));
188
+ const locator = By.className(className);
189
+ await this._waitForElement(driver, locator);
190
+ const element = await driver.findElement(locator);
119
191
  // make sure we clear it
120
192
  await element.clear();
121
193
  return element.sendKeys(text);
122
194
  } catch (error) {
195
+ const url = await this._getUrl();
123
196
  log.error(
124
197
  'Could not add text %s to class name %s error: %s',
125
198
  text,
@@ -127,7 +200,9 @@ export class AddText {
127
200
  error.message
128
201
  );
129
202
  log.verbose(error);
130
- throw new Error(`Could not add text ${text} to class name ${className}`);
203
+ throw new Error(
204
+ `Could not add text ${text} to class name ${className}${url}`
205
+ );
131
206
  }
132
207
  }
133
208
 
@@ -135,6 +210,7 @@ export class AddText {
135
210
  * Adds text to an element identified by its name attribute.
136
211
  *
137
212
  * @async
213
+ * @private
138
214
  * @example commands.addText.byName('mytext', 'name');
139
215
  * @param {string} text - The text string to add.
140
216
  * @param {string} name - The name attribute of the element.
@@ -144,11 +220,14 @@ export class AddText {
144
220
  async byName(text, name) {
145
221
  const driver = this.browser.getDriver();
146
222
  try {
147
- const element = await driver.findElement(By.name(name));
223
+ const locator = By.name(name);
224
+ await this._waitForElement(driver, locator);
225
+ const element = await driver.findElement(locator);
148
226
  // make sure we clear it
149
227
  await element.clear();
150
228
  return element.sendKeys(text);
151
229
  } catch (error) {
230
+ const url = await this._getUrl();
152
231
  log.error(
153
232
  'Could not add text %s to name attribute %s error: %s',
154
233
  text,
@@ -156,7 +235,9 @@ export class AddText {
156
235
  error.message
157
236
  );
158
237
  log.verbose(error);
159
- throw new Error(`Could not add text ${text} to name attribute ${name}`);
238
+ throw new Error(
239
+ `Could not add text ${text} to name attribute ${name}${url}`
240
+ );
160
241
  }
161
242
  }
162
243
  }