@checkly/playwright-core 1.47.12 → 1.48.10-alpha

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 (227) hide show
  1. package/browsers.json +14 -10
  2. package/lib/cli/program.js +22 -12
  3. package/lib/client/api.js +6 -0
  4. package/lib/client/browserContext.js +20 -2
  5. package/lib/client/channelOwner.js +5 -2
  6. package/lib/client/connection.js +3 -0
  7. package/lib/client/fetch.js +16 -3
  8. package/lib/client/jsHandle.js +0 -8
  9. package/lib/client/localUtils.js +1 -0
  10. package/lib/client/network.js +175 -17
  11. package/lib/client/page.js +21 -0
  12. package/lib/client/playwright.js +6 -3
  13. package/lib/client/tracing.js +16 -20
  14. package/lib/generated/consoleApiSource.js +1 -1
  15. package/lib/generated/injectedScriptSource.js +1 -1
  16. package/lib/generated/pollingRecorderSource.js +7 -0
  17. package/lib/generated/webSocketMockSource.js +7 -0
  18. package/lib/protocol/validator.js +79 -14
  19. package/lib/server/bidi/bidiBrowser.js +23 -8
  20. package/lib/server/bidi/bidiChromium.js +124 -0
  21. package/lib/server/bidi/bidiConnection.js +1 -1
  22. package/lib/server/bidi/bidiExecutionContext.js +0 -3
  23. package/lib/server/bidi/bidiFirefox.js +15 -21
  24. package/lib/server/bidi/bidiInput.js +16 -32
  25. package/lib/server/bidi/bidiNetworkManager.js +39 -5
  26. package/lib/server/bidi/bidiOverCdp.js +103 -0
  27. package/lib/server/bidi/bidiPage.js +98 -25
  28. package/lib/server/bidi/bidiPdf.js +140 -0
  29. package/lib/server/bidi/third_party/firefoxPrefs.js +221 -0
  30. package/lib/server/browser.js +13 -2
  31. package/lib/server/browserContext.js +6 -23
  32. package/lib/server/browserType.js +39 -11
  33. package/lib/server/chromium/chromium.js +3 -15
  34. package/lib/server/chromium/chromiumSwitches.js +3 -1
  35. package/lib/server/chromium/crBrowser.js +4 -3
  36. package/lib/server/chromium/crExecutionContext.js +0 -7
  37. package/lib/server/chromium/crPage.js +5 -2
  38. package/lib/server/chromium/videoRecorder.js +1 -1
  39. package/lib/server/codegen/csharp.js +2 -2
  40. package/lib/server/codegen/java.js +1 -1
  41. package/lib/server/codegen/javascript.js +1 -1
  42. package/lib/server/codegen/language.js +14 -2
  43. package/lib/server/codegen/python.js +2 -2
  44. package/lib/server/cookieStore.js +73 -0
  45. package/lib/server/debugController.js +2 -2
  46. package/lib/server/deviceDescriptorsSource.json +51 -51
  47. package/lib/server/dialog.js +1 -0
  48. package/lib/server/dispatchers/browserContextDispatcher.js +19 -2
  49. package/lib/server/dispatchers/jsHandleDispatcher.js +0 -5
  50. package/lib/server/dispatchers/pageDispatcher.js +9 -0
  51. package/lib/server/dispatchers/playwrightDispatcher.js +2 -1
  52. package/lib/server/dispatchers/webSocketRouteDispatcher.js +189 -0
  53. package/lib/server/download.js +9 -2
  54. package/lib/server/fetch.js +96 -99
  55. package/lib/server/firefox/ffBrowser.js +6 -4
  56. package/lib/server/firefox/ffExecutionContext.js +0 -3
  57. package/lib/server/firefox/ffPage.js +3 -0
  58. package/lib/server/firefox/firefox.js +2 -13
  59. package/lib/server/frameSelectors.js +1 -1
  60. package/lib/server/frames.js +3 -2
  61. package/lib/server/har/harTracer.js +11 -0
  62. package/lib/server/input.js +0 -1
  63. package/lib/server/javascript.js +0 -7
  64. package/lib/server/page.js +5 -1
  65. package/lib/server/playwright.js +5 -2
  66. package/lib/server/recorder/contextRecorder.js +33 -50
  67. package/lib/server/recorder/recorderActions.js +2 -1
  68. package/lib/server/recorder/recorderApp.js +15 -9
  69. package/lib/server/recorder/recorderCollection.js +68 -79
  70. package/lib/server/recorder/recorderFrontend.js +5 -0
  71. package/lib/server/recorder/recorderInTraceViewer.js +144 -0
  72. package/lib/server/recorder/recorderRunner.js +75 -97
  73. package/lib/server/recorder/recorderUtils.js +47 -6
  74. package/lib/server/recorder.js +28 -25
  75. package/lib/server/registry/index.js +85 -4
  76. package/lib/server/socksClientCertificatesInterceptor.js +15 -3
  77. package/lib/server/trace/recorder/snapshotter.js +1 -0
  78. package/lib/server/trace/recorder/snapshotterInjected.js +2 -2
  79. package/lib/server/trace/recorder/tracing.js +58 -2
  80. package/lib/server/trace/test/inMemorySnapshotter.js +1 -1
  81. package/lib/server/trace/viewer/traceViewer.js +2 -5
  82. package/lib/server/webkit/webkit.js +1 -1
  83. package/lib/server/webkit/wkBrowser.js +6 -5
  84. package/lib/server/webkit/wkExecutionContext.js +0 -3
  85. package/lib/server/webkit/wkPage.js +4 -1
  86. package/lib/utils/happy-eyeballs.js +13 -0
  87. package/lib/utils/hostPlatform.js +2 -2
  88. package/lib/utils/httpServer.js +1 -0
  89. package/lib/utils/isomorphic/locatorGenerators.js +9 -18
  90. package/lib/utils/isomorphic/locatorParser.js +2 -2
  91. package/lib/utils/isomorphic/recorderUtils.js +195 -0
  92. package/lib/vite/htmlReport/index.html +12 -12
  93. package/lib/vite/recorder/assets/codeMirrorModule-CND2fZ5Q.js +24 -0
  94. package/lib/vite/recorder/assets/{index-NC7rIA63.css → index-BW-aOBcL.css} +1 -1
  95. package/lib/vite/recorder/assets/{index-A2TWT47O.js → index-CEc83sSS.js} +10 -15
  96. package/lib/vite/recorder/index.html +2 -2
  97. package/lib/vite/traceViewer/assets/codeMirrorModule-5yiV-3wl.js +16831 -0
  98. package/lib/vite/traceViewer/assets/codeMirrorModule-B7Z3vq11.js +24 -0
  99. package/lib/vite/traceViewer/assets/codeMirrorModule-BdBhzV6t.js +16443 -0
  100. package/lib/vite/traceViewer/assets/codeMirrorModule-BqcXH1AO.js +16838 -0
  101. package/lib/vite/traceViewer/assets/codeMirrorModule-C6p3E9Zg.js +24 -0
  102. package/lib/vite/traceViewer/assets/codeMirrorModule-Ca-1BNel.js +24 -0
  103. package/lib/vite/traceViewer/assets/codeMirrorModule-CcviAl53.js +16831 -0
  104. package/lib/vite/{recorder/assets/codeMirrorModule-vr7pfcwZ.js → traceViewer/assets/codeMirrorModule-CqYUz5ms.js} +1 -1
  105. package/lib/vite/traceViewer/assets/codeMirrorModule-DS3v0XrQ.js +24 -0
  106. package/lib/vite/traceViewer/assets/codeMirrorModule-Dx6AXgMV.js +16838 -0
  107. package/lib/vite/traceViewer/assets/codeMirrorModule-EhKN7Okm.js +16449 -0
  108. package/lib/vite/traceViewer/assets/codeMirrorModule-MzSmL4X2.js +24 -0
  109. package/lib/vite/traceViewer/assets/{codeMirrorModule-cCPLLRBo.js → codeMirrorModule-T_sdMrbM.js} +1 -1
  110. package/lib/vite/traceViewer/assets/codeMirrorModule-U6XMqGkV.js +16437 -0
  111. package/lib/vite/traceViewer/assets/inspectorTab-BABZNwlH.js +17351 -0
  112. package/lib/vite/traceViewer/assets/inspectorTab-BPzVEZSf.js +17351 -0
  113. package/lib/vite/traceViewer/assets/inspectorTab-Bbgq0hgt.js +64 -0
  114. package/lib/vite/traceViewer/assets/inspectorTab-DhBbZz8I.js +64 -0
  115. package/lib/vite/traceViewer/assets/inspectorTab-DpvLVMq5.js +17351 -0
  116. package/lib/vite/traceViewer/assets/testServerConnection-D-tXL3sj.js +224 -0
  117. package/lib/vite/traceViewer/assets/workbench-B13nfocr.js +9 -0
  118. package/lib/vite/traceViewer/assets/workbench-BcgGQnKb.js +1473 -0
  119. package/lib/vite/traceViewer/assets/{wsPort-MnTGOuCA.js → workbench-Bjkiwcr1.js} +1505 -926
  120. package/lib/vite/traceViewer/assets/workbench-BwodYCgl.js +19119 -0
  121. package/lib/vite/traceViewer/assets/workbench-ByyWxoT8.js +1473 -0
  122. package/lib/vite/traceViewer/assets/{workbench-z8ylMSQK.js → workbench-C43LWZEX.js} +7 -7
  123. package/lib/vite/traceViewer/assets/workbench-C5OQh9VX.js +19119 -0
  124. package/lib/vite/traceViewer/assets/workbench-Crj6jzdv.js +19119 -0
  125. package/lib/vite/traceViewer/assets/workbench-DhqI6jeL.js +1473 -0
  126. package/lib/vite/traceViewer/assets/workbench-DrQjKdyE.js +72 -0
  127. package/lib/vite/traceViewer/assets/workbench-Pa1v1Ojh.js +72 -0
  128. package/lib/vite/traceViewer/assets/workbench-caTaZnzx.js +72 -0
  129. package/lib/vite/traceViewer/assets/workbench-gtYcQBNA.js +9 -0
  130. package/lib/vite/traceViewer/assets/workbench-u2lRPMOT.js +72 -0
  131. package/lib/vite/traceViewer/assets/xtermModule-CZ7sDYXB.js +6529 -0
  132. package/lib/vite/traceViewer/assets/xtermModule-DZP0glxx.js +5982 -0
  133. package/lib/vite/traceViewer/codeMirrorModule.Cy8X9Wtw.css +344 -0
  134. package/lib/vite/traceViewer/embedded.27BGR_eD.js +105 -0
  135. package/lib/vite/traceViewer/embedded.BBZ9gQEw.js +104 -0
  136. package/lib/vite/traceViewer/embedded.BQq6Psnz.js +104 -0
  137. package/lib/vite/traceViewer/{embedded.TOXRJZ9A.js → embedded.BVDVQOzc.js} +1 -1
  138. package/lib/vite/traceViewer/embedded.Bn8Ptzv6.js +2 -0
  139. package/lib/vite/traceViewer/embedded.CorI3dFX.js +104 -0
  140. package/lib/vite/traceViewer/embedded.CvhnUgIi.js +2 -0
  141. package/lib/vite/traceViewer/embedded.D27cnKiB.js +104 -0
  142. package/lib/vite/traceViewer/embedded.D4lqGydT.js +2 -0
  143. package/lib/vite/traceViewer/embedded.DPqrDeET.js +2 -0
  144. package/lib/vite/traceViewer/embedded.DTjd2aiy.js +105 -0
  145. package/lib/vite/traceViewer/embedded.DbzY7Q8w.js +2 -0
  146. package/lib/vite/traceViewer/embedded.DjZq4InJ.css +68 -0
  147. package/lib/vite/traceViewer/embedded.SsjKHrxC.js +105 -0
  148. package/lib/vite/traceViewer/embedded.f-PLGsBT.js +2 -0
  149. package/lib/vite/traceViewer/embedded.html +6 -4
  150. package/lib/vite/traceViewer/index.B7aiTMfZ.js +2 -0
  151. package/lib/vite/traceViewer/{index.e7qpO0B0.js → index.B8dgQwuN.js} +1 -1
  152. package/lib/vite/traceViewer/index.BGj8jY3H.js +2 -0
  153. package/lib/vite/traceViewer/index.BSak5QT9.js +2 -0
  154. package/lib/vite/traceViewer/index.BrT2kfuc.js +2 -0
  155. package/lib/vite/traceViewer/{index.RT4iItO_.js → index.C0EgJ4oW.js} +36 -21
  156. package/lib/vite/traceViewer/index.CUpI-BFe.js +195 -0
  157. package/lib/vite/traceViewer/index.DkRbtWVo.js +195 -0
  158. package/lib/vite/traceViewer/index.DsjmhbB6.js +195 -0
  159. package/lib/vite/traceViewer/index.Dz3icWJV.js +196 -0
  160. package/lib/vite/traceViewer/index.PqcsvBxQ.js +196 -0
  161. package/lib/vite/traceViewer/index.QanXxRUb.css +131 -0
  162. package/lib/vite/traceViewer/index._cX8k4co.js +2 -0
  163. package/lib/vite/traceViewer/index.html +7 -5
  164. package/lib/vite/traceViewer/index.pMAN88y-.js +2 -0
  165. package/lib/vite/traceViewer/index.yxAwzeWG.js +196 -0
  166. package/lib/vite/traceViewer/inspectorTab.DGJWXOSd.css +3145 -0
  167. package/lib/vite/traceViewer/inspectorTab.DLjBDrQR.css +1 -0
  168. package/lib/vite/traceViewer/recorder.7Wl6HrQl.js +550 -0
  169. package/lib/vite/traceViewer/recorder.B_SY1GJM.css +0 -0
  170. package/lib/vite/traceViewer/recorder.BufKu9Hp.js +550 -0
  171. package/lib/vite/traceViewer/recorder.Ch-WHviK.js +2 -0
  172. package/lib/vite/traceViewer/recorder.DBDpiNOK.css +15 -0
  173. package/lib/vite/traceViewer/recorder.POd-toIn.js +2 -0
  174. package/lib/vite/traceViewer/recorder.am-MV-DQ.js +550 -0
  175. package/lib/vite/traceViewer/recorder.html +17 -0
  176. package/lib/vite/traceViewer/sw.bundle.js +3 -3
  177. package/lib/vite/traceViewer/uiMode.BEZVCe5O.js +5 -0
  178. package/lib/vite/traceViewer/uiMode.BZoFj6zV.js +1723 -0
  179. package/lib/vite/traceViewer/uiMode.C4nbcio6.js +1730 -0
  180. package/lib/vite/traceViewer/uiMode.CAYqod-m.css +1 -0
  181. package/lib/vite/traceViewer/uiMode.D-tg1Oci.js +1730 -0
  182. package/lib/vite/traceViewer/uiMode.DKjMBMlc.js +1730 -0
  183. package/lib/vite/traceViewer/uiMode.DRmgrHSk.css +1462 -0
  184. package/lib/vite/traceViewer/uiMode.DVWUEIHq.css +1424 -0
  185. package/lib/vite/traceViewer/{uiMode.MTXOs_2V.js → uiMode.DVrL7a1K.js} +5 -5
  186. package/lib/vite/traceViewer/uiMode.DdtUZZVS.js +5 -0
  187. package/lib/vite/traceViewer/uiMode.Dg9oJCQU.js +10 -0
  188. package/lib/vite/traceViewer/uiMode.Dlo9s_YX.js +1723 -0
  189. package/lib/vite/traceViewer/uiMode.DwZAzstF.js +10 -0
  190. package/lib/vite/traceViewer/uiMode.O07awP3T.js +10 -0
  191. package/lib/vite/traceViewer/uiMode.gGHHTsyL.js +1730 -0
  192. package/lib/vite/traceViewer/uiMode.html +7 -5
  193. package/lib/vite/traceViewer/uiMode.jY2s-9ps.js +10 -0
  194. package/lib/vite/traceViewer/uiMode.wsGnVMQK.js +1723 -0
  195. package/lib/vite/traceViewer/workbench.B3X2QtYa.css +3702 -0
  196. package/lib/vite/traceViewer/workbench.BQNDbcQ0.css +550 -0
  197. package/lib/vite/traceViewer/{workbench.NokwQoMV.css → workbench.DjbIuxix.css} +1 -1
  198. package/lib/vite/traceViewer/workbench.DlsCx8k5.css +1 -0
  199. package/lib/vite/traceViewer/workbench.DyTpxWVb.css +1 -0
  200. package/lib/vite/traceViewer/workbench.wuxQoE2z.css +3703 -0
  201. package/lib/vite/traceViewer/xtermModule.4oRVGWQ-.css +209 -0
  202. package/package.json +1 -1
  203. package/types/protocol.d.ts +610 -173
  204. package/types/types.d.ts +2037 -949
  205. package/lib/vite/traceViewer/assets/codeMirrorModule-0bpaqixv.js +0 -24
  206. package/lib/vite/traceViewer/assets/codeMirrorModule-clyjx5sb.js +0 -15578
  207. package/lib/vite/traceViewer/assets/codeMirrorModule-wLpsbIhd.js +0 -24
  208. package/lib/vite/traceViewer/assets/wsPort-_JBDEilC.js +0 -69
  209. package/lib/vite/traceViewer/assets/wsPort-f2dAQL4I.js +0 -69
  210. package/lib/vite/traceViewer/index.-_8-eHEE.js +0 -2
  211. package/lib/vite/traceViewer/index.-g_5lMbJ.css +0 -1
  212. package/lib/vite/traceViewer/index.u51inEcm.js +0 -2
  213. package/lib/vite/traceViewer/uiMode.9CwNsWc6.js +0 -10
  214. package/lib/vite/traceViewer/uiMode.Fb0bNA4H.js +0 -10
  215. package/lib/vite/traceViewer/uiMode.pWy0Re7G.css +0 -1
  216. package/lib/vite/traceViewer/uiMode.yLNTmFO4.js +0 -1490
  217. package/lib/vite/traceViewer/wsPort.zR1WIy9-.css +0 -1
  218. /package/lib/vite/recorder/assets/{codeMirrorModule-Hs9-1ZG4.css → codeMirrorModule-ez37Vkbh.css} +0 -0
  219. /package/lib/vite/recorder/assets/{codicon-wpoHPmsu.ttf → codicon-DCmgc-ay.ttf} +0 -0
  220. /package/lib/vite/traceViewer/assets/{testServerConnection-_1gRQKgk.js → testServerConnection-DeE2kSzz.js} +0 -0
  221. /package/lib/vite/traceViewer/assets/{xtermModule-Yt6xwiJ_.js → xtermModule-BeNbaIVa.js} +0 -0
  222. /package/lib/vite/traceViewer/{codeMirrorModule.Hs9-1ZG4.css → codeMirrorModule.ez37Vkbh.css} +0 -0
  223. /package/lib/vite/traceViewer/{codicon.wpoHPmsu.ttf → codicon.DCmgc-ay.ttf} +0 -0
  224. /package/lib/vite/traceViewer/{embedded.MO1jdrtU.css → embedded.w7WN2u1R.css} +0 -0
  225. /package/lib/vite/traceViewer/{index.q21lh23x.css → index.CrbWWHbf.css} +0 -0
  226. /package/lib/vite/traceViewer/{uiMode.93DRT-rm.css → uiMode.D3cNFP6u.css} +0 -0
  227. /package/lib/vite/traceViewer/{xtermModule.0lwXJFHT.css → xtermModule.DSXBckUd.css} +0 -0
@@ -1,3 +1,9 @@
1
+ function __vite__mapDeps(indexes) {
2
+ if (!__vite__mapDeps.viteFileDeps) {
3
+ __vite__mapDeps.viteFileDeps = ["./codeMirrorModule-5yiV-3wl.js","../codeMirrorModule.Cy8X9Wtw.css"]
4
+ }
5
+ return indexes.map((i) => __vite__mapDeps.viteFileDeps[i])
6
+ }
1
7
  var __defProp = Object.defineProperty;
