@checkly/playwright-core 1.47.20-alpha → 1.48.20

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 (203) hide show
  1. package/browsers.json +14 -10
  2. package/lib/checkly/escapeRegExp.js +33 -0
  3. package/lib/checkly/secretsFilter.js +23 -0
  4. package/lib/cli/program.js +26 -14
  5. package/lib/client/api.js +6 -0
  6. package/lib/client/browserContext.js +20 -2
  7. package/lib/client/channelOwner.js +5 -2
  8. package/lib/client/connection.js +3 -0
  9. package/lib/client/fetch.js +16 -3
  10. package/lib/client/jsHandle.js +0 -8
  11. package/lib/client/localUtils.js +1 -0
  12. package/lib/client/network.js +175 -17
  13. package/lib/client/page.js +21 -0
  14. package/lib/client/playwright.js +6 -3
  15. package/lib/client/tracing.js +16 -20
  16. package/lib/generated/consoleApiSource.js +1 -1
  17. package/lib/generated/injectedScriptSource.js +1 -1
  18. package/lib/generated/pollingRecorderSource.js +7 -0
  19. package/lib/generated/webSocketMockSource.js +7 -0
  20. package/lib/protocol/validator.js +80 -14
  21. package/lib/server/bidi/bidiBrowser.js +23 -8
  22. package/lib/server/bidi/bidiChromium.js +124 -0
  23. package/lib/server/bidi/bidiConnection.js +1 -1
  24. package/lib/server/bidi/bidiExecutionContext.js +0 -3
  25. package/lib/server/bidi/bidiFirefox.js +15 -21
  26. package/lib/server/bidi/bidiInput.js +16 -32
  27. package/lib/server/bidi/bidiNetworkManager.js +39 -5
  28. package/lib/server/bidi/bidiOverCdp.js +103 -0
  29. package/lib/server/bidi/bidiPage.js +98 -25
  30. package/lib/server/bidi/bidiPdf.js +140 -0
  31. package/lib/server/bidi/third_party/firefoxPrefs.js +221 -0
  32. package/lib/server/browser.js +13 -2
  33. package/lib/server/browserContext.js +6 -23
  34. package/lib/server/browserType.js +39 -11
  35. package/lib/server/chromium/chromium.js +3 -15
  36. package/lib/server/chromium/chromiumSwitches.js +3 -1
  37. package/lib/server/chromium/crBrowser.js +4 -3
  38. package/lib/server/chromium/crExecutionContext.js +0 -7
  39. package/lib/server/chromium/crPage.js +5 -2
  40. package/lib/server/chromium/videoRecorder.js +1 -1
  41. package/lib/server/codegen/csharp.js +2 -2
  42. package/lib/server/codegen/java.js +1 -1
  43. package/lib/server/codegen/javascript.js +1 -1
  44. package/lib/server/codegen/language.js +14 -2
  45. package/lib/server/codegen/python.js +2 -2
  46. package/lib/server/cookieStore.js +73 -0
  47. package/lib/server/debugController.js +2 -2
  48. package/lib/server/deviceDescriptorsSource.json +51 -51
  49. package/lib/server/dialog.js +1 -0
  50. package/lib/server/dispatchers/browserContextDispatcher.js +19 -2
  51. package/lib/server/dispatchers/jsHandleDispatcher.js +0 -5
  52. package/lib/server/dispatchers/pageDispatcher.js +9 -0
  53. package/lib/server/dispatchers/playwrightDispatcher.js +2 -1
  54. package/lib/server/dispatchers/webSocketRouteDispatcher.js +189 -0
  55. package/lib/server/download.js +9 -2
  56. package/lib/server/fetch.js +96 -99
  57. package/lib/server/firefox/ffBrowser.js +6 -4
  58. package/lib/server/firefox/ffExecutionContext.js +0 -3
  59. package/lib/server/firefox/ffPage.js +3 -0
  60. package/lib/server/firefox/firefox.js +2 -13
  61. package/lib/server/frameSelectors.js +1 -1
  62. package/lib/server/frames.js +3 -2
  63. package/lib/server/har/harTracer.js +11 -0
  64. package/lib/server/input.js +0 -1
  65. package/lib/server/javascript.js +0 -7
  66. package/lib/server/page.js +5 -1
  67. package/lib/server/playwright.js +5 -2
  68. package/lib/server/recorder/contextRecorder.js +33 -50
  69. package/lib/server/recorder/recorderActions.js +2 -1
  70. package/lib/server/recorder/recorderApp.js +16 -10
  71. package/lib/server/recorder/recorderCollection.js +68 -79
  72. package/lib/server/recorder/recorderFrontend.js +5 -0
  73. package/lib/server/recorder/recorderInTraceViewer.js +144 -0
  74. package/lib/server/recorder/recorderRunner.js +75 -97
  75. package/lib/server/recorder/recorderUtils.js +47 -6
  76. package/lib/server/recorder.js +30 -25
  77. package/lib/server/registry/index.js +85 -4
  78. package/lib/server/socksClientCertificatesInterceptor.js +15 -3
  79. package/lib/server/trace/recorder/snapshotter.js +1 -0
  80. package/lib/server/trace/recorder/snapshotterInjected.js +2 -2
  81. package/lib/server/trace/recorder/tracing.js +70 -5
  82. package/lib/server/trace/test/inMemorySnapshotter.js +1 -1
  83. package/lib/server/trace/viewer/traceViewer.js +2 -5
  84. package/lib/server/webkit/webkit.js +1 -1
  85. package/lib/server/webkit/wkBrowser.js +6 -5
  86. package/lib/server/webkit/wkExecutionContext.js +0 -3
  87. package/lib/server/webkit/wkPage.js +4 -1
  88. package/lib/utils/happy-eyeballs.js +13 -0
  89. package/lib/utils/hostPlatform.js +2 -2
  90. package/lib/utils/httpServer.js +1 -0
  91. package/lib/utils/isomorphic/locatorGenerators.js +9 -18
  92. package/lib/utils/isomorphic/locatorParser.js +2 -2
  93. package/lib/utils/isomorphic/recorderUtils.js +195 -0
  94. package/lib/vite/htmlReport/index.html +12 -12
  95. package/lib/vite/recorder/assets/codeMirrorModule-d0KhC1qL.js +24 -0
  96. package/lib/vite/recorder/assets/{index-B-MT5gKo.css → index-BW-aOBcL.css} +1 -1
  97. package/lib/vite/recorder/assets/{index-D-5S5PPN.js → index-Bxxcmxlu.js} +10 -15
  98. package/lib/vite/recorder/index.html +2 -2
  99. package/lib/vite/traceViewer/assets/codeMirrorModule-BTYWvxEC.js +16437 -0
  100. package/lib/vite/traceViewer/assets/codeMirrorModule-BdBhzV6t.js +16443 -0
  101. package/lib/vite/traceViewer/assets/codeMirrorModule-BqcXH1AO.js +16838 -0
  102. package/lib/vite/traceViewer/assets/codeMirrorModule-Ca-1BNel.js +24 -0
  103. package/lib/vite/traceViewer/assets/codeMirrorModule-CcviAl53.js +16831 -0
  104. package/lib/vite/traceViewer/assets/codeMirrorModule-DS3v0XrQ.js +24 -0
  105. package/lib/vite/traceViewer/assets/codeMirrorModule-DZoSgqUd.js +24 -0
  106. package/lib/vite/traceViewer/assets/codeMirrorModule-DblsdhjA.js +16449 -0
  107. package/lib/vite/traceViewer/assets/codeMirrorModule-DtXZtbmO.js +16437 -0
  108. package/lib/vite/traceViewer/assets/codeMirrorModule-EhKN7Okm.js +16449 -0
  109. package/lib/vite/{recorder/assets/codeMirrorModule-C-fQ5QZD.js → traceViewer/assets/codeMirrorModule-MzSmL4X2.js} +1 -1
  110. package/lib/vite/traceViewer/assets/codeMirrorModule-U6XMqGkV.js +16437 -0
  111. package/lib/vite/traceViewer/assets/codeMirrorModule-lDjkI8Ax.js +24 -0
  112. package/lib/vite/traceViewer/assets/inspectorTab-BABZNwlH.js +17351 -0
  113. package/lib/vite/traceViewer/assets/inspectorTab-BB2Bm-wy.js +17361 -0
  114. package/lib/vite/traceViewer/assets/inspectorTab-BHcfR9dD.js +64 -0
  115. package/lib/vite/traceViewer/assets/inspectorTab-BPzVEZSf.js +17351 -0
  116. package/lib/vite/traceViewer/assets/inspectorTab-BPzhNk9r.js +64 -0
  117. package/lib/vite/traceViewer/assets/inspectorTab-Bbgq0hgt.js +64 -0
  118. package/lib/vite/traceViewer/assets/inspectorTab-C_OTuI8x.js +17361 -0
  119. package/lib/vite/traceViewer/assets/inspectorTab-DOc4D3cX.js +17361 -0
  120. package/lib/vite/traceViewer/assets/inspectorTab-DhBbZz8I.js +64 -0
  121. package/lib/vite/traceViewer/assets/inspectorTab-DpvLVMq5.js +17351 -0
  122. package/lib/vite/traceViewer/assets/workbench-B13nfocr.js +9 -0
  123. package/lib/vite/traceViewer/assets/workbench-BcgGQnKb.js +1473 -0
  124. package/lib/vite/traceViewer/assets/workbench-BwodYCgl.js +19119 -0
  125. package/lib/vite/traceViewer/assets/workbench-ByyWxoT8.js +1473 -0
  126. package/lib/vite/traceViewer/assets/workbench-CWtpwfKK.js +1473 -0
  127. package/lib/vite/traceViewer/assets/workbench-Crj6jzdv.js +19119 -0
  128. package/lib/vite/traceViewer/assets/workbench-DLv_q9ji.js +9 -0
  129. package/lib/vite/traceViewer/assets/workbench-DZqNXdoV.js +9 -0
  130. package/lib/vite/traceViewer/assets/workbench-DhqI6jeL.js +1473 -0
  131. package/lib/vite/traceViewer/assets/workbench-I4s6sWjN.js +1473 -0
  132. package/lib/vite/traceViewer/assets/workbench-M-Dh_RgU.js +1473 -0
  133. package/lib/vite/traceViewer/assets/workbench-Pa1v1Ojh.js +72 -0
  134. package/lib/vite/traceViewer/assets/workbench-gtYcQBNA.js +9 -0
  135. package/lib/vite/traceViewer/assets/xtermModule-DZP0glxx.js +5982 -0
  136. package/lib/vite/traceViewer/embedded.27BGR_eD.js +105 -0
  137. package/lib/vite/traceViewer/embedded.BBZ9gQEw.js +104 -0
  138. package/lib/vite/traceViewer/embedded.BIubxTi3.js +2 -0
  139. package/lib/vite/traceViewer/embedded.CHH7D63q.js +106 -0
  140. package/lib/vite/traceViewer/embedded.CorI3dFX.js +104 -0
  141. package/lib/vite/traceViewer/embedded.D4lqGydT.js +2 -0
  142. package/lib/vite/traceViewer/embedded.DTjd2aiy.js +105 -0
  143. package/lib/vite/traceViewer/embedded.DbzY7Q8w.js +2 -0
  144. package/lib/vite/traceViewer/embedded.Dxe2heQk.js +2 -0
  145. package/lib/vite/traceViewer/embedded.SsjKHrxC.js +105 -0
  146. package/lib/vite/traceViewer/embedded.Zu332ZC1.js +106 -0
  147. package/lib/vite/traceViewer/embedded.f-PLGsBT.js +2 -0
  148. package/lib/vite/traceViewer/embedded.html +5 -3
  149. package/lib/vite/traceViewer/embedded.ymLJ2mBS.js +106 -0
  150. package/lib/vite/traceViewer/index.B7aiTMfZ.js +2 -0
  151. package/lib/vite/traceViewer/index.BSak5QT9.js +2 -0
  152. package/lib/vite/traceViewer/index.Bfh46hDK.js +197 -0
  153. package/lib/vite/traceViewer/index.BrT2kfuc.js +2 -0
  154. package/lib/vite/traceViewer/index.C8ZWP1Qw.js +197 -0
  155. package/lib/vite/traceViewer/index.CB297BuW.js +2 -0
  156. package/lib/vite/traceViewer/index.CLxsp2W_.js +197 -0
  157. package/lib/vite/traceViewer/index.DPD22sZn.js +2 -0
  158. package/lib/vite/traceViewer/index.DkRbtWVo.js +195 -0
  159. package/lib/vite/traceViewer/index.DsjmhbB6.js +195 -0
  160. package/lib/vite/traceViewer/index.Dz3icWJV.js +196 -0
  161. package/lib/vite/traceViewer/index.PqcsvBxQ.js +196 -0
  162. package/lib/vite/traceViewer/index.html +5 -3
  163. package/lib/vite/traceViewer/index.yxAwzeWG.js +196 -0
  164. package/lib/vite/traceViewer/inspectorTab.DGJWXOSd.css +3145 -0
  165. package/lib/vite/traceViewer/inspectorTab.DLjBDrQR.css +1 -0
  166. package/lib/vite/traceViewer/recorder.7Wl6HrQl.js +550 -0
  167. package/lib/vite/traceViewer/recorder.BHq8OXiu.js +551 -0
  168. package/lib/vite/traceViewer/recorder.B_SY1GJM.css +0 -0
  169. package/lib/vite/traceViewer/recorder.BaRuS6Pc.js +2 -0
  170. package/lib/vite/traceViewer/recorder.BufKu9Hp.js +550 -0
  171. package/lib/vite/traceViewer/recorder.C88JDknq.js +2 -0
  172. package/lib/vite/traceViewer/recorder.Ch-WHviK.js +2 -0
  173. package/lib/vite/traceViewer/recorder.DBDpiNOK.css +15 -0
  174. package/lib/vite/traceViewer/recorder.Fwf59ZKh.js +551 -0
  175. package/lib/vite/traceViewer/recorder.POd-toIn.js +2 -0
  176. package/lib/vite/traceViewer/recorder.am-MV-DQ.js +550 -0
  177. package/lib/vite/traceViewer/recorder.html +17 -0
  178. package/lib/vite/traceViewer/recorder.zV_xPHM4.js +551 -0
  179. package/lib/vite/traceViewer/sw.bundle.js +3 -3
  180. package/lib/vite/traceViewer/uiMode.2tr9k625.js +5 -0
  181. package/lib/vite/traceViewer/uiMode.B11wexdJ.js +5 -0
  182. package/lib/vite/traceViewer/uiMode.BEZVCe5O.js +5 -0
  183. package/lib/vite/traceViewer/uiMode.BH2Nj2h0.js +1724 -0
  184. package/lib/vite/traceViewer/uiMode.BZoFj6zV.js +1723 -0
  185. package/lib/vite/traceViewer/uiMode.C4nbcio6.js +1730 -0
  186. package/lib/vite/traceViewer/uiMode.CAYqod-m.css +1 -0
  187. package/lib/vite/traceViewer/uiMode.CBRJkC_K.js +1724 -0
  188. package/lib/vite/traceViewer/uiMode.CpC2B27N.js +1724 -0
  189. package/lib/vite/traceViewer/uiMode.DRmgrHSk.css +1462 -0
  190. package/lib/vite/traceViewer/uiMode.DdtUZZVS.js +5 -0
  191. package/lib/vite/traceViewer/uiMode.Dlo9s_YX.js +1723 -0
  192. package/lib/vite/traceViewer/uiMode.O07awP3T.js +10 -0
  193. package/lib/vite/traceViewer/uiMode.gGHHTsyL.js +1730 -0
  194. package/lib/vite/traceViewer/uiMode.html +6 -4
  195. package/lib/vite/traceViewer/uiMode.wsGnVMQK.js +1723 -0
  196. package/lib/vite/traceViewer/workbench.9Es1K_T7.css +549 -0
  197. package/lib/vite/traceViewer/workbench.BQNDbcQ0.css +550 -0
  198. package/lib/vite/traceViewer/workbench.DjbIuxix.css +1 -0
  199. package/lib/vite/traceViewer/workbench.DlsCx8k5.css +1 -0
  200. package/lib/vite/traceViewer/workbench.wuxQoE2z.css +3703 -0
  201. package/package.json +1 -1
  202. package/types/protocol.d.ts +610 -173
  203. package/types/types.d.ts +2037 -949
