playwright-cucumber-ts-steps 0.0.8 → 0.1.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.
@@ -2,45 +2,40 @@
2
2
  import { When } from "@cucumber/cucumber";
3
3
  import { parseClickOptions } from "../helpers/utils/optionsUtils";
4
4
  When("I click", async function (...rest) {
5
- var _a;
6
5
  const maybeTable = rest[0];
7
- const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseClickOptions(maybeTable) : {};
6
+ const options = maybeTable?.rowsHash ? parseClickOptions(maybeTable) : {};
8
7
  if (!this.element)
9
8
  throw new Error("❌ No stored element to click.");
10
9
  await this.element.click(options);
11
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, "🖱️ Clicked on stored element");
10
+ this.log?.("🖱️ Clicked on stored element");
12
11
  });
13
12
  When("I click on button {string}", async function (label, ...rest) {
14
- var _a;
15
13
  const maybeTable = rest[0];
16
- const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseClickOptions(maybeTable) : {};
14
+ const options = maybeTable?.rowsHash ? parseClickOptions(maybeTable) : {};
17
15
  const button = await this.page.getByRole("button", { name: label });
18
16
  await button.click(options);
19
17
  this.element = button;
20
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `🖱️ Clicked on button "${label}"`);
18
+ this.log?.(`🖱️ Clicked on button "${label}"`);
21
19
  });
22
20
  When("I click on link {string}", async function (text, ...rest) {
23
- var _a;
24
21
  const maybeTable = rest[0];
25
- const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseClickOptions(maybeTable) : {};
22
+ const options = maybeTable?.rowsHash ? parseClickOptions(maybeTable) : {};
26
23
  const link = await this.page.getByRole("link", { name: text });
27
24
  await link.click(options);
28
25
  this.element = link;
29
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `✅ Clicked on link "${text}"`);
26
+ this.log?.(`✅ Clicked on link "${text}"`);
30
27
  });
31
28
  When("I click on label {string}", async function (labelText, ...rest) {
32
- var _a;
33
29
  const maybeTable = rest[0];
34
- const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseClickOptions(maybeTable) : {};
30
+ const options = maybeTable?.rowsHash ? parseClickOptions(maybeTable) : {};
35
31
  const label = await this.page.getByLabel(labelText);
36
32
  await label.click(options);
37
33
  this.element = label;
38
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `🏷️ Clicked on label "${labelText}"`);
34
+ this.log?.(`🏷️ Clicked on label "${labelText}"`);
39
35
  });
40
36
  When("I click on text {string}", async function (rawText, ...rest) {
41
- var _a;
42
37
  const maybeTable = rest[0];
43
- const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseClickOptions(maybeTable) : {};
38
+ const options = maybeTable?.rowsHash ? parseClickOptions(maybeTable) : {};
44
39
  let text = rawText;
45
40
  if (rawText.startsWith("@")) {
46
41
  const alias = rawText.slice(1);
@@ -52,22 +47,20 @@ When("I click on text {string}", async function (rawText, ...rest) {
52
47
  await locator.first().waitFor({ state: "visible", timeout: 5000 });
53
48
  await locator.first().click(options);
54
49
  this.element = locator.first();
55
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `🖱️ Clicked on text "${text}"`);
50
+ this.log?.(`🖱️ Clicked on text "${text}"`);
56
51
  });
57
52
  When("I click on exact text {string}", async function (exactText, ...rest) {
58
- var _a;
59
53
  const maybeTable = rest[0];
60
- const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseClickOptions(maybeTable) : {};
54
+ const options = maybeTable?.rowsHash ? parseClickOptions(maybeTable) : {};
61
55
  const locator = this.page.getByText(exactText, { exact: true });
62
56
  await locator.waitFor({ state: "visible", timeout: 5000 });
63
57
  await locator.click(options);
64
58
  this.element = locator;
65
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `🖱️ Clicked on exact text "${exactText}"`);
59
+ this.log?.(`🖱️ Clicked on exact text "${exactText}"`);
66
60
  });
67
61
  When("I click all", async function (...rest) {
68
- var _a, _b;
69
62
  const maybeTable = rest[0];
70
- const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseClickOptions(maybeTable) : {};
63
+ const options = maybeTable?.rowsHash ? parseClickOptions(maybeTable) : {};
71
64
  if (!this.elements)
72
65
  throw new Error("❌ No stored elements to click.");
73
66
  const count = await this.elements.count();
@@ -77,77 +70,68 @@ When("I click all", async function (...rest) {
77
70
  const el = this.elements.nth(i);
78
71
  await el.waitFor({ state: "visible", timeout: 5000 });
79
72
  await el.click(options);
80
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `🖱️ Clicked element #${i + 1}`);
73
+ this.log?.(`🖱️ Clicked element #${i + 1}`);
81
74
  }
82
- (_b = this.log) === null || _b === void 0 ? void 0 : _b.call(this, `✅ Clicked all ${count} elements.`);
75
+ this.log?.(`✅ Clicked all ${count} elements.`);
83
76
  });
84
77
  When("I double click on text {string}", async function (text, ...rest) {
85
- var _a;
86
78
  const maybeTable = rest[0];
87
- const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseClickOptions(maybeTable) : {};
79
+ const options = maybeTable?.rowsHash ? parseClickOptions(maybeTable) : {};
88
80
  const element = this.element || this.page.getByText(text);
89
81
  await element.dblclick(options);
90
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `🖱️ Double-clicked on text "${text}"`);
82
+ this.log?.(`🖱️ Double-clicked on text "${text}"`);
91
83
  });
92
84
  When("I double click position {int} {int}", async function (x, y, ...rest) {
93
- var _a;
94
85
  const maybeTable = rest[0];
95
- const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseClickOptions(maybeTable) : {};
86
+ const options = maybeTable?.rowsHash ? parseClickOptions(maybeTable) : {};
96
87
  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})`);
88
+ this.log?.(`🖱️ Double-clicked at (${x}, ${y})`);
98
89
  });
99
90
  When("I double click", async function (...rest) {
100
- var _a;
101
91
  const maybeTable = rest[0];
102
- const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseClickOptions(maybeTable) : {};
92
+ const options = maybeTable?.rowsHash ? parseClickOptions(maybeTable) : {};
103
93
  if (!this.element)
104
94
  throw new Error("❌ No stored element to double-click.");
105
95
  await this.element.dblclick(options);
106
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, "🖱️ Double-clicked on stored element");
96
+ this.log?.("🖱️ Double-clicked on stored element");
107
97
  });
108
98
  When("I right click", async function (...rest) {
109
- var _a;
110
99
  const maybeTable = rest[0];
111
- const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseClickOptions(maybeTable) : {};
100
+ const options = maybeTable?.rowsHash ? parseClickOptions(maybeTable) : {};
112
101
  if (!this.element)
113
102
  throw new Error("❌ No stored element to right-click.");
114
103
  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");
104
+ this.log?.("🖱️ Right-clicked on stored element");
116
105
  });
117
106
  When("I right click on text {string}", async function (text, ...rest) {
118
- var _a;
119
107
  const maybeTable = rest[0];
120
- const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseClickOptions(maybeTable) : {};
108
+ const options = maybeTable?.rowsHash ? parseClickOptions(maybeTable) : {};
121
109
  const element = this.page.getByText(text);
122
110
  await element.click({ button: "right", ...options });
123
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `🖱️ Right-clicked on text "${text}"`);
111
+ this.log?.(`🖱️ Right-clicked on text "${text}"`);
124
112
  });
125
113
  When("I right click position {int} {int}", async function (x, y, ...rest) {
126
- var _a;
127
114
  const maybeTable = rest[0];
128
- const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseClickOptions(maybeTable) : {};
115
+ const options = maybeTable?.rowsHash ? parseClickOptions(maybeTable) : {};
129
116
  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})`);
