@checkly/playwright-core 1.48.10-alpha → 1.48.21

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 (60) hide show
  1. package/lib/checkly/fetch.js +3 -10
  2. package/lib/cli/program.js +4 -2
  3. package/lib/generated/injectedScriptSource.js +1 -1
  4. package/lib/generated/pollingRecorderSource.js +1 -1
  5. package/lib/protocol/validator.js +1 -0
  6. package/lib/server/fetch.js +1 -1
  7. package/lib/server/recorder/recorderApp.js +1 -1
  8. package/lib/server/recorder.js +2 -0
  9. package/lib/vite/recorder/assets/{codeMirrorModule-CND2fZ5Q.js → codeMirrorModule-d0KhC1qL.js} +11 -11
  10. package/lib/vite/recorder/assets/{index-CEc83sSS.js → index-Bxxcmxlu.js} +2 -2
  11. package/lib/vite/recorder/index.html +1 -1
  12. package/lib/vite/traceViewer/assets/codeMirrorModule-BTYWvxEC.js +16437 -0
  13. package/lib/vite/traceViewer/assets/codeMirrorModule-DGE2kpkE.js +16443 -0
  14. package/lib/vite/traceViewer/assets/codeMirrorModule-DZoSgqUd.js +24 -0
  15. package/lib/vite/traceViewer/assets/codeMirrorModule-DblsdhjA.js +16449 -0
  16. package/lib/vite/traceViewer/assets/codeMirrorModule-DtXZtbmO.js +16437 -0
  17. package/lib/vite/traceViewer/assets/codeMirrorModule-lDjkI8Ax.js +24 -0
  18. package/lib/vite/traceViewer/assets/inspectorTab-BB2Bm-wy.js +17361 -0
  19. package/lib/vite/traceViewer/assets/inspectorTab-BHcfR9dD.js +64 -0
  20. package/lib/vite/traceViewer/assets/inspectorTab-BPzhNk9r.js +64 -0
  21. package/lib/vite/traceViewer/assets/inspectorTab-CHcHvp_a.js +17361 -0
  22. package/lib/vite/traceViewer/assets/inspectorTab-C_OTuI8x.js +17361 -0
  23. package/lib/vite/traceViewer/assets/inspectorTab-DOc4D3cX.js +17361 -0
  24. package/lib/vite/traceViewer/assets/workbench-CWtpwfKK.js +1473 -0
  25. package/lib/vite/traceViewer/assets/workbench-DLv_q9ji.js +9 -0
  26. package/lib/vite/traceViewer/assets/workbench-DZqNXdoV.js +9 -0
  27. package/lib/vite/traceViewer/assets/workbench-DjoIOtwK.js +1473 -0
  28. package/lib/vite/traceViewer/assets/workbench-I4s6sWjN.js +1473 -0
  29. package/lib/vite/traceViewer/assets/workbench-M-Dh_RgU.js +1473 -0
  30. package/lib/vite/traceViewer/embedded.BIubxTi3.js +2 -0
  31. package/lib/vite/traceViewer/embedded.CHH7D63q.js +106 -0
  32. package/lib/vite/traceViewer/embedded.DnD_eIZU.js +106 -0
  33. package/lib/vite/traceViewer/embedded.Dxe2heQk.js +2 -0
  34. package/lib/vite/traceViewer/embedded.Zu332ZC1.js +106 -0
  35. package/lib/vite/traceViewer/embedded.html +3 -3
  36. package/lib/vite/traceViewer/embedded.ymLJ2mBS.js +106 -0
  37. package/lib/vite/traceViewer/index.Bfh46hDK.js +197 -0
  38. package/lib/vite/traceViewer/index.C8ZWP1Qw.js +197 -0
  39. package/lib/vite/traceViewer/index.CB297BuW.js +2 -0
  40. package/lib/vite/traceViewer/index.CLxsp2W_.js +197 -0
  41. package/lib/vite/traceViewer/index.DPD22sZn.js +2 -0
  42. package/lib/vite/traceViewer/index.UtHmfPiA.js +197 -0
  43. package/lib/vite/traceViewer/index.html +3 -3
  44. package/lib/vite/traceViewer/recorder.BHq8OXiu.js +551 -0
  45. package/lib/vite/traceViewer/recorder.BWH6blRw.js +551 -0
  46. package/lib/vite/traceViewer/recorder.BaRuS6Pc.js +2 -0
  47. package/lib/vite/traceViewer/recorder.C88JDknq.js +2 -0
  48. package/lib/vite/traceViewer/recorder.Fwf59ZKh.js +551 -0
  49. package/lib/vite/traceViewer/recorder.html +2 -2
  50. package/lib/vite/traceViewer/recorder.zV_xPHM4.js +551 -0
  51. package/lib/vite/traceViewer/sw.bundle.js +3 -3
  52. package/lib/vite/traceViewer/uiMode.2tr9k625.js +5 -0
  53. package/lib/vite/traceViewer/uiMode.B11wexdJ.js +5 -0
  54. package/lib/vite/traceViewer/uiMode.BH2Nj2h0.js +1724 -0
  55. package/lib/vite/traceViewer/uiMode.CBRJkC_K.js +1724 -0
  56. package/lib/vite/traceViewer/uiMode.CpC2B27N.js +1724 -0
  57. package/lib/vite/traceViewer/uiMode._Kp3dUXk.js +1724 -0
  58. package/lib/vite/traceViewer/uiMode.html +3 -3
  59. package/lib/vite/traceViewer/workbench.9Es1K_T7.css +549 -0
  60. package/package.json +1 -1
