@checkly/playwright-core 1.42.17 → 1.47.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 (246) hide show
  1. package/ThirdPartyNotices.txt +144 -109
  2. package/browsers.json +15 -25
  3. package/lib/androidServerImpl.js +1 -1
  4. package/lib/browserServerImpl.js +1 -1
  5. package/lib/cli/driver.js +1 -3
  6. package/lib/cli/program.js +5 -10
  7. package/lib/client/android.js +1 -1
  8. package/lib/client/api.js +7 -0
  9. package/lib/client/browserContext.js +37 -5
  10. package/lib/client/browserType.js +19 -11
  11. package/lib/client/channelOwner.js +19 -16
  12. package/lib/client/clientInstrumentation.js +17 -7
  13. package/lib/client/clock.js +68 -0
  14. package/lib/client/connection.js +9 -6
  15. package/lib/client/electron.js +7 -5
  16. package/lib/client/elementHandle.js +44 -14
  17. package/lib/client/eventEmitter.js +314 -0
  18. package/lib/client/fetch.js +81 -28
  19. package/lib/client/frame.js +2 -4
  20. package/lib/client/jsHandle.js +7 -1
  21. package/lib/client/locator.js +9 -0
  22. package/lib/client/network.js +12 -9
  23. package/lib/client/page.js +45 -23
  24. package/lib/client/playwright.js +3 -0
  25. package/lib/client/tracing.js +7 -4
  26. package/lib/common/socksProxy.js +2 -2
  27. package/lib/generated/clockSource.js +7 -0
  28. package/lib/generated/injectedScriptSource.js +1 -1
  29. package/lib/generated/recorderSource.js +1 -1
  30. package/lib/generated/utilityScriptSource.js +1 -1
  31. package/lib/protocol/serializers.js +12 -11
  32. package/lib/protocol/validator.js +137 -55
  33. package/lib/server/bidi/bidiBrowser.js +296 -0
  34. package/lib/server/bidi/bidiConnection.js +206 -0
  35. package/lib/server/bidi/bidiExecutionContext.js +162 -0
  36. package/lib/server/bidi/bidiFirefox.js +110 -0
  37. package/lib/server/bidi/bidiInput.js +174 -0
  38. package/lib/server/bidi/bidiNetworkManager.js +304 -0
  39. package/lib/server/bidi/bidiPage.js +456 -0
  40. package/lib/server/bidi/third_party/bidiDeserializer.js +93 -0
  41. package/lib/server/bidi/third_party/bidiKeyboard.js +238 -0
  42. package/lib/server/bidi/third_party/bidiProtocol.js +139 -0
  43. package/lib/server/bidi/third_party/bidiSerializer.js +144 -0
  44. package/lib/server/browser.js +9 -1
  45. package/lib/server/browserContext.js +97 -22
  46. package/lib/server/browserType.js +27 -20
  47. package/lib/server/chromium/chromium.js +30 -15
  48. package/lib/server/chromium/chromiumSwitches.js +6 -3
  49. package/lib/server/chromium/crBrowser.js +11 -17
  50. package/lib/server/chromium/crConnection.js +2 -2
  51. package/lib/server/chromium/crDragDrop.js +28 -29
  52. package/lib/server/chromium/crNetworkManager.js +130 -84
  53. package/lib/server/chromium/crPage.js +34 -79
  54. package/lib/server/chromium/crProtocolHelper.js +3 -1
  55. package/lib/server/chromium/crServiceWorker.js +20 -23
  56. package/lib/server/chromium/videoRecorder.js +1 -1
  57. package/lib/server/clock.js +125 -0
  58. package/lib/server/codegen/csharp.js +299 -0
  59. package/lib/server/codegen/java.js +235 -0
  60. package/lib/server/codegen/javascript.js +223 -0
  61. package/lib/server/codegen/jsonl.js +47 -0
  62. package/lib/server/codegen/language.js +76 -0
  63. package/lib/server/codegen/languages.js +30 -0
  64. package/lib/server/codegen/python.js +265 -0
  65. package/lib/server/codegen/types.js +5 -0
  66. package/lib/server/debugController.js +3 -5
  67. package/lib/server/deviceDescriptors.js +9 -4
  68. package/lib/server/deviceDescriptorsSource.json +239 -119
  69. package/lib/server/dispatchers/androidDispatcher.js +1 -1
  70. package/lib/server/dispatchers/browserContextDispatcher.js +51 -7
  71. package/lib/server/dispatchers/dispatcher.js +36 -40
  72. package/lib/server/dispatchers/frameDispatcher.js +1 -2
  73. package/lib/server/dispatchers/jsHandleDispatcher.js +1 -1
  74. package/lib/server/dispatchers/jsonPipeDispatcher.js +4 -6
  75. package/lib/server/dispatchers/localUtilsDispatcher.js +19 -5
  76. package/lib/server/dispatchers/networkDispatchers.js +2 -2
  77. package/lib/server/dispatchers/pageDispatcher.js +5 -2
  78. package/lib/server/dispatchers/playwrightDispatcher.js +1 -0
  79. package/lib/server/dispatchers/writableStreamDispatcher.js +8 -5
  80. package/lib/server/dom.js +90 -53
  81. package/lib/server/electron/electron.js +21 -4
  82. package/lib/server/fetch.js +74 -25
  83. package/lib/server/fileUploadUtils.js +7 -3
  84. package/lib/server/firefox/ffBrowser.js +36 -25
  85. package/lib/server/firefox/ffConnection.js +2 -2
  86. package/lib/server/firefox/ffNetworkManager.js +6 -4
  87. package/lib/server/firefox/ffPage.js +22 -24
  88. package/lib/server/firefox/firefox.js +25 -6
  89. package/lib/server/frameSelectors.js +2 -2
  90. package/lib/server/frames.js +205 -159
  91. package/lib/server/har/harTracer.js +4 -12
  92. package/lib/server/helper.js +3 -3
  93. package/lib/server/index.js +18 -0
  94. package/lib/server/input.js +18 -8
  95. package/lib/server/instrumentation.js +0 -4
  96. package/lib/server/isomorphic/utilityScriptSerializers.js +19 -5
  97. package/lib/server/javascript.js +3 -2
  98. package/lib/server/launchApp.js +3 -2
  99. package/lib/server/network.js +14 -4
  100. package/lib/server/page.js +75 -46
  101. package/lib/server/playwright.js +5 -2
  102. package/lib/server/recorder/codeGenerator.js +2 -1
  103. package/lib/server/recorder/contextRecorder.js +316 -0
  104. package/lib/server/recorder/csharp.js +2 -1
  105. package/lib/server/recorder/java.js +2 -1
  106. package/lib/server/recorder/javascript.js +2 -1
  107. package/lib/server/recorder/jsonl.js +2 -1
  108. package/lib/server/recorder/language.js +2 -1
  109. package/lib/server/recorder/python.js +2 -1
  110. package/lib/server/recorder/recorderApp.js +14 -5
  111. package/lib/server/recorder/recorderCollection.js +127 -0
  112. package/lib/server/recorder/recorderRunner.js +177 -0
  113. package/lib/server/recorder/recorderUtils.js +23 -0
  114. package/lib/server/recorder/throttledFile.js +46 -0
  115. package/lib/server/recorder/utils.js +2 -1
  116. package/lib/server/recorder.js +42 -418
  117. package/lib/server/registry/index.js +99 -100
  118. package/lib/server/registry/nativeDeps.js +107 -0
  119. package/lib/server/screenshotter.js +6 -12
  120. package/lib/server/socksClientCertificatesInterceptor.js +328 -0
  121. package/lib/server/trace/recorder/snapshotter.js +4 -1
  122. package/lib/server/trace/recorder/tracing.js +27 -96
  123. package/lib/server/trace/viewer/traceViewer.js +54 -67
  124. package/lib/server/transport.js +1 -1
  125. package/lib/server/webkit/webkit.js +5 -5
  126. package/lib/server/webkit/wkBrowser.js +14 -14
  127. package/lib/server/webkit/wkConnection.js +3 -3
  128. package/lib/server/webkit/wkInterceptableRequest.js +8 -4
  129. package/lib/server/webkit/wkPage.js +52 -34
  130. package/lib/server/webkit/wkProvisionalPage.js +36 -1
  131. package/lib/utils/crypto.js +141 -0
  132. package/lib/utils/debugLogger.js +2 -0
  133. package/lib/utils/env.js +4 -2
  134. package/lib/utils/expectUtils.js +33 -0
  135. package/lib/utils/fileUtils.js +140 -1
  136. package/lib/utils/glob.js +2 -1
  137. package/lib/utils/happy-eyeballs.js +29 -2
  138. package/lib/utils/hostPlatform.js +13 -4
  139. package/lib/utils/httpServer.js +54 -13
  140. package/lib/utils/index.js +53 -31
  141. package/lib/utils/isomorphic/cssTokenizer.js +1 -1
  142. package/lib/utils/isomorphic/locatorParser.js +1 -1
  143. package/lib/utils/isomorphic/mimeType.js +29 -0
  144. package/lib/utils/isomorphic/stringUtils.js +28 -1
  145. package/lib/utils/isomorphic/urlMatch.js +120 -0
  146. package/lib/utils/mimeType.js +2 -1
  147. package/lib/utils/network.js +7 -35
  148. package/lib/utils/stackTrace.js +2 -4
  149. package/lib/utils/timeoutRunner.js +11 -76
  150. package/lib/utils/zones.js +23 -60
  151. package/lib/utilsBundle.js +2 -1
  152. package/lib/utilsBundleImpl/index.js +33 -31
  153. package/lib/vite/htmlReport/index.html +12 -12
  154. package/lib/vite/recorder/assets/codeMirrorModule-BN0yUF4I.js +24 -0
  155. package/lib/vite/recorder/assets/{codicon-zGuYmc9o.ttf → codicon-DCmgc-ay.ttf} +0 -0
  156. package/lib/vite/recorder/assets/index-B-MT5gKo.css +1 -0
  157. package/lib/vite/recorder/assets/index-DVt3E1Ef.js +47 -0
  158. package/lib/vite/recorder/index.html +2 -2
  159. package/lib/vite/traceViewer/assets/codeMirrorModule-5yiV-3wl.js +16831 -0
  160. package/lib/vite/traceViewer/assets/codeMirrorModule-B7Z3vq11.js +24 -0
  161. package/lib/vite/traceViewer/assets/codeMirrorModule-C6p3E9Zg.js +24 -0
  162. package/lib/vite/traceViewer/assets/codeMirrorModule-CcviAl53.js +16831 -0
  163. package/lib/vite/traceViewer/assets/codeMirrorModule-CqYUz5ms.js +24 -0
  164. package/lib/vite/traceViewer/assets/codeMirrorModule-DS3v0XrQ.js +24 -0
  165. package/lib/vite/traceViewer/assets/codeMirrorModule-Dx6AXgMV.js +16838 -0
  166. package/lib/vite/traceViewer/assets/codeMirrorModule-T_sdMrbM.js +24 -0
  167. package/lib/vite/traceViewer/assets/codeMirrorModule-V7N6ppkd.js +15585 -0
  168. package/lib/vite/traceViewer/assets/testServerConnection-D-tXL3sj.js +224 -0
  169. package/lib/vite/traceViewer/assets/testServerConnection-DeE2kSzz.js +1 -0
  170. package/lib/vite/traceViewer/assets/workbench-Bjkiwcr1.js +19119 -0
  171. package/lib/vite/traceViewer/assets/workbench-C43LWZEX.js +72 -0
  172. package/lib/vite/traceViewer/assets/workbench-C5OQh9VX.js +19119 -0
  173. package/lib/vite/traceViewer/assets/workbench-Crj6jzdv.js +19119 -0
  174. package/lib/vite/traceViewer/assets/workbench-DrQjKdyE.js +72 -0
  175. package/lib/vite/traceViewer/assets/workbench-Pa1v1Ojh.js +72 -0
  176. package/lib/vite/traceViewer/assets/workbench-caTaZnzx.js +72 -0
  177. package/lib/vite/traceViewer/assets/workbench-u2lRPMOT.js +72 -0
  178. package/lib/vite/traceViewer/assets/wsPort-EUvw-dwH.js +18540 -0
  179. package/lib/vite/traceViewer/assets/xtermModule-CZ7sDYXB.js +6529 -0
  180. package/lib/vite/traceViewer/assets/xtermModule-_6TC5FYT.js +6529 -0
  181. package/lib/vite/traceViewer/codeMirrorModule.Cy8X9Wtw.css +344 -0
  182. package/lib/vite/traceViewer/codeMirrorModule.svF_VrcJ.css +344 -0
  183. package/lib/vite/traceViewer/codicon.DCmgc-ay.ttf +0 -0
  184. package/lib/vite/traceViewer/embedded.BBZ9gQEw.js +104 -0
  185. package/lib/vite/traceViewer/embedded.BQq6Psnz.js +104 -0
  186. package/lib/vite/traceViewer/embedded.BVDVQOzc.js +2 -0
  187. package/lib/vite/traceViewer/embedded.Bn8Ptzv6.js +2 -0
  188. package/lib/vite/traceViewer/embedded.CvhnUgIi.js +2 -0
  189. package/lib/vite/traceViewer/embedded.D27cnKiB.js +104 -0
  190. package/lib/vite/traceViewer/embedded.DPqrDeET.js +2 -0
  191. package/lib/vite/traceViewer/embedded.DbzY7Q8w.js +2 -0
  192. package/lib/vite/traceViewer/embedded.DjZq4InJ.css +68 -0
  193. package/lib/vite/traceViewer/embedded.html +16 -0
  194. package/lib/vite/traceViewer/embedded.w7WN2u1R.css +1 -0
  195. package/lib/vite/traceViewer/index.5mge2rY_.css +124 -0
  196. package/lib/vite/traceViewer/index.6KJ-JQ0L.js +180 -0
  197. package/lib/vite/traceViewer/index.B8dgQwuN.js +2 -0
  198. package/lib/vite/traceViewer/index.BGj8jY3H.js +2 -0
  199. package/lib/vite/traceViewer/index.BSak5QT9.js +2 -0
  200. package/lib/vite/traceViewer/index.C0EgJ4oW.js +195 -0
  201. package/lib/vite/traceViewer/index.CUpI-BFe.js +195 -0
  202. package/lib/vite/traceViewer/{index.-g_5lMbJ.css → index.CrbWWHbf.css} +1 -1
  203. package/lib/vite/traceViewer/index.DkRbtWVo.js +195 -0
  204. package/lib/vite/traceViewer/index.QanXxRUb.css +131 -0
  205. package/lib/vite/traceViewer/index._cX8k4co.js +2 -0
  206. package/lib/vite/traceViewer/index.html +5 -4
  207. package/lib/vite/traceViewer/index.pMAN88y-.js +2 -0
  208. package/lib/vite/traceViewer/snapshot.html +1 -1
  209. package/lib/vite/traceViewer/sw.bundle.js +3 -4
  210. package/lib/vite/traceViewer/uiMode.D-tg1Oci.js +1730 -0
  211. package/lib/vite/traceViewer/uiMode.D3cNFP6u.css +1 -0
  212. package/lib/vite/traceViewer/uiMode.DKjMBMlc.js +1730 -0
  213. package/lib/vite/traceViewer/uiMode.DVWUEIHq.css +1424 -0
  214. package/lib/vite/traceViewer/uiMode.DVrL7a1K.js +10 -0
  215. package/lib/vite/traceViewer/uiMode.Dg9oJCQU.js +10 -0
  216. package/lib/vite/traceViewer/uiMode.DwZAzstF.js +10 -0
  217. package/lib/vite/traceViewer/uiMode.O07awP3T.js +10 -0
  218. package/lib/vite/traceViewer/uiMode.gGHHTsyL.js +1730 -0
  219. package/lib/vite/traceViewer/uiMode.html +5 -4
  220. package/lib/vite/traceViewer/uiMode.iq7CyYy7.js +1490 -0
  221. package/lib/vite/traceViewer/uiMode.jY2s-9ps.js +10 -0
  222. package/lib/vite/traceViewer/uiMode.xvJHbkzl.css +1324 -0
  223. package/lib/vite/traceViewer/workbench.B3X2QtYa.css +3702 -0
  224. package/lib/vite/traceViewer/workbench.DjbIuxix.css +1 -0
  225. package/lib/vite/traceViewer/workbench.DyTpxWVb.css +1 -0
  226. package/lib/vite/traceViewer/workbench.wuxQoE2z.css +3703 -0
  227. package/lib/vite/traceViewer/wsPort.p5jUwABW.css +3450 -0
  228. package/lib/vite/traceViewer/xtermModule.4oRVGWQ-.css +209 -0
  229. package/lib/vite/traceViewer/xtermModule.OKEVRlkP.css +209 -0
  230. package/package.json +2 -2
  231. package/types/protocol.d.ts +960 -78
  232. package/types/structs.d.ts +1 -1
  233. package/types/types.d.ts +3083 -2448
  234. package/lib/vite/recorder/assets/codeMirrorModule-I9ks4y7D.js +0 -24
  235. package/lib/vite/recorder/assets/index-ljsTwXtJ.css +0 -1
  236. package/lib/vite/recorder/assets/index-yg8ypzl6.js +0 -47
  237. package/lib/vite/traceViewer/assets/codeMirrorModule-0bpaqixv.js +0 -24
  238. package/lib/vite/traceViewer/assets/wsPort-_JBDEilC.js +0 -69
  239. package/lib/vite/traceViewer/index.u51inEcm.js +0 -2
  240. package/lib/vite/traceViewer/uiMode.Fb0bNA4H.js +0 -10
  241. package/lib/vite/traceViewer/uiMode.pWy0Re7G.css +0 -1
  242. package/lib/vite/traceViewer/wsPort.zR1WIy9-.css +0 -1
  243. /package/lib/vite/recorder/assets/{codeMirrorModule-Hs9-1ZG4.css → codeMirrorModule-ez37Vkbh.css} +0 -0
  244. /package/lib/vite/traceViewer/assets/{xtermModule-Yt6xwiJ_.js → xtermModule-BeNbaIVa.js} +0 -0
  245. /package/lib/vite/traceViewer/{codeMirrorModule.Hs9-1ZG4.css → codeMirrorModule.ez37Vkbh.css} +0 -0
  246. /package/lib/vite/traceViewer/{xtermModule.0lwXJFHT.css → xtermModule.DSXBckUd.css} +0 -0
