@esimplicity/stack-tests 0.1.0
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 +7 -0
- package/README.md +77 -0
- package/dist/chunk-YPUQQZM2.js +827 -0
- package/dist/index.d.ts +540 -0
- package/dist/index.js +881 -0
- package/dist/steps/index.d.ts +58 -0
- package/dist/steps/index.js +34 -0
- package/package.json +65 -0
|
@@ -0,0 +1,827 @@
|
|
|
1
|
+
// src/steps/api.http.ts
|
|
2
|
+
import { createBdd } from "playwright-bdd";
|
|
3
|
+
|
|
4
|
+
// src/utils.ts
|
|
5
|
+
import { expect } from "@playwright/test";
|
|
6
|
+
function interpolate(template, vars) {
|
|
7
|
+
return String(template).replace(/\{([a-zA-Z0-9_-]+)\}/g, (_, key) => {
|
|
8
|
+
const v = vars[key];
|
|
9
|
+
return v === void 0 ? `{${key}}` : v;
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
function tryParseJson(text) {
|
|
13
|
+
try {
|
|
14
|
+
return JSON.parse(text);
|
|
15
|
+
} catch {
|
|
16
|
+
return void 0;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function tokenize(path) {
|
|
20
|
+
const out = [];
|
|
21
|
+
let i = 0;
|
|
22
|
+
while (i < path.length) {
|
|
23
|
+
if (path[i] === ".") {
|
|
24
|
+
i++;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (path[i] === "[") {
|
|
28
|
+
const j2 = path.indexOf("]", i + 1);
|
|
29
|
+
if (j2 < 0) throw new Error(`Invalid path: ${path}`);
|
|
30
|
+
const idxStr = path.slice(i + 1, j2);
|
|
31
|
+
const idx = Number(idxStr);
|
|
32
|
+
if (!Number.isInteger(idx)) throw new Error(`Invalid array index '${idxStr}' in path '${path}'`);
|
|
33
|
+
out.push(idx);
|
|
34
|
+
i = j2 + 1;
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
let j = i;
|
|
38
|
+
while (j < path.length && /[a-zA-Z0-9_-]/.test(path[j])) j++;
|
|
39
|
+
const key = path.slice(i, j);
|
|
40
|
+
out.push(key);
|
|
41
|
+
i = j;
|
|
42
|
+
}
|
|
43
|
+
return out;
|
|
44
|
+
}
|
|
45
|
+
function selectPath(root, path) {
|
|
46
|
+
if (!path) return root;
|
|
47
|
+
let cur = root;
|
|
48
|
+
for (const token of tokenize(path)) {
|
|
49
|
+
if (typeof token === "number") {
|
|
50
|
+
if (!Array.isArray(cur)) {
|
|
51
|
+
const gotType = cur === null ? "null" : Array.isArray(cur) ? "array" : typeof cur;
|
|
52
|
+
throw new Error(`Path '${path}': expected array but got ${gotType}`);
|
|
53
|
+
}
|
|
54
|
+
cur = cur[token];
|
|
55
|
+
} else {
|
|
56
|
+
if (cur == null || typeof cur !== "object" || Array.isArray(cur)) {
|
|
57
|
+
const gotType = cur === null ? "null" : Array.isArray(cur) ? "array" : typeof cur;
|
|
58
|
+
throw new Error(`Path '${path}': expected object but got ${gotType}`);
|
|
59
|
+
}
|
|
60
|
+
cur = cur[token];
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return cur;
|
|
64
|
+
}
|
|
65
|
+
function parseExpected(input, world) {
|
|
66
|
+
const s = interpolate(input, world.vars);
|
|
67
|
+
if (s === "null") return null;
|
|
68
|
+
if (s === "true") return true;
|
|
69
|
+
if (s === "false") return false;
|
|
70
|
+
if (!Number.isNaN(Number(s)) && s.trim() !== "") return Number(s);
|
|
71
|
+
return s;
|
|
72
|
+
}
|
|
73
|
+
function assertMasked(val) {
|
|
74
|
+
expect(val).toBe("****");
|
|
75
|
+
}
|
|
76
|
+
function registerCleanup(world, item) {
|
|
77
|
+
const method = item.method ?? "DELETE";
|
|
78
|
+
if (world.cleanup.some((c) => c.method === method && c.path === item.path)) return;
|
|
79
|
+
world.cleanup.push({ method, path: item.path });
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// src/steps/api.http.ts
|
|
83
|
+
function registerApiHttpSteps(test) {
|
|
84
|
+
const { When } = createBdd(test);
|
|
85
|
+
async function send(args, method, pathTemplate, body) {
|
|
86
|
+
const { api, world } = args;
|
|
87
|
+
const path = interpolate(pathTemplate, world.vars);
|
|
88
|
+
const result = await api.sendJson(method, path, body, world.headers);
|
|
89
|
+
world.lastStatus = result.status;
|
|
90
|
+
world.lastText = result.text;
|
|
91
|
+
world.lastJson = result.json;
|
|
92
|
+
world.lastHeaders = result.headers;
|
|
93
|
+
world.lastContentType = result.contentType;
|
|
94
|
+
world.lastResponse = result.response;
|
|
95
|
+
}
|
|
96
|
+
When("I GET {string}", { tags: "@api" }, async ({ api, world }, path) => {
|
|
97
|
+
await send({ api, world }, "GET", path);
|
|
98
|
+
});
|
|
99
|
+
When("I DELETE {string}", { tags: "@api" }, async ({ api, world }, path) => {
|
|
100
|
+
await send({ api, world }, "DELETE", path);
|
|
101
|
+
});
|
|
102
|
+
When("I POST {string} with JSON body:", { tags: "@api" }, async ({ api, world }, path, docString) => {
|
|
103
|
+
const interpolated = interpolate(docString ?? "", world.vars);
|
|
104
|
+
const parsed = tryParseJson(interpolated) ?? interpolated;
|
|
105
|
+
await send({ api, world }, "POST", path, parsed);
|
|
106
|
+
});
|
|
107
|
+
When("I PATCH {string} with JSON body:", { tags: "@api" }, async ({ api, world }, path, docString) => {
|
|
108
|
+
const interpolated = interpolate(docString ?? "", world.vars);
|
|
109
|
+
const parsed = tryParseJson(interpolated) ?? interpolated;
|
|
110
|
+
await send({ api, world }, "PATCH", path, parsed);
|
|
111
|
+
});
|
|
112
|
+
When("I PUT {string} with JSON body:", { tags: "@api" }, async ({ api, world }, path, docString) => {
|
|
113
|
+
const interpolated = interpolate(docString ?? "", world.vars);
|
|
114
|
+
const parsed = tryParseJson(interpolated) ?? interpolated;
|
|
115
|
+
await send({ api, world }, "PUT", path, parsed);
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// src/steps/api.assertion.ts
|
|
120
|
+
import { createBdd as createBdd2 } from "playwright-bdd";
|
|
121
|
+
import { expect as expect2 } from "@playwright/test";
|
|
122
|
+
function registerApiAssertionSteps(test) {
|
|
123
|
+
const { Then } = createBdd2(test);
|
|
124
|
+
Then("the response status should be {int}", { tags: "@api" }, async ({ world }, code) => {
|
|
125
|
+
expect2(world.lastStatus, `Unexpected status. Body: ${world.lastText}`).toBe(code);
|
|
126
|
+
});
|
|
127
|
+
Then("the response should be a JSON array", { tags: "@api" }, async ({ world }) => {
|
|
128
|
+
expect2(Array.isArray(world.lastJson), `Expected JSON array. Body: ${world.lastText}`).toBe(true);
|
|
129
|
+
});
|
|
130
|
+
Then("the response should be a JSON object", { tags: "@api" }, async ({ world }) => {
|
|
131
|
+
const v = world.lastJson;
|
|
132
|
+
expect2(v !== null && typeof v === "object" && !Array.isArray(v), `Expected JSON object. Body: ${world.lastText}`).toBe(true);
|
|
133
|
+
});
|
|
134
|
+
Then("the value at {string} should equal {string}", { tags: "@api" }, async ({ world }, path, expectedRaw) => {
|
|
135
|
+
const actual = selectPath(world.lastJson, path);
|
|
136
|
+
const expected = parseExpected(expectedRaw, world);
|
|
137
|
+
expect2(actual).toEqual(expected);
|
|
138
|
+
});
|
|
139
|
+
Then("I store the value at {string} as {string}", { tags: "@api" }, async ({ world, cleanup }, path, varName) => {
|
|
140
|
+
const val = selectPath(world.lastJson, path);
|
|
141
|
+
world.vars[varName] = String(val);
|
|
142
|
+
cleanup.registerFromVar(world, varName, val, world.lastJson);
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// src/steps/api.auth.ts
|
|
147
|
+
import { createBdd as createBdd3 } from "playwright-bdd";
|
|
148
|
+
function registerApiAuthSteps(test) {
|
|
149
|
+
const { Given } = createBdd3(test);
|
|
150
|
+
Given("I am authenticated as an admin via API", { tags: "@api" }, async ({ auth, world }) => {
|
|
151
|
+
await auth.apiLoginAsAdmin(world);
|
|
152
|
+
});
|
|
153
|
+
Given("I am authenticated as a user via API", { tags: "@api" }, async ({ auth, world }) => {
|
|
154
|
+
await auth.apiLoginAsUser(world);
|
|
155
|
+
});
|
|
156
|
+
Given("I set bearer token from variable {string}", { tags: "@api" }, async ({ auth, world }, varName) => {
|
|
157
|
+
const token = world.vars[varName];
|
|
158
|
+
if (!token) throw new Error(`No token found in variable '${varName}'`);
|
|
159
|
+
auth.apiSetBearer(world, token);
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// src/steps/hybrid.ts
|
|
164
|
+
import { createBdd as createBdd4 } from "playwright-bdd";
|
|
165
|
+
function registerHybridSteps(test) {
|
|
166
|
+
const { Given } = createBdd4(test);
|
|
167
|
+
Given("I navigate to interpolated path {string}", { tags: "@hybrid" }, async ({ ui, world }, path) => {
|
|
168
|
+
await ui.goto(interpolate(path, world.vars));
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// src/steps/shared.cleanup.ts
|
|
173
|
+
import { createBdd as createBdd5 } from "playwright-bdd";
|
|
174
|
+
function registerSharedCleanupSteps(test) {
|
|
175
|
+
const { Given } = createBdd5(test);
|
|
176
|
+
Given("I register cleanup DELETE {string}", async ({ world }, pathTemplate) => {
|
|
177
|
+
registerCleanup(world, { method: "DELETE", path: interpolate(pathTemplate, world.vars) });
|
|
178
|
+
});
|
|
179
|
+
Given("I register cleanup POST {string}", async ({ world }, pathTemplate) => {
|
|
180
|
+
registerCleanup(world, { method: "POST", path: interpolate(pathTemplate, world.vars) });
|
|
181
|
+
});
|
|
182
|
+
Given("I register cleanup PATCH {string}", async ({ world }, pathTemplate) => {
|
|
183
|
+
registerCleanup(world, { method: "PATCH", path: interpolate(pathTemplate, world.vars) });
|
|
184
|
+
});
|
|
185
|
+
Given("I register cleanup PUT {string}", async ({ world }, pathTemplate) => {
|
|
186
|
+
registerCleanup(world, { method: "PUT", path: interpolate(pathTemplate, world.vars) });
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// src/steps/shared.vars.ts
|
|
191
|
+
import { createBdd as createBdd6 } from "playwright-bdd";
|
|
192
|
+
import { randomUUID } from "crypto";
|
|
193
|
+
function registerSharedVarSteps(test) {
|
|
194
|
+
const { Given } = createBdd6(test);
|
|
195
|
+
Given("I set variable {string} to {string}", async ({ world }, name, value) => {
|
|
196
|
+
world.vars[name] = value;
|
|
197
|
+
});
|
|
198
|
+
Given("I generate a UUID and store as {string}", async ({ world }, name) => {
|
|
199
|
+
world.vars[name] = randomUUID();
|
|
200
|
+
});
|
|
201
|
+
Given("I set header {string} to {string}", async ({ world }, header, value) => {
|
|
202
|
+
world.headers = { ...world.headers || {}, [header]: value };
|
|
203
|
+
});
|
|
204
|
+
Given("I disable cleanup", async ({ world }) => {
|
|
205
|
+
world.skipCleanup = true;
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// src/steps/ui.basic.ts
|
|
210
|
+
import { createBdd as createBdd7 } from "playwright-bdd";
|
|
211
|
+
function registerUiBasicSteps(test) {
|
|
212
|
+
const { Given, When, Then } = createBdd7(test);
|
|
213
|
+
Given("I navigate to {string}", { tags: "@ui" }, async ({ ui, world }, path) => {
|
|
214
|
+
await ui.goto(interpolate(path, world.vars));
|
|
215
|
+
});
|
|
216
|
+
When("I click the button {string}", { tags: "@ui" }, async ({ ui, world }, name) => {
|
|
217
|
+
await ui.clickButton(interpolate(name, world.vars));
|
|
218
|
+
});
|
|
219
|
+
When("I click the link {string}", { tags: "@ui" }, async ({ ui, world }, name) => {
|
|
220
|
+
await ui.clickLink(interpolate(name, world.vars));
|
|
221
|
+
});
|
|
222
|
+
When("I fill the placeholder {string} with {string}", { tags: "@ui" }, async ({ ui, world }, placeholder, value) => {
|
|
223
|
+
await ui.fillPlaceholder(interpolate(placeholder, world.vars), interpolate(value, world.vars));
|
|
224
|
+
});
|
|
225
|
+
When("I fill the field {string} with {string}", { tags: "@ui" }, async ({ ui, world }, label, value) => {
|
|
226
|
+
await ui.fillLabel(interpolate(label, world.vars), interpolate(value, world.vars));
|
|
227
|
+
});
|
|
228
|
+
When("I log in as admin in UI", { tags: "@ui" }, async ({ auth, world }) => {
|
|
229
|
+
await auth.uiLoginAsAdmin(world);
|
|
230
|
+
});
|
|
231
|
+
When("I log in as user in UI", { tags: "@ui" }, async ({ auth, world }) => {
|
|
232
|
+
await auth.uiLoginAsUser(world);
|
|
233
|
+
});
|
|
234
|
+
Then("I should see text {string}", { tags: "@ui" }, async ({ ui, world }, text) => {
|
|
235
|
+
await ui.expectText(interpolate(text, world.vars));
|
|
236
|
+
});
|
|
237
|
+
Then("the URL should contain {string}", { tags: "@ui" }, async ({ ui, world }, part) => {
|
|
238
|
+
await ui.expectUrlContains(interpolate(part, world.vars));
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// src/steps/ui.wizard.ts
|
|
243
|
+
import { createBdd as createBdd8 } from "playwright-bdd";
|
|
244
|
+
function resolveValue(input, world) {
|
|
245
|
+
const interpolated = interpolate(input, world.vars);
|
|
246
|
+
if (interpolated === input && world.vars[input] !== void 0) {
|
|
247
|
+
return world.vars[input];
|
|
248
|
+
}
|
|
249
|
+
return interpolated;
|
|
250
|
+
}
|
|
251
|
+
function parseNumber(input, world) {
|
|
252
|
+
const resolved = resolveValue(input, world);
|
|
253
|
+
const n = Number.parseFloat(resolved);
|
|
254
|
+
if (!Number.isFinite(n)) {
|
|
255
|
+
throw new Error(`Expected a number but got '${resolved}'`);
|
|
256
|
+
}
|
|
257
|
+
return n;
|
|
258
|
+
}
|
|
259
|
+
function parseOrdinalIndex(input, world) {
|
|
260
|
+
const resolved = resolveValue(input, world);
|
|
261
|
+
const n = Number.parseInt(resolved, 10);
|
|
262
|
+
if (!Number.isFinite(n) || n < 1) {
|
|
263
|
+
throw new Error(`Expected a 1-based index number but got '${resolved}'`);
|
|
264
|
+
}
|
|
265
|
+
return n - 1;
|
|
266
|
+
}
|
|
267
|
+
function locatorByPage(page, method, text) {
|
|
268
|
+
switch (method) {
|
|
269
|
+
case "text":
|
|
270
|
+
return page.getByText(text);
|
|
271
|
+
case "label":
|
|
272
|
+
return page.getByLabel(text);
|
|
273
|
+
case "placeholder":
|
|
274
|
+
return page.getByPlaceholder(text);
|
|
275
|
+
case "role":
|
|
276
|
+
return page.getByRole(text);
|
|
277
|
+
case "test ID":
|
|
278
|
+
return page.getByTestId(text);
|
|
279
|
+
case "alternative text":
|
|
280
|
+
return page.getByAltText(text);
|
|
281
|
+
case "title":
|
|
282
|
+
return page.getByTitle(text);
|
|
283
|
+
case "locator":
|
|
284
|
+
return page.locator(text);
|
|
285
|
+
default: {
|
|
286
|
+
const neverMethod = method;
|
|
287
|
+
throw new Error(`Unsupported locator method '${neverMethod}'`);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
function asClickMode(input) {
|
|
292
|
+
const v = input.trim().toLowerCase();
|
|
293
|
+
if (v === "click" || v === "dispatch click" || v === "force click" || v === "force dispatch click") {
|
|
294
|
+
return v;
|
|
295
|
+
}
|
|
296
|
+
throw new Error(`Unsupported click mode '${input}'`);
|
|
297
|
+
}
|
|
298
|
+
function asInputMode(input) {
|
|
299
|
+
const v = input.trim().toLowerCase();
|
|
300
|
+
if (v === "type" || v === "fill" || v === "choose") {
|
|
301
|
+
return v;
|
|
302
|
+
}
|
|
303
|
+
throw new Error(`Unsupported input mode '${input}'`);
|
|
304
|
+
}
|
|
305
|
+
function asUrlAssertMode(input) {
|
|
306
|
+
const v = input.trim().toLowerCase();
|
|
307
|
+
if (v === "contains" || v === "doesntcontain" || v === "equals") {
|
|
308
|
+
return v === "doesntcontain" ? "doesntContain" : v;
|
|
309
|
+
}
|
|
310
|
+
throw new Error(`Unsupported URL assert mode '${input}'`);
|
|
311
|
+
}
|
|
312
|
+
function asLocatorMethod(input) {
|
|
313
|
+
const v = input.trim().toLowerCase();
|
|
314
|
+
if (v === "text") return "text";
|
|
315
|
+
if (v === "label") return "label";
|
|
316
|
+
if (v === "placeholder") return "placeholder";
|
|
317
|
+
if (v === "role") return "role";
|
|
318
|
+
if (v === "test id" || v === "testid" || v === "test-id") return "test ID";
|
|
319
|
+
if (v === "alternative text" || v === "alt text" || v === "alt") return "alternative text";
|
|
320
|
+
if (v === "title") return "title";
|
|
321
|
+
if (v === "locator") return "locator";
|
|
322
|
+
throw new Error(`Unsupported locator method '${input}'`);
|
|
323
|
+
}
|
|
324
|
+
function asElementState(input) {
|
|
325
|
+
const v = input.trim().toLowerCase();
|
|
326
|
+
if (v === "visible" || v === "hidden" || v === "editable" || v === "disabled" || v === "enabled") return v;
|
|
327
|
+
if (v === "read-only" || v === "readonly" || v === "read only") return "read-only";
|
|
328
|
+
throw new Error(`Unsupported element state '${input}'`);
|
|
329
|
+
}
|
|
330
|
+
function parseRegex(input) {
|
|
331
|
+
const raw = String(input);
|
|
332
|
+
if (raw.startsWith("/") && raw.lastIndexOf("/") > 0) {
|
|
333
|
+
const last = raw.lastIndexOf("/");
|
|
334
|
+
const pattern = raw.slice(1, last);
|
|
335
|
+
const flags = raw.slice(last + 1);
|
|
336
|
+
return new RegExp(pattern, flags);
|
|
337
|
+
}
|
|
338
|
+
return new RegExp(raw);
|
|
339
|
+
}
|
|
340
|
+
function registerWizardSteps(test) {
|
|
341
|
+
const { Given, When, Then } = createBdd8(test);
|
|
342
|
+
Given("I open {string} page", { tags: "@ui" }, async ({ ui, world }, urlOrVar) => {
|
|
343
|
+
await ui.goto(resolveValue(urlOrVar, world));
|
|
344
|
+
});
|
|
345
|
+
Given("I open {string} in the browser", { tags: "@ui" }, async ({ ui, world }, urlOrVar) => {
|
|
346
|
+
await ui.goto(resolveValue(urlOrVar, world));
|
|
347
|
+
});
|
|
348
|
+
When("I go back in the browser", { tags: "@ui" }, async ({ ui }) => {
|
|
349
|
+
await ui.goBack();
|
|
350
|
+
});
|
|
351
|
+
When("I save the current URL as {string}", { tags: "@ui" }, async ({ ui, world }, varName) => {
|
|
352
|
+
world.vars[varName] = await ui.getCurrentUrl();
|
|
353
|
+
});
|
|
354
|
+
When("I save the current url as {string}", { tags: "@ui" }, async ({ ui, world }, varName) => {
|
|
355
|
+
world.vars[varName] = await ui.getCurrentUrl();
|
|
356
|
+
});
|
|
357
|
+
Then("I zoom to {string} in the browser", { tags: "@ui" }, async ({ ui, world }, scale) => {
|
|
358
|
+
await ui.zoomTo(parseNumber(scale, world));
|
|
359
|
+
});
|
|
360
|
+
When("I reload the page", { tags: "@ui" }, async ({ ui }) => {
|
|
361
|
+
await ui.reload();
|
|
362
|
+
});
|
|
363
|
+
Then("I wait {string} seconds", { tags: "@ui" }, async ({ ui, world }, seconds) => {
|
|
364
|
+
await ui.waitSeconds(parseNumber(seconds, world));
|
|
365
|
+
});
|
|
366
|
+
Then("I wait for the page to load", { tags: "@ui" }, async ({ ui }) => {
|
|
367
|
+
await ui.waitForPageLoad();
|
|
368
|
+
});
|
|
369
|
+
When(
|
|
370
|
+
"I get a part of the URL based on {string} regular expression and save it as {string}",
|
|
371
|
+
{ tags: "@ui" },
|
|
372
|
+
async ({ ui, world }, regexString, varName) => {
|
|
373
|
+
const url = await ui.getCurrentUrl();
|
|
374
|
+
const regex = parseRegex(resolveValue(regexString, world));
|
|
375
|
+
const match = regex.exec(url);
|
|
376
|
+
if (!match) throw new Error(`Regex '${regex}' did not match URL '${url}'`);
|
|
377
|
+
world.vars[varName] = match[1] ?? match[0];
|
|
378
|
+
}
|
|
379
|
+
);
|
|
380
|
+
Then("I {string} {string}", { tags: "@ui" }, async ({ ui, world }, action, value) => {
|
|
381
|
+
const verb = action.trim().toLowerCase();
|
|
382
|
+
const resolved = resolveValue(value, world);
|
|
383
|
+
if (verb === "type") {
|
|
384
|
+
await ui.typeText(resolved);
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
if (verb === "press") {
|
|
388
|
+
await ui.pressKey(resolved);
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
throw new Error(`Unsupported keyboard action '${action}'. Expected 'type' or 'press'.`);
|
|
392
|
+
});
|
|
393
|
+
When(
|
|
394
|
+
"I {string} the {string} element that contains {string}",
|
|
395
|
+
{ tags: "@ui" },
|
|
396
|
+
async ({ ui, world }, clickMode, elementType, text) => {
|
|
397
|
+
await ui.clickElementThatContains(
|
|
398
|
+
asClickMode(resolveValue(clickMode, world)),
|
|
399
|
+
resolveValue(elementType, world),
|
|
400
|
+
resolveValue(text, world)
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
);
|
|
404
|
+
When(
|
|
405
|
+
"I {string} the {string} element with {string} {string}",
|
|
406
|
+
{ tags: "@ui" },
|
|
407
|
+
async ({ ui, world }, clickMode, ordinal, text, method) => {
|
|
408
|
+
await ui.clickElementWith(
|
|
409
|
+
asClickMode(resolveValue(clickMode, world)),
|
|
410
|
+
resolveValue(ordinal, world),
|
|
411
|
+
resolveValue(text, world),
|
|
412
|
+
asLocatorMethod(resolveValue(method, world))
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
);
|
|
416
|
+
When("I click on the top left corner of the page", { tags: "@ui" }, async ({ page }) => {
|
|
417
|
+
await page.mouse.click(0, 0);
|
|
418
|
+
});
|
|
419
|
+
When(
|
|
420
|
+
"If its visible, I {string} the {string} element with {string} {string}",
|
|
421
|
+
{ tags: "@ui" },
|
|
422
|
+
async ({ page, ui, world }, clickMode, ordinal, text, method) => {
|
|
423
|
+
const idx = parseOrdinalIndex(ordinal, world);
|
|
424
|
+
const resolvedText = resolveValue(text, world);
|
|
425
|
+
const resolvedMethod = asLocatorMethod(resolveValue(method, world));
|
|
426
|
+
const locator = locatorByPage(page, resolvedMethod, resolvedText).nth(idx);
|
|
427
|
+
if (await locator.count() === 0) return;
|
|
428
|
+
if (!await locator.isVisible()) return;
|
|
429
|
+
await ui.clickElementWith(asClickMode(resolveValue(clickMode, world)), ordinal, resolvedText, resolvedMethod);
|
|
430
|
+
}
|
|
431
|
+
);
|
|
432
|
+
Then("I fill {string} into the {string} dropdown", { tags: "@ui" }, async ({ ui, world }, value, label) => {
|
|
433
|
+
await ui.fillDropdown(resolveValue(value, world), resolveValue(label, world));
|
|
434
|
+
});
|
|
435
|
+
When(
|
|
436
|
+
"I {string} {string} in the {string} element with {string} {string}",
|
|
437
|
+
{ tags: "@ui" },
|
|
438
|
+
async ({ ui, world }, action, value, ordinal, text, method) => {
|
|
439
|
+
await ui.inputInElement(
|
|
440
|
+
asInputMode(resolveValue(action, world)),
|
|
441
|
+
resolveValue(value, world),
|
|
442
|
+
resolveValue(ordinal, world),
|
|
443
|
+
resolveValue(text, world),
|
|
444
|
+
asLocatorMethod(resolveValue(method, world))
|
|
445
|
+
);
|
|
446
|
+
}
|
|
447
|
+
);
|
|
448
|
+
Then(
|
|
449
|
+
"I verify if a new tab which URL {string} {string} opens",
|
|
450
|
+
{ tags: "@ui" },
|
|
451
|
+
async ({ ui, world }, mode, expected) => {
|
|
452
|
+
await ui.expectNewTabUrl(asUrlAssertMode(resolveValue(mode, world)), resolveValue(expected, world));
|
|
453
|
+
}
|
|
454
|
+
);
|
|
455
|
+
Then(
|
|
456
|
+
"I verify if a new tab which url {string} {string} opens",
|
|
457
|
+
{ tags: "@ui" },
|
|
458
|
+
async ({ ui, world }, mode, expected) => {
|
|
459
|
+
await ui.expectNewTabUrl(asUrlAssertMode(resolveValue(mode, world)), resolveValue(expected, world));
|
|
460
|
+
}
|
|
461
|
+
);
|
|
462
|
+
Then("I verify if the URL {string} {string}", { tags: "@ui" }, async ({ ui, world }, mode, expected) => {
|
|
463
|
+
await ui.expectUrl(asUrlAssertMode(resolveValue(mode, world)), resolveValue(expected, world));
|
|
464
|
+
});
|
|
465
|
+
Then("I verify if the url {string} {string}", { tags: "@ui" }, async ({ ui, world }, mode, expected) => {
|
|
466
|
+
await ui.expectUrl(asUrlAssertMode(resolveValue(mode, world)), resolveValue(expected, world));
|
|
467
|
+
});
|
|
468
|
+
Then("I verify if the URL {string} {string} opens", { tags: "@ui" }, async ({ ui, world }, mode, expected) => {
|
|
469
|
+
await ui.expectUrl(asUrlAssertMode(resolveValue(mode, world)), resolveValue(expected, world));
|
|
470
|
+
});
|
|
471
|
+
Then("I verify if the url {string} {string} opens", { tags: "@ui" }, async ({ ui, world }, mode, expected) => {
|
|
472
|
+
await ui.expectUrl(asUrlAssertMode(resolveValue(mode, world)), resolveValue(expected, world));
|
|
473
|
+
});
|
|
474
|
+
Then(
|
|
475
|
+
"I verify that a {string} element with {string} text {string} visible",
|
|
476
|
+
{ tags: "@ui" },
|
|
477
|
+
async ({ ui, world }, elementType, text, assertion) => {
|
|
478
|
+
const normalized = resolveValue(assertion, world).trim().toLowerCase();
|
|
479
|
+
const shouldBeVisible = normalized === "is";
|
|
480
|
+
if (!shouldBeVisible && normalized !== "is not") {
|
|
481
|
+
throw new Error(`Expected 'is' or 'is not' but got '${assertion}'`);
|
|
482
|
+
}
|
|
483
|
+
await ui.expectElementWithTextVisible(resolveValue(elementType, world), resolveValue(text, world), shouldBeVisible);
|
|
484
|
+
}
|
|
485
|
+
);
|
|
486
|
+
Then(
|
|
487
|
+
"I verify that {string} element with {string} {string} is {string}",
|
|
488
|
+
{ tags: "@ui" },
|
|
489
|
+
async ({ ui, world }, ordinal, text, method, state) => {
|
|
490
|
+
await ui.expectElementState(
|
|
491
|
+
resolveValue(ordinal, world),
|
|
492
|
+
resolveValue(text, world),
|
|
493
|
+
asLocatorMethod(resolveValue(method, world)),
|
|
494
|
+
asElementState(resolveValue(state, world))
|
|
495
|
+
);
|
|
496
|
+
}
|
|
497
|
+
);
|
|
498
|
+
Then(
|
|
499
|
+
"I verify that {string} element with {string} {string} becomes {string} during {string} seconds",
|
|
500
|
+
{ tags: "@ui" },
|
|
501
|
+
async ({ ui, world }, ordinal, text, method, state, seconds) => {
|
|
502
|
+
await ui.expectElementStateWithin(
|
|
503
|
+
resolveValue(ordinal, world),
|
|
504
|
+
resolveValue(text, world),
|
|
505
|
+
asLocatorMethod(resolveValue(method, world)),
|
|
506
|
+
asElementState(resolveValue(state, world)),
|
|
507
|
+
parseNumber(seconds, world)
|
|
508
|
+
);
|
|
509
|
+
}
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// src/steps/tui.basic.ts
|
|
514
|
+
import { createBdd as createBdd9 } from "playwright-bdd";
|
|
515
|
+
function registerTuiBasicSteps(test) {
|
|
516
|
+
const { Given, When, Then } = createBdd9(test);
|
|
517
|
+
Given("I start the TUI application", { tags: "@tui" }, async ({ tui }) => {
|
|
518
|
+
await tui.start();
|
|
519
|
+
await tui.waitForReady();
|
|
520
|
+
});
|
|
521
|
+
Given("the TUI application is running", { tags: "@tui" }, async ({ tui }) => {
|
|
522
|
+
if (!tui.isRunning()) {
|
|
523
|
+
await tui.start();
|
|
524
|
+
await tui.waitForReady();
|
|
525
|
+
}
|
|
526
|
+
});
|
|
527
|
+
When("I restart the TUI application", { tags: "@tui" }, async ({ tui }) => {
|
|
528
|
+
await tui.restart();
|
|
529
|
+
await tui.waitForReady();
|
|
530
|
+
});
|
|
531
|
+
When("I stop the TUI application", { tags: "@tui" }, async ({ tui }) => {
|
|
532
|
+
await tui.stop();
|
|
533
|
+
});
|
|
534
|
+
When("I type {string}", { tags: "@tui" }, async ({ tui, world }, text) => {
|
|
535
|
+
await tui.typeText(interpolate(text, world.vars));
|
|
536
|
+
});
|
|
537
|
+
When("I type {string} slowly", { tags: "@tui" }, async ({ tui, world }, text) => {
|
|
538
|
+
await tui.typeText(interpolate(text, world.vars), { delay: 50 });
|
|
539
|
+
});
|
|
540
|
+
When("I press {string}", { tags: "@tui" }, async ({ tui }, key) => {
|
|
541
|
+
await tui.pressKey(key);
|
|
542
|
+
});
|
|
543
|
+
When("I press {string} with ctrl", { tags: "@tui" }, async ({ tui }, key) => {
|
|
544
|
+
await tui.pressKey(key, { ctrl: true });
|
|
545
|
+
});
|
|
546
|
+
When("I press {string} with alt", { tags: "@tui" }, async ({ tui }, key) => {
|
|
547
|
+
await tui.pressKey(key, { alt: true });
|
|
548
|
+
});
|
|
549
|
+
When("I press {string} with shift", { tags: "@tui" }, async ({ tui }, key) => {
|
|
550
|
+
await tui.pressKey(key, { shift: true });
|
|
551
|
+
});
|
|
552
|
+
When("I press enter", { tags: "@tui" }, async ({ tui }) => {
|
|
553
|
+
await tui.pressKey("enter");
|
|
554
|
+
});
|
|
555
|
+
When("I press tab", { tags: "@tui" }, async ({ tui }) => {
|
|
556
|
+
await tui.pressKey("tab");
|
|
557
|
+
});
|
|
558
|
+
When("I press escape", { tags: "@tui" }, async ({ tui }) => {
|
|
559
|
+
await tui.pressKey("escape");
|
|
560
|
+
});
|
|
561
|
+
When(
|
|
562
|
+
"I fill the TUI field {string} with {string}",
|
|
563
|
+
{ tags: "@tui" },
|
|
564
|
+
async ({ tui, world }, field, value) => {
|
|
565
|
+
await tui.fillField(interpolate(field, world.vars), interpolate(value, world.vars));
|
|
566
|
+
}
|
|
567
|
+
);
|
|
568
|
+
When(
|
|
569
|
+
"I enter {string} in the {string} field",
|
|
570
|
+
{ tags: "@tui" },
|
|
571
|
+
async ({ tui, world }, value, field) => {
|
|
572
|
+
await tui.fillField(interpolate(field, world.vars), interpolate(value, world.vars));
|
|
573
|
+
}
|
|
574
|
+
);
|
|
575
|
+
When("I select {string}", { tags: "@tui" }, async ({ tui, world }, option) => {
|
|
576
|
+
await tui.selectOption(interpolate(option, world.vars));
|
|
577
|
+
});
|
|
578
|
+
When("I select option {string}", { tags: "@tui" }, async ({ tui, world }, option) => {
|
|
579
|
+
await tui.selectOption(interpolate(option, world.vars));
|
|
580
|
+
});
|
|
581
|
+
When("I click at position {int}, {int}", { tags: "@tui" }, async ({ tui }, x, y) => {
|
|
582
|
+
await tui.click(x, y);
|
|
583
|
+
});
|
|
584
|
+
When("I click on {string}", { tags: "@tui" }, async ({ tui, world }, text) => {
|
|
585
|
+
await tui.clickOnText(interpolate(text, world.vars));
|
|
586
|
+
});
|
|
587
|
+
Then("I should see {string}", { tags: "@tui" }, async ({ tui, world }, text) => {
|
|
588
|
+
await tui.expectText(interpolate(text, world.vars));
|
|
589
|
+
});
|
|
590
|
+
Then("I should see {string} in the terminal", { tags: "@tui" }, async ({ tui, world }, text) => {
|
|
591
|
+
await tui.expectText(interpolate(text, world.vars));
|
|
592
|
+
});
|
|
593
|
+
Then("I should see text {string}", { tags: "@tui" }, async ({ tui, world }, text) => {
|
|
594
|
+
await tui.expectText(interpolate(text, world.vars));
|
|
595
|
+
});
|
|
596
|
+
Then("I should not see {string}", { tags: "@tui" }, async ({ tui, world }, text) => {
|
|
597
|
+
await tui.expectNotText(interpolate(text, world.vars));
|
|
598
|
+
});
|
|
599
|
+
Then("the screen should contain {string}", { tags: "@tui" }, async ({ tui, world }, text) => {
|
|
600
|
+
await tui.assertScreenContains(interpolate(text, world.vars));
|
|
601
|
+
});
|
|
602
|
+
Then("the screen should match pattern {string}", { tags: "@tui" }, async ({ tui }, pattern) => {
|
|
603
|
+
await tui.assertScreenMatches(new RegExp(pattern));
|
|
604
|
+
});
|
|
605
|
+
When("I wait for {string}", { tags: "@tui" }, async ({ tui, world }, text) => {
|
|
606
|
+
await tui.waitForText(interpolate(text, world.vars));
|
|
607
|
+
});
|
|
608
|
+
When(
|
|
609
|
+
"I wait for {string} for {int} seconds",
|
|
610
|
+
{ tags: "@tui" },
|
|
611
|
+
async ({ tui, world }, text, seconds) => {
|
|
612
|
+
await tui.waitForText(interpolate(text, world.vars), { timeout: seconds * 1e3 });
|
|
613
|
+
}
|
|
614
|
+
);
|
|
615
|
+
When("I wait {int} seconds", { tags: "@tui" }, async ({ tui }, seconds) => {
|
|
616
|
+
await tui.waitSeconds(seconds);
|
|
617
|
+
});
|
|
618
|
+
Then("the screen should match snapshot {string}", { tags: "@tui" }, async ({ tui }, name) => {
|
|
619
|
+
const result = await tui.matchSnapshot(name);
|
|
620
|
+
if (!result.pass) {
|
|
621
|
+
throw new Error(`Snapshot "${name}" mismatch:
|
|
622
|
+
${result.diff || "No diff available"}`);
|
|
623
|
+
}
|
|
624
|
+
});
|
|
625
|
+
Then("I take a snapshot named {string}", { tags: "@tui" }, async ({ tui }, name) => {
|
|
626
|
+
await tui.takeSnapshot(name);
|
|
627
|
+
});
|
|
628
|
+
When("I clear the terminal", { tags: "@tui" }, async ({ tui }) => {
|
|
629
|
+
await tui.clear();
|
|
630
|
+
});
|
|
631
|
+
When("I resize the terminal to {int}x{int}", { tags: "@tui" }, async ({ tui }, cols, rows) => {
|
|
632
|
+
await tui.resize({ cols, rows });
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
// src/steps/tui.wizard.ts
|
|
637
|
+
import { createBdd as createBdd10 } from "playwright-bdd";
|
|
638
|
+
function registerTuiWizardSteps(test) {
|
|
639
|
+
const { Given, When, Then } = createBdd10(test);
|
|
640
|
+
When("I navigate down {int} times", { tags: "@tui" }, async ({ tui }, times) => {
|
|
641
|
+
for (let i = 0; i < times; i++) {
|
|
642
|
+
await tui.pressKey("down");
|
|
643
|
+
}
|
|
644
|
+
});
|
|
645
|
+
When("I navigate up {int} times", { tags: "@tui" }, async ({ tui }, times) => {
|
|
646
|
+
for (let i = 0; i < times; i++) {
|
|
647
|
+
await tui.pressKey("up");
|
|
648
|
+
}
|
|
649
|
+
});
|
|
650
|
+
When("I navigate to {string} and select", { tags: "@tui" }, async ({ tui, world }, option) => {
|
|
651
|
+
const target = interpolate(option, world.vars);
|
|
652
|
+
await tui.waitForText(target);
|
|
653
|
+
await tui.pressKey("enter");
|
|
654
|
+
});
|
|
655
|
+
When("I go back", { tags: "@tui" }, async ({ tui }) => {
|
|
656
|
+
await tui.pressKey("escape");
|
|
657
|
+
});
|
|
658
|
+
When("I fill the form:", { tags: "@tui" }, async ({ tui, world }, dataTable) => {
|
|
659
|
+
const rows = dataTable.hashes();
|
|
660
|
+
for (const row of rows) {
|
|
661
|
+
const field = interpolate(row.field || row.Field, world.vars);
|
|
662
|
+
const value = interpolate(row.value || row.Value, world.vars);
|
|
663
|
+
await tui.fillField(field, value);
|
|
664
|
+
await tui.pressKey("tab");
|
|
665
|
+
}
|
|
666
|
+
});
|
|
667
|
+
When("I submit the form", { tags: "@tui" }, async ({ tui }) => {
|
|
668
|
+
await tui.pressKey("enter");
|
|
669
|
+
});
|
|
670
|
+
When("I submit the form with ctrl+s", { tags: "@tui" }, async ({ tui }) => {
|
|
671
|
+
await tui.pressKey("s", { ctrl: true });
|
|
672
|
+
});
|
|
673
|
+
When("I select menu item {string}", { tags: "@tui" }, async ({ tui, world }, item) => {
|
|
674
|
+
const target = interpolate(item, world.vars);
|
|
675
|
+
await tui.waitForText(target);
|
|
676
|
+
await tui.selectOption(target);
|
|
677
|
+
});
|
|
678
|
+
When("I open the menu", { tags: "@tui" }, async ({ tui }) => {
|
|
679
|
+
await tui.pressKey("m", { alt: true });
|
|
680
|
+
});
|
|
681
|
+
When("I select from dropdown {string} value {string}", { tags: "@tui" }, async ({ tui, world }, dropdown, value) => {
|
|
682
|
+
const dropdownLabel = interpolate(dropdown, world.vars);
|
|
683
|
+
const selectedValue = interpolate(value, world.vars);
|
|
684
|
+
await tui.waitForText(dropdownLabel);
|
|
685
|
+
await tui.pressKey("enter");
|
|
686
|
+
await tui.waitForText(selectedValue);
|
|
687
|
+
await tui.pressKey("enter");
|
|
688
|
+
});
|
|
689
|
+
When("I press ctrl+{word}", { tags: "@tui" }, async ({ tui }, key) => {
|
|
690
|
+
await tui.pressKey(key, { ctrl: true });
|
|
691
|
+
});
|
|
692
|
+
When("I press alt+{word}", { tags: "@tui" }, async ({ tui }, key) => {
|
|
693
|
+
await tui.pressKey(key, { alt: true });
|
|
694
|
+
});
|
|
695
|
+
When("I press shift+{word}", { tags: "@tui" }, async ({ tui }, key) => {
|
|
696
|
+
await tui.pressKey(key, { shift: true });
|
|
697
|
+
});
|
|
698
|
+
When("I press ctrl+shift+{word}", { tags: "@tui" }, async ({ tui }, key) => {
|
|
699
|
+
await tui.pressKey(key, { ctrl: true, shift: true });
|
|
700
|
+
});
|
|
701
|
+
When("I quit the application", { tags: "@tui" }, async ({ tui }) => {
|
|
702
|
+
await tui.pressKey("q");
|
|
703
|
+
});
|
|
704
|
+
When("I force quit the application", { tags: "@tui" }, async ({ tui }) => {
|
|
705
|
+
await tui.pressKey("c", { ctrl: true });
|
|
706
|
+
});
|
|
707
|
+
Then("line {int} should contain {string}", { tags: "@tui" }, async ({ tui, world }, lineNum, text) => {
|
|
708
|
+
const lines = await tui.getScreenLines();
|
|
709
|
+
const expectedText = interpolate(text, world.vars);
|
|
710
|
+
const lineIndex = lineNum - 1;
|
|
711
|
+
if (lineIndex < 0 || lineIndex >= lines.length) {
|
|
712
|
+
throw new Error(`Line ${lineNum} does not exist. Screen has ${lines.length} lines.`);
|
|
713
|
+
}
|
|
714
|
+
if (!lines[lineIndex].includes(expectedText)) {
|
|
715
|
+
throw new Error(`Expected line ${lineNum} to contain "${expectedText}"
|
|
716
|
+
Actual: "${lines[lineIndex]}"`);
|
|
717
|
+
}
|
|
718
|
+
});
|
|
719
|
+
Then("the first line should contain {string}", { tags: "@tui" }, async ({ tui, world }, text) => {
|
|
720
|
+
const lines = await tui.getScreenLines();
|
|
721
|
+
const expectedText = interpolate(text, world.vars);
|
|
722
|
+
if (!lines[0]?.includes(expectedText)) {
|
|
723
|
+
throw new Error(`Expected first line to contain "${expectedText}"
|
|
724
|
+
Actual: "${lines[0]}"`);
|
|
725
|
+
}
|
|
726
|
+
});
|
|
727
|
+
Then("the last line should contain {string}", { tags: "@tui" }, async ({ tui, world }, text) => {
|
|
728
|
+
const lines = await tui.getScreenLines();
|
|
729
|
+
const expectedText = interpolate(text, world.vars);
|
|
730
|
+
const lastLine = lines[lines.length - 1] || "";
|
|
731
|
+
if (!lastLine.includes(expectedText)) {
|
|
732
|
+
throw new Error(`Expected last line to contain "${expectedText}"
|
|
733
|
+
Actual: "${lastLine}"`);
|
|
734
|
+
}
|
|
735
|
+
});
|
|
736
|
+
Then("I should see all of:", { tags: "@tui" }, async ({ tui, world }, dataTable) => {
|
|
737
|
+
const rows = dataTable.raw();
|
|
738
|
+
for (const row of rows) {
|
|
739
|
+
const text = interpolate(row[0], world.vars);
|
|
740
|
+
await tui.expectText(text);
|
|
741
|
+
}
|
|
742
|
+
});
|
|
743
|
+
Then("I should not see any of:", { tags: "@tui" }, async ({ tui, world }, dataTable) => {
|
|
744
|
+
const rows = dataTable.raw();
|
|
745
|
+
for (const row of rows) {
|
|
746
|
+
const text = interpolate(row[0], world.vars);
|
|
747
|
+
await tui.expectNotText(text);
|
|
748
|
+
}
|
|
749
|
+
});
|
|
750
|
+
When("I capture the screen", { tags: "@tui" }, async ({ tui, world }) => {
|
|
751
|
+
const capture = await tui.captureScreen();
|
|
752
|
+
world.vars["lastScreenCapture"] = capture.text;
|
|
753
|
+
});
|
|
754
|
+
Then("I print the screen", { tags: "@tui" }, async ({ tui }) => {
|
|
755
|
+
const text = await tui.getScreenText();
|
|
756
|
+
console.log("=== Screen Content ===");
|
|
757
|
+
console.log(text);
|
|
758
|
+
console.log("======================");
|
|
759
|
+
});
|
|
760
|
+
When("I execute command {string}", { tags: "@tui" }, async ({ tui, world }, command) => {
|
|
761
|
+
const cmd = interpolate(command, world.vars);
|
|
762
|
+
await tui.typeText(cmd);
|
|
763
|
+
await tui.pressKey("enter");
|
|
764
|
+
});
|
|
765
|
+
When("I run {string}", { tags: "@tui" }, async ({ tui, world }, command) => {
|
|
766
|
+
const cmd = interpolate(command, world.vars);
|
|
767
|
+
await tui.typeText(cmd);
|
|
768
|
+
await tui.pressKey("enter");
|
|
769
|
+
});
|
|
770
|
+
When("I confirm the dialog", { tags: "@tui" }, async ({ tui }) => {
|
|
771
|
+
await tui.typeText("y");
|
|
772
|
+
await tui.pressKey("enter");
|
|
773
|
+
});
|
|
774
|
+
When("I cancel the dialog", { tags: "@tui" }, async ({ tui }) => {
|
|
775
|
+
await tui.typeText("n");
|
|
776
|
+
await tui.pressKey("enter");
|
|
777
|
+
});
|
|
778
|
+
When("I dismiss the dialog", { tags: "@tui" }, async ({ tui }) => {
|
|
779
|
+
await tui.pressKey("escape");
|
|
780
|
+
});
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
// src/steps/index.ts
|
|
784
|
+
function registerApiSteps(test) {
|
|
785
|
+
registerApiAuthSteps(test);
|
|
786
|
+
registerApiHttpSteps(test);
|
|
787
|
+
registerApiAssertionSteps(test);
|
|
788
|
+
}
|
|
789
|
+
function registerUiSteps(test) {
|
|
790
|
+
registerUiBasicSteps(test);
|
|
791
|
+
registerWizardSteps(test);
|
|
792
|
+
}
|
|
793
|
+
function registerSharedSteps(test) {
|
|
794
|
+
registerSharedVarSteps(test);
|
|
795
|
+
registerSharedCleanupSteps(test);
|
|
796
|
+
}
|
|
797
|
+
function registerHybridSuite(test) {
|
|
798
|
+
registerHybridSteps(test);
|
|
799
|
+
}
|
|
800
|
+
function registerTuiSteps(test) {
|
|
801
|
+
registerTuiBasicSteps(test);
|
|
802
|
+
registerTuiWizardSteps(test);
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
export {
|
|
806
|
+
interpolate,
|
|
807
|
+
tryParseJson,
|
|
808
|
+
selectPath,
|
|
809
|
+
parseExpected,
|
|
810
|
+
assertMasked,
|
|
811
|
+
registerCleanup,
|
|
812
|
+
registerApiHttpSteps,
|
|
813
|
+
registerApiAssertionSteps,
|
|
814
|
+
registerApiAuthSteps,
|
|
815
|
+
registerHybridSteps,
|
|
816
|
+
registerSharedCleanupSteps,
|
|
817
|
+
registerSharedVarSteps,
|
|
818
|
+
registerUiBasicSteps,
|
|
819
|
+
registerWizardSteps,
|
|
820
|
+
registerTuiBasicSteps,
|
|
821
|
+
registerTuiWizardSteps,
|
|
822
|
+
registerApiSteps,
|
|
823
|
+
registerUiSteps,
|
|
824
|
+
registerSharedSteps,
|
|
825
|
+
registerHybridSuite,
|
|
826
|
+
registerTuiSteps
|
|
827
|
+
};
|