@checkly/playwright-core 1.51.17-beta.1 → 1.54.2-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (376) hide show
  1. package/ThirdPartyNotices.txt +65 -123
  2. package/browsers.json +16 -14
  3. package/index.js +1 -1
  4. package/lib/androidServerImpl.js +47 -50
  5. package/lib/browserServerImpl.js +89 -69
  6. package/lib/checkly/escapeRegExp.js +23 -27
  7. package/lib/checkly/fetch.js +64 -46
  8. package/lib/checkly/secretsFilter.js +49 -36
  9. package/lib/cli/driver.js +71 -69
  10. package/lib/cli/program.js +400 -359
  11. package/lib/cli/programWithTestStub.js +51 -45
  12. package/lib/client/accessibility.js +31 -32
  13. package/lib/client/android.js +151 -242
  14. package/lib/client/api.js +135 -283
  15. package/lib/client/artifact.js +39 -36
  16. package/lib/client/browser.js +96 -71
  17. package/lib/client/browserContext.js +314 -345
  18. package/lib/client/browserType.js +103 -127
  19. package/lib/client/cdpSession.js +29 -31
  20. package/lib/client/channelOwner.js +90 -113
  21. package/lib/client/clientHelper.js +48 -39
  22. package/lib/client/clientInstrumentation.js +40 -37
  23. package/lib/client/clientStackTrace.js +41 -37
  24. package/lib/client/clock.js +36 -36
  25. package/lib/client/connection.js +188 -214
  26. package/lib/client/consoleMessage.js +31 -28
  27. package/lib/client/coverage.js +25 -22
  28. package/lib/client/dialog.js +30 -31
  29. package/lib/client/download.js +25 -25
  30. package/lib/client/electron.js +80 -77
  31. package/lib/client/elementHandle.js +120 -159
  32. package/lib/client/errors.js +53 -53
  33. package/lib/client/eventEmitter.js +124 -121
  34. package/lib/client/events.js +72 -68
  35. package/lib/client/fetch.js +166 -190
  36. package/lib/client/fileChooser.js +25 -24
  37. package/lib/client/fileUtils.js +31 -28
  38. package/lib/client/frame.js +207 -306
  39. package/lib/client/harRouter.js +42 -52
  40. package/lib/client/input.js +42 -69
  41. package/lib/client/jsHandle.js +54 -69
  42. package/lib/client/jsonPipe.js +27 -23
  43. package/lib/client/localUtils.js +29 -29
  44. package/lib/client/locator.js +145 -237
  45. package/lib/client/network.js +282 -307
  46. package/lib/client/page.js +269 -318
  47. package/lib/client/platform.js +46 -43
  48. package/lib/client/playwright.js +51 -76
  49. package/lib/client/selectors.js +45 -63
  50. package/lib/client/stream.js +29 -25
  51. package/lib/client/timeoutSettings.js +55 -41
  52. package/lib/client/tracing.js +49 -96
  53. package/lib/client/types.js +26 -22
  54. package/lib/client/video.js +35 -27
  55. package/lib/client/waiter.js +69 -88
  56. package/lib/client/webError.js +25 -23
  57. package/lib/client/webSocket.js +43 -56
  58. package/lib/client/worker.js +48 -56
  59. package/lib/client/writableStream.js +27 -23
  60. package/lib/generated/bindingsControllerSource.js +28 -0
  61. package/lib/generated/clockSource.js +26 -6
  62. package/lib/generated/consoleApiSource.js +26 -6
  63. package/lib/generated/injectedScriptSource.js +26 -6
  64. package/lib/generated/pollingRecorderSource.js +26 -6
  65. package/lib/generated/storageScriptSource.js +28 -0
  66. package/lib/generated/utilityScriptSource.js +26 -6
  67. package/lib/generated/webSocketMockSource.js +333 -5
  68. package/lib/inProcessFactory.js +51 -53
  69. package/lib/inprocess.js +2 -19
  70. package/lib/outofprocess.js +51 -46
  71. package/lib/protocol/serializers.js +153 -134
  72. package/lib/protocol/validator.js +2807 -2739
  73. package/lib/protocol/validatorPrimitives.js +114 -73
  74. package/lib/remote/playwrightConnection.js +88 -242
  75. package/lib/remote/playwrightServer.js +305 -92
  76. package/lib/server/accessibility.js +44 -37
  77. package/lib/server/android/android.js +251 -241
  78. package/lib/server/android/backendAdb.js +87 -82
  79. package/lib/server/artifact.js +78 -55
  80. package/lib/server/bidi/bidiBrowser.js +297 -158
  81. package/lib/server/bidi/bidiChromium.js +119 -89
  82. package/lib/server/bidi/bidiConnection.js +66 -83
  83. package/lib/server/bidi/bidiExecutionContext.js +129 -113
  84. package/lib/server/bidi/bidiFirefox.js +86 -76
  85. package/lib/server/bidi/bidiInput.js +106 -117
  86. package/lib/server/bidi/bidiNetworkManager.js +142 -159
  87. package/lib/server/bidi/bidiOverCdp.js +57 -58
  88. package/lib/server/bidi/bidiPage.js +260 -260
  89. package/lib/server/bidi/bidiPdf.js +52 -86
  90. package/lib/server/bidi/third_party/bidiCommands.d.js +22 -0
  91. package/lib/server/bidi/third_party/bidiDeserializer.js +55 -50
  92. package/lib/server/bidi/third_party/bidiKeyboard.js +236 -220
  93. package/lib/server/bidi/third_party/bidiProtocol.js +22 -137
  94. package/lib/server/bidi/third_party/bidiProtocolCore.js +152 -0
  95. package/lib/server/bidi/third_party/bidiProtocolPermissions.js +42 -0
  96. package/lib/server/bidi/third_party/bidiSerializer.js +67 -63
  97. package/lib/server/bidi/third_party/firefoxPrefs.js +141 -119
  98. package/lib/server/browser.js +93 -95
  99. package/lib/server/browserContext.js +419 -429
  100. package/lib/server/browserType.js +186 -216
  101. package/lib/server/callLog.js +47 -44
  102. package/lib/server/chromium/chromium.js +235 -203
  103. package/lib/server/chromium/chromiumSwitches.js +100 -67
  104. package/lib/server/chromium/crAccessibility.js +157 -131
  105. package/lib/server/chromium/crBrowser.js +310 -292
  106. package/lib/server/chromium/crConnection.js +95 -121
  107. package/lib/server/chromium/crCoverage.js +121 -131
  108. package/lib/server/chromium/crDevTools.js +60 -51
  109. package/lib/server/chromium/crDragDrop.js +68 -84
  110. package/lib/server/chromium/crExecutionContext.js +89 -83
  111. package/lib/server/chromium/crInput.js +118 -113
  112. package/lib/server/chromium/crNetworkManager.js +274 -375
  113. package/lib/server/chromium/crPage.js +536 -593
  114. package/lib/server/chromium/crPdf.js +54 -86
  115. package/lib/server/chromium/crProtocolHelper.js +92 -80
  116. package/lib/server/chromium/crServiceWorker.js +84 -73
  117. package/lib/server/chromium/defaultFontFamilies.js +152 -135
  118. package/lib/server/chromium/protocol.d.js +16 -0
  119. package/lib/server/chromium/videoRecorder.js +66 -99
  120. package/lib/server/clock.js +107 -83
  121. package/lib/server/codegen/csharp.js +192 -162
  122. package/lib/server/codegen/java.js +156 -129
  123. package/lib/server/codegen/javascript.js +163 -148
  124. package/lib/server/codegen/jsonl.js +32 -28
  125. package/lib/server/codegen/language.js +75 -52
  126. package/lib/server/codegen/languages.js +65 -27
  127. package/lib/server/codegen/python.js +141 -126
  128. package/lib/server/codegen/types.js +15 -4
  129. package/lib/server/console.js +28 -32
  130. package/lib/server/cookieStore.js +108 -86
  131. package/lib/server/debugController.js +147 -151
  132. package/lib/server/debugger.js +86 -78
  133. package/lib/server/deviceDescriptors.js +37 -24
  134. package/lib/server/deviceDescriptorsSource.json +238 -128
  135. package/lib/server/dialog.js +84 -39
  136. package/lib/server/dispatchers/androidDispatcher.js +257 -148
  137. package/lib/server/dispatchers/artifactDispatcher.js +79 -79
  138. package/lib/server/dispatchers/browserContextDispatcher.js +289 -259
  139. package/lib/server/dispatchers/browserDispatcher.js +96 -148
  140. package/lib/server/dispatchers/browserTypeDispatcher.js +50 -41
  141. package/lib/server/dispatchers/cdpSessionDispatcher.js +35 -39
  142. package/lib/server/dispatchers/debugControllerDispatcher.js +65 -83
  143. package/lib/server/dispatchers/dialogDispatcher.js +34 -31
  144. package/lib/server/dispatchers/dispatcher.js +208 -248
  145. package/lib/server/dispatchers/electronDispatcher.js +66 -70
  146. package/lib/server/dispatchers/elementHandlerDispatcher.js +164 -216
  147. package/lib/server/dispatchers/frameDispatcher.js +211 -272
  148. package/lib/server/dispatchers/jsHandleDispatcher.js +63 -75
  149. package/lib/server/dispatchers/jsonPipeDispatcher.js +37 -38
  150. package/lib/server/dispatchers/localUtilsDispatcher.js +121 -119
  151. package/lib/server/dispatchers/networkDispatchers.js +117 -128
  152. package/lib/server/dispatchers/pageDispatcher.js +256 -248
  153. package/lib/server/dispatchers/playwrightDispatcher.js +92 -87
  154. package/lib/server/dispatchers/streamDispatcher.js +52 -48
  155. package/lib/server/dispatchers/tracingDispatcher.js +47 -52
  156. package/lib/server/dispatchers/webSocketRouteDispatcher.js +126 -150
  157. package/lib/server/dispatchers/writableStreamDispatcher.js +65 -43
  158. package/lib/server/dom.js +485 -582
  159. package/lib/server/download.js +47 -37
  160. package/lib/server/electron/electron.js +216 -243
  161. package/lib/server/electron/loader.js +9 -37
  162. package/lib/server/errors.js +47 -46
  163. package/lib/server/fetch.js +317 -360
  164. package/lib/server/fileChooser.js +25 -24
  165. package/lib/server/fileUploadUtils.js +66 -60
  166. package/lib/server/firefox/ffAccessibility.js +153 -131
  167. package/lib/server/firefox/ffBrowser.js +268 -305
  168. package/lib/server/firefox/ffConnection.js +63 -84
  169. package/lib/server/firefox/ffExecutionContext.js +92 -73
  170. package/lib/server/firefox/ffInput.js +82 -84
  171. package/lib/server/firefox/ffNetworkManager.js +137 -114
  172. package/lib/server/firefox/ffPage.js +261 -293
  173. package/lib/server/firefox/firefox.js +80 -72
  174. package/lib/server/firefox/protocol.d.js +16 -0
  175. package/lib/server/formData.js +107 -35
  176. package/lib/server/frameSelectors.js +98 -114
  177. package/lib/server/frames.js +845 -1055
  178. package/lib/server/har/harRecorder.js +85 -77
  179. package/lib/server/har/harTracer.js +290 -223
  180. package/lib/server/harBackend.js +80 -80
  181. package/lib/server/helper.js +55 -59
  182. package/lib/server/index.js +59 -99
  183. package/lib/server/input.js +151 -189
  184. package/lib/server/instrumentation.js +57 -44
  185. package/lib/server/javascript.js +133 -134
  186. package/lib/server/launchApp.js +113 -75
  187. package/lib/server/localUtils.js +150 -142
  188. package/lib/server/macEditingCommands.js +141 -137
  189. package/lib/server/network.js +299 -303
  190. package/lib/server/page.js +513 -544
  191. package/lib/server/pipeTransport.js +49 -45
  192. package/lib/server/playwright.js +58 -67
  193. package/lib/server/progress.js +137 -68
  194. package/lib/server/protocolError.js +34 -31
  195. package/lib/server/recorder/chat.js +70 -86
  196. package/lib/server/recorder/recorderApp.js +341 -176
  197. package/lib/server/recorder/recorderInTraceViewer.js +65 -94
  198. package/lib/server/recorder/recorderRunner.js +93 -116
  199. package/lib/server/recorder/recorderSignalProcessor.js +83 -0
  200. package/lib/server/recorder/recorderUtils.js +104 -47
  201. package/lib/server/recorder/throttledFile.js +42 -30
  202. package/lib/server/recorder.js +395 -275
  203. package/lib/server/registry/browserFetcher.js +106 -101
  204. package/lib/server/registry/dependencies.js +245 -196
  205. package/lib/server/registry/index.js +930 -803
  206. package/lib/server/registry/nativeDeps.js +1073 -464
  207. package/lib/server/registry/oopDownloadBrowserMain.js +57 -75
  208. package/lib/server/screenshotter.js +160 -191
  209. package/lib/server/selectors.js +90 -51
  210. package/lib/server/socksClientCertificatesInterceptor.js +171 -186
  211. package/lib/server/socksInterceptor.js +62 -70
  212. package/lib/server/trace/recorder/snapshotter.js +76 -102
  213. package/lib/server/trace/recorder/snapshotterInjected.js +238 -217
  214. package/lib/server/trace/recorder/tracing.js +354 -362
  215. package/lib/server/trace/test/inMemorySnapshotter.js +46 -52
  216. package/lib/server/trace/viewer/traceViewer.js +160 -147
  217. package/lib/server/transport.js +119 -134
  218. package/lib/server/types.js +26 -22
  219. package/lib/server/usKeyboardLayout.js +135 -545
  220. package/lib/server/utils/ascii.js +39 -26
  221. package/lib/server/utils/comparators.js +105 -103
  222. package/lib/server/utils/crypto.js +157 -112
  223. package/lib/server/utils/debug.js +36 -32
  224. package/lib/server/utils/debugLogger.js +77 -48
  225. package/lib/server/utils/env.js +52 -37
  226. package/lib/server/utils/eventsHelper.js +29 -28
  227. package/lib/server/utils/expectUtils.js +31 -26
  228. package/lib/server/utils/fileUtils.js +123 -136
  229. package/lib/server/utils/happyEyeballs.js +141 -126
  230. package/lib/server/utils/hostPlatform.js +84 -120
  231. package/lib/server/utils/httpServer.js +106 -121
  232. package/lib/server/utils/image_tools/colorUtils.js +42 -51
  233. package/lib/server/utils/image_tools/compare.js +44 -43
  234. package/lib/server/utils/image_tools/imageChannel.js +38 -30
  235. package/lib/server/utils/image_tools/stats.js +40 -40
  236. package/lib/server/utils/linuxUtils.js +50 -37
  237. package/lib/server/utils/network.js +152 -96
  238. package/lib/server/utils/nodePlatform.js +87 -79
  239. package/lib/server/utils/pipeTransport.js +44 -42
  240. package/lib/server/utils/processLauncher.js +111 -121
  241. package/lib/server/utils/profiler.js +52 -39
  242. package/lib/server/utils/socksProxy.js +280 -339
  243. package/lib/server/utils/spawnAsync.js +37 -41
  244. package/lib/server/utils/task.js +31 -38
  245. package/lib/server/utils/userAgent.js +73 -66
  246. package/lib/server/utils/wsServer.js +68 -75
  247. package/lib/server/utils/zipFile.js +36 -37
  248. package/lib/server/utils/zones.js +37 -34
  249. package/lib/server/webkit/protocol.d.js +16 -0
  250. package/lib/server/webkit/webkit.js +77 -61
  251. package/lib/server/webkit/wkAccessibility.js +161 -118
  252. package/lib/server/webkit/wkBrowser.js +193 -184
  253. package/lib/server/webkit/wkConnection.js +59 -83
  254. package/lib/server/webkit/wkExecutionContext.js +85 -70
  255. package/lib/server/webkit/wkInput.js +97 -95
  256. package/lib/server/webkit/wkInterceptableRequest.js +102 -95
  257. package/lib/server/webkit/wkPage.js +568 -667
  258. package/lib/server/webkit/wkProvisionalPage.js +45 -56
  259. package/lib/server/webkit/wkWorkers.js +79 -79
  260. package/lib/utils/expectUtils.js +31 -26
  261. package/lib/utils/isomorphic/ariaSnapshot.js +149 -152
  262. package/lib/utils/isomorphic/assert.js +28 -22
  263. package/lib/utils/isomorphic/colors.js +66 -59
  264. package/lib/utils/isomorphic/cssParser.js +120 -125
  265. package/lib/utils/isomorphic/cssTokenizer.js +436 -364
  266. package/lib/utils/isomorphic/headers.js +38 -37
  267. package/lib/utils/isomorphic/locatorGenerators.js +358 -357
  268. package/lib/utils/isomorphic/locatorParser.js +96 -105
  269. package/lib/utils/isomorphic/locatorUtils.js +63 -44
  270. package/lib/utils/isomorphic/manualPromise.js +46 -39
  271. package/lib/utils/isomorphic/mimeType.js +447 -25
  272. package/lib/utils/isomorphic/multimap.js +34 -27
  273. package/lib/utils/isomorphic/protocolFormatter.js +68 -0
  274. package/lib/utils/isomorphic/protocolMetainfo.js +321 -0
  275. package/lib/utils/isomorphic/recorderUtils.js +140 -181
  276. package/lib/utils/isomorphic/rtti.js +35 -33
  277. package/lib/utils/isomorphic/selectorParser.js +182 -193
  278. package/lib/utils/isomorphic/semaphore.js +27 -24
  279. package/lib/utils/isomorphic/stackTrace.js +87 -98
  280. package/lib/utils/isomorphic/stringUtils.js +98 -112
  281. package/lib/utils/isomorphic/time.js +46 -22
  282. package/lib/utils/isomorphic/timeoutRunner.js +53 -53
  283. package/lib/utils/isomorphic/traceUtils.js +37 -41
  284. package/lib/utils/isomorphic/types.js +15 -4
  285. package/lib/utils/isomorphic/urlMatch.js +113 -67
  286. package/lib/utils/isomorphic/utilityScriptSerializers.js +251 -0
  287. package/lib/utils.js +101 -443
  288. package/lib/utilsBundle.js +101 -52
  289. package/lib/utilsBundleImpl/index.js +160 -150
  290. package/lib/zipBundle.js +32 -23
  291. package/lib/zipBundleImpl.js +4 -4
  292. package/package.json +1 -1
  293. package/types/protocol.d.ts +1267 -1057
  294. package/types/types.d.ts +131 -29
  295. package/lib/common/socksProxy.js +0 -569
  296. package/lib/common/timeoutSettings.js +0 -73
  297. package/lib/common/types.js +0 -5
  298. package/lib/image_tools/colorUtils.js +0 -98
  299. package/lib/image_tools/compare.js +0 -108
  300. package/lib/image_tools/imageChannel.js +0 -70
  301. package/lib/image_tools/stats.js +0 -102
  302. package/lib/protocol/debug.js +0 -27
  303. package/lib/protocol/transport.js +0 -82
  304. package/lib/server/dispatchers/selectorsDispatcher.js +0 -36
  305. package/lib/server/isomorphic/utilityScriptSerializers.js +0 -229
  306. package/lib/server/recorder/contextRecorder.js +0 -290
  307. package/lib/server/recorder/recorderCollection.js +0 -104
  308. package/lib/server/recorder/recorderFrontend.js +0 -5
  309. package/lib/server/storageScript.js +0 -160
  310. package/lib/server/timeoutSettings.js +0 -74
  311. package/lib/third_party/diff_match_patch.js +0 -2222
  312. package/lib/utils/ascii.js +0 -31
  313. package/lib/utils/comparators.js +0 -171
  314. package/lib/utils/crypto.js +0 -174
  315. package/lib/utils/debug.js +0 -46
  316. package/lib/utils/debugLogger.js +0 -91
  317. package/lib/utils/env.js +0 -49
  318. package/lib/utils/eventsHelper.js +0 -38
  319. package/lib/utils/fileUtils.js +0 -205
  320. package/lib/utils/happy-eyeballs.js +0 -210
  321. package/lib/utils/headers.js +0 -52
  322. package/lib/utils/hostPlatform.js +0 -133
  323. package/lib/utils/httpServer.js +0 -237
  324. package/lib/utils/index.js +0 -368
  325. package/lib/utils/linuxUtils.js +0 -78
  326. package/lib/utils/manualPromise.js +0 -109
  327. package/lib/utils/multimap.js +0 -75
  328. package/lib/utils/network.js +0 -160
  329. package/lib/utils/processLauncher.js +0 -248
  330. package/lib/utils/profiler.js +0 -53
  331. package/lib/utils/rtti.js +0 -44
  332. package/lib/utils/semaphore.js +0 -51
  333. package/lib/utils/spawnAsync.js +0 -45
  334. package/lib/utils/stackTrace.js +0 -121
  335. package/lib/utils/task.js +0 -58
  336. package/lib/utils/time.js +0 -37
  337. package/lib/utils/timeoutRunner.js +0 -66
  338. package/lib/utils/traceUtils.js +0 -44
  339. package/lib/utils/userAgent.js +0 -105
  340. package/lib/utils/wsServer.js +0 -127
  341. package/lib/utils/zipFile.js +0 -75
  342. package/lib/utils/zones.js +0 -62
  343. package/lib/vite/htmlReport/index.html +0 -69
  344. package/lib/vite/recorder/assets/codeMirrorModule-DrMbgOIo.js +0 -16684
  345. package/lib/vite/recorder/assets/codeMirrorModule-DuST8d_k.css +0 -344
  346. package/lib/vite/recorder/assets/codicon-DCmgc-ay.ttf +0 -0
  347. package/lib/vite/recorder/assets/index-5NM3V7eb.css +0 -2524
  348. package/lib/vite/recorder/assets/index-CT-scFHn.js +0 -16848
  349. package/lib/vite/recorder/index.html +0 -29
  350. package/lib/vite/recorder/playwright-logo.svg +0 -9
  351. package/lib/vite/traceViewer/assets/codeMirrorModule-CB-2okZ8.js +0 -16684
  352. package/lib/vite/traceViewer/assets/defaultSettingsView-CBiB4avC.js +0 -217
  353. package/lib/vite/traceViewer/assets/inspectorTab-CwgfffWb.js +0 -25143
  354. package/lib/vite/traceViewer/assets/workbench-CWZselvp.js +0 -2470
  355. package/lib/vite/traceViewer/assets/xtermModule-Es_gt_u7.js +0 -5994
  356. package/lib/vite/traceViewer/codeMirrorModule.DuST8d_k.css +0 -344
  357. package/lib/vite/traceViewer/codicon.DCmgc-ay.ttf +0 -0
  358. package/lib/vite/traceViewer/defaultSettingsView.Dp3b_92q.css +0 -41
  359. package/lib/vite/traceViewer/embedded.BeldSa2G.css +0 -68
  360. package/lib/vite/traceViewer/embedded.gzudoghF.js +0 -106
  361. package/lib/vite/traceViewer/embedded.html +0 -18
  362. package/lib/vite/traceViewer/index.DilotR1h.js +0 -314
  363. package/lib/vite/traceViewer/index.QewjJ85u.css +0 -131
  364. package/lib/vite/traceViewer/index.html +0 -47
  365. package/lib/vite/traceViewer/inspectorTab.DnGm18kV.css +0 -3178
  366. package/lib/vite/traceViewer/playwright-logo.svg +0 -9
  367. package/lib/vite/traceViewer/recorder.DLgqV9db.css +0 -15
  368. package/lib/vite/traceViewer/recorder.DVrkq3Um.js +0 -551
  369. package/lib/vite/traceViewer/recorder.html +0 -17
  370. package/lib/vite/traceViewer/snapshot.html +0 -21
  371. package/lib/vite/traceViewer/sw.bundle.js +0 -3
  372. package/lib/vite/traceViewer/uiMode.C9_OcpPU.js +0 -1756
  373. package/lib/vite/traceViewer/uiMode.c5ORgcrX.css +0 -1424
  374. package/lib/vite/traceViewer/uiMode.html +0 -21
  375. package/lib/vite/traceViewer/workbench.xUZSA8PY.css +0 -787
  376. package/lib/vite/traceViewer/xtermModule.EsaqrrTX.css +0 -209