2
8
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
9
  var __publicField = (obj, key, value) => {
@@ -348,14 +354,14 @@ const React = /* @__PURE__ */ getDefaultExportFromCjs(reactExports);
348
354
  * This source code is licensed under the MIT license found in the
349
355
  * LICENSE file in the root directory of this source tree.
350
356
  */
351
- var f = reactExports, k = Symbol.for("react.element"), l = Symbol.for("react.fragment"), m = Object.prototype.hasOwnProperty, n = f.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner, p$1 = { key: true, ref: true, __self: true, __source: true };
357
+ var f = reactExports, k = Symbol.for("react.element"), l = Symbol.for("react.fragment"), m$1 = Object.prototype.hasOwnProperty, n = f.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner, p$1 = { key: true, ref: true, __self: true, __source: true };
352
358
  function q(c, a, g) {
353
359
  var b, d = {}, e = null, h = null;
354
360
  void 0 !== g && (e = "" + g);
355
361
  void 0 !== a.key && (e = "" + a.key);
356
362
  void 0 !== a.ref && (h = a.ref);
357
363
  for (b in a)
358
- m.call(a, b) && !p$1.hasOwnProperty(b) && (d[b] = a[b]);
364
+ m$1.call(a, b) && !p$1.hasOwnProperty(b) && (d[b] = a[b]);
359
365
  if (c && c.defaultProps)
360
366
  for (b in a = c.defaultProps, a)
361
367
  void 0 === d[b] && (d[b] = a[b]);
@@ -402,7 +408,7 @@ function useMeasure() {
402
408
  return [measure, ref];
403
409
  }
404
410
  function msToString(ms) {
405
- if (!isFinite(ms))
411
+ if (ms < 0 || !isFinite(ms))
406
412
  return "-";
407
413
  if (ms === 0)
408
414
  return "0";
@@ -458,24 +464,37 @@ function copy(text) {
458
464
  document.execCommand("copy");
459
465
  textArea.remove();
460
466
  }
461
- function useSetting(name, defaultValue) {
462
- const value = name ? settings.getObject(name, defaultValue) : defaultValue;
463
- const [state, setState] = React.useState(value);
464
- const setStateWrapper = (value2) => {
467
+ function useSetting(name, defaultValue, title) {
468
+ if (name)
469
+ defaultValue = settings.getObject(name, defaultValue);
470
+ const [value, setValue] = React.useState(defaultValue);
471
+ const setValueWrapper = React.useCallback((value2) => {
465
472
  if (name)
466
473
  settings.setObject(name, value2);
467
- setState(value2);
468
- };
469
- return [state, setStateWrapper];
474
+ else
475
+ setValue(value2);
476
+ }, [name, setValue]);
477
+ React.useEffect(() => {
478
+ if (name) {
479
+ const onStoreChange = () => setValue(settings.getObject(name, defaultValue));
480
+ settings.onChangeEmitter.addEventListener(name, onStoreChange);
481
+ return () => settings.onChangeEmitter.removeEventListener(name, onStoreChange);
482
+ }
483
+ }, [defaultValue, name]);
484
+ return [value, setValueWrapper];
470
485
  }
471
486
  class Settings {
487
+ constructor() {
488
+ this.onChangeEmitter = new EventTarget();
489
+ }
472
490
  getString(name, defaultValue) {
473
491
  return localStorage[name] || defaultValue;
474
492
  }
475
493
  setString(name, value) {
494
+ var _a;
476
495
  localStorage[name] = value;
477
- if (window.saveSettings)
478
- window.saveSettings();
496
+ this.onChangeEmitter.dispatchEvent(new Event(name));
497
+ (_a = window.saveSettings) == null ? void 0 : _a.call(window);
479
498
  }
480
499
  getObject(name, defaultValue) {
481
500
  if (!localStorage[name])
@@ -487,12 +506,18 @@ class Settings {
487
506
  }
488
507
  }
489
508
  setObject(name, value) {
509
+ var _a;
490
510
  localStorage[name] = JSON.stringify(value);
491
- if (window.saveSettings)
492
- window.saveSettings();
511
+ this.onChangeEmitter.dispatchEvent(new Event(name));
512
+ (_a = window.saveSettings) == null ? void 0 : _a.call(window);
493
513
  }
494
514
  }
495
515
  const settings = new Settings();
516
+ function clsx(...classes) {
517
+ return classes.filter(Boolean).join(" ");
518
+ }
519
+ const kControlCodesRe = "\\u0000-\\u0020\\u007f-\\u009f";
520
+ const kWebLinkRe = new RegExp("(?:[a-zA-Z][a-zA-Z0-9+.-]{2,}:\\/\\/|www\\.)[^\\s" + kControlCodesRe + '"]{2,}[^\\s' + kControlCodesRe + `"')}\\],:;.!?]`, "ug");
496
521
  function applyTheme() {
497
522
  if (document.playwrightThemeInitialized)
498
523
  return;
@@ -511,12 +536,8 @@ function applyTheme() {
511
536
  }
512
537
  const listeners = /* @__PURE__ */ new Set();
513
538
  function toggleTheme() {
514
- const oldTheme = settings.getString("theme", "light-mode");
515
- let newTheme;
516
- if (oldTheme === "dark-mode")
517
- newTheme = "light-mode";
518
- else
519
- newTheme = "dark-mode";
539
+ const oldTheme = currentTheme();
540
+ const newTheme = oldTheme === "dark-mode" ? "light-mode" : "dark-mode";
520
541
  if (oldTheme)
521
542
  document.body.classList.remove(oldTheme);
522
543
  document.body.classList.add(newTheme);
@@ -533,6 +554,15 @@ function removeThemeListener(listener) {
533
554
  function currentTheme() {
534
555
  return document.body.classList.contains("dark-mode") ? "dark-mode" : "light-mode";
535
556
  }
557
+ function useDarkModeSetting() {
558
+ const [theme, setTheme] = React.useState(currentTheme() === "dark-mode");
559
+ return [theme, (value) => {
560
+ const current = currentTheme() === "dark-mode";
561
+ if (current !== value)
562
+ toggleTheme();
563
+ setTheme(value);
564
+ }];
565
+ }
536
566
  var reactDom = { exports: {} };
537
567
  var reactDom_production_min = {};
538
568
  var scheduler = { exports: {} };
@@ -7750,6 +7780,12 @@ function checkDCE() {
7750
7780
  reactDom.exports = reactDom_production_min;
7751
7781
  }
7752
7782
  var reactDomExports = reactDom.exports;
7783
+ var createRoot;
7784
+ var m = reactDomExports;
7785
+ {
7786
+ createRoot = m.createRoot;
7787
+ m.hydrateRoot;
7788
+ }
7753
7789
  const ToolbarButton = ({
7754
7790
  children,
7755
7791
  title = "",
@@ -7758,9 +7794,11 @@ const ToolbarButton = ({
7758
7794
  toggled = false,
7759
7795
  onClick = () => {
7760
7796
  },
7761
- style
7797
+ style,
7798
+ testId,
7799
+ className
7762
7800
  }) => {
7763
- let className = `toolbar-button ${icon}`;
7801
+ className = (className || "") + ` toolbar-button ${icon}`;
7764
7802
  if (toggled)
7765
7803
  className += " toggled";
7766
7804
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
@@ -7773,6 +7811,7 @@ const ToolbarButton = ({
7773
7811
  title,
7774
7812
  disabled: !!disabled,
7775
7813
  style,
7814
+ "data-testid": testId,
7776
7815
  children: [
7777
7816
  icon && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `codicon codicon-${icon}`, style: children ? { marginRight: 5 } : {} }),
7778
7817
  children
@@ -7811,24 +7850,24 @@ class MultiTraceModel {
7811
7850
  __publicField(this, "sources");
7812
7851
  __publicField(this, "resources");
7813
7852
  contexts.forEach((contextEntry) => indexModel(contextEntry));
7814
- const primaryContext = contexts.find((context2) => context2.isPrimary);
7815
- this.browserName = (primaryContext == null ? void 0 : primaryContext.browserName) || "";
7816
- this.sdkLanguage = primaryContext == null ? void 0 : primaryContext.sdkLanguage;
7817
- this.channel = primaryContext == null ? void 0 : primaryContext.channel;
7818
- this.testIdAttributeName = primaryContext == null ? void 0 : primaryContext.testIdAttributeName;
7819
- this.platform = (primaryContext == null ? void 0 : primaryContext.platform) || "";
7820
- this.title = (primaryContext == null ? void 0 : primaryContext.title) || "";
7821
- this.options = (primaryContext == null ? void 0 : primaryContext.options) || {};
7853
+ const libraryContext = contexts.find((context2) => context2.origin === "library");
7854
+ this.browserName = (libraryContext == null ? void 0 : libraryContext.browserName) || "";
7855
+ this.sdkLanguage = libraryContext == null ? void 0 : libraryContext.sdkLanguage;
7856
+ this.channel = libraryContext == null ? void 0 : libraryContext.channel;
7857
+ this.testIdAttributeName = libraryContext == null ? void 0 : libraryContext.testIdAttributeName;
7858
+ this.platform = (libraryContext == null ? void 0 : libraryContext.platform) || "";
7859
+ this.title = (libraryContext == null ? void 0 : libraryContext.title) || "";
7860
+ this.options = (libraryContext == null ? void 0 : libraryContext.options) || {};
7861
+ this.actions = mergeActionsAndUpdateTiming(contexts);
7862
+ this.pages = [].concat(...contexts.map((c) => c.pages));
7822
7863
  this.wallTime = contexts.map((c) => c.wallTime).reduce((prev, cur) => Math.min(prev || Number.MAX_VALUE, cur), Number.MAX_VALUE);
7823
7864
  this.startTime = contexts.map((c) => c.startTime).reduce((prev, cur) => Math.min(prev, cur), Number.MAX_VALUE);
7824
7865
  this.endTime = contexts.map((c) => c.endTime).reduce((prev, cur) => Math.max(prev, cur), Number.MIN_VALUE);
7825
- this.pages = [].concat(...contexts.map((c) => c.pages));
7826
- this.actions = mergeActions(contexts);
7827
7866
  this.events = [].concat(...contexts.map((c) => c.events));
7828
7867
  this.stdio = [].concat(...contexts.map((c) => c.stdio));
7829
7868
  this.errors = [].concat(...contexts.map((c) => c.errors));
7830
7869
  this.hasSource = contexts.some((c) => c.hasSource);
7831
- this.hasStepData = contexts.some((context2) => !context2.isPrimary);
7870
+ this.hasStepData = contexts.some((context2) => context2.origin === "testRunner");
7832
7871
  this.resources = [...contexts.map((c) => c.resources)].flat();
7833
7872
  this.events.sort((a1, a2) => a1.time - a2.time);
7834
7873
  this.resources.sort((a1, a2) => a1._monotonicTime - a2._monotonicTime);
@@ -7881,31 +7920,74 @@ function indexModel(context2) {
7881
7920
  }
7882
7921
  for (const event of context2.events)
7883
7922
  event[contextSymbol] = context2;
7923
+ for (const resource of context2.resources)
7924
+ resource[contextSymbol] = context2;
7884
7925
  }
7885
- function mergeActions(contexts) {
7926
+ function mergeActionsAndUpdateTiming(contexts) {
7927
+ const traceFileToContexts = /* @__PURE__ */ new Map();
7928
+ for (const context2 of contexts) {
7929
+ const traceFile = context2.traceUrl;
7930
+ let list = traceFileToContexts.get(traceFile);
7931
+ if (!list) {
7932
+ list = [];
7933
+ traceFileToContexts.set(traceFile, list);
7934
+ }
7935
+ list.push(context2);
7936
+ }
7937
+ const result = [];
7938
+ let traceFileId = 0;
7939
+ for (const [, contexts2] of traceFileToContexts) {
7940
+ if (traceFileToContexts.size > 1)
7941
+ makeCallIdsUniqueAcrossTraceFiles(contexts2, ++traceFileId);
7942
+ const actions = mergeActionsAndUpdateTimingSameTrace(contexts2);
7943
+ result.push(...actions);
7944
+ }
7945
+ result.sort((a1, a2) => {
7946
+ if (a2.parentId === a1.callId)
7947
+ return -1;
7948
+ if (a1.parentId === a2.callId)
7949
+ return 1;
7950
+ return a1.startTime - a2.startTime;
7951
+ });
7952
+ for (let i = 1; i < result.length; ++i)
7953
+ result[i][prevInListSymbol] = result[i - 1];
7954
+ return result;
7955
+ }
7956
+ function makeCallIdsUniqueAcrossTraceFiles(contexts, traceFileId) {
7957
+ for (const context2 of contexts) {
7958
+ for (const action of context2.actions) {
7959
+ if (action.callId)
7960
+ action.callId = `${traceFileId}:${action.callId}`;
7961
+ if (action.parentId)
7962
+ action.parentId = `${traceFileId}:${action.parentId}`;
7963
+ }
7964
+ }
7965
+ }
7966
+ function mergeActionsAndUpdateTimingSameTrace(contexts) {
7886
7967
  const map = /* @__PURE__ */ new Map();
7887
- let offset = 0;
7888
- const primaryContexts = contexts.filter((context2) => context2.isPrimary);
7889
- const nonPrimaryContexts = contexts.filter((context2) => !context2.isPrimary);
7890
- for (const context2 of primaryContexts) {
7891
- for (const action of context2.actions)
7892
- map.set(`${action.apiName}@${action.wallTime}`, { ...action, context: context2 });
7893
- if (!offset && context2.actions.length)
7894
- offset = context2.actions[0].startTime - context2.actions[0].wallTime;
7968
+ const libraryContexts = contexts.filter((context2) => context2.origin === "library");
7969
+ const testRunnerContexts = contexts.filter((context2) => context2.origin === "testRunner");
7970
+ if (!testRunnerContexts.length || !libraryContexts.length) {
7971
+ return contexts.map((context2) => {
7972
+ return context2.actions.map((action) => ({ ...action, context: context2 }));
7973
+ }).flat();
7974
+ }
7975
+ const matchByStepId = libraryContexts.some((c) => c.actions.some((a) => !!a.stepId));
7976
+ for (const context2 of libraryContexts) {
7977
+ for (const action of context2.actions) {
7978
+ const key = matchByStepId ? action.stepId : `${action.apiName}@${action.wallTime}`;
7979
+ map.set(key, { ...action, context: context2 });
7980
+ }
7895
7981
  }
7982
+ const delta = monotonicTimeDeltaBetweenLibraryAndRunner(testRunnerContexts, map, matchByStepId);
7983
+ if (delta)
7984
+ adjustMonotonicTime(libraryContexts, delta);
7896
7985
  const nonPrimaryIdToPrimaryId = /* @__PURE__ */ new Map();
7897
- for (const context2 of nonPrimaryContexts) {
7986
+ for (const context2 of testRunnerContexts) {
7898
7987
  for (const action of context2.actions) {
7899
- if (offset) {
7900
- const duration = action.endTime - action.startTime;
7901
- if (action.startTime)
7902
- action.startTime = action.wallTime + offset;
7903
- if (action.endTime)
7904
- action.endTime = action.startTime + duration;
7905
- }
7906
- const key = `${action.apiName}@${action.wallTime}`;
7988
+ const key = matchByStepId ? action.callId : `${action.apiName}@${action.wallTime}`;
7907
7989
  const existing = map.get(key);
7908
- if (existing && existing.apiName === action.apiName) {
7990
+ if (existing) {
7909
7991
  nonPrimaryIdToPrimaryId.set(action.callId, existing.callId);
7910
7992
  if (action.error)
7911
7993
  existing.error = action.error;
@@ -7913,6 +7995,8 @@ function mergeActions(contexts) {
7913
7995
  existing.attachments = action.attachments;
7914
7996
  if (action.parentId)
7915
7997
  existing.parentId = nonPrimaryIdToPrimaryId.get(action.parentId) ?? action.parentId;
7998
+ existing.startTime = action.startTime;
7999
+ existing.endTime = action.endTime;
7916
8000
  continue;
7917
8001
  }
7918
8002
  if (action.parentId)
@@ -7920,17 +8004,44 @@ function mergeActions(contexts) {
7920
8004
  map.set(key, { ...action, context: context2 });
7921
8005
  }
7922
8006
  }
7923
- const result = [...map.values()];
7924
- result.sort((a1, a2) => {
7925
- if (a2.parentId === a1.callId)
7926
- return -1;
7927
- if (a1.parentId === a2.callId)
7928
- return 1;
7929
- return a1.wallTime - a2.wallTime || a1.startTime - a2.startTime;
7930
- });
7931
- for (let i = 1; i < result.length; ++i)
7932
- result[i][prevInListSymbol] = result[i - 1];
7933
- return result;
8007
+ return [...map.values()];
8008
+ }
8009
+ function adjustMonotonicTime(contexts, monotonicTimeDelta) {
8010
+ for (const context2 of contexts) {
8011
+ context2.startTime += monotonicTimeDelta;
8012
+ context2.endTime += monotonicTimeDelta;
8013
+ for (const action of context2.actions) {
8014
+ if (action.startTime)
8015
+ action.startTime += monotonicTimeDelta;
8016
+ if (action.endTime)
8017
+ action.endTime += monotonicTimeDelta;
8018
+ }
8019
+ for (const event of context2.events)
8020
+ event.time += monotonicTimeDelta;
8021
+ for (const event of context2.stdio)
8022
+ event.timestamp += monotonicTimeDelta;
8023
+ for (const page of context2.pages) {
8024
+ for (const frame of page.screencastFrames)
8025
+ frame.timestamp += monotonicTimeDelta;
8026
+ }
8027
+ for (const resource of context2.resources) {
8028
+ if (resource._monotonicTime)
8029
+ resource._monotonicTime += monotonicTimeDelta;
8030
+ }
8031
+ }
8032
+ }
8033
+ function monotonicTimeDeltaBetweenLibraryAndRunner(nonPrimaryContexts, libraryActions, matchByStepId) {
8034
+ for (const context2 of nonPrimaryContexts) {
8035
+ for (const action of context2.actions) {
8036
+ if (!action.startTime)
8037
+ continue;
8038
+ const key = matchByStepId ? action.stepId : `${action.apiName}@${action.wallTime}`;
8039
+ const libraryAction = libraryActions.get(key);
8040
+ if (libraryAction)
8041
+ return action.startTime - libraryAction.startTime;
8042
+ }
8043
+ }
8044
+ return 0;
7934
8045
  }
7935
8046
  function buildActionTree(actions) {
7936
8047
  const itemMap = /* @__PURE__ */ new Map();
@@ -8012,6 +8123,30 @@ function collectSources(actions, errorDescriptors) {
8012
8123
  }
8013
8124
  return result;
8014
8125
  }
8126
+ const kRouteMethods = /* @__PURE__ */ new Set([
8127
+ "page.route",
8128
+ "page.routefromhar",
8129
+ "page.unroute",
8130
+ "page.unrouteall",
8131
+ "browsercontext.route",
8132
+ "browsercontext.routefromhar",
8133
+ "browsercontext.unroute",
8134
+ "browsercontext.unrouteall"
8135
+ ]);
8136
+ {
8137
+ for (const method of [...kRouteMethods])
8138
+ kRouteMethods.add(method + "async");
8139
+ for (const method of [
8140
+ "page.route_from_har",
8141
+ "page.unroute_all",
8142
+ "context.route_from_har",
8143
+ "context.unroute_all"
8144
+ ])
8145
+ kRouteMethods.add(method);
8146
+ }
8147
+ function isRouteAction(action) {
8148
+ return action.class === "Route" || kRouteMethods.has(action.apiName.toLowerCase());
8149
+ }
8015
8150
  const kMinSize = 50;
8016
8151
  const SplitView = ({
8017
8152
  sidebarSize,
@@ -8020,10 +8155,12 @@ const SplitView = ({
8020
8155
  orientation = "vertical",
8021
8156
  minSidebarSize = kMinSize,
8022
8157
  settingName,
8023
- children
8158
+ sidebar,
8159
+ main
8024
8160
  }) => {
8025
- const [hSize, setHSize] = useSetting(settingName ? settingName + "." + orientation + ":size" : void 0, Math.max(minSidebarSize, sidebarSize) * window.devicePixelRatio);
8026
- const [vSize, setVSize] = useSetting(settingName ? settingName + "." + orientation + ":size" : void 0, Math.max(minSidebarSize, sidebarSize) * window.devicePixelRatio);
8161
+ const defaultSize = Math.max(minSidebarSize, sidebarSize) * window.devicePixelRatio;
8162
+ const [hSize, setHSize] = useSetting(settingName ? settingName + "." + orientation + ":size" : void 0, defaultSize);
8163
+ const [vSize, setVSize] = useSetting(settingName ? settingName + "." + orientation + ":size" : void 0, defaultSize);
8027
8164
  const [resizing, setResizing] = reactExports.useState(null);
8028
8165
  const [measure, ref] = useMeasure();
8029
8166
  let size;
@@ -8036,7 +8173,6 @@ const SplitView = ({
8036
8173
  if (measure && measure.width < size)
8037
8174
  size = measure.width - 10;
8038
8175
  }
8039
- const childrenArray = reactExports.Children.toArray(children);
8040
8176
  document.body.style.userSelect = resizing ? "none" : "inherit";
8041
8177
  let resizerStyle = {};
8042
8178
  if (orientation === "vertical") {
@@ -8050,9 +8186,9 @@ const SplitView = ({
8050
8186
  else
8051
8187
  resizerStyle = { right: resizing ? 0 : size - 4, left: resizing ? 0 : void 0, width: resizing ? "initial" : 8 };
8052
8188
  }
8053
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "split-view " + orientation + (sidebarIsFirst ? " sidebar-first" : ""), ref, children: [
8054
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "split-view-main", children: childrenArray[0] }),
8055
- !sidebarHidden && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { flexBasis: size }, className: "split-view-sidebar", children: childrenArray[1] }),
8189
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: clsx("split-view", orientation, sidebarIsFirst && "sidebar-first"), ref, children: [
8190
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "split-view-main", children: main }),
8191
+ !sidebarHidden && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { flexBasis: size }, className: "split-view-sidebar", children: sidebar }),
8056
8192
  !sidebarHidden && /* @__PURE__ */ jsxRuntimeExports.jsx(
8057
8193
  "div",
8058
8194
  {
@@ -8118,8 +8254,17 @@ function cssEscapeOne(s, i) {
8118
8254
  return s.charAt(i);
8119
8255
  return "\\" + s.charAt(i);
8120
8256
  }
8257
+ let normalizedWhitespaceCache;
8258
+ function cacheNormalizedWhitespaces() {
8259
+ normalizedWhitespaceCache = /* @__PURE__ */ new Map();
8260
+ }
8121
8261
  function normalizeWhiteSpace(text) {
8122
- return text.replace(/\u200b/g, "").trim().replace(/\s+/g, " ");
8262
+ let result = normalizedWhitespaceCache == null ? void 0 : normalizedWhitespaceCache.get(text);
8263
+ if (result === void 0) {
8264
+ result = text.replace(/\u200b/g, "").trim().replace(/\s+/g, " ");
8265
+ normalizedWhitespaceCache == null ? void 0 : normalizedWhitespaceCache.set(text, result);
8266
+ }
8267
+ return result;
8123
8268
  }
8124
8269
  function normalizeEscapedRegexQuotes(source) {
8125
8270
  return source.replace(/(^|[^\\])(\\\\)*\\(['"`])/g, "$1$2$3");
@@ -8153,6 +8298,13 @@ function trimStringWithEllipsis(input, cap) {
8153
8298
  function escapeRegExp(s) {
8154
8299
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
8155
8300
  }
8301
+ const escaped = { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" };
8302
+ function escapeHTMLAttribute(s) {
8303
+ return s.replace(/[&<>"']/ug, (char) => escaped[char]);
8304
+ }
8305
+ function escapeHTML$1(s) {
8306
+ return s.replace(/[&<]/ug, (char) => escaped[char]);
8307
+ }
8156
8308
  const between = function(num, first, last) {
8157
8309
  return num >= first && num <= last;
8158
8310
  };
@@ -10185,7 +10337,7 @@ function ListView({
10185
10337
  onIconClicked,
10186
10338
  noItemsMessage,
10187
10339
  dataTestId,
10188
- noHighlightOnHover
10340
+ notSelectable
10189
10341
  }) {
10190
10342
  const itemListRef = reactExports.useRef(null);
10191
10343
  const [highlightedItem, setHighlightedItem] = reactExports.useState();
@@ -10206,12 +10358,11 @@ function ListView({
10206
10358
  if (itemListRef.current)
10207
10359
  itemListRef.current.scrollTop = scrollPositions.get(name) || 0;
10208
10360
  }, [name]);
10209
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "list-view vbox", role: items.length > 0 ? "list" : void 0, "data-testid": dataTestId || name + "-list", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
10361
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: clsx(`list-view vbox`, name + "-list-view"), role: items.length > 0 ? "list" : void 0, "data-testid": dataTestId || name + "-list", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
10210
10362
  "div",
10211
10363
  {
10212
- className: "list-view-content",
10364
+ className: clsx("list-view-content", notSelectable && "not-selectable"),
10213
10365
  tabIndex: 0,
10214
- onDoubleClick: () => selectedItem && (onAccepted == null ? void 0 : onAccepted(selectedItem, items.indexOf(selectedItem))),
10215
10366
  onKeyDown: (event) => {
10216
10367
  var _a;
10217
10368
  if (selectedItem && event.key === "Enter") {
@@ -10248,23 +10399,27 @@ function ListView({
10248
10399
  scrollIntoViewIfNeeded(element || void 0);
10249
10400
  onHighlighted == null ? void 0 : onHighlighted(void 0);
10250
10401
  onSelected == null ? void 0 : onSelected(items[newIndex], newIndex);
10402
+ setHighlightedItem(void 0);
10251
10403
  },
10252
10404
  ref: itemListRef,
10253
10405
  children: [
10254
10406
  noItemsMessage && items.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "list-view-empty", children: noItemsMessage }),
10255
10407
  items.map((item, index) => {
10256
- const selectedSuffix = selectedItem === item ? " selected" : "";
10257
- const highlightedSuffix = !noHighlightOnHover && highlightedItem === item ? " highlighted" : "";
10258
- const errorSuffix = (isError == null ? void 0 : isError(item, index)) ? " error" : "";
10259
- const warningSuffix = (isWarning == null ? void 0 : isWarning(item, index)) ? " warning" : "";
10260
- const infoSuffix = (isInfo == null ? void 0 : isInfo(item, index)) ? " info" : "";
10261
10408
  const indentation = (indent == null ? void 0 : indent(item, index)) || 0;
10262
10409
  const rendered = render(item, index);
10263
10410
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
10264
10411
  "div",
10265
10412
  {
10413
+ onDoubleClick: () => onAccepted == null ? void 0 : onAccepted(item, index),
10266
10414
  role: "listitem",
10267
- className: "list-view-entry" + selectedSuffix + highlightedSuffix + errorSuffix + warningSuffix + infoSuffix,
10415
+ className: clsx(
10416
+ "list-view-entry",
10417
+ selectedItem === item && "selected",
10418
+ !notSelectable && highlightedItem === item && "highlighted",
10419
+ (isError == null ? void 0 : isError(item, index)) && "error",
10420
+ (isWarning == null ? void 0 : isWarning(item, index)) && "warning",
10421
+ (isInfo == null ? void 0 : isInfo(item, index)) && "info"
10422
+ ),
10268
10423
  onClick: () => onSelected == null ? void 0 : onSelected(item, index),
10269
10424
  onMouseEnter: () => setHighlightedItem(item),
10270
10425
  onMouseLeave: () => setHighlightedItem(void 0),
@@ -10487,7 +10642,8 @@ const renderAction = (action, options) => {
10487
10642
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "action-title", title: action.apiName, children: [
10488
10643
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: action.apiName }),
10489
10644
  locator && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "action-selector", title: locator, children: locator }),
10490
- action.method === "goto" && action.params.url && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "action-url", title: action.params.url, children: action.params.url })
10645
+ action.method === "goto" && action.params.url && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "action-url", title: action.params.url, children: action.params.url }),
10646
+ action.class === "APIRequestContext" && action.params.url && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "action-url", title: action.params.url, children: excludeOrigin(action.params.url) })
10491
10647
  ] }),
10492
10648
  (showDuration || showBadges) && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "spacer" }),
10493
10649
  showDuration && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "action-duration", children: time || /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "codicon codicon-loading" }) }),
@@ -10503,19 +10659,27 @@ const renderAction = (action, options) => {
10503
10659
  ] })
10504
10660
  ] });
10505
10661
  };
10506
- const CopyToClipboard = ({ value }) => {
10507
- const [iconClassName, setIconClassName] = reactExports.useState("codicon-clippy");
10662
+ function excludeOrigin(url) {
10663
+ try {
10664
+ const urlObject = new URL(url);
10665
+ return urlObject.pathname + urlObject.search;
10666
+ } catch (error) {
10667
+ return url;
10668
+ }
10669
+ }
10670
+ const CopyToClipboard = ({ value, description }) => {
10671
+ const [icon, setIcon] = reactExports.useState("copy");
10508
10672
  const handleCopy = reactExports.useCallback(() => {
10509
10673
  navigator.clipboard.writeText(value).then(() => {
10510
- setIconClassName("codicon-check");
10674
+ setIcon("check");
10511
10675
  setTimeout(() => {
10512
- setIconClassName("codicon-clippy");
10676
+ setIcon("copy");
10513
10677
  }, 3e3);
10514
10678
  }, () => {
10515
- setIconClassName("codicon-close");
10679
+ setIcon("close");
10516
10680
  });
10517
10681
  }, [value]);
10518
- return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `copy-icon codicon ${iconClassName}`, onClick: handleCopy });
10682
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { title: description ? description : "Copy", icon, onClick: handleCopy });
10519
10683
  };
10520
10684
  const PlaceholderPanel = ({ text }) => {
10521
10685
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fill", style: {
@@ -10533,7 +10697,8 @@ const CallTab = ({ action, sdkLanguage }) => {
10533
10697
  const params = { ...action.params };
10534
10698
  delete params.info;
10535
10699
  const paramKeys = Object.keys(params);
10536
- const wallTime = action.wallTime ? new Date(action.wallTime).toLocaleString() : null;
10700
+ const timeMillis = action.startTime + (action.context.wallTime - action.context.startTime);
10701
+ const wallTime = new Date(timeMillis).toLocaleString();
10537
10702
  const duration = action.endTime ? msToString(action.endTime - action.startTime) : "Timed Out";
10538
10703
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-tab", children: [
10539
10704
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-line", children: action.apiName }),
@@ -10563,7 +10728,7 @@ function renderProperty(property, key) {
10563
10728
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
10564
10729
  property.name,
10565
10730
  ":",
10566
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `call-value ${property.type}`, title: property.text, children: text }),
10731
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: clsx("call-value", property.type), title: property.text, children: text }),
10567
10732
  ["string", "number", "object", "locator"].includes(property.type) && /* @__PURE__ */ jsxRuntimeExports.jsx(CopyToClipboard, { value: property.text })
10568
10733
  ] }, key);
10569
10734
  }
@@ -10631,7 +10796,7 @@ const LogTab = ({ action, isLive }) => {
10631
10796
  if (!action || !action.log.length)
10632
10797
  return [];
10633
10798
  const log = action.log;
10634
- const wallTimeOffset = action.wallTime - action.startTime;
10799
+ const wallTimeOffset = action.context.wallTime - action.context.startTime;
10635
10800
  const entries2 = [];
10636
10801
  for (let i = 0; i < log.length; ++i) {
10637
10802
  let time = "";
@@ -10664,7 +10829,7 @@ const LogTab = ({ action, isLive }) => {
10664
10829
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "log-list-duration", children: entry.time }),
10665
10830
  entry.message
10666
10831
  ] }),
10667
- noHighlightOnHover: true
10832
+ notSelectable: true
10668
10833
  }
10669
10834
  );
10670
10835
  };
@@ -10886,21 +11051,23 @@ function useConsoleTabModel(model, selectedTime) {
10886
11051
  }, [entries, selectedTime]);
10887
11052
  return { entries: filteredEntries };
10888
11053
  }
10889
- const ConsoleTab = ({ consoleModel, boundaries }) => {
11054
+ const ConsoleTab = ({ consoleModel, boundaries, onEntryHovered, onAccepted }) => {
10890
11055
  if (!consoleModel.entries.length)
10891
11056
  return /* @__PURE__ */ jsxRuntimeExports.jsx(PlaceholderPanel, { text: "No console entries" });
10892
11057
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "console-tab", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
10893
11058
  ConsoleListView,
10894
11059
  {
10895
11060
  name: "console",
11061
+ onAccepted,
11062
+ onHighlighted: onEntryHovered,
10896
11063
  items: consoleModel.entries,
10897
11064
  isError: (entry) => entry.isError,
10898
11065
  isWarning: (entry) => entry.isWarning,
10899
11066
  render: (entry) => {
10900
11067
  const timestamp = msToString(entry.timestamp - boundaries.minimum);
10901
11068
  const timestampElement = /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "console-time", children: timestamp });
10902
- const errorSuffix = entry.isError ? " status-error" : entry.isWarning ? " status-warning" : " status-none";
10903
- const statusElement = entry.browserMessage || entry.browserError ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "codicon codicon-browser" + errorSuffix, title: "Browser message" }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "codicon codicon-file" + errorSuffix, title: "Runner message" });
11069
+ const errorSuffix = entry.isError ? "status-error" : entry.isWarning ? "status-warning" : "status-none";
11070
+ const statusElement = entry.browserMessage || entry.browserError ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: clsx("codicon", "codicon-browser", errorSuffix), title: "Browser message" }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: clsx("codicon", "codicon-file", errorSuffix), title: "Runner message" });
10904
11071
  let locationText;
10905
11072
  let messageBody;
10906
11073
  let messageInnerHTML;
@@ -11010,9 +11177,11 @@ function supportProperty(cssKey) {
11010
11177
  const Toolbar = ({
11011
11178
  noShadow,
11012
11179
  children,
11013
- noMinHeight
11180
+ noMinHeight,
11181
+ className,
11182
+ onClick
11014
11183
  }) => {
11015
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "toolbar" + (noShadow ? " no-shadow" : "") + (noMinHeight ? " no-min-height" : ""), children });
11184
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: clsx("toolbar", noShadow && "no-shadow", noMinHeight && "no-min-height", className), onClick, children });
11016
11185
  };
11017
11186
  const TabbedPane = ({ tabs, selectedTab, setSelectedTab, leftToolbar, rightToolbar, dataTestId, mode }) => {
11018
11187
  if (!mode)
@@ -11032,25 +11201,22 @@ const TabbedPane = ({ tabs, selectedTab, setSelectedTab, leftToolbar, rightToolb
11032
11201
  errorCount: tab.errorCount,
11033
11202
  selected: selectedTab === tab.id,
11034
11203
  onSelect: setSelectedTab
11035
- }
11204
+ },
11205
+ tab.id
11036
11206
  ))
11037
11207
  ] }),
11038
11208
  mode === "select" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { flex: "auto", display: "flex", height: "100%", overflow: "hidden" }, children: /* @__PURE__ */ jsxRuntimeExports.jsx("select", { style: { width: "100%", background: "none", cursor: "pointer" }, onChange: (e) => {
11039
11209
  setSelectedTab(tabs[e.currentTarget.selectedIndex].id);
11040
11210
  }, children: tabs.map((tab) => {
11041
11211
  let suffix = "";
11042
- if (tab.count === 1)
11043
- suffix = " 🔵";
11044
- else if (tab.count)
11045
- suffix = ` 🔵✖️${tab.count}`;
11046
- if (tab.errorCount === 1)
11047
- suffix = ` 🔴`;
11048
- else if (tab.errorCount)
11049
- suffix = ` 🔴✖️${tab.errorCount}`;
11212
+ if (tab.count)
11213
+ suffix = ` (${tab.count})`;
11214
+ if (tab.errorCount)
11215
+ suffix = ` (${tab.errorCount})`;
11050
11216
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("option", { value: tab.id, selected: tab.id === selectedTab, children: [
11051
11217
  tab.title,
11052
11218
  suffix
11053
- ] });
11219
+ ] }, tab.id);
11054
11220
  }) }) }),
11055
11221
  rightToolbar && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { flex: "none", display: "flex", alignItems: "center" }, children: [
11056
11222
  ...rightToolbar
@@ -11069,7 +11235,7 @@ const TabbedPaneTab = ({ id: id2, title, count, errorCount, selected, onSelect }
11069
11235
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
11070
11236
  "div",
11071
11237
  {
11072
- className: "tabbed-pane-tab " + (selected ? "selected" : ""),
11238
+ className: clsx("tabbed-pane-tab", selected && "selected"),
11073
11239
  onClick: () => onSelect(id2),
11074
11240
  title,
11075
11241
  children: [
@@ -11090,6 +11256,8 @@ const __vitePreload = function preload(baseModule, deps, importerUrl) {
11090
11256
  let promise = Promise.resolve();
11091
11257
  if (deps && deps.length > 0) {
11092
11258
  const links = document.getElementsByTagName("link");
11259
+ const cspNonceMeta = document.querySelector("meta[property=csp-nonce]");
11260
+ const cspNonce = (cspNonceMeta == null ? void 0 : cspNonceMeta.nonce) || (cspNonceMeta == null ? void 0 : cspNonceMeta.getAttribute("nonce"));
11093
11261
  promise = Promise.all(deps.map((dep) => {
11094
11262
  dep = assetsURL(dep, importerUrl);
11095
11263
  if (dep in seen)
@@ -11115,6 +11283,9 @@ const __vitePreload = function preload(baseModule, deps, importerUrl) {
11115
11283
  link.crossOrigin = "";
11116
11284
  }
11117
11285
  link.href = dep;
11286
+ if (cspNonce) {
11287
+ link.setAttribute("nonce", cspNonce);
11288
+ }
11118
11289
  document.head.appendChild(link);
11119
11290
  if (isCss) {
11120
11291
  return new Promise((res, rej) => {
@@ -11136,6 +11307,8 @@ const __vitePreload = function preload(baseModule, deps, importerUrl) {
11136
11307
  const CodeMirrorWrapper = ({
11137
11308
  text,
11138
11309
  language,
11310
+ mimeType,
11311
+ linkify,
11139
11312
  readOnly,
11140
11313
  highlight,
11141
11314
  revealLine,
@@ -11146,29 +11319,18 @@ const CodeMirrorWrapper = ({
11146
11319
  onChange
11147
11320
  }) => {
11148
11321
  const [measure, codemirrorElement] = useMeasure();
11149
- const [modulePromise] = reactExports.useState(__vitePreload(() => import("./codeMirrorModule-clyjx5sb.js"), true ? __vite__mapDeps([0,1]) : void 0, import.meta.url).then((m2) => m2.default));
11322
+ const [modulePromise] = reactExports.useState(__vitePreload(() => import("./codeMirrorModule-5yiV-3wl.js"), true ? __vite__mapDeps([0,1]) : void 0, import.meta.url).then((m2) => m2.default));
11150
11323
  const codemirrorRef = reactExports.useRef(null);
11151
11324
  const [codemirror, setCodemirror] = reactExports.useState();
11152
11325
  reactExports.useEffect(() => {
11153
11326
  (async () => {
11154
11327
  var _a, _b;
11155
11328
  const CodeMirror = await modulePromise;
11329
+ defineCustomMode(CodeMirror);
11156
11330
  const element = codemirrorElement.current;
11157
11331
  if (!element)
11158
11332
  return;
11159
- let mode = "";
11160
- if (language === "javascript")
11161
- mode = "javascript";
11162
- if (language === "python")
11163
- mode = "python";
11164
- if (language === "java")
11165
- mode = "text/x-java";
11166
- if (language === "csharp")
11167
- mode = "text/x-csharp";
11168
- if (language === "html")
11169
- mode = "htmlmixed";
11170
- if (language === "css")
11171
- mode = "css";
11333
+ const mode = languageToMode(language) || mimeTypeToMode(mimeType) || (linkify ? "text/linkified" : "");
11172
11334
  if (codemirrorRef.current && mode === codemirrorRef.current.cm.getOption("mode") && !!readOnly === codemirrorRef.current.cm.getOption("readOnly") && lineNumbers === codemirrorRef.current.cm.getOption("lineNumbers") && wrapLines === codemirrorRef.current.cm.getOption("lineWrapping")) {
11173
11335
  return;
11174
11336
  }
@@ -11186,7 +11348,7 @@ const CodeMirrorWrapper = ({
11186
11348
  setCodemirror(cm);
11187
11349
  return cm;
11188
11350
  })();
11189
- }, [modulePromise, codemirror, codemirrorElement, language, lineNumbers, wrapLines, readOnly, isFocused]);
11351
+ }, [modulePromise, codemirror, codemirrorElement, language, mimeType, linkify, lineNumbers, wrapLines, readOnly, isFocused]);
11190
11352
  reactExports.useEffect(() => {
11191
11353
  if (codemirrorRef.current)
11192
11354
  codemirrorRef.current.cm.setSize(measure.width, measure.height);
@@ -11242,15 +11404,74 @@ const CodeMirrorWrapper = ({
11242
11404
  codemirror.off("change", changeListener);
11243
11405
  };
11244
11406
  }, [codemirror, text, highlight, revealLine, focusOnChange, onChange]);
11245
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "cm-wrapper", ref: codemirrorElement });
11407
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "cm-wrapper", ref: codemirrorElement, onClick: onCodeMirrorClick });
11246
11408
  };
11409
+ function onCodeMirrorClick(event) {
11410
+ var _a;
11411
+ if (!(event.target instanceof HTMLElement))
11412
+ return;
11413
+ let url;
11414
+ if (event.target.classList.contains("cm-linkified")) {
11415
+ url = event.target.textContent;
11416
+ } else if (event.target.classList.contains("cm-link") && ((_a = event.target.nextElementSibling) == null ? void 0 : _a.classList.contains("cm-url"))) {
11417
+ url = event.target.nextElementSibling.textContent.slice(1, -1);
11418
+ }
11419
+ if (url) {
11420
+ event.preventDefault();
11421
+ event.stopPropagation();
11422
+ window.open(url, "_blank");
11423
+ }
11424
+ }
11425
+ let customModeDefined = false;
11426
+ function defineCustomMode(cm) {
11427
+ if (customModeDefined)
11428
+ return;
11429
+ customModeDefined = true;
11430
+ cm.defineSimpleMode("text/linkified", {
11431
+ start: [
11432
+ { regex: kWebLinkRe, token: "linkified" }
11433
+ ]
11434
+ });
11435
+ }
11436
+ function mimeTypeToMode(mimeType) {
11437
+ if (!mimeType)
11438
+ return;
11439
+ if (mimeType.includes("javascript") || mimeType.includes("json"))
11440
+ return "javascript";
11441
+ if (mimeType.includes("python"))
11442
+ return "python";
11443
+ if (mimeType.includes("csharp"))
11444
+ return "text/x-csharp";
11445
+ if (mimeType.includes("java"))
11446
+ return "text/x-java";
11447
+ if (mimeType.includes("markdown"))
11448
+ return "markdown";
11449
+ if (mimeType.includes("html") || mimeType.includes("svg"))
11450
+ return "htmlmixed";
11451
+ if (mimeType.includes("css"))
11452
+ return "css";
11453
+ }
11454
+ function languageToMode(language) {
11455
+ if (!language)
11456
+ return;
11457
+ return {
11458
+ javascript: "javascript",
11459
+ jsonl: "javascript",
11460
+ python: "python",
11461
+ csharp: "text/x-csharp",
11462
+ java: "text/x-java",
11463
+ markdown: "markdown",
11464
+ html: "htmlmixed",
11465
+ css: "css"
11466
+ }[language];
11467
+ }
11247
11468
  const NetworkResourceDetails = ({ resource, onClose }) => {
11248
11469
  const [selectedTab, setSelectedTab] = reactExports.useState("request");
11249
11470
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
11250
11471
  TabbedPane,
11251
11472
  {
11252
11473
  dataTestId: "network-request-details",
11253
- leftToolbar: [/* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "close", title: "Close", onClick: onClose })],
11474
+ leftToolbar: [/* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "close", title: "Close", onClick: onClose }, "close")],
11254
11475
  tabs: [
11255
11476
  {
11256
11477
  id: "request",
@@ -11278,26 +11499,36 @@ const RequestTab = ({ resource }) => {
11278
11499
  reactExports.useEffect(() => {
11279
11500
  const readResources = async () => {
11280
11501
  if (resource.request.postData) {
11281
- const requestContentTypeHeader = resource.request.headers.find((q2) => q2.name === "Content-Type");
11502
+ const requestContentTypeHeader = resource.request.headers.find((q2) => q2.name.toLowerCase() === "content-type");
11282
11503
  const requestContentType = requestContentTypeHeader ? requestContentTypeHeader.value : "";
11283
- const language = mimeTypeToHighlighter(requestContentType);
11284
11504
  if (resource.request.postData._sha1) {
11285
11505
  const response = await fetch(`sha1/${resource.request.postData._sha1}`);
11286
- setRequestBody({ text: formatBody(await response.text(), requestContentType), language });
11506
+ setRequestBody({ text: formatBody(await response.text(), requestContentType), mimeType: requestContentType });
11287
11507
  } else {
11288
- setRequestBody({ text: formatBody(resource.request.postData.text, requestContentType), language });
11508
+ setRequestBody({ text: formatBody(resource.request.postData.text, requestContentType), mimeType: requestContentType });
11289
11509
  }
11510
+ } else {
11511
+ setRequestBody(null);
11290
11512
  }
11291
11513
  };
11292
11514
  readResources();
11293
11515
  }, [resource]);
11294
11516
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "network-request-details-tab", children: [
11295
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "network-request-details-header", children: "URL" }),
11296
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "network-request-details-url", children: resource.request.url }),
11517
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "network-request-details-header", children: "General" }),
11518
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "network-request-details-url", children: `URL: ${resource.request.url}` }),
11519
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "network-request-details-general", children: `Method: ${resource.request.method}` }),
11520
+ resource.response.status !== -1 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "network-request-details-general", style: { display: "flex" }, children: [
11521
+ "Status Code: ",
11522
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: statusClass(resource.response.status), style: { display: "inline-flex" }, children: `${resource.response.status} ${resource.response.statusText}` })
11523
+ ] }),
11524
+ resource.request.queryString.length ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
11525
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "network-request-details-header", children: "Query String Parameters" }),
11526
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "network-request-details-headers", children: resource.request.queryString.map((param) => `${param.name}: ${param.value}`).join("\n") })
11527
+ ] }) : null,
11297
11528
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "network-request-details-header", children: "Request Headers" }),
11298
11529
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "network-request-details-headers", children: resource.request.headers.map((pair) => `${pair.name}: ${pair.value}`).join("\n") }),
11299
11530
  requestBody && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "network-request-details-header", children: "Request Body" }),
11300
- requestBody && /* @__PURE__ */ jsxRuntimeExports.jsx(CodeMirrorWrapper, { text: requestBody.text, language: requestBody.language, readOnly: true, lineNumbers: true })
11531
+ requestBody && /* @__PURE__ */ jsxRuntimeExports.jsx(CodeMirrorWrapper, { text: requestBody.text, mimeType: requestBody.mimeType, readOnly: true, lineNumbers: true })
11301
11532
  ] });
11302
11533
  };
11303
11534
  const ResponseTab = ({ resource }) => {
@@ -11312,6 +11543,7 @@ const BodyTab = ({ resource }) => {
11312
11543
  const readResources = async () => {
11313
11544
  if (resource.response.content._sha1) {
11314
11545
  const useBase64 = resource.response.content.mimeType.includes("image");
11546
+ const isFont = resource.response.content.mimeType.includes("font");
11315
11547
  const response = await fetch(`sha1/${resource.response.content._sha1}`);
11316
11548
  if (useBase64) {
11317
11549
  const blob = await response.blob();
@@ -11319,21 +11551,64 @@ const BodyTab = ({ resource }) => {
11319
11551
  const eventPromise = new Promise((f2) => reader.onload = f2);
11320
11552
  reader.readAsDataURL(blob);
11321
11553
  setResponseBody({ dataUrl: (await eventPromise).target.result });
11554
+ } else if (isFont) {
11555
+ const font = await response.arrayBuffer();
11556
+ setResponseBody({ font });
11322
11557
  } else {
11323
11558
  const formattedBody = formatBody(await response.text(), resource.response.content.mimeType);
11324
- const language = mimeTypeToHighlighter(resource.response.content.mimeType);
11325
- setResponseBody({ text: formattedBody, language });
11559
+ setResponseBody({ text: formattedBody, mimeType: resource.response.content.mimeType });
11326
11560
  }
11561
+ } else {
11562
+ setResponseBody(null);
11327
11563
  }
11328
11564
  };
11329
11565
  readResources();
11330
11566
  }, [resource]);
11331
11567
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "network-request-details-tab", children: [
11332
11568
  !resource.response.content._sha1 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Response body is not available for this request." }),
11569
+ responseBody && responseBody.font && /* @__PURE__ */ jsxRuntimeExports.jsx(FontPreview, { font: responseBody.font }),
11333
11570
  responseBody && responseBody.dataUrl && /* @__PURE__ */ jsxRuntimeExports.jsx("img", { draggable: "false", src: responseBody.dataUrl }),
11334
- responseBody && responseBody.text && /* @__PURE__ */ jsxRuntimeExports.jsx(CodeMirrorWrapper, { text: responseBody.text, language: responseBody.language, readOnly: true, lineNumbers: true })
11571
+ responseBody && responseBody.text && /* @__PURE__ */ jsxRuntimeExports.jsx(CodeMirrorWrapper, { text: responseBody.text, mimeType: responseBody.mimeType, readOnly: true, lineNumbers: true })
11572
+ ] });
11573
+ };
11574
+ const FontPreview = ({ font }) => {
11575
+ const [isError, setIsError] = reactExports.useState(false);
11576
+ reactExports.useEffect(() => {
11577
+ let fontFace;
11578
+ try {
11579
+ fontFace = new FontFace("font-preview", font);
11580
+ if (fontFace.status === "loaded")
11581
+ document.fonts.add(fontFace);
11582
+ if (fontFace.status === "error")
11583
+ setIsError(true);
11584
+ } catch {
11585
+ setIsError(true);
11586
+ }
11587
+ return () => {
11588
+ document.fonts.delete(fontFace);
11589
+ };
11590
+ }, [font]);
11591
+ if (isError)
11592
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "network-font-preview-error", children: "Could not load font preview" });
11593
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "network-font-preview", children: [
11594
+ "ABCDEFGHIJKLM",
11595
+ /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
11596
+ "NOPQRSTUVWXYZ",
11597
+ /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
11598
+ "abcdefghijklm",
11599
+ /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
11600
+ "nopqrstuvwxyz",
11601
+ /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
11602
+ "1234567890"
11335
11603
  ] });
11336
11604
  };
11605
+ function statusClass(statusCode) {
11606
+ if (statusCode < 300 || statusCode === 304)
11607
+ return "green-circle";
11608
+ if (statusCode < 400)
11609
+ return "yellow-circle";
11610
+ return "red-circle";
11611
+ }
11337
11612
  function formatBody(body, contentType) {
11338
11613
  if (body === null)
11339
11614
  return "Loading...";
@@ -11351,14 +11626,6 @@ function formatBody(body, contentType) {
11351
11626
  return decodeURIComponent(bodyStr);
11352
11627
  return bodyStr;
11353
11628
  }
11354
- function mimeTypeToHighlighter(mimeType) {
11355
- if (mimeType.includes("javascript") || mimeType.includes("json"))
11356
- return "javascript";
11357
- if (mimeType.includes("html"))
11358
- return "html";
11359
- if (mimeType.includes("css"))
11360
- return "css";
11361
- }
11362
11629
  const GlassPane = ({ cursor, onPaneMouseMove, onPaneMouseUp, onPaneDoubleClick }) => {
11363
11630
  React.useEffect(() => {
11364
11631
  const glassPaneDiv = document.createElement("div");
@@ -11422,7 +11689,8 @@ const ResizeView = ({ orientation, offsets, setOffsets, resizerColor, resizerWid
11422
11689
  right: 0,
11423
11690
  bottom: 0,
11424
11691
  left: -(7 - resizerWidth) / 2,
11425
- zIndex: 1e3,
11692
+ zIndex: 100,
11693
+ // Above the content, but below the film strip hover.
11426
11694
  pointerEvents: "none"
11427
11695
  },
11428
11696
  ref,
@@ -11463,7 +11731,8 @@ const ResizeView = ({ orientation, offsets, setOffsets, resizerColor, resizerWid
11463
11731
  ...fillStyle,
11464
11732
  background: resizerColor
11465
11733
  } })
11466
- }
11734
+ },
11735
+ index
11467
11736
  );
11468
11737
  })
11469
11738
  ]
@@ -11471,12 +11740,24 @@ const ResizeView = ({ orientation, offsets, setOffsets, resizerColor, resizerWid
11471
11740
  );
11472
11741
  };
11473
11742
  function GridView(model) {
11474
- const initialOffsets = [];
11475
- for (let i = 0; i < model.columns.length - 1; ++i) {
11476
- const column = model.columns[i];
11477
- initialOffsets[i] = (initialOffsets[i - 1] || 0) + model.columnWidth(column);
11743
+ const [offsets, setOffsets] = reactExports.useState([]);
11744
+ reactExports.useEffect(() => {
11745
+ const offsets2 = [];
11746
+ for (let i = 0; i < model.columns.length - 1; ++i) {
11747
+ const column = model.columns[i];
11748
+ offsets2[i] = (offsets2[i - 1] || 0) + model.columnWidths.get(column);
11749
+ }
11750
+ setOffsets(offsets2);
11751
+ }, [model.columns, model.columnWidths]);
11752
+ function updateColumnWidths(offsets2) {
11753
+ const widths = new Map(model.columnWidths.entries());
11754
+ for (let i = 0; i < offsets2.length; ++i) {
11755
+ const width = offsets2[i] - (offsets2[i - 1] || 0);
11756
+ const column = model.columns[i];
11757
+ widths.set(column, width);
11758
+ }
11759
+ model.setColumnWidths(widths);
11478
11760
  }
11479
- const [offsets, setOffsets] = reactExports.useState(initialOffsets);
11480
11761
  const toggleSorting = reactExports.useCallback((f2) => {
11481
11762
  var _a, _b;
11482
11763
  (_b = model.setSorting) == null ? void 0 : _b.call(model, { by: f2, negate: ((_a = model.sorting) == null ? void 0 : _a.by) === f2 ? !model.sorting.negate : false });
@@ -11487,7 +11768,7 @@ function GridView(model) {
11487
11768
  {
11488
11769
  orientation: "horizontal",
11489
11770
  offsets,
11490
- setOffsets,
11771
+ setOffsets: updateColumnWidths,
11491
11772
  resizerColor: "var(--vscode-panel-border)",
11492
11773
  resizerWidth: 1,
11493
11774
  minColumnWidth: 25
@@ -11500,7 +11781,7 @@ function GridView(model) {
11500
11781
  {
11501
11782
  className: "grid-view-header-cell " + sortingHeader(column, model.sorting),
11502
11783
  style: {
11503
- width: offsets[i] - (offsets[i - 1] || 0)
11784
+ width: i < model.columns.length - 1 ? model.columnWidths.get(column) : void 0
11504
11785
  },
11505
11786
  onClick: () => model.setSorting && toggleSorting(column),
11506
11787
  children: [
@@ -11508,7 +11789,8 @@ function GridView(model) {
11508
11789
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "codicon codicon-triangle-up" }),
11509
11790
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "codicon codicon-triangle-down" })
11510
11791
  ]
11511
- }
11792
+ },
11793
+ model.columnTitle(column)
11512
11794
  );
11513
11795
  }) }),
11514
11796
  /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -11525,9 +11807,12 @@ function GridView(model) {
11525
11807
  {
11526
11808
  className: `grid-view-cell grid-view-column-${String(column)}`,
11527
11809
  title,
11528
- style: { width: offsets[i] - (offsets[i - 1] || 0) },
11810
+ style: {
11811
+ width: i < model.columns.length - 1 ? model.columnWidths.get(column) : void 0
11812
+ },
11529
11813
  children: body
11530
- }
11814
+ },
11815
+ model.columnTitle(column)
11531
11816
  );
