walkwright 0.0.1

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 (107) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +276 -0
  3. package/bin/walkwright.js +3 -0
  4. package/build/aria.d.ts +92 -0
  5. package/build/aria.js +215 -0
  6. package/build/aria.js.map +1 -0
  7. package/build/browser.d.ts +3 -0
  8. package/build/browser.js +18 -0
  9. package/build/browser.js.map +1 -0
  10. package/build/chunk-5CHKYNP7.js +507 -0
  11. package/build/chunk-5CHKYNP7.js.map +1 -0
  12. package/build/chunk-6YRKPGUO.js +1197 -0
  13. package/build/chunk-6YRKPGUO.js.map +1 -0
  14. package/build/chunk-A452S7R3.js +35 -0
  15. package/build/chunk-A452S7R3.js.map +1 -0
  16. package/build/chunk-BODO6HIH.js +60 -0
  17. package/build/chunk-BODO6HIH.js.map +1 -0
  18. package/build/chunk-FJI2CMCE.js +439 -0
  19. package/build/chunk-FJI2CMCE.js.map +1 -0
  20. package/build/chunk-JYHZVRB2.js +80 -0
  21. package/build/chunk-JYHZVRB2.js.map +1 -0
  22. package/build/chunk-KQN5IYN6.js +97 -0
  23. package/build/chunk-KQN5IYN6.js.map +1 -0
  24. package/build/chunk-KTXNERHT.js +72 -0
  25. package/build/chunk-KTXNERHT.js.map +1 -0
  26. package/build/chunk-MFTC7XL2.js +141 -0
  27. package/build/chunk-MFTC7XL2.js.map +1 -0
  28. package/build/chunk-N4SSLHMP.js +108 -0
  29. package/build/chunk-N4SSLHMP.js.map +1 -0
  30. package/build/chunk-RNNW7OW2.js +270 -0
  31. package/build/chunk-RNNW7OW2.js.map +1 -0
  32. package/build/chunk-UAWBPTDW.js +51 -0
  33. package/build/chunk-UAWBPTDW.js.map +1 -0
  34. package/build/chunk-Z7CW5CAY.js +64 -0
  35. package/build/chunk-Z7CW5CAY.js.map +1 -0
  36. package/build/cli.d.ts +1 -0
  37. package/build/cli.js +253 -0
  38. package/build/cli.js.map +1 -0
  39. package/build/config.d.ts +13 -0
  40. package/build/config.js +15 -0
  41. package/build/config.js.map +1 -0
  42. package/build/descriptor.d.ts +96 -0
  43. package/build/descriptor.js +27 -0
  44. package/build/descriptor.js.map +1 -0
  45. package/build/device-auth.d.ts +6 -0
  46. package/build/device-auth.js +11 -0
  47. package/build/device-auth.js.map +1 -0
  48. package/build/locator.d.ts +140 -0
  49. package/build/locator.js +92 -0
  50. package/build/locator.js.map +1 -0
  51. package/build/paths.d.ts +11 -0
  52. package/build/paths.js +22 -0
  53. package/build/paths.js.map +1 -0
  54. package/build/pom-kcSMxwX2.d.ts +349 -0
  55. package/build/pom.d.ts +6 -0
  56. package/build/pom.js +37 -0
  57. package/build/pom.js.map +1 -0
  58. package/build/project.d.ts +13 -0
  59. package/build/project.js +19 -0
  60. package/build/project.js.map +1 -0
  61. package/build/provisioner.d.ts +34 -0
  62. package/build/provisioner.js +14 -0
  63. package/build/provisioner.js.map +1 -0
  64. package/build/recorder.d.ts +6 -0
  65. package/build/recorder.js +15 -0
  66. package/build/recorder.js.map +1 -0
  67. package/build/reporter.d.ts +16 -0
  68. package/build/reporter.js +426 -0
  69. package/build/reporter.js.map +1 -0
  70. package/build/schema.d.ts +49 -0
  71. package/build/schema.js +16 -0
  72. package/build/schema.js.map +1 -0
  73. package/build/storage-state.d.ts +22 -0
  74. package/build/storage-state.js +42 -0
  75. package/build/storage-state.js.map +1 -0
  76. package/build/store.d.ts +17 -0
  77. package/build/store.js +9 -0
  78. package/build/store.js.map +1 -0
  79. package/build/ui.d.ts +49 -0
  80. package/build/ui.js +56 -0
  81. package/build/ui.js.map +1 -0
  82. package/build/upload.d.ts +10 -0
  83. package/build/upload.js +8 -0
  84. package/build/upload.js.map +1 -0
  85. package/build/wait.d.ts +14 -0
  86. package/build/wait.js +50 -0
  87. package/build/wait.js.map +1 -0
  88. package/package.json +52 -0
  89. package/src/aria.ts +326 -0
  90. package/src/browser.ts +15 -0
  91. package/src/cli.ts +295 -0
  92. package/src/config.ts +16 -0
  93. package/src/descriptor.ts +179 -0
  94. package/src/device-auth.ts +188 -0
  95. package/src/locator.ts +683 -0
  96. package/src/paths.ts +70 -0
  97. package/src/pom.ts +2363 -0
  98. package/src/project.ts +77 -0
  99. package/src/provisioner.ts +183 -0
  100. package/src/recorder.ts +877 -0
  101. package/src/reporter.ts +561 -0
  102. package/src/schema.ts +37 -0
  103. package/src/storage-state.ts +71 -0
  104. package/src/store.ts +96 -0
  105. package/src/ui.ts +333 -0
  106. package/src/upload.ts +116 -0
  107. package/src/wait.ts +63 -0
