@checkly/playwright-core 1.41.25 → 1.42.11

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 (176) hide show
  1. package/ThirdPartyNotices.txt +3 -3
  2. package/bin/reinstall_chrome_beta_win.ps1 +2 -1
  3. package/bin/reinstall_chrome_stable_win.ps1 +2 -1
  4. package/bin/reinstall_msedge_beta_win.ps1 +2 -1
  5. package/bin/reinstall_msedge_dev_win.ps1 +2 -1
  6. package/bin/reinstall_msedge_stable_win.ps1 +2 -1
  7. package/browsers.json +14 -15
  8. package/cli.js +2 -1
  9. package/lib/checkly/fetch.js +28 -1
  10. package/lib/cli/cli.js +2 -1
  11. package/lib/cli/driver.js +9 -1
  12. package/lib/cli/program.js +12 -4
  13. package/lib/client/browserContext.js +1 -1
  14. package/lib/client/channelOwner.js +1 -1
  15. package/lib/client/clientHelper.js +5 -1
  16. package/lib/client/connection.js +1 -1
  17. package/lib/client/consoleMessage.js +1 -1
  18. package/lib/client/electron.js +3 -0
  19. package/lib/client/events.js +1 -0
  20. package/lib/client/frame.js +2 -1
  21. package/lib/client/harRouter.js +7 -1
  22. package/lib/client/page.js +25 -6
  23. package/lib/common/debugLogger.js +3 -1
  24. package/lib/common/socksProxy.js +1 -1
  25. package/lib/generated/consoleApiSource.js +1 -1
  26. package/lib/generated/injectedScriptSource.js +1 -1
  27. package/lib/generated/recorderSource.js +1 -1
  28. package/lib/outofprocess.js +1 -1
  29. package/lib/protocol/validator.js +60 -30
  30. package/lib/remote/playwrightConnection.js +1 -1
  31. package/lib/remote/playwrightServer.js +72 -166
  32. package/lib/server/android/android.js +1 -1
  33. package/lib/server/browserType.js +2 -2
  34. package/lib/server/chromium/chromium.js +5 -4
  35. package/lib/server/chromium/crConnection.js +1 -1
  36. package/lib/server/chromium/crNetworkManager.js +1 -3
  37. package/lib/server/chromium/crPage.js +45 -2
  38. package/lib/server/chromium/crPdf.js +8 -2
  39. package/lib/server/console.js +1 -3
  40. package/lib/server/debugController.js +0 -3
  41. package/lib/server/deviceDescriptorsSource.json +50 -50
  42. package/lib/server/dispatchers/browserContextDispatcher.js +3 -2
  43. package/lib/server/dispatchers/dispatcher.js +9 -10
  44. package/lib/server/dispatchers/electronDispatcher.js +13 -0
  45. package/lib/server/dispatchers/frameDispatcher.js +0 -6
  46. package/lib/server/dispatchers/networkDispatchers.js +1 -0
  47. package/lib/server/dispatchers/pageDispatcher.js +14 -10
  48. package/lib/server/dom.js +130 -167
  49. package/lib/server/electron/electron.js +38 -12
  50. package/lib/server/electron/loader.js +4 -2
  51. package/lib/server/fetch.js +1 -0
  52. package/lib/server/firefox/ffAccessibility.js +2 -1
  53. package/lib/server/firefox/ffConnection.js +1 -1
  54. package/lib/server/firefox/ffPage.js +1 -1
  55. package/lib/server/frames.js +39 -20
  56. package/lib/server/helper.js +1 -1
  57. package/lib/server/page.js +49 -5
  58. package/lib/server/pipeTransport.js +1 -1
  59. package/lib/server/playwright.js +1 -1
  60. package/lib/server/progress.js +3 -11
  61. package/lib/server/recorder/csharp.js +1 -1
  62. package/lib/server/recorder/java.js +36 -4
  63. package/lib/server/recorder.js +2 -2
  64. package/lib/server/registry/browserFetcher.js +1 -1
  65. package/lib/server/registry/dependencies.js +5 -4
  66. package/lib/server/registry/index.js +48 -30
  67. package/lib/server/registry/nativeDeps.js +0 -94
  68. package/lib/server/trace/recorder/snapshotter.js +1 -1
  69. package/lib/server/trace/recorder/tracing.js +5 -2
  70. package/lib/server/trace/viewer/traceViewer.js +1 -1
  71. package/lib/server/transport.js +4 -2
  72. package/lib/server/webkit/wkConnection.js +1 -1
  73. package/lib/server/webkit/wkPage.js +2 -2
  74. package/lib/utils/comparators.js +4 -4
  75. package/lib/utils/fileUtils.js +4 -0
  76. package/lib/utils/hostPlatform.js +1 -1
  77. package/lib/utils/index.js +33 -0
  78. package/lib/utils/isomorphic/locatorParser.js +6 -4
  79. package/lib/utils/isomorphic/stringUtils.js +5 -0
  80. package/lib/utils/network.js +32 -0
  81. package/lib/utils/processLauncher.js +7 -0
  82. package/lib/utils/rtti.js +7 -4
  83. package/lib/utils/wsServer.js +5 -3
  84. package/lib/utilsBundleImpl/index.js +4 -4
  85. package/lib/vite/htmlReport/index.html +11 -11
  86. package/lib/vite/{traceViewer/assets/codeMirrorModule-GJA8DRmd.js → recorder/assets/codeMirrorModule-W69B4LBB.js} +1 -1
  87. package/lib/vite/recorder/assets/{index-yg8ypzl6.js → index-Ly3PcVUb.js} +2 -2
  88. package/lib/vite/recorder/index.html +1 -1
  89. package/lib/vite/traceViewer/assets/{codeMirrorModule-GluP1cQ1.js → codeMirrorModule-BK3t1EEu.js} +1 -1
  90. package/lib/vite/traceViewer/assets/codeMirrorModule-cc2329e4.js +15593 -0
  91. package/lib/vite/traceViewer/assets/codeMirrorModule-d725feea.js +15586 -0
  92. package/lib/vite/traceViewer/assets/{codeMirrorModule-fqJB1XDu.js → codeMirrorModule-e5a15eec.js} +1 -1
  93. package/lib/vite/traceViewer/assets/codeMirrorModule-kT-uS7F4.js +15592 -0
  94. package/lib/vite/traceViewer/assets/codeMirrorModule-rcsC5no8.js +15592 -0
  95. package/lib/vite/traceViewer/assets/codeMirrorModule-yboVpgC0.js +15592 -0
  96. package/lib/vite/traceViewer/assets/codeMirrorModule-ytMY1awF.js +15585 -0
  97. package/lib/vite/traceViewer/assets/wsPort-54626118.js +18361 -0
  98. package/lib/vite/traceViewer/assets/{wsPort-uVqol1LI.js → wsPort-964mA9MZ.js} +18 -18
  99. package/lib/vite/traceViewer/assets/wsPort-CAXygIGt.js +18540 -0
  100. package/lib/vite/traceViewer/assets/wsPort-a88a6a12.js +18361 -0
  101. package/lib/vite/traceViewer/assets/{wsPort-722747dc.js → wsPort-cb764cde.js} +1 -1
  102. package/lib/vite/traceViewer/assets/wsPort-lTlmZhJd.js +18564 -0
  103. package/lib/vite/traceViewer/assets/wsPort-xpIMLVfx.js +18540 -0
  104. package/lib/vite/traceViewer/assets/wsPort-yM58htfg.js +18360 -0
  105. package/lib/vite/traceViewer/assets/xtermModule-60687b6b.js +6410 -0
  106. package/lib/vite/traceViewer/assets/xtermModule-_6TC5FYT.js +6529 -0
  107. package/lib/vite/traceViewer/codeMirrorModule.eb494ea9.css +344 -0
  108. package/lib/vite/traceViewer/codeMirrorModule.svF_VrcJ.css +344 -0
  109. package/lib/vite/traceViewer/{index.0d08c336.js → index.4a8ee36e.js} +1 -1
  110. package/lib/vite/traceViewer/index.55e65778.js +181 -0
  111. package/lib/vite/traceViewer/index.5mge2rY_.css +124 -0
  112. package/lib/vite/traceViewer/index.5nqVcfiC.js +180 -0
  113. package/lib/vite/traceViewer/index.742fd3e5.js +181 -0
  114. package/lib/vite/traceViewer/index.76e9f312.css +124 -0
  115. package/lib/vite/traceViewer/{index.LR1HufLs.js → index.cbtHmFgM.js} +1 -1
  116. package/lib/vite/traceViewer/index.html +3 -3
  117. package/lib/vite/traceViewer/index.ici1bqta.js +180 -0
  118. package/lib/vite/traceViewer/index.mxOcKqpu.js +180 -0
  119. package/lib/vite/traceViewer/index.zXVxM5ps.js +180 -0
  120. package/lib/vite/traceViewer/sw.bundle.js +4 -4
  121. package/lib/vite/traceViewer/uiMode.216233d5.js +1484 -0
  122. package/lib/vite/traceViewer/uiMode.2c31018f.css +1324 -0
  123. package/lib/vite/traceViewer/{uiMode.c1ebfc43.js → uiMode.468b0309.js} +1 -1
  124. package/lib/vite/traceViewer/uiMode.67C8Ij-c.js +1490 -0
  125. package/lib/vite/traceViewer/uiMode.F_k6a2aC.js +1488 -0
  126. package/lib/vite/traceViewer/uiMode.NjZAwD_B.js +1485 -0
  127. package/lib/vite/traceViewer/uiMode.YQRCZjm8.js +1485 -0
  128. package/lib/vite/traceViewer/uiMode.b2068d00.js +1484 -0
  129. package/lib/vite/traceViewer/uiMode.e-PLonGl.js +1490 -0
  130. package/lib/vite/traceViewer/{uiMode.PlLkrJDI.js → uiMode.fcU_T5Nf.js} +1 -1
  131. package/lib/vite/traceViewer/uiMode.html +3 -3
  132. package/lib/vite/traceViewer/uiMode.xvJHbkzl.css +1324 -0
  133. package/lib/vite/traceViewer/uiMode.ybQP_6Xr.js +10 -0
  134. package/lib/vite/traceViewer/wsPort.997c92cf.css +3513 -0
  135. package/lib/vite/traceViewer/wsPort.Oa05jfrO.css +3513 -0
  136. package/lib/vite/traceViewer/wsPort.p5jUwABW.css +3450 -0
  137. package/lib/vite/traceViewer/xtermModule.125f4259.css +191 -0
  138. package/lib/vite/traceViewer/xtermModule.OKEVRlkP.css +209 -0
  139. package/package.json +6 -5
  140. package/types/protocol.d.ts +367 -53
  141. package/types/types.d.ts +220 -50
  142. package/LICENSE +0 -202
  143. package/NOTICE +0 -5
  144. package/lib/vite/recorder/assets/codeMirrorModule-I9ks4y7D.js +0 -24
  145. package/lib/vite/traceViewer/assets/codeMirrorModule-2mdjgmqe.js +0 -24
  146. package/lib/vite/traceViewer/assets/codeMirrorModule-56536a77.js +0 -24
  147. package/lib/vite/traceViewer/assets/codeMirrorModule-A2_PGeGB.js +0 -24
  148. package/lib/vite/traceViewer/assets/codeMirrorModule-aUzO-LID.js +0 -24
  149. package/lib/vite/traceViewer/assets/codeMirrorModule-b361a51f.js +0 -24
  150. package/lib/vite/traceViewer/assets/codeMirrorModule-f333a775.js +0 -24
  151. package/lib/vite/traceViewer/assets/codeMirrorModule-y3M3aAqy.js +0 -24
  152. package/lib/vite/traceViewer/assets/wsPort-762c6840.js +0 -64
  153. package/lib/vite/traceViewer/assets/wsPort-93o0i57c.js +0 -69
  154. package/lib/vite/traceViewer/assets/wsPort-L8WBvZfK.js +0 -69
  155. package/lib/vite/traceViewer/assets/wsPort-Rvwd4WC-.js +0 -69
  156. package/lib/vite/traceViewer/assets/wsPort-db501ca9.js +0 -64
  157. package/lib/vite/traceViewer/assets/wsPort-dlD7vDkY.js +0 -69
  158. package/lib/vite/traceViewer/assets/wsPort-qI0zJPR7.js +0 -69
  159. package/lib/vite/traceViewer/assets/wsPort-qOE2NWrO.js +0 -69
  160. package/lib/vite/traceViewer/index.4X7zDysg.js +0 -2
  161. package/lib/vite/traceViewer/index.4xhUWj1f.js +0 -2
  162. package/lib/vite/traceViewer/index.HkJgzlGy.js +0 -2
  163. package/lib/vite/traceViewer/index.Ox-CymYJ.js +0 -2
  164. package/lib/vite/traceViewer/index.d05939c9.js +0 -2
  165. package/lib/vite/traceViewer/index.ed9a3c58.js +0 -2
  166. package/lib/vite/traceViewer/index.kRjx5sAJ.js +0 -2
  167. package/lib/vite/traceViewer/index.o6j3Cv4u.js +0 -2
  168. package/lib/vite/traceViewer/uiMode.1Wcp_Kto.js +0 -10
  169. package/lib/vite/traceViewer/uiMode.3ff70f7d.js +0 -4
  170. package/lib/vite/traceViewer/uiMode.8e0454c4.js +0 -4
  171. package/lib/vite/traceViewer/uiMode.GTNzARcV.js +0 -10
  172. package/lib/vite/traceViewer/uiMode.YGPXSUMv.js +0 -10
  173. package/lib/vite/traceViewer/uiMode.YYFJGvtV.js +0 -10
  174. package/lib/vite/traceViewer/uiMode.qpn6w4df.js +0 -10
  175. package/lib/vite/traceViewer/uiMode.zV-7Lf9v.js +0 -10
  176. package/lib/vite/traceViewer/wsPort.kSgQKQ0y.css +0 -1