11532
11817
  }) });
11533
11818
  },
@@ -11545,7 +11830,7 @@ function GridView(model) {
11545
11830
  onIconClicked: model.onIconClicked,
11546
11831
  noItemsMessage: model.noItemsMessage,
11547
11832
  dataTestId: model.dataTestId,
11548
- noHighlightOnHover: model.noHighlightOnHover
11833
+ notSelectable: model.notSelectable
11549
11834
  }
11550
11835
  )
11551
11836
  ] })
@@ -11554,6 +11839,32 @@ function GridView(model) {
11554
11839
  function sortingHeader(column, sorting) {
11555
11840
  return column === (sorting == null ? void 0 : sorting.by) ? " filter-" + (sorting.negate ? "negative" : "positive") : "";
11556
11841
  }
11842
+ const resourceTypes = ["All", "Fetch", "HTML", "JS", "CSS", "Font", "Image"];
11843
+ const defaultFilterState = { searchValue: "", resourceType: "All" };
11844
+ const NetworkFilters = ({ filterState, onFilterStateChange }) => {
11845
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "network-filters", children: [
11846
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
11847
+ "input",
11848
+ {
11849
+ type: "search",
11850
+ placeholder: "Filter network",
11851
+ spellCheck: false,
11852
+ value: filterState.searchValue,
11853
+ onChange: (e) => onFilterStateChange({ ...filterState, searchValue: e.target.value })
11854
+ }
11855
+ ),
11856
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "network-filters-resource-types", children: resourceTypes.map((resourceType) => /* @__PURE__ */ jsxRuntimeExports.jsx(
11857
+ "div",
11858
+ {
11859
+ title: resourceType,
11860
+ onClick: () => onFilterStateChange({ ...filterState, resourceType }),
11861
+ className: `network-filters-resource-type ${filterState.resourceType === resourceType ? "selected" : ""}`,
11862
+ children: resourceType
11863
+ },
11864
+ resourceType
11865
+ )) })
11866
+ ] });
11867
+ };
11557
11868
  const NetworkGridView = GridView;
11558
11869
  function useNetworkTabModel(model, selectedTime) {
11559
11870
  const resources = reactExports.useMemo(() => {
@@ -11565,17 +11876,26 @@ function useNetworkTabModel(model, selectedTime) {
11565
11876
  });
11566
11877
  return filtered;
11567
11878
  }, [model, selectedTime]);
11568
- return { resources };
11879
+ const contextIdMap = reactExports.useMemo(() => new ContextIdMap(model), [model]);
11880
+ return { resources, contextIdMap };
11569
11881
  }
11570
11882
  const NetworkTab = ({ boundaries, networkModel, onEntryHovered }) => {
11571
11883
  const [sorting, setSorting] = reactExports.useState(void 0);
11572
11884
  const [selectedEntry, setSelectedEntry] = reactExports.useState(void 0);
11885
+ const [filterState, setFilterState] = reactExports.useState(defaultFilterState);
11573
11886
  const { renderedEntries } = reactExports.useMemo(() => {
11574
- const renderedEntries2 = networkModel.resources.map((entry) => renderEntry(entry, boundaries));
11887
+ const renderedEntries2 = networkModel.resources.map((entry) => renderEntry(entry, boundaries, networkModel.contextIdMap)).filter(filterEntry(filterState));
11575
11888
  if (sorting)
11576
11889
  sort(renderedEntries2, sorting);
11577
11890
  return { renderedEntries: renderedEntries2 };
11578
- }, [networkModel.resources, sorting, boundaries]);
11891
+ }, [networkModel.resources, networkModel.contextIdMap, filterState, sorting, boundaries]);
11892
+ const [columnWidths, setColumnWidths] = reactExports.useState(() => {
11893
+ return new Map(allColumns().map((column) => [column, columnWidth(column)]));
11894
+ });
11895
+ const onFilterStateChange = reactExports.useCallback((newFilterState) => {
11896
+ setFilterState(newFilterState);
11897
+ setSelectedEntry(void 0);
11898
+ }, []);
11579
11899
  if (!networkModel.resources.length)
11580
11900
  return /* @__PURE__ */ jsxRuntimeExports.jsx(PlaceholderPanel, { text: "No network calls" });
11581
11901
  const grid = /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -11586,10 +11906,11 @@ const NetworkTab = ({ boundaries, networkModel, onEntryHovered }) => {
11586
11906
  selectedItem: selectedEntry,
11587
11907
  onSelected: (item) => setSelectedEntry(item),
11588
11908
  onHighlighted: (item) => onEntryHovered(item == null ? void 0 : item.resource),
11589
- columns: selectedEntry ? ["name"] : ["name", "method", "status", "contentType", "duration", "size", "start", "route"],
11909
+ columns: visibleColumns(!!selectedEntry, renderedEntries),
11590
11910
  columnTitle,
11591
- columnWidth,
11592
- isError: (item) => item.status.code >= 400,
11911
+ columnWidths,
11912
+ setColumnWidths,
11913
+ isError: (item) => item.status.code >= 400 || item.status.code === -1,
11593
11914
  isInfo: (item) => !!item.route,
11594
11915
  render: (item, column) => renderCell(item, column),
11595
11916
  sorting,
@@ -11597,14 +11918,24 @@ const NetworkTab = ({ boundaries, networkModel, onEntryHovered }) => {
11597
11918
  }
11598
11919
  );
11599
11920
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
11921
+ /* @__PURE__ */ jsxRuntimeExports.jsx(NetworkFilters, { filterState, onFilterStateChange }),
11600
11922
  !selectedEntry && grid,
11601
- selectedEntry && /* @__PURE__ */ jsxRuntimeExports.jsxs(SplitView, { sidebarSize: 200, sidebarIsFirst: true, orientation: "horizontal", children: [
11602
- /* @__PURE__ */ jsxRuntimeExports.jsx(NetworkResourceDetails, { resource: selectedEntry.resource, onClose: () => setSelectedEntry(void 0) }),
11603
- grid
11604
- ] })
11923
+ selectedEntry && /* @__PURE__ */ jsxRuntimeExports.jsx(
11924
+ SplitView,
11925
+ {
11926
+ sidebarSize: columnWidths.get("name"),
11927
+ sidebarIsFirst: true,
11928
+ orientation: "horizontal",
11929
+ settingName: "networkResourceDetails",
11930
+ main: /* @__PURE__ */ jsxRuntimeExports.jsx(NetworkResourceDetails, { resource: selectedEntry.resource, onClose: () => setSelectedEntry(void 0) }),
11931
+ sidebar: grid
11932
+ }
11933
+ )
11605
11934
  ] });
11606
11935
  };