package/lib/server/dom.js CHANGED
@@ -8,6 +8,7 @@ exports.assertDone = assertDone;
8
8
  exports.isNonRecoverableDOMError = isNonRecoverableDOMError;
9
9
  exports.kUnableToAdoptErrorMessage = void 0;
10
10
  exports.throwRetargetableDOMError = throwRetargetableDOMError;
11
+ var _fs = _interopRequireDefault(require("fs"));
11
12
  var injectedScriptSource = _interopRequireWildcard(require("../generated/injectedScriptSource"));
12
13
  var _protocolError = require("./protocolError");
13
14
  var js = _interopRequireWildcard(require("./javascript"));
@@ -16,6 +17,7 @@ var _utils = require("../utils");
16
17
  var _fileUploadUtils = require("./fileUploadUtils");
17
18
  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); }
18
19
  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; }
20
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
21
  /**
20
22
  * Copyright (c) Microsoft Corporation.
21
23
  *
@@ -217,6 +219,7 @@ class ElementHandle extends js.JSHandle {
217
219
  width: innerWidth,
218
220
  height: innerHeight
219
221
  })))]);
222
+ if (quads === 'error:notconnected') return quads;
220
223
  if (!quads || !quads.length) return 'error:notvisible';
221
224
 
222
225
  // Allow 1x1 elements. Compensate for rounding errors by comparing with 0.99 instead.
@@ -399,20 +402,22 @@ class ElementHandle extends js.JSHandle {
399
402
  hitTargetInterceptionHandle.dispose();
400
403
  });
401
404
  }
402
- const actionResult = await this._page._frameManager.waitForSignalsCreatedBy(progress, options.noWaitAfter, async () => {
405
+ const actionResult = await this._page._frameManager.waitForSignalsCreatedBy(progress, options.waitAfter === true, async () => {
403
406
  if (options.__testHookBeforePointerAction) await options.__testHookBeforePointerAction();
404
407
  progress.throwIfAborted(); // Avoid action that has side-effects.
405
408
  let restoreModifiers;
406
- if (options && options.modifiers) restoreModifiers = await this._page.keyboard._ensureModifiers(options.modifiers);
409
+ if (options && options.modifiers) restoreModifiers = await this._page.keyboard.ensureModifiers(options.modifiers);
407
410
  progress.log(` performing ${actionName} action`);
408
411
  await action(point);
409
- if (restoreModifiers) await this._page.keyboard._ensureModifiers(restoreModifiers);
412
+ if (restoreModifiers) await this._page.keyboard.ensureModifiers(restoreModifiers);
410
413
  if (hitTargetInterceptionHandle) {
411
- const stopHitTargetInterception = hitTargetInterceptionHandle.evaluate(h => h.stop()).catch(e => 'done').finally(() => {
414
+ const stopHitTargetInterception = this._frame.raceAgainstEvaluationStallingEvents(() => {
415
+ return hitTargetInterceptionHandle.evaluate(h => h.stop());
416
+ }).catch(e => 'done').finally(() => {
412
417
  var _hitTargetInterceptio;
413
418
  (_hitTargetInterceptio = hitTargetInterceptionHandle) === null || _hitTargetInterceptio === void 0 || _hitTargetInterceptio.dispose();
414
419
  });
415
- if (!options.noWaitAfter) {
420
+ if (options.waitAfter !== false) {
416
421
  // When noWaitAfter is passed, we do not want to accidentally stall on
417
422
  // non-committed navigation blocking the evaluate.
418
423
  const hitTargetResult = await stopHitTargetInterception;
@@ -423,7 +428,7 @@ class ElementHandle extends js.JSHandle {
423
428
  progress.log(' waiting for scheduled navigations to finish');
424
429
  if (options.__testHookAfterPointerAction) await options.__testHookAfterPointerAction();
425
430
  return 'done';
426
- }, 'input');
431
+ });
427
432
  if (actionResult !== 'done') return actionResult;
428
433
  progress.log(' navigations have finished');
429
434
  return 'done';
@@ -436,12 +441,18 @@ class ElementHandle extends js.JSHandle {
436
441
  }, this._page._timeoutSettings.timeout(options));
437
442
  }
438
443
  _hover(progress, options) {
439
- return this._retryPointerAction(progress, 'hover', false /* waitForEnabled */, point => this._page.mouse.move(point.x, point.y), options);
444
+ return this._retryPointerAction(progress, 'hover', false /* waitForEnabled */, point => this._page.mouse.move(point.x, point.y), {
445
+ ...options,
446
+ waitAfter: 'disabled'
447
+ });
440
448
  }
