playwright-cucumber-ts-steps 0.1.7 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -11
- package/lib/actions/clickSteps.d.ts +251 -1
- package/lib/actions/clickSteps.js +297 -47
- package/lib/actions/cookieSteps.d.ts +18 -1
- package/lib/actions/cookieSteps.js +65 -0
- package/lib/actions/debugSteps.d.ts +14 -1
- package/lib/actions/debugSteps.js +18 -3
- package/lib/actions/elementFindSteps.d.ts +668 -1
- package/lib/actions/elementFindSteps.js +808 -94
- package/lib/actions/fillFormSteps.d.ts +69 -1
- package/lib/actions/fillFormSteps.js +178 -71
- package/lib/actions/index.d.ts +11 -0
- package/lib/actions/index.js +28 -0
- package/lib/actions/inputSteps.d.ts +218 -1
- package/lib/actions/inputSteps.js +303 -57
- package/lib/actions/interceptionSteps.d.ts +169 -1
- package/lib/actions/interceptionSteps.js +258 -38
- package/lib/actions/miscSteps.d.ts +645 -1
- package/lib/actions/miscSteps.js +898 -157
- package/lib/actions/mouseSteps.d.ts +143 -1
- package/lib/actions/mouseSteps.js +200 -32
- package/lib/actions/scrollSteps.d.ts +82 -1
- package/lib/actions/scrollSteps.js +116 -16
- package/lib/actions/storageSteps.d.ts +174 -1
- package/lib/actions/storageSteps.js +253 -33
- package/lib/assertions/buttonAndTextVisibilitySteps.d.ts +245 -1
- package/lib/assertions/buttonAndTextVisibilitySteps.js +342 -91
- package/lib/assertions/cookieSteps.d.ts +75 -1
- package/lib/assertions/cookieSteps.js +97 -29
- package/lib/assertions/elementSteps.d.ts +264 -1
- package/lib/assertions/elementSteps.js +376 -78
- package/lib/assertions/formInputSteps.d.ts +248 -1
- package/lib/assertions/formInputSteps.js +342 -79
- package/lib/assertions/index.d.ts +10 -0
- package/lib/assertions/index.js +27 -0
- package/lib/assertions/interceptionRequestsSteps.d.ts +353 -1
- package/lib/assertions/interceptionRequestsSteps.js +569 -177
- package/lib/assertions/locationSteps.d.ts +217 -1
- package/lib/assertions/locationSteps.js +287 -64
- package/lib/assertions/roleTestIdSteps.d.ts +159 -1
- package/lib/assertions/roleTestIdSteps.js +217 -22
- package/lib/assertions/semanticSteps.d.ts +176 -1
- package/lib/assertions/semanticSteps.js +245 -60
- package/lib/assertions/storageSteps.d.ts +149 -1
- package/lib/assertions/storageSteps.js +201 -65
- package/lib/assertions/visualSteps.d.ts +74 -1
- package/lib/assertions/visualSteps.js +178 -45
- package/lib/custom_setups/loginHooks.js +19 -2
- package/lib/helpers/world.d.ts +3 -0
- package/lib/helpers/world.js +11 -5
- package/lib/index.d.ts +3 -21
- package/lib/index.js +3 -23
- package/package.json +9 -2
- package/src/actions/clickSteps.ts +364 -142
- package/src/actions/cookieSteps.ts +66 -0
- package/src/actions/debugSteps.ts +17 -3
- package/src/actions/elementFindSteps.ts +822 -117
- package/src/actions/fillFormSteps.ts +234 -177
- package/src/actions/index.ts +12 -0
- package/src/actions/inputSteps.ts +318 -82
- package/src/actions/interceptionSteps.ts +295 -57
- package/src/actions/miscSteps.ts +984 -254
- package/src/actions/mouseSteps.ts +212 -55
- package/src/actions/scrollSteps.ts +114 -16
- package/src/actions/storageSteps.ts +267 -42
- package/src/assertions/buttonAndTextVisibilitySteps.ts +353 -95
- package/src/assertions/cookieSteps.ts +115 -36
- package/src/assertions/elementSteps.ts +414 -85
- package/src/assertions/formInputSteps.ts +375 -108
- package/src/assertions/index.ts +11 -0
- package/src/assertions/interceptionRequestsSteps.ts +619 -195
- package/src/assertions/locationSteps.ts +280 -64
- package/src/assertions/roleTestIdSteps.ts +244 -26
- package/src/assertions/semanticSteps.ts +257 -69
- package/src/assertions/storageSteps.ts +234 -73
- package/src/assertions/visualSteps.ts +245 -68
- package/src/custom_setups/loginHooks.ts +21 -2
- package/src/helpers/world.ts +30 -4
- package/src/index.ts +4 -25
|
@@ -6,76 +6,339 @@ import { CustomWorld } from "../helpers/world";
|
|
|
6
6
|
// WHEN I FIND ELEMENT(S)
|
|
7
7
|
// =============================
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Finds an element by CSS selector and stores it as the current element.
|
|
11
|
+
*
|
|
12
|
+
* ```gherkin
|
|
13
|
+
* When I find element by selector {string}
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* When I find element by selector ".my-class"
|
|
18
|
+
*
|
|
19
|
+
* @remarks
|
|
20
|
+
* This step sets the {@link CustomWorld.element | current element} in the test context.
|
|
21
|
+
* Subsequent steps can then interact with this single element. An `expect` assertion is included
|
|
22
|
+
* to ensure exactly one element is found.
|
|
23
|
+
*/
|
|
24
|
+
export async function When_I_find_element_by_selector(this: CustomWorld, selector: string) {
|
|
10
25
|
this.element = this.page.locator(selector);
|
|
11
26
|
await expect(this.element).toHaveCount(1);
|
|
12
|
-
}
|
|
13
|
-
When("I find
|
|
27
|
+
}
|
|
28
|
+
When("I find element by selector {string}", When_I_find_element_by_selector);
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Finds a link by its text and stores it as the current locator.
|
|
32
|
+
*
|
|
33
|
+
* ```gherkin
|
|
34
|
+
* When I find link by text {string}
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* When I find link by text "Home"
|
|
39
|
+
*
|
|
40
|
+
* @remarks
|
|
41
|
+
* This step sets the {@link CustomWorld.currentLocator | currentLocator} in the test context,
|
|
42
|
+
* allowing subsequent steps to operate on the found link. For example:
|
|
43
|
+
*
|
|
44
|
+
* ```gherkin
|
|
45
|
+
* When I find link by text "Products"
|
|
46
|
+
* And I click current element
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export async function When_I_find_link_by_text(this: CustomWorld, text: string) {
|
|
14
50
|
this.currentLocator = this.getScope().getByRole("link", { name: text });
|
|
15
|
-
}
|
|
51
|
+
}
|
|
52
|
+
When("I find link by text {string}", When_I_find_link_by_text);
|
|
16
53
|
|
|
17
|
-
|
|
54
|
+
/**
|
|
55
|
+
* Finds a heading by its text and stores it as the current locator.
|
|
56
|
+
*
|
|
57
|
+
* ```gherkin
|
|
58
|
+
* When I find heading by text {string}
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* When I find heading by text "Welcome"
|
|
63
|
+
*
|
|
64
|
+
* @remarks
|
|
65
|
+
* This step sets the {@link CustomWorld.currentLocator | currentLocator} in the test context,
|
|
66
|
+
* allowing subsequent steps to operate on the found heading.
|
|
67
|
+
*/
|
|
68
|
+
export async function When_I_find_heading_by_text(this: CustomWorld, text: string) {
|
|
18
69
|
this.currentLocator = this.getScope().getByRole("heading", { name: text });
|
|
19
|
-
}
|
|
70
|
+
}
|
|
71
|
+
When("I find heading by text {string}", When_I_find_heading_by_text);
|
|
20
72
|
|
|
21
|
-
|
|
73
|
+
/**
|
|
74
|
+
* Finds all headings by text and stores them as the current locator.
|
|
75
|
+
*
|
|
76
|
+
* ```gherkin
|
|
77
|
+
* When I find headings by text {string}
|
|
78
|
+
* ```
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* When I find headings by text "Section"
|
|
82
|
+
*
|
|
83
|
+
* @remarks
|
|
84
|
+
* This step sets the {@link CustomWorld.currentLocator | currentLocator} in the test context
|
|
85
|
+
* to a locator that matches *all* headings with the specified text. This is useful for
|
|
86
|
+
* verifying multiple instances or iterating.
|
|
87
|
+
*/
|
|
88
|
+
export async function When_I_find_headings_by_text(this: CustomWorld, text: string) {
|
|
22
89
|
this.currentLocator = this.getScope().getByRole("heading", { name: text });
|
|
23
|
-
}
|
|
24
|
-
When("I find
|
|
90
|
+
}
|
|
91
|
+
When("I find headings by text {string}", When_I_find_headings_by_text);
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Finds all elements by CSS selector and stores them.
|
|
95
|
+
*
|
|
96
|
+
* ```gherkin
|
|
97
|
+
* When I find elements by selector {string}
|
|
98
|
+
* ```
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* When I find elements by selector ".item"
|
|
102
|
+
*
|
|
103
|
+
* @remarks
|
|
104
|
+
* This step sets the {@link CustomWorld.elements | elements} property in the test context
|
|
105
|
+
* to a Playwright `Locator` representing all matching elements. You can then use steps like
|
|
106
|
+
* "When I get first element" to pick a specific one.
|
|
107
|
+
*/
|
|
108
|
+
export async function When_I_find_elements_by_selector(this: CustomWorld, selector: string) {
|
|
25
109
|
this.elements = this.page.locator(selector);
|
|
26
110
|
const count = await this.elements.count();
|
|
27
111
|
this.log?.(`Found ${count} elements with selector ${selector}`);
|
|
28
|
-
}
|
|
112
|
+
}
|
|
113
|
+
When("I find elements by selector {string}", When_I_find_elements_by_selector);
|
|
29
114
|
|
|
30
|
-
|
|
115
|
+
/**
|
|
116
|
+
* Finds an element by its exact text and stores it as the current element.
|
|
117
|
+
*
|
|
118
|
+
* ```gherkin
|
|
119
|
+
* When I find element by text {string}
|
|
120
|
+
* ```
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* When I find element by text "Submit"
|
|
124
|
+
*
|
|
125
|
+
* @remarks
|
|
126
|
+
* This step uses `page.getByText` with `exact: true` to find an element
|
|
127
|
+
* that matches the text precisely. It stores the result in {@link CustomWorld.element | this.element}.
|
|
128
|
+
* An `expect` assertion is included to ensure exactly one element is found.
|
|
129
|
+
*/
|
|
130
|
+
export async function When_I_find_element_by_text(this: CustomWorld, text: string) {
|
|
31
131
|
this.element = this.page.getByText(text, { exact: true });
|
|
32
132
|
await expect(this.element).toHaveCount(1);
|
|
33
|
-
}
|
|
133
|
+
}
|
|
134
|
+
When("I find element by text {string}", When_I_find_element_by_text);
|
|
34
135
|
|
|
35
|
-
|
|
136
|
+
/**
|
|
137
|
+
* Finds an element by its title attribute and stores it as the current element.
|
|
138
|
+
*
|
|
139
|
+
* ```gherkin
|
|
140
|
+
* When I find element by title {string}
|
|
141
|
+
* ```
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* When I find element by title "Tooltip"
|
|
145
|
+
*
|
|
146
|
+
* @remarks
|
|
147
|
+
* This step uses `page.getByTitle` to find an element with the specified `title` attribute.
|
|
148
|
+
* It stores the result in {@link CustomWorld.element | this.element}.
|
|
149
|
+
* An `expect` assertion is included to ensure exactly one element is found.
|
|
150
|
+
*/
|
|
151
|
+
export async function When_I_find_element_by_title(this: CustomWorld, title: string) {
|
|
36
152
|
this.element = this.page.getByTitle(title);
|
|
37
153
|
await expect(this.element).toHaveCount(1);
|
|
38
|
-
}
|
|
154
|
+
}
|
|
155
|
+
When("I find element by title {string}", When_I_find_element_by_title);
|
|
39
156
|
|
|
40
|
-
|
|
157
|
+
/**
|
|
158
|
+
* Finds an element by its test id and stores it as the current element.
|
|
159
|
+
*
|
|
160
|
+
* ```gherkin
|
|
161
|
+
* When I find element by testid {string}
|
|
162
|
+
* ```
|
|
163
|
+
*
|
|
164
|
+
* @example
|
|
165
|
+
* When I find element by testid "main-content"
|
|
166
|
+
*
|
|
167
|
+
* @remarks
|
|
168
|
+
* This step uses `page.getByTestId` to find an element based on its
|
|
169
|
+
* `data-testid` attribute (or configured test ID attribute).
|
|
170
|
+
* It stores the result in {@link CustomWorld.element | this.element}.
|
|
171
|
+
* An `expect` assertion is included to ensure exactly one element is found.
|
|
172
|
+
*/
|
|
173
|
+
export async function When_I_find_element_by_testid(this: CustomWorld, testid: string) {
|
|
41
174
|
this.element = this.page.getByTestId(testid);
|
|
42
175
|
await expect(this.element).toHaveCount(1);
|
|
43
|
-
}
|
|
176
|
+
}
|
|
177
|
+
When("I find element by testid {string}", When_I_find_element_by_testid);
|
|
44
178
|
|
|
45
|
-
|
|
179
|
+
/**
|
|
180
|
+
* Finds an element by its role and stores it as the current element.
|
|
181
|
+
*
|
|
182
|
+
* ```gherkin
|
|
183
|
+
* When I find element by role {string}
|
|
184
|
+
* ```
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
* When I find element by role "button"
|
|
188
|
+
*
|
|
189
|
+
* @remarks
|
|
190
|
+
* This step uses `page.getByRole` to find an element based on its
|
|
191
|
+
* ARIA role. It stores the result in {@link CustomWorld.element | this.element}.
|
|
192
|
+
* An `expect` assertion is included to ensure exactly one element is found.
|
|
193
|
+
*/
|
|
194
|
+
export async function When_I_find_element_by_role(this: CustomWorld, role: string) {
|
|
46
195
|
this.element = this.page.getByRole(role as any);
|
|
47
196
|
await expect(this.element).toHaveCount(1);
|
|
48
|
-
}
|
|
197
|
+
}
|
|
198
|
+
When("I find element by role {string}", When_I_find_element_by_role);
|
|
49
199
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
200
|
+
/**
|
|
201
|
+
* Finds an element by its placeholder text and stores it as the current element.
|
|
202
|
+
*
|
|
203
|
+
* ```gherkin
|
|
204
|
+
* When I find element by placeholder text {string}
|
|
205
|
+
* ```
|
|
206
|
+
*
|
|
207
|
+
* @example
|
|
208
|
+
* When I find element by placeholder text "Enter your name"
|
|
209
|
+
*
|
|
210
|
+
* @remarks
|
|
211
|
+
* This step uses `page.getByPlaceholder` to find an input or textarea element
|
|
212
|
+
* based on its `placeholder` attribute. It stores the result in {@link CustomWorld.element | this.element}.
|
|
213
|
+
* An `expect` assertion is included to ensure exactly one element is found.
|
|
214
|
+
*/
|
|
215
|
+
export async function When_I_find_element_by_placeholder_text(this: CustomWorld, text: string) {
|
|
216
|
+
this.element = this.page.getByPlaceholder(text);
|
|
217
|
+
await expect(this.element).toHaveCount(1);
|
|
218
|
+
}
|
|
219
|
+
When("I find element by placeholder text {string}", When_I_find_element_by_placeholder_text);
|
|
57
220
|
|
|
58
|
-
|
|
221
|
+
/**
|
|
222
|
+
* Finds an element by its label text and stores it as the current element.
|
|
223
|
+
*
|
|
224
|
+
* ```gherkin
|
|
225
|
+
* When I find element by label text {string}
|
|
226
|
+
* ```
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* When I find element by label text "Username"
|
|
230
|
+
*
|
|
231
|
+
* @remarks
|
|
232
|
+
* This step uses `page.getByLabel` to find an element associated with a given
|
|
233
|
+
* label text (e.g., using a `<label for="...">` or wrapping the input).
|
|
234
|
+
* It stores the result in {@link CustomWorld.element | this.element}.
|
|
235
|
+
* An `expect` assertion is included to ensure exactly one element is found.
|
|
236
|
+
*/
|
|
237
|
+
export async function When_I_find_element_by_label_text(this: CustomWorld, label: string) {
|
|
59
238
|
this.element = this.page.getByLabel(label);
|
|
60
239
|
await expect(this.element).toHaveCount(1);
|
|
61
|
-
}
|
|
62
|
-
When("I find
|
|
240
|
+
}
|
|
241
|
+
When("I find element by label text {string}", When_I_find_element_by_label_text);
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Finds all elements by label text and stores them as the current locator.
|
|
245
|
+
*
|
|
246
|
+
* ```gherkin
|
|
247
|
+
* When I find elements by label text {string}
|
|
248
|
+
* ```
|
|
249
|
+
*
|
|
250
|
+
* @example
|
|
251
|
+
* When I find elements by label text "Username"
|
|
252
|
+
*
|
|
253
|
+
* @remarks
|
|
254
|
+
* This step sets the {@link CustomWorld.currentLocator | currentLocator} to a locator
|
|
255
|
+
* representing all elements associated with the given label text. This is useful
|
|
256
|
+
* for scenarios where multiple inputs might share a similar label.
|
|
257
|
+
*/
|
|
258
|
+
export async function When_I_find_elements_by_label_text(this: CustomWorld, label: string) {
|
|
63
259
|
this.currentLocator = this.getScope().getByLabel(label);
|
|
64
|
-
}
|
|
65
|
-
When("I find
|
|
260
|
+
}
|
|
261
|
+
When("I find elements by label text {string}", When_I_find_elements_by_label_text);
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Finds an element by its alt text and stores it as the current element.
|
|
265
|
+
*
|
|
266
|
+
* ```gherkin
|
|
267
|
+
* When I find element by alt text {string}
|
|
268
|
+
* ```
|
|
269
|
+
*
|
|
270
|
+
* @example
|
|
271
|
+
* When I find element by alt text "Logo"
|
|
272
|
+
*
|
|
273
|
+
* @remarks
|
|
274
|
+
* This step uses `page.getByAltText` to find elements, typically images,
|
|
275
|
+
* based on their `alt` attribute. It stores the result in {@link CustomWorld.element | this.element}.
|
|
276
|
+
* An `expect` assertion is included to ensure exactly one element is found.
|
|
277
|
+
*/
|
|
278
|
+
export async function When_I_find_element_by_alt_text(this: CustomWorld, alt: string) {
|
|
66
279
|
this.element = this.page.getByAltText(alt);
|
|
67
280
|
await expect(this.element).toHaveCount(1);
|
|
68
|
-
}
|
|
281
|
+
}
|
|
282
|
+
When("I find element by alt text {string}", When_I_find_element_by_alt_text);
|
|
69
283
|
|
|
70
|
-
|
|
284
|
+
/**
|
|
285
|
+
* Finds an input element by its name attribute and stores it as the current element.
|
|
286
|
+
*
|
|
287
|
+
* ```gherkin
|
|
288
|
+
* When I find element by name {string}
|
|
289
|
+
* ```
|
|
290
|
+
*
|
|
291
|
+
* @example
|
|
292
|
+
* When I find element by name "email"
|
|
293
|
+
*
|
|
294
|
+
* @remarks
|
|
295
|
+
* This step uses `page.getByRole("textbox", { name })` to specifically find an input
|
|
296
|
+
* element (or similar interactive element) with the given `name` attribute.
|
|
297
|
+
* It stores the result in {@link CustomWorld.element | this.element}.
|
|
298
|
+
* An `expect` assertion is included to ensure exactly one element is found.
|
|
299
|
+
*/
|
|
300
|
+
export async function When_I_find_element_by_name(this: CustomWorld, name: string) {
|
|
71
301
|
this.element = this.page.getByRole("textbox", { name });
|
|
72
302
|
await expect(this.element).toHaveCount(1);
|
|
73
|
-
}
|
|
74
|
-
When("I find
|
|
303
|
+
}
|
|
304
|
+
When("I find element by name {string}", When_I_find_element_by_name);
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Finds all elements by name attribute and stores them as the current locator.
|
|
308
|
+
*
|
|
309
|
+
* ```gherkin
|
|
310
|
+
* When I find elements by name {string}
|
|
311
|
+
* ```
|
|
312
|
+
*
|
|
313
|
+
* @example
|
|
314
|
+
* When I find elements by name "email"
|
|
315
|
+
*
|
|
316
|
+
* @remarks
|
|
317
|
+
* This step sets the {@link CustomWorld.currentLocator | currentLocator} to a CSS locator
|
|
318
|
+
* targeting all elements with the specified `name` attribute.
|
|
319
|
+
*/
|
|
320
|
+
export async function When_I_find_elements_by_name(this: CustomWorld, name: string) {
|
|
75
321
|
this.currentLocator = this.getScope().locator(`[name="${name}"]`);
|
|
76
|
-
}
|
|
322
|
+
}
|
|
323
|
+
When("I find elements by name {string}", When_I_find_elements_by_name);
|
|
77
324
|
|
|
78
|
-
|
|
325
|
+
/**
|
|
326
|
+
* Finds all buttons by text (supports alias) and stores them as elements.
|
|
327
|
+
*
|
|
328
|
+
* ```gherkin
|
|
329
|
+
* When I find buttons by text {string}
|
|
330
|
+
* ```
|
|
331
|
+
*
|
|
332
|
+
* @example
|
|
333
|
+
* When I find buttons by text "Save"
|
|
334
|
+
* When I find buttons by text "@buttonAlias"
|
|
335
|
+
*
|
|
336
|
+
* @remarks
|
|
337
|
+
* This step uses `page.getByRole("button", { name })` to find all buttons
|
|
338
|
+
* matching the provided text. It supports resolving an alias from `this.data`.
|
|
339
|
+
* The result is stored in {@link CustomWorld.elements | this.elements}.
|
|
340
|
+
*/
|
|
341
|
+
export async function When_I_find_buttons_by_text(this: CustomWorld, buttonText: string) {
|
|
79
342
|
// 🧠 Resolve alias
|
|
80
343
|
if (buttonText.startsWith("@")) {
|
|
81
344
|
const alias = buttonText.slice(1);
|
|
@@ -92,143 +355,565 @@ When("I find buttons by text {string}", async function (this: CustomWorld, butto
|
|
|
92
355
|
});
|
|
93
356
|
|
|
94
357
|
this.log?.(`🔘 Stored all buttons matching text "${buttonText}"`);
|
|
95
|
-
}
|
|
358
|
+
}
|
|
359
|
+
When("I find buttons by text {string}", When_I_find_buttons_by_text);
|
|
360
|
+
|
|
96
361
|
// =============================
|
|
97
362
|
// WHEN I GET ELEMENT(S)
|
|
98
363
|
// =============================
|
|
99
364
|
|
|
100
|
-
|
|
365
|
+
/**
|
|
366
|
+
* Gets the first element matching the selector and stores it as the current element.
|
|
367
|
+
*
|
|
368
|
+
* ```gherkin
|
|
369
|
+
* When I get element by selector {string}
|
|
370
|
+
* ```
|
|
371
|
+
*
|
|
372
|
+
* @example
|
|
373
|
+
* When I get element by selector ".item"
|
|
374
|
+
*
|
|
375
|
+
* @remarks
|
|
376
|
+
* This step targets a single element using a CSS selector and sets it as the
|
|
377
|
+
* {@link CustomWorld.element | current element}. It's useful when you expect only
|
|
378
|
+
* one element to match or you only need the first one.
|
|
379
|
+
*/
|
|
380
|
+
export async function When_I_get_element_by_selector(this: CustomWorld, selector: string) {
|
|
101
381
|
this.element = this.page.locator(selector).first();
|
|
102
|
-
}
|
|
382
|
+
}
|
|
383
|
+
When("I get element by selector {string}", When_I_get_element_by_selector);
|
|
103
384
|
|
|
104
|
-
|
|
385
|
+
/**
|
|
386
|
+
* Gets all elements matching the selector and stores them.
|
|
387
|
+
*
|
|
388
|
+
* ```gherkin
|
|
389
|
+
* When I get elements by selector {string}
|
|
390
|
+
* ```
|
|
391
|
+
*
|
|
392
|
+
* @example
|
|
393
|
+
* When I get elements by selector ".item"
|
|
394
|
+
*
|
|
395
|
+
* @remarks
|
|
396
|
+
* This step sets the {@link CustomWorld.elements | elements} property to a
|
|
397
|
+
* Playwright `Locator` representing all elements that match the given CSS selector.
|
|
398
|
+
* You can then use other steps like "When I get first element" to work with specific items.
|
|
399
|
+
*/
|
|
400
|
+
export async function When_I_get_elements_by_selector(this: CustomWorld, selector: string) {
|
|
105
401
|
this.elements = this.page.locator(selector);
|
|
106
|
-
}
|
|
402
|
+
}
|
|
403
|
+
When("I get elements by selector {string}", When_I_get_elements_by_selector);
|
|
107
404
|
|
|
108
|
-
|
|
109
|
-
|
|
405
|
+
/**
|
|
406
|
+
* Gets the first element from the stored elements collection.
|
|
407
|
+
*
|
|
408
|
+
* ```gherkin
|
|
409
|
+
* When I get first element
|
|
410
|
+
* ```
|
|
411
|
+
*
|
|
412
|
+
* @example
|
|
413
|
+
* When I get first element
|
|
414
|
+
*
|
|
415
|
+
* @remarks
|
|
416
|
+
* This step requires a preceding step that populates {@link CustomWorld.elements | this.elements}
|
|
417
|
+
* (e.g., "When I find elements by selector"). It then selects the very first
|
|
418
|
+
* element from that collection and sets it as the {@link CustomWorld.element | current element}.
|
|
419
|
+
*/
|
|
420
|
+
export async function When_I_get_first_element(this: CustomWorld) {
|
|
421
|
+
if (!this.elements)
|
|
422
|
+
throw new Error("No element collection found. Use a 'find elements' step first.");
|
|
110
423
|
this.element = this.elements.first();
|
|
111
|
-
}
|
|
424
|
+
}
|
|
425
|
+
When("I get first element", When_I_get_first_element);
|
|
112
426
|
|
|
113
|
-
|
|
114
|
-
|
|
427
|
+
/**
|
|
428
|
+
* Gets the last element from the stored elements collection.
|
|
429
|
+
*
|
|
430
|
+
* ```gherkin
|
|
431
|
+
* When I get last element
|
|
432
|
+
* ```
|
|
433
|
+
*
|
|
434
|
+
* @example
|
|
435
|
+
* When I get last element
|
|
436
|
+
*
|
|
437
|
+
* @remarks
|
|
438
|
+
* This step requires a preceding step that populates {@link CustomWorld.elements | this.elements}
|
|
439
|
+
* (e.g., "When I find elements by selector"). It then selects the very last
|
|
440
|
+
* element from that collection and sets it as the {@link CustomWorld.element | current element}.
|
|
441
|
+
*/
|
|
442
|
+
export async function When_I_get_last_element(this: CustomWorld) {
|
|
443
|
+
if (!this.elements)
|
|
444
|
+
throw new Error("No element collection found. Use a 'find elements' step first.");
|
|
115
445
|
this.element = this.elements.last();
|
|
116
|
-
}
|
|
446
|
+
}
|
|
447
|
+
When("I get last element", When_I_get_last_element);
|
|
117
448
|
|
|
118
|
-
|
|
119
|
-
|
|
449
|
+
/**
|
|
450
|
+
* Gets the nth element (1-based index) from the stored elements.
|
|
451
|
+
*
|
|
452
|
+
* ```gherkin
|
|
453
|
+
* When I get {int}st element
|
|
454
|
+
* When I get {int}nd element
|
|
455
|
+
* When I get {int}rd element
|
|
456
|
+
* When I get {int}th element
|
|
457
|
+
* ```
|
|
458
|
+
*
|
|
459
|
+
* @example
|
|
460
|
+
* When I get 2nd element
|
|
461
|
+
*
|
|
462
|
+
* @remarks
|
|
463
|
+
* This step requires a preceding step that populates {@link CustomWorld.elements | this.elements}
|
|
464
|
+
* (e.g., "When I find elements by selector"). It then selects the element at the
|
|
465
|
+
* specified 1-based index from that collection and sets it as the {@link CustomWorld.element | current element}.
|
|
466
|
+
* Error handling is included for out-of-bounds indices.
|
|
467
|
+
*/
|
|
468
|
+
export async function When_I_get_nth_element(this: CustomWorld, index: number) {
|
|
469
|
+
if (!this.elements)
|
|
470
|
+
throw new Error("No elements stored to pick from. Use a 'find elements' step first.");
|
|
120
471
|
const count = await this.elements.count();
|
|
121
472
|
if (index < 1 || index > count) {
|
|
122
|
-
throw new Error(`Cannot get element ${index} — only ${count} found
|
|
473
|
+
throw new Error(`Cannot get element ${index} — only ${count} found.`);
|
|
123
474
|
}
|
|
124
|
-
this.element = this.elements.nth(index - 1);
|
|
475
|
+
this.element = this.elements.nth(index - 1); // Playwright is 0-based
|
|
125
476
|
this.log?.(`Selected ${index} element from stored elements`);
|
|
126
|
-
}
|
|
477
|
+
}
|
|
478
|
+
When(/^I get (\d+)(?:st|nd|rd|th) element$/, When_I_get_nth_element);
|
|
127
479
|
|
|
128
|
-
|
|
480
|
+
/**
|
|
481
|
+
* Finds all elements by role and stores them in the elements collection.
|
|
482
|
+
*
|
|
483
|
+
* ```gherkin
|
|
484
|
+
* When I find elements by role {string}
|
|
485
|
+
* ```
|
|
486
|
+
*
|
|
487
|
+
* @example
|
|
488
|
+
* When I find elements by role "button"
|
|
489
|
+
*
|
|
490
|
+
* @remarks
|
|
491
|
+
* This step uses `page.getByRole` to find all elements with a specific ARIA role
|
|
492
|
+
* and stores them in {@link CustomWorld.elements | this.elements}.
|
|
493
|
+
* It includes a check to ensure at least one element is found.
|
|
494
|
+
*/
|
|
495
|
+
export async function When_I_find_elements_by_role(this: CustomWorld, role: string) {
|
|
129
496
|
const locator = this.page.getByRole(role as any);
|
|
130
497
|
const count = await locator.count();
|
|
131
498
|
|
|
132
499
|
if (count === 0) {
|
|
133
|
-
throw new Error(`No elements found with role "${role}"
|
|
500
|
+
throw new Error(`No elements found with role "${role}".`);
|
|
134
501
|
}
|
|
135
502
|
|
|
136
503
|
this.elements = locator;
|
|
137
504
|
this.log?.(`Stored ${count} elements with role "${role}"`);
|
|
138
|
-
}
|
|
505
|
+
}
|
|
506
|
+
When("I find elements by role {string}", When_I_find_elements_by_role);
|
|
139
507
|
|
|
140
|
-
|
|
141
|
-
|
|
508
|
+
/**
|
|
509
|
+
* Gets the nth element (0-based index) from the stored elements.
|
|
510
|
+
*
|
|
511
|
+
* ```gherkin
|
|
512
|
+
* When I get {int}rd element
|
|
513
|
+
* ```
|
|
514
|
+
*
|
|
515
|
+
* @example
|
|
516
|
+
* When I get 3rd element
|
|
517
|
+
*
|
|
518
|
+
* @remarks
|
|
519
|
+
* This step requires a preceding step that populates {@link CustomWorld.elements | this.elements}.
|
|
520
|
+
* It selects the element at the specified **0-based index** from the collection
|
|
521
|
+
* and sets it as the {@link CustomWorld.element | current element}.
|
|
522
|
+
*
|
|
523
|
+
* **Note:** Consider using `When I get {int}(?:st|nd|rd|th) element` for a 1-based index
|
|
524
|
+
* which is often more user-friendly in Gherkin.
|
|
525
|
+
*/
|
|
526
|
+
export async function When_I_get_int_rd_element(this: CustomWorld, index: number) {
|
|
527
|
+
if (!this.elements)
|
|
528
|
+
throw new Error("No element collection found. Use a 'find elements' step first.");
|
|
142
529
|
this.element = this.elements.nth(index);
|
|
143
|
-
}
|
|
530
|
+
}
|
|
531
|
+
When("I get {int}rd element", When_I_get_int_rd_element); // This step pattern is a bit specific; the regex-based one is more general.
|
|
144
532
|
|
|
145
|
-
|
|
533
|
+
/**
|
|
534
|
+
* Gets the currently focused element and stores it as the current element.
|
|
535
|
+
*
|
|
536
|
+
* ```gherkin
|
|
537
|
+
* When I get focused element
|
|
538
|
+
* ```
|
|
539
|
+
*
|
|
540
|
+
* @example
|
|
541
|
+
* When I get focused element
|
|
542
|
+
*
|
|
543
|
+
* @remarks
|
|
544
|
+
* This step uses `page.evaluateHandle` to find the `document.activeElement`
|
|
545
|
+
* (the currently focused element in the browser DOM) and sets it as the
|
|
546
|
+
* {@link CustomWorld.element | current element}. This is useful for testing focus management.
|
|
547
|
+
*/
|
|
548
|
+
export async function When_I_get_focused_element(this: CustomWorld) {
|
|
146
549
|
this.element = (await this.page.evaluateHandle(
|
|
147
550
|
() => document.activeElement
|
|
148
551
|
)) as unknown as Locator;
|
|
149
|
-
}
|
|
150
|
-
When("I
|
|
552
|
+
}
|
|
553
|
+
When("I get focused element", When_I_get_focused_element);
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* Stores the text content of the current element as an alias in the test data.
|
|
557
|
+
*
|
|
558
|
+
* ```gherkin
|
|
559
|
+
* When I store element text as {string}
|
|
560
|
+
* ```
|
|
561
|
+
*
|
|
562
|
+
* @example
|
|
563
|
+
* When I store element text as "greeting"
|
|
564
|
+
*
|
|
565
|
+
* @remarks
|
|
566
|
+
* This step requires a preceding step that sets the {@link CustomWorld.element | current element}.
|
|
567
|
+
* It retrieves the `textContent` of that element and stores it in
|
|
568
|
+
* {@link CustomWorld.data | this.data} under the provided alias, allowing it to be
|
|
569
|
+
* reused in subsequent steps (e.g., in assertions or input fields).
|
|
570
|
+
*/
|
|
571
|
+
export async function When_I_store_element_text_as(this: CustomWorld, alias: string) {
|
|
151
572
|
const element = this.element;
|
|
152
|
-
if (!element) throw new Error("No element selected");
|
|
573
|
+
if (!element) throw new Error("No element selected. Use a 'find element' step first.");
|
|
153
574
|
const text = await element.textContent();
|
|
154
575
|
this.data[alias] = text?.trim();
|
|
155
576
|
this.log?.(`Stored text "${text}" as "${alias}"`);
|
|
156
|
-
}
|
|
157
|
-
When("I
|
|
577
|
+
}
|
|
578
|
+
When("I store element text as {string}", When_I_store_element_text_as);
|
|
579
|
+
|
|
580
|
+
// =============================
|
|
581
|
+
// WHEN I FIND TEXTAREA(S)
|
|
582
|
+
// =============================
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Finds a textarea by its label text and stores it as the current element.
|
|
586
|
+
*
|
|
587
|
+
* ```gherkin
|
|
588
|
+
* When I find textarea by label text {string}
|
|
589
|
+
* ```
|
|
590
|
+
*
|
|
591
|
+
* @example
|
|
592
|
+
* When I find textarea by label text "Description"
|
|
593
|
+
*
|
|
594
|
+
* @remarks
|
|
595
|
+
* This step uses Playwright's `getByLabel` to locate a textarea associated
|
|
596
|
+
* with the given label text. It sets the found textarea as the
|
|
597
|
+
* {@link CustomWorld.element | current element}.
|
|
598
|
+
*/
|
|
599
|
+
export async function When_I_find_textarea_by_label_text(this: CustomWorld, label: string) {
|
|
158
600
|
this.element = this.page.getByLabel(label);
|
|
159
601
|
this.log?.(`Stored textarea with label "${label}"`);
|
|
160
|
-
}
|
|
161
|
-
When(
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
602
|
+
}
|
|
603
|
+
When("I find textarea by label text {string}", When_I_find_textarea_by_label_text);
|
|
604
|
+
|
|
605
|
+
/**
|
|
606
|
+
* Finds a textarea by its placeholder text and stores it as the current element.
|
|
607
|
+
*
|
|
608
|
+
* ```gherkin
|
|
609
|
+
* When I find textarea by placeholder text {string}
|
|
610
|
+
* ```
|
|
611
|
+
*
|
|
612
|
+
* @example
|
|
613
|
+
* When I find textarea by placeholder text "Type here"
|
|
614
|
+
*
|
|
615
|
+
* @remarks
|
|
616
|
+
* This step uses Playwright's `getByPlaceholder` to locate a textarea
|
|
617
|
+
* based on its `placeholder` attribute. It sets the found textarea as the
|
|
618
|
+
* {@link CustomWorld.element | current element}.
|
|
619
|
+
*/
|
|
620
|
+
export async function When_I_find_textarea_by_placeholder_text(
|
|
621
|
+
this: CustomWorld,
|
|
622
|
+
placeholder: string
|
|
623
|
+
) {
|
|
624
|
+
this.element = this.page.getByPlaceholder(placeholder);
|
|
625
|
+
this.log?.(`Stored textarea with placeholder "${placeholder}"`);
|
|
626
|
+
}
|
|
627
|
+
When("I find textarea by placeholder text {string}", When_I_find_textarea_by_placeholder_text);
|
|
628
|
+
|
|
629
|
+
/**
|
|
630
|
+
* Finds all textareas by label text and stores them as elements.
|
|
631
|
+
*
|
|
632
|
+
* ```gherkin
|
|
633
|
+
* When I find textareas by label text {string}
|
|
634
|
+
* ```
|
|
635
|
+
*
|
|
636
|
+
* @example
|
|
637
|
+
* When I find textareas by label text "Comment"
|
|
638
|
+
*
|
|
639
|
+
* @remarks
|
|
640
|
+
* This step uses a CSS selector to find all textareas associated with the
|
|
641
|
+
* given label text and stores them in the {@link CustomWorld.elements | elements}
|
|
642
|
+
* collection.
|
|
643
|
+
*/
|
|
644
|
+
export async function When_I_find_textareas_by_label_text(this: CustomWorld, label: string) {
|
|
169
645
|
this.elements = this.page.locator(`label:has-text("${label}") + textarea`);
|
|
170
646
|
this.log?.(`Stored multiple textareas with label "${label}"`);
|
|
171
|
-
}
|
|
172
|
-
When("I find
|
|
647
|
+
}
|
|
648
|
+
When("I find textareas by label text {string}", When_I_find_textareas_by_label_text);
|
|
649
|
+
|
|
650
|
+
/**
|
|
651
|
+
* Finds a textarea by its name attribute and stores it as the current element.
|
|
652
|
+
*
|
|
653
|
+
* ```gherkin
|
|
654
|
+
* When I find textarea by name {string}
|
|
655
|
+
* ```
|
|
656
|
+
*
|
|
657
|
+
* @example
|
|
658
|
+
* When I find textarea by name "bio"
|
|
659
|
+
*
|
|
660
|
+
* @remarks
|
|
661
|
+
* This step uses a CSS selector to locate a textarea based on its `name` attribute.
|
|
662
|
+
* It sets the found textarea as the {@link CustomWorld.element | current element}.
|
|
663
|
+
*/
|
|
664
|
+
export async function When_I_find_textarea_by_name(this: CustomWorld, name: string) {
|
|
173
665
|
this.element = this.page.locator(`textarea[name="${name}"]`);
|
|
174
666
|
this.log?.(`Stored textarea with name "${name}"`);
|
|
175
|
-
}
|
|
176
|
-
When("I find
|
|
667
|
+
}
|
|
668
|
+
When("I find textarea by name {string}", When_I_find_textarea_by_name);
|
|
669
|
+
|
|
670
|
+
/**
|
|
671
|
+
* Finds all textareas by ID and stores them as elements.
|
|
672
|
+
*
|
|
673
|
+
* ```gherkin
|
|
674
|
+
* When I find textareas by ID {string}
|
|
675
|
+
* ```
|
|
676
|
+
*
|
|
677
|
+
* @example
|
|
678
|
+
* When I find textareas by ID "my-textarea"
|
|
679
|
+
*
|
|
680
|
+
* @remarks
|
|
681
|
+
* This step uses a CSS selector to find all textareas with the specified ID
|
|
682
|
+
* and stores them in the {@link CustomWorld.elements | elements} collection.
|
|
683
|
+
*/
|
|
684
|
+
export async function When_I_find_textareas_by_ID(this: CustomWorld, id: string) {
|
|
177
685
|
this.elements = this.page.locator(`textarea#${id}`);
|
|
178
686
|
this.log?.(`Stored multiple textareas with ID "${id}"`);
|
|
179
|
-
}
|
|
180
|
-
When("I find
|
|
687
|
+
}
|
|
688
|
+
When("I find textareas by ID {string}", When_I_find_textareas_by_ID);
|
|
689
|
+
|
|
690
|
+
/**
|
|
691
|
+
* Finds all textareas by placeholder text and stores them as elements.
|
|
692
|
+
*
|
|
693
|
+
* ```gherkin
|
|
694
|
+
* When I find textareas by placeholder text {string}
|
|
695
|
+
* ```
|
|
696
|
+
*
|
|
697
|
+
* @example
|
|
698
|
+
* When I find textareas by placeholder text "Type here"
|
|
699
|
+
*
|
|
700
|
+
* @remarks
|
|
701
|
+
* This step uses a CSS selector to find all textareas with the specified
|
|
702
|
+
* `placeholder` attribute and stores them in the {@link CustomWorld.elements | elements}
|
|
703
|
+
* collection.
|
|
704
|
+
*/
|
|
705
|
+
export async function When_I_find_textareas_by_placeholder_text_multiple(
|
|
706
|
+
this: CustomWorld,
|
|
707
|
+
placeholder: string
|
|
708
|
+
) {
|
|
709
|
+
this.elements = this.page.locator(`textarea[placeholder="${placeholder}"]`);
|
|
710
|
+
this.log?.(`Stored multiple textareas with placeholder "${placeholder}"`);
|
|
711
|
+
}
|
|
712
|
+
When(
|
|
713
|
+
"I find textareas by placeholder text {string}",
|
|
714
|
+
When_I_find_textareas_by_placeholder_text_multiple
|
|
715
|
+
);
|
|
716
|
+
|
|
717
|
+
// =============================
|
|
718
|
+
// WHEN I FIND INPUT(S)
|
|
719
|
+
// =============================
|
|
720
|
+
|
|
721
|
+
/**
|
|
722
|
+
* Finds an input by its ID and stores it as the current element.
|
|
723
|
+
*
|
|
724
|
+
* ```gherkin
|
|
725
|
+
* When I find input by ID {string}
|
|
726
|
+
* ```
|
|
727
|
+
*
|
|
728
|
+
* @example
|
|
729
|
+
* When I find input by ID "email"
|
|
730
|
+
*
|
|
731
|
+
* @remarks
|
|
732
|
+
* This step uses a CSS selector to locate an input element by its ID.
|
|
733
|
+
* It sets the found input as the {@link CustomWorld.element | current element}.
|
|
734
|
+
*/
|
|
735
|
+
export async function When_I_find_input_by_ID(this: CustomWorld, id: string) {
|
|
181
736
|
this.element = this.page.locator(`input#${id}`);
|
|
182
737
|
this.log?.(`Stored input with ID "${id}"`);
|
|
183
|
-
}
|
|
184
|
-
When("I find
|
|
738
|
+
}
|
|
739
|
+
When("I find input by ID {string}", When_I_find_input_by_ID);
|
|
740
|
+
|
|
741
|
+
/**
|
|
742
|
+
* Finds all inputs by ID and stores them as elements.
|
|
743
|
+
*
|
|
744
|
+
* ```gherkin
|
|
745
|
+
* When I find inputs by ID {string}
|
|
746
|
+
* ```
|
|
747
|
+
*
|
|
748
|
+
* @example
|
|
749
|
+
* When I find inputs by ID "email"
|
|
750
|
+
*
|
|
751
|
+
* @remarks
|
|
752
|
+
* This step uses a CSS selector to find all input elements with the specified ID
|
|
753
|
+
* and stores them in the {@link CustomWorld.elements | elements} collection.
|
|
754
|
+
*/
|
|
755
|
+
export async function When_I_find_inputs_by_ID(this: CustomWorld, id: string) {
|
|
185
756
|
this.elements = this.page.locator(`input#${id}`);
|
|
186
757
|
this.log?.(`Stored multiple inputs with ID "${id}"`);
|
|
187
|
-
}
|
|
188
|
-
When(
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
758
|
+
}
|
|
759
|
+
When("I find inputs by ID {string}", When_I_find_inputs_by_ID);
|
|
760
|
+
|
|
761
|
+
/**
|
|
762
|
+
* Finds an input by its label text and stores it as the current element.
|
|
763
|
+
*
|
|
764
|
+
* ```gherkin
|
|
765
|
+
* When I find input by label text {string}
|
|
766
|
+
* ```
|
|
767
|
+
*
|
|
768
|
+
* @example
|
|
769
|
+
* When I find input by label text "Email"
|
|
770
|
+
*
|
|
771
|
+
* @remarks
|
|
772
|
+
* This step uses Playwright's `getByLabel` to locate an input associated
|
|
773
|
+
* with the given label text. It sets the found input as the
|
|
774
|
+
* {@link CustomWorld.element | current element}.
|
|
775
|
+
*/
|
|
776
|
+
export async function When_I_find_input_by_label_text(this: CustomWorld, label: string) {
|
|
196
777
|
this.element = this.page.getByLabel(label);
|
|
197
778
|
this.log?.(`Stored input with label "${label}"`);
|
|
198
|
-
}
|
|
199
|
-
When("I find input by
|
|
779
|
+
}
|
|
780
|
+
When("I find input by label text {string}", When_I_find_input_by_label_text);
|
|
781
|
+
|
|
782
|
+
/**
|
|
783
|
+
* Finds an input by its name attribute and stores it as the current element.
|
|
784
|
+
*
|
|
785
|
+
* ```gherkin
|
|
786
|
+
* When I find input by name {string}
|
|
787
|
+
* ```
|
|
788
|
+
* * @example
|
|
789
|
+
* When I find input by name "username"
|
|
790
|
+
*
|
|
791
|
+
* @remarks
|
|
792
|
+
* This step uses a CSS selector to locate an input element based on its `name` attribute.
|
|
793
|
+
* It sets the found input as the {@link CustomWorld.element | current element}.
|
|
794
|
+
*/
|
|
795
|
+
export async function When_I_find_input_by_name(this: CustomWorld, name: string) {
|
|
200
796
|
this.element = this.page.locator(`input[name="${name}"]`);
|
|
201
797
|
this.log?.(`Stored input with name "${name}"`);
|
|
202
|
-
}
|
|
203
|
-
When(
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
798
|
+
}
|
|
799
|
+
When("I find input by name {string}", When_I_find_input_by_name);
|
|
800
|
+
|
|
801
|
+
/**
|
|
802
|
+
* Finds an input by its placeholder text and stores it as the current element.
|
|
803
|
+
*
|
|
804
|
+
* ```gherkin
|
|
805
|
+
* When I find input by placeholder text {string}
|
|
806
|
+
* ```
|
|
807
|
+
*
|
|
808
|
+
* @example
|
|
809
|
+
* When I find input by placeholder text "Enter your email"
|
|
810
|
+
*
|
|
811
|
+
* @remarks
|
|
812
|
+
* This step uses Playwright's `getByPlaceholder` to locate an input
|
|
813
|
+
* based on its `placeholder` attribute. It sets the found input as the
|
|
814
|
+
* {@link CustomWorld.element | current element}.
|
|
815
|
+
*/
|
|
816
|
+
export async function When_I_find_input_by_placeholder_text(
|
|
817
|
+
this: CustomWorld,
|
|
818
|
+
placeholder: string
|
|
819
|
+
) {
|
|
820
|
+
this.element = this.page.getByPlaceholder(placeholder);
|
|
821
|
+
this.log?.(`Stored input with placeholder "${placeholder}"`);
|
|
822
|
+
}
|
|
823
|
+
When("I find input by placeholder text {string}", When_I_find_input_by_placeholder_text);
|
|
824
|
+
|
|
825
|
+
/**
|
|
826
|
+
* Finds all inputs by name attribute and stores them as elements.
|
|
827
|
+
*
|
|
828
|
+
* ```gherkin
|
|
829
|
+
* When I find inputs by name {string}
|
|
830
|
+
* ```
|
|
831
|
+
*
|
|
832
|
+
* @example
|
|
833
|
+
* When I find inputs by name "username"
|
|
834
|
+
*
|
|
835
|
+
* @remarks
|
|
836
|
+
* This step uses a CSS selector to find all input elements with the specified
|
|
837
|
+
* `name` attribute and stores them in the {@link CustomWorld.elements | elements}
|
|
838
|
+
* collection.
|
|
839
|
+
*/
|
|
840
|
+
export async function When_I_find_inputs_by_name_multiple(this: CustomWorld, name: string) {
|
|
211
841
|
this.elements = this.page.locator(`input[name="${name}"]`);
|
|
212
842
|
this.log?.(`Stored multiple inputs with name "${name}"`);
|
|
213
|
-
}
|
|
214
|
-
When(
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
843
|
+
}
|
|
844
|
+
When("I find inputs by name {string}", When_I_find_inputs_by_name_multiple);
|
|
845
|
+
|
|
846
|
+
/**
|
|
847
|
+
* Finds all inputs by placeholder text and stores them as elements.
|
|
848
|
+
*
|
|
849
|
+
* ```gherkin
|
|
850
|
+
* When I find inputs by placeholder text {string}
|
|
851
|
+
* ```
|
|
852
|
+
*
|
|
853
|
+
* @example
|
|
854
|
+
* When I find inputs by placeholder text "Search"
|
|
855
|
+
*
|
|
856
|
+
* @remarks
|
|
857
|
+
* This step uses a CSS selector to find all input elements with the specified
|
|
858
|
+
* `placeholder` attribute and stores them in the {@link CustomWorld.elements | elements}
|
|
859
|
+
* collection.
|
|
860
|
+
*/
|
|
861
|
+
export async function When_I_find_inputs_by_placeholder_text_multiple(
|
|
862
|
+
this: CustomWorld,
|
|
863
|
+
placeholder: string
|
|
864
|
+
) {
|
|
865
|
+
this.elements = this.page.locator(`input[placeholder="${placeholder}"]`);
|
|
866
|
+
this.log?.(`Stored multiple inputs with placeholder "${placeholder}"`);
|
|
867
|
+
}
|
|
868
|
+
When("I find inputs by placeholder text {string}", When_I_find_inputs_by_placeholder_text_multiple);
|
|
869
|
+
|
|
870
|
+
/**
|
|
871
|
+
* Finds all inputs by label text and stores them as elements.
|
|
872
|
+
*
|
|
873
|
+
* ```gherkin
|
|
874
|
+
* When I find inputs by label text {string}
|
|
875
|
+
* ```
|
|
876
|
+
*
|
|
877
|
+
* @example
|
|
878
|
+
* When I find inputs by label text "Email"
|
|
879
|
+
*
|
|
880
|
+
* @remarks
|
|
881
|
+
* This step uses a CSS selector to find all input elements associated with the
|
|
882
|
+
* given label text and stores them in the {@link CustomWorld.elements | elements}
|
|
883
|
+
* collection.
|
|
884
|
+
*/
|
|
885
|
+
export async function When_I_find_inputs_by_label_text_multiple(this: CustomWorld, label: string) {
|
|
222
886
|
this.elements = this.page.locator(`label:has-text("${label}") + input`);
|
|
223
887
|
this.log?.(`Stored multiple inputs with label "${label}"`);
|
|
224
|
-
}
|
|
225
|
-
When("I find inputs by
|
|
888
|
+
}
|
|
889
|
+
When("I find inputs by label text {string}", When_I_find_inputs_by_label_text_multiple);
|
|
890
|
+
|
|
891
|
+
/**
|
|
892
|
+
* Finds all inputs by display value (supports alias) and stores them as elements.
|
|
893
|
+
*
|
|
894
|
+
* ```gherkin
|
|
895
|
+
* When I find inputs by display value {string}
|
|
896
|
+
* ```
|
|
897
|
+
*
|
|
898
|
+
* @example
|
|
899
|
+
* When I find inputs by display value "John"
|
|
900
|
+
* When I find inputs by display value "@userName"
|
|
901
|
+
*
|
|
902
|
+
* @remarks
|
|
903
|
+
* This step searches for all input elements whose `value` attribute matches
|
|
904
|
+
* the provided text or resolved alias. The matching inputs are stored in the
|
|
905
|
+
* {@link CustomWorld.elements | elements} collection.
|
|
906
|
+
*/
|
|
907
|
+
export async function When_I_find_inputs_by_display_value_multiple(
|
|
908
|
+
this: CustomWorld,
|
|
909
|
+
value: string
|
|
910
|
+
) {
|
|
226
911
|
// 🧠 Handle alias
|
|
227
912
|
if (value.startsWith("@")) {
|
|
228
913
|
const alias = value.slice(1);
|
|
229
914
|
value = this.data?.[alias];
|
|
230
915
|
if (!value) {
|
|
231
|
-
throw new Error(`No value found for alias "@${alias}"
|
|
916
|
+
throw new Error(`No value found for alias "@${alias}".`);
|
|
232
917
|
}
|
|
233
918
|
}
|
|
234
919
|
|
|
@@ -236,14 +921,33 @@ When("I find inputs by display value {string}", async function (this: CustomWorl
|
|
|
236
921
|
this.elements = this.page.locator(`input[value="${value}"]`);
|
|
237
922
|
|
|
238
923
|
this.log?.(`📦 Stored multiple inputs with display value "${value}"`);
|
|
239
|
-
}
|
|
240
|
-
When("I find
|
|
924
|
+
}
|
|
925
|
+
When("I find inputs by display value {string}", When_I_find_inputs_by_display_value_multiple);
|
|
926
|
+
|
|
927
|
+
/**
|
|
928
|
+
* Finds an input by display value (supports alias) and stores it as the current element.
|
|
929
|
+
*
|
|
930
|
+
* ```gherkin
|
|
931
|
+
* When I find input by display value {string}
|
|
932
|
+
* ```
|
|
933
|
+
*
|
|
934
|
+
* @example
|
|
935
|
+
* When I find input by display value "John"
|
|
936
|
+
* When I find input by display value "@userName"
|
|
937
|
+
*
|
|
938
|
+
* @remarks
|
|
939
|
+
* This step searches for a single input element whose `value` attribute matches
|
|
940
|
+
* the provided text or resolved alias. It sets the found input as the
|
|
941
|
+
* {@link CustomWorld.element | current element}. An `expect` assertion
|
|
942
|
+
* is included to ensure the element is visible.
|
|
943
|
+
*/
|
|
944
|
+
export async function When_I_find_input_by_display_value(this: CustomWorld, value: string) {
|
|
241
945
|
// 🧠 Handle alias
|
|
242
946
|
if (value.startsWith("@")) {
|
|
243
947
|
const alias = value.slice(1);
|
|
244
948
|
value = this.data?.[alias];
|
|
245
949
|
if (!value) {
|
|
246
|
-
throw new Error(`No value found for alias "@${alias}"
|
|
950
|
+
throw new Error(`No value found for alias "@${alias}".`);
|
|
247
951
|
}
|
|
248
952
|
}
|
|
249
953
|
|
|
@@ -253,4 +957,5 @@ When("I find input by display value {string}", async function (this: CustomWorld
|
|
|
253
957
|
await expect(locator).toBeVisible({ timeout: 5000 });
|
|
254
958
|
this.element = locator;
|
|
255
959
|
this.log?.(`🔍 Found input with value: "${value}"`);
|
|
256
|
-
}
|
|
960
|
+
}
|
|
961
|
+
When("I find input by display value {string}", When_I_find_input_by_display_value);
|