package/lib/server/dom.js CHANGED
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.NonRecoverableDOMError = exports.InjectedScriptPollHandler = exports.FrameExecutionContext = exports.ElementHandle = void 0;
6
+ exports.NonRecoverableDOMError = exports.FrameExecutionContext = exports.ElementHandle = void 0;
7
7
  exports.assertDone = assertDone;
8
8
  exports.isNonRecoverableDOMError = isNonRecoverableDOMError;
9
9
  exports.kUnableToAdoptErrorMessage = void 0;
@@ -136,17 +136,6 @@ class ElementHandle extends js.JSHandle {
136
136
  return 'error:notconnected';
137
137
  }
138
138
  }
139
- async evaluatePoll(progress, pageFunction, arg) {
140
- try {
141
- const utility = await this._frame._utilityContext();
142
- const poll = await utility.evaluateHandle(pageFunction, [await utility.injectedScript(), this, arg]);
143
- const pollHandler = new InjectedScriptPollHandler(progress, poll);
144
- return await pollHandler.finish();
145
- } catch (e) {
146
- if (js.isJavaScriptErrorInEvaluate(e) || (0, _protocolError.isSessionClosedError)(e)) throw e;
147
- return 'error:notconnected';
148
- }
149
- }
150
139
  async ownerFrame() {
151
140
  const frameId = await this._page._delegate.getOwnerFrame(this);
152
141
  if (!frameId) return null;
@@ -188,25 +177,19 @@ class ElementHandle extends js.JSHandle {
188
177
  return await this._page._delegate.scrollRectIntoViewIfNeeded(this, rect);
189
178
  }
190
179
  async _waitAndScrollIntoViewIfNeeded(progress, waitForVisible) {
191
- const timeouts = [0, 50, 100, 250];
192
- while (progress.isRunning()) {
193
- assertDone(throwRetargetableDOMError(await this._waitForElementStates(progress, waitForVisible ? ['visible', 'stable'] : ['stable'], false /* force */)));
194
- progress.throwIfAborted(); // Avoid action that has side-effects.
195
- const result = throwRetargetableDOMError(await this._scrollRectIntoViewIfNeeded());
196
- if (result === 'error:notvisible') {
197
- if (!waitForVisible) {
198
- var _timeouts$shift;
199
- // Wait for a timeout to avoid retrying too often when not waiting for visible.
200
- // If we wait for visible, this should be covered by _waitForElementStates instead.
201
- const timeout = (_timeouts$shift = timeouts.shift()) !== null && _timeouts$shift !== void 0 ? _timeouts$shift : 500;
202
- progress.log(` element is not displayed, retrying in ${timeout}ms`);
203
- await new Promise(f => setTimeout(f, timeout));
204
- }
205
- continue;
206
- }
207
- assertDone(result);
208
- return;
209
- }
180
+ const result = await this._retryAction(progress, 'scroll into view', async () => {
181
+ progress.log(` waiting for element to be stable`);
182
+ const waitResult = await this.evaluateInUtility(async ([injected, node, {
183
+ waitForVisible
184
+ }]) => {
185
+ return await injected.checkElementStates(node, waitForVisible ? ['visible', 'stable'] : ['stable']);
186
+ }, {
187
+ waitForVisible
188
+ });
189
+ if (waitResult) return waitResult;
190
+ return await this._scrollRectIntoViewIfNeeded();
191
+ }, {});
192
+ assertDone(throwRetargetableDOMError(result));
210
193
  }
211
194
  async scrollIntoViewIfNeeded(metadata, options = {}) {
212
195
  const controller = new _progress.ProgressController(metadata, this);
@@ -261,25 +244,10 @@ class ElementHandle extends js.JSHandle {
261
244
  y: box.y + border.top + offset.y
262
245
  };
263
246
  }
264
- async _retryPointerAction(progress, actionName, waitForEnabled, action, options) {
247
+ async _retryAction(progress, actionName, action, options) {
265
248
  let retry = 0;
266
249
  // We progressively wait longer between retries, up to 500ms.
267
250
  const waitTime = [0, 20, 100, 100, 500];
268
-
269
- // By default, we scroll with protocol method to reveal the action point.
270
- // However, that might not work to scroll from under position:sticky elements
271
- // that overlay the target element. To fight this, we cycle through different
272
- // scroll alignments. This works in most scenarios.
273
- const scrollOptions = [undefined, {
274
- block: 'end',
275
- inline: 'end'
276
- }, {
277
- block: 'center',
278
- inline: 'center'
279
- }, {
280
- block: 'start',
281
- inline: 'start'
282
- }];
283
251
  while (progress.isRunning()) {
284
252
  if (retry) {
285
253
  progress.log(`retrying ${actionName} action${options.trial ? ' (trial run)' : ''}, attempt #${retry}`);
@@ -292,8 +260,8 @@ class ElementHandle extends js.JSHandle {
292
260
  } else {
293
261
  progress.log(`attempting ${actionName} action${options.trial ? ' (trial run)' : ''}`);
294
262
  }
295
- const forceScrollOptions = scrollOptions[retry % scrollOptions.length];
296
- const result = await this._performPointerAction(progress, actionName, waitForEnabled, action, forceScrollOptions, options);
263
+ if (!options.skipLocatorHandlersCheckpoint && !options.force) await this._frame._page.performLocatorHandlersCheckpoint(progress);
264
+ const result = await action(retry);
297
265
  ++retry;
298
266
  if (result === 'error:notvisible') {
299
267
  if (options.force) throw new NonRecoverableDOMError('Element is not visible');
@@ -305,14 +273,47 @@ class ElementHandle extends js.JSHandle {
305
273
  progress.log(' element is outside of the viewport');
306
274
  continue;
307
275
  }
276
+ if (result === 'error:optionsnotfound') {
277
+ progress.log(' did not find some options');
278
+ continue;
279
+ }
308
280
  if (typeof result === 'object' && 'hitTargetDescription' in result) {
309
281
  progress.log(` ${result.hitTargetDescription} intercepts pointer events`);
310
282
  continue;
311
283
  }
284
+ if (typeof result === 'object' && 'missingState' in result) {
285
+ progress.log(` element is not ${result.missingState}`);
286
+ continue;
287
+ }
312
288
  return result;
313
289
  }
314
290
  return 'done';
315
291
  }
292
+ async _retryPointerAction(progress, actionName, waitForEnabled, action, options) {
293
+ // Note: do not perform locator handlers checkpoint to avoid moving the mouse in the middle of a drag operation.
294
+ const skipLocatorHandlersCheckpoint = actionName === 'move and up';
295
+ return await this._retryAction(progress, actionName, async retry => {
296
+ // By default, we scroll with protocol method to reveal the action point.
297
+ // However, that might not work to scroll from under position:sticky elements
298
+ // that overlay the target element. To fight this, we cycle through different
299
+ // scroll alignments. This works in most scenarios.
300
+ const scrollOptions = [undefined, {
301
+ block: 'end',
302
+ inline: 'end'
303
+ }, {
304
+ block: 'center',
305
+ inline: 'center'
306
+ }, {
307
+ block: 'start',
308
+ inline: 'start'
309
+ }];
310
+ const forceScrollOptions = scrollOptions[retry % scrollOptions.length];
311
+ return await this._performPointerAction(progress, actionName, waitForEnabled, action, forceScrollOptions, options);
312
+ }, {
313
+ ...options,
314
+ skipLocatorHandlersCheckpoint
315
+ });
316
+ }
316
317
  async _performPointerAction(progress, actionName, waitForEnabled, action, forceScrollOptions, options) {
317
318
  const {
318
319
  force = false,
@@ -340,8 +341,19 @@ class ElementHandle extends js.JSHandle {
340
341
  await doScrollIntoView().catch(() => {});
341
342
  }
342
343
  if (options.__testHookBeforeStable) await options.__testHookBeforeStable();
343
- const result = await this._waitForElementStates(progress, waitForEnabled ? ['visible', 'enabled', 'stable'] : ['visible', 'stable'], force);
344
- if (result !== 'done') return result;
344
+ if (!force) {
345
+ const elementStates = waitForEnabled ? ['visible', 'enabled', 'stable'] : ['visible', 'stable'];
346
+ progress.log(` waiting for element to be ${waitForEnabled ? 'visible, enabled and stable' : 'visible and stable'}`);
347
+ const result = await this.evaluateInUtility(async ([injected, node, {
348
+ elementStates
349
+ }]) => {
350
+ return await injected.checkElementStates(node, elementStates);
351
+ }, {
352
+ elementStates
353
+ });
354
+ if (result) return result;
355
+ progress.log(` element is ${waitForEnabled ? 'visible, enabled and stable' : 'visible and stable'}`);
356
+ }
345
357
  if (options.__testHookAfterStable) await options.__testHookAfterStable();
346
358
  progress.log(' scrolling into view if needed');
347
359
  progress.throwIfAborted(); // Avoid action that has side-effects.
@@ -354,7 +366,9 @@ class ElementHandle extends js.JSHandle {
354
366
  progress.metadata.point = point;
355
367
  await progress.beforeInputAction(this);
356
368
  let hitTargetInterceptionHandle;
357
- if (!options.force) {
369
+ if (force) {
370
+ progress.log(` forcing action`);
371
+ } else {
358
372
  if (options.__testHookBeforeHitTarget) await options.__testHookBeforeHitTarget();
359
373
  const frameCheckResult = await this._checkFrameIsHitTarget(point);
360
374
  if (frameCheckResult === 'error:notconnected' || 'hitTargetDescription' in frameCheckResult) return frameCheckResult;
@@ -462,22 +476,32 @@ class ElementHandle extends js.JSHandle {
462
476
  }, this._page._timeoutSettings.timeout(options));
463
477
  }
464
478
  async _selectOption(progress, elements, values, options) {
465
- const optionsToSelect = [...elements, ...values];
466
- await progress.beforeInputAction(this);
467
- return this._page._frameManager.waitForSignalsCreatedBy(progress, options.noWaitAfter, async () => {
468
- progress.throwIfAborted(); // Avoid action that has side-effects.
469
- progress.log(' selecting specified option(s)');
470
- const result = await this.evaluatePoll(progress, ([injected, node, {
479
+ let resultingOptions = [];
480
+ await this._retryAction(progress, 'select option', async () => {
481
+ await progress.beforeInputAction(this);
482
+ if (!options.force) progress.log(` waiting for element to be visible and enabled`);
483
+ const optionsToSelect = [...elements, ...values];
484
+ const result = await this.evaluateInUtility(async ([injected, node, {
471
485
  optionsToSelect,
472
486
  force
473
487
  }]) => {
474
- return injected.waitForElementStatesAndPerformAction(node, ['visible', 'enabled'], force, injected.selectOptions.bind(injected, optionsToSelect));
488
+ if (!force) {
489
+ const checkResult = await injected.checkElementStates(node, ['visible', 'enabled']);
490
+ if (checkResult) return checkResult;
491
+ }
492
+ return injected.selectOptions(node, optionsToSelect);
475
493
  }, {
476
494
  optionsToSelect,
477
495
  force: options.force
478
496
  });
497
+ if (Array.isArray(result)) {
498
+ progress.log(' selected specified option(s)');
499
+ resultingOptions = result;
500
+ return 'done';
501
+ }
479
502
  return result;
480
- });
503
+ }, options);
504
+ return resultingOptions;
481
505
  }
482
506
  async fill(metadata, value, options = {}) {
483
507
  const controller = new _progress.ProgressController(metadata, this);
@@ -487,38 +511,51 @@ class ElementHandle extends js.JSHandle {
487
511
  }, this._page._timeoutSettings.timeout(options));
488
512
  }
489
513
  async _fill(progress, value, options) {
490
- progress.log(`elementHandle.fill("${value}")`);
491
- await progress.beforeInputAction(this);
492
- return this._page._frameManager.waitForSignalsCreatedBy(progress, options.noWaitAfter, async () => {
493
- progress.log(' waiting for element to be visible, enabled and editable');
494
- const filled = await this.evaluatePoll(progress, ([injected, node, {
495
- value,
496
- force
497
- }]) => {
498
- return injected.waitForElementStatesAndPerformAction(node, ['visible', 'enabled', 'editable'], force, injected.fill.bind(injected, value));
499
- }, {
500
- value,
501
- force: options.force
502
- });
503
- progress.throwIfAborted(); // Avoid action that has side-effects.
504
- if (filled === 'error:notconnected') return filled;
505
- progress.log(' element is visible, enabled and editable');
506
- if (filled === 'needsinput') {
514
+ progress.log(` fill("${value}")`);
515
+ return await this._retryAction(progress, 'fill', async () => {
516
+ await progress.beforeInputAction(this);
517
+ return this._page._frameManager.waitForSignalsCreatedBy(progress, options.noWaitAfter, async () => {
518
+ if (!options.force) progress.log(' waiting for element to be visible, enabled and editable');
519
+ const result = await this.evaluateInUtility(async ([injected, node, {
520
+ value,
521
+ force
522
+ }]) => {
523
+ if (!force) {
524
+ const checkResult = await injected.checkElementStates(node, ['visible', 'enabled', 'editable']);
525
+ if (checkResult) return checkResult;
526
+ }
527
+ return injected.fill(node, value);
528
+ }, {
529
+ value,
530
+ force: options.force
531
+ });
507
532
  progress.throwIfAborted(); // Avoid action that has side-effects.
508
- if (value) await this._page.keyboard.insertText(value);else await this._page.keyboard.press('Delete');
509
- } else {
510
- assertDone(filled);
511
- }
512
- return 'done';
513
- }, 'input');
533
+ if (result === 'needsinput') {
534
+ if (value) await this._page.keyboard.insertText(value);else await this._page.keyboard.press('Delete');
535
+ return 'done';
536
+ } else {
537
+ return result;
538
+ }
539
+ }, 'input');
540
+ }, options);
514
541
  }
515
542
  async selectText(metadata, options = {}) {
516
543
  const controller = new _progress.ProgressController(metadata, this);
517
544
  return controller.run(async progress => {
518
- progress.throwIfAborted(); // Avoid action that has side-effects.
519
- const result = await this.evaluatePoll(progress, ([injected, node, force]) => {
520
- return injected.waitForElementStatesAndPerformAction(node, ['visible'], force, injected.selectText.bind(injected));
521
- }, options.force);
545
+ const result = await this._retryAction(progress, 'selectText', async () => {
546
+ if (!options.force) progress.log(' waiting for element to be visible');
547
+ return await this.evaluateInUtility(async ([injected, node, {
548
+ force
549
+ }]) => {
550
+ if (!force) {
551
+ const checkResult = await injected.checkElementStates(node, ['visible']);
552
+ if (checkResult) return checkResult;
553
+ }
554
+ return injected.selectText(node);
555
+ }, {
556
+ force: options.force
557
+ });
558
+ }, options);
522
559
  assertDone(throwRetargetableDOMError(result));
523
560
  }, this._page._timeoutSettings.timeout(options));
524
561
  }
@@ -669,10 +706,12 @@ class ElementHandle extends js.JSHandle {
669
706
  async waitForElementState(metadata, state, options = {}) {
670
707
  const controller = new _progress.ProgressController(metadata, this);
671
708
  return controller.run(async progress => {
672
- progress.log(` waiting for element to be ${state}`);
673
- const result = await this.evaluatePoll(progress, ([injected, node, state]) => {
674
- return injected.waitForElementStatesAndPerformAction(node, [state], false, () => 'done');
675
- }, state);
709
+ const actionName = `wait for ${state}`;
710
+ const result = await this._retryAction(progress, actionName, async () => {
711
+ return await this.evaluateInUtility(async ([injected, node, state]) => {
712
+ return (await injected.checkElementStates(node, [state])) || 'done';
713
+ }, state);
714
+ }, {});
676
715
  assertDone(throwRetargetableDOMError(result));
677
716
  }, this._page._timeoutSettings.timeout(options));
678
717
  }
@@ -687,22 +726,6 @@ class ElementHandle extends js.JSHandle {
687
726
  }
688
727
  return this;
689
728
  }
690
- async _waitForElementStates(progress, states, force) {
691
- const title = joinWithAnd(states);
692
- progress.log(` waiting for element to be ${title}`);
693
- const result = await this.evaluatePoll(progress, ([injected, node, {
694
- states,
695
- force
696
- }]) => {
697
- return injected.waitForElementStatesAndPerformAction(node, states, force, () => 'done');
698
- }, {
699
- states,
700
- force
701
- });
702
- if (result === 'error:notconnected') return result;
703
- progress.log(` element is ${title}`);
704
- return result;
705
- }
706
729
  async _checkFrameIsHitTarget(point) {
707
730
  let frame = this._frame;
708
731
  const data = [];
@@ -751,63 +774,7 @@ class ElementHandle extends js.JSHandle {
751
774
  };
752
775
  }
753
776
  }
754
-
755
- // Handles an InjectedScriptPoll running in injected script:
756
- // - streams logs into progress;
757
- // - cancels the poll when progress cancels.
758
777
  exports.ElementHandle = ElementHandle;
759
- class InjectedScriptPollHandler {
760
- constructor(progress, poll) {
761
- this._progress = void 0;
762
- this._poll = void 0;
763
- this._progress = progress;
764
- this._poll = poll;
765
- // Ensure we cancel the poll before progress aborts and returns:
766
- // - no unnecessary work in the page;
767
- // - no possible side effects after progress promise rejects.
768
- this._progress.cleanupWhenAborted(() => this.cancel());
769
- this._streamLogs();
770
- }
771
- async _streamLogs() {
772
- while (this._poll && this._progress.isRunning()) {
773
- const log = await this._poll.evaluate(poll => poll.takeNextLogs()).catch(e => []);
774
- if (!this._poll || !this._progress.isRunning()) return;
775
- for (const entry of log) this._progress.logEntry(entry);
776
- }
777
- }
778
- async finishHandle() {
779
- try {
780
- const result = await this._poll.evaluateHandle(poll => poll.run());
781
- await this._finishInternal();
782
- return result;
783
- } finally {
784
- await this.cancel();
785
- }
786
- }
787
- async finish() {
788
- try {
789
- const result = await this._poll.evaluate(poll => poll.run());
790
- await this._finishInternal();
791
- return result;
792
- } finally {
793
- await this.cancel();
794
- }
795
- }
796
- async _finishInternal() {
797
- if (!this._poll) return;
798
- // Retrieve all the logs before continuing.
799
- const log = await this._poll.evaluate(poll => poll.takeLastLogs()).catch(e => []);
800
- for (const entry of log) this._progress.logEntry(entry);
801
- }
802
- async cancel() {
803
- if (!this._poll) return;
804
- const copy = this._poll;
805
- this._poll = null;
806
- await copy.evaluate(p => p.cancel()).catch(e => {});
807
- copy.dispose();
808
- }
809
- }
810
- exports.InjectedScriptPollHandler = InjectedScriptPollHandler;
811
778
  function throwRetargetableDOMError(result) {
812
779
  if (result === 'error:notconnected') throw new Error('Element is not attached to the DOM');
813
780
  return result;
@@ -838,8 +805,4 @@ function compensateHalfIntegerRoundingError(point) {
838
805
  const remainderY = point.y - Math.floor(point.y);
839
806
  if (remainderY > 0.49 && remainderY < 0.51) point.y -= 0.02;
840
807
  }
841
- function joinWithAnd(strings) {
842
- if (strings.length <= 1) return strings.join('');
843
- return strings.slice(0, strings.length - 1).join(', ') + ' and ' + strings[strings.length - 1];
844
- }
845
808
  const kUnableToAdoptErrorMessage = exports.kUnableToAdoptErrorMessage = 'Unable to adopt element handle from a different document';
@@ -20,8 +20,10 @@ var _progress = require("../progress");
20
20
  var _helper = require("../helper");
21
21
  var _eventsHelper = require("../../utils/eventsHelper");
22
22
  var readline = _interopRequireWildcard(require("readline"));
23
- var _debugLogger = require("../../common/debugLogger");
23
+ var _debugLogger = require("../../utils/debugLogger");
24
24
  var _instrumentation = require("../instrumentation");
25
+ var _crProtocolHelper = require("../chromium/crProtocolHelper");
26
+ var _console = require("../console");
25
27
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
26
28
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
27
29
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -54,10 +56,6 @@ class ElectronApplication extends _instrumentation.SdkObject {
54
56
  this._process = void 0;
55
57
  this._process = process;
56
58
  this._browserContext = browser._defaultContext;
57
- this._browserContext.on(_browserContext.BrowserContext.Events.Close, () => {
58
- // Emit application closed after context closed.
59
- Promise.resolve().then(() => this.emit(ElectronApplication.Events.Close));
60
- });
61
59
  this._nodeConnection = nodeConnection;
62
60
  this._nodeSession = nodeConnection.rootSession;
63
61
  this._nodeSession.on('Runtime.executionContextCreated', async event => {
@@ -74,14 +72,40 @@ class ElectronApplication extends _instrumentation.SdkObject {
74
72
  });
75
73
  this._nodeElectronHandlePromise.resolve(new js.JSHandle(this._nodeExecutionContext, 'object', 'ElectronModule', remoteObject.objectId));
76
74
  });
75
+ this._nodeSession.on('Runtime.consoleAPICalled', event => this._onConsoleAPI(event));
76
+ const appClosePromise = new Promise(f => this.once(ElectronApplication.Events.Close, f));
77
77
  this._browserContext.setCustomCloseHandler(async () => {
78
78
  await this._browserContext.stopVideoRecording();
79
79
  const electronHandle = await this._nodeElectronHandlePromise;
80
80
  await electronHandle.evaluate(({
81
81
  app
82
82
  }) => app.quit()).catch(() => {});
83
+ this._nodeConnection.close();
84
+ await appClosePromise;
83
85
  });
84
86
  }
87
+ async _onConsoleAPI(event) {
88
+ if (event.executionContextId === 0) {
89
+ // DevTools protocol stores the last 1000 console messages. These
90
+ // messages are always reported even for removed execution contexts. In
91
+ // this case, they are marked with executionContextId = 0 and are
92
+ // reported upon enabling Runtime agent.
93
+ //
94
+ // Ignore these messages since:
95
+ // - there's no execution context we can use to operate with message
96
+ // arguments
97
+ // - these messages are reported before Playwright clients can subscribe
98
+ // to the 'console'
99
+ // page event.
100
+ //
101
+ // @see https://github.com/GoogleChrome/puppeteer/issues/3865
102
+ return;
103
+ }
104
+ if (!this._nodeExecutionContext) return;
105
+ const args = event.args.map(arg => this._nodeExecutionContext.createHandle(arg));
106
+ const message = new _console.ConsoleMessage(null, event.type, undefined, args, (0, _crProtocolHelper.toConsoleMessageLocation)(event.stackTrace));
107
+ this.emit(ElectronApplication.Events.Console, message);
108
+ }
85
109
  async initialize() {
86
110
  await this._nodeSession.send('Runtime.enable', {});
87
111
  // Delay loading the app until browser is started and the browser targets are configured to auto-attach.
@@ -96,13 +120,10 @@ class ElectronApplication extends _instrumentation.SdkObject {
96
120
  return this._browserContext;
97
121
  }
98
122
  async close() {
99
- const progressController = new _progress.ProgressController((0, _instrumentation.serverSideCallMetadata)(), this);
100
- const closed = progressController.run(progress => _helper.helper.waitForEvent(progress, this, ElectronApplication.Events.Close).promise);
123
+ // This will call BrowserContext.setCustomCloseHandler.
101
124
  await this._browserContext.close({
102
125
  reason: 'Application exited'
103
126
  });
104
- this._nodeConnection.close();
105
- await closed;
106
127
  }
107
128
  async browserWindow(page) {
108
129
  // Assume CRPage as Electron is always Chromium.
@@ -119,7 +140,8 @@ class ElectronApplication extends _instrumentation.SdkObject {
119
140
  }
120
141
  exports.ElectronApplication = ElectronApplication;
121
142
  ElectronApplication.Events = {
122
- Close: 'close'
143
+ Close: 'close',
144
+ Console: 'console'
123
145
  };
124
146
  class Electron extends _instrumentation.SdkObject {
125
147
  constructor(playwright) {
@@ -133,10 +155,11 @@ class Electron extends _instrumentation.SdkObject {
133
155
  controller.setLogName('browser');
134
156
  return controller.run(async progress => {
135
157
  let app = undefined;
158
+ // --remote-debugging-port=0 must be the last playwright's argument, loader.ts relies on it.
136
159
  const electronArguments = ['--inspect=0', '--remote-debugging-port=0', ...args];
137
160
  if (_os.default.platform() === 'linux') {
138
161
  const runningAsRoot = process.geteuid && process.geteuid() === 0;
139
- if (runningAsRoot && electronArguments.indexOf('--no-sandbox') === -1) electronArguments.push('--no-sandbox');
162
+ if (runningAsRoot && electronArguments.indexOf('--no-sandbox') === -1) electronArguments.unshift('--no-sandbox');
140
163
  }
141
164
  const artifactsDir = await _fs.default.promises.mkdtemp(ARTIFACTS_FOLDER);
142
165
  const browserLogsCollector = new _debugLogger.RecentLogsCollector();
@@ -183,7 +206,10 @@ class Electron extends _instrumentation.SdkObject {
183
206
  handleSIGINT: true,
184
207
  handleSIGTERM: true,
185
208
  handleSIGHUP: true,
186
- onExit: () => {}
209
+ onExit: () => {
210
+ var _app;
211
+ return (_app = app) === null || _app === void 0 ? void 0 : _app.emit(ElectronApplication.Events.Close);
212
+ }
187
213
  });
188
214
  const waitForXserverError = new Promise(async (resolve, reject) => {
189
215
  waitForLine(progress, launchedProcess, /Unable to open X display/).then(() => reject(new Error(['Unable to open X display!', `================================`, 'Most likely this is because there is no X server available.', "Use 'xvfb-run' on Linux to launch your tests with an emulated display server.", "For example: 'xvfb-run npm run test:e2e'", `================================`, progress.metadata.log].join('\n')))).catch(() => {});
@@ -23,8 +23,10 @@ const {
23
23
  chromiumSwitches
24
24
  } = require('../chromium/chromiumSwitches');
25
25
 
26
- // [Electron, -r, loader.js, --inspect=0, --remote-debugging-port=0, ...args]
27
- process.argv.splice(1, 4);
26
+ // Always pass user arguments first, see https://github.com/microsoft/playwright/issues/16614 and
27
+ // https://github.com/microsoft/playwright/issues/29198.
28
+ // [Electron, -r, loader.js[, --no-sandbox>], --inspect=0, --remote-debugging-port=0, ...args]
29
+ process.argv.splice(1, process.argv.indexOf('--remote-debugging-port=0'));
28
30
  for (const arg of chromiumSwitches) {
29
31
  const match = arg.match(/--([^=]*)=?(.*)/);
30
32
  app.commandLine.appendSwitch(match[1], match[2]);
@@ -149,6 +149,7 @@ class APIRequestContext extends _instrumentation.SdkObject {
149
149
  queryParams: (0, _fetch.parseQueryParameters)(fetchResponse.url),
150
150
  url: params.tokenizedURL || fetchResponse.url,
151
151
  timings: (0, _fetch.getTimings)(fetchResponse.timings),
152
+ requestBody: (0, _fetch.getRequestBody)(postData, params.multipartData, options),
152
153
  body: (0, _fetch.getBody)(fetchResponse.body),
153
154
  method: options.method
154
155
  };
@@ -200,7 +200,7 @@ class FFAXNode {
200
200
  if (!(numericalProperty in this._payload)) continue;
201
201
  node[numericalProperty] = this._payload[numericalProperty];
202
202
  }
203
- const tokenProperties = ['autocomplete', 'haspopup', 'invalid', 'orientation'];
203
+ const tokenProperties = ['autocomplete', 'haspopup', 'orientation'];
204
204
  for (const tokenProperty of tokenProperties) {
205
205
  const value = this._payload[tokenProperty];
206
206
  if (!value || value === 'false') continue;
@@ -210,6 +210,7 @@ class FFAXNode {
210
210
  axNode.valueString = this._payload.value;
211
211
  if ('checked' in this._payload) axNode.checked = this._payload.checked === true ? 'checked' : this._payload.checked === 'mixed' ? 'mixed' : 'unchecked';
212
212
  if ('pressed' in this._payload) axNode.pressed = this._payload.pressed === true ? 'pressed' : 'released';
213
+ if ('invalid' in this._payload) axNode.invalid = this._payload.invalid === true ? 'true' : 'false';
213
214
  return axNode;
214
215
  }
215
216
  }
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.kBrowserCloseMessageId = exports.FFSession = exports.FFConnection = exports.ConnectionEvents = void 0;
7
7
  var _events = require("events");
8
- var _debugLogger = require("../../common/debugLogger");
8
+ var _debugLogger = require("../../utils/debugLogger");
9
9
  var _helper = require("../helper");
10
10
  var _protocolError = require("../protocolError");
11
11
  /**
@@ -14,7 +14,7 @@ var _ffExecutionContext = require("./ffExecutionContext");
14
14
  var _ffInput = require("./ffInput");
15
15
  var _ffNetworkManager = require("./ffNetworkManager");
16
16
  var _stackTrace = require("../../utils/stackTrace");
17
- var _debugLogger = require("../../common/debugLogger");
17
+ var _debugLogger = require("../../utils/debugLogger");
18
18
  var _manualPromise = require("../../utils/manualPromise");
19
19
  var _browserContext = require("../browserContext");
20
20
  var _errors = require("../errors");