playwright-cucumber-ts-steps 0.0.3 โ†’ 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/actions/Interception & Requests.d.ts +1 -0
  2. package/dist/actions/Interception & Requests.js +39 -0
  3. package/dist/actions/clickSteps.d.ts +1 -0
  4. package/dist/actions/clickSteps.js +173 -0
  5. package/dist/actions/cookieSteps.d.ts +1 -0
  6. package/dist/actions/cookieSteps.js +26 -0
  7. package/dist/actions/debugSteps.d.ts +1 -0
  8. package/dist/actions/debugSteps.js +9 -0
  9. package/dist/actions/elementFindSteps.d.ts +1 -0
  10. package/dist/actions/elementFindSteps.js +239 -0
  11. package/dist/actions/inputSteps.d.ts +1 -0
  12. package/dist/actions/inputSteps.js +166 -0
  13. package/dist/actions/interceptionSteps.d.ts +1 -0
  14. package/dist/actions/interceptionSteps.js +64 -0
  15. package/dist/actions/miscSteps.d.ts +1 -0
  16. package/dist/actions/miscSteps.js +277 -0
  17. package/dist/actions/mouseSteps.d.ts +1 -0
  18. package/dist/actions/mouseSteps.js +67 -0
  19. package/dist/actions/scrollSteps.d.ts +1 -0
  20. package/dist/actions/scrollSteps.js +21 -0
  21. package/dist/actions/storageSteps.d.ts +1 -0
  22. package/dist/actions/storageSteps.js +49 -0
  23. package/dist/assertions/button_and_text_visibility.d.ts +1 -0
  24. package/dist/assertions/button_and_text_visibility.js +172 -0
  25. package/dist/assertions/cookieSteps.d.ts +1 -0
  26. package/dist/assertions/cookieSteps.js +43 -0
  27. package/dist/assertions/elementSteps.d.ts +1 -0
  28. package/dist/assertions/elementSteps.js +84 -0
  29. package/dist/assertions/formInputSteps.d.ts +1 -0
  30. package/dist/assertions/formInputSteps.js +85 -0
  31. package/dist/assertions/locationSteps.d.ts +1 -0
  32. package/dist/assertions/locationSteps.js +69 -0
  33. package/dist/assertions/roleTestIdSteps.d.ts +1 -0
  34. package/dist/assertions/roleTestIdSteps.js +24 -0
  35. package/dist/assertions/semanticSteps.d.ts +1 -0
  36. package/dist/assertions/semanticSteps.js +52 -0
  37. package/dist/assertions/storageSteps.d.ts +1 -0
  38. package/dist/assertions/storageSteps.js +70 -0
  39. package/dist/assertions/visualSteps.d.ts +1 -0
  40. package/dist/assertions/visualSteps.js +70 -0
  41. package/dist/custom_setups/global-login.d.ts +2 -0
  42. package/dist/custom_setups/global-login.js +20 -0
  43. package/dist/custom_setups/loginHooks.d.ts +1 -0
  44. package/dist/custom_setups/loginHooks.js +139 -0
  45. package/dist/helpers/compareSnapshots.d.ts +6 -0
  46. package/dist/helpers/compareSnapshots.js +14 -0
  47. package/dist/helpers/hooks.d.ts +1 -0
  48. package/dist/helpers/hooks.js +148 -0
  49. package/dist/helpers/world.js +9 -7
  50. package/dist/iframes/frames.d.ts +1 -0
  51. package/dist/iframes/frames.js +9 -0
  52. package/dist/index.d.ts +28 -5
  53. package/dist/index.js +28 -5
  54. package/dist/register.d.ts +1 -0
  55. package/dist/register.js +2 -0
  56. package/package.json +2 -8
  57. package/index.ts +0 -10
  58. package/register.ts +0 -31
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,39 @@
1
+ import { When, Then } from "@cucumber/cucumber";
2
+ When("I intercept URL {string}", async function (url) {
3
+ await this.page.route(url, async (route) => {
4
+ await route.continue();
5
+ });
6
+ });
7
+ When("I intercept URL {string} and stub body {string}", async function (url, body) {
8
+ await this.page.route(url, (route) => {
9
+ route.fulfill({
10
+ status: 200,
11
+ contentType: "application/json",
12
+ body,
13
+ });
14
+ });
15
+ });
16
+ When("I make a request to {string}", async function (url) {
17
+ const response = await this.page.request.get(url);
18
+ this.data.lastResponse = response;
19
+ });
20
+ Then("I see response status {int}", async function (status) {
21
+ const res = this.data.lastResponse;
22
+ if (!res)
23
+ throw new Error("No response available");
24
+ const actual = res.status();
25
+ if (actual !== status)
26
+ throw new Error(`Expected status ${status}, got ${actual}`);
27
+ });
28
+ Then("I see response body {string}", async function (expected) {
29
+ const res = this.data.lastResponse;
30
+ const body = await res.text();
31
+ if (body !== expected)
32
+ throw new Error(`Expected body "${expected}", got "${body}"`);
33
+ });
34
+ Then("I see response body contains {string}", async function (part) {
35
+ const res = this.data.lastResponse;
36
+ const body = await res.text();
37
+ if (!body.includes(part))
38
+ throw new Error(`Body does not contain "${part}"`);
39
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,173 @@
1
+ // e2e/step_definitions/common/actions/clickSteps.ts
2
+ import { When } from "@cucumber/cucumber";
3
+ import { parseClickOptions } from "../helpers/utils/optionsUtils";
4
+ When("I click", async function (...rest) {
5
+ var _a;
6
+ const maybeTable = rest[0];
7
+ const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseClickOptions(maybeTable) : {};
8
+ if (!this.element)
9
+ throw new Error("โŒ No stored element to click.");
10
+ await this.element.click(options);
11
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, "๐Ÿ–ฑ๏ธ Clicked on stored element");
12
+ });
13
+ When("I click on button {string}", async function (label, ...rest) {
14
+ var _a;
15
+ const maybeTable = rest[0];
16
+ const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseClickOptions(maybeTable) : {};
17
+ const button = await this.page.getByRole("button", { name: label });
18
+ await button.click(options);
19
+ this.element = button;
20
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `๐Ÿ–ฑ๏ธ Clicked on button "${label}"`);
21
+ });
22
+ When("I click on link {string}", async function (text, ...rest) {
23
+ var _a;
24
+ const maybeTable = rest[0];
25
+ const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseClickOptions(maybeTable) : {};
26
+ const link = await this.page.getByRole("link", { name: text });
27
+ await link.click(options);
28
+ this.element = link;
29
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `โœ… Clicked on link "${text}"`);
30
+ });
31
+ When("I click on label {string}", async function (labelText, ...rest) {
32
+ var _a;
33
+ const maybeTable = rest[0];
34
+ const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseClickOptions(maybeTable) : {};
35
+ const label = await this.page.getByLabel(labelText);
36
+ await label.click(options);
37
+ this.element = label;
38
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `๐Ÿท๏ธ Clicked on label "${labelText}"`);
39
+ });
40
+ When("I click on text {string}", async function (rawText, ...rest) {
41
+ var _a;
42
+ const maybeTable = rest[0];
43
+ const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseClickOptions(maybeTable) : {};
44
+ let text = rawText;
45
+ if (rawText.startsWith("@")) {
46
+ const alias = rawText.slice(1);
47
+ text = this.data[alias];
48
+ if (!text)
49
+ throw new Error(`โŒ No value found for alias "@${alias}"`);
50
+ }
51
+ const locator = this.page.getByText(text, { exact: false });
52
+ await locator.first().waitFor({ state: "visible", timeout: 5000 });
53
+ await locator.first().click(options);
54
+ this.element = locator.first();
55
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `๐Ÿ–ฑ๏ธ Clicked on text "${text}"`);
56
+ });
57
+ When("I click on exact text {string}", async function (exactText, ...rest) {
58
+ var _a;
59
+ const maybeTable = rest[0];
60
+ const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseClickOptions(maybeTable) : {};
61
+ const locator = this.page.getByText(exactText, { exact: true });
62
+ await locator.waitFor({ state: "visible", timeout: 5000 });
63
+ await locator.click(options);
64
+ this.element = locator;
65
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `๐Ÿ–ฑ๏ธ Clicked on exact text "${exactText}"`);
66
+ });
67
+ When("I click all", async function (...rest) {
68
+ var _a, _b;
69
+ const maybeTable = rest[0];
70
+ const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseClickOptions(maybeTable) : {};
71
+ if (!this.elements)
72
+ throw new Error("โŒ No stored elements to click.");
73
+ const count = await this.elements.count();
74
+ if (count === 0)
75
+ throw new Error("โš ๏ธ No elements found to click.");
76
+ for (let i = 0; i < count; i++) {
77
+ const el = this.elements.nth(i);
78
+ await el.waitFor({ state: "visible", timeout: 5000 });
79
+ await el.click(options);
80
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `๐Ÿ–ฑ๏ธ Clicked element #${i + 1}`);
81
+ }
82
+ (_b = this.log) === null || _b === void 0 ? void 0 : _b.call(this, `โœ… Clicked all ${count} elements.`);
83
+ });
84
+ When("I double click on text {string}", async function (text, ...rest) {
85
+ var _a;
86
+ const maybeTable = rest[0];
87
+ const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseClickOptions(maybeTable) : {};
88
+ const element = this.element || this.page.getByText(text);
89
+ await element.dblclick(options);
90
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `๐Ÿ–ฑ๏ธ Double-clicked on text "${text}"`);
91
+ });
92
+ When("I double click position {int} {int}", async function (x, y, ...rest) {
93
+ var _a;
94
+ const maybeTable = rest[0];
95
+ const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseClickOptions(maybeTable) : {};
96
+ await this.page.mouse.dblclick(x, y, options);
97
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `๐Ÿ–ฑ๏ธ Double-clicked at (${x}, ${y})`);
98
+ });
99
+ When("I double click", async function (...rest) {
100
+ var _a;
101
+ const maybeTable = rest[0];
102
+ const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseClickOptions(maybeTable) : {};
103
+ if (!this.element)
104
+ throw new Error("โŒ No stored element to double-click.");
105
+ await this.element.dblclick(options);
106
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, "๐Ÿ–ฑ๏ธ Double-clicked on stored element");
107
+ });
108
+ When("I right click", async function (...rest) {
109
+ var _a;
110
+ const maybeTable = rest[0];
111
+ const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseClickOptions(maybeTable) : {};
112
+ if (!this.element)
113
+ throw new Error("โŒ No stored element to right-click.");
114
+ await this.element.click({ button: "right", ...options });
115
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, "๐Ÿ–ฑ๏ธ Right-clicked on stored element");
116
+ });
117
+ When("I right click on text {string}", async function (text, ...rest) {
118
+ var _a;
119
+ const maybeTable = rest[0];
120
+ const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseClickOptions(maybeTable) : {};
121
+ const element = this.page.getByText(text);
122
+ await element.click({ button: "right", ...options });
123
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `๐Ÿ–ฑ๏ธ Right-clicked on text "${text}"`);
124
+ });
125
+ When("I right click position {int} {int}", async function (x, y, ...rest) {
126
+ var _a;
127
+ const maybeTable = rest[0];
128
+ const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseClickOptions(maybeTable) : {};
129
+ await this.page.mouse.click(x, y, { button: "right", ...options });
130
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `๐Ÿ–ฑ๏ธ Right-clicked at (${x}, ${y})`);
131
+ });
132
+ When("I blur", async function () {
133
+ var _a;
134
+ await this.page.evaluate(() => {
135
+ const active = document.activeElement;
136
+ if (active && typeof active.blur === "function") {
137
+ active.blur();
138
+ }
139
+ });
140
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, "๐ŸŒ€ Blurred active element");
141
+ });
142
+ When("I focus", async function () {
143
+ var _a;
144
+ if (!this.element)
145
+ throw new Error("โŒ No stored element to focus.");
146
+ await this.element.focus();
147
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, "๐ŸŽฏ Focused stored element");
148
+ });
149
+ When("I click all", async function (dataTable) {
150
+ var _a, _b;
151
+ const options = parseClickOptions(dataTable);
152
+ if (!this.elements) {
153
+ throw new Error("โŒ No elements stored. Use a 'find' step before 'I click all'.");
154
+ }
155
+ const count = await this.elements.count();
156
+ if (count === 0) {
157
+ throw new Error("โš ๏ธ Stored elements are empty. Nothing to click.");
158
+ }
159
+ for (let i = 0; i < count; i++) {
160
+ const element = this.elements.nth(i);
161
+ await element.waitFor({ state: "visible", timeout: 5000 });
162
+ await element.click(options);
163
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `๐Ÿ–ฑ๏ธ Clicked element #${i + 1}`);
164
+ }
165
+ (_b = this.log) === null || _b === void 0 ? void 0 : _b.call(this, `โœ… Clicked all ${count} stored elements.`);
166
+ });
167
+ When(/^I click on selector "([^"]+)"$/, async function (selector) {
168
+ var _a;
169
+ const scope = this.getScope();
170
+ const element = scope.locator(selector);
171
+ await element.click();
172
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `๐Ÿ–ฑ๏ธ Clicked on selector: ${selector}`);
173
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,26 @@
1
+ // e2e/step_definitions/common/actions/cookieSteps.ts
2
+ import { When } from "@cucumber/cucumber";
3
+ When("I clear all cookies", async function () {
4
+ await this.page.context().clearCookies();
5
+ this.log("Cleared all cookies");
6
+ });
7
+ When("I clear cookies", async function () {
8
+ await this.page.context().clearCookies();
9
+ this.log("Cleared cookies (alias)");
10
+ });
11
+ When("I clear cookie {string}", async function (name) {
12
+ await this.page.context().addCookies([
13
+ {
14
+ name,
15
+ value: "",
16
+ domain: new URL(this.page.url()).hostname,
17
+ path: "/",
18
+ expires: 0,
19
+ },
20
+ ]);
21
+ this.log(`Cleared cookie: ${name}`);
22
+ });
23
+ When("I log all cookies", async function () {
24
+ const cookies = await this.page.context().cookies();
25
+ console.log("Cookies:", cookies);
26
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ // e2e/step_definitions/common/actions/debugSteps.ts
2
+ import { When } from "@cucumber/cucumber";
3
+ When("I debug", async function () {
4
+ await this.page.pause();
5
+ this.log("Paused test for debugging");
6
+ });
7
+ When("I log {string}", async function (msg) {
8
+ this.log(msg);
9
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,239 @@
1
+ import { When } from "@cucumber/cucumber";
2
+ import { expect } from "@playwright/test";
3
+ // =============================
4
+ // WHEN I FIND ELEMENT(S)
5
+ // =============================
6
+ When("I find element by selector {string}", async function (selector) {
7
+ this.element = this.page.locator(selector);
8
+ await expect(this.element).toHaveCount(1);
9
+ });
10
+ When("I find elements by selector {string}", async function (selector) {
11
+ var _a;
12
+ this.elements = this.page.locator(selector);
13
+ const count = await this.elements.count();
14
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `Found ${count} elements with selector ${selector}`);
15
+ });
16
+ When("I find element by text {string}", async function (text) {
17
+ this.element = this.page.getByText(text, { exact: true });
18
+ await expect(this.element).toHaveCount(1);
19
+ });
20
+ When("I find element by title {string}", async function (title) {
21
+ this.element = this.page.getByTitle(title);
22
+ await expect(this.element).toHaveCount(1);
23
+ });
24
+ When("I find element by testid {string}", async function (testid) {
25
+ this.element = this.page.getByTestId(testid);
26
+ await expect(this.element).toHaveCount(1);
27
+ });
28
+ When("I find element by role {string}", async function (role) {
29
+ this.element = this.page.getByRole(role);
30
+ await expect(this.element).toHaveCount(1);
31
+ });
32
+ When("I find element by placeholder text {string}", async function (text) {
33
+ this.element = this.page.getByPlaceholder(text);
34
+ await expect(this.element).toHaveCount(1);
35
+ });
36
+ When("I find element by label text {string}", async function (label) {
37
+ this.element = this.page.getByLabel(label);
38
+ await expect(this.element).toHaveCount(1);
39
+ });
40
+ When("I find element by alt text {string}", async function (alt) {
41
+ this.element = this.page.getByAltText(alt);
42
+ await expect(this.element).toHaveCount(1);
43
+ });
44
+ When("I find element by name {string}", async function (name) {
45
+ this.element = this.page.getByRole("textbox", { name });
46
+ await expect(this.element).toHaveCount(1);
47
+ });
48
+ When("I find buttons by text {string}", async function (buttonText) {
49
+ var _a, _b;
50
+ // ๐Ÿง  Resolve alias
51
+ if (buttonText.startsWith("@")) {
52
+ const alias = buttonText.slice(1);
53
+ buttonText = (_a = this.data) === null || _a === void 0 ? void 0 : _a[alias];
54
+ if (!buttonText) {
55
+ throw new Error(`No value found for alias "@${alias}"`);
56
+ }
57
+ }
58
+ // ๐Ÿ” Locate all matching buttons
59
+ this.elements = this.page.getByRole("button", {
60
+ name: buttonText,
61
+ exact: false,
62
+ });
63
+ (_b = this.log) === null || _b === void 0 ? void 0 : _b.call(this, `๐Ÿ”˜ Stored all buttons matching text "${buttonText}"`);
64
+ });
65
+ // =============================
66
+ // WHEN I GET ELEMENT(S)
67
+ // =============================
68
+ When("I get element by selector {string}", async function (selector) {
69
+ this.element = this.page.locator(selector).first();
70
+ });
71
+ When("I get elements by selector {string}", async function (selector) {
72
+ this.elements = this.page.locator(selector);
73
+ });
74
+ When("I get first element", async function () {
75
+ if (!this.elements)
76
+ throw new Error("No element collection found");
77
+ this.element = this.elements.first();
78
+ });
79
+ When("I get last element", async function () {
80
+ if (!this.elements)
81
+ throw new Error("No element collection found");
82
+ this.element = this.elements.last();
83
+ });
84
+ When(/^I get (\d+)(?:st|nd|rd|th) element$/, async function (index) {
85
+ var _a;
86
+ if (!this.elements)
87
+ throw new Error("No elements stored to pick from");
88
+ const count = await this.elements.count();
89
+ if (index < 1 || index > count) {
90
+ throw new Error(`Cannot get element ${index} โ€” only ${count} found`);
91
+ }
92
+ this.element = this.elements.nth(index - 1);
93
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `Selected ${index} element from stored elements`);
94
+ });
95
+ When("I find elements by role {string}", async function (role) {
96
+ var _a;
97
+ const locator = this.page.getByRole(role);
98
+ const count = await locator.count();
99
+ if (count === 0) {
100
+ throw new Error(`No elements found with role "${role}"`);
101
+ }
102
+ this.elements = locator;
103
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `Stored ${count} elements with role "${role}"`);
104
+ });
105
+ // When(
106
+ // "I get {int}{ordinal} element",
107
+ // async function (this: CustomWorld, index: number) {
108
+ // if (!this.elements) {
109
+ // throw new Error(
110
+ // "No element collection found. Did you call 'find elements by' first?"
111
+ // );
112
+ // }
113
+ // const total = await this.elements.count();
114
+ // if (index < 1 || index > total) {
115
+ // throw new Error(
116
+ // `Index ${index} out of bounds. Found only ${total} elements.`
117
+ // );
118
+ // }
119
+ // this.element = this.elements.nth(index - 1);
120
+ // this.log?.(`Stored ${index}th element from collection`);
121
+ // }
122
+ // );
123
+ When("I get {int}rd element", async function (index) {
124
+ if (!this.elements)
125
+ throw new Error("No element collection found");
126
+ this.element = this.elements.nth(index);
127
+ });
128
+ When("I get focused element", async function () {
129
+ this.element = (await this.page.evaluateHandle(() => document.activeElement));
130
+ });
131
+ When("I store element text as {string}", async function (alias) {
132
+ var _a;
133
+ const element = this.element;
134
+ if (!element)
135
+ throw new Error("No element selected");
136
+ const text = await element.textContent();
137
+ this.data[alias] = text === null || text === void 0 ? void 0 : text.trim();
138
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `Stored text "${text}" as "${alias}"`);
139
+ });
140
+ When("I find textarea by label text {string}", async function (label) {
141
+ var _a;
142
+ this.element = this.page.getByLabel(label);
143
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `Stored textarea with label "${label}"`);
144
+ });
145
+ When("I find textarea by placeholder text {string}", async function (placeholder) {
146
+ var _a;
147
+ this.element = this.page.getByPlaceholder(placeholder);
148
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `Stored textarea with placeholder "${placeholder}"`);
149
+ });
150
+ When("I find textareas by label text {string}", async function (label) {
151
+ var _a;
152
+ this.elements = this.page.locator(`label:has-text("${label}") + textarea`);
153
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `Stored multiple textareas with label "${label}"`);
154
+ });
155
+ When("I find textarea by name {string}", async function (name) {
156
+ var _a;
157
+ this.element = this.page.locator(`textarea[name="${name}"]`);
158
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `Stored textarea with name "${name}"`);
159
+ });
160
+ When("I find textareas by ID {string}", async function (id) {
161
+ var _a;
162
+ this.elements = this.page.locator(`textarea#${id}`);
163
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `Stored multiple textareas with ID "${id}"`);
164
+ });
165
+ When("I find input by ID {string}", async function (id) {
166
+ var _a;
167
+ this.element = this.page.locator(`input#${id}`);
168
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `Stored input with ID "${id}"`);
169
+ });
170
+ When("I find inputs by ID {string}", async function (id) {
171
+ var _a;
172
+ this.elements = this.page.locator(`input#${id}`);
173
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `Stored multiple inputs with ID "${id}"`);
174
+ });
175
+ When("I find textareas by placeholder text {string}", async function (placeholder) {
176
+ var _a;
177
+ this.elements = this.page.locator(`textarea[placeholder="${placeholder}"]`);
178
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `Stored multiple textareas with placeholder "${placeholder}"`);
179
+ });
180
+ When("I find input by label text {string}", async function (label) {
181
+ var _a;
182
+ this.element = this.page.getByLabel(label);
183
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `Stored input with label "${label}"`);
184
+ });
185
+ When("I find input by name {string}", async function (name) {
186
+ var _a;
187
+ this.element = this.page.locator(`input[name="${name}"]`);
188
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `Stored input with name "${name}"`);
189
+ });
190
+ When("I find input by placeholder text {string}", async function (placeholder) {
191
+ var _a;
192
+ this.element = this.page.getByPlaceholder(placeholder);
193
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `Stored input with placeholder "${placeholder}"`);
194
+ });
195
+ When("I find inputs by name {string}", async function (name) {
196
+ var _a;
197
+ this.elements = this.page.locator(`input[name="${name}"]`);
198
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `Stored multiple inputs with name "${name}"`);
199
+ });
200
+ When("I find inputs by placeholder text {string}", async function (placeholder) {
201
+ var _a;
202
+ this.elements = this.page.locator(`input[placeholder="${placeholder}"]`);
203
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `Stored multiple inputs with placeholder "${placeholder}"`);
204
+ });
205
+ When("I find inputs by label text {string}", async function (label) {
206
+ var _a;
207
+ this.elements = this.page.locator(`label:has-text("${label}") + input`);
208
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `Stored multiple inputs with label "${label}"`);
209
+ });
210
+ When("I find inputs by display value {string}", async function (value) {
211
+ var _a, _b;
212
+ // ๐Ÿง  Handle alias
213
+ if (value.startsWith("@")) {
214
+ const alias = value.slice(1);
215
+ value = (_a = this.data) === null || _a === void 0 ? void 0 : _a[alias];
216
+ if (!value) {
217
+ throw new Error(`No value found for alias "@${alias}"`);
218
+ }
219
+ }
220
+ // ๐Ÿ” Find all matching inputs
221
+ this.elements = this.page.locator(`input[value="${value}"]`);
222
+ (_b = this.log) === null || _b === void 0 ? void 0 : _b.call(this, `๐Ÿ“ฆ Stored multiple inputs with display value "${value}"`);
223
+ });
224
+ When("I find input by display value {string}", async function (value) {
225
+ var _a, _b;
226
+ // ๐Ÿง  Handle alias
227
+ if (value.startsWith("@")) {
228
+ const alias = value.slice(1);
229
+ value = (_a = this.data) === null || _a === void 0 ? void 0 : _a[alias];
230
+ if (!value) {
231
+ throw new Error(`No value found for alias "@${alias}"`);
232
+ }
233
+ }
234
+ // ๐ŸŽฏ Try to find input element with matching display value
235
+ const locator = this.page.locator(`input[value="${value}"]`);
236
+ await expect(locator).toBeVisible({ timeout: 5000 });
237
+ this.element = locator;
238
+ (_b = this.log) === null || _b === void 0 ? void 0 : _b.call(this, `๐Ÿ” Found input with value: "${value}"`);
239
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,166 @@
1
+ // e2e/step_definitions/common/actions/inputSteps.ts
2
+ import { When } from "@cucumber/cucumber";
3
+ import { expect } from "@playwright/test";
4
+ import path from "path";
5
+ import fs from "fs";
6
+ import { evaluateFaker } from "../helpers/utils/fakerUtils";
7
+ import { parseClickOptions, parseCheckOptions, parseFillOptions, parseSelectOptions, } from "../helpers/utils/optionsUtils";
8
+ When("I check", async function (...rest) {
9
+ var _a, _b;
10
+ const maybeTable = rest[0];
11
+ const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseCheckOptions(maybeTable) : {};
12
+ await ((_a = this.element) === null || _a === void 0 ? void 0 : _a.check(options));
13
+ (_b = this.log) === null || _b === void 0 ? void 0 : _b.call(this, "โœ… Checked stored checkbox");
14
+ });
15
+ When("I uncheck", async function (...rest) {
16
+ var _a, _b;
17
+ const maybeTable = rest[0];
18
+ const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseCheckOptions(maybeTable) : {};
19
+ await ((_a = this.element) === null || _a === void 0 ? void 0 : _a.uncheck(options));
20
+ (_b = this.log) === null || _b === void 0 ? void 0 : _b.call(this, "โœ… Unchecked stored checkbox");
21
+ });
22
+ When("I check input", async function (...rest) {
23
+ const maybeTable = rest[0];
24
+ const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseCheckOptions(maybeTable) : {};
25
+ if (!this.element)
26
+ throw new Error("No input selected");
27
+ await this.element.check(options);
28
+ });
29
+ When("I uncheck input", async function (...rest) {
30
+ const maybeTable = rest[0];
31
+ const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseCheckOptions(maybeTable) : {};
32
+ if (!this.element)
33
+ throw new Error("No input selected");
34
+ await this.element.uncheck(options);
35
+ });
36
+ When("I fill the following {string} form data:", async function (_formName, tableData, ...rest) {
37
+ var _a, _b, _c, _d;
38
+ const maybeOptionsTable = rest[0];
39
+ const globalOptions = (maybeOptionsTable === null || maybeOptionsTable === void 0 ? void 0 : maybeOptionsTable.rowsHash)
40
+ ? parseClickOptions(maybeOptionsTable)
41
+ : {};
42
+ const rows = tableData.raw().slice(1); // Remove header row
43
+ for (const [rawTarget, rawValue] of rows) {
44
+ let element;
45
+ let resolvedValue;
46
+ if (rawTarget.startsWith("@")) {
47
+ element = this.data[rawTarget.slice(1)];
48
+ if (!element)
49
+ throw new Error(`No element found for alias: ${rawTarget}`);
50
+ }
51
+ else if (await this.page.locator(rawTarget).count()) {
52
+ element = this.page.locator(rawTarget);
53
+ }
54
+ else {
55
+ element = this.page.getByText(rawTarget, { exact: true }).first();
56
+ }
57
+ if (!element)
58
+ throw new Error(`Unable to resolve element for target: ${rawTarget}`);
59
+ await element.waitFor({ state: "visible", timeout: 7000 });
60
+ if (rawValue.startsWith("@")) {
61
+ resolvedValue = this.data[rawValue.slice(1)];
62
+ if (!resolvedValue)
63
+ throw new Error(`No value found for alias: ${rawValue}`);
64
+ }
65
+ else {
66
+ resolvedValue = evaluateFaker(rawValue);
67
+ }
68
+ if (resolvedValue === "Click") {
69
+ await element.click(globalOptions);
70
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `๐Ÿ–ฑ๏ธ Clicked on "${rawTarget}"`);
71
+ }
72
+ else if (rawTarget.includes('input[type="file"]')) {
73
+ const filePath = path.resolve("test-data", resolvedValue);
74
+ if (!fs.existsSync(filePath))
75
+ throw new Error(`File not found: ${filePath}`);
76
+ await element.setInputFiles(filePath);
77
+ (_b = this.log) === null || _b === void 0 ? void 0 : _b.call(this, `๐Ÿ“ Uploaded file to "${rawTarget}": ${resolvedValue}`);
78
+ }
79
+ else {
80
+ const keyPattern = /{(\w+)}/g;
81
+ const matches = [...resolvedValue.matchAll(keyPattern)];
82
+ const keys = matches.map((m) => m[1]);
83
+ const inputText = resolvedValue.replace(keyPattern, "").trim();
84
+ const fillOptions = (maybeOptionsTable === null || maybeOptionsTable === void 0 ? void 0 : maybeOptionsTable.rowsHash)
85
+ ? parseFillOptions(maybeOptionsTable)
86
+ : {};
87
+ if (inputText) {
88
+ await element.fill(inputText, fillOptions);
89
+ (_c = this.log) === null || _c === void 0 ? void 0 : _c.call(this, `โŒจ๏ธ Filled "${rawTarget}" with: ${inputText}`);
90
+ }
91
+ for (const key of keys) {
92
+ await element.focus();
93
+ await this.page.waitForTimeout(200);
94
+ await element.press(key);
95
+ (_d = this.log) === null || _d === void 0 ? void 0 : _d.call(this, `๐ŸŽน Pressed {${key}} on "${rawTarget}"`);
96
+ }
97
+ }
98
+ await expect(element).toBeVisible();
99
+ }
100
+ });
101
+ const typeStep = async function (textOrAlias, ...rest) {
102
+ var _a, _b;
103
+ if (!this.element)
104
+ throw new Error("No element selected");
105
+ const maybeTable = rest[0];
106
+ const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseFillOptions(maybeTable) : {};
107
+ const text = textOrAlias.startsWith("@")
108
+ ? (_a = this.data[textOrAlias.slice(1)]) !== null && _a !== void 0 ? _a : (() => {
109
+ throw new Error(`No value found for alias "${textOrAlias}"`);
110
+ })()
111
+ : evaluateFaker(textOrAlias);
112
+ await this.element.fill("");
113
+ await this.element.fill(text, options);
114
+ this.data.lastTyped = text;
115
+ (_b = this.log) === null || _b === void 0 ? void 0 : _b.call(this, `โŒจ๏ธ Typed "${text}" into selected element`);
116
+ };
117
+ When("I type {string}", typeStep);
118
+ When("I type stored {string}", typeStep);
119
+ When("I type random {string}", typeStep);
120
+ When("I set value {string}", async function (valueOrAlias, ...rest) {
121
+ var _a, _b;
122
+ if (!this.element)
123
+ throw new Error("No element selected");
124
+ const maybeTable = rest[0];
125
+ const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseFillOptions(maybeTable) : {};
126
+ const value = valueOrAlias.startsWith("@")
127
+ ? (_a = this.data[valueOrAlias.slice(1)]) !== null && _a !== void 0 ? _a : (() => {
128
+ throw new Error(`No value found for alias "${valueOrAlias}"`);
129
+ })()
130
+ : evaluateFaker(valueOrAlias);
131
+ await this.element.fill(value, options);
132
+ this.data.lastValueSet = value;
133
+ (_b = this.log) === null || _b === void 0 ? void 0 : _b.call(this, `๐Ÿ“ Set value to "${value}"`);
134
+ });
135
+ When("I clear", async function () {
136
+ var _a;
137
+ if (!this.element)
138
+ throw new Error("No element selected");
139
+ await this.element.fill("");
140
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, "๐Ÿงผ Cleared value of selected element");
141
+ });
142
+ When("I submit", async function (...rest) {
143
+ var _a, _b;
144
+ const maybeTable = rest[0];
145
+ const form = (_a = this.element) !== null && _a !== void 0 ? _a : this.page.locator("form");
146
+ await form.evaluate((f) => f.submit());
147
+ (_b = this.log) === null || _b === void 0 ? void 0 : _b.call(this, "๐Ÿ“จ Submitted form");
148
+ });
149
+ When("I select option {string}", async function (option, ...rest) {
150
+ var _a;
151
+ if (!this.element)
152
+ throw new Error("No select element stored");
153
+ const maybeTable = rest[0];
154
+ const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseSelectOptions(maybeTable) : {};
155
+ await this.element.selectOption({ label: option }, options);
156
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `๐Ÿ”ฝ Selected option "${option}"`);
157
+ });
158
+ When("I select file {string}", async function (filePath, ...rest) {
159
+ var _a;
160
+ if (!this.element)
161
+ throw new Error("No file input selected");
162
+ const maybeTable = rest[0];
163
+ const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseSelectOptions(maybeTable) : {};
164
+ await this.element.setInputFiles(filePath, options);
165
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `๐Ÿ“ Set input file to "${filePath}"`);
166
+ });