@letsrunit/bdd 0.5.1 → 0.7.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/dist/index.d.ts CHANGED
@@ -1,11 +1,13 @@
1
+ import * as _letsrunit_utils from '@letsrunit/utils';
1
2
  import * as _letsrunit_gherkin from '@letsrunit/gherkin';
2
3
  import { ParameterTypeDefinition } from '@letsrunit/gherkin';
3
- import * as _letsrunit_utils from '@letsrunit/utils';
4
4
  import { World as World$1 } from '@cucumber/cucumber';
5
5
  import { BrowserContextOptions, Page } from '@playwright/test';
6
6
  import { Readable } from 'node:stream';
7
7
  import * as _cucumber_cucumber_expressions from '@cucumber/cucumber-expressions';
8
8
 
9
+ declare const typeDefinitions: (_letsrunit_gherkin.ParameterTypeDefinition<boolean> | _letsrunit_gherkin.ParameterTypeDefinition<_letsrunit_utils.Scalar | _letsrunit_utils.Scalar[]> | _letsrunit_gherkin.ParameterTypeDefinition<_letsrunit_gherkin.KeyCombo>)[];
10
+
9
11
  interface World extends World$1<BrowserContextOptions> {
10
12
  page: Page;
11
13
  startTime: number;
@@ -25,8 +27,6 @@ interface StepDefinition {
25
27
  comment?: string;
26
28
  }
27
29
 
28
- declare const typeDefinitions: (_letsrunit_gherkin.ParameterTypeDefinition<_letsrunit_utils.Scalar | _letsrunit_utils.Scalar[]> | _letsrunit_gherkin.ParameterTypeDefinition<_letsrunit_gherkin.KeyCombo> | _letsrunit_gherkin.ParameterTypeDefinition<boolean>)[];
29
-
30
30
  type AttachData = string | Buffer | Readable;
31
31
  type AttachOptions = string | {
32
32
  mediaType: string;
package/dist/index.js CHANGED
@@ -1,20 +1,321 @@
1
- export { Given, Then, When, createRegistry, registry, typeDefinitions } from './chunk-D6IA6AFW.js';
1
+ import { locatorParameter, valueParameter, keysParameter, booleanParameter, enumParameter, sanitizeStepDefinition } from '@letsrunit/gherkin';
2
+ import { fuzzyLocator, suppressInterferences, waitForIdle, waitAfterInteraction, setFieldValue } from '@letsrunit/playwright';
3
+ import { expect } from '@playwright/test';
4
+ import { ParameterTypeRegistry, ParameterType, CucumberExpression, RegularExpression } from '@cucumber/cucumber-expressions';
5
+ import { eventually, splitUrl, pathRegexp, sleep, textToHtml, asFilename } from '@letsrunit/utils';
6
+ import ISO6391 from 'iso-639-1';
7
+ import metascraper from 'metascraper';
8
+ import metascraperLang from 'metascraper-lang';
9
+ import { receiveMail, toEml } from '@letsrunit/mailbox';
10
+
11
+ // src/parameters.ts
12
+ var typeDefinitions = [
13
+ locatorParameter(),
14
+ valueParameter(),
15
+ keysParameter(),
16
+ booleanParameter("visible", "hidden"),
17
+ booleanParameter("enabled", "disabled", /((?:en|dis)abled)/),
18
+ booleanParameter("checked", "unchecked", /((?:un)?checked)/),
19
+ booleanParameter("contains", "not contains", /((?:not )?contains)/),
20
+ booleanParameter("check", "uncheck", /((?:un)?check)/),
21
+ booleanParameter("focus", "blur"),
22
+ enumParameter(["click", "double-click", "right-click", "hover"], /((?:double-|right-)?click|hover)/),
23
+ enumParameter(["mobile", "tablet", "desktop"])
24
+ ];
25
+ function expectOrNot(actual, toBe) {
26
+ return toBe ? expect(actual) : expect(actual).not;
27
+ }
28
+ function createRegistry() {
29
+ const _paramRegistry = new ParameterTypeRegistry();
30
+ const _entries = [];
31
+ for (const t of typeDefinitions) {
32
+ _paramRegistry.defineParameterType(
33
+ new ParameterType(t.name, t.regexp, null, t.transformer, t.useForSnippets)
34
+ );
35
+ }
36
+ return {
37
+ /** IStepRegistry-compatible defs (source = String(expression), no raw expr). */
38
+ get defs() {
39
+ return _entries.map(({ type: type2, expression, fn, comment }) => ({
40
+ type: type2,
41
+ source: String(expression),
42
+ fn,
43
+ comment
44
+ }));
45
+ },
46
+ /** Raw step definitions with original expression — used by define.ts for Cucumber registration. */
47
+ get definitions() {
48
+ return _entries.map(({ type: type2, expression, fn, comment }) => ({ type: type2, expression, fn, comment }));
49
+ },
50
+ defineStep(type2, expression, fn, comment) {
51
+ const expr = typeof expression === "string" ? new CucumberExpression(sanitizeStepDefinition(expression), _paramRegistry) : new RegularExpression(expression, _paramRegistry);
52
+ _entries.push({ type: type2, expression, fn, comment, expr });
53
+ },
54
+ defineParameterType(type2) {
55
+ _paramRegistry.defineParameterType(
56
+ new ParameterType(type2.name, type2.regexp, null, type2.transformer, type2.useForSnippets)
57
+ );
58
+ },
59
+ match(text) {
60
+ for (const entry of _entries) {
61
+ const args = entry.expr.match(text);
62
+ if (args) {
63
+ return {
64
+ def: { type: entry.type, source: String(entry.expression), fn: entry.fn, comment: entry.comment },
65
+ values: args.map((a) => a.getValue(null)),
66
+ args
67
+ };
68
+ }
69
+ }
70
+ return null;
71
+ }
72
+ };
73
+ }
74
+ var registry = createRegistry();
75
+ function Given(expression, fn, comment) {
76
+ const def = { type: "Given", expression, fn, comment };
77
+ registry.defineStep("Given", expression, fn, comment);
78
+ return def;
79
+ }
80
+ function When(expression, fn, comment) {
81
+ const def = { type: "When", expression, fn, comment };
82
+ registry.defineStep("When", expression, fn, comment);
83
+ return def;
84
+ }
85
+ function Then(expression, fn, comment) {
86
+ const def = { type: "Then", expression, fn, comment };
87
+ registry.defineStep("Then", expression, fn, comment);
88
+ return def;
89
+ }
90
+
91
+ // src/steps/assert.ts
92
+ var WAIT_TIMEOUT = 5e3;
93
+ Then(
94
+ "The page {contains|not contains} {locator}",
95
+ async function(visible, selector) {
96
+ const el = await fuzzyLocator(this.page, selector);
97
+ await expectOrNot(el, visible).toBeVisible({ timeout: WAIT_TIMEOUT });
98
+ }
99
+ );
100
+ Then(
101
+ "{locator} {contains|not contains} {locator}",
102
+ async function(selector, contain2, child) {
103
+ const el = await fuzzyLocator(this.page, selector);
104
+ const childElement = el.locator(child);
105
+ await expectOrNot(childElement, contain2).toBeAttached({ timeout: WAIT_TIMEOUT });
106
+ }
107
+ );
108
+ var scrapeLang = metascraper([metascraperLang()]);
109
+ async function getLang(page) {
110
+ const html = "html" in page ? page.html : await page.content();
111
+ const url = typeof page.url === "function" ? page.url() : page.url;
112
+ const { lang = null } = await scrapeLang({ html, url });
113
+ if (!lang) return null;
114
+ const code = lang.substring(0, 2);
115
+ const name = ISO6391.getName(code) || code;
116
+ return { code, name };
117
+ }
118
+
119
+ // src/steps/navigation.ts
120
+ async function openPage(world, path) {
121
+ const { page } = world;
122
+ const result = await page.goto(path);
123
+ expect(result?.status()).toBeLessThan(400);
124
+ await waitForIdle(page);
125
+ world.lang ??= await getLang(page) || void 0;
126
+ }
127
+ Given("I'm on the homepage", async function() {
128
+ await openPage(this, "/");
129
+ });
130
+ Given("I'm on page {string}", async function(path) {
131
+ await openPage(this, path);
132
+ });
133
+ Given("all popups are closed", async function() {
134
+ await suppressInterferences(this.page, { lang: this.lang?.code });
135
+ });
136
+ Then("I should be on page {string}", async function(expectedPath) {
137
+ await eventually(async () => {
138
+ const { path: actualPath } = splitUrl(this.page.url());
139
+ if (expectedPath.includes(":")) {
140
+ const { regexp, names } = pathRegexp(expectedPath);
141
+ expect(actualPath, `Expected path ${actualPath} to match pattern ${expectedPath}`).toMatch(regexp);
142
+ const match = actualPath.match(regexp);
143
+ this.pathParams = Object.fromEntries(names.map((name, i) => [name, decodeURIComponent(match[i + 1])]));
144
+ } else {
145
+ expect(actualPath).toEqual(expectedPath);
146
+ delete this.pathParams;
147
+ }
148
+ });
149
+ });
150
+ When("I go back to the previous page", async function() {
151
+ await this.page.goBack();
152
+ await waitForIdle(this.page);
153
+ });
154
+ var TIMEOUT = 2500;
155
+ async function press(el, action) {
156
+ if (action === "hover") {
157
+ await el.hover({ timeout: TIMEOUT });
158
+ } else {
159
+ await el.click({
160
+ button: action === "right-click" ? "right" : "left",
161
+ clickCount: action === "double-click" ? 2 : 1,
162
+ timeout: TIMEOUT
163
+ });
164
+ }
165
+ }
166
+ When(
167
+ "I {click|double-click|right-click|hover} {locator}",
168
+ async function(action, selector) {
169
+ const prevUrl = this.page.url();
170
+ const el = await fuzzyLocator(this.page, selector);
171
+ await press(el, action);
172
+ await waitAfterInteraction(this.page, el, { prevUrl });
173
+ }
174
+ );
175
+ When(
176
+ "I {click|double-click|right-click|hover} {locator} while holding {keys}",
177
+ async function(action, selector, combo) {
178
+ const prevUrl = this.page.url();
179
+ const el = await fuzzyLocator(this.page, selector);
180
+ const keys = [...combo.modifiers, combo.key];
181
+ for (const m of keys) await this.page.keyboard.down(m);
182
+ await press(el, action);
183
+ for (const m of keys.reverse()) await this.page.keyboard.up(m);
184
+ await waitAfterInteraction(this.page, el, { prevUrl });
185
+ }
186
+ );
187
+ When("I scroll {locator} into view", async function(selector) {
188
+ const el = await fuzzyLocator(this.page, selector);
189
+ await el.scrollIntoViewIfNeeded({ timeout: TIMEOUT });
190
+ });
191
+ var TIMEOUT2 = 500;
192
+ var DELAY = 500;
193
+ When("I set {locator} to {value}", async function(selector, value) {
194
+ const el = await fuzzyLocator(this.page, selector);
195
+ await setFieldValue(el, value, { timeout: TIMEOUT2 });
196
+ await sleep(DELAY);
197
+ });
198
+ When(
199
+ "I set {locator} to range of {value} to {value}",
200
+ async function(selector, from, to) {
201
+ const el = await fuzzyLocator(this.page, selector);
202
+ await setFieldValue(el, { from, to }, { timeout: TIMEOUT2 });
203
+ await sleep(DELAY);
204
+ }
205
+ );
206
+ When("I clear {locator}", async function(selector) {
207
+ const el = await fuzzyLocator(this.page, selector);
208
+ await setFieldValue(el, null, { timeout: TIMEOUT2 });
209
+ await sleep(DELAY);
210
+ });
211
+ When(
212
+ "I {check|uncheck} {locator}",
213
+ async function(check2, selector) {
214
+ const el = await fuzzyLocator(this.page, selector);
215
+ await setFieldValue(el, check2, { timeout: TIMEOUT2 });
216
+ await sleep(DELAY);
217
+ },
218
+ "For checkbox input or switch component"
219
+ );
220
+ When("I {focus|blur} {locator}", async function(focus2, selector) {
221
+ const el = await fuzzyLocator(this.page, selector);
222
+ if (focus2) {
223
+ await el.focus({ timeout: TIMEOUT2 });
224
+ } else {
225
+ await el.blur({ timeout: TIMEOUT2 });
226
+ }
227
+ });
228
+ var DELAY2 = 500;
229
+ When("I press {keys}", async function(combo) {
230
+ for (const m of combo.modifiers) await this.page.keyboard.down(m);
231
+ await this.page.keyboard.press(combo.key);
232
+ for (const m of combo.modifiers.toReversed()) await this.page.keyboard.up(m);
233
+ await sleep(DELAY2);
234
+ });
235
+ When("I type {string}", async function(value) {
236
+ await this.page.keyboard.type(value, { delay: 200 });
237
+ await sleep(DELAY2);
238
+ });
239
+ var MAX_RECEIVE_WAIT = 12e4;
240
+ Given(
241
+ `I'm viewing an email sent to {string} with subject {string}`,
242
+ async function(address, subject) {
243
+ const emails = await receiveMail(address, { full: true, after: this.startTime, subject, limit: 1 });
244
+ if (emails.length === 0) {
245
+ throw new Error(`Did not receive an email with subject "${subject}"`);
246
+ }
247
+ const email = emails[0];
248
+ await this.page.goto("about:blank", { waitUntil: "load" });
249
+ await this.page.setContent(email.html ?? textToHtml(email.text), { waitUntil: "domcontentloaded" });
250
+ }
251
+ );
252
+ Then(
253
+ "I received an email sent to {string} with subject {string}",
254
+ async function(address, subject) {
255
+ const emails = await receiveMail(address, {
256
+ after: this.startTime,
257
+ full: true,
258
+ subject,
259
+ wait: true,
260
+ timeout: MAX_RECEIVE_WAIT,
261
+ limit: 1
262
+ });
263
+ if (emails.length === 0) {
264
+ throw new Error(`Did not receive an email with subject "${subject}"`);
265
+ }
266
+ const email = emails[0];
267
+ this.attach(toEml(email), {
268
+ mediaType: "message/rfc822",
269
+ fileName: asFilename(email.subject, "eml")
270
+ });
271
+ }
272
+ );
273
+ var TIMEOUT3 = 500;
274
+ async function copyInput(el) {
275
+ try {
276
+ return await el.inputValue();
277
+ } catch {
278
+ }
279
+ }
280
+ async function copyLink(el) {
281
+ try {
282
+ const tag = await el.evaluate((n) => n.tagName.toLowerCase());
283
+ const href = tag === "a" ? await el.getAttribute("href") : null;
284
+ if (href) {
285
+ return href.startsWith("mailto:") ? href.replace(/^mailto:/i, "") : href;
286
+ }
287
+ } catch {
288
+ }
289
+ }
290
+ async function copyText(el) {
291
+ return await el.textContent() ?? null;
292
+ }
293
+ When("I copy {locator} to the clipboard", async function(selector) {
294
+ const el = await fuzzyLocator(this.page, selector);
295
+ let value = await copyInput(el) ?? await copyLink(el) ?? await copyText(el);
296
+ this.clipboard = { value };
297
+ });
298
+ When("I paste from the clipboard into {locator}", async function(selector) {
299
+ const el = await fuzzyLocator(this.page, selector);
300
+ const value = this.clipboard?.value || "";
301
+ await el.fill(String(value), { timeout: TIMEOUT3 });
302
+ });
2
303
 
3
304
  // src/utils/file.ts
4
305
  function toFile(data, options) {
5
306
  const opt = typeof options === "string" ? { mediaType: options } : options ?? { mediaType: "application/octet-stream" };
6
- const type = opt.mediaType || "application/octet-stream";
307
+ const type2 = opt.mediaType || "application/octet-stream";
7
308
  const name = opt.fileName || `attachment-${Date.now()}`;
8
309
  if (isReadable(data)) {
9
310
  throw new Error("toFile does not support Readable streams; provide Buffer or string");
10
311
  }
11
312
  const part = typeof data === "string" ? data : new Uint8Array(data);
12
- return new File([part], name, { type });
313
+ return new File([part], name, { type: type2 });
13
314
  }
14
315
  function isReadable(value) {
15
316
  return !!value && typeof value === "object" && (typeof value.pipe === "function" || typeof value.read === "function");
16
317
  }
17
318
 
18
- export { toFile };
319
+ export { Given, Then, When, createRegistry, registry, toFile, typeDefinitions };
19
320
  //# sourceMappingURL=index.js.map
20
321
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/file.ts"],"names":[],"mappings":";;;AAQO,SAAS,MAAA,CAAO,MAAkB,OAAA,EAA+B;AACtE,EAAA,MAAM,GAAA,GACJ,OAAO,OAAA,KAAY,QAAA,GACf,EAAE,SAAA,EAAW,OAAA,EAAQ,GACrB,OAAA,IAAW,EAAE,SAAA,EAAW,0BAAA,EAA2B;AAEzD,EAAA,MAAM,IAAA,GAAO,IAAI,SAAA,IAAa,0BAAA;AAC9B,EAAA,MAAM,OAAO,GAAA,CAAI,QAAA,IAAY,CAAA,WAAA,EAAc,IAAA,CAAK,KAAK,CAAA,CAAA;AAErD,EAAA,IAAI,UAAA,CAAW,IAAI,CAAA,EAAG;AACpB,IAAA,MAAM,IAAI,MAAM,oEAAoE,CAAA;AAAA,EACtF;AAEA,EAAA,MAAM,OAAO,OAAO,IAAA,KAAS,WAAW,IAAA,GAAO,IAAI,WAAW,IAAI,CAAA;AAElE,EAAA,OAAO,IAAI,KAAK,CAAC,IAAI,GAAG,IAAA,EAAM,EAAE,MAAM,CAAA;AACxC;AAEA,SAAS,WAAW,KAAA,EAAmC;AACrD,EAAA,OACE,CAAC,CAAC,KAAA,IACF,OAAO,KAAA,KAAU,QAAA,KAChB,OAAQ,KAAA,CAAc,IAAA,KAAS,UAAA,IAAc,OAAQ,KAAA,CAAc,IAAA,KAAS,UAAA,CAAA;AAEjF","file":"index.js","sourcesContent":["import type { Readable } from 'node:stream';\n\ntype AttachData = string | Buffer | Readable;\ntype AttachOptions = string | {\n mediaType: string;\n fileName?: string;\n};\n\nexport function toFile(data: AttachData, options?: AttachOptions): File {\n const opt =\n typeof options === 'string'\n ? { mediaType: options }\n : options ?? { mediaType: 'application/octet-stream' };\n\n const type = opt.mediaType || 'application/octet-stream';\n const name = opt.fileName || `attachment-${Date.now()}`;\n\n if (isReadable(data)) {\n throw new Error('toFile does not support Readable streams; provide Buffer or string');\n }\n\n const part = typeof data === 'string' ? data : new Uint8Array(data);\n\n return new File([part], name, { type });\n}\n\nfunction isReadable(value: unknown): value is Readable {\n return (\n !!value &&\n typeof value === 'object' &&\n (typeof (value as any).pipe === 'function' || typeof (value as any).read === 'function')\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/parameters.ts","../src/utils/test-helpers.ts","../src/registry.ts","../src/steps/assert.ts","../src/utils/get-lang.ts","../src/steps/navigation.ts","../src/steps/mouse.ts","../src/steps/form.ts","../src/steps/keyboard.ts","../src/steps/mailbox.ts","../src/steps/clipboard.ts","../src/utils/file.ts"],"names":["type","contain","expect","fuzzyLocator","TIMEOUT","check","focus","DELAY","sleep"],"mappings":"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","file":"index.js","sourcesContent":["import { booleanParameter, enumParameter, keysParameter, locatorParameter, valueParameter } from '@letsrunit/gherkin';\n\nexport const typeDefinitions = [\n locatorParameter(),\n valueParameter(),\n keysParameter(),\n\n booleanParameter('visible', 'hidden'),\n booleanParameter('enabled', 'disabled', /((?:en|dis)abled)/),\n booleanParameter('checked', 'unchecked', /((?:un)?checked)/),\n booleanParameter('contains', 'not contains', /((?:not )?contains)/),\n\n booleanParameter('check', 'uncheck', /((?:un)?check)/),\n booleanParameter('focus', 'blur'),\n\n enumParameter(['click', 'double-click', 'right-click', 'hover'], /((?:double-|right-)?click|hover)/),\n enumParameter(['mobile', 'tablet', 'desktop']),\n];\n","import { expect, type Expect } from '@playwright/test';\n\nexport function expectOrNot<T>(\n actual: T,\n toBe: boolean\n): ReturnType<Expect<T>> | ReturnType<ReturnType<Expect<T>>['not']> {\n return toBe ? expect(actual) : expect(actual).not;\n}\n","import {\n CucumberExpression,\n ParameterType,\n ParameterTypeRegistry,\n RegularExpression,\n} from '@cucumber/cucumber-expressions';\nimport { sanitizeStepDefinition, type ParameterTypeDefinition } from '@letsrunit/gherkin';\nimport { typeDefinitions } from './parameters';\nimport type { StepDefinition, StepHandler, StepType } from './types';\n\ninterface Entry {\n type: StepType;\n expression: string | RegExp;\n fn: StepHandler;\n comment?: string;\n expr: CucumberExpression | RegularExpression;\n}\n\nexport function createRegistry() {\n const _paramRegistry = new ParameterTypeRegistry();\n const _entries: Entry[] = [];\n\n for (const t of typeDefinitions) {\n _paramRegistry.defineParameterType(\n new ParameterType(t.name, t.regexp, null, t.transformer as any, t.useForSnippets),\n );\n }\n\n return {\n /** IStepRegistry-compatible defs (source = String(expression), no raw expr). */\n get defs() {\n return _entries.map(({ type, expression, fn, comment }) => ({\n type,\n source: String(expression),\n fn,\n comment,\n }));\n },\n\n /** Raw step definitions with original expression — used by define.ts for Cucumber registration. */\n get definitions(): StepDefinition[] {\n return _entries.map(({ type, expression, fn, comment }) => ({ type, expression, fn, comment }));\n },\n\n defineStep(type: StepType, expression: string | RegExp, fn: StepHandler, comment?: string): void {\n const expr =\n typeof expression === 'string'\n ? new CucumberExpression(sanitizeStepDefinition(expression), _paramRegistry)\n : new RegularExpression(expression, _paramRegistry);\n _entries.push({ type, expression, fn, comment, expr });\n },\n\n defineParameterType(type: ParameterTypeDefinition<unknown>): void {\n _paramRegistry.defineParameterType(\n new ParameterType(type.name, type.regexp, null, type.transformer, type.useForSnippets),\n );\n },\n\n match(text: string) {\n for (const entry of _entries) {\n const args = entry.expr.match(text);\n if (args) {\n return {\n def: { type: entry.type, source: String(entry.expression), fn: entry.fn, comment: entry.comment },\n values: args.map((a) => a.getValue(null)),\n args,\n };\n }\n }\n return null;\n },\n };\n}\n\nexport const registry = createRegistry();\n\nexport function Given(expression: string | RegExp, fn: StepHandler, comment?: string): StepDefinition {\n const def: StepDefinition = { type: 'Given', expression, fn, comment };\n registry.defineStep('Given', expression, fn, comment);\n return def;\n}\n\nexport function When(expression: string | RegExp, fn: StepHandler, comment?: string): StepDefinition {\n const def: StepDefinition = { type: 'When', expression, fn, comment };\n registry.defineStep('When', expression, fn, comment);\n return def;\n}\n\nexport function Then(expression: string | RegExp, fn: StepHandler, comment?: string): StepDefinition {\n const def: StepDefinition = { type: 'Then', expression, fn, comment };\n registry.defineStep('Then', expression, fn, comment);\n return def;\n}\n","import { fuzzyLocator } from '@letsrunit/playwright';\nimport { expectOrNot } from '../utils/test-helpers';\nimport { Then } from '../registry';\n\nconst WAIT_TIMEOUT = 5000;\n\nexport const see = Then(\n 'The page {contains|not contains} {locator}',\n async function (visible: boolean, selector: string) {\n const el = await fuzzyLocator(this.page, selector);\n await expectOrNot(el, visible).toBeVisible({ timeout: WAIT_TIMEOUT });\n },\n);\n\nexport const contain = Then(\n '{locator} {contains|not contains} {locator}',\n async function (selector: string, contain: boolean, child: string) {\n const el = await fuzzyLocator(this.page, selector);\n const childElement = el.locator(child);\n await expectOrNot(childElement, contain).toBeAttached({ timeout: WAIT_TIMEOUT });\n },\n);\n","import type { Snapshot } from '@letsrunit/playwright';\nimport { Page } from '@playwright/test';\nimport ISO6391 from 'iso-639-1';\nimport metascraper from 'metascraper';\nimport metascraperLang from 'metascraper-lang';\n\nconst scrapeLang = metascraper([metascraperLang()]);\n\nexport async function getLang(\n page: Pick<Page, 'content' | 'url'> | Snapshot,\n): Promise<{ code: string; name: string} | null> {\n const html = 'html' in page ? page.html : await page.content();\n const url = typeof page.url === 'function' ? page.url() : page.url;\n\n const { lang = null } = await scrapeLang({ html, url });\n if (!lang) return null;\n\n const code = lang.substring(0, 2);\n const name = ISO6391.getName(code) || code;\n\n return { code, name };\n}\n","import { suppressInterferences, waitForIdle } from '@letsrunit/playwright';\nimport { eventually, pathRegexp, splitUrl } from '@letsrunit/utils';\nimport { expect } from '@playwright/test';\nimport { World } from '../types';\nimport { getLang } from '../utils/get-lang';\nimport { Given, Then, When } from '../registry';\n\nasync function openPage(world: World, path: string): Promise<void> {\n const { page } = world;\n\n const result = await page.goto(path);\n expect(result?.status()).toBeLessThan(400);\n\n await waitForIdle(page);\n\n world.lang ??= (await getLang(page)) || undefined;\n}\n\nexport const navHome = Given(\"I'm on the homepage\", async function () {\n await openPage(this, '/');\n});\n\nexport const navPath = Given(\"I'm on page {string}\", async function (path: string) {\n await openPage(this, path);\n});\n\nexport const popupClosed = Given('all popups are closed', async function (){\n await suppressInterferences(this.page, { lang: this.lang?.code });\n});\n\nexport const assertPath = Then('I should be on page {string}', async function (expectedPath: string) {\n await eventually(async () => {\n const { path: actualPath } = splitUrl(this.page.url());\n\n if (expectedPath.includes(':')) {\n const { regexp, names } = pathRegexp(expectedPath);\n\n expect(actualPath, `Expected path ${actualPath} to match pattern ${expectedPath}`).toMatch(regexp);\n\n const match = actualPath.match(regexp);\n this.pathParams = Object.fromEntries(names.map((name, i) => [name, decodeURIComponent(match![i + 1])]));\n } else {\n expect(actualPath).toEqual(expectedPath);\n delete this.pathParams;\n }\n });\n});\n\nexport const back = When('I go back to the previous page', async function () {\n await this.page.goBack();\n await waitForIdle(this.page);\n});\n","import type { KeyCombo } from '@letsrunit/gherkin';\nimport { fuzzyLocator, waitAfterInteraction } from '@letsrunit/playwright';\nimport type { Locator } from '@playwright/test';\nimport { When } from '../registry';\n\nconst TIMEOUT = 2500;\n\ntype MouseAction = 'click' | 'double-click' | 'right-click' | 'hover';\n\nasync function press(el: Locator, action: MouseAction) {\n if (action === 'hover') {\n await el.hover({ timeout: TIMEOUT });\n } else {\n await el.click({\n button: action === 'right-click' ? 'right' : 'left',\n clickCount: action === 'double-click' ? 2 : 1,\n timeout: TIMEOUT,\n });\n }\n}\n\nexport const click = When(\n 'I {click|double-click|right-click|hover} {locator}',\n async function (action: MouseAction, selector: string) {\n const prevUrl = this.page.url();\n\n const el = await fuzzyLocator(this.page, selector);\n await press(el, action);\n\n await waitAfterInteraction(this.page, el, { prevUrl });\n },\n);\n\nexport const clickHold = When(\n 'I {click|double-click|right-click|hover} {locator} while holding {keys}',\n async function (action: MouseAction, selector: string, combo: KeyCombo) {\n const prevUrl = this.page.url();\n\n const el = await fuzzyLocator(this.page, selector);\n const keys = [...combo.modifiers, combo.key];\n\n for (const m of keys) await this.page.keyboard.down(m);\n await press(el, action);\n for (const m of keys.reverse()) await this.page.keyboard.up(m);\n\n await waitAfterInteraction(this.page, el, { prevUrl });\n },\n);\n\nexport const scroll = When('I scroll {locator} into view', async function (selector: string) {\n const el = await fuzzyLocator(this.page, selector);\n await el.scrollIntoViewIfNeeded({ timeout: TIMEOUT });\n});\n","import { fuzzyLocator, setFieldValue } from '@letsrunit/playwright';\nimport { type Scalar, sleep } from '@letsrunit/utils';\nimport { When } from '../registry';\n\nconst TIMEOUT = 500;\nconst DELAY = 500;\n\nexport const set = When('I set {locator} to {value}', async function (selector: string, value: Scalar | Scalar[]) {\n const el = await fuzzyLocator(this.page, selector);\n await setFieldValue(el, value, { timeout: TIMEOUT });\n await sleep(DELAY);\n});\n\nexport const setRange = When(\n 'I set {locator} to range of {value} to {value}',\n async function (selector: string, from: Scalar, to: Scalar) {\n const el = await fuzzyLocator(this.page, selector);\n await setFieldValue(el, { from, to }, { timeout: TIMEOUT });\n await sleep(DELAY);\n },\n);\n\nexport const clear = When('I clear {locator}', async function (selector) {\n const el = await fuzzyLocator(this.page, selector);\n await setFieldValue(el, null, { timeout: TIMEOUT });\n await sleep(DELAY);\n});\n\nexport const check = When(\n 'I {check|uncheck} {locator}',\n async function (check: boolean, selector: string) {\n const el = await fuzzyLocator(this.page, selector);\n await setFieldValue(el, check, { timeout: TIMEOUT });\n await sleep(DELAY);\n },\n 'For checkbox input or switch component',\n);\n\nexport const focus = When('I {focus|blur} {locator}', async function (focus: boolean, selector: string) {\n const el = await fuzzyLocator(this.page, selector);\n\n if (focus) {\n await el.focus({ timeout: TIMEOUT });\n } else {\n await el.blur({ timeout: TIMEOUT });\n }\n});\n","import type { KeyCombo } from '@letsrunit/gherkin';\nimport { sleep } from '@letsrunit/utils';\nimport { When } from '../registry';\n\nconst DELAY = 500;\n\nexport const press = When('I press {keys}', async function (combo: KeyCombo) {\n // Hold modifiers\n for (const m of combo.modifiers) await this.page.keyboard.down(m);\n\n // Press final key\n await this.page.keyboard.press(combo.key);\n\n // Release modifiers (reverse order)\n for (const m of combo.modifiers.toReversed()) await this.page.keyboard.up(m);\n\n await sleep(DELAY);\n});\n\nexport const type = When('I type {string}', async function (value: string) {\n await this.page.keyboard.type(value, { delay: 200 });\n await sleep(DELAY);\n});\n","import { receiveMail, toEml } from '@letsrunit/mailbox';\nimport { asFilename, textToHtml } from '@letsrunit/utils';\nimport { Given, Then } from '../registry';\n\nconst MAX_RECEIVE_WAIT = 120_000; // 2 minutes\n\nexport const view = Given(\n `I'm viewing an email sent to {string} with subject {string}`,\n async function (address: string, subject: string) {\n const emails = await receiveMail(address, { full: true, after: this.startTime, subject, limit: 1 });\n if (emails.length === 0) {\n throw new Error(`Did not receive an email with subject \"${subject}\"`);\n }\n\n const email = emails[0];\n\n await this.page.goto('about:blank', { waitUntil: 'load' });\n await this.page.setContent(email.html ?? textToHtml(email.text!), { waitUntil: 'domcontentloaded' });\n },\n);\n\nexport const receive = Then(\n 'I received an email sent to {string} with subject {string}',\n async function (address: string, subject: string) {\n const emails = await receiveMail(address, {\n after: this.startTime,\n full: true,\n subject,\n wait: true,\n timeout: MAX_RECEIVE_WAIT,\n limit: 1,\n });\n\n if (emails.length === 0) {\n throw new Error(`Did not receive an email with subject \"${subject}\"`);\n }\n\n const email = emails[0];\n\n this.attach(toEml(email), {\n mediaType: 'message/rfc822',\n fileName: asFilename(email.subject, 'eml'),\n });\n },\n);\n","import { fuzzyLocator } from '@letsrunit/playwright';\nimport type { Locator } from '@playwright/test';\nimport { When } from '../registry';\n\nconst TIMEOUT = 500;\n\nasync function copyInput(el: Locator): Promise<string | undefined> {\n try {\n return await el.inputValue();\n } catch {}\n}\n\nasync function copyLink(el: Locator): Promise<string | undefined> {\n try {\n const tag = await el.evaluate<string>((n: Element) => n.tagName.toLowerCase());\n const href = tag === 'a' ? await el.getAttribute('href') : null;\n if (href) {\n return href.startsWith('mailto:') ? href.replace(/^mailto:/i, '') : href;\n }\n } catch {}\n}\n\nasync function copyText(el: Locator): Promise<string | null> {\n return (await el.textContent()) ?? null;\n}\n\nexport const copy = When('I copy {locator} to the clipboard', async function (selector: string) {\n const el = await fuzzyLocator(this.page, selector);\n let value = (await copyInput(el)) ?? (await copyLink(el)) ?? (await copyText(el));\n\n this.clipboard = { value };\n});\n\nexport const paste = When('I paste from the clipboard into {locator}', async function (selector: string) {\n const el = await fuzzyLocator(this.page, selector);\n const value = this.clipboard?.value || '';\n\n await el.fill(String(value), { timeout: TIMEOUT });\n});\n","import type { Readable } from 'node:stream';\n\ntype AttachData = string | Buffer | Readable;\ntype AttachOptions = string | {\n mediaType: string;\n fileName?: string;\n};\n\nexport function toFile(data: AttachData, options?: AttachOptions): File {\n const opt =\n typeof options === 'string'\n ? { mediaType: options }\n : options ?? { mediaType: 'application/octet-stream' };\n\n const type = opt.mediaType || 'application/octet-stream';\n const name = opt.fileName || `attachment-${Date.now()}`;\n\n if (isReadable(data)) {\n throw new Error('toFile does not support Readable streams; provide Buffer or string');\n }\n\n const part = typeof data === 'string' ? data : new Uint8Array(data);\n\n return new File([part], name, { type });\n}\n\nfunction isReadable(value: unknown): value is Readable {\n return (\n !!value &&\n typeof value === 'object' &&\n (typeof (value as any).pipe === 'function' || typeof (value as any).read === 'function')\n );\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letsrunit/bdd",
3
- "version": "0.5.1",
3
+ "version": "0.7.0",
4
4
  "description": "BDD step definitions for browser automation with letsrunit",
5
5
  "keywords": [
6
6
  "testing",
@@ -29,11 +29,6 @@
29
29
  "types": "./dist/index.d.ts",
30
30
  "import": "./dist/index.js",
31
31
  "default": "./dist/index.js"
32
- },
33
- "./define": {
34
- "types": "./dist/define.d.ts",
35
- "import": "./dist/define.js",
36
- "default": "./dist/define.js"
37
32
  }
38
33
  }
39
34
  },
@@ -47,15 +42,15 @@
47
42
  "test": "vitest run",
48
43
  "test:cov": "vitest run --coverage",
49
44
  "typecheck": "tsc --noEmit",
50
- "gen:stub": "tsx scripts/generate-stub.ts"
45
+ "gen:stub": "npx tsx scripts/generate-stub.ts"
51
46
  },
52
47
  "packageManager": "yarn@4.10.3",
53
48
  "dependencies": {
54
49
  "@cucumber/cucumber-expressions": "^18.1.0",
55
- "@letsrunit/gherkin": "0.5.1",
56
- "@letsrunit/mailbox": "0.5.1",
57
- "@letsrunit/playwright": "0.5.1",
58
- "@letsrunit/utils": "0.5.1",
50
+ "@letsrunit/gherkin": "0.7.0",
51
+ "@letsrunit/mailbox": "0.7.0",
52
+ "@letsrunit/playwright": "0.7.0",
53
+ "@letsrunit/utils": "0.7.0",
59
54
  "@playwright/test": "^1.57.0",
60
55
  "iso-639-1": "^3.1.5",
61
56
  "metascraper": "^5.49.15",
@@ -75,11 +70,6 @@
75
70
  "types": "./dist/index.d.ts",
76
71
  "import": "./dist/index.js",
77
72
  "default": "./dist/index.js"
78
- },
79
- "./define": {
80
- "types": "./dist/define.d.ts",
81
- "import": "./dist/define.js",
82
- "default": "./dist/define.js"
83
73
  }
84
74
  }
85
75
  }