@@ -0,0 +1,507 @@
1
+ import {
2
+ paramNamesOf,
3
+ resolveLocator
4
+ } from "./chunk-FJI2CMCE.js";
5
+
6
+ // src/recorder.ts
7
+ import { mkdirSync } from "fs";
8
+ var defaultTimeoutMs = 3e4;
9
+ var transitionSettleMs = 300;
10
+ var overlaySettleMs = 500;
11
+ var failedState = "failed";
12
+ function createRecorder(page, runDir, descriptor, { enabled = true } = {}) {
13
+ page.setDefaultTimeout(defaultTimeoutMs);
14
+ const pages = pageMetasOf(descriptor);
15
+ const shots = [];
16
+ const usedNames = /* @__PURE__ */ new Map();
17
+ const identityOf = (target, options) => {
18
+ const meta = pages.find((candidate) => candidate.path === target.path);
19
+ const group = options?.group ?? meta?.group;
20
+ return {
21
+ ...options,
22
+ page: options?.page ?? meta?.name ?? target.name,
23
+ path: target.path,
24
+ ...group === void 0 ? {} : { group }
25
+ };
26
+ };
27
+ const capture = async (state, options, failure = false, dialog) => {
28
+ if (!enabled) {
29
+ return;
30
+ }
31
+ const identity = identify(page.url(), descriptor.pages);
32
+ const shotPage = options?.page ?? identity.page;
33
+ const path = options?.path ?? (options?.page === void 0 ? identity.path : void 0);
34
+ const group = options?.group ?? identity.group;
35
+ const label = options?.state ?? state ?? "";
36
+ const name = slugParts([group?.[0], shotPage, label]);
37
+ const count = (usedNames.get(name) ?? 0) + 1;
38
+ usedNames.set(name, count);
39
+ const file = `${name}${count > 1 ? `-${String(count)}` : ""}.png`;
40
+ if (!failure) {
41
+ shots.push({
42
+ file,
43
+ state: label === "" ? "" : slugify(label),
44
+ page: shotPage,
45
+ ...path === void 0 ? {} : { path },
46
+ ...group === void 0 ? {} : { group }
47
+ });
48
+ }
49
+ const viewport = page.viewportSize();
50
+ const resize = options?.viewport !== void 0 && viewport !== null;
51
+ if (resize) {
52
+ await page.setViewportSize({
53
+ width: options.viewport?.width ?? viewport.width,
54
+ height: options.viewport?.height ?? viewport.height
55
+ });
56
+ }
57
+ try {
58
+ await page.waitForTimeout(transitionSettleMs);
59
+ const rules = collectRules(descriptor, identity.descriptor, dialog);
60
+ try {
61
+ if (rules.length > 0) {
62
+ await applyCaptureRules(page, rules);
63
+ }
64
+ await page.screenshot({ path: `${runDir}/${file}`, fullPage: true });
65
+ } finally {
66
+ if (rules.length > 0) {
67
+ await restoreCaptureRules(page).catch(() => void 0);
68
+ }
69
+ }
70
+ } finally {
71
+ if (resize) {
72
+ await page.setViewportSize(viewport);
73
+ await page.waitForTimeout(200);
74
+ }
75
+ }
76
+ };
77
+ const attempt = async (what, fn) => {
78
+ try {
79
+ return await fn();
80
+ } catch (error) {
81
+ await capture(failedState, void 0, true).catch(() => void 0);
82
+ throw new Error(`recording ${what}: ${describeError(error)}`, {
83
+ cause: error
84
+ });
85
+ }
86
+ };
87
+ const alreadyAt = (url) => {
88
+ try {
89
+ return pathOf(page.url()) === pathOf(new URL(url, page.url()).href);
90
+ } catch {
91
+ return false;
92
+ }
93
+ };
94
+ const visitPage = async (target, params, state, options) => {
95
+ const visiting = instantiate(page, target);
96
+ await attempt(describe(visiting.name, state), async () => {
97
+ if (!alreadyAt(visiting.url(params))) {
98
+ await visiting.goto(params);
99
+ }
100
+ await capture(state, identityOf(visiting, options));
101
+ });
102
+ return visiting;
103
+ };
104
+ const shootCurrentPage = async (target, state, options) => {
105
+ const shooting = instantiate(page, target);
106
+ await attempt(describe(shooting.name, state), async () => {
107
+ const path = pathOf(page.url());
108
+ if (!patternFor(shooting.path).test(path)) {
109
+ throw new Error(
110
+ `the "${shooting.name}" page is at ${shooting.path}, but the browser is at ${path}`
111
+ );
112
+ }
113
+ await capture(state, identityOf(shooting, options));
114
+ });
115
+ return shooting;
116
+ };
117
+ const overlay = async (state, dialog, options) => {
118
+ await attempt(`the "${state}" overlay`, async () => {
119
+ await dialog.waitFor();
120
+ await page.waitForTimeout(overlaySettleMs);
121
+ await capture(state, options, false, dialog);
122
+ await dialog.close();
123
+ await page.waitForTimeout(overlaySettleMs);
124
+ });
125
+ };
126
+ const record = (async (target, second, third, options) => {
127
+ if (isPageTarget(target)) {
128
+ if (second === void 0 || typeof second === "string") {
129
+ return await shootCurrentPage(
130
+ target,
131
+ second,
132
+ third
133
+ );
134
+ }
135
+ return await visitPage(
136
+ target,
137
+ second,
138
+ third,
139
+ options
140
+ );
141
+ }
142
+ if (target !== void 0 && typeof target !== "string") {
143
+ await overlay(
144
+ dialogState(target),
145
+ target,
146
+ second
147
+ );
148
+ return void 0;
149
+ }
150
+ if (isDialog(second)) {
151
+ await overlay(
152
+ target ?? dialogState(second),
153
+ second,
154
+ third
155
+ );
156
+ return void 0;
157
+ }
158
+ await capture(target, second);
159
+ return void 0;
160
+ });
161
+ return {
162
+ record,
163
+ shots: () => shots
164
+ };
165
+ }
166
+ var runDirVariable = "WALKWRIGHT_RUN_DIR";
167
+ var shotsAttachment = "walkwright-shots";
168
+ function pageMetasOf(descriptor) {
169
+ return descriptor.pages.map(({ name, path, recorder }) => ({
170
+ name,
171
+ path,
172
+ ...recorder?.group === void 0 ? {} : { group: recorder.group }
173
+ }));
174
+ }
175
+ function createRecorderFixtures(app) {
176
+ return {
177
+ recording: [false, { option: true }],
178
+ runDir: async ({ recording }, use, testInfo) => {
179
+ if (!recording) {
180
+ await use(testInfo.outputDir);
181
+ return;
182
+ }
183
+ const runDir = process.env[runDirVariable];
184
+ if (runDir === void 0) {
185
+ throw new Error(
186
+ `no ${runDirVariable} in the environment \u2014 add walkwright's reporter to the Playwright config`
187
+ );
188
+ }
189
+ mkdirSync(runDir, { recursive: true });
190
+ await use(runDir);
191
+ },
192
+ record: async ({ page, runDir, recording }, use, testInfo) => {
193
+ const recorder = createRecorder(page, runDir, app.descriptor, {
194
+ enabled: recording
195
+ });
196
+ await use(recorder.record);
197
+ if (!recording) {
198
+ return;
199
+ }
200
+ const recorded = {
201
+ pages: pageMetasOf(app.descriptor),
202
+ shots: recorder.shots()
203
+ };
204
+ await testInfo.attach(shotsAttachment, {
205
+ contentType: "application/json",
206
+ body: Buffer.from(JSON.stringify(recorded))
207
+ });
208
+ }
209
+ };
210
+ }
211
+ function describe(name, state) {
212
+ return state === void 0 ? `the "${name}" page` : `"${name}" ${state}`;
213
+ }
214
+ function instantiate(page, target) {
215
+ return typeof target === "function" ? target(page) : target;
216
+ }
217
+ function isPageTarget(value) {
218
+ if (typeof value === "function") {
219
+ return true;
220
+ }
221
+ return typeof value === "object" && value !== null && "goto" in value && "path" in value;
222
+ }
223
+ function isDialog(value) {
224
+ return typeof value === "object" && value !== null && "close" in value && "waitFor" in value;
225
+ }
226
+ function dialogState(dialog) {
227
+ if (dialog.label === void 0) {
228
+ throw new Error("the overlay needs an explicit state: it has no label");
229
+ }
230
+ return dialog.label;
231
+ }
232
+ function identify(url, pages) {
233
+ const path = pathOf(url);
234
+ const matched = pages.filter((candidate) => patternFor(candidate.path).test(path)).sort(
235
+ (a, b) => paramCount(a.path) - paramCount(b.path) || b.path.length - a.path.length
236
+ ).at(0);
237
+ if (matched === void 0) {
238
+ return { page: pathSlug(path) };
239
+ }
240
+ return {
241
+ page: matched.name,
242
+ path: matched.path,
243
+ ...matched.recorder?.group === void 0 ? {} : { group: matched.recorder.group },
244
+ descriptor: matched
245
+ };
246
+ }
247
+ function chainForElement(path, root, elements) {
248
+ let chain = root;
249
+ let current = elements;
250
+ for (const segment of path) {
251
+ const found = current[segment];
252
+ if (found === void 0) {
253
+ throw new Error(`capture rule references unknown element "${segment}"`);
254
+ }
255
+ if ("locator" in found) {
256
+ chain = [...chain, ...found.locator];
257
+ continue;
258
+ }
259
+ if ("surface" in found) {
260
+ chain = [...chain, ...found.surface.root ?? []];
261
+ current = found.surface.elements;
262
+ continue;
263
+ }
264
+ if ("overlay" in found) {
265
+ chain = [...chain, ...found.overlay.root];
266
+ current = found.overlay.elements;
267
+ continue;
268
+ }
269
+ throw new Error(`capture rule targets "${segment}", which has no locator`);
270
+ }
271
+ return chain;
272
+ }
273
+ function collectAt(root, elements, rule) {
274
+ const chain = rule.element === void 0 ? root : chainForElement(rule.element, root, elements);
275
+ return {
276
+ scope: widenChain(chain),
277
+ ...rule.match === void 0 ? {} : { match: rule.match },
278
+ text: rule.text
279
+ };
280
+ }
281
+ function collectSurfaceRules(surface, root, out) {
282
+ for (const element of Object.values(surface.elements)) {
283
+ if ("surface" in element) {
284
+ collectSurfaceRules(
285
+ element.surface,
286
+ [...root, ...element.surface.root ?? []],
287
+ out
288
+ );
289
+ } else if ("overlay" in element) {
290
+ collectSurfaceRules(
291
+ element.overlay,
292
+ [...root, ...element.overlay.root],
293
+ out
294
+ );
295
+ }
296
+ }
297
+ for (const rule of surface.capture?.rules ?? []) {
298
+ out.push(collectAt(root, surface.elements, rule));
299
+ }
300
+ }
301
+ function collectRules(app, page, dialog) {
302
+ const out = [];
303
+ if (dialog?.descriptor !== void 0 && dialog.self !== void 0) {
304
+ collectSurfaceRules(dialog.descriptor, dialog.self.chain, out);
305
+ }
306
+ if (page !== void 0) {
307
+ collectSurfaceRules(page, [], out);
308
+ }
309
+ for (const rule of app.capture?.rules ?? []) {
310
+ out.push({ scope: [], match: rule.match, text: rule.text });
311
+ }
312
+ return out;
313
+ }
314
+ function textCarriesParam(text) {
315
+ if (text === void 0) {
316
+ return false;
317
+ }
318
+ return paramNamesOf([{ by: "text", text }]).length > 0;
319
+ }
320
+ function widenFilter(filter) {
321
+ const widened = {
322
+ ...filter.hasText === void 0 || textCarriesParam(filter.hasText) ? {} : { hasText: filter.hasText },
323
+ ...filter.has === void 0 ? {} : { has: widenChain(filter.has) },
324
+ ...filter.hasNot === void 0 ? {} : { hasNot: widenChain(filter.hasNot) }
325
+ };
326
+ return Object.keys(widened).length === 0 ? void 0 : widened;
327
+ }
328
+ function widenRefinement(refinement) {
329
+ if ("nth" in refinement) {
330
+ return refinement;
331
+ }
332
+ const filter = widenFilter(refinement.filter);
333
+ return filter === void 0 ? void 0 : { filter };
334
+ }
335
+ function widenRefine(refine) {
336
+ if (refine === void 0) {
337
+ return void 0;
338
+ }
339
+ const widened = refine.map(widenRefinement).filter((refinement) => refinement !== void 0);
340
+ return widened.length === 0 ? void 0 : widened;
341
+ }
342
+ function widenNode(node) {
343
+ if ("or" in node) {
344
+ return { or: node.or.map(widenChain) };
345
+ }
346
+ if ("and" in node) {
347
+ return { and: node.and.map(widenChain) };
348
+ }
349
+ if ((node.by === "text" || node.by === "label" || node.by === "placeholder" || node.by === "title") && textCarriesParam(node.text)) {
350
+ return void 0;
351
+ }
352
+ const { refine, ...base } = node;
353
+ const widenedRefine = widenRefine(refine);
354
+ if (base.by === "role" && textCarriesParam(base.name)) {
355
+ const { name, ...rest } = base;
356
+ return {
357
+ ...rest,
358
+ ...widenedRefine === void 0 ? {} : { refine: widenedRefine }
359
+ };
360
+ }
361
+ return {
362
+ ...base,
363
+ ...widenedRefine === void 0 ? {} : { refine: widenedRefine }
364
+ };
365
+ }
366
+ function widenChain(chain) {
367
+ return chain.map(widenNode).filter((node) => node !== void 0);
368
+ }
369
+ function applyRule(nodes, rule) {
370
+ function isField(node) {
371
+ return node instanceof HTMLInputElement || node instanceof HTMLTextAreaElement;
372
+ }
373
+ function textNodesUnder(root) {
374
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
375
+ acceptNode: (candidate) => {
376
+ const parent = candidate.parentElement;
377
+ return parent !== null && (parent.tagName === "SCRIPT" || parent.tagName === "STYLE") ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT;
378
+ }
379
+ });
380
+ const found = [];
381
+ for (let current = walker.nextNode(); current !== null; current = walker.nextNode()) {
382
+ found.push(current);
383
+ }
384
+ return found;
385
+ }
386
+ function pushRestore(undo) {
387
+ window.__walkwrightRestore ??= [];
388
+ window.__walkwrightRestore.push(undo);
389
+ }
390
+ function write(get, set, value = rule.text) {
391
+ const previous = get();
392
+ const next = rule.match === void 0 ? value : previous.replace(
393
+ new RegExp(rule.match.pattern, rule.match.flags),
394
+ rule.text
395
+ );
396
+ if (next === previous) {
397
+ return;
398
+ }
399
+ set(next);
400
+ pushRestore(() => {
401
+ set(previous);
402
+ });
403
+ }
404
+ function writeField(field) {
405
+ write(
406
+ () => field.value,
407
+ (value) => {
408
+ field.value = value;
409
+ }
410
+ );
411
+ }
412
+ function writeText(text, value) {
413
+ write(
414
+ () => text.data,
415
+ (next) => {
416
+ text.data = next;
417
+ },
418
+ value
419
+ );
420
+ }
421
+ for (const node of nodes) {
422
+ if (isField(node)) {
423
+ writeField(node);
424
+ continue;
425
+ }
426
+ const [first, ...rest] = textNodesUnder(node);
427
+ if (rule.match !== void 0) {
428
+ for (const text of first === void 0 ? [] : [first, ...rest]) {
429
+ writeText(text);
430
+ }
431
+ for (const field of node.querySelectorAll("input,textarea")) {
432
+ writeField(field);
433
+ }
434
+ continue;
435
+ }
436
+ if (first === void 0) {
437
+ const created = document.createTextNode(rule.text);
438
+ node.append(created);
439
+ pushRestore(() => {
440
+ created.remove();
441
+ });
442
+ continue;
443
+ }
444
+ writeText(first);
445
+ for (const extra of rest) {
446
+ writeText(extra, "");
447
+ }
448
+ }
449
+ }
450
+ function restoreAll() {
451
+ const list = window.__walkwrightRestore ?? [];
452
+ for (let index = list.length - 1; index >= 0; index -= 1) {
453
+ list[index]?.();
454
+ }
455
+ window.__walkwrightRestore = [];
456
+ }
457
+ async function applyCaptureRules(page, rules) {
458
+ for (const rule of rules) {
459
+ const locator = rule.scope.length === 0 ? page.locator("body") : resolveLocator(page, rule.scope);
460
+ await locator.evaluateAll(applyRule, {
461
+ text: rule.text,
462
+ ...rule.match === void 0 ? {} : {
463
+ match: {
464
+ pattern: rule.match.pattern,
465
+ flags: rule.match.flags ?? ""
466
+ }
467
+ }
468
+ });
469
+ }
470
+ }
471
+ async function restoreCaptureRules(page) {
472
+ await page.evaluate(restoreAll);
473
+ }
474
+ function patternFor(path) {
475
+ return new RegExp(`^${path.replaceAll(/:[A-Za-z]+/g, "[^/]+")}/?$`);
476
+ }
477
+ function paramCount(path) {
478
+ return path.match(/:[A-Za-z]+/g)?.length ?? 0;
479
+ }
480
+ function pathOf(url) {
481
+ return url.replace(/^[a-z]+:\/\/[^/]+/, "").replace(/[?#].*$/, "");
482
+ }
483
+ var idSegment = /^(?:\d+|[\dA-Za-z_-]{12,})$/;
484
+ function pathSlug(path) {
485
+ const parts = path.split("/").filter((part) => part !== "" && !idSegment.test(part));
486
+ return parts.length === 0 ? "root" : slugify(parts.join("-"));
487
+ }
488
+ function slugParts(parts) {
489
+ return parts.filter((part) => part !== void 0 && part !== "").map(slugify).join("-") || "shot";
490
+ }
491
+ function slugify(value) {
492
+ return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "shot";
493
+ }
494
+ function describeError(error) {
495
+ if (error instanceof Error) {
496
+ return error.message;
497
+ }
498
+ return String(error);
499
+ }
500
+
501
+ export {
502
+ runDirVariable,
503
+ shotsAttachment,
504
+ createRecorderFixtures,
505
+ describeError
506
+ };
507
+ //# sourceMappingURL=chunk-5CHKYNP7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/recorder.ts"],"sourcesContent":["import { mkdirSync } from \"node:fs\";\n\nimport type { Fixtures, Page, PlaywrightTestArgs } from \"@playwright/test\";\n\nimport type {\n AppDescriptor,\n ElementDescriptor,\n OverlayDescriptor,\n PageDescriptor,\n RegexDescriptor,\n SurfaceDescriptor,\n} from \"./descriptor.js\";\nimport type {\n LocatorDescriptor,\n LocatorFilter,\n LocatorNode,\n Text as LocatorText,\n Refinement,\n} from \"./locator.js\";\nimport { paramNamesOf, resolveLocator } from \"./locator.js\";\nimport type { PageMeta } from \"./pom.js\";\n\nexport interface ShotRecord {\n file: string;\n state: string;\n page: string;\n path?: string;\n group?: string[];\n}\n\nexport interface Recorder {\n record: {\n <Target extends VisitablePage<never>>(\n target: PageOrFactory<Target>,\n state?: string,\n options?: ShotOptions,\n ): Promise<Target>;\n <Params, Target extends VisitablePage<Params>>(\n target: PageOrFactory<Target>,\n params: Params,\n state?: string,\n options?: ShotOptions,\n ): Promise<Target>;\n (dialog: OverlayDialog, options?: ShotOptions): Promise<void>;\n (\n state: string,\n dialog: OverlayDialog,\n options?: ShotOptions,\n ): Promise<void>;\n (state?: string, options?: ShotOptions): Promise<void>;\n };\n shots: () => ShotRecord[];\n}\n\nexport interface ShotOptions {\n viewport?: { width?: number; height?: number };\n page?: string;\n group?: string[];\n state?: string;\n}\n\nexport type PageFactory<Target> = (page: Page) => Target;\n\nexport type PageOrFactory<Target> = Target | PageFactory<Target>;\n\nexport interface VisitablePage<Params> {\n path: string;\n name: string;\n url: (params: Params) => string;\n goto: (params: Params) => Promise<void>;\n}\n\nexport interface OverlayDialog {\n label?: string;\n waitFor: (state?: \"visible\" | \"hidden\") => Promise<unknown>;\n close: () => Promise<unknown>;\n descriptor?: OverlayDescriptor;\n self?: { chain: LocatorDescriptor };\n}\n\ninterface Identity {\n page: string;\n path?: string;\n group?: string[];\n descriptor?: PageDescriptor;\n}\n\ninterface CaptureOptions extends ShotOptions {\n path?: string;\n}\n\ninterface RecorderOptions {\n enabled?: boolean;\n}\n\nconst defaultTimeoutMs = 30_000;\nconst transitionSettleMs = 300;\nconst overlaySettleMs = 500;\nconst failedState = \"failed\";\n\nfunction createRecorder(\n page: Page,\n runDir: string,\n descriptor: AppDescriptor,\n { enabled = true }: RecorderOptions = {},\n): Recorder {\n page.setDefaultTimeout(defaultTimeoutMs);\n\n const pages = pageMetasOf(descriptor);\n const shots: ShotRecord[] = [];\n const usedNames = new Map<string, number>();\n\n const identityOf = (\n target: VisitablePage<never> | VisitablePage<unknown>,\n options?: ShotOptions,\n ): CaptureOptions => {\n const meta = pages.find((candidate) => candidate.path === target.path);\n const group = options?.group ?? meta?.group;\n\n return {\n ...options,\n page: options?.page ?? meta?.name ?? target.name,\n path: target.path,\n ...(group === undefined ? {} : { group }),\n };\n };\n\n const capture = async (\n state: string | undefined,\n options?: CaptureOptions,\n failure = false,\n dialog?: OverlayDialog,\n ): Promise<void> => {\n if (!enabled) {\n return;\n }\n\n const identity = identify(page.url(), descriptor.pages);\n const shotPage = options?.page ?? identity.page;\n const path =\n options?.path ??\n (options?.page === undefined ? identity.path : undefined);\n const group = options?.group ?? identity.group;\n const label = options?.state ?? state ?? \"\";\n\n const name = slugParts([group?.[0], shotPage, label]);\n\n const count = (usedNames.get(name) ?? 0) + 1;\n usedNames.set(name, count);\n\n const file = `${name}${count > 1 ? `-${String(count)}` : \"\"}.png`;\n\n if (!failure) {\n shots.push({\n file,\n state: label === \"\" ? \"\" : slugify(label),\n page: shotPage,\n ...(path === undefined ? {} : { path }),\n ...(group === undefined ? {} : { group }),\n });\n }\n\n const viewport = page.viewportSize();\n const resize = options?.viewport !== undefined && viewport !== null;\n if (resize) {\n await page.setViewportSize({\n width: options.viewport?.width ?? viewport.width,\n height: options.viewport?.height ?? viewport.height,\n });\n }\n\n try {\n await page.waitForTimeout(transitionSettleMs);\n\n const rules = collectRules(descriptor, identity.descriptor, dialog);\n\n try {\n if (rules.length > 0) {\n await applyCaptureRules(page, rules);\n }\n\n await page.screenshot({ path: `${runDir}/${file}`, fullPage: true });\n } finally {\n if (rules.length > 0) {\n await restoreCaptureRules(page).catch(() => undefined);\n }\n }\n } finally {\n if (resize) {\n await page.setViewportSize(viewport);\n await page.waitForTimeout(200);\n }\n }\n };\n\n const attempt = async <Result>(\n what: string,\n fn: () => Promise<Result>,\n ): Promise<Result> => {\n try {\n return await fn();\n } catch (error) {\n await capture(failedState, undefined, true).catch(() => undefined);\n\n throw new Error(`recording ${what}: ${describeError(error)}`, {\n cause: error,\n });\n }\n };\n\n const alreadyAt = (url: string): boolean => {\n try {\n return pathOf(page.url()) === pathOf(new URL(url, page.url()).href);\n } catch {\n return false;\n }\n };\n\n const visitPage = async <Params, Target extends VisitablePage<Params>>(\n target: PageOrFactory<Target>,\n params: Params,\n state?: string,\n options?: ShotOptions,\n ): Promise<Target> => {\n const visiting = instantiate(page, target);\n\n await attempt(describe(visiting.name, state), async () => {\n if (!alreadyAt(visiting.url(params))) {\n await visiting.goto(params);\n }\n\n await capture(state, identityOf(visiting, options));\n });\n\n return visiting;\n };\n\n const shootCurrentPage = async <Target extends VisitablePage<never>>(\n target: PageOrFactory<Target>,\n state?: string,\n options?: ShotOptions,\n ): Promise<Target> => {\n const shooting = instantiate(page, target);\n\n await attempt(describe(shooting.name, state), async () => {\n const path = pathOf(page.url());\n\n if (!patternFor(shooting.path).test(path)) {\n throw new Error(\n `the \"${shooting.name}\" page is at ${shooting.path}, but the browser is at ${path}`,\n );\n }\n\n await capture(state, identityOf(shooting, options));\n });\n\n return shooting;\n };\n\n const overlay = async (\n state: string,\n dialog: OverlayDialog,\n options?: ShotOptions,\n ): Promise<void> => {\n await attempt(`the \"${state}\" overlay`, async () => {\n await dialog.waitFor();\n await page.waitForTimeout(overlaySettleMs);\n await capture(state, options, false, dialog);\n await dialog.close();\n await page.waitForTimeout(overlaySettleMs);\n });\n };\n\n const record = (async (\n target?: string | PageOrFactory<VisitablePage<never>> | OverlayDialog,\n second?: unknown,\n third?: unknown,\n options?: ShotOptions,\n ) => {\n if (isPageTarget(target)) {\n if (second === undefined || typeof second === \"string\") {\n return await shootCurrentPage(\n target,\n second,\n third as ShotOptions | undefined,\n );\n }\n\n return await visitPage(\n target as PageOrFactory<VisitablePage<unknown>>,\n second,\n third as string | undefined,\n options,\n );\n }\n\n if (target !== undefined && typeof target !== \"string\") {\n await overlay(\n dialogState(target),\n target,\n second as ShotOptions | undefined,\n );\n\n return undefined;\n }\n\n if (isDialog(second)) {\n await overlay(\n target ?? dialogState(second),\n second,\n third as ShotOptions | undefined,\n );\n\n return undefined;\n }\n\n await capture(target, second as ShotOptions | undefined);\n return undefined;\n }) as Recorder[\"record\"];\n\n return {\n record,\n shots: () => shots,\n };\n}\n\nexport const runDirVariable = \"WALKWRIGHT_RUN_DIR\";\n\nexport const shotsAttachment = \"walkwright-shots\";\n\nexport interface RecordedShots {\n pages: PageMeta[];\n shots: ShotRecord[];\n}\n\nexport interface RecorderFixtures {\n recording: boolean;\n runDir: string;\n record: Recorder[\"record\"];\n}\n\nexport interface RecordedApp {\n descriptor: AppDescriptor;\n}\n\nfunction pageMetasOf(descriptor: AppDescriptor): PageMeta[] {\n return descriptor.pages.map(({ name, path, recorder }) => ({\n name,\n path,\n ...(recorder?.group === undefined ? {} : { group: recorder.group }),\n }));\n}\n\nexport function createRecorderFixtures(\n app: RecordedApp,\n): Fixtures<RecorderFixtures, object, PlaywrightTestArgs> {\n return {\n recording: [false, { option: true }],\n\n runDir: async ({ recording }, use, testInfo): Promise<void> => {\n if (!recording) {\n await use(testInfo.outputDir);\n return;\n }\n\n const runDir = process.env[runDirVariable];\n\n if (runDir === undefined) {\n throw new Error(\n `no ${runDirVariable} in the environment — add walkwright's reporter to the Playwright config`,\n );\n }\n\n mkdirSync(runDir, { recursive: true });\n\n await use(runDir);\n },\n\n record: async (\n { page, runDir, recording },\n use,\n testInfo,\n ): Promise<void> => {\n const recorder = createRecorder(page, runDir, app.descriptor, {\n enabled: recording,\n });\n\n await use(recorder.record);\n\n if (!recording) {\n return;\n }\n\n const recorded: RecordedShots = {\n pages: pageMetasOf(app.descriptor),\n shots: recorder.shots(),\n };\n\n await testInfo.attach(shotsAttachment, {\n contentType: \"application/json\",\n body: Buffer.from(JSON.stringify(recorded)),\n });\n },\n };\n}\n\nfunction describe(name: string, state?: string): string {\n return state === undefined ? `the \"${name}\" page` : `\"${name}\" ${state}`;\n}\n\nfunction instantiate<Target>(\n page: Page,\n target: PageOrFactory<Target>,\n): Target {\n return typeof target === \"function\"\n ? (target as PageFactory<Target>)(page)\n : target;\n}\n\nfunction isPageTarget(\n value: unknown,\n): value is PageOrFactory<VisitablePage<never>> {\n if (typeof value === \"function\") {\n return true;\n }\n\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"goto\" in value &&\n \"path\" in value\n );\n}\n\nfunction isDialog(value: unknown): value is OverlayDialog {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"close\" in value &&\n \"waitFor\" in value\n );\n}\n\nfunction dialogState(dialog: OverlayDialog): string {\n if (dialog.label === undefined) {\n throw new Error(\"the overlay needs an explicit state: it has no label\");\n }\n\n return dialog.label;\n}\n\nfunction identify(url: string, pages: PageDescriptor[]): Identity {\n const path = pathOf(url);\n\n const matched = pages\n .filter((candidate) => patternFor(candidate.path).test(path))\n .sort(\n (a, b) =>\n paramCount(a.path) - paramCount(b.path) ||\n b.path.length - a.path.length,\n )\n .at(0);\n\n if (matched === undefined) {\n return { page: pathSlug(path) };\n }\n\n return {\n page: matched.name,\n path: matched.path,\n ...(matched.recorder?.group === undefined\n ? {}\n : { group: matched.recorder.group }),\n descriptor: matched,\n };\n}\n\ninterface CollectedRule {\n scope: LocatorDescriptor;\n match?: RegexDescriptor;\n text: string;\n}\n\nfunction chainForElement(\n path: string[],\n root: LocatorDescriptor,\n elements: Record<string, ElementDescriptor>,\n): LocatorDescriptor {\n let chain = root;\n let current = elements;\n\n for (const segment of path) {\n const found = current[segment];\n\n if (found === undefined) {\n throw new Error(`capture rule references unknown element \"${segment}\"`);\n }\n\n if (\"locator\" in found) {\n chain = [...chain, ...found.locator];\n continue;\n }\n\n if (\"surface\" in found) {\n chain = [...chain, ...(found.surface.root ?? [])];\n current = found.surface.elements;\n continue;\n }\n\n if (\"overlay\" in found) {\n chain = [...chain, ...found.overlay.root];\n current = found.overlay.elements;\n continue;\n }\n\n throw new Error(`capture rule targets \"${segment}\", which has no locator`);\n }\n\n return chain;\n}\n\nfunction collectAt(\n root: LocatorDescriptor,\n elements: Record<string, ElementDescriptor>,\n rule: { element?: string[]; match?: RegexDescriptor; text: string },\n): CollectedRule {\n const chain =\n rule.element === undefined\n ? root\n : chainForElement(rule.element, root, elements);\n\n return {\n scope: widenChain(chain),\n ...(rule.match === undefined ? {} : { match: rule.match }),\n text: rule.text,\n };\n}\n\nfunction collectSurfaceRules(\n surface: SurfaceDescriptor,\n root: LocatorDescriptor,\n out: CollectedRule[],\n): void {\n for (const element of Object.values(surface.elements)) {\n if (\"surface\" in element) {\n collectSurfaceRules(\n element.surface,\n [...root, ...(element.surface.root ?? [])],\n out,\n );\n } else if (\"overlay\" in element) {\n collectSurfaceRules(\n element.overlay,\n [...root, ...element.overlay.root],\n out,\n );\n }\n }\n\n for (const rule of surface.capture?.rules ?? []) {\n out.push(collectAt(root, surface.elements, rule));\n }\n}\n\nfunction collectRules(\n app: AppDescriptor,\n page: PageDescriptor | undefined,\n dialog: OverlayDialog | undefined,\n): CollectedRule[] {\n const out: CollectedRule[] = [];\n\n if (dialog?.descriptor !== undefined && dialog.self !== undefined) {\n collectSurfaceRules(dialog.descriptor, dialog.self.chain, out);\n }\n\n if (page !== undefined) {\n collectSurfaceRules(page, [], out);\n }\n\n for (const rule of app.capture?.rules ?? []) {\n out.push({ scope: [], match: rule.match, text: rule.text });\n }\n\n return out;\n}\n\nfunction textCarriesParam(text: LocatorText | undefined): boolean {\n if (text === undefined) {\n return false;\n }\n\n return paramNamesOf([{ by: \"text\", text }]).length > 0;\n}\n\nfunction widenFilter(filter: LocatorFilter): LocatorFilter | undefined {\n const widened: LocatorFilter = {\n ...(filter.hasText === undefined || textCarriesParam(filter.hasText)\n ? {}\n : { hasText: filter.hasText }),\n ...(filter.has === undefined ? {} : { has: widenChain(filter.has) }),\n ...(filter.hasNot === undefined\n ? {}\n : { hasNot: widenChain(filter.hasNot) }),\n };\n\n return Object.keys(widened).length === 0 ? undefined : widened;\n}\n\nfunction widenRefinement(refinement: Refinement): Refinement | undefined {\n if (\"nth\" in refinement) {\n return refinement;\n }\n\n const filter = widenFilter(refinement.filter);\n return filter === undefined ? undefined : { filter };\n}\n\nfunction widenRefine(\n refine: Refinement[] | undefined,\n): Refinement[] | undefined {\n if (refine === undefined) {\n return undefined;\n }\n\n const widened = refine\n .map(widenRefinement)\n .filter((refinement): refinement is Refinement => refinement !== undefined);\n\n return widened.length === 0 ? undefined : widened;\n}\n\nfunction widenNode(node: LocatorNode): LocatorNode | undefined {\n if (\"or\" in node) {\n return { or: node.or.map(widenChain) };\n }\n\n if (\"and\" in node) {\n return { and: node.and.map(widenChain) };\n }\n\n if (\n (node.by === \"text\" ||\n node.by === \"label\" ||\n node.by === \"placeholder\" ||\n node.by === \"title\") &&\n textCarriesParam(node.text)\n ) {\n return undefined;\n }\n\n const { refine, ...base } = node;\n const widenedRefine = widenRefine(refine);\n\n if (base.by === \"role\" && textCarriesParam(base.name)) {\n const { name, ...rest } = base;\n return {\n ...rest,\n ...(widenedRefine === undefined ? {} : { refine: widenedRefine }),\n };\n }\n\n return {\n ...base,\n ...(widenedRefine === undefined ? {} : { refine: widenedRefine }),\n };\n}\n\nfunction widenChain(chain: LocatorDescriptor): LocatorDescriptor {\n return chain\n .map(widenNode)\n .filter((node): node is LocatorNode => node !== undefined);\n}\n\ndeclare global {\n interface Window {\n __walkwrightRestore?: (() => void)[];\n }\n}\n\nfunction applyRule(\n nodes: (SVGElement | HTMLElement)[],\n rule: { text: string; match?: { pattern: string; flags: string } },\n): void {\n function isField(\n node: Element,\n ): node is HTMLInputElement | HTMLTextAreaElement {\n return (\n node instanceof HTMLInputElement || node instanceof HTMLTextAreaElement\n );\n }\n\n function textNodesUnder(root: Node): Text[] {\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {\n acceptNode: (candidate) => {\n const parent = candidate.parentElement;\n return parent !== null &&\n (parent.tagName === \"SCRIPT\" || parent.tagName === \"STYLE\")\n ? NodeFilter.FILTER_REJECT\n : NodeFilter.FILTER_ACCEPT;\n },\n });\n\n const found: Text[] = [];\n for (\n let current = walker.nextNode();\n current !== null;\n current = walker.nextNode()\n ) {\n found.push(current as Text);\n }\n\n return found;\n }\n\n function pushRestore(undo: () => void): void {\n window.__walkwrightRestore ??= [];\n window.__walkwrightRestore.push(undo);\n }\n\n function write(\n get: () => string,\n set: (value: string) => void,\n value = rule.text,\n ): void {\n const previous = get();\n const next =\n rule.match === undefined\n ? value\n : previous.replace(\n new RegExp(rule.match.pattern, rule.match.flags),\n rule.text,\n );\n if (next === previous) {\n return;\n }\n set(next);\n pushRestore(() => {\n set(previous);\n });\n }\n\n function writeField(field: HTMLInputElement | HTMLTextAreaElement): void {\n write(\n () => field.value,\n (value) => {\n field.value = value;\n },\n );\n }\n\n function writeText(text: Text, value?: string): void {\n write(\n () => text.data,\n (next) => {\n text.data = next;\n },\n value,\n );\n }\n\n for (const node of nodes) {\n if (isField(node)) {\n writeField(node);\n continue;\n }\n\n const [first, ...rest] = textNodesUnder(node);\n\n if (rule.match !== undefined) {\n for (const text of first === undefined ? [] : [first, ...rest]) {\n writeText(text);\n }\n for (const field of node.querySelectorAll(\"input,textarea\")) {\n writeField(field as HTMLInputElement | HTMLTextAreaElement);\n }\n continue;\n }\n\n if (first === undefined) {\n const created = document.createTextNode(rule.text);\n node.append(created);\n pushRestore(() => {\n created.remove();\n });\n continue;\n }\n\n writeText(first);\n for (const extra of rest) {\n writeText(extra, \"\");\n }\n }\n}\n\nfunction restoreAll(): void {\n const list = window.__walkwrightRestore ?? [];\n for (let index = list.length - 1; index >= 0; index -= 1) {\n list[index]?.();\n }\n window.__walkwrightRestore = [];\n}\n\nasync function applyCaptureRules(\n page: Page,\n rules: CollectedRule[],\n): Promise<void> {\n for (const rule of rules) {\n const locator =\n rule.scope.length === 0\n ? page.locator(\"body\")\n : resolveLocator(page, rule.scope);\n\n await locator.evaluateAll(applyRule, {\n text: rule.text,\n ...(rule.match === undefined\n ? {}\n : {\n match: {\n pattern: rule.match.pattern,\n flags: rule.match.flags ?? \"\",\n },\n }),\n });\n }\n}\n\nasync function restoreCaptureRules(page: Page): Promise<void> {\n await page.evaluate(restoreAll);\n}\n\nfunction patternFor(path: string): RegExp {\n return new RegExp(`^${path.replaceAll(/:[A-Za-z]+/g, \"[^/]+\")}/?$`);\n}\n\nfunction paramCount(path: string): number {\n return path.match(/:[A-Za-z]+/g)?.length ?? 0;\n}\n\nfunction pathOf(url: string): string {\n return url.replace(/^[a-z]+:\\/\\/[^/]+/, \"\").replace(/[?#].*$/, \"\");\n}\n\nconst idSegment = /^(?:\\d+|[\\dA-Za-z_-]{12,})$/;\n\nfunction pathSlug(path: string): string {\n const parts = path\n .split(\"/\")\n .filter((part) => part !== \"\" && !idSegment.test(part));\n\n return parts.length === 0 ? \"root\" : slugify(parts.join(\"-\"));\n}\n\nfunction slugParts(parts: (string | undefined)[]): string {\n return (\n parts\n .filter((part): part is string => part !== undefined && part !== \"\")\n .map(slugify)\n .join(\"-\") || \"shot\"\n );\n}\n\nfunction slugify(value: string): string {\n return (\n value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\") || \"shot\"\n );\n}\n\nexport function describeError(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n\n return String(error);\n}\n"],"mappings":"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","names":[]}