117
+ this.log?.(`🖱️ Right-clicked at (${x}, ${y})`);
131
118
  });
132
119
  When("I blur", async function () {
133
- var _a;
134
120
  await this.page.evaluate(() => {
135
121
  const active = document.activeElement;
136
122
  if (active && typeof active.blur === "function") {
137
123
  active.blur();
138
124
  }
139
125
  });
140
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, "🌀 Blurred active element");
126
+ this.log?.("🌀 Blurred active element");
141
127
  });
142
128
  When("I focus", async function () {
143
- var _a;
144
129
  if (!this.element)
145
130
  throw new Error("❌ No stored element to focus.");
146
131
  await this.element.focus();
147
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, "🎯 Focused stored element");
132
+ this.log?.("🎯 Focused stored element");
148
133
  });
149
134
  When("I click all", async function (dataTable) {
150
- var _a, _b;
151
135
  const options = parseClickOptions(dataTable);
152
136
  if (!this.elements) {
153
137
  throw new Error("❌ No elements stored. Use a 'find' step before 'I click all'.");
@@ -160,14 +144,13 @@ When("I click all", async function (dataTable) {
160
144
  const element = this.elements.nth(i);
161
145
  await element.waitFor({ state: "visible", timeout: 5000 });
162
146
  await element.click(options);
163
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `🖱️ Clicked element #${i + 1}`);
147
+ this.log?.(`🖱️ Clicked element #${i + 1}`);
164
148
  }
165
- (_b = this.log) === null || _b === void 0 ? void 0 : _b.call(this, `✅ Clicked all ${count} stored elements.`);
149
+ this.log?.(`✅ Clicked all ${count} stored elements.`);
166
150
  });
167
151
  When(/^I click on selector "([^"]+)"$/, async function (selector) {
168
- var _a;
169
152
  const scope = this.getScope();
170
153
  const element = scope.locator(selector);
171
154
  await element.click();
172
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `🖱️ Clicked on selector: ${selector}`);
155
+ this.log?.(`🖱️ Clicked on selector: ${selector}`);
173
156
  });
@@ -8,10 +8,9 @@ When("I find element by selector {string}", async function (selector) {
8
8
  await expect(this.element).toHaveCount(1);
9
9
  });
10
10
  When("I find elements by selector {string}", async function (selector) {
11
- var _a;
12
11
  this.elements = this.page.locator(selector);
13
12
  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}`);
13
+ this.log?.(`Found ${count} elements with selector ${selector}`);
15
14
  });
16
15
  When("I find element by text {string}", async function (text) {
17
16
  this.element = this.page.getByText(text, { exact: true });
@@ -46,11 +45,10 @@ When("I find element by name {string}", async function (name) {
46
45
  await expect(this.element).toHaveCount(1);
47
46
  });
48
47
  When("I find buttons by text {string}", async function (buttonText) {
49
- var _a, _b;
50
48
  // 🧠 Resolve alias
51
49
  if (buttonText.startsWith("@")) {
52
50
  const alias = buttonText.slice(1);
53
- buttonText = (_a = this.data) === null || _a === void 0 ? void 0 : _a[alias];
51
+ buttonText = this.data?.[alias];
54
52
  if (!buttonText) {
55
53
  throw new Error(`No value found for alias "@${alias}"`);
56
54
  }
@@ -60,7 +58,7 @@ When("I find buttons by text {string}", async function (buttonText) {
60
58
  name: buttonText,
61
59
  exact: false,
62
60
  });
63
- (_b = this.log) === null || _b === void 0 ? void 0 : _b.call(this, `🔘 Stored all buttons matching text "${buttonText}"`);
61
+ this.log?.(`🔘 Stored all buttons matching text "${buttonText}"`);
64
62
  });
65
63
  // =============================
66
64
  // WHEN I GET ELEMENT(S)
@@ -82,7 +80,6 @@ When("I get last element", async function () {
82
80
  this.element = this.elements.last();
83
81
  });
84
82
  When(/^I get (\d+)(?:st|nd|rd|th) element$/, async function (index) {
85
- var _a;
86
83
  if (!this.elements)
87
84
  throw new Error("No elements stored to pick from");
88
85
  const count = await this.elements.count();
@@ -90,17 +87,16 @@ When(/^I get (\d+)(?:st|nd|rd|th) element$/, async function (index) {
90
87
  throw new Error(`Cannot get element ${index} — only ${count} found`);
91
88
  }
92
89
  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`);
90
+ this.log?.(`Selected ${index} element from stored elements`);
94
91
  });
95
92
  When("I find elements by role {string}", async function (role) {
96
- var _a;
97
93
  const locator = this.page.getByRole(role);
98
94
  const count = await locator.count();
99
95
  if (count === 0) {
100
96
  throw new Error(`No elements found with role "${role}"`);
101
97
  }
102
98
  this.elements = locator;
103
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `Stored ${count} elements with role "${role}"`);
99
+ this.log?.(`Stored ${count} elements with role "${role}"`);
104
100
  });
105
101
  // When(
106
102
  // "I get {int}{ordinal} element",
@@ -129,104 +125,87 @@ When("I get focused element", async function () {
129
125
  this.element = (await this.page.evaluateHandle(() => document.activeElement));
130
126
  });
131
127
  When("I store element text as {string}", async function (alias) {
132
- var _a;
133
128
  const element = this.element;
134
129
  if (!element)
135
130
  throw new Error("No element selected");
136
131
  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}"`);
132
+ this.data[alias] = text?.trim();
133
+ this.log?.(`Stored text "${text}" as "${alias}"`);
139
134
  });
140
135
  When("I find textarea by label text {string}", async function (label) {
141
- var _a;
142
136
  this.element = this.page.getByLabel(label);
143
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `Stored textarea with label "${label}"`);
137
+ this.log?.(`Stored textarea with label "${label}"`);
144
138
  });
145
139
  When("I find textarea by placeholder text {string}", async function (placeholder) {
146
- var _a;
147
140
  this.element = this.page.getByPlaceholder(placeholder);
148
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `Stored textarea with placeholder "${placeholder}"`);
141
+ this.log?.(`Stored textarea with placeholder "${placeholder}"`);
149
142
  });
150
143
  When("I find textareas by label text {string}", async function (label) {
151
- var _a;
152
144
  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}"`);
145
+ this.log?.(`Stored multiple textareas with label "${label}"`);
154
146
  });
155
147
  When("I find textarea by name {string}", async function (name) {
156
- var _a;
157
148
  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}"`);
149
+ this.log?.(`Stored textarea with name "${name}"`);
159
150
  });
160
151
  When("I find textareas by ID {string}", async function (id) {
161
- var _a;
162
152
  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}"`);
153
+ this.log?.(`Stored multiple textareas with ID "${id}"`);
164
154
  });
165
155
  When("I find input by ID {string}", async function (id) {
166
- var _a;
167
156
  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}"`);
157
+ this.log?.(`Stored input with ID "${id}"`);
169
158
  });
170
159
  When("I find inputs by ID {string}", async function (id) {
171
- var _a;
172
160
  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}"`);
161
+ this.log?.(`Stored multiple inputs with ID "${id}"`);
174
162
  });
175
163
  When("I find textareas by placeholder text {string}", async function (placeholder) {
176
- var _a;
177
164
  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}"`);
165
+ this.log?.(`Stored multiple textareas with placeholder "${placeholder}"`);
179
166
  });