package/src/_stub.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  import { defineParameterType } from '@cucumber/cucumber';
3
3
 
4
4
  defineParameterType({ name: 'locator', regexp: /((?:(?:the )?\w+(?: "[^"]*")?|`([^`]+|\\.)*`)(?: with(?:in|out)? (?:(?:the )?\w+(?: "[^"]*")?|`([^`]+|\\.)*`))*)/, transformer: (s: string) => s });
5
- defineParameterType({ name: 'value', regexp: /"((?:[^"\\]+|\\.)*)"|(-?\d+(?:\.\d+)?)|date (?:of )?((?:today|tomorrow|yesterday|\d+ \w+ (?:ago|from now))(?: (?:at )?\d\d?:\d\d(?:\d\d)?)?|"((?:[^"\\]+|\\.)*)")/, transformer: (s: string) => s });
5
+ defineParameterType({ name: 'value', regexp: /.+/, transformer: (s: string) => s });
6
6
  defineParameterType({ name: 'keys', regexp: /"([^"]+)"|'([^']+)'/, transformer: (s: string) => s });
7
7
  defineParameterType({ name: 'visible|hidden', regexp: /(visible|hidden)/, transformer: (s: string) => s });
8
8
  defineParameterType({ name: 'enabled|disabled', regexp: /((?:en|dis)abled)/, transformer: (s: string) => s });
@@ -11,3 +11,4 @@ defineParameterType({ name: 'contains|not contains', regexp: /((?:not )?contains
11
11
  defineParameterType({ name: 'check|uncheck', regexp: /((?:un)?check)/, transformer: (s: string) => s });
12
12
  defineParameterType({ name: 'focus|blur', regexp: /(focus|blur)/, transformer: (s: string) => s });
13
13
  defineParameterType({ name: 'click|double-click|right-click|hover', regexp: /((?:double-|right-)?click|hover)/, transformer: (s: string) => s });
14
+ defineParameterType({ name: 'mobile|tablet|desktop', regexp: /(mobile|tablet|desktop)/, transformer: (s: string) => s });
package/src/parameters.ts CHANGED
@@ -14,4 +14,5 @@ export const typeDefinitions = [
14
14
  booleanParameter('focus', 'blur'),
15
15
 
16
16
  enumParameter(['click', 'double-click', 'right-click', 'hover'], /((?:double-|right-)?click|hover)/),
17
+ enumParameter(['mobile', 'tablet', 'desktop']),
17
18
  ];
@@ -0,0 +1,19 @@
1
+ import { Given } from '../registry';
2
+
3
+ const viewports = {
4
+ mobile: { width: 375, height: 812 },
5
+ tablet: { width: 768, height: 1024 },
6
+ desktop: { width: 1920, height: 1080 },
7
+ };
8
+
9
+ export const viewport = Given(
10
+ "I'm on a {mobile|tablet|desktop} device",
11
+ async function (type: 'mobile' | 'tablet' | 'desktop') {
12
+ const size = viewports[type];
13
+ const current = this.page.viewportSize();
14
+
15
+ if (current?.height !== size.height || current?.width !== size.width) {
16
+ await this.page.setViewportSize(size);
17
+ }
18
+ },
19
+ );
@@ -1,305 +0,0 @@
1
- import { locatorParameter, valueParameter, keysParameter, booleanParameter, enumParameter, sanitizeStepDefinition } from '@letsrunit/gherkin';
2
- import { ParameterTypeRegistry, ParameterType, CucumberExpression, RegularExpression } from '@cucumber/cucumber-expressions';
3
- import { fuzzyLocator, suppressInterferences, waitForIdle, waitAfterInteraction, setFieldValue } from '@letsrunit/playwright';
4
- import { expect } from '@playwright/test';
5
- import { eventually, splitUrl, pathRegexp, sleep, textToHtml, asFilename } from '@letsrunit/utils';
6
- import ISO6391 from 'iso-639-1';
7
- import metascraper from 'metascraper';
8
- import metascraperLang from 'metascraper-lang';
9
- import { receiveMail, toEml } from '@letsrunit/mailbox';
10
-
11
- // src/parameters.ts
12
- var typeDefinitions = [
13
- locatorParameter(),
14
- valueParameter(),
15
- keysParameter(),
16
- booleanParameter("visible", "hidden"),
17
- booleanParameter("enabled", "disabled", /((?:en|dis)abled)/),
18
- booleanParameter("checked", "unchecked", /((?:un)?checked)/),
19
- booleanParameter("contains", "not contains", /((?:not )?contains)/),
20
- booleanParameter("check", "uncheck", /((?:un)?check)/),
21
- booleanParameter("focus", "blur"),
22
- enumParameter(["click", "double-click", "right-click", "hover"], /((?:double-|right-)?click|hover)/)
23
- ];
24
- function createRegistry() {
25
- const _paramRegistry = new ParameterTypeRegistry();
26
- const _entries = [];
27
- for (const t of typeDefinitions) {
28
- _paramRegistry.defineParameterType(
29
- new ParameterType(t.name, t.regexp, null, t.transformer, t.useForSnippets)
30
- );
31
- }
32
- return {
33
- /** IStepRegistry-compatible defs (source = String(expression), no raw expr). */
34
- get defs() {
35
- return _entries.map(({ type: type2, expression, fn, comment }) => ({
36
- type: type2,
37
- source: String(expression),
38
- fn,
39
- comment
40
- }));
41
- },
42
- /** Raw step definitions with original expression — used by define.ts for Cucumber registration. */
43
- get definitions() {
44
- return _entries.map(({ type: type2, expression, fn, comment }) => ({ type: type2, expression, fn, comment }));
45
- },
46
- defineStep(type2, expression, fn, comment) {
47
- const expr = typeof expression === "string" ? new CucumberExpression(sanitizeStepDefinition(expression), _paramRegistry) : new RegularExpression(expression, _paramRegistry);
48
- _entries.push({ type: type2, expression, fn, comment, expr });
49
- },
50
- defineParameterType(type2) {
51
- _paramRegistry.defineParameterType(
52
- new ParameterType(type2.name, type2.regexp, null, type2.transformer, type2.useForSnippets)
53
- );
54
- },
55
- match(text) {
56
- for (const entry of _entries) {
57
- const args = entry.expr.match(text);
58
- if (args) {
59
- return {
60
- def: { type: entry.type, source: String(entry.expression), fn: entry.fn, comment: entry.comment },
61
- values: args.map((a) => a.getValue(null)),
62
- args
63
- };
64
- }
65
- }
66
- return null;
67
- }
68
- };
69
- }
70
- var registry = createRegistry();
71
- function Given(expression, fn, comment) {
72
- const def = { type: "Given", expression, fn, comment };
73
- registry.defineStep("Given", expression, fn, comment);
74
- return def;
75
- }
76
- function When(expression, fn, comment) {
77
- const def = { type: "When", expression, fn, comment };
78
- registry.defineStep("When", expression, fn, comment);
79
- return def;
80
- }
81
- function Then(expression, fn, comment) {
82
- const def = { type: "Then", expression, fn, comment };
83
- registry.defineStep("Then", expression, fn, comment);
84
- return def;
85
- }
86
- function expectOrNot(actual, toBe) {
87
- return toBe ? expect(actual) : expect(actual).not;
88
- }
89
-
90
- // src/steps/assert.ts
91
- var WAIT_TIMEOUT = 5e3;
92
- Then(
93
- "The page {contains|not contains} {locator}",
94
- async function(visible, selector) {
95
- const el = await fuzzyLocator(this.page, selector);
96
- await expectOrNot(el, visible).toBeVisible({ timeout: WAIT_TIMEOUT });
97
- }
98
- );
99
- Then(
100
- "{locator} {contains|not contains} {locator}",
101
- async function(selector, contain2, child) {
102
- const el = await fuzzyLocator(this.page, selector);
103
- const childElement = el.locator(child);
104
- await expectOrNot(childElement, contain2).toBeAttached({ timeout: WAIT_TIMEOUT });
105
- }
106
- );
107
- var scrapeLang = metascraper([metascraperLang()]);
108
- async function getLang(page) {
109
- const html = "html" in page ? page.html : await page.content();
110
- const url = typeof page.url === "function" ? page.url() : page.url;
111
- const { lang = null } = await scrapeLang({ html, url });
112
- if (!lang) return null;
113
- const code = lang.substring(0, 2);
114
- const name = ISO6391.getName(code) || code;
115
- return { code, name };
116
- }
117
-
118
- // src/steps/navigation.ts
119
- async function openPage(world, path) {
120
- const { page } = world;
121
- const result = await page.goto(path);
122
- expect(result?.status()).toBeLessThan(400);
123
- await waitForIdle(page);
124
- world.lang ??= await getLang(page) || void 0;
125
- }
126
- Given("I'm on the homepage", async function() {
127
- await openPage(this, "/");
128
- });
129
- Given("I'm on page {string}", async function(path) {
130
- await openPage(this, path);
131
- });
132
- Given("all popups are closed", async function() {
133
- await suppressInterferences(this.page, { lang: this.lang?.code });
134
- });
135
- Then("I should be on page {string}", async function(expectedPath) {
136
- await eventually(async () => {
137
- const { path: actualPath } = splitUrl(this.page.url());
138
- if (expectedPath.includes(":")) {
139
- const { regexp, names } = pathRegexp(expectedPath);
140
- expect(actualPath, `Expected path ${actualPath} to match pattern ${expectedPath}`).toMatch(regexp);
141
- const match = actualPath.match(regexp);
142
- this.pathParams = Object.fromEntries(names.map((name, i) => [name, decodeURIComponent(match[i + 1])]));
143
- } else {
144
- expect(actualPath).toEqual(expectedPath);
145
- delete this.pathParams;
146
- }
147
- });
148
- });
149
- When("I go back to the previous page", async function() {
150
- await this.page.goBack();
151
- await waitForIdle(this.page);
152
- });
153
- var TIMEOUT = 2500;
154
- async function press(el, action) {
155
- if (action === "hover") {
156
- await el.hover({ timeout: TIMEOUT });
157
- } else {
158
- await el.click({
159
- button: action === "right-click" ? "right" : "left",
160
- clickCount: action === "double-click" ? 2 : 1,
161
- timeout: TIMEOUT
162
- });
163
- }
164
- }
165
- When(
166
- "I {click|double-click|right-click|hover} {locator}",
167
- async function(action, selector) {
168
- const prevUrl = this.page.url();
169
- const el = await fuzzyLocator(this.page, selector);
170
- await press(el, action);
171
- await waitAfterInteraction(this.page, el, { prevUrl });
172
- }
173
- );
174
- When(
175
- "I {click|double-click|right-click|hover} {locator} while holding {keys}",
176
- async function(action, selector, combo) {
177
- const prevUrl = this.page.url();
178
- const el = await fuzzyLocator(this.page, selector);
179
- const keys = [...combo.modifiers, combo.key];
180
- for (const m of keys) await this.page.keyboard.down(m);
181
- await press(el, action);
182
- for (const m of keys.reverse()) await this.page.keyboard.up(m);
183
- await waitAfterInteraction(this.page, el, { prevUrl });
184
- }
185
- );
186
- When("I scroll {locator} into view", async function(selector) {
187
- const el = await fuzzyLocator(this.page, selector);
188
- await el.scrollIntoViewIfNeeded({ timeout: TIMEOUT });
189
- });
190
- var TIMEOUT2 = 500;
191
- var DELAY = 500;
192
- When("I set {locator} to {value}", async function(selector, value) {
193
- const el = await fuzzyLocator(this.page, selector);
194
- await setFieldValue(el, value, { timeout: TIMEOUT2 });
195
- await sleep(DELAY);
196
- });
197
- When(
198
- "I set {locator} to range of {value} to {value}",
199
- async function(selector, from, to) {
200
- const el = await fuzzyLocator(this.page, selector);
201
- await setFieldValue(el, { from, to }, { timeout: TIMEOUT2 });
202
- await sleep(DELAY);
203
- }
204
- );
205
- When("I clear {locator}", async function(selector) {
206
- const el = await fuzzyLocator(this.page, selector);
207
- await setFieldValue(el, null, { timeout: TIMEOUT2 });
208
- await sleep(DELAY);
209
- });
210
- When(
211
- "I {check|uncheck} {locator}",
212
- async function(check2, selector) {
213
- const el = await fuzzyLocator(this.page, selector);
214
- await setFieldValue(el, check2, { timeout: TIMEOUT2 });
215
- await sleep(DELAY);
216
- },
217
- "For checkbox input or switch component"
218
- );
219
- When("I {focus|blur} {locator}", async function(focus2, selector) {
220
- const el = await fuzzyLocator(this.page, selector);
221
- if (focus2) {
222
- await el.focus({ timeout: TIMEOUT2 });
223
- } else {
224
- await el.blur({ timeout: TIMEOUT2 });
225
- }
226
- });
227
- var DELAY2 = 500;
228
- When("I press {keys}", async function(combo) {
229
- for (const m of combo.modifiers) await this.page.keyboard.down(m);
230
- await this.page.keyboard.press(combo.key);
231
- for (const m of combo.modifiers.toReversed()) await this.page.keyboard.up(m);
232
- await sleep(DELAY2);
233
- });
234
- When("I type {string}", async function(value) {
235
- await this.page.keyboard.type(value, { delay: 200 });
236
- await sleep(DELAY2);
237
- });
238
- var MAX_RECEIVE_WAIT = 12e4;
239
- Given(
240
- `I'm viewing an email sent to {string} with subject {string}`,
241
- async function(address, subject) {
242
- const emails = await receiveMail(address, { full: true, after: this.startTime, subject, limit: 1 });
243
- if (emails.length === 0) {
244
- throw new Error(`Did not receive an email with subject "${subject}"`);
245
- }
246
- const email = emails[0];
247
- await this.page.goto("about:blank", { waitUntil: "load" });
248
- await this.page.setContent(email.html ?? textToHtml(email.text), { waitUntil: "domcontentloaded" });
249
- }
250
- );
251
- Then(
252
- "I received an email sent to {string} with subject {string}",
253
- async function(address, subject) {
254
- const emails = await receiveMail(address, {
255
- after: this.startTime,
256
- full: true,
257
- subject,
258
- wait: true,
259
- timeout: MAX_RECEIVE_WAIT,
260
- limit: 1
261
- });
262
- if (emails.length === 0) {
263
- throw new Error(`Did not receive an email with subject "${subject}"`);
264
- }
265
- const email = emails[0];
266
- this.attach(toEml(email), {
267
- mediaType: "message/rfc822",
268
- fileName: asFilename(email.subject, "eml")
269
- });
270
- }
271
- );
272
- var TIMEOUT3 = 500;
273
- async function copyInput(el) {
274
- try {
275
- return await el.inputValue();
276
- } catch {
277
- }
278
- }
279
- async function copyLink(el) {
280
- try {
281
- const tag = await el.evaluate((n) => n.tagName.toLowerCase());
282
- const href = tag === "a" ? await el.getAttribute("href") : null;
283
- if (href) {
284
- return href.startsWith("mailto:") ? href.replace(/^mailto:/i, "") : href;
285
- }
286
- } catch {
287
- }
288
- }
289
- async function copyText(el) {
290
- return await el.textContent() ?? null;
291
- }
292
- When("I copy {locator} to the clipboard", async function(selector) {
293
- const el = await fuzzyLocator(this.page, selector);
294
- let value = await copyInput(el) ?? await copyLink(el) ?? await copyText(el);
295
- this.clipboard = { value };
296
- });
297
- When("I paste from the clipboard into {locator}", async function(selector) {
298
- const el = await fuzzyLocator(this.page, selector);
299
- const value = this.clipboard?.value || "";
300
- await el.fill(String(value), { timeout: TIMEOUT3 });
301
- });
302
-
303
- export { Given, Then, When, createRegistry, registry, typeDefinitions };
304
- //# sourceMappingURL=chunk-D6IA6AFW.js.map
305
- //# sourceMappingURL=chunk-D6IA6AFW.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/parameters.ts","../src/registry.ts","../src/utils/test-helpers.ts","../src/steps/assert.ts","../src/utils/get-lang.ts","../src/steps/navigation.ts","../src/steps/mouse.ts","../src/steps/form.ts","../src/steps/keyboard.ts","../src/steps/mailbox.ts","../src/steps/clipboard.ts"],"names":["type","contain","expect","fuzzyLocator","TIMEOUT","check","focus","DELAY","sleep"],"mappings":"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","file":"chunk-D6IA6AFW.js","sourcesContent":["import { booleanParameter, enumParameter, keysParameter, locatorParameter, valueParameter } from '@letsrunit/gherkin';\n\nexport const typeDefinitions = [\n locatorParameter(),\n valueParameter(),\n keysParameter(),\n\n booleanParameter('visible', 'hidden'),\n booleanParameter('enabled', 'disabled', /((?:en|dis)abled)/),\n booleanParameter('checked', 'unchecked', /((?:un)?checked)/),\n booleanParameter('contains', 'not contains', /((?:not )?contains)/),\n\n booleanParameter('check', 'uncheck', /((?:un)?check)/),\n booleanParameter('focus', 'blur'),\n\n enumParameter(['click', 'double-click', 'right-click', 'hover'], /((?:double-|right-)?click|hover)/),\n];\n","import {\n CucumberExpression,\n ParameterType,\n ParameterTypeRegistry,\n RegularExpression,\n} from '@cucumber/cucumber-expressions';\nimport { sanitizeStepDefinition, type ParameterTypeDefinition } from '@letsrunit/gherkin';\nimport { typeDefinitions } from './parameters';\nimport type { StepDefinition, StepHandler, StepType } from './types';\n\ninterface Entry {\n type: StepType;\n expression: string | RegExp;\n fn: StepHandler;\n comment?: string;\n expr: CucumberExpression | RegularExpression;\n}\n\nexport function createRegistry() {\n const _paramRegistry = new ParameterTypeRegistry();\n const _entries: Entry[] = [];\n\n for (const t of typeDefinitions) {\n _paramRegistry.defineParameterType(\n new ParameterType(t.name, t.regexp, null, t.transformer as any, t.useForSnippets),\n );\n }\n\n return {\n /** IStepRegistry-compatible defs (source = String(expression), no raw expr). */\n get defs() {\n return _entries.map(({ type, expression, fn, comment }) => ({\n type,\n source: String(expression),\n fn,\n comment,\n }));\n },\n\n /** Raw step definitions with original expression — used by define.ts for Cucumber registration. */\n get definitions(): StepDefinition[] {\n return _entries.map(({ type, expression, fn, comment }) => ({ type, expression, fn, comment }));\n },\n\n defineStep(type: StepType, expression: string | RegExp, fn: StepHandler, comment?: string): void {\n const expr =\n typeof expression === 'string'\n ? new CucumberExpression(sanitizeStepDefinition(expression), _paramRegistry)\n : new RegularExpression(expression, _paramRegistry);\n _entries.push({ type, expression, fn, comment, expr });\n },\n\n defineParameterType(type: ParameterTypeDefinition<unknown>): void {\n _paramRegistry.defineParameterType(\n new ParameterType(type.name, type.regexp, null, type.transformer, type.useForSnippets),\n );\n },\n\n match(text: string) {\n for (const entry of _entries) {\n const args = entry.expr.match(text);\n if (args) {\n return {\n def: { type: entry.type, source: String(entry.expression), fn: entry.fn, comment: entry.comment },\n values: args.map((a) => a.getValue(null)),\n args,\n };\n }\n }\n return null;\n },\n };\n}\n\nexport const registry = createRegistry();\n\nexport function Given(expression: string | RegExp, fn: StepHandler, comment?: string): StepDefinition {\n const def: StepDefinition = { type: 'Given', expression, fn, comment };\n registry.defineStep('Given', expression, fn, comment);\n return def;\n}\n\nexport function When(expression: string | RegExp, fn: StepHandler, comment?: string): StepDefinition {\n const def: StepDefinition = { type: 'When', expression, fn, comment };\n registry.defineStep('When', expression, fn, comment);\n return def;\n}\n\nexport function Then(expression: string | RegExp, fn: StepHandler, comment?: string): StepDefinition {\n const def: StepDefinition = { type: 'Then', expression, fn, comment };\n registry.defineStep('Then', expression, fn, comment);\n return def;\n}\n","import { expect, type Expect } from '@playwright/test';\n\nexport function expectOrNot<T>(\n actual: T,\n toBe: boolean\n): ReturnType<Expect<T>> | ReturnType<ReturnType<Expect<T>>['not']> {\n return toBe ? expect(actual) : expect(actual).not;\n}\n","import { fuzzyLocator } from '@letsrunit/playwright';\nimport { expectOrNot } from '../utils/test-helpers';\nimport { Then } from '../registry';\n\nconst WAIT_TIMEOUT = 5000;\n\nexport const see = Then(\n 'The page {contains|not contains} {locator}',\n async function (visible: boolean, selector: string) {\n const el = await fuzzyLocator(this.page, selector);\n await expectOrNot(el, visible).toBeVisible({ timeout: WAIT_TIMEOUT });\n },\n);\n\nexport const contain = Then(\n '{locator} {contains|not contains} {locator}',\n async function (selector: string, contain: boolean, child: string) {\n const el = await fuzzyLocator(this.page, selector);\n const childElement = el.locator(child);\n await expectOrNot(childElement, contain).toBeAttached({ timeout: WAIT_TIMEOUT });\n },\n);\n","import type { Snapshot } from '@letsrunit/playwright';\nimport { Page } from '@playwright/test';\nimport ISO6391 from 'iso-639-1';\nimport metascraper from 'metascraper';\nimport metascraperLang from 'metascraper-lang';\n\nconst scrapeLang = metascraper([metascraperLang()]);\n\nexport async function getLang(\n page: Pick<Page, 'content' | 'url'> | Snapshot,\n): Promise<{ code: string; name: string} | null> {\n const html = 'html' in page ? page.html : await page.content();\n const url = typeof page.url === 'function' ? page.url() : page.url;\n\n const { lang = null } = await scrapeLang({ html, url });\n if (!lang) return null;\n\n const code = lang.substring(0, 2);\n const name = ISO6391.getName(code) || code;\n\n return { code, name };\n}\n","import { suppressInterferences, waitForIdle } from '@letsrunit/playwright';\nimport { eventually, pathRegexp, splitUrl } from '@letsrunit/utils';\nimport { expect } from '@playwright/test';\nimport { World } from '../types';\nimport { getLang } from '../utils/get-lang';\nimport { Given, Then, When } from '../registry';\n\nasync function openPage(world: World, path: string): Promise<void> {\n const { page } = world;\n\n const result = await page.goto(path);\n expect(result?.status()).toBeLessThan(400);\n\n await waitForIdle(page);\n\n world.lang ??= (await getLang(page)) || undefined;\n}\n\nexport const navHome = Given(\"I'm on the homepage\", async function () {\n await openPage(this, '/');\n});\n\nexport const navPath = Given(\"I'm on page {string}\", async function (path: string) {\n await openPage(this, path);\n});\n\nexport const popupClosed = Given('all popups are closed', async function (){\n await suppressInterferences(this.page, { lang: this.lang?.code });\n});\n\nexport const assertPath = Then('I should be on page {string}', async function (expectedPath: string) {\n await eventually(async () => {\n const { path: actualPath } = splitUrl(this.page.url());\n\n if (expectedPath.includes(':')) {\n const { regexp, names } = pathRegexp(expectedPath);\n\n expect(actualPath, `Expected path ${actualPath} to match pattern ${expectedPath}`).toMatch(regexp);\n\n const match = actualPath.match(regexp);\n this.pathParams = Object.fromEntries(names.map((name, i) => [name, decodeURIComponent(match![i + 1])]));\n } else {\n expect(actualPath).toEqual(expectedPath);\n delete this.pathParams;\n }\n });\n});\n\nexport const back = When('I go back to the previous page', async function () {\n await this.page.goBack();\n await waitForIdle(this.page);\n});\n","import type { KeyCombo } from '@letsrunit/gherkin';\nimport { fuzzyLocator, waitAfterInteraction } from '@letsrunit/playwright';\nimport type { Locator } from '@playwright/test';\nimport { When } from '../registry';\n\nconst TIMEOUT = 2500;\n\ntype MouseAction = 'click' | 'double-click' | 'right-click' | 'hover';\n\nasync function press(el: Locator, action: MouseAction) {\n if (action === 'hover') {\n await el.hover({ timeout: TIMEOUT });\n } else {\n await el.click({\n button: action === 'right-click' ? 'right' : 'left',\n clickCount: action === 'double-click' ? 2 : 1,\n timeout: TIMEOUT,\n });\n }\n}\n\nexport const click = When(\n 'I {click|double-click|right-click|hover} {locator}',\n async function (action: MouseAction, selector: string) {\n const prevUrl = this.page.url();\n\n const el = await fuzzyLocator(this.page, selector);\n await press(el, action);\n\n await waitAfterInteraction(this.page, el, { prevUrl });\n },\n);\n\nexport const clickHold = When(\n 'I {click|double-click|right-click|hover} {locator} while holding {keys}',\n async function (action: MouseAction, selector: string, combo: KeyCombo) {\n const prevUrl = this.page.url();\n\n const el = await fuzzyLocator(this.page, selector);\n const keys = [...combo.modifiers, combo.key];\n\n for (const m of keys) await this.page.keyboard.down(m);\n await press(el, action);\n for (const m of keys.reverse()) await this.page.keyboard.up(m);\n\n await waitAfterInteraction(this.page, el, { prevUrl });\n },\n);\n\nexport const scroll = When('I scroll {locator} into view', async function (selector: string) {\n const el = await fuzzyLocator(this.page, selector);\n await el.scrollIntoViewIfNeeded({ timeout: TIMEOUT });\n});\n","import { fuzzyLocator, setFieldValue } from '@letsrunit/playwright';\nimport { type Scalar, sleep } from '@letsrunit/utils';\nimport { When } from '../registry';\n\nconst TIMEOUT = 500;\nconst DELAY = 500;\n\nexport const set = When('I set {locator} to {value}', async function (selector: string, value: Scalar | Scalar[]) {\n const el = await fuzzyLocator(this.page, selector);\n await setFieldValue(el, value, { timeout: TIMEOUT });\n await sleep(DELAY);\n});\n\nexport const setRange = When(\n 'I set {locator} to range of {value} to {value}',\n async function (selector: string, from: Scalar, to: Scalar) {\n const el = await fuzzyLocator(this.page, selector);\n await setFieldValue(el, { from, to }, { timeout: TIMEOUT });\n await sleep(DELAY);\n },\n);\n\nexport const clear = When('I clear {locator}', async function (selector) {\n const el = await fuzzyLocator(this.page, selector);\n await setFieldValue(el, null, { timeout: TIMEOUT });\n await sleep(DELAY);\n});\n\nexport const check = When(\n 'I {check|uncheck} {locator}',\n async function (check: boolean, selector: string) {\n const el = await fuzzyLocator(this.page, selector);\n await setFieldValue(el, check, { timeout: TIMEOUT });\n await sleep(DELAY);\n },\n 'For checkbox input or switch component',\n);\n\nexport const focus = When('I {focus|blur} {locator}', async function (focus: boolean, selector: string) {\n const el = await fuzzyLocator(this.page, selector);\n\n if (focus) {\n await el.focus({ timeout: TIMEOUT });\n } else {\n await el.blur({ timeout: TIMEOUT });\n }\n});\n","import type { KeyCombo } from '@letsrunit/gherkin';\nimport { sleep } from '@letsrunit/utils';\nimport { When } from '../registry';\n\nconst DELAY = 500;\n\nexport const press = When('I press {keys}', async function (combo: KeyCombo) {\n // Hold modifiers\n for (const m of combo.modifiers) await this.page.keyboard.down(m);\n\n // Press final key\n await this.page.keyboard.press(combo.key);\n\n // Release modifiers (reverse order)\n for (const m of combo.modifiers.toReversed()) await this.page.keyboard.up(m);\n\n await sleep(DELAY);\n});\n\nexport const type = When('I type {string}', async function (value: string) {\n await this.page.keyboard.type(value, { delay: 200 });\n await sleep(DELAY);\n});\n","import { receiveMail, toEml } from '@letsrunit/mailbox';\nimport { asFilename, textToHtml } from '@letsrunit/utils';\nimport { Given, Then } from '../registry';\n\nconst MAX_RECEIVE_WAIT = 120_000; // 2 minutes\n\nexport const view = Given(\n `I'm viewing an email sent to {string} with subject {string}`,\n async function (address: string, subject: string) {\n const emails = await receiveMail(address, { full: true, after: this.startTime, subject, limit: 1 });\n if (emails.length === 0) {\n throw new Error(`Did not receive an email with subject \"${subject}\"`);\n }\n\n const email = emails[0];\n\n await this.page.goto('about:blank', { waitUntil: 'load' });\n await this.page.setContent(email.html ?? textToHtml(email.text!), { waitUntil: 'domcontentloaded' });\n },\n);\n\nexport const receive = Then(\n 'I received an email sent to {string} with subject {string}',\n async function (address: string, subject: string) {\n const emails = await receiveMail(address, {\n after: this.startTime,\n full: true,\n subject,\n wait: true,\n timeout: MAX_RECEIVE_WAIT,\n limit: 1,\n });\n\n if (emails.length === 0) {\n throw new Error(`Did not receive an email with subject \"${subject}\"`);\n }\n\n const email = emails[0];\n\n this.attach(toEml(email), {\n mediaType: 'message/rfc822',\n fileName: asFilename(email.subject, 'eml'),\n });\n },\n);\n","import { fuzzyLocator } from '@letsrunit/playwright';\nimport type { Locator } from '@playwright/test';\nimport { When } from '../registry';\n\nconst TIMEOUT = 500;\n\nasync function copyInput(el: Locator): Promise<string | undefined> {\n try {\n return await el.inputValue();\n } catch {}\n}\n\nasync function copyLink(el: Locator): Promise<string | undefined> {\n try {\n const tag = await el.evaluate<string>((n: Element) => n.tagName.toLowerCase());\n const href = tag === 'a' ? await el.getAttribute('href') : null;\n if (href) {\n return href.startsWith('mailto:') ? href.replace(/^mailto:/i, '') : href;\n }\n } catch {}\n}\n\nasync function copyText(el: Locator): Promise<string | null> {\n return (await el.textContent()) ?? null;\n}\n\nexport const copy = When('I copy {locator} to the clipboard', async function (selector: string) {\n const el = await fuzzyLocator(this.page, selector);\n let value = (await copyInput(el)) ?? (await copyLink(el)) ?? (await copyText(el));\n\n this.clipboard = { value };\n});\n\nexport const paste = When('I paste from the clipboard into {locator}', async function (selector: string) {\n const el = await fuzzyLocator(this.page, selector);\n const value = this.clipboard?.value || '';\n\n await el.fill(String(value), { timeout: TIMEOUT });\n});\n"]}
package/dist/define.d.ts DELETED
@@ -1,2 +0,0 @@
1
-
2
- export { }
package/dist/define.js DELETED
@@ -1,34 +0,0 @@
1
- import { typeDefinitions, registry } from './chunk-D6IA6AFW.js';
2
- import { defineParameterType, Given, When, Then, BeforeAll, Before, After } from '@cucumber/cucumber';
3
- import { createFieldEngine, createDateEngine, browse } from '@letsrunit/playwright';
4
- import { selectors, chromium } from '@playwright/test';
5
- import { sanitizeStepDefinition } from '@letsrunit/gherkin';
6
-
7
- for (const type of typeDefinitions) {
8
- defineParameterType(type);
9
- }
10
- for (const step of registry.definitions) {
11
- const def = step.type === "Given" ? Given : step.type === "When" ? When : Then;
12
- def(sanitizeStepDefinition(step.expression), step.fn);
13
- }
14
- var selectorsRegistered = false;
15
- BeforeAll(async function() {
16
- if (selectorsRegistered) return;
17
- try {
18
- await selectors.register("field", createFieldEngine);
19
- await selectors.register("date", createDateEngine);
20
- selectorsRegistered = true;
21
- } catch {
22
- }
23
- });
24
- Before(async function() {
25
- const browser = await chromium.launch({ headless: true });
26
- this._browser = browser;
27
- this.page = await browse(browser, this.parameters);
28
- this.startTime = Date.now();
29
- });
30
- After(async function() {
31
- await this._browser?.close();
32
- });
33
- //# sourceMappingURL=define.js.map
34
- //# sourceMappingURL=define.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/define.ts"],"names":[],"mappings":";;;;;;AAQA,KAAA,MAAW,QAAQ,eAAA,EAAiB;AAClC,EAAA,mBAAA,CAAoB,IAAI,CAAA;AAC1B;AAEA,KAAA,MAAW,IAAA,IAAQ,SAAS,WAAA,EAAa;AACvC,EAAA,MAAM,GAAA,GAAM,KAAK,IAAA,KAAS,OAAA,GAAU,QAAQ,IAAA,CAAK,IAAA,KAAS,SAAS,IAAA,GAAO,IAAA;AAC1E,EAAA,GAAA,CAAI,sBAAA,CAAuB,IAAA,CAAK,UAAU,CAAA,EAAG,KAAK,EAAE,CAAA;AACtD;AAEA,IAAI,mBAAA,GAAsB,KAAA;AAE1B,SAAA,CAAU,iBAAkB;AAC1B,EAAA,IAAI,mBAAA,EAAqB;AACzB,EAAA,IAAI;AACF,IAAA,MAAM,SAAA,CAAU,QAAA,CAAS,OAAA,EAAS,iBAAiB,CAAA;AACnD,IAAA,MAAM,SAAA,CAAU,QAAA,CAAS,MAAA,EAAQ,gBAAgB,CAAA;AACjD,IAAA,mBAAA,GAAsB,IAAA;AAAA,EACxB,CAAA,CAAA,MAAQ;AAAA,EAAC;AACX,CAAC,CAAA;AAED,MAAA,CAAO,iBAAkB;AACvB,EAAA,MAAM,UAAU,MAAM,QAAA,CAAS,OAAO,EAAE,QAAA,EAAU,MAAM,CAAA;AACxD,EAAA,IAAA,CAAK,QAAA,GAAW,OAAA;AAChB,EAAA,IAAA,CAAK,IAAA,GAAO,MAAM,MAAA,CAAO,OAAA,EAAS,KAAK,UAAU,CAAA;AACjD,EAAA,IAAA,CAAK,SAAA,GAAY,KAAK,GAAA,EAAI;AAC5B,CAAC,CAAA;AAED,KAAA,CAAM,iBAAkB;AACtB,EAAA,MAAM,IAAA,CAAK,UAAU,KAAA,EAAM;AAC7B,CAAC,CAAA","file":"define.js","sourcesContent":["import { After, Before, BeforeAll, defineParameterType, Given, Then, When } from '@cucumber/cucumber';\nimport { browse, createDateEngine, createFieldEngine } from '@letsrunit/playwright';\nimport { chromium, selectors } from '@playwright/test';\nimport { sanitizeStepDefinition } from '@letsrunit/gherkin';\nimport { typeDefinitions } from './parameters';\nimport { registry } from './registry';\nimport './steps'; // ensure built-in steps are registered before Cucumber receives them\n\nfor (const type of typeDefinitions) {\n defineParameterType(type);\n}\n\nfor (const step of registry.definitions) {\n const def = step.type === 'Given' ? Given : step.type === 'When' ? When : Then;\n def(sanitizeStepDefinition(step.expression), step.fn);\n}\n\nlet selectorsRegistered = false;\n\nBeforeAll(async function () {\n if (selectorsRegistered) return;\n try {\n await selectors.register('field', createFieldEngine);\n await selectors.register('date', createDateEngine);\n selectorsRegistered = true;\n } catch {}\n});\n\nBefore(async function () {\n const browser = await chromium.launch({ headless: true });\n this._browser = browser;\n this.page = await browse(browser, this.parameters);\n this.startTime = Date.now();\n});\n\nAfter(async function () {\n await this._browser?.close();\n});\n"]}
package/src/define.ts DELETED
@@ -1,38 +0,0 @@
1
- import { After, Before, BeforeAll, defineParameterType, Given, Then, When } from '@cucumber/cucumber';
2
- import { browse, createDateEngine, createFieldEngine } from '@letsrunit/playwright';
3
- import { chromium, selectors } from '@playwright/test';
4
- import { sanitizeStepDefinition } from '@letsrunit/gherkin';
5
- import { typeDefinitions } from './parameters';
6
- import { registry } from './registry';
7
- import './steps'; // ensure built-in steps are registered before Cucumber receives them
8
-
9
- for (const type of typeDefinitions) {
10
- defineParameterType(type);
11
- }
12
-
13
- for (const step of registry.definitions) {
14
- const def = step.type === 'Given' ? Given : step.type === 'When' ? When : Then;
15
- def(sanitizeStepDefinition(step.expression), step.fn);
16
- }
17
-
18
- let selectorsRegistered = false;
19
-
20
- BeforeAll(async function () {
21
- if (selectorsRegistered) return;
22
- try {
23
- await selectors.register('field', createFieldEngine);
24
- await selectors.register('date', createDateEngine);
25
- selectorsRegistered = true;
26
- } catch {}
27
- });
28
-
29
- Before(async function () {
30
- const browser = await chromium.launch({ headless: true });
31
- this._browser = browser;
32
- this.page = await browse(browser, this.parameters);
33
- this.startTime = Date.now();
34
- });
35
-
36
- After(async function () {
37
- await this._browser?.close();
38
- });