playwright-cucumber-ts-steps 1.1.8 → 1.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/LICENSE +21 -0
  2. package/dist/backend/actions/click.d.ts +132 -1
  3. package/dist/backend/actions/click.d.ts.map +1 -1
  4. package/dist/backend/actions/click.js +122 -53
  5. package/dist/backend/actions/find.d.ts +243 -1
  6. package/dist/backend/actions/find.d.ts.map +1 -1
  7. package/dist/backend/actions/find.js +196 -72
  8. package/dist/backend/actions/form.d.ts +37 -1
  9. package/dist/backend/actions/form.d.ts.map +1 -1
  10. package/dist/backend/actions/form.js +55 -3
  11. package/dist/backend/actions/formTable.d.ts +25 -1
  12. package/dist/backend/actions/formTable.d.ts.map +1 -1
  13. package/dist/backend/actions/formTable.js +27 -5
  14. package/dist/backend/actions/frames.d.ts +53 -1
  15. package/dist/backend/actions/frames.d.ts.map +1 -1
  16. package/dist/backend/actions/frames.js +48 -11
  17. package/dist/backend/actions/inputs.d.ts +139 -1
  18. package/dist/backend/actions/inputs.d.ts.map +1 -1
  19. package/dist/backend/actions/inputs.js +113 -43
  20. package/dist/backend/actions/interactions.d.ts +61 -1
  21. package/dist/backend/actions/interactions.d.ts.map +1 -1
  22. package/dist/backend/actions/interactions.js +65 -10
  23. package/dist/backend/actions/keyboard.d.ts +70 -1
  24. package/dist/backend/actions/keyboard.d.ts.map +1 -1
  25. package/dist/backend/actions/keyboard.js +59 -23
  26. package/dist/backend/actions/misc.d.ts +134 -1
  27. package/dist/backend/actions/misc.d.ts.map +1 -1
  28. package/dist/backend/actions/misc.js +106 -42
  29. package/dist/backend/actions/mobile.d.ts +74 -1
  30. package/dist/backend/actions/mobile.d.ts.map +1 -1
  31. package/dist/backend/actions/mobile.js +74 -13
  32. package/dist/backend/actions/mouse.d.ts +79 -1
  33. package/dist/backend/actions/mouse.d.ts.map +1 -1
  34. package/dist/backend/actions/mouse.js +66 -21
  35. package/dist/backend/actions/navigation.d.ts +48 -1
  36. package/dist/backend/actions/navigation.d.ts.map +1 -1
  37. package/dist/backend/actions/navigation.js +42 -15
  38. package/dist/backend/actions/waits.d.ts +55 -1
  39. package/dist/backend/actions/waits.d.ts.map +1 -1
  40. package/dist/backend/actions/waits.js +49 -17
  41. package/dist/backend/api/assertions.d.ts +32 -1
  42. package/dist/backend/api/assertions.d.ts.map +1 -1
  43. package/dist/backend/api/assertions.js +37 -9
  44. package/dist/backend/api/mock.d.ts +34 -1
  45. package/dist/backend/api/mock.d.ts.map +1 -1
  46. package/dist/backend/api/mock.js +37 -10
  47. package/dist/backend/api/network.d.ts +60 -1
  48. package/dist/backend/api/network.d.ts.map +1 -1
  49. package/dist/backend/api/network.js +53 -21
  50. package/dist/backend/api/requests.d.ts +43 -1
  51. package/dist/backend/api/requests.d.ts.map +1 -1
  52. package/dist/backend/api/requests.js +49 -17
  53. package/dist/backend/assertions/pageState.d.ts +40 -1
  54. package/dist/backend/assertions/pageState.d.ts.map +1 -1
  55. package/dist/backend/assertions/pageState.js +33 -12
  56. package/dist/backend/assertions/text.d.ts +46 -1
  57. package/dist/backend/assertions/text.d.ts.map +1 -1
  58. package/dist/backend/assertions/text.js +51 -8
  59. package/dist/backend/assertions/visibility.d.ts +102 -1
  60. package/dist/backend/assertions/visibility.d.ts.map +1 -1
  61. package/dist/backend/assertions/visibility.js +86 -36
  62. package/dist/backend/auth/index.js +2 -2
  63. package/dist/backend/db/steps.d.ts +35 -1
  64. package/dist/backend/db/steps.d.ts.map +1 -1
  65. package/dist/backend/db/steps.js +48 -15
  66. package/dist/backend/elements/alerts.d.ts +35 -1
  67. package/dist/backend/elements/alerts.d.ts.map +1 -1
  68. package/dist/backend/elements/alerts.js +39 -6
  69. package/dist/backend/elements/forms.d.ts +44 -1
  70. package/dist/backend/elements/forms.d.ts.map +1 -1
  71. package/dist/backend/elements/forms.js +50 -11
  72. package/dist/backend/elements/frames.d.ts +36 -1
  73. package/dist/backend/elements/frames.d.ts.map +1 -1
  74. package/dist/backend/elements/frames.js +43 -13
  75. package/dist/core/runner.d.ts.map +1 -1
  76. package/dist/core/runner.js +3 -4
  77. package/package.json +52 -12
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StoreElementText = exports.FindTextareaByLabel = exports.FindInputByValue = exports.FindInputByPlaceholder = exports.FindInputByName = exports.FindInputById = exports.GetFocusedElement = exports.GetNthElement = exports.GetLastElement = exports.GetFirstElement = exports.FindButtonsByText = exports.FindHeadingsByText = exports.FindElementsBySelector = exports.FindElementByName = exports.FindHeadingByText = exports.FindLinkByText = exports.FindElementByAltText = exports.FindElementByLabel = exports.FindElementByPlaceholder = exports.FindElementByRole = exports.FindElementByTestId = exports.FindElementByTitle = exports.FindElementByText = exports.FindElementBySelector = void 0;
3
4
  const test_1 = require("@playwright/test");
