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.
- package/LICENSE +21 -0
- package/README.md +276 -0
- package/bin/walkwright.js +3 -0
- package/build/aria.d.ts +92 -0
- package/build/aria.js +215 -0
- package/build/aria.js.map +1 -0
- package/build/browser.d.ts +3 -0
- package/build/browser.js +18 -0
- package/build/browser.js.map +1 -0
- package/build/chunk-5CHKYNP7.js +507 -0
- package/build/chunk-5CHKYNP7.js.map +1 -0
- package/build/chunk-6YRKPGUO.js +1197 -0
- package/build/chunk-6YRKPGUO.js.map +1 -0
- package/build/chunk-A452S7R3.js +35 -0
- package/build/chunk-A452S7R3.js.map +1 -0
- package/build/chunk-BODO6HIH.js +60 -0
- package/build/chunk-BODO6HIH.js.map +1 -0
- package/build/chunk-FJI2CMCE.js +439 -0
- package/build/chunk-FJI2CMCE.js.map +1 -0
- package/build/chunk-JYHZVRB2.js +80 -0
- package/build/chunk-JYHZVRB2.js.map +1 -0
- package/build/chunk-KQN5IYN6.js +97 -0
- package/build/chunk-KQN5IYN6.js.map +1 -0
- package/build/chunk-KTXNERHT.js +72 -0
- package/build/chunk-KTXNERHT.js.map +1 -0
- package/build/chunk-MFTC7XL2.js +141 -0
- package/build/chunk-MFTC7XL2.js.map +1 -0
- package/build/chunk-N4SSLHMP.js +108 -0
- package/build/chunk-N4SSLHMP.js.map +1 -0
- package/build/chunk-RNNW7OW2.js +270 -0
- package/build/chunk-RNNW7OW2.js.map +1 -0
- package/build/chunk-UAWBPTDW.js +51 -0
- package/build/chunk-UAWBPTDW.js.map +1 -0
- package/build/chunk-Z7CW5CAY.js +64 -0
- package/build/chunk-Z7CW5CAY.js.map +1 -0
- package/build/cli.d.ts +1 -0
- package/build/cli.js +253 -0
- package/build/cli.js.map +1 -0
- package/build/config.d.ts +13 -0
- package/build/config.js +15 -0
- package/build/config.js.map +1 -0
- package/build/descriptor.d.ts +96 -0
- package/build/descriptor.js +27 -0
- package/build/descriptor.js.map +1 -0
- package/build/device-auth.d.ts +6 -0
- package/build/device-auth.js +11 -0
- package/build/device-auth.js.map +1 -0
- package/build/locator.d.ts +140 -0
- package/build/locator.js +92 -0
- package/build/locator.js.map +1 -0
- package/build/paths.d.ts +11 -0
- package/build/paths.js +22 -0
- package/build/paths.js.map +1 -0
- package/build/pom-kcSMxwX2.d.ts +349 -0
- package/build/pom.d.ts +6 -0
- package/build/pom.js +37 -0
- package/build/pom.js.map +1 -0
- package/build/project.d.ts +13 -0
- package/build/project.js +19 -0
- package/build/project.js.map +1 -0
- package/build/provisioner.d.ts +34 -0
- package/build/provisioner.js +14 -0
- package/build/provisioner.js.map +1 -0
- package/build/recorder.d.ts +6 -0
- package/build/recorder.js +15 -0
- package/build/recorder.js.map +1 -0
- package/build/reporter.d.ts +16 -0
- package/build/reporter.js +426 -0
- package/build/reporter.js.map +1 -0
- package/build/schema.d.ts +49 -0
- package/build/schema.js +16 -0
- package/build/schema.js.map +1 -0
- package/build/storage-state.d.ts +22 -0
- package/build/storage-state.js +42 -0
- package/build/storage-state.js.map +1 -0
- package/build/store.d.ts +17 -0
- package/build/store.js +9 -0
- package/build/store.js.map +1 -0
- package/build/ui.d.ts +49 -0
- package/build/ui.js +56 -0
- package/build/ui.js.map +1 -0
- package/build/upload.d.ts +10 -0
- package/build/upload.js +8 -0
- package/build/upload.js.map +1 -0
- package/build/wait.d.ts +14 -0
- package/build/wait.js +50 -0
- package/build/wait.js.map +1 -0
- package/package.json +52 -0
- package/src/aria.ts +326 -0
- package/src/browser.ts +15 -0
- package/src/cli.ts +295 -0
- package/src/config.ts +16 -0
- package/src/descriptor.ts +179 -0
- package/src/device-auth.ts +188 -0
- package/src/locator.ts +683 -0
- package/src/paths.ts +70 -0
- package/src/pom.ts +2363 -0
- package/src/project.ts +77 -0
- package/src/provisioner.ts +183 -0
- package/src/recorder.ts +877 -0
- package/src/reporter.ts +561 -0
- package/src/schema.ts +37 -0
- package/src/storage-state.ts +71 -0
- package/src/store.ts +96 -0
- package/src/ui.ts +333 -0
- package/src/upload.ts +116 -0
- package/src/wait.ts +63 -0
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
// src/locator.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
function pageOf(mount) {
|
|
4
|
+
return "goto" in mount ? mount : mount.page();
|
|
5
|
+
}
|
|
6
|
+
var textSchema = z.union([
|
|
7
|
+
z.string(),
|
|
8
|
+
z.object({ pattern: z.string(), flags: z.string().optional() }),
|
|
9
|
+
z.object({ param: z.string() }),
|
|
10
|
+
z.object({
|
|
11
|
+
template: z.array(z.union([z.string(), z.object({ param: z.string() })]))
|
|
12
|
+
})
|
|
13
|
+
]);
|
|
14
|
+
var roleStepSchema = z.object({
|
|
15
|
+
by: z.literal("role"),
|
|
16
|
+
role: z.string(),
|
|
17
|
+
name: textSchema.optional(),
|
|
18
|
+
exact: z.literal(true).optional(),
|
|
19
|
+
checked: z.boolean().optional(),
|
|
20
|
+
expanded: z.boolean().optional(),
|
|
21
|
+
selected: z.boolean().optional(),
|
|
22
|
+
pressed: z.boolean().optional(),
|
|
23
|
+
disabled: z.boolean().optional()
|
|
24
|
+
});
|
|
25
|
+
var textStepSchema = z.object({
|
|
26
|
+
by: z.enum(["label", "placeholder", "text", "title"]),
|
|
27
|
+
text: textSchema,
|
|
28
|
+
exact: z.literal(true).optional()
|
|
29
|
+
});
|
|
30
|
+
var testIdStepSchema = z.object({
|
|
31
|
+
by: z.literal("testid"),
|
|
32
|
+
id: z.string()
|
|
33
|
+
});
|
|
34
|
+
var filterSchema = z.object({
|
|
35
|
+
hasText: textSchema.optional(),
|
|
36
|
+
has: z.lazy(() => locatorDescriptorSchema).optional(),
|
|
37
|
+
hasNot: z.lazy(() => locatorDescriptorSchema).optional()
|
|
38
|
+
});
|
|
39
|
+
var refinementSchema = z.union([
|
|
40
|
+
z.object({ filter: filterSchema }),
|
|
41
|
+
z.object({ nth: z.number() })
|
|
42
|
+
]);
|
|
43
|
+
var refinementShape = {
|
|
44
|
+
refine: z.array(refinementSchema).optional()
|
|
45
|
+
};
|
|
46
|
+
var cssXpathStepSchema = z.object({
|
|
47
|
+
by: z.enum(["css", "xpath"]),
|
|
48
|
+
selector: z.string()
|
|
49
|
+
});
|
|
50
|
+
var locatorNodeSchema = z.lazy(
|
|
51
|
+
() => z.union([
|
|
52
|
+
roleStepSchema.extend(refinementShape),
|
|
53
|
+
textStepSchema.extend(refinementShape),
|
|
54
|
+
testIdStepSchema.extend(refinementShape),
|
|
55
|
+
cssXpathStepSchema.extend(refinementShape),
|
|
56
|
+
z.object({ or: z.array(locatorDescriptorSchema) }),
|
|
57
|
+
z.object({ and: z.array(locatorDescriptorSchema) })
|
|
58
|
+
])
|
|
59
|
+
);
|
|
60
|
+
var locatorDescriptorSchema = z.array(locatorNodeSchema);
|
|
61
|
+
function paramValueOf(name, params) {
|
|
62
|
+
const value = params[name];
|
|
63
|
+
if (value === void 0) {
|
|
64
|
+
throw new Error(`missing locator param "${name}"`);
|
|
65
|
+
}
|
|
66
|
+
return value;
|
|
67
|
+
}
|
|
68
|
+
function textOf(text2, params) {
|
|
69
|
+
if (typeof text2 === "string") {
|
|
70
|
+
return text2;
|
|
71
|
+
}
|
|
72
|
+
if ("pattern" in text2) {
|
|
73
|
+
return new RegExp(text2.pattern, text2.flags);
|
|
74
|
+
}
|
|
75
|
+
if ("template" in text2) {
|
|
76
|
+
return text2.template.map(
|
|
77
|
+
(part) => typeof part === "string" ? part : paramValueOf(part.param, params)
|
|
78
|
+
).join("");
|
|
79
|
+
}
|
|
80
|
+
return paramValueOf(text2.param, params);
|
|
81
|
+
}
|
|
82
|
+
function exactOptions(exact) {
|
|
83
|
+
return exact === void 0 ? void 0 : { exact };
|
|
84
|
+
}
|
|
85
|
+
function roleOptions(node, params) {
|
|
86
|
+
const { name, exact, checked, expanded, selected, pressed, disabled } = node;
|
|
87
|
+
if (name === void 0 && exact === void 0 && checked === void 0 && expanded === void 0 && selected === void 0 && pressed === void 0 && disabled === void 0) {
|
|
88
|
+
return void 0;
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
...name === void 0 ? {} : { name: textOf(name, params) },
|
|
92
|
+
...exact === void 0 ? {} : { exact },
|
|
93
|
+
...checked === void 0 ? {} : { checked },
|
|
94
|
+
...expanded === void 0 ? {} : { expanded },
|
|
95
|
+
...selected === void 0 ? {} : { selected },
|
|
96
|
+
...pressed === void 0 ? {} : { pressed },
|
|
97
|
+
...disabled === void 0 ? {} : { disabled }
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function applyStep(current, node, params) {
|
|
101
|
+
if ("or" in node) {
|
|
102
|
+
return orOf(current, node.or, params);
|
|
103
|
+
}
|
|
104
|
+
if ("and" in node) {
|
|
105
|
+
return andOf(current, node.and, params);
|
|
106
|
+
}
|
|
107
|
+
switch (node.by) {
|
|
108
|
+
case "role":
|
|
109
|
+
return current.getByRole(node.role, roleOptions(node, params));
|
|
110
|
+
case "label":
|
|
111
|
+
return current.getByLabel(
|
|
112
|
+
textOf(node.text, params),
|
|
113
|
+
exactOptions(node.exact)
|
|
114
|
+
);
|
|
115
|
+
case "placeholder":
|
|
116
|
+
return current.getByPlaceholder(
|
|
117
|
+
textOf(node.text, params),
|
|
118
|
+
exactOptions(node.exact)
|
|
119
|
+
);
|
|
120
|
+
case "text":
|
|
121
|
+
return current.getByText(
|
|
122
|
+
textOf(node.text, params),
|
|
123
|
+
exactOptions(node.exact)
|
|
124
|
+
);
|
|
125
|
+
case "title":
|
|
126
|
+
return current.getByTitle(
|
|
127
|
+
textOf(node.text, params),
|
|
128
|
+
exactOptions(node.exact)
|
|
129
|
+
);
|
|
130
|
+
case "testid":
|
|
131
|
+
return current.getByTestId(node.id);
|
|
132
|
+
case "css":
|
|
133
|
+
return current.locator(node.selector);
|
|
134
|
+
case "xpath":
|
|
135
|
+
return current.locator(`xpath=${node.selector}`);
|
|
136
|
+
default: {
|
|
137
|
+
const exhaustive = node;
|
|
138
|
+
throw new Error(`unknown locator step: ${JSON.stringify(exhaustive)}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function applyRefinement(located, current, refinement, params) {
|
|
143
|
+
if ("nth" in refinement) {
|
|
144
|
+
return located.nth(refinement.nth);
|
|
145
|
+
}
|
|
146
|
+
const { hasText, has, hasNot } = refinement.filter;
|
|
147
|
+
const page = pageOf(current);
|
|
148
|
+
return located.filter({
|
|
149
|
+
...hasText === void 0 ? {} : { hasText: textOf(hasText, params) },
|
|
150
|
+
...has === void 0 ? {} : { has: resolveLocator(page, has, params) },
|
|
151
|
+
...hasNot === void 0 ? {} : { hasNot: resolveLocator(page, hasNot, params) }
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
function applyNode(current, node, params) {
|
|
155
|
+
const located = applyStep(current, node, params);
|
|
156
|
+
const refine = "by" in node ? node.refine ?? [] : [];
|
|
157
|
+
return refine.reduce(
|
|
158
|
+
(refined, refinement) => applyRefinement(refined, current, refinement, params),
|
|
159
|
+
located
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
function orOf(current, branches, params) {
|
|
163
|
+
const [first, ...rest] = branches;
|
|
164
|
+
if (first === void 0) {
|
|
165
|
+
throw new Error(`locator descriptor's "or" has no branches`);
|
|
166
|
+
}
|
|
167
|
+
return rest.reduce(
|
|
168
|
+
(acc, branch) => acc.or(resolveLocator(current, branch, params)),
|
|
169
|
+
resolveLocator(current, first, params)
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
function andOf(current, branches, params) {
|
|
173
|
+
const [first, ...rest] = branches;
|
|
174
|
+
if (first === void 0) {
|
|
175
|
+
throw new Error(`locator descriptor's "and" has no branches`);
|
|
176
|
+
}
|
|
177
|
+
return rest.reduce(
|
|
178
|
+
(acc, branch) => acc.and(resolveLocator(current, branch, params)),
|
|
179
|
+
resolveLocator(current, first, params)
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
function resolveLocator(scope, locator, params = {}) {
|
|
183
|
+
const [first, ...rest] = locator;
|
|
184
|
+
if (first === void 0) {
|
|
185
|
+
throw new Error("locator descriptor has no nodes");
|
|
186
|
+
}
|
|
187
|
+
return rest.reduce(
|
|
188
|
+
(current, node) => applyNode(current, node, params),
|
|
189
|
+
applyNode(scope, first, params)
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
function isLazyLocator(value) {
|
|
193
|
+
return typeof value === "function" && Array.isArray(value.chain) && Array.isArray(value.params);
|
|
194
|
+
}
|
|
195
|
+
function textFrom(value) {
|
|
196
|
+
return typeof value === "string" ? value : { pattern: value.source, flags: value.flags };
|
|
197
|
+
}
|
|
198
|
+
function plainTextOf(text2, what) {
|
|
199
|
+
if (typeof text2 === "string") {
|
|
200
|
+
return text2;
|
|
201
|
+
}
|
|
202
|
+
if ("pattern" in text2) {
|
|
203
|
+
return new RegExp(text2.pattern, text2.flags);
|
|
204
|
+
}
|
|
205
|
+
throw new Error(`a ${what} cannot be a param placeholder`);
|
|
206
|
+
}
|
|
207
|
+
function hasTextOf(value) {
|
|
208
|
+
return value instanceof RegExp ? textFrom(value) : value;
|
|
209
|
+
}
|
|
210
|
+
function lastNodeOf(locator) {
|
|
211
|
+
const last = locator[locator.length - 1];
|
|
212
|
+
if (last === void 0) {
|
|
213
|
+
throw new Error("locator descriptor has no nodes");
|
|
214
|
+
}
|
|
215
|
+
if ("or" in last || "and" in last) {
|
|
216
|
+
const kind = "or" in last ? "or" : "and";
|
|
217
|
+
throw new Error(`cannot refine an ${kind} node`);
|
|
218
|
+
}
|
|
219
|
+
return last;
|
|
220
|
+
}
|
|
221
|
+
function mergeRefinement(locator, step) {
|
|
222
|
+
const last = lastNodeOf(locator);
|
|
223
|
+
return [
|
|
224
|
+
...locator.slice(0, -1),
|
|
225
|
+
{ ...last, refine: [...last.refine ?? [], step] }
|
|
226
|
+
];
|
|
227
|
+
}
|
|
228
|
+
function filterDescriptorOf(options) {
|
|
229
|
+
return {
|
|
230
|
+
...options.hasText === void 0 ? {} : { hasText: hasTextOf(options.hasText) },
|
|
231
|
+
...options.has === void 0 ? {} : { has: options.has.chain },
|
|
232
|
+
...options.hasNot === void 0 ? {} : { hasNot: options.hasNot.chain }
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
function collectParamNames(locator, seen, names) {
|
|
236
|
+
const noteName = (name) => {
|
|
237
|
+
if (!seen.has(name)) {
|
|
238
|
+
seen.add(name);
|
|
239
|
+
names.push(name);
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
const noteText = (text2) => {
|
|
243
|
+
if (text2 === void 0 || typeof text2 === "string") {
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
if ("param" in text2) {
|
|
247
|
+
noteName(text2.param);
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
if ("template" in text2) {
|
|
251
|
+
for (const part of text2.template) {
|
|
252
|
+
if (typeof part !== "string") {
|
|
253
|
+
noteName(part.param);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
for (const node of locator) {
|
|
259
|
+
if ("or" in node || "and" in node) {
|
|
260
|
+
for (const branch of "or" in node ? node.or : node.and) {
|
|
261
|
+
collectParamNames(branch, seen, names);
|
|
262
|
+
}
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
if (node.by === "role") {
|
|
266
|
+
noteText(node.name);
|
|
267
|
+
} else if ("text" in node) {
|
|
268
|
+
noteText(node.text);
|
|
269
|
+
}
|
|
270
|
+
for (const refinement of node.refine ?? []) {
|
|
271
|
+
if ("filter" in refinement) {
|
|
272
|
+
noteText(refinement.filter.hasText);
|
|
273
|
+
if (refinement.filter.has !== void 0) {
|
|
274
|
+
collectParamNames(refinement.filter.has, seen, names);
|
|
275
|
+
}
|
|
276
|
+
if (refinement.filter.hasNot !== void 0) {
|
|
277
|
+
collectParamNames(refinement.filter.hasNot, seen, names);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
function paramNamesOf(locator) {
|
|
284
|
+
const names = [];
|
|
285
|
+
collectParamNames(locator, /* @__PURE__ */ new Set(), names);
|
|
286
|
+
return names;
|
|
287
|
+
}
|
|
288
|
+
function lazyLocatorOf(locator) {
|
|
289
|
+
function call(scope) {
|
|
290
|
+
return isLazyLocator(scope) ? lazyLocatorOf([...scope.chain, ...locator]) : resolveLocator(scope, locator);
|
|
291
|
+
}
|
|
292
|
+
return Object.assign(call, {
|
|
293
|
+
chain: locator,
|
|
294
|
+
params: paramNamesOf(locator),
|
|
295
|
+
getByRole: (role2, options) => lazyLocatorOf([...locator, roleNodeOf(role2, options?.name, options)]),
|
|
296
|
+
getByLabel: (text2, options) => lazyLocatorOf([...locator, textNodeOf("label", text2, options?.exact)]),
|
|
297
|
+
getByPlaceholder: (text2, options) => lazyLocatorOf([
|
|
298
|
+
...locator,
|
|
299
|
+
textNodeOf("placeholder", text2, options?.exact)
|
|
300
|
+
]),
|
|
301
|
+
getByText: (text2, options) => lazyLocatorOf([...locator, textNodeOf("text", text2, options?.exact)]),
|
|
302
|
+
getByTitle: (text2, options) => lazyLocatorOf([...locator, textNodeOf("title", text2, options?.exact)]),
|
|
303
|
+
getByTestId: (id) => lazyLocatorOf([...locator, { by: "testid", id }]),
|
|
304
|
+
locator: (selector) => lazyLocatorOf([...locator, { by: "css", selector }]),
|
|
305
|
+
filter: (options) => lazyLocatorOf(
|
|
306
|
+
mergeRefinement(locator, { filter: filterDescriptorOf(options) })
|
|
307
|
+
),
|
|
308
|
+
nth: (n) => lazyLocatorOf(mergeRefinement(locator, { nth: n })),
|
|
309
|
+
first: () => lazyLocatorOf(mergeRefinement(locator, { nth: 0 })),
|
|
310
|
+
last: () => lazyLocatorOf(mergeRefinement(locator, { nth: -1 })),
|
|
311
|
+
or: (other) => lazyLocatorOf([{ or: [locator, other.chain] }]),
|
|
312
|
+
and: (other) => lazyLocatorOf([{ and: [locator, other.chain] }]),
|
|
313
|
+
within: (parent) => lazyLocatorOf([...parent.chain, ...locator])
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
function stepLocator(by) {
|
|
317
|
+
return lazyLocatorOf([by]);
|
|
318
|
+
}
|
|
319
|
+
function css(selector) {
|
|
320
|
+
return lazyLocatorOf([{ by: "css", selector }]);
|
|
321
|
+
}
|
|
322
|
+
function xpath(selector) {
|
|
323
|
+
return lazyLocatorOf([{ by: "xpath", selector }]);
|
|
324
|
+
}
|
|
325
|
+
function roleNodeOf(role2, name, options) {
|
|
326
|
+
return {
|
|
327
|
+
by: "role",
|
|
328
|
+
role: role2,
|
|
329
|
+
...name === void 0 ? {} : { name: textFrom(name) },
|
|
330
|
+
...options?.exact === true ? { exact: true } : {},
|
|
331
|
+
...options?.checked === void 0 ? {} : { checked: options.checked },
|
|
332
|
+
...options?.expanded === void 0 ? {} : { expanded: options.expanded },
|
|
333
|
+
...options?.selected === void 0 ? {} : { selected: options.selected },
|
|
334
|
+
...options?.pressed === void 0 ? {} : { pressed: options.pressed },
|
|
335
|
+
...options?.disabled === void 0 ? {} : { disabled: options.disabled }
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
function roleLeaf(role2, name, options) {
|
|
339
|
+
return stepLocator(roleNodeOf(role2, name, options));
|
|
340
|
+
}
|
|
341
|
+
function textNodeOf(by, value, exact) {
|
|
342
|
+
return {
|
|
343
|
+
by,
|
|
344
|
+
text: textFrom(value),
|
|
345
|
+
...exact === true ? { exact: true } : {}
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
function textStepLeaf(by, value, exact) {
|
|
349
|
+
return stepLocator(textNodeOf(by, value, exact));
|
|
350
|
+
}
|
|
351
|
+
var named = (role2) => (name, ...rest) => roleLeaf(role2, name, rest[0]);
|
|
352
|
+
var optionallyNamed = (role2) => (name, ...rest) => roleLeaf(role2, name, rest[0]);
|
|
353
|
+
var button = named("button");
|
|
354
|
+
var link = named("link");
|
|
355
|
+
var heading = named("heading");
|
|
356
|
+
var radio = named("radio");
|
|
357
|
+
var tab = named("tab");
|
|
358
|
+
var option = named("option");
|
|
359
|
+
var menuitem = named("menuitem");
|
|
360
|
+
var columnheader = named("columnheader");
|
|
361
|
+
var textbox = optionallyNamed("textbox");
|
|
362
|
+
var checkbox = optionallyNamed("checkbox");
|
|
363
|
+
var combobox = optionallyNamed("combobox");
|
|
364
|
+
var treeitem = optionallyNamed("treeitem");
|
|
365
|
+
var table = optionallyNamed("table");
|
|
366
|
+
var grid = optionallyNamed("grid");
|
|
367
|
+
var tree = optionallyNamed("tree");
|
|
368
|
+
var list = optionallyNamed("list");
|
|
369
|
+
var listitem = optionallyNamed("listitem");
|
|
370
|
+
var alert = optionallyNamed("alert");
|
|
371
|
+
var main = optionallyNamed("main");
|
|
372
|
+
var navigation = optionallyNamed("navigation");
|
|
373
|
+
var tabpanel = optionallyNamed("tabpanel");
|
|
374
|
+
var menu = optionallyNamed("menu");
|
|
375
|
+
var row = optionallyNamed("row");
|
|
376
|
+
var cell = optionallyNamed("cell");
|
|
377
|
+
var listbox = optionallyNamed("listbox");
|
|
378
|
+
var radiogroup = optionallyNamed("radiogroup");
|
|
379
|
+
var dialog = optionallyNamed("dialog");
|
|
380
|
+
var banner = optionallyNamed("banner");
|
|
381
|
+
function label(value, options) {
|
|
382
|
+
return textStepLeaf("label", value, options?.exact);
|
|
383
|
+
}
|
|
384
|
+
function testId(id) {
|
|
385
|
+
return stepLocator({ by: "testid", id });
|
|
386
|
+
}
|
|
387
|
+
function text(value, options) {
|
|
388
|
+
return textStepLeaf("text", value, options?.exact);
|
|
389
|
+
}
|
|
390
|
+
function role(roleName, name, options) {
|
|
391
|
+
return roleLeaf(roleName, name, options);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
export {
|
|
395
|
+
pageOf,
|
|
396
|
+
textSchema,
|
|
397
|
+
locatorDescriptorSchema,
|
|
398
|
+
resolveLocator,
|
|
399
|
+
isLazyLocator,
|
|
400
|
+
textFrom,
|
|
401
|
+
plainTextOf,
|
|
402
|
+
paramNamesOf,
|
|
403
|
+
lazyLocatorOf,
|
|
404
|
+
css,
|
|
405
|
+
xpath,
|
|
406
|
+
button,
|
|
407
|
+
link,
|
|
408
|
+
heading,
|
|
409
|
+
radio,
|
|
410
|
+
tab,
|
|
411
|
+
option,
|
|
412
|
+
menuitem,
|
|
413
|
+
columnheader,
|
|
414
|
+
textbox,
|
|
415
|
+
checkbox,
|
|
416
|
+
combobox,
|
|
417
|
+
treeitem,
|
|
418
|
+
table,
|
|
419
|
+
grid,
|
|
420
|
+
tree,
|
|
421
|
+
list,
|
|
422
|
+
listitem,
|
|
423
|
+
alert,
|
|
424
|
+
main,
|
|
425
|
+
navigation,
|
|
426
|
+
tabpanel,
|
|
427
|
+
menu,
|
|
428
|
+
row,
|
|
429
|
+
cell,
|
|
430
|
+
listbox,
|
|
431
|
+
radiogroup,
|
|
432
|
+
dialog,
|
|
433
|
+
banner,
|
|
434
|
+
label,
|
|
435
|
+
testId,
|
|
436
|
+
text,
|
|
437
|
+
role
|
|
438
|
+
};
|
|
439
|
+
//# sourceMappingURL=chunk-FJI2CMCE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/locator.ts"],"sourcesContent":["import type { Locator, Page } from \"@playwright/test\";\nimport { z } from \"zod\";\n\nexport type Mount = Page | Locator;\n\nexport type Scope = Page | LazyLocator;\n\nexport function pageOf(mount: Mount): Page {\n return \"goto\" in mount ? mount : mount.page();\n}\n\nexport type Text =\n | string\n | { pattern: string; flags?: string }\n | { param: string }\n | { template: (string | { param: string })[] };\n\nexport const textSchema: z.ZodType<Text> = z.union([\n z.string(),\n z.object({ pattern: z.string(), flags: z.string().optional() }),\n z.object({ param: z.string() }),\n z.object({\n template: z.array(z.union([z.string(), z.object({ param: z.string() })])),\n }),\n]);\n\nexport type By =\n | {\n by: \"role\";\n role: string;\n name?: Text;\n exact?: true;\n checked?: boolean;\n expanded?: boolean;\n selected?: boolean;\n pressed?: boolean;\n disabled?: boolean;\n }\n | { by: \"label\" | \"placeholder\" | \"text\" | \"title\"; text: Text; exact?: true }\n | { by: \"testid\"; id: string };\n\nconst roleStepSchema = z.object({\n by: z.literal(\"role\"),\n role: z.string(),\n name: textSchema.optional(),\n exact: z.literal(true).optional(),\n checked: z.boolean().optional(),\n expanded: z.boolean().optional(),\n selected: z.boolean().optional(),\n pressed: z.boolean().optional(),\n disabled: z.boolean().optional(),\n});\n\nconst textStepSchema = z.object({\n by: z.enum([\"label\", \"placeholder\", \"text\", \"title\"]),\n text: textSchema,\n exact: z.literal(true).optional(),\n});\n\nconst testIdStepSchema = z.object({\n by: z.literal(\"testid\"),\n id: z.string(),\n});\n\nexport interface LocatorFilter {\n hasText?: Text;\n has?: LocatorDescriptor;\n hasNot?: LocatorDescriptor;\n}\n\nexport type Refinement = { filter: LocatorFilter } | { nth: number };\n\nexport interface Refined {\n refine?: Refinement[];\n}\n\nconst filterSchema = z.object({\n hasText: textSchema.optional(),\n has: z\n .lazy((): z.ZodType<LocatorDescriptor> => locatorDescriptorSchema)\n .optional(),\n hasNot: z\n .lazy((): z.ZodType<LocatorDescriptor> => locatorDescriptorSchema)\n .optional(),\n});\n\nconst refinementSchema: z.ZodType<Refinement> = z.union([\n z.object({ filter: filterSchema }),\n z.object({ nth: z.number() }),\n]);\n\nconst refinementShape = {\n refine: z.array(refinementSchema).optional(),\n};\n\nconst cssXpathStepSchema = z.object({\n by: z.enum([\"css\", \"xpath\"]),\n selector: z.string(),\n});\n\nexport type LocatorNode =\n | (By & Refined)\n | ({ by: \"css\" | \"xpath\"; selector: string } & Refined)\n | { or: LocatorDescriptor[] }\n | { and: LocatorDescriptor[] };\n\nconst locatorNodeSchema: z.ZodType<LocatorNode> = z.lazy(() =>\n z.union([\n roleStepSchema.extend(refinementShape),\n textStepSchema.extend(refinementShape),\n testIdStepSchema.extend(refinementShape),\n cssXpathStepSchema.extend(refinementShape),\n z.object({ or: z.array(locatorDescriptorSchema) }),\n z.object({ and: z.array(locatorDescriptorSchema) }),\n ]),\n);\n\nexport type LocatorDescriptor = LocatorNode[];\n\nexport const locatorDescriptorSchema: z.ZodType<LocatorDescriptor> =\n z.array(locatorNodeSchema);\n\nexport type Role = Parameters<Page[\"getByRole\"]>[0];\ntype RoleQueryOptions = Parameters<Page[\"getByRole\"]>[1];\n\nfunction paramValueOf(name: string, params: Record<string, string>): string {\n const value = params[name];\n if (value === undefined) {\n throw new Error(`missing locator param \"${name}\"`);\n }\n\n return value;\n}\n\nfunction textOf(text: Text, params: Record<string, string>): string | RegExp {\n if (typeof text === \"string\") {\n return text;\n }\n\n if (\"pattern\" in text) {\n return new RegExp(text.pattern, text.flags);\n }\n\n if (\"template\" in text) {\n return text.template\n .map((part) =>\n typeof part === \"string\" ? part : paramValueOf(part.param, params),\n )\n .join(\"\");\n }\n\n return paramValueOf(text.param, params);\n}\n\nfunction exactOptions(exact: true | undefined): { exact: true } | undefined {\n return exact === undefined ? undefined : { exact };\n}\n\nfunction roleOptions(\n node: Extract<By, { by: \"role\" }>,\n params: Record<string, string>,\n): RoleQueryOptions {\n const { name, exact, checked, expanded, selected, pressed, disabled } = node;\n\n if (\n name === undefined &&\n exact === undefined &&\n checked === undefined &&\n expanded === undefined &&\n selected === undefined &&\n pressed === undefined &&\n disabled === undefined\n ) {\n return undefined;\n }\n\n return {\n ...(name === undefined ? {} : { name: textOf(name, params) }),\n ...(exact === undefined ? {} : { exact }),\n ...(checked === undefined ? {} : { checked }),\n ...(expanded === undefined ? {} : { expanded }),\n ...(selected === undefined ? {} : { selected }),\n ...(pressed === undefined ? {} : { pressed }),\n ...(disabled === undefined ? {} : { disabled }),\n };\n}\n\nfunction applyStep(\n current: Page | Locator,\n node: LocatorNode,\n params: Record<string, string>,\n): Locator {\n if (\"or\" in node) {\n return orOf(current, node.or, params);\n }\n\n if (\"and\" in node) {\n return andOf(current, node.and, params);\n }\n\n switch (node.by) {\n case \"role\":\n return current.getByRole(node.role as Role, roleOptions(node, params));\n case \"label\":\n return current.getByLabel(\n textOf(node.text, params),\n exactOptions(node.exact),\n );\n case \"placeholder\":\n return current.getByPlaceholder(\n textOf(node.text, params),\n exactOptions(node.exact),\n );\n case \"text\":\n return current.getByText(\n textOf(node.text, params),\n exactOptions(node.exact),\n );\n case \"title\":\n return current.getByTitle(\n textOf(node.text, params),\n exactOptions(node.exact),\n );\n case \"testid\":\n return current.getByTestId(node.id);\n case \"css\":\n return current.locator(node.selector);\n case \"xpath\":\n return current.locator(`xpath=${node.selector}`);\n default: {\n const exhaustive: never = node;\n throw new Error(`unknown locator step: ${JSON.stringify(exhaustive)}`);\n }\n }\n}\n\nfunction applyRefinement(\n located: Locator,\n current: Page | Locator,\n refinement: Refinement,\n params: Record<string, string>,\n): Locator {\n if (\"nth\" in refinement) {\n return located.nth(refinement.nth);\n }\n\n const { hasText, has, hasNot } = refinement.filter;\n const page = pageOf(current);\n\n return located.filter({\n ...(hasText === undefined ? {} : { hasText: textOf(hasText, params) }),\n ...(has === undefined ? {} : { has: resolveLocator(page, has, params) }),\n ...(hasNot === undefined\n ? {}\n : { hasNot: resolveLocator(page, hasNot, params) }),\n });\n}\n\nfunction applyNode(\n current: Page | Locator,\n node: LocatorNode,\n params: Record<string, string>,\n): Locator {\n const located = applyStep(current, node, params);\n const refine = \"by\" in node ? (node.refine ?? []) : [];\n\n return refine.reduce(\n (refined, refinement) =>\n applyRefinement(refined, current, refinement, params),\n located,\n );\n}\n\nfunction orOf(\n current: Page | Locator,\n branches: LocatorDescriptor[],\n params: Record<string, string>,\n): Locator {\n const [first, ...rest] = branches;\n if (first === undefined) {\n throw new Error('locator descriptor\\'s \"or\" has no branches');\n }\n\n return rest.reduce(\n (acc, branch) => acc.or(resolveLocator(current, branch, params)),\n resolveLocator(current, first, params),\n );\n}\n\nfunction andOf(\n current: Page | Locator,\n branches: LocatorDescriptor[],\n params: Record<string, string>,\n): Locator {\n const [first, ...rest] = branches;\n if (first === undefined) {\n throw new Error('locator descriptor\\'s \"and\" has no branches');\n }\n\n return rest.reduce(\n (acc, branch) => acc.and(resolveLocator(current, branch, params)),\n resolveLocator(current, first, params),\n );\n}\n\nexport function resolveLocator(\n scope: Page | Locator,\n locator: LocatorDescriptor,\n params: Record<string, string> = {},\n): Locator {\n const [first, ...rest] = locator;\n if (first === undefined) {\n throw new Error(\"locator descriptor has no nodes\");\n }\n\n return rest.reduce<Locator>(\n (current, node) => applyNode(current, node, params),\n applyNode(scope, first, params),\n );\n}\n\nexport interface FilterOptions {\n hasText?: string | RegExp | Text;\n has?: LazyLocator;\n hasNot?: LazyLocator;\n}\n\nexport interface LazyLocator {\n (scope: LazyLocator): LazyLocator;\n (scope: Page): Locator;\n chain: LocatorDescriptor;\n params: readonly string[];\n getByRole: (\n role: Role,\n options?: RoleLeafOptions & { name?: string | RegExp },\n ) => LazyLocator;\n getByLabel: (text: string | RegExp, options?: NameOptions) => LazyLocator;\n getByPlaceholder: (\n text: string | RegExp,\n options?: NameOptions,\n ) => LazyLocator;\n getByText: (text: string | RegExp, options?: NameOptions) => LazyLocator;\n getByTitle: (text: string | RegExp, options?: NameOptions) => LazyLocator;\n getByTestId: (id: string) => LazyLocator;\n locator: (selector: string) => LazyLocator;\n filter: (options: FilterOptions) => LazyLocator;\n nth: (n: number) => LazyLocator;\n first: () => LazyLocator;\n last: () => LazyLocator;\n or: (other: LazyLocator) => LazyLocator;\n and: (other: LazyLocator) => LazyLocator;\n within: (parent: LazyLocator) => LazyLocator;\n}\n\nexport function isLazyLocator(value: unknown): value is LazyLocator {\n return (\n typeof value === \"function\" &&\n Array.isArray((value as { chain?: unknown }).chain) &&\n Array.isArray((value as { params?: unknown }).params)\n );\n}\n\nexport function textFrom(value: string | RegExp): Text {\n return typeof value === \"string\"\n ? value\n : { pattern: value.source, flags: value.flags };\n}\n\nexport function plainTextOf(text: Text, what: string): string | RegExp {\n if (typeof text === \"string\") {\n return text;\n }\n\n if (\"pattern\" in text) {\n return new RegExp(text.pattern, text.flags);\n }\n\n throw new Error(`a ${what} cannot be a param placeholder`);\n}\n\nfunction hasTextOf(value: string | RegExp | Text): Text {\n return value instanceof RegExp ? textFrom(value) : value;\n}\n\nfunction lastNodeOf(locator: LocatorDescriptor): LocatorNode & Refined {\n const last = locator[locator.length - 1];\n if (last === undefined) {\n throw new Error(\"locator descriptor has no nodes\");\n }\n\n if (\"or\" in last || \"and\" in last) {\n const kind = \"or\" in last ? \"or\" : \"and\";\n throw new Error(`cannot refine an ${kind} node`);\n }\n\n return last;\n}\n\nfunction mergeRefinement(\n locator: LocatorDescriptor,\n step: Refinement,\n): LocatorDescriptor {\n const last = lastNodeOf(locator);\n return [\n ...locator.slice(0, -1),\n { ...last, refine: [...(last.refine ?? []), step] },\n ];\n}\n\nfunction filterDescriptorOf(options: FilterOptions): LocatorFilter {\n return {\n ...(options.hasText === undefined\n ? {}\n : { hasText: hasTextOf(options.hasText) }),\n ...(options.has === undefined ? {} : { has: options.has.chain }),\n ...(options.hasNot === undefined ? {} : { hasNot: options.hasNot.chain }),\n };\n}\n\nfunction collectParamNames(\n locator: LocatorDescriptor,\n seen: Set<string>,\n names: string[],\n): void {\n const noteName = (name: string): void => {\n if (!seen.has(name)) {\n seen.add(name);\n names.push(name);\n }\n };\n\n const noteText = (text: Text | undefined): void => {\n if (text === undefined || typeof text === \"string\") {\n return;\n }\n\n if (\"param\" in text) {\n noteName(text.param);\n return;\n }\n\n if (\"template\" in text) {\n for (const part of text.template) {\n if (typeof part !== \"string\") {\n noteName(part.param);\n }\n }\n }\n };\n\n for (const node of locator) {\n if (\"or\" in node || \"and\" in node) {\n for (const branch of \"or\" in node ? node.or : node.and) {\n collectParamNames(branch, seen, names);\n }\n continue;\n }\n\n if (node.by === \"role\") {\n noteText(node.name);\n } else if (\"text\" in node) {\n noteText(node.text);\n }\n\n for (const refinement of node.refine ?? []) {\n if (\"filter\" in refinement) {\n noteText(refinement.filter.hasText);\n if (refinement.filter.has !== undefined) {\n collectParamNames(refinement.filter.has, seen, names);\n }\n if (refinement.filter.hasNot !== undefined) {\n collectParamNames(refinement.filter.hasNot, seen, names);\n }\n }\n }\n }\n}\n\nexport function paramNamesOf(locator: LocatorDescriptor): string[] {\n const names: string[] = [];\n collectParamNames(locator, new Set(), names);\n return names;\n}\n\nexport function lazyLocatorOf(locator: LocatorDescriptor): LazyLocator {\n function call(scope: LazyLocator): LazyLocator;\n function call(scope: Page): Locator;\n function call(scope: Scope): LazyLocator | Locator {\n return isLazyLocator(scope)\n ? lazyLocatorOf([...scope.chain, ...locator])\n : resolveLocator(scope, locator);\n }\n\n return Object.assign(call, {\n chain: locator,\n params: paramNamesOf(locator),\n getByRole: (\n role: Role,\n options?: RoleLeafOptions & { name?: string | RegExp },\n ): LazyLocator =>\n lazyLocatorOf([...locator, roleNodeOf(role, options?.name, options)]),\n getByLabel: (text: string | RegExp, options?: NameOptions): LazyLocator =>\n lazyLocatorOf([...locator, textNodeOf(\"label\", text, options?.exact)]),\n getByPlaceholder: (\n text: string | RegExp,\n options?: NameOptions,\n ): LazyLocator =>\n lazyLocatorOf([\n ...locator,\n textNodeOf(\"placeholder\", text, options?.exact),\n ]),\n getByText: (text: string | RegExp, options?: NameOptions): LazyLocator =>\n lazyLocatorOf([...locator, textNodeOf(\"text\", text, options?.exact)]),\n getByTitle: (text: string | RegExp, options?: NameOptions): LazyLocator =>\n lazyLocatorOf([...locator, textNodeOf(\"title\", text, options?.exact)]),\n getByTestId: (id: string): LazyLocator =>\n lazyLocatorOf([...locator, { by: \"testid\", id }]),\n locator: (selector: string): LazyLocator =>\n lazyLocatorOf([...locator, { by: \"css\", selector }]),\n filter: (options: FilterOptions): LazyLocator =>\n lazyLocatorOf(\n mergeRefinement(locator, { filter: filterDescriptorOf(options) }),\n ),\n nth: (n: number): LazyLocator =>\n lazyLocatorOf(mergeRefinement(locator, { nth: n })),\n first: (): LazyLocator =>\n lazyLocatorOf(mergeRefinement(locator, { nth: 0 })),\n last: (): LazyLocator =>\n lazyLocatorOf(mergeRefinement(locator, { nth: -1 })),\n or: (other: LazyLocator): LazyLocator =>\n lazyLocatorOf([{ or: [locator, other.chain] }]),\n and: (other: LazyLocator): LazyLocator =>\n lazyLocatorOf([{ and: [locator, other.chain] }]),\n within: (parent: LazyLocator): LazyLocator =>\n lazyLocatorOf([...parent.chain, ...locator]),\n });\n}\n\nfunction stepLocator(by: By): LazyLocator {\n return lazyLocatorOf([by]);\n}\n\nexport function css(selector: string): LazyLocator {\n return lazyLocatorOf([{ by: \"css\", selector }]);\n}\n\nexport function xpath(selector: string): LazyLocator {\n return lazyLocatorOf([{ by: \"xpath\", selector }]);\n}\n\nexport interface NameOptions {\n exact?: boolean;\n}\n\nexport interface RoleLeafOptions extends NameOptions {\n checked?: boolean;\n expanded?: boolean;\n selected?: boolean;\n pressed?: boolean;\n disabled?: boolean;\n}\n\ntype NamedLazyLocator = (\n name: string | RegExp,\n options?: RoleLeafOptions,\n) => LazyLocator;\n\ntype OptionallyNamedLazyLocator = (\n name?: string | RegExp,\n options?: RoleLeafOptions,\n) => LazyLocator;\n\nfunction roleNodeOf(\n role: Role,\n name: string | RegExp | undefined,\n options: RoleLeafOptions | undefined,\n): Extract<By, { by: \"role\" }> {\n return {\n by: \"role\",\n role,\n ...(name === undefined ? {} : { name: textFrom(name) }),\n ...(options?.exact === true ? { exact: true as const } : {}),\n ...(options?.checked === undefined ? {} : { checked: options.checked }),\n ...(options?.expanded === undefined ? {} : { expanded: options.expanded }),\n ...(options?.selected === undefined ? {} : { selected: options.selected }),\n ...(options?.pressed === undefined ? {} : { pressed: options.pressed }),\n ...(options?.disabled === undefined ? {} : { disabled: options.disabled }),\n };\n}\n\nfunction roleLeaf(\n role: Role,\n name: string | RegExp | undefined,\n options: RoleLeafOptions | undefined,\n): LazyLocator {\n return stepLocator(roleNodeOf(role, name, options));\n}\n\nfunction textNodeOf(\n by: \"label\" | \"placeholder\" | \"text\" | \"title\",\n value: string | RegExp,\n exact: boolean | undefined,\n): Extract<By, { by: \"label\" | \"placeholder\" | \"text\" | \"title\" }> {\n return {\n by,\n text: textFrom(value),\n ...(exact === true ? { exact: true as const } : {}),\n };\n}\n\nfunction textStepLeaf(\n by: \"label\" | \"placeholder\" | \"text\" | \"title\",\n value: string | RegExp,\n exact: boolean | undefined,\n): LazyLocator {\n return stepLocator(textNodeOf(by, value, exact));\n}\n\nconst named =\n (role: Role): NamedLazyLocator =>\n (name, ...rest: [RoleLeafOptions?]) =>\n roleLeaf(role, name, rest[0]);\n\nconst optionallyNamed =\n (role: Role): OptionallyNamedLazyLocator =>\n (name, ...rest: [RoleLeafOptions?]) =>\n roleLeaf(role, name, rest[0]);\n\nexport const button = named(\"button\");\nexport const link = named(\"link\");\nexport const heading = named(\"heading\");\nexport const radio = named(\"radio\");\nexport const tab = named(\"tab\");\nexport const option = named(\"option\");\nexport const menuitem = named(\"menuitem\");\nexport const columnheader = named(\"columnheader\");\n\nexport const textbox = optionallyNamed(\"textbox\");\nexport const checkbox = optionallyNamed(\"checkbox\");\nexport const combobox = optionallyNamed(\"combobox\");\nexport const treeitem = optionallyNamed(\"treeitem\");\nexport const table = optionallyNamed(\"table\");\nexport const grid = optionallyNamed(\"grid\");\nexport const tree = optionallyNamed(\"tree\");\nexport const list = optionallyNamed(\"list\");\nexport const listitem = optionallyNamed(\"listitem\");\nexport const alert = optionallyNamed(\"alert\");\nexport const main = optionallyNamed(\"main\");\nexport const navigation = optionallyNamed(\"navigation\");\nexport const tabpanel = optionallyNamed(\"tabpanel\");\nexport const menu = optionallyNamed(\"menu\");\nexport const row = optionallyNamed(\"row\");\nexport const cell = optionallyNamed(\"cell\");\nexport const listbox = optionallyNamed(\"listbox\");\nexport const radiogroup = optionallyNamed(\"radiogroup\");\nexport const dialog = optionallyNamed(\"dialog\");\nexport const banner = optionallyNamed(\"banner\");\n\nexport function label(\n value: string | RegExp,\n options?: NameOptions,\n): LazyLocator {\n return textStepLeaf(\"label\", value, options?.exact);\n}\n\nexport function testId(id: string): LazyLocator {\n return stepLocator({ by: \"testid\", id });\n}\n\nexport function text(\n value: string | RegExp,\n options?: NameOptions,\n): LazyLocator {\n return textStepLeaf(\"text\", value, options?.exact);\n}\n\nexport function role(\n roleName: Role,\n name?: string | RegExp,\n options?: RoleLeafOptions,\n): LazyLocator {\n return roleLeaf(roleName, name, options);\n}\n"],"mappings":"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","names":["text","role"]}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// src/upload.ts
|
|
2
|
+
import { readFileSync } from "fs";
|
|
3
|
+
import { basename, join } from "path";
|
|
4
|
+
var uploadConcurrency = 8;
|
|
5
|
+
async function uploadRun(config, branch, runDir, files, onProgress) {
|
|
6
|
+
const base = config.url.replace(/\/$/, "");
|
|
7
|
+
const auth = { authorization: `Bearer ${config.token}` };
|
|
8
|
+
const { id } = await request(`${base}/api/reports`, {
|
|
9
|
+
method: "POST",
|
|
10
|
+
headers: auth
|
|
11
|
+
});
|
|
12
|
+
let next = 0;
|
|
13
|
+
let done = 0;
|
|
14
|
+
await Promise.all(
|
|
15
|
+
Array.from(
|
|
16
|
+
{ length: Math.min(uploadConcurrency, files.length) },
|
|
17
|
+
async () => {
|
|
18
|
+
while (next < files.length) {
|
|
19
|
+
const file = files[next++];
|
|
20
|
+
if (file === void 0) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
await request(
|
|
24
|
+
`${base}/api/reports/${id}/files/${encodeURIComponent(file)}`,
|
|
25
|
+
{
|
|
26
|
+
method: "PUT",
|
|
27
|
+
headers: auth,
|
|
28
|
+
body: readFileSync(join(runDir, file))
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
onProgress?.(++done, files.length, file);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
)
|
|
35
|
+
);
|
|
36
|
+
const { url, number } = await request(
|
|
37
|
+
`${base}/api/reports/${id}/finalize`,
|
|
38
|
+
{
|
|
39
|
+
method: "POST",
|
|
40
|
+
headers: { ...auth, "x-walkwright-branch": encodeURIComponent(branch) }
|
|
41
|
+
}
|
|
42
|
+
);
|
|
43
|
+
return { url, number: number ?? numberFromUrl(url) };
|
|
44
|
+
}
|
|
45
|
+
function numberFromUrl(url) {
|
|
46
|
+
const last = Number(url.replace(/\/$/, "").split("/").at(-1));
|
|
47
|
+
return Number.isInteger(last) ? last : void 0;
|
|
48
|
+
}
|
|
49
|
+
async function errorDetail(response) {
|
|
50
|
+
let body;
|
|
51
|
+
try {
|
|
52
|
+
body = await response.json();
|
|
53
|
+
} catch {
|
|
54
|
+
return void 0;
|
|
55
|
+
}
|
|
56
|
+
if (typeof body !== "object" || body === null) {
|
|
57
|
+
return void 0;
|
|
58
|
+
}
|
|
59
|
+
const error = body["error"];
|
|
60
|
+
return typeof error === "string" ? error : void 0;
|
|
61
|
+
}
|
|
62
|
+
async function request(url, init) {
|
|
63
|
+
const response = await fetch(url, {
|
|
64
|
+
method: init.method,
|
|
65
|
+
headers: init.headers,
|
|
66
|
+
...init.body === void 0 ? {} : { body: new Uint8Array(init.body) }
|
|
67
|
+
});
|
|
68
|
+
if (!response.ok) {
|
|
69
|
+
const detail = await errorDetail(response);
|
|
70
|
+
throw new Error(
|
|
71
|
+
`upload failed \u2014 ${String(response.status)} on ${init.method} ${basename(url)}${detail === void 0 ? "" : `: ${detail}`}`
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
return await response.json();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export {
|
|
78
|
+
uploadRun
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=chunk-JYHZVRB2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/upload.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { basename, join } from \"node:path\";\n\nimport type { WalkwrightConfig } from \"./project.js\";\n\nconst uploadConcurrency = 8;\n\nexport type UploadProgress = (\n done: number,\n total: number,\n file: string,\n) => void;\n\nexport interface Uploaded {\n url: string;\n number: number | undefined;\n}\n\nexport async function uploadRun(\n config: WalkwrightConfig,\n branch: string,\n runDir: string,\n files: string[],\n onProgress?: UploadProgress,\n): Promise<Uploaded> {\n const base = config.url.replace(/\\/$/, \"\");\n const auth = { authorization: `Bearer ${config.token}` };\n\n const { id } = await request<{ id: string }>(`${base}/api/reports`, {\n method: \"POST\",\n headers: auth,\n });\n\n let next = 0;\n let done = 0;\n\n await Promise.all(\n Array.from(\n { length: Math.min(uploadConcurrency, files.length) },\n async () => {\n while (next < files.length) {\n const file = files[next++];\n\n if (file === undefined) {\n return;\n }\n\n await request(\n `${base}/api/reports/${id}/files/${encodeURIComponent(file)}`,\n {\n method: \"PUT\",\n headers: auth,\n body: readFileSync(join(runDir, file)),\n },\n );\n onProgress?.(++done, files.length, file);\n }\n },\n ),\n );\n\n const { url, number } = await request<{ url: string; number?: number }>(\n `${base}/api/reports/${id}/finalize`,\n {\n method: \"POST\",\n headers: { ...auth, \"x-walkwright-branch\": encodeURIComponent(branch) },\n },\n );\n\n return { url, number: number ?? numberFromUrl(url) };\n}\n\nfunction numberFromUrl(url: string): number | undefined {\n const last = Number(url.replace(/\\/$/, \"\").split(\"/\").at(-1));\n\n return Number.isInteger(last) ? last : undefined;\n}\n\nasync function errorDetail(response: Response): Promise<string | undefined> {\n let body: unknown;\n\n try {\n body = await response.json();\n } catch {\n return undefined;\n }\n\n if (typeof body !== \"object\" || body === null) {\n return undefined;\n }\n\n const error = (body as Record<string, unknown>)[\"error\"];\n\n return typeof error === \"string\" ? error : undefined;\n}\n\nasync function request<Body>(\n url: string,\n init: { method: string; headers: Record<string, string>; body?: Buffer },\n): Promise<Body> {\n const response = await fetch(url, {\n method: init.method,\n headers: init.headers,\n ...(init.body === undefined ? {} : { body: new Uint8Array(init.body) }),\n });\n\n if (!response.ok) {\n const detail = await errorDetail(response);\n\n throw new Error(\n `upload failed — ${String(response.status)} on ${init.method} ${basename(url)}${detail === undefined ? \"\" : `: ${detail}`}`,\n );\n }\n\n return (await response.json()) as Body;\n}\n"],"mappings":";AAAA,SAAS,oBAAoB;AAC7B,SAAS,UAAU,YAAY;AAI/B,IAAM,oBAAoB;AAa1B,eAAsB,UACpB,QACA,QACA,QACA,OACA,YACmB;AACnB,QAAM,OAAO,OAAO,IAAI,QAAQ,OAAO,EAAE;AACzC,QAAM,OAAO,EAAE,eAAe,UAAU,OAAO,KAAK,GAAG;AAEvD,QAAM,EAAE,GAAG,IAAI,MAAM,QAAwB,GAAG,IAAI,gBAAgB;AAAA,IAClE,QAAQ;AAAA,IACR,SAAS;AAAA,EACX,CAAC;AAED,MAAI,OAAO;AACX,MAAI,OAAO;AAEX,QAAM,QAAQ;AAAA,IACZ,MAAM;AAAA,MACJ,EAAE,QAAQ,KAAK,IAAI,mBAAmB,MAAM,MAAM,EAAE;AAAA,MACpD,YAAY;AACV,eAAO,OAAO,MAAM,QAAQ;AAC1B,gBAAM,OAAO,MAAM,MAAM;AAEzB,cAAI,SAAS,QAAW;AACtB;AAAA,UACF;AAEA,gBAAM;AAAA,YACJ,GAAG,IAAI,gBAAgB,EAAE,UAAU,mBAAmB,IAAI,CAAC;AAAA,YAC3D;AAAA,cACE,QAAQ;AAAA,cACR,SAAS;AAAA,cACT,MAAM,aAAa,KAAK,QAAQ,IAAI,CAAC;AAAA,YACvC;AAAA,UACF;AACA,uBAAa,EAAE,MAAM,MAAM,QAAQ,IAAI;AAAA,QACzC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,EAAE,KAAK,OAAO,IAAI,MAAM;AAAA,IAC5B,GAAG,IAAI,gBAAgB,EAAE;AAAA,IACzB;AAAA,MACE,QAAQ;AAAA,MACR,SAAS,EAAE,GAAG,MAAM,uBAAuB,mBAAmB,MAAM,EAAE;AAAA,IACxE;AAAA,EACF;AAEA,SAAO,EAAE,KAAK,QAAQ,UAAU,cAAc,GAAG,EAAE;AACrD;AAEA,SAAS,cAAc,KAAiC;AACtD,QAAM,OAAO,OAAO,IAAI,QAAQ,OAAO,EAAE,EAAE,MAAM,GAAG,EAAE,GAAG,EAAE,CAAC;AAE5D,SAAO,OAAO,UAAU,IAAI,IAAI,OAAO;AACzC;AAEA,eAAe,YAAY,UAAiD;AAC1E,MAAI;AAEJ,MAAI;AACF,WAAO,MAAM,SAAS,KAAK;AAAA,EAC7B,QAAQ;AACN,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAC7C,WAAO;AAAA,EACT;AAEA,QAAM,QAAS,KAAiC,OAAO;AAEvD,SAAO,OAAO,UAAU,WAAW,QAAQ;AAC7C;AAEA,eAAe,QACb,KACA,MACe;AACf,QAAM,WAAW,MAAM,MAAM,KAAK;AAAA,IAChC,QAAQ,KAAK;AAAA,IACb,SAAS,KAAK;AAAA,IACd,GAAI,KAAK,SAAS,SAAY,CAAC,IAAI,EAAE,MAAM,IAAI,WAAW,KAAK,IAAI,EAAE;AAAA,EACvE,CAAC;AAED,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,SAAS,MAAM,YAAY,QAAQ;AAEzC,UAAM,IAAI;AAAA,MACR,wBAAmB,OAAO,SAAS,MAAM,CAAC,OAAO,KAAK,MAAM,IAAI,SAAS,GAAG,CAAC,GAAG,WAAW,SAAY,KAAK,KAAK,MAAM,EAAE;AAAA,IAC3H;AAAA,EACF;AAEA,SAAQ,MAAM,SAAS,KAAK;AAC9B;","names":[]}
|