180
167
  When("I find input by label text {string}", async function (label) {
181
- var _a;
182
168
  this.element = this.page.getByLabel(label);
183
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `Stored input with label "${label}"`);
169
+ this.log?.(`Stored input with label "${label}"`);
184
170
  });
185
171
  When("I find input by name {string}", async function (name) {
186
- var _a;
187
172
  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}"`);
173
+ this.log?.(`Stored input with name "${name}"`);
189
174
  });
190
175
  When("I find input by placeholder text {string}", async function (placeholder) {
191
- var _a;
192
176
  this.element = this.page.getByPlaceholder(placeholder);
193
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `Stored input with placeholder "${placeholder}"`);
177
+ this.log?.(`Stored input with placeholder "${placeholder}"`);
194
178
  });
195
179
  When("I find inputs by name {string}", async function (name) {
196
- var _a;
197
180
  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}"`);
181
+ this.log?.(`Stored multiple inputs with name "${name}"`);
199
182
  });
200
183
  When("I find inputs by placeholder text {string}", async function (placeholder) {
201
- var _a;
202
184
  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}"`);
185
+ this.log?.(`Stored multiple inputs with placeholder "${placeholder}"`);
204
186
  });
205
187
  When("I find inputs by label text {string}", async function (label) {
206
- var _a;
207
188
  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}"`);
189
+ this.log?.(`Stored multiple inputs with label "${label}"`);
209
190
  });
210
191
  When("I find inputs by display value {string}", async function (value) {
211
- var _a, _b;
212
192
  // 🧠 Handle alias
213
193
  if (value.startsWith("@")) {
214
194
  const alias = value.slice(1);
215
- value = (_a = this.data) === null || _a === void 0 ? void 0 : _a[alias];
195
+ value = this.data?.[alias];
216
196
  if (!value) {
217
197
  throw new Error(`No value found for alias "@${alias}"`);
218
198
  }
219
199
  }
220
200
  // 🔍 Find all matching inputs
221
201
  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}"`);
202
+ this.log?.(`📦 Stored multiple inputs with display value "${value}"`);
223
203
  });
224
204
  When("I find input by display value {string}", async function (value) {
225
- var _a, _b;
226
205
  // 🧠 Handle alias
227
206
  if (value.startsWith("@")) {
228
207
  const alias = value.slice(1);
229
- value = (_a = this.data) === null || _a === void 0 ? void 0 : _a[alias];
208
+ value = this.data?.[alias];
230
209
  if (!value) {
231
210
  throw new Error(`No value found for alias "@${alias}"`);
232
211
  }
@@ -235,5 +214,5 @@ When("I find input by display value {string}", async function (value) {
235
214
  const locator = this.page.locator(`input[value="${value}"]`);
236
215
  await expect(locator).toBeVisible({ timeout: 5000 });
237
216
  this.element = locator;
238
- (_b = this.log) === null || _b === void 0 ? void 0 : _b.call(this, `🔍 Found input with value: "${value}"`);
217
+ this.log?.(`🔍 Found input with value: "${value}"`);
239
218
  });
@@ -6,37 +6,34 @@ import fs from "fs";
6
6
  import { evaluateFaker } from "../helpers/utils/fakerUtils";
7
7
  import { parseClickOptions, parseCheckOptions, parseFillOptions, parseSelectOptions, } from "../helpers/utils/optionsUtils";
8
8
  When("I check", async function (...rest) {
9
- var _a, _b;
10
9
  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");
10
+ const options = maybeTable?.rowsHash ? parseCheckOptions(maybeTable) : {};
11
+ await this.element?.check(options);
12
+ this.log?.("✅ Checked stored checkbox");
14
13
  });
15
14
  When("I uncheck", async function (...rest) {
16
- var _a, _b;
17
15
  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");
16
+ const options = maybeTable?.rowsHash ? parseCheckOptions(maybeTable) : {};
17
+ await this.element?.uncheck(options);
18
+ this.log?.("✅ Unchecked stored checkbox");
21
19
  });
22
20
  When("I check input", async function (...rest) {
23
21
  const maybeTable = rest[0];
24
- const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseCheckOptions(maybeTable) : {};
22
+ const options = maybeTable?.rowsHash ? parseCheckOptions(maybeTable) : {};
25
23
  if (!this.element)
26
24
  throw new Error("No input selected");
27
25
  await this.element.check(options);
28
26
  });
29
27
  When("I uncheck input", async function (...rest) {
30
28
  const maybeTable = rest[0];
31
- const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseCheckOptions(maybeTable) : {};
29
+ const options = maybeTable?.rowsHash ? parseCheckOptions(maybeTable) : {};
32
30
  if (!this.element)
33
31
  throw new Error("No input selected");
34
32
  await this.element.uncheck(options);
35
33
  });
36
34
  When("I fill the following {string} form data:", async function (_formName, tableData, ...rest) {
37
- var _a, _b, _c, _d;
38
35
  const maybeOptionsTable = rest[0];
39
- const globalOptions = (maybeOptionsTable === null || maybeOptionsTable === void 0 ? void 0 : maybeOptionsTable.rowsHash)
36
+ const globalOptions = maybeOptionsTable?.rowsHash
40
37
  ? parseClickOptions(maybeOptionsTable)
41
38
  : {};
42
39
  const rows = tableData.raw().slice(1); // Remove header row
@@ -67,100 +64,96 @@ When("I fill the following {string} form data:", async function (_formName, tabl
67
64
  }
68
65
  if (resolvedValue === "Click") {
69
66
  await element.click(globalOptions);
70
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `🖱️ Clicked on "${rawTarget}"`);
67
+ this.log?.(`🖱️ Clicked on "${rawTarget}"`);
71
68
  }
72
69
  else if (rawTarget.includes('input[type="file"]')) {
73
70
  const filePath = path.resolve("test-data", resolvedValue);
74
71
  if (!fs.existsSync(filePath))
75
72
  throw new Error(`File not found: ${filePath}`);
76
73
  await element.setInputFiles(filePath);
77
- (_b = this.log) === null || _b === void 0 ? void 0 : _b.call(this, `📁 Uploaded file to "${rawTarget}": ${resolvedValue}`);
74
+ this.log?.(`📁 Uploaded file to "${rawTarget}": ${resolvedValue}`);
78
75
  }
79
76
  else {
80
77
  const keyPattern = /{(\w+)}/g;
81
78
  const matches = [...resolvedValue.matchAll(keyPattern)];
82
79
  const keys = matches.map((m) => m[1]);
83
80
  const inputText = resolvedValue.replace(keyPattern, "").trim();
84
- const fillOptions = (maybeOptionsTable === null || maybeOptionsTable === void 0 ? void 0 : maybeOptionsTable.rowsHash)
81
+ const fillOptions = maybeOptionsTable?.rowsHash
85
82
  ? parseFillOptions(maybeOptionsTable)
86
83
  : {};
87
84
  if (inputText) {
88
85
  await element.fill(inputText, fillOptions);
89
- (_c = this.log) === null || _c === void 0 ? void 0 : _c.call(this, `⌨️ Filled "${rawTarget}" with: ${inputText}`);
86
+ this.log?.(`⌨️ Filled "${rawTarget}" with: ${inputText}`);
90
87
  }
91
88
  for (const key of keys) {
92
89
  await element.focus();
93
90
  await this.page.waitForTimeout(200);
94
91
  await element.press(key);
95
- (_d = this.log) === null || _d === void 0 ? void 0 : _d.call(this, `🎹 Pressed {${key}} on "${rawTarget}"`);
92
+ this.log?.(`🎹 Pressed {${key}} on "${rawTarget}"`);
96
93
  }
97
94
  }
98
95
  await expect(element).toBeVisible();
99
96
  }
100
97
  });
101
98
  const typeStep = async function (textOrAlias, ...rest) {
102
- var _a, _b;
103
99
  if (!this.element)
104
100
  throw new Error("No element selected");
105
101
  const maybeTable = rest[0];
106
- const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseFillOptions(maybeTable) : {};
102
+ const options = maybeTable?.rowsHash ? parseFillOptions(maybeTable) : {};
107
103
  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
- })()
104
+ ? this.data[textOrAlias.slice(1)] ??
105
+ (() => {
106
+ throw new Error(`No value found for alias "${textOrAlias}"`);
107
+ })()
111
108
  : evaluateFaker(textOrAlias);
112
109
  await this.element.fill("");
113
110
  await this.element.fill(text, options);
114
111
  this.data.lastTyped = text;
115
- (_b = this.log) === null || _b === void 0 ? void 0 : _b.call(this, `⌨️ Typed "${text}" into selected element`);
112
+ this.log?.(`⌨️ Typed "${text}" into selected element`);
116
113
  };