4
5
  const registry_1 = require("../../core/registry");
5
6
  const state_1 = require("../utils/state");
@@ -7,80 +8,121 @@ const state_1 = require("../utils/state");
7
8
  // 1. GENERAL FINDING (Single)
8
9
  // =============================
9
10
  /**
10
- * Finds an element by CSS selector.
11
- * Pattern: When I find element by selector ".my-class"
11
+ * Finds a single element using a CSS or XPath selector.
12
+ * Asserts that exactly one element is found.
13
+ *
14
+ * ```gherkin
15
+ * When I find element by selector ".nav-bar"
16
+ * ```
17
+ *
18
+ * @param selector - The CSS or XPath selector string.
12
19
  */
13
- (0, registry_1.Step)("I find element by selector {string}", async (page, selector) => {
20
+ exports.FindElementBySelector = (0, registry_1.Step)("I find element by selector {string}", async (page, selector) => {
14
21
  const element = page.locator(selector);
15
22
  await (0, test_1.expect)(element).toHaveCount(1);
16
23
  (0, state_1.setActiveElement)(page, element);
17
24
  console.log(`🔍 Found element by selector: "${selector}"`);
18
25
  });
19
26
  /**
20
- * Finds an element by exact text.
21
- * Pattern: When I find element by text "Submit"
27
+ * Finds an element containing the exact text provided.
28
+ *
29
+ * ```gherkin
30
+ * When I find element by text "Submit Order"
31
+ * ```
32
+ *
33
+ * @param text - The exact text content to match.
22
34
  */
23
- (0, registry_1.Step)("I find element by text {string}", async (page, text) => {
35
+ exports.FindElementByText = (0, registry_1.Step)("I find element by text {string}", async (page, text) => {
24
36
  const element = page.getByText(text, { exact: true });
25
37
  await (0, test_1.expect)(element).toHaveCount(1);
26
38
  (0, state_1.setActiveElement)(page, element);
27
39
  console.log(`🔍 Found element by exact text: "${text}"`);
28
40
  });
29
41
  /**
30
- * Finds an element by title attribute.
31
- * Pattern: When I find element by title "Tooltip"
42
+ * Finds an element by its `title` attribute.
43
+ *
44
+ * ```gherkin
45
+ * When I find element by title "Close Modal"
46
+ * ```
47
+ *
48
+ * @param title - The value of the title attribute.
32
49
  */
33
- (0, registry_1.Step)("I find element by title {string}", async (page, title) => {
50
+ exports.FindElementByTitle = (0, registry_1.Step)("I find element by title {string}", async (page, title) => {
34
51
  const element = page.getByTitle(title);
35
52
  await (0, test_1.expect)(element).toHaveCount(1);
36
53
  (0, state_1.setActiveElement)(page, element);
37
54
  console.log(`🔍 Found element by title: "${title}"`);
38
55
  });
39
56
  /**
40
- * Finds an element by test id (data-testid).
41
- * Pattern: When I find element by testid "submit-btn"
57
+ * Finds an element by its test ID (usually `data-testid`).
58
+ *
59
+ * ```gherkin
60
+ * When I find element by testid "login-form"
61
+ * ```
62
+ *
63
+ * @param testid - The data-testid attribute value.
42
64
  */
43
- (0, registry_1.Step)("I find element by testid {string}", async (page, testid) => {
65
+ exports.FindElementByTestId = (0, registry_1.Step)("I find element by testid {string}", async (page, testid) => {
44
66
  const element = page.getByTestId(testid);
45
67
  await (0, test_1.expect)(element).toHaveCount(1);
46
68
  (0, state_1.setActiveElement)(page, element);
47
69
  console.log(`🔍 Found element by testid: "${testid}"`);
48
70
  });
49
71
  /**
50
- * Finds an element by ARIA role.
51
- * Pattern: When I find element by role "button"
72
+ * Finds an element by its ARIA role.
73
+ *
74
+ * ```gherkin
75
+ * When I find element by role "button"
76
+ * ```
77
+ *
78
+ * @param role - The ARIA role (e.g., "button", "link", "heading").
52
79
  */
53
- (0, registry_1.Step)("I find element by role {string}", async (page, role) => {
80
+ exports.FindElementByRole = (0, registry_1.Step)("I find element by role {string}", async (page, role) => {
54
81
  const element = page.getByRole(role);
55
82
  await (0, test_1.expect)(element).toHaveCount(1);
56
83
  (0, state_1.setActiveElement)(page, element);
57
84
  console.log(`🔍 Found element by role: "${role}"`);
58
85
  });
59
86
  /**
60
- * Finds an element by placeholder.
61
- * Pattern: When I find element by placeholder text "Search..."
87
+ * Finds an input element by its placeholder text.
88
+ *
89
+ * ```gherkin
90
+ * When I find element by placeholder text "Enter your email"
91
+ * ```
92
+ *
93
+ * @param text - The placeholder text value.
62
94
  */
63
- (0, registry_1.Step)("I find element by placeholder text {string}", async (page, text) => {
95
+ exports.FindElementByPlaceholder = (0, registry_1.Step)("I find element by placeholder text {string}", async (page, text) => {
64
96
  const element = page.getByPlaceholder(text);
65
97
  await (0, test_1.expect)(element).toHaveCount(1);
66
98
  (0, state_1.setActiveElement)(page, element);
67
99
  console.log(`🔍 Found element by placeholder: "${text}"`);
68
100
  });
69
101
  /**
70
- * Finds an element by label.
71
- * Pattern: When I find element by label text "Username"
102
+ * Finds a form control associated with a specific label text.
103
+ *
104
+ * ```gherkin
105
+ * When I find element by label text "Password"
106
+ * ```
107
+ *
108
+ * @param label - The visible text of the label.
72
109
  */
73
- (0, registry_1.Step)("I find element by label text {string}", async (page, label) => {
110
+ exports.FindElementByLabel = (0, registry_1.Step)("I find element by label text {string}", async (page, label) => {
74
111
  const element = page.getByLabel(label);
75
112
  await (0, test_1.expect)(element).toHaveCount(1);
76
113
  (0, state_1.setActiveElement)(page, element);
77
114
  console.log(`🔍 Found element by label: "${label}"`);
78
115
  });
79
116
  /**
80
- * Finds an element by alt text (images).
81
- * Pattern: When I find element by alt text "Logo"
117
+ * Finds an element (usually an image) by its alt text.
118
+ *
119
+ * ```gherkin
120
+ * When I find element by alt text "Company Logo"
121
+ * ```
122
+ *
123
+ * @param alt - The value of the alt attribute.
82
124
  */
83
- (0, registry_1.Step)("I find element by alt text {string}", async (page, alt) => {
125
+ exports.FindElementByAltText = (0, registry_1.Step)("I find element by alt text {string}", async (page, alt) => {
84
126
  const element = page.getByAltText(alt);
85
127
  await (0, test_1.expect)(element).toHaveCount(1);
86
128
  (0, state_1.setActiveElement)(page, element);
@@ -90,10 +132,16 @@ const state_1 = require("../utils/state");
90
132
  // 2. SPECIFIC ELEMENTS (Link/Heading/Name)
91
133
  // =============================
92
134
  /**
93
- * Finds a link by text.
94
- * Pattern: When I find link by text "Home"
135
+ * Finds a specific link by its visible text.
136
+ * If multiple links match, selects the first one.
137
+ *
138
+ * ```gherkin
139
+ * When I find link by text "Read More"
140
+ * ```
141
+ *
142
+ * @param text - The visible text of the link.
95
143
  */
96
- (0, registry_1.Step)("I find link by text {string}", async (page, text) => {
144
+ exports.FindLinkByText = (0, registry_1.Step)("I find link by text {string}", async (page, text) => {
97
145
  const element = page.getByRole("link", { name: text });
98
146
  // We use .first() here because links often have duplicates (e.g. footer/header)
99
147
  // but strict mode usually prefers uniqueness.
@@ -101,19 +149,31 @@ const state_1 = require("../utils/state");
101
149
  console.log(`🔍 Found link by text: "${text}"`);
102
150
  });
103
151
  /**
104
- * Finds a heading by text.
105
- * Pattern: When I find heading by text "Welcome"
152
+ * Finds a heading (h1-h6) by its text content.
153
+ * If multiple headings match, selects the first one.
154
+ *
155
+ * ```gherkin
156
+ * When I find heading by text "Dashboard"
157
+ * ```
158
+ *
159
+ * @param text - The text content of the heading.
106
160
  */
107
- (0, registry_1.Step)("I find heading by text {string}", async (page, text) => {
161
+ exports.FindHeadingByText = (0, registry_1.Step)("I find heading by text {string}", async (page, text) => {
108
162
  const element = page.getByRole("heading", { name: text });
109
163
  (0, state_1.setActiveElement)(page, element.first());
110
164
  console.log(`🔍 Found heading by text: "${text}"`);
111
165
  });
112
166
  /**
113
- * Finds an element by name attribute.
114
- * Pattern: When I find element by name "email"
167
+ * Finds an element by its `name` attribute.
168
+ * Useful for form fields not easily accessible by label.
169
+ *
170
+ * ```gherkin
171
+ * When I find element by name "csrf_token"
172
+ * ```
173
+ *
174
+ * @param name - The value of the name attribute.
115
175
  */
116
- (0, registry_1.Step)("I find element by name {string}", async (page, name) => {
176
+ exports.FindElementByName = (0, registry_1.Step)("I find element by name {string}", async (page, name) => {
117
177
  // Broad selector for name attribute
118
178
  const element = page.locator(`[name="${name}"]`);
119
179
  await (0, test_1.expect)(element).toHaveCount(1);
@@ -124,29 +184,45 @@ const state_1 = require("../utils/state");
124
184
  // 3. GENERAL FINDING (Multiple)
125
185
  // =============================
126
186
  /**
127
- * Finds all elements by selector.
128
- * Pattern: When I find elements by selector ".items"
187
+ * Finds all elements matching a CSS selector and stores them as a list.
188
+ *
189
+ * ```gherkin
190
+ * When I find elements by selector "ul > li"
191
+ * ```
192
+ *
193
+ * @param selector - The CSS selector.
129
194
  */
130
- (0, registry_1.Step)("I find elements by selector {string}", async (page, selector) => {
195
+ exports.FindElementsBySelector = (0, registry_1.Step)("I find elements by selector {string}", async (page, selector) => {
131
196
  const elements = page.locator(selector);
132
197
  const count = await elements.count();
133
198
  (0, state_1.setActiveElements)(page, elements);
134
199
  console.log(`🔍 Found ${count} elements with selector: "${selector}"`);
135
200
  });
136
201
  /**
137
- * Finds all headings by text.
138
- * Pattern: When I find headings by text "Chapter"
202
+ * Finds all headings matching specific text.
203
+ *
204
+ * ```gherkin
205
+ * When I find headings by text "Article Title"
206
+ * ```
207
+ *
208
+ * @param text - The text to match headings against.
139
209
  */
140
- (0, registry_1.Step)("I find headings by text {string}", async (page, text) => {
210
+ exports.FindHeadingsByText = (0, registry_1.Step)("I find headings by text {string}", async (page, text) => {
141
211
  const elements = page.getByRole("heading", { name: text });
142
212
  (0, state_1.setActiveElements)(page, elements);
143
213
  console.log(`🔍 Found headings matching "${text}"`);
144
214
  });
145
215
  /**
146
- * Finds all buttons by text (supports alias).
147
- * Pattern: When I find buttons by text "Save"
216
+ * Finds all buttons matching specific text.
217
+ * Supports variable aliasing (e.g., "@buttonName").
218
+ *
219
+ * ```gherkin
220
+ * When I find buttons by text "Add to Cart"
221
+ * ```
222
+ *
223
+ * @param text - The button text or an alias (e.g., "@myBtn").
148
224
  */
149
- (0, registry_1.Step)("I find buttons by text {string}", async (page, text) => {
225
+ exports.FindButtonsByText = (0, registry_1.Step)("I find buttons by text {string}", async (page, text) => {
150
226
  let searchText = text;
151
227
  // Handle Alias
152
228
  if (text.startsWith("@")) {
@@ -164,30 +240,43 @@ const state_1 = require("../utils/state");
164
240
  // 4. GET / REFINE SELECTION
165
241
  // =============================
166
242
  /**
167
- * Gets the first element from a stored list.
168
- * Pattern: When I get first element
243
+ * Selects the first element from the currently stored list of elements.
244
+ *
245
+ * ```gherkin
246
+ * When I get first element
247
+ * ```
169
248
  */
170
- (0, registry_1.Step)("I get first element", async (page) => {
249
+ exports.GetFirstElement = (0, registry_1.Step)("I get first element", async (page) => {
171
250
  const elements = (0, state_1.getActiveElements)(page);
172
251
  const element = elements.first();
173
252
  (0, state_1.setActiveElement)(page, element);
174
253
  console.log("👉 Selected FIRST element");
175
254
  });
176
255
  /**
177
- * Gets the last element from a stored list.
178
- * Pattern: When I get last element
256
+ * Selects the last element from the currently stored list of elements.
257
+ *
258
+ * ```gherkin
259
+ * When I get last element
260
+ * ```
179
261
  */
180
- (0, registry_1.Step)("I get last element", async (page) => {
262
+ exports.GetLastElement = (0, registry_1.Step)("I get last element", async (page) => {
181
263
  const elements = (0, state_1.getActiveElements)(page);
182
264
  const element = elements.last();
183
265
  (0, state_1.setActiveElement)(page, element);
184
266
  console.log("👉 Selected LAST element");
185
267
  });
186
268
  /**
187
- * Gets the nth element (1-based index).
188
- * Pattern: When I get 2nd element
269
+ * Selects the nth element from the currently stored list.
270
+ * Uses 1-based indexing (e.g., 1st, 2nd, 3rd).
271
+ *
272
+ * ```gherkin
273
+ * When I get 2nd element
274
+ * When I get 10th element
275
+ * ```
276
+ *
277
+ * @param indexStr - The number captured from the regex (e.g., "2").
189
278
  */
190
- (0, registry_1.Step)(/^I get (\d+)(?:st|nd|rd|th) element$/, async (page, indexStr) => {
279
+ exports.GetNthElement = (0, registry_1.Step)(/^I get (\d+)(?:st|nd|rd|th) element$/, async (page, indexStr) => {
191
280
  const index = parseInt(indexStr, 10);
192
281
  const elements = (0, state_1.getActiveElements)(page);
193
282
  const count = await elements.count();
@@ -200,10 +289,13 @@ const state_1 = require("../utils/state");
200
289
  console.log(`👉 Selected element #${index}`);
201
290
  });
202
291
  /**
203
- * Gets the currently focused element.
204
- * Pattern: When I get focused element
292
+ * Selects the element that currently has browser focus.
293
+ *
294
+ * ```gherkin
295
+ * When I get focused element
296
+ * ```
205
297
  */
206
- (0, registry_1.Step)("I get focused element", async (page) => {
298
+ exports.GetFocusedElement = (0, registry_1.Step)("I get focused element", async (page) => {
207
299
  // Use CSS selector for focused element
208
300
  const element = page.locator("*:focus");
209
301
  (0, state_1.setActiveElement)(page, element);
@@ -213,37 +305,58 @@ const state_1 = require("../utils/state");
213
305
  // 5. INPUTS & TEXTAREAS SPECIFICS
214
306
  // =============================
215
307
  /**
216
- * Finds input by ID.
217
- * Pattern: When I find input by ID "username"
308
+ * Finds an input field by its ID attribute.
309
+ *
310
+ * ```gherkin
311
+ * When I find input by ID "user_email"
312
+ * ```
313
+ *
314
+ * @param id - The ID string.
218
315
  */
219
- (0, registry_1.Step)("I find input by ID {string}", async (page, id) => {
316
+ exports.FindInputById = (0, registry_1.Step)("I find input by ID {string}", async (page, id) => {
220
317
  const element = page.locator(`input#${id}`);
221
318
  (0, state_1.setActiveElement)(page, element);
222
319
  console.log(`🔍 Found input by ID: "${id}"`);
223
320
  });
224
321
  /**
225
- * Finds input by name.
226
- * Pattern: When I find input by name "email"
322
+ * Finds an input field by its name attribute.
323
+ *
324
+ * ```gherkin
325
+ * When I find input by name "password"
326
+ * ```
327
+ *
328
+ * @param name - The name attribute value.
227
329
  */
228
- (0, registry_1.Step)("I find input by name {string}", async (page, name) => {
330
+ exports.FindInputByName = (0, registry_1.Step)("I find input by name {string}", async (page, name) => {
229
331
  const element = page.locator(`input[name="${name}"]`);
230
332
  (0, state_1.setActiveElement)(page, element);
231
333
  console.log(`🔍 Found input by name: "${name}"`);
232
334
  });
233
335
  /**
234
- * Finds input by placeholder.
235
- * Pattern: When I find input by placeholder text "Enter email"
336
+ * Finds an input field by its placeholder text.
337
+ *
338
+ * ```gherkin
339
+ * When I find input by placeholder text "Search products..."
340
+ * ```
341
+ *
342
+ * @param placeholder - The placeholder text.
236
343
  */
237
- (0, registry_1.Step)("I find input by placeholder text {string}", async (page, placeholder) => {
344
+ exports.FindInputByPlaceholder = (0, registry_1.Step)("I find input by placeholder text {string}", async (page, placeholder) => {
238
345
  const element = page.locator(`input[placeholder="${placeholder}"]`);
239
346
  (0, state_1.setActiveElement)(page, element);
240
347
  console.log(`🔍 Found input by placeholder: "${placeholder}"`);
241
348
  });
242
349
  /**
243
- * Finds input by display value (supports alias).
244
- * Pattern: When I find input by display value "John Doe"
350
+ * Finds an input field that currently has a specific value.
351
+ * Supports variable aliasing (e.g., "@storedValue").
352
+ *
353
+ * ```gherkin
354
+ * When I find input by display value "John"
355
+ * ```
356
+ *
357
+ * @param value - The value to match.
245
358
  */
246
- (0, registry_1.Step)("I find input by display value {string}", async (page, value) => {
359
+ exports.FindInputByValue = (0, registry_1.Step)("I find input by display value {string}", async (page, value) => {
247
360
  let searchValue = value;
248
361
  if (value.startsWith("@")) {
249
362
  const alias = value.slice(1);
@@ -258,10 +371,16 @@ const state_1 = require("../utils/state");
258
371
  console.log(`🔍 Found input with value: "${searchValue}"`);
259
372
  });
260
373
  /**
261
- * Finds textarea by label.
262
- * Pattern: When I find textarea by label text "Comments"
374
+ * Finds a textarea associated with a specific label.
375
+ * Fallback mechanism attempts to find the textarea via label if the standard getByLabel returns a generic element.
376
+ *
377
+ * ```gherkin
378
+ * When I find textarea by label text "Description"
379
+ * ```
380
+ *
381
+ * @param label - The visible text of the label.
263
382
  */
264
- (0, registry_1.Step)("I find textarea by label text {string}", async (page, label) => {
383
+ exports.FindTextareaByLabel = (0, registry_1.Step)("I find textarea by label text {string}", async (page, label) => {
265
384
  const element = page.getByLabel(label).locator("textarea").first();
266
385
  // Fallback if strict label matching fails, try locator strategy
267
386
  const count = await element.count();
@@ -279,10 +398,15 @@ const state_1 = require("../utils/state");
279
398
  // 6. UTILITIES (Store Text)
280
399
  // =============================
281
400
  /**
282
- * Stores the text of the current element into a variable.
283
- * Pattern: When I store element text as "myVar"
401
+ * Reads the text content of the currently active element and stores it in a variable.
402
+ *
403
+ * ```gherkin
404
+ * When I store element text as "confirmationCode"
405
+ * ```
406
+ *
407
+ * @param alias - The name of the variable to store the text in (without "@").
284
408
  */
285
- (0, registry_1.Step)("I store element text as {string}", async (page, alias) => {
409
+ exports.StoreElementText = (0, registry_1.Step)("I store element text as {string}", async (page, alias) => {
286
410
  const element = (0, state_1.getActiveElement)(page);
287
411
  const text = await element.textContent();
288
412
  const cleanText = text?.trim() || "";
@@ -1,2 +1,38 @@
1
- export {};
1
+ /**
2
+ * A "Swiss Army Knife" step for filling forms, performing assertions, and executing mixed workflows.
3
+ * It iterates through a Data Table and performs actions based on the `Target` and `Value` columns.
4
+ *
5
+ * ```gherkin
6
+ * When I fill the following {string} form data
7
+ * ```
8
+ *
9
+ * @remarks
10
+ * **Columns:**
11
+ * - `Target`: The CSS selector, or a special keyword (request:, set:localStorage:, wait).
12
+ * - `Value`: The value to input, the action (click, check), or assertion pattern.
13
+ *
14
+ * **Supported UI Actions:**
15
+ * - **Fill:** Default behavior. Types `Value` into `Target`.
16
+ * - **Click:** Set `Value` to "click".
17
+ * - **Check:** Set `Value` to "check".
18
+ * - **Select:** Set `Value` to "select" (selects first option).
19
+ * - **Assert Visible:** Set `Value` to "assert:visible".
20
+ * - **Assert Text:** Set `Value` to "assert:text:Expected Text".
21
+ *
22
+ * **Supported Special Actions:**
23
+ * - **API Request:** Target = `request:METHOD:URL`, Value = `payload_filename.json`.
24
+ * - **Local Storage:** Target = `set:localStorage:key`, Value = `value`.
25
+ * - **Wait:** Target = `wait`, Value = `wait:1000` (ms).
26
+ *
27
+ * @example
28
+ * When I fill the following "Login Flow" form data:
29
+ * | Target | Value |
30
+ * | #username | myuser |
31
+ * | #password | @secretPassword |
32
+ * | #login-btn | click |
33
+ * | wait | wait:500 |
34
+ * | .error-msg | assert:visible |
35
+ * | request:GET:/api/status | body: {} |
36
+ */
37
+ export declare const FillFormData: void;
2
38
  //# sourceMappingURL=form.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../../../src/backend/actions/form.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../../../src/backend/actions/form.ts"],"names":[],"mappings":"AAkFA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,eAAO,MAAM,YAAY,MAgIxB,CAAC"}
@@ -33,14 +33,19 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.FillFormData = void 0;
36
37
  const fs = __importStar(require("fs"));
37
38
  const path = __importStar(require("path"));
38
39
  const test_1 = require("@playwright/test");
39
40
  const registry_1 = require("../../core/registry");
40
41
  const state_1 = require("../utils/state");
41
42
  /**
42
- * Helper to convert raw runner table into Objects (ActionRow[])
43
- * Handles whitespace in headers (e.g., "| Target |" -> "Target")
43
+ * Helper to convert raw runner table into Objects (ActionRow[]).
44
+ * Handles whitespace in headers (e.g., "| Target |" -> "Target").
45
+ * Supports both Cucumber DataTables (hashes) and Raw Arrays (Custom Runner).
46
+ *
47
+ * @param table - The raw table object from the test runner.
48
+ * @returns An array of ActionRow objects.
44
49
  */
45
50
  function parseDataTable(table) {
46
51
  // Debug Log: See exactly what the runner is passing
@@ -65,6 +70,14 @@ function parseDataTable(table) {
65
70
  }
66
71
  return [];
67
72
  }
73
+ /**
74
+ * Helper to resolve values, handling variable aliases.
75
+ * If a value starts with "@", it retrieves it from the global state.
76
+ *
77
+ * @param page - The Playwright Page object (for context).
78
+ * @param rawValue - The value string from the Gherkin table.
79
+ * @returns The resolved string value.
80
+ */
68
81
  function resolveValue(page, rawValue) {
69
82
  if (!rawValue)
70
83
  return "";
@@ -81,7 +94,43 @@ function resolveValue(page, rawValue) {
81
94
  }
82
95
  return trimmed;
83
96
  }
84
- (0, registry_1.Step)("I fill the following {string} form data", async (page, formName, table) => {
97
+ /**
98
+ * A "Swiss Army Knife" step for filling forms, performing assertions, and executing mixed workflows.
99
+ * It iterates through a Data Table and performs actions based on the `Target` and `Value` columns.
100
+ *
101
+ * ```gherkin
102
+ * When I fill the following {string} form data
103
+ * ```
104
+ *
105
+ * @remarks
106
+ * **Columns:**
107
+ * - `Target`: The CSS selector, or a special keyword (request:, set:localStorage:, wait).
108
+ * - `Value`: The value to input, the action (click, check), or assertion pattern.
109
+ *
110
+ * **Supported UI Actions:**
111
+ * - **Fill:** Default behavior. Types `Value` into `Target`.
112
+ * - **Click:** Set `Value` to "click".
113
+ * - **Check:** Set `Value` to "check".
114
+ * - **Select:** Set `Value` to "select" (selects first option).
115
+ * - **Assert Visible:** Set `Value` to "assert:visible".
116
+ * - **Assert Text:** Set `Value` to "assert:text:Expected Text".
117
+ *
118
+ * **Supported Special Actions:**
119
+ * - **API Request:** Target = `request:METHOD:URL`, Value = `payload_filename.json`.
120
+ * - **Local Storage:** Target = `set:localStorage:key`, Value = `value`.
121
+ * - **Wait:** Target = `wait`, Value = `wait:1000` (ms).
122
+ *
123
+ * @example
124
+ * When I fill the following "Login Flow" form data:
125
+ * | Target | Value |
126
+ * | #username | myuser |
127
+ * | #password | @secretPassword |
128
+ * | #login-btn | click |
129
+ * | wait | wait:500 |
130
+ * | .error-msg | assert:visible |
131
+ * | request:GET:/api/status | body: {} |
132
+ */
133
+ exports.FillFormData = (0, registry_1.Step)("I fill the following {string} form data", async (page, formName, table) => {
85
134
  console.log(`📝 Processing Form: "${formName}"`);
86
135
  // Parse the table
87
136
  const rows = parseDataTable(table);
@@ -101,6 +150,7 @@ function resolveValue(page, rawValue) {
101
150
  // ============================================
102
151
  // 1. SPECIAL ACTIONS
103
152
  // ============================================
153
+ // ✅ API Requests
104
154
  if (target.startsWith("request:")) {
105
155
  const parts = target.replace("request:", "").split(":");
106
156
  const method = parts[0].toUpperCase();
@@ -126,6 +176,7 @@ function resolveValue(page, rawValue) {
126
176
  }
127
177
  continue;
128
178
  }
179
+ // ✅ Local Storage
129
180
  if (target.startsWith("set:localStorage:")) {
130
181
  const key = target.split(":")[2];
131
182
  await page.evaluate(({ k, v }) => localStorage.setItem(k, v), {
@@ -135,6 +186,7 @@ function resolveValue(page, rawValue) {
135
186
  console.log(`📦 localStorage: Set "${key}"`);
136
187
  continue;
137
188
  }
189
+ // ✅ Explicit Waits
138
190
  if (target === "wait") {
139
191
  const time = parseInt(rawValue.replace("wait:", ""), 10);
140
192
  if (!isNaN(time)) {
@@ -1,2 +1,26 @@
1
- export {};
1
+ /**
2
+ * Iterates through a provided Data Table to fill inputs, click elements, or perform assertions.
3
+ * This step is designed for bulk form interaction without writing repetitive "When I..." steps.
4
+ *
5
+ * ```gherkin
6
+ * When I fill the following "Login" test form data
7
+ * | #username | tomsmith |
8
+ * | #password | SuperSecretPassword! |
9
+ * | #login | click |
10
+ * ```
11
+ *
12
+ * @param formName - A descriptive name for the form being filled (used for logging only).
13
+ * @param tableData - A 2D array representing the data table rows (automatically passed by the runner).
14
+ *
15
+ * @remarks
16
+ * **Supported Values in Column 2:**
17
+ * - `Any String`: Fills the input found by the selector in Column 1.
18
+ * - `"click"`: Clicks the element.
19
+ * - `"check"`: Checks a checkbox or radio button.
20
+ * - `"assert:visible"`: Asserts that the element is visible.
21
+ * - `"assert:text:EXPECTED"`: Asserts that the element contains the specific text.
22
+ *
23
+ * @throws {Error} If the Data Table is missing or invalid.
24
+ */
25
+ export declare const FillTestFormData: void;
2
26
  //# sourceMappingURL=formTable.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"formTable.d.ts","sourceRoot":"","sources":["../../../src/backend/actions/formTable.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"formTable.d.ts","sourceRoot":"","sources":["../../../src/backend/actions/formTable.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,gBAAgB,MA8B5B,CAAC"}
@@ -1,12 +1,34 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const registry_1 = require("../../core/registry");
3
+ exports.FillTestFormData = void 0;
4
4
  const test_1 = require("@playwright/test");
5
- // CHANGE: Removed the ':' at the end of the string below
6
- (0, registry_1.Step)("I fill the following {string} test form data", async (page, formName, tableData) => {
5
+ const registry_1 = require("../../core/registry");
6
+ /**
7
+ * Iterates through a provided Data Table to fill inputs, click elements, or perform assertions.
8
+ * This step is designed for bulk form interaction without writing repetitive "When I..." steps.
9
+ *
10
+ * ```gherkin
11
+ * When I fill the following "Login" test form data
12
+ * | #username | tomsmith |
13
+ * | #password | SuperSecretPassword! |
14
+ * | #login | click |
15
+ * ```
16
+ *
17
+ * @param formName - A descriptive name for the form being filled (used for logging only).
18
+ * @param tableData - A 2D array representing the data table rows (automatically passed by the runner).
19
+ *
20
+ * @remarks
21
+ * **Supported Values in Column 2:**
22
+ * - `Any String`: Fills the input found by the selector in Column 1.
23
+ * - `"click"`: Clicks the element.
24
+ * - `"check"`: Checks a checkbox or radio button.
25
+ * - `"assert:visible"`: Asserts that the element is visible.
26
+ * - `"assert:text:EXPECTED"`: Asserts that the element contains the specific text.
27
+ *
28
+ * @throws {Error} If the Data Table is missing or invalid.
29
+ */
30
+ exports.FillTestFormData = (0, registry_1.Step)("I fill the following {string} test form data", async (page, formName, tableData) => {
7
31
  console.log(`📝 Processing Form: ${formName}`);
8
- // The runner passes the table data as the last argument
9
- // tableData = [ ['#username', 'tomsmith'], ['#password', '...'] ]
10
32
  // Guard clause: Ensure tableData exists to prevent crashes if user forgets the table
11
33
  if (!tableData || !Array.isArray(tableData)) {
12
34
  throw new Error(`❌ The step "I fill the following '${formName}' form data" requires a Data Table below it.`);