11607
11936
  const columnTitle = (column) => {
11937
+ if (column === "contextId")
11938
+ return "Source";
11608
11939
  if (column === "name")
11609
11940
  return "Name";
11610
11941
  if (column === "method")
@@ -11632,9 +11963,32 @@ const columnWidth = (column) => {
11632
11963
  return 60;
11633
11964
  if (column === "contentType")
11634
11965
  return 200;
11966
+ if (column === "contextId")
11967
+ return 60;
11635
11968
  return 100;
11636
11969
  };
11970
+ function visibleColumns(entrySelected, renderedEntries) {
11971
+ if (entrySelected) {
11972
+ const columns2 = ["name"];
11973
+ if (hasMultipleContexts(renderedEntries))
11974
+ columns2.unshift("contextId");
11975
+ return columns2;
11976
+ }
11977
+ let columns = allColumns();
11978
+ if (!hasMultipleContexts(renderedEntries))
11979
+ columns = columns.filter((name) => name !== "contextId");
11980
+ return columns;
11981
+ }
11982
+ function allColumns() {
11983
+ return ["contextId", "name", "method", "status", "contentType", "duration", "size", "start", "route"];
11984
+ }
11637
11985
  const renderCell = (entry, column) => {
11986
+ if (column === "contextId") {
11987
+ return {
11988
+ body: entry.contextId,
11989
+ title: entry.name.url
11990
+ };
11991
+ }
11638
11992
  if (column === "name") {
11639
11993
  return {
11640
11994
  body: entry.name.name,
@@ -11661,7 +12015,52 @@ const renderCell = (entry, column) => {
11661
12015
  return { body: entry.route };
11662
12016
  return { body: "" };
11663
12017
  };
11664
- const renderEntry = (resource, boundaries) => {
12018
+ class ContextIdMap {
12019
+ constructor(model) {
12020
+ __publicField(this, "_pagerefToShortId", /* @__PURE__ */ new Map());
12021
+ __publicField(this, "_contextToId", /* @__PURE__ */ new Map());
12022
+ __publicField(this, "_lastPageId", 0);
12023
+ __publicField(this, "_lastApiRequestContextId", 0);
12024
+ }
12025
+ contextId(resource) {
12026
+ if (resource.pageref)
12027
+ return this._pageId(resource.pageref);
12028
+ else if (resource._apiRequest)
12029
+ return this._apiRequestContextId(resource);
12030
+ return "";
12031
+ }
12032
+ _pageId(pageref) {
12033
+ let shortId = this._pagerefToShortId.get(pageref);
12034
+ if (!shortId) {
12035
+ ++this._lastPageId;
12036
+ shortId = "page#" + this._lastPageId;
12037
+ this._pagerefToShortId.set(pageref, shortId);
12038
+ }
12039
+ return shortId;
12040
+ }
12041
+ _apiRequestContextId(resource) {
12042
+ const contextEntry = context(resource);
12043
+ if (!contextEntry)
12044
+ return "";
12045
+ let contextId = this._contextToId.get(contextEntry);
12046
+ if (!contextId) {
12047
+ ++this._lastApiRequestContextId;
12048
+ contextId = "api#" + this._lastApiRequestContextId;
12049
+ this._contextToId.set(contextEntry, contextId);
12050
+ }
12051
+ return contextId;
12052
+ }
12053
+ }
12054
+ function hasMultipleContexts(renderedEntries) {
12055
+ const contextIds = /* @__PURE__ */ new Set();
12056
+ for (const entry of renderedEntries) {
12057
+ contextIds.add(entry.contextId);
12058
+ if (contextIds.size > 1)
12059
+ return true;
12060
+ }
12061
+ return false;
12062
+ }
12063
+ const renderEntry = (resource, boundaries, contextIdGenerator) => {
11665
12064
  const routeStatus = formatRouteStatus(resource);
11666
12065
  let resourceName;
11667
12066
  try {
@@ -11685,7 +12084,8 @@ const renderEntry = (resource, boundaries) => {
11685
12084
  size: resource.response._transferSize > 0 ? resource.response._transferSize : resource.response.bodySize,
11686
12085
  start: resource._monotonicTime - boundaries.minimum,
11687
12086
  route: routeStatus,
11688
- resource
12087
+ resource,
12088
+ contextId: contextIdGenerator.contextId(resource)
11689
12089
  };
11690
12090
  };
11691
12091
  function formatRouteStatus(request) {
@@ -11740,6 +12140,23 @@ function comparator(sortBy) {
11740
12140
  return a.route.localeCompare(b.route);
11741
12141
  };
11742
12142
  }
12143
+ if (sortBy === "contextId")
12144
+ return (a, b) => a.contextId.localeCompare(b.contextId);
12145
+ }
12146
+ const resourceTypePredicates = {
12147
+ "All": () => true,
12148
+ "Fetch": (contentType) => contentType === "application/json",
12149
+ "HTML": (contentType) => contentType === "text/html",
12150
+ "CSS": (contentType) => contentType === "text/css",
12151
+ "JS": (contentType) => contentType.includes("javascript"),
12152
+ "Font": (contentType) => contentType.includes("font"),
12153
+ "Image": (contentType) => contentType.includes("image")
12154
+ };
12155
+ function filterEntry({ searchValue, resourceType }) {
12156
+ return (entry) => {
12157
+ const typePredicate = resourceTypePredicates[resourceType];
12158
+ return typePredicate(entry.contentType) && entry.name.url.toLowerCase().includes(searchValue.toLowerCase());
12159
+ };
11743
12160
  }
11744
12161
  const XPathEngine = {
11745
12162
  queryAll(root, selector) {
@@ -11807,7 +12224,7 @@ function isElementStyleVisibilityVisible(element, style) {
11807
12224
  if (!style)
11808
12225
  return true;
11809
12226
  if (Element.prototype.checkVisibility && browserNameForWorkarounds !== "webkit") {
11810
- if (!element.checkVisibility({ checkOpacity: false, checkVisibilityCSS: false }))
12227
+ if (!element.checkVisibility())
11811
12228
  return false;
11812
12229
  } else {
11813
12230
  const detailsOrSummary = element.closest("details,summary");
@@ -11842,35 +12259,62 @@ function isVisibleTextNode(node) {
11842
12259
  const rect = range.getBoundingClientRect();
11843
12260
  return rect.width > 0 && rect.height > 0;
11844
12261
  }
12262
+ function elementSafeTagName(element) {
12263
+ if (element instanceof HTMLFormElement)
12264
+ return "FORM";
12265
+ return element.tagName.toUpperCase();
12266
+ }
11845
12267
  function hasExplicitAccessibleName(e) {
11846
12268
  return e.hasAttribute("aria-label") || e.hasAttribute("aria-labelledby");
11847
12269
  }
11848
12270
  const kAncestorPreventingLandmark = "article:not([role]), aside:not([role]), main:not([role]), nav:not([role]), section:not([role]), [role=article], [role=complementary], [role=main], [role=navigation], [role=region]";
11849
- const kGlobalAriaAttributes = [
11850
- "aria-atomic",
11851
- "aria-busy",
11852
- "aria-controls",
11853
- "aria-current",
11854
- "aria-describedby",
11855
- "aria-details",
11856
- "aria-disabled",
11857
- "aria-dropeffect",
11858
- "aria-errormessage",
11859
- "aria-flowto",
11860
- "aria-grabbed",
11861
- "aria-haspopup",
11862
- "aria-hidden",
11863
- "aria-invalid",
11864
- "aria-keyshortcuts",
11865
- "aria-label",
11866
- "aria-labelledby",
11867
- "aria-live",
11868
- "aria-owns",
11869
- "aria-relevant",
11870
- "aria-roledescription"
11871
- ];
11872
- function hasGlobalAriaAttribute(e) {
11873
- return kGlobalAriaAttributes.some((a) => e.hasAttribute(a));
12271
+ const kGlobalAriaAttributes = /* @__PURE__ */ new Map([
12272
+ ["aria-atomic", void 0],
12273
+ ["aria-busy", void 0],
12274
+ ["aria-controls", void 0],
12275
+ ["aria-current", void 0],
12276
+ ["aria-describedby", void 0],
12277
+ ["aria-details", void 0],
12278
+ // Global use deprecated in ARIA 1.2
12279
+ // ['aria-disabled', undefined],
12280
+ ["aria-dropeffect", void 0],
12281
+ // Global use deprecated in ARIA 1.2
12282
+ // ['aria-errormessage', undefined],
12283
+ ["aria-flowto", void 0],
12284
+ ["aria-grabbed", void 0],
12285
+ // Global use deprecated in ARIA 1.2
12286
+ // ['aria-haspopup', undefined],
12287
+ ["aria-hidden", void 0],
12288
+ // Global use deprecated in ARIA 1.2
12289
+ // ['aria-invalid', undefined],
12290
+ ["aria-keyshortcuts", void 0],
12291
+ ["aria-label", /* @__PURE__ */ new Set(["caption", "code", "deletion", "emphasis", "generic", "insertion", "paragraph", "presentation", "strong", "subscript", "superscript"])],
12292
+ ["aria-labelledby", /* @__PURE__ */ new Set(["caption", "code", "deletion", "emphasis", "generic", "insertion", "paragraph", "presentation", "strong", "subscript", "superscript"])],
12293
+ ["aria-live", void 0],
12294
+ ["aria-owns", void 0],
12295
+ ["aria-relevant", void 0],
12296
+ ["aria-roledescription", /* @__PURE__ */ new Set(["generic"])]
12297
+ ]);
12298
+ function hasGlobalAriaAttribute(element, forRole) {
12299
+ return [...kGlobalAriaAttributes].some(([attr, prohibited]) => {
12300
+ return !(prohibited == null ? void 0 : prohibited.has(forRole || "")) && element.hasAttribute(attr);
12301
+ });
12302
+ }
12303
+ function hasTabIndex(element) {
12304
+ return !Number.isNaN(Number(String(element.getAttribute("tabindex"))));
12305
+ }
12306
+ function isFocusable(element) {
12307
+ return !isNativelyDisabled(element) && (isNativelyFocusable(element) || hasTabIndex(element));
12308
+ }
12309
+ function isNativelyFocusable(element) {
12310
+ const tagName = elementSafeTagName(element);
12311
+ if (["BUTTON", "DETAILS", "SELECT", "TEXTAREA"].includes(tagName))
12312
+ return true;
12313
+ if (tagName === "A" || tagName === "AREA")
12314
+ return element.hasAttribute("href");
12315
+ if (tagName === "INPUT")
12316
+ return !element.hidden;
12317
+ return false;
11874
12318
  }
11875
12319
  const kImplicitRoleByTagName = {
11876
12320
  "A": (e) => {
@@ -11906,14 +12350,14 @@ const kImplicitRoleByTagName = {
11906
12350
  "HEADER": (e) => closestCrossShadow(e, kAncestorPreventingLandmark) ? null : "banner",
11907
12351
  "HR": () => "separator",
11908
12352
  "HTML": () => "document",
11909
- "IMG": (e) => e.getAttribute("alt") === "" && !hasGlobalAriaAttribute(e) && Number.isNaN(Number(String(e.getAttribute("tabindex")))) ? "presentation" : "img",
12353
+ "IMG": (e) => e.getAttribute("alt") === "" && !e.getAttribute("title") && !hasGlobalAriaAttribute(e) && !hasTabIndex(e) ? "presentation" : "img",
11910
12354
  "INPUT": (e) => {
11911
12355
  const type = e.type.toLowerCase();
11912
12356
  if (type === "search")
11913
12357
  return e.hasAttribute("list") ? "combobox" : "searchbox";
11914
12358
  if (["email", "tel", "text", "url", ""].includes(type)) {
11915
12359
  const list = getIdRefs(e, e.getAttribute("list"))[0];
11916
- return list && list.tagName === "DATALIST" ? "combobox" : "textbox";
12360
+ return list && elementSafeTagName(list) === "DATALIST" ? "combobox" : "textbox";
11917
12361
  }
11918
12362
  if (type === "hidden")
11919
12363
  return "";
@@ -11989,17 +12433,17 @@ const kPresentationInheritanceParents = {
11989
12433
  };
11990
12434
  function getImplicitAriaRole(element) {
11991
12435
  var _a;
11992
- const implicitRole = ((_a = kImplicitRoleByTagName[element.tagName.toUpperCase()]) == null ? void 0 : _a.call(kImplicitRoleByTagName, element)) || "";
12436
+ const implicitRole = ((_a = kImplicitRoleByTagName[elementSafeTagName(element)]) == null ? void 0 : _a.call(kImplicitRoleByTagName, element)) || "";
11993
12437
  if (!implicitRole)
11994
12438
  return null;
11995
12439
  let ancestor = element;
11996
12440
  while (ancestor) {
11997
12441
  const parent = parentElementOrShadowHost(ancestor);
11998
- const parents = kPresentationInheritanceParents[ancestor.tagName];
11999
- if (!parents || !parent || !parents.includes(parent.tagName))
12442
+ const parents = kPresentationInheritanceParents[elementSafeTagName(ancestor)];
12443
+ if (!parents || !parent || !parents.includes(elementSafeTagName(parent)))
12000
12444
  break;
12001
12445
  const parentExplicitRole = getExplicitAriaRole(parent);
12002
- if ((parentExplicitRole === "none" || parentExplicitRole === "presentation") && !hasPresentationConflictResolution(parent))
12446
+ if ((parentExplicitRole === "none" || parentExplicitRole === "presentation") && !hasPresentationConflictResolution(parent, parentExplicitRole))
12003
12447
  return parentExplicitRole;
12004
12448
  ancestor = parent;
12005
12449
  }
@@ -12107,22 +12551,28 @@ function getExplicitAriaRole(element) {
12107
12551
  const roles = (element.getAttribute("role") || "").split(" ").map((role) => role.trim());
12108
12552
  return roles.find((role) => validRoles.includes(role)) || null;
12109
12553
  }
12110
- function hasPresentationConflictResolution(element) {
12111
- return !hasGlobalAriaAttribute(element);
12554
+ function hasPresentationConflictResolution(element, role) {
12555
+ return hasGlobalAriaAttribute(element, role) || isFocusable(element);
12112
12556
  }
12113
12557
  function getAriaRole(element) {
12114
12558
  const explicitRole = getExplicitAriaRole(element);
12115
12559
  if (!explicitRole)
12116
12560
  return getImplicitAriaRole(element);
12117
- if ((explicitRole === "none" || explicitRole === "presentation") && hasPresentationConflictResolution(element))
12118
- return getImplicitAriaRole(element);
12561
+ if (explicitRole === "none" || explicitRole === "presentation") {
12562
+ const implicitRole = getImplicitAriaRole(element);
12563
+ if (hasPresentationConflictResolution(element, implicitRole))
12564
+ return implicitRole;
12565
+ }
12119
12566
  return explicitRole;
12120
12567
  }
12121
12568
  function getAriaBoolean(attr) {
12122
12569
  return attr === null ? void 0 : attr.toLowerCase() === "true";
12123
12570
  }
12571
+ function isElementIgnoredForAria(element) {
12572
+ return ["STYLE", "SCRIPT", "NOSCRIPT", "TEMPLATE"].includes(elementSafeTagName(element));
12573
+ }
12124
12574
  function isElementHiddenForAria(element) {
12125
- if (["STYLE", "SCRIPT", "NOSCRIPT", "TEMPLATE"].includes(element.tagName))
12575
+ if (isElementIgnoredForAria(element))
12126
12576
  return true;
12127
12577
  const style = getElementComputedStyle(element);
12128
12578
  const isSlot = element.nodeName === "SLOT";
@@ -12178,8 +12628,11 @@ function getIdRefs(element, ref) {
12178
12628
  return [];
12179
12629
  }
12180
12630
  }
12181
- function normalizeAccessbileName(s) {
12182
- return s.replace(/\r\n/g, "\n").replace(/\u00A0/g, " ").replace(/\s\s+/g, " ").trim();
12631
+ function trimFlatString(s) {
12632
+ return s.trim();
12633
+ }
12634
+ function asFlatString(s) {
12635
+ return s.split(" ").map((chunk) => chunk.replace(/\r\n/g, "\n").replace(/\s\s*/g, " ")).join(" ").trim();
12183
12636
  }
12184
12637
  function queryInAriaOwned(element, selector) {
12185
12638
  const result = [...element.querySelectorAll(selector)];
@@ -12201,7 +12654,7 @@ function getPseudoContent(element, pseudo) {
12201
12654
  return content;
12202
12655
  }
12203
12656
  function getPseudoContentImpl(pseudoStyle) {
12204
- if (!pseudoStyle)
12657
+ if (!pseudoStyle || pseudoStyle.display === "none" || pseudoStyle.visibility === "hidden")
12205
12658
  return "";
12206
12659
  const content = pseudoStyle.content;
12207
12660
  if (content[0] === "'" && content[content.length - 1] === "'" || content[0] === '"' && content[content.length - 1] === '"') {
@@ -12231,12 +12684,13 @@ function getElementAccessibleName(element, includeHidden) {
12231
12684
  accessibleName = "";
12232
12685
  const elementProhibitsNaming = ["caption", "code", "definition", "deletion", "emphasis", "generic", "insertion", "mark", "paragraph", "presentation", "strong", "subscript", "suggestion", "superscript", "term", "time"].includes(getAriaRole(element) || "");
12233
12686
  if (!elementProhibitsNaming) {
12234
- accessibleName = normalizeAccessbileName(getElementAccessibleNameInternal(element, {
12687
+ accessibleName = asFlatString(getTextAlternativeInternal(element, {
12235
12688
  includeHidden,
12236
12689
  visitedElements: /* @__PURE__ */ new Set(),
12237
- embeddedInLabelledBy: "none",
12238
- embeddedInLabel: "none",
12239
- embeddedInTextAlternativeElement: false,
12690
+ embeddedInDescribedBy: void 0,
12691
+ embeddedInLabelledBy: void 0,
12692
+ embeddedInLabel: void 0,
12693
+ embeddedInNativeTextAlternative: void 0,
12240
12694
  embeddedInTargetElement: "self"
12241
12695
  }));
12242
12696
  }
@@ -12244,46 +12698,75 @@ function getElementAccessibleName(element, includeHidden) {
12244
12698
  }
12245
12699
  return accessibleName;
12246
12700
  }
12247
- function getElementAccessibleNameInternal(element, options) {
12701
+ function getElementAccessibleDescription(element, includeHidden) {
12702
+ const cache = includeHidden ? cacheAccessibleDescriptionHidden : cacheAccessibleDescription;
12703
+ let accessibleDescription = cache == null ? void 0 : cache.get(element);
12704
+ if (accessibleDescription === void 0) {
12705
+ accessibleDescription = "";
12706
+ if (element.hasAttribute("aria-describedby")) {
12707
+ const describedBy = getIdRefs(element, element.getAttribute("aria-describedby"));
12708
+ accessibleDescription = asFlatString(describedBy.map((ref) => getTextAlternativeInternal(ref, {
12709
+ includeHidden,
12710
+ visitedElements: /* @__PURE__ */ new Set(),
12711
+ embeddedInLabelledBy: void 0,
12712
+ embeddedInLabel: void 0,
12713
+ embeddedInNativeTextAlternative: void 0,
12714
+ embeddedInTargetElement: "none",
12715
+ embeddedInDescribedBy: { element: ref, hidden: isElementHiddenForAria(ref) }
12716
+ })).join(" "));
12717
+ } else if (element.hasAttribute("aria-description")) {
12718
+ accessibleDescription = asFlatString(element.getAttribute("aria-description") || "");
12719
+ } else {
12720
+ accessibleDescription = asFlatString(element.getAttribute("title") || "");
12721
+ }
12722
+ cache == null ? void 0 : cache.set(element, accessibleDescription);
12723
+ }
12724
+ return accessibleDescription;
12725
+ }
12726
+ function getTextAlternativeInternal(element, options) {
12727
+ var _a, _b, _c, _d;
12248
12728
  if (options.visitedElements.has(element))
12249
12729
  return "";
12250
12730
  const childOptions = {
12251
12731
  ...options,
12252
- embeddedInLabel: options.embeddedInLabel === "self" ? "descendant" : options.embeddedInLabel,
12253
- embeddedInLabelledBy: options.embeddedInLabelledBy === "self" ? "descendant" : options.embeddedInLabelledBy,
12254
12732
  embeddedInTargetElement: options.embeddedInTargetElement === "self" ? "descendant" : options.embeddedInTargetElement
12255
12733
  };
12256
- if (!options.includeHidden && options.embeddedInLabelledBy !== "self" && isElementHiddenForAria(element)) {
12257
- options.visitedElements.add(element);
12258
- return "";
12734
+ if (!options.includeHidden) {
12735
+ const isEmbeddedInHiddenReferenceTraversal = !!((_a = options.embeddedInLabelledBy) == null ? void 0 : _a.hidden) || !!((_b = options.embeddedInDescribedBy) == null ? void 0 : _b.hidden) || !!((_c = options.embeddedInNativeTextAlternative) == null ? void 0 : _c.hidden) || !!((_d = options.embeddedInLabel) == null ? void 0 : _d.hidden);
12736
+ if (isElementIgnoredForAria(element) || !isEmbeddedInHiddenReferenceTraversal && isElementHiddenForAria(element)) {
12737
+ options.visitedElements.add(element);
12738
+ return "";
12739
+ }
12259
12740
  }
12260
12741
  const labelledBy = getAriaLabelledByElements(element);
12261
- if (options.embeddedInLabelledBy === "none") {
12262
- const accessibleName = (labelledBy || []).map((ref) => getElementAccessibleNameInternal(ref, {
12742
+ if (!options.embeddedInLabelledBy) {
12743
+ const accessibleName = (labelledBy || []).map((ref) => getTextAlternativeInternal(ref, {
12263
12744
  ...options,
12264
- embeddedInLabelledBy: "self",
12745
+ embeddedInLabelledBy: { element: ref, hidden: isElementHiddenForAria(ref) },
12746
+ embeddedInDescribedBy: void 0,
12265
12747
  embeddedInTargetElement: "none",
12266
- embeddedInLabel: "none",
12267
- embeddedInTextAlternativeElement: false
12748
+ embeddedInLabel: void 0,
12749
+ embeddedInNativeTextAlternative: void 0
12268
12750
  })).join(" ");
12269
12751
  if (accessibleName)
12270
12752
  return accessibleName;
12271
12753
  }
12272
12754
  const role = getAriaRole(element) || "";
12273
- if (options.embeddedInLabel !== "none" || options.embeddedInLabelledBy !== "none") {
12755
+ const tagName = elementSafeTagName(element);
12756
+ if (!!options.embeddedInLabel || !!options.embeddedInLabelledBy || options.embeddedInTargetElement === "descendant") {
12274
12757
  const isOwnLabel = [...element.labels || []].includes(element);
12275
12758
  const isOwnLabelledBy = (labelledBy || []).includes(element);
12276
12759
  if (!isOwnLabel && !isOwnLabelledBy) {
12277
12760
  if (role === "textbox") {
12278
12761
  options.visitedElements.add(element);
12279
- if (element.tagName === "INPUT" || element.tagName === "TEXTAREA")
12762
+ if (tagName === "INPUT" || tagName === "TEXTAREA")
12280
12763
  return element.value;
12281
12764
  return element.textContent || "";
12282
12765
  }
12283
12766
  if (["combobox", "listbox"].includes(role)) {
12284
12767
  options.visitedElements.add(element);
12285
12768
  let selectedOptions;
12286
- if (element.tagName === "SELECT") {
12769
+ if (tagName === "SELECT") {
12287
12770
  selectedOptions = [...element.selectedOptions];
12288
12771
  if (!selectedOptions.length && element.options.length)
12289
12772
  selectedOptions.push(element.options[0]);
@@ -12291,7 +12774,10 @@ function getElementAccessibleNameInternal(element, options) {
12291
12774
  const listbox = role === "combobox" ? queryInAriaOwned(element, "*").find((e) => getAriaRole(e) === "listbox") : element;
12292
12775
  selectedOptions = listbox ? queryInAriaOwned(listbox, '[aria-selected="true"]').filter((e) => getAriaRole(e) === "option") : [];
12293
12776
  }
12294
- return selectedOptions.map((option) => getElementAccessibleNameInternal(option, childOptions)).join(" ");
12777
+ if (!selectedOptions.length && tagName === "INPUT") {
12778
+ return element.value;
12779
+ }
12780
+ return selectedOptions.map((option) => getTextAlternativeInternal(option, childOptions)).join(" ");
12295
12781
  }
12296
12782
  if (["progressbar", "scrollbar", "slider", "spinbutton", "meter"].includes(role)) {
12297
12783
  options.visitedElements.add(element);
@@ -12308,15 +12794,15 @@ function getElementAccessibleNameInternal(element, options) {
12308
12794
  }
12309
12795
  }
12310
12796
  const ariaLabel = element.getAttribute("aria-label") || "";
12311
- if (ariaLabel.trim()) {
12797
+ if (trimFlatString(ariaLabel)) {
12312
12798
  options.visitedElements.add(element);
12313
12799
  return ariaLabel;
12314
12800
  }
12315
12801
  if (!["presentation", "none"].includes(role)) {
12316
- if (element.tagName === "INPUT" && ["button", "submit", "reset"].includes(element.type)) {
12802
+ if (tagName === "INPUT" && ["button", "submit", "reset"].includes(element.type)) {
12317
12803
  options.visitedElements.add(element);
12318
12804
  const value = element.value || "";
12319
- if (value.trim())
12805
+ if (trimFlatString(value))
12320
12806
  return value;
12321
12807
  if (element.type === "submit")
12322
12808
  return "Submit";
@@ -12325,85 +12811,85 @@ function getElementAccessibleNameInternal(element, options) {
12325
12811
  const title = element.getAttribute("title") || "";
12326
12812
  return title;
12327
12813
  }
12328
- if (element.tagName === "INPUT" && element.type === "image") {
12814
+ if (tagName === "INPUT" && element.type === "image") {
12329
12815
  options.visitedElements.add(element);
12330
12816
  const labels = element.labels || [];
12331
- if (labels.length && options.embeddedInLabelledBy === "none")
12817
+ if (labels.length && !options.embeddedInLabelledBy)
12332
12818
  return getAccessibleNameFromAssociatedLabels(labels, options);
12333
12819
  const alt = element.getAttribute("alt") || "";
12334
- if (alt.trim())
12820
+ if (trimFlatString(alt))
12335
12821
  return alt;
12336
12822
  const title = element.getAttribute("title") || "";
12337
- if (title.trim())
12823
+ if (trimFlatString(title))
12338
12824
  return title;
12339
12825
  return "Submit";
12340
12826
  }
12341
- if (!labelledBy && element.tagName === "BUTTON") {
12827
+ if (!labelledBy && tagName === "BUTTON") {
12342
12828
  options.visitedElements.add(element);
12343
12829
  const labels = element.labels || [];
12344
12830
  if (labels.length)
12345
12831
  return getAccessibleNameFromAssociatedLabels(labels, options);
12346
12832
  }
12347
- if (!labelledBy && element.tagName === "OUTPUT") {
12833
+ if (!labelledBy && tagName === "OUTPUT") {
12348
12834
  options.visitedElements.add(element);
12349
12835
  const labels = element.labels || [];
12350
12836
  if (labels.length)
12351
12837
  return getAccessibleNameFromAssociatedLabels(labels, options);
12352
12838
  return element.getAttribute("title") || "";
12353
12839
  }
12354
- if (!labelledBy && (element.tagName === "TEXTAREA" || element.tagName === "SELECT" || element.tagName === "INPUT")) {
12840
+ if (!labelledBy && (tagName === "TEXTAREA" || tagName === "SELECT" || tagName === "INPUT")) {
12355
12841
  options.visitedElements.add(element);
12356
12842
  const labels = element.labels || [];
12357
12843
  if (labels.length)
12358
12844
  return getAccessibleNameFromAssociatedLabels(labels, options);
12359
- const usePlaceholder = element.tagName === "INPUT" && ["text", "password", "search", "tel", "email", "url"].includes(element.type) || element.tagName === "TEXTAREA";
12845
+ const usePlaceholder = tagName === "INPUT" && ["text", "password", "search", "tel", "email", "url"].includes(element.type) || tagName === "TEXTAREA";
12360
12846
  const placeholder = element.getAttribute("placeholder") || "";
12361
12847
  const title = element.getAttribute("title") || "";
12362
12848
  if (!usePlaceholder || title)
12363
12849
  return title;
12364
12850
  return placeholder;
12365
12851
  }
12366
- if (!labelledBy && element.tagName === "FIELDSET") {
12852
+ if (!labelledBy && tagName === "FIELDSET") {
12367
12853
  options.visitedElements.add(element);
12368
12854
  for (let child = element.firstElementChild; child; child = child.nextElementSibling) {
12369
- if (child.tagName === "LEGEND") {
12370
- return getElementAccessibleNameInternal(child, {
12855
+ if (elementSafeTagName(child) === "LEGEND") {
12856
+ return getTextAlternativeInternal(child, {
12371
12857
  ...childOptions,
12372
- embeddedInTextAlternativeElement: true
12858
+ embeddedInNativeTextAlternative: { element: child, hidden: isElementHiddenForAria(child) }
12373
12859
  });
12374
12860
  }
12375
12861
  }
12376
12862
  const title = element.getAttribute("title") || "";
12377
12863
  return title;
12378
12864
  }
12379
- if (!labelledBy && element.tagName === "FIGURE") {
12865
+ if (!labelledBy && tagName === "FIGURE") {
12380
12866
  options.visitedElements.add(element);
12381
12867
  for (let child = element.firstElementChild; child; child = child.nextElementSibling) {
12382
- if (child.tagName === "FIGCAPTION") {
12383
- return getElementAccessibleNameInternal(child, {
12868
+ if (elementSafeTagName(child) === "FIGCAPTION") {
12869
+ return getTextAlternativeInternal(child, {
12384
12870
  ...childOptions,
12385
- embeddedInTextAlternativeElement: true
12871
+ embeddedInNativeTextAlternative: { element: child, hidden: isElementHiddenForAria(child) }
12386
12872
  });
12387
12873
  }
12388
12874
  }
12389
12875
  const title = element.getAttribute("title") || "";
12390
12876
  return title;
12391
12877
  }
12392
- if (element.tagName === "IMG") {
12878
+ if (tagName === "IMG") {
12393
12879
  options.visitedElements.add(element);
12394
12880
  const alt = element.getAttribute("alt") || "";
12395
- if (alt.trim())
12881
+ if (trimFlatString(alt))
12396
12882
  return alt;
12397
12883
  const title = element.getAttribute("title") || "";
12398
12884
  return title;
12399
12885
  }
12400
- if (element.tagName === "TABLE") {
12886
+ if (tagName === "TABLE") {
12401
12887
  options.visitedElements.add(element);
12402
12888
  for (let child = element.firstElementChild; child; child = child.nextElementSibling) {
12403
- if (child.tagName === "CAPTION") {
12404
- return getElementAccessibleNameInternal(child, {
12889
+ if (elementSafeTagName(child) === "CAPTION") {
12890
+ return getTextAlternativeInternal(child, {
12405
12891
  ...childOptions,
12406
- embeddedInTextAlternativeElement: true
12892
+ embeddedInNativeTextAlternative: { element: child, hidden: isElementHiddenForAria(child) }
12407
12893
  });
12408
12894
  }
12409
12895
  }
@@ -12411,43 +12897,44 @@ function getElementAccessibleNameInternal(element, options) {
12411
12897
  if (summary)
12412
12898
  return summary;
12413
12899
  }
12414
- if (element.tagName === "AREA") {
12900
+ if (tagName === "AREA") {
12415
12901
  options.visitedElements.add(element);
12416
12902
  const alt = element.getAttribute("alt") || "";
12417
- if (alt.trim())
12903
+ if (trimFlatString(alt))
12418
12904
  return alt;
12419
12905
  const title = element.getAttribute("title") || "";
12420
12906
  return title;
12421
12907
  }
12422
- if (element.tagName.toUpperCase() === "SVG" || element.ownerSVGElement) {
12908
+ if (tagName === "SVG" || element.ownerSVGElement) {
12423
12909
  options.visitedElements.add(element);
12424
12910
  for (let child = element.firstElementChild; child; child = child.nextElementSibling) {
12425
- if (child.tagName.toUpperCase() === "TITLE" && child.ownerSVGElement) {
12426
- return getElementAccessibleNameInternal(child, {
12911
+ if (elementSafeTagName(child) === "TITLE" && child.ownerSVGElement) {
12912
+ return getTextAlternativeInternal(child, {
12427
12913
  ...childOptions,
12428
- embeddedInLabelledBy: "self"
12914
+ embeddedInLabelledBy: { element: child, hidden: isElementHiddenForAria(child) }
12429
12915
  });
12430
12916
  }
12431
12917
  }
12432
12918
  }
12433
- if (element.ownerSVGElement && element.tagName.toUpperCase() === "A") {
12919
+ if (element.ownerSVGElement && tagName === "A") {
12434
12920
  const title = element.getAttribute("xlink:title") || "";
12435
- if (title.trim()) {
12921
+ if (trimFlatString(title)) {
12436
12922
  options.visitedElements.add(element);
12437
12923
  return title;
12438
12924
  }
12439
12925
  }
12440
12926
  }
12441
- if (allowsNameFromContent(role, options.embeddedInTargetElement === "descendant") || options.embeddedInLabelledBy !== "none" || options.embeddedInLabel !== "none" || options.embeddedInTextAlternativeElement) {
12927
+ const shouldNameFromContentForSummary = tagName === "SUMMARY" && !["presentation", "none"].includes(role);
12928
+ if (allowsNameFromContent(role, options.embeddedInTargetElement === "descendant") || shouldNameFromContentForSummary || !!options.embeddedInLabelledBy || !!options.embeddedInDescribedBy || !!options.embeddedInLabel || !!options.embeddedInNativeTextAlternative) {
12442
12929
  options.visitedElements.add(element);
12443
12930
  const tokens = [];
12444
12931
  const visit = (node, skipSlotted) => {
12445
- var _a;
12932
+ var _a2;
12446
12933
  if (skipSlotted && node.assignedSlot)
12447
12934
  return;
12448
12935
  if (node.nodeType === 1) {
12449
- const display = ((_a = getElementComputedStyle(node)) == null ? void 0 : _a.display) || "inline";
12450
- let token = getElementAccessibleNameInternal(node, childOptions);
12936
+ const display = ((_a2 = getElementComputedStyle(node)) == null ? void 0 : _a2.display) || "inline";
12937
+ let token = getTextAlternativeInternal(node, childOptions);
12451
12938
  if (display !== "inline" || node.nodeName === "BR")
12452
12939
  token = " " + token + " ";
12453
12940
  tokens.push(token);
@@ -12472,13 +12959,14 @@ function getElementAccessibleNameInternal(element, options) {
12472
12959
  }
12473
12960
  tokens.push(getPseudoContent(element, "::after"));
12474
12961
  const accessibleName = tokens.join("");
12475
- if (accessibleName.trim())
12962
+ const maybeTrimmedAccessibleName = options.embeddedInTargetElement === "self" ? trimFlatString(accessibleName) : accessibleName;
12963
+ if (maybeTrimmedAccessibleName)
12476
12964
  return accessibleName;
12477
12965
  }
12478
- if (!["presentation", "none"].includes(role) || element.tagName === "IFRAME") {
12966
+ if (!["presentation", "none"].includes(role) || tagName === "IFRAME") {
12479
12967
  options.visitedElements.add(element);
12480
12968
  const title = element.getAttribute("title") || "";
12481
- if (title.trim())
12969
+ if (trimFlatString(title))
12482
12970
  return title;
12483
12971
  }
12484
12972
  options.visitedElements.add(element);
@@ -12486,7 +12974,7 @@ function getElementAccessibleNameInternal(element, options) {
12486
12974
  }
12487
12975
  const kAriaSelectedRoles = ["gridcell", "option", "row", "tab", "rowheader", "columnheader", "treeitem"];
12488
12976
  function getAriaSelected(element) {
12489
- if (element.tagName === "OPTION")
12977
+ if (elementSafeTagName(element) === "OPTION")
12490
12978
  return element.selected;
12491
12979
  if (kAriaSelectedRoles.includes(getAriaRole(element) || ""))
12492
12980
  return getAriaBoolean(element.getAttribute("aria-selected")) === true;
@@ -12498,9 +12986,10 @@ function getAriaChecked(element) {
12498
12986
  return result === "error" ? false : result;
12499
12987
  }
12500
12988
  function getChecked(element, allowMixed) {
12501
- if (allowMixed && element.tagName === "INPUT" && element.indeterminate)
12989
+ const tagName = elementSafeTagName(element);
12990
+ if (allowMixed && tagName === "INPUT" && element.indeterminate)
12502
12991
  return "mixed";
12503
- if (element.tagName === "INPUT" && ["checkbox", "radio"].includes(element.type))
12992
+ if (tagName === "INPUT" && ["checkbox", "radio"].includes(element.type))
12504
12993
  return element.checked;
12505
12994
  if (kAriaCheckedRoles.includes(getAriaRole(element) || "")) {
12506
12995
  const checked = element.getAttribute("aria-checked");
@@ -12525,7 +13014,7 @@ function getAriaPressed(element) {
12525
13014
  }
12526
13015
  const kAriaExpandedRoles = ["application", "button", "checkbox", "combobox", "gridcell", "link", "listbox", "menuitem", "row", "rowheader", "tab", "treeitem", "columnheader", "menuitemcheckbox", "menuitemradio", "rowheader", "switch"];
12527
13016
  function getAriaExpanded(element) {
12528
- if (element.tagName === "DETAILS")
13017
+ if (elementSafeTagName(element) === "DETAILS")
12529
13018
  return element.open;
12530
13019
  if (kAriaExpandedRoles.includes(getAriaRole(element) || "")) {
12531
13020
  const expanded = element.getAttribute("aria-expanded");
@@ -12539,7 +13028,7 @@ function getAriaExpanded(element) {
12539
13028
  }
12540
13029
  const kAriaLevelRoles = ["heading", "listitem", "row", "treeitem"];
12541
13030
  function getAriaLevel(element) {
12542
- const native = { "H1": 1, "H2": 2, "H3": 3, "H4": 4, "H5": 5, "H6": 6 }[element.tagName];
13031
+ const native = { "H1": 1, "H2": 2, "H3": 3, "H4": 4, "H5": 5, "H6": 6 }[elementSafeTagName(element)];
12543
13032
  if (native)
12544
13033
  return native;
12545
13034
  if (kAriaLevelRoles.includes(getAriaRole(element) || "")) {
@@ -12552,15 +13041,16 @@ function getAriaLevel(element) {
12552
13041
  }
12553
13042
  const kAriaDisabledRoles = ["application", "button", "composite", "gridcell", "group", "input", "link", "menuitem", "scrollbar", "separator", "tab", "checkbox", "columnheader", "combobox", "grid", "listbox", "menu", "menubar", "menuitemcheckbox", "menuitemradio", "option", "radio", "radiogroup", "row", "rowheader", "searchbox", "select", "slider", "spinbutton", "switch", "tablist", "textbox", "toolbar", "tree", "treegrid", "treeitem"];
12554
13043
  function getAriaDisabled(element) {
13044
+ return isNativelyDisabled(element) || hasExplicitAriaDisabled(element);
13045
+ }
13046
+ function isNativelyDisabled(element) {
12555
13047
  const isNativeFormControl = ["BUTTON", "INPUT", "SELECT", "TEXTAREA", "OPTION", "OPTGROUP"].includes(element.tagName);
12556
- if (isNativeFormControl && (element.hasAttribute("disabled") || belongsToDisabledFieldSet(element)))
12557
- return true;
12558
- return hasExplicitAriaDisabled(element);
13048
+ return isNativeFormControl && (element.hasAttribute("disabled") || belongsToDisabledFieldSet(element));
12559
13049
  }
12560
13050
  function belongsToDisabledFieldSet(element) {
12561
13051
  if (!element)
12562
13052
  return false;
12563
- if (element.tagName === "FIELDSET" && element.hasAttribute("disabled"))
13053
+ if (elementSafeTagName(element) === "FIELDSET" && element.hasAttribute("disabled"))
12564
13054
  return true;
12565
13055
  return belongsToDisabledFieldSet(element.parentElement);
12566
13056
  }
@@ -12577,16 +13067,19 @@ function hasExplicitAriaDisabled(element) {
12577
13067
  return hasExplicitAriaDisabled(parentElementOrShadowHost(element));
12578
13068
  }
12579
13069
  function getAccessibleNameFromAssociatedLabels(labels, options) {
12580
- return [...labels].map((label) => getElementAccessibleNameInternal(label, {
13070
+ return [...labels].map((label) => getTextAlternativeInternal(label, {
12581
13071
  ...options,
12582
- embeddedInLabel: "self",
12583
- embeddedInTextAlternativeElement: false,
12584
- embeddedInLabelledBy: "none",
13072
+ embeddedInLabel: { element: label, hidden: isElementHiddenForAria(label) },
13073
+ embeddedInNativeTextAlternative: void 0,
13074
+ embeddedInLabelledBy: void 0,
13075
+ embeddedInDescribedBy: void 0,
12585
13076
  embeddedInTargetElement: "none"
12586
13077
  })).filter((accessibleName) => !!accessibleName).join(" ");
12587
13078
  }
12588
13079
  let cacheAccessibleName;
12589
13080
  let cacheAccessibleNameHidden;
13081
+ let cacheAccessibleDescription;
13082
+ let cacheAccessibleDescriptionHidden;
12590
13083
  let cacheIsHidden;
12591
13084
  let cachePseudoContentBefore;
12592
13085
  let cachePseudoContentAfter;
@@ -12595,6 +13088,8 @@ function beginAriaCaches() {
12595
13088
  ++cachesCounter;
12596
13089
  cacheAccessibleName ?? (cacheAccessibleName = /* @__PURE__ */ new Map());
12597
13090
  cacheAccessibleNameHidden ?? (cacheAccessibleNameHidden = /* @__PURE__ */ new Map());
13091
+ cacheAccessibleDescription ?? (cacheAccessibleDescription = /* @__PURE__ */ new Map());
13092
+ cacheAccessibleDescriptionHidden ?? (cacheAccessibleDescriptionHidden = /* @__PURE__ */ new Map());
12598
13093
  cacheIsHidden ?? (cacheIsHidden = /* @__PURE__ */ new Map());
12599
13094
  cachePseudoContentBefore ?? (cachePseudoContentBefore = /* @__PURE__ */ new Map());
12600
13095
  cachePseudoContentAfter ?? (cachePseudoContentAfter = /* @__PURE__ */ new Map());
@@ -12603,6 +13098,8 @@ function endAriaCaches() {
12603
13098
  if (!--cachesCounter) {
12604
13099
  cacheAccessibleName = void 0;
12605
13100
  cacheAccessibleNameHidden = void 0;
13101
+ cacheAccessibleDescription = void 0;
13102
+ cacheAccessibleDescriptionHidden = void 0;
12606
13103
  cacheIsHidden = void 0;
12607
13104
  cachePseudoContentBefore = void 0;
12608
13105
  cachePseudoContentAfter = void 0;
@@ -13775,7 +14272,11 @@ function generateSelector(injectedScript, targetElement, options) {
13775
14272
  }
13776
14273
  selectors = [joinTokens(targetTokens)];
13777
14274
  } else {
13778
- targetElement = closestCrossShadow(targetElement, "button,select,input,[role=button],[role=checkbox],[role=radio],a,[role=link]", options.root) || targetElement;
14275
+ if (!targetElement.matches("input,textarea,select") && !targetElement.isContentEditable) {
14276
+ const interactiveParent = closestCrossShadow(targetElement, "button,select,input,[role=button],[role=checkbox],[role=radio],a,[role=link]", options.root);
14277
+ if (interactiveParent && isElementVisible(interactiveParent))
14278
+ targetElement = interactiveParent;
14279
+ }
13779
14280
  if (options.multiple) {
13780
14281
  const withText = generateSelectorFor(injectedScript, targetElement, options);
13781
14282
  const withoutText = generateSelectorFor(injectedScript, targetElement, { ...options, noText: true });
@@ -13955,8 +14456,10 @@ function buildTextCandidates(injectedScript, element, isTargetNode) {
13955
14456
  const cssToken = { engine: "css", selector: cssEscape(element.nodeName.toLowerCase()), score: kCSSTagNameScore };
13956
14457
  for (const alternative of alternatives)
13957
14458
  candidates.push([cssToken, { engine: "internal:has-text", selector: escapeForTextSelector(alternative.text, false), score: kTextScore - alternative.scoreBouns }]);
13958
- if (text.length <= 80)
13959
- candidates.push([cssToken, { engine: "internal:has-text", selector: "/^" + escapeRegExp(text) + "$/", score: kTextScoreRegex }]);
14459
+ if (text.length <= 80) {
14460
+ const re2 = new RegExp("^" + escapeRegExp(text) + "$");
14461
+ candidates.push([cssToken, { engine: "internal:has-text", selector: escapeForTextSelector(re2, false), score: kTextScoreRegex }]);
14462
+ }
13960
14463
  }
13961
14464
  const ariaRole = getAriaRole(element);
13962
14465
  if (ariaRole && !["none", "presentation"].includes(ariaRole)) {
@@ -14123,7 +14626,7 @@ function suitableTextAlternatives(text) {
14123
14626
  const match = text.match(/^([\d.,]+)[^.,\w]/);
14124
14627
  const leadingNumberLength = match ? match[1].length : 0;
14125
14628
  if (leadingNumberLength) {
14126
- const alt = text.substring(leadingNumberLength).trimStart();
14629
+ const alt = trimWordBoundary(text.substring(leadingNumberLength).trimStart(), 80);
14127
14630
  result.push({ text: alt, scoreBouns: alt.length <= 30 ? 2 : 1 });
14128
14631
  }
14129
14632
  }
@@ -14131,7 +14634,7 @@ function suitableTextAlternatives(text) {
14131
14634
  const match = text.match(/[^.,\w]([\d.,]+)$/);
14132
14635
  const trailingNumberLength = match ? match[1].length : 0;
14133
14636
  if (trailingNumberLength) {
14134
- const alt = text.substring(0, text.length - trailingNumberLength).trimEnd();
14637
+ const alt = trimWordBoundary(text.substring(0, text.length - trailingNumberLength).trimEnd(), 80);
14135
14638
  result.push({ text: alt, scoreBouns: alt.length <= 30 ? 2 : 1 });
14136
14639
  }
14137
14640
  }
@@ -14146,328 +14649,7 @@ function suitableTextAlternatives(text) {
14146
14649
  result.push({ text: text.substring(0, 80), scoreBouns: 0 });
14147
14650
  return result;
14148
14651
  }
14149
- const highlightCSS = `/**
14150
- * Copyright (c) Microsoft Corporation.
14151
- *
14152
- * Licensed under the Apache License, Version 2.0 (the "License");
14153
- * you may not use this file except in compliance with the License.
14154
- * You may obtain a copy of the License at
14155
- *
14156
- * http://www.apache.org/licenses/LICENSE-2.0
14157
- *
14158
- * Unless required by applicable law or agreed to in writing, software
14159
- * distributed under the License is distributed on an "AS IS" BASIS,
14160
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14161
- * See the License for the specific language governing permissions and
14162
- * limitations under the License.
14163
- */
14164
-
14165
- :host {
14166
- font-size: 13px;
14167
- font-family: system-ui, "Ubuntu", "Droid Sans", sans-serif;
14168
- color: #333;
14169
- }
14170
-
14171
- x-pw-tooltip {
14172
- backdrop-filter: blur(5px);
14173
- background-color: white;
14174
- border-radius: 6px;
14175
- box-shadow: 0 0.5rem 1.2rem rgba(0,0,0,.3);
14176
- display: none;
14177
- font-size: 12.8px;
14178
- font-weight: normal;
14179
- left: 0;
14180
- line-height: 1.5;
14181
- max-width: 600px;
14182
- position: absolute;
14183
- top: 0;
14184
- padding: 0;
14185
- flex-direction: column;
14186
- overflow: hidden;
14187
- }
14188
-
14189
- x-pw-tooltip-line {
14190
- display: flex;
14191
- max-width: 600px;
14192
- padding: 6px;
14193
- user-select: none;
14194
- cursor: pointer;
14195
- }
14196
-
14197
- x-pw-tooltip-line.selectable:hover {
14198
- background-color: hsl(0, 0%, 95%);
14199
- overflow: hidden;
14200
- }
14201
-
14202
- x-pw-tooltip-footer {
14203
- display: flex;
14204
- max-width: 600px;
14205
- padding: 6px;
14206
- user-select: none;
14207
- color: #777;
14208
- }
14209
-
14210
- x-pw-dialog {
14211
- background-color: white;
14212
- pointer-events: auto;
14213
- border-radius: 6px;
14214
- box-shadow: 0 0.5rem 1.2rem rgba(0,0,0,.3);
14215
- display: flex;
14216
- flex-direction: column;
14217
- position: absolute;
14218
- width: 400px;
14219
- height: 150px;
14220
- z-index: 10;
14221
- font-size: 13px;
14222
- }
14223
-
14224
- x-pw-dialog-body {
14225
- display: flex;
14226
- flex-direction: column;
14227
- flex: auto;
14228
- }
14229
-
14230
- x-pw-dialog-body label {
14231
- margin: 5px 8px;
14232
- display: flex;
14233
- flex-direction: row;
14234
- align-items: center;
14235
- }
14236
-
14237
- x-pw-highlight {
14238
- position: absolute;
14239
- top: 0;
14240
- left: 0;
14241
- width: 0;
14242
- height: 0;
14243
- }
14244
-
14245
- x-pw-action-point {
14246
- position: absolute;
14247
- width: 20px;
14248
- height: 20px;
14249
- background: red;
14250
- border-radius: 10px;
14251
- margin: -10px 0 0 -10px;
14252
- z-index: 2;
14253
- }
14254
-
14255
- x-pw-separator {
14256
- height: 1px;
14257
- margin: 6px 9px;
14258
- background: rgb(148 148 148 / 90%);
14259
- }
14260
-
14261
- x-pw-tool-gripper {
14262
- height: 28px;
14263
- width: 24px;
14264
- margin: 2px 0;
14265
- cursor: grab;
14266
- }
14267
-
14268
- x-pw-tool-gripper:active {
14269
- cursor: grabbing;
14270
- }
14271
-
14272
- x-pw-tool-gripper > x-div {
14273
- width: 100%;
14274
- height: 100%;
14275
- -webkit-mask-repeat: no-repeat;
14276
- -webkit-mask-position: center;
14277
- -webkit-mask-size: 20px;
14278
- mask-repeat: no-repeat;
14279
- mask-position: center;
14280
- mask-size: 16px;
14281
- -webkit-mask-image: url("data:image/svg+xml;utf8,<svg width='16' height='16' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg' fill='currentColor'><path d='M11 18c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2zm-2-8c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0-6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm6 4c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z' /></svg>");
14282
- mask-image: url("data:image/svg+xml;utf8,<svg width='16' height='16' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg' fill='currentColor'><path d='M11 18c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2zm-2-8c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0-6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm6 4c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z' /></svg>");
14283
- background-color: #555555;
14284
- }
14285
-
14286
- x-pw-tools-list > label {
14287
- display: flex;
14288
- align-items: center;
14289
- margin: 0 10px;
14290
- user-select: none;
14291
- }
14292
-
14293
- x-pw-tools-list {
14294
- display: flex;
14295
- width: 100%;
14296
- border-bottom: 1px solid #dddddd;
14297
- }
14298
-
14299
- x-pw-tool-item {
14300
- pointer-events: auto;
14301
- cursor: pointer;
14302
- height: 28px;
14303
- width: 28px;
14304
- border-radius: 3px;
14305
- }
14306
-
14307
- x-pw-tool-item:not(.disabled):hover {
14308
- background-color: hsl(0, 0%, 86%);
14309
- }
14310
-
14311
- x-pw-tool-item.active {
14312
- background-color: rgba(138, 202, 228, 0.5);
14313
- }
14314
-
14315
- x-pw-tool-item.active:not(.disabled):hover {
14316
- background-color: #8acae4c4;
14317
- }
14318
-
14319
- x-pw-tool-item > x-div {
14320
- width: 100%;
14321
- height: 100%;
14322
- -webkit-mask-repeat: no-repeat;
14323
- -webkit-mask-position: center;
14324
- -webkit-mask-size: 20px;
14325
- mask-repeat: no-repeat;
14326
- mask-position: center;
14327
- mask-size: 16px;
14328
- background-color: #3a3a3a;
14329
- }
14330
-
14331
- x-pw-tool-item.disabled > x-div {
14332
- background-color: rgba(97, 97, 97, 0.5);
14333
- cursor: default;
14334
- }
14335
-
14336
- x-pw-tool-item.record.active {
14337
- background-color: transparent;
14338
- }
14339
-
14340
- x-pw-tool-item.record.active:hover {
14341
- background-color: hsl(0, 0%, 86%);
14342
- }
14343
-
14344
- x-pw-tool-item.record.active > x-div {
14345
- background-color: #a1260d;
14346
- }
14347
-
14348
- x-pw-tool-item.accept > x-div {
14349
- background-color: #388a34;
14350
- }
14351
-
14352
- x-pw-tool-item.record > x-div {
14353
- /* codicon: circle-large-filled */
14354
- -webkit-mask-image: url("data:image/svg+xml;utf8,<svg width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg' fill='currentColor'><path d='M8 1a6.8 6.8 0 0 1 1.86.253 6.899 6.899 0 0 1 3.083 1.805 6.903 6.903 0 0 1 1.804 3.083C14.916 6.738 15 7.357 15 8s-.084 1.262-.253 1.86a6.9 6.9 0 0 1-.704 1.674 7.157 7.157 0 0 1-2.516 2.509 6.966 6.966 0 0 1-1.668.71A6.984 6.984 0 0 1 8 15a6.984 6.984 0 0 1-1.86-.246 7.098 7.098 0 0 1-1.674-.711 7.3 7.3 0 0 1-1.415-1.094 7.295 7.295 0 0 1-1.094-1.415 7.098 7.098 0 0 1-.71-1.675A6.985 6.985 0 0 1 1 8c0-.643.082-1.262.246-1.86a6.968 6.968 0 0 1 .711-1.667 7.156 7.156 0 0 1 2.509-2.516 6.895 6.895 0 0 1 1.675-.704A6.808 6.808 0 0 1 8 1z'/></svg>");
14355
- mask-image: url("data:image/svg+xml;utf8,<svg width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg' fill='currentColor'><path d='M8 1a6.8 6.8 0 0 1 1.86.253 6.899 6.899 0 0 1 3.083 1.805 6.903 6.903 0 0 1 1.804 3.083C14.916 6.738 15 7.357 15 8s-.084 1.262-.253 1.86a6.9 6.9 0 0 1-.704 1.674 7.157 7.157 0 0 1-2.516 2.509 6.966 6.966 0 0 1-1.668.71A6.984 6.984 0 0 1 8 15a6.984 6.984 0 0 1-1.86-.246 7.098 7.098 0 0 1-1.674-.711 7.3 7.3 0 0 1-1.415-1.094 7.295 7.295 0 0 1-1.094-1.415 7.098 7.098 0 0 1-.71-1.675A6.985 6.985 0 0 1 1 8c0-.643.082-1.262.246-1.86a6.968 6.968 0 0 1 .711-1.667 7.156 7.156 0 0 1 2.509-2.516 6.895 6.895 0 0 1 1.675-.704A6.808 6.808 0 0 1 8 1z'/></svg>");
14356
- }
14357
-
14358
- x-pw-tool-item.pick-locator > x-div {
14359
- /* codicon: inspect */
14360
- -webkit-mask-image: url("data:image/svg+xml;utf8,<svg width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg' fill='currentColor'><path fill-rule='evenodd' clip-rule='evenodd' d='M1 3l1-1h12l1 1v6h-1V3H2v8h5v1H2l-1-1V3zm14.707 9.707L9 6v9.414l2.707-2.707h4zM10 13V8.414l3.293 3.293h-2L10 13z'/></svg>");
14361
- mask-image: url("data:image/svg+xml;utf8,<svg width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg' fill='currentColor'><path fill-rule='evenodd' clip-rule='evenodd' d='M1 3l1-1h12l1 1v6h-1V3H2v8h5v1H2l-1-1V3zm14.707 9.707L9 6v9.414l2.707-2.707h4zM10 13V8.414l3.293 3.293h-2L10 13z'/></svg>");
14362
- }
14363
-
14364
- x-pw-tool-item.text > x-div {
14365
- /* codicon: whole-word */
14366
- -webkit-mask-image: url("data:image/svg+xml;utf8,<svg width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg' fill='currentColor'><path fill-rule='evenodd' clip-rule='evenodd' d='M0 11H1V13H15V11H16V14H15H1H0V11Z'/><path d='M6.84048 11H5.95963V10.1406H5.93814C5.555 10.7995 4.99104 11.1289 4.24625 11.1289C3.69839 11.1289 3.26871 10.9839 2.95718 10.6938C2.64924 10.4038 2.49527 10.0189 2.49527 9.53906C2.49527 8.51139 3.10041 7.91341 4.3107 7.74512L5.95963 7.51416C5.95963 6.57959 5.58186 6.1123 4.82632 6.1123C4.16389 6.1123 3.56591 6.33789 3.03238 6.78906V5.88672C3.57307 5.54297 4.19612 5.37109 4.90152 5.37109C6.19416 5.37109 6.84048 6.05501 6.84048 7.42285V11ZM5.95963 8.21777L4.63297 8.40039C4.22476 8.45768 3.91682 8.55973 3.70914 8.70654C3.50145 8.84977 3.39761 9.10579 3.39761 9.47461C3.39761 9.74316 3.4925 9.96338 3.68228 10.1353C3.87564 10.3035 4.13166 10.3877 4.45035 10.3877C4.8872 10.3877 5.24706 10.2355 5.52994 9.93115C5.8164 9.62321 5.95963 9.2347 5.95963 8.76562V8.21777Z'/><path d='M9.3475 10.2051H9.32601V11H8.44515V2.85742H9.32601V6.4668H9.3475C9.78076 5.73633 10.4146 5.37109 11.2489 5.37109C11.9543 5.37109 12.5057 5.61816 12.9032 6.1123C13.3042 6.60286 13.5047 7.26172 13.5047 8.08887C13.5047 9.00911 13.2809 9.74674 12.8333 10.3018C12.3857 10.8532 11.7734 11.1289 10.9964 11.1289C10.2695 11.1289 9.71989 10.821 9.3475 10.2051ZM9.32601 7.98682V8.75488C9.32601 9.20964 9.47282 9.59635 9.76644 9.91504C10.0636 10.2301 10.4396 10.3877 10.8944 10.3877C11.4279 10.3877 11.8451 10.1836 12.1458 9.77539C12.4502 9.36719 12.6024 8.79964 12.6024 8.07275C12.6024 7.46045 12.4609 6.98063 12.1781 6.6333C11.8952 6.28597 11.512 6.1123 11.0286 6.1123C10.5166 6.1123 10.1048 6.29134 9.7933 6.64941C9.48177 7.00391 9.32601 7.44971 9.32601 7.98682Z'/></svg>");
14367
- mask-image: url("data:image/svg+xml;utf8,<svg width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg' fill='currentColor'><path fill-rule='evenodd' clip-rule='evenodd' d='M0 11H1V13H15V11H16V14H15H1H0V11Z'/><path d='M6.84048 11H5.95963V10.1406H5.93814C5.555 10.7995 4.99104 11.1289 4.24625 11.1289C3.69839 11.1289 3.26871 10.9839 2.95718 10.6938C2.64924 10.4038 2.49527 10.0189 2.49527 9.53906C2.49527 8.51139 3.10041 7.91341 4.3107 7.74512L5.95963 7.51416C5.95963 6.57959 5.58186 6.1123 4.82632 6.1123C4.16389 6.1123 3.56591 6.33789 3.03238 6.78906V5.88672C3.57307 5.54297 4.19612 5.37109 4.90152 5.37109C6.19416 5.37109 6.84048 6.05501 6.84048 7.42285V11ZM5.95963 8.21777L4.63297 8.40039C4.22476 8.45768 3.91682 8.55973 3.70914 8.70654C3.50145 8.84977 3.39761 9.10579 3.39761 9.47461C3.39761 9.74316 3.4925 9.96338 3.68228 10.1353C3.87564 10.3035 4.13166 10.3877 4.45035 10.3877C4.8872 10.3877 5.24706 10.2355 5.52994 9.93115C5.8164 9.62321 5.95963 9.2347 5.95963 8.76562V8.21777Z'/><path d='M9.3475 10.2051H9.32601V11H8.44515V2.85742H9.32601V6.4668H9.3475C9.78076 5.73633 10.4146 5.37109 11.2489 5.37109C11.9543 5.37109 12.5057 5.61816 12.9032 6.1123C13.3042 6.60286 13.5047 7.26172 13.5047 8.08887C13.5047 9.00911 13.2809 9.74674 12.8333 10.3018C12.3857 10.8532 11.7734 11.1289 10.9964 11.1289C10.2695 11.1289 9.71989 10.821 9.3475 10.2051ZM9.32601 7.98682V8.75488C9.32601 9.20964 9.47282 9.59635 9.76644 9.91504C10.0636 10.2301 10.4396 10.3877 10.8944 10.3877C11.4279 10.3877 11.8451 10.1836 12.1458 9.77539C12.4502 9.36719 12.6024 8.79964 12.6024 8.07275C12.6024 7.46045 12.4609 6.98063 12.1781 6.6333C11.8952 6.28597 11.512 6.1123 11.0286 6.1123C10.5166 6.1123 10.1048 6.29134 9.7933 6.64941C9.48177 7.00391 9.32601 7.44971 9.32601 7.98682Z'/></svg>");
14368
- }
14369
-
14370
- x-pw-tool-item.visibility > x-div {
14371
- /* codicon: eye */
14372
- -webkit-mask-image: url("data:image/svg+xml;utf8,<svg width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg' fill='currentColor'><path d='M7.99993 6.00316C9.47266 6.00316 10.6666 7.19708 10.6666 8.66981C10.6666 10.1426 9.47266 11.3365 7.99993 11.3365C6.52715 11.3365 5.33324 10.1426 5.33324 8.66981C5.33324 7.19708 6.52715 6.00316 7.99993 6.00316ZM7.99993 7.00315C7.07946 7.00315 6.33324 7.74935 6.33324 8.66981C6.33324 9.59028 7.07946 10.3365 7.99993 10.3365C8.9204 10.3365 9.6666 9.59028 9.6666 8.66981C9.6666 7.74935 8.9204 7.00315 7.99993 7.00315ZM7.99993 3.66675C11.0756 3.66675 13.7307 5.76675 14.4673 8.70968C14.5344 8.97755 14.3716 9.24908 14.1037 9.31615C13.8358 9.38315 13.5643 9.22041 13.4973 8.95248C12.8713 6.45205 10.6141 4.66675 7.99993 4.66675C5.38454 4.66675 3.12664 6.45359 2.50182 8.95555C2.43491 9.22341 2.16348 9.38635 1.89557 9.31948C1.62766 9.25255 1.46471 8.98115 1.53162 8.71321C2.26701 5.76856 4.9229 3.66675 7.99993 3.66675Z'/></svg>");
14373
- mask-image: url("data:image/svg+xml;utf8,<svg width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg' fill='currentColor'><path d='M7.99993 6.00316C9.47266 6.00316 10.6666 7.19708 10.6666 8.66981C10.6666 10.1426 9.47266 11.3365 7.99993 11.3365C6.52715 11.3365 5.33324 10.1426 5.33324 8.66981C5.33324 7.19708 6.52715 6.00316 7.99993 6.00316ZM7.99993 7.00315C7.07946 7.00315 6.33324 7.74935 6.33324 8.66981C6.33324 9.59028 7.07946 10.3365 7.99993 10.3365C8.9204 10.3365 9.6666 9.59028 9.6666 8.66981C9.6666 7.74935 8.9204 7.00315 7.99993 7.00315ZM7.99993 3.66675C11.0756 3.66675 13.7307 5.76675 14.4673 8.70968C14.5344 8.97755 14.3716 9.24908 14.1037 9.31615C13.8358 9.38315 13.5643 9.22041 13.4973 8.95248C12.8713 6.45205 10.6141 4.66675 7.99993 4.66675C5.38454 4.66675 3.12664 6.45359 2.50182 8.95555C2.43491 9.22341 2.16348 9.38635 1.89557 9.31948C1.62766 9.25255 1.46471 8.98115 1.53162 8.71321C2.26701 5.76856 4.9229 3.66675 7.99993 3.66675Z'/></svg>");
14374
- }
14375
-
14376
- x-pw-tool-item.value > x-div {
14377
- /* codicon: symbol-constant */
14378
- -webkit-mask-image: url("data:image/svg+xml;utf8,<svg width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg' fill='currentColor'><path fill-rule='evenodd' clip-rule='evenodd' d='M4 6h8v1H4V6zm8 3H4v1h8V9z'/><path fill-rule='evenodd' clip-rule='evenodd' d='M1 4l1-1h12l1 1v8l-1 1H2l-1-1V4zm1 0v8h12V4H2z'/></svg>");
14379
- mask-image: url("data:image/svg+xml;utf8,<svg width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg' fill='currentColor'><path fill-rule='evenodd' clip-rule='evenodd' d='M4 6h8v1H4V6zm8 3H4v1h8V9z'/><path fill-rule='evenodd' clip-rule='evenodd' d='M1 4l1-1h12l1 1v8l-1 1H2l-1-1V4zm1 0v8h12V4H2z'/></svg>");
14380
- }
14381
-
14382
- x-pw-tool-item.accept > x-div {
14383
- -webkit-mask-image: url("data:image/svg+xml;utf8,<svg width='16' height='16' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg' fill='currentColor'><path d='M9 16.17 4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z'/></svg>");
14384
- mask-image: url("data:image/svg+xml;utf8,<svg width='16' height='16' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg' fill='currentColor'><path d='M9 16.17 4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z'/></svg>");
14385
- }
14386
-
14387
- x-pw-tool-item.cancel > x-div {
14388
- -webkit-mask-image: url("data:image/svg+xml;utf8,<svg width='16' height='16' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg' fill='currentColor'><path d='M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z'/></svg>");
14389
- mask-image: url("data:image/svg+xml;utf8,<svg width='16' height='16' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg' fill='currentColor'><path d='M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z'/></svg>");
14390
- }
14391
-
14392
- x-pw-tool-item.succeeded > x-div {
14393
- /* codicon: pass */
14394
- -webkit-mask-image: url("data:image/svg+xml;utf8,<svg width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg' fill='currentColor'><path d='M6.27 10.87h.71l4.56-4.56-.71-.71-4.2 4.21-1.92-1.92L4 8.6l2.27 2.27z'/><path fill-rule='evenodd' clip-rule='evenodd' d='M8.6 1c1.6.1 3.1.9 4.2 2 1.3 1.4 2 3.1 2 5.1 0 1.6-.6 3.1-1.6 4.4-1 1.2-2.4 2.1-4 2.4-1.6.3-3.2.1-4.6-.7-1.4-.8-2.5-2-3.1-3.5C.9 9.2.8 7.5 1.3 6c.5-1.6 1.4-2.9 2.8-3.8C5.4 1.3 7 .9 8.6 1zm.5 12.9c1.3-.3 2.5-1 3.4-2.1.8-1.1 1.3-2.4 1.2-3.8 0-1.6-.6-3.2-1.7-4.3-1-1-2.2-1.6-3.6-1.7-1.3-.1-2.7.2-3.8 1-1.1.8-1.9 1.9-2.3 3.3-.4 1.3-.4 2.7.2 4 .6 1.3 1.5 2.3 2.7 3 1.2.7 2.6.9 3.9.6z'/></svg>") !important;
14395
- mask-image: url("data:image/svg+xml;utf8,<svg width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg' fill='currentColor'><path d='M6.27 10.87h.71l4.56-4.56-.71-.71-4.2 4.21-1.92-1.92L4 8.6l2.27 2.27z'/><path fill-rule='evenodd' clip-rule='evenodd' d='M8.6 1c1.6.1 3.1.9 4.2 2 1.3 1.4 2 3.1 2 5.1 0 1.6-.6 3.1-1.6 4.4-1 1.2-2.4 2.1-4 2.4-1.6.3-3.2.1-4.6-.7-1.4-.8-2.5-2-3.1-3.5C.9 9.2.8 7.5 1.3 6c.5-1.6 1.4-2.9 2.8-3.8C5.4 1.3 7 .9 8.6 1zm.5 12.9c1.3-.3 2.5-1 3.4-2.1.8-1.1 1.3-2.4 1.2-3.8 0-1.6-.6-3.2-1.7-4.3-1-1-2.2-1.6-3.6-1.7-1.3-.1-2.7.2-3.8 1-1.1.8-1.9 1.9-2.3 3.3-.4 1.3-.4 2.7.2 4 .6 1.3 1.5 2.3 2.7 3 1.2.7 2.6.9 3.9.6z'/></svg>") !important;
14396
- background-color: #388a34 !important;
14397
- -webkit-mask-size: 18px !important;
14398
- mask-size: 18px !important;
14399
- }
14400
-
14401
- x-pw-overlay {
14402
- position: absolute;
14403
- top: 0;
14404
- max-width: min-content;
14405
- z-index: 2147483647;
14406
- background: transparent;
14407
- pointer-events: auto;
14408
- }
14409
-
14410
- x-pw-overlay x-pw-tools-list {
14411
- background-color: #ffffffdd;
14412
- box-shadow: rgba(0, 0, 0, 0.1) 0px 5px 5px;
14413
- border-radius: 3px;
14414
- border-bottom: none;
14415
- }
14416
-
14417
- x-pw-overlay x-pw-tool-item {
14418
- margin: 2px;
14419
- }
14420
-
14421
- textarea.text-editor {
14422
- font-family: system-ui,Ubuntu,Droid Sans,sans-serif;
14423
- flex: auto;
14424
- border: none;
14425
- margin: 6px 10px;
14426
- color: #333;
14427
- outline: 1px solid transparent!important;
14428
- resize: none;
14429
- padding: 0;
14430
- font-size: 13px;
14431
- }
14432
-
14433
- textarea.text-editor.does-not-match {
14434
- outline: 1px solid red !important;
14435
- }
14436
-
14437
- x-div {
14438
- display: block;
14439
- }
14440
-
14441
- x-spacer {
14442
- flex: auto;
14443
- }
14444
-
14445
- * {
14446
- box-sizing: border-box;
14447
- }
14448
-
14449
- *[hidden] {
14450
- display: none !important;
14451
- }
14452
-
14453
- x-locator-editor {
14454
- flex: none;
14455
- width: 100%;
14456
- height: 60px;
14457
- padding: 4px;
14458
- border-bottom: 1px solid #dddddd;
14459
- outline: 1px solid transparent;
14460
- }
14461
-
14462
- x-locator-editor.does-not-match {
14463
- outline: 1px solid red;
14464
- }
14465
-
14466
- .CodeMirror {
14467
- width: 100% !important;
14468
- height: 100% !important;
14469
- }
14470
- `;
14652
+ const highlightCSS = '/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the "License");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n:host {\n font-size: 13px;\n font-family: system-ui, "Ubuntu", "Droid Sans", sans-serif;\n color: #333;\n}\n\nsvg {\n position: absolute;\n height: 0;\n}\n\nx-pw-tooltip {\n backdrop-filter: blur(5px);\n background-color: white;\n border-radius: 6px;\n box-shadow: 0 0.5rem 1.2rem rgba(0,0,0,.3);\n display: none;\n font-size: 12.8px;\n font-weight: normal;\n left: 0;\n line-height: 1.5;\n max-width: 600px;\n position: absolute;\n top: 0;\n padding: 0;\n flex-direction: column;\n overflow: hidden;\n}\n\nx-pw-tooltip-line {\n display: flex;\n max-width: 600px;\n padding: 6px;\n user-select: none;\n cursor: pointer;\n}\n\nx-pw-tooltip-line.selectable:hover {\n background-color: hsl(0, 0%, 95%);\n overflow: hidden;\n}\n\nx-pw-tooltip-footer {\n display: flex;\n max-width: 600px;\n padding: 6px;\n user-select: none;\n color: #777;\n}\n\nx-pw-dialog {\n background-color: white;\n pointer-events: auto;\n border-radius: 6px;\n box-shadow: 0 0.5rem 1.2rem rgba(0,0,0,.3);\n display: flex;\n flex-direction: column;\n position: absolute;\n width: 400px;\n height: 150px;\n z-index: 10;\n font-size: 13px;\n}\n\nx-pw-dialog-body {\n display: flex;\n flex-direction: column;\n flex: auto;\n}\n\nx-pw-dialog-body label {\n margin: 5px 8px;\n display: flex;\n flex-direction: row;\n align-items: center;\n}\n\nx-pw-highlight {\n position: absolute;\n top: 0;\n left: 0;\n width: 0;\n height: 0;\n}\n\nx-pw-action-point {\n position: absolute;\n width: 20px;\n height: 20px;\n background: red;\n border-radius: 10px;\n margin: -10px 0 0 -10px;\n z-index: 2;\n}\n\nx-pw-separator {\n height: 1px;\n margin: 6px 9px;\n background: rgb(148 148 148 / 90%);\n}\n\nx-pw-tool-gripper {\n height: 28px;\n width: 24px;\n margin: 2px 0;\n cursor: grab;\n}\n\nx-pw-tool-gripper:active {\n cursor: grabbing;\n}\n\nx-pw-tool-gripper > x-div {\n width: 16px;\n height: 16px;\n margin: 6px 4px;\n clip-path: url(#icon-gripper);\n background-color: #555555;\n}\n\nx-pw-tools-list > label {\n display: flex;\n align-items: center;\n margin: 0 10px;\n user-select: none;\n}\n\nx-pw-tools-list {\n display: flex;\n width: 100%;\n border-bottom: 1px solid #dddddd;\n}\n\nx-pw-tool-item {\n pointer-events: auto;\n cursor: pointer;\n height: 28px;\n width: 28px;\n border-radius: 3px;\n}\n\nx-pw-tool-item:not(.disabled):hover {\n background-color: hsl(0, 0%, 86%);\n}\n\nx-pw-tool-item.active {\n background-color: rgba(138, 202, 228, 0.5);\n}\n\nx-pw-tool-item.active:not(.disabled):hover {\n background-color: #8acae4c4;\n}\n\nx-pw-tool-item > x-div {\n width: 16px;\n height: 16px;\n margin: 6px;\n background-color: #3a3a3a;\n}\n\nx-pw-tool-item.disabled > x-div {\n background-color: rgba(97, 97, 97, 0.5);\n cursor: default;\n}\n\nx-pw-tool-item.record.active {\n background-color: transparent;\n}\n\nx-pw-tool-item.record.active:hover {\n background-color: hsl(0, 0%, 86%);\n}\n\nx-pw-tool-item.record.active > x-div {\n background-color: #a1260d;\n}\n\nx-pw-tool-item.accept > x-div {\n background-color: #388a34;\n}\n\nx-pw-tool-item.record > x-div {\n /* codicon: circle-large-filled */\n clip-path: url(#icon-circle-large-filled);\n}\n\nx-pw-tool-item.pick-locator > x-div {\n /* codicon: inspect */\n clip-path: url(#icon-inspect);\n}\n\nx-pw-tool-item.text > x-div {\n /* codicon: whole-word */\n clip-path: url(#icon-whole-word);\n}\n\nx-pw-tool-item.visibility > x-div {\n /* codicon: eye */\n clip-path: url(#icon-eye);\n}\n\nx-pw-tool-item.value > x-div {\n /* codicon: symbol-constant */\n clip-path: url(#icon-symbol-constant);\n}\n\nx-pw-tool-item.accept > x-div {\n clip-path: url(#icon-check);\n}\n\nx-pw-tool-item.cancel > x-div {\n clip-path: url(#icon-close);\n}\n\nx-pw-tool-item.succeeded > x-div {\n /* codicon: pass */\n clip-path: url(#icon-pass);\n background-color: #388a34 !important;\n}\n\nx-pw-overlay {\n position: absolute;\n top: 0;\n max-width: min-content;\n z-index: 2147483647;\n background: transparent;\n pointer-events: auto;\n}\n\nx-pw-overlay x-pw-tools-list {\n background-color: #ffffffdd;\n box-shadow: rgba(0, 0, 0, 0.1) 0px 5px 5px;\n border-radius: 3px;\n border-bottom: none;\n}\n\nx-pw-overlay x-pw-tool-item {\n margin: 2px;\n}\n\ntextarea.text-editor {\n font-family: system-ui,Ubuntu,Droid Sans,sans-serif;\n flex: auto;\n border: none;\n margin: 6px 10px;\n color: #333;\n outline: 1px solid transparent!important;\n resize: none;\n padding: 0;\n font-size: 13px;\n}\n\ntextarea.text-editor.does-not-match {\n outline: 1px solid red !important;\n}\n\nx-div {\n display: block;\n}\n\nx-spacer {\n flex: auto;\n}\n\n* {\n box-sizing: border-box;\n}\n\n*[hidden] {\n display: none !important;\n}\n\nx-locator-editor {\n flex: none;\n width: 100%;\n height: 60px;\n padding: 4px;\n border-bottom: 1px solid #dddddd;\n outline: 1px solid transparent;\n}\n\nx-locator-editor.does-not-match {\n outline: 1px solid red;\n}\n\n.CodeMirror {\n width: 100% !important;\n height: 100% !important;\n}\n';
14471
14653
  class Highlight {
14472
14654
  constructor(injectedScript) {
14473
14655
  this._highlightEntries = [];
@@ -14497,10 +14679,16 @@ class Highlight {
14497
14679
  this._actionPointElement = document2.createElement("x-pw-action-point");
14498
14680
  this._actionPointElement.setAttribute("hidden", "true");
14499
14681
  this._glassPaneShadow = this._glassPaneElement.attachShadow({ mode: this._isUnderTest ? "open" : "closed" });
14682
+ if (typeof this._glassPaneShadow.adoptedStyleSheets.push === "function") {
14683
+ const sheet = new this._injectedScript.window.CSSStyleSheet();
14684
+ sheet.replaceSync(highlightCSS);
14685
+ this._glassPaneShadow.adoptedStyleSheets.push(sheet);
14686
+ } else {
14687
+ const styleElement = this._injectedScript.document.createElement("style");
14688
+ styleElement.textContent = highlightCSS;
14689
+ this._glassPaneShadow.appendChild(styleElement);
14690
+ }
14500
14691
  this._glassPaneShadow.appendChild(this._actionPointElement);
14501
- const styleElement = document2.createElement("style");
14502
- styleElement.textContent = highlightCSS;
14503
- this._glassPaneShadow.appendChild(styleElement);
14504
14692
  }
14505
14693
  install() {
14506
14694
  this._injectedScript.document.documentElement.appendChild(this._glassPaneElement);
@@ -14512,7 +14700,7 @@ class Highlight {
14512
14700
  if (this._rafRequest)
14513
14701
  cancelAnimationFrame(this._rafRequest);
14514
14702
  this.updateHighlight(this._injectedScript.querySelectorAll(selector, this._injectedScript.document.documentElement), { tooltipText: asLocator(this._language, stringifySelector(selector)) });
14515
- this._rafRequest = requestAnimationFrame(() => this.runHighlightOnRaf(selector));
14703
+ this._rafRequest = this._injectedScript.builtinRequestAnimationFrame(() => this.runHighlightOnRaf(selector));
14516
14704
  }
14517
14705
  uninstall() {
14518
14706
  if (this._rafRequest)
@@ -14672,12 +14860,107 @@ class Highlight {
14672
14860
  this._glassPaneShadow.appendChild(element);
14673
14861
  }
14674
14862
  }
14863
+ const leafRoles = /* @__PURE__ */ new Set([
14864
+ "button",
14865
+ "checkbox",
14866
+ "combobox",
14867
+ "link",
14868
+ "textbox"
14869
+ ]);
14870
+ let lastDom;
14871
+ function generateSimpleDomNode(injectedScript, target) {
14872
+ return generate(injectedScript, target).node;
14873
+ }
14874
+ function selectorForSimpleDomNodeId(injectedScript, id2) {
14875
+ const element = lastDom == null ? void 0 : lastDom.elements.get(id2);
14876
+ if (!element)
14877
+ throw new Error(`Internal error: element with id "${id2}" not found`);
14878
+ return injectedScript.generateSelectorSimple(element);
14879
+ }
14880
+ function generate(injectedScript, target) {
14881
+ const normalizeWhitespace = (text) => text.replace(/[\s\n]+/g, (match) => match.includes("\n") ? "\n" : " ");
14882
+ const tokens = [];
14883
+ const elements = /* @__PURE__ */ new Map();
14884
+ let lastId = 0;
14885
+ let resultTarget;
14886
+ const visit = (node) => {
14887
+ if (node.nodeType === Node.TEXT_NODE) {
14888
+ tokens.push(node.nodeValue);
14889
+ return;
14890
+ }
14891
+ if (node.nodeType === Node.ELEMENT_NODE) {
14892
+ const element = node;
14893
+ if (element.nodeName === "SCRIPT" || element.nodeName === "STYLE" || element.nodeName === "NOSCRIPT")
14894
+ return;
14895
+ if (injectedScript.utils.isElementVisible(element)) {
14896
+ const role = injectedScript.utils.getAriaRole(element);
14897
+ if (role && leafRoles.has(role)) {
14898
+ let value;
14899
+ if (element.nodeName === "INPUT" || element.nodeName === "TEXTAREA")
14900
+ value = element.value;
14901
+ const name = injectedScript.utils.getElementAccessibleName(element, false);
14902
+ const structuralId = String(++lastId);
14903
+ elements.set(structuralId, element);
14904
+ tokens.push(renderTag(injectedScript, role, name, structuralId, { value }));
14905
+ if (element === target) {
14906
+ const tagNoValue = renderTag(injectedScript, role, name, structuralId);
14907
+ resultTarget = { tag: tagNoValue, id: structuralId };
14908
+ }
14909
+ return;
14910
+ }
14911
+ }
14912
+ for (let child = element.firstChild; child; child = child.nextSibling)
14913
+ visit(child);
14914
+ }
14915
+ };
14916
+ injectedScript.utils.beginAriaCaches();
14917
+ try {
14918
+ visit(injectedScript.document.body);
14919
+ } finally {
14920
+ injectedScript.utils.endAriaCaches();
14921
+ }
14922
+ const dom = {
14923
+ markup: normalizeWhitespace(tokens.join(" ")),
14924
+ elements
14925
+ };
14926
+ if (target && !resultTarget)
14927
+ throw new Error("Target element is not in the simple DOM");
14928
+ lastDom = dom;
14929
+ return { dom, node: resultTarget ? { dom, ...resultTarget } : void 0 };
14930
+ }
14931
+ function renderTag(injectedScript, role, name, id2, params) {
14932
+ const escapedTextContent = injectedScript.utils.escapeHTML(name);
14933
+ const escapedValue = injectedScript.utils.escapeHTMLAttribute((params == null ? void 0 : params.value) || "");
14934
+ switch (role) {
14935
+ case "button":
14936
+ return `<button id="${id2}">${escapedTextContent}</button>`;
14937
+ case "link":
14938
+ return `<a id="${id2}">${escapedTextContent}</a>`;
14939
+ case "textbox":
14940
+ return `<input id="${id2}" title="${escapedTextContent}" value="${escapedValue}"></input>`;
14941
+ }
14942
+ return `<div role=${role} id="${id2}">${escapedTextContent}</div>`;
14943
+ }
14675
14944
  class InjectedScript {
14676
14945
  // eslint-disable-next-line no-restricted-globals
14677
14946
  constructor(window2, isUnderTest, sdkLanguage, testIdAttributeNameForStrictErrorAndConsoleCodegen, stableRafCount, browserName, customEngines) {
14678
14947
  this.onGlobalListenersRemoved = /* @__PURE__ */ new Set();
14679
14948
  this._testIdAttributeNameForStrictErrorAndConsoleCodegen = "data-testid";
14680
- this.utils = { isInsideScope, elementText, asLocator, normalizeWhiteSpace };
14949
+ this.utils = {
14950
+ asLocator,
14951
+ beginAriaCaches,
14952
+ cacheNormalizedWhitespaces,
14953
+ elementText,
14954
+ endAriaCaches,
14955
+ escapeHTML: escapeHTML$1,
14956
+ escapeHTMLAttribute,
14957
+ getAriaRole,
14958
+ getElementAccessibleDescription,
14959
+ getElementAccessibleName,
14960
+ isElementVisible,
14961
+ isInsideScope,
14962
+ normalizeWhiteSpace
14963
+ };
14681
14964
  this.window = window2;
14682
14965
  this.document = window2.document;
14683
14966
  this.isUnderTest = isUnderTest;
@@ -14726,6 +15009,18 @@ class InjectedScript {
14726
15009
  if (isUnderTest)
14727
15010
  this.window.__injectedScript = this;
14728
15011
  }
15012
+ builtinSetTimeout(callback, timeout) {
15013
+ var _a;
15014
+ if ((_a = this.window.__pwClock) == null ? void 0 : _a.builtin)
15015
+ return this.window.__pwClock.builtin.setTimeout(callback, timeout);
15016
+ return setTimeout(callback, timeout);
15017
+ }
15018
+ builtinRequestAnimationFrame(callback) {
15019
+ var _a;
15020
+ if ((_a = this.window.__pwClock) == null ? void 0 : _a.builtin)
15021
+ return this.window.__pwClock.builtin.requestAnimationFrame(callback);
15022
+ return requestAnimationFrame(callback);
15023
+ }
14729
15024
  eval(expression) {
14730
15025
  return this.window.eval(expression);
14731
15026
  }
@@ -14980,9 +15275,6 @@ class InjectedScript {
14980
15275
  })()`);
14981
15276
  return new constrFunction(this, params);
14982
15277
  }
14983
- isVisible(element) {
14984
- return isElementVisible(element);
14985
- }
14986
15278
  async viewportRatio(element) {
14987
15279
  return await new Promise((resolve) => {
14988
15280
  const observer = new IntersectionObserver((entries) => {
@@ -14990,7 +15282,7 @@ class InjectedScript {
14990
15282
  observer.disconnect();
14991
15283
  });
14992
15284
  observer.observe(element);
14993
- requestAnimationFrame(() => {
15285
+ this.builtinRequestAnimationFrame(() => {
14994
15286
  });
14995
15287
  });
14996
15288
  }
@@ -15020,14 +15312,14 @@ class InjectedScript {
15020
15312
  return null;
15021
15313
  if (behavior === "none")
15022
15314
  return element;
15023
- if (!element.matches("input, textarea, select")) {
15315
+ if (!element.matches("input, textarea, select") && !element.isContentEditable) {
15024
15316
  if (behavior === "button-link")
15025
15317
  element = element.closest("button, [role=button], a, [role=link]") || element;
15026
15318
  else
15027
15319
  element = element.closest("button, [role=button], [role=checkbox], [role=radio]") || element;
15028
15320
  }
15029
15321
  if (behavior === "follow-label") {
15030
- if (!element.matches("input, textarea, button, select, [role=button], [role=checkbox], [role=radio]") && !element.isContentEditable) {
15322
+ if (!element.matches("a, input, textarea, button, select, [role=link], [role=button], [role=checkbox], [role=radio]") && !element.isContentEditable) {
15031
15323
  element = element.closest("label") || element;
15032
15324
  }
15033
15325
  if (element.nodeName === "LABEL")
@@ -15090,12 +15382,12 @@ class InjectedScript {
15090
15382
  if (success !== continuePolling)
15091
15383
  fulfill(success);
15092
15384
  else
15093
- requestAnimationFrame(raf);
15385
+ this.builtinRequestAnimationFrame(raf);
15094
15386
  } catch (e) {
15095
15387
  reject(e);
15096
15388
  }
15097
15389
  };
15098
- requestAnimationFrame(raf);
15390
+ this.builtinRequestAnimationFrame(raf);
15099
15391
  return result;
15100
15392
  }
15101
15393
  elementState(node, state) {
@@ -15106,9 +15398,9 @@ class InjectedScript {
15106
15398
  return "error:notconnected";
15107
15399
  }
15108
15400
  if (state === "visible")
15109
- return this.isVisible(element);
15401
+ return isElementVisible(element);
15110
15402
  if (state === "hidden")
15111
- return !this.isVisible(element);
15403
+ return !isElementVisible(element);
15112
15404
  const disabled = getAriaDisabled(element);
15113
15405
  if (state === "disabled")
15114
15406
  return disabled;
@@ -15476,7 +15768,7 @@ class InjectedScript {
15476
15768
  attrs.push(` ${name}="${value}"`);
15477
15769
  }
15478
15770
  attrs.sort((a, b) => a.length - b.length);
15479
- const attrText = trimStringWithEllipsis(attrs.join(""), 50);
15771
+ const attrText = trimStringWithEllipsis(attrs.join(""), 500);
15480
15772
  if (autoClosingTags.has(element.nodeName))
15481
15773
  return oneLine(`<${element.nodeName.toLowerCase()}${attrText}/>`);
15482
15774
  const children = element.childNodes;
@@ -15592,7 +15884,7 @@ class InjectedScript {
15592
15884
  return { matches: false };
15593
15885
  if (options.isNot && options.expression === "to.be.in.viewport")
15594
15886
  return { matches: false };
15595
- return { matches: options.isNot, missingRecevied: true };
15887
+ return { matches: options.isNot, missingReceived: true };
15596
15888
  }
15597
15889
  return await this.expectSingleElement(element, options);
15598
15890
  }
@@ -15685,6 +15977,20 @@ class InjectedScript {
15685
15977
  received = element.id;
15686
15978
  } else if (expression === "to.have.text") {
15687
15979
  received = options.useInnerText ? element.innerText : elementText(/* @__PURE__ */ new Map(), element).full;
15980
+ } else if (expression === "to.have.accessible.name") {
15981
+ received = getElementAccessibleName(
15982
+ element,
15983
+ false
15984
+ /* includeHidden */
15985
+ );
15986
+ } else if (expression === "to.have.accessible.description") {
15987
+ received = getElementAccessibleDescription(
15988
+ element,
15989
+ false
15990
+ /* includeHidden */
15991
+ );
15992
+ } else if (expression === "to.have.role") {
15993
+ received = getAriaRole(element) || "";
15688
15994
  } else if (expression === "to.have.title") {
15689
15995
  received = this.document.title;
15690
15996
  } else if (expression === "to.have.url") {
@@ -15730,11 +16036,14 @@ class InjectedScript {
15730
16036
  }
15731
16037
  throw this.createStacklessError("Unknown expect matcher: " + expression);
15732
16038
  }
15733
- getElementAccessibleName(element, includeHidden) {
15734
- return getElementAccessibleName(element, !!includeHidden);
16039
+ generateSimpleDomNode(selector) {
16040
+ const element = this.querySelector(this.parseSelector(selector), this.document.documentElement, true);
16041
+ if (!element)
16042
+ return;
16043
+ return generateSimpleDomNode(this, element);
15735
16044
  }
15736
- getAriaRole(element) {
15737
- return getAriaRole(element);
16045
+ selectorForSimpleDomNodeId(nodeId) {
16046
+ return selectorForSimpleDomNodeId(this, nodeId);
15738
16047
  }
15739
16048
  }
15740
16049
  const autoClosingTags = /* @__PURE__ */ new Set(["AREA", "BASE", "BR", "COL", "COMMAND", "EMBED", "HR", "IMG", "INPUT", "KEYGEN", "LINK", "MENUITEM", "META", "PARAM", "SOURCE", "TRACK", "WBR"]);
@@ -15914,6 +16223,7 @@ function deepEquals(a, b) {
15914
16223
  return isNaN(a) && isNaN(b);
15915
16224
  return false;
15916
16225
  }
16226
+ const svgJson = { "tagName": "svg", "children": [{ "tagName": "defs", "children": [{ "tagName": "clipPath", "attrs": { "width": "16", "height": "16", "viewBox": "0 0 16 16", "fill": "currentColor", "id": "icon-gripper" }, "children": [{ "tagName": "path", "attrs": { "d": "M5 3h2v2H5zm0 4h2v2H5zm0 4h2v2H5zm4-8h2v2H9zm0 4h2v2H9zm0 4h2v2H9z" } }] }, { "tagName": "clipPath", "attrs": { "width": "16", "height": "16", "viewBox": "0 0 16 16", "fill": "currentColor", "id": "icon-circle-large-filled" }, "children": [{ "tagName": "path", "attrs": { "d": "M8 1a6.8 6.8 0 0 1 1.86.253 6.899 6.899 0 0 1 3.083 1.805 6.903 6.903 0 0 1 1.804 3.083C14.916 6.738 15 7.357 15 8s-.084 1.262-.253 1.86a6.9 6.9 0 0 1-.704 1.674 7.157 7.157 0 0 1-2.516 2.509 6.966 6.966 0 0 1-1.668.71A6.984 6.984 0 0 1 8 15a6.984 6.984 0 0 1-1.86-.246 7.098 7.098 0 0 1-1.674-.711 7.3 7.3 0 0 1-1.415-1.094 7.295 7.295 0 0 1-1.094-1.415 7.098 7.098 0 0 1-.71-1.675A6.985 6.985 0 0 1 1 8c0-.643.082-1.262.246-1.86a6.968 6.968 0 0 1 .711-1.667 7.156 7.156 0 0 1 2.509-2.516 6.895 6.895 0 0 1 1.675-.704A6.808 6.808 0 0 1 8 1z" } }] }, { "tagName": "clipPath", "attrs": { "width": "16", "height": "16", "viewBox": "0 0 16 16", "fill": "currentColor", "id": "icon-inspect" }, "children": [{ "tagName": "path", "attrs": { "fill-rule": "evenodd", "clip-rule": "evenodd", "d": "M1 3l1-1h12l1 1v6h-1V3H2v8h5v1H2l-1-1V3zm14.707 9.707L9 6v9.414l2.707-2.707h4zM10 13V8.414l3.293 3.293h-2L10 13z" } }] }, { "tagName": "clipPath", "attrs": { "width": "16", "height": "16", "viewBox": "0 0 16 16", "fill": "currentColor", "id": "icon-whole-word" }, "children": [{ "tagName": "path", "attrs": { "fill-rule": "evenodd", "clip-rule": "evenodd", "d": "M0 11H1V13H15V11H16V14H15H1H0V11Z" } }, { "tagName": "path", "attrs": { "d": "M6.84048 11H5.95963V10.1406H5.93814C5.555 10.7995 4.99104 11.1289 4.24625 11.1289C3.69839 11.1289 3.26871 10.9839 2.95718 10.6938C2.64924 10.4038 2.49527 10.0189 2.49527 9.53906C2.49527 8.51139 3.10041 7.91341 4.3107 7.74512L5.95963 7.51416C5.95963 6.57959 5.58186 6.1123 4.82632 6.1123C4.16389 6.1123 3.56591 6.33789 3.03238 6.78906V5.88672C3.57307 5.54297 4.19612 5.37109 4.90152 5.37109C6.19416 5.37109 6.84048 6.05501 6.84048 7.42285V11ZM5.95963 8.21777L4.63297 8.40039C4.22476 8.45768 3.91682 8.55973 3.70914 8.70654C3.50145 8.84977 3.39761 9.10579 3.39761 9.47461C3.39761 9.74316 3.4925 9.96338 3.68228 10.1353C3.87564 10.3035 4.13166 10.3877 4.45035 10.3877C4.8872 10.3877 5.24706 10.2355 5.52994 9.93115C5.8164 9.62321 5.95963 9.2347 5.95963 8.76562V8.21777Z" } }, { "tagName": "path", "attrs": { "d": "M9.3475 10.2051H9.32601V11H8.44515V2.85742H9.32601V6.4668H9.3475C9.78076 5.73633 10.4146 5.37109 11.2489 5.37109C11.9543 5.37109 12.5057 5.61816 12.9032 6.1123C13.3042 6.60286 13.5047 7.26172 13.5047 8.08887C13.5047 9.00911 13.2809 9.74674 12.8333 10.3018C12.3857 10.8532 11.7734 11.1289 10.9964 11.1289C10.2695 11.1289 9.71989 10.821 9.3475 10.2051ZM9.32601 7.98682V8.75488C9.32601 9.20964 9.47282 9.59635 9.76644 9.91504C10.0636 10.2301 10.4396 10.3877 10.8944 10.3877C11.4279 10.3877 11.8451 10.1836 12.1458 9.77539C12.4502 9.36719 12.6024 8.79964 12.6024 8.07275C12.6024 7.46045 12.4609 6.98063 12.1781 6.6333C11.8952 6.28597 11.512 6.1123 11.0286 6.1123C10.5166 6.1123 10.1048 6.29134 9.7933 6.64941C9.48177 7.00391 9.32601 7.44971 9.32601 7.98682Z" } }] }, { "tagName": "clipPath", "attrs": { "width": "16", "height": "16", "viewBox": "0 0 16 16", "fill": "currentColor", "id": "icon-eye" }, "children": [{ "tagName": "path", "attrs": { "d": "M7.99993 6.00316C9.47266 6.00316 10.6666 7.19708 10.6666 8.66981C10.6666 10.1426 9.47266 11.3365 7.99993 11.3365C6.52715 11.3365 5.33324 10.1426 5.33324 8.66981C5.33324 7.19708 6.52715 6.00316 7.99993 6.00316ZM7.99993 7.00315C7.07946 7.00315 6.33324 7.74935 6.33324 8.66981C6.33324 9.59028 7.07946 10.3365 7.99993 10.3365C8.9204 10.3365 9.6666 9.59028 9.6666 8.66981C9.6666 7.74935 8.9204 7.00315 7.99993 7.00315ZM7.99993 3.66675C11.0756 3.66675 13.7307 5.76675 14.4673 8.70968C14.5344 8.97755 14.3716 9.24908 14.1037 9.31615C13.8358 9.38315 13.5643 9.22041 13.4973 8.95248C12.8713 6.45205 10.6141 4.66675 7.99993 4.66675C5.38454 4.66675 3.12664 6.45359 2.50182 8.95555C2.43491 9.22341 2.16348 9.38635 1.89557 9.31948C1.62766 9.25255 1.46471 8.98115 1.53162 8.71321C2.26701 5.76856 4.9229 3.66675 7.99993 3.66675Z" } }] }, { "tagName": "clipPath", "attrs": { "width": "16", "height": "16", "viewBox": "0 0 16 16", "fill": "currentColor", "id": "icon-symbol-constant" }, "children": [{ "tagName": "path", "attrs": { "fill-rule": "evenodd", "clip-rule": "evenodd", "d": "M4 6h8v1H4V6zm8 3H4v1h8V9z" } }, { "tagName": "path", "attrs": { "fill-rule": "evenodd", "clip-rule": "evenodd", "d": "M1 4l1-1h12l1 1v8l-1 1H2l-1-1V4zm1 0v8h12V4H2z" } }] }, { "tagName": "clipPath", "attrs": { "width": "16", "height": "16", "viewBox": "0 0 16 16", "fill": "currentColor", "id": "icon-check" }, "children": [{ "tagName": "path", "attrs": { "fill-rule": "evenodd", "clip-rule": "evenodd", "d": "M14.431 3.323l-8.47 10-.79-.036-3.35-4.77.818-.574 2.978 4.24 8.051-9.506.764.646z" } }] }, { "tagName": "clipPath", "attrs": { "width": "16", "height": "16", "viewBox": "0 0 16 16", "fill": "currentColor", "id": "icon-close" }, "children": [{ "tagName": "path", "attrs": { "fill-rule": "evenodd", "clip-rule": "evenodd", "d": "M8 8.707l3.646 3.647.708-.707L8.707 8l3.647-3.646-.707-.708L8 7.293 4.354 3.646l-.707.708L7.293 8l-3.646 3.646.707.708L8 8.707z" } }] }, { "tagName": "clipPath", "attrs": { "width": "16", "height": "16", "viewBox": "0 0 16 16", "fill": "currentColor", "id": "icon-pass" }, "children": [{ "tagName": "path", "attrs": { "d": "M6.27 10.87h.71l4.56-4.56-.71-.71-4.2 4.21-1.92-1.92L4 8.6l2.27 2.27z" } }, { "tagName": "path", "attrs": { "fill-rule": "evenodd", "clip-rule": "evenodd", "d": "M8.6 1c1.6.1 3.1.9 4.2 2 1.3 1.4 2 3.1 2 5.1 0 1.6-.6 3.1-1.6 4.4-1 1.2-2.4 2.1-4 2.4-1.6.3-3.2.1-4.6-.7-1.4-.8-2.5-2-3.1-3.5C.9 9.2.8 7.5 1.3 6c.5-1.6 1.4-2.9 2.8-3.8C5.4 1.3 7 .9 8.6 1zm.5 12.9c1.3-.3 2.5-1 3.4-2.1.8-1.1 1.3-2.4 1.2-3.8 0-1.6-.6-3.2-1.7-4.3-1-1-2.2-1.6-3.6-1.7-1.3-.1-2.7.2-3.8 1-1.1.8-1.9 1.9-2.3 3.3-.4 1.3-.4 2.7.2 4 .6 1.3 1.5 2.3 2.7 3 1.2.7 2.6.9 3.9.6z" } }] }] }] };
15917
16227
  class NoneTool {
15918
16228
  cursor() {
15919
16229
  return "default";
@@ -16008,13 +16318,13 @@ class InspectTool {
16008
16318
  this._reset(true);
16009
16319
  }
16010
16320
  onKeyDown(event) {
16011
- var _a, _b, _c;
16321
+ var _a;
16012
16322
  consumeEvent(event);
16013
16323
  if (event.key === "Escape") {
16014
16324
  if ((_a = this._hoveredModel) == null ? void 0 : _a.tooltipListItemSelected)
16015
16325
  this._reset(true);
16016
16326
  else if (this._assertVisibility)
16017
- (_c = (_b = this._recorder.delegate).setMode) == null ? void 0 : _c.call(_b, "recording");
16327
+ this._recorder.setMode("recording");
16018
16328
  }
16019
16329
  }
16020
16330
  onKeyUp(event) {
@@ -16024,17 +16334,17 @@ class InspectTool {
16024
16334
  this._reset(false);
16025
16335
  }
16026
16336
  _commit(selector) {
16027
- var _a, _b, _c, _d, _e, _f, _g;
16337
+ var _a;
16028
16338
  if (this._assertVisibility) {
16029
- (_b = (_a = this._recorder.delegate).recordAction) == null ? void 0 : _b.call(_a, {
16339
+ this._recorder.recordAction({
16030
16340
  name: "assertVisible",
16031
16341
  selector,
16032
16342
  signals: []
16033
16343
  });
16034
- (_d = (_c = this._recorder.delegate).setMode) == null ? void 0 : _d.call(_c, "recording");
16035
- (_e = this._recorder.overlay) == null ? void 0 : _e.flashToolSucceeded("assertingVisibility");
16344
+ this._recorder.setMode("recording");
16345
+ (_a = this._recorder.overlay) == null ? void 0 : _a.flashToolSucceeded("assertingVisibility");
16036
16346
  } else {
16037
- (_g = (_f = this._recorder.delegate).setSelector) == null ? void 0 : _g.call(_f, selector);
16347
+ this._recorder.setSelector(selector);
16038
16348
  }
16039
16349
  }
16040
16350
  _reset(userGesture) {
@@ -16065,6 +16375,8 @@ class RecordActionTool {
16065
16375
  onClick(event) {
16066
16376
  if (isRangeInput(this._hoveredElement))
16067
16377
  return;
16378
+ if (event.button === 2 && event.type === "auxclick")
16379
+ return;
16068
16380
  if (this._shouldIgnoreMouseEvent(event))
16069
16381
  return;
16070
16382
  if (this._actionInProgress(event))
@@ -16090,6 +16402,23 @@ class RecordActionTool {
16090
16402
  clickCount: event.detail
16091
16403
  });
16092
16404
  }
16405
+ onContextMenu(event) {
16406
+ if (this._shouldIgnoreMouseEvent(event))
16407
+ return;
16408
+ if (this._actionInProgress(event))
16409
+ return;
16410
+ if (this._consumedDueToNoModel(event, this._hoveredModel))
16411
+ return;
16412
+ this._performAction({
16413
+ name: "click",
16414
+ selector: this._hoveredModel.selector,
16415
+ position: positionForEvent(event),
16416
+ signals: [],
16417
+ button: "right",
16418
+ modifiers: 0,
16419
+ clickCount: 0
16420
+ });
16421
+ }
16093
16422
  onPointerDown(event) {
16094
16423
  if (this._shouldIgnoreMouseEvent(event))
16095
16424
  return;
@@ -16133,10 +16462,9 @@ class RecordActionTool {
16133
16462
  this._onFocus(true);
16134
16463
  }
16135
16464
  onInput(event) {
16136
- var _a, _b, _c, _d, _e, _f;
16137
16465
  const target = this._recorder.deepEventTarget(event);
16138
16466
  if (target.nodeName === "INPUT" && target.type.toLowerCase() === "file") {
16139
- (_b = (_a = this._recorder.delegate).recordAction) == null ? void 0 : _b.call(_a, {
16467
+ this._recorder.recordAction({
16140
16468
  name: "setInputFiles",
16141
16469
  selector: this._activeModel.selector,
16142
16470
  signals: [],
@@ -16145,7 +16473,7 @@ class RecordActionTool {
16145
16473
  return;
16146
16474
  }
16147
16475
  if (isRangeInput(target)) {
16148
- (_d = (_c = this._recorder.delegate).recordAction) == null ? void 0 : _d.call(_c, {
16476
+ this._recorder.recordAction({
16149
16477
  name: "fill",
16150
16478
  // must use hoveredModel instead of activeModel for it to work in webkit
16151
16479
  selector: this._hoveredModel.selector,
@@ -16160,7 +16488,7 @@ class RecordActionTool {
16160
16488
  }
16161
16489
  if (this._consumedDueWrongTarget(event))
16162
16490
  return;
16163
- (_f = (_e = this._recorder.delegate).recordAction) == null ? void 0 : _f.call(_e, {
16491
+ this._recorder.recordAction({
16164
16492
  name: "fill",
16165
16493
  selector: this._activeModel.selector,
16166
16494
  signals: [],
@@ -16173,7 +16501,7 @@ class RecordActionTool {
16173
16501
  return;
16174
16502
  this._performAction({
16175
16503
  name: "select",
16176
- selector: this._hoveredModel.selector,
16504
+ selector: this._activeModel.selector,
16177
16505
  options: [...selectElement.selectedOptions].map((option) => option.value),
16178
16506
  signals: []
16179
16507
  });
@@ -16258,24 +16586,23 @@ class RecordActionTool {
16258
16586
  consumeEvent(event);
16259
16587
  return true;
16260
16588
  }
16261
- async _performAction(action) {
16262
- var _a, _b;
16589
+ _performAction(action) {
16263
16590
  this._hoveredElement = null;
16264
16591
  this._hoveredModel = null;
16265
16592
  this._activeModel = null;
16266
16593
  this._recorder.updateHighlight(null, false);
16267
16594
  this._performingAction = true;
16268
- await ((_b = (_a = this._recorder.delegate).performAction) == null ? void 0 : _b.call(_a, action).catch(() => {
16269
- }));
16270
- this._performingAction = false;
16271
- this._onFocus(false);
16272
- if (this._recorder.injectedScript.isUnderTest) {
16273
- console.error("Action performed for test: " + JSON.stringify({
16274
- // eslint-disable-line no-console
16275
- hovered: this._hoveredModel ? this._hoveredModel.selector : null,
16276
- active: this._activeModel ? this._activeModel.selector : null
16277
- }));
16278
- }
16595
+ void this._recorder.performAction(action).then(() => {
16596
+ this._performingAction = false;
16597
+ this._onFocus(false);
16598
+ if (this._recorder.injectedScript.isUnderTest) {
16599
+ console.error("Action performed for test: " + JSON.stringify({
16600
+ // eslint-disable-line no-console
16601
+ hovered: this._hoveredModel ? this._hoveredModel.selector : null,
16602
+ active: this._activeModel ? this._activeModel.selector : null
16603
+ }));
16604
+ }
16605
+ });
16279
16606
  }
16280
16607
  _shouldGenerateKeyPressFor(event) {
16281
16608
  if (event.key === "Enter" && (this._recorder.deepEventTarget(event).nodeName === "TEXTAREA" || this._recorder.deepEventTarget(event).isContentEditable))
@@ -16318,26 +16645,16 @@ class TextAssertionTool {
16318
16645
  constructor(recorder, kind) {
16319
16646
  this._hoverHighlight = null;
16320
16647
  this._action = null;
16321
- this._dialogElement = null;
16322
16648
  this._textCache = /* @__PURE__ */ new Map();
16323
16649
  this._recorder = recorder;
16324
16650
  this._kind = kind;
16325
- this._acceptButton = this._recorder.document.createElement("x-pw-tool-item");
16326
- this._acceptButton.title = "Accept";
16327
- this._acceptButton.classList.add("accept");
16328
- this._acceptButton.appendChild(this._recorder.document.createElement("x-div"));
16329
- this._acceptButton.addEventListener("click", () => this._commit());
16330
- this._cancelButton = this._recorder.document.createElement("x-pw-tool-item");
16331
- this._cancelButton.title = "Close";
16332
- this._cancelButton.classList.add("cancel");
16333
- this._cancelButton.appendChild(this._recorder.document.createElement("x-div"));
16334
- this._cancelButton.addEventListener("click", () => this._closeDialog());
16651
+ this._dialog = new Dialog(recorder);
16335
16652
  }
16336
16653
  cursor() {
16337
16654
  return "pointer";
16338
16655
  }
16339
16656
  cleanup() {
16340
- this._closeDialog();
16657
+ this._dialog.close();
16341
16658
  this._hoverHighlight = null;
16342
16659
  }
16343
16660
  onClick(event) {
@@ -16345,7 +16662,7 @@ class TextAssertionTool {
16345
16662
  if (this._kind === "value") {
16346
16663
  this._commitAssertValue();
16347
16664
  } else {
16348
- if (!this._dialogElement)
16665
+ if (!this._dialog.isShowing())
16349
16666
  this._showDialog();
16350
16667
  }
16351
16668
  }
@@ -16357,13 +16674,13 @@ class TextAssertionTool {
16357
16674
  onPointerUp(event) {
16358
16675
  var _a;
16359
16676
  const target = (_a = this._hoverHighlight) == null ? void 0 : _a.elements[0];
16360
- if (this._kind === "value" && target && target.nodeName === "INPUT" && target.disabled) {
16677
+ if (this._kind === "value" && target && (target.nodeName === "INPUT" || target.nodeName === "SELECT") && target.disabled) {
16361
16678
  this._commitAssertValue();
16362
16679
  }
16363
16680
  }
16364
16681
  onMouseMove(event) {
16365
16682
  var _a;
16366
- if (this._dialogElement)
16683
+ if (this._dialog.isShowing())
16367
16684
  return;
16368
16685
  const target = this._recorder.deepEventTarget(event);
16369
16686
  if (((_a = this._hoverHighlight) == null ? void 0 : _a.elements[0]) === target)
@@ -16377,9 +16694,8 @@ class TextAssertionTool {
16377
16694
  this._recorder.updateHighlight(this._hoverHighlight, true);
16378
16695
  }
16379
16696
  onKeyDown(event) {
16380
- var _a, _b;
16381
16697
  if (event.key === "Escape")
16382
- (_b = (_a = this._recorder.delegate).setMode) == null ? void 0 : _b.call(_a, "recording");
16698
+ this._recorder.setMode("recording");
16383
16699
  consumeEvent(event);
16384
16700
  }
16385
16701
  onScroll(event) {
@@ -16437,12 +16753,11 @@ class TextAssertionTool {
16437
16753
  return "";
16438
16754
  }
16439
16755
  _commit() {
16440
- var _a, _b, _c, _d;
16441
- if (!this._action || !this._dialogElement)
16756
+ if (!this._action || !this._dialog.isShowing())
16442
16757
  return;
16443
- this._closeDialog();
16444
- (_b = (_a = this._recorder.delegate).recordAction) == null ? void 0 : _b.call(_a, this._action);
16445
- (_d = (_c = this._recorder.delegate).setMode) == null ? void 0 : _d.call(_c, "recording");
16758
+ this._dialog.close();
16759
+ this._recorder.recordAction(this._action);
16760
+ this._recorder.setMode("recording");
16446
16761
  }
16447
16762
  _showDialog() {
16448
16763
  var _a;
@@ -16451,28 +16766,6 @@ class TextAssertionTool {
16451
16766
  this._action = this._generateAction();
16452
16767
  if (!this._action || this._action.name !== "assertText")
16453
16768
  return;
16454
- this._dialogElement = this._recorder.document.createElement("x-pw-dialog");
16455
- this._keyboardListener = (event) => {
16456
- if (event.key === "Escape") {
16457
- this._closeDialog();
16458
- return;
16459
- }
16460
- if (event.key === "Enter" && (event.ctrlKey || event.metaKey)) {
16461
- if (this._dialogElement)
16462
- this._commit();
16463
- return;
16464
- }
16465
- };
16466
- this._recorder.document.addEventListener("keydown", this._keyboardListener, true);
16467
- const toolbarElement = this._recorder.document.createElement("x-pw-tools-list");
16468
- const labelElement = this._recorder.document.createElement("label");
16469
- labelElement.textContent = "Assert that element contains text";
16470
- toolbarElement.appendChild(labelElement);
16471
- toolbarElement.appendChild(this._recorder.document.createElement("x-spacer"));
16472
- toolbarElement.appendChild(this._acceptButton);
16473
- toolbarElement.appendChild(this._cancelButton);
16474
- this._dialogElement.appendChild(toolbarElement);
16475
- const bodyElement = this._recorder.document.createElement("x-pw-dialog-body");
16476
16769
  const action = this._action;
16477
16770
  const textElement = this._recorder.document.createElement("textarea");
16478
16771
  textElement.setAttribute("spellcheck", "false");
@@ -16490,31 +16783,26 @@ class TextAssertionTool {
16490
16783
  textElement.classList.toggle("does-not-match", !matches);
16491
16784
  };
16492
16785
  textElement.addEventListener("input", updateAndValidate);
16493
- bodyElement.appendChild(textElement);
16494
- this._dialogElement.appendChild(bodyElement);
16495
- this._recorder.highlight.appendChild(this._dialogElement);
16496
- const position = this._recorder.highlight.tooltipPosition(this._recorder.highlight.firstBox(), this._dialogElement);
16497
- this._dialogElement.style.top = position.anchorTop + "px";
16498
- this._dialogElement.style.left = position.anchorLeft + "px";
16786
+ const label = "Assert that element contains text";
16787
+ const dialogElement = this._dialog.show({
16788
+ label,
16789
+ body: textElement,
16790
+ onCommit: () => this._commit()
16791
+ });
16792
+ const position = this._recorder.highlight.tooltipPosition(this._recorder.highlight.firstBox(), dialogElement);
16793
+ this._dialog.moveTo(position.anchorTop, position.anchorLeft);
16499
16794
  textElement.focus();
16500
16795
  }
16501
- _closeDialog() {
16502
- if (!this._dialogElement)
16503
- return;
16504
- this._dialogElement.remove();
16505
- this._recorder.document.removeEventListener("keydown", this._keyboardListener);
16506
- this._dialogElement = null;
16507
- }
16508
16796
  _commitAssertValue() {
16509
- var _a, _b, _c, _d, _e;
16797
+ var _a;
16510
16798
  if (this._kind !== "value")
16511
16799
  return;
16512
16800
  const action = this._generateAction();
16513
16801
  if (!action)
16514
16802
  return;
16515
- (_b = (_a = this._recorder.delegate).recordAction) == null ? void 0 : _b.call(_a, action);
16516
- (_d = (_c = this._recorder.delegate).setMode) == null ? void 0 : _d.call(_c, "recording");
16517
- (_e = this._recorder.overlay) == null ? void 0 : _e.flashToolSucceeded("assertingValue");
16803
+ this._recorder.recordAction(action);
16804
+ this._recorder.setMode("recording");
16805
+ (_a = this._recorder.overlay) == null ? void 0 : _a.flashToolSucceeded("assertingValue");
16518
16806
  }
16519
16807
  }
16520
16808
  class Overlay {
@@ -16523,37 +16811,38 @@ class Overlay {
16523
16811
  this._offsetX = 0;
16524
16812
  this._measure = { width: 0, height: 0 };
16525
16813
  this._recorder = recorder;
16526
- const document2 = this._recorder.injectedScript.document;
16814
+ const document2 = this._recorder.document;
16527
16815
  this._overlayElement = document2.createElement("x-pw-overlay");
16816
+ this._overlayElement.appendChild(createSvgElement(this._recorder.document, svgJson));
16528
16817
  const toolsListElement = document2.createElement("x-pw-tools-list");
16529
16818
  this._overlayElement.appendChild(toolsListElement);
16530
16819
  this._dragHandle = document2.createElement("x-pw-tool-gripper");
16531
16820
  this._dragHandle.appendChild(document2.createElement("x-div"));
16532
16821
  toolsListElement.appendChild(this._dragHandle);
16533
- this._recordToggle = this._recorder.injectedScript.document.createElement("x-pw-tool-item");
16822
+ this._recordToggle = this._recorder.document.createElement("x-pw-tool-item");
16534
16823
  this._recordToggle.title = "Record";
16535
16824
  this._recordToggle.classList.add("record");
16536
- this._recordToggle.appendChild(this._recorder.injectedScript.document.createElement("x-div"));
16825
+ this._recordToggle.appendChild(this._recorder.document.createElement("x-div"));
16537
16826
  toolsListElement.appendChild(this._recordToggle);
16538
- this._pickLocatorToggle = this._recorder.injectedScript.document.createElement("x-pw-tool-item");
16827
+ this._pickLocatorToggle = this._recorder.document.createElement("x-pw-tool-item");
16539
16828
  this._pickLocatorToggle.title = "Pick locator";
16540
16829
  this._pickLocatorToggle.classList.add("pick-locator");
16541
- this._pickLocatorToggle.appendChild(this._recorder.injectedScript.document.createElement("x-div"));
16830
+ this._pickLocatorToggle.appendChild(this._recorder.document.createElement("x-div"));
16542
16831
  toolsListElement.appendChild(this._pickLocatorToggle);
16543
- this._assertVisibilityToggle = this._recorder.injectedScript.document.createElement("x-pw-tool-item");
16832
+ this._assertVisibilityToggle = this._recorder.document.createElement("x-pw-tool-item");
16544
16833
  this._assertVisibilityToggle.title = "Assert visibility";
16545
16834
  this._assertVisibilityToggle.classList.add("visibility");
16546
- this._assertVisibilityToggle.appendChild(this._recorder.injectedScript.document.createElement("x-div"));
16835
+ this._assertVisibilityToggle.appendChild(this._recorder.document.createElement("x-div"));
16547
16836
  toolsListElement.appendChild(this._assertVisibilityToggle);
16548
- this._assertTextToggle = this._recorder.injectedScript.document.createElement("x-pw-tool-item");
16837
+ this._assertTextToggle = this._recorder.document.createElement("x-pw-tool-item");
16549
16838
  this._assertTextToggle.title = "Assert text";
16550
16839
  this._assertTextToggle.classList.add("text");
16551
- this._assertTextToggle.appendChild(this._recorder.injectedScript.document.createElement("x-div"));
16840
+ this._assertTextToggle.appendChild(this._recorder.document.createElement("x-div"));
16552
16841
  toolsListElement.appendChild(this._assertTextToggle);
16553
- this._assertValuesToggle = this._recorder.injectedScript.document.createElement("x-pw-tool-item");
16842
+ this._assertValuesToggle = this._recorder.document.createElement("x-pw-tool-item");
16554
16843
  this._assertValuesToggle.title = "Assert value";
16555
16844
  this._assertValuesToggle.classList.add("value");
16556
- this._assertValuesToggle.appendChild(this._recorder.injectedScript.document.createElement("x-div"));
16845
+ this._assertValuesToggle.appendChild(this._recorder.document.createElement("x-div"));
16557
16846
  toolsListElement.appendChild(this._assertValuesToggle);
16558
16847
  this._updateVisualPosition();
16559
16848
  this._refreshListeners();
@@ -16565,11 +16854,9 @@ class Overlay {
16565
16854
  this._dragState = { offsetX: this._offsetX, dragStart: { x: event.clientX, y: 0 } };
16566
16855
  }),
16567
16856
  addEventListener(this._recordToggle, "click", () => {
16568
- var _a, _b;
16569
- (_b = (_a = this._recorder.delegate).setMode) == null ? void 0 : _b.call(_a, this._recorder.state.mode === "none" || this._recorder.state.mode === "standby" || this._recorder.state.mode === "inspecting" ? "recording" : "standby");
16857
+ this._recorder.setMode(this._recorder.state.mode === "none" || this._recorder.state.mode === "standby" || this._recorder.state.mode === "inspecting" ? "recording" : "standby");
16570
16858
  }),
16571
16859
  addEventListener(this._pickLocatorToggle, "click", () => {
16572
- var _a, _b;
16573
16860
  const newMode = {
16574
16861
  "inspecting": "standby",
16575
16862
  "none": "inspecting",
@@ -16580,22 +16867,19 @@ class Overlay {
16580
16867
  "assertingVisibility": "recording-inspecting",
16581
16868
  "assertingValue": "recording-inspecting"
16582
16869
  };
16583
- (_b = (_a = this._recorder.delegate).setMode) == null ? void 0 : _b.call(_a, newMode[this._recorder.state.mode]);
16870
+ this._recorder.setMode(newMode[this._recorder.state.mode]);
16584
16871
  }),
16585
16872
  addEventListener(this._assertVisibilityToggle, "click", () => {
16586
- var _a, _b;
16587
16873
  if (!this._assertVisibilityToggle.classList.contains("disabled"))
16588
- (_b = (_a = this._recorder.delegate).setMode) == null ? void 0 : _b.call(_a, this._recorder.state.mode === "assertingVisibility" ? "recording" : "assertingVisibility");
16874
+ this._recorder.setMode(this._recorder.state.mode === "assertingVisibility" ? "recording" : "assertingVisibility");
16589
16875
  }),
16590
16876
  addEventListener(this._assertTextToggle, "click", () => {
16591
- var _a, _b;
16592
16877
  if (!this._assertTextToggle.classList.contains("disabled"))
16593
- (_b = (_a = this._recorder.delegate).setMode) == null ? void 0 : _b.call(_a, this._recorder.state.mode === "assertingText" ? "recording" : "assertingText");
16878
+ this._recorder.setMode(this._recorder.state.mode === "assertingText" ? "recording" : "assertingText");
16594
16879
  }),
16595
16880
  addEventListener(this._assertValuesToggle, "click", () => {
16596
- var _a, _b;
16597
16881
  if (!this._assertValuesToggle.classList.contains("disabled"))
16598
- (_b = (_a = this._recorder.delegate).setMode) == null ? void 0 : _b.call(_a, this._recorder.state.mode === "assertingValue" ? "recording" : "assertingValue");
16882
+ this._recorder.setMode(this._recorder.state.mode === "assertingValue" ? "recording" : "assertingValue");
16599
16883
  })
16600
16884
  ];
16601
16885
  }
@@ -16628,7 +16912,7 @@ class Overlay {
16628
16912
  flashToolSucceeded(tool) {
16629
16913
  const element = tool === "assertingVisibility" ? this._assertVisibilityToggle : this._assertValuesToggle;
16630
16914
  element.classList.add("succeeded");
16631
- setTimeout(() => element.classList.remove("succeeded"), 2e3);
16915
+ this._recorder.injectedScript.builtinSetTimeout(() => element.classList.remove("succeeded"), 2e3);
16632
16916
  }
16633
16917
  _hideOverlay() {
16634
16918
  this._overlayElement.setAttribute("hidden", "true");
@@ -16644,7 +16928,6 @@ class Overlay {
16644
16928
  this._overlayElement.style.left = (this._recorder.injectedScript.window.innerWidth - this._measure.width) / 2 + this._offsetX + "px";
16645
16929
  }
16646
16930
  onMouseMove(event) {
16647
- var _a, _b;
16648
16931
  if (!event.buttons) {
16649
16932
  this._dragState = void 0;
16650
16933
  return false;
@@ -16654,7 +16937,7 @@ class Overlay {
16654
16937
  const halfGapSize = (this._recorder.injectedScript.window.innerWidth - this._measure.width) / 2 - 10;
16655
16938
  this._offsetX = Math.max(-halfGapSize, Math.min(halfGapSize, this._offsetX));
16656
16939
  this._updateVisualPosition();
16657
- (_b = (_a = this._recorder.delegate).setOverlayState) == null ? void 0 : _b.call(_a, { offsetX: this._offsetX });
16940
+ this._recorder.setOverlayState({ offsetX: this._offsetX });
16658
16941
  consumeEvent(event);
16659
16942
  return true;
16660
16943
  }
@@ -16680,8 +16963,13 @@ class Recorder {
16680
16963
  constructor(injectedScript) {
16681
16964
  this._listeners = [];
16682
16965
  this._actionSelectorModel = null;
16683
- this.state = { mode: "none", testIdAttributeName: "data-testid", language: "javascript", overlay: { offsetX: 0 } };
16684
- this.delegate = {};
16966
+ this.state = {
16967
+ mode: "none",
16968
+ testIdAttributeName: "data-testid",
16969
+ language: "javascript",
16970
+ overlay: { offsetX: 0 }
16971
+ };
16972
+ this._delegate = {};
16685
16973
  this.document = injectedScript.document;
16686
16974
  this.injectedScript = injectedScript;
16687
16975
  this.highlight = injectedScript.createHighlight();
@@ -16700,12 +16988,13 @@ class Recorder {
16700
16988
  this.overlay = new Overlay(this);
16701
16989
  this.overlay.setUIState(this.state);
16702
16990
  }
16703
- this._styleElement = this.document.createElement("style");
16704
- this._styleElement.textContent = `
16991
+ this._stylesheet = new injectedScript.window.CSSStyleSheet();
16992
+ this._stylesheet.replaceSync(`
16705
16993
  body[data-pw-cursor=pointer] *, body[data-pw-cursor=pointer] *::after { cursor: pointer !important; }
16706
16994
  body[data-pw-cursor=text] *, body[data-pw-cursor=text] *::after { cursor: text !important; }
16707
- `;
16995
+ `);
16708
16996
  this.installListeners();
16997
+ injectedScript.utils.cacheNormalizedWhitespaces();
16709
16998
  if (injectedScript.isUnderTest)
16710
16999
  console.error("Recorder script ready for test");
16711
17000
  }
@@ -16732,7 +17021,7 @@ class Recorder {
16732
17021
  ];
16733
17022
  this.highlight.install();
16734
17023
  (_a = this.overlay) == null ? void 0 : _a.install();
16735
- this.injectedScript.document.head.appendChild(this._styleElement);
17024
+ this.document.adoptedStyleSheets.push(this._stylesheet);
16736
17025
  }
16737
17026
  _switchCurrentTool() {
16738
17027
  var _a, _b, _c;
@@ -16746,7 +17035,7 @@ class Recorder {
16746
17035
  }
16747
17036
  setUIState(state, delegate) {
16748
17037
  var _a, _b, _c, _d;
16749
- this.delegate = delegate;
17038
+ this._delegate = delegate;
16750
17039
  if (state.actionPoint && this.state.actionPoint && state.actionPoint.x === this.state.actionPoint.x && state.actionPoint.y === this.state.actionPoint.y)
16751
17040
  ;
16752
17041
  else if (!state.actionPoint && !this.state.actionPoint)
@@ -16903,7 +17192,7 @@ class Recorder {
16903
17192
  tooltipText = this.injectedScript.utils.asLocator(this.state.language, model.selector);
16904
17193
  this.highlight.updateHighlight((model == null ? void 0 : model.elements) || [], { ...model, tooltipText });
16905
17194
  if (userGesture)
16906
- (_b = (_a = this.delegate).highlightUpdated) == null ? void 0 : _b.call(_a);
17195
+ (_b = (_a = this._delegate).highlightUpdated) == null ? void 0 : _b.call(_a);
16907
17196
  }
16908
17197
  _ignoreOverlayEvent(event) {
16909
17198
  return event.composedPath().some((e) => {
@@ -16919,6 +17208,93 @@ class Recorder {
16919
17208
  }
16920
17209
  return event.composedPath()[0];
16921
17210
  }
17211
+ setMode(mode) {
17212
+ var _a, _b;
17213
+ void ((_b = (_a = this._delegate).setMode) == null ? void 0 : _b.call(_a, mode));
17214
+ }
17215
+ async performAction(action) {
17216
+ var _a, _b;
17217
+ await ((_b = (_a = this._delegate).performAction) == null ? void 0 : _b.call(_a, action).catch(() => {
17218
+ }));
17219
+ }
17220
+ recordAction(action) {
17221
+ var _a, _b;
17222
+ void ((_b = (_a = this._delegate).recordAction) == null ? void 0 : _b.call(_a, action));
17223
+ }
17224
+ setOverlayState(state) {
17225
+ var _a, _b;
17226
+ void ((_b = (_a = this._delegate).setOverlayState) == null ? void 0 : _b.call(_a, state));
17227
+ }
17228
+ setSelector(selector) {
17229
+ var _a, _b;
17230
+ void ((_b = (_a = this._delegate).setSelector) == null ? void 0 : _b.call(_a, selector));
17231
+ }
17232
+ }
17233
+ class Dialog {
17234
+ constructor(recorder) {
17235
+ this._dialogElement = null;
17236
+ this._recorder = recorder;
17237
+ }
17238
+ isShowing() {
17239
+ return !!this._dialogElement;
17240
+ }
17241
+ show(options) {
17242
+ const acceptButton = this._recorder.document.createElement("x-pw-tool-item");
17243
+ acceptButton.title = "Accept";
17244
+ acceptButton.classList.add("accept");
17245
+ acceptButton.appendChild(this._recorder.document.createElement("x-div"));
17246
+ acceptButton.addEventListener("click", () => options.onCommit());
17247
+ const cancelButton = this._recorder.document.createElement("x-pw-tool-item");
17248
+ cancelButton.title = "Close";
17249
+ cancelButton.classList.add("cancel");
17250
+ cancelButton.appendChild(this._recorder.document.createElement("x-div"));
17251
+ cancelButton.addEventListener("click", () => {
17252
+ var _a;
17253
+ this.close();
17254
+ (_a = options.onCancel) == null ? void 0 : _a.call(options);
17255
+ });
17256
+ this._dialogElement = this._recorder.document.createElement("x-pw-dialog");
17257
+ this._keyboardListener = (event) => {
17258
+ var _a;
17259
+ if (event.key === "Escape") {
17260
+ this.close();
17261
+ (_a = options.onCancel) == null ? void 0 : _a.call(options);
17262
+ return;
17263
+ }
17264
+ if (event.key === "Enter" && (event.ctrlKey || event.metaKey)) {
17265
+ if (this._dialogElement)
17266
+ options.onCommit();
17267
+ return;
17268
+ }
17269
+ };
17270
+ this._recorder.document.addEventListener("keydown", this._keyboardListener, true);
17271
+ const toolbarElement = this._recorder.document.createElement("x-pw-tools-list");
17272
+ const labelElement = this._recorder.document.createElement("label");
17273
+ labelElement.textContent = options.label;
17274
+ toolbarElement.appendChild(labelElement);
17275
+ toolbarElement.appendChild(this._recorder.document.createElement("x-spacer"));
17276
+ toolbarElement.appendChild(acceptButton);
17277
+ toolbarElement.appendChild(cancelButton);
17278
+ this._dialogElement.appendChild(toolbarElement);
17279
+ const bodyElement = this._recorder.document.createElement("x-pw-dialog-body");
17280
+ bodyElement.appendChild(options.body);
17281
+ this._dialogElement.appendChild(bodyElement);
17282
+ this._recorder.highlight.appendChild(this._dialogElement);
17283
+ return this._dialogElement;
17284
+ }
17285
+ moveTo(top, left) {
17286
+ if (!this._dialogElement)
17287
+ return;
17288
+ this._dialogElement.style.top = top + "px";
17289
+ this._dialogElement.style.left = left + "px";
17290
+ }
17291
+ close() {
17292
+ if (!this._dialogElement)
17293
+ return;
17294
+ this._dialogElement.remove();
17295
+ this._recorder.document.removeEventListener("keydown", this._keyboardListener);
17296
+ this._dialogElement = null;
17297
+ }
16922
17298
  }
16923
17299
  function deepActiveElement(document2) {
16924
17300
  let activeElement = document2.activeElement;
@@ -16992,6 +17368,18 @@ function querySelector(injectedScript, selector, ownerDocument) {
16992
17368
  };
16993
17369
  }
16994
17370
  }
17371
+ function createSvgElement(doc, { tagName, attrs, children }) {
17372
+ const elem = doc.createElementNS("http://www.w3.org/2000/svg", tagName);
17373
+ if (attrs) {
17374
+ for (const [k2, v2] of Object.entries(attrs))
17375
+ elem.setAttribute(k2, v2);
17376
+ }
17377
+ if (children) {
17378
+ for (const c of children)
17379
+ elem.appendChild(createSvgElement(doc, c));
17380
+ }
17381
+ return elem;
17382
+ }
16995
17383
  function getByAttributeTextSelector(attrName, text, options) {
16996
17384
  return `internal:attr=[${attrName}=${escapeForAttributeSelector(text, (options == null ? void 0 : options.exact) || false)}]`;
16997
17385
  }
@@ -17279,7 +17667,7 @@ const BrowserFrame = ({ url }) => {
17279
17667
  ] }) })
17280
17668
  ] });
17281
17669
  };
17282
- const SnapshotTab = ({ action, sdkLanguage, testIdAttributeName, isInspecting, setIsInspecting, highlightedLocator, setHighlightedLocator }) => {
17670
+ const SnapshotTab = ({ action, sdkLanguage, testIdAttributeName, isInspecting, setIsInspecting, highlightedLocator, setHighlightedLocator, openPage }) => {
17283
17671
  const [measure, ref] = useMeasure();
17284
17672
  const [snapshotTab, setSnapshotTab] = reactExports.useState("action");
17285
17673
  const { snapshots } = reactExports.useMemo(() => {
@@ -17412,6 +17800,7 @@ const SnapshotTab = ({ action, sdkLanguage, testIdAttributeName, isInspecting, s
17412
17800
  }
17413
17801
  ),
17414
17802
  /* @__PURE__ */ jsxRuntimeExports.jsxs(Toolbar, { children: [
17803
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { className: "pick-locator", title: "Pick locator", icon: "target", toggled: isInspecting, onClick: () => setIsInspecting(!isInspecting) }),
17415
17804
  ["action", "before", "after"].map((tab) => {
17416
17805
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
17417
17806
  TabbedPaneTab,
@@ -17420,12 +17809,15 @@ const SnapshotTab = ({ action, sdkLanguage, testIdAttributeName, isInspecting, s
17420
17809
  title: renderTitle(tab),
17421
17810
  selected: snapshotTab === tab,
17422
17811
  onSelect: () => setSnapshotTab(tab)
17423
- }
17812
+ },
17813
+ tab
17424
17814
  );
17425
17815
  }),
17426
17816
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { flex: "auto" } }),
17427
17817
  /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "link-external", title: "Open snapshot in a new tab", disabled: !popoutUrl, onClick: () => {
17428
- const win = window.open(popoutUrl || "", "_blank");
17818
+ if (!openPage)
17819
+ openPage = window.open;
17820
+ const win = openPage(popoutUrl || "", "_blank");
17429
17821
  win == null ? void 0 : win.addEventListener("DOMContentLoaded", () => {
17430
17822
  const injectedScript = new InjectedScript(win, false, sdkLanguage, testIdAttributeName, 1, "chromium", []);
17431
17823
  new ConsoleAPI(injectedScript);
@@ -17439,8 +17831,8 @@ const SnapshotTab = ({ action, sdkLanguage, testIdAttributeName, isInspecting, s
17439
17831
  }, children: [
17440
17832
  /* @__PURE__ */ jsxRuntimeExports.jsx(BrowserFrame, { url: snapshotInfo.url }),
17441
17833
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "snapshot-switcher", children: [
17442
- /* @__PURE__ */ jsxRuntimeExports.jsx("iframe", { ref: iframeRef0, name: "snapshot", title: "DOM Snapshot", className: loadingRef.current.visibleIframe === 0 ? "snapshot-visible" : "" }),
17443
- /* @__PURE__ */ jsxRuntimeExports.jsx("iframe", { ref: iframeRef1, name: "snapshot", title: "DOM Snapshot", className: loadingRef.current.visibleIframe === 1 ? "snapshot-visible" : "" })
17834
+ /* @__PURE__ */ jsxRuntimeExports.jsx("iframe", { ref: iframeRef0, name: "snapshot", title: "DOM Snapshot", className: clsx(loadingRef.current.visibleIframe === 0 && "snapshot-visible") }),
17835
+ /* @__PURE__ */ jsxRuntimeExports.jsx("iframe", { ref: iframeRef1, name: "snapshot", title: "DOM Snapshot", className: clsx(loadingRef.current.visibleIframe === 1 && "snapshot-visible") })
17444
17836
  ] })
17445
17837
  ] }) })
17446
17838
  ]
@@ -17527,7 +17919,7 @@ const StackTraceView = ({ stack, setSelectedFrame, selectedFrame }) => {
17527
17919
  }
17528
17920
  );
17529
17921
  };
17530
- const SourceTab = ({ stack, sources, hideStackFrames, rootDir, fallbackLocation }) => {
17922
+ const SourceTab = ({ stack, sources, rootDir, fallbackLocation, stackFrameLocation, onOpenExternally }) => {
17531
17923
  const [lastStack, setLastStack] = reactExports.useState();
17532
17924
  const [selectedFrame, setSelectedFrame] = reactExports.useState(0);
17533
17925
  reactExports.useEffect(() => {
@@ -17536,7 +17928,7 @@ const SourceTab = ({ stack, sources, hideStackFrames, rootDir, fallbackLocation
17536
17928
  setSelectedFrame(0);
17537
17929
  }
17538
17930
  }, [stack, lastStack, setLastStack, setSelectedFrame]);
17539
- const { source, highlight, targetLine, fileName } = useAsyncMemo(async () => {
17931
+ const { source, highlight, targetLine, fileName, location } = useAsyncMemo(async () => {
17540
17932
  var _a, _b;
17541
17933
  const actionLocation = stack == null ? void 0 : stack[selectedFrame];
17542
17934
  const shouldUseFallback = !(actionLocation == null ? void 0 : actionLocation.file);
@@ -17548,6 +17940,7 @@ const SourceTab = ({ stack, sources, hideStackFrames, rootDir, fallbackLocation
17548
17940
  source2 = { errors: ((_a = fallbackLocation == null ? void 0 : fallbackLocation.source) == null ? void 0 : _a.errors) || [], content: void 0 };
17549
17941
  sources.set(file, source2);
17550
17942
  }
17943
+ const location2 = shouldUseFallback ? fallbackLocation : actionLocation;
17551
17944
  const targetLine2 = shouldUseFallback ? (fallbackLocation == null ? void 0 : fallbackLocation.line) || ((_b = source2.errors[0]) == null ? void 0 : _b.line) || 0 : actionLocation.line;
17552
17945
  const fileName2 = rootDir && file.startsWith(rootDir) ? file.substring(rootDir.length + 1) : file;
17553
17946
  const highlight2 = source2.errors.map((e) => ({ type: "error", line: e.line, message: e.message }));
@@ -17566,15 +17959,36 @@ const SourceTab = ({ stack, sources, hideStackFrames, rootDir, fallbackLocation
17566
17959
  source2.content = `<Unable to read "${file}">`;
17567
17960
  }
17568
17961
  }
17569
- return { source: source2, highlight: highlight2, targetLine: targetLine2, fileName: fileName2 };
17962
+ return { source: source2, highlight: highlight2, targetLine: targetLine2, fileName: fileName2, location: location2 };
17570
17963
  }, [stack, selectedFrame, rootDir, fallbackLocation], { source: { errors: [], content: "Loading…" }, highlight: [] });
17571
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(SplitView, { sidebarSize: 200, orientation: "horizontal", sidebarHidden: hideStackFrames, children: [
17572
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "vbox", "data-testid": "source-code", children: [
17573
- fileName && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "source-tab-file-name", children: fileName }),
17574
- /* @__PURE__ */ jsxRuntimeExports.jsx(CodeMirrorWrapper, { text: source.content || "", language: "javascript", highlight, revealLine: targetLine, readOnly: true, lineNumbers: true })
17575
- ] }),
17576
- /* @__PURE__ */ jsxRuntimeExports.jsx(StackTraceView, { stack, selectedFrame, setSelectedFrame })
17577
- ] });
17964
+ const openExternally = reactExports.useCallback(() => {
17965
+ if (!location)
17966
+ return;
17967
+ if (onOpenExternally) {
17968
+ onOpenExternally(location);
17969
+ } else {
17970
+ window.location.href = `vscode://file//${location.file}:${location.line}`;
17971
+ }
17972
+ }, [onOpenExternally, location]);
17973
+ const showStackFrames = ((stack == null ? void 0 : stack.length) ?? 0) > 1;
17974
+ const shortFileName = getFileName(fileName);
17975
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
17976
+ SplitView,
17977
+ {
17978
+ sidebarSize: 200,
17979
+ orientation: stackFrameLocation === "bottom" ? "vertical" : "horizontal",
17980
+ sidebarHidden: !showStackFrames,
17981
+ main: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "vbox", "data-testid": "source-code", children: [
17982
+ fileName && /* @__PURE__ */ jsxRuntimeExports.jsxs(Toolbar, { children: [
17983
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "source-tab-file-name", title: fileName, children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: shortFileName }) }),
17984
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CopyToClipboard, { description: "Copy filename", value: shortFileName }),
17985
+ location && /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "link-external", title: "Open in VS Code", onClick: openExternally })
17986
+ ] }),
17987
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CodeMirrorWrapper, { text: source.content || "", language: "javascript", highlight, revealLine: targetLine, readOnly: true, lineNumbers: true })
17988
+ ] }),
17989
+ sidebar: /* @__PURE__ */ jsxRuntimeExports.jsx(StackTraceView, { stack, selectedFrame, setSelectedFrame })
17990
+ }
17991
+ );
17578
17992
  };
17579
17993
  async function calculateSha1(text) {
17580
17994
  const buffer = new TextEncoder().encode(text);
@@ -17587,6 +18001,12 @@ async function calculateSha1(text) {
17587
18001
  }
17588
18002
  return hexCodes.join("");
17589
18003
  }
18004
+ function getFileName(fullPath) {
18005
+ if (!fullPath)
18006
+ return "";
18007
+ const pathSep = (fullPath == null ? void 0 : fullPath.includes("/")) ? "/" : "\\";
18008
+ return (fullPath == null ? void 0 : fullPath.split(pathSep).pop()) ?? "";
18009
+ }
17590
18010
  const tileSize = { width: 200, height: 45 };
17591
18011
  const frameMargin = 2.5;
17592
18012
  const rowHeight = tileSize.height + frameMargin * 2;
@@ -17602,7 +18022,7 @@ const FilmStrip = ({ model, boundaries, previewPoint }) => {
17602
18022
  const screencastFrames = (_b = (_a = model == null ? void 0 : model.pages) == null ? void 0 : _a[pageIndex]) == null ? void 0 : _b.screencastFrames;
17603
18023
  let previewImage = void 0;
17604
18024
  let previewSize = void 0;
17605
- if (previewPoint !== void 0 && screencastFrames) {
18025
+ if (previewPoint !== void 0 && screencastFrames && screencastFrames.length) {
17606
18026
  const previewTime = boundaries.minimum + (boundaries.maximum - boundaries.minimum) * previewPoint.x / measure.width;
17607
18027
  previewImage = screencastFrames[upperBound(screencastFrames, previewTime, timeComparator) - 1];
17608
18028
  const fitInto = {
@@ -17612,7 +18032,7 @@ const FilmStrip = ({ model, boundaries, previewPoint }) => {
17612
18032
  previewSize = previewImage ? inscribe({ width: previewImage.width, height: previewImage.height }, fitInto) : void 0;
17613
18033
  }
17614
18034
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "film-strip", ref, children: [
17615
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "film-strip-lanes", ref: lanesRef, children: model == null ? void 0 : model.pages.map((page, index) => /* @__PURE__ */ jsxRuntimeExports.jsx(
18035
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "film-strip-lanes", ref: lanesRef, children: model == null ? void 0 : model.pages.map((page, index) => page.screencastFrames.length ? /* @__PURE__ */ jsxRuntimeExports.jsx(
17616
18036
  FilmStripLane,
17617
18037
  {
17618
18038
  boundaries,
@@ -17620,7 +18040,7 @@ const FilmStrip = ({ model, boundaries, previewPoint }) => {
17620
18040
  width: measure.width
17621
18041
  },
17622
18042
  index
17623
- )) }),
18043
+ ) : null) }),
17624
18044
  (previewPoint == null ? void 0 : previewPoint.x) !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "film-strip-hover", style: {
17625
18045
  top: measure.bottom + 5,
17626
18046
  left: Math.min(previewPoint.x, measure.width - (previewSize ? previewSize.width : 0) - 10)
@@ -17682,7 +18102,7 @@ function inscribe(object, area) {
17682
18102
  height: object.height / scale | 0
17683
18103
  };
17684
18104
  }
17685
- const Timeline = ({ model, boundaries, onSelected, highlightedAction, highlightedEntry, selectedTime, setSelectedTime, sdkLanguage }) => {
18105
+ const Timeline = ({ model, boundaries, consoleEntries, onSelected, highlightedAction, highlightedEntry, highlightedConsoleEntry, selectedTime, setSelectedTime, sdkLanguage }) => {
17686
18106
  const [measure, ref] = useMeasure();
17687
18107
  const [dragWindow, setDragWindow] = reactExports.useState();
17688
18108
  const [previewPoint, setPreviewPoint] = reactExports.useState();
@@ -17726,12 +18146,31 @@ const Timeline = ({ model, boundaries, onSelected, highlightedAction, highlighte
17726
18146
  error: false
17727
18147
  });
17728
18148
  }
18149
+ for (const consoleMessage of consoleEntries || []) {
18150
+ bars2.push({
18151
+ consoleMessage,
18152
+ leftTime: consoleMessage.timestamp,
18153
+ rightTime: consoleMessage.timestamp,
18154
+ leftPosition: timeToPosition(measure.width, boundaries, consoleMessage.timestamp),
18155
+ rightPosition: timeToPosition(measure.width, boundaries, consoleMessage.timestamp),
18156
+ active: false,
18157
+ error: consoleMessage.isError
18158
+ });
18159
+ }
17729
18160
  return bars2;
17730
- }, [model, boundaries, measure]);
18161
+ }, [model, consoleEntries, boundaries, measure]);
17731
18162
  reactExports.useMemo(() => {
17732
- for (const bar of bars)
17733
- bar.active = !!highlightedAction && bar.action === highlightedAction || !!highlightedEntry && bar.resource === highlightedEntry;
17734
- }, [bars, highlightedAction, highlightedEntry]);
18163
+ for (const bar of bars) {
18164
+ if (highlightedAction)
18165
+ bar.active = bar.action === highlightedAction;
18166
+ else if (highlightedEntry)
18167
+ bar.active = bar.resource === highlightedEntry;
18168
+ else if (highlightedConsoleEntry)
18169
+ bar.active = bar.consoleMessage === highlightedConsoleEntry;
18170
+ else
18171
+ bar.active = false;
18172
+ }
18173
+ }, [bars, highlightedAction, highlightedEntry, highlightedConsoleEntry]);
17735
18174
  const onMouseDown = reactExports.useCallback((event) => {
17736
18175
  setPreviewPoint(void 0);
17737
18176
  if (!ref.current)
@@ -17846,10 +18285,17 @@ const Timeline = ({ model, boundaries, onSelected, highlightedAction, highlighte
17846
18285
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
17847
18286
  "div",
17848
18287
  {
17849
- className: "timeline-bar" + (bar.action ? " action" : "") + (bar.resource ? " network" : "") + (bar.active ? " active" : "") + (bar.error ? " error" : ""),
18288
+ className: clsx(
18289
+ "timeline-bar",
18290
+ bar.action && "action",
18291
+ bar.resource && "network",
18292
+ bar.consoleMessage && "console-message",
18293
+ bar.active && "active",
18294
+ bar.error && "error"
18295
+ ),
17850
18296
  style: {
17851
18297
  left: bar.leftPosition,
17852
- width: Math.max(1, bar.rightPosition - bar.leftPosition),
18298
+ width: Math.max(5, bar.rightPosition - bar.leftPosition),
17853
18299
  top: barTop(bar),
17854
18300
  bottom: 0
17855
18301
  }
@@ -17911,7 +18357,7 @@ const MetadataView = ({ model }) => {
17911
18357
  var _a, _b;
17912
18358
  if (!model)
17913
18359
  return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, {});
17914
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "metadata-view vbox", children: [
18360
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { "data-testid": "metadata-view", className: "vbox", style: { flexShrink: 0 }, children: [
17915
18361
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-section", style: { paddingTop: 2 }, children: "Time" }),
17916
18362
  !!model.wallTime && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
17917
18363
  "start time:",
@@ -17938,6 +18384,13 @@ const MetadataView = ({ model }) => {
17938
18384
  "user agent:",
17939
18385
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value datetime", title: model.options.userAgent, children: model.options.userAgent })
17940
18386
  ] }),
18387
+ model.options.baseURL && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
18388
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-section", style: { paddingTop: 2 }, children: "Config" }),
18389
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
18390
+ "baseURL:",
18391
+ /* @__PURE__ */ jsxRuntimeExports.jsx("a", { className: "call-value string", href: model.options.baseURL, title: model.options.baseURL, target: "_blank", rel: "noopener noreferrer", children: model.options.baseURL })
18392
+ ] })
18393
+ ] }),
17941
18394
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-section", children: "Viewport" }),
17942
18395
  model.options.viewport && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
17943
18396
  "width:",
@@ -17994,7 +18447,7 @@ const checkerboardStyle = {
17994
18447
  rgb(0 0 0 / 15%) 0px -6.1px 12px,
17995
18448
  rgb(0 0 0 / 25%) 0px 6px 12px`
17996
18449
  };
17997
- const ImageDiffView = ({ diff }) => {
18450
+ const ImageDiffView = ({ diff, noTargetBlank }) => {
17998
18451
  const [mode, setMode] = reactExports.useState(diff.diff ? "diff" : "actual");
17999
18452
  const [showSxsDiff, setShowSxsDiff] = reactExports.useState(false);
18000
18453
  const [expectedImage, setExpectedImage] = reactExports.useState(null);
@@ -18046,10 +18499,10 @@ const ImageDiffView = ({ diff }) => {
18046
18499
  /* @__PURE__ */ jsxRuntimeExports.jsx(ImageWithSize, { image: actualImage, title: "Actual", canvasWidth: sxsScale * imageWidth, canvasHeight: sxsScale * imageHeight, scale: sxsScale })
18047
18500
  ] })
18048
18501
  ] }),
18049
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { alignSelf: "start", lineHeight: "18px" }, children: [
18050
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: diff.diff && /* @__PURE__ */ jsxRuntimeExports.jsx("a", { target: "_blank", href: diff.diff.attachment.path, children: diff.diff.attachment.name }) }),
18051
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: /* @__PURE__ */ jsxRuntimeExports.jsx("a", { target: "_blank", href: diff.actual.attachment.path, children: diff.actual.attachment.name }) }),
18052
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: /* @__PURE__ */ jsxRuntimeExports.jsx("a", { target: "_blank", href: diff.expected.attachment.path, children: diff.expected.attachment.name }) })
18502
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { alignSelf: "start", lineHeight: "18px", marginLeft: "15px" }, children: [
18503
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: diff.diff && /* @__PURE__ */ jsxRuntimeExports.jsx("a", { target: "_blank", href: diff.diff.attachment.path, rel: "noreferrer", children: diff.diff.attachment.name }) }),
18504
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: /* @__PURE__ */ jsxRuntimeExports.jsx("a", { target: noTargetBlank ? "" : "_blank", href: diff.actual.attachment.path, rel: "noreferrer", children: diff.actual.attachment.name }) }),
18505
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: /* @__PURE__ */ jsxRuntimeExports.jsx("a", { target: noTargetBlank ? "" : "_blank", href: diff.expected.attachment.path, rel: "noreferrer", children: diff.expected.attachment.name }) })
18053
18506
  ] })
18054
18507
  ] }) });
18055
18508
  };
@@ -18116,6 +18569,87 @@ const ImageWithSize = ({ image, title, alt, canvasWidth, canvasHeight, scale, on
18116
18569
  ) })
18117
18570
  ] });
18118
18571
  };
18572
+ function isTextualMimeType(mimeType) {
18573
+ return !!mimeType.match(/^(text\/.*?|application\/(json|(x-)?javascript|xml.*?|ecmascript|graphql|x-www-form-urlencoded)|image\/svg(\+xml)?|application\/.*?(\+json|\+xml))(;\s*charset=.*)?$/);
18574
+ }
18575
+ const Expandable = ({ title, children, setExpanded, expanded, expandOnTitleClick }) => {
18576
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: clsx("expandable", expanded && "expanded"), children: [
18577
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "expandable-title", onClick: () => expandOnTitleClick && setExpanded(!expanded), children: [
18578
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
18579
+ "div",
18580
+ {
18581
+ className: clsx("codicon", expanded ? "codicon-chevron-down" : "codicon-chevron-right"),
18582
+ style: { cursor: "pointer", color: "var(--vscode-foreground)", marginLeft: "5px" },
18583
+ onClick: () => !expandOnTitleClick && setExpanded(!expanded)
18584
+ }
18585
+ ),
18586
+ title
18587
+ ] }),
18588
+ expanded && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { marginLeft: 25 }, children })
18589
+ ] });
18590
+ };
18591
+ function linkifyText(description) {
18592
+ const result = [];
18593
+ let currentIndex = 0;
18594
+ let match;
18595
+ while ((match = kWebLinkRe.exec(description)) !== null) {
18596
+ const stringBeforeMatch = description.substring(currentIndex, match.index);
18597
+ if (stringBeforeMatch)
18598
+ result.push(stringBeforeMatch);
18599
+ const value = match[0];
18600
+ result.push(renderLink(value));
18601
+ currentIndex = match.index + value.length;
18602
+ }
18603
+ const stringAfterMatches = description.substring(currentIndex);
18604
+ if (stringAfterMatches)
18605
+ result.push(stringAfterMatches);
18606
+ return result;
18607
+ }
18608
+ function renderLink(text) {
18609
+ let link = text;
18610
+ if (link.startsWith("www."))
18611
+ link = "https://" + link;
18612
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: link, target: "_blank", rel: "noopener noreferrer", children: text });
18613
+ }
18614
+ const ExpandableAttachment = ({ attachment }) => {
18615
+ const [expanded, setExpanded] = reactExports.useState(false);
18616
+ const [attachmentText, setAttachmentText] = reactExports.useState(null);
18617
+ const [placeholder, setPlaceholder] = reactExports.useState(null);
18618
+ const isTextAttachment = isTextualMimeType(attachment.contentType);
18619
+ const hasContent = !!attachment.sha1 || !!attachment.path;
18620
+ reactExports.useEffect(() => {
18621
+ if (expanded && attachmentText === null && placeholder === null) {
18622
+ setPlaceholder("Loading ...");
18623
+ fetch(attachmentURL(attachment)).then((response) => response.text()).then((text) => {
18624
+ setAttachmentText(text);
18625
+ setPlaceholder(null);
18626
+ }).catch((e) => {
18627
+ setPlaceholder("Failed to load: " + e.message);
18628
+ });
18629
+ }
18630
+ }, [expanded, attachmentText, placeholder, attachment]);
18631
+ const title = /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { style: { marginLeft: 5 }, children: [
18632
+ linkifyText(attachment.name),
18633
+ " ",
18634
+ hasContent && /* @__PURE__ */ jsxRuntimeExports.jsx("a", { style: { marginLeft: 5 }, href: downloadURL(attachment), children: "download" })
18635
+ ] });
18636
+ if (!isTextAttachment || !hasContent)
18637
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { marginLeft: 20 }, children: title });
18638
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
18639
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Expandable, { title, expanded, setExpanded, expandOnTitleClick: true, children: placeholder && /* @__PURE__ */ jsxRuntimeExports.jsx("i", { children: placeholder }) }),
18640
+ expanded && attachmentText !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(
18641
+ CodeMirrorWrapper,
18642
+ {
18643
+ text: attachmentText,
18644
+ readOnly: true,
18645
+ mimeType: attachment.contentType,
18646
+ linkify: true,
18647
+ lineNumbers: true,
18648
+ wrapLines: false
18649
+ }
18650
+ )
18651
+ ] });
18652
+ };
18119
18653
  const AttachmentsTab = ({ model }) => {
18120
18654
  const { diffMap, screenshots, attachments } = reactExports.useMemo(() => {
18121
18655
  const attachments2 = /* @__PURE__ */ new Set();
@@ -18136,8 +18670,8 @@ const AttachmentsTab = ({ model }) => {
18136
18670
  const entry = diffMap2.get(name) || { expected: void 0, actual: void 0, diff: void 0 };
18137
18671
  entry[type] = attachment;
18138
18672
  diffMap2.set(name, entry);
18139
- }
18140
- if (attachment.contentType.startsWith("image/")) {
18673
+ attachments2.delete(attachment);
18674
+ } else if (attachment.contentType.startsWith("image/")) {
18141
18675
  screenshots2.add(attachment);
18142
18676
  attachments2.delete(attachment);
18143
18677
  }
@@ -18150,11 +18684,11 @@ const AttachmentsTab = ({ model }) => {
18150
18684
  [...diffMap.values()].map(({ expected, actual, diff }) => {
18151
18685
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
18152
18686
  expected && actual && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "attachments-section", children: "Image diff" }),
18153
- expected && actual && /* @__PURE__ */ jsxRuntimeExports.jsx(ImageDiffView, { diff: {
18687
+ expected && actual && /* @__PURE__ */ jsxRuntimeExports.jsx(ImageDiffView, { noTargetBlank: true, diff: {
18154
18688
  name: "Image diff",
18155
- expected: { attachment: { ...expected, path: attachmentURL(expected) }, title: "Expected" },
18156
- actual: { attachment: { ...actual, path: attachmentURL(actual) } },
18157
- diff: diff ? { attachment: { ...diff, path: attachmentURL(diff) } } : void 0
18689
+ expected: { attachment: { ...expected, path: downloadURL(expected) }, title: "Expected" },
18690
+ actual: { attachment: { ...actual, path: downloadURL(actual) } },
18691
+ diff: diff ? { attachment: { ...diff, path: downloadURL(diff) } } : void 0
18158
18692
  } })
18159
18693
  ] });
18160
18694
  }),
@@ -18163,20 +18697,46 @@ const AttachmentsTab = ({ model }) => {
18163
18697
  const url = attachmentURL(a);
18164
18698
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "attachment-item", children: [
18165
18699
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: /* @__PURE__ */ jsxRuntimeExports.jsx("img", { draggable: "false", src: url }) }),
18166
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: /* @__PURE__ */ jsxRuntimeExports.jsx("a", { target: "_blank", href: url, children: a.name }) })
18700
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: /* @__PURE__ */ jsxRuntimeExports.jsx("a", { target: "_blank", href: url, rel: "noreferrer", children: a.name }) })
18167
18701
  ] }, `screenshot-${i}`);
18168
18702
  }),
18169
18703
  attachments.size ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "attachments-section", children: "Attachments" }) : void 0,
18170
18704
  [...attachments.values()].map((a, i) => {
18171
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "attachment-item", children: /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: attachmentURL(a) + "&download", children: a.name }) }, `attachment-${i}`);
18705
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "attachment-item", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ExpandableAttachment, { attachment: a }) }, attachmentKey(a, i));
18172
18706
  })
18173
18707
  ] });
18174
18708
  };
18175
- function attachmentURL(attachment) {
18176
- if (attachment.sha1)
18177
- return "sha1/" + attachment.sha1 + "?trace=" + encodeURIComponent(attachment.traceUrl);
18178
- return "file?path=" + encodeURIComponent(attachment.path);
18179
- }
18709
+ function attachmentURL(attachment, queryParams = {}) {
18710
+ const params = new URLSearchParams(queryParams);
18711
+ if (attachment.sha1) {
18712
+ params.set("trace", attachment.traceUrl);
18713
+ return "sha1/" + attachment.sha1 + "?" + params.toString();
18714
+ }
18715
+ params.set("path", attachment.path);
18716
+ return "file?" + params.toString();
18717
+ }
18718
+ function downloadURL(attachment) {
18719
+ const params = { dn: attachment.name };
18720
+ if (attachment.contentType)
18721
+ params.dct = attachment.contentType;
18722
+ return attachmentURL(attachment, params);
18723
+ }
18724
+ function attachmentKey(attachment, index) {
18725
+ return index + "-" + (attachment.sha1 ? `sha1-` + attachment.sha1 : `path-` + attachment.path);
18726
+ }
18727
+ const AnnotationsTab = ({ annotations }) => {
18728
+ if (!annotations.length)
18729
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(PlaceholderPanel, { text: "No annotations" });
18730
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "annotations-tab", children: annotations.map((annotation, i) => {
18731
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "annotation-item", children: [
18732
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { fontWeight: "bold" }, children: annotation.type }),
18733
+ annotation.description && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
18734
+ ": ",
18735
+ linkifyText(annotation.description)
18736
+ ] })
18737
+ ] }, `annotation-${i}`);
18738
+ }) });
18739
+ };
18180
18740
  const InspectorTab = ({ sdkLanguage, setIsInspecting, highlightedLocator, setHighlightedLocator }) => {
18181
18741
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "vbox", style: { backgroundColor: "var(--vscode-sideBar-background)" }, children: [
18182
18742
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { margin: "10px 0px 10px 10px", color: "var(--vscode-editorCodeLens-foreground)", flex: "none" }, children: "Locator" }),
@@ -18215,18 +18775,32 @@ function testStatusText(status) {
18215
18775
  return "Skipped";
18216
18776
  return "Did not run";
18217
18777
  }
18218
- const Workbench = ({ model, hideStackFrames, showSourcesFirst, rootDir, fallbackLocation, initialSelection, onSelectionChanged, isLive, status }) => {
18778
+ const SettingsView = ({ settings: settings2 }) => {
18779
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "vbox settings-view", children: settings2.map(({ value, set, title }) => {
18780
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "setting", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { children: [
18781
+ /* @__PURE__ */ jsxRuntimeExports.jsx("input", { type: "checkbox", checked: value, onClick: () => set(!value) }),
18782
+ title
18783
+ ] }) }, title);
18784
+ }) });
18785
+ };
18786
+ const Workbench = ({ model, showSourcesFirst, rootDir, fallbackLocation, initialSelection, onSelectionChanged, isLive, status, annotations, inert, openPage, onOpenExternally, revealSource, showSettings }) => {
18787
+ var _a;
18219
18788
  const [selectedAction, setSelectedActionImpl] = reactExports.useState(void 0);
18220
18789
  const [revealedStack, setRevealedStack] = reactExports.useState(void 0);
18221
18790
  const [highlightedAction, setHighlightedAction] = reactExports.useState();
18222
18791
  const [highlightedEntry, setHighlightedEntry] = reactExports.useState();
18792
+ const [highlightedConsoleMessage, setHighlightedConsoleMessage] = reactExports.useState();
18223
18793
  const [selectedNavigatorTab, setSelectedNavigatorTab] = reactExports.useState("actions");
18224
18794
  const [selectedPropertiesTab, setSelectedPropertiesTab] = useSetting("propertiesTab", showSourcesFirst ? "source" : "call");
18225
- const [isInspecting, setIsInspecting] = reactExports.useState(false);
18795
+ const [isInspecting, setIsInspectingState] = reactExports.useState(false);
18226
18796
  const [highlightedLocator, setHighlightedLocator] = reactExports.useState("");
18227
18797
  const activeAction = model ? highlightedAction || selectedAction : void 0;
18228
18798
  const [selectedTime, setSelectedTime] = reactExports.useState();
18229
18799
  const [sidebarLocation, setSidebarLocation] = useSetting("propertiesSidebarLocation", "bottom");
18800
+ const [showRouteActions, setShowRouteActions] = useSetting("show-route-actions", true);
18801
+ const filteredActions = reactExports.useMemo(() => {
18802
+ return ((model == null ? void 0 : model.actions) || []).filter((action) => showRouteActions || !isRouteAction(action));
18803
+ }, [model, showRouteActions]);
18230
18804
  const setSelectedAction = reactExports.useCallback((action) => {
18231
18805
  setSelectedActionImpl(action);
18232
18806
  setRevealedStack(action == null ? void 0 : action.stack);
@@ -18234,6 +18808,7 @@ const Workbench = ({ model, hideStackFrames, showSourcesFirst, rootDir, fallback
18234
18808
  const sources = reactExports.useMemo(() => (model == null ? void 0 : model.sources) || /* @__PURE__ */ new Map(), [model]);
18235
18809
  reactExports.useEffect(() => {
18236
18810
  setSelectedTime(void 0);
18811
+ setRevealedStack(void 0);
18237
18812
  }, [model]);
18238
18813
  reactExports.useEffect(() => {
18239
18814
  if (selectedAction && (model == null ? void 0 : model.actions.includes(selectedAction)))
@@ -18256,17 +18831,27 @@ const Workbench = ({ model, hideStackFrames, showSourcesFirst, rootDir, fallback
18256
18831
  }, [model, selectedAction, setSelectedAction, initialSelection]);
18257
18832
  const onActionSelected = reactExports.useCallback((action) => {
18258
18833
  setSelectedAction(action);
18834
+ setHighlightedAction(void 0);
18259
18835
  onSelectionChanged == null ? void 0 : onSelectionChanged(action);
18260
- }, [setSelectedAction, onSelectionChanged]);
18836
+ }, [setSelectedAction, onSelectionChanged, setHighlightedAction]);
18261
18837
  const selectPropertiesTab = reactExports.useCallback((tab) => {
18262
18838
  setSelectedPropertiesTab(tab);
18263
18839
  if (tab !== "inspector")
18264
- setIsInspecting(false);
18840
+ setIsInspectingState(false);
18265
18841
  }, [setSelectedPropertiesTab]);
18842
+ const setIsInspecting = reactExports.useCallback((value) => {
18843
+ if (!isInspecting && value)
18844
+ selectPropertiesTab("inspector");
18845
+ setIsInspectingState(value);
18846
+ }, [setIsInspectingState, selectPropertiesTab, isInspecting]);
18266
18847
  const locatorPicked = reactExports.useCallback((locator) => {
18267
18848
  setHighlightedLocator(locator);
18268
18849
  selectPropertiesTab("inspector");
18269
18850
  }, [selectPropertiesTab]);
18851
+ reactExports.useEffect(() => {
18852
+ if (revealSource)
18853
+ selectPropertiesTab("source");
18854
+ }, [revealSource, selectPropertiesTab]);
18270
18855
  const consoleModel = useConsoleTabModel(model, selectedTime);
18271
18856
  const networkModel = useNetworkTabModel(model, selectedTime);
18272
18857
  const errorsModel = useErrorsTabModel(model);
@@ -18309,17 +18894,22 @@ const Workbench = ({ model, hideStackFrames, showSourcesFirst, rootDir, fallback
18309
18894
  selectPropertiesTab("source");
18310
18895
  } })
18311
18896
  };
18897
+ let fallbackSourceErrorCount = void 0;
18898
+ if (!selectedAction && fallbackLocation)
18899
+ fallbackSourceErrorCount = (_a = fallbackLocation.source) == null ? void 0 : _a.errors.length;
18312
18900
  const sourceTab = {
18313
18901
  id: "source",
18314
18902
  title: "Source",
18903
+ errorCount: fallbackSourceErrorCount,
18315
18904
  render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(
18316
18905
  SourceTab,
18317
18906
  {
18318
18907
  stack: revealedStack,
18319
18908
  sources,
18320
- hideStackFrames,
18321
18909
  rootDir,
18322
- fallbackLocation
18910
+ stackFrameLocation: sidebarLocation === "bottom" ? "right" : "bottom",
18911
+ fallbackLocation,
18912
+ onOpenExternally
18323
18913
  }
18324
18914
  )
18325
18915
  };
@@ -18327,7 +18917,16 @@ const Workbench = ({ model, hideStackFrames, showSourcesFirst, rootDir, fallback
18327
18917
  id: "console",
18328
18918
  title: "Console",
18329
18919
  count: consoleModel.entries.length,
18330
- render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(ConsoleTab, { consoleModel, boundaries, selectedTime })
18920
+ render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(
18921
+ ConsoleTab,
18922
+ {
18923
+ consoleModel,
18924
+ boundaries,
18925
+ selectedTime,
18926
+ onAccepted: (m2) => setSelectedTime({ minimum: m2.timestamp, maximum: m2.timestamp }),
18927
+ onEntryHovered: setHighlightedConsoleMessage
18928
+ }
18929
+ )
18331
18930
  };
18332
18931
  const networkTab = {
18333
18932
  id: "network",
@@ -18351,6 +18950,15 @@ const Workbench = ({ model, hideStackFrames, showSourcesFirst, rootDir, fallback
18351
18950
  sourceTab,
18352
18951
  attachmentsTab
18353
18952
  ];
18953
+ if (annotations !== void 0) {
18954
+ const annotationsTab = {
18955
+ id: "annotations",
18956
+ title: "Annotations",
18957
+ count: annotations.length,
18958
+ render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(AnnotationsTab, { annotations })
18959
+ };
18960
+ tabs.push(annotationsTab);
18961
+ }
18354
18962
  if (showSourcesFirst) {
18355
18963
  const sourceTabIndex = tabs.indexOf(sourceTab);
18356
18964
  tabs.splice(sourceTabIndex, 1);
@@ -18370,141 +18978,116 @@ const Workbench = ({ model, hideStackFrames, showSourcesFirst, rootDir, fallback
18370
18978
  time = model.endTime - model.startTime;
18371
18979
  else if (model && model.wallTime)
18372
18980
  time = Date.now() - model.wallTime;
18373
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "vbox workbench", children: [
18981
+ const actionsTab = {
18982
+ id: "actions",
18983
+ title: "Actions",
18984
+ component: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "vbox", children: [
18985
+ status && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "workbench-run-status", children: [
18986
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: clsx("codicon", testStatusIcon(status)) }),
18987
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: testStatusText(status) }),
18988
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "spacer" }),
18989
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "workbench-run-duration", children: time ? msToString(time) : "" })
18990
+ ] }),
18991
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
18992
+ ActionList,
18993
+ {
18994
+ sdkLanguage,
18995
+ actions: filteredActions,
18996
+ selectedAction: model ? selectedAction : void 0,
18997
+ selectedTime,
18998
+ setSelectedTime,
18999
+ onSelected: onActionSelected,
19000
+ onHighlighted: setHighlightedAction,
19001
+ revealConsole: () => selectPropertiesTab("console"),
19002
+ isLive
19003
+ }
19004
+ )
19005
+ ] })
19006
+ };
19007
+ const metadataTab = {
19008
+ id: "metadata",
19009
+ title: "Metadata",
19010
+ component: /* @__PURE__ */ jsxRuntimeExports.jsx(MetadataView, { model })
19011
+ };
19012
+ const settingsTab = {
19013
+ id: "settings",
19014
+ title: "Settings",
19015
+ component: /* @__PURE__ */ jsxRuntimeExports.jsx(SettingsView, { settings: [{ value: showRouteActions, set: setShowRouteActions, title: "Show route actions" }] })
19016
+ };
19017
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "vbox workbench", ...inert ? { inert: "true" } : {}, children: [
18374
19018
  /* @__PURE__ */ jsxRuntimeExports.jsx(
18375
19019
  Timeline,
18376
19020
  {
18377
19021
  model,
19022
+ consoleEntries: consoleModel.entries,
18378
19023
  boundaries,
18379
19024
  highlightedAction,
18380
19025
  highlightedEntry,
19026
+ highlightedConsoleEntry: highlightedConsoleMessage,
18381
19027
  onSelected: onActionSelected,
18382
19028
  sdkLanguage,
18383
19029
  selectedTime,
18384
19030
  setSelectedTime
18385
19031
  }
18386
19032
  ),
18387
- /* @__PURE__ */ jsxRuntimeExports.jsxs(SplitView, { sidebarSize: 250, orientation: sidebarLocation === "bottom" ? "vertical" : "horizontal", settingName: "propertiesSidebar", children: [
18388
- /* @__PURE__ */ jsxRuntimeExports.jsxs(SplitView, { sidebarSize: 250, orientation: "horizontal", sidebarIsFirst: true, settingName: "actionListSidebar", children: [
18389
- /* @__PURE__ */ jsxRuntimeExports.jsx(
18390
- SnapshotTab,
19033
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
19034
+ SplitView,
19035
+ {
19036
+ sidebarSize: 250,
19037
+ orientation: sidebarLocation === "bottom" ? "vertical" : "horizontal",
19038
+ settingName: "propertiesSidebar",
19039
+ main: /* @__PURE__ */ jsxRuntimeExports.jsx(
19040
+ SplitView,
18391
19041
  {
18392
- action: activeAction,
18393
- sdkLanguage,
18394
- testIdAttributeName: (model == null ? void 0 : model.testIdAttributeName) || "data-testid",
18395
- isInspecting,
18396
- setIsInspecting,
18397
- highlightedLocator,
18398
- setHighlightedLocator: locatorPicked
19042
+ sidebarSize: 250,
19043
+ orientation: "horizontal",
19044
+ sidebarIsFirst: true,
19045
+ settingName: "actionListSidebar",
19046
+ main: /* @__PURE__ */ jsxRuntimeExports.jsx(
19047
+ SnapshotTab,
19048
+ {
19049
+ action: activeAction,
19050
+ sdkLanguage,
19051
+ testIdAttributeName: (model == null ? void 0 : model.testIdAttributeName) || "data-testid",
19052
+ isInspecting,
19053
+ setIsInspecting,
19054
+ highlightedLocator,
19055
+ setHighlightedLocator: locatorPicked,
19056
+ openPage
19057
+ }
19058
+ ),
19059
+ sidebar: /* @__PURE__ */ jsxRuntimeExports.jsx(
19060
+ TabbedPane,
19061
+ {
19062
+ tabs: showSettings ? [actionsTab, metadataTab, settingsTab] : [actionsTab, metadataTab],
19063
+ selectedTab: selectedNavigatorTab,
19064
+ setSelectedTab: setSelectedNavigatorTab
19065
+ }
19066
+ )
18399
19067
  }
18400
19068
  ),
18401
- /* @__PURE__ */ jsxRuntimeExports.jsx(
19069
+ sidebar: /* @__PURE__ */ jsxRuntimeExports.jsx(
18402
19070
  TabbedPane,
18403
19071
  {
18404
- tabs: [
18405
- {
18406
- id: "actions",
18407
- title: "Actions",
18408
- component: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "vbox", children: [
18409
- status && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "workbench-run-status", children: [
18410
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `codicon ${testStatusIcon(status)}` }),
18411
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: testStatusText(status) }),
18412
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "spacer" }),
18413
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "workbench-run-duration", children: time ? msToString(time) : "" })
18414
- ] }),
18415
- /* @__PURE__ */ jsxRuntimeExports.jsx(
18416
- ActionList,
18417
- {
18418
- sdkLanguage,
18419
- actions: (model == null ? void 0 : model.actions) || [],
18420
- selectedAction: model ? selectedAction : void 0,
18421
- selectedTime,
18422
- setSelectedTime,
18423
- onSelected: onActionSelected,
18424
- onHighlighted: setHighlightedAction,
18425
- revealConsole: () => selectPropertiesTab("console"),
18426
- isLive
18427
- }
18428
- )
18429
- ] })
18430
- },
18431
- {
18432
- id: "metadata",
18433
- title: "Metadata",
18434
- component: /* @__PURE__ */ jsxRuntimeExports.jsx(MetadataView, { model })
18435
- }
19072
+ tabs,
19073
+ selectedTab: selectedPropertiesTab,
19074
+ setSelectedTab: selectPropertiesTab,
19075
+ rightToolbar: [
19076
+ sidebarLocation === "bottom" ? /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { title: "Dock to right", icon: "layout-sidebar-right-off", onClick: () => {
19077
+ setSidebarLocation("right");
19078
+ } }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { title: "Dock to bottom", icon: "layout-panel-off", onClick: () => {
19079
+ setSidebarLocation("bottom");
19080
+ } })
18436
19081
  ],
18437
- selectedTab: selectedNavigatorTab,
18438
- setSelectedTab: setSelectedNavigatorTab
19082
+ mode: sidebarLocation === "bottom" ? "default" : "select"
18439
19083
  }
18440
19084
  )
18441
- ] }),
18442
- /* @__PURE__ */ jsxRuntimeExports.jsx(
18443
- TabbedPane,
18444
- {
18445
- tabs,
18446
- selectedTab: selectedPropertiesTab,
18447
- setSelectedTab: selectPropertiesTab,
18448
- leftToolbar: [
18449
- /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { title: "Pick locator", icon: "target", toggled: isInspecting, onClick: () => {
18450
- if (!isInspecting)
18451
- selectPropertiesTab("inspector");
18452
- setIsInspecting(!isInspecting);
18453
- } })
18454
- ],
18455
- rightToolbar: [
18456
- sidebarLocation === "bottom" ? /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { title: "Dock to right", icon: "layout-sidebar-right-off", onClick: () => {
18457
- setSidebarLocation("right");
18458
- } }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { title: "Dock to bottom", icon: "layout-panel-off", onClick: () => {
18459
- setSidebarLocation("bottom");
18460
- } })
18461
- ],
18462
- mode: sidebarLocation === "bottom" ? "default" : "select"
18463
- }
18464
- )
18465
- ] })
19085
+ }
19086
+ )
18466
19087
  ] });
18467
19088
  };
18468
- let lastId = 0;
18469
- let _ws;
18470
- const callbacks = /* @__PURE__ */ new Map();
18471
- async function connect(options) {
18472
- const guid = new URLSearchParams(window.location.search).get("ws");
18473
- const wsURL = new URL(`../${guid}`, window.location.toString());
18474
- wsURL.protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
18475
- const ws = new WebSocket(wsURL);
18476
- await new Promise((f2) => ws.addEventListener("open", f2));
18477
- ws.addEventListener("close", options.onClose);
18478
- ws.addEventListener("message", (event) => {
18479
- const message = JSON.parse(event.data);
18480
- const { id: id2, result, error, method, params } = message;
18481
- if (id2) {
18482
- const callback = callbacks.get(id2);
18483
- if (!callback)
18484
- return;
18485
- callbacks.delete(id2);
18486
- if (error)
18487
- callback.reject(new Error(error));
18488
- else
18489
- callback.resolve(result);
18490
- } else {
18491
- options.onEvent(method, params);
18492
- }
18493
- });
18494
- _ws = ws;
18495
- setInterval(() => sendMessage("ping").catch(() => {
18496
- }), 3e4);
18497
- return sendMessage;
18498
- }
18499
- const sendMessage = async (method, params) => {
18500
- const id2 = ++lastId;
18501
- const message = { id: id2, method, params };
18502
- _ws.send(JSON.stringify(message));
18503
- return new Promise((resolve, reject) => {
18504
- callbacks.set(id2, { resolve, reject });
18505
- });
18506
- };
18507
19089
  export {
19090
+ Expandable as E,
18508
19091
  MultiTraceModel as M,
18509
19092
  React as R,
18510
19093
  SplitView as S,
@@ -18512,29 +19095,25 @@ export {
18512
19095
  Workbench as W,
18513
19096
  __vitePreload as _,
18514
19097
  applyTheme as a,
18515
- reactDomExports as b,
18516
- connect as c,
18517
- currentTheme as d,
18518
- addThemeListener as e,
18519
- removeThemeListener as f,
18520
- useSetting as g,
18521
- Toolbar as h,
18522
- testStatusIcon as i,
19098
+ currentTheme as b,
19099
+ createRoot as c,
19100
+ addThemeListener as d,
19101
+ removeThemeListener as e,
19102
+ clsx as f,
19103
+ Toolbar as g,
19104
+ testStatusIcon as h,
19105
+ TreeView as i,
18523
19106
  jsxRuntimeExports as j,
18524
19107
  idForAction as k,
18525
- TreeView as l,
19108
+ useSetting as l,
18526
19109
  msToString as m,
18527
- getDefaultExportFromCjs as n,
18528
- commonjsGlobal as o,
19110
+ useDarkModeSetting as n,
19111
+ SettingsView as o,
19112
+ commonjsGlobal as p,
19113
+ getDefaultExportFromCjs as q,
18529
19114
  reactExports as r,
18530
19115
  settings as s,
18531
19116
  toggleTheme as t,
18532
19117
  useMeasure as u
18533
19118
  };
18534
- function __vite__mapDeps(indexes) {
18535
- if (!__vite__mapDeps.viteFileDeps) {
18536
- __vite__mapDeps.viteFileDeps = ["./codeMirrorModule-clyjx5sb.js","../codeMirrorModule.svF_VrcJ.css"]
18537
- }
18538
- return indexes.map((i) => __vite__mapDeps.viteFileDeps[i])
18539
- }
18540
- //# sourceMappingURL=wsPort-MnTGOuCA.js.map
19119
+ //# sourceMappingURL=workbench-Bjkiwcr1.js.map