@@ -0,0 +1,551 @@
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 { j as jsxRuntimeExports, r as reactExports, M as MultiTraceModel, F as sha1, n as asLocator, L as ListView, g as Toolbar, T as ToolbarButton, H as ToolbarSeparator, J as copy, t as toggleTheme, S as SplitView, D as TabbedPane, y as useConsoleTabModel, z as useNetworkTabModel, h as useSetting, A as ConsoleTab, N as NetworkTab, K as collectSnapshots, O as extendSnapshot, Q as SnapshotView, I as InspectorTab, E as SourceTab, a as applyTheme, c as createRoot } from "./assets/inspectorTab-CHcHvp_a.js";
5
+ const SourceChooser = ({ sources, fileId, setFileId }) => {
6
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("select", { className: "source-chooser", hidden: !sources.length, title: "Source chooser", value: fileId, onChange: (event) => {
7
+ setFileId(event.target.selectedOptions[0].value);
8
+ }, children: renderSourceOptions(sources) });
9
+ };
10
+ function renderSourceOptions(sources) {
11
+ const transformTitle = (title) => title.replace(/.*[/\\]([^/\\]+)/, "$1");
12
+ const renderOption = (source) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: source.id, children: transformTitle(source.label) }, source.id);
13
+ const sourcesByGroups = /* @__PURE__ */ new Map();
14
+ for (const source of sources) {
15
+ let list = sourcesByGroups.get(source.group || "Debugger");
16
+ if (!list) {
17
+ list = [];
18
+ sourcesByGroups.set(source.group || "Debugger", list);
19
+ }
20
+ list.push(source);
21
+ }
22
+ return [...sourcesByGroups.entries()].map(([group, sources2]) => /* @__PURE__ */ jsxRuntimeExports.jsx("optgroup", { label: group, children: sources2.filter((s) => (s.group || "Debugger") === group).map((source) => renderOption(source)) }, group));
23
+ }
24
+ const ModelContext = reactExports.createContext(void 0);
25
+ const ModelProvider = ({ trace, children }) => {
26
+ const [model, setModel] = reactExports.useState();
27
+ const [counter, setCounter] = reactExports.useState(0);
28
+ const pollTimer = reactExports.useRef(null);
29
+ reactExports.useEffect(() => {
30
+ if (pollTimer.current)
31
+ clearTimeout(pollTimer.current);
32
+ pollTimer.current = setTimeout(async () => {
33
+ try {
34
+ const result = await loadSingleTraceFile(trace);
35
+ if (result.sha1 !== (model == null ? void 0 : model.sha1))
36
+ setModel(result);
37
+ } catch {
38
+ setModel(void 0);
39
+ } finally {
40
+ setCounter(counter + 1);
41
+ }
42
+ }, 500);
43
+ return () => {
44
+ if (pollTimer.current)
45
+ clearTimeout(pollTimer.current);
46
+ };
47
+ }, [counter, model, trace]);
48
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(ModelContext.Provider, { value: model == null ? void 0 : model.model, children });
49
+ };
50
+ async function loadSingleTraceFile(url) {
51
+ const params = new URLSearchParams();
52
+ params.set("trace", url);
53
+ params.set("limit", "1");
54
+ const response = await fetch(`contexts?${params.toString()}`);
55
+ const contextEntries = await response.json();
56
+ const tokens = [];
57
+ for (const entry of contextEntries) {
58
+ entry.actions.forEach((a) => tokens.push(a.type + "@" + a.startTime + "-" + a.endTime));
59
+ entry.events.forEach((e) => tokens.push(e.type + "@" + e.time));
60
+ }
61
+ return { model: new MultiTraceModel(contextEntries), sha1: await sha1(tokens.join("|")) };
62
+ }
63
+ function buildFullSelector(framePath, selector) {
64
+ return [...framePath, selector].join(" >> internal:control=enter-frame >> ");
65
+ }
66
+ function traceParamsForAction(actionInContext) {
67
+ const { action } = actionInContext;
68
+ switch (action.name) {
69
+ case "navigate": {
70
+ const params = {
71
+ url: action.url
72
+ };
73
+ return { method: "goto", params };
74
+ }
75
+ case "openPage":
76
+ case "closePage":
77
+ throw new Error("Not reached");
78
+ }
79
+ const selector = buildFullSelector(actionInContext.frame.framePath, action.selector);
80
+ switch (action.name) {
81
+ case "click": {
82
+ const params = {
83
+ selector,
84
+ strict: true,
85
+ modifiers: toKeyboardModifiers(action.modifiers),
86
+ button: action.button,
87
+ clickCount: action.clickCount,
88
+ position: action.position
89
+ };
90
+ return { method: "click", params };
91
+ }
92
+ case "press": {
93
+ const params = {
94
+ selector,
95
+ strict: true,
96
+ key: [...toKeyboardModifiers(action.modifiers), action.key].join("+")
97
+ };
98
+ return { method: "press", params };
99
+ }
100
+ case "fill": {
101
+ const params = {
102
+ selector,
103
+ strict: true,
104
+ value: action.text
105
+ };
106
+ return { method: "fill", params };
107
+ }
108
+ case "setInputFiles": {
109
+ const params = {
110
+ selector,
111
+ strict: true,
112
+ localPaths: action.files
113
+ };
114
+ return { method: "setInputFiles", params };
115
+ }
116
+ case "check": {
117
+ const params = {
118
+ selector,
119
+ strict: true
120
+ };
121
+ return { method: "check", params };
122
+ }
123
+ case "uncheck": {
124
+ const params = {
125
+ selector,
126
+ strict: true
127
+ };
128
+ return { method: "uncheck", params };
129
+ }
130
+ case "select": {
131
+ const params = {
132
+ selector,
133
+ strict: true,
134
+ options: action.options.map((option) => ({ value: option }))
135
+ };
136
+ return { method: "selectOption", params };
137
+ }
138
+ case "assertChecked": {
139
+ const params = {
140
+ selector: action.selector,
141
+ expression: "to.be.checked",
142
+ isNot: !action.checked
143
+ };
144
+ return { method: "expect", params };
145
+ }
146
+ case "assertText": {
147
+ const params = {
148
+ selector,
149
+ expression: "to.have.text",
150
+ expectedText: [],
151
+ isNot: false
152
+ };
153
+ return { method: "expect", params };
154
+ }
155
+ case "assertValue": {
156
+ const params = {
157
+ selector,
158
+ expression: "to.have.value",
159
+ expectedValue: void 0,
160
+ isNot: false
161
+ };
162
+ return { method: "expect", params };
163
+ }
164
+ case "assertVisible": {
165
+ const params = {
166
+ selector,
167
+ expression: "to.be.visible",
168
+ isNot: false
169
+ };
170
+ return { method: "expect", params };
171
+ }
172
+ }
173
+ }
174
+ function toKeyboardModifiers(modifiers) {
175
+ const result = [];
176
+ if (modifiers & 1)
177
+ result.push("Alt");
178
+ if (modifiers & 2)
179
+ result.push("ControlOrMeta");
180
+ if (modifiers & 4)
181
+ result.push("ControlOrMeta");
182
+ if (modifiers & 8)
183
+ result.push("Shift");
184
+ return result;
185
+ }
186
+ const ActionList = ListView;
187
+ const ActionListView = ({
188
+ sdkLanguage,
189
+ actions,
190
+ selectedAction,
191
+ onSelectedAction
192
+ }) => {
193
+ const render = reactExports.useCallback((action) => {
194
+ return renderAction(sdkLanguage, action);
195
+ }, [sdkLanguage]);
196
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "vbox", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
197
+ ActionList,
198
+ {
199
+ name: "actions",
200
+ items: actions,
201
+ selectedItem: selectedAction,
202
+ onSelected: onSelectedAction,
203
+ render
204
+ }
205
+ ) });
206
+ };
207
+ const renderAction = (sdkLanguage, action) => {
208
+ const { method, params } = traceParamsForAction(action);
209
+ const locator = params.selector ? asLocator(sdkLanguage || "javascript", params.selector) : void 0;
210
+ const apiName = `page.${method}`;
211
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "action-title", title: apiName, children: [
212
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: apiName }),
213
+ locator && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "action-selector", title: locator, children: locator }),
214
+ method === "goto" && params.url && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "action-url", title: params.url, children: params.url })
215
+ ] }) });
216
+ };
217
+ const BackendContext = reactExports.createContext(void 0);
218
+ const BackendProvider = ({ guid, children }) => {
219
+ const [connection, setConnection] = reactExports.useState(void 0);
220
+ const [mode, setMode] = reactExports.useState("none");
221
+ const [actions, setActions] = reactExports.useState({ actions: [], sources: [] });
222
+ const callbacks = reactExports.useRef({ setMode, setActions });
223
+ reactExports.useEffect(() => {
224
+ const wsURL = new URL(`../${guid}`, window.location.toString());
225
+ wsURL.protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
226
+ const webSocket = new WebSocket(wsURL.toString());
227
+ setConnection(new Connection(webSocket, callbacks.current));
228
+ return () => {
229
+ webSocket.close();
230
+ };
231
+ }, [guid]);
232
+ const backend = reactExports.useMemo(() => {
233
+ return connection ? { mode, actions: actions.actions, sources: actions.sources, connection } : void 0;
234
+ }, [actions, mode, connection]);
235
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(BackendContext.Provider, { value: backend, children });
236
+ };
237
+ class Connection {
238
+ constructor(webSocket, options) {
239
+ __publicField(this, "_lastId", 0);
240
+ __publicField(this, "_webSocket");
241
+ __publicField(this, "_callbacks", /* @__PURE__ */ new Map());
242
+ __publicField(this, "_options");
243
+ this._webSocket = webSocket;
244
+ this._callbacks = /* @__PURE__ */ new Map();
245
+ this._options = options;
246
+ this._webSocket.addEventListener("message", (event) => {
247
+ const message = JSON.parse(event.data);
248
+ const { id, result, error, method, params } = message;
249
+ if (id) {
250
+ const callback = this._callbacks.get(id);
251
+ if (!callback)
252
+ return;
253
+ this._callbacks.delete(id);
254
+ if (error)
255
+ callback.reject(new Error(error));
256
+ else
257
+ callback.resolve(result);
258
+ } else {
259
+ this._dispatchEvent(method, params);
260
+ }
261
+ });
262
+ }
263
+ setMode(mode) {
264
+ this._sendMessageNoReply("setMode", { mode });
265
+ }
266
+ async _sendMessage(method, params) {
267
+ const id = ++this._lastId;
268
+ const message = { id, method, params };
269
+ this._webSocket.send(JSON.stringify(message));
270
+ return new Promise((resolve, reject) => {
271
+ this._callbacks.set(id, { resolve, reject });
272
+ });
273
+ }
274
+ _sendMessageNoReply(method, params) {
275
+ this._sendMessage(method, params).catch(() => {
276
+ });
277
+ }
278
+ _dispatchEvent(method, params) {
279
+ if (method === "setMode") {
280
+ const { mode } = params;
281
+ this._options.setMode(mode);
282
+ }
283
+ if (method === "setActions") {
284
+ const { actions, sources } = params;
285
+ this._options.setActions({ actions: actions.filter((a) => a.action.name !== "openPage" && a.action.name !== "closePage"), sources });
286
+ window.playwrightSourcesEchoForTest = sources;
287
+ }
288
+ }
289
+ }
290
+ const RecorderView = () => {
291
+ const searchParams = new URLSearchParams(window.location.search);
292
+ const guid = searchParams.get("ws");
293
+ const trace = searchParams.get("trace") + ".json";
294
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(BackendProvider, { guid, children: /* @__PURE__ */ jsxRuntimeExports.jsx(ModelProvider, { trace, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Workbench, {}) }) });
295
+ };
296
+ const Workbench = () => {
297
+ const backend = reactExports.useContext(BackendContext);
298
+ const model = reactExports.useContext(ModelContext);
299
+ const [fileId, setFileId] = reactExports.useState();
300
+ const [selectedStartTime, setSelectedStartTime] = reactExports.useState(void 0);
301
+ const [isInspecting, setIsInspecting] = reactExports.useState(false);
302
+ const [highlightedLocatorInProperties, setHighlightedLocatorInProperties] = reactExports.useState("");
303
+ const [highlightedLocatorInTrace, setHighlightedLocatorInTrace] = reactExports.useState("");
304
+ const [traceCallId, setTraceCallId] = reactExports.useState();
305
+ const setSelectedAction = reactExports.useCallback((action) => {
306
+ setSelectedStartTime(action == null ? void 0 : action.startTime);
307
+ }, []);
308
+ const selectedAction = reactExports.useMemo(() => {
309
+ return backend == null ? void 0 : backend.actions.find((a) => a.startTime === selectedStartTime);
310
+ }, [backend == null ? void 0 : backend.actions, selectedStartTime]);
311
+ reactExports.useEffect(() => {
312
+ var _a;
313
+ const callId = (_a = model == null ? void 0 : model.actions.find((a) => a.endTime && a.endTime === (selectedAction == null ? void 0 : selectedAction.endTime))) == null ? void 0 : _a.callId;
314
+ if (callId)
315
+ setTraceCallId(callId);
316
+ }, [model, selectedAction]);
317
+ const source = reactExports.useMemo(() => (backend == null ? void 0 : backend.sources.find((s) => s.id === fileId)) || (backend == null ? void 0 : backend.sources[0]), [backend == null ? void 0 : backend.sources, fileId]);
318
+ const sourceLocation = reactExports.useMemo(() => {
319
+ if (!source)
320
+ return void 0;
321
+ const sourceLocation2 = {
322
+ file: "",
323
+ line: 0,
324
+ column: 0,
325
+ source: {
326
+ errors: [],
327
+ content: source.text
328
+ }
329
+ };
330
+ return sourceLocation2;
331
+ }, [source]);
332
+ const sdkLanguage = (source == null ? void 0 : source.language) || "javascript";
333
+ const { boundaries } = reactExports.useMemo(() => {
334
+ const boundaries2 = { minimum: (model == null ? void 0 : model.startTime) || 0, maximum: (model == null ? void 0 : model.endTime) || 3e4 };
335
+ if (boundaries2.minimum > boundaries2.maximum) {
336
+ boundaries2.minimum = 0;
337
+ boundaries2.maximum = 3e4;
338
+ }
339
+ boundaries2.maximum += (boundaries2.maximum - boundaries2.minimum) / 20;
340
+ return { boundaries: boundaries2 };
341
+ }, [model]);
342
+ const locatorPickedInTrace = reactExports.useCallback((locator) => {
343
+ setHighlightedLocatorInProperties(locator);
344
+ setHighlightedLocatorInTrace("");
345
+ setIsInspecting(false);
346
+ }, []);
347
+ const locatorTypedInProperties = reactExports.useCallback((locator) => {
348
+ setHighlightedLocatorInTrace(locator);
349
+ setHighlightedLocatorInProperties(locator);
350
+ }, []);
351
+ const actionList = /* @__PURE__ */ jsxRuntimeExports.jsx(
352
+ ActionListView,
353
+ {
354
+ sdkLanguage,
355
+ actions: (backend == null ? void 0 : backend.actions) || [],
356
+ selectedAction,
357
+ onSelectedAction: setSelectedAction
358
+ }
359
+ );
360
+ const actionsTab = {
361
+ id: "actions",
362
+ title: "Actions",
363
+ component: actionList
364
+ };
365
+ const toolbar = /* @__PURE__ */ jsxRuntimeExports.jsxs(Toolbar, { sidebarBackground: true, children: [
366
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { width: 4 } }),
367
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "inspect", title: "Pick locator", toggled: isInspecting, onClick: () => {
368
+ setIsInspecting(!isInspecting);
369
+ } }),
370
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "eye", title: "Assert visibility", onClick: () => {
371
+ } }),
372
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "whole-word", title: "Assert text", onClick: () => {
373
+ } }),
374
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "symbol-constant", title: "Assert value", onClick: () => {
375
+ } }),
376
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarSeparator, {}),
377
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "files", title: "Copy", disabled: !source || !source.text, onClick: () => {
378
+ if (source == null ? void 0 : source.text)
379
+ copy(source.text);
380
+ } }),
381
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { flex: "auto" } }),
382
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Target:" }),
383
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SourceChooser, { fileId, sources: (backend == null ? void 0 : backend.sources) || [], setFileId: (fileId2) => {
384
+ setFileId(fileId2);
385
+ } }),
386
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "color-mode", title: "Toggle color mode", toggled: false, onClick: () => toggleTheme() })
387
+ ] });
388
+ const sidebarTabbedPane = /* @__PURE__ */ jsxRuntimeExports.jsx(TabbedPane, { tabs: [actionsTab] });
389
+ const traceView = /* @__PURE__ */ jsxRuntimeExports.jsx(
390
+ TraceView,
391
+ {
392
+ sdkLanguage,
393
+ callId: traceCallId,
394
+ isInspecting,
395
+ setIsInspecting,
396
+ highlightedLocator: highlightedLocatorInTrace,
397
+ setHighlightedLocator: locatorPickedInTrace
398
+ }
399
+ );
400
+ const propertiesView = /* @__PURE__ */ jsxRuntimeExports.jsx(
401
+ PropertiesView,
402
+ {
403
+ sdkLanguage,
404
+ boundaries,
405
+ setIsInspecting,
406
+ highlightedLocator: highlightedLocatorInProperties,
407
+ setHighlightedLocator: locatorTypedInProperties,
408
+ sourceLocation
409
+ }
410
+ );
411
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "vbox workbench", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
412
+ SplitView,
413
+ {
414
+ sidebarSize: 250,
415
+ orientation: "horizontal",
416
+ settingName: "recorderActionListSidebar",
417
+ sidebarIsFirst: true,
418
+ main: /* @__PURE__ */ jsxRuntimeExports.jsx(
419
+ SplitView,
420
+ {
421
+ sidebarSize: 250,
422
+ orientation: "vertical",
423
+ settingName: "recorderPropertiesSidebar",
424
+ main: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "vbox", children: [
425
+ toolbar,
426
+ traceView
427
+ ] }),
428
+ sidebar: propertiesView
429
+ }
430
+ ),
431
+ sidebar: sidebarTabbedPane
432
+ }
433
+ ) });
434
+ };
435
+ const PropertiesView = ({
436
+ sdkLanguage,
437
+ boundaries,
438
+ setIsInspecting,
439
+ highlightedLocator,
440
+ setHighlightedLocator,
441
+ sourceLocation
442
+ }) => {
443
+ const model = reactExports.useContext(ModelContext);
444
+ const consoleModel = useConsoleTabModel(model, boundaries);
445
+ const networkModel = useNetworkTabModel(model, boundaries);
446
+ const sourceModel = reactExports.useRef(/* @__PURE__ */ new Map());
447
+ const [selectedPropertiesTab, setSelectedPropertiesTab] = useSetting("recorderPropertiesTab", "source");
448
+ const inspectorTab = {
449
+ id: "inspector",
450
+ title: "Locator",
451
+ render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(
452
+ InspectorTab,
453
+ {
454
+ showScreenshot: false,
455
+ sdkLanguage,
456
+ setIsInspecting,
457
+ highlightedLocator,
458
+ setHighlightedLocator
459
+ }
460
+ )
461
+ };
462
+ const sourceTab = {
463
+ id: "source",
464
+ title: "Source",
465
+ render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(
466
+ SourceTab,
467
+ {
468
+ sources: sourceModel.current,
469
+ stackFrameLocation: "right",
470
+ fallbackLocation: sourceLocation
471
+ }
472
+ )
473
+ };
474
+ const consoleTab = {
475
+ id: "console",
476
+ title: "Console",
477
+ count: consoleModel.entries.length,
478
+ render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(ConsoleTab, { boundaries, consoleModel })
479
+ };
480
+ const networkTab = {
481
+ id: "network",
482
+ title: "Network",
483
+ count: networkModel.resources.length,
484
+ render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(NetworkTab, { boundaries, networkModel })
485
+ };
486
+ const tabs = [
487
+ sourceTab,
488
+ inspectorTab,
489
+ consoleTab,
490
+ networkTab
491
+ ];
492
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
493
+ TabbedPane,
494
+ {
495
+ tabs,
496
+ selectedTab: selectedPropertiesTab,
497
+ setSelectedTab: setSelectedPropertiesTab
498
+ }
499
+ );
500
+ };
501
+ const TraceView = ({
502
+ sdkLanguage,
503
+ callId,
504
+ isInspecting,
505
+ setIsInspecting,
506
+ highlightedLocator,
507
+ setHighlightedLocator
508
+ }) => {
509
+ const model = reactExports.useContext(ModelContext);
510
+ const action = reactExports.useMemo(() => {
511
+ return model == null ? void 0 : model.actions.find((a) => a.callId === callId);
512
+ }, [model, callId]);
513
+ const snapshot = reactExports.useMemo(() => {
514
+ const snapshot2 = collectSnapshots(action);
515
+ return snapshot2.action || snapshot2.after || snapshot2.before;
516
+ }, [action]);
517
+ const snapshotUrls = reactExports.useMemo(() => {
518
+ return snapshot ? extendSnapshot(snapshot) : void 0;
519
+ }, [snapshot]);
520
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
521
+ SnapshotView,
522
+ {
523
+ sdkLanguage,
524
+ testIdAttributeName: "data-testid",
525
+ isInspecting,
526
+ setIsInspecting,
527
+ highlightedLocator,
528
+ setHighlightedLocator,
529
+ snapshotUrls
530
+ }
531
+ );
532
+ };
533
+ (async () => {
534
+ applyTheme();
535
+ if (window.location.protocol !== "file:") {
536
+ if (!navigator.serviceWorker)
537
+ throw new Error(`Service workers are not supported.
538
+ Make sure to serve the Recorder (${window.location}) via HTTPS or localhost.`);
539
+ navigator.serviceWorker.register("sw.bundle.js");
540
+ if (!navigator.serviceWorker.controller) {
541
+ await new Promise((f) => {
542
+ navigator.serviceWorker.oncontrollerchange = () => f();
543
+ });
544
+ }
545
+ setInterval(function() {
546
+ fetch("ping");
547
+ }, 1e4);
548
+ }
549
+ createRoot(document.querySelector("#root")).render(/* @__PURE__ */ jsxRuntimeExports.jsx(RecorderView, {}));
550
+ })();
551
+ //# sourceMappingURL=recorder.BWH6blRw.js.map
@@ -0,0 +1,2 @@
1
+ var H=Object.defineProperty;var W=(t,e,s)=>e in t?H(t,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):t[e]=s;var w=(t,e,s)=>W(t,typeof e!="symbol"?e+"":e,s);import{j as n,r as a,M as B,F as U,n as $,L as z,g as D,T as f,H as J,J as K,t as q,S as C,D as y,y as G,z as Q,h as X,A as Y,N as Z,K as ee,O as te,Q as se,I as oe,E as re,a as ne,c as ce}from"./assets/inspectorTab-BPzhNk9r.js";const ae=({sources:t,fileId:e,setFileId:s})=>n.jsx("select",{className:"source-chooser",hidden:!t.length,title:"Source chooser",value:e,onChange:o=>{s(o.target.selectedOptions[0].value)},children:ie(t)});function ie(t){const e=r=>r.replace(/.*[/\\]([^/\\]+)/,"$1"),s=r=>n.jsx("option",{value:r.id,children:e(r.label)},r.id),o=new Map;for(const r of t){let i=o.get(r.group||"Debugger");i||(i=[],o.set(r.group||"Debugger",i)),i.push(r)}return[...o.entries()].map(([r,i])=>n.jsx("optgroup",{label:r,children:i.filter(c=>(c.group||"Debugger")===r).map(c=>s(c))},r))}const b=a.createContext(void 0),le=({trace:t,children:e})=>{const[s,o]=a.useState(),[r,i]=a.useState(0),c=a.useRef(null);return a.useEffect(()=>(c.current&&clearTimeout(c.current),c.current=setTimeout(async()=>{try{const u=await ue(t);u.sha1!==(s==null?void 0:s.sha1)&&o(u)}catch{o(void 0)}finally{i(r+1)}},500),()=>{c.current&&clearTimeout(c.current)}),[r,s,t]),n.jsx(b.Provider,{value:s==null?void 0:s.model,children:e})};async function ue(t){const e=new URLSearchParams;e.set("trace",t),e.set("limit","1");const o=await(await fetch(`contexts?${e.toString()}`)).json(),r=[];for(const i of o)i.actions.forEach(c=>r.push(c.type+"@"+c.startTime+"-"+c.endTime)),i.events.forEach(c=>r.push(c.type+"@"+c.time));return{model:new B(o),sha1:await U(r.join("|"))}}function de(t,e){return[...t,e].join(" >> internal:control=enter-frame >> ")}function me(t){const{action:e}=t;switch(e.name){case"navigate":return{method:"goto",params:{url:e.url}};case"openPage":case"closePage":throw new Error("Not reached")}const s=de(t.frame.framePath,e.selector);switch(e.name){case"click":return{method:"click",params:{selector:s,strict:!0,modifiers:P(e.modifiers),button:e.button,clickCount:e.clickCount,position:e.position}};case"press":return{method:"press",params:{selector:s,strict:!0,key:[...P(e.modifiers),e.key].join("+")}};case"fill":return{method:"fill",params:{selector:s,strict:!0,value:e.text}};case"setInputFiles":return{method:"setInputFiles",params:{selector:s,strict:!0,localPaths:e.files}};case"check":return{method:"check",params:{selector:s,strict:!0}};case"uncheck":return{method:"uncheck",params:{selector:s,strict:!0}};case"select":return{method:"selectOption",params:{selector:s,strict:!0,options:e.options.map(r=>({value:r}))}};case"assertChecked":return{method:"expect",params:{selector:e.selector,expression:"to.be.checked",isNot:!e.checked}};case"assertText":return{method:"expect",params:{selector:s,expression:"to.have.text",expectedText:[],isNot:!1}};case"assertValue":return{method:"expect",params:{selector:s,expression:"to.have.value",expectedValue:void 0,isNot:!1}};case"assertVisible":return{method:"expect",params:{selector:s,expression:"to.be.visible",isNot:!1}}}}function P(t){const e=[];return t&1&&e.push("Alt"),t&2&&e.push("ControlOrMeta"),t&4&&e.push("ControlOrMeta"),t&8&&e.push("Shift"),e}const he=z,pe=({sdkLanguage:t,actions:e,selectedAction:s,onSelectedAction:o})=>{const r=a.useCallback(i=>xe(t,i),[t]);return n.jsx("div",{className:"vbox",children:n.jsx(he,{name:"actions",items:e,selectedItem:s,onSelected:o,render:r})})},xe=(t,e)=>{const{method:s,params:o}=me(e),r=o.selector?$(t||"javascript",o.selector):void 0,i=`page.${s}`;return n.jsx(n.Fragment,{children:n.jsxs("div",{className:"action-title",title:i,children:[n.jsx("span",{children:i}),r&&n.jsx("div",{className:"action-selector",title:r,children:r}),s==="goto"&&o.url&&n.jsx("div",{className:"action-url",title:o.url,children:o.url})]})})},L=a.createContext(void 0),ge=({guid:t,children:e})=>{const[s,o]=a.useState(void 0),[r,i]=a.useState("none"),[c,u]=a.useState({actions:[],sources:[]}),h=a.useRef({setMode:i,setActions:u});a.useEffect(()=>{const d=new URL(`../${t}`,window.location.toString());d.protocol=window.location.protocol==="https:"?"wss:":"ws:";const x=new WebSocket(d.toString());return o(new fe(x,h.current)),()=>{x.close()}},[t]);const p=a.useMemo(()=>s?{mode:r,actions:c.actions,sources:c.sources,connection:s}:void 0,[c,r,s]);return n.jsx(L.Provider,{value:p,children:e})};class fe{constructor(e,s){w(this,"_lastId",0);w(this,"_webSocket");w(this,"_callbacks",new Map);w(this,"_options");this._webSocket=e,this._callbacks=new Map,this._options=s,this._webSocket.addEventListener("message",o=>{const r=JSON.parse(o.data),{id:i,result:c,error:u,method:h,params:p}=r;if(i){const d=this._callbacks.get(i);if(!d)return;this._callbacks.delete(i),u?d.reject(new Error(u)):d.resolve(c)}else this._dispatchEvent(h,p)})}setMode(e){this._sendMessageNoReply("setMode",{mode:e})}async _sendMessage(e,s){const o=++this._lastId,r={id:o,method:e,params:s};return this._webSocket.send(JSON.stringify(r)),new Promise((i,c)=>{this._callbacks.set(o,{resolve:i,reject:c})})}_sendMessageNoReply(e,s){this._sendMessage(e,s).catch(()=>{})}_dispatchEvent(e,s){if(e==="setMode"){const{mode:o}=s;this._options.setMode(o)}if(e==="setActions"){const{actions:o,sources:r}=s;this._options.setActions({actions:o.filter(i=>i.action.name!=="openPage"&&i.action.name!=="closePage"),sources:r}),window.playwrightSourcesEchoForTest=r}}}const we=()=>{const t=new URLSearchParams(window.location.search),e=t.get("ws"),s=t.get("trace")+".json";return n.jsx(ge,{guid:e,children:n.jsx(le,{trace:s,children:n.jsx(be,{})})})},be=()=>{const t=a.useContext(L),e=a.useContext(b),[s,o]=a.useState(),[r,i]=a.useState(void 0),[c,u]=a.useState(!1),[h,p]=a.useState(""),[d,x]=a.useState(""),[v,S]=a.useState(),T=a.useCallback(l=>{i(l==null?void 0:l.startTime)},[]),g=a.useMemo(()=>t==null?void 0:t.actions.find(l=>l.startTime===r),[t==null?void 0:t.actions,r]);a.useEffect(()=>{var k;const l=(k=e==null?void 0:e.actions.find(M=>M.endTime&&M.endTime===(g==null?void 0:g.endTime)))==null?void 0:k.callId;l&&S(l)},[e,g]);const m=a.useMemo(()=>(t==null?void 0:t.sources.find(l=>l.id===s))||(t==null?void 0:t.sources[0]),[t==null?void 0:t.sources,s]),I=a.useMemo(()=>m?{file:"",line:0,column:0,source:{errors:[],content:m.text}}:void 0,[m]),j=(m==null?void 0:m.language)||"javascript",{boundaries:N}=a.useMemo(()=>{const l={minimum:(e==null?void 0:e.startTime)||0,maximum:(e==null?void 0:e.endTime)||3e4};return l.minimum>l.maximum&&(l.minimum=0,l.maximum=3e4),l.maximum+=(l.maximum-l.minimum)/20,{boundaries:l}},[e]),_=a.useCallback(l=>{p(l),x(""),u(!1)},[]),A=a.useCallback(l=>{x(l),p(l)},[]),E={id:"actions",title:"Actions",component:n.jsx(pe,{sdkLanguage:j,actions:(t==null?void 0:t.actions)||[],selectedAction:g,onSelectedAction:T})},R=n.jsxs(D,{sidebarBackground:!0,children:[n.jsx("div",{style:{width:4}}),n.jsx(f,{icon:"inspect",title:"Pick locator",toggled:c,onClick:()=>{u(!c)}}),n.jsx(f,{icon:"eye",title:"Assert visibility",onClick:()=>{}}),n.jsx(f,{icon:"whole-word",title:"Assert text",onClick:()=>{}}),n.jsx(f,{icon:"symbol-constant",title:"Assert value",onClick:()=>{}}),n.jsx(J,{}),n.jsx(f,{icon:"files",title:"Copy",disabled:!m||!m.text,onClick:()=>{m!=null&&m.text&&K(m.text)}}),n.jsx("div",{style:{flex:"auto"}}),n.jsx("div",{children:"Target:"}),n.jsx(ae,{fileId:s,sources:(t==null?void 0:t.sources)||[],setFileId:l=>{o(l)}}),n.jsx(f,{icon:"color-mode",title:"Toggle color mode",toggled:!1,onClick:()=>q()})]}),F=n.jsx(y,{tabs:[E]}),V=n.jsx(Se,{sdkLanguage:j,callId:v,isInspecting:c,setIsInspecting:u,highlightedLocator:d,setHighlightedLocator:_}),O=n.jsx(ve,{sdkLanguage:j,boundaries:N,setIsInspecting:u,highlightedLocator:h,setHighlightedLocator:A,sourceLocation:I});return n.jsx("div",{className:"vbox workbench",children:n.jsx(C,{sidebarSize:250,orientation:"horizontal",settingName:"recorderActionListSidebar",sidebarIsFirst:!0,main:n.jsx(C,{sidebarSize:250,orientation:"vertical",settingName:"recorderPropertiesSidebar",main:n.jsxs("div",{className:"vbox",children:[R,V]}),sidebar:O}),sidebar:F})})},ve=({sdkLanguage:t,boundaries:e,setIsInspecting:s,highlightedLocator:o,setHighlightedLocator:r,sourceLocation:i})=>{const c=a.useContext(b),u=G(c,e),h=Q(c,e),p=a.useRef(new Map),[d,x]=X("recorderPropertiesTab","source"),v={id:"inspector",title:"Locator",render:()=>n.jsx(oe,{showScreenshot:!1,sdkLanguage:t,setIsInspecting:s,highlightedLocator:o,setHighlightedLocator:r})},S={id:"source",title:"Source",render:()=>n.jsx(re,{sources:p.current,stackFrameLocation:"right",fallbackLocation:i})},T={id:"console",title:"Console",count:u.entries.length,render:()=>n.jsx(Y,{boundaries:e,consoleModel:u})},g={id:"network",title:"Network",count:h.resources.length,render:()=>n.jsx(Z,{boundaries:e,networkModel:h})},m=[S,v,T,g];return n.jsx(y,{tabs:m,selectedTab:d,setSelectedTab:x})},Se=({sdkLanguage:t,callId:e,isInspecting:s,setIsInspecting:o,highlightedLocator:r,setHighlightedLocator:i})=>{const c=a.useContext(b),u=a.useMemo(()=>c==null?void 0:c.actions.find(d=>d.callId===e),[c,e]),h=a.useMemo(()=>{const d=ee(u);return d.action||d.after||d.before},[u]),p=a.useMemo(()=>h?te(h):void 0,[h]);return n.jsx(se,{sdkLanguage:t,testIdAttributeName:"data-testid",isInspecting:s,setIsInspecting:o,highlightedLocator:r,setHighlightedLocator:i,snapshotUrls:p})};(async()=>{if(ne(),window.location.protocol!=="file:"){if(!navigator.serviceWorker)throw new Error(`Service workers are not supported.
2
+ Make sure to serve the Recorder (${window.location}) via HTTPS or localhost.`);navigator.serviceWorker.register("sw.bundle.js"),navigator.serviceWorker.controller||await new Promise(t=>{navigator.serviceWorker.oncontrollerchange=()=>t()}),setInterval(function(){fetch("ping")},1e4)}ce(document.querySelector("#root")).render(n.jsx(we,{}))})();
@@ -0,0 +1,2 @@
1
+ var H=Object.defineProperty;var W=(t,e,s)=>e in t?H(t,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):t[e]=s;var w=(t,e,s)=>W(t,typeof e!="symbol"?e+"":e,s);import{j as n,r as a,M as B,F as U,n as $,L as z,g as D,T as f,H as J,J as K,t as q,S as C,D as y,y as G,z as Q,h as X,A as Y,N as Z,K as ee,O as te,Q as se,I as oe,E as re,a as ne,c as ce}from"./assets/inspectorTab-BHcfR9dD.js";const ae=({sources:t,fileId:e,setFileId:s})=>n.jsx("select",{className:"source-chooser",hidden:!t.length,title:"Source chooser",value:e,onChange:o=>{s(o.target.selectedOptions[0].value)},children:ie(t)});function ie(t){const e=r=>r.replace(/.*[/\\]([^/\\]+)/,"$1"),s=r=>n.jsx("option",{value:r.id,children:e(r.label)},r.id),o=new Map;for(const r of t){let i=o.get(r.group||"Debugger");i||(i=[],o.set(r.group||"Debugger",i)),i.push(r)}return[...o.entries()].map(([r,i])=>n.jsx("optgroup",{label:r,children:i.filter(c=>(c.group||"Debugger")===r).map(c=>s(c))},r))}const b=a.createContext(void 0),le=({trace:t,children:e})=>{const[s,o]=a.useState(),[r,i]=a.useState(0),c=a.useRef(null);return a.useEffect(()=>(c.current&&clearTimeout(c.current),c.current=setTimeout(async()=>{try{const u=await ue(t);u.sha1!==(s==null?void 0:s.sha1)&&o(u)}catch{o(void 0)}finally{i(r+1)}},500),()=>{c.current&&clearTimeout(c.current)}),[r,s,t]),n.jsx(b.Provider,{value:s==null?void 0:s.model,children:e})};async function ue(t){const e=new URLSearchParams;e.set("trace",t),e.set("limit","1");const o=await(await fetch(`contexts?${e.toString()}`)).json(),r=[];for(const i of o)i.actions.forEach(c=>r.push(c.type+"@"+c.startTime+"-"+c.endTime)),i.events.forEach(c=>r.push(c.type+"@"+c.time));return{model:new B(o),sha1:await U(r.join("|"))}}function de(t,e){return[...t,e].join(" >> internal:control=enter-frame >> ")}function me(t){const{action:e}=t;switch(e.name){case"navigate":return{method:"goto",params:{url:e.url}};case"openPage":case"closePage":throw new Error("Not reached")}const s=de(t.frame.framePath,e.selector);switch(e.name){case"click":return{method:"click",params:{selector:s,strict:!0,modifiers:P(e.modifiers),button:e.button,clickCount:e.clickCount,position:e.position}};case"press":return{method:"press",params:{selector:s,strict:!0,key:[...P(e.modifiers),e.key].join("+")}};case"fill":return{method:"fill",params:{selector:s,strict:!0,value:e.text}};case"setInputFiles":return{method:"setInputFiles",params:{selector:s,strict:!0,localPaths:e.files}};case"check":return{method:"check",params:{selector:s,strict:!0}};case"uncheck":return{method:"uncheck",params:{selector:s,strict:!0}};case"select":return{method:"selectOption",params:{selector:s,strict:!0,options:e.options.map(r=>({value:r}))}};case"assertChecked":return{method:"expect",params:{selector:e.selector,expression:"to.be.checked",isNot:!e.checked}};case"assertText":return{method:"expect",params:{selector:s,expression:"to.have.text",expectedText:[],isNot:!1}};case"assertValue":return{method:"expect",params:{selector:s,expression:"to.have.value",expectedValue:void 0,isNot:!1}};case"assertVisible":return{method:"expect",params:{selector:s,expression:"to.be.visible",isNot:!1}}}}function P(t){const e=[];return t&1&&e.push("Alt"),t&2&&e.push("ControlOrMeta"),t&4&&e.push("ControlOrMeta"),t&8&&e.push("Shift"),e}const he=z,pe=({sdkLanguage:t,actions:e,selectedAction:s,onSelectedAction:o})=>{const r=a.useCallback(i=>xe(t,i),[t]);return n.jsx("div",{className:"vbox",children:n.jsx(he,{name:"actions",items:e,selectedItem:s,onSelected:o,render:r})})},xe=(t,e)=>{const{method:s,params:o}=me(e),r=o.selector?$(t||"javascript",o.selector):void 0,i=`page.${s}`;return n.jsx(n.Fragment,{children:n.jsxs("div",{className:"action-title",title:i,children:[n.jsx("span",{children:i}),r&&n.jsx("div",{className:"action-selector",title:r,children:r}),s==="goto"&&o.url&&n.jsx("div",{className:"action-url",title:o.url,children:o.url})]})})},L=a.createContext(void 0),ge=({guid:t,children:e})=>{const[s,o]=a.useState(void 0),[r,i]=a.useState("none"),[c,u]=a.useState({actions:[],sources:[]}),h=a.useRef({setMode:i,setActions:u});a.useEffect(()=>{const d=new URL(`../${t}`,window.location.toString());d.protocol=window.location.protocol==="https:"?"wss:":"ws:";const x=new WebSocket(d.toString());return o(new fe(x,h.current)),()=>{x.close()}},[t]);const p=a.useMemo(()=>s?{mode:r,actions:c.actions,sources:c.sources,connection:s}:void 0,[c,r,s]);return n.jsx(L.Provider,{value:p,children:e})};class fe{constructor(e,s){w(this,"_lastId",0);w(this,"_webSocket");w(this,"_callbacks",new Map);w(this,"_options");this._webSocket=e,this._callbacks=new Map,this._options=s,this._webSocket.addEventListener("message",o=>{const r=JSON.parse(o.data),{id:i,result:c,error:u,method:h,params:p}=r;if(i){const d=this._callbacks.get(i);if(!d)return;this._callbacks.delete(i),u?d.reject(new Error(u)):d.resolve(c)}else this._dispatchEvent(h,p)})}setMode(e){this._sendMessageNoReply("setMode",{mode:e})}async _sendMessage(e,s){const o=++this._lastId,r={id:o,method:e,params:s};return this._webSocket.send(JSON.stringify(r)),new Promise((i,c)=>{this._callbacks.set(o,{resolve:i,reject:c})})}_sendMessageNoReply(e,s){this._sendMessage(e,s).catch(()=>{})}_dispatchEvent(e,s){if(e==="setMode"){const{mode:o}=s;this._options.setMode(o)}if(e==="setActions"){const{actions:o,sources:r}=s;this._options.setActions({actions:o.filter(i=>i.action.name!=="openPage"&&i.action.name!=="closePage"),sources:r}),window.playwrightSourcesEchoForTest=r}}}const we=()=>{const t=new URLSearchParams(window.location.search),e=t.get("ws"),s=t.get("trace")+".json";return n.jsx(ge,{guid:e,children:n.jsx(le,{trace:s,children:n.jsx(be,{})})})},be=()=>{const t=a.useContext(L),e=a.useContext(b),[s,o]=a.useState(),[r,i]=a.useState(void 0),[c,u]=a.useState(!1),[h,p]=a.useState(""),[d,x]=a.useState(""),[v,S]=a.useState(),T=a.useCallback(l=>{i(l==null?void 0:l.startTime)},[]),g=a.useMemo(()=>t==null?void 0:t.actions.find(l=>l.startTime===r),[t==null?void 0:t.actions,r]);a.useEffect(()=>{var k;const l=(k=e==null?void 0:e.actions.find(M=>M.endTime&&M.endTime===(g==null?void 0:g.endTime)))==null?void 0:k.callId;l&&S(l)},[e,g]);const m=a.useMemo(()=>(t==null?void 0:t.sources.find(l=>l.id===s))||(t==null?void 0:t.sources[0]),[t==null?void 0:t.sources,s]),I=a.useMemo(()=>m?{file:"",line:0,column:0,source:{errors:[],content:m.text}}:void 0,[m]),j=(m==null?void 0:m.language)||"javascript",{boundaries:N}=a.useMemo(()=>{const l={minimum:(e==null?void 0:e.startTime)||0,maximum:(e==null?void 0:e.endTime)||3e4};return l.minimum>l.maximum&&(l.minimum=0,l.maximum=3e4),l.maximum+=(l.maximum-l.minimum)/20,{boundaries:l}},[e]),_=a.useCallback(l=>{p(l),x(""),u(!1)},[]),A=a.useCallback(l=>{x(l),p(l)},[]),E={id:"actions",title:"Actions",component:n.jsx(pe,{sdkLanguage:j,actions:(t==null?void 0:t.actions)||[],selectedAction:g,onSelectedAction:T})},R=n.jsxs(D,{sidebarBackground:!0,children:[n.jsx("div",{style:{width:4}}),n.jsx(f,{icon:"inspect",title:"Pick locator",toggled:c,onClick:()=>{u(!c)}}),n.jsx(f,{icon:"eye",title:"Assert visibility",onClick:()=>{}}),n.jsx(f,{icon:"whole-word",title:"Assert text",onClick:()=>{}}),n.jsx(f,{icon:"symbol-constant",title:"Assert value",onClick:()=>{}}),n.jsx(J,{}),n.jsx(f,{icon:"files",title:"Copy",disabled:!m||!m.text,onClick:()=>{m!=null&&m.text&&K(m.text)}}),n.jsx("div",{style:{flex:"auto"}}),n.jsx("div",{children:"Target:"}),n.jsx(ae,{fileId:s,sources:(t==null?void 0:t.sources)||[],setFileId:l=>{o(l)}}),n.jsx(f,{icon:"color-mode",title:"Toggle color mode",toggled:!1,onClick:()=>q()})]}),F=n.jsx(y,{tabs:[E]}),V=n.jsx(Se,{sdkLanguage:j,callId:v,isInspecting:c,setIsInspecting:u,highlightedLocator:d,setHighlightedLocator:_}),O=n.jsx(ve,{sdkLanguage:j,boundaries:N,setIsInspecting:u,highlightedLocator:h,setHighlightedLocator:A,sourceLocation:I});return n.jsx("div",{className:"vbox workbench",children:n.jsx(C,{sidebarSize:250,orientation:"horizontal",settingName:"recorderActionListSidebar",sidebarIsFirst:!0,main:n.jsx(C,{sidebarSize:250,orientation:"vertical",settingName:"recorderPropertiesSidebar",main:n.jsxs("div",{className:"vbox",children:[R,V]}),sidebar:O}),sidebar:F})})},ve=({sdkLanguage:t,boundaries:e,setIsInspecting:s,highlightedLocator:o,setHighlightedLocator:r,sourceLocation:i})=>{const c=a.useContext(b),u=G(c,e),h=Q(c,e),p=a.useRef(new Map),[d,x]=X("recorderPropertiesTab","source"),v={id:"inspector",title:"Locator",render:()=>n.jsx(oe,{showScreenshot:!1,sdkLanguage:t,setIsInspecting:s,highlightedLocator:o,setHighlightedLocator:r})},S={id:"source",title:"Source",render:()=>n.jsx(re,{sources:p.current,stackFrameLocation:"right",fallbackLocation:i})},T={id:"console",title:"Console",count:u.entries.length,render:()=>n.jsx(Y,{boundaries:e,consoleModel:u})},g={id:"network",title:"Network",count:h.resources.length,render:()=>n.jsx(Z,{boundaries:e,networkModel:h})},m=[S,v,T,g];return n.jsx(y,{tabs:m,selectedTab:d,setSelectedTab:x})},Se=({sdkLanguage:t,callId:e,isInspecting:s,setIsInspecting:o,highlightedLocator:r,setHighlightedLocator:i})=>{const c=a.useContext(b),u=a.useMemo(()=>c==null?void 0:c.actions.find(d=>d.callId===e),[c,e]),h=a.useMemo(()=>{const d=ee(u);return d.action||d.after||d.before},[u]),p=a.useMemo(()=>h?te(h):void 0,[h]);return n.jsx(se,{sdkLanguage:t,testIdAttributeName:"data-testid",isInspecting:s,setIsInspecting:o,highlightedLocator:r,setHighlightedLocator:i,snapshotUrls:p})};(async()=>{if(ne(),window.location.protocol!=="file:"){if(!navigator.serviceWorker)throw new Error(`Service workers are not supported.
2
+ Make sure to serve the Recorder (${window.location}) via HTTPS or localhost.`);navigator.serviceWorker.register("sw.bundle.js"),navigator.serviceWorker.controller||await new Promise(t=>{navigator.serviceWorker.oncontrollerchange=()=>t()}),setInterval(function(){fetch("ping")},1e4)}ce(document.querySelector("#root")).render(n.jsx(we,{}))})();