441
449
  async click(metadata, options = {}) {
442
450
  const controller = new _progress.ProgressController(metadata, this);
443
451
  return controller.run(async progress => {
444
- const result = await this._click(progress, options);
452
+ const result = await this._click(progress, {
453
+ ...options,
454
+ waitAfter: !options.noWaitAfter
455
+ });
445
456
  return assertDone(throwRetargetableDOMError(result));
446
457
  }, this._page._timeoutSettings.timeout(options));
447
458
  }
@@ -456,7 +467,10 @@ class ElementHandle extends js.JSHandle {
456
467
  }, this._page._timeoutSettings.timeout(options));
457
468
  }
458
469
  _dblclick(progress, options) {
459
- return this._retryPointerAction(progress, 'dblclick', true /* waitForEnabled */, point => this._page.mouse.dblclick(point.x, point.y, options), options);
470
+ return this._retryPointerAction(progress, 'dblclick', true /* waitForEnabled */, point => this._page.mouse.dblclick(point.x, point.y, options), {
471
+ ...options,
472
+ waitAfter: 'disabled'
473
+ });
460
474
  }
461
475
  async tap(metadata, options = {}) {
462
476
  const controller = new _progress.ProgressController(metadata, this);
@@ -466,7 +480,10 @@ class ElementHandle extends js.JSHandle {
466
480
  }, this._page._timeoutSettings.timeout(options));
