@checkly/playwright-core 1.51.16-beta.0 → 1.51.17-beta

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 (79) hide show
  1. package/lib/checkly/checklyFileSystem.js +44 -0
  2. package/lib/checkly/secretsFilter.js +19 -13
  3. package/lib/escapeRegExp.js +30 -0
  4. package/lib/generated/bindingsControllerSource.js +7 -0
  5. package/lib/generated/clockSource.js +1 -2
  6. package/lib/generated/consoleApiSource.js +1 -2
  7. package/lib/generated/injectedScriptSource.js +1 -2
  8. package/lib/generated/pollingRecorderSource.js +1 -2
  9. package/lib/generated/storageScriptSource.js +7 -0
  10. package/lib/generated/utilityScriptSource.js +1 -2
  11. package/lib/generated/webSocketMockSource.js +1 -2
  12. package/lib/secretsFilter.js +131 -0
  13. package/lib/server/bidi/third_party/bidiCommands.d.js +22 -0
  14. package/lib/server/bidi/third_party/bidiProtocolCore.js +152 -0
  15. package/lib/server/bidi/third_party/bidiProtocolPermissions.js +42 -0
  16. package/lib/server/chromium/protocol.d.js +16 -0
  17. package/lib/server/firefox/protocol.d.js +16 -0
  18. package/lib/server/har/harRecorder.js +4 -2
  19. package/lib/server/pageBinding.js +88 -0
  20. package/lib/server/recorder/recorderSignalProcessor.js +83 -0
  21. package/lib/server/registry/index.d.ts +86 -0
  22. package/lib/server/trace/recorder/tracing.js +10 -20
  23. package/lib/server/utils/fileUtils.js +65 -2
  24. package/lib/server/webkit/protocol.d.js +16 -0
  25. package/lib/utils/isomorphic/builtins.js +90 -0
  26. package/lib/utils/isomorphic/protocolFormatter.js +68 -0
  27. package/lib/utils/isomorphic/protocolMetainfo.js +321 -0
  28. package/lib/utils/isomorphic/utilityScriptSerializers.js +251 -0
  29. package/lib/vite/recorder/assets/codeMirrorModule-B9YMkrwa.js +24 -0
  30. package/lib/vite/recorder/assets/codeMirrorModule-C3UTv-Ge.css +1 -0
  31. package/lib/vite/recorder/assets/index-ELPgmkwA.js +184 -0
  32. package/lib/vite/recorder/assets/index-eHBmevrY.css +1 -0
  33. package/lib/vite/recorder/index.html +2 -2
  34. package/lib/vite/traceViewer/assets/codeMirrorModule-gU1OOCQO.js +24 -0
  35. package/lib/vite/traceViewer/assets/defaultSettingsView-B5n_FjMx.js +1 -0
  36. package/lib/vite/traceViewer/assets/inspectorTab-6Tru8Mn_.js +235 -0
  37. package/lib/vite/traceViewer/assets/workbench-B_Nj4NA2.js +25 -0
  38. package/lib/vite/traceViewer/assets/xtermModule-BoAIEibi.js +9 -0
  39. package/lib/vite/traceViewer/codeMirrorModule.C3UTv-Ge.css +1 -0
  40. package/lib/vite/traceViewer/defaultSettingsView.CO3FR0CX.css +1 -0
  41. package/lib/vite/traceViewer/embedded.DpNPH6mk.js +2 -0
  42. package/lib/vite/traceViewer/embedded.html +6 -6
  43. package/lib/vite/traceViewer/embedded.mLhjB5IF.css +1 -0
  44. package/lib/vite/traceViewer/index.CFOW-Ezb.css +1 -0
  45. package/lib/vite/traceViewer/index.CuE3SYGw.js +2 -0
  46. package/lib/vite/traceViewer/index.html +8 -8
  47. package/lib/vite/traceViewer/inspectorTab.CXDulcFG.css +1 -0
  48. package/lib/vite/traceViewer/recorder.BD-uZJs7.js +2 -0
  49. package/lib/vite/traceViewer/recorder.html +4 -4
  50. package/lib/vite/traceViewer/recorder.tn0RQdqM.css +0 -0
  51. package/lib/vite/traceViewer/sw.bundle.js +7888 -3
  52. package/lib/vite/traceViewer/uiMode.BatfzHMG.css +1 -0
  53. package/lib/vite/traceViewer/uiMode.DHrNgddz.js +5 -0
  54. package/lib/vite/traceViewer/uiMode.html +8 -8
  55. package/lib/vite/traceViewer/workbench.B9vIAzH9.css +1 -0
  56. package/lib/vite/traceViewer/xtermModule.Beg8tuEN.css +32 -0
  57. package/package.json +1 -1
  58. package/lib/vite/recorder/assets/codeMirrorModule-DrMbgOIo.js +0 -16684
  59. package/lib/vite/recorder/assets/codeMirrorModule-DuST8d_k.css +0 -344
  60. package/lib/vite/recorder/assets/index-5NM3V7eb.css +0 -2524
  61. package/lib/vite/recorder/assets/index-CT-scFHn.js +0 -16848
  62. package/lib/vite/traceViewer/assets/codeMirrorModule-CB-2okZ8.js +0 -16684
  63. package/lib/vite/traceViewer/assets/defaultSettingsView-CBiB4avC.js +0 -217
  64. package/lib/vite/traceViewer/assets/inspectorTab-CwgfffWb.js +0 -25143
  65. package/lib/vite/traceViewer/assets/workbench-CWZselvp.js +0 -2470
  66. package/lib/vite/traceViewer/assets/xtermModule-Es_gt_u7.js +0 -5994
  67. package/lib/vite/traceViewer/codeMirrorModule.DuST8d_k.css +0 -344
  68. package/lib/vite/traceViewer/defaultSettingsView.Dp3b_92q.css +0 -41
  69. package/lib/vite/traceViewer/embedded.BeldSa2G.css +0 -68
  70. package/lib/vite/traceViewer/embedded.gzudoghF.js +0 -106
  71. package/lib/vite/traceViewer/index.DilotR1h.js +0 -314
  72. package/lib/vite/traceViewer/index.QewjJ85u.css +0 -131
  73. package/lib/vite/traceViewer/inspectorTab.DnGm18kV.css +0 -3178
  74. package/lib/vite/traceViewer/recorder.DLgqV9db.css +0 -15
  75. package/lib/vite/traceViewer/recorder.DVrkq3Um.js +0 -551
  76. package/lib/vite/traceViewer/uiMode.C9_OcpPU.js +0 -1756
  77. package/lib/vite/traceViewer/uiMode.c5ORgcrX.css +0 -1424
  78. package/lib/vite/traceViewer/workbench.xUZSA8PY.css +0 -787
  79. package/lib/vite/traceViewer/xtermModule.EsaqrrTX.css +0 -209