117
114
  When("I type {string}", typeStep);
118
115
  When("I type stored {string}", typeStep);
119
116
  When("I type random {string}", typeStep);
120
117
  When("I set value {string}", async function (valueOrAlias, ...rest) {
121
- var _a, _b;
122
118
  if (!this.element)
123
119
  throw new Error("No element selected");
124
120
  const maybeTable = rest[0];
125
- const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseFillOptions(maybeTable) : {};
121
+ const options = maybeTable?.rowsHash ? parseFillOptions(maybeTable) : {};
126
122
  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
- })()
123
+ ? this.data[valueOrAlias.slice(1)] ??
124
+ (() => {
125
+ throw new Error(`No value found for alias "${valueOrAlias}"`);
126
+ })()
130
127
  : evaluateFaker(valueOrAlias);
131
128
  await this.element.fill(value, options);
132
129
  this.data.lastValueSet = value;
133
- (_b = this.log) === null || _b === void 0 ? void 0 : _b.call(this, `📝 Set value to "${value}"`);
130
+ this.log?.(`📝 Set value to "${value}"`);
134
131
  });
135
132
  When("I clear", async function () {
136
- var _a;
137
133
  if (!this.element)
138
134
  throw new Error("No element selected");
139
135
  await this.element.fill("");
140
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, "🧼 Cleared value of selected element");
136
+ this.log?.("🧼 Cleared value of selected element");
141
137
  });
142
138
  When("I submit", async function (...rest) {
143
- var _a, _b;
144
139
  const maybeTable = rest[0];
145
- const form = (_a = this.element) !== null && _a !== void 0 ? _a : this.page.locator("form");
140
+ const form = this.element ?? this.page.locator("form");
146
141
  await form.evaluate((f) => f.submit());
147
- (_b = this.log) === null || _b === void 0 ? void 0 : _b.call(this, "📨 Submitted form");
142
+ this.log?.("📨 Submitted form");
148
143
  });
149
144
  When("I select option {string}", async function (option, ...rest) {
150
- var _a;
151
145
  if (!this.element)
152
146
  throw new Error("No select element stored");
153
147
  const maybeTable = rest[0];
154
- const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseSelectOptions(maybeTable) : {};
148
+ const options = maybeTable?.rowsHash ? parseSelectOptions(maybeTable) : {};
155
149
  await this.element.selectOption({ label: option }, options);
156
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `🔽 Selected option "${option}"`);
150
+ this.log?.(`🔽 Selected option "${option}"`);
157
151
  });
158
152
  When("I select file {string}", async function (filePath, ...rest) {
159
- var _a;
160
153
  if (!this.element)
161
154
  throw new Error("No file input selected");
162
155
  const maybeTable = rest[0];
163
- const options = (maybeTable === null || maybeTable === void 0 ? void 0 : maybeTable.rowsHash) ? parseSelectOptions(maybeTable) : {};
156
+ const options = maybeTable?.rowsHash ? parseSelectOptions(maybeTable) : {};
164
157
  await this.element.setInputFiles(filePath, options);
165
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `📁 Set input file to "${filePath}"`);
158
+ this.log?.(`📁 Set input file to "${filePath}"`);
166
159
  });
@@ -84,16 +84,14 @@ When(/^I screenshot "(.*)"$/, async function (name) {
84
84
  });
85
85
  });
86
86
  When("I screenshot", async function () {
87
- var _a;
88
87
  const path = `screenshots/screenshot-${Date.now()}.png`;
89
88
  await this.page.screenshot({ path, fullPage: true });
90
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `Saved screenshot to ${path}`);
89
+ this.log?.(`Saved screenshot to ${path}`);
91
90
  });
92
91
  //
93
92
  // Page Navigation
94
93
  //