467
481
  }
468
482
  _tap(progress, options) {
469
- return this._retryPointerAction(progress, 'tap', true /* waitForEnabled */, point => this._page.touchscreen.tap(point.x, point.y), options);
483
+ return this._retryPointerAction(progress, 'tap', true /* waitForEnabled */, point => this._page.touchscreen.tap(point.x, point.y), {
484
+ ...options,
485
+ waitAfter: 'disabled'
486
+ });
470
487
  }
471
488
  async selectOption(metadata, elements, values, options) {
472
489
  const controller = new _progress.ProgressController(metadata, this);
@@ -514,29 +531,27 @@ class ElementHandle extends js.JSHandle {
514
531
  progress.log(` fill("${value}")`);
515
532
  return await this._retryAction(progress, 'fill', async () => {
516
533
  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
- });
532
- progress.throwIfAborted(); // Avoid action that has side-effects.
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;
534
+ if (!options.force) progress.log(' waiting for element to be visible, enabled and editable');
535
+ const result = await this.evaluateInUtility(async ([injected, node, {
536
+ value,
537
+ force
538
+ }]) => {
539
+ if (!force) {
540
+ const checkResult = await injected.checkElementStates(node, ['visible', 'enabled', 'editable']);
541
+ if (checkResult) return checkResult;
538
542
  }
539
- }, 'input');
543
+ return injected.fill(node, value);
544
+ }, {
545
+ value,
546
+ force: options.force
547
+ });
548
+ progress.throwIfAborted(); // Avoid action that has side-effects.
549
+ if (result === 'needsinput') {
550
+ if (value) await this._page.keyboard.insertText(value);else await this._page.keyboard.press('Delete');
551
+ return 'done';
552
+ } else {
553
+ return result;
554
+ }
540
555
  }, options);
541
556
  }
