playwright-cucumber-ts-steps 0.0.8 → 0.0.9

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.
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,172 @@
1
+ import { Then } from "@cucumber/cucumber";
2
+ import { expect } from "@playwright/test";
3
+ import { evaluateFaker } from "../helpers/utils/fakerUtils";
4
+ Then("I count {int} elements", async function (expectedCount) {
5
+ if (!this.elements)
6
+ throw new Error("No elements found to count");
7
+ const count = await this.elements.count();
8
+ await this.page.waitForLoadState("networkidle");
9
+ expect(count).toBe(expectedCount);
10
+ });
11
+ /**
12
+ * THEN: I see button "Submit"
13
+ */
14
+ Then(/^I see button "(.*)"$/, async function (rawText) {
15
+ let buttonText = rawText.startsWith("@")
16
+ ? this.data[rawText.slice(1)]
17
+ : rawText;
18
+ if (!buttonText) {
19
+ throw new Error(`No value found for alias: "${rawText}"`);
20
+ }
21
+ const button = this.page.getByRole("button", {
22
+ name: buttonText,
23
+ exact: false,
24
+ });
25
+ await this.page.waitForLoadState("networkidle");
26
+ await expect(button).toBeVisible();
27
+ });
28
+ /**
29
+ * THEN: I do not see button "Cancel"
30
+ */
31
+ Then(/^I do not see button "(.*)"$/, async function (rawText) {
32
+ let buttonText = rawText.startsWith("@")
33
+ ? this.data[rawText.slice(1)]
34
+ : rawText;
35
+ if (!buttonText) {
36
+ throw new Error(`No value found for alias: "${rawText}"`);
37
+ }
38
+ const button = this.page.getByRole("button", {
39
+ name: buttonText,
40
+ exact: false,
41
+ });
42
+ await this.page.waitForLoadState("networkidle");
43
+ const count = await button.count();
44
+ for (let i = 0; i < count; i++) {
45
+ const item = button.nth(i);
46
+ if (await item.isVisible()) {
47
+ throw new Error(`Button "${buttonText}" is visible but should not be`);
48
+ }
49
+ }
50
+ });
51
+ /**
52
+ * THEN: I see text "Welcome"
53
+ */
54
+ Then("I see text {string}", async function (expected) {
55
+ var _a;
56
+ const scope = this.getScope(); // ✅ Supports iframe OR main page
57
+ const locator = scope.locator(`text=${expected}`);
58
+ await locator.waitFor({ state: "visible", timeout: 5000 });
59
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `✅ Verified text visible: ${expected}`);
60
+ });
61
+ /**
62
+ * THEN: I do not see text "Error"
63
+ */
64
+ Then("I do not see text {string}", async function (text) {
65
+ await this.page.waitForLoadState("networkidle");
66
+ const locator = this.page.locator(`:has-text("${text}")`);
67
+ const count = await locator.count();
68
+ for (let i = 0; i < count; i++) {
69
+ const item = locator.nth(i);
70
+ if (await item.isVisible()) {
71
+ throw new Error(`Text "${text}" is visible but should not be`);
72
+ }
73
+ }
74
+ });
75
+ /**
76
+ * THEN: I see visible text "Dashboard"
77
+ */
78
+ Then("I see visible text {string}", async function (text) {
79
+ await this.page.waitForLoadState("networkidle");
80
+ const locator = this.page.locator(`:text-is("${text}")`);
81
+ if (!(await locator.first().isVisible())) {
82
+ throw new Error(`Visible text "${text}" not found`);
83
+ }
84
+ });
85
+ /**
86
+ * THEN: I do not see visible text "Logout"
87
+ */
88
+ Then("I do not see visible text {string}", async function (text) {
89
+ const locator = this.page.locator(`:text-is("${text}")`);
90
+ if ((await locator.count()) > 0 && (await locator.first().isVisible())) {
91
+ throw new Error(`Visible text "${text}" should not be visible`);
92
+ }
93
+ });
94
+ Then("I see value {string}", async function (expected) {
95
+ if (!this.element)
96
+ throw new Error("No element selected");
97
+ const value = await this.element.inputValue();
98
+ if (value !== expected) {
99
+ throw new Error(`Expected value "${expected}", but got "${value}"`);
100
+ }
101
+ });
102
+ Then("I do not see value {string}", async function (unwanted) {
103
+ if (!this.element)
104
+ throw new Error("No element selected");
105
+ const value = await this.element.inputValue();
106
+ if (value === unwanted) {
107
+ throw new Error(`Value "${unwanted}" is present but should not be`);
108
+ }
109
+ });
110
+ //
111
+ // 📃 VISIBLE TEXT ASSERTIONS
112
+ //
113
+ Then(/^I do not see text "(.*)"$/, async function (unexpectedText) {
114
+ const el = this.page.getByText(unexpectedText, { exact: true });
115
+ await expect(el).toHaveCount(0);
116
+ });
117
+ //
118
+ // 🆕 Visible Text - Alias for clarity (optional if you want separate steps for naming)
119
+ //
120
+ Then("I see {string} in the element", async function (expected) {
121
+ var _a;
122
+ const element = this.element;
123
+ if (!element)
124
+ throw new Error("No element selected");
125
+ // ✅ Resolve alias
126
+ if (expected.startsWith("@")) {
127
+ const alias = expected.substring(1);
128
+ expected = this.data[alias];
129
+ if (!expected)
130
+ throw new Error(`No data stored for alias "@${alias}"`);
131
+ }
132
+ // ✅ Resolve faker syntax
133
+ expected = evaluateFaker(expected);
134
+ const textContent = await element.textContent();
135
+ if (!textContent)
136
+ throw new Error("Element has no text content");
137
+ expect(textContent).toContain(expected);
138
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `Verified "${expected}" in element text`);
139
+ });
140
+ Then("I see @{word} in the element", async function (alias) {
141
+ var _a;
142
+ const storedValue = this.data[alias];
143
+ if (!storedValue) {
144
+ throw new Error(`No value found in data storage under alias "@${alias}".`);
145
+ }
146
+ if (!this.element) {
147
+ throw new Error("No element found. You must get an element before asserting its contents.");
148
+ }
149
+ const actualText = ((_a = (await this.element.textContent())) === null || _a === void 0 ? void 0 : _a.trim()) || "";
150
+ expect(actualText).toContain(storedValue);
151
+ this.log(`Verified element contains value from "@${alias}" = "${storedValue}". Actual: "${actualText}"`);
152
+ });
153
+ Then("I see button {string} is disabled", async function (rawText) {
154
+ var _a;
155
+ // Resolve alias
156
+ let buttonText = rawText.startsWith("@")
157
+ ? this.data[rawText.slice(1)]
158
+ : rawText;
159
+ if (!buttonText) {
160
+ throw new Error(`No value found for alias: "${rawText}"`);
161
+ }
162
+ const button = this.page.getByRole("button", {
163
+ name: buttonText,
164
+ exact: false,
165
+ });
166
+ await expect(button).toBeVisible({ timeout: 5000 });
167
+ const isDisabled = await button.isDisabled();
168
+ if (!isDisabled) {
169
+ throw new Error(`🚫 Button "${buttonText}" is not disabled as expected.`);
170
+ }
171
+ (_a = this.log) === null || _a === void 0 ? void 0 : _a.call(this, `✅ Verified button "${buttonText}" is disabled.`);
172
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,191 @@
1
+ import { Then } from "@cucumber/cucumber";
2
+ import { expect } from "@playwright/test";
3
+ // Accessing the Last Response
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);
7
+ this.log(`Verified response status is ${expectedStatus}`);
8
+ });
9
+ 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);
12
+ this.log(`Verified response body contains "${expectedText}"`);
13
+ });
14
+ Then("I see response body {string}", async function (expected) {
15
+ const res = this.data.lastResponse;
16
+ const body = await res.text();
17
+ if (body !== expected)
18
+ throw new Error(`Expected body "${expected}", got "${body}"`);
19
+ });
20
+ Then("I see response body contains {string}", async function (part) {
21
+ const res = this.data.lastResponse;
22
+ const body = await res.text();
23
+ if (!body.includes(part))
24
+ throw new Error(`Body does not contain "${part}"`);
25
+ });
26
+ Then("I see response body matches JSON schema {string}", async function (schemaPath) {
27
+ const res = this.data.lastResponse;
28
+ const body = await res.text();
29
+ const schema = require(schemaPath); // Assuming schema is a JSON file
30
+ const Ajv = require("ajv");
31
+ const ajv = new Ajv();
32
+ const validate = ajv.compile(schema);
33
+ const valid = validate(JSON.parse(body));
34
+ if (!valid) {
35
+ throw new Error(`Response body does not match schema: ${ajv.errorsText(validate.errors)}`);
36
+ }
37
+ });
38
+ Then("I see response header {string} equals {string}", async function (headerName, expectedValue) {
39
+ const res = this.data.lastResponse;
40
+ const headerValue = res.headers()[headerName.toLowerCase()];
41
+ if (headerValue !== expectedValue) {
42
+ throw new Error(`Expected header "${headerName}" to be "${expectedValue}", got "${headerValue}"`);
43
+ }
44
+ this.log(`Verified response header "${headerName}" equals "${expectedValue}"`);
45
+ });
46
+ Then("I see response header {string} contains {string}", async function (headerName, expectedValue) {
47
+ const res = this.data.lastResponse;
48
+ const headerValue = res.headers()[headerName.toLowerCase()];
49
+ if (!headerValue || !headerValue.includes(expectedValue)) {
50
+ throw new Error(`Expected header "${headerName}" to contain "${expectedValue}", got "${headerValue}"`);
51
+ }
52
+ this.log(`Verified response header "${headerName}" contains "${expectedValue}"`);
53
+ });
54
+ Then("I see response header {string} does not contain {string}", async function (headerName, unexpectedValue) {
55
+ const res = this.data.lastResponse;
56
+ const headerValue = res.headers()[headerName.toLowerCase()];
57
+ if (headerValue && headerValue.includes(unexpectedValue)) {
58
+ throw new Error(`Expected header "${headerName}" to not contain "${unexpectedValue}", but it does`);
59
+ }
60
+ this.log(`Verified response header "${headerName}" does not contain "${unexpectedValue}"`);
61
+ });
62
+ Then("I see response header {string} does not equal {string}", async function (headerName, unexpectedValue) {
63
+ const res = this.data.lastResponse;
64
+ const headerValue = res.headers()[headerName.toLowerCase()];
65
+ if (headerValue === unexpectedValue) {
66
+ throw new Error(`Expected header "${headerName}" to not equal "${unexpectedValue}", but it does`);
67
+ }
68
+ this.log(`Verified response header "${headerName}" does not equal "${unexpectedValue}"`);
69
+ });
70
+ Then("I see response header {string} exists", async function (headerName) {
71
+ const res = this.data.lastResponse;
72
+ const headerValue = res.headers()[headerName.toLowerCase()];
73
+ if (!headerValue) {
74
+ throw new Error(`Expected header "${headerName}" to exist, but it does not`);
75
+ }
76
+ this.log(`Verified response header "${headerName}" exists`);
77
+ });
78
+ Then("I see response header {string} does not exist", async function (headerName) {
79
+ const res = this.data.lastResponse;
80
+ const headerValue = res.headers()[headerName.toLowerCase()];
81
+ if (headerValue) {
82
+ throw new Error(`Expected header "${headerName}" to not exist, but it does`);
83
+ }
84
+ this.log(`Verified response header "${headerName}" does not exist`);
85
+ });
86
+ Then("I see response status {int}", async function (status) {
87
+ const res = this.data.lastResponse;
88
+ if (!res)
89
+ throw new Error("No response available");
90
+ const actual = res.status();
91
+ if (actual !== status)
92
+ throw new Error(`Expected status ${status}, got ${actual}`);
93
+ });
94
+ Then("I see response status is not {int}", async function (status) {
95
+ const res = this.data.lastResponse;
96
+ if (!res)
97
+ throw new Error("No response available");
98
+ const actual = res.status();
99
+ if (actual === status)
100
+ throw new Error(`Expected status not to be ${status}, but it is`);
101
+ });
102
+ Then("I see response body matches JSON schema", async function (schema) {
103
+ const res = this.data.lastResponse;
104
+ if (!res)
105
+ throw new Error("No response available");
106
+ const body = await res.text();
107
+ const Ajv = require("ajv");
108
+ const ajv = new Ajv();
109
+ const validate = ajv.compile(schema);
110
+ const valid = validate(JSON.parse(body));
111
+ if (!valid) {
112
+ throw new Error(`Response body does not match schema: ${ajv.errorsText(validate.errors)}`);
113
+ }
114
+ this.log(`Response body matches JSON schema`);
115
+ });
116
+ Then("I see response body is empty", async function () {
117
+ const res = this.data.lastResponse;
118
+ if (!res)
119
+ throw new Error("No response available");
120
+ const body = await res.text();
121
+ if (body.trim() !== "") {
122
+ throw new Error(`Expected empty response body, got "${body}"`);
123
+ }
124
+ this.log(`Verified response body is empty`);
125
+ });
126
+ Then("I see response body is not empty", async function () {
127
+ const res = this.data.lastResponse;
128
+ if (!res)
129
+ throw new Error("No response available");
130
+ const body = await res.text();
131
+ if (body.trim() === "") {
132
+ throw new Error(`Expected non-empty response body, got empty`);
133
+ }
134
+ this.log(`Verified response body is not empty`);
135
+ });
136
+ Then("I see response body matches {string}", async function (expected) {
137
+ const res = this.data.lastResponse;
138
+ if (!res)
139
+ throw new Error("No response available");
140
+ const body = await res.text();
141
+ if (body !== expected) {
142
+ throw new Error(`Expected body "${expected}", got "${body}"`);
143
+ }
144
+ this.log(`Verified response body matches: ${expected}`);
145
+ });
146
+ Then("I see response body contains {string}", async function (part) {
147
+ const res = this.data.lastResponse;
148
+ if (!res)
149
+ throw new Error("No response available");
150
+ const body = await res.text();
151
+ if (!body.includes(part)) {
152
+ throw new Error(`Body does not contain "${part}"`);
153
+ }
154
+ this.log(`Verified response body contains: ${part}`);
155
+ });
156
+ Then("I see response body does not contain {string}", async function (part) {
157
+ const res = this.data.lastResponse;
158
+ if (!res)
159
+ throw new Error("No response available");
160
+ const body = await res.text();
161
+ if (body.includes(part)) {
162
+ throw new Error(`Body contains "${part}", but it should not`);
163
+ }
164
+ this.log(`Verified response body does not contain: ${part}`);
165
+ });
166
+ Then("I see response body is JSON", async function () {
167
+ const res = this.data.lastResponse;
168
+ if (!res)
169
+ throw new Error("No response available");
170
+ const body = await res.text();
171
+ try {
172
+ JSON.parse(body);
173
+ this.log(`Verified response body is valid JSON`);
174
+ }
175
+ catch (e) {
176
+ throw new Error(`Response body is not valid JSON: ${e.message}`);
177
+ }
178
+ });
179
+ Then("I see response body is not JSON", async function () {
180
+ const res = this.data.lastResponse;
181
+ if (!res)
182
+ throw new Error("No response available");
183
+ const body = await res.text();
184
+ try {
185
+ JSON.parse(body);
186
+ throw new Error(`Expected response body to not be JSON, but it is`);
187
+ }
188
+ catch (e) {
189
+ this.log(`Verified response body is not JSON: ${e.message}`);
190
+ }
191
+ });
@@ -0,0 +1,2 @@
1
+ declare function globalSetup(): Promise<void>;
2
+ export default globalSetup;
@@ -0,0 +1,20 @@
1
+ // global-setup.ts
2
+ import { chromium } from "@playwright/test";
3
+ import path from "path";
4
+ async function globalSetup() {
5
+ const browser = await chromium.launch();
6
+ const page = await browser.newPage();
7
+ // Navigate to login and log in
8
+ await page.goto(process.env.PLAYWRIGHT_BASE_URL || "http://demoqa.com");
9
+ await page.getByPlaceholder("Email").fill("user@example.com");
10
+ await page.getByPlaceholder("Password").fill("SuperSecret123");
11
+ await page.getByRole("button", { name: "Login" }).click();
12
+ // Wait for navigation or some indicator that login is complete
13
+ await page.waitForURL("**/dashboard");
14
+ // Save session to file
15
+ await page
16
+ .context()
17
+ .storageState({ path: path.resolve(__dirname, "storageState.json") });
18
+ await browser.close();
19
+ }
20
+ export default globalSetup;
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,6 +1,6 @@
1
1
  {
2
2
  "name": "playwright-cucumber-ts-steps",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
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",