@@ -1,2470 +0,0 @@
1
- var __defProp = Object.defineProperty;
2
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
- import { r as reactExports, j as jsxRuntimeExports, f as clsx, k as scrollIntoViewIfNeeded, l as buildActionTree, n as stats, m as msToString, T as ToolbarButton, o as asLocator, P as PlaceholderPanel, C as CopyToClipboard, L as ListView, p as ansi2html, q as useCookies, u as useMeasure, v as ResizeView, w as kWebLinkRe, x as useFlash, y as lineHeight, z as CodeMirrorWrapper, A as useAsyncMemo, B as CopyToClipboardTextButton, D as upperBound, G as GlassPane, h as useSetting, E as useConsoleTabModel, F as useNetworkTabModel, S as SplitView, H as TabbedPane, I as SnapshotTabsView, J as InspectorTab, K as ConsoleTab, N as NetworkTab, O as SourceTab } from "./inspectorTab-CwgfffWb.js";
5
- const scrollPositions = /* @__PURE__ */ new Map();
6
- function TreeView({
7
- name,
8
- rootItem,
9
- render,
10
- title,
11
- icon,
12
- isError,
13
- isVisible,
14
- selectedItem,
15
- onAccepted,
16
- onSelected,
17
- onHighlighted,
18
- treeState,
19
- setTreeState,
20
- noItemsMessage,
21
- dataTestId,
22
- autoExpandDepth
23
- }) {
24
- const treeItems = reactExports.useMemo(() => {
25
- return indexTree(rootItem, selectedItem, treeState.expandedItems, autoExpandDepth || 0, isVisible);
26
- }, [rootItem, selectedItem, treeState, autoExpandDepth, isVisible]);
27
- const itemListRef = reactExports.useRef(null);
28
- const [highlightedItem, setHighlightedItem] = reactExports.useState();
29
- const [isKeyboardNavigation, setIsKeyboardNavigation] = reactExports.useState(false);
30
- reactExports.useEffect(() => {
31
- onHighlighted == null ? void 0 : onHighlighted(highlightedItem);
32
- }, [onHighlighted, highlightedItem]);
33
- reactExports.useEffect(() => {
34
- const treeElem = itemListRef.current;
35
- if (!treeElem)
36
- return;
37
- const saveScrollPosition = () => {
38
- scrollPositions.set(name, treeElem.scrollTop);
39
- };
40
- treeElem.addEventListener("scroll", saveScrollPosition, { passive: true });
41
- return () => treeElem.removeEventListener("scroll", saveScrollPosition);
42
- }, [name]);
43
- reactExports.useEffect(() => {
44
- if (itemListRef.current)
45
- itemListRef.current.scrollTop = scrollPositions.get(name) || 0;
46
- }, [name]);
47
- const toggleExpanded = reactExports.useCallback((item) => {
48
- const { expanded } = treeItems.get(item);
49
- if (expanded) {
50
- for (let i2 = selectedItem; i2; i2 = i2.parent) {
51
- if (i2 === item) {
52
- onSelected == null ? void 0 : onSelected(item);
53
- break;
54
- }
55
- }
56
- treeState.expandedItems.set(item.id, false);
57
- } else {
58
- treeState.expandedItems.set(item.id, true);
59
- }
60
- setTreeState({ ...treeState });
61
- }, [treeItems, selectedItem, onSelected, treeState, setTreeState]);
62
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: clsx(`tree-view vbox`, name + "-tree-view"), role: "tree", "data-testid": dataTestId || name + "-tree", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
63
- "div",
64
- {
65
- className: clsx("tree-view-content"),
66
- tabIndex: 0,
67
- onKeyDown: (event) => {
68
- if (selectedItem && event.key === "Enter") {
69
- onAccepted == null ? void 0 : onAccepted(selectedItem);
70
- return;
71
- }
72
- if (event.key !== "ArrowDown" && event.key !== "ArrowUp" && event.key !== "ArrowLeft" && event.key !== "ArrowRight")
73
- return;
74
- event.stopPropagation();
75
- event.preventDefault();
76
- if (selectedItem && event.key === "ArrowLeft") {
77
- const { expanded, parent } = treeItems.get(selectedItem);
78
- if (expanded) {
79
- treeState.expandedItems.set(selectedItem.id, false);
80
- setTreeState({ ...treeState });
81
- } else if (parent) {
82
- onSelected == null ? void 0 : onSelected(parent);
83
- }
84
- return;
85
- }
86
- if (selectedItem && event.key === "ArrowRight") {
87
- if (selectedItem.children.length) {
88
- treeState.expandedItems.set(selectedItem.id, true);
89
- setTreeState({ ...treeState });
90
- }
91
- return;
92
- }
93
- let newSelectedItem = selectedItem;
94
- if (event.key === "ArrowDown") {
95
- if (selectedItem) {
96
- const itemData = treeItems.get(selectedItem);
97
- newSelectedItem = itemData.next;
98
- } else if (treeItems.size) {
99
- const itemList = [...treeItems.keys()];
100
- newSelectedItem = itemList[0];
101
- }
102
- }
103
- if (event.key === "ArrowUp") {
104
- if (selectedItem) {
105
- const itemData = treeItems.get(selectedItem);
106
- newSelectedItem = itemData.prev;
107
- } else if (treeItems.size) {
108
- const itemList = [...treeItems.keys()];
109
- newSelectedItem = itemList[itemList.length - 1];
110
- }
111
- }
112
- onHighlighted == null ? void 0 : onHighlighted(void 0);
113
- if (newSelectedItem) {
114
- setIsKeyboardNavigation(true);
115
- onSelected == null ? void 0 : onSelected(newSelectedItem);
116
- }
117
- setHighlightedItem(void 0);
118
- },
119
- ref: itemListRef,
120
- children: [
121
- noItemsMessage && treeItems.size === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "tree-view-empty", children: noItemsMessage }),
122
- rootItem.children.map((child) => {
123
- const itemData = treeItems.get(child);
124
- return itemData && /* @__PURE__ */ jsxRuntimeExports.jsx(
125
- TreeItemHeader,
126
- {
127
- item: child,
128
- treeItems,
129
- selectedItem,
130
- onSelected,
131
- onAccepted,
132
- isError,
133
- toggleExpanded,
134
- highlightedItem,
135
- setHighlightedItem,
136
- render,
137
- icon,
138
- title,
139
- isKeyboardNavigation,
140
- setIsKeyboardNavigation
141
- },
142
- child.id
143
- );
144
- })
145
- ]
146
- }
147
- ) });
148
- }
149
- function TreeItemHeader({
150
- item,
151
- treeItems,
152
- selectedItem,
153
- onSelected,
154
- highlightedItem,
155
- setHighlightedItem,
156
- isError,
157
- onAccepted,
158
- toggleExpanded,
159
- render,
160
- title,
161
- icon,
162
- isKeyboardNavigation,
163
- setIsKeyboardNavigation
164
- }) {
165
- const groupId = reactExports.useId();
166
- const itemRef = reactExports.useRef(null);
167
- reactExports.useEffect(() => {
168
- if (selectedItem === item && isKeyboardNavigation && itemRef.current) {
169
- scrollIntoViewIfNeeded(itemRef.current);
170
- setIsKeyboardNavigation(false);
171
- }
172
- }, [item, selectedItem, isKeyboardNavigation, setIsKeyboardNavigation]);
173
- const itemData = treeItems.get(item);
174
- const indentation = itemData.depth;
175
- const expanded = itemData.expanded;
176
- let expandIcon = "codicon-blank";
177
- if (typeof expanded === "boolean")
178
- expandIcon = expanded ? "codicon-chevron-down" : "codicon-chevron-right";
179
- const rendered = render(item);
180
- const children = expanded && item.children.length ? item.children : [];
181
- const titled = title == null ? void 0 : title(item);
182
- const iconed = (icon == null ? void 0 : icon(item)) || "codicon-blank";
183
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { ref: itemRef, role: "treeitem", "aria-selected": item === selectedItem, "aria-expanded": expanded, "aria-controls": groupId, title: titled, className: "vbox", style: { flex: "none" }, children: [
184
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
185
- "div",
186
- {
187
- onDoubleClick: () => onAccepted == null ? void 0 : onAccepted(item),
188
- className: clsx(
189
- "tree-view-entry",
190
- selectedItem === item && "selected",
191
- highlightedItem === item && "highlighted",
192
- (isError == null ? void 0 : isError(item)) && "error"
193
- ),
194
- onClick: () => onSelected == null ? void 0 : onSelected(item),
195
- onMouseEnter: () => setHighlightedItem(item),
196
- onMouseLeave: () => setHighlightedItem(void 0),
197
- children: [
198
- indentation ? new Array(indentation).fill(0).map((_2, i2) => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "tree-view-indent" }, "indent-" + i2)) : void 0,
199
- /* @__PURE__ */ jsxRuntimeExports.jsx(
200
- "div",
201
- {
202
- "aria-hidden": "true",
203
- className: "codicon " + expandIcon,
204
- style: { minWidth: 16, marginRight: 4 },
205
- onDoubleClick: (e) => {
206
- e.preventDefault();
207
- e.stopPropagation();
208
- },
209
- onClick: (e) => {
210
- e.stopPropagation();
211
- e.preventDefault();
212
- toggleExpanded(item);
213
- }
214
- }
215
- ),
216
- icon && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "codicon " + iconed, style: { minWidth: 16, marginRight: 4 }, "aria-label": "[" + iconed.replace("codicon", "icon") + "]" }),
217
- typeof rendered === "string" ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { textOverflow: "ellipsis", overflow: "hidden" }, children: rendered }) : rendered
218
- ]
219
- }
220
- ),
221
- !!children.length && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { id: groupId, role: "group", children: children.map((child) => {
222
- const itemData2 = treeItems.get(child);
223
- return itemData2 && /* @__PURE__ */ jsxRuntimeExports.jsx(
224
- TreeItemHeader,
225
- {
226
- item: child,
227
- treeItems,
228
- selectedItem,
229
- onSelected,
230
- onAccepted,
231
- isError,
232
- toggleExpanded,
233
- highlightedItem,
234
- setHighlightedItem,
235
- render,
236
- title,
237
- icon,
238
- isKeyboardNavigation,
239
- setIsKeyboardNavigation
240
- },
241
- child.id
242
- );
243
- }) })
244
- ] });
245
- }
246
- function indexTree(rootItem, selectedItem, expandedItems, autoExpandDepth, isVisible = () => true) {
247
- if (!isVisible(rootItem))
248
- return /* @__PURE__ */ new Map();
249
- const result = /* @__PURE__ */ new Map();
250
- const temporaryExpanded = /* @__PURE__ */ new Set();
251
- for (let item = selectedItem == null ? void 0 : selectedItem.parent; item; item = item.parent)
252
- temporaryExpanded.add(item.id);
253
- let lastItem = null;
254
- const appendChildren = (parent, depth) => {
255
- for (const item of parent.children) {
256
- if (!isVisible(item))
257
- continue;
258
- const expandState = temporaryExpanded.has(item.id) || expandedItems.get(item.id);
259
- const autoExpandMatches = autoExpandDepth > depth && result.size < 25 && expandState !== false;
260
- const expanded = item.children.length ? expandState ?? autoExpandMatches : void 0;
261
- const itemData = {
262
- depth,
263
- expanded,
264
- parent: rootItem === parent ? null : parent,
265
- next: null,
266
- prev: lastItem
267
- };
268
- if (lastItem)
269
- result.get(lastItem).next = item;
270
- lastItem = item;
271
- result.set(item, itemData);
272
- if (expanded)
273
- appendChildren(item, depth + 1);
274
- }
275
- };
276
- appendChildren(rootItem, 0);
277
- return result;
278
- }
279
- function testStatusIcon(status) {
280
- if (status === "scheduled")
281
- return "codicon-clock";
282
- if (status === "running")
283
- return "codicon-loading";
284
- if (status === "failed")
285
- return "codicon-error";
286
- if (status === "passed")
287
- return "codicon-check";
288
- if (status === "skipped")
289
- return "codicon-circle-slash";
290
- return "codicon-circle-outline";
291
- }
292
- function testStatusText(status) {
293
- if (status === "scheduled")
294
- return "Pending";
295
- if (status === "running")
296
- return "Running";
297
- if (status === "failed")
298
- return "Failed";
299
- if (status === "passed")
300
- return "Passed";
301
- if (status === "skipped")
302
- return "Skipped";
303
- return "Did not run";
304
- }
305
- const ActionTreeView = TreeView;
306
- const ActionList = ({
307
- actions,
308
- selectedAction,
309
- selectedTime,
310
- setSelectedTime,
311
- sdkLanguage,
312
- onSelected,
313
- onHighlighted,
314
- revealConsole,
315
- revealAttachment,
316
- isLive
317
- }) => {
318
- const [treeState, setTreeState] = reactExports.useState({ expandedItems: /* @__PURE__ */ new Map() });
319
- const { rootItem, itemMap } = reactExports.useMemo(() => buildActionTree(actions), [actions]);
320
- const { selectedItem } = reactExports.useMemo(() => {
321
- const selectedItem2 = selectedAction ? itemMap.get(selectedAction.callId) : void 0;
322
- return { selectedItem: selectedItem2 };
323
- }, [itemMap, selectedAction]);
324
- const isError = reactExports.useCallback((item) => {
325
- var _a, _b;
326
- return !!((_b = (_a = item.action) == null ? void 0 : _a.error) == null ? void 0 : _b.message);
327
- }, []);
328
- const onAccepted = reactExports.useCallback((item) => {
329
- return setSelectedTime({ minimum: item.action.startTime, maximum: item.action.endTime });
330
- }, [setSelectedTime]);
331
- const render = reactExports.useCallback((item) => {
332
- return renderAction(item.action, { sdkLanguage, revealConsole, revealAttachment, isLive, showDuration: true, showBadges: true });
333
- }, [isLive, revealConsole, revealAttachment, sdkLanguage]);
334
- const isVisible = reactExports.useCallback((item) => {
335
- return !selectedTime || !item.action || item.action.startTime <= selectedTime.maximum && item.action.endTime >= selectedTime.minimum;
336
- }, [selectedTime]);
337
- const onSelectedAction = reactExports.useCallback((item) => {
338
- onSelected == null ? void 0 : onSelected(item.action);
339
- }, [onSelected]);
340
- const onHighlightedAction = reactExports.useCallback((item) => {
341
- onHighlighted == null ? void 0 : onHighlighted(item == null ? void 0 : item.action);
342
- }, [onHighlighted]);
343
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "vbox", children: [
344
- selectedTime && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "action-list-show-all", onClick: () => setSelectedTime(void 0), children: [
345
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "codicon codicon-triangle-left" }),
346
- "Show all"
347
- ] }),
348
- /* @__PURE__ */ jsxRuntimeExports.jsx(
349
- ActionTreeView,
350
- {
351
- name: "actions",
352
- rootItem,
353
- treeState,
354
- setTreeState,
355
- selectedItem,
356
- onSelected: onSelectedAction,
357
- onHighlighted: onHighlightedAction,
358
- onAccepted,
359
- isError,
360
- isVisible,
361
- render
362
- }
363
- )
364
- ] });
365
- };
366
- const renderAction = (action, options) => {
367
- var _a, _b;
368
- const { sdkLanguage, revealConsole, revealAttachment, isLive, showDuration, showBadges } = options;
369
- const { errors, warnings } = stats(action);
370
- const showAttachments = !!((_a = action.attachments) == null ? void 0 : _a.length) && !!revealAttachment;
371
- const parameterString = actionParameterDisplayString(action, sdkLanguage || "javascript");
372
- const isSkipped = action.class === "Test" && action.method === "step" && ((_b = action.annotations) == null ? void 0 : _b.some((a2) => a2.type === "skip"));
373
- let time = "";
374
- if (action.endTime)
375
- time = msToString(action.endTime - action.startTime);
376
- else if (action.error)
377
- time = "Timed out";
378
- else if (!isLive)
379
- time = "-";
380
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
381
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "action-title", title: action.apiName, children: [
382
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: action.apiName }),
383
- parameterString && (parameterString.type === "locator" ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
384
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "action-parameter action-locator-parameter", children: parameterString.value }),
385
- parameterString.childDisplayString && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "action-parameter action-generic-parameter", children: parameterString.childDisplayString.value })
386
- ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "action-parameter action-generic-parameter", children: parameterString.value })),
387
- action.method === "goto" && action.params.url && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "action-url", title: action.params.url, children: action.params.url }),
388
- action.class === "APIRequestContext" && action.params.url && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "action-url", title: action.params.url, children: excludeOrigin(action.params.url) })
389
- ] }),
390
- (showDuration || showBadges || showAttachments || isSkipped) && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "spacer" }),
391
- showAttachments && /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "attach", title: "Open Attachment", onClick: () => revealAttachment(action.attachments[0]) }),
392
- showDuration && !isSkipped && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "action-duration", children: time || /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "codicon codicon-loading" }) }),
393
- isSkipped && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: clsx("action-skipped", "codicon", testStatusIcon("skipped")), title: "skipped" }),
394
- showBadges && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "action-icons", onClick: () => revealConsole == null ? void 0 : revealConsole(), children: [
395
- !!errors && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "action-icon", children: [
396
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "codicon codicon-error" }),
397
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "action-icon-value", children: errors })
398
- ] }),
399
- !!warnings && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "action-icon", children: [
400
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "codicon codicon-warning" }),
401
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "action-icon-value", children: warnings })
402
- ] })
403
- ] })
404
- ] });
405
- };
406
- function excludeOrigin(url) {
407
- try {
408
- const urlObject = new URL(url);
409
- return urlObject.pathname + urlObject.search;
410
- } catch (error) {
411
- return url;
412
- }
413
- }
414
- const clockDisplayString = (action) => {
415
- switch (action.method) {
416
- case "clockPauseAt":
417
- case "clockSetFixedTime":
418
- case "clockSetSystemTime": {
419
- if (action.params.timeString === void 0 && action.params.timeNumber === void 0)
420
- return void 0;
421
- return {
422
- type: "generic",
423
- value: new Date(
424
- action.params.timeString ?? action.params.timeNumber
425
- ).toLocaleString(void 0, { timeZone: "UTC" })
426
- };
427
- }
428
- case "clockFastForward":
429
- case "clockRunFor": {
430
- if (action.params.ticksNumber === void 0 && action.params.ticksString === void 0)
431
- return void 0;
432
- return {
433
- type: "generic",
434
- value: action.params.ticksString ?? `${action.params.ticksNumber}ms`
435
- };
436
- }
437
- }
438
- return void 0;
439
- };
440
- const keyboardDisplayString = (action) => {
441
- switch (action.method) {
442
- case "press":
443
- case "keyboardPress":
444
- case "keyboardDown":
445
- case "keyboardUp": {
446
- if (action.params.key === void 0)
447
- return void 0;
448
- return { type: "generic", value: action.params.key };
449
- }
450
- case "type":
451
- case "fill":
452
- case "keyboardType":
453
- case "keyboardInsertText": {
454
- const string = action.params.text ?? action.params.value;
455
- if (string === void 0)
456
- return void 0;
457
- return { type: "generic", value: `"${string}"` };
458
- }
459
- }
460
- };
461
- const mouseDisplayString = (action) => {
462
- switch (action.method) {
463
- case "click":
464
- case "dblclick":
465
- case "mouseClick":
466
- case "mouseMove": {
467
- if (action.params.x === void 0 || action.params.y === void 0)
468
- return void 0;
469
- return {
470
- type: "generic",
471
- value: `(${action.params.x}, ${action.params.y})`
472
- };
473
- }
474
- case "mouseWheel": {
475
- if (action.params.deltaX === void 0 || action.params.deltaY === void 0)
476
- return void 0;
477
- return {
478
- type: "generic",
479
- value: `(${action.params.deltaX}, ${action.params.deltaY})`
480
- };
481
- }
482
- }
483
- };
484
- const touchscreenDisplayString = (action) => {
485
- switch (action.method) {
486
- case "tap": {
487
- if (action.params.x === void 0 || action.params.y === void 0)
488
- return void 0;
489
- return {
490
- type: "generic",
491
- value: `(${action.params.x}, ${action.params.y})`
492
- };
493
- }
494
- }
495
- };
496
- const actionParameterDisplayString = (action, sdkLanguage, ignoreLocator = false) => {
497
- const params = action.params;
498
- if (!ignoreLocator && params.selector !== void 0) {
499
- return {
500
- type: "locator",
501
- value: asLocator(sdkLanguage, params.selector),
502
- childDisplayString: actionParameterDisplayString(
503
- action,
504
- sdkLanguage,
505
- true
506
- )
507
- };
508
- }
509
- switch (action.class.toLowerCase()) {
510
- case "browsercontext":
511
- return clockDisplayString(action);
512
- case "page":
513
- case "frame":
514
- case "elementhandle":
515
- return keyboardDisplayString(action) ?? mouseDisplayString(action) ?? touchscreenDisplayString(action);
516
- }
517
- return void 0;
518
- };
519
- const CallTab = ({ action, startTimeOffset, sdkLanguage }) => {
520
- const paramKeys = reactExports.useMemo(() => Object.keys((action == null ? void 0 : action.params) ?? {}).filter((name) => name !== "info"), [action]);
521
- if (!action)
522
- return /* @__PURE__ */ jsxRuntimeExports.jsx(PlaceholderPanel, { text: "No action selected" });
523
- const startTimeMillis = action.startTime - startTimeOffset;
524
- const startTime = msToString(startTimeMillis);
525
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-tab", children: [
526
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-line", children: action.apiName }),
527
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-section", children: "Time" }),
528
- /* @__PURE__ */ jsxRuntimeExports.jsx(DateTimeCallLine, { name: "start:", value: startTime }),
529
- /* @__PURE__ */ jsxRuntimeExports.jsx(DateTimeCallLine, { name: "duration:", value: renderDuration(action) }),
530
- !!paramKeys.length && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
531
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-section", children: "Parameters" }),
532
- paramKeys.map((name) => renderProperty(propertyToString(action, name, action.params[name], sdkLanguage)))
533
- ] }),
534
- !!action.result && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
535
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-section", children: "Return value" }),
536
- Object.keys(action.result).map(
537
- (name) => renderProperty(propertyToString(action, name, action.result[name], sdkLanguage))
538
- )
539
- ] })
540
- ] });
541
- };
542
- const DateTimeCallLine = ({ name, value }) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
543
- name,
544
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value datetime", title: value, children: value })
545
- ] });
546
- function renderDuration(action) {
547
- if (action.endTime)
548
- return msToString(action.endTime - action.startTime);
549
- else if (!!action.error)
550
- return "Timed Out";
551
- else
552
- return "Running";
553
- }
554
- function renderProperty(property) {
555
- let text = property.text.replace(/\n/g, "↵");
556
- if (property.type === "string")
557
- text = `"${text}"`;
558
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
559
- property.name,
560
- ":",
561
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: clsx("call-value", property.type), title: property.text, children: text }),
562
- ["string", "number", "object", "locator"].includes(property.type) && /* @__PURE__ */ jsxRuntimeExports.jsx(CopyToClipboard, { value: property.text })
563
- ] }, property.name);
564
- }
565
- function propertyToString(event, name, value, sdkLanguage) {
566
- const isEval = event.method.includes("eval") || event.method === "waitForFunction";
567
- if (name === "files")
568
- return { text: "<files>", type: "string", name };
569
- if (name === "eventInit" || name === "expectedValue" || name === "arg" && isEval)
570
- value = parseSerializedValue(value.value, new Array(10).fill({ handle: "<handle>" }));
571
- if (name === "value" && isEval || name === "received" && event.method === "expect")
572
- value = parseSerializedValue(value, new Array(10).fill({ handle: "<handle>" }));
573
- if (name === "selector")
574
- return { text: asLocator(sdkLanguage || "javascript", event.params.selector), type: "locator", name: "locator" };
575
- const type = typeof value;
576
- if (type !== "object" || value === null)
577
- return { text: String(value), type, name };
578
- if (value.guid)
579
- return { text: "<handle>", type: "handle", name };
580
- return { text: JSON.stringify(value).slice(0, 1e3), type: "object", name };
581
- }
582
- function parseSerializedValue(value, handles) {
583
- if (value.n !== void 0)
584
- return value.n;
585
- if (value.s !== void 0)
586
- return value.s;
587
- if (value.b !== void 0)
588
- return value.b;
589
- if (value.v !== void 0) {
590
- if (value.v === "undefined")
591
- return void 0;
592
- if (value.v === "null")
593
- return null;
594
- if (value.v === "NaN")
595
- return NaN;
596
- if (value.v === "Infinity")
597
- return Infinity;
598
- if (value.v === "-Infinity")
599
- return -Infinity;
600
- if (value.v === "-0")
601
- return -0;
602
- }
603
- if (value.d !== void 0)
604
- return new Date(value.d);
605
- if (value.r !== void 0)
606
- return new RegExp(value.r.p, value.r.f);
607
- if (value.a !== void 0)
608
- return value.a.map((a2) => parseSerializedValue(a2, handles));
609
- if (value.o !== void 0) {
610
- const result = {};
611
- for (const { k: k2, v: v2 } of value.o)
612
- result[k2] = parseSerializedValue(v2, handles);
613
- return result;
614
- }
615
- if (value.h !== void 0) {
616
- if (handles === void 0)
617
- return "<object>";
618
- return handles[value.h];
619
- }
620
- return "<object>";
621
- }
622
- const LogList = ListView;
623
- const LogTab = ({ action, isLive }) => {
624
- const entries = reactExports.useMemo(() => {
625
- var _a;
626
- if (!action || !action.log.length)
627
- return [];
628
- const log = action.log;
629
- const wallTimeOffset = action.context.wallTime - action.context.startTime;
630
- const entries2 = [];
631
- for (let i2 = 0; i2 < log.length; ++i2) {
632
- let time = "";
633
- if (log[i2].time !== -1) {
634
- const timeStart = (_a = log[i2]) == null ? void 0 : _a.time;
635
- if (i2 + 1 < log.length)
636
- time = msToString(log[i2 + 1].time - timeStart);
637
- else if (action.endTime > 0)
638
- time = msToString(action.endTime - timeStart);
639
- else if (isLive)
640
- time = msToString(Date.now() - wallTimeOffset - timeStart);
641
- else
642
- time = "-";
643
- }
644
- entries2.push({
645
- message: log[i2].message,
646
- time
647
- });
648
- }
649
- return entries2;
650
- }, [action, isLive]);
651
- if (!entries.length)
652
- return /* @__PURE__ */ jsxRuntimeExports.jsx(PlaceholderPanel, { text: "No log entries" });
653
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
654
- LogList,
655
- {
656
- name: "log",
657
- items: entries,
658
- render: (entry) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "log-list-item", children: [
659
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "log-list-duration", children: entry.time }),
660
- entry.message
661
- ] }),
662
- notSelectable: true
663
- }
664
- );
665
- };
666
- const ErrorMessage = ({ error }) => {
667
- const html = reactExports.useMemo(() => ansi2html(error), [error]);
668
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "error-message", dangerouslySetInnerHTML: { __html: html || "" } });
669
- };
670
- function t() {
671
- return t = Object.assign ? Object.assign.bind() : function(e) {
672
- for (var t2 = 1; t2 < arguments.length; t2++) {
673
- var n2 = arguments[t2];
674
- for (var r2 in n2) Object.prototype.hasOwnProperty.call(n2, r2) && (e[r2] = n2[r2]);
675
- }
676
- return e;
677
- }, t.apply(this, arguments);
678
- }
679
- const n = ["children", "options"], r = { blockQuote: "0", breakLine: "1", breakThematic: "2", codeBlock: "3", codeFenced: "4", codeInline: "5", footnote: "6", footnoteReference: "7", gfmTask: "8", heading: "9", headingSetext: "10", htmlBlock: "11", htmlComment: "12", htmlSelfClosing: "13", image: "14", link: "15", linkAngleBraceStyleDetector: "16", linkBareUrlDetector: "17", linkMailtoDetector: "18", newlineCoalescer: "19", orderedList: "20", paragraph: "21", ref: "22", refImage: "23", refLink: "24", table: "25", text: "27", textBolded: "28", textEmphasized: "29", textEscaped: "30", textMarked: "31", textStrikethroughed: "32", unorderedList: "33" };
680
- var i;
681
- !function(e) {
682
- e[e.MAX = 0] = "MAX", e[e.HIGH = 1] = "HIGH", e[e.MED = 2] = "MED", e[e.LOW = 3] = "LOW", e[e.MIN = 4] = "MIN";
683
- }(i || (i = {}));
684
- const l = ["allowFullScreen", "allowTransparency", "autoComplete", "autoFocus", "autoPlay", "cellPadding", "cellSpacing", "charSet", "classId", "colSpan", "contentEditable", "contextMenu", "crossOrigin", "encType", "formAction", "formEncType", "formMethod", "formNoValidate", "formTarget", "frameBorder", "hrefLang", "inputMode", "keyParams", "keyType", "marginHeight", "marginWidth", "maxLength", "mediaGroup", "minLength", "noValidate", "radioGroup", "readOnly", "rowSpan", "spellCheck", "srcDoc", "srcLang", "srcSet", "tabIndex", "useMap"].reduce((e, t2) => (e[t2.toLowerCase()] = t2, e), { class: "className", for: "htmlFor" }), a = { amp: "&", apos: "'", gt: ">", lt: "<", nbsp: " ", quot: "“" }, o = ["style", "script"], c = /([-A-Z0-9_:]+)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|(?:\{((?:\\.|{[^}]*?}|[^}])*)\})))?/gi, s = /mailto:/i, d = /\n{2,}$/, u = /^(\s*>[\s\S]*?)(?=\n\n|$)/, p = /^ *> ?/gm, f = /^(?:\[!([^\]]*)\]\n)?([\s\S]*)/, h = /^ {2,}\n/, m = /^(?:( *[-*_])){3,} *(?:\n *)+\n/, g = /^(?: {1,3})?(`{3,}|~{3,}) *(\S+)? *([^\n]*?)?\n([\s\S]*?)(?:\1\n?|$)/, y = /^(?: {4}[^\n]+\n*)+(?:\n *)+\n?/, k = /^(`+)((?:\\`|[^`])+)\1/, x = /^(?:\n *)*\n/, b = /\r\n?/g, v = /^\[\^([^\]]+)](:(.*)((\n+ {4,}.*)|(\n(?!\[\^).+))*)/, C = /^\[\^([^\]]+)]/, $ = /\f/g, S = /^---[ \t]*\n(.|\n)*\n---[ \t]*\n/, w = /^\s*?\[(x|\s)\]/, E = /^ *(#{1,6}) *([^\n]+?)(?: +#*)?(?:\n *)*(?:\n|$)/, z = /^ *(#{1,6}) +([^\n]+?)(?: +#*)?(?:\n *)*(?:\n|$)/, L = /^([^\n]+)\n *(=|-){3,} *(?:\n *)+\n/, A = /^ *(?!<[a-z][^ >/]* ?\/>)<([a-z][^ >/]*) ?((?:[^>]*[^/])?)>\n?(\s*(?:<\1[^>]*?>[\s\S]*?<\/\1>|(?!<\1\b)[\s\S])*?)<\/\1>(?!<\/\1>)\n*/i, T = /&([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-fA-F]{1,6});/gi, B = /^<!--[\s\S]*?(?:-->)/, O = /^(data|aria|x)-[a-z_][a-z\d_.-]*$/, M = /^ *<([a-z][a-z0-9:]*)(?:\s+((?:<.*?>|[^>])*))?\/?>(?!<\/\1>)(\s*\n)?/i, R = /^\{.*\}$/, I = /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/, U = /^<([^ >]+@[^ >]+)>/, D = /^<([^ >]+:\/[^ >]+)>/, N = /-([a-z])?/gi, j = /^(\|.*)\n(?: *(\|? *[-:]+ *\|[-| :]*)\n((?:.*\|.*\n)*))?\n?/, H = /^\[([^\]]*)\]:\s+<?([^\s>]+)>?\s*("([^"]*)")?/, P = /^!\[([^\]]*)\] ?\[([^\]]*)\]/, _ = /^\[([^\]]*)\] ?\[([^\]]*)\]/, F = /(\n|^[-*]\s|^#|^ {2,}|^-{2,}|^>\s)/, G = /\t/g, W = /(^ *\||\| *$)/g, Z = /^ *:-+: *$/, q = /^ *:-+ *$/, Q = /^ *-+: *$/, V = "((?:\\[.*?\\][([].*?[)\\]]|<.*?>(?:.*?<.*?>)?|`.*?`|\\\\\\1|[\\s\\S])+?)", X = new RegExp(`^([*_])\\1${V}\\1\\1(?!\\1)`), J = new RegExp(`^([*_])${V}\\1(?!\\1)`), K = new RegExp(`^(==)${V}\\1`), Y = new RegExp(`^(~~)${V}\\1`), ee = /^\\([^0-9A-Za-z\s])/, te = /\\([^0-9A-Za-z\s])/g, ne = /^([\s\S](?:(?! |[0-9]\.)[^*_~\-\n<`\\\[!])*)/, re = /^\n+/, ie = /^([ \t]*)/, le = /\\([^\\])/g, ae = /(?:^|\n)( *)$/, oe = "(?:\\d+\\.)", ce = "(?:[*+-])";
685
- function se(e) {
686
- return "( *)(" + (1 === e ? oe : ce) + ") +";
687
- }
688
- const de = se(1), ue = se(2);
689
- function pe(e) {
690
- return new RegExp("^" + (1 === e ? de : ue));
691
- }
692
- const fe = pe(1), he = pe(2);
693
- function me(e) {
694
- return new RegExp("^" + (1 === e ? de : ue) + "[^\\n]*(?:\\n(?!\\1" + (1 === e ? oe : ce) + " )[^\\n]*)*(\\n|$)", "gm");
695
- }
696
- const ge = me(1), ye = me(2);
697
- function ke(e) {
698
- const t2 = 1 === e ? oe : ce;
699
- return new RegExp("^( *)(" + t2 + ") [\\s\\S]+?(?:\\n{2,}(?! )(?!\\1" + t2 + " (?!" + t2 + " ))\\n*|\\s*\\n*$)");
700
- }
701
- const xe = ke(1), be = ke(2);
702
- function ve(e, t2) {
703
- const n2 = 1 === t2, i2 = n2 ? xe : be, l2 = n2 ? ge : ye, a2 = n2 ? fe : he;
704
- return { match: Oe(function(e2, t3) {
705
- const n3 = ae.exec(t3.prevCapture);
706
- return n3 && (t3.list || !t3.inline && !t3.simple) ? i2.exec(e2 = n3[1] + e2) : null;
707
- }), order: 1, parse(e2, t3, r2) {
708
- const i3 = n2 ? +e2[2] : void 0, o2 = e2[0].replace(d, "\n").match(l2);
709
- let c2 = false;
710
- return { items: o2.map(function(e3, n3) {
711
- const i4 = a2.exec(e3)[0].length, l3 = new RegExp("^ {1," + i4 + "}", "gm"), s2 = e3.replace(l3, "").replace(a2, ""), d2 = n3 === o2.length - 1, u2 = -1 !== s2.indexOf("\n\n") || d2 && c2;
712
- c2 = u2;
713
- const p2 = r2.inline, f2 = r2.list;
714
- let h2;
715
- r2.list = true, u2 ? (r2.inline = false, h2 = Ee(s2) + "\n\n") : (r2.inline = true, h2 = Ee(s2));
716
- const m2 = t3(h2, r2);
717
- return r2.inline = p2, r2.list = f2, m2;
718
- }), ordered: n2, start: i3 };
719
- }, render: (t3, n3, i3) => e(t3.ordered ? "ol" : "ul", { key: i3.key, start: t3.type === r.orderedList ? t3.start : void 0 }, t3.items.map(function(t4, r2) {
720
- return e("li", { key: r2 }, n3(t4, i3));
721
- })) };
722
- }
723
- const Ce = new RegExp(`^\\[((?:\\[[^\\]]*\\]|[^\\[\\]]|\\](?=[^\\[]*\\]))*)\\]\\(\\s*<?((?:\\([^)]*\\)|[^\\s\\\\]|\\\\.)*?)>?(?:\\s+['"]([\\s\\S]*?)['"])?\\s*\\)`), $e = /^!\[(.*?)\]\( *((?:\([^)]*\)|[^() ])*) *"?([^)"]*)?"?\)/, Se = [u, g, y, E, L, z, j, xe, be], we = [...Se, /^[^\n]+(?: \n|\n{2,})/, A, B, M];
724
- function Ee(e) {
725
- let t2 = e.length;
726
- for (; t2 > 0 && e[t2 - 1] <= " "; ) t2--;
727
- return e.slice(0, t2);
728
- }
729
- function ze(e) {
730
- return e.replace(/[ÀÁÂÃÄÅàáâãä忯]/g, "a").replace(/[çÇ]/g, "c").replace(/[ðÐ]/g, "d").replace(/[ÈÉÊËéèêë]/g, "e").replace(/[ÏïÎîÍíÌì]/g, "i").replace(/[Ññ]/g, "n").replace(/[øØœŒÕõÔôÓóÒò]/g, "o").replace(/[ÜüÛûÚúÙù]/g, "u").replace(/[ŸÿÝý]/g, "y").replace(/[^a-z0-9- ]/gi, "").replace(/ /gi, "-").toLowerCase();
731
- }
732
- function Le(e) {
733
- return Q.test(e) ? "right" : Z.test(e) ? "center" : q.test(e) ? "left" : null;
734
- }
735
- function Ae(e, t2, n2, r2) {
736
- const i2 = n2.inTable;
737
- n2.inTable = true;
738
- let l2 = [[]], a2 = "";
739
- function o2() {
740
- if (!a2) return;
741
- const e2 = l2[l2.length - 1];
742
- e2.push.apply(e2, t2(a2, n2)), a2 = "";
743
- }
744
- return e.trim().split(/(`[^`]*`|\\\||\|)/).filter(Boolean).forEach((e2, t3, n3) => {
745
- "|" === e2.trim() && (o2(), r2) ? 0 !== t3 && t3 !== n3.length - 1 && l2.push([]) : a2 += e2;
746
- }), o2(), n2.inTable = i2, l2;
747
- }
748
- function Te(e, t2, n2) {
749
- n2.inline = true;
750
- const i2 = e[2] ? e[2].replace(W, "").split("|").map(Le) : [], l2 = e[3] ? function(e2, t3, n3) {
751
- return e2.trim().split("\n").map(function(e3) {
752
- return Ae(e3, t3, n3, true);
753
- });
754
- }(e[3], t2, n2) : [], a2 = Ae(e[1], t2, n2, !!l2.length);
755
- return n2.inline = false, l2.length ? { align: i2, cells: l2, header: a2, type: r.table } : { children: a2, type: r.paragraph };
756
- }
757
- function Be(e, t2) {
758
- return null == e.align[t2] ? {} : { textAlign: e.align[t2] };
759
- }
760
- function Oe(e) {
761
- return e.inline = 1, e;
762
- }
763
- function Me(e) {
764
- return Oe(function(t2, n2) {
765
- return n2.inline ? e.exec(t2) : null;
766
- });
767
- }
768
- function Re(e) {
769
- return Oe(function(t2, n2) {
770
- return n2.inline || n2.simple ? e.exec(t2) : null;
771
- });
772
- }
773
- function Ie(e) {
774
- return function(t2, n2) {
775
- return n2.inline || n2.simple ? null : e.exec(t2);
776
- };
777
- }
778
- function Ue(e) {
779
- return Oe(function(t2) {
780
- return e.exec(t2);
781
- });
782
- }
783
- function De(e, t2) {
784
- if (t2.inline || t2.simple) return null;
785
- let n2 = "";
786
- e.split("\n").every((e2) => (e2 += "\n", !Se.some((t3) => t3.test(e2)) && (n2 += e2, !!e2.trim())));
787
- const r2 = Ee(n2);
788
- return "" == r2 ? null : [n2, , r2];
789
- }
790
- function Ne(e) {
791
- try {
792
- if (decodeURIComponent(e).replace(/[^A-Za-z0-9/:]/g, "").match(/^\s*(javascript|vbscript|data(?!:image)):/i)) return null;
793
- } catch (e2) {
794
- return null;
795
- }
796
- return e;
797
- }
798
- function je(e) {
799
- return e.replace(le, "$1");
800
- }
801
- function He(e, t2, n2) {
802
- const r2 = n2.inline || false, i2 = n2.simple || false;
803
- n2.inline = true, n2.simple = true;
804
- const l2 = e(t2, n2);
805
- return n2.inline = r2, n2.simple = i2, l2;
806
- }
807
- function Pe(e, t2, n2) {
808
- const r2 = n2.inline || false, i2 = n2.simple || false;
809
- n2.inline = false, n2.simple = true;
810
- const l2 = e(t2, n2);
811
- return n2.inline = r2, n2.simple = i2, l2;
812
- }
813
- function _e(e, t2, n2) {
814
- const r2 = n2.inline || false;
815
- n2.inline = false;
816
- const i2 = e(t2, n2);
817
- return n2.inline = r2, i2;
818
- }
819
- const Fe = (e, t2, n2) => ({ children: He(t2, e[2], n2) });
820
- function Ge() {
821
- return {};
822
- }
823
- function We() {
824
- return null;
825
- }
826
- function Ze(...e) {
827
- return e.filter(Boolean).join(" ");
828
- }
829
- function qe(e, t2, n2) {
830
- let r2 = e;
831
- const i2 = t2.split(".");
832
- for (; i2.length && (r2 = r2[i2[0]], void 0 !== r2); ) i2.shift();
833
- return r2 || n2;
834
- }
835
- function Qe(n2 = "", i2 = {}) {
836
- function d2(e, n3, ...r2) {
837
- const l2 = qe(i2.overrides, `${e}.props`, {});
838
- return i2.createElement(function(e2, t2) {
839
- const n4 = qe(t2, e2);
840
- return n4 ? "function" == typeof n4 || "object" == typeof n4 && "render" in n4 ? n4 : qe(t2, `${e2}.component`, e2) : e2;
841
- }(e, i2.overrides), t({}, n3, l2, { className: Ze(null == n3 ? void 0 : n3.className, l2.className) || void 0 }), ...r2);
842
- }
843
- function W2(e) {
844
- e = e.replace(S, "");
845
- let t2 = false;
846
- i2.forceInline ? t2 = true : i2.forceBlock || (t2 = false === F.test(e));
847
- const n3 = ae2(le2(t2 ? e : `${Ee(e).replace(re, "")}
848
-
849
- `, { inline: t2 }));
850
- for (; "string" == typeof n3[n3.length - 1] && !n3[n3.length - 1].trim(); ) n3.pop();
851
- if (null === i2.wrapper) return n3;
852
- const r2 = i2.wrapper || (t2 ? "span" : "div");
853
- let l2;
854
- if (n3.length > 1 || i2.forceWrapper) l2 = n3;
855
- else {
856
- if (1 === n3.length) return l2 = n3[0], "string" == typeof l2 ? d2("span", { key: "outer" }, l2) : l2;
857
- l2 = null;
858
- }
859
- return i2.createElement(r2, { key: "outer" }, l2);
860
- }
861
- function Z2(e, t2) {
862
- const n3 = t2.match(c);
863
- return n3 ? n3.reduce(function(t3, n4) {
864
- const r2 = n4.indexOf("=");
865
- if (-1 !== r2) {
866
- const a2 = function(e2) {
867
- return -1 !== e2.indexOf("-") && null === e2.match(O) && (e2 = e2.replace(N, function(e3, t4) {
868
- return t4.toUpperCase();
869
- })), e2;
870
- }(n4.slice(0, r2)).trim(), o2 = function(e2) {
871
- const t4 = e2[0];
872
- return ('"' === t4 || "'" === t4) && e2.length >= 2 && e2[e2.length - 1] === t4 ? e2.slice(1, -1) : e2;
873
- }(n4.slice(r2 + 1).trim()), c2 = l[a2] || a2;
874
- if ("ref" === c2) return t3;
875
- const s2 = t3[c2] = function(e2, t4, n5, r3) {
876
- return "style" === t4 ? n5.split(/;\s?/).reduce(function(e3, t5) {
877
- const n6 = t5.slice(0, t5.indexOf(":"));
878
- return e3[n6.trim().replace(/(-[a-z])/g, (e4) => e4[1].toUpperCase())] = t5.slice(n6.length + 1).trim(), e3;
879
- }, {}) : "href" === t4 || "src" === t4 ? r3(n5, e2, t4) : (n5.match(R) && (n5 = n5.slice(1, n5.length - 1)), "true" === n5 || "false" !== n5 && n5);
880
- }(e, a2, o2, i2.sanitizer);
881
- "string" == typeof s2 && (A.test(s2) || M.test(s2)) && (t3[c2] = W2(s2.trim()));
882
- } else "style" !== n4 && (t3[l[n4] || n4] = true);
883
- return t3;
884
- }, {}) : null;
885
- }
886
- i2.overrides = i2.overrides || {}, i2.sanitizer = i2.sanitizer || Ne, i2.slugify = i2.slugify || ze, i2.namedCodesToUnicode = i2.namedCodesToUnicode ? t({}, a, i2.namedCodesToUnicode) : a, i2.createElement = i2.createElement || reactExports.createElement;
887
- const q2 = [], Q2 = {}, V2 = { [r.blockQuote]: { match: Ie(u), order: 1, parse(e, t2, n3) {
888
- const [, r2, i3] = e[0].replace(p, "").match(f);
889
- return { alert: r2, children: t2(i3, n3) };
890
- }, render(e, t2, n3) {
891
- const l2 = { key: n3.key };
892
- return e.alert && (l2.className = "markdown-alert-" + i2.slugify(e.alert.toLowerCase(), ze), e.children.unshift({ attrs: {}, children: [{ type: r.text, text: e.alert }], noInnerParse: true, type: r.htmlBlock, tag: "header" })), d2("blockquote", l2, t2(e.children, n3));
893
- } }, [r.breakLine]: { match: Ue(h), order: 1, parse: Ge, render: (e, t2, n3) => d2("br", { key: n3.key }) }, [r.breakThematic]: { match: Ie(m), order: 1, parse: Ge, render: (e, t2, n3) => d2("hr", { key: n3.key }) }, [r.codeBlock]: { match: Ie(y), order: 0, parse: (e) => ({ lang: void 0, text: Ee(e[0].replace(/^ {4}/gm, "")).replace(te, "$1") }), render: (e, n3, r2) => d2("pre", { key: r2.key }, d2("code", t({}, e.attrs, { className: e.lang ? `lang-${e.lang}` : "" }), e.text)) }, [r.codeFenced]: { match: Ie(g), order: 0, parse: (e) => ({ attrs: Z2("code", e[3] || ""), lang: e[2] || void 0, text: e[4].replace(te, "$1"), type: r.codeBlock }) }, [r.codeInline]: { match: Re(k), order: 3, parse: (e) => ({ text: e[2].replace(te, "$1") }), render: (e, t2, n3) => d2("code", { key: n3.key }, e.text) }, [r.footnote]: { match: Ie(v), order: 0, parse: (e) => (q2.push({ footnote: e[2], identifier: e[1] }), {}), render: We }, [r.footnoteReference]: { match: Me(C), order: 1, parse: (e) => ({ target: `#${i2.slugify(e[1], ze)}`, text: e[1] }), render: (e, t2, n3) => d2("a", { key: n3.key, href: i2.sanitizer(e.target, "a", "href") }, d2("sup", { key: n3.key }, e.text)) }, [r.gfmTask]: { match: Me(w), order: 1, parse: (e) => ({ completed: "x" === e[1].toLowerCase() }), render: (e, t2, n3) => d2("input", { checked: e.completed, key: n3.key, readOnly: true, type: "checkbox" }) }, [r.heading]: { match: Ie(i2.enforceAtxHeadings ? z : E), order: 1, parse: (e, t2, n3) => ({ children: He(t2, e[2], n3), id: i2.slugify(e[2], ze), level: e[1].length }), render: (e, t2, n3) => d2(`h${e.level}`, { id: e.id, key: n3.key }, t2(e.children, n3)) }, [r.headingSetext]: { match: Ie(L), order: 0, parse: (e, t2, n3) => ({ children: He(t2, e[1], n3), level: "=" === e[2] ? 1 : 2, type: r.heading }) }, [r.htmlBlock]: { match: Ue(A), order: 1, parse(e, t2, n3) {
894
- const [, r2] = e[3].match(ie), i3 = new RegExp(`^${r2}`, "gm"), l2 = e[3].replace(i3, ""), a2 = (c2 = l2, we.some((e2) => e2.test(c2)) ? _e : He);
895
- var c2;
896
- const s2 = e[1].toLowerCase(), d3 = -1 !== o.indexOf(s2), u2 = (d3 ? s2 : e[1]).trim(), p2 = { attrs: Z2(u2, e[2]), noInnerParse: d3, tag: u2 };
897
- return n3.inAnchor = n3.inAnchor || "a" === s2, d3 ? p2.text = e[3] : p2.children = a2(t2, l2, n3), n3.inAnchor = false, p2;
898
- }, render: (e, n3, r2) => d2(e.tag, t({ key: r2.key }, e.attrs), e.text || (e.children ? n3(e.children, r2) : "")) }, [r.htmlSelfClosing]: { match: Ue(M), order: 1, parse(e) {
899
- const t2 = e[1].trim();
900
- return { attrs: Z2(t2, e[2] || ""), tag: t2 };
901
- }, render: (e, n3, r2) => d2(e.tag, t({}, e.attrs, { key: r2.key })) }, [r.htmlComment]: { match: Ue(B), order: 1, parse: () => ({}), render: We }, [r.image]: { match: Re($e), order: 1, parse: (e) => ({ alt: e[1], target: je(e[2]), title: e[3] }), render: (e, t2, n3) => d2("img", { key: n3.key, alt: e.alt || void 0, title: e.title || void 0, src: i2.sanitizer(e.target, "img", "src") }) }, [r.link]: { match: Me(Ce), order: 3, parse: (e, t2, n3) => ({ children: Pe(t2, e[1], n3), target: je(e[2]), title: e[3] }), render: (e, t2, n3) => d2("a", { key: n3.key, href: i2.sanitizer(e.target, "a", "href"), title: e.title }, t2(e.children, n3)) }, [r.linkAngleBraceStyleDetector]: { match: Me(D), order: 0, parse: (e) => ({ children: [{ text: e[1], type: r.text }], target: e[1], type: r.link }) }, [r.linkBareUrlDetector]: { match: Oe((e, t2) => t2.inAnchor || i2.disableAutoLink ? null : Me(I)(e, t2)), order: 0, parse: (e) => ({ children: [{ text: e[1], type: r.text }], target: e[1], title: void 0, type: r.link }) }, [r.linkMailtoDetector]: { match: Me(U), order: 0, parse(e) {
902
- let t2 = e[1], n3 = e[1];
903
- return s.test(n3) || (n3 = "mailto:" + n3), { children: [{ text: t2.replace("mailto:", ""), type: r.text }], target: n3, type: r.link };
904
- } }, [r.orderedList]: ve(d2, 1), [r.unorderedList]: ve(d2, 2), [r.newlineCoalescer]: { match: Ie(x), order: 3, parse: Ge, render: () => "\n" }, [r.paragraph]: { match: Oe(De), order: 3, parse: Fe, render: (e, t2, n3) => d2("p", { key: n3.key }, t2(e.children, n3)) }, [r.ref]: { match: Me(H), order: 0, parse: (e) => (Q2[e[1]] = { target: e[2], title: e[4] }, {}), render: We }, [r.refImage]: { match: Re(P), order: 0, parse: (e) => ({ alt: e[1] || void 0, ref: e[2] }), render: (e, t2, n3) => Q2[e.ref] ? d2("img", { key: n3.key, alt: e.alt, src: i2.sanitizer(Q2[e.ref].target, "img", "src"), title: Q2[e.ref].title }) : null }, [r.refLink]: { match: Me(_), order: 0, parse: (e, t2, n3) => ({ children: t2(e[1], n3), fallbackChildren: e[0], ref: e[2] }), render: (e, t2, n3) => Q2[e.ref] ? d2("a", { key: n3.key, href: i2.sanitizer(Q2[e.ref].target, "a", "href"), title: Q2[e.ref].title }, t2(e.children, n3)) : d2("span", { key: n3.key }, e.fallbackChildren) }, [r.table]: { match: Ie(j), order: 1, parse: Te, render(e, t2, n3) {
905
- const r2 = e;
906
- return d2("table", { key: n3.key }, d2("thead", null, d2("tr", null, r2.header.map(function(e2, i3) {
907
- return d2("th", { key: i3, style: Be(r2, i3) }, t2(e2, n3));
908
- }))), d2("tbody", null, r2.cells.map(function(e2, i3) {
909
- return d2("tr", { key: i3 }, e2.map(function(e3, i4) {
910
- return d2("td", { key: i4, style: Be(r2, i4) }, t2(e3, n3));
911
- }));
912
- })));
913
- } }, [r.text]: { match: Ue(ne), order: 4, parse: (e) => ({ text: e[0].replace(T, (e2, t2) => i2.namedCodesToUnicode[t2] ? i2.namedCodesToUnicode[t2] : e2) }), render: (e) => e.text }, [r.textBolded]: { match: Re(X), order: 2, parse: (e, t2, n3) => ({ children: t2(e[2], n3) }), render: (e, t2, n3) => d2("strong", { key: n3.key }, t2(e.children, n3)) }, [r.textEmphasized]: { match: Re(J), order: 3, parse: (e, t2, n3) => ({ children: t2(e[2], n3) }), render: (e, t2, n3) => d2("em", { key: n3.key }, t2(e.children, n3)) }, [r.textEscaped]: { match: Re(ee), order: 1, parse: (e) => ({ text: e[1], type: r.text }) }, [r.textMarked]: { match: Re(K), order: 3, parse: Fe, render: (e, t2, n3) => d2("mark", { key: n3.key }, t2(e.children, n3)) }, [r.textStrikethroughed]: { match: Re(Y), order: 3, parse: Fe, render: (e, t2, n3) => d2("del", { key: n3.key }, t2(e.children, n3)) } };
914
- true === i2.disableParsingRawHTML && (delete V2[r.htmlBlock], delete V2[r.htmlSelfClosing]);
915
- const le2 = function(e) {
916
- let t2 = Object.keys(e);
917
- function n3(r2, i3) {
918
- let l2, a2, o2 = [], c2 = "", s2 = "";
919
- for (i3.prevCapture = i3.prevCapture || ""; r2; ) {
920
- let d3 = 0;
921
- for (; d3 < t2.length; ) {
922
- if (c2 = t2[d3], l2 = e[c2], i3.inline && !l2.match.inline) {
923
- d3++;
924
- continue;
925
- }
926
- const u2 = l2.match(r2, i3);
927
- if (u2) {
928
- s2 = u2[0], i3.prevCapture += s2, r2 = r2.substring(s2.length), a2 = l2.parse(u2, n3, i3), null == a2.type && (a2.type = c2), o2.push(a2);
929
- break;
930
- }
931
- d3++;
932
- }
933
- }
934
- return i3.prevCapture = "", o2;
935
- }
936
- return t2.sort(function(t3, n4) {
937
- let r2 = e[t3].order, i3 = e[n4].order;
938
- return r2 !== i3 ? r2 - i3 : t3 < n4 ? -1 : 1;
939
- }), function(e2, t3) {
940
- return n3(function(e3) {
941
- return e3.replace(b, "\n").replace($, "").replace(G, " ");
942
- }(e2), t3);
943
- };
944
- }(V2), ae2 = (oe2 = /* @__PURE__ */ function(e, t2) {
945
- return function(n3, r2, i3) {
946
- const l2 = e[n3.type].render;
947
- return t2 ? t2(() => l2(n3, r2, i3), n3, r2, i3) : l2(n3, r2, i3);
948
- };
949
- }(V2, i2.renderRule), function e(t2, n3 = {}) {
950
- if (Array.isArray(t2)) {
951
- const r2 = n3.key, i3 = [];
952
- let l2 = false;
953
- for (let r3 = 0; r3 < t2.length; r3++) {
954
- n3.key = r3;
955
- const a2 = e(t2[r3], n3), o2 = "string" == typeof a2;
956
- o2 && l2 ? i3[i3.length - 1] += a2 : null !== a2 && i3.push(a2), l2 = o2;
957
- }
958
- return n3.key = r2, i3;
959
- }
960
- return oe2(t2, e, n3);
961
- });
962
- var oe2;
963
- const ce2 = W2(n2);
964
- return q2.length ? d2("div", null, ce2, d2("footer", { key: "footer" }, q2.map(function(e) {
965
- return d2("div", { id: i2.slugify(e.identifier, ze), key: e.identifier }, e.identifier, ae2(le2(e.footnote, { inline: true })));
966
- }))) : ce2;
967
- }
968
- const Markdown = (t2) => {
969
- let { children: r2 = "", options: i2 } = t2, l2 = function(e, t3) {
970
- if (null == e) return {};
971
- var n2, r3, i3 = {}, l3 = Object.keys(e);
972
- for (r3 = 0; r3 < l3.length; r3++) t3.indexOf(n2 = l3[r3]) >= 0 || (i3[n2] = e[n2]);
973
- return i3;
974
- }(t2, n);
975
- return reactExports.cloneElement(Qe(r2, i2), l2);
976
- };
977
- var Disposable;
978
- ((Disposable2) => {
979
- function disposeAll(disposables) {
980
- for (const disposable of disposables.splice(0))
981
- disposable.dispose();
982
- }
983
- Disposable2.disposeAll = disposeAll;
984
- })(Disposable || (Disposable = {}));
985
- class EventEmitter {
986
- constructor() {
987
- this._listeners = /* @__PURE__ */ new Set();
988
- this.event = (listener, disposables) => {
989
- this._listeners.add(listener);
990
- let disposed = false;
991
- const self = this;
992
- const result = {
993
- dispose() {
994
- if (!disposed) {
995
- disposed = true;
996
- self._listeners.delete(listener);
997
- }
998
- }
999
- };
1000
- if (disposables)
1001
- disposables.push(result);
1002
- return result;
1003
- };
1004
- }
1005
- fire(event) {
1006
- const dispatch = !this._deliveryQueue;
1007
- if (!this._deliveryQueue)
1008
- this._deliveryQueue = [];
1009
- for (const listener of this._listeners)
1010
- this._deliveryQueue.push({ listener, event });
1011
- if (!dispatch)
1012
- return;
1013
- for (let index = 0; index < this._deliveryQueue.length; index++) {
1014
- const { listener, event: event2 } = this._deliveryQueue[index];
1015
- listener.call(null, event2);
1016
- }
1017
- this._deliveryQueue = void 0;
1018
- }
1019
- dispose() {
1020
- this._listeners.clear();
1021
- if (this._deliveryQueue)
1022
- this._deliveryQueue = [];
1023
- }
1024
- }
1025
- async function* parseSSE(body) {
1026
- const reader = body.pipeThrough(new TextDecoderStream()).getReader();
1027
- let buffer = "";
1028
- let lastEventId = "";
1029
- let type = "";
1030
- let data = "";
1031
- while (true) {
1032
- const { value, done } = await reader.read();
1033
- if (done)
1034
- break;
1035
- buffer += value;
1036
- const lines = buffer.split("\n");
1037
- buffer = lines.pop();
1038
- for (const line of lines) {
1039
- if (line.length === 0) {
1040
- if (data === "") {
1041
- data = "";
1042
- type = "";
1043
- continue;
1044
- }
1045
- if (data[data.length - 1] === "\n")
1046
- data = data.substring(0, data.length - 1);
1047
- const event = { type: type || "message", data, id: lastEventId };
1048
- type = "";
1049
- data = "";
1050
- yield event;
1051
- }
1052
- if (line[0] === ":")
1053
- continue;
1054
- let name = "";
1055
- let value2 = "";
1056
- const colon = line.indexOf(":");
1057
- if (colon === -1) {
1058
- name = line;
1059
- } else {
1060
- name = line.substring(0, colon);
1061
- value2 = line[colon + 1] === " " ? line.substring(colon + 2) : line.substring(colon + 1);
1062
- }
1063
- switch (name) {
1064
- case "event":
1065
- type = value2;
1066
- break;
1067
- case "data":
1068
- data += value2 + "\n";
1069
- break;
1070
- case "id":
1071
- lastEventId = value2;
1072
- break;
1073
- }
1074
- }
1075
- }
1076
- }
1077
- class OpenAI {
1078
- constructor(apiKey, baseURL = "https://api.openai.com") {
1079
- __publicField(this, "name", "OpenAI");
1080
- this.apiKey = apiKey;
1081
- this.baseURL = baseURL;
1082
- }
1083
- async *chatCompletion(messages, signal) {
1084
- const url = new URL("./v1/chat/completions", this.baseURL);
1085
- const response = await fetch(url, {
1086
- method: "POST",
1087
- headers: {
1088
- "Content-Type": "application/json",
1089
- "Authorization": `Bearer ${this.apiKey}`,
1090
- "x-pw-serviceworker": "forward"
1091
- },
1092
- body: JSON.stringify({
1093
- model: "gpt-4o",
1094
- // TODO: make configurable
1095
- messages: messages.map(({ role, content }) => ({ role, content })),
1096
- stream: true
1097
- }),
1098
- signal
1099
- });
1100
- if (response.status !== 200 || !response.body)
1101
- throw new Error("Failed to chat with OpenAI, unexpected status: " + response.status + await response.text());
1102
- for await (const sseEvent of parseSSE(response.body)) {
1103
- const event = JSON.parse(sseEvent.data);
1104
- if (event.object === "chat.completion.chunk") {
1105
- if (event.choices[0].finish_reason)
1106
- break;
1107
- yield event.choices[0].delta.content;
1108
- }
1109
- }
1110
- }
1111
- }
1112
- class Anthropic {
1113
- constructor(apiKey, baseURL = "https://api.anthropic.com") {
1114
- __publicField(this, "name", "Anthropic");
1115
- this.apiKey = apiKey;
1116
- this.baseURL = baseURL;
1117
- }
1118
- async *chatCompletion(messages, signal) {
1119
- var _a;
1120
- const response = await fetch(new URL("./v1/messages", this.baseURL), {
1121
- method: "POST",
1122
- headers: {
1123
- "Content-Type": "application/json",
1124
- "x-api-key": this.apiKey,
1125
- "anthropic-version": "2023-06-01",
1126
- "x-pw-serviceworker": "forward"
1127
- },
1128
- body: JSON.stringify({
1129
- model: "claude-3-5-sonnet-20241022",
1130
- // TODO: make configurable
1131
- messages: messages.filter(({ role }) => role !== "developer").map(({ role, content }) => ({ role, content })),
1132
- system: (_a = messages.find(({ role }) => role === "developer")) == null ? void 0 : _a.content,
1133
- max_tokens: 1024,
1134
- stream: true
1135
- }),
1136
- signal
1137
- });
1138
- if (response.status !== 200 || !response.body)
1139
- throw new Error("Failed to chat with Anthropic, unexpected status: " + response.status + await response.text());
1140
- for await (const sseEvent of parseSSE(response.body)) {
1141
- const event = JSON.parse(sseEvent.data);
1142
- if (event.type === "content_block_delta")
1143
- yield event.delta.text;
1144
- }
1145
- }
1146
- }
1147
- class LLMChat {
1148
- constructor(api) {
1149
- __publicField(this, "conversations", /* @__PURE__ */ new Map());
1150
- this.api = api;
1151
- }
1152
- getConversation(id) {
1153
- return this.conversations.get(id);
1154
- }
1155
- startConversation(id, systemPrompt) {
1156
- const conversation = new Conversation(this, systemPrompt);
1157
- this.conversations.set(id, conversation);
1158
- return conversation;
1159
- }
1160
- }
1161
- class Conversation {
1162
- constructor(chat, systemPrompt) {
1163
- __publicField(this, "history");
1164
- __publicField(this, "onChange", new EventEmitter());
1165
- __publicField(this, "_abortControllers", /* @__PURE__ */ new Set());
1166
- this.chat = chat;
1167
- this.history = [{ role: "developer", content: systemPrompt }];
1168
- }
1169
- async send(content, displayContent) {
1170
- const response = { role: "assistant", content: "" };
1171
- this.history.push({ role: "user", content, displayContent }, response);
1172
- const abortController = new AbortController();
1173
- this._abortControllers.add(abortController);
1174
- this.onChange.fire();
1175
- try {
1176
- for await (const chunk of this.chat.api.chatCompletion(this.history, abortController.signal)) {
1177
- response.content += chunk;
1178
- this.onChange.fire();
1179
- }
1180
- } finally {
1181
- this._abortControllers.delete(abortController);
1182
- this.onChange.fire();
1183
- }
1184
- }
1185
- isSending() {
1186
- return this._abortControllers.size > 0;
1187
- }
1188
- abortSending() {
1189
- for (const controller of this._abortControllers)
1190
- controller.abort();
1191
- this._abortControllers.clear();
1192
- this.onChange.fire();
1193
- }
1194
- isEmpty() {
1195
- return this.history.length < 2;
1196
- }
1197
- }
1198
- const llmContext = reactExports.createContext(void 0);
1199
- function LLMProvider({ children }) {
1200
- const cookiePairs = useCookies();
1201
- const chat = reactExports.useMemo(() => {
1202
- const cookies = Object.fromEntries(cookiePairs);
1203
- if (cookies.openai_api_key)
1204
- return new LLMChat(new OpenAI(cookies.openai_api_key, cookies.openai_base_url));
1205
- if (cookies.anthropic_api_key)
1206
- return new LLMChat(new Anthropic(cookies.anthropic_api_key, cookies.anthropic_base_url));
1207
- }, [cookiePairs]);
1208
- return /* @__PURE__ */ jsxRuntimeExports.jsx(llmContext.Provider, { value: chat, children });
1209
- }
1210
- function useLLMChat() {
1211
- const chat = reactExports.useContext(llmContext);
1212
- if (!chat)
1213
- throw new Error("No LLM chat available, make sure theres a LLMProvider above");
1214
- return chat;
1215
- }
1216
- function useIsLLMAvailable() {
1217
- return !!reactExports.useContext(llmContext);
1218
- }
1219
- function useLLMConversation(id) {
1220
- const conversation = useLLMChat().getConversation(id);
1221
- if (!conversation)
1222
- throw new Error("No conversation found for id: " + id);
1223
- const [history, setHistory] = reactExports.useState(conversation.history);
1224
- reactExports.useEffect(() => {
1225
- function update() {
1226
- setHistory([...conversation.history]);
1227
- }
1228
- update();
1229
- const subscription = conversation.onChange.event(update);
1230
- return subscription.dispose;
1231
- }, [conversation]);
1232
- return [history, conversation];
1233
- }
1234
- function AIConversation({ conversationId }) {
1235
- const [history, conversation] = useLLMConversation(conversationId);
1236
- const [input, setInput] = reactExports.useState("");
1237
- const onSubmit = reactExports.useCallback(() => {
1238
- setInput((content) => {
1239
- conversation.send(content);
1240
- return "";
1241
- });
1242
- }, [conversation]);
1243
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "chat-container", children: [
1244
- /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "chat-disclaimer", children: [
1245
- "Chat based on ",
1246
- conversation.chat.api.name,
1247
- ". Check for mistakes."
1248
- ] }),
1249
- /* @__PURE__ */ jsxRuntimeExports.jsx("hr", {}),
1250
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "messages-container", children: history.filter(({ role }) => role !== "developer").map((message, index) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
1251
- "div",
1252
- {
1253
- className: clsx("message", message.role === "user" && "user-message"),
1254
- children: [
1255
- message.role === "assistant" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "message-icon", children: /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: "playwright-logo.svg" }) }),
1256
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "message-content", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Markdown, { options: { disableParsingRawHTML: true }, children: message.displayContent ?? message.content }) })
1257
- ]
1258
- },
1259
- "" + index
1260
- )) }),
1261
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "input-form", children: [
1262
- /* @__PURE__ */ jsxRuntimeExports.jsx(
1263
- "textarea",
1264
- {
1265
- name: "content",
1266
- value: input,
1267
- onChange: (e) => setInput(e.target.value),
1268
- onKeyDown: (e) => {
1269
- if (e.key === "Enter" && !e.shiftKey) {
1270
- e.preventDefault();
1271
- onSubmit();
1272
- }
1273
- },
1274
- placeholder: "Ask a question...",
1275
- className: "message-input"
1276
- }
1277
- ),
1278
- conversation.isSending() ? /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "send-button", onClick: (evt) => {
1279
- evt.preventDefault();
1280
- conversation.abortSending();
1281
- }, children: "Cancel" }) : /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "send-button", disabled: !input.trim(), onClick: onSubmit, children: "Send" })
1282
- ] })
1283
- ] });
1284
- }
1285
- async function loadImage(src) {
1286
- const image = new Image();
1287
- if (src) {
1288
- image.src = src;
1289
- await new Promise((f2, r2) => {
1290
- image.onload = f2;
1291
- image.onerror = f2;
1292
- });
1293
- }
1294
- return image;
1295
- }
1296
- const checkerboardStyle = {
1297
- backgroundImage: `linear-gradient(45deg, #80808020 25%, transparent 25%),
1298
- linear-gradient(-45deg, #80808020 25%, transparent 25%),
1299
- linear-gradient(45deg, transparent 75%, #80808020 75%),
1300
- linear-gradient(-45deg, transparent 75%, #80808020 75%)`,
1301
- backgroundSize: "20px 20px",
1302
- backgroundPosition: "0 0, 0 10px, 10px -10px, -10px 0px",
1303
- boxShadow: `rgb(0 0 0 / 10%) 0px 1.8px 1.9px,
1304
- rgb(0 0 0 / 15%) 0px 6.1px 6.3px,
1305
- rgb(0 0 0 / 10%) 0px -2px 4px,
1306
- rgb(0 0 0 / 15%) 0px -6.1px 12px,
1307
- rgb(0 0 0 / 25%) 0px 6px 12px`
1308
- };
1309
- const ImageDiffView = ({ diff, noTargetBlank, hideDetails }) => {
1310
- const [mode, setMode] = reactExports.useState(diff.diff ? "diff" : "actual");
1311
- const [showSxsDiff, setShowSxsDiff] = reactExports.useState(false);
1312
- const [expectedImage, setExpectedImage] = reactExports.useState(null);
1313
- const [expectedImageTitle, setExpectedImageTitle] = reactExports.useState("Expected");
1314
- const [actualImage, setActualImage] = reactExports.useState(null);
1315
- const [diffImage, setDiffImage] = reactExports.useState(null);
1316
- const [measure, ref] = useMeasure();
1317
- reactExports.useEffect(() => {
1318
- (async () => {
1319
- var _a, _b, _c, _d;
1320
- setExpectedImage(await loadImage((_a = diff.expected) == null ? void 0 : _a.attachment.path));
1321
- setExpectedImageTitle(((_b = diff.expected) == null ? void 0 : _b.title) || "Expected");
1322
- setActualImage(await loadImage((_c = diff.actual) == null ? void 0 : _c.attachment.path));
1323
- setDiffImage(await loadImage((_d = diff.diff) == null ? void 0 : _d.attachment.path));
1324
- })();
1325
- }, [diff]);
1326
- const isLoaded = expectedImage && actualImage && diffImage;
1327
- const imageWidth = isLoaded ? Math.max(expectedImage.naturalWidth, actualImage.naturalWidth, 200) : 500;
1328
- const imageHeight = isLoaded ? Math.max(expectedImage.naturalHeight, actualImage.naturalHeight, 200) : 500;
1329
- const scale = Math.min(1, (measure.width - 30) / imageWidth);
1330
- const sxsScale = Math.min(1, (measure.width - 50) / imageWidth / 2);
1331
- const fitWidth = imageWidth * scale;
1332
- const fitHeight = imageHeight * scale;
1333
- const modeStyle = {
1334
- flex: "none",
1335
- margin: "0 10px",
1336
- cursor: "pointer",
1337
- userSelect: "none"
1338
- };
1339
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { "data-testid": "test-result-image-mismatch", style: { display: "flex", flexDirection: "column", alignItems: "center", flex: "auto" }, ref, children: isLoaded && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1340
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { "data-testid": "test-result-image-mismatch-tabs", style: { display: "flex", margin: "10px 0 20px" }, children: [
1341
- diff.diff && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { ...modeStyle, fontWeight: mode === "diff" ? 600 : "initial" }, onClick: () => setMode("diff"), children: "Diff" }),
1342
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { ...modeStyle, fontWeight: mode === "actual" ? 600 : "initial" }, onClick: () => setMode("actual"), children: "Actual" }),
1343
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { ...modeStyle, fontWeight: mode === "expected" ? 600 : "initial" }, onClick: () => setMode("expected"), children: expectedImageTitle }),
1344
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { ...modeStyle, fontWeight: mode === "sxs" ? 600 : "initial" }, onClick: () => setMode("sxs"), children: "Side by side" }),
1345
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { ...modeStyle, fontWeight: mode === "slider" ? 600 : "initial" }, onClick: () => setMode("slider"), children: "Slider" })
1346
- ] }),
1347
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex", justifyContent: "center", flex: "auto", minHeight: fitHeight + 60 }, children: [
1348
- diff.diff && mode === "diff" && /* @__PURE__ */ jsxRuntimeExports.jsx(ImageWithSize, { image: diffImage, alt: "Diff", hideSize: hideDetails, canvasWidth: fitWidth, canvasHeight: fitHeight, scale }),
1349
- diff.diff && mode === "actual" && /* @__PURE__ */ jsxRuntimeExports.jsx(ImageWithSize, { image: actualImage, alt: "Actual", hideSize: hideDetails, canvasWidth: fitWidth, canvasHeight: fitHeight, scale }),
1350
- diff.diff && mode === "expected" && /* @__PURE__ */ jsxRuntimeExports.jsx(ImageWithSize, { image: expectedImage, alt: expectedImageTitle, hideSize: hideDetails, canvasWidth: fitWidth, canvasHeight: fitHeight, scale }),
1351
- diff.diff && mode === "slider" && /* @__PURE__ */ jsxRuntimeExports.jsx(ImageDiffSlider, { expectedImage, actualImage, hideSize: hideDetails, canvasWidth: fitWidth, canvasHeight: fitHeight, scale, expectedTitle: expectedImageTitle }),
1352
- diff.diff && mode === "sxs" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex" }, children: [
1353
- /* @__PURE__ */ jsxRuntimeExports.jsx(ImageWithSize, { image: expectedImage, title: expectedImageTitle, hideSize: hideDetails, canvasWidth: sxsScale * imageWidth, canvasHeight: sxsScale * imageHeight, scale: sxsScale }),
1354
- /* @__PURE__ */ jsxRuntimeExports.jsx(ImageWithSize, { image: showSxsDiff ? diffImage : actualImage, title: showSxsDiff ? "Diff" : "Actual", onClick: () => setShowSxsDiff(!showSxsDiff), hideSize: hideDetails, canvasWidth: sxsScale * imageWidth, canvasHeight: sxsScale * imageHeight, scale: sxsScale })
1355
- ] }),
1356
- !diff.diff && mode === "actual" && /* @__PURE__ */ jsxRuntimeExports.jsx(ImageWithSize, { image: actualImage, title: "Actual", hideSize: hideDetails, canvasWidth: fitWidth, canvasHeight: fitHeight, scale }),
1357
- !diff.diff && mode === "expected" && /* @__PURE__ */ jsxRuntimeExports.jsx(ImageWithSize, { image: expectedImage, title: expectedImageTitle, hideSize: hideDetails, canvasWidth: fitWidth, canvasHeight: fitHeight, scale }),
1358
- !diff.diff && mode === "sxs" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex" }, children: [
1359
- /* @__PURE__ */ jsxRuntimeExports.jsx(ImageWithSize, { image: expectedImage, title: expectedImageTitle, canvasWidth: sxsScale * imageWidth, canvasHeight: sxsScale * imageHeight, scale: sxsScale }),
1360
- /* @__PURE__ */ jsxRuntimeExports.jsx(ImageWithSize, { image: actualImage, title: "Actual", canvasWidth: sxsScale * imageWidth, canvasHeight: sxsScale * imageHeight, scale: sxsScale })
1361
- ] })
1362
- ] }),
1363
- !hideDetails && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { alignSelf: "start", lineHeight: "18px", marginLeft: "15px" }, children: [
1364
- /* @__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 }) }),
1365
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: /* @__PURE__ */ jsxRuntimeExports.jsx("a", { target: noTargetBlank ? "" : "_blank", href: diff.actual.attachment.path, rel: "noreferrer", children: diff.actual.attachment.name }) }),
1366
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: /* @__PURE__ */ jsxRuntimeExports.jsx("a", { target: noTargetBlank ? "" : "_blank", href: diff.expected.attachment.path, rel: "noreferrer", children: diff.expected.attachment.name }) })
1367
- ] })
1368
- ] }) });
1369
- };
1370
- const ImageDiffSlider = ({ expectedImage, actualImage, canvasWidth, canvasHeight, scale, expectedTitle, hideSize }) => {
1371
- const absoluteStyle = {
1372
- position: "absolute",
1373
- top: 0,
1374
- left: 0
1375
- };
1376
- const [slider, setSlider] = reactExports.useState(canvasWidth / 2);
1377
- const sameSize = expectedImage.naturalWidth === actualImage.naturalWidth && expectedImage.naturalHeight === actualImage.naturalHeight;
1378
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { flex: "none", display: "flex", alignItems: "center", flexDirection: "column", userSelect: "none" }, children: [
1379
- !hideSize && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { margin: 5 }, children: [
1380
- !sameSize && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { flex: "none", margin: "0 5px" }, children: "Expected " }),
1381
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: expectedImage.naturalWidth }),
1382
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { flex: "none", margin: "0 5px" }, children: "x" }),
1383
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: expectedImage.naturalHeight }),
1384
- !sameSize && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { flex: "none", margin: "0 5px 0 15px" }, children: "Actual " }),
1385
- !sameSize && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: actualImage.naturalWidth }),
1386
- !sameSize && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { flex: "none", margin: "0 5px" }, children: "x" }),
1387
- !sameSize && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: actualImage.naturalHeight })
1388
- ] }),
1389
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { position: "relative", width: canvasWidth, height: canvasHeight, margin: 15, ...checkerboardStyle }, children: [
1390
- /* @__PURE__ */ jsxRuntimeExports.jsx(
1391
- ResizeView,
1392
- {
1393
- orientation: "horizontal",
1394
- offsets: [slider],
1395
- setOffsets: (offsets) => setSlider(offsets[0]),
1396
- resizerColor: "#57606a80",
1397
- resizerWidth: 6
1398
- }
1399
- ),
1400
- /* @__PURE__ */ jsxRuntimeExports.jsx("img", { alt: expectedTitle, style: {
1401
- width: expectedImage.naturalWidth * scale,
1402
- height: expectedImage.naturalHeight * scale
1403
- }, draggable: "false", src: expectedImage.src }),
1404
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { ...absoluteStyle, bottom: 0, overflow: "hidden", width: slider, ...checkerboardStyle }, children: /* @__PURE__ */ jsxRuntimeExports.jsx("img", { alt: "Actual", style: {
1405
- width: actualImage.naturalWidth * scale,
1406
- height: actualImage.naturalHeight * scale
1407
- }, draggable: "false", src: actualImage.src }) })
1408
- ] })
1409
- ] });
1410
- };
1411
- const ImageWithSize = ({ image, title, alt, hideSize, canvasWidth, canvasHeight, scale, onClick }) => {
1412
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { flex: "none", display: "flex", alignItems: "center", flexDirection: "column" }, children: [
1413
- !hideSize && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { margin: 5 }, children: [
1414
- title && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { flex: "none", margin: "0 5px" }, children: title }),
1415
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: image.naturalWidth }),
1416
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { flex: "none", margin: "0 5px" }, children: "x" }),
1417
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: image.naturalHeight })
1418
- ] }),
1419
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { display: "flex", flex: "none", width: canvasWidth, height: canvasHeight, margin: 15, ...checkerboardStyle }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
1420
- "img",
1421
- {
1422
- width: image.naturalWidth * scale,
1423
- height: image.naturalHeight * scale,
1424
- alt: title || alt,
1425
- style: { cursor: onClick ? "pointer" : "initial" },
1426
- draggable: "false",
1427
- src: image.src,
1428
- onClick
1429
- }
1430
- ) })
1431
- ] });
1432
- };
1433
- function isTextualMimeType(mimeType) {
1434
- return !!mimeType.match(/^(text\/.*?|application\/(json|(x-)?javascript|xml.*?|ecmascript|graphql|x-www-form-urlencoded)|image\/svg(\+xml)?|application\/.*?(\+json|\+xml))(;\s*charset=.*)?$/);
1435
- }
1436
- const Expandable = ({ title, children, setExpanded, expanded, expandOnTitleClick }) => {
1437
- const id = reactExports.useId();
1438
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: clsx("expandable", expanded && "expanded"), children: [
1439
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
1440
- "div",
1441
- {
1442
- role: "button",
1443
- "aria-expanded": expanded,
1444
- "aria-controls": id,
1445
- className: "expandable-title",
1446
- onClick: () => expandOnTitleClick && setExpanded(!expanded),
1447
- children: [
1448
- /* @__PURE__ */ jsxRuntimeExports.jsx(
1449
- "div",
1450
- {
1451
- className: clsx("codicon", expanded ? "codicon-chevron-down" : "codicon-chevron-right"),
1452
- style: { cursor: "pointer", color: "var(--vscode-foreground)", marginLeft: "5px" },
1453
- onClick: () => !expandOnTitleClick && setExpanded(!expanded)
1454
- }
1455
- ),
1456
- title
1457
- ]
1458
- }
1459
- ),
1460
- expanded && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { id, role: "region", style: { marginLeft: 25 }, children })
1461
- ] });
1462
- };
1463
- function linkifyText(description) {
1464
- const result = [];
1465
- let currentIndex = 0;
1466
- let match;
1467
- while ((match = kWebLinkRe.exec(description)) !== null) {
1468
- const stringBeforeMatch = description.substring(currentIndex, match.index);
1469
- if (stringBeforeMatch)
1470
- result.push(stringBeforeMatch);
1471
- const value = match[0];
1472
- result.push(renderLink(value));
1473
- currentIndex = match.index + value.length;
1474
- }
1475
- const stringAfterMatches = description.substring(currentIndex);
1476
- if (stringAfterMatches)
1477
- result.push(stringAfterMatches);
1478
- return result;
1479
- }
1480
- function renderLink(text) {
1481
- let link = text;
1482
- if (link.startsWith("www."))
1483
- link = "https://" + link;
1484
- return /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: link, target: "_blank", rel: "noopener noreferrer", children: text });
1485
- }
1486
- const ExpandableAttachment = ({ attachment, reveal }) => {
1487
- const [expanded, setExpanded] = reactExports.useState(false);
1488
- const [attachmentText, setAttachmentText] = reactExports.useState(null);
1489
- const [placeholder, setPlaceholder] = reactExports.useState(null);
1490
- const [flash, triggerFlash] = useFlash();
1491
- const ref = reactExports.useRef(null);
1492
- const isTextAttachment = isTextualMimeType(attachment.contentType);
1493
- const hasContent = !!attachment.sha1 || !!attachment.path;
1494
- reactExports.useEffect(() => {
1495
- var _a;
1496
- if (reveal) {
1497
- (_a = ref.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth" });
1498
- return triggerFlash();
1499
- }
1500
- }, [reveal, triggerFlash]);
1501
- reactExports.useEffect(() => {
1502
- if (expanded && attachmentText === null && placeholder === null) {
1503
- setPlaceholder("Loading ...");
1504
- fetch(attachmentURL(attachment)).then((response) => response.text()).then((text) => {
1505
- setAttachmentText(text);
1506
- setPlaceholder(null);
1507
- }).catch((e) => {
1508
- setPlaceholder("Failed to load: " + e.message);
1509
- });
1510
- }
1511
- }, [expanded, attachmentText, placeholder, attachment]);
1512
- const snippetHeight = reactExports.useMemo(() => {
1513
- const lineCount = attachmentText ? attachmentText.split("\n").length : 0;
1514
- return Math.min(Math.max(5, lineCount), 20) * lineHeight;
1515
- }, [attachmentText]);
1516
- const title = /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { style: { marginLeft: 5 }, ref, "aria-label": attachment.name, children: [
1517
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: linkifyText(attachment.name) }),
1518
- hasContent && /* @__PURE__ */ jsxRuntimeExports.jsx("a", { style: { marginLeft: 5 }, href: downloadURL(attachment), children: "download" })
1519
- ] });
1520
- if (!isTextAttachment || !hasContent)
1521
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { marginLeft: 20 }, children: title });
1522
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: clsx(flash && "yellow-flash"), children: [
1523
- /* @__PURE__ */ jsxRuntimeExports.jsx(Expandable, { title, expanded, setExpanded, expandOnTitleClick: true, children: placeholder && /* @__PURE__ */ jsxRuntimeExports.jsx("i", { children: placeholder }) }),
1524
- expanded && attachmentText !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "vbox", style: { height: snippetHeight }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
1525
- CodeMirrorWrapper,
1526
- {
1527
- text: attachmentText,
1528
- readOnly: true,
1529
- mimeType: attachment.contentType,
1530
- linkify: true,
1531
- lineNumbers: true,
1532
- wrapLines: false
1533
- }
1534
- ) })
1535
- ] });
1536
- };
1537
- const AttachmentsTab = ({ model, revealedAttachment }) => {
1538
- const { diffMap, screenshots, attachments } = reactExports.useMemo(() => {
1539
- const attachments2 = new Set((model == null ? void 0 : model.visibleAttachments) ?? []);
1540
- const screenshots2 = /* @__PURE__ */ new Set();
1541
- const diffMap2 = /* @__PURE__ */ new Map();
1542
- for (const attachment of attachments2) {
1543
- if (!attachment.path && !attachment.sha1)
1544
- continue;
1545
- const match = attachment.name.match(/^(.*)-(expected|actual|diff)\.png$/);
1546
- if (match) {
1547
- const name = match[1];
1548
- const type = match[2];
1549
- const entry = diffMap2.get(name) || { expected: void 0, actual: void 0, diff: void 0 };
1550
- entry[type] = attachment;
1551
- diffMap2.set(name, entry);
1552
- attachments2.delete(attachment);
1553
- } else if (attachment.contentType.startsWith("image/")) {
1554
- screenshots2.add(attachment);
1555
- attachments2.delete(attachment);
1556
- }
1557
- }
1558
- return { diffMap: diffMap2, attachments: attachments2, screenshots: screenshots2 };
1559
- }, [model]);
1560
- if (!diffMap.size && !screenshots.size && !attachments.size)
1561
- return /* @__PURE__ */ jsxRuntimeExports.jsx(PlaceholderPanel, { text: "No attachments" });
1562
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "attachments-tab", children: [
1563
- [...diffMap.values()].map(({ expected, actual, diff }) => {
1564
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1565
- expected && actual && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "attachments-section", children: "Image diff" }),
1566
- expected && actual && /* @__PURE__ */ jsxRuntimeExports.jsx(ImageDiffView, { noTargetBlank: true, diff: {
1567
- name: "Image diff",
1568
- expected: { attachment: { ...expected, path: downloadURL(expected) }, title: "Expected" },
1569
- actual: { attachment: { ...actual, path: downloadURL(actual) } },
1570
- diff: diff ? { attachment: { ...diff, path: downloadURL(diff) } } : void 0
1571
- } })
1572
- ] });
1573
- }),
1574
- screenshots.size ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "attachments-section", children: "Screenshots" }) : void 0,
1575
- [...screenshots.values()].map((a2, i2) => {
1576
- const url = attachmentURL(a2);
1577
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "attachment-item", children: [
1578
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: /* @__PURE__ */ jsxRuntimeExports.jsx("img", { draggable: "false", src: url }) }),
1579
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: /* @__PURE__ */ jsxRuntimeExports.jsx("a", { target: "_blank", href: url, rel: "noreferrer", children: a2.name }) })
1580
- ] }, `screenshot-${i2}`);
1581
- }),
1582
- attachments.size ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "attachments-section", children: "Attachments" }) : void 0,
1583
- [...attachments.values()].map((a2, i2) => {
1584
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "attachment-item", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
1585
- ExpandableAttachment,
1586
- {
1587
- attachment: a2,
1588
- reveal: !!revealedAttachment && isEqualAttachment(a2, revealedAttachment[0]) ? revealedAttachment : void 0
1589
- }
1590
- ) }, attachmentKey(a2, i2));
1591
- })
1592
- ] });
1593
- };
1594
- function isEqualAttachment(a2, b2) {
1595
- return a2.name === b2.name && a2.path === b2.path && a2.sha1 === b2.sha1;
1596
- }
1597
- function attachmentURL(attachment, queryParams = {}) {
1598
- const params = new URLSearchParams(queryParams);
1599
- if (attachment.sha1) {
1600
- params.set("trace", attachment.traceUrl);
1601
- return "sha1/" + attachment.sha1 + "?" + params.toString();
1602
- }
1603
- params.set("path", attachment.path);
1604
- return "file?" + params.toString();
1605
- }
1606
- function downloadURL(attachment) {
1607
- const params = { dn: attachment.name };
1608
- if (attachment.contentType)
1609
- params.dct = attachment.contentType;
1610
- return attachmentURL(attachment, params);
1611
- }
1612
- function attachmentKey(attachment, index) {
1613
- return index + "-" + (attachment.sha1 ? `sha1-` + attachment.sha1 : `path-` + attachment.path);
1614
- }
1615
- const CopyPromptButton = ({ prompt }) => {
1616
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
1617
- CopyToClipboardTextButton,
1618
- {
1619
- value: prompt,
1620
- description: "Copy prompt",
1621
- copiedDescription: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1622
- "Copied ",
1623
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "codicon codicon-copy", style: { marginLeft: "5px" } })
1624
- ] }),
1625
- style: { width: "120px", justifyContent: "center" }
1626
- }
1627
- );
1628
- };
1629
- function useErrorsTabModel(model) {
1630
- return reactExports.useMemo(() => {
1631
- if (!model)
1632
- return { errors: /* @__PURE__ */ new Map() };
1633
- const errors = /* @__PURE__ */ new Map();
1634
- for (const error of model.errorDescriptors)
1635
- errors.set(error.message, error);
1636
- return { errors };
1637
- }, [model]);
1638
- }
1639
- function Error$1({ message, error, errorId, sdkLanguage, revealInSource }) {
1640
- var _a;
1641
- const [showLLM, setShowLLM] = reactExports.useState(false);
1642
- const llmAvailable = useIsLLMAvailable();
1643
- let location;
1644
- let longLocation;
1645
- const stackFrame = (_a = error.stack) == null ? void 0 : _a[0];
1646
- if (stackFrame) {
1647
- const file = stackFrame.file.replace(/.*[/\\](.*)/, "$1");
1648
- location = file + ":" + stackFrame.line;
1649
- longLocation = stackFrame.file + ":" + stackFrame.line;
1650
- }
1651
- const prompt = useAsyncMemo(async () => {
1652
- if (!error.prompt)
1653
- return;
1654
- const response = await fetch(attachmentURL(error.prompt));
1655
- return await response.text();
1656
- }, [error], void 0);
1657
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex", flexDirection: "column", overflowX: "clip" }, children: [
1658
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "hbox", style: {
1659
- alignItems: "center",
1660
- padding: "5px 10px",
1661
- minHeight: 36,
1662
- fontWeight: "bold",
1663
- color: "var(--vscode-errorForeground)",
1664
- flex: 0
1665
- }, children: [
1666
- error.action && renderAction(error.action, { sdkLanguage }),
1667
- location && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "action-location", children: [
1668
- "@ ",
1669
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { title: longLocation, onClick: () => revealInSource(error), children: location })
1670
- ] }),
1671
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { position: "absolute", right: "5px" }, children: prompt && (llmAvailable ? /* @__PURE__ */ jsxRuntimeExports.jsx(FixWithAIButton, { conversationId: errorId, onChange: setShowLLM, value: showLLM, prompt }) : /* @__PURE__ */ jsxRuntimeExports.jsx(CopyPromptButton, { prompt })) })
1672
- ] }),
1673
- /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorMessage, { error: message }),
1674
- showLLM && /* @__PURE__ */ jsxRuntimeExports.jsx(AIConversation, { conversationId: errorId })
1675
- ] });
1676
- }
1677
- function FixWithAIButton({ conversationId, value, onChange, prompt }) {
1678
- const chat = useLLMChat();
1679
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
1680
- ToolbarButton,
1681
- {
1682
- onClick: () => {
1683
- if (!chat.getConversation(conversationId)) {
1684
- const conversation = chat.startConversation(conversationId, [
1685
- `My Playwright test failed. What's going wrong?`,
1686
- `Please give me a suggestion how to fix it, and then explain what went wrong. Be very concise and apply Playwright best practices.`,
1687
- `Don't include many headings in your output. Make sure what you're saying is correct, and take into account whether there might be a bug in the app.`
1688
- ].join("\n"));
1689
- let displayPrompt = `Help me with the error above.`;
1690
- const hasDiff = prompt.includes("Local changes:");
1691
- const hasSnapshot = prompt.includes("Page snapshot:");
1692
- if (hasDiff)
1693
- displayPrompt += ` Take the code diff${hasSnapshot ? " and page snapshot" : ""} into account.`;
1694
- else if (hasSnapshot)
1695
- displayPrompt += ` Take the page snapshot into account.`;
1696
- conversation.send(prompt, displayPrompt);
1697
- }
1698
- onChange((v2) => !v2);
1699
- },
1700
- style: { width: "96px", justifyContent: "center" },
1701
- title: "Fix with AI",
1702
- className: "copy-to-clipboard-text-button",
1703
- children: value ? "Hide AI" : "Fix with AI"
1704
- }
1705
- );
1706
- }
1707
- const ErrorsTab = ({ errorsModel, sdkLanguage, revealInSource, wallTime }) => {
1708
- if (!errorsModel.errors.size)
1709
- return /* @__PURE__ */ jsxRuntimeExports.jsx(PlaceholderPanel, { text: "No errors" });
1710
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fill", style: { overflow: "auto" }, children: [...errorsModel.errors.entries()].map(([message, error]) => {
1711
- const errorId = `error-${wallTime}-${message}`;
1712
- return /* @__PURE__ */ jsxRuntimeExports.jsx(Error$1, { errorId, message, error, revealInSource, sdkLanguage }, errorId);
1713
- }) });
1714
- };
1715
- const tileSize = { width: 200, height: 45 };
1716
- const frameMargin = 2.5;
1717
- const rowHeight = tileSize.height + frameMargin * 2;
1718
- const FilmStrip = ({ model, boundaries, previewPoint }) => {
1719
- var _a, _b;
1720
- const [measure, ref] = useMeasure();
1721
- const lanesRef = reactExports.useRef(null);
1722
- let pageIndex = 0;
1723
- if (lanesRef.current && previewPoint) {
1724
- const bounds = lanesRef.current.getBoundingClientRect();
1725
- pageIndex = (previewPoint.clientY - bounds.top + lanesRef.current.scrollTop) / rowHeight | 0;
1726
- }
1727
- const screencastFrames = (_b = (_a = model == null ? void 0 : model.pages) == null ? void 0 : _a[pageIndex]) == null ? void 0 : _b.screencastFrames;
1728
- let previewImage = void 0;
1729
- let previewSize = void 0;
1730
- if (previewPoint !== void 0 && screencastFrames && screencastFrames.length) {
1731
- const previewTime = boundaries.minimum + (boundaries.maximum - boundaries.minimum) * previewPoint.x / measure.width;
1732
- previewImage = screencastFrames[upperBound(screencastFrames, previewTime, timeComparator) - 1];
1733
- const fitInto = {
1734
- width: Math.min(800, window.innerWidth / 2 | 0),
1735
- height: Math.min(800, window.innerHeight / 2 | 0)
1736
- };
1737
- previewSize = previewImage ? inscribe({ width: previewImage.width, height: previewImage.height }, fitInto) : void 0;
1738
- }
1739
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "film-strip", ref, children: [
1740
- /* @__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(
1741
- FilmStripLane,
1742
- {
1743
- boundaries,
1744
- page,
1745
- width: measure.width
1746
- },
1747
- index
1748
- ) : null) }),
1749
- (previewPoint == null ? void 0 : previewPoint.x) !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "film-strip-hover", style: {
1750
- top: measure.bottom + 5,
1751
- left: Math.min(previewPoint.x, measure.width - (previewSize ? previewSize.width : 0) - 10)
1752
- }, children: [
1753
- previewPoint.action && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "film-strip-hover-title", children: renderAction(previewPoint.action, previewPoint) }),
1754
- previewImage && previewSize && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { width: previewSize.width, height: previewSize.height }, children: /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: `sha1/${previewImage.sha1}`, width: previewSize.width, height: previewSize.height }) })
1755
- ] })
1756
- ] });
1757
- };
1758
- const FilmStripLane = ({ boundaries, page, width }) => {
1759
- const viewportSize = { width: 0, height: 0 };
1760
- const screencastFrames = page.screencastFrames;
1761
- for (const frame of screencastFrames) {
1762
- viewportSize.width = Math.max(viewportSize.width, frame.width);
1763
- viewportSize.height = Math.max(viewportSize.height, frame.height);
1764
- }
1765
- const frameSize = inscribe(viewportSize, tileSize);
1766
- const startTime = screencastFrames[0].timestamp;
1767
- const endTime = screencastFrames[screencastFrames.length - 1].timestamp;
1768
- const boundariesDuration = boundaries.maximum - boundaries.minimum;
1769
- const gapLeft = (startTime - boundaries.minimum) / boundariesDuration * width;
1770
- const gapRight = (boundaries.maximum - endTime) / boundariesDuration * width;
1771
- const effectiveWidth = (endTime - startTime) / boundariesDuration * width;
1772
- const frameCount = effectiveWidth / (frameSize.width + 2 * frameMargin) | 0;
1773
- const frameDuration = (endTime - startTime) / frameCount;
1774
- const frames = [];
1775
- for (let i2 = 0; startTime && frameDuration && i2 < frameCount; ++i2) {
1776
- const time = startTime + frameDuration * i2;
1777
- const index = upperBound(screencastFrames, time, timeComparator) - 1;
1778
- frames.push(/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "film-strip-frame", style: {
1779
- width: frameSize.width,
1780
- height: frameSize.height,
1781
- backgroundImage: `url(sha1/${screencastFrames[index].sha1})`,
1782
- backgroundSize: `${frameSize.width}px ${frameSize.height}px`,
1783
- margin: frameMargin,
1784
- marginRight: frameMargin
1785
- } }, i2));
1786
- }
1787
- frames.push(/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "film-strip-frame", style: {
1788
- width: frameSize.width,
1789
- height: frameSize.height,
1790
- backgroundImage: `url(sha1/${screencastFrames[screencastFrames.length - 1].sha1})`,
1791
- backgroundSize: `${frameSize.width}px ${frameSize.height}px`,
1792
- margin: frameMargin,
1793
- marginRight: frameMargin
1794
- } }, frames.length));
1795
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "film-strip-lane", style: {
1796
- marginLeft: gapLeft + "px",
1797
- marginRight: gapRight + "px"
1798
- }, children: frames });
1799
- };
1800
- function timeComparator(time, frame) {
1801
- return time - frame.timestamp;
1802
- }
1803
- function inscribe(object, area) {
1804
- const scale = Math.max(object.width / area.width, object.height / area.height);
1805
- return {
1806
- width: object.width / scale | 0,
1807
- height: object.height / scale | 0
1808
- };
1809
- }
1810
- const Timeline = ({ model, boundaries, consoleEntries, onSelected, highlightedAction, highlightedEntry, highlightedConsoleEntry, selectedTime, setSelectedTime, sdkLanguage }) => {
1811
- const [measure, ref] = useMeasure();
1812
- const [dragWindow, setDragWindow] = reactExports.useState();
1813
- const [previewPoint, setPreviewPoint] = reactExports.useState();
1814
- const { offsets, curtainLeft, curtainRight } = reactExports.useMemo(() => {
1815
- let activeWindow = selectedTime || boundaries;
1816
- if (dragWindow && dragWindow.startX !== dragWindow.endX) {
1817
- const time1 = positionToTime(measure.width, boundaries, dragWindow.startX);
1818
- const time2 = positionToTime(measure.width, boundaries, dragWindow.endX);
1819
- activeWindow = { minimum: Math.min(time1, time2), maximum: Math.max(time1, time2) };
1820
- }
1821
- const curtainLeft2 = timeToPosition(measure.width, boundaries, activeWindow.minimum);
1822
- const maxRight = timeToPosition(measure.width, boundaries, boundaries.maximum);
1823
- const curtainRight2 = maxRight - timeToPosition(measure.width, boundaries, activeWindow.maximum);
1824
- return { offsets: calculateDividerOffsets(measure.width, boundaries), curtainLeft: curtainLeft2, curtainRight: curtainRight2 };
1825
- }, [selectedTime, boundaries, dragWindow, measure]);
1826
- const bars = reactExports.useMemo(() => {
1827
- const bars2 = [];
1828
- for (const entry of (model == null ? void 0 : model.actions) || []) {
1829
- if (entry.class === "Test")
1830
- continue;
1831
- bars2.push({
1832
- action: entry,
1833
- leftTime: entry.startTime,
1834
- rightTime: entry.endTime || boundaries.maximum,
1835
- leftPosition: timeToPosition(measure.width, boundaries, entry.startTime),
1836
- rightPosition: timeToPosition(measure.width, boundaries, entry.endTime || boundaries.maximum),
1837
- active: false,
1838
- error: !!entry.error
1839
- });
1840
- }
1841
- for (const resource of (model == null ? void 0 : model.resources) || []) {
1842
- const startTime = resource._monotonicTime;
1843
- const endTime = resource._monotonicTime + resource.time;
1844
- bars2.push({
1845
- resource,
1846
- leftTime: startTime,
1847
- rightTime: endTime,
1848
- leftPosition: timeToPosition(measure.width, boundaries, startTime),
1849
- rightPosition: timeToPosition(measure.width, boundaries, endTime),
1850
- active: false,
1851
- error: false
1852
- });
1853
- }
1854
- for (const consoleMessage of consoleEntries || []) {
1855
- bars2.push({
1856
- consoleMessage,
1857
- leftTime: consoleMessage.timestamp,
1858
- rightTime: consoleMessage.timestamp,
1859
- leftPosition: timeToPosition(measure.width, boundaries, consoleMessage.timestamp),
1860
- rightPosition: timeToPosition(measure.width, boundaries, consoleMessage.timestamp),
1861
- active: false,
1862
- error: consoleMessage.isError
1863
- });
1864
- }
1865
- return bars2;
1866
- }, [model, consoleEntries, boundaries, measure]);
1867
- reactExports.useMemo(() => {
1868
- for (const bar of bars) {
1869
- if (highlightedAction)
1870
- bar.active = bar.action === highlightedAction;
1871
- else if (highlightedEntry)
1872
- bar.active = bar.resource === highlightedEntry;
1873
- else if (highlightedConsoleEntry)
1874
- bar.active = bar.consoleMessage === highlightedConsoleEntry;
1875
- else
1876
- bar.active = false;
1877
- }
1878
- }, [bars, highlightedAction, highlightedEntry, highlightedConsoleEntry]);
1879
- const onMouseDown = reactExports.useCallback((event) => {
1880
- setPreviewPoint(void 0);
1881
- if (!ref.current)
1882
- return;
1883
- const x2 = event.clientX - ref.current.getBoundingClientRect().left;
1884
- const time = positionToTime(measure.width, boundaries, x2);
1885
- const leftX = selectedTime ? timeToPosition(measure.width, boundaries, selectedTime.minimum) : 0;
1886
- const rightX = selectedTime ? timeToPosition(measure.width, boundaries, selectedTime.maximum) : 0;
1887
- if (selectedTime && Math.abs(x2 - leftX) < 10) {
1888
- setDragWindow({ startX: rightX, endX: x2, type: "resize" });
1889
- } else if (selectedTime && Math.abs(x2 - rightX) < 10) {
1890
- setDragWindow({ startX: leftX, endX: x2, type: "resize" });
1891
- } else if (selectedTime && time > selectedTime.minimum && time < selectedTime.maximum && event.clientY - ref.current.getBoundingClientRect().top < 20) {
1892
- setDragWindow({ startX: leftX, endX: rightX, pivot: x2, type: "move" });
1893
- } else {
1894
- setDragWindow({ startX: x2, endX: x2, type: "resize" });
1895
- }
1896
- }, [boundaries, measure, ref, selectedTime]);
1897
- const onGlassPaneMouseMove = reactExports.useCallback((event) => {
1898
- if (!ref.current)
1899
- return;
1900
- const x2 = event.clientX - ref.current.getBoundingClientRect().left;
1901
- const time = positionToTime(measure.width, boundaries, x2);
1902
- const action = model == null ? void 0 : model.actions.findLast((action2) => action2.startTime <= time);
1903
- if (!event.buttons) {
1904
- setDragWindow(void 0);
1905
- return;
1906
- }
1907
- if (action)
1908
- onSelected(action);
1909
- if (!dragWindow)
1910
- return;
1911
- let newDragWindow = dragWindow;
1912
- if (dragWindow.type === "resize") {
1913
- newDragWindow = { ...dragWindow, endX: x2 };
1914
- } else {
1915
- const delta = x2 - dragWindow.pivot;
1916
- let startX = dragWindow.startX + delta;
1917
- let endX = dragWindow.endX + delta;
1918
- if (startX < 0) {
1919
- startX = 0;
1920
- endX = startX + (dragWindow.endX - dragWindow.startX);
1921
- }
1922
- if (endX > measure.width) {
1923
- endX = measure.width;
1924
- startX = endX - (dragWindow.endX - dragWindow.startX);
1925
- }
1926
- newDragWindow = { ...dragWindow, startX, endX, pivot: x2 };
1927
- }
1928
- setDragWindow(newDragWindow);
1929
- const time1 = positionToTime(measure.width, boundaries, newDragWindow.startX);
1930
- const time2 = positionToTime(measure.width, boundaries, newDragWindow.endX);
1931
- if (time1 !== time2)
1932
- setSelectedTime({ minimum: Math.min(time1, time2), maximum: Math.max(time1, time2) });
1933
- }, [boundaries, dragWindow, measure, model, onSelected, ref, setSelectedTime]);
1934
- const onGlassPaneMouseUp = reactExports.useCallback(() => {
1935
- setPreviewPoint(void 0);
1936
- if (!dragWindow)
1937
- return;
1938
- if (dragWindow.startX !== dragWindow.endX) {
1939
- const time1 = positionToTime(measure.width, boundaries, dragWindow.startX);
1940
- const time2 = positionToTime(measure.width, boundaries, dragWindow.endX);
1941
- setSelectedTime({ minimum: Math.min(time1, time2), maximum: Math.max(time1, time2) });
1942
- } else {
1943
- const time = positionToTime(measure.width, boundaries, dragWindow.startX);
1944
- const action = model == null ? void 0 : model.actions.findLast((action2) => action2.startTime <= time);
1945
- if (action)
1946
- onSelected(action);
1947
- setSelectedTime(void 0);
1948
- }
1949
- setDragWindow(void 0);
1950
- }, [boundaries, dragWindow, measure, model, setSelectedTime, onSelected]);
1951
- const onMouseMove = reactExports.useCallback((event) => {
1952
- if (!ref.current)
1953
- return;
1954
- const x2 = event.clientX - ref.current.getBoundingClientRect().left;
1955
- const time = positionToTime(measure.width, boundaries, x2);
1956
- const action = model == null ? void 0 : model.actions.findLast((action2) => action2.startTime <= time);
1957
- setPreviewPoint({ x: x2, clientY: event.clientY, action, sdkLanguage });
1958
- }, [boundaries, measure, model, ref, sdkLanguage]);
1959
- const onMouseLeave = reactExports.useCallback(() => {
1960
- setPreviewPoint(void 0);
1961
- }, []);
1962
- const onPaneDoubleClick = reactExports.useCallback(() => {
1963
- setSelectedTime(void 0);
1964
- }, [setSelectedTime]);
1965
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { flex: "none", borderBottom: "1px solid var(--vscode-panel-border)" }, children: [
1966
- !!dragWindow && /* @__PURE__ */ jsxRuntimeExports.jsx(
1967
- GlassPane,
1968
- {
1969
- cursor: (dragWindow == null ? void 0 : dragWindow.type) === "resize" ? "ew-resize" : "grab",
1970
- onPaneMouseUp: onGlassPaneMouseUp,
1971
- onPaneMouseMove: onGlassPaneMouseMove,
1972
- onPaneDoubleClick
1973
- }
1974
- ),
1975
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
1976
- "div",
1977
- {
1978
- ref,
1979
- className: "timeline-view",
1980
- onMouseDown,
1981
- onMouseMove,
1982
- onMouseLeave,
1983
- children: [
1984
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-grid", children: offsets.map((offset, index) => {
1985
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-divider", style: { left: offset.position + "px" }, children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-time", children: msToString(offset.time - boundaries.minimum) }) }, index);
1986
- }) }),
1987
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { height: 8 } }),
1988
- /* @__PURE__ */ jsxRuntimeExports.jsx(FilmStrip, { model, boundaries, previewPoint }),
1989
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-bars", children: bars.map((bar, index) => {
1990
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
1991
- "div",
1992
- {
1993
- className: clsx(
1994
- "timeline-bar",
1995
- bar.action && "action",
1996
- bar.resource && "network",
1997
- bar.consoleMessage && "console-message",
1998
- bar.active && "active",
1999
- bar.error && "error"
2000
- ),
2001
- style: {
2002
- left: bar.leftPosition,
2003
- width: Math.max(5, bar.rightPosition - bar.leftPosition),
2004
- top: barTop(bar),
2005
- bottom: 0
2006
- }
2007
- },
2008
- index
2009
- );
2010
- }) }),
2011
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-marker", style: {
2012
- display: previewPoint !== void 0 ? "block" : "none",
2013
- left: ((previewPoint == null ? void 0 : previewPoint.x) || 0) + "px"
2014
- } }),
2015
- selectedTime && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "timeline-window", children: [
2016
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-window-curtain left", style: { width: curtainLeft } }),
2017
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-window-resizer", style: { left: -5 } }),
2018
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-window-center", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-window-drag" }) }),
2019
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-window-resizer", style: { left: 5 } }),
2020
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-window-curtain right", style: { width: curtainRight } })
2021
- ] })
2022
- ]
2023
- }
2024
- )
2025
- ] });
2026
- };
2027
- function calculateDividerOffsets(clientWidth, boundaries) {
2028
- const minimumGap = 64;
2029
- let dividerCount = clientWidth / minimumGap;
2030
- const boundarySpan = boundaries.maximum - boundaries.minimum;
2031
- const pixelsPerMillisecond = clientWidth / boundarySpan;
2032
- let sectionTime = boundarySpan / dividerCount;
2033
- const logSectionTime = Math.ceil(Math.log(sectionTime) / Math.LN10);
2034
- sectionTime = Math.pow(10, logSectionTime);
2035
- if (sectionTime * pixelsPerMillisecond >= 5 * minimumGap)
2036
- sectionTime = sectionTime / 5;
2037
- if (sectionTime * pixelsPerMillisecond >= 2 * minimumGap)
2038
- sectionTime = sectionTime / 2;
2039
- const firstDividerTime = boundaries.minimum;
2040
- let lastDividerTime = boundaries.maximum;
2041
- lastDividerTime += minimumGap / pixelsPerMillisecond;
2042
- dividerCount = Math.ceil((lastDividerTime - firstDividerTime) / sectionTime);
2043
- if (!sectionTime)
2044
- dividerCount = 0;
2045
- const offsets = [];
2046
- for (let i2 = 0; i2 < dividerCount; ++i2) {
2047
- const time = firstDividerTime + sectionTime * i2;
2048
- offsets.push({ position: timeToPosition(clientWidth, boundaries, time), time });
2049
- }
2050
- return offsets;
2051
- }
2052
- function timeToPosition(clientWidth, boundaries, time) {
2053
- return (time - boundaries.minimum) / (boundaries.maximum - boundaries.minimum) * clientWidth;
2054
- }
2055
- function positionToTime(clientWidth, boundaries, x2) {
2056
- return x2 / clientWidth * (boundaries.maximum - boundaries.minimum) + boundaries.minimum;
2057
- }
2058
- function barTop(bar) {
2059
- return bar.resource ? 25 : 20;
2060
- }
2061
- const MetadataView = ({ model }) => {
2062
- var _a, _b;
2063
- if (!model)
2064
- return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, {});
2065
- const wallTime = model.wallTime !== void 0 ? new Date(model.wallTime).toLocaleString(void 0, { timeZoneName: "short" }) : void 0;
2066
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { "data-testid": "metadata-view", className: "vbox", style: { flexShrink: 0 }, children: [
2067
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-section", style: { paddingTop: 2 }, children: "Time" }),
2068
- !!wallTime && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
2069
- "start time:",
2070
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value datetime", title: wallTime, children: wallTime })
2071
- ] }),
2072
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
2073
- "duration:",
2074
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value number", title: msToString(model.endTime - model.startTime), children: msToString(model.endTime - model.startTime) })
2075
- ] }),
2076
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-section", children: "Browser" }),
2077
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
2078
- "engine:",
2079
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value string", title: model.browserName, children: model.browserName })
2080
- ] }),
2081
- model.channel && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
2082
- "channel:",
2083
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value string", title: model.channel, children: model.channel })
2084
- ] }),
2085
- model.platform && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
2086
- "platform:",
2087
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value string", title: model.platform, children: model.platform })
2088
- ] }),
2089
- model.options.userAgent && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
2090
- "user agent:",
2091
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value datetime", title: model.options.userAgent, children: model.options.userAgent })
2092
- ] }),
2093
- model.options.baseURL && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
2094
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-section", style: { paddingTop: 2 }, children: "Config" }),
2095
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
2096
- "baseURL:",
2097
- /* @__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 })
2098
- ] })
2099
- ] }),
2100
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-section", children: "Viewport" }),
2101
- model.options.viewport && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
2102
- "width:",
2103
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value number", title: String(!!((_a = model.options.viewport) == null ? void 0 : _a.width)), children: model.options.viewport.width })
2104
- ] }),
2105
- model.options.viewport && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
2106
- "height:",
2107
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value number", title: String(!!((_b = model.options.viewport) == null ? void 0 : _b.height)), children: model.options.viewport.height })
2108
- ] }),
2109
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
2110
- "is mobile:",
2111
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value boolean", title: String(!!model.options.isMobile), children: String(!!model.options.isMobile) })
2112
- ] }),
2113
- model.options.deviceScaleFactor && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
2114
- "device scale:",
2115
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value number", title: String(model.options.deviceScaleFactor), children: String(model.options.deviceScaleFactor) })
2116
- ] }),
2117
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-section", children: "Counts" }),
2118
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
2119
- "pages:",
2120
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value number", children: model.pages.length })
2121
- ] }),
2122
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
2123
- "actions:",
2124
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value number", children: model.actions.length })
2125
- ] }),
2126
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
2127
- "events:",
2128
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value number", children: model.events.length })
2129
- ] })
2130
- ] });
2131
- };
2132
- const AnnotationsTab = ({ annotations }) => {
2133
- if (!annotations.length)
2134
- return /* @__PURE__ */ jsxRuntimeExports.jsx(PlaceholderPanel, { text: "No annotations" });
2135
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "annotations-tab", children: annotations.map((annotation, i2) => {
2136
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "annotation-item", children: [
2137
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { fontWeight: "bold" }, children: annotation.type }),
2138
- annotation.description && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
2139
- ": ",
2140
- linkifyText(annotation.description)
2141
- ] })
2142
- ] }, `annotation-${i2}`);
2143
- }) });
2144
- };
2145
- const Workbench = ({ model, showSourcesFirst, rootDir, fallbackLocation, isLive, hideTimeline, status, annotations, inert, onOpenExternally, revealSource }) => {
2146
- var _a;
2147
- const [selectedCallId, setSelectedCallId] = reactExports.useState(void 0);
2148
- const [revealedError, setRevealedError] = reactExports.useState(void 0);
2149
- const [revealedAttachment, setRevealedAttachment] = reactExports.useState(void 0);
2150
- const [highlightedCallId, setHighlightedCallId] = reactExports.useState();
2151
- const [highlightedEntry, setHighlightedEntry] = reactExports.useState();
2152
- const [highlightedConsoleMessage, setHighlightedConsoleMessage] = reactExports.useState();
2153
- const [selectedNavigatorTab, setSelectedNavigatorTab] = reactExports.useState("actions");
2154
- const [selectedPropertiesTab, setSelectedPropertiesTab] = useSetting("propertiesTab", showSourcesFirst ? "source" : "call");
2155
- const [isInspecting, setIsInspectingState] = reactExports.useState(false);
2156
- const [highlightedElement, setHighlightedElement] = reactExports.useState({ lastEdited: "none" });
2157
- const [selectedTime, setSelectedTime] = reactExports.useState();
2158
- const [sidebarLocation, setSidebarLocation] = useSetting("propertiesSidebarLocation", "bottom");
2159
- const showScreenshot = false;
2160
- const setSelectedAction = reactExports.useCallback((action) => {
2161
- setSelectedCallId(action == null ? void 0 : action.callId);
2162
- setRevealedError(void 0);
2163
- }, []);
2164
- const highlightedAction = reactExports.useMemo(() => {
2165
- return model == null ? void 0 : model.actions.find((a2) => a2.callId === highlightedCallId);
2166
- }, [model, highlightedCallId]);
2167
- const setHighlightedAction = reactExports.useCallback((highlightedAction2) => {
2168
- setHighlightedCallId(highlightedAction2 == null ? void 0 : highlightedAction2.callId);
2169
- }, []);
2170
- const sources = reactExports.useMemo(() => (model == null ? void 0 : model.sources) || /* @__PURE__ */ new Map(), [model]);
2171
- reactExports.useEffect(() => {
2172
- setSelectedTime(void 0);
2173
- setRevealedError(void 0);
2174
- }, [model]);
2175
- const selectedAction = reactExports.useMemo(() => {
2176
- if (selectedCallId) {
2177
- const action = model == null ? void 0 : model.actions.find((a2) => a2.callId === selectedCallId);
2178
- if (action)
2179
- return action;
2180
- }
2181
- const failedAction = model == null ? void 0 : model.failedAction();
2182
- if (failedAction)
2183
- return failedAction;
2184
- if (model == null ? void 0 : model.actions.length) {
2185
- let index = model.actions.length - 1;
2186
- for (let i2 = 0; i2 < model.actions.length; ++i2) {
2187
- if (model.actions[i2].apiName === "After Hooks" && i2) {
2188
- index = i2 - 1;
2189
- break;
2190
- }
2191
- }
2192
- return model.actions[index];
2193
- }
2194
- }, [model, selectedCallId]);
2195
- const activeAction = reactExports.useMemo(() => {
2196
- return highlightedAction || selectedAction;
2197
- }, [selectedAction, highlightedAction]);
2198
- const revealedStack = reactExports.useMemo(() => {
2199
- if (revealedError)
2200
- return revealedError.stack;
2201
- return activeAction == null ? void 0 : activeAction.stack;
2202
- }, [activeAction, revealedError]);
2203
- const onActionSelected = reactExports.useCallback((action) => {
2204
- setSelectedAction(action);
2205
- setHighlightedAction(void 0);
2206
- }, [setSelectedAction, setHighlightedAction]);
2207
- const selectPropertiesTab = reactExports.useCallback((tab) => {
2208
- setSelectedPropertiesTab(tab);
2209
- if (tab !== "inspector")
2210
- setIsInspectingState(false);
2211
- }, [setSelectedPropertiesTab]);
2212
- const setIsInspecting = reactExports.useCallback((value) => {
2213
- if (!isInspecting && value)
2214
- selectPropertiesTab("inspector");
2215
- setIsInspectingState(value);
2216
- }, [setIsInspectingState, selectPropertiesTab, isInspecting]);
2217
- const elementPicked = reactExports.useCallback((element) => {
2218
- setHighlightedElement(element);
2219
- selectPropertiesTab("inspector");
2220
- }, [selectPropertiesTab]);
2221
- const revealAttachment = reactExports.useCallback((attachment) => {
2222
- selectPropertiesTab("attachments");
2223
- setRevealedAttachment((currentValue) => {
2224
- if (!currentValue)
2225
- return [attachment, 0];
2226
- const revealCounter = currentValue[1];
2227
- return [attachment, revealCounter + 1];
2228
- });
2229
- }, [selectPropertiesTab]);
2230
- reactExports.useEffect(() => {
2231
- if (revealSource)
2232
- selectPropertiesTab("source");
2233
- }, [revealSource, selectPropertiesTab]);
2234
- const consoleModel = useConsoleTabModel(model, selectedTime);
2235
- const networkModel = useNetworkTabModel(model, selectedTime);
2236
- const errorsModel = useErrorsTabModel(model);
2237
- const sdkLanguage = (model == null ? void 0 : model.sdkLanguage) || "javascript";
2238
- const inspectorTab = {
2239
- id: "inspector",
2240
- title: "Locator",
2241
- render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(
2242
- InspectorTab,
2243
- {
2244
- showScreenshot,
2245
- sdkLanguage,
2246
- setIsInspecting,
2247
- highlightedElement,
2248
- setHighlightedElement
2249
- }
2250
- )
2251
- };
2252
- const callTab = {
2253
- id: "call",
2254
- title: "Call",
2255
- render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(CallTab, { action: activeAction, startTimeOffset: (model == null ? void 0 : model.startTime) ?? 0, sdkLanguage })
2256
- };
2257
- const logTab = {
2258
- id: "log",
2259
- title: "Log",
2260
- render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(LogTab, { action: activeAction, isLive })
2261
- };
2262
- const errorsTab = {
2263
- id: "errors",
2264
- title: "Errors",
2265
- errorCount: errorsModel.errors.size,
2266
- render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorsTab, { errorsModel, sdkLanguage, revealInSource: (error) => {
2267
- if (error.action)
2268
- setSelectedAction(error.action);
2269
- else
2270
- setRevealedError(error);
2271
- selectPropertiesTab("source");
2272
- }, wallTime: (model == null ? void 0 : model.wallTime) ?? 0 })
2273
- };
2274
- let fallbackSourceErrorCount = void 0;
2275
- if (!selectedAction && fallbackLocation)
2276
- fallbackSourceErrorCount = (_a = fallbackLocation.source) == null ? void 0 : _a.errors.length;
2277
- const sourceTab = {
2278
- id: "source",
2279
- title: "Source",
2280
- errorCount: fallbackSourceErrorCount,
2281
- render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(
2282
- SourceTab,
2283
- {
2284
- stack: revealedStack,
2285
- sources,
2286
- rootDir,
2287
- stackFrameLocation: sidebarLocation === "bottom" ? "right" : "bottom",
2288
- fallbackLocation,
2289
- onOpenExternally
2290
- }
2291
- )
2292
- };
2293
- const consoleTab = {
2294
- id: "console",
2295
- title: "Console",
2296
- count: consoleModel.entries.length,
2297
- render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(
2298
- ConsoleTab,
2299
- {
2300
- consoleModel,
2301
- boundaries,
2302
- selectedTime,
2303
- onAccepted: (m2) => setSelectedTime({ minimum: m2.timestamp, maximum: m2.timestamp }),
2304
- onEntryHovered: setHighlightedConsoleMessage
2305
- }
2306
- )
2307
- };
2308
- const networkTab = {
2309
- id: "network",
2310
- title: "Network",
2311
- count: networkModel.resources.length,
2312
- render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(NetworkTab, { boundaries, networkModel, onEntryHovered: setHighlightedEntry, sdkLanguage: (model == null ? void 0 : model.sdkLanguage) ?? "javascript" })
2313
- };
2314
- const attachmentsTab = {
2315
- id: "attachments",
2316
- title: "Attachments",
2317
- count: model == null ? void 0 : model.visibleAttachments.length,
2318
- render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(AttachmentsTab, { model, revealedAttachment })
2319
- };
2320
- const tabs = [
2321
- inspectorTab,
2322
- callTab,
2323
- logTab,
2324
- errorsTab,
2325
- consoleTab,
2326
- networkTab,
2327
- sourceTab,
2328
- attachmentsTab
2329
- ];
2330
- if (annotations !== void 0) {
2331
- const annotationsTab = {
2332
- id: "annotations",
2333
- title: "Annotations",
2334
- count: annotations.length,
2335
- render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(AnnotationsTab, { annotations })
2336
- };
2337
- tabs.push(annotationsTab);
2338
- }
2339
- if (showSourcesFirst) {
2340
- const sourceTabIndex = tabs.indexOf(sourceTab);
2341
- tabs.splice(sourceTabIndex, 1);
2342
- tabs.splice(1, 0, sourceTab);
2343
- }
2344
- const { boundaries } = reactExports.useMemo(() => {
2345
- const boundaries2 = { minimum: (model == null ? void 0 : model.startTime) || 0, maximum: (model == null ? void 0 : model.endTime) || 3e4 };
2346
- if (boundaries2.minimum > boundaries2.maximum) {
2347
- boundaries2.minimum = 0;
2348
- boundaries2.maximum = 3e4;
2349
- }
2350
- boundaries2.maximum += (boundaries2.maximum - boundaries2.minimum) / 20;
2351
- return { boundaries: boundaries2 };
2352
- }, [model]);
2353
- let time = 0;
2354
- if (!isLive && model && model.endTime >= 0)
2355
- time = model.endTime - model.startTime;
2356
- else if (model && model.wallTime)
2357
- time = Date.now() - model.wallTime;
2358
- const actionsTab = {
2359
- id: "actions",
2360
- title: "Actions",
2361
- component: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "vbox", children: [
2362
- status && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "workbench-run-status", children: [
2363
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: clsx("codicon", testStatusIcon(status)) }),
2364
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: testStatusText(status) }),
2365
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "spacer" }),
2366
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "workbench-run-duration", children: time ? msToString(time) : "" })
2367
- ] }),
2368
- /* @__PURE__ */ jsxRuntimeExports.jsx(
2369
- ActionList,
2370
- {
2371
- sdkLanguage,
2372
- actions: (model == null ? void 0 : model.actions) || [],
2373
- selectedAction: model ? selectedAction : void 0,
2374
- selectedTime,
2375
- setSelectedTime,
2376
- onSelected: onActionSelected,
2377
- onHighlighted: setHighlightedAction,
2378
- revealAttachment,
2379
- revealConsole: () => selectPropertiesTab("console"),
2380
- isLive
2381
- }
2382
- )
2383
- ] })
2384
- };
2385
- const metadataTab = {
2386
- id: "metadata",
2387
- title: "Metadata",
2388
- component: /* @__PURE__ */ jsxRuntimeExports.jsx(MetadataView, { model })
2389
- };
2390
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "vbox workbench", ...inert ? { inert: "true" } : {}, children: [
2391
- !hideTimeline && /* @__PURE__ */ jsxRuntimeExports.jsx(
2392
- Timeline,
2393
- {
2394
- model,
2395
- consoleEntries: consoleModel.entries,
2396
- boundaries,
2397
- highlightedAction,
2398
- highlightedEntry,
2399
- highlightedConsoleEntry: highlightedConsoleMessage,
2400
- onSelected: onActionSelected,
2401
- sdkLanguage,
2402
- selectedTime,
2403
- setSelectedTime
2404
- }
2405
- ),
2406
- /* @__PURE__ */ jsxRuntimeExports.jsx(
2407
- SplitView,
2408
- {
2409
- sidebarSize: 250,
2410
- orientation: sidebarLocation === "bottom" ? "vertical" : "horizontal",
2411
- settingName: "propertiesSidebar",
2412
- main: /* @__PURE__ */ jsxRuntimeExports.jsx(
2413
- SplitView,
2414
- {
2415
- sidebarSize: 250,
2416
- orientation: "horizontal",
2417
- sidebarIsFirst: true,
2418
- settingName: "actionListSidebar",
2419
- main: /* @__PURE__ */ jsxRuntimeExports.jsx(
2420
- SnapshotTabsView,
2421
- {
2422
- action: activeAction,
2423
- model,
2424
- sdkLanguage,
2425
- testIdAttributeName: (model == null ? void 0 : model.testIdAttributeName) || "data-testid",
2426
- isInspecting,
2427
- setIsInspecting,
2428
- highlightedElement,
2429
- setHighlightedElement: elementPicked
2430
- }
2431
- ),
2432
- sidebar: /* @__PURE__ */ jsxRuntimeExports.jsx(
2433
- TabbedPane,
2434
- {
2435
- tabs: [actionsTab, metadataTab],
2436
- selectedTab: selectedNavigatorTab,
2437
- setSelectedTab: setSelectedNavigatorTab
2438
- }
2439
- )
2440
- }
2441
- ),
2442
- sidebar: /* @__PURE__ */ jsxRuntimeExports.jsx(
2443
- TabbedPane,
2444
- {
2445
- tabs,
2446
- selectedTab: selectedPropertiesTab,
2447
- setSelectedTab: selectPropertiesTab,
2448
- rightToolbar: [
2449
- sidebarLocation === "bottom" ? /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { title: "Dock to right", icon: "layout-sidebar-right-off", onClick: () => {
2450
- setSidebarLocation("right");
2451
- } }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { title: "Dock to bottom", icon: "layout-panel-off", onClick: () => {
2452
- setSidebarLocation("bottom");
2453
- } })
2454
- ],
2455
- mode: sidebarLocation === "bottom" ? "default" : "select"
2456
- }
2457
- )
2458
- }
2459
- )
2460
- ] });
2461
- };
2462
- export {
2463
- Expandable as E,
2464
- LLMProvider as L,
2465
- TreeView as T,
2466
- Workbench as W,
2467
- EventEmitter as a,
2468
- testStatusIcon as t
2469
- };
2470
- //# sourceMappingURL=workbench-CWZselvp.js.map