95
94
  When("I visit {string}", async function (urlOrAlias) {
96
- var _a;
97
95
  let url = urlOrAlias;
98
96
  if (url.startsWith("@")) {
99
97
  const alias = url.substring(1);
@@ -107,7 +105,7 @@ When("I visit {string}", async function (urlOrAlias) {
107
105
  throw new Error("BASE_URL not defined");
108
106
  url = `${baseUrl.replace(/\/+$/, "")}${url}`;
109
107
  }
110
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `Visiting: ${url}`);
108
+ this.log?.(`Visiting: ${url}`);
111
109
  await this.page.goto(url);
112
110
  });
113
111
  When("I reload the page", async function () {
@@ -142,8 +140,7 @@ const validUnits = [
142
140
  "years",
143
141
  ];
144
142
  When('I store {string} {int} {word} {word} as "{word}"', async function (baseAlias, amount, unit, direction, newAlias) {
145
- var _a, _b;
146
- const baseDateRaw = (_a = this.data) === null || _a === void 0 ? void 0 : _a[baseAlias];
143
+ const baseDateRaw = this.data?.[baseAlias];
147
144
  if (!baseDateRaw)
148
145
  throw new Error(`Alias "${baseAlias}" not found`);
149
146
  if (!validUnits.includes(unit))
@@ -154,35 +151,32 @@ When('I store {string} {int} {word} {word} as "{word}"', async function (baseAli
154
151
  const result = baseDate[direction === "before" ? "subtract" : "add"](amount, unit);
155
152
  const formatted = result.format("YYYY-MM-DD");
156
153
  this.data[newAlias] = formatted;
157
- (_b = this.log) === null || _b === void 0 ? void 0 : _b.call(this, `📅 Stored ${amount} ${unit} ${direction} "${baseAlias}" as "@${newAlias}" = ${formatted}`);
154
+ this.log?.(`📅 Stored ${amount} ${unit} ${direction} "${baseAlias}" as "@${newAlias}" = ${formatted}`);
158
155
  });
159
156
  //
160
157
  // IFrame
161
158
  //
162
159
  When("I switch to iframe with selector {string}", async function (selector) {
163
- var _a;
164
160
  const frameLocator = this.page.frameLocator(selector);
165
161
  await frameLocator
166
162
  .locator("body")
167
163
  .waitFor({ state: "visible", timeout: 10000 });
168
164
  this.frame = frameLocator;
169
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `🪟 Switched to iframe: ${selector}`);
165
+ this.log?.(`🪟 Switched to iframe: ${selector}`);
170
166
  });
171
167
  When("I switch to iframe with title {string}", async function (title) {
172
- var _a;
173
168
  const frames = this.page.frames();
174
169
  const match = frames.find((f) => f.title().then((t) => t.includes(title)));
175
170
  if (!match)
176
171
  throw new Error(`No iframe with title "${title}"`);
177
172
  this.frame = this.page.frameLocator(`iframe[title*="${title}"]`);
178
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `🪟 Switched to iframe titled: ${title}`);
173
+ this.log?.(`🪟 Switched to iframe titled: ${title}`);
179
174
  });
180
175
  When("I switch to iframe with selector {string} and wait for text {string}", async function (selector, expected) {
181
- var _a;
182
176
  const frameLocator = this.page.frameLocator(selector);
183
177
  await frameLocator.locator(`text=${expected}`).waitFor({ timeout: 10000 });
184
178
  this.frame = frameLocator;
185
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `🪟 Switched to iframe: ${selector}, waited for "${expected}"`);
179
+ this.log?.(`🪟 Switched to iframe: ${selector}, waited for "${expected}"`);
186
180
  });
187
181
  When("I exit iframe", function () {
188
182
  this.exitIframe();
@@ -207,8 +201,7 @@ async function getReadableLabel(el) {
207
201
  }
208
202
  }
209
203
  async function getElementsSubset(world, mode, count) {
210
- var _a;
211
- const total = await ((_a = world.elements) === null || _a === void 0 ? void 0 : _a.count());
204
+ const total = await world.elements?.count();
212
205
  if (!total || total < 1)
213
206
  throw new Error("No elements stored");
214
207
  if (count > total)
@@ -243,7 +236,6 @@ const locatorActions = {
243
236
  fill: (el, table) => el.fill("", parseFillOptions(table)), // Extend this to support value
244
237
  };
245
238
  When(/^I (\w+) the (first|last|random) (\d+)$/, async function (action, mode, count, table) {
246
- var _a;
247
239
  const elements = await getElementsSubset(this, mode, count);
248
240
  const actionFn = locatorActions[action];
249
241
  if (!actionFn)
@@ -251,11 +243,10 @@ When(/^I (\w+) the (first|last|random) (\d+)$/, async function (action, mode, co
251
243
  for (const el of elements) {
252
244
  const label = await getReadableLabel(el);
253
245
  await actionFn(el, table);
254
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `✅ ${actionDisplayNames[action] || action} element: "${label}"`);
246
+ this.log?.(`✅ ${actionDisplayNames[action] || action} element: "${label}"`);
255
247
  }
256
248
  });
257
249
  When(/^I (\w+) the (\d+)(?:st|nd|rd|th) element$/, async function (action, nth, table) {
258
- var _a;
259
250
  const elements = await getElementsSubset(this, "nth", nth);
260
251
  const actionFn = locatorActions[action];
261
252
  if (!actionFn)
@@ -263,15 +254,14 @@ When(/^I (\w+) the (\d+)(?:st|nd|rd|th) element$/, async function (action, nth,
263
254
  for (const el of elements) {
264
255
  const label = await getReadableLabel(el);
265
256
  await actionFn(el, table);
266
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `✅ ${actionDisplayNames[action] || action} the ${toOrdinal(nth)} element: "${label}"`);
257
+ this.log?.(`✅ ${actionDisplayNames[action] || action} the ${toOrdinal(nth)} element: "${label}"`);
267
258
  }
268
259
  });
269
260
  When("I press key {string}", async function (key) {
270
- var _a;
271
261
  if (!this.element)
272
262
  throw new Error("No element selected");
273
263
  await this.element.focus();
274
264
  await this.page.waitForTimeout(100); // buffer
275
265
  await this.element.press(key);
276
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `🎹 Pressed {${key}}`);
266
+ this.log?.(`🎹 Pressed {${key}}`);
277
267
  });
@@ -25,7 +25,6 @@ When(/^I scroll window to position top:(\d+) left:(\d+)$/, async function (top,
25
25
  }, top, left);
26
26
  });
27
27
  When('I scroll to "{word}"', async function (direction) {
28
- var _a;
29
28
  const validDirections = ["top", "bottom", "left", "right"];
30
29
  if (!validDirections.includes(direction)) {
31
30
  throw new Error(`Invalid scroll direction "${direction}". Must be one of: ${validDirections.join(", ")}.`);
@@ -50,18 +49,16 @@ When('I scroll to "{word}"', async function (direction) {
50
49
  }
51
50
  window.scrollTo(scrollOptions);
52
51
  }, direction);
53
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `🖱️ Scrolled to "${direction}"`);
52
+ this.log?.(`🖱️ Scrolled to "${direction}"`);
54
53
  await this.page.waitForTimeout(500); // allow scroll to complete
55
54
  });
56
55
  When("I hover over the element {string}", async function (selector) {
57
- var _a;
58
56
  const element = this.getScope().locator(selector);
59
57
  await element.hover();
60
58
  this.element = element;
61
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `🖱️ Hovered: ${selector}`);
59
+ this.log?.(`🖱️ Hovered: ${selector}`);
62
60
  });
63
61
  When("I move mouse to coordinates {int}, {int}", async function (x, y) {
64
- var _a;
65
62
  await this.page.mouse.move(x, y);
66
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `🧭 Mouse moved to (${x}, ${y})`);
63
+ this.log?.(`🧭 Mouse moved to (${x}, ${y})`);
67
64
  });
@@ -37,7 +37,6 @@ When("I clear local storage", async function () {
37
37
  await this.page.evaluate(() => localStorage.clear());
38
38
  });
