playwright-cucumber-ts-steps 0.1.7 โ 1.0.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/README.md +21 -11
- 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
- package/lib/actions/clickSteps.d.ts +0 -1
- package/lib/actions/clickSteps.js +0 -165
- package/lib/actions/cookieSteps.d.ts +0 -1
- package/lib/actions/cookieSteps.js +0 -28
- package/lib/actions/debugSteps.d.ts +0 -1
- package/lib/actions/debugSteps.js +0 -8
- package/lib/actions/elementFindSteps.d.ts +0 -1
- package/lib/actions/elementFindSteps.js +0 -217
- package/lib/actions/fillFormSteps.d.ts +0 -1
- package/lib/actions/fillFormSteps.js +0 -130
- package/lib/actions/inputSteps.d.ts +0 -1
- package/lib/actions/inputSteps.js +0 -97
- package/lib/actions/interceptionSteps.d.ts +0 -1
- package/lib/actions/interceptionSteps.js +0 -71
- package/lib/actions/miscSteps.d.ts +0 -1
- package/lib/actions/miscSteps.js +0 -320
- package/lib/actions/mouseSteps.d.ts +0 -1
- package/lib/actions/mouseSteps.js +0 -66
- package/lib/actions/scrollSteps.d.ts +0 -1
- package/lib/actions/scrollSteps.js +0 -23
- package/lib/actions/storageSteps.d.ts +0 -1
- package/lib/actions/storageSteps.js +0 -72
- package/lib/assertions/buttonAndTextVisibilitySteps.d.ts +0 -1
- package/lib/assertions/buttonAndTextVisibilitySteps.js +0 -150
- package/lib/assertions/cookieSteps.d.ts +0 -1
- package/lib/assertions/cookieSteps.js +0 -45
- package/lib/assertions/elementSteps.d.ts +0 -1
- package/lib/assertions/elementSteps.js +0 -90
- package/lib/assertions/formInputSteps.d.ts +0 -1
- package/lib/assertions/formInputSteps.js +0 -87
- package/lib/assertions/interceptionRequestsSteps.d.ts +0 -1
- package/lib/assertions/interceptionRequestsSteps.js +0 -201
- package/lib/assertions/locationSteps.d.ts +0 -1
- package/lib/assertions/locationSteps.js +0 -87
- package/lib/assertions/roleTestIdSteps.d.ts +0 -1
- package/lib/assertions/roleTestIdSteps.js +0 -26
- package/lib/assertions/semanticSteps.d.ts +0 -1
- package/lib/assertions/semanticSteps.js +0 -67
- package/lib/assertions/storageSteps.d.ts +0 -1
- package/lib/assertions/storageSteps.js +0 -74
- package/lib/assertions/visualSteps.d.ts +0 -1
- package/lib/assertions/visualSteps.js +0 -76
- package/lib/custom_setups/loginHooks.d.ts +0 -1
- package/lib/custom_setups/loginHooks.js +0 -113
- package/lib/helpers/checkPeerDeps.d.ts +0 -1
- package/lib/helpers/checkPeerDeps.js +0 -19
- package/lib/helpers/compareSnapshots.d.ts +0 -6
- package/lib/helpers/compareSnapshots.js +0 -20
- package/lib/helpers/hooks.d.ts +0 -1
- package/lib/helpers/hooks.js +0 -210
- package/lib/helpers/utils/fakerUtils.d.ts +0 -1
- package/lib/helpers/utils/fakerUtils.js +0 -60
- package/lib/helpers/utils/index.d.ts +0 -4
- package/lib/helpers/utils/index.js +0 -20
- package/lib/helpers/utils/optionsUtils.d.ts +0 -24
- package/lib/helpers/utils/optionsUtils.js +0 -88
- package/lib/helpers/utils/resolveUtils.d.ts +0 -6
- package/lib/helpers/utils/resolveUtils.js +0 -72
- package/lib/helpers/utils/sessionUtils.d.ts +0 -3
- package/lib/helpers/utils/sessionUtils.js +0 -40
- package/lib/helpers/world.d.ts +0 -31
- package/lib/helpers/world.js +0 -104
- package/lib/iframes/frames.d.ts +0 -1
- package/lib/iframes/frames.js +0 -11
- package/lib/index.d.ts +0 -28
- package/lib/index.js +0 -48
- package/lib/register.d.ts +0 -1
- package/lib/register.js +0 -6
|
@@ -1,118 +1,354 @@
|
|
|
1
1
|
// e2e/step_definitions/common/actions/inputSteps.ts
|
|
2
|
-
// import fs from "fs";
|
|
3
|
-
// import path from "path";
|
|
4
2
|
import { When } from "@cucumber/cucumber";
|
|
5
|
-
import { evaluateFaker } from "../helpers/utils/fakerUtils";
|
|
3
|
+
import { evaluateFaker } from "../helpers/utils/fakerUtils"; // Assuming this path is correct
|
|
6
4
|
import {
|
|
7
5
|
parseCheckOptions,
|
|
8
6
|
parseFillOptions,
|
|
9
7
|
parseSelectOptions,
|
|
10
|
-
} from "../helpers/utils/optionsUtils";
|
|
11
|
-
import { CustomWorld } from "../helpers/world";
|
|
8
|
+
} from "../helpers/utils/optionsUtils"; // Assuming this path is correct
|
|
9
|
+
import { CustomWorld } from "../helpers/world"; // Assuming this path is correct
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
// =============================
|
|
12
|
+
// WHEN I CHECK / UNCHECK
|
|
13
|
+
// =============================
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Checks the previously selected element (e.g., a checkbox or radio button).
|
|
17
|
+
*
|
|
18
|
+
* ```gherkin
|
|
19
|
+
* When I check
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* When I find element by label text "Remember me"
|
|
24
|
+
* And I check
|
|
25
|
+
*
|
|
26
|
+
* @remarks
|
|
27
|
+
* This step requires a preceding step that sets the {@link CustomWorld.element | current element}
|
|
28
|
+
* to a checkbox or radio button. It will mark the element as checked. Optional Playwright
|
|
29
|
+
* `CheckOptions` can be provided via a data table.
|
|
30
|
+
*/
|
|
31
|
+
export async function When_I_check(this: CustomWorld, ...rest: any[]) {
|
|
32
|
+
if (!this.element) throw new Error("No element selected to check.");
|
|
14
33
|
const maybeTable = rest[0];
|
|
15
34
|
const options = maybeTable?.rowsHash ? parseCheckOptions(maybeTable) : {};
|
|
16
|
-
await this.element
|
|
17
|
-
this.log?.("โ
Checked stored
|
|
18
|
-
}
|
|
35
|
+
await this.element.check(options);
|
|
36
|
+
this.log?.("โ
Checked stored element.");
|
|
37
|
+
}
|
|
38
|
+
When("I check", When_I_check);
|
|
19
39
|
|
|
20
|
-
|
|
40
|
+
/**
|
|
41
|
+
* Unchecks the previously selected element (e.g., a checkbox).
|
|
42
|
+
*
|
|
43
|
+
* ```gherkin
|
|
44
|
+
* When I uncheck
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* When I find element by label text "Agree to terms"
|
|
49
|
+
* And I uncheck
|
|
50
|
+
*
|
|
51
|
+
* @remarks
|
|
52
|
+
* This step requires a preceding step that sets the {@link CustomWorld.element | current element}
|
|
53
|
+
* to a checkbox. It will mark the element as unchecked. Optional Playwright
|
|
54
|
+
* `CheckOptions` can be provided via a data table.
|
|
55
|
+
*/
|
|
56
|
+
export async function When_I_uncheck(this: CustomWorld, ...rest: any[]) {
|
|
57
|
+
if (!this.element) throw new Error("No element selected to uncheck.");
|
|
21
58
|
const maybeTable = rest[0];
|
|
22
59
|
const options = maybeTable?.rowsHash ? parseCheckOptions(maybeTable) : {};
|
|
23
|
-
await this.element
|
|
24
|
-
this.log?.("โ
Unchecked stored
|
|
25
|
-
}
|
|
60
|
+
await this.element.uncheck(options);
|
|
61
|
+
this.log?.("โ
Unchecked stored element.");
|
|
62
|
+
}
|
|
63
|
+
When("I uncheck", When_I_uncheck);
|
|
26
64
|
|
|
27
|
-
|
|
65
|
+
/**
|
|
66
|
+
* Checks a specific input element, requiring a preceding step to select it.
|
|
67
|
+
*
|
|
68
|
+
* ```gherkin
|
|
69
|
+
* When I check input
|
|
70
|
+
* ```
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* When I find element by selector "input#myCheckbox"
|
|
74
|
+
* And I check input
|
|
75
|
+
*
|
|
76
|
+
* @remarks
|
|
77
|
+
* This is an alias for "I check". It requires a preceding step that sets the
|
|
78
|
+
* {@link CustomWorld.element | current element} to an input element (like a checkbox or radio).
|
|
79
|
+
* Optional Playwright `CheckOptions` can be provided via a data table.
|
|
80
|
+
*/
|
|
81
|
+
export async function When_I_check_input(this: CustomWorld, ...rest: any[]) {
|
|
82
|
+
if (!this.element) throw new Error("No input selected to check.");
|
|
28
83
|
const maybeTable = rest[0];
|
|
29
84
|
const options = maybeTable?.rowsHash ? parseCheckOptions(maybeTable) : {};
|
|
30
|
-
if (!this.element) throw new Error("No input selected");
|
|
31
85
|
await this.element.check(options);
|
|
32
|
-
|
|
86
|
+
this.log?.("โ
Checked stored input.");
|
|
87
|
+
}
|
|
88
|
+
When("I check input", When_I_check_input);
|
|
33
89
|
|
|
34
|
-
|
|
90
|
+
/**
|
|
91
|
+
* Unchecks a specific input element, requiring a preceding step to select it.
|
|
92
|
+
*
|
|
93
|
+
* ```gherkin
|
|
94
|
+
* When I uncheck input
|
|
95
|
+
* ```
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* When I find element by selector "input#newsletter"
|
|
99
|
+
* And I uncheck input
|
|
100
|
+
*
|
|
101
|
+
* @remarks
|
|
102
|
+
* This is an alias for "I uncheck". It requires a preceding step that sets the
|
|
103
|
+
* {@link CustomWorld.element | current element} to an input element (like a checkbox).
|
|
104
|
+
* Optional Playwright `CheckOptions` can be provided via a data table.
|
|
105
|
+
*/
|
|
106
|
+
export async function When_I_uncheck_input(this: CustomWorld, ...rest: any[]) {
|
|
107
|
+
if (!this.element) throw new Error("No input selected to uncheck.");
|
|
35
108
|
const maybeTable = rest[0];
|
|
36
109
|
const options = maybeTable?.rowsHash ? parseCheckOptions(maybeTable) : {};
|
|
37
|
-
if (!this.element) throw new Error("No input selected");
|
|
38
110
|
await this.element.uncheck(options);
|
|
39
|
-
|
|
111
|
+
this.log?.("โ
Unchecked stored input.");
|
|
112
|
+
}
|
|
113
|
+
When("I uncheck input", When_I_uncheck_input);
|
|
40
114
|
|
|
41
|
-
//
|
|
115
|
+
// =============================
|
|
116
|
+
// WHEN I TYPE / SET VALUE
|
|
117
|
+
// =============================
|
|
42
118
|
|
|
43
|
-
|
|
44
|
-
|
|
119
|
+
/**
|
|
120
|
+
* Shared implementation for typing steps.
|
|
121
|
+
* @internal
|
|
122
|
+
*/
|
|
123
|
+
const typeStepImplementation = async function (
|
|
124
|
+
this: CustomWorld,
|
|
125
|
+
textOrAlias: string,
|
|
126
|
+
...rest: any[]
|
|
127
|
+
) {
|
|
128
|
+
if (!this.element) throw new Error("No element selected to type into.");
|
|
45
129
|
|
|
46
130
|
const maybeTable = rest[0];
|
|
47
131
|
const options = maybeTable?.rowsHash ? parseFillOptions(maybeTable) : {};
|
|
48
132
|
const text = textOrAlias.startsWith("@")
|
|
49
133
|
? (this.data[textOrAlias.slice(1)] ??
|
|
50
134
|
(() => {
|
|
51
|
-
throw new Error(`No value found for alias "${textOrAlias}"
|
|
135
|
+
throw new Error(`No value found for alias "${textOrAlias}".`);
|
|
52
136
|
})())
|
|
53
|
-
: evaluateFaker(textOrAlias);
|
|
137
|
+
: evaluateFaker(textOrAlias); // Evaluate faker directly here if it's not an alias
|
|
54
138
|
|
|
55
|
-
|
|
139
|
+
// Playwright's fill clears the field by default, but explicitly clearing can be safer
|
|
140
|
+
// await this.element.fill(""); // This explicit clear might not be necessary depending on Playwright version/behavior
|
|
56
141
|
await this.element.fill(text, options);
|
|
57
|
-
this.data.lastTyped = text;
|
|
58
|
-
this.log?.(`โจ๏ธ Typed "${text}" into selected element
|
|
142
|
+
this.data.lastTyped = text; // Store the actual text typed for potential later use
|
|
143
|
+
this.log?.(`โจ๏ธ Typed "${text}" into selected element.`);
|
|
59
144
|
};
|
|
60
145
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
When
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
146
|
+
/**
|
|
147
|
+
* Types the given text into the previously selected element.
|
|
148
|
+
*
|
|
149
|
+
* ```gherkin
|
|
150
|
+
* When I type {string}
|
|
151
|
+
* ```
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* When I find element by selector "input[name='email']"
|
|
155
|
+
* And I type "user@example.com"
|
|
156
|
+
*
|
|
157
|
+
* @remarks
|
|
158
|
+
* This step requires a preceding step that sets the {@link CustomWorld.element | current element}
|
|
159
|
+
* to an input field (or any element that supports `fill`). The provided text can be a literal
|
|
160
|
+
* string or a faker expression (e.g., `{{internet.email}}`).
|
|
161
|
+
* Optional Playwright `FillOptions` can be provided via a data table.
|
|
162
|
+
*/
|
|
163
|
+
export const When_I_type = typeStepImplementation;
|
|
164
|
+
When("I type {string}", When_I_type);
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Types the value stored in an alias into the previously selected element.
|
|
168
|
+
*
|
|
169
|
+
* ```gherkin
|
|
170
|
+
* When I type stored {string}
|
|
171
|
+
* ```
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* Given I store "my.user@example.com" as "userEmail"
|
|
175
|
+
* When I find element by selector "input[name='email']"
|
|
176
|
+
* And I type stored "userEmail"
|
|
177
|
+
*
|
|
178
|
+
* @remarks
|
|
179
|
+
* This step requires a preceding step that sets the {@link CustomWorld.element | current element}
|
|
180
|
+
* to an input field. The `string` argument must be an alias (e.g., `userEmail`).
|
|
181
|
+
* The value associated with this alias in `this.data` will be typed into the element.
|
|
182
|
+
* Optional Playwright `FillOptions` can be provided via a data table.
|
|
183
|
+
*/
|
|
184
|
+
export const When_I_type_stored = typeStepImplementation;
|
|
185
|
+
When("I type stored {string}", When_I_type_stored);
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Types a randomly generated value (using Faker.js) into the previously selected element.
|
|
189
|
+
*
|
|
190
|
+
* ```gherkin
|
|
191
|
+
* When I type random {string}
|
|
192
|
+
* ```
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* When I find element by selector "input[name='username']"
|
|
196
|
+
* And I type random "internet.userName"
|
|
197
|
+
*
|
|
198
|
+
* @remarks
|
|
199
|
+
* This step requires a preceding step that sets the {@link CustomWorld.element | current element}
|
|
200
|
+
* to an input field. The `string` argument should be a Faker.js path (e.g., `internet.email`,
|
|
201
|
+
* `person.firstName`). A random value generated by Faker will be typed into the element.
|
|
202
|
+
* Optional Playwright `FillOptions` can be provided via a data table.
|
|
203
|
+
*/
|
|
204
|
+
export const When_I_type_random = typeStepImplementation;
|
|
205
|
+
When("I type random {string}", When_I_type_random);
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Sets the value of the previously selected element.
|
|
209
|
+
*
|
|
210
|
+
* ```gherkin
|
|
211
|
+
* When I set value {string}
|
|
212
|
+
* ```
|
|
213
|
+
*
|
|
214
|
+
* @example
|
|
215
|
+
* When I find element by selector "input[name='password']"
|
|
216
|
+
* And I set value "@userPassword"
|
|
217
|
+
*
|
|
218
|
+
* @remarks
|
|
219
|
+
* This step requires a preceding step that sets the {@link CustomWorld.element | current element}
|
|
220
|
+
* to an input field (or any element that supports `fill`). The provided `valueOrAlias` can be
|
|
221
|
+
* a literal string, an alias (prefixed with `@`), or a Faker expression. This will directly
|
|
222
|
+
* set the input's value, which is generally faster than typing for non-interactive scenarios.
|
|
223
|
+
* Optional Playwright `FillOptions` can be provided via a data table.
|
|
224
|
+
*/
|
|
225
|
+
export async function When_I_set_value(this: CustomWorld, valueOrAlias: string, ...rest: any[]) {
|
|
226
|
+
if (!this.element) throw new Error("No element selected to set value.");
|
|
227
|
+
|
|
228
|
+
const maybeTable = rest[0];
|
|
229
|
+
const options = maybeTable?.rowsHash ? parseFillOptions(maybeTable) : {};
|
|
230
|
+
const value = valueOrAlias.startsWith("@")
|
|
231
|
+
? (this.data[valueOrAlias.slice(1)] ??
|
|
232
|
+
(() => {
|
|
233
|
+
throw new Error(`No value found for alias "${valueOrAlias}".`);
|
|
234
|
+
})())
|
|
235
|
+
: evaluateFaker(valueOrAlias); // Evaluate faker directly here if it's not an alias
|
|
236
|
+
|
|
237
|
+
await this.element.fill(value, options);
|
|
238
|
+
this.data.lastValueSet = value; // Store the actual value set for potential later use
|
|
239
|
+
this.log?.(`๐ Set value of selected element to "${value}".`);
|
|
240
|
+
}
|
|
241
|
+
When("I set value {string}", When_I_set_value);
|
|
84
242
|
|
|
85
|
-
|
|
86
|
-
|
|
243
|
+
/**
|
|
244
|
+
* Clears the value of the previously selected element.
|
|
245
|
+
*
|
|
246
|
+
* ```gherkin
|
|
247
|
+
* When I clear
|
|
248
|
+
* ```
|
|
249
|
+
*
|
|
250
|
+
* @example
|
|
251
|
+
* When I find element by selector "input[name='search']"
|
|
252
|
+
* And I clear
|
|
253
|
+
*
|
|
254
|
+
* @remarks
|
|
255
|
+
* This step requires a preceding step that sets the {@link CustomWorld.element | current element}
|
|
256
|
+
* to an input field (or any element that supports `fill`). It effectively empties the input field.
|
|
257
|
+
*/
|
|
258
|
+
export async function When_I_clear(this: CustomWorld) {
|
|
259
|
+
if (!this.element) throw new Error("No element selected to clear.");
|
|
87
260
|
await this.element.fill("");
|
|
88
|
-
this.log?.("๐งผ Cleared value of selected element");
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
this.
|
|
261
|
+
this.log?.("๐งผ Cleared value of selected element.");
|
|
262
|
+
}
|
|
263
|
+
When("I clear", When_I_clear);
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Submits the form associated with the previously selected element, or the first form on the page.
|
|
267
|
+
*
|
|
268
|
+
* ```gherkin
|
|
269
|
+
* When I submit
|
|
270
|
+
* ```
|
|
271
|
+
*
|
|
272
|
+
* @example
|
|
273
|
+
* When I find element by selector "form#loginForm"
|
|
274
|
+
* And I submit
|
|
275
|
+
* # OR (submits the first form found if no element is selected)
|
|
276
|
+
* When I go to "/login"
|
|
277
|
+
* And I submit
|
|
278
|
+
*
|
|
279
|
+
* @remarks
|
|
280
|
+
* This step will find a form to submit. If {@link CustomWorld.element | this.element}
|
|
281
|
+
* is a form or an element within a form, that form will be submitted. Otherwise, it will
|
|
282
|
+
* attempt to submit the first `<form>` element found on the page.
|
|
283
|
+
* It uses a direct DOM `submit()` call, which bypasses Playwright's default event handling
|
|
284
|
+
* and can be useful for testing native form submission behavior.
|
|
285
|
+
*/
|
|
286
|
+
export async function When_I_submit(this: CustomWorld) {
|
|
287
|
+
// Use the current element if it's a form or within a form, otherwise default to the first form on the page.
|
|
288
|
+
const formLocator = this.element
|
|
289
|
+
? this.element.locator("xpath=ancestor-or-self::form")
|
|
290
|
+
: this.page.locator("form").first();
|
|
291
|
+
|
|
292
|
+
if (!(await formLocator.isVisible())) {
|
|
293
|
+
throw new Error(
|
|
294
|
+
"No visible form found to submit. Ensure an element within a form is selected, or a form exists on the page."
|
|
295
|
+
);
|
|
117
296
|
}
|
|
118
|
-
|
|
297
|
+
|
|
298
|
+
await formLocator.evaluate((f: HTMLFormElement) => f.submit());
|
|
299
|
+
this.log?.("๐จ Submitted form.");
|
|
300
|
+
}
|
|
301
|
+
When("I submit", When_I_submit);
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Selects an option by its visible text label in a `<select>` element.
|
|
305
|
+
*
|
|
306
|
+
* ```gherkin
|
|
307
|
+
* When I select option {string}
|
|
308
|
+
* ```
|
|
309
|
+
*
|
|
310
|
+
* @example
|
|
311
|
+
* When I find element by selector "select[name='role']"
|
|
312
|
+
* And I select option "Administrator"
|
|
313
|
+
*
|
|
314
|
+
* @remarks
|
|
315
|
+
* This step requires a preceding step that sets the {@link CustomWorld.element | current element}
|
|
316
|
+
* to a `<select>` HTML element. It will then select the option whose visible text matches
|
|
317
|
+
* the provided `option` string.
|
|
318
|
+
* Optional Playwright `SelectOptionOptions` can be provided via a data table.
|
|
319
|
+
*/
|
|
320
|
+
export async function When_I_select_option(this: CustomWorld, option: string, ...rest: any[]) {
|
|
321
|
+
if (!this.element) throw new Error("No select element stored to select an option.");
|
|
322
|
+
const maybeTable = rest[0];
|
|
323
|
+
const options = maybeTable?.rowsHash ? parseSelectOptions(maybeTable) : {};
|
|
324
|
+
await this.element.selectOption({ label: option }, options);
|
|
325
|
+
this.log?.(`๐ฝ Selected option "${option}".`);
|
|
326
|
+
}
|
|
327
|
+
When("I select option {string}", When_I_select_option);
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Sets the file input of the previously selected element to the specified file path.
|
|
331
|
+
*
|
|
332
|
+
* ```gherkin
|
|
333
|
+
* When I select file {string}
|
|
334
|
+
* ```
|
|
335
|
+
*
|
|
336
|
+
* @example
|
|
337
|
+
* When I find element by selector "input[type='file']"
|
|
338
|
+
* And I select file "path/to/my/document.pdf"
|
|
339
|
+
*
|
|
340
|
+
* @remarks
|
|
341
|
+
* This step requires a preceding step that sets the {@link CustomWorld.element | current element}
|
|
342
|
+
* to an `input` element of `type="file"`. The `filePath` should be relative to your project's
|
|
343
|
+
* root or an absolute path. Playwright will automatically handle making the file available
|
|
344
|
+
* for upload.
|
|
345
|
+
* Optional Playwright `SetInputFilesOptions` can be provided via a data table.
|
|
346
|
+
*/
|
|
347
|
+
export async function When_I_select_file(this: CustomWorld, filePath: string, ...rest: any[]) {
|
|
348
|
+
if (!this.element) throw new Error("No file input selected to set a file.");
|
|
349
|
+
const maybeTable = rest[0];
|
|
350
|
+
const options = maybeTable?.rowsHash ? parseSelectOptions(maybeTable) : {}; // Note: parseSelectOptions is used here, assuming it returns `SetInputFilesOptions` compatible object or is generic enough. If not, a new parser for SetInputFilesOptions would be ideal.
|
|
351
|
+
await this.element.setInputFiles(filePath, options);
|
|
352
|
+
this.log?.(`๐ Set input file to "${filePath}".`);
|
|
353
|
+
}
|
|
354
|
+
When("I select file {string}", When_I_select_file);
|