@@ -1,1756 +0,0 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./assets/xtermModule-Es_gt_u7.js","./xtermModule.EsaqrrTX.css"])))=>i.map(i=>d[i]);
2
- import { u as useMeasure, r as reactExports, b as currentTheme, _ as __vitePreload, d as addThemeListener, e as removeThemeListener, j as jsxRuntimeExports, R as React, s as settings, f as clsx, m as msToString, g as Toolbar, T as ToolbarButton, M as MultiTraceModel, h as useSetting, S as SplitView, a as applyTheme, c as clientExports } from "./assets/inspectorTab-CwgfffWb.js";
3
- import { T as TestServerConnection, W as WebSocketTestServerTransport, D as DefaultSettingsView } from "./assets/defaultSettingsView-CBiB4avC.js";
4
- import { E as Expandable, T as TreeView, t as testStatusIcon, W as Workbench, L as LLMProvider } from "./assets/workbench-CWZselvp.js";
5
- var define_process_env_default = {};
6
- class TeleReporterReceiver {
7
- constructor(reporter, options = {}) {
8
- this.isListing = false;
9
- this._tests = /* @__PURE__ */ new Map();
10
- this._rootSuite = new TeleSuite("", "root");
11
- this._options = options;
12
- this._reporter = reporter;
13
- }
14
- reset() {
15
- this._rootSuite._entries = [];
16
- this._tests.clear();
17
- }
18
- dispatch(message) {
19
- const { method, params } = message;
20
- if (method === "onConfigure") {
21
- this._onConfigure(params.config);
22
- return;
23
- }
24
- if (method === "onProject") {
25
- this._onProject(params.project);
26
- return;
27
- }
28
- if (method === "onBegin") {
29
- this._onBegin();
30
- return;
31
- }
32
- if (method === "onTestBegin") {
33
- this._onTestBegin(params.testId, params.result);
34
- return;
35
- }
36
- if (method === "onTestEnd") {
37
- this._onTestEnd(params.test, params.result);
38
- return;
39
- }
40
- if (method === "onStepBegin") {
41
- this._onStepBegin(params.testId, params.resultId, params.step);
42
- return;
43
- }
44
- if (method === "onStepEnd") {
45
- this._onStepEnd(params.testId, params.resultId, params.step);
46
- return;
47
- }
48
- if (method === "onError") {
49
- this._onError(params.error);
50
- return;
51
- }
52
- if (method === "onStdIO") {
53
- this._onStdIO(params.type, params.testId, params.resultId, params.data, params.isBase64);
54
- return;
55
- }
56
- if (method === "onEnd")
57
- return this._onEnd(params.result);
58
- if (method === "onExit")
59
- return this._onExit();
60
- }
61
- _onConfigure(config) {
62
- var _a, _b;
63
- this._rootDir = config.rootDir;
64
- this._config = this._parseConfig(config);
65
- (_b = (_a = this._reporter).onConfigure) == null ? void 0 : _b.call(_a, this._config);
66
- }
67
- _onProject(project) {
68
- let projectSuite = this._options.mergeProjects ? this._rootSuite.suites.find((suite) => suite.project().name === project.name) : void 0;
69
- if (!projectSuite) {
70
- projectSuite = new TeleSuite(project.name, "project");
71
- this._rootSuite._addSuite(projectSuite);
72
- }
73
- projectSuite._project = this._parseProject(project);
74
- for (const suite of project.suites)
75
- this._mergeSuiteInto(suite, projectSuite);
76
- }
77
- _onBegin() {
78
- var _a, _b;
79
- (_b = (_a = this._reporter).onBegin) == null ? void 0 : _b.call(_a, this._rootSuite);
80
- }
81
- _onTestBegin(testId, payload) {
82
- var _a, _b;
83
- const test = this._tests.get(testId);
84
- if (this._options.clearPreviousResultsWhenTestBegins)
85
- test.results = [];
86
- const testResult = test._createTestResult(payload.id);
87
- testResult.retry = payload.retry;
88
- testResult.workerIndex = payload.workerIndex;
89
- testResult.parallelIndex = payload.parallelIndex;
90
- testResult.setStartTimeNumber(payload.startTime);
91
- (_b = (_a = this._reporter).onTestBegin) == null ? void 0 : _b.call(_a, test, testResult);
92
- }
93
- _onTestEnd(testEndPayload, payload) {
94
- var _a, _b, _c;
95
- const test = this._tests.get(testEndPayload.testId);
96
- test.timeout = testEndPayload.timeout;
97
- test.expectedStatus = testEndPayload.expectedStatus;
98
- test.annotations = testEndPayload.annotations;
99
- const result = test.results.find((r) => r._id === payload.id);
100
- result.duration = payload.duration;
101
- result.status = payload.status;
102
- result.errors = payload.errors;
103
- result.error = (_a = result.errors) == null ? void 0 : _a[0];
104
- result.attachments = this._parseAttachments(payload.attachments);
105
- (_c = (_b = this._reporter).onTestEnd) == null ? void 0 : _c.call(_b, test, result);
106
- result._stepMap = /* @__PURE__ */ new Map();
107
- }
108
- _onStepBegin(testId, resultId, payload) {
109
- var _a, _b;
110
- const test = this._tests.get(testId);
111
- const result = test.results.find((r) => r._id === resultId);
112
- const parentStep = payload.parentStepId ? result._stepMap.get(payload.parentStepId) : void 0;
113
- const location = this._absoluteLocation(payload.location);
114
- const step = new TeleTestStep(payload, parentStep, location, result);
115
- if (parentStep)
116
- parentStep.steps.push(step);
117
- else
118
- result.steps.push(step);
119
- result._stepMap.set(payload.id, step);
120
- (_b = (_a = this._reporter).onStepBegin) == null ? void 0 : _b.call(_a, test, result, step);
121
- }
122
- _onStepEnd(testId, resultId, payload) {
123
- var _a, _b;
124
- const test = this._tests.get(testId);
125
- const result = test.results.find((r) => r._id === resultId);
126
- const step = result._stepMap.get(payload.id);
127
- step._endPayload = payload;
128
- step.duration = payload.duration;
129
- step.error = payload.error;
130
- (_b = (_a = this._reporter).onStepEnd) == null ? void 0 : _b.call(_a, test, result, step);
131
- }
132
- _onError(error) {
133
- var _a, _b;
134
- (_b = (_a = this._reporter).onError) == null ? void 0 : _b.call(_a, error);
135
- }
136
- _onStdIO(type, testId, resultId, data, isBase64) {
137
- var _a, _b, _c, _d;
138
- const chunk = isBase64 ? globalThis.Buffer ? Buffer.from(data, "base64") : atob(data) : data;
139
- const test = testId ? this._tests.get(testId) : void 0;
140
- const result = test && resultId ? test.results.find((r) => r._id === resultId) : void 0;
141
- if (type === "stdout") {
142
- result == null ? void 0 : result.stdout.push(chunk);
143
- (_b = (_a = this._reporter).onStdOut) == null ? void 0 : _b.call(_a, chunk, test, result);
144
- } else {
145
- result == null ? void 0 : result.stderr.push(chunk);
146
- (_d = (_c = this._reporter).onStdErr) == null ? void 0 : _d.call(_c, chunk, test, result);
147
- }
148
- }
149
- async _onEnd(result) {
150
- var _a, _b;
151
- await ((_b = (_a = this._reporter).onEnd) == null ? void 0 : _b.call(_a, {
152
- status: result.status,
153
- startTime: new Date(result.startTime),
154
- duration: result.duration
155
- }));
156
- }
157
- _onExit() {
158
- var _a, _b;
159
- return (_b = (_a = this._reporter).onExit) == null ? void 0 : _b.call(_a);
160
- }
161
- _parseConfig(config) {
162
- const result = { ...baseFullConfig, ...config };
163
- if (this._options.configOverrides) {
164
- result.configFile = this._options.configOverrides.configFile;
165
- result.reportSlowTests = this._options.configOverrides.reportSlowTests;
166
- result.quiet = this._options.configOverrides.quiet;
167
- result.reporter = [...this._options.configOverrides.reporter];
168
- }
169
- return result;
170
- }
171
- _parseProject(project) {
172
- return {
173
- metadata: project.metadata,
174
- name: project.name,
175
- outputDir: this._absolutePath(project.outputDir),
176
- repeatEach: project.repeatEach,
177
- retries: project.retries,
178
- testDir: this._absolutePath(project.testDir),
179
- testIgnore: parseRegexPatterns(project.testIgnore),
180
- testMatch: parseRegexPatterns(project.testMatch),
181
- timeout: project.timeout,
182
- grep: parseRegexPatterns(project.grep),
183
- grepInvert: parseRegexPatterns(project.grepInvert),
184
- dependencies: project.dependencies,
185
- teardown: project.teardown,
186
- snapshotDir: this._absolutePath(project.snapshotDir),
187
- use: project.use
188
- };
189
- }
190
- _parseAttachments(attachments) {
191
- return attachments.map((a) => {
192
- return {
193
- ...a,
194
- body: a.base64 && globalThis.Buffer ? Buffer.from(a.base64, "base64") : void 0
195
- };
196
- });
197
- }
198
- _mergeSuiteInto(jsonSuite, parent) {
199
- let targetSuite = parent.suites.find((s) => s.title === jsonSuite.title);
200
- if (!targetSuite) {
201
- targetSuite = new TeleSuite(jsonSuite.title, parent.type === "project" ? "file" : "describe");
202
- parent._addSuite(targetSuite);
203
- }
204
- targetSuite.location = this._absoluteLocation(jsonSuite.location);
205
- jsonSuite.entries.forEach((e) => {
206
- if ("testId" in e)
207
- this._mergeTestInto(e, targetSuite);
208
- else
209
- this._mergeSuiteInto(e, targetSuite);
210
- });
211
- }
212
- _mergeTestInto(jsonTest, parent) {
213
- let targetTest = this._options.mergeTestCases ? parent.tests.find((s) => s.title === jsonTest.title && s.repeatEachIndex === jsonTest.repeatEachIndex) : void 0;
214
- if (!targetTest) {
215
- targetTest = new TeleTestCase(jsonTest.testId, jsonTest.title, this._absoluteLocation(jsonTest.location), jsonTest.repeatEachIndex);
216
- parent._addTest(targetTest);
217
- this._tests.set(targetTest.id, targetTest);
218
- }
219
- this._updateTest(jsonTest, targetTest);
220
- }
221
- _updateTest(payload, test) {
222
- test.id = payload.testId;
223
- test.location = this._absoluteLocation(payload.location);
224
- test.retries = payload.retries;
225
- test.tags = payload.tags ?? [];
226
- test.annotations = payload.annotations ?? [];
227
- return test;
228
- }
229
- _absoluteLocation(location) {
230
- if (!location)
231
- return location;
232
- return {
233
- ...location,
234
- file: this._absolutePath(location.file)
235
- };
236
- }
237
- _absolutePath(relativePath) {
238
- if (relativePath === void 0)
239
- return;
240
- return this._options.resolvePath ? this._options.resolvePath(this._rootDir, relativePath) : this._rootDir + "/" + relativePath;
241
- }
242
- }
243
- class TeleSuite {
244
- constructor(title, type) {
245
- this._entries = [];
246
- this._requireFile = "";
247
- this._parallelMode = "none";
248
- this.title = title;
249
- this._type = type;
250
- }
251
- get type() {
252
- return this._type;
253
- }
254
- get suites() {
255
- return this._entries.filter((e) => e.type !== "test");
256
- }
257
- get tests() {
258
- return this._entries.filter((e) => e.type === "test");
259
- }
260
- entries() {
261
- return this._entries;
262
- }
263
- allTests() {
264
- const result = [];
265
- const visit = (suite) => {
266
- for (const entry of suite.entries()) {
267
- if (entry.type === "test")
268
- result.push(entry);
269
- else
270
- visit(entry);
271
- }
272
- };
273
- visit(this);
274
- return result;
275
- }
276
- titlePath() {
277
- const titlePath = this.parent ? this.parent.titlePath() : [];
278
- if (this.title || this._type !== "describe")
279
- titlePath.push(this.title);
280
- return titlePath;
281
- }
282
- project() {
283
- var _a;
284
- return this._project ?? ((_a = this.parent) == null ? void 0 : _a.project());
285
- }
286
- _addTest(test) {
287
- test.parent = this;
288
- this._entries.push(test);
289
- }
290
- _addSuite(suite) {
291
- suite.parent = this;
292
- this._entries.push(suite);
293
- }
294
- }
295
- class TeleTestCase {
296
- constructor(id, title, location, repeatEachIndex) {
297
- this.fn = () => {
298
- };
299
- this.results = [];
300
- this.type = "test";
301
- this.expectedStatus = "passed";
302
- this.timeout = 0;
303
- this.annotations = [];
304
- this.retries = 0;
305
- this.tags = [];
306
- this.repeatEachIndex = 0;
307
- this.id = id;
308
- this.title = title;
309
- this.location = location;
310
- this.repeatEachIndex = repeatEachIndex;
311
- }
312
- titlePath() {
313
- const titlePath = this.parent ? this.parent.titlePath() : [];
314
- titlePath.push(this.title);
315
- return titlePath;
316
- }
317
- outcome() {
318
- return computeTestCaseOutcome(this);
319
- }
320
- ok() {
321
- const status = this.outcome();
322
- return status === "expected" || status === "flaky" || status === "skipped";
323
- }
324
- _createTestResult(id) {
325
- const result = new TeleTestResult(this.results.length, id);
326
- this.results.push(result);
327
- return result;
328
- }
329
- }
330
- class TeleTestStep {
331
- constructor(payload, parentStep, location, result) {
332
- this.duration = -1;
333
- this.steps = [];
334
- this._startTime = 0;
335
- this.title = payload.title;
336
- this.category = payload.category;
337
- this.location = location;
338
- this.parent = parentStep;
339
- this._startTime = payload.startTime;
340
- this._result = result;
341
- }
342
- titlePath() {
343
- var _a;
344
- const parentPath = ((_a = this.parent) == null ? void 0 : _a.titlePath()) || [];
345
- return [...parentPath, this.title];
346
- }
347
- get startTime() {
348
- return new Date(this._startTime);
349
- }
350
- set startTime(value) {
351
- this._startTime = +value;
352
- }
353
- get attachments() {
354
- var _a, _b;
355
- return ((_b = (_a = this._endPayload) == null ? void 0 : _a.attachments) == null ? void 0 : _b.map((index) => this._result.attachments[index])) ?? [];
356
- }
357
- get annotations() {
358
- var _a;
359
- return ((_a = this._endPayload) == null ? void 0 : _a.annotations) ?? [];
360
- }
361
- }
362
- class TeleTestResult {
363
- constructor(retry, id) {
364
- this.parallelIndex = -1;
365
- this.workerIndex = -1;
366
- this.duration = -1;
367
- this.stdout = [];
368
- this.stderr = [];
369
- this.attachments = [];
370
- this.status = "skipped";
371
- this.steps = [];
372
- this.errors = [];
373
- this._stepMap = /* @__PURE__ */ new Map();
374
- this._startTime = 0;
375
- this.retry = retry;
376
- this._id = id;
377
- }
378
- setStartTimeNumber(startTime) {
379
- this._startTime = startTime;
380
- }
381
- get startTime() {
382
- return new Date(this._startTime);
383
- }
384
- set startTime(value) {
385
- this._startTime = +value;
386
- }
387
- }
388
- const baseFullConfig = {
389
- forbidOnly: false,
390
- fullyParallel: false,
391
- globalSetup: null,
392
- globalTeardown: null,
393
- globalTimeout: 0,
394
- grep: /.*/,
395
- grepInvert: null,
396
- maxFailures: 0,
397
- metadata: {},
398
- preserveOutput: "always",
399
- projects: [],
400
- reporter: [[define_process_env_default.CI ? "dot" : "list"]],
401
- reportSlowTests: {
402
- max: 5,
403
- threshold: 3e5
404
- /* 5 minutes */
405
- },
406
- configFile: "",
407
- rootDir: "",
408
- quiet: false,
409
- shard: null,
410
- updateSnapshots: "missing",
411
- updateSourceMethod: "patch",
412
- version: "",
413
- workers: 0,
414
- webServer: null
415
- };
416
- function parseRegexPatterns(patterns) {
417
- return patterns.map((p) => {
418
- if (p.s !== void 0)
419
- return p.s;
420
- return new RegExp(p.r.source, p.r.flags);
421
- });
422
- }
423
- function computeTestCaseOutcome(test) {
424
- let skipped = 0;
425
- let expected = 0;
426
- let unexpected = 0;
427
- for (const result of test.results) {
428
- if (result.status === "interrupted") ;
429
- else if (result.status === "skipped" && test.expectedStatus === "skipped") {
430
- ++skipped;
431
- } else if (result.status === "skipped") ;
432
- else if (result.status === test.expectedStatus) {
433
- ++expected;
434
- } else {
435
- ++unexpected;
436
- }
437
- }
438
- if (expected === 0 && unexpected === 0)
439
- return "skipped";
440
- if (unexpected === 0)
441
- return "expected";
442
- if (expected === 0 && skipped === 0)
443
- return "unexpected";
444
- return "flaky";
445
- }
446
- class TestTree {
447
- constructor(rootFolder, rootSuite, loadErrors, projectFilters, pathSeparator) {
448
- this._treeItemById = /* @__PURE__ */ new Map();
449
- this._treeItemByTestId = /* @__PURE__ */ new Map();
450
- const filterProjects = projectFilters && [...projectFilters.values()].some(Boolean);
451
- this.pathSeparator = pathSeparator;
452
- this.rootItem = {
453
- kind: "group",
454
- subKind: "folder",
455
- id: rootFolder,
456
- title: "",
457
- location: { file: "", line: 0, column: 0 },
458
- duration: 0,
459
- parent: void 0,
460
- children: [],
461
- status: "none",
462
- hasLoadErrors: false
463
- };
464
- this._treeItemById.set(rootFolder, this.rootItem);
465
- const visitSuite = (project, parentSuite, parentGroup) => {
466
- for (const suite of parentSuite.suites) {
467
- if (!suite.title) {
468
- visitSuite(project, suite, parentGroup);
469
- continue;
470
- }
471
- let group = parentGroup.children.find((item) => item.kind === "group" && item.title === suite.title);
472
- if (!group) {
473
- group = {
474
- kind: "group",
475
- subKind: "describe",
476
- id: "suite:" + parentSuite.titlePath().join("") + "" + suite.title,
477
- // account for anonymous suites
478
- title: suite.title,
479
- location: suite.location,
480
- duration: 0,
481
- parent: parentGroup,
482
- children: [],
483
- status: "none",
484
- hasLoadErrors: false
485
- };
486
- this._addChild(parentGroup, group);
487
- }
488
- visitSuite(project, suite, group);
489
- }
490
- for (const test of parentSuite.tests) {
491
- const title = test.title;
492
- let testCaseItem = parentGroup.children.find((t) => t.kind !== "group" && t.title === title);
493
- if (!testCaseItem) {
494
- testCaseItem = {
495
- kind: "case",
496
- id: "test:" + test.titlePath().join(""),
497
- title,
498
- parent: parentGroup,
499
- children: [],
500
- tests: [],
501
- location: test.location,
502
- duration: 0,
503
- status: "none",
504
- project: void 0,
505
- test: void 0,
506
- tags: test.tags
507
- };
508
- this._addChild(parentGroup, testCaseItem);
509
- }
510
- const result = test.results[0];
511
- let status = "none";
512
- if ((result == null ? void 0 : result[statusEx]) === "scheduled")
513
- status = "scheduled";
514
- else if ((result == null ? void 0 : result[statusEx]) === "running")
515
- status = "running";
516
- else if ((result == null ? void 0 : result.status) === "skipped")
517
- status = "skipped";
518
- else if ((result == null ? void 0 : result.status) === "interrupted")
519
- status = "none";
520
- else if (result && test.outcome() !== "expected")
521
- status = "failed";
522
- else if (result && test.outcome() === "expected")
523
- status = "passed";
524
- testCaseItem.tests.push(test);
525
- const testItem = {
526
- kind: "test",
527
- id: test.id,
528
- title: project.name,
529
- location: test.location,
530
- test,
531
- parent: testCaseItem,
532
- children: [],
533
- status,
534
- duration: test.results.length ? Math.max(0, test.results[0].duration) : 0,
535
- project
536
- };
537
- this._addChild(testCaseItem, testItem);
538
- this._treeItemByTestId.set(test.id, testItem);
539
- testCaseItem.duration = testCaseItem.children.reduce((a, b) => a + b.duration, 0);
540
- }
541
- };
542
- for (const projectSuite of (rootSuite == null ? void 0 : rootSuite.suites) || []) {
543
- if (filterProjects && !projectFilters.get(projectSuite.title))
544
- continue;
545
- for (const fileSuite of projectSuite.suites) {
546
- const fileItem = this._fileItem(fileSuite.location.file.split(pathSeparator), true);
547
- visitSuite(projectSuite.project(), fileSuite, fileItem);
548
- }
549
- }
550
- for (const loadError of loadErrors) {
551
- if (!loadError.location)
552
- continue;
553
- const fileItem = this._fileItem(loadError.location.file.split(pathSeparator), true);
554
- fileItem.hasLoadErrors = true;
555
- }
556
- }
557
- _addChild(parent, child) {
558
- parent.children.push(child);
559
- child.parent = parent;
560
- this._treeItemById.set(child.id, child);
561
- }
562
- filterTree(filterText, statusFilters, runningTestIds) {
563
- const tokens = filterText.trim().toLowerCase().split(" ");
564
- const filtersStatuses = [...statusFilters.values()].some(Boolean);
565
- const filter = (testCase) => {
566
- const titleWithTags = [...testCase.tests[0].titlePath(), ...testCase.tests[0].tags].join(" ").toLowerCase();
567
- if (!tokens.every((token) => titleWithTags.includes(token)) && !testCase.tests.some((t) => runningTestIds == null ? void 0 : runningTestIds.has(t.id)))
568
- return false;
569
- testCase.children = testCase.children.filter((test) => {
570
- return !filtersStatuses || (runningTestIds == null ? void 0 : runningTestIds.has(test.test.id)) || statusFilters.get(test.status);
571
- });
572
- testCase.tests = testCase.children.map((c) => c.test);
573
- return !!testCase.children.length;
574
- };
575
- const visit = (treeItem) => {
576
- const newChildren = [];
577
- for (const child of treeItem.children) {
578
- if (child.kind === "case") {
579
- if (filter(child))
580
- newChildren.push(child);
581
- } else {
582
- visit(child);
583
- if (child.children.length || child.hasLoadErrors)
584
- newChildren.push(child);
585
- }
586
- }
587
- treeItem.children = newChildren;
588
- };
589
- visit(this.rootItem);
590
- }
591
- _fileItem(filePath, isFile) {
592
- if (filePath.length === 0)
593
- return this.rootItem;
594
- const fileName = filePath.join(this.pathSeparator);
595
- const existingFileItem = this._treeItemById.get(fileName);
596
- if (existingFileItem)
597
- return existingFileItem;
598
- const parentFileItem = this._fileItem(filePath.slice(0, filePath.length - 1), false);
599
- const fileItem = {
600
- kind: "group",
601
- subKind: isFile ? "file" : "folder",
602
- id: fileName,
603
- title: filePath[filePath.length - 1],
604
- location: { file: fileName, line: 0, column: 0 },
605
- duration: 0,
606
- parent: parentFileItem,
607
- children: [],
608
- status: "none",
609
- hasLoadErrors: false
610
- };
611
- this._addChild(parentFileItem, fileItem);
612
- return fileItem;
613
- }
614
- sortAndPropagateStatus() {
615
- sortAndPropagateStatus(this.rootItem);
616
- }
617
- flattenForSingleProject() {
618
- const visit = (treeItem) => {
619
- if (treeItem.kind === "case" && treeItem.children.length === 1) {
620
- treeItem.project = treeItem.children[0].project;
621
- treeItem.test = treeItem.children[0].test;
622
- treeItem.children = [];
623
- this._treeItemByTestId.set(treeItem.test.id, treeItem);
624
- } else {
625
- treeItem.children.forEach(visit);
626
- }
627
- };
628
- visit(this.rootItem);
629
- }
630
- shortenRoot() {
631
- let shortRoot = this.rootItem;
632
- while (shortRoot.children.length === 1 && shortRoot.children[0].kind === "group" && shortRoot.children[0].subKind === "folder")
633
- shortRoot = shortRoot.children[0];
634
- shortRoot.location = this.rootItem.location;
635
- this.rootItem = shortRoot;
636
- }
637
- testIds() {
638
- const result = /* @__PURE__ */ new Set();
639
- const visit = (treeItem) => {
640
- if (treeItem.kind === "case")
641
- treeItem.tests.forEach((t) => result.add(t.id));
642
- treeItem.children.forEach(visit);
643
- };
644
- visit(this.rootItem);
645
- return result;
646
- }
647
- fileNames() {
648
- const result = /* @__PURE__ */ new Set();
649
- const visit = (treeItem) => {
650
- if (treeItem.kind === "group" && treeItem.subKind === "file")
651
- result.add(treeItem.id);
652
- else
653
- treeItem.children.forEach(visit);
654
- };
655
- visit(this.rootItem);
656
- return [...result];
657
- }
658
- flatTreeItems() {
659
- const result = [];
660
- const visit = (treeItem) => {
661
- result.push(treeItem);
662
- treeItem.children.forEach(visit);
663
- };
664
- visit(this.rootItem);
665
- return result;
666
- }
667
- treeItemById(id) {
668
- return this._treeItemById.get(id);
669
- }
670
- collectTestIds(treeItem) {
671
- return treeItem ? collectTestIds(treeItem) : /* @__PURE__ */ new Set();
672
- }
673
- }
674
- function sortAndPropagateStatus(treeItem) {
675
- for (const child of treeItem.children)
676
- sortAndPropagateStatus(child);
677
- if (treeItem.kind === "group") {
678
- treeItem.children.sort((a, b) => {
679
- const fc = a.location.file.localeCompare(b.location.file);
680
- return fc || a.location.line - b.location.line;
681
- });
682
- }
683
- let allPassed = treeItem.children.length > 0;
684
- let allSkipped = treeItem.children.length > 0;
685
- let hasFailed = false;
686
- let hasRunning = false;
687
- let hasScheduled = false;
688
- for (const child of treeItem.children) {
689
- allSkipped = allSkipped && child.status === "skipped";
690
- allPassed = allPassed && (child.status === "passed" || child.status === "skipped");
691
- hasFailed = hasFailed || child.status === "failed";
692
- hasRunning = hasRunning || child.status === "running";
693
- hasScheduled = hasScheduled || child.status === "scheduled";
694
- }
695
- if (hasRunning)
696
- treeItem.status = "running";
697
- else if (hasScheduled)
698
- treeItem.status = "scheduled";
699
- else if (hasFailed)
700
- treeItem.status = "failed";
701
- else if (allSkipped)
702
- treeItem.status = "skipped";
703
- else if (allPassed)
704
- treeItem.status = "passed";
705
- }
706
- function collectTestIds(treeItem) {
707
- const testIds = /* @__PURE__ */ new Set();
708
- const visit = (treeItem2) => {
709
- var _a;
710
- if (treeItem2.kind === "case")
711
- treeItem2.tests.map((t) => t.id).forEach((id) => testIds.add(id));
712
- else if (treeItem2.kind === "test")
713
- testIds.add(treeItem2.id);
714
- else
715
- (_a = treeItem2.children) == null ? void 0 : _a.forEach(visit);
716
- };
717
- visit(treeItem);
718
- return testIds;
719
- }
720
- const statusEx = Symbol("statusEx");
721
- class TeleSuiteUpdater {
722
- constructor(options) {
723
- this.loadErrors = [];
724
- this.progress = {
725
- total: 0,
726
- passed: 0,
727
- failed: 0,
728
- skipped: 0
729
- };
730
- this._lastRunTestCount = 0;
731
- this._receiver = new TeleReporterReceiver(this._createReporter(), {
732
- mergeProjects: true,
733
- mergeTestCases: true,
734
- resolvePath: (rootDir, relativePath) => rootDir + options.pathSeparator + relativePath,
735
- clearPreviousResultsWhenTestBegins: true
736
- });
737
- this._options = options;
738
- }
739
- _createReporter() {
740
- return {
741
- version: () => "v2",
742
- onConfigure: (c) => {
743
- this.config = c;
744
- this._lastRunReceiver = new TeleReporterReceiver({
745
- version: () => "v2",
746
- onBegin: (suite) => {
747
- this._lastRunTestCount = suite.allTests().length;
748
- this._lastRunReceiver = void 0;
749
- }
750
- }, {
751
- mergeProjects: true,
752
- mergeTestCases: false,
753
- resolvePath: (rootDir, relativePath) => rootDir + this._options.pathSeparator + relativePath
754
- });
755
- },
756
- onBegin: (suite) => {
757
- var _a;
758
- if (!this.rootSuite)
759
- this.rootSuite = suite;
760
- if (this._testResultsSnapshot) {
761
- for (const test of this.rootSuite.allTests())
762
- test.results = ((_a = this._testResultsSnapshot) == null ? void 0 : _a.get(test.id)) || test.results;
763
- this._testResultsSnapshot = void 0;
764
- }
765
- this.progress.total = this._lastRunTestCount;
766
- this.progress.passed = 0;
767
- this.progress.failed = 0;
768
- this.progress.skipped = 0;
769
- this._options.onUpdate(true);
770
- },
771
- onEnd: () => {
772
- this._options.onUpdate(true);
773
- },
774
- onTestBegin: (test, testResult) => {
775
- testResult[statusEx] = "running";
776
- this._options.onUpdate();
777
- },
778
- onTestEnd: (test, testResult) => {
779
- if (test.outcome() === "skipped")
780
- ++this.progress.skipped;
781
- else if (test.outcome() === "unexpected")
782
- ++this.progress.failed;
783
- else
784
- ++this.progress.passed;
785
- testResult[statusEx] = testResult.status;
786
- this._options.onUpdate();
787
- },
788
- onError: (error) => this._handleOnError(error),
789
- printsToStdio: () => false
790
- };
791
- }
792
- processGlobalReport(report) {
793
- const receiver = new TeleReporterReceiver({
794
- version: () => "v2",
795
- onConfigure: (c) => {
796
- this.config = c;
797
- },
798
- onError: (error) => this._handleOnError(error)
799
- });
800
- for (const message of report)
801
- void receiver.dispatch(message);
802
- }
803
- processListReport(report) {
804
- var _a;
805
- const tests = ((_a = this.rootSuite) == null ? void 0 : _a.allTests()) || [];
806
- this._testResultsSnapshot = new Map(tests.map((test) => [test.id, test.results]));
807
- this._receiver.reset();
808
- for (const message of report)
809
- void this._receiver.dispatch(message);
810
- }
811
- processTestReportEvent(message) {
812
- var _a, _b, _c;
813
- (_b = (_a = this._lastRunReceiver) == null ? void 0 : _a.dispatch(message)) == null ? void 0 : _b.catch(() => {
814
- });
815
- (_c = this._receiver.dispatch(message)) == null ? void 0 : _c.catch(() => {
816
- });
817
- }
818
- _handleOnError(error) {
819
- var _a, _b;
820
- this.loadErrors.push(error);
821
- (_b = (_a = this._options).onError) == null ? void 0 : _b.call(_a, error);
822
- this._options.onUpdate();
823
- }
824
- asModel() {
825
- return {
826
- rootSuite: this.rootSuite || new TeleSuite("", "root"),
827
- config: this.config,
828
- loadErrors: this.loadErrors,
829
- progress: this.progress
830
- };
831
- }
832
- }
833
- const XtermWrapper = ({
834
- source
835
- }) => {
836
- const [measure, xtermElement] = useMeasure();
837
- const [theme, setTheme] = reactExports.useState(currentTheme());
838
- const [modulePromise] = reactExports.useState(__vitePreload(() => import("./assets/xtermModule-Es_gt_u7.js"), true ? __vite__mapDeps([0,1]) : void 0, import.meta.url).then((m) => m.default));
839
- const terminal = reactExports.useRef(null);
840
- reactExports.useEffect(() => {
841
- addThemeListener(setTheme);
842
- return () => removeThemeListener(setTheme);
843
- }, []);
844
- reactExports.useEffect(() => {
845
- const oldSourceWrite = source.write;
846
- const oldSourceClear = source.clear;
847
- (async () => {
848
- const { Terminal, FitAddon } = await modulePromise;
849
- const element = xtermElement.current;
850
- if (!element)
851
- return;
852
- const terminalTheme = theme === "dark-mode" ? darkTheme : lightTheme;
853
- if (terminal.current && terminal.current.terminal.options.theme === terminalTheme)
854
- return;
855
- if (terminal.current)
856
- element.textContent = "";
857
- const newTerminal = new Terminal({
858
- convertEol: true,
859
- fontSize: 13,
860
- scrollback: 1e4,
861
- fontFamily: "var(--vscode-editor-font-family)",
862
- theme: terminalTheme
863
- });
864
- const fitAddon = new FitAddon();
865
- newTerminal.loadAddon(fitAddon);
866
- for (const p of source.pending)
867
- newTerminal.write(p);
868
- source.write = (data) => {
869
- source.pending.push(data);
870
- newTerminal.write(data);
871
- };
872
- source.clear = () => {
873
- source.pending = [];
874
- newTerminal.clear();
875
- };
876
- newTerminal.open(element);
877
- fitAddon.fit();
878
- terminal.current = { terminal: newTerminal, fitAddon };
879
- })();
880
- return () => {
881
- source.clear = oldSourceClear;
882
- source.write = oldSourceWrite;
883
- };
884
- }, [modulePromise, terminal, xtermElement, source, theme]);
885
- reactExports.useEffect(() => {
886
- setTimeout(() => {
887
- if (!terminal.current)
888
- return;
889
- terminal.current.fitAddon.fit();
890
- source.resize(terminal.current.terminal.cols, terminal.current.terminal.rows);
891
- }, 250);
892
- }, [measure, source]);
893
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { "data-testid": "output", className: "xterm-wrapper", style: { flex: "auto" }, ref: xtermElement });
894
- };
895
- const lightTheme = {
896
- foreground: "#383a42",
897
- background: "#fafafa",
898
- cursor: "#383a42",
899
- black: "#000000",
900
- red: "#e45649",
901
- green: "#50a14f",
902
- yellow: "#c18401",
903
- blue: "#4078f2",
904
- magenta: "#a626a4",
905
- cyan: "#0184bc",
906
- white: "#a0a0a0",
907
- brightBlack: "#000000",
908
- brightRed: "#e06c75",
909
- brightGreen: "#98c379",
910
- brightYellow: "#d19a66",
911
- brightBlue: "#4078f2",
912
- brightMagenta: "#a626a4",
913
- brightCyan: "#0184bc",
914
- brightWhite: "#383a42",
915
- selectionBackground: "#d7d7d7",
916
- selectionForeground: "#383a42"
917
- };
918
- const darkTheme = {
919
- foreground: "#f8f8f2",
920
- background: "#1e1e1e",
921
- cursor: "#f8f8f0",
922
- black: "#000000",
923
- red: "#ff5555",
924
- green: "#50fa7b",
925
- yellow: "#f1fa8c",
926
- blue: "#bd93f9",
927
- magenta: "#ff79c6",
928
- cyan: "#8be9fd",
929
- white: "#bfbfbf",
930
- brightBlack: "#4d4d4d",
931
- brightRed: "#ff6e6e",
932
- brightGreen: "#69ff94",
933
- brightYellow: "#ffffa5",
934
- brightBlue: "#d6acff",
935
- brightMagenta: "#ff92df",
936
- brightCyan: "#a4ffff",
937
- brightWhite: "#e6e6e6",
938
- selectionBackground: "#44475a",
939
- selectionForeground: "#f8f8f2"
940
- };
941
- const FiltersView = ({ filterText, setFilterText, statusFilters, setStatusFilters, projectFilters, setProjectFilters, testModel, runTests }) => {
942
- const [expanded, setExpanded] = React.useState(false);
943
- const inputRef = React.useRef(null);
944
- React.useEffect(() => {
945
- var _a;
946
- (_a = inputRef.current) == null ? void 0 : _a.focus();
947
- }, []);
948
- const statusLine = [...statusFilters.entries()].filter(([_, v]) => v).map(([s]) => s).join(" ") || "all";
949
- const projectsLine = [...projectFilters.entries()].filter(([_, v]) => v).map(([p]) => p).join(" ") || "all";
950
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "filters", children: [
951
- /* @__PURE__ */ jsxRuntimeExports.jsx(
952
- Expandable,
953
- {
954
- expanded,
955
- setExpanded,
956
- title: /* @__PURE__ */ jsxRuntimeExports.jsx(
957
- "input",
958
- {
959
- ref: inputRef,
960
- type: "search",
961
- placeholder: "Filter (e.g. text, @tag)",
962
- spellCheck: false,
963
- value: filterText,
964
- onChange: (e) => {
965
- setFilterText(e.target.value);
966
- },
967
- onKeyDown: (e) => {
968
- if (e.key === "Enter")
969
- runTests();
970
- }
971
- }
972
- )
973
- }
974
- ),
975
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "filter-summary", title: "Status: " + statusLine + "\nProjects: " + projectsLine, onClick: () => setExpanded(!expanded), children: [
976
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "filter-label", children: "Status:" }),
977
- " ",
978
- statusLine,
979
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "filter-label", children: "Projects:" }),
980
- " ",
981
- projectsLine
982
- ] }),
983
- expanded && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "hbox", style: { marginLeft: 14, maxHeight: 200, overflowY: "auto" }, children: [
984
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "filter-list", role: "list", "data-testid": "status-filters", children: [...statusFilters.entries()].map(([status, value]) => {
985
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "filter-entry", role: "listitem", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { children: [
986
- /* @__PURE__ */ jsxRuntimeExports.jsx("input", { type: "checkbox", checked: value, onChange: () => {
987
- const copy = new Map(statusFilters);
988
- copy.set(status, !copy.get(status));
989
- setStatusFilters(copy);
990
- } }),
991
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: status })
992
- ] }) }, status);
993
- }) }),
994
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "filter-list", role: "list", "data-testid": "project-filters", children: [...projectFilters.entries()].map(([projectName, value]) => {
995
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "filter-entry", role: "listitem", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { children: [
996
- /* @__PURE__ */ jsxRuntimeExports.jsx("input", { type: "checkbox", checked: value, onChange: () => {
997
- var _a;
998
- const copy = new Map(projectFilters);
999
- copy.set(projectName, !copy.get(projectName));
1000
- setProjectFilters(copy);
1001
- const configFile = (_a = testModel == null ? void 0 : testModel.config) == null ? void 0 : _a.configFile;
1002
- if (configFile)
1003
- settings.setObject(configFile + ":projects", [...copy.entries()].filter(([_, v]) => v).map(([k]) => k));
1004
- } }),
1005
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: projectName || "untitled" })
1006
- ] }) }, projectName);
1007
- }) })
1008
- ] })
1009
- ] });
1010
- };
1011
- const TagView = ({ tag, style, onClick }) => {
1012
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
1013
- "span",
1014
- {
1015
- className: clsx("tag", `tag-color-${tagNameToColor(tag)}`),
1016
- onClick,
1017
- style: { margin: "6px 0 0 6px", ...style },
1018
- title: `Click to filter by tag: ${tag}`,
1019
- children: tag
1020
- }
1021
- );
1022
- };
1023
- function tagNameToColor(str) {
1024
- let hash = 0;
1025
- for (let i = 0; i < str.length; i++)
1026
- hash = str.charCodeAt(i) + ((hash << 8) - hash);
1027
- return Math.abs(hash % 6);
1028
- }
1029
- const TestTreeView = TreeView;
1030
- const TestListView = ({ filterText, testModel, testServerConnection, testTree, runTests, runningState, watchAll, watchedTreeIds, setWatchedTreeIds, isLoading, onItemSelected, requestedCollapseAllCount, requestedExpandAllCount, setFilterText, onRevealSource }) => {
1031
- const [treeState, setTreeState] = React.useState({ expandedItems: /* @__PURE__ */ new Map() });
1032
- const [selectedTreeItemId, setSelectedTreeItemId] = React.useState();
1033
- const [collapseAllCount, setCollapseAllCount] = React.useState(requestedCollapseAllCount);
1034
- const [expandAllCount, setExpandAllCount] = React.useState(requestedExpandAllCount);
1035
- React.useEffect(() => {
1036
- if (collapseAllCount !== requestedCollapseAllCount) {
1037
- treeState.expandedItems.clear();
1038
- for (const item of testTree.flatTreeItems())
1039
- treeState.expandedItems.set(item.id, false);
1040
- setCollapseAllCount(requestedCollapseAllCount);
1041
- setSelectedTreeItemId(void 0);
1042
- setTreeState({ ...treeState });
1043
- return;
1044
- }
1045
- if (expandAllCount !== requestedExpandAllCount) {
1046
- treeState.expandedItems.clear();
1047
- for (const item of testTree.flatTreeItems())
1048
- treeState.expandedItems.set(item.id, true);
1049
- setExpandAllCount(requestedExpandAllCount);
1050
- setSelectedTreeItemId(void 0);
1051
- setTreeState({ ...treeState });
1052
- return;
1053
- }
1054
- if (!runningState || runningState.itemSelectedByUser)
1055
- return;
1056
- let selectedTreeItem2;
1057
- const visit = (treeItem) => {
1058
- var _a;
1059
- treeItem.children.forEach(visit);
1060
- if (selectedTreeItem2)
1061
- return;
1062
- if (treeItem.status === "failed") {
1063
- if (treeItem.kind === "test" && runningState.testIds.has(treeItem.test.id))
1064
- selectedTreeItem2 = treeItem;
1065
- else if (treeItem.kind === "case" && runningState.testIds.has((_a = treeItem.tests[0]) == null ? void 0 : _a.id))
1066
- selectedTreeItem2 = treeItem;
1067
- }
1068
- };
1069
- visit(testTree.rootItem);
1070
- if (selectedTreeItem2)
1071
- setSelectedTreeItemId(selectedTreeItem2.id);
1072
- }, [runningState, setSelectedTreeItemId, testTree, collapseAllCount, setCollapseAllCount, requestedCollapseAllCount, expandAllCount, setExpandAllCount, requestedExpandAllCount, treeState, setTreeState]);
1073
- const selectedTreeItem = React.useMemo(() => {
1074
- if (!selectedTreeItemId)
1075
- return void 0;
1076
- return testTree.treeItemById(selectedTreeItemId);
1077
- }, [selectedTreeItemId, testTree]);
1078
- React.useEffect(() => {
1079
- if (!testModel)
1080
- return;
1081
- const testFile = itemLocation(selectedTreeItem, testModel);
1082
- let selectedTest;
1083
- if ((selectedTreeItem == null ? void 0 : selectedTreeItem.kind) === "test")
1084
- selectedTest = selectedTreeItem.test;
1085
- else if ((selectedTreeItem == null ? void 0 : selectedTreeItem.kind) === "case" && selectedTreeItem.tests.length === 1)
1086
- selectedTest = selectedTreeItem.tests[0];
1087
- onItemSelected({ treeItem: selectedTreeItem, testCase: selectedTest, testFile });
1088
- }, [testModel, selectedTreeItem, onItemSelected]);
1089
- React.useEffect(() => {
1090
- if (isLoading)
1091
- return;
1092
- if (watchAll) {
1093
- testServerConnection == null ? void 0 : testServerConnection.watchNoReply({ fileNames: testTree.fileNames() });
1094
- } else {
1095
- const fileNames = /* @__PURE__ */ new Set();
1096
- for (const itemId of watchedTreeIds.value) {
1097
- const treeItem = testTree.treeItemById(itemId);
1098
- const fileName = treeItem == null ? void 0 : treeItem.location.file;
1099
- if (fileName)
1100
- fileNames.add(fileName);
1101
- }
1102
- testServerConnection == null ? void 0 : testServerConnection.watchNoReply({ fileNames: [...fileNames] });
1103
- }
1104
- }, [isLoading, testTree, watchAll, watchedTreeIds, testServerConnection]);
1105
- const runTreeItem = (treeItem) => {
1106
- setSelectedTreeItemId(treeItem.id);
1107
- runTests("bounce-if-busy", testTree.collectTestIds(treeItem));
1108
- };
1109
- const handleTagClick = (e, tag) => {
1110
- e.preventDefault();
1111
- e.stopPropagation();
1112
- if (e.metaKey || e.ctrlKey) {
1113
- const parts = filterText.split(" ");
1114
- if (parts.includes(tag))
1115
- setFilterText(parts.filter((t) => t !== tag).join(" ").trim());
1116
- else
1117
- setFilterText((filterText + " " + tag).trim());
1118
- } else {
1119
- setFilterText((filterText.split(" ").filter((t) => !t.startsWith("@")).join(" ") + " " + tag).trim());
1120
- }
1121
- };
1122
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
1123
- TestTreeView,
1124
- {
1125
- name: "tests",
1126
- treeState,
1127
- setTreeState,
1128
- rootItem: testTree.rootItem,
1129
- dataTestId: "test-tree",
1130
- render: (treeItem) => {
1131
- const prefixId = treeItem.id.replace(/[^\w\d-_]/g, "-");
1132
- const labelId = prefixId + "-label";
1133
- const timeId = prefixId + "-time";
1134
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "hbox ui-mode-tree-item", "aria-labelledby": `${labelId} ${timeId}`, children: [
1135
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { id: labelId, className: "ui-mode-tree-item-title", children: [
1136
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: treeItem.title }),
1137
- treeItem.kind === "case" ? treeItem.tags.map((tag) => /* @__PURE__ */ jsxRuntimeExports.jsx(TagView, { tag: tag.slice(1), onClick: (e) => handleTagClick(e, tag) }, tag)) : null
1138
- ] }),
1139
- !!treeItem.duration && treeItem.status !== "skipped" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { id: timeId, className: "ui-mode-tree-item-time", children: msToString(treeItem.duration) }),
1140
- /* @__PURE__ */ jsxRuntimeExports.jsxs(Toolbar, { noMinHeight: true, noShadow: true, children: [
1141
- /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "play", title: "Run", onClick: () => runTreeItem(treeItem), disabled: !!runningState && !runningState.completed }),
1142
- /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "go-to-file", title: "Show source", onClick: onRevealSource, style: treeItem.kind === "group" && treeItem.subKind === "folder" ? { visibility: "hidden" } : {} }),
1143
- !watchAll && /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "eye", title: "Watch", onClick: () => {
1144
- if (watchedTreeIds.value.has(treeItem.id))
1145
- watchedTreeIds.value.delete(treeItem.id);
1146
- else
1147
- watchedTreeIds.value.add(treeItem.id);
1148
- setWatchedTreeIds({ ...watchedTreeIds });
1149
- }, toggled: watchedTreeIds.value.has(treeItem.id) })
1150
- ] })
1151
- ] });
1152
- },
1153
- icon: (treeItem) => testStatusIcon(treeItem.status),
1154
- title: (treeItem) => treeItem.title,
1155
- selectedItem: selectedTreeItem,
1156
- onAccepted: runTreeItem,
1157
- onSelected: (treeItem) => {
1158
- if (runningState)
1159
- runningState.itemSelectedByUser = true;
1160
- setSelectedTreeItemId(treeItem.id);
1161
- },
1162
- isError: (treeItem) => treeItem.kind === "group" ? treeItem.hasLoadErrors : false,
1163
- autoExpandDepth: filterText ? 5 : 1,
1164
- noItemsMessage: isLoading ? "Loading…" : "No tests"
1165
- }
1166
- );
1167
- };
1168
- function itemLocation(item, model) {
1169
- if (!item || !model)
1170
- return;
1171
- return {
1172
- file: item.location.file,
1173
- line: item.location.line,
1174
- column: item.location.column,
1175
- source: {
1176
- errors: model.loadErrors.filter((e) => {
1177
- var _a;
1178
- return ((_a = e.location) == null ? void 0 : _a.file) === item.location.file;
1179
- }).map((e) => ({ line: e.location.line, message: e.message })),
1180
- content: void 0
1181
- }
1182
- };
1183
- }
1184
- function artifactsFolderName(workerIndex) {
1185
- return `.playwright-artifacts-${workerIndex}`;
1186
- }
1187
- const TraceView = ({ item, rootDir, onOpenExternally, revealSource, pathSeparator }) => {
1188
- var _a, _b;
1189
- const [model, setModel] = React.useState();
1190
- const [counter, setCounter] = React.useState(0);
1191
- const pollTimer = React.useRef(null);
1192
- const { outputDir } = React.useMemo(() => {
1193
- const outputDir2 = item.testCase ? outputDirForTestCase(item.testCase) : void 0;
1194
- return { outputDir: outputDir2 };
1195
- }, [item]);
1196
- React.useEffect(() => {
1197
- var _a2, _b2;
1198
- if (pollTimer.current)
1199
- clearTimeout(pollTimer.current);
1200
- const result = (_a2 = item.testCase) == null ? void 0 : _a2.results[0];
1201
- if (!result) {
1202
- setModel(void 0);
1203
- return;
1204
- }
1205
- const attachment = result && result.duration >= 0 && result.attachments.find((a) => a.name === "trace");
1206
- if (attachment && attachment.path) {
1207
- loadSingleTraceFile(attachment.path).then((model2) => setModel({ model: model2, isLive: false }));
1208
- return;
1209
- }
1210
- if (!outputDir) {
1211
- setModel(void 0);
1212
- return;
1213
- }
1214
- const traceLocation = [
1215
- outputDir,
1216
- artifactsFolderName(result.workerIndex),
1217
- "traces",
1218
- `${(_b2 = item.testCase) == null ? void 0 : _b2.id}.json`
1219
- ].join(pathSeparator);
1220
- pollTimer.current = setTimeout(async () => {
1221
- try {
1222
- const model2 = await loadSingleTraceFile(traceLocation);
1223
- setModel({ model: model2, isLive: true });
1224
- } catch {
1225
- setModel(void 0);
1226
- } finally {
1227
- setCounter(counter + 1);
1228
- }
1229
- }, 500);
1230
- return () => {
1231
- if (pollTimer.current)
1232
- clearTimeout(pollTimer.current);
1233
- };
1234
- }, [outputDir, item, setModel, counter, setCounter, pathSeparator]);
1235
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
1236
- Workbench,
1237
- {
1238
- model: model == null ? void 0 : model.model,
1239
- showSourcesFirst: true,
1240
- rootDir,
1241
- fallbackLocation: item.testFile,
1242
- isLive: model == null ? void 0 : model.isLive,
1243
- status: (_a = item.treeItem) == null ? void 0 : _a.status,
1244
- annotations: ((_b = item.testCase) == null ? void 0 : _b.annotations) || [],
1245
- onOpenExternally,
1246
- revealSource
1247
- },
1248
- "workbench"
1249
- );
1250
- };
1251
- const outputDirForTestCase = (testCase) => {
1252
- var _a;
1253
- for (let suite = testCase.parent; suite; suite = suite.parent) {
1254
- if (suite.project())
1255
- return (_a = suite.project()) == null ? void 0 : _a.outputDir;
1256
- }
1257
- return void 0;
1258
- };
1259
- async function loadSingleTraceFile(url) {
1260
- const params = new URLSearchParams();
1261
- params.set("trace", url);
1262
- params.set("limit", "1");
1263
- const response = await fetch(`contexts?${params.toString()}`);
1264
- const contextEntries = await response.json();
1265
- return new MultiTraceModel(contextEntries);
1266
- }
1267
- let xtermSize = { cols: 80 };
1268
- const xtermDataSource = {
1269
- pending: [],
1270
- clear: () => {
1271
- },
1272
- write: (data) => xtermDataSource.pending.push(data),
1273
- resize: () => {
1274
- }
1275
- };
1276
- const searchParams = new URLSearchParams(window.location.search);
1277
- const testServerBaseUrl = new URL(searchParams.get("server") ?? "../", window.location.href);
1278
- const wsURL = new URL(searchParams.get("ws"), testServerBaseUrl);
1279
- wsURL.protocol = wsURL.protocol === "https:" ? "wss:" : "ws:";
1280
- const queryParams = {
1281
- args: searchParams.getAll("arg"),
1282
- grep: searchParams.get("grep") || void 0,
1283
- grepInvert: searchParams.get("grepInvert") || void 0,
1284
- projects: searchParams.getAll("project"),
1285
- workers: searchParams.get("workers") || void 0,
1286
- headed: searchParams.has("headed"),
1287
- updateSnapshots: searchParams.get("updateSnapshots") || void 0,
1288
- reporters: searchParams.has("reporter") ? searchParams.getAll("reporter") : void 0,
1289
- pathSeparator: searchParams.get("pathSeparator") || "/"
1290
- };
1291
- if (queryParams.updateSnapshots && !["all", "none", "missing"].includes(queryParams.updateSnapshots))
1292
- queryParams.updateSnapshots = void 0;
1293
- const isMac = navigator.platform === "MacIntel";
1294
- const UIModeView = ({}) => {
1295
- var _a;
1296
- const [filterText, setFilterText] = React.useState("");
1297
- const [isShowingOutput, setIsShowingOutput] = React.useState(false);
1298
- const [outputContainsError, setOutputContainsError] = React.useState(false);
1299
- const [statusFilters, setStatusFilters] = React.useState(/* @__PURE__ */ new Map([
1300
- ["passed", false],
1301
- ["failed", false],
1302
- ["skipped", false]
1303
- ]));
1304
- const [projectFilters, setProjectFilters] = React.useState(/* @__PURE__ */ new Map());
1305
- const [testModel, setTestModel] = React.useState();
1306
- const [progress, setProgress] = React.useState();
1307
- const [selectedItem, setSelectedItem] = React.useState({});
1308
- const [visibleTestIds, setVisibleTestIds] = React.useState(/* @__PURE__ */ new Set());
1309
- const [isLoading, setIsLoading] = React.useState(false);
1310
- const [runningState, setRunningState] = React.useState();
1311
- const isRunningTest = runningState && !runningState.completed;
1312
- const [watchAll, setWatchAll] = useSetting("watch-all", false);
1313
- const [watchedTreeIds, setWatchedTreeIds] = React.useState({ value: /* @__PURE__ */ new Set() });
1314
- const commandQueue = React.useRef(Promise.resolve());
1315
- const runTestBacklog = React.useRef(/* @__PURE__ */ new Set());
1316
- const [collapseAllCount, setCollapseAllCount] = React.useState(0);
1317
- const [expandAllCount, setExpandAllCount] = React.useState(0);
1318
- const [isDisconnected, setIsDisconnected] = React.useState(false);
1319
- const [hasBrowsers, setHasBrowsers] = React.useState(true);
1320
- const [testServerConnection, setTestServerConnection] = React.useState();
1321
- const [teleSuiteUpdater, setTeleSuiteUpdater] = React.useState();
1322
- const [settingsVisible, setSettingsVisible] = React.useState(false);
1323
- const [testingOptionsVisible, setTestingOptionsVisible] = React.useState(false);
1324
- const [revealSource, setRevealSource] = React.useState(false);
1325
- const onRevealSource = React.useCallback(() => setRevealSource(true), [setRevealSource]);
1326
- const showTestingOptions = false;
1327
- const [singleWorker, setSingleWorker] = React.useState(false);
1328
- const [showBrowser, setShowBrowser] = React.useState(false);
1329
- const [updateSnapshots, setUpdateSnapshots] = React.useState(false);
1330
- const inputRef = React.useRef(null);
1331
- const reloadTests = React.useCallback(() => {
1332
- setTestServerConnection((prevConnection) => {
1333
- prevConnection == null ? void 0 : prevConnection.close();
1334
- return new TestServerConnection(new WebSocketTestServerTransport(wsURL));
1335
- });
1336
- }, []);
1337
- React.useEffect(() => {
1338
- var _a2;
1339
- (_a2 = inputRef.current) == null ? void 0 : _a2.focus();
1340
- setIsLoading(true);
1341
- reloadTests();
1342
- }, [reloadTests]);
1343
- React.useEffect(() => {
1344
- if (!testServerConnection)
1345
- return;
1346
- const disposables = [
1347
- testServerConnection.onStdio((params) => {
1348
- if (params.buffer) {
1349
- const data = atob(params.buffer);
1350
- xtermDataSource.write(data);
1351
- } else {
1352
- xtermDataSource.write(params.text);
1353
- }
1354
- if (params.type === "stderr")
1355
- setOutputContainsError(true);
1356
- }),
1357
- testServerConnection.onClose(() => setIsDisconnected(true))
1358
- ];
1359
- xtermDataSource.resize = (cols, rows) => {
1360
- xtermSize = { cols, rows };
1361
- testServerConnection.resizeTerminalNoReply({ cols, rows });
1362
- };
1363
- return () => {
1364
- for (const disposable of disposables)
1365
- disposable.dispose();
1366
- };
1367
- }, [testServerConnection]);
1368
- React.useEffect(() => {
1369
- if (!testServerConnection)
1370
- return;
1371
- let throttleTimer;
1372
- const teleSuiteUpdater2 = new TeleSuiteUpdater({
1373
- onUpdate: (immediate) => {
1374
- clearTimeout(throttleTimer);
1375
- throttleTimer = void 0;
1376
- if (immediate) {
1377
- setTestModel(teleSuiteUpdater2.asModel());
1378
- } else if (!throttleTimer) {
1379
- throttleTimer = setTimeout(() => {
1380
- setTestModel(teleSuiteUpdater2.asModel());
1381
- }, 250);
1382
- }
1383
- },
1384
- onError: (error) => {
1385
- xtermDataSource.write((error.stack || error.value || "") + "\n");
1386
- setOutputContainsError(true);
1387
- },
1388
- pathSeparator: queryParams.pathSeparator
1389
- });
1390
- setTeleSuiteUpdater(teleSuiteUpdater2);
1391
- setTestModel(void 0);
1392
- setIsLoading(true);
1393
- setWatchedTreeIds({ value: /* @__PURE__ */ new Set() });
1394
- (async () => {
1395
- try {
1396
- await testServerConnection.initialize({
1397
- interceptStdio: true,
1398
- watchTestDirs: true
1399
- });
1400
- const { status, report } = await testServerConnection.runGlobalSetup({});
1401
- teleSuiteUpdater2.processGlobalReport(report);
1402
- if (status !== "passed")
1403
- return;
1404
- const result = await testServerConnection.listTests({ projects: queryParams.projects, locations: queryParams.args, grep: queryParams.grep, grepInvert: queryParams.grepInvert });
1405
- teleSuiteUpdater2.processListReport(result.report);
1406
- testServerConnection.onReport((params) => {
1407
- teleSuiteUpdater2.processTestReportEvent(params);
1408
- });
1409
- const { hasBrowsers: hasBrowsers2 } = await testServerConnection.checkBrowsers({});
1410
- setHasBrowsers(hasBrowsers2);
1411
- } finally {
1412
- setIsLoading(false);
1413
- }
1414
- })();
1415
- return () => {
1416
- clearTimeout(throttleTimer);
1417
- };
1418
- }, [testServerConnection]);
1419
- React.useEffect(() => {
1420
- if (!testModel)
1421
- return;
1422
- const { config, rootSuite } = testModel;
1423
- const selectedProjects = config.configFile ? settings.getObject(config.configFile + ":projects", void 0) : void 0;
1424
- const newFilter = new Map(projectFilters);
1425
- for (const projectName of newFilter.keys()) {
1426
- if (!rootSuite.suites.find((s) => s.title === projectName))
1427
- newFilter.delete(projectName);
1428
- }
1429
- for (const projectSuite of rootSuite.suites) {
1430
- if (!newFilter.has(projectSuite.title))
1431
- newFilter.set(projectSuite.title, !!(selectedProjects == null ? void 0 : selectedProjects.includes(projectSuite.title)));
1432
- }
1433
- if (!selectedProjects && newFilter.size && ![...newFilter.values()].includes(true))
1434
- newFilter.set(newFilter.entries().next().value[0], true);
1435
- if (projectFilters.size !== newFilter.size || [...projectFilters].some(([k, v]) => newFilter.get(k) !== v))
1436
- setProjectFilters(newFilter);
1437
- }, [projectFilters, testModel]);
1438
- React.useEffect(() => {
1439
- if (isRunningTest && (testModel == null ? void 0 : testModel.progress))
1440
- setProgress(testModel.progress);
1441
- else if (!testModel)
1442
- setProgress(void 0);
1443
- }, [testModel, isRunningTest]);
1444
- const { testTree } = React.useMemo(() => {
1445
- if (!testModel)
1446
- return { testTree: new TestTree("", new TeleSuite("", "root"), [], projectFilters, queryParams.pathSeparator) };
1447
- const testTree2 = new TestTree("", testModel.rootSuite, testModel.loadErrors, projectFilters, queryParams.pathSeparator);
1448
- testTree2.filterTree(filterText, statusFilters, isRunningTest ? runningState == null ? void 0 : runningState.testIds : void 0);
1449
- testTree2.sortAndPropagateStatus();
1450
- testTree2.shortenRoot();
1451
- testTree2.flattenForSingleProject();
1452
- setVisibleTestIds(testTree2.testIds());
1453
- return { testTree: testTree2 };
1454
- }, [filterText, testModel, statusFilters, projectFilters, setVisibleTestIds, runningState, isRunningTest]);
1455
- const runTests = React.useCallback((mode, testIds) => {
1456
- if (!testServerConnection || !testModel)
1457
- return;
1458
- if (mode === "bounce-if-busy" && isRunningTest)
1459
- return;
1460
- runTestBacklog.current = /* @__PURE__ */ new Set([...runTestBacklog.current, ...testIds]);
1461
- commandQueue.current = commandQueue.current.then(async () => {
1462
- var _a2, _b, _c;
1463
- const testIds2 = runTestBacklog.current;
1464
- runTestBacklog.current = /* @__PURE__ */ new Set();
1465
- if (!testIds2.size)
1466
- return;
1467
- {
1468
- for (const test of ((_a2 = testModel.rootSuite) == null ? void 0 : _a2.allTests()) || []) {
1469
- if (testIds2.has(test.id)) {
1470
- test.results = [];
1471
- const result = test._createTestResult("pending");
1472
- result[statusEx] = "scheduled";
1473
- }
1474
- }
1475
- setTestModel({ ...testModel });
1476
- }
1477
- const time = " [" + (/* @__PURE__ */ new Date()).toLocaleTimeString() + "]";
1478
- xtermDataSource.write("\x1B[2m—".repeat(Math.max(0, xtermSize.cols - time.length)) + time + "\x1B[22m");
1479
- setProgress({ total: 0, passed: 0, failed: 0, skipped: 0 });
1480
- setRunningState({ testIds: testIds2 });
1481
- await testServerConnection.runTests({
1482
- locations: queryParams.args,
1483
- grep: queryParams.grep,
1484
- grepInvert: queryParams.grepInvert,
1485
- testIds: [...testIds2],
1486
- projects: [...projectFilters].filter(([_, v]) => v).map(([p]) => p),
1487
- ...singleWorker ? { workers: "1" } : {},
1488
- ...showBrowser ? { headed: true } : {},
1489
- ...updateSnapshots ? { updateSnapshots: "all" } : {},
1490
- reporters: queryParams.reporters,
1491
- trace: "on"
1492
- });
1493
- for (const test of ((_b = testModel.rootSuite) == null ? void 0 : _b.allTests()) || []) {
1494
- if (((_c = test.results[0]) == null ? void 0 : _c.duration) === -1)
1495
- test.results = [];
1496
- }
1497
- setTestModel({ ...testModel });
1498
- setRunningState((oldState) => oldState ? { ...oldState, completed: true } : void 0);
1499
- });
1500
- }, [projectFilters, isRunningTest, testModel, testServerConnection, singleWorker, showBrowser, updateSnapshots]);
1501
- React.useEffect(() => {
1502
- if (!testServerConnection || !teleSuiteUpdater)
1503
- return;
1504
- const disposable = testServerConnection.onTestFilesChanged(async (params) => {
1505
- commandQueue.current = commandQueue.current.then(async () => {
1506
- setIsLoading(true);
1507
- try {
1508
- const result = await testServerConnection.listTests({ projects: queryParams.projects, locations: queryParams.args, grep: queryParams.grep, grepInvert: queryParams.grepInvert });
1509
- teleSuiteUpdater.processListReport(result.report);
1510
- } catch (e) {
1511
- console.log(e);
1512
- } finally {
1513
- setIsLoading(false);
1514
- }
1515
- });
1516
- await commandQueue.current;
1517
- if (params.testFiles.length === 0)
1518
- return;
1519
- const testModel2 = teleSuiteUpdater.asModel();
1520
- const testTree2 = new TestTree("", testModel2.rootSuite, testModel2.loadErrors, projectFilters, queryParams.pathSeparator);
1521
- const testIds = [];
1522
- const set = new Set(params.testFiles);
1523
- if (watchAll) {
1524
- const visit = (treeItem) => {
1525
- const fileName = treeItem.location.file;
1526
- if (fileName && set.has(fileName))
1527
- testIds.push(...testTree2.collectTestIds(treeItem));
1528
- if (treeItem.kind === "group" && treeItem.subKind === "folder")
1529
- treeItem.children.forEach(visit);
1530
- };
1531
- visit(testTree2.rootItem);
1532
- } else {
1533
- for (const treeId of watchedTreeIds.value) {
1534
- const treeItem = testTree2.treeItemById(treeId);
1535
- const fileName = treeItem == null ? void 0 : treeItem.location.file;
1536
- if (fileName && set.has(fileName))
1537
- testIds.push(...testTree2.collectTestIds(treeItem));
1538
- }
1539
- }
1540
- runTests("queue-if-busy", new Set(testIds));
1541
- });
1542
- return () => disposable.dispose();
1543
- }, [runTests, testServerConnection, watchAll, watchedTreeIds, teleSuiteUpdater, projectFilters]);
1544
- React.useEffect(() => {
1545
- if (!testServerConnection)
1546
- return;
1547
- const onShortcutEvent = (e) => {
1548
- if (e.code === "Backquote" && e.ctrlKey) {
1549
- e.preventDefault();
1550
- setIsShowingOutput(!isShowingOutput);
1551
- } else if (e.code === "F5" && e.shiftKey) {
1552
- e.preventDefault();
1553
- testServerConnection == null ? void 0 : testServerConnection.stopTestsNoReply({});
1554
- } else if (e.code === "F5") {
1555
- e.preventDefault();
1556
- runTests("bounce-if-busy", visibleTestIds);
1557
- }
1558
- };
1559
- addEventListener("keydown", onShortcutEvent);
1560
- return () => {
1561
- removeEventListener("keydown", onShortcutEvent);
1562
- };
1563
- }, [runTests, reloadTests, testServerConnection, visibleTestIds, isShowingOutput]);
1564
- const dialogRef = React.useRef(null);
1565
- const openInstallDialog = React.useCallback((e) => {
1566
- var _a2;
1567
- e.preventDefault();
1568
- e.stopPropagation();
1569
- (_a2 = dialogRef.current) == null ? void 0 : _a2.showModal();
1570
- }, []);
1571
- const closeInstallDialog = React.useCallback((e) => {
1572
- var _a2;
1573
- e.preventDefault();
1574
- e.stopPropagation();
1575
- (_a2 = dialogRef.current) == null ? void 0 : _a2.close();
1576
- }, []);
1577
- const installBrowsers = React.useCallback((e) => {
1578
- closeInstallDialog(e);
1579
- setIsShowingOutput(true);
1580
- testServerConnection == null ? void 0 : testServerConnection.installBrowsers({}).then(async () => {
1581
- setIsShowingOutput(false);
1582
- const { hasBrowsers: hasBrowsers2 } = await (testServerConnection == null ? void 0 : testServerConnection.checkBrowsers({}));
1583
- setHasBrowsers(hasBrowsers2);
1584
- });
1585
- }, [closeInstallDialog, testServerConnection]);
1586
- return /* @__PURE__ */ jsxRuntimeExports.jsx(LLMProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "vbox ui-mode", children: [
1587
- !hasBrowsers && /* @__PURE__ */ jsxRuntimeExports.jsxs("dialog", { ref: dialogRef, children: [
1588
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "title", children: [
1589
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "codicon codicon-lightbulb" }),
1590
- "Install browsers"
1591
- ] }),
1592
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "body", children: [
1593
- "Playwright did not find installed browsers.",
1594
- /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
1595
- "Would you like to run `playwright install`?",
1596
- /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
1597
- /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "button", onClick: installBrowsers, children: "Install" }),
1598
- /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "button secondary", onClick: closeInstallDialog, children: "Dismiss" })
1599
- ] })
1600
- ] }),
1601
- isDisconnected && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "disconnected", children: [
1602
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "title", children: "UI Mode disconnected" }),
1603
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1604
- /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "#", onClick: () => window.location.href = "/", children: "Reload the page" }),
1605
- " to reconnect"
1606
- ] })
1607
- ] }),
1608
- /* @__PURE__ */ jsxRuntimeExports.jsx(
1609
- SplitView,
1610
- {
1611
- sidebarSize: 250,
1612
- minSidebarSize: 150,
1613
- orientation: "horizontal",
1614
- sidebarIsFirst: true,
1615
- settingName: "testListSidebar",
1616
- main: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "vbox", children: [
1617
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: clsx("vbox", !isShowingOutput && "hidden"), children: [
1618
- /* @__PURE__ */ jsxRuntimeExports.jsxs(Toolbar, { children: [
1619
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "section-title", style: { flex: "none" }, children: "Output" }),
1620
- /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "circle-slash", title: "Clear output", onClick: () => {
1621
- xtermDataSource.clear();
1622
- setOutputContainsError(false);
1623
- } }),
1624
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "spacer" }),
1625
- /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "close", title: "Close", onClick: () => setIsShowingOutput(false) })
1626
- ] }),
1627
- /* @__PURE__ */ jsxRuntimeExports.jsx(XtermWrapper, { source: xtermDataSource })
1628
- ] }),
1629
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: clsx("vbox", isShowingOutput && "hidden"), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
1630
- TraceView,
1631
- {
1632
- pathSeparator: queryParams.pathSeparator,
1633
- item: selectedItem,
1634
- rootDir: (_a = testModel == null ? void 0 : testModel.config) == null ? void 0 : _a.rootDir,
1635
- revealSource,
1636
- onOpenExternally: (location) => testServerConnection == null ? void 0 : testServerConnection.openNoReply({ location: { file: location.file, line: location.line, column: location.column } })
1637
- }
1638
- ) })
1639
- ] }),
1640
- sidebar: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "vbox ui-mode-sidebar", children: [
1641
- /* @__PURE__ */ jsxRuntimeExports.jsxs(Toolbar, { noShadow: true, noMinHeight: true, children: [
1642
- /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: "playwright-logo.svg", alt: "Playwright logo" }),
1643
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "section-title", children: "Playwright" }),
1644
- /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "refresh", title: "Reload", onClick: () => reloadTests(), disabled: isRunningTest || isLoading }),
1645
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { position: "relative" }, children: [
1646
- /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "terminal", title: "Toggle output — " + (isMac ? "⌃`" : "Ctrl + `"), toggled: isShowingOutput, onClick: () => {
1647
- setIsShowingOutput(!isShowingOutput);
1648
- } }),
1649
- outputContainsError && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { title: "Output contains error", style: { position: "absolute", top: 2, right: 2, width: 7, height: 7, borderRadius: "50%", backgroundColor: "var(--vscode-notificationsErrorIcon-foreground)" } })
1650
- ] }),
1651
- !hasBrowsers && /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "lightbulb-autofix", style: { color: "var(--vscode-list-warningForeground)" }, title: "Playwright browsers are missing", onClick: openInstallDialog })
1652
- ] }),
1653
- /* @__PURE__ */ jsxRuntimeExports.jsx(
1654
- FiltersView,
1655
- {
1656
- filterText,
1657
- setFilterText,
1658
- statusFilters,
1659
- setStatusFilters,
1660
- projectFilters,
1661
- setProjectFilters,
1662
- testModel,
1663
- runTests: () => runTests("bounce-if-busy", visibleTestIds)
1664
- }
1665
- ),
1666
- /* @__PURE__ */ jsxRuntimeExports.jsxs(Toolbar, { noMinHeight: true, children: [
1667
- !isRunningTest && !progress && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "section-title", children: "Tests" }),
1668
- !isRunningTest && progress && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { "data-testid": "status-line", className: "status-line", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1669
- progress.passed,
1670
- "/",
1671
- progress.total,
1672
- " passed (",
1673
- progress.passed / progress.total * 100 | 0,
1674
- "%)"
1675
- ] }) }),
1676
- isRunningTest && progress && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { "data-testid": "status-line", className: "status-line", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1677
- "Running ",
1678
- progress.passed,
1679
- "/",
1680
- runningState.testIds.size,
1681
- " passed (",
1682
- progress.passed / runningState.testIds.size * 100 | 0,
1683
- "%)"
1684
- ] }) }),
1685
- /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "play", title: "Run all — F5", onClick: () => runTests("bounce-if-busy", visibleTestIds), disabled: isRunningTest || isLoading }),
1686
- /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "debug-stop", title: "Stop — " + (isMac ? "⇧F5" : "Shift + F5"), onClick: () => testServerConnection == null ? void 0 : testServerConnection.stopTests({}), disabled: !isRunningTest || isLoading }),
1687
- /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "eye", title: "Watch all", toggled: watchAll, onClick: () => {
1688
- setWatchedTreeIds({ value: /* @__PURE__ */ new Set() });
1689
- setWatchAll(!watchAll);
1690
- } }),
1691
- /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "collapse-all", title: "Collapse all", onClick: () => {
1692
- setCollapseAllCount(collapseAllCount + 1);
1693
- } }),
1694
- /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "expand-all", title: "Expand all", onClick: () => {
1695
- setExpandAllCount(expandAllCount + 1);
1696
- } })
1697
- ] }),
1698
- /* @__PURE__ */ jsxRuntimeExports.jsx(
1699
- TestListView,
1700
- {
1701
- filterText,
1702
- testModel,
1703
- testTree,
1704
- testServerConnection,
1705
- runningState,
1706
- runTests,
1707
- onItemSelected: setSelectedItem,
1708
- watchAll,
1709
- watchedTreeIds,
1710
- setWatchedTreeIds,
1711
- isLoading,
1712
- requestedCollapseAllCount: collapseAllCount,
1713
- requestedExpandAllCount: expandAllCount,
1714
- setFilterText,
1715
- onRevealSource
1716
- }
1717
- ),
1718
- showTestingOptions,
1719
- /* @__PURE__ */ jsxRuntimeExports.jsxs(Toolbar, { noShadow: true, noMinHeight: true, className: "settings-toolbar", onClick: () => setSettingsVisible(!settingsVisible), children: [
1720
- /* @__PURE__ */ jsxRuntimeExports.jsx(
1721
- "span",
1722
- {
1723
- className: `codicon codicon-${settingsVisible ? "chevron-down" : "chevron-right"}`,
1724
- style: { marginLeft: 5 },
1725
- title: settingsVisible ? "Hide Settings" : "Show Settings"
1726
- }
1727
- ),
1728
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "section-title", children: "Settings" })
1729
- ] }),
1730
- settingsVisible && /* @__PURE__ */ jsxRuntimeExports.jsx(DefaultSettingsView, {})
1731
- ] })
1732
- }
1733
- )
1734
- ] }) });
1735
- };
1736
- (async () => {
1737
- applyTheme();
1738
- if (window.location.protocol !== "file:") {
1739
- if (window.location.href.includes("isUnderTest=true"))
1740
- await new Promise((f) => setTimeout(f, 1e3));
1741
- if (!navigator.serviceWorker)
1742
- throw new Error(`Service workers are not supported.
1743
- Make sure to serve the website (${window.location}) via HTTPS or localhost.`);
1744
- navigator.serviceWorker.register("sw.bundle.js");
1745
- if (!navigator.serviceWorker.controller) {
1746
- await new Promise((f) => {
1747
- navigator.serviceWorker.oncontrollerchange = () => f();
1748
- });
1749
- }
1750
- setInterval(function() {
1751
- fetch("ping");
1752
- }, 1e4);
1753
- }
1754
- clientExports.createRoot(document.querySelector("#root")).render(/* @__PURE__ */ jsxRuntimeExports.jsx(UIModeView, {}));
1755
- })();
1756
- //# sourceMappingURL=uiMode.C9_OcpPU.js.map