playwright-cucumber-ts-steps 1.1.8 → 1.1.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.
- package/LICENSE +21 -0
- package/dist/backend/actions/click.d.ts +132 -1
- package/dist/backend/actions/click.d.ts.map +1 -1
- package/dist/backend/actions/click.js +122 -53
- package/dist/backend/actions/find.d.ts +243 -1
- package/dist/backend/actions/find.d.ts.map +1 -1
- package/dist/backend/actions/find.js +196 -72
- package/dist/backend/actions/form.d.ts +37 -1
- package/dist/backend/actions/form.d.ts.map +1 -1
- package/dist/backend/actions/form.js +55 -3
- package/dist/backend/actions/formTable.d.ts +25 -1
- package/dist/backend/actions/formTable.d.ts.map +1 -1
- package/dist/backend/actions/formTable.js +27 -5
- package/dist/backend/actions/frames.d.ts +53 -1
- package/dist/backend/actions/frames.d.ts.map +1 -1
- package/dist/backend/actions/frames.js +48 -11
- package/dist/backend/actions/inputs.d.ts +139 -1
- package/dist/backend/actions/inputs.d.ts.map +1 -1
- package/dist/backend/actions/inputs.js +113 -43
- package/dist/backend/actions/interactions.d.ts +61 -1
- package/dist/backend/actions/interactions.d.ts.map +1 -1
- package/dist/backend/actions/interactions.js +65 -10
- package/dist/backend/actions/keyboard.d.ts +70 -1
- package/dist/backend/actions/keyboard.d.ts.map +1 -1
- package/dist/backend/actions/keyboard.js +59 -23
- package/dist/backend/actions/misc.d.ts +134 -1
- package/dist/backend/actions/misc.d.ts.map +1 -1
- package/dist/backend/actions/misc.js +106 -42
- package/dist/backend/actions/mobile.d.ts +74 -1
- package/dist/backend/actions/mobile.d.ts.map +1 -1
- package/dist/backend/actions/mobile.js +74 -13
- package/dist/backend/actions/mouse.d.ts +79 -1
- package/dist/backend/actions/mouse.d.ts.map +1 -1
- package/dist/backend/actions/mouse.js +66 -21
- package/dist/backend/actions/navigation.d.ts +48 -1
- package/dist/backend/actions/navigation.d.ts.map +1 -1
- package/dist/backend/actions/navigation.js +42 -15
- package/dist/backend/actions/waits.d.ts +55 -1
- package/dist/backend/actions/waits.d.ts.map +1 -1
- package/dist/backend/actions/waits.js +49 -17
- package/dist/backend/api/assertions.d.ts +32 -1
- package/dist/backend/api/assertions.d.ts.map +1 -1
- package/dist/backend/api/assertions.js +37 -9
- package/dist/backend/api/mock.d.ts +34 -1
- package/dist/backend/api/mock.d.ts.map +1 -1
- package/dist/backend/api/mock.js +37 -10
- package/dist/backend/api/network.d.ts +60 -1
- package/dist/backend/api/network.d.ts.map +1 -1
- package/dist/backend/api/network.js +53 -21
- package/dist/backend/api/requests.d.ts +43 -1
- package/dist/backend/api/requests.d.ts.map +1 -1
- package/dist/backend/api/requests.js +49 -17
- package/dist/backend/assertions/pageState.d.ts +40 -1
- package/dist/backend/assertions/pageState.d.ts.map +1 -1
- package/dist/backend/assertions/pageState.js +33 -12
- package/dist/backend/assertions/text.d.ts +46 -1
- package/dist/backend/assertions/text.d.ts.map +1 -1
- package/dist/backend/assertions/text.js +51 -8
- package/dist/backend/assertions/visibility.d.ts +102 -1
- package/dist/backend/assertions/visibility.d.ts.map +1 -1
- package/dist/backend/assertions/visibility.js +86 -36
- package/dist/backend/auth/index.js +2 -2
- package/dist/backend/db/steps.d.ts +35 -1
- package/dist/backend/db/steps.d.ts.map +1 -1
- package/dist/backend/db/steps.js +48 -15
- package/dist/backend/elements/alerts.d.ts +35 -1
- package/dist/backend/elements/alerts.d.ts.map +1 -1
- package/dist/backend/elements/alerts.js +39 -6
- package/dist/backend/elements/forms.d.ts +44 -1
- package/dist/backend/elements/forms.d.ts.map +1 -1
- package/dist/backend/elements/forms.js +50 -11
- package/dist/backend/elements/frames.d.ts +36 -1
- package/dist/backend/elements/frames.d.ts.map +1 -1
- package/dist/backend/elements/frames.js +43 -13
- package/dist/core/runner.d.ts.map +1 -1
- package/dist/core/runner.js +3 -4
- package/package.json +52 -12
|
@@ -33,9 +33,9 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
const registry_1 = require("../../core/registry");
|
|
37
|
-
const path = __importStar(require("path"));
|
|
38
36
|
const fs = __importStar(require("fs"));
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const registry_1 = require("../../core/registry");
|
|
39
39
|
// 1. SAVE STATE (Use this after a successful login)
|
|
40
40
|
// Example: And I save the browser state to "admin.json"
|
|
41
41
|
(0, registry_1.Step)("I save the browser state to {string}", async (page, filename) => {
|
|
@@ -1,2 +1,36 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @module DatabaseSteps
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Executes a raw SQL query against the configured database.
|
|
6
|
+
* The results are stored in the internal `dbState` for subsequent assertions.
|
|
7
|
+
* * @example
|
|
8
|
+
* ```gherkin
|
|
9
|
+
* When I run the database query "SELECT * FROM users WHERE email = 'test@example.com'"
|
|
10
|
+
* ```
|
|
11
|
+
* * @param query - The SQL query string to execute.
|
|
12
|
+
*/
|
|
13
|
+
export declare const RunDbQuery: void;
|
|
14
|
+
/**
|
|
15
|
+
* Asserts that the last executed database query returned a specific number of records.
|
|
16
|
+
* * @example
|
|
17
|
+
* ```gherkin
|
|
18
|
+
* Then I expect the database to return 1 record
|
|
19
|
+
* ```
|
|
20
|
+
* * @param count - The expected number of rows in the result set.
|
|
21
|
+
*/
|
|
22
|
+
export declare const ExpectDbRecordCount: void;
|
|
23
|
+
/**
|
|
24
|
+
* Asserts that the first record of the last database result set contains specific column values.
|
|
25
|
+
* Performs a loose equality check (converts values to strings) to handle type mismatches.
|
|
26
|
+
* * @example
|
|
27
|
+
* ```gherkin
|
|
28
|
+
* Then I expect the first database record to contain
|
|
29
|
+
* | username | admin |
|
|
30
|
+
* | is_active| 1 |
|
|
31
|
+
* | role | superuser |
|
|
32
|
+
* ```
|
|
33
|
+
* * @param tableData - A Gherkin Data Table containing column names (keys) and expected values.
|
|
34
|
+
*/
|
|
35
|
+
export declare const ExpectFirstDbRecordToContain: void;
|
|
2
36
|
//# sourceMappingURL=steps.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"steps.d.ts","sourceRoot":"","sources":["../../../src/backend/db/steps.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"steps.d.ts","sourceRoot":"","sources":["../../../src/backend/db/steps.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,MAGrB,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,MAW/B,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,4BAA4B,MAgCxC,CAAC"}
|
package/dist/backend/db/steps.js
CHANGED
|
@@ -1,43 +1,76 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ExpectFirstDbRecordToContain = exports.ExpectDbRecordCount = exports.RunDbQuery = void 0;
|
|
4
|
+
const test_1 = require("@playwright/test");
|
|
3
5
|
const registry_1 = require("../../core/registry");
|
|
4
6
|
const state_1 = require("./state");
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* @module DatabaseSteps
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Executes a raw SQL query against the configured database.
|
|
12
|
+
* The results are stored in the internal `dbState` for subsequent assertions.
|
|
13
|
+
* * @example
|
|
14
|
+
* ```gherkin
|
|
15
|
+
* When I run the database query "SELECT * FROM users WHERE email = 'test@example.com'"
|
|
16
|
+
* ```
|
|
17
|
+
* * @param query - The SQL query string to execute.
|
|
18
|
+
*/
|
|
19
|
+
exports.RunDbQuery = (0, registry_1.Step)("I run the database query {string}", async (page, query) => {
|
|
8
20
|
await state_1.dbState.executeQuery(query);
|
|
21
|
+
console.log(`🗄️ Executed DB Query: ${query}`);
|
|
9
22
|
});
|
|
10
|
-
|
|
11
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Asserts that the last executed database query returned a specific number of records.
|
|
25
|
+
* * @example
|
|
26
|
+
* ```gherkin
|
|
27
|
+
* Then I expect the database to return 1 record
|
|
28
|
+
* ```
|
|
29
|
+
* * @param count - The expected number of rows in the result set.
|
|
30
|
+
*/
|
|
31
|
+
exports.ExpectDbRecordCount = (0, registry_1.Step)("I expect the database to return {int} record(s)", async (page, count) => {
|
|
12
32
|
const result = state_1.dbState.getLastResult();
|
|
13
33
|
if (Array.isArray(result)) {
|
|
14
34
|
(0, test_1.expect)(result.length).toBe(count);
|
|
35
|
+
console.log(`✅ Database returned exactly ${count} record(s).`);
|
|
15
36
|
}
|
|
16
37
|
else {
|
|
17
|
-
throw new Error(`Expected array result but got: ${typeof result}`);
|
|
38
|
+
throw new Error(`Expected array result from database but got: ${typeof result}`);
|
|
18
39
|
}
|
|
19
40
|
});
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Asserts that the first record of the last database result set contains specific column values.
|
|
43
|
+
* Performs a loose equality check (converts values to strings) to handle type mismatches.
|
|
44
|
+
* * @example
|
|
45
|
+
* ```gherkin
|
|
46
|
+
* Then I expect the first database record to contain
|
|
47
|
+
* | username | admin |
|
|
48
|
+
* | is_active| 1 |
|
|
49
|
+
* | role | superuser |
|
|
50
|
+
* ```
|
|
51
|
+
* * @param tableData - A Gherkin Data Table containing column names (keys) and expected values.
|
|
52
|
+
*/
|
|
53
|
+
exports.ExpectFirstDbRecordToContain = (0, registry_1.Step)("I expect the first database record to contain", async (page, tableData) => {
|
|
23
54
|
const result = state_1.dbState.getLastResult();
|
|
24
55
|
// Guard Clauses
|
|
25
56
|
if (!Array.isArray(result) || result.length === 0) {
|
|
26
|
-
throw new Error("Database returned no records to check.");
|
|
57
|
+
throw new Error("❌ Database returned no records to check.");
|
|
27
58
|
}
|
|
28
59
|
if (!tableData) {
|
|
29
|
-
throw new Error("This step requires a Data Table.");
|
|
60
|
+
throw new Error("❌ This step requires a Data Table.");
|
|
30
61
|
}
|
|
31
|
-
const firstRow = result[0];
|
|
32
|
-
// tableData is [ ["
|
|
62
|
+
const firstRow = result[0];
|
|
63
|
+
// tableData is [ ["column", "value"], ... ]
|
|
33
64
|
for (const row of tableData) {
|
|
34
65
|
const key = row[0];
|
|
35
66
|
const expectedValue = row[1];
|
|
36
67
|
// Check if the key exists in the DB result
|
|
37
68
|
if (!(key in firstRow)) {
|
|
38
|
-
throw new Error(
|
|
69
|
+
throw new Error(`❌ DB Record does not have column: "${key}"`);
|
|
39
70
|
}
|
|
40
71
|
// Loose equality check (DB might return int, Gherkin sends string)
|
|
41
|
-
|
|
72
|
+
const actualValue = String(firstRow[key]);
|
|
73
|
+
(0, test_1.expect)(actualValue).toBe(expectedValue);
|
|
42
74
|
}
|
|
75
|
+
console.log("✅ First DB record matches the expected data table.");
|
|
43
76
|
});
|
|
@@ -1,2 +1,36 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @module DialogActions
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Sets up a listener to automatically click "OK" or "Accept" on the very next browser dialog
|
|
6
|
+
* (alert, confirm, or prompt) that appears.
|
|
7
|
+
* * **Note:** This must be called *before* the action that triggers the dialog.
|
|
8
|
+
* * * @example
|
|
9
|
+
* ```gherkin
|
|
10
|
+
* Given I accept the next dialog
|
|
11
|
+
* When I click "#delete-button"
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export declare const AcceptNextDialog: void;
|
|
15
|
+
/**
|
|
16
|
+
* Sets up a listener to automatically click "Cancel" or "Dismiss" on the very next browser dialog.
|
|
17
|
+
* * **Note:** This must be called *before* the action that triggers the dialog.
|
|
18
|
+
* * * @example
|
|
19
|
+
* ```gherkin
|
|
20
|
+
* Given I dismiss the next dialog
|
|
21
|
+
* When I click "#reset-settings"
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare const DismissNextDialog: void;
|
|
25
|
+
/**
|
|
26
|
+
* Sets up a listener to type a specific string into the next browser prompt and then accept it.
|
|
27
|
+
* * **Note:** This must be called *before* the action that triggers the prompt.
|
|
28
|
+
* * * @example
|
|
29
|
+
* ```gherkin
|
|
30
|
+
* Given I type "My New Folder" into the next prompt and accept
|
|
31
|
+
* When I click "button:has-text('Create')"
|
|
32
|
+
* ```
|
|
33
|
+
* * @param text - The string to be entered into the prompt input field.
|
|
34
|
+
*/
|
|
35
|
+
export declare const TypeAndAcceptPrompt: void;
|
|
2
36
|
//# sourceMappingURL=alerts.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alerts.d.ts","sourceRoot":"","sources":["../../../src/backend/elements/alerts.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"alerts.d.ts","sourceRoot":"","sources":["../../../src/backend/elements/alerts.ts"],"names":[],"mappings":"AAEA;;GAEG;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,MAK3B,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,MAK5B,CAAC;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB,MAQ/B,CAAC"}
|
|
@@ -1,21 +1,54 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TypeAndAcceptPrompt = exports.DismissNextDialog = exports.AcceptNextDialog = void 0;
|
|
3
4
|
const registry_1 = require("../../core/registry");
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* @module DialogActions
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Sets up a listener to automatically click "OK" or "Accept" on the very next browser dialog
|
|
10
|
+
* (alert, confirm, or prompt) that appears.
|
|
11
|
+
* * **Note:** This must be called *before* the action that triggers the dialog.
|
|
12
|
+
* * * @example
|
|
13
|
+
* ```gherkin
|
|
14
|
+
* Given I accept the next dialog
|
|
15
|
+
* When I click "#delete-button"
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
exports.AcceptNextDialog = (0, registry_1.Step)("I accept the next dialog", async (page) => {
|
|
6
19
|
page.once("dialog", async (dialog) => {
|
|
7
20
|
await dialog.accept();
|
|
21
|
+
console.log(`✅ Accepted dialog: [${dialog.type()}] "${dialog.message()}"`);
|
|
8
22
|
});
|
|
9
23
|
});
|
|
10
|
-
|
|
11
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Sets up a listener to automatically click "Cancel" or "Dismiss" on the very next browser dialog.
|
|
26
|
+
* * **Note:** This must be called *before* the action that triggers the dialog.
|
|
27
|
+
* * * @example
|
|
28
|
+
* ```gherkin
|
|
29
|
+
* Given I dismiss the next dialog
|
|
30
|
+
* When I click "#reset-settings"
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
exports.DismissNextDialog = (0, registry_1.Step)("I dismiss the next dialog", async (page) => {
|
|
12
34
|
page.once("dialog", async (dialog) => {
|
|
13
35
|
await dialog.dismiss();
|
|
36
|
+
console.log(`❌ Dismissed dialog: [${dialog.type()}] "${dialog.message()}"`);
|
|
14
37
|
});
|
|
15
38
|
});
|
|
16
|
-
|
|
17
|
-
|
|
39
|
+
/**
|
|
40
|
+
* Sets up a listener to type a specific string into the next browser prompt and then accept it.
|
|
41
|
+
* * **Note:** This must be called *before* the action that triggers the prompt.
|
|
42
|
+
* * * @example
|
|
43
|
+
* ```gherkin
|
|
44
|
+
* Given I type "My New Folder" into the next prompt and accept
|
|
45
|
+
* When I click "button:has-text('Create')"
|
|
46
|
+
* ```
|
|
47
|
+
* * @param text - The string to be entered into the prompt input field.
|
|
48
|
+
*/
|
|
49
|
+
exports.TypeAndAcceptPrompt = (0, registry_1.Step)("I type {string} into the next prompt and accept", async (page, text) => {
|
|
18
50
|
page.once("dialog", async (dialog) => {
|
|
19
51
|
await dialog.accept(text);
|
|
52
|
+
console.log(`✍️ Typed "${text}" into prompt and accepted.`);
|
|
20
53
|
});
|
|
21
54
|
});
|
|
@@ -1,2 +1,45 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @module FormActions
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Selects an option from a `<select>` dropdown menu.
|
|
6
|
+
* It first attempts to match by the visible label; if that fails, it tries to match by the underlying `value` attribute.
|
|
7
|
+
* * @example
|
|
8
|
+
* ```gherkin
|
|
9
|
+
* When I select option "Canada" from "#country-selector"
|
|
10
|
+
* When I select option "CA" from "#country-selector"
|
|
11
|
+
* ```
|
|
12
|
+
* * @param option - The visible text (label) or the value attribute of the option.
|
|
13
|
+
* @param selector - The CSS or Playwright selector for the select element.
|
|
14
|
+
*/
|
|
15
|
+
export declare const SelectDropdownOption: void;
|
|
16
|
+
/**
|
|
17
|
+
* Checks a checkbox or radio button.
|
|
18
|
+
* * @example
|
|
19
|
+
* ```gherkin
|
|
20
|
+
* When I check "#terms-and-conditions"
|
|
21
|
+
* ```
|
|
22
|
+
* * @param selector - The selector for the checkbox or radio input.
|
|
23
|
+
*/
|
|
24
|
+
export declare const CheckInput: void;
|
|
25
|
+
/**
|
|
26
|
+
* Unchecks a checkbox.
|
|
27
|
+
* * @example
|
|
28
|
+
* ```gherkin
|
|
29
|
+
* When I uncheck "#subscribe-newsletter"
|
|
30
|
+
* ```
|
|
31
|
+
* * @param selector - The selector for the checkbox input.
|
|
32
|
+
*/
|
|
33
|
+
export declare const UncheckInput: void;
|
|
34
|
+
/**
|
|
35
|
+
* Uploads a file to an `<input type="file">` element.
|
|
36
|
+
* The file path is resolved relative to the current working directory of the project.
|
|
37
|
+
* * @example
|
|
38
|
+
* ```gherkin
|
|
39
|
+
* When I upload file "test-data/profile.jpg" to "#avatar-upload"
|
|
40
|
+
* ```
|
|
41
|
+
* * @param fileName - The relative path to the file from the project root.
|
|
42
|
+
* @param selector - The selector for the file input element.
|
|
43
|
+
*/
|
|
44
|
+
export declare const UploadFile: void;
|
|
2
45
|
//# sourceMappingURL=forms.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"forms.d.ts","sourceRoot":"","sources":["../../../src/backend/elements/forms.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"forms.d.ts","sourceRoot":"","sources":["../../../src/backend/elements/forms.ts"],"names":[],"mappings":"AAGA;;GAEG;AAEH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,oBAAoB,MAShC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,MAGrB,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,MAGvB,CAAC;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,UAAU,MAOtB,CAAC"}
|
|
@@ -33,27 +33,66 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
|
|
36
|
+
exports.UploadFile = exports.UncheckInput = exports.CheckInput = exports.SelectDropdownOption = void 0;
|
|
37
37
|
const path = __importStar(require("path"));
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
const registry_1 = require("../../core/registry");
|
|
39
|
+
/**
|
|
40
|
+
* @module FormActions
|
|
41
|
+
*/
|
|
42
|
+
/**
|
|
43
|
+
* Selects an option from a `<select>` dropdown menu.
|
|
44
|
+
* It first attempts to match by the visible label; if that fails, it tries to match by the underlying `value` attribute.
|
|
45
|
+
* * @example
|
|
46
|
+
* ```gherkin
|
|
47
|
+
* When I select option "Canada" from "#country-selector"
|
|
48
|
+
* When I select option "CA" from "#country-selector"
|
|
49
|
+
* ```
|
|
50
|
+
* * @param option - The visible text (label) or the value attribute of the option.
|
|
51
|
+
* @param selector - The CSS or Playwright selector for the select element.
|
|
52
|
+
*/
|
|
53
|
+
exports.SelectDropdownOption = (0, registry_1.Step)("I select option {string} from {string}", async (page, option, selector) => {
|
|
40
54
|
await page.selectOption(selector, { label: option }).catch(() => {
|
|
41
55
|
// Fallback: try selecting by value if label fails
|
|
42
56
|
return page.selectOption(selector, { value: option });
|
|
43
57
|
});
|
|
58
|
+
console.log(`✅ Selected option "${option}" from "${selector}"`);
|
|
44
59
|
});
|
|
45
|
-
|
|
46
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Checks a checkbox or radio button.
|
|
62
|
+
* * @example
|
|
63
|
+
* ```gherkin
|
|
64
|
+
* When I check "#terms-and-conditions"
|
|
65
|
+
* ```
|
|
66
|
+
* * @param selector - The selector for the checkbox or radio input.
|
|
67
|
+
*/
|
|
68
|
+
exports.CheckInput = (0, registry_1.Step)("I check {string}", async (page, selector) => {
|
|
47
69
|
await page.check(selector);
|
|
70
|
+
console.log(`✅ Checked "${selector}"`);
|
|
48
71
|
});
|
|
49
|
-
|
|
72
|
+
/**
|
|
73
|
+
* Unchecks a checkbox.
|
|
74
|
+
* * @example
|
|
75
|
+
* ```gherkin
|
|
76
|
+
* When I uncheck "#subscribe-newsletter"
|
|
77
|
+
* ```
|
|
78
|
+
* * @param selector - The selector for the checkbox input.
|
|
79
|
+
*/
|
|
80
|
+
exports.UncheckInput = (0, registry_1.Step)("I uncheck {string}", async (page, selector) => {
|
|
50
81
|
await page.uncheck(selector);
|
|
82
|
+
console.log(`✅ Unchecked "${selector}"`);
|
|
51
83
|
});
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
84
|
+
/**
|
|
85
|
+
* Uploads a file to an `<input type="file">` element.
|
|
86
|
+
* The file path is resolved relative to the current working directory of the project.
|
|
87
|
+
* * @example
|
|
88
|
+
* ```gherkin
|
|
89
|
+
* When I upload file "test-data/profile.jpg" to "#avatar-upload"
|
|
90
|
+
* ```
|
|
91
|
+
* * @param fileName - The relative path to the file from the project root.
|
|
92
|
+
* @param selector - The selector for the file input element.
|
|
93
|
+
*/
|
|
94
|
+
exports.UploadFile = (0, registry_1.Step)("I upload file {string} to {string}", async (page, fileName, selector) => {
|
|
57
95
|
const filePath = path.resolve(process.cwd(), fileName);
|
|
58
96
|
await page.setInputFiles(selector, filePath);
|
|
97
|
+
console.log(`📁 Uploaded file "${fileName}" to "${selector}"`);
|
|
59
98
|
});
|
|
@@ -1,2 +1,37 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @module FrameActions
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Clicks an element located inside a specific `<iframe>`.
|
|
6
|
+
* * @example
|
|
7
|
+
* ```gherkin
|
|
8
|
+
* When I click "button#submit" inside frame "#payment-iframe"
|
|
9
|
+
* ```
|
|
10
|
+
* * @param elementSelector - The CSS/Playwright selector for the element to click.
|
|
11
|
+
* @param frameSelector - The selector for the iframe element itself.
|
|
12
|
+
*/
|
|
13
|
+
export declare const ClickInsideFrame: void;
|
|
14
|
+
/**
|
|
15
|
+
* Fills an input field located inside a specific `<iframe>`.
|
|
16
|
+
* * @example
|
|
17
|
+
* ```gherkin
|
|
18
|
+
* When I fill "input[name='card-number']" inside frame "#checkout-frame" with "42424242"
|
|
19
|
+
* ```
|
|
20
|
+
* * @param elementSelector - The selector for the input field inside the frame.
|
|
21
|
+
* @param frameSelector - The selector for the iframe.
|
|
22
|
+
* @param value - The text to type into the input.
|
|
23
|
+
*/
|
|
24
|
+
export declare const FillInsideFrame: void;
|
|
25
|
+
/**
|
|
26
|
+
* Asserts that an element inside a specific `<iframe>` contains the expected text.
|
|
27
|
+
* Uses Playwright's web-first assertions for automatic retries.
|
|
28
|
+
* * @example
|
|
29
|
+
* ```gherkin
|
|
30
|
+
* Then I expect ".success-msg" inside frame "#upload-frame" to have text "Upload Complete"
|
|
31
|
+
* ```
|
|
32
|
+
* * @param elementSelector - The selector for the element inside the frame.
|
|
33
|
+
* @param frameSelector - The selector for the iframe.
|
|
34
|
+
* @param text - The text expected to be found.
|
|
35
|
+
*/
|
|
36
|
+
export declare const ExpectTextInsideFrame: void;
|
|
2
37
|
//# sourceMappingURL=frames.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frames.d.ts","sourceRoot":"","sources":["../../../src/backend/elements/frames.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"frames.d.ts","sourceRoot":"","sources":["../../../src/backend/elements/frames.ts"],"names":[],"mappings":"AAGA;;GAEG;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,MAO5B,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,MAO3B,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,qBAAqB,MAUjC,CAAC"}
|
|
@@ -1,25 +1,55 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ExpectTextInsideFrame = exports.FillInsideFrame = exports.ClickInsideFrame = void 0;
|
|
4
|
+
const test_1 = require("@playwright/test");
|
|
3
5
|
const registry_1 = require("../../core/registry");
|
|
4
|
-
|
|
5
|
-
|
|
6
|
+
/**
|
|
7
|
+
* @module FrameActions
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Clicks an element located inside a specific `<iframe>`.
|
|
11
|
+
* * @example
|
|
12
|
+
* ```gherkin
|
|
13
|
+
* When I click "button#submit" inside frame "#payment-iframe"
|
|
14
|
+
* ```
|
|
15
|
+
* * @param elementSelector - The CSS/Playwright selector for the element to click.
|
|
16
|
+
* @param frameSelector - The selector for the iframe element itself.
|
|
17
|
+
*/
|
|
18
|
+
exports.ClickInsideFrame = (0, registry_1.Step)("I click {string} inside frame {string}", async (page, elementSelector, frameSelector) => {
|
|
6
19
|
const frame = page.frameLocator(frameSelector);
|
|
7
20
|
await frame.locator(elementSelector).click();
|
|
21
|
+
console.log(`🖼️ Clicked "${elementSelector}" inside frame "${frameSelector}".`);
|
|
8
22
|
});
|
|
9
|
-
|
|
10
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Fills an input field located inside a specific `<iframe>`.
|
|
25
|
+
* * @example
|
|
26
|
+
* ```gherkin
|
|
27
|
+
* When I fill "input[name='card-number']" inside frame "#checkout-frame" with "42424242"
|
|
28
|
+
* ```
|
|
29
|
+
* * @param elementSelector - The selector for the input field inside the frame.
|
|
30
|
+
* @param frameSelector - The selector for the iframe.
|
|
31
|
+
* @param value - The text to type into the input.
|
|
32
|
+
*/
|
|
33
|
+
exports.FillInsideFrame = (0, registry_1.Step)("I fill {string} inside frame {string} with {string}", async (page, elementSelector, frameSelector, value) => {
|
|
11
34
|
const frame = page.frameLocator(frameSelector);
|
|
12
35
|
await frame.locator(elementSelector).fill(value);
|
|
36
|
+
console.log(`🖼️ Filled "${elementSelector}" inside frame "${frameSelector}" with value.`);
|
|
13
37
|
});
|
|
14
|
-
|
|
15
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Asserts that an element inside a specific `<iframe>` contains the expected text.
|
|
40
|
+
* Uses Playwright's web-first assertions for automatic retries.
|
|
41
|
+
* * @example
|
|
42
|
+
* ```gherkin
|
|
43
|
+
* Then I expect ".success-msg" inside frame "#upload-frame" to have text "Upload Complete"
|
|
44
|
+
* ```
|
|
45
|
+
* * @param elementSelector - The selector for the element inside the frame.
|
|
46
|
+
* @param frameSelector - The selector for the iframe.
|
|
47
|
+
* @param text - The text expected to be found.
|
|
48
|
+
*/
|
|
49
|
+
exports.ExpectTextInsideFrame = (0, registry_1.Step)("I expect {string} inside frame {string} to have text {string}", async (page, elementSelector, frameSelector, text) => {
|
|
16
50
|
const frame = page.frameLocator(frameSelector);
|
|
17
51
|
const locator = frame.locator(elementSelector);
|
|
18
|
-
//
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const actualText = await locator.textContent();
|
|
22
|
-
if (!actualText?.includes(text)) {
|
|
23
|
-
throw new Error(`Expected text "${text}" but found "${actualText}" in frame`);
|
|
24
|
-
}
|
|
52
|
+
// Using Playwright expect for robust retries
|
|
53
|
+
await (0, test_1.expect)(locator).toContainText(text);
|
|
54
|
+
console.log(`✅ Frame "${frameSelector}" element "${elementSelector}" contains "${text}".`);
|
|
25
55
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/core/runner.ts"],"names":[],"mappings":"AAMA,OAAO,0BAA0B,CAAC;AAClC,OAAO,6BAA6B,CAAC;AACrC,OAAO,2BAA2B,CAAC;AACnC,OAAO,sBAAsB,CAAC;AAC9B,OAAO,uBAAuB,CAAC;AAE/B,OAAO,qBAAqB,CAAC;AAE7B,UAAU,aAAa;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;CAC3C;AASD,wBAAgB,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/core/runner.ts"],"names":[],"mappings":"AAMA,OAAO,0BAA0B,CAAC;AAClC,OAAO,6BAA6B,CAAC;AACrC,OAAO,2BAA2B,CAAC;AACnC,OAAO,sBAAsB,CAAC;AAC9B,OAAO,uBAAuB,CAAC;AAE/B,OAAO,qBAAqB,CAAC;AAE7B,UAAU,aAAa;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;CAC3C;AASD,wBAAgB,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,QA4LpE"}
|
package/dist/core/runner.js
CHANGED
|
@@ -34,8 +34,8 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.runTests = runTests;
|
|
37
|
-
const test_1 = require("@playwright/test");
|
|
38
37
|
const fs = __importStar(require("fs"));
|
|
38
|
+
const test_1 = require("@playwright/test");
|
|
39
39
|
const glob_1 = require("glob");
|
|
40
40
|
const registry_1 = require("./registry");
|
|
41
41
|
// LOAD BACKEND LIBRARIES
|
|
@@ -136,9 +136,8 @@ function runTests(featureGlob, options) {
|
|
|
136
136
|
if (currentStep) {
|
|
137
137
|
if (!currentStep.dataTable)
|
|
138
138
|
currentStep.dataTable = [];
|
|
139
|
-
const row = trimmedLine
|
|
140
|
-
|
|
141
|
-
.map((cell) => cell.trim())
|
|
139
|
+
const row = trimmedLine;
|
|
140
|
+
const _row = trimmedLine.split("|").map((cell) => cell.trim())
|
|
142
141
|
.filter((cell, index, arr) => index > 0 && index < arr.length - 1);
|
|
143
142
|
// Simple split often leaves empty strings at start/end
|
|
144
143
|
// Better split logic:
|
package/package.json
CHANGED
|
@@ -1,23 +1,40 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "playwright-cucumber-ts-steps",
|
|
3
3
|
"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.",
|
|
4
|
-
"version": "1.1.
|
|
4
|
+
"version": "1.1.9",
|
|
5
5
|
"private": false,
|
|
6
6
|
"main": "dist/index.js",
|
|
7
|
+
"type": "module",
|
|
7
8
|
"types": "dist/index.d.ts",
|
|
8
|
-
"files": [
|
|
9
|
-
"dist"
|
|
10
|
-
],
|
|
11
9
|
"scripts": {
|
|
12
10
|
"build": "tsc",
|
|
13
11
|
"docs": "typedoc",
|
|
14
|
-
"
|
|
12
|
+
"docs:deploy": "gh-pages -d temp-docs",
|
|
13
|
+
"prepublishOnly": "npm run build",
|
|
14
|
+
"prepare": "husky",
|
|
15
|
+
"playwright:ui": "npx playwright test --headed",
|
|
16
|
+
"lint": "eslint .",
|
|
17
|
+
"lint:fix": "eslint . --ext .ts --fix",
|
|
18
|
+
"lint:tsc": "tsc --noEmit",
|
|
19
|
+
"format": "prettier --write .",
|
|
20
|
+
"clean": "rm -rf playwright/report",
|
|
21
|
+
"test": "npx playwright test demoTest.spec.ts",
|
|
22
|
+
"commitlint": "commitlint --edit"
|
|
15
23
|
},
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
24
|
+
"lint-staged": {
|
|
25
|
+
"*.{js,ts,tsx,json,md}": [
|
|
26
|
+
"eslint --fix",
|
|
27
|
+
"prettier --write"
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
"commitlint": {
|
|
31
|
+
"extends": [
|
|
32
|
+
"@commitlint/config-conventional"
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "git+https://github.com/qaPaschalE/playwright-cucumber-ts-steps.git"
|
|
21
38
|
},
|
|
22
39
|
"keywords": [
|
|
23
40
|
"playwright",
|
|
@@ -44,13 +61,36 @@
|
|
|
44
61
|
},
|
|
45
62
|
"homepage": "https://github.com/qaPaschalE/playwright-cucumber-ts-steps#readme",
|
|
46
63
|
"peerDependencies": {
|
|
47
|
-
"@playwright/test": "
|
|
64
|
+
"@playwright/test": "*"
|
|
48
65
|
},
|
|
66
|
+
"files": [
|
|
67
|
+
"dist/"
|
|
68
|
+
],
|
|
49
69
|
"devDependencies": {
|
|
70
|
+
"@commitlint/cli": "^19.8.1",
|
|
71
|
+
"@commitlint/config-conventional": "^19.8.1",
|
|
50
72
|
"@playwright/test": "^1.41.0",
|
|
51
73
|
"@types/glob": "^8.1.0",
|
|
52
74
|
"@types/node": "^20.11.0",
|
|
75
|
+
"@types/pngjs": "^6.0.5",
|
|
76
|
+
"@typescript-eslint/eslint-plugin": "^8.52.0",
|
|
77
|
+
"@typescript-eslint/parser": "^8.52.0",
|
|
78
|
+
"eslint": "^9.29.0",
|
|
79
|
+
"eslint-config-prettier": "^10.1.5",
|
|
80
|
+
"eslint-plugin-import": "^2.32.0",
|
|
81
|
+
"gh-pages": "^6.3.0",
|
|
82
|
+
"husky": "^9.1.7",
|
|
83
|
+
"lint-staged": "^16.1.2",
|
|
84
|
+
"prettier": "^3.5.3",
|
|
85
|
+
"ts-node": "^10.9.2",
|
|
53
86
|
"typedoc": "^0.28.15",
|
|
54
|
-
"typescript": "^5.3.3"
|
|
87
|
+
"typescript": "^5.3.3",
|
|
88
|
+
"typescript-eslint": "^8.34.1"
|
|
89
|
+
},
|
|
90
|
+
"dependencies": {
|
|
91
|
+
"@cucumber/cucumber-expressions": "^17.1.0",
|
|
92
|
+
"@cucumber/gherkin": "^27.0.0",
|
|
93
|
+
"@cucumber/messages": "^22.0.0",
|
|
94
|
+
"glob": "^10.3.10"
|
|
55
95
|
}
|
|
56
96
|
}
|