542
557
  async selectText(metadata, options = {}) {
@@ -563,30 +578,51 @@ class ElementHandle extends js.JSHandle {
563
578
  const inputFileItems = await (0, _fileUploadUtils.prepareFilesForUpload)(this._frame, params);
564
579
  const controller = new _progress.ProgressController(metadata, this);
565
580
  return controller.run(async progress => {
566
- const result = await this._setInputFiles(progress, inputFileItems, params);
581
+ const result = await this._setInputFiles(progress, inputFileItems);
567
582
  return assertDone(throwRetargetableDOMError(result));
568
583
  }, this._page._timeoutSettings.timeout(params));
569
584
  }
570
- async _setInputFiles(progress, items, options) {
585
+ async _setInputFiles(progress, items) {
571
586
  const {
572
587
  filePayloads,
573
- localPaths
588
+ localPaths,
589
+ localDirectory
574
590
  } = items;
575
591
  const multiple = filePayloads && filePayloads.length > 1 || localPaths && localPaths.length > 1;
576
- const result = await this.evaluateHandleInUtility(([injected, node, multiple]) => {
592
+ const result = await this.evaluateHandleInUtility(([injected, node, {
593
+ multiple,
594
+ directoryUpload
595
+ }]) => {
577
596
  const element = injected.retarget(node, 'follow-label');
578
597
  if (!element) return;
579
598
  if (element.tagName !== 'INPUT') throw injected.createStacklessError('Node is not an HTMLInputElement');
580
- if (multiple && !element.multiple) throw injected.createStacklessError('Non-multiple file input can only accept single file');
581
- return element;
582
- }, multiple);
599
+ const inputElement = element;
600
+ if (multiple && !inputElement.multiple && !inputElement.webkitdirectory) throw injected.createStacklessError('Non-multiple file input can only accept single file');
601
+ if (directoryUpload && !inputElement.webkitdirectory) throw injected.createStacklessError('File input does not support directories, pass individual files instead');
602
+ if (!directoryUpload && inputElement.webkitdirectory) throw injected.createStacklessError('[webkitdirectory] input requires passing a path to a directory');
603
+ return inputElement;
604
+ }, {
605
+ multiple,
606
+ directoryUpload: !!localDirectory
607
+ });
583
608
  if (result === 'error:notconnected' || !result.asElement()) return 'error:notconnected';
584
609
  const retargeted = result.asElement();
585
610
  await progress.beforeInputAction(this);
586
- await this._page._frameManager.waitForSignalsCreatedBy(progress, options.noWaitAfter, async () => {
587
- progress.throwIfAborted(); // Avoid action that has side-effects.
588
- if (localPaths) await this._page._delegate.setInputFilePaths(progress, retargeted, localPaths);else await this._page._delegate.setInputFiles(retargeted, filePayloads);
589
- });
611
+ progress.throwIfAborted(); // Avoid action that has side-effects.
612
+ if (localPaths || localDirectory) {
613
+ const localPathsOrDirectory = localDirectory ? [localDirectory] : localPaths;
614
+ await Promise.all(localPathsOrDirectory.map(localPath => _fs.default.promises.access(localPath, _fs.default.constants.F_OK)));
615
+ // Browsers traverse the given directory asynchronously and we want to ensure all files are uploaded.
616
+ const waitForInputEvent = localDirectory ? this.evaluate(node => new Promise(fulfill => {
617
+ node.addEventListener('input', fulfill, {
618
+ once: true
619
+ });
620
+ })).catch(() => {}) : Promise.resolve();
621
+ await this._page._delegate.setInputFilePaths(retargeted, localPathsOrDirectory);
622
+ await waitForInputEvent;
623
+ } else {
624
+ await this._page._delegate.setInputFiles(retargeted, filePayloads);
625
+ }
590
626
  return 'done';
591
627
  }
592
628
  async focus(metadata) {
@@ -614,13 +650,11 @@ class ElementHandle extends js.JSHandle {
614
650
  async _type(progress, text, options) {
615
651
  progress.log(`elementHandle.type("${text}")`);
616
652
  await progress.beforeInputAction(this);
617
- return this._page._frameManager.waitForSignalsCreatedBy(progress, options.noWaitAfter, async () => {
618
- const result = await this._focus(progress, true /* resetSelectionIfNotFocused */);
619
- if (result !== 'done') return result;
620
- progress.throwIfAborted(); // Avoid action that has side-effects.
621
- await this._page.keyboard.type(text, options);
622
- return 'done';
623
- }, 'input');
653
+ const result = await this._focus(progress, true /* resetSelectionIfNotFocused */);
654
+ if (result !== 'done') return result;
655
+ progress.throwIfAborted(); // Avoid action that has side-effects.
656
+ await this._page.keyboard.type(text, options);
657
+ return 'done';
624
658
  }
625
659
  async press(metadata, key, options) {
626
660
  const controller = new _progress.ProgressController(metadata, this);
@@ -632,13 +666,13 @@ class ElementHandle extends js.JSHandle {
632
666
  async _press(progress, key, options) {
633
667
  progress.log(`elementHandle.press("${key}")`);
634
668
  await progress.beforeInputAction(this);
635
- return this._page._frameManager.waitForSignalsCreatedBy(progress, options.noWaitAfter, async () => {
669
+ return this._page._frameManager.waitForSignalsCreatedBy(progress, !options.noWaitAfter, async () => {
636
670
  const result = await this._focus(progress, true /* resetSelectionIfNotFocused */);
637
671
  if (result !== 'done') return result;
638
672
  progress.throwIfAborted(); // Avoid action that has side-effects.
639
673
  await this._page.keyboard.press(key, options);
640
674
  return 'done';
641
- }, 'input');
675
+ });
642
676
  }
643
677
  async check(metadata, options) {
644
678
  const controller = new _progress.ProgressController(metadata, this);
@@ -660,7 +694,10 @@ class ElementHandle extends js.JSHandle {
660
694
  return throwRetargetableDOMError(result);
661
695
  };
662
696
  if ((await isChecked()) === state) return 'done';
663
- const result = await this._click(progress, options);
697
+ const result = await this._click(progress, {
698
+ ...options,
699
+ waitAfter: 'disabled'
700
+ });
664
701
  if (result !== 'done') return result;
665
702
  if (options.trial) return 'done';
666
703
  if ((await isChecked()) !== state) throw new NonRecoverableDOMError('Clicking the checkbox did not change its state');
@@ -156,7 +156,7 @@ class Electron extends _instrumentation.SdkObject {
156
156
  return controller.run(async progress => {
157
157
  let app = undefined;
158
158
  // --remote-debugging-port=0 must be the last playwright's argument, loader.ts relies on it.
159
- const electronArguments = ['--inspect=0', '--remote-debugging-port=0', ...args];
159
+ let electronArguments = ['--inspect=0', '--remote-debugging-port=0', ...args];
160
160
  if (_os.default.platform() === 'linux') {
161
161
  const runningAsRoot = process.geteuid && process.geteuid() === 0;
162
162
  if (runningAsRoot && electronArguments.indexOf('--no-sandbox') === -1) electronArguments.unshift('--no-sandbox');
@@ -182,6 +182,16 @@ class Electron extends _instrumentation.SdkObject {
182
182
  // Packaged apps might have their own command line handling.
183
183
  electronArguments.unshift('-r', require.resolve('./loader'));
184
184
  }
185
+ let shell = false;
186
+ if (process.platform === 'win32') {
187
+ // On Windows in order to run .cmd files, shell: true is required.
188
+ // https://github.com/nodejs/node/issues/52554
189
+ shell = true;
190
+ // On Windows, we need to quote the executable path due to shell: true.
191
+ command = `"${command}"`;
192
+ // On Windows, we need to quote the arguments due to shell: true.
193
+ electronArguments = electronArguments.map(arg => `"${arg}"`);
194
+ }
185
195
 
186
196
  // When debugging Playwright test that runs Electron, NODE_OPTIONS
187
197
  // will make the debugger attach to Electron's Node. But Playwright
@@ -199,6 +209,7 @@ class Electron extends _instrumentation.SdkObject {
199
209
  progress.log(message);
200
210
  browserLogsCollector.log(message);
201
211
  },
212
+ shell,
202
213
  stdio: 'pipe',
203
214
  cwd: options.cwd,
204
215
  tempDirectories: [artifactsDir],
@@ -211,18 +222,24 @@ class Electron extends _instrumentation.SdkObject {
211
222
  return (_app = app) === null || _app === void 0 ? void 0 : _app.emit(ElectronApplication.Events.Close);
212
223
  }
213
224
  });
225
+
226
+ // All waitForLines must be started immediately.
227
+ // Otherwise the lines might come before we are ready.
214
228
  const waitForXserverError = new Promise(async (resolve, reject) => {
215
229
  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(() => {});
216
230
  });
217
- const nodeMatch = await waitForLine(progress, launchedProcess, /^Debugger listening on (ws:\/\/.*)$/);
231
+ const nodeMatchPromise = waitForLine(progress, launchedProcess, /^Debugger listening on (ws:\/\/.*)$/);
232
+ const chromeMatchPromise = waitForLine(progress, launchedProcess, /^DevTools listening on (ws:\/\/.*)$/);
233
+ const debuggerDisconnectPromise = waitForLine(progress, launchedProcess, /Waiting for the debugger to disconnect\.\.\./);
234
+ const nodeMatch = await nodeMatchPromise;
218
235
  const nodeTransport = await _transport.WebSocketTransport.connect(progress, nodeMatch[1]);
219
236
  const nodeConnection = new _crConnection.CRConnection(nodeTransport, _helper.helper.debugProtocolLogger(), browserLogsCollector);
220
237
 
221
238
  // Immediately release exiting process under debug.
222
- waitForLine(progress, launchedProcess, /Waiting for the debugger to disconnect\.\.\./).then(() => {
239
+ debuggerDisconnectPromise.then(() => {
223
240
  nodeTransport.close();
224
241
  }).catch(() => {});
225
- const chromeMatch = await Promise.race([waitForLine(progress, launchedProcess, /^DevTools listening on (ws:\/\/.*)$/), waitForXserverError]);
242
+ const chromeMatch = await Promise.race([chromeMatchPromise, waitForXserverError]);
226
243
  const chromeTransport = await _transport.WebSocketTransport.connect(progress, chromeMatch[1]);
227
244
  const browserProcess = {
228
245
  onclose: undefined,
@@ -4,8 +4,8 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.GlobalAPIRequestContext = exports.BrowserContextAPIRequestContext = exports.APIRequestContext = void 0;
7
- var http = _interopRequireWildcard(require("http"));
8
- var https = _interopRequireWildcard(require("https"));
7
+ var _http = _interopRequireDefault(require("http"));
8
+ var _https = _interopRequireDefault(require("https"));
9
9
  var _stream = require("stream");
10
10
  var _url = _interopRequireDefault(require("url"));
11
11
  var _zlib = _interopRequireDefault(require("zlib"));
@@ -22,10 +22,9 @@ var _instrumentation = require("./instrumentation");
22
22
  var _progress = require("./progress");
23
23
  var _tracing = require("./trace/recorder/tracing");
24
24
  var _network = require("./network");
25
+ var _socksClientCertificatesInterceptor = require("./socksClientCertificatesInterceptor");
25
26
  var _fetch = require("../checkly/fetch");
26
27
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
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); }
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; }
29
28
  /**
30
29
  * Copyright (c) Microsoft Corporation.
31
30
  *
@@ -74,7 +73,7 @@ class APIRequestContext extends _instrumentation.SdkObject {
74
73
  return uid;
75
74
  }
76
75
  async fetch(params, metadata) {
77
- var _params$method;
76
+ var _params$method, _defaults$clientCerti;
78
77
  const defaults = this._defaultOptions();
79
78
  const headers = {
80
79
  'user-agent': defaults.userAgent,
@@ -98,12 +97,17 @@ class APIRequestContext extends _instrumentation.SdkObject {
98
97
  for (const {
99
98
  name,
100
99
  value
101
- } of params.params) requestUrl.searchParams.set(name, value);
100
+ } of params.params) requestUrl.searchParams.append(name, value);
102
101
  }
102
+ const credentials = this._getHttpCredentials(requestUrl);
103
+ if ((credentials === null || credentials === void 0 ? void 0 : credentials.send) === 'always') setBasicAuthorizationHeader(headers, credentials);
103
104
  const method = ((_params$method = params.method) === null || _params$method === void 0 ? void 0 : _params$method.toUpperCase()) || 'GET';
104
105
  const proxy = defaults.proxy;
105
106
  let agent;
106
- if (proxy && proxy.server !== 'per-context' && !shouldBypassProxy(requestUrl, proxy.bypass)) {
107
+ // When `clientCertificates` is present, we set the `proxy` property to our own socks proxy
108
+ // for the browser to use. However, we don't need it here, because we already respect
109
+ // `clientCertificates` when fetching from Node.js.
110
+ if (proxy && !((_defaults$clientCerti = defaults.clientCertificates) !== null && _defaults$clientCerti !== void 0 && _defaults$clientCerti.length) && proxy.server !== 'per-context' && !shouldBypassProxy(requestUrl, proxy.bypass)) {
107
111
  var _proxyOpts$protocol;
108
112
  const proxyOpts = _url.default.parse(proxy.server);
109
113
  if ((_proxyOpts$protocol = proxyOpts.protocol) !== null && _proxyOpts$protocol !== void 0 && _proxyOpts$protocol.startsWith('socks')) {
@@ -126,21 +130,30 @@ class APIRequestContext extends _instrumentation.SdkObject {
126
130
  maxRedirects: params.maxRedirects === 0 ? -1 : params.maxRedirects === undefined ? 20 : params.maxRedirects,
127
131
  timeout,
128
132
  deadline,
133
+ ...(0, _socksClientCertificatesInterceptor.getMatchingTLSOptionsForOrigin)(this._defaultOptions().clientCertificates, requestUrl.origin),
129
134
  __testHookLookup: params.__testHookLookup,
130
135
  tokenizedURL: params.tokenizedURL,
131
136
  ...(0, _fetch.getClientCertificates)(params)
132
137
  };
133
- // rejectUnauthorized = undefined is treated as true in node 12.
138
+ // rejectUnauthorized = undefined is treated as true in Node.js 12.
134
139
  if (params.ignoreHTTPSErrors || defaults.ignoreHTTPSErrors) options.rejectUnauthorized = false;
135
140
  const postData = serializePostData(params, headers);
136
141
  if (postData) setHeader(headers, 'content-length', String(postData.byteLength));
137
142
  const controller = new _progress.ProgressController(metadata, this);
138
143
  const fetchResponse = await controller.run(progress => {
139
- return this._sendRequest(progress, requestUrl, options, postData);
144
+ return this._sendRequestWithRetries(progress, requestUrl, options, postData, params.maxRetries);
140
145
  });
141
146
  const fetchUid = this._storeResponseBody(fetchResponse.body);
142
147
  this.fetchLog.set(fetchUid, controller.metadata.log);
143
- if (params.failOnStatusCode && (fetchResponse.status < 200 || fetchResponse.status >= 400)) throw new Error(`${fetchResponse.status} ${fetchResponse.statusText}`);
148
+ if (params.failOnStatusCode && (fetchResponse.status < 200 || fetchResponse.status >= 400)) {
149
+ let responseText = '';
150
+ if (fetchResponse.body.byteLength) {
151
+ let text = fetchResponse.body.toString('utf8');
152
+ if (text.length > 1000) text = text.substring(0, 997) + '...';
153
+ responseText = `\nResponse text:\n${text}`;
154
+ }
155
+ throw new Error(`${fetchResponse.status} ${fetchResponse.statusText}${responseText}`);
156
+ }
144
157
  return {
145
158
  ...fetchResponse,
146
159
  fetchUid,
@@ -181,6 +194,25 @@ class APIRequestContext extends _instrumentation.SdkObject {
181
194
  setHeader(headers, 'cookie', valueArray.join('; '));
182
195
  }
183
196
  }
197
+ async _sendRequestWithRetries(progress, url, options, postData, maxRetries) {
198
+ var _maxRetries;
199
+ (_maxRetries = maxRetries) !== null && _maxRetries !== void 0 ? _maxRetries : maxRetries = 0;
200
+ let backoff = 250;
201
+ for (let i = 0; i <= maxRetries; i++) {
202
+ try {
203
+ return await this._sendRequest(progress, url, options, postData);
204
+ } catch (e) {
205
+ if (maxRetries === 0) throw e;
206
+ if (i === maxRetries || options.deadline && (0, _utils.monotonicTime)() + backoff > options.deadline) throw new Error(`Failed after ${i + 1} attempt(s): ${e}`);
207
+ // Retry on connection reset only.
208
+ if (e.code !== 'ECONNRESET') throw e;
209
+ progress.log(` Received ECONNRESET, will retry after ${backoff}ms.`);
210
+ await new Promise(f => setTimeout(f, backoff));
211
+ backoff *= 2;
212
+ }
213
+ }
214
+ throw new Error('Unreachable');
215
+ }
184
216
  async _sendRequest(progress, url, options, postData) {
185
217
  var _getHeader;
186
218
  await this._updateRequestCookieHeader(url, options.headers);
@@ -200,7 +232,7 @@ class APIRequestContext extends _instrumentation.SdkObject {
200
232
  };
201
233
  this.emit(APIRequestContext.Events.Request, requestEvent);
202
234
  return new Promise((fulfill, reject) => {
203
- const requestConstructor = (url.protocol === 'https:' ? https : http).request;
235
+ const requestConstructor = (url.protocol === 'https:' ? _https.default : _http.default).request;
204
236
  // If we have a proxy agent already, do not override it.
205
237
  const agent = options.agent || (url.protocol === 'https:' ? _happyEyeballs.httpsHappyEyeballsAgent : _happyEyeballs.httpHappyEyeballsAgent);
206
238
  const requestOptions = {
@@ -236,6 +268,7 @@ class APIRequestContext extends _instrumentation.SdkObject {
236
268
  }
237
269
  }
238
270
  if (redirectStatus.includes(response.statusCode) && options.maxRedirects >= 0) {
271
+ var _response$headers$loc;
239
272
  if (!options.maxRedirects) {
240
273
  reject(new Error('Max redirect count exceeded'));
241
274
  request.destroy();
@@ -265,18 +298,22 @@ class APIRequestContext extends _instrumentation.SdkObject {
265
298
  maxRedirects: options.maxRedirects - 1,
266
299
  timeout: options.timeout,
267
300
  deadline: options.deadline,
301
+ ...(0, _socksClientCertificatesInterceptor.getMatchingTLSOptionsForOrigin)(this._defaultOptions().clientCertificates, url.origin),
268
302
  __testHookLookup: options.__testHookLookup
269
303
  };
270
304
  // rejectUnauthorized = undefined is treated as true in node 12.
271
305
  if (options.rejectUnauthorized === false) redirectOptions.rejectUnauthorized = false;
272
306
 
273
307
  // HTTP-redirect fetch step 4: If locationURL is null, then return response.
274
- if (response.headers.location) {
308
+ // Best-effort UTF-8 decoding, per spec it's US-ASCII only, but browsers are more lenient.
309
+ // Node.js parses it as Latin1 via std::v8::String, so we convert it to UTF-8.
310
+ const locationHeaderValue = Buffer.from((_response$headers$loc = response.headers.location) !== null && _response$headers$loc !== void 0 ? _response$headers$loc : '', 'latin1').toString('utf8');
311
+ if (locationHeaderValue) {
275
312
  let locationURL;
276
313
  try {
277
- locationURL = new URL(response.headers.location, url);
314
+ locationURL = new URL(locationHeaderValue, url);
278
315
  } catch (error) {
279
- reject(new Error(`uri requested responds with an invalid redirect URL: ${response.headers.location}`));
316
+ reject(new Error(`uri requested responds with an invalid redirect URL: ${locationHeaderValue}`));
280
317
  request.destroy();
281
318
  return;
282
319
  }
@@ -291,12 +328,7 @@ class APIRequestContext extends _instrumentation.SdkObject {
291
328
  const auth = response.headers['www-authenticate'];
292
329
  const credentials = this._getHttpCredentials(url);
293
330
  if (auth !== null && auth !== void 0 && auth.trim().startsWith('Basic') && credentials) {
294
- const {
295
- username,
296
- password
297
- } = credentials;
298
- const encoded = Buffer.from(`${username || ''}:${password || ''}`).toString('base64');
299
- setHeader(options.headers, 'authorization', `Basic ${encoded}`);
331
+ setBasicAuthorizationHeader(options.headers, credentials);
300
332
  notifyRequestFinished();
301
333
  fulfill(this._sendRequest(progress, url, options, postData));
302
334
  request.destroy();
@@ -334,7 +366,10 @@ class APIRequestContext extends _instrumentation.SdkObject {
334
366
  finishFlush: _zlib.default.constants.Z_SYNC_FLUSH
335
367
  });
336
368
  } else if (encoding === 'br') {
337
- transform = _zlib.default.createBrotliDecompress();
369
+ transform = _zlib.default.createBrotliDecompress({
370
+ flush: _zlib.default.constants.BROTLI_OPERATION_FLUSH,
371
+ finishFlush: _zlib.default.constants.BROTLI_OPERATION_FLUSH
372
+ });
338
373
  } else if (encoding === 'deflate') {
339
374
  transform = _zlib.default.createInflate();
340
375
  }
@@ -351,8 +386,8 @@ class APIRequestContext extends _instrumentation.SdkObject {
351
386
  body.on('data', chunk => chunks.push(chunk));
352
387
  body.on('end', notifyBodyFinished);
353
388
  });
389
+ request.on('error', error => reject((0, _socksClientCertificatesInterceptor.rewriteOpenSSLErrorIfNeeded)(error)));
354
390
  (0, _fetch.addRequestListeners)(request, timings);
355
- request.on('error', reject);
356
391
  const disposeListener = () => {
357
392
  reject(new Error('Request context disposed.'));
358
393
  request.destroy();
@@ -417,7 +452,8 @@ class BrowserContextAPIRequestContext extends APIRequestContext {
417
452
  tracing() {
418
453
  return this._context.tracing;
419
454
  }
420
- async dispose() {
455
+ async dispose(options) {
456
+ this._closeReason = options.reason;
421
457
  this.fetchResponses.clear();
422
458
  }
423
459
  _defaultOptions() {
@@ -428,7 +464,8 @@ class BrowserContextAPIRequestContext extends APIRequestContext {
428
464
  proxy: this._context._options.proxy || this._context._browser.options.proxy,
429
465
  timeoutSettings: this._context._timeoutSettings,
430
466
  ignoreHTTPSErrors: this._context._options.ignoreHTTPSErrors,
431
- baseURL: this._context._options.baseURL
467
+ baseURL: this._context._options.baseURL,
468
+ clientCertificates: this._context._options.clientCertificates
432
469
  };
433
470
  }
434
471
  async _addCookies(cookies) {
@@ -457,17 +494,20 @@ class GlobalAPIRequestContext extends APIRequestContext {
457
494
  let url = proxy === null || proxy === void 0 ? void 0 : proxy.server.trim();
458
495
  if (!/^\w+:\/\//.test(url)) url = 'http://' + url;
459
496
  proxy.server = url;
497
+ if (options.clientCertificates) throw new Error('Cannot specify both proxy and clientCertificates');
460
498
  }
461
499
  if (options.storageState) {
462
500
  this._origins = options.storageState.origins;
463
501
  this._cookieStore.addCookies(options.storageState.cookies || []);
464
502
  }
503
+ (0, _browserContext.verifyClientCertificates)(options.clientCertificates);
465
504
  this._options = {
466
505
  baseURL: options.baseURL,
467
506
  userAgent: options.userAgent || (0, _userAgent.getUserAgent)(),
468
507
  extraHTTPHeaders: options.extraHTTPHeaders,
469
508
  ignoreHTTPSErrors: !!options.ignoreHTTPSErrors,
470
509
  httpCredentials: options.httpCredentials,
510
+ clientCertificates: options.clientCertificates,
471
511
  proxy,
472
512
  timeoutSettings
473
513
  };
@@ -476,7 +516,8 @@ class GlobalAPIRequestContext extends APIRequestContext {
476
516
  tracing() {
477
517
  return this._tracing;
478
518
  }
479
- async dispose() {
519
+ async dispose(options) {
520
+ this._closeReason = options.reason;
480
521
  await this._tracing.flush();
481
522
  await this._tracing.deleteTmpTracesDir();
482
523
  this._disposeImpl();
@@ -632,4 +673,12 @@ function shouldBypassProxy(url, bypass) {
632
673
  });
633
674
  const domain = '.' + url.hostname;
634
675
  return domains.some(d => domain.endsWith(d));
676
+ }
677
+ function setBasicAuthorizationHeader(headers, credentials) {
678
+ const {
679
+ username,
680
+ password
681
+ } = credentials;
682
+ const encoded = Buffer.from(`${username || ''}:${password || ''}`).toString('base64');
683
+ setHeader(headers, 'authorization', `Basic ${encoded}`);
635
684
  }
@@ -33,13 +33,16 @@ async function prepareFilesForUpload(frame, params) {
33
33
  var _fileBuffers;
34
34
  const {
35
35
  payloads,
36
- streams
36
+ streams,
37
+ directoryStream
37
38
  } = params;
38
39
  let {
39
- localPaths
40
+ localPaths,
41
+ localDirectory
40
42
  } = params;
41
- if ([payloads, localPaths, streams].filter(Boolean).length !== 1) throw new Error('Exactly one of payloads, localPaths and streams must be provided');
43
+ if ([payloads, localPaths, localDirectory, streams, directoryStream].filter(Boolean).length !== 1) throw new Error('Exactly one of payloads, localPaths and streams must be provided');
42
44
  if (streams) localPaths = streams.map(c => c.path());
45
+ if (directoryStream) localDirectory = directoryStream.path();
43
46
  if (localPaths) {
44
47
  for (const p of localPaths) (0, _utils.assert)(_path.default.isAbsolute(p) && _path.default.resolve(p) === p, 'Paths provided to localPaths must be absolute and fully resolved.');
45
48
  }
@@ -66,6 +69,7 @@ async function prepareFilesForUpload(frame, params) {
66
69
  }));
67
70
  return {
68
71
  localPaths,
72
+ localDirectory,
69
73
  filePayloads
70
74
  };
71
75
  }