@@ -0,0 +1,1473 @@
1
+ import { r as reactExports, j as jsxRuntimeExports, L as ListView, k as buildActionTree, l as stats, n as asLocator, m as msToString, P as PlaceholderPanel, f as clsx, C as CopyToClipboard, o as ansi2html, u as useMeasure, p as upperBound, G as GlassPane, q as ResizeView, v as kWebLinkRe, w as lineHeight, x as CodeMirrorWrapper, h as useSetting, y as useConsoleTabModel, z as useNetworkTabModel, A as ConsoleTab, N as NetworkTab, S as SplitView, B as SnapshotTabsView, D as TabbedPane, T as ToolbarButton, I as InspectorTab, E as SourceTab } from "./inspectorTab-DpvLVMq5.js";
2
+ const TreeListView = ListView;
3
+ function TreeView({
4
+ name,
5
+ rootItem,
6
+ render,
7
+ icon,
8
+ isError,
9
+ isVisible,
10
+ selectedItem,
11
+ onAccepted,
12
+ onSelected,
13
+ onHighlighted,
14
+ treeState,
15
+ setTreeState,
16
+ noItemsMessage,
17
+ dataTestId,
18
+ autoExpandDepth
19
+ }) {
20
+ const treeItems = reactExports.useMemo(() => {
21
+ return flattenTree(rootItem, selectedItem, treeState.expandedItems, autoExpandDepth || 0);
22
+ }, [rootItem, selectedItem, treeState, autoExpandDepth]);
23
+ const visibleItems = reactExports.useMemo(() => {
24
+ if (!isVisible)
25
+ return [...treeItems.keys()];
26
+ const cachedVisible = /* @__PURE__ */ new Map();
27
+ const visit = (item) => {
28
+ const cachedResult = cachedVisible.get(item);
29
+ if (cachedResult !== void 0)
30
+ return cachedResult;
31
+ let hasVisibleChildren = item.children.some((child) => visit(child));
32
+ for (const child of item.children) {
33
+ const result3 = visit(child);
34
+ hasVisibleChildren = hasVisibleChildren || result3;
35
+ }
36
+ const result2 = isVisible(item) || hasVisibleChildren;
37
+ cachedVisible.set(item, result2);
38
+ return result2;
39
+ };
40
+ for (const item of treeItems.keys())
41
+ visit(item);
42
+ const result = [];
43
+ for (const item of treeItems.keys()) {
44
+ if (isVisible(item))
45
+ result.push(item);
46
+ }
47
+ return result;
48
+ }, [treeItems, isVisible]);
49
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
50
+ TreeListView,
51
+ {
52
+ name,
53
+ items: visibleItems,
54
+ id: (item) => item.id,
55
+ dataTestId: dataTestId || name + "-tree",
56
+ render: (item) => {
57
+ const rendered = render(item);
58
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
59
+ icon && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "codicon " + (icon(item) || "blank"), style: { minWidth: 16, marginRight: 4 } }),
60
+ typeof rendered === "string" ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { textOverflow: "ellipsis", overflow: "hidden" }, children: rendered }) : rendered
61
+ ] });
62
+ },
63
+ icon: (item) => {
64
+ const expanded = treeItems.get(item).expanded;
65
+ if (typeof expanded === "boolean")
66
+ return expanded ? "codicon-chevron-down" : "codicon-chevron-right";
67
+ },
68
+ isError: (item) => (isError == null ? void 0 : isError(item)) || false,
69
+ indent: (item) => treeItems.get(item).depth,
70
+ selectedItem,
71
+ onAccepted: (item) => onAccepted == null ? void 0 : onAccepted(item),
72
+ onSelected: (item) => onSelected == null ? void 0 : onSelected(item),
73
+ onHighlighted: (item) => onHighlighted == null ? void 0 : onHighlighted(item),
74
+ onLeftArrow: (item) => {
75
+ const { expanded, parent } = treeItems.get(item);
76
+ if (expanded) {
77
+ treeState.expandedItems.set(item.id, false);
78
+ setTreeState({ ...treeState });
79
+ } else if (parent) {
80
+ onSelected == null ? void 0 : onSelected(parent);
81
+ }
82
+ },
83
+ onRightArrow: (item) => {
84
+ if (item.children.length) {
85
+ treeState.expandedItems.set(item.id, true);
86
+ setTreeState({ ...treeState });
87
+ }
88
+ },
89
+ onIconClicked: (item) => {
90
+ const { expanded } = treeItems.get(item);
91
+ if (expanded) {
92
+ for (let i = selectedItem; i; i = i.parent) {
93
+ if (i === item) {
94
+ onSelected == null ? void 0 : onSelected(item);
95
+ break;
96
+ }
97
+ }
98
+ treeState.expandedItems.set(item.id, false);
99
+ } else {
100
+ treeState.expandedItems.set(item.id, true);
101
+ }
102
+ setTreeState({ ...treeState });
103
+ },
104
+ noItemsMessage
105
+ }
106
+ );
107
+ }
108
+ function flattenTree(rootItem, selectedItem, expandedItems, autoExpandDepth) {
109
+ const result = /* @__PURE__ */ new Map();
110
+ const temporaryExpanded = /* @__PURE__ */ new Set();
111
+ for (let item = selectedItem == null ? void 0 : selectedItem.parent; item; item = item.parent)
112
+ temporaryExpanded.add(item.id);
113
+ const appendChildren = (parent, depth) => {
114
+ for (const item of parent.children) {
115
+ const expandState = temporaryExpanded.has(item.id) || expandedItems.get(item.id);
116
+ const autoExpandMatches = autoExpandDepth > depth && result.size < 25 && expandState !== false;
117
+ const expanded = item.children.length ? expandState ?? autoExpandMatches : void 0;
118
+ result.set(item, { depth, expanded, parent: rootItem === parent ? null : parent });
119
+ if (expanded)
120
+ appendChildren(item, depth + 1);
121
+ }
122
+ };
123
+ appendChildren(rootItem, 0);
124
+ return result;
125
+ }
126
+ const ActionTreeView = TreeView;
127
+ const ActionList = ({
128
+ actions,
129
+ selectedAction,
130
+ selectedTime,
131
+ setSelectedTime,
132
+ sdkLanguage,
133
+ onSelected,
134
+ onHighlighted,
135
+ revealConsole,
136
+ isLive
137
+ }) => {
138
+ const [treeState, setTreeState] = reactExports.useState({ expandedItems: /* @__PURE__ */ new Map() });
139
+ const { rootItem, itemMap } = reactExports.useMemo(() => buildActionTree(actions), [actions]);
140
+ const { selectedItem } = reactExports.useMemo(() => {
141
+ const selectedItem2 = selectedAction ? itemMap.get(selectedAction.callId) : void 0;
142
+ return { selectedItem: selectedItem2 };
143
+ }, [itemMap, selectedAction]);
144
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "vbox", children: [
145
+ selectedTime && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "action-list-show-all", onClick: () => setSelectedTime(void 0), children: [
146
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "codicon codicon-triangle-left" }),
147
+ "Show all"
148
+ ] }),
149
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
150
+ ActionTreeView,
151
+ {
152
+ name: "actions",
153
+ rootItem,
154
+ treeState,
155
+ setTreeState,
156
+ selectedItem,
157
+ onSelected: (item) => onSelected == null ? void 0 : onSelected(item.action),
158
+ onHighlighted: (item) => onHighlighted == null ? void 0 : onHighlighted(item == null ? void 0 : item.action),
159
+ onAccepted: (item) => setSelectedTime({ minimum: item.action.startTime, maximum: item.action.endTime }),
160
+ isError: (item) => {
161
+ var _a, _b;
162
+ return !!((_b = (_a = item.action) == null ? void 0 : _a.error) == null ? void 0 : _b.message);
163
+ },
164
+ isVisible: (item) => !selectedTime || item.action.startTime <= selectedTime.maximum && item.action.endTime >= selectedTime.minimum,
165
+ render: (item) => renderAction(item.action, { sdkLanguage, revealConsole, isLive, showDuration: true, showBadges: true })
166
+ }
167
+ )
168
+ ] });
169
+ };
170
+ const renderAction = (action, options) => {
171
+ const { sdkLanguage, revealConsole, isLive, showDuration, showBadges } = options;
172
+ const { errors, warnings } = stats(action);
173
+ const locator = action.params.selector ? asLocator(sdkLanguage || "javascript", action.params.selector) : void 0;
174
+ let time = "";
175
+ if (action.endTime)
176
+ time = msToString(action.endTime - action.startTime);
177
+ else if (action.error)
178
+ time = "Timed out";
179
+ else if (!isLive)
180
+ time = "-";
181
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
182
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "action-title", title: action.apiName, children: [
183
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: action.apiName }),
184
+ locator && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "action-selector", title: locator, children: locator }),
185
+ action.method === "goto" && action.params.url && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "action-url", title: action.params.url, children: action.params.url }),
186
+ action.class === "APIRequestContext" && action.params.url && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "action-url", title: action.params.url, children: excludeOrigin(action.params.url) })
187
+ ] }),
188
+ (showDuration || showBadges) && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "spacer" }),
189
+ showDuration && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "action-duration", children: time || /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "codicon codicon-loading" }) }),
190
+ showBadges && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "action-icons", onClick: () => revealConsole == null ? void 0 : revealConsole(), children: [
191
+ !!errors && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "action-icon", children: [
192
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "codicon codicon-error" }),
193
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "action-icon-value", children: errors })
194
+ ] }),
195
+ !!warnings && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "action-icon", children: [
196
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "codicon codicon-warning" }),
197
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "action-icon-value", children: warnings })
198
+ ] })
199
+ ] })
200
+ ] });
201
+ };
202
+ function excludeOrigin(url) {
203
+ try {
204
+ const urlObject = new URL(url);
205
+ return urlObject.pathname + urlObject.search;
206
+ } catch (error) {
207
+ return url;
208
+ }
209
+ }
210
+ const CallTab = ({ action, sdkLanguage }) => {
211
+ if (!action)
212
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(PlaceholderPanel, { text: "No action selected" });
213
+ const params = { ...action.params };
214
+ delete params.info;
215
+ const paramKeys = Object.keys(params);
216
+ const timeMillis = action.startTime + (action.context.wallTime - action.context.startTime);
217
+ const wallTime = new Date(timeMillis).toLocaleString();
218
+ const duration = action.endTime ? msToString(action.endTime - action.startTime) : "Timed Out";
219
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-tab", children: [
220
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-line", children: action.apiName }),
221
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
222
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-section", children: "Time" }),
223
+ wallTime && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
224
+ "wall time:",
225
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value datetime", title: wallTime, children: wallTime })
226
+ ] }),
227
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
228
+ "duration:",
229
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value datetime", title: duration, children: duration })
230
+ ] })
231
+ ] }),
232
+ !!paramKeys.length && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-section", children: "Parameters" }),
233
+ !!paramKeys.length && paramKeys.map((name, index) => renderProperty(propertyToString(action, name, params[name], sdkLanguage), "param-" + index)),
234
+ !!action.result && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-section", children: "Return value" }),
235
+ !!action.result && Object.keys(action.result).map(
236
+ (name, index) => renderProperty(propertyToString(action, name, action.result[name], sdkLanguage), "result-" + index)
237
+ )
238
+ ] });
239
+ };
240
+ function renderProperty(property, key) {
241
+ let text = property.text.replace(/\n/g, "↵");
242
+ if (property.type === "string")
243
+ text = `"${text}"`;
244
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
245
+ property.name,
246
+ ":",
247
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: clsx("call-value", property.type), title: property.text, children: text }),
248
+ ["string", "number", "object", "locator"].includes(property.type) && /* @__PURE__ */ jsxRuntimeExports.jsx(CopyToClipboard, { value: property.text })
249
+ ] }, key);
250
+ }
251
+ function propertyToString(event, name, value, sdkLanguage) {
252
+ const isEval = event.method.includes("eval") || event.method === "waitForFunction";
253
+ if (name === "files")
254
+ return { text: "<files>", type: "string", name };
255
+ if (name === "eventInit" || name === "expectedValue" || name === "arg" && isEval)
256
+ value = parseSerializedValue(value.value, new Array(10).fill({ handle: "<handle>" }));
257
+ if (name === "value" && isEval || name === "received" && event.method === "expect")
258
+ value = parseSerializedValue(value, new Array(10).fill({ handle: "<handle>" }));
259
+ if (name === "selector")
260
+ return { text: asLocator(sdkLanguage || "javascript", event.params.selector), type: "locator", name: "locator" };
261
+ const type = typeof value;
262
+ if (type !== "object" || value === null)
263
+ return { text: String(value), type, name };
264
+ if (value.guid)
265
+ return { text: "<handle>", type: "handle", name };
266
+ return { text: JSON.stringify(value).slice(0, 1e3), type: "object", name };
267
+ }
268
+ function parseSerializedValue(value, handles) {
269
+ if (value.n !== void 0)
270
+ return value.n;
271
+ if (value.s !== void 0)
272
+ return value.s;
273
+ if (value.b !== void 0)
274
+ return value.b;
275
+ if (value.v !== void 0) {
276
+ if (value.v === "undefined")
277
+ return void 0;
278
+ if (value.v === "null")
279
+ return null;
280
+ if (value.v === "NaN")
281
+ return NaN;
282
+ if (value.v === "Infinity")
283
+ return Infinity;
284
+ if (value.v === "-Infinity")
285
+ return -Infinity;
286
+ if (value.v === "-0")
287
+ return -0;
288
+ }
289
+ if (value.d !== void 0)
290
+ return new Date(value.d);
291
+ if (value.r !== void 0)
292
+ return new RegExp(value.r.p, value.r.f);
293
+ if (value.a !== void 0)
294
+ return value.a.map((a) => parseSerializedValue(a, handles));
295
+ if (value.o !== void 0) {
296
+ const result = {};
297
+ for (const { k, v } of value.o)
298
+ result[k] = parseSerializedValue(v, handles);
299
+ return result;
300
+ }
301
+ if (value.h !== void 0) {
302
+ if (handles === void 0)
303
+ return "<object>";
304
+ return handles[value.h];
305
+ }
306
+ return "<object>";
307
+ }
308
+ const LogList = ListView;
309
+ const LogTab = ({ action, isLive }) => {
310
+ const entries = reactExports.useMemo(() => {
311
+ var _a;
312
+ if (!action || !action.log.length)
313
+ return [];
314
+ const log = action.log;
315
+ const wallTimeOffset = action.context.wallTime - action.context.startTime;
316
+ const entries2 = [];
317
+ for (let i = 0; i < log.length; ++i) {
318
+ let time = "";
319
+ if (log[i].time !== -1) {
320
+ const timeStart = (_a = log[i]) == null ? void 0 : _a.time;
321
+ if (i + 1 < log.length)
322
+ time = msToString(log[i + 1].time - timeStart);
323
+ else if (action.endTime > 0)
324
+ time = msToString(action.endTime - timeStart);
325
+ else if (isLive)
326
+ time = msToString(Date.now() - wallTimeOffset - timeStart);
327
+ else
328
+ time = "-";
329
+ }
330
+ entries2.push({
331
+ message: log[i].message,
332
+ time
333
+ });
334
+ }
335
+ return entries2;
336
+ }, [action, isLive]);
337
+ if (!entries.length)
338
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(PlaceholderPanel, { text: "No log entries" });
339
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
340
+ LogList,
341
+ {
342
+ name: "log",
343
+ items: entries,
344
+ render: (entry) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "log-list-item", children: [
345
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "log-list-duration", children: entry.time }),
346
+ entry.message
347
+ ] }),
348
+ notSelectable: true
349
+ }
350
+ );
351
+ };
352
+ const ErrorMessage = ({ error }) => {
353
+ const html = reactExports.useMemo(() => ansi2html(error), [error]);
354
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "error-message", dangerouslySetInnerHTML: { __html: html || "" } });
355
+ };
356
+ function useErrorsTabModel(model) {
357
+ return reactExports.useMemo(() => {
358
+ if (!model)
359
+ return { errors: /* @__PURE__ */ new Map() };
360
+ const errors = /* @__PURE__ */ new Map();
361
+ for (const error of model.errorDescriptors)
362
+ errors.set(error.message, error);
363
+ return { errors };
364
+ }, [model]);
365
+ }
366
+ const ErrorsTab = ({ errorsModel, sdkLanguage, revealInSource }) => {
367
+ if (!errorsModel.errors.size)
368
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(PlaceholderPanel, { text: "No errors" });
369
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fill", style: { overflow: "auto" }, children: [...errorsModel.errors.entries()].map(([message, error]) => {
370
+ var _a;
371
+ let location;
372
+ let longLocation;
373
+ const stackFrame = (_a = error.stack) == null ? void 0 : _a[0];
374
+ if (stackFrame) {
375
+ const file = stackFrame.file.replace(/.*[/\\](.*)/, "$1");
376
+ location = file + ":" + stackFrame.line;
377
+ longLocation = stackFrame.file + ":" + stackFrame.line;
378
+ }
379
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
380
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "hbox", style: {
381
+ alignItems: "center",
382
+ padding: "5px 10px",
383
+ minHeight: 36,
384
+ fontWeight: "bold",
385
+ color: "var(--vscode-errorForeground)"
386
+ }, children: [
387
+ error.action && renderAction(error.action, { sdkLanguage }),
388
+ location && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "action-location", children: [
389
+ "@ ",
390
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { title: longLocation, onClick: () => revealInSource(error), children: location })
391
+ ] })
392
+ ] }),
393
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorMessage, { error: message })
394
+ ] }, message);
395
+ }) });
396
+ };
397
+ const tileSize = { width: 200, height: 45 };
398
+ const frameMargin = 2.5;
399
+ const rowHeight = tileSize.height + frameMargin * 2;
400
+ const FilmStrip = ({ model, boundaries, previewPoint }) => {
401
+ var _a, _b;
402
+ const [measure, ref] = useMeasure();
403
+ const lanesRef = reactExports.useRef(null);
404
+ let pageIndex = 0;
405
+ if (lanesRef.current && previewPoint) {
406
+ const bounds = lanesRef.current.getBoundingClientRect();
407
+ pageIndex = (previewPoint.clientY - bounds.top + lanesRef.current.scrollTop) / rowHeight | 0;
408
+ }
409
+ const screencastFrames = (_b = (_a = model == null ? void 0 : model.pages) == null ? void 0 : _a[pageIndex]) == null ? void 0 : _b.screencastFrames;
410
+ let previewImage = void 0;
411
+ let previewSize = void 0;
412
+ if (previewPoint !== void 0 && screencastFrames && screencastFrames.length) {
413
+ const previewTime = boundaries.minimum + (boundaries.maximum - boundaries.minimum) * previewPoint.x / measure.width;
414
+ previewImage = screencastFrames[upperBound(screencastFrames, previewTime, timeComparator) - 1];
415
+ const fitInto = {
416
+ width: Math.min(800, window.innerWidth / 2 | 0),
417
+ height: Math.min(800, window.innerHeight / 2 | 0)
418
+ };
419
+ previewSize = previewImage ? inscribe({ width: previewImage.width, height: previewImage.height }, fitInto) : void 0;
420
+ }
421
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "film-strip", ref, children: [
422
+ /* @__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(
423
+ FilmStripLane,
424
+ {
425
+ boundaries,
426
+ page,
427
+ width: measure.width
428
+ },
429
+ index
430
+ ) : null) }),
431
+ (previewPoint == null ? void 0 : previewPoint.x) !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "film-strip-hover", style: {
432
+ top: measure.bottom + 5,
433
+ left: Math.min(previewPoint.x, measure.width - (previewSize ? previewSize.width : 0) - 10)
434
+ }, children: [
435
+ previewPoint.action && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "film-strip-hover-title", children: renderAction(previewPoint.action, previewPoint) }),
436
+ 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 }) })
437
+ ] })
438
+ ] });
439
+ };
440
+ const FilmStripLane = ({ boundaries, page, width }) => {
441
+ const viewportSize = { width: 0, height: 0 };
442
+ const screencastFrames = page.screencastFrames;
443
+ for (const frame of screencastFrames) {
444
+ viewportSize.width = Math.max(viewportSize.width, frame.width);
445
+ viewportSize.height = Math.max(viewportSize.height, frame.height);
446
+ }
447
+ const frameSize = inscribe(viewportSize, tileSize);
448
+ const startTime = screencastFrames[0].timestamp;
449
+ const endTime = screencastFrames[screencastFrames.length - 1].timestamp;
450
+ const boundariesDuration = boundaries.maximum - boundaries.minimum;
451
+ const gapLeft = (startTime - boundaries.minimum) / boundariesDuration * width;
452
+ const gapRight = (boundaries.maximum - endTime) / boundariesDuration * width;
453
+ const effectiveWidth = (endTime - startTime) / boundariesDuration * width;
454
+ const frameCount = effectiveWidth / (frameSize.width + 2 * frameMargin) | 0;
455
+ const frameDuration = (endTime - startTime) / frameCount;
456
+ const frames = [];
457
+ for (let i = 0; startTime && frameDuration && i < frameCount; ++i) {
458
+ const time = startTime + frameDuration * i;
459
+ const index = upperBound(screencastFrames, time, timeComparator) - 1;
460
+ frames.push(/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "film-strip-frame", style: {
461
+ width: frameSize.width,
462
+ height: frameSize.height,
463
+ backgroundImage: `url(sha1/${screencastFrames[index].sha1})`,
464
+ backgroundSize: `${frameSize.width}px ${frameSize.height}px`,
465
+ margin: frameMargin,
466
+ marginRight: frameMargin
467
+ } }, i));
468
+ }
469
+ frames.push(/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "film-strip-frame", style: {
470
+ width: frameSize.width,
471
+ height: frameSize.height,
472
+ backgroundImage: `url(sha1/${screencastFrames[screencastFrames.length - 1].sha1})`,
473
+ backgroundSize: `${frameSize.width}px ${frameSize.height}px`,
474
+ margin: frameMargin,
475
+ marginRight: frameMargin
476
+ } }, frames.length));
477
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "film-strip-lane", style: {
478
+ marginLeft: gapLeft + "px",
479
+ marginRight: gapRight + "px"
480
+ }, children: frames });
481
+ };
482
+ function timeComparator(time, frame) {
483
+ return time - frame.timestamp;
484
+ }
485
+ function inscribe(object, area) {
486
+ const scale = Math.max(object.width / area.width, object.height / area.height);
487
+ return {
488
+ width: object.width / scale | 0,
489
+ height: object.height / scale | 0
490
+ };
491
+ }
492
+ const Timeline = ({ model, boundaries, consoleEntries, onSelected, highlightedAction, highlightedEntry, highlightedConsoleEntry, selectedTime, setSelectedTime, sdkLanguage }) => {
493
+ const [measure, ref] = useMeasure();
494
+ const [dragWindow, setDragWindow] = reactExports.useState();
495
+ const [previewPoint, setPreviewPoint] = reactExports.useState();
496
+ const { offsets, curtainLeft, curtainRight } = reactExports.useMemo(() => {
497
+ let activeWindow = selectedTime || boundaries;
498
+ if (dragWindow && dragWindow.startX !== dragWindow.endX) {
499
+ const time1 = positionToTime(measure.width, boundaries, dragWindow.startX);
500
+ const time2 = positionToTime(measure.width, boundaries, dragWindow.endX);
501
+ activeWindow = { minimum: Math.min(time1, time2), maximum: Math.max(time1, time2) };
502
+ }
503
+ const curtainLeft2 = timeToPosition(measure.width, boundaries, activeWindow.minimum);
504
+ const maxRight = timeToPosition(measure.width, boundaries, boundaries.maximum);
505
+ const curtainRight2 = maxRight - timeToPosition(measure.width, boundaries, activeWindow.maximum);
506
+ return { offsets: calculateDividerOffsets(measure.width, boundaries), curtainLeft: curtainLeft2, curtainRight: curtainRight2 };
507
+ }, [selectedTime, boundaries, dragWindow, measure]);
508
+ const bars = reactExports.useMemo(() => {
509
+ const bars2 = [];
510
+ for (const entry of (model == null ? void 0 : model.actions) || []) {
511
+ if (entry.class === "Test")
512
+ continue;
513
+ bars2.push({
514
+ action: entry,
515
+ leftTime: entry.startTime,
516
+ rightTime: entry.endTime || boundaries.maximum,
517
+ leftPosition: timeToPosition(measure.width, boundaries, entry.startTime),
518
+ rightPosition: timeToPosition(measure.width, boundaries, entry.endTime || boundaries.maximum),
519
+ active: false,
520
+ error: !!entry.error
521
+ });
522
+ }
523
+ for (const resource of (model == null ? void 0 : model.resources) || []) {
524
+ const startTime = resource._monotonicTime;
525
+ const endTime = resource._monotonicTime + resource.time;
526
+ bars2.push({
527
+ resource,
528
+ leftTime: startTime,
529
+ rightTime: endTime,
530
+ leftPosition: timeToPosition(measure.width, boundaries, startTime),
531
+ rightPosition: timeToPosition(measure.width, boundaries, endTime),
532
+ active: false,
533
+ error: false
534
+ });
535
+ }
536
+ for (const consoleMessage of consoleEntries || []) {
537
+ bars2.push({
538
+ consoleMessage,
539
+ leftTime: consoleMessage.timestamp,
540
+ rightTime: consoleMessage.timestamp,
541
+ leftPosition: timeToPosition(measure.width, boundaries, consoleMessage.timestamp),
542
+ rightPosition: timeToPosition(measure.width, boundaries, consoleMessage.timestamp),
543
+ active: false,
544
+ error: consoleMessage.isError
545
+ });
546
+ }
547
+ return bars2;
548
+ }, [model, consoleEntries, boundaries, measure]);
549
+ reactExports.useMemo(() => {
550
+ for (const bar of bars) {
551
+ if (highlightedAction)
552
+ bar.active = bar.action === highlightedAction;
553
+ else if (highlightedEntry)
554
+ bar.active = bar.resource === highlightedEntry;
555
+ else if (highlightedConsoleEntry)
556
+ bar.active = bar.consoleMessage === highlightedConsoleEntry;
557
+ else
558
+ bar.active = false;
559
+ }
560
+ }, [bars, highlightedAction, highlightedEntry, highlightedConsoleEntry]);
561
+ const onMouseDown = reactExports.useCallback((event) => {
562
+ setPreviewPoint(void 0);
563
+ if (!ref.current)
564
+ return;
565
+ const x = event.clientX - ref.current.getBoundingClientRect().left;
566
+ const time = positionToTime(measure.width, boundaries, x);
567
+ const leftX = selectedTime ? timeToPosition(measure.width, boundaries, selectedTime.minimum) : 0;
568
+ const rightX = selectedTime ? timeToPosition(measure.width, boundaries, selectedTime.maximum) : 0;
569
+ if (selectedTime && Math.abs(x - leftX) < 10) {
570
+ setDragWindow({ startX: rightX, endX: x, type: "resize" });
571
+ } else if (selectedTime && Math.abs(x - rightX) < 10) {
572
+ setDragWindow({ startX: leftX, endX: x, type: "resize" });
573
+ } else if (selectedTime && time > selectedTime.minimum && time < selectedTime.maximum && event.clientY - ref.current.getBoundingClientRect().top < 20) {
574
+ setDragWindow({ startX: leftX, endX: rightX, pivot: x, type: "move" });
575
+ } else {
576
+ setDragWindow({ startX: x, endX: x, type: "resize" });
577
+ }
578
+ }, [boundaries, measure, ref, selectedTime]);
579
+ const onGlassPaneMouseMove = reactExports.useCallback((event) => {
580
+ if (!ref.current)
581
+ return;
582
+ const x = event.clientX - ref.current.getBoundingClientRect().left;
583
+ const time = positionToTime(measure.width, boundaries, x);
584
+ const action = model == null ? void 0 : model.actions.findLast((action2) => action2.startTime <= time);
585
+ if (!event.buttons) {
586
+ setDragWindow(void 0);
587
+ return;
588
+ }
589
+ if (action)
590
+ onSelected(action);
591
+ if (!dragWindow)
592
+ return;
593
+ let newDragWindow = dragWindow;
594
+ if (dragWindow.type === "resize") {
595
+ newDragWindow = { ...dragWindow, endX: x };
596
+ } else {
597
+ const delta = x - dragWindow.pivot;
598
+ let startX = dragWindow.startX + delta;
599
+ let endX = dragWindow.endX + delta;
600
+ if (startX < 0) {
601
+ startX = 0;
602
+ endX = startX + (dragWindow.endX - dragWindow.startX);
603
+ }
604
+ if (endX > measure.width) {
605
+ endX = measure.width;
606
+ startX = endX - (dragWindow.endX - dragWindow.startX);
607
+ }
608
+ newDragWindow = { ...dragWindow, startX, endX, pivot: x };
609
+ }
610
+ setDragWindow(newDragWindow);
611
+ const time1 = positionToTime(measure.width, boundaries, newDragWindow.startX);
612
+ const time2 = positionToTime(measure.width, boundaries, newDragWindow.endX);
613
+ if (time1 !== time2)
614
+ setSelectedTime({ minimum: Math.min(time1, time2), maximum: Math.max(time1, time2) });
615
+ }, [boundaries, dragWindow, measure, model, onSelected, ref, setSelectedTime]);
616
+ const onGlassPaneMouseUp = reactExports.useCallback(() => {
617
+ setPreviewPoint(void 0);
618
+ if (!dragWindow)
619
+ return;
620
+ if (dragWindow.startX !== dragWindow.endX) {
621
+ const time1 = positionToTime(measure.width, boundaries, dragWindow.startX);
622
+ const time2 = positionToTime(measure.width, boundaries, dragWindow.endX);
623
+ setSelectedTime({ minimum: Math.min(time1, time2), maximum: Math.max(time1, time2) });
624
+ } else {
625
+ const time = positionToTime(measure.width, boundaries, dragWindow.startX);
626
+ const action = model == null ? void 0 : model.actions.findLast((action2) => action2.startTime <= time);
627
+ if (action)
628
+ onSelected(action);
629
+ setSelectedTime(void 0);
630
+ }
631
+ setDragWindow(void 0);
632
+ }, [boundaries, dragWindow, measure, model, setSelectedTime, onSelected]);
633
+ const onMouseMove = reactExports.useCallback((event) => {
634
+ if (!ref.current)
635
+ return;
636
+ const x = event.clientX - ref.current.getBoundingClientRect().left;
637
+ const time = positionToTime(measure.width, boundaries, x);
638
+ const action = model == null ? void 0 : model.actions.findLast((action2) => action2.startTime <= time);
639
+ setPreviewPoint({ x, clientY: event.clientY, action, sdkLanguage });
640
+ }, [boundaries, measure, model, ref, sdkLanguage]);
641
+ const onMouseLeave = reactExports.useCallback(() => {
642
+ setPreviewPoint(void 0);
643
+ }, []);
644
+ const onPaneDoubleClick = reactExports.useCallback(() => {
645
+ setSelectedTime(void 0);
646
+ }, [setSelectedTime]);
647
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { flex: "none", borderBottom: "1px solid var(--vscode-panel-border)" }, children: [
648
+ !!dragWindow && /* @__PURE__ */ jsxRuntimeExports.jsx(
649
+ GlassPane,
650
+ {
651
+ cursor: (dragWindow == null ? void 0 : dragWindow.type) === "resize" ? "ew-resize" : "grab",
652
+ onPaneMouseUp: onGlassPaneMouseUp,
653
+ onPaneMouseMove: onGlassPaneMouseMove,
654
+ onPaneDoubleClick
655
+ }
656
+ ),
657
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
658
+ "div",
659
+ {
660
+ ref,
661
+ className: "timeline-view",
662
+ onMouseDown,
663
+ onMouseMove,
664
+ onMouseLeave,
665
+ children: [
666
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-grid", children: offsets.map((offset, index) => {
667
+ 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);
668
+ }) }),
669
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { height: 8 } }),
670
+ /* @__PURE__ */ jsxRuntimeExports.jsx(FilmStrip, { model, boundaries, previewPoint }),
671
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-bars", children: bars.map((bar, index) => {
672
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
673
+ "div",
674
+ {
675
+ className: clsx(
676
+ "timeline-bar",
677
+ bar.action && "action",
678
+ bar.resource && "network",
679
+ bar.consoleMessage && "console-message",
680
+ bar.active && "active",
681
+ bar.error && "error"
682
+ ),
683
+ style: {
684
+ left: bar.leftPosition,
685
+ width: Math.max(5, bar.rightPosition - bar.leftPosition),
686
+ top: barTop(bar),
687
+ bottom: 0
688
+ }
689
+ },
690
+ index
691
+ );
692
+ }) }),
693
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-marker", style: {
694
+ display: previewPoint !== void 0 ? "block" : "none",
695
+ left: ((previewPoint == null ? void 0 : previewPoint.x) || 0) + "px"
696
+ } }),
697
+ selectedTime && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "timeline-window", children: [
698
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-window-curtain left", style: { width: curtainLeft } }),
699
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-window-resizer", style: { left: -5 } }),
700
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-window-center", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-window-drag" }) }),
701
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-window-resizer", style: { left: 5 } }),
702
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-window-curtain right", style: { width: curtainRight } })
703
+ ] })
704
+ ]
705
+ }
706
+ )
707
+ ] });
708
+ };
709
+ function calculateDividerOffsets(clientWidth, boundaries) {
710
+ const minimumGap = 64;
711
+ let dividerCount = clientWidth / minimumGap;
712
+ const boundarySpan = boundaries.maximum - boundaries.minimum;
713
+ const pixelsPerMillisecond = clientWidth / boundarySpan;
714
+ let sectionTime = boundarySpan / dividerCount;
715
+ const logSectionTime = Math.ceil(Math.log(sectionTime) / Math.LN10);
716
+ sectionTime = Math.pow(10, logSectionTime);
717
+ if (sectionTime * pixelsPerMillisecond >= 5 * minimumGap)
718
+ sectionTime = sectionTime / 5;
719
+ if (sectionTime * pixelsPerMillisecond >= 2 * minimumGap)
720
+ sectionTime = sectionTime / 2;
721
+ const firstDividerTime = boundaries.minimum;
722
+ let lastDividerTime = boundaries.maximum;
723
+ lastDividerTime += minimumGap / pixelsPerMillisecond;
724
+ dividerCount = Math.ceil((lastDividerTime - firstDividerTime) / sectionTime);
725
+ if (!sectionTime)
726
+ dividerCount = 0;
727
+ const offsets = [];
728
+ for (let i = 0; i < dividerCount; ++i) {
729
+ const time = firstDividerTime + sectionTime * i;
730
+ offsets.push({ position: timeToPosition(clientWidth, boundaries, time), time });
731
+ }
732
+ return offsets;
733
+ }
734
+ function timeToPosition(clientWidth, boundaries, time) {
735
+ return (time - boundaries.minimum) / (boundaries.maximum - boundaries.minimum) * clientWidth;
736
+ }
737
+ function positionToTime(clientWidth, boundaries, x) {
738
+ return x / clientWidth * (boundaries.maximum - boundaries.minimum) + boundaries.minimum;
739
+ }
740
+ function barTop(bar) {
741
+ return bar.resource ? 25 : 20;
742
+ }
743
+ const MetadataView = ({ model }) => {
744
+ var _a, _b;
745
+ if (!model)
746
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, {});
747
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { "data-testid": "metadata-view", className: "vbox", style: { flexShrink: 0 }, children: [
748
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-section", style: { paddingTop: 2 }, children: "Time" }),
749
+ !!model.wallTime && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
750
+ "start time:",
751
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value datetime", title: new Date(model.wallTime).toLocaleString(), children: new Date(model.wallTime).toLocaleString() })
752
+ ] }),
753
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
754
+ "duration:",
755
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value number", title: msToString(model.endTime - model.startTime), children: msToString(model.endTime - model.startTime) })
756
+ ] }),
757
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-section", children: "Browser" }),
758
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
759
+ "engine:",
760
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value string", title: model.browserName, children: model.browserName })
761
+ ] }),
762
+ model.channel && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
763
+ "channel:",
764
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value string", title: model.channel, children: model.channel })
765
+ ] }),
766
+ model.platform && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
767
+ "platform:",
768
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value string", title: model.platform, children: model.platform })
769
+ ] }),
770
+ model.options.userAgent && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
771
+ "user agent:",
772
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value datetime", title: model.options.userAgent, children: model.options.userAgent })
773
+ ] }),
774
+ model.options.baseURL && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
775
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-section", style: { paddingTop: 2 }, children: "Config" }),
776
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
777
+ "baseURL:",
778
+ /* @__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 })
779
+ ] })
780
+ ] }),
781
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-section", children: "Viewport" }),
782
+ model.options.viewport && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
783
+ "width:",
784
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value number", title: String(!!((_a = model.options.viewport) == null ? void 0 : _a.width)), children: model.options.viewport.width })
785
+ ] }),
786
+ model.options.viewport && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
787
+ "height:",
788
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value number", title: String(!!((_b = model.options.viewport) == null ? void 0 : _b.height)), children: model.options.viewport.height })
789
+ ] }),
790
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
791
+ "is mobile:",
792
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value boolean", title: String(!!model.options.isMobile), children: String(!!model.options.isMobile) })
793
+ ] }),
794
+ model.options.deviceScaleFactor && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
795
+ "device scale:",
796
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value number", title: String(model.options.deviceScaleFactor), children: String(model.options.deviceScaleFactor) })
797
+ ] }),
798
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-section", children: "Counts" }),
799
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
800
+ "pages:",
801
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value number", children: model.pages.length })
802
+ ] }),
803
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
804
+ "actions:",
805
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value number", children: model.actions.length })
806
+ ] }),
807
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
808
+ "events:",
809
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value number", children: model.events.length })
810
+ ] })
811
+ ] });
812
+ };
813
+ async function loadImage(src) {
814
+ const image = new Image();
815
+ if (src) {
816
+ image.src = src;
817
+ await new Promise((f, r) => {
818
+ image.onload = f;
819
+ image.onerror = f;
820
+ });
821
+ }
822
+ return image;
823
+ }
824
+ const checkerboardStyle = {
825
+ backgroundImage: `linear-gradient(45deg, #80808020 25%, transparent 25%),
826
+ linear-gradient(-45deg, #80808020 25%, transparent 25%),
827
+ linear-gradient(45deg, transparent 75%, #80808020 75%),
828
+ linear-gradient(-45deg, transparent 75%, #80808020 75%)`,
829
+ backgroundSize: "20px 20px",
830
+ backgroundPosition: "0 0, 0 10px, 10px -10px, -10px 0px",
831
+ boxShadow: `rgb(0 0 0 / 10%) 0px 1.8px 1.9px,
832
+ rgb(0 0 0 / 15%) 0px 6.1px 6.3px,
833
+ rgb(0 0 0 / 10%) 0px -2px 4px,
834
+ rgb(0 0 0 / 15%) 0px -6.1px 12px,
835
+ rgb(0 0 0 / 25%) 0px 6px 12px`
836
+ };
837
+ const ImageDiffView = ({ diff, noTargetBlank }) => {
838
+ const [mode, setMode] = reactExports.useState(diff.diff ? "diff" : "actual");
839
+ const [showSxsDiff, setShowSxsDiff] = reactExports.useState(false);
840
+ const [expectedImage, setExpectedImage] = reactExports.useState(null);
841
+ const [actualImage, setActualImage] = reactExports.useState(null);
842
+ const [diffImage, setDiffImage] = reactExports.useState(null);
843
+ const [measure, ref] = useMeasure();
844
+ reactExports.useEffect(() => {
845
+ (async () => {
846
+ var _a, _b, _c;
847
+ setExpectedImage(await loadImage((_a = diff.expected) == null ? void 0 : _a.attachment.path));
848
+ setActualImage(await loadImage((_b = diff.actual) == null ? void 0 : _b.attachment.path));
849
+ setDiffImage(await loadImage((_c = diff.diff) == null ? void 0 : _c.attachment.path));
850
+ })();
851
+ }, [diff]);
852
+ const isLoaded = expectedImage && actualImage && diffImage;
853
+ const imageWidth = isLoaded ? Math.max(expectedImage.naturalWidth, actualImage.naturalWidth, 200) : 500;
854
+ const imageHeight = isLoaded ? Math.max(expectedImage.naturalHeight, actualImage.naturalHeight, 200) : 500;
855
+ const scale = Math.min(1, (measure.width - 30) / imageWidth);
856
+ const sxsScale = Math.min(1, (measure.width - 50) / imageWidth / 2);
857
+ const fitWidth = imageWidth * scale;
858
+ const fitHeight = imageHeight * scale;
859
+ const modeStyle = {
860
+ flex: "none",
861
+ margin: "0 10px",
862
+ cursor: "pointer",
863
+ userSelect: "none"
864
+ };
865
+ 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: [
866
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { "data-testid": "test-result-image-mismatch-tabs", style: { display: "flex", margin: "10px 0 20px" }, children: [
867
+ diff.diff && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { ...modeStyle, fontWeight: mode === "diff" ? 600 : "initial" }, onClick: () => setMode("diff"), children: "Diff" }),
868
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { ...modeStyle, fontWeight: mode === "actual" ? 600 : "initial" }, onClick: () => setMode("actual"), children: "Actual" }),
869
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { ...modeStyle, fontWeight: mode === "expected" ? 600 : "initial" }, onClick: () => setMode("expected"), children: "Expected" }),
870
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { ...modeStyle, fontWeight: mode === "sxs" ? 600 : "initial" }, onClick: () => setMode("sxs"), children: "Side by side" }),
871
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { ...modeStyle, fontWeight: mode === "slider" ? 600 : "initial" }, onClick: () => setMode("slider"), children: "Slider" })
872
+ ] }),
873
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex", justifyContent: "center", flex: "auto", minHeight: fitHeight + 60 }, children: [
874
+ diff.diff && mode === "diff" && /* @__PURE__ */ jsxRuntimeExports.jsx(ImageWithSize, { image: diffImage, alt: "Diff", canvasWidth: fitWidth, canvasHeight: fitHeight, scale }),
875
+ diff.diff && mode === "actual" && /* @__PURE__ */ jsxRuntimeExports.jsx(ImageWithSize, { image: actualImage, alt: "Actual", canvasWidth: fitWidth, canvasHeight: fitHeight, scale }),
876
+ diff.diff && mode === "expected" && /* @__PURE__ */ jsxRuntimeExports.jsx(ImageWithSize, { image: expectedImage, alt: "Expected", canvasWidth: fitWidth, canvasHeight: fitHeight, scale }),
877
+ diff.diff && mode === "slider" && /* @__PURE__ */ jsxRuntimeExports.jsx(ImageDiffSlider, { expectedImage, actualImage, canvasWidth: fitWidth, canvasHeight: fitHeight, scale }),
878
+ diff.diff && mode === "sxs" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex" }, children: [
879
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ImageWithSize, { image: expectedImage, title: "Expected", canvasWidth: sxsScale * imageWidth, canvasHeight: sxsScale * imageHeight, scale: sxsScale }),
880
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ImageWithSize, { image: showSxsDiff ? diffImage : actualImage, title: showSxsDiff ? "Diff" : "Actual", onClick: () => setShowSxsDiff(!showSxsDiff), canvasWidth: sxsScale * imageWidth, canvasHeight: sxsScale * imageHeight, scale: sxsScale })
881
+ ] }),
882
+ !diff.diff && mode === "actual" && /* @__PURE__ */ jsxRuntimeExports.jsx(ImageWithSize, { image: actualImage, title: "Actual", canvasWidth: fitWidth, canvasHeight: fitHeight, scale }),
883
+ !diff.diff && mode === "expected" && /* @__PURE__ */ jsxRuntimeExports.jsx(ImageWithSize, { image: expectedImage, title: "Expected", canvasWidth: fitWidth, canvasHeight: fitHeight, scale }),
884
+ !diff.diff && mode === "sxs" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex" }, children: [
885
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ImageWithSize, { image: expectedImage, title: "Expected", canvasWidth: sxsScale * imageWidth, canvasHeight: sxsScale * imageHeight, scale: sxsScale }),
886
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ImageWithSize, { image: actualImage, title: "Actual", canvasWidth: sxsScale * imageWidth, canvasHeight: sxsScale * imageHeight, scale: sxsScale })
887
+ ] })
888
+ ] }),
889
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { alignSelf: "start", lineHeight: "18px", marginLeft: "15px" }, children: [
890
+ /* @__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 }) }),
891
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: /* @__PURE__ */ jsxRuntimeExports.jsx("a", { target: noTargetBlank ? "" : "_blank", href: diff.actual.attachment.path, rel: "noreferrer", children: diff.actual.attachment.name }) }),
892
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: /* @__PURE__ */ jsxRuntimeExports.jsx("a", { target: noTargetBlank ? "" : "_blank", href: diff.expected.attachment.path, rel: "noreferrer", children: diff.expected.attachment.name }) })
893
+ ] })
894
+ ] }) });
895
+ };
896
+ const ImageDiffSlider = ({ expectedImage, actualImage, canvasWidth, canvasHeight, scale }) => {
897
+ const absoluteStyle = {
898
+ position: "absolute",
899
+ top: 0,
900
+ left: 0
901
+ };
902
+ const [slider, setSlider] = reactExports.useState(canvasWidth / 2);
903
+ const sameSize = expectedImage.naturalWidth === actualImage.naturalWidth && expectedImage.naturalHeight === actualImage.naturalHeight;
904
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { flex: "none", display: "flex", alignItems: "center", flexDirection: "column", userSelect: "none" }, children: [
905
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { margin: 5 }, children: [
906
+ !sameSize && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { flex: "none", margin: "0 5px" }, children: "Expected " }),
907
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: expectedImage.naturalWidth }),
908
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { flex: "none", margin: "0 5px" }, children: "x" }),
909
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: expectedImage.naturalHeight }),
910
+ !sameSize && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { flex: "none", margin: "0 5px 0 15px" }, children: "Actual " }),
911
+ !sameSize && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: actualImage.naturalWidth }),
912
+ !sameSize && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { flex: "none", margin: "0 5px" }, children: "x" }),
913
+ !sameSize && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: actualImage.naturalHeight })
914
+ ] }),
915
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { position: "relative", width: canvasWidth, height: canvasHeight, margin: 15, ...checkerboardStyle }, children: [
916
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
917
+ ResizeView,
918
+ {
919
+ orientation: "horizontal",
920
+ offsets: [slider],
921
+ setOffsets: (offsets) => setSlider(offsets[0]),
922
+ resizerColor: "#57606a80",
923
+ resizerWidth: 6
924
+ }
925
+ ),
926
+ /* @__PURE__ */ jsxRuntimeExports.jsx("img", { alt: "Expected", style: {
927
+ width: expectedImage.naturalWidth * scale,
928
+ height: expectedImage.naturalHeight * scale
929
+ }, draggable: "false", src: expectedImage.src }),
930
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { ...absoluteStyle, bottom: 0, overflow: "hidden", width: slider, ...checkerboardStyle }, children: /* @__PURE__ */ jsxRuntimeExports.jsx("img", { alt: "Actual", style: {
931
+ width: actualImage.naturalWidth * scale,
932
+ height: actualImage.naturalHeight * scale
933
+ }, draggable: "false", src: actualImage.src }) })
934
+ ] })
935
+ ] });
936
+ };
937
+ const ImageWithSize = ({ image, title, alt, canvasWidth, canvasHeight, scale, onClick }) => {
938
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { flex: "none", display: "flex", alignItems: "center", flexDirection: "column" }, children: [
939
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { margin: 5 }, children: [
940
+ title && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { flex: "none", margin: "0 5px" }, children: title }),
941
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: image.naturalWidth }),
942
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { flex: "none", margin: "0 5px" }, children: "x" }),
943
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: image.naturalHeight })
944
+ ] }),
945
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { display: "flex", flex: "none", width: canvasWidth, height: canvasHeight, margin: 15, ...checkerboardStyle }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
946
+ "img",
947
+ {
948
+ width: image.naturalWidth * scale,
949
+ height: image.naturalHeight * scale,
950
+ alt: title || alt,
951
+ style: { cursor: onClick ? "pointer" : "initial" },
952
+ draggable: "false",
953
+ src: image.src,
954
+ onClick
955
+ }
956
+ ) })
957
+ ] });
958
+ };
959
+ function isTextualMimeType(mimeType) {
960
+ return !!mimeType.match(/^(text\/.*?|application\/(json|(x-)?javascript|xml.*?|ecmascript|graphql|x-www-form-urlencoded)|image\/svg(\+xml)?|application\/.*?(\+json|\+xml))(;\s*charset=.*)?$/);
961
+ }
962
+ const Expandable = ({ title, children, setExpanded, expanded, expandOnTitleClick }) => {
963
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: clsx("expandable", expanded && "expanded"), children: [
964
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "expandable-title", onClick: () => expandOnTitleClick && setExpanded(!expanded), children: [
965
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
966
+ "div",
967
+ {
968
+ className: clsx("codicon", expanded ? "codicon-chevron-down" : "codicon-chevron-right"),
969
+ style: { cursor: "pointer", color: "var(--vscode-foreground)", marginLeft: "5px" },
970
+ onClick: () => !expandOnTitleClick && setExpanded(!expanded)
971
+ }
972
+ ),
973
+ title
974
+ ] }),
975
+ expanded && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { marginLeft: 25 }, children })
976
+ ] });
977
+ };
978
+ function linkifyText(description) {
979
+ const result = [];
980
+ let currentIndex = 0;
981
+ let match;
982
+ while ((match = kWebLinkRe.exec(description)) !== null) {
983
+ const stringBeforeMatch = description.substring(currentIndex, match.index);
984
+ if (stringBeforeMatch)
985
+ result.push(stringBeforeMatch);
986
+ const value = match[0];
987
+ result.push(renderLink(value));
988
+ currentIndex = match.index + value.length;
989
+ }
990
+ const stringAfterMatches = description.substring(currentIndex);
991
+ if (stringAfterMatches)
992
+ result.push(stringAfterMatches);
993
+ return result;
994
+ }
995
+ function renderLink(text) {
996
+ let link = text;
997
+ if (link.startsWith("www."))
998
+ link = "https://" + link;
999
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: link, target: "_blank", rel: "noopener noreferrer", children: text });
1000
+ }
1001
+ const ExpandableAttachment = ({ attachment }) => {
1002
+ const [expanded, setExpanded] = reactExports.useState(false);
1003
+ const [attachmentText, setAttachmentText] = reactExports.useState(null);
1004
+ const [placeholder, setPlaceholder] = reactExports.useState(null);
1005
+ const isTextAttachment = isTextualMimeType(attachment.contentType);
1006
+ const hasContent = !!attachment.sha1 || !!attachment.path;
1007
+ reactExports.useEffect(() => {
1008
+ if (expanded && attachmentText === null && placeholder === null) {
1009
+ setPlaceholder("Loading ...");
1010
+ fetch(attachmentURL(attachment)).then((response) => response.text()).then((text) => {
1011
+ setAttachmentText(text);
1012
+ setPlaceholder(null);
1013
+ }).catch((e) => {
1014
+ setPlaceholder("Failed to load: " + e.message);
1015
+ });
1016
+ }
1017
+ }, [expanded, attachmentText, placeholder, attachment]);
1018
+ const snippetHeight = reactExports.useMemo(() => {
1019
+ const lineCount = attachmentText ? attachmentText.split("\n").length : 0;
1020
+ return Math.min(Math.max(5, lineCount), 20) * lineHeight;
1021
+ }, [attachmentText]);
1022
+ const title = /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { style: { marginLeft: 5 }, children: [
1023
+ linkifyText(attachment.name),
1024
+ " ",
1025
+ hasContent && /* @__PURE__ */ jsxRuntimeExports.jsx("a", { style: { marginLeft: 5 }, href: downloadURL(attachment), children: "download" })
1026
+ ] });
1027
+ if (!isTextAttachment || !hasContent)
1028
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { marginLeft: 20 }, children: title });
1029
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1030
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Expandable, { title, expanded, setExpanded, expandOnTitleClick: true, children: placeholder && /* @__PURE__ */ jsxRuntimeExports.jsx("i", { children: placeholder }) }),
1031
+ expanded && attachmentText !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "vbox", style: { height: snippetHeight }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
1032
+ CodeMirrorWrapper,
1033
+ {
1034
+ text: attachmentText,
1035
+ readOnly: true,
1036
+ mimeType: attachment.contentType,
1037
+ linkify: true,
1038
+ lineNumbers: true,
1039
+ wrapLines: false
1040
+ }
1041
+ ) })
1042
+ ] });
1043
+ };
1044
+ const AttachmentsTab = ({ model }) => {
1045
+ const { diffMap, screenshots, attachments } = reactExports.useMemo(() => {
1046
+ const attachments2 = /* @__PURE__ */ new Set();
1047
+ const screenshots2 = /* @__PURE__ */ new Set();
1048
+ for (const action of (model == null ? void 0 : model.actions) || []) {
1049
+ const traceUrl = action.context.traceUrl;
1050
+ for (const attachment of action.attachments || [])
1051
+ attachments2.add({ ...attachment, traceUrl });
1052
+ }
1053
+ const diffMap2 = /* @__PURE__ */ new Map();
1054
+ for (const attachment of attachments2) {
1055
+ if (!attachment.path && !attachment.sha1)
1056
+ continue;
1057
+ const match = attachment.name.match(/^(.*)-(expected|actual|diff)\.png$/);
1058
+ if (match) {
1059
+ const name = match[1];
1060
+ const type = match[2];
1061
+ const entry = diffMap2.get(name) || { expected: void 0, actual: void 0, diff: void 0 };
1062
+ entry[type] = attachment;
1063
+ diffMap2.set(name, entry);
1064
+ attachments2.delete(attachment);
1065
+ } else if (attachment.contentType.startsWith("image/")) {
1066
+ screenshots2.add(attachment);
1067
+ attachments2.delete(attachment);
1068
+ }
1069
+ }
1070
+ return { diffMap: diffMap2, attachments: attachments2, screenshots: screenshots2 };
1071
+ }, [model]);
1072
+ if (!diffMap.size && !screenshots.size && !attachments.size)
1073
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(PlaceholderPanel, { text: "No attachments" });
1074
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "attachments-tab", children: [
1075
+ [...diffMap.values()].map(({ expected, actual, diff }) => {
1076
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1077
+ expected && actual && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "attachments-section", children: "Image diff" }),
1078
+ expected && actual && /* @__PURE__ */ jsxRuntimeExports.jsx(ImageDiffView, { noTargetBlank: true, diff: {
1079
+ name: "Image diff",
1080
+ expected: { attachment: { ...expected, path: downloadURL(expected) }, title: "Expected" },
1081
+ actual: { attachment: { ...actual, path: downloadURL(actual) } },
1082
+ diff: diff ? { attachment: { ...diff, path: downloadURL(diff) } } : void 0
1083
+ } })
1084
+ ] });
1085
+ }),
1086
+ screenshots.size ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "attachments-section", children: "Screenshots" }) : void 0,
1087
+ [...screenshots.values()].map((a, i) => {
1088
+ const url = attachmentURL(a);
1089
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "attachment-item", children: [
1090
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: /* @__PURE__ */ jsxRuntimeExports.jsx("img", { draggable: "false", src: url }) }),
1091
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: /* @__PURE__ */ jsxRuntimeExports.jsx("a", { target: "_blank", href: url, rel: "noreferrer", children: a.name }) })
1092
+ ] }, `screenshot-${i}`);
1093
+ }),
1094
+ attachments.size ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "attachments-section", children: "Attachments" }) : void 0,
1095
+ [...attachments.values()].map((a, i) => {
1096
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "attachment-item", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ExpandableAttachment, { attachment: a }) }, attachmentKey(a, i));
1097
+ })
1098
+ ] });
1099
+ };
1100
+ function attachmentURL(attachment, queryParams = {}) {
1101
+ const params = new URLSearchParams(queryParams);
1102
+ if (attachment.sha1) {
1103
+ params.set("trace", attachment.traceUrl);
1104
+ return "sha1/" + attachment.sha1 + "?" + params.toString();
1105
+ }
1106
+ params.set("path", attachment.path);
1107
+ return "file?" + params.toString();
1108
+ }
1109
+ function downloadURL(attachment) {
1110
+ const params = { dn: attachment.name };
1111
+ if (attachment.contentType)
1112
+ params.dct = attachment.contentType;
1113
+ return attachmentURL(attachment, params);
1114
+ }
1115
+ function attachmentKey(attachment, index) {
1116
+ return index + "-" + (attachment.sha1 ? `sha1-` + attachment.sha1 : `path-` + attachment.path);
1117
+ }
1118
+ const AnnotationsTab = ({ annotations }) => {
1119
+ if (!annotations.length)
1120
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(PlaceholderPanel, { text: "No annotations" });
1121
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "annotations-tab", children: annotations.map((annotation, i) => {
1122
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "annotation-item", children: [
1123
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { fontWeight: "bold" }, children: annotation.type }),
1124
+ annotation.description && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
1125
+ ": ",
1126
+ linkifyText(annotation.description)
1127
+ ] })
1128
+ ] }, `annotation-${i}`);
1129
+ }) });
1130
+ };
1131
+ function testStatusIcon(status) {
1132
+ if (status === "scheduled")
1133
+ return "codicon-clock";
1134
+ if (status === "running")
1135
+ return "codicon-loading";
1136
+ if (status === "failed")
1137
+ return "codicon-error";
1138
+ if (status === "passed")
1139
+ return "codicon-check";
1140
+ if (status === "skipped")
1141
+ return "codicon-circle-slash";
1142
+ return "codicon-circle-outline";
1143
+ }
1144
+ function testStatusText(status) {
1145
+ if (status === "scheduled")
1146
+ return "Pending";
1147
+ if (status === "running")
1148
+ return "Running";
1149
+ if (status === "failed")
1150
+ return "Failed";
1151
+ if (status === "passed")
1152
+ return "Passed";
1153
+ if (status === "skipped")
1154
+ return "Skipped";
1155
+ return "Did not run";
1156
+ }
1157
+ const Workbench = ({ model, showSourcesFirst, rootDir, fallbackLocation, isLive, hideTimeline, status, annotations, inert, openPage, onOpenExternally, revealSource, showSettings }) => {
1158
+ var _a;
1159
+ const [selectedCallId, setSelectedCallId] = reactExports.useState(void 0);
1160
+ const [revealedError, setRevealedError] = reactExports.useState(void 0);
1161
+ const [highlightedCallId, setHighlightedCallId] = reactExports.useState();
1162
+ const [highlightedEntry, setHighlightedEntry] = reactExports.useState();
1163
+ const [highlightedConsoleMessage, setHighlightedConsoleMessage] = reactExports.useState();
1164
+ const [selectedNavigatorTab, setSelectedNavigatorTab] = reactExports.useState("actions");
1165
+ const [selectedPropertiesTab, setSelectedPropertiesTab] = useSetting("propertiesTab", showSourcesFirst ? "source" : "call");
1166
+ const [isInspecting, setIsInspectingState] = reactExports.useState(false);
1167
+ const [highlightedLocator, setHighlightedLocator] = reactExports.useState("");
1168
+ const [selectedTime, setSelectedTime] = reactExports.useState();
1169
+ const [sidebarLocation, setSidebarLocation] = useSetting("propertiesSidebarLocation", "bottom");
1170
+ const showScreenshot = false;
1171
+ const setSelectedAction = reactExports.useCallback((action) => {
1172
+ setSelectedCallId(action == null ? void 0 : action.callId);
1173
+ setRevealedError(void 0);
1174
+ }, []);
1175
+ const highlightedAction = reactExports.useMemo(() => {
1176
+ return model == null ? void 0 : model.actions.find((a) => a.callId === highlightedCallId);
1177
+ }, [model, highlightedCallId]);
1178
+ const setHighlightedAction = reactExports.useCallback((highlightedAction2) => {
1179
+ setHighlightedCallId(highlightedAction2 == null ? void 0 : highlightedAction2.callId);
1180
+ }, []);
1181
+ const sources = reactExports.useMemo(() => (model == null ? void 0 : model.sources) || /* @__PURE__ */ new Map(), [model]);
1182
+ reactExports.useEffect(() => {
1183
+ setSelectedTime(void 0);
1184
+ setRevealedError(void 0);
1185
+ }, [model]);
1186
+ const selectedAction = reactExports.useMemo(() => {
1187
+ if (selectedCallId) {
1188
+ const action = model == null ? void 0 : model.actions.find((a) => a.callId === selectedCallId);
1189
+ if (action)
1190
+ return action;
1191
+ }
1192
+ const failedAction = model == null ? void 0 : model.failedAction();
1193
+ if (failedAction)
1194
+ return failedAction;
1195
+ if (model == null ? void 0 : model.actions.length) {
1196
+ let index = model.actions.length - 1;
1197
+ for (let i = 0; i < model.actions.length; ++i) {
1198
+ if (model.actions[i].apiName === "After Hooks" && i) {
1199
+ index = i - 1;
1200
+ break;
1201
+ }
1202
+ }
1203
+ return model.actions[index];
1204
+ }
1205
+ }, [model, selectedCallId]);
1206
+ const revealedStack = reactExports.useMemo(() => {
1207
+ if (revealedError)
1208
+ return revealedError.stack;
1209
+ return selectedAction == null ? void 0 : selectedAction.stack;
1210
+ }, [selectedAction, revealedError]);
1211
+ const activeAction = reactExports.useMemo(() => {
1212
+ return highlightedAction || selectedAction;
1213
+ }, [selectedAction, highlightedAction]);
1214
+ const onActionSelected = reactExports.useCallback((action) => {
1215
+ setSelectedAction(action);
1216
+ setHighlightedAction(void 0);
1217
+ }, [setSelectedAction, setHighlightedAction]);
1218
+ const selectPropertiesTab = reactExports.useCallback((tab) => {
1219
+ setSelectedPropertiesTab(tab);
1220
+ if (tab !== "inspector")
1221
+ setIsInspectingState(false);
1222
+ }, [setSelectedPropertiesTab]);
1223
+ const setIsInspecting = reactExports.useCallback((value) => {
1224
+ if (!isInspecting && value)
1225
+ selectPropertiesTab("inspector");
1226
+ setIsInspectingState(value);
1227
+ }, [setIsInspectingState, selectPropertiesTab, isInspecting]);
1228
+ const locatorPicked = reactExports.useCallback((locator) => {
1229
+ setHighlightedLocator(locator);
1230
+ selectPropertiesTab("inspector");
1231
+ }, [selectPropertiesTab]);
1232
+ reactExports.useEffect(() => {
1233
+ if (revealSource)
1234
+ selectPropertiesTab("source");
1235
+ }, [revealSource, selectPropertiesTab]);
1236
+ const consoleModel = useConsoleTabModel(model, selectedTime);
1237
+ const networkModel = useNetworkTabModel(model, selectedTime);
1238
+ const errorsModel = useErrorsTabModel(model);
1239
+ const attachments = reactExports.useMemo(() => {
1240
+ return (model == null ? void 0 : model.actions.map((a) => a.attachments || []).flat()) || [];
1241
+ }, [model]);
1242
+ const sdkLanguage = (model == null ? void 0 : model.sdkLanguage) || "javascript";
1243
+ const inspectorTab = {
1244
+ id: "inspector",
1245
+ title: "Locator",
1246
+ render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(
1247
+ InspectorTab,
1248
+ {
1249
+ showScreenshot,
1250
+ sdkLanguage,
1251
+ setIsInspecting,
1252
+ highlightedLocator,
1253
+ setHighlightedLocator
1254
+ }
1255
+ )
1256
+ };
1257
+ const callTab = {
1258
+ id: "call",
1259
+ title: "Call",
1260
+ render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(CallTab, { action: activeAction, sdkLanguage })
1261
+ };
1262
+ const logTab = {
1263
+ id: "log",
1264
+ title: "Log",
1265
+ render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(LogTab, { action: activeAction, isLive })
1266
+ };
1267
+ const errorsTab = {
1268
+ id: "errors",
1269
+ title: "Errors",
1270
+ errorCount: errorsModel.errors.size,
1271
+ render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorsTab, { errorsModel, sdkLanguage, revealInSource: (error) => {
1272
+ if (error.action)
1273
+ setSelectedAction(error.action);
1274
+ else
1275
+ setRevealedError(error);
1276
+ selectPropertiesTab("source");
1277
+ } })
1278
+ };
1279
+ let fallbackSourceErrorCount = void 0;
1280
+ if (!selectedAction && fallbackLocation)
1281
+ fallbackSourceErrorCount = (_a = fallbackLocation.source) == null ? void 0 : _a.errors.length;
1282
+ const sourceTab = {
1283
+ id: "source",
1284
+ title: "Source",
1285
+ errorCount: fallbackSourceErrorCount,
1286
+ render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(
1287
+ SourceTab,
1288
+ {
1289
+ stack: revealedStack,
1290
+ sources,
1291
+ rootDir,
1292
+ stackFrameLocation: sidebarLocation === "bottom" ? "right" : "bottom",
1293
+ fallbackLocation,
1294
+ onOpenExternally
1295
+ }
1296
+ )
1297
+ };
1298
+ const consoleTab = {
1299
+ id: "console",
1300
+ title: "Console",
1301
+ count: consoleModel.entries.length,
1302
+ render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(
1303
+ ConsoleTab,
1304
+ {
1305
+ consoleModel,
1306
+ boundaries,
1307
+ selectedTime,
1308
+ onAccepted: (m) => setSelectedTime({ minimum: m.timestamp, maximum: m.timestamp }),
1309
+ onEntryHovered: setHighlightedConsoleMessage
1310
+ }
1311
+ )
1312
+ };
1313
+ const networkTab = {
1314
+ id: "network",
1315
+ title: "Network",
1316
+ count: networkModel.resources.length,
1317
+ render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(NetworkTab, { boundaries, networkModel, onEntryHovered: setHighlightedEntry })
1318
+ };
1319
+ const attachmentsTab = {
1320
+ id: "attachments",
1321
+ title: "Attachments",
1322
+ count: attachments.length,
1323
+ render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(AttachmentsTab, { model })
1324
+ };
1325
+ const tabs = [
1326
+ inspectorTab,
1327
+ callTab,
1328
+ logTab,
1329
+ errorsTab,
1330
+ consoleTab,
1331
+ networkTab,
1332
+ sourceTab,
1333
+ attachmentsTab
1334
+ ];
1335
+ if (annotations !== void 0) {
1336
+ const annotationsTab = {
1337
+ id: "annotations",
1338
+ title: "Annotations",
1339
+ count: annotations.length,
1340
+ render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(AnnotationsTab, { annotations })
1341
+ };
1342
+ tabs.push(annotationsTab);
1343
+ }
1344
+ if (showSourcesFirst) {
1345
+ const sourceTabIndex = tabs.indexOf(sourceTab);
1346
+ tabs.splice(sourceTabIndex, 1);
1347
+ tabs.splice(1, 0, sourceTab);
1348
+ }
1349
+ const { boundaries } = reactExports.useMemo(() => {
1350
+ const boundaries2 = { minimum: (model == null ? void 0 : model.startTime) || 0, maximum: (model == null ? void 0 : model.endTime) || 3e4 };
1351
+ if (boundaries2.minimum > boundaries2.maximum) {
1352
+ boundaries2.minimum = 0;
1353
+ boundaries2.maximum = 3e4;
1354
+ }
1355
+ boundaries2.maximum += (boundaries2.maximum - boundaries2.minimum) / 20;
1356
+ return { boundaries: boundaries2 };
1357
+ }, [model]);
1358
+ let time = 0;
1359
+ if (!isLive && model && model.endTime >= 0)
1360
+ time = model.endTime - model.startTime;
1361
+ else if (model && model.wallTime)
1362
+ time = Date.now() - model.wallTime;
1363
+ const actionsTab = {
1364
+ id: "actions",
1365
+ title: "Actions",
1366
+ component: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "vbox", children: [
1367
+ status && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "workbench-run-status", children: [
1368
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: clsx("codicon", testStatusIcon(status)) }),
1369
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: testStatusText(status) }),
1370
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "spacer" }),
1371
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "workbench-run-duration", children: time ? msToString(time) : "" })
1372
+ ] }),
1373
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1374
+ ActionList,
1375
+ {
1376
+ sdkLanguage,
1377
+ actions: (model == null ? void 0 : model.actions) || [],
1378
+ selectedAction: model ? selectedAction : void 0,
1379
+ selectedTime,
1380
+ setSelectedTime,
1381
+ onSelected: onActionSelected,
1382
+ onHighlighted: setHighlightedAction,
1383
+ revealConsole: () => selectPropertiesTab("console"),
1384
+ isLive
1385
+ }
1386
+ )
1387
+ ] })
1388
+ };
1389
+ const metadataTab = {
1390
+ id: "metadata",
1391
+ title: "Metadata",
1392
+ component: /* @__PURE__ */ jsxRuntimeExports.jsx(MetadataView, { model })
1393
+ };
1394
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "vbox workbench", ...inert ? { inert: "true" } : {}, children: [
1395
+ !hideTimeline && /* @__PURE__ */ jsxRuntimeExports.jsx(
1396
+ Timeline,
1397
+ {
1398
+ model,
1399
+ consoleEntries: consoleModel.entries,
1400
+ boundaries,
1401
+ highlightedAction,
1402
+ highlightedEntry,
1403
+ highlightedConsoleEntry: highlightedConsoleMessage,
1404
+ onSelected: onActionSelected,
1405
+ sdkLanguage,
1406
+ selectedTime,
1407
+ setSelectedTime
1408
+ }
1409
+ ),
1410
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1411
+ SplitView,
1412
+ {
1413
+ sidebarSize: 250,
1414
+ orientation: sidebarLocation === "bottom" ? "vertical" : "horizontal",
1415
+ settingName: "propertiesSidebar",
1416
+ main: /* @__PURE__ */ jsxRuntimeExports.jsx(
1417
+ SplitView,
1418
+ {
1419
+ sidebarSize: 250,
1420
+ orientation: "horizontal",
1421
+ sidebarIsFirst: true,
1422
+ settingName: "actionListSidebar",
1423
+ main: /* @__PURE__ */ jsxRuntimeExports.jsx(
1424
+ SnapshotTabsView,
1425
+ {
1426
+ action: activeAction,
1427
+ model,
1428
+ sdkLanguage,
1429
+ testIdAttributeName: (model == null ? void 0 : model.testIdAttributeName) || "data-testid",
1430
+ isInspecting,
1431
+ setIsInspecting,
1432
+ highlightedLocator,
1433
+ setHighlightedLocator: locatorPicked,
1434
+ openPage
1435
+ }
1436
+ ),
1437
+ sidebar: /* @__PURE__ */ jsxRuntimeExports.jsx(
1438
+ TabbedPane,
1439
+ {
1440
+ tabs: [actionsTab, metadataTab],
1441
+ selectedTab: selectedNavigatorTab,
1442
+ setSelectedTab: setSelectedNavigatorTab
1443
+ }
1444
+ )
1445
+ }
1446
+ ),
1447
+ sidebar: /* @__PURE__ */ jsxRuntimeExports.jsx(
1448
+ TabbedPane,
1449
+ {
1450
+ tabs,
1451
+ selectedTab: selectedPropertiesTab,
1452
+ setSelectedTab: selectPropertiesTab,
1453
+ rightToolbar: [
1454
+ sidebarLocation === "bottom" ? /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { title: "Dock to right", icon: "layout-sidebar-right-off", onClick: () => {
1455
+ setSidebarLocation("right");
1456
+ } }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { title: "Dock to bottom", icon: "layout-panel-off", onClick: () => {
1457
+ setSidebarLocation("bottom");
1458
+ } })
1459
+ ],
1460
+ mode: sidebarLocation === "bottom" ? "default" : "select"
1461
+ }
1462
+ )
1463
+ }
1464
+ )
1465
+ ] });
1466
+ };
1467
+ export {
1468
+ Expandable as E,
1469
+ TreeView as T,
1470
+ Workbench as W,
1471
+ testStatusIcon as t
1472
+ };
1473
+ //# sourceMappingURL=workbench-BcgGQnKb.js.map