playwright-cucumber-ts-steps 0.1.6 → 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 +429 -0
- package/src/actions/cookieSteps.ts +95 -0
- package/src/actions/debugSteps.ts +21 -0
- package/src/actions/elementFindSteps.ts +961 -0
- package/src/actions/fillFormSteps.ts +270 -0
- package/src/actions/index.ts +12 -0
- package/src/actions/inputSteps.ts +354 -0
- package/src/actions/interceptionSteps.ts +325 -0
- package/src/actions/miscSteps.ts +1144 -0
- package/src/actions/mouseSteps.ts +256 -0
- package/src/actions/scrollSteps.ts +122 -0
- package/src/actions/storageSteps.ts +308 -0
- package/src/assertions/buttonAndTextVisibilitySteps.ts +436 -0
- package/src/assertions/cookieSteps.ts +131 -0
- package/src/assertions/elementSteps.ts +432 -0
- package/src/assertions/formInputSteps.ts +377 -0
- package/src/assertions/index.ts +11 -0
- package/src/assertions/interceptionRequestsSteps.ts +640 -0
- package/src/assertions/locationSteps.ts +315 -0
- package/src/assertions/roleTestIdSteps.ts +254 -0
- package/src/assertions/semanticSteps.ts +267 -0
- package/src/assertions/storageSteps.ts +250 -0
- package/src/assertions/visualSteps.ts +275 -0
- package/src/custom_setups/loginHooks.ts +154 -0
- package/src/helpers/checkPeerDeps.ts +19 -0
- package/src/helpers/compareSnapshots.ts +35 -0
- package/src/helpers/hooks.ts +212 -0
- package/src/helpers/utils/fakerUtils.ts +64 -0
- package/src/helpers/utils/optionsUtils.ts +104 -0
- package/src/helpers/utils/resolveUtils.ts +74 -0
- package/src/helpers/utils/sessionUtils.ts +36 -0
- package/src/helpers/world.ts +119 -0
- package/src/iframes/frames.ts +15 -0
- package/src/index.ts +18 -0
- package/src/register.ts +4 -0
- 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.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
- /package/{lib/helpers/utils/index.d.ts → src/helpers/utils/index.ts} +0 -0
package/README.md
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
# 🎭 playwright-cucumber-ts-steps
|
|
2
2
|
|
|
3
|
-
[](https://github.com/qaPaschalE/playwright-cucumber-ts-steps/blob/main/LICENSE)
|
|
5
|
-
[](https://github.com/qaPaschalE/playwright-cucumber-ts-steps/actions)
|
|
6
|
-
[](https://www.npmjs.com/package/playwright-cucumber-ts-steps)
|
|
7
|
-
[](https://github.com/qaPaschalE/playwright-cucumber-ts-steps/issues)
|
|
8
|
-
[](https://github.com/qaPaschalE/playwright-cucumber-ts-steps/stargazers)
|
|
3
|
+
[](https://nodei.co/npm/playwright-cucumber-ts-steps/)
|
|
9
4
|
|
|
10
|
-
|
|
5
|
+
<table align="center" style="margin-bottom:30px;"><tr><td align="center" width="9999" heigth="9999" >
|
|
6
|
+
<img src="https://github.com/qaPaschalE/k6-cucumber-steps/blob/main/assets/paschal%20logo%20(2).png?raw=true" alt="paschal Logo" style="margin-top:25px;" align="center"/>
|
|
7
|
+
</td></tr></table>
|
|
11
8
|
|
|
12
|
-
|
|
9
|
+
[](https://www.npmjs.com/package/playwright-cucumber-ts-steps)
|
|
10
|
+
[](https://github.com/qaPaschalE/playwright-cucumber-ts-steps/blob/main/LICENSE)
|
|
11
|
+
[](https://nodejs.org/)
|
|
12
|
+
[](https://github.com/qaPaschalE/playwright-cucumber-ts-steps/actions)
|
|
13
|
+
[](https://www.npmjs.com/package/playwright-cucumber-ts-steps)
|
|
14
|
+
[](https://github.com/qaPaschalE/playwright-cucumber-ts-steps/issues)
|
|
15
|
+
[](https://github.com/qaPaschalE/playwright-cucumber-ts-steps/stargazers)
|
|
13
16
|
|
|
14
|
-
|
|
17
|
+
> A collection of reusable Playwright step definitions for Cucumber in TypeScript, designed to streamline end-to-end testing across web, API, and mobile applications.
|
|
18
|
+
|
|
19
|
+
> **Note:** This package is designed for advanced Cucumber+Playwright+TypeScript setups. For basic Playwright usage, see the [official Playwright docs](https://playwright.dev/).
|
|
15
20
|
|
|
16
21
|
## ✨ Features
|
|
17
22
|
|
|
@@ -54,6 +59,10 @@ npm install --save-dev @playwright/test @cucumber/cucumber typescript ts-node
|
|
|
54
59
|
npx playwright install
|
|
55
60
|
```
|
|
56
61
|
|
|
62
|
+
## 📘 Step Definition Documentation
|
|
63
|
+
|
|
64
|
+
👉 [View Steps Documentation](https://qapaschale.github.io/playwright-cucumber-ts-steps/) and [examples](https://github.com/qaPaschale/playwright-cucumber-ts-steps/tree/master/playwright/e2e).
|
|
65
|
+
|
|
57
66
|
---
|
|
58
67
|
|
|
59
68
|
## 🛠️ Usage
|
|
@@ -229,8 +238,9 @@ const ARTIFACT_DIR = process.env.TEST_ARTIFACT_DIR || "test-artifacts";
|
|
|
229
238
|
const defaultWorldParams = {
|
|
230
239
|
artifactDir: ARTIFACT_DIR,
|
|
231
240
|
payloadDir: "payloads",
|
|
232
|
-
|
|
233
|
-
|
|
241
|
+
enableTrace: process.env.ENABLE_TRACE || "fail", // "false" | "fail" | "all"
|
|
242
|
+
enableScreenshots: process.env.ENABLE_SCREENSHOTS || "fail", // "false" | "fail" | "all"
|
|
243
|
+
enableVideos: process.env.ENABLE_VIDEOS || "all", // "false" | "fail" | "all"
|
|
234
244
|
enableVisualTest: process.env.ENABLE_VISUAL_TEST === "true",
|
|
235
245
|
device: process.env.MOBILE_DEVICE || undefined, // e.g., "Pixel 5"
|
|
236
246
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "playwright-cucumber-ts-steps",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "A collection of reusable Playwright step definitions for Cucumber in TypeScript, designed to streamline end-to-end testing across web, API, and mobile applications.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -26,7 +26,8 @@
|
|
|
26
26
|
},
|
|
27
27
|
"scripts": {
|
|
28
28
|
"build": "tsc",
|
|
29
|
-
"docs": "typedoc
|
|
29
|
+
"docs": "typedoc",
|
|
30
|
+
"docs:deploy": "gh-pages -d temp-docs",
|
|
30
31
|
"prepare": "husky",
|
|
31
32
|
"lint": "eslint . --ext .ts",
|
|
32
33
|
"lint:fix": "eslint . --ext .ts --fix",
|
|
@@ -79,6 +80,10 @@
|
|
|
79
80
|
"@cucumber/cucumber": "*",
|
|
80
81
|
"@playwright/test": "*"
|
|
81
82
|
},
|
|
83
|
+
"files": [
|
|
84
|
+
"lib/",
|
|
85
|
+
"src/"
|
|
86
|
+
],
|
|
82
87
|
"dependencies": {
|
|
83
88
|
"@cucumber/tag-expressions": "^6.2.0",
|
|
84
89
|
"@faker-js/faker": "^9.8.0",
|
|
@@ -96,10 +101,12 @@
|
|
|
96
101
|
"eslint": "^9.29.0",
|
|
97
102
|
"eslint-config-prettier": "^10.1.5",
|
|
98
103
|
"eslint-plugin-import": "^2.32.0",
|
|
104
|
+
"gh-pages": "^6.3.0",
|
|
99
105
|
"husky": "^9.1.7",
|
|
100
106
|
"lint-staged": "^16.1.2",
|
|
101
107
|
"prettier": "^3.5.3",
|
|
102
108
|
"ts-node": "^10.9.2",
|
|
109
|
+
"typedoc": "^0.28.5",
|
|
103
110
|
"typescript": "^5.8.3",
|
|
104
111
|
"typescript-eslint": "^8.34.1"
|
|
105
112
|
}
|
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
// e2e/step_definitions/common/actions/clickSteps.ts
|
|
2
|
+
import { When, DataTable } from "@cucumber/cucumber";
|
|
3
|
+
import { parseClickOptions } from "../helpers/utils/optionsUtils";
|
|
4
|
+
import { CustomWorld } from "../helpers/world";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Clicks on the previously stored element.
|
|
8
|
+
*
|
|
9
|
+
* ```gherkin
|
|
10
|
+
* When I click
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```gherkin
|
|
15
|
+
* When I click
|
|
16
|
+
* ```
|
|
17
|
+
* @remarks
|
|
18
|
+
* Requires a previous step that stores an element.
|
|
19
|
+
* @category Click Steps
|
|
20
|
+
*/
|
|
21
|
+
export async function When_I_click(this: CustomWorld, ...rest: any[]) {
|
|
22
|
+
const maybeTable = rest[0];
|
|
23
|
+
const options = maybeTable?.rowsHash ? parseClickOptions(maybeTable) : {};
|
|
24
|
+
if (!this.element) throw new Error("❌ No stored element to click.");
|
|
25
|
+
await this.element.click(options);
|
|
26
|
+
this.log?.("🖱️ Clicked on stored element");
|
|
27
|
+
}
|
|
28
|
+
When("I click", When_I_click);
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Clicks on an element matching the given selector.
|
|
32
|
+
*
|
|
33
|
+
* ```gherkin
|
|
34
|
+
* When I click on element {string}
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```gherkin
|
|
39
|
+
* When I click on element ".my-class"
|
|
40
|
+
* ```
|
|
41
|
+
* @remarks
|
|
42
|
+
* Stores the clicked element for later use.
|
|
43
|
+
* @category Click Steps
|
|
44
|
+
*/
|
|
45
|
+
export async function When_I_click_on_element(this: CustomWorld, selector: string, ...rest: any[]) {
|
|
46
|
+
const maybeTable = rest[0];
|
|
47
|
+
const options = maybeTable?.rowsHash ? parseClickOptions(maybeTable) : {};
|
|
48
|
+
const element = this.getLocator(selector);
|
|
49
|
+
await element.click(options);
|
|
50
|
+
this.element = element;
|
|
51
|
+
this.log?.(`🖱️ Clicked on element "${selector}"`);
|
|
52
|
+
}
|
|
53
|
+
When("I click on element {string}", When_I_click_on_element);
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Clicks on a button with the given label.
|
|
57
|
+
*
|
|
58
|
+
* ```gherkin
|
|
59
|
+
* When I click on button {string}
|
|
60
|
+
* ```
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```gherkin
|
|
64
|
+
* When I click on button "Submit"
|
|
65
|
+
* ```
|
|
66
|
+
* @remarks
|
|
67
|
+
* Stores the clicked button for later use.
|
|
68
|
+
* @category Click Steps
|
|
69
|
+
*/
|
|
70
|
+
export async function When_I_click_on_button(this: CustomWorld, label: string, ...rest: any[]) {
|
|
71
|
+
const maybeTable = rest[0];
|
|
72
|
+
const options = maybeTable?.rowsHash ? parseClickOptions(maybeTable) : {};
|
|
73
|
+
const button = await this.page.getByRole("button", { name: label });
|
|
74
|
+
await button.click(options);
|
|
75
|
+
this.element = button;
|
|
76
|
+
this.log?.(`🖱️ Clicked on button "${label}"`);
|
|
77
|
+
}
|
|
78
|
+
When("I click on button {string}", When_I_click_on_button);
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Clicks on a link with the given text.
|
|
82
|
+
*
|
|
83
|
+
* ```gherkin
|
|
84
|
+
* When I click on link {string}
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```gherkin
|
|
89
|
+
* When I click on link "Home"
|
|
90
|
+
* ```
|
|
91
|
+
* @remarks
|
|
92
|
+
* Stores the clicked link for later use.
|
|
93
|
+
* @category Click Steps
|
|
94
|
+
*/
|
|
95
|
+
export async function When_I_click_on_link(this: CustomWorld, text: string, ...rest: any[]) {
|
|
96
|
+
const maybeTable = rest[0];
|
|
97
|
+
const options = maybeTable?.rowsHash ? parseClickOptions(maybeTable) : {};
|
|
98
|
+
const link = await this.page.getByRole("link", { name: text });
|
|
99
|
+
await link.click(options);
|
|
100
|
+
this.element = link;
|
|
101
|
+
this.log?.(`✅ Clicked on link "${text}"`);
|
|
102
|
+
}
|
|
103
|
+
When("I click on link {string}", When_I_click_on_link);
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Clicks on a label with the given text.
|
|
107
|
+
*
|
|
108
|
+
* ```gherkin
|
|
109
|
+
* When I click on label {string}
|
|
110
|
+
* ```
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```gherkin
|
|
114
|
+
* When I click on label "Username"
|
|
115
|
+
* ```
|
|
116
|
+
* @remarks
|
|
117
|
+
* Stores the clicked label for later use.
|
|
118
|
+
* @category Click Steps
|
|
119
|
+
*/
|
|
120
|
+
export async function When_I_click_on_label(this: CustomWorld, labelText: string, ...rest: any[]) {
|
|
121
|
+
const maybeTable = rest[0];
|
|
122
|
+
const options = maybeTable?.rowsHash ? parseClickOptions(maybeTable) : {};
|
|
123
|
+
const label = await this.page.getByLabel(labelText);
|
|
124
|
+
await label.click(options);
|
|
125
|
+
this.element = label;
|
|
126
|
+
this.log?.(`🏷️ Clicked on label "${labelText}"`);
|
|
127
|
+
}
|
|
128
|
+
When("I click on label {string}", When_I_click_on_label);
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Clicks on an element containing the given text (not exact match). Supports aliasing with @alias.
|
|
132
|
+
*
|
|
133
|
+
* ```gherkin
|
|
134
|
+
* When I click on text {string}
|
|
135
|
+
* ```
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```gherkin
|
|
139
|
+
* When I click on text "Welcome"
|
|
140
|
+
* When I click on text "@username"
|
|
141
|
+
* ```
|
|
142
|
+
* @remarks
|
|
143
|
+
* Stores the clicked element for later use.
|
|
144
|
+
* @category Click Steps
|
|
145
|
+
*/
|
|
146
|
+
export async function When_I_click_on_text(this: CustomWorld, rawText: string, ...rest: any[]) {
|
|
147
|
+
const maybeTable = rest[0];
|
|
148
|
+
const options = maybeTable?.rowsHash ? parseClickOptions(maybeTable) : {};
|
|
149
|
+
|
|
150
|
+
let text = rawText;
|
|
151
|
+
if (rawText.startsWith("@")) {
|
|
152
|
+
const alias = rawText.slice(1);
|
|
153
|
+
text = this.data[alias];
|
|
154
|
+
if (!text) throw new Error(`❌ No value found for alias "@${alias}"`);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const locator = this.page.getByText(text, { exact: false });
|
|
158
|
+
await locator.first().waitFor({ state: "visible", timeout: 5000 });
|
|
159
|
+
await locator.first().click(options);
|
|
160
|
+
|
|
161
|
+
this.element = locator.first();
|
|
162
|
+
this.log?.(`🖱️ Clicked on text "${text}"`);
|
|
163
|
+
}
|
|
164
|
+
When("I click on text {string}", When_I_click_on_text);
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Clicks on an element containing the exact given text.
|
|
168
|
+
*
|
|
169
|
+
* ```gherkin
|
|
170
|
+
* When I click on exact text {string}
|
|
171
|
+
* ```
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```gherkin
|
|
175
|
+
* When I click on exact text "Log out"
|
|
176
|
+
* ```
|
|
177
|
+
* @remarks
|
|
178
|
+
* Stores the clicked element for later use.
|
|
179
|
+
* @category Click Steps
|
|
180
|
+
*/
|
|
181
|
+
export async function When_I_click_on_exact_text(
|
|
182
|
+
this: CustomWorld,
|
|
183
|
+
exactText: string,
|
|
184
|
+
...rest: any[]
|
|
185
|
+
) {
|
|
186
|
+
const maybeTable = rest[0];
|
|
187
|
+
const options = maybeTable?.rowsHash ? parseClickOptions(maybeTable) : {};
|
|
188
|
+
const locator = this.page.getByText(exactText, { exact: true });
|
|
189
|
+
await locator.waitFor({ state: "visible", timeout: 5000 });
|
|
190
|
+
await locator.click(options);
|
|
191
|
+
this.element = locator;
|
|
192
|
+
this.log?.(`🖱️ Clicked on exact text "${exactText}"`);
|
|
193
|
+
}
|
|
194
|
+
When("I click on exact text {string}", When_I_click_on_exact_text);
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Clicks all previously stored elements.
|
|
198
|
+
*
|
|
199
|
+
* ```gherkin
|
|
200
|
+
* When I click all
|
|
201
|
+
* ```
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* ```gherkin
|
|
205
|
+
* When I click all
|
|
206
|
+
* ```
|
|
207
|
+
* @remarks
|
|
208
|
+
* Requires a previous step that stores elements.
|
|
209
|
+
* @category Click Steps
|
|
210
|
+
*/
|
|
211
|
+
export async function When_I_click_all(this: CustomWorld, ...rest: any[]) {
|
|
212
|
+
const maybeTable = rest[0];
|
|
213
|
+
const options = maybeTable?.rowsHash ? parseClickOptions(maybeTable) : {};
|
|
214
|
+
if (!this.elements) throw new Error("❌ No stored elements to click.");
|
|
215
|
+
const count = await this.elements.count();
|
|
216
|
+
if (count === 0) throw new Error("⚠️ No elements found to click.");
|
|
217
|
+
for (let i = 0; i < count; i++) {
|
|
218
|
+
const el = this.elements.nth(i);
|
|
219
|
+
await el.waitFor({ state: "visible", timeout: 5000 });
|
|
220
|
+
await el.click(options);
|
|
221
|
+
this.log?.(`🖱️ Clicked element #${i + 1}`);
|
|
222
|
+
}
|
|
223
|
+
this.log?.(`✅ Clicked all ${count} elements.`);
|
|
224
|
+
}
|
|
225
|
+
When("I click all", When_I_click_all);
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Double-clicks on an element containing the given text.
|
|
229
|
+
*
|
|
230
|
+
* ```gherkin
|
|
231
|
+
* When I double click on text {string}
|
|
232
|
+
* ```
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* ```gherkin
|
|
236
|
+
* When I double click on text "Edit"
|
|
237
|
+
* ```
|
|
238
|
+
* @remarks
|
|
239
|
+
* Uses the previously stored element if available.
|
|
240
|
+
* @category Click Steps
|
|
241
|
+
*/
|
|
242
|
+
export async function When_I_double_click_on_text(this: CustomWorld, text: string, ...rest: any[]) {
|
|
243
|
+
const maybeTable = rest[0];
|
|
244
|
+
const options = maybeTable?.rowsHash ? parseClickOptions(maybeTable) : {};
|
|
245
|
+
const element = this.element || this.page.getByText(text);
|
|
246
|
+
await element.dblclick(options);
|
|
247
|
+
this.log?.(`🖱️ Double-clicked on text "${text}"`);
|
|
248
|
+
}
|
|
249
|
+
When("I double click on text {string}", When_I_double_click_on_text);
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Double-clicks at the given page coordinates.
|
|
253
|
+
*
|
|
254
|
+
* ```gherkin
|
|
255
|
+
* When I double click position {int} {int}
|
|
256
|
+
* ```
|
|
257
|
+
*
|
|
258
|
+
* @example
|
|
259
|
+
* ```gherkin
|
|
260
|
+
* When I double click position 100 200
|
|
261
|
+
* ```
|
|
262
|
+
* @category Click Steps
|
|
263
|
+
*/
|
|
264
|
+
export async function When_I_double_click_position(
|
|
265
|
+
this: CustomWorld,
|
|
266
|
+
x: number,
|
|
267
|
+
y: number,
|
|
268
|
+
...rest: any[]
|
|
269
|
+
) {
|
|
270
|
+
const maybeTable = rest[0];
|
|
271
|
+
const options = maybeTable?.rowsHash ? parseClickOptions(maybeTable) : {};
|
|
272
|
+
await this.page.mouse.dblclick(x, y, options);
|
|
273
|
+
this.log?.(`🖱️ Double-clicked at (${x}, ${y})`);
|
|
274
|
+
}
|
|
275
|
+
When("I double click position {int} {int}", When_I_double_click_position);
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Double-clicks on the previously stored element.
|
|
279
|
+
*
|
|
280
|
+
* ```gherkin
|
|
281
|
+
* When I double click
|
|
282
|
+
* ```
|
|
283
|
+
*
|
|
284
|
+
* @example
|
|
285
|
+
* ```gherkin
|
|
286
|
+
* When I double click
|
|
287
|
+
* ```
|
|
288
|
+
* @remarks
|
|
289
|
+
* Requires a previous step that stores an element.
|
|
290
|
+
* @category Click Steps
|
|
291
|
+
*/
|
|
292
|
+
export async function When_I_double_click(this: CustomWorld, ...rest: any[]) {
|
|
293
|
+
const maybeTable = rest[0];
|
|
294
|
+
const options = maybeTable?.rowsHash ? parseClickOptions(maybeTable) : {};
|
|
295
|
+
if (!this.element) throw new Error("❌ No stored element to double-click.");
|
|
296
|
+
await this.element.dblclick(options);
|
|
297
|
+
this.log?.("🖱️ Double-clicked on stored element");
|
|
298
|
+
}
|
|
299
|
+
When("I double click", When_I_double_click);
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Right-clicks on the previously stored element.
|
|
303
|
+
*
|
|
304
|
+
* ```gherkin
|
|
305
|
+
* When I right click
|
|
306
|
+
* ```
|
|
307
|
+
*
|
|
308
|
+
* @example
|
|
309
|
+
* ```gherkin
|
|
310
|
+
* When I right click
|
|
311
|
+
* ```
|
|
312
|
+
* @remarks
|
|
313
|
+
* Requires a previous step that stores an element.
|
|
314
|
+
* @category Click Steps
|
|
315
|
+
*/
|
|
316
|
+
export async function When_I_right_click(this: CustomWorld, ...rest: any[]) {
|
|
317
|
+
const maybeTable = rest[0];
|
|
318
|
+
const options = maybeTable?.rowsHash ? parseClickOptions(maybeTable) : {};
|
|
319
|
+
if (!this.element) throw new Error("❌ No stored element to right-click.");
|
|
320
|
+
await this.element.click({ button: "right", ...options });
|
|
321
|
+
this.log?.("🖱️ Right-clicked on stored element");
|
|
322
|
+
}
|
|
323
|
+
When("I right click", When_I_right_click);
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Right-clicks on an element containing the given text.
|
|
327
|
+
*
|
|
328
|
+
* ```gherkin
|
|
329
|
+
* When I right click on text {string}
|
|
330
|
+
* ```
|
|
331
|
+
*
|
|
332
|
+
* @example
|
|
333
|
+
* ```gherkin
|
|
334
|
+
* When I right click on text "Options"
|
|
335
|
+
* ```
|
|
336
|
+
* @category Click Steps
|
|
337
|
+
*/
|
|
338
|
+
export async function When_I_right_click_on_text(this: CustomWorld, text: string, ...rest: any[]) {
|
|
339
|
+
const maybeTable = rest[0];
|
|
340
|
+
const options = maybeTable?.rowsHash ? parseClickOptions(maybeTable) : {};
|
|
341
|
+
const element = this.page.getByText(text);
|
|
342
|
+
await element.click({ button: "right", ...options });
|
|
343
|
+
this.log?.(`🖱️ Right-clicked on text "${text}"`);
|
|
344
|
+
}
|
|
345
|
+
When("I right click on text {string}", When_I_right_click_on_text);
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Right-clicks at the given page coordinates.
|
|
349
|
+
*
|
|
350
|
+
* ```gherkin
|
|
351
|
+
* When I right click position {int} {int}
|
|
352
|
+
* ```
|
|
353
|
+
*
|
|
354
|
+
* @example
|
|
355
|
+
* ```gherkin
|
|
356
|
+
* When I right click position 50 50
|
|
357
|
+
* ```
|
|
358
|
+
* @category Click Steps
|
|
359
|
+
*/
|
|
360
|
+
export async function When_I_right_click_position(
|
|
361
|
+
this: CustomWorld,
|
|
362
|
+
x: number,
|
|
363
|
+
y: number,
|
|
364
|
+
...rest: any[]
|
|
365
|
+
) {
|
|
366
|
+
const maybeTable = rest[0];
|
|
367
|
+
const options = maybeTable?.rowsHash ? parseClickOptions(maybeTable) : {};
|
|
368
|
+
await this.page.mouse.click(x, y, { button: "right", ...options });
|
|
369
|
+
this.log?.(`🖱️ Right-clicked at (${x}, ${y})`);
|
|
370
|
+
}
|
|
371
|
+
When("I right click position {int} {int}", When_I_right_click_position);
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Clicks all stored elements (alternative signature).
|
|
375
|
+
*
|
|
376
|
+
* ```gherkin
|
|
377
|
+
* When I click all
|
|
378
|
+
* ```
|
|
379
|
+
*
|
|
380
|
+
* @example
|
|
381
|
+
* ```gherkin
|
|
382
|
+
* When I click all
|
|
383
|
+
* ```
|
|
384
|
+
* @remarks
|
|
385
|
+
* Requires a previous step that stores elements.
|
|
386
|
+
* @category Click Steps
|
|
387
|
+
*/
|
|
388
|
+
export async function When_I_click_all_alt(this: CustomWorld, dataTable?: DataTable) {
|
|
389
|
+
const options = parseClickOptions(dataTable);
|
|
390
|
+
|
|
391
|
+
if (!this.elements) {
|
|
392
|
+
throw new Error("❌ No elements stored. Use a 'find' step before 'I click all'.");
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
const count = await this.elements.count();
|
|
396
|
+
if (count === 0) {
|
|
397
|
+
throw new Error("⚠️ Stored elements are empty. Nothing to click.");
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
for (let i = 0; i < count; i++) {
|
|
401
|
+
const element = this.elements.nth(i);
|
|
402
|
+
await element.waitFor({ state: "visible", timeout: 5000 });
|
|
403
|
+
await element.click(options);
|
|
404
|
+
this.log?.(`🖱️ Clicked element #${i + 1}`);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
this.log?.(`✅ Clicked all ${count} stored elements.`);
|
|
408
|
+
}
|
|
409
|
+
When("I click all", When_I_click_all_alt);
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Clicks on an element matching the given selector (regex step).
|
|
413
|
+
*
|
|
414
|
+
* ```gherkin
|
|
415
|
+
* When I click on selector {string}
|
|
416
|
+
* ```
|
|
417
|
+
*
|
|
418
|
+
* @example
|
|
419
|
+
* ```gherkin
|
|
420
|
+
* When I click on selector ".my-selector"
|
|
421
|
+
* ```
|
|
422
|
+
* @category Click Steps
|
|
423
|
+
*/
|
|
424
|
+
export async function When_I_click_on_selector(this: CustomWorld, selector: string) {
|
|
425
|
+
const locator = this.getLocator(selector);
|
|
426
|
+
await locator.click();
|
|
427
|
+
this.log?.(`🖱️ Clicked on selector: ${selector}`);
|
|
428
|
+
}
|
|
429
|
+
When(/^I click on selector "([^"]+)"$/, When_I_click_on_selector);
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// e2e/step_definitions/common/actions/cookieSteps.ts
|
|
2
|
+
import { When } from "@cucumber/cucumber";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @step
|
|
6
|
+
* @description Clears all cookies in the current browser context.
|
|
7
|
+
* @example
|
|
8
|
+
* When I clear all cookies
|
|
9
|
+
*/
|
|
10
|
+
When("I clear all cookies", async function () {
|
|
11
|
+
await this.page.context().clearCookies();
|
|
12
|
+
this.log("Cleared all cookies");
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @step
|
|
17
|
+
* @description Clears all cookies in the current browser context (alias).
|
|
18
|
+
* @example
|
|
19
|
+
* When I clear cookies
|
|
20
|
+
*/
|
|
21
|
+
When("I clear cookies", async function () {
|
|
22
|
+
await this.page.context().clearCookies();
|
|
23
|
+
this.log("Cleared cookies (alias)");
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @step
|
|
28
|
+
* @description Clears a specific cookie by name.
|
|
29
|
+
* @example
|
|
30
|
+
* When I clear cookie "session_id"
|
|
31
|
+
*/
|
|
32
|
+
When("I clear cookie {string}", async function (name: string) {
|
|
33
|
+
await this.page.context().addCookies([
|
|
34
|
+
{
|
|
35
|
+
name,
|
|
36
|
+
value: "",
|
|
37
|
+
domain: new URL(this.page.url()).hostname,
|
|
38
|
+
path: "/",
|
|
39
|
+
expires: 0,
|
|
40
|
+
},
|
|
41
|
+
]);
|
|
42
|
+
this.log(`Cleared cookie: ${name}`);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @step
|
|
47
|
+
* @description Logs all cookies in the current browser context to the console.
|
|
48
|
+
* @example
|
|
49
|
+
* When I log all cookies
|
|
50
|
+
*/
|
|
51
|
+
When("I log all cookies", async function () {
|
|
52
|
+
const cookies = await this.page.context().cookies();
|
|
53
|
+
console.log("Cookies:", cookies);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @step
|
|
58
|
+
* @description Sets a cookie with the given name and value for the current domain.
|
|
59
|
+
* @example
|
|
60
|
+
* When I set cookie "session_id" to "abc123"
|
|
61
|
+
* @remarks
|
|
62
|
+
* The cookie is set for the current page's domain and path "/".
|
|
63
|
+
* @category Cookie Steps
|
|
64
|
+
*/
|
|
65
|
+
export async function When_I_set_cookie(this: any, name: string, value: string) {
|
|
66
|
+
const url = new URL(this.page.url());
|
|
67
|
+
await this.page.context().addCookies([
|
|
68
|
+
{
|
|
69
|
+
name,
|
|
70
|
+
value,
|
|
71
|
+
domain: url.hostname,
|
|
72
|
+
path: "/",
|
|
73
|
+
expires: Math.floor(Date.now() / 1000) + 3600, // 1 hour from now
|
|
74
|
+
httpOnly: false,
|
|
75
|
+
secure: false,
|
|
76
|
+
sameSite: "Lax",
|
|
77
|
+
},
|
|
78
|
+
]);
|
|
79
|
+
this.log?.(`Set cookie: ${name}=${value}`);
|
|
80
|
+
}
|
|
81
|
+
When("I set cookie {string} to {string}", When_I_set_cookie);
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* @step
|
|
85
|
+
* @description Gets a cookie value by name and logs it.
|
|
86
|
+
* @example
|
|
87
|
+
* When I get cookie "session_id"
|
|
88
|
+
* @category Cookie Steps
|
|
89
|
+
*/
|
|
90
|
+
export async function When_I_get_cookie(this: any, name: string) {
|
|
91
|
+
const cookies = await this.page.context().cookies();
|
|
92
|
+
const found = cookies.find((c: any) => c.name === name);
|
|
93
|
+
this.log?.(`Cookie "${name}": ${found ? found.value : "not found"}`);
|
|
94
|
+
}
|
|
95
|
+
When("I get cookie {string}", When_I_get_cookie);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// e2e/step_definitions/common/actions/debugSteps.ts
|
|
2
|
+
import { When } from "@cucumber/cucumber";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Pauses the test execution for debugging with a custom message.
|
|
6
|
+
*
|
|
7
|
+
* ```gherkin
|
|
8
|
+
* When I debug with message {string}
|
|
9
|
+
* ```
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```gherkin
|
|
13
|
+
* When I debug with message "Check login form"
|
|
14
|
+
* ```
|
|
15
|
+
* @category Debug Steps
|
|
16
|
+
*/
|
|
17
|
+
export async function When_I_debug_with_message(this: any, message: string) {
|
|
18
|
+
await this.page.pause();
|
|
19
|
+
this.log?.(`Paused test for debugging: ${message}`);
|
|
20
|
+
}
|
|
21
|
+
When("I debug with message {string}", When_I_debug_with_message);
|