39
39
  When("I store input text as {string}", async function (alias) {
40
- var _a;
41
40
  const activeElementHandle = await this.page.evaluateHandle(() => document.activeElement);
42
41
  const tagName = await activeElementHandle.evaluate((el) => el ? el.tagName.toLowerCase() : "");
43
42
  if (tagName !== "input" && tagName !== "textarea") {
@@ -45,5 +44,5 @@ When("I store input text as {string}", async function (alias) {
45
44
  }
46
45
  const value = await activeElementHandle.evaluate((el) => el.value);
47
46
  this.data[alias] = value;
48
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `📥 Stored value from input as "${alias}": ${value}`);
47
+ this.log?.(`📥 Stored value from input as "${alias}": ${value}`);
49
48
  });
@@ -52,11 +52,10 @@ Then(/^I do not see button "(.*)"$/, async function (rawText) {
52
52
  * THEN: I see text "Welcome"
53
53
  */
54
54
  Then("I see text {string}", async function (expected) {
55
- var _a;
56
55
  const scope = this.getScope(); // ✅ Supports iframe OR main page
57
56
  const locator = scope.locator(`text=${expected}`);
58
57
  await locator.waitFor({ state: "visible", timeout: 5000 });
59
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `✅ Verified text visible: ${expected}`);
58
+ this.log?.(`✅ Verified text visible: ${expected}`);
60
59
  });
61
60
  /**
62
61
  * THEN: I do not see text "Error"
@@ -118,7 +117,6 @@ Then(/^I do not see text "(.*)"$/, async function (unexpectedText) {
118
117
  // 🆕 Visible Text - Alias for clarity (optional if you want separate steps for naming)
119
118
  //
120
119
  Then("I see {string} in the element", async function (expected) {
121
- var _a;
122
120
  const element = this.element;
123
121
  if (!element)
124
122
  throw new Error("No element selected");
@@ -135,10 +133,9 @@ Then("I see {string} in the element", async function (expected) {
135
133
  if (!textContent)
136
134
  throw new Error("Element has no text content");
137
135
  expect(textContent).toContain(expected);
138
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `Verified "${expected}" in element text`);
136
+ this.log?.(`Verified "${expected}" in element text`);
139
137
  });
140
138
  Then("I see @{word} in the element", async function (alias) {
141
- var _a;
142
139
  const storedValue = this.data[alias];
143
140
  if (!storedValue) {
144
141
  throw new Error(`No value found in data storage under alias "@${alias}".`);
@@ -146,12 +143,11 @@ Then("I see @{word} in the element", async function (alias) {
146
143
  if (!this.element) {
147
144
  throw new Error("No element found. You must get an element before asserting its contents.");
148
145
  }
149
- const actualText = ((_a = (await this.element.textContent())) === null || _a === void 0 ? void 0 : _a.trim()) || "";
146
+ const actualText = (await this.element.textContent())?.trim() || "";
150
147
  expect(actualText).toContain(storedValue);
151
148
  this.log(`Verified element contains value from "@${alias}" = "${storedValue}". Actual: "${actualText}"`);
152
149
  });
153
150
  Then("I see button {string} is disabled", async function (rawText) {
154
- var _a;
155
151
  // Resolve alias
156
152
  let buttonText = rawText.startsWith("@")
157
153
  ? this.data[rawText.slice(1)]
@@ -168,5 +164,5 @@ Then("I see button {string} is disabled", async function (rawText) {
168
164
  if (!isDisabled) {
169
165
  throw new Error(`🚫 Button "${buttonText}" is not disabled as expected.`);
170
166
  }
171
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `✅ Verified button "${buttonText}" is disabled.`);
167
+ this.log?.(`✅ Verified button "${buttonText}" is disabled.`);
172
168
  });
@@ -8,18 +8,16 @@ Then(/^I see element "([^"]+)" exists$/, async function (selector) {
8
8
  await expect(el).toHaveCount(1);
9
9
  });
10
10
  Then("I see element exists", async function () {
11
- var _a, _b, _c;
12
11
  if (!this.element)
13
12
  throw new Error("No element stored in context");
14
- const count = (_c = (await ((_b = (_a = this.element).count) === null || _b === void 0 ? void 0 : _b.call(_a)))) !== null && _c !== void 0 ? _c : 1;
13
+ const count = (await this.element.count?.()) ?? 1;
15
14
  if (count === 0)
16
15
  throw new Error("Element does not exist");
17
16
  });
18
17
  Then("I see element does not exist", async function () {
19
- var _a, _b, _c;
20
18
  if (!this.element)
21
19
  throw new Error("No element stored in context");
22
- const count = (_c = (await ((_b = (_a = this.element).count) === null || _b === void 0 ? void 0 : _b.call(_a)))) !== null && _c !== void 0 ? _c : 1;
20
+ const count = (await this.element.count?.()) ?? 1;
23
21
  if (count > 0)
24
22
  throw new Error("Element exists but should not");
25
23
  });
@@ -70,13 +68,13 @@ Then("I see element attribute {string} contains {string}", async function (attr,
70
68
  if (!this.element)
71
69
  throw new Error("No element in context");
72
70
  const value = await this.element.getAttribute(attr);
73
- if (!(value === null || value === void 0 ? void 0 : value.includes(part))) {
71
+ if (!value?.includes(part)) {
74
72
  throw new Error(`Attribute "${attr}" does not contain "${part}". Got: "${value}"`);
75
73
  }
76
74
  });
77
75
  Then(/^I see element "([^"]+)" attribute "([^"]+)" contains "(.*)"$/, async function (selector, attribute, substring) {
78
76
  const attr = await this.page.locator(selector).getAttribute(attribute);
79
- expect(attr === null || attr === void 0 ? void 0 : attr.includes(substring)).toBeTruthy();
77
+ expect(attr?.includes(substring)).toBeTruthy();
80
78
  });
81
79
  Then(/^I see element "([^"]+)" has attribute "([^"]+)"$/, async function (selector, attribute) {
82
80
  const attr = await this.page.locator(selector).getAttribute(attribute);
@@ -2,13 +2,11 @@ import { Then } from "@cucumber/cucumber";
2
2
  import { expect } from "@playwright/test";
3
3
  // Accessing the Last Response
4
4
  Then("I should see response status {int}", function (expectedStatus) {
5
- var _a;
6
- expect((_a = this.data.lastResponse) === null || _a === void 0 ? void 0 : _a.status).toBe(expectedStatus);
5
+ expect(this.data.lastResponse?.status).toBe(expectedStatus);
7
6
  this.log(`Verified response status is ${expectedStatus}`);
8
7
  });
9
8
  Then("I should see response body contains {string}", function (expectedText) {
10
- var _a;
11
- expect((_a = this.data.lastResponse) === null || _a === void 0 ? void 0 : _a.body).toContain(expectedText);
9
+ expect(this.data.lastResponse?.body).toContain(expectedText);
12
10
  this.log(`Verified response body contains "${expectedText}"`);
13
11
  });
14
12
  Then("I see response body {string}", async function (expected) {
@@ -173,7 +171,12 @@ Then("I see response body is JSON", async function () {
173
171
  this.log(`Verified response body is valid JSON`);
174
172
  }
175
173
  catch (e) {
176
- throw new Error(`Response body is not valid JSON: ${e.message}`);
174
+ if (e instanceof Error) {
175
+ throw new Error(`Response body is not valid JSON: ${e.message}`);
176
+ }
177
+ else {
178
+ throw new Error(`Response body is not valid JSON: ${String(e)}`);
179
+ }
177
180
  }
178
181
  });
179
182
  Then("I see response body is not JSON", async function () {
@@ -186,6 +189,11 @@ Then("I see response body is not JSON", async function () {
186
189
  throw new Error(`Expected response body to not be JSON, but it is`);
187
190
  }
188
191
  catch (e) {
189
- this.log(`Verified response body is not JSON: ${e.message}`);
192
+ if (e instanceof Error) {
193
+ this.log(`Verified response body is not JSON: ${e.message}`);
194
+ }
195
+ else {
196
+ this.log(`Verified response body is not JSON: ${String(e)}`);
197
+ }
190
198
  }
191
199
  });
@@ -40,7 +40,6 @@ Then("I do not see session storage item {string}", async function (key) {
40
40
  throw new Error(`Expected sessionStorage["${key}"] to be null, but got "${value}"`);
41
41
  });
42
42
  When("I clear all saved session files", async function () {
43
- var _a, _b;
44
43
  const authDir = path.resolve("e2e/support/helper/auth");
45
44
  if (fs.existsSync(authDir)) {
46
45
  const files = fs.readdirSync(authDir);
@@ -48,12 +47,12 @@ When("I clear all saved session files", async function () {
48
47
  const filePath = path.join(authDir, file);
49
48
  if (fs.lstatSync(filePath).isFile()) {
50
49
  fs.unlinkSync(filePath);
51
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `🧹 Deleted session file: ${file}`);
50
+ this.log?.(`🧹 Deleted session file: ${file}`);
52
51
  }
53
52
  }
54
53
  }
55
54
  else {
56
- (_b = this.log) === null || _b === void 0 ? void 0 : _b.call(this, `⚠️ Auth directory not found at ${authDir}`);
55
+ this.log?.(`⚠️ Auth directory not found at ${authDir}`);
57
56
  }
58
57
  });
59
58
  Then("I see session storage item {string} equals {string}", async function (key, expected) {
@@ -16,7 +16,6 @@ function getSnapshotPaths(name) {
16
16
  };
17
17
  }
18
18
  Then("I should see the page matches the snapshot {string}", async function (name) {
19
- var _a, _b;
20
19
  const { page } = this;
21
20
  const paths = getSnapshotPaths(name);
22
21
  fs.mkdirSync(BASELINE_DIR, { recursive: true });
@@ -25,7 +24,7 @@ Then("I should see the page matches the snapshot {string}", async function (name
25
24
  await page.screenshot({ path: paths.current, fullPage: true });
26
25
  if (!fs.existsSync(paths.baseline)) {
27
26
  fs.copyFileSync(paths.current, paths.baseline);
28
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `📸 Created baseline snapshot: ${paths.baseline}`);
27
+ this.log?.(`📸 Created baseline snapshot: ${paths.baseline}`);
29
28
  return;
30
29
  }
31
30
  const baseline = PNG.sync.read(fs.readFileSync(paths.baseline));
@@ -35,20 +34,18 @@ Then("I should see the page matches the snapshot {string}", async function (name
35
34
  const pixelDiff = pixelmatch(baseline.data, current.data, diff.data, width, height, { threshold: 0.1 });
36
35
  if (pixelDiff > 0) {
37
36
  fs.writeFileSync(paths.diff, PNG.sync.write(diff));
38
- (_b = this.log) === null || _b === void 0 ? void 0 : _b.call(this, `❌ Visual mismatch detected, diff: ${paths.diff}`);
37
+ this.log?.(`❌ Visual mismatch detected, diff: ${paths.diff}`);
39
38
  }
40
39
  expect(pixelDiff, "Pixels that differ").toBe(0);
41
40
  });
42
41
  Then("I capture a snapshot of the element {string} as {string}", async function (selector, alias) {
43
- var _a;
44
42
  const element = this.getScope().locator(selector);
45
43
  const pathCurrent = path.join(CURRENT_DIR, `${alias}.png`);
46
44
  fs.mkdirSync(CURRENT_DIR, { recursive: true });
47
45
  await element.screenshot({ path: pathCurrent });
48
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `📸 Snapshot for ${selector} saved as ${alias}`);
46
+ this.log?.(`📸 Snapshot for ${selector} saved as ${alias}`);
49
47
  });
50
48
  Then("The snapshot {string} should match baseline", async function (alias) {
51
- var _a, _b;
52
49
  const paths = getSnapshotPaths(alias);
53
50
  const current = PNG.sync.read(fs.readFileSync(paths.current));
54
51
  const baseline = fs.existsSync(paths.baseline)
@@ -56,7 +53,7 @@ Then("The snapshot {string} should match baseline", async function (alias) {
56
53
  : null;
57
54
  if (!baseline) {
58
55
  fs.copyFileSync(paths.current, paths.baseline);
59
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `📸 Created new baseline for ${alias}`);
56
+ this.log?.(`📸 Created new baseline for ${alias}`);
60
57
  return;
61
58
  }
62
59
  const { width, height } = baseline;
@@ -64,7 +61,7 @@ Then("The snapshot {string} should match baseline", async function (alias) {
64
61
  const pixelDiff = pixelmatch(baseline.data, current.data, diff.data, width, height, { threshold: 0.1 });
65
62
  if (pixelDiff > 0) {
66
63
  fs.writeFileSync(paths.diff, PNG.sync.write(diff));
67
- (_b = this.log) === null || _b === void 0 ? void 0 : _b.call(this, `⚠️ Snapshot mismatch: ${alias}`);
64
+ this.log?.(`⚠️ Snapshot mismatch: ${alias}`);
68
65
  }
69
66
  expect(pixelDiff).toBe(0);
70
67
  });
@@ -6,10 +6,9 @@ import { resolveValue, deriveSessionName, resolveLoginValue, } from "../helpers/
6
6
  import fs from "fs";
7
7
  import { log } from "console";
8
8
  async function tryRestoreSession(world, sessionName) {
9
- var _a;
10
9
  const storagePath = path.resolve("e2e/support/helper/auth", `${sessionName}.json`);
11
10
  if (fs.existsSync(storagePath)) {
12
- await ((_a = world.context) === null || _a === void 0 ? void 0 : _a.addCookies([]));
11
+ await world.context?.addCookies([]);
13
12
  await world.page.context().addInitScript(() => {
14
13
  // preload logic if needed
15
14
  });
@@ -91,15 +90,14 @@ When("I login as {string} user", async function (alias) {
91
90
  this.log(`💾 Saved session to ${alias}User.json`);
92
91
  });
93
92
  When("I perform login with:", async function (dataTable) {
94
- var _a, _b, _c;
95
93
  const loginData = Object.fromEntries(dataTable.raw());
96
94
  const email = resolveLoginValue(loginData.email, this);
97
- const password = (_a = resolveLoginValue(loginData.password, this)) !== null && _a !== void 0 ? _a : process.env.USER_PASSWORD;
95
+ const password = resolveLoginValue(loginData.password, this) ?? process.env.USER_PASSWORD;
98
96
  if (!email)
99
97
  throw new Error("Missing or invalid email for login");
100
98
  if (!password)
101
99
  throw new Error("Missing or invalid password for login");
102
- (_b = this.log) === null || _b === void 0 ? void 0 : _b.call(this, `🔐 Logging in with: ${email}`);
100
+ this.log?.(`🔐 Logging in with: ${email}`);
103
101
  await this.page.goto(`${process.env.BASE_URL}/login`);
104
102
  await this.page.waitForLoadState("networkidle");
105
103
  await this.page.fill('input[type="email"]', email);
@@ -107,10 +105,9 @@ When("I perform login with:", async function (dataTable) {
107
105
  const loginButton = this.page.getByRole("button", { name: /login/i });
108
106
  await loginButton.click();
109
107
  await this.page.waitForLoadState("networkidle");
110
- (_c = this.log) === null || _c === void 0 ? void 0 : _c.call(this, "✅ Login successful");
108
+ this.log?.("✅ Login successful");
111
109
  });
112
110
  async function pageLogin(world, baseUrl, email, password) {
113
- var _a;
114
111
  const { page } = world;
115
112
  await page.goto(baseUrl);
116
113
  await page.waitForLoadState("networkidle");
@@ -131,7 +128,7 @@ async function pageLogin(world, baseUrl, email, password) {
131
128
  path: path.resolve("e2e/support/helper/auth", "session.json"),
132
129
  });
133
130
  world.data["loggedIn"] = true;
134
- (_a = world.log) === null || _a === void 0 ? void 0 : _a.call(world, "✅ Logged in and session saved.");
131
+ world.log?.("✅ Logged in and session saved.");
135
132
  }
136
133
  else {
137
134
  console.log("Already logged in");
@@ -35,11 +35,10 @@ BeforeAll(async () => {
35
35
  console.log("🚀 Launched shared browser for all scenarios");
36
36
  });
37
37
  AfterAll(async () => {
38
- await (sharedBrowser === null || sharedBrowser === void 0 ? void 0 : sharedBrowser.close());
38
+ await sharedBrowser?.close();
39
39
  console.log("🧹 Closed shared browser after all scenarios");
40
40
  });
41
41
  Before(async function (scenario) {
42
- var _a, _b;
43
42
  // 🛡️ Ensure browser is still usable
44
43
  if (!sharedBrowser || !sharedBrowser.isConnected()) {
45
44
  console.warn("⚠️ Shared browser was disconnected. Restarting...");
@@ -57,7 +56,7 @@ Before(async function (scenario) {
57
56
  };
58
57
  if (fs.existsSync(SESSION_FILE)) {
59
58
  contextOptions.storageState = SESSION_FILE;
60
- (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, "✅ Reusing session from saved file.");
59
+ this.log?.("✅ Reusing session from saved file.");
61
60
  }
62
61
  const context = await sharedBrowser.newContext(contextOptions);
63
62
  const page = await context.newPage();
@@ -65,11 +64,10 @@ Before(async function (scenario) {
65
64
  this.context = context;
66
65
  this.page = page;
67
66
  if (isMobile)
68
- (_b = this.log) === null || _b === void 0 ? void 0 : _b.call(this, "📱 Mobile emulation enabled (iPhone 13 Pro)");
67
+ this.log?.("📱 Mobile emulation enabled (iPhone 13 Pro)");
69
68
  });
70
69
  After(async function (scenario) {
71
- var _a, _b, _c;
72
- const failed = ((_a = scenario.result) === null || _a === void 0 ? void 0 : _a.status) === "FAILED";
70
+ const failed = scenario.result?.status === "FAILED";
73
71
  const name = scenario.pickle.name.replace(/[^a-z0-9]+/gi, "_").toLowerCase();
74
72
  // 📸 Screenshot on failure
75
73
  if (failed && this.page) {
@@ -86,7 +84,7 @@ After(async function (scenario) {
86
84
  // 🎥 Handle video recording
87
85
  let rawPath;
88
86
  try {
89
- rawPath = await ((_c = (_b = this.page) === null || _b === void 0 ? void 0 : _b.video()) === null || _c === void 0 ? void 0 : _c.path());
87
+ rawPath = await this.page?.video()?.path();
90
88
  }
91
89
  catch (err) {
92
90
  console.warn(`⚠️ Unable to access video path: ${err.message}`);
@@ -17,7 +17,7 @@ export class CustomWorld extends World {
17
17
  };
18
18
  }
19
19
  async init(testInfo) {
20
- const isMobile = testInfo === null || testInfo === void 0 ? void 0 : testInfo.pickle.tags.some((tag) => tag.name === "@mobile");
20
+ const isMobile = testInfo?.pickle.tags.some((tag) => tag.name === "@mobile");
21
21
  const device = isMobile ? devices["Pixel 5"] : undefined;
22
22
  this.browser = await chromium.launch({ headless: isHeadless, slowMo });
23
23
  this.context = await this.browser.newContext({
@@ -25,34 +25,32 @@ export class CustomWorld extends World {
25
25
  recordVideo: { dir: "e2e/test-artifacts/videos" },
26
26
  });
27
27
  this.page = await this.context.newPage();
28
- this.testName = testInfo === null || testInfo === void 0 ? void 0 : testInfo.pickle.name;
28
+ this.testName = testInfo?.pickle.name;
29
29
  this.log(`🧪 Initialized context${isMobile ? " (mobile)" : ""}`);
30
30
  }
31
31
  getScope() {
32
- var _a;
33
- return (_a = this.frame) !== null && _a !== void 0 ? _a : this.page;
32
+ return this.frame ?? this.page;
34
33
  }
35
34
  exitIframe() {
36
35
  this.frame = undefined;
37
36
  this.log("⬅️ Exited iframe, scope is now main page");
38
37
  }
39
38
  async cleanup(testInfo) {
40
- var _a, _b, _c, _d;
41
- const failed = ((_a = testInfo === null || testInfo === void 0 ? void 0 : testInfo.result) === null || _a === void 0 ? void 0 : _a.status) === "FAILED";
39
+ const failed = testInfo?.result?.status === "FAILED";
42
40
  try {
43
- await ((_b = this.page) === null || _b === void 0 ? void 0 : _b.close());
41
+ await this.page?.close();
44
42
  }
45
43
  catch (err) {
46
44
  this.log(`⚠️ Error closing page: ${err.message}`);
47
45
  }
48
46
  try {
49
- await ((_c = this.context) === null || _c === void 0 ? void 0 : _c.close());
47
+ await this.context?.close();
50
48
  }
51
49
  catch (err) {
52
50
  this.log(`⚠️ Error closing context: ${err.message}`);
53
51
  }
54
52
  try {
55
- await ((_d = this.browser) === null || _d === void 0 ? void 0 : _d.close());
53
+ await this.browser?.close();
56
54
  }
57
55
  catch (err) {
58
56
  this.log(`⚠️ Error closing browser: ${err.message}`);
package/dist/index.d.ts CHANGED
@@ -8,19 +8,19 @@ export * from "./actions/miscSteps";
8
8
  export * from "./actions/mouseSteps";
9
9
  export * from "./actions/scrollSteps";
10
10
  export * from "./actions/storageSteps";
11
- export * from "./assertions/button_and_text_visibility";
11
+ export * from "./assertions/buttonAndTextVisibilitySteps";
12
12
  export * from "./assertions/cookieSteps";
13
13
  export * from "./assertions/elementSteps";
14
14
  export * from "./assertions/formInputSteps";
15
- export * from "./assertions/InterceptionRequests";
15
+ export * from "./assertions/interceptionRequestsSteps";
16
16
  export * from "./assertions/locationSteps";
17
17
  export * from "./assertions/roleTestIdSteps";
18
18
  export * from "./assertions/semanticSteps";
19
19
  export * from "./assertions/storageSteps";
20
20
  export * from "./assertions/visualSteps";
21
- export * from "./custom_setups/global-login";
22
- export * from "./custom_setups/loginHooks";
23
21
  export * from "./iframes/frames";
22
+ export * from "./custom_setups/globalLogin";
23
+ export * from "./custom_setups/loginHooks";
24
24
  export * from "./helpers/compareSnapshots";
25
25
  export * from "./helpers/hooks";
26
26
  export * from "./helpers/utils";
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- //src/index.ts
1
+ // Actions
2
2
  export * from "./actions/clickSteps";
3
3
  export * from "./actions/cookieSteps";
4
4
  export * from "./actions/debugSteps";
@@ -9,20 +9,23 @@ export * from "./actions/miscSteps";
9
9
  export * from "./actions/mouseSteps";
10
10
  export * from "./actions/scrollSteps";
11
11
  export * from "./actions/storageSteps";
12
- export * from "./assertions/button_and_text_visibility";
12
+ // Assertions
13
+ export * from "./assertions/buttonAndTextVisibilitySteps";
13
14
  export * from "./assertions/cookieSteps";
14
15
  export * from "./assertions/elementSteps";
15
16
  export * from "./assertions/formInputSteps";
16
- export * from "./assertions/InterceptionRequests";
17
+ export * from "./assertions/interceptionRequestsSteps";
17
18
  export * from "./assertions/locationSteps";
18
19
  export * from "./assertions/roleTestIdSteps";
19
20
  export * from "./assertions/semanticSteps";
20
21
  export * from "./assertions/storageSteps";
21
22
  export * from "./assertions/visualSteps";
22
- export * from "./custom_setups/global-login";
23
- export * from "./custom_setups/loginHooks";
23
+ // Iframes
24
24
  export * from "./iframes/frames";
25
- // Export core utilities and helpers
25
+ // Setup (custom hooks, login, etc.)
26
+ export * from "./custom_setups/globalLogin";
27
+ export * from "./custom_setups/loginHooks";
28
+ // Core helpers and utilities
26
29
  export * from "./helpers/compareSnapshots";
27
30
  export * from "./helpers/hooks";
28
31
  export * from "./helpers/utils";
package/package.json CHANGED
@@ -1,10 +1,26 @@
1
1
  {
2
2
  "name": "playwright-cucumber-ts-steps",
3
- "version": "0.0.8",
3
+ "version": "0.1.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": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js"
11
+ },
12
+ "./register": {
13
+ "import": "./dist/register.js"
14
+ }
15
+ },
16
+ "sideEffects": false,
17
+ "typesVersions": {
18
+ "*": {
19
+ "*": [
20
+ "dist/*"
21
+ ]
22
+ }
23
+ },
8
24
  "scripts": {
9
25
  "build": "tsc"
10
26
  },