pw-element-interactions 0.0.4 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +167 -15
- package/dist/enum/Options.d.ts +53 -0
- package/dist/enum/Options.js +15 -0
- package/dist/fixture/BaseFixture.d.ts +13 -0
- package/dist/fixture/BaseFixture.js +24 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.js +28 -10
- package/dist/interactions/Extraction.d.ts +25 -0
- package/dist/interactions/Extraction.js +40 -0
- package/dist/interactions/Interaction.d.ts +33 -24
- package/dist/interactions/Interaction.js +111 -27
- package/dist/interactions/Navigation.js +0 -4
- package/dist/interactions/Verification.d.ts +20 -9
- package/dist/interactions/Verification.js +58 -13
- package/dist/interactions/facade/ElementInteractions.d.ts +24 -0
- package/dist/interactions/facade/ElementInteractions.js +33 -0
- package/dist/steps/CommonSteps.d.ts +97 -18
- package/dist/steps/CommonSteps.js +149 -22
- package/dist/utils/DateUtilities.js +1 -5
- package/dist/utils/ElementUtilities.d.ts +26 -0
- package/dist/utils/ElementUtilities.js +51 -0
- package/package.json +4 -2
- package/dist/ElementInteractions.d.ts +0 -10
- package/dist/ElementInteractions.js +0 -17
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Page } from '@playwright/test';
|
|
2
2
|
import { ElementRepository } from 'pw-element-repository';
|
|
3
|
-
import { DropdownSelectOptions } from '../
|
|
3
|
+
import { DropdownSelectOptions, TextVerifyOptions, CountVerifyOptions, DragAndDropOptions } from '../enum/Options';
|
|
4
4
|
/**
|
|
5
5
|
* The `Steps` class serves as a unified Facade for test orchestration.
|
|
6
6
|
* It combines element acquisition (via `pw-element-repository`) with
|
|
@@ -12,52 +12,87 @@ export declare class Steps {
|
|
|
12
12
|
private repo;
|
|
13
13
|
private interact;
|
|
14
14
|
private navigate;
|
|
15
|
+
private extract;
|
|
15
16
|
private verify;
|
|
17
|
+
private utils;
|
|
16
18
|
/**
|
|
17
19
|
* Initializes the Steps class with the required Playwright page and element repository.
|
|
18
|
-
*
|
|
20
|
+
* @param page - The current Playwright Page object.
|
|
19
21
|
* @param repo - An initialized instance of `ElementRepository` containing your locators.
|
|
22
|
+
* @param timeout - Optional global timeout override (in milliseconds).
|
|
20
23
|
*/
|
|
21
|
-
constructor(page: Page, repo: ElementRepository);
|
|
24
|
+
constructor(page: Page, repo: ElementRepository, timeout?: number);
|
|
22
25
|
/**
|
|
23
26
|
* Navigates the browser to the specified URL.
|
|
24
|
-
*
|
|
27
|
+
* @param url - The absolute or relative URL to navigate to.
|
|
25
28
|
*/
|
|
26
29
|
navigateTo(url: string): Promise<void>;
|
|
27
30
|
/**
|
|
28
31
|
* Reloads the current page.
|
|
29
32
|
*/
|
|
30
33
|
refresh(): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Navigates the browser history stack either backwards or forwards.
|
|
36
|
+
* Mirrors the behavior of the browser's native Back and Forward buttons.
|
|
37
|
+
* @param direction - The direction to move in history: either 'BACKWARDS' or 'FORWARDS'.
|
|
38
|
+
*/
|
|
39
|
+
backOrForward(direction: 'BACKWARDS' | 'FORWARDS'): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Resizes the browser viewport to the specified dimensions.
|
|
42
|
+
* Useful for simulating different device screen sizes or responsive breakpoints.
|
|
43
|
+
* @param width - The desired width of the viewport in pixels.
|
|
44
|
+
* @param height - The desired height of the viewport in pixels.
|
|
45
|
+
*/
|
|
46
|
+
setViewport(width: number, height: number): Promise<void>;
|
|
31
47
|
/**
|
|
32
48
|
* Retrieves an element from the repository and performs a standard click.
|
|
33
|
-
*
|
|
49
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
34
50
|
* @param elementName - The specific element name in your repository.
|
|
35
51
|
*/
|
|
36
52
|
click(pageName: string, elementName: string): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* Retrieves an element and dispatches a native 'click' event directly to it.
|
|
55
|
+
* Bypasses default scrolling and intersection checks. Useful for obscured elements.
|
|
56
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
57
|
+
* @param elementName - The specific element name in your repository.
|
|
58
|
+
*/
|
|
59
|
+
clickWithoutScrolling(pageName: string, elementName: string): Promise<void>;
|
|
37
60
|
/**
|
|
38
61
|
* Retrieves a random element from a resolved list of locators and clicks it.
|
|
39
62
|
* Useful for clicking random items in a list or grid (e.g., product cards).
|
|
40
|
-
*
|
|
63
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
41
64
|
* @param elementName - The specific element name in your repository representing multiple elements.
|
|
42
65
|
*/
|
|
43
66
|
clickRandom(pageName: string, elementName: string): Promise<void>;
|
|
44
67
|
/**
|
|
45
68
|
* Retrieves an element and clicks it only if it is visible.
|
|
46
69
|
* Prevents test failures on optional elements like cookie banners or promotional pop-ups.
|
|
47
|
-
*
|
|
70
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
48
71
|
* @param elementName - The specific element name in your repository.
|
|
49
72
|
*/
|
|
50
73
|
clickIfPresent(pageName: string, elementName: string): Promise<void>;
|
|
74
|
+
/**
|
|
75
|
+
* Retrieves an element and hovers over it. Useful for triggering dropdowns or tooltips.
|
|
76
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
77
|
+
* @param elementName - The specific element name in your repository.
|
|
78
|
+
*/
|
|
79
|
+
hover(pageName: string, elementName: string): Promise<void>;
|
|
80
|
+
/**
|
|
81
|
+
* Retrieves an element and scrolls it into view if it is not already visible.
|
|
82
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
83
|
+
* @param elementName - The specific element name in your repository.
|
|
84
|
+
*/
|
|
85
|
+
scrollIntoView(pageName: string, elementName: string): Promise<void>;
|
|
51
86
|
/**
|
|
52
87
|
* Retrieves an input field and fills it with the provided text, replacing any existing value.
|
|
53
|
-
*
|
|
88
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
54
89
|
* @param elementName - The specific element name in your repository.
|
|
55
90
|
* @param text - The text to type into the input field.
|
|
56
91
|
*/
|
|
57
92
|
fill(pageName: string, elementName: string, text: string): Promise<void>;
|
|
58
93
|
/**
|
|
59
94
|
* Retrieves an input element of type `file` and sets its files.
|
|
60
|
-
*
|
|
95
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
61
96
|
* @param elementName - The specific element name in your repository.
|
|
62
97
|
* @param filePath - The local file path of the file to be uploaded.
|
|
63
98
|
*/
|
|
@@ -65,43 +100,87 @@ export declare class Steps {
|
|
|
65
100
|
/**
|
|
66
101
|
* Retrieves a `<select>` dropdown element and selects an option based on the provided strategy.
|
|
67
102
|
* Defaults to selecting a random, non-disabled option if no strategy is specified.
|
|
68
|
-
*
|
|
103
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
69
104
|
* @param elementName - The specific element name in your repository.
|
|
70
105
|
* @param options - Configuration specifying whether to select by 'random', 'index', or 'value'.
|
|
71
106
|
* @returns The exact value attribute of the selected option.
|
|
72
107
|
*/
|
|
73
108
|
selectDropdown(pageName: string, elementName: string, options?: DropdownSelectOptions): Promise<string>;
|
|
109
|
+
/**
|
|
110
|
+
* Drags an element either to a specified target element, a target element with an offset, or by a coordinate offset.
|
|
111
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
112
|
+
* @param elementName - The specific element name in your repository (the element to drag).
|
|
113
|
+
* @param options - Configuration specifying a 'targetLocator', offsets, or both.
|
|
114
|
+
*/
|
|
115
|
+
dragAndDrop(pageName: string, elementName: string, options: DragAndDropOptions): Promise<void>;
|
|
116
|
+
/**
|
|
117
|
+
* Drags an element either to a specified target element, a target element with an offset, or by a coordinate offset.
|
|
118
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
119
|
+
* @param elementName - The specific element name in your repository (the element to drag).
|
|
120
|
+
* @param options - Configuration specifying a 'targetLocator', offsets, or both.
|
|
121
|
+
*/
|
|
122
|
+
dragAndDropListedElement(pageName: string, elementName: string, elementText: string, options: DragAndDropOptions): Promise<void>;
|
|
123
|
+
/**
|
|
124
|
+
* Safely retrieves and trims the text content of a specified element.
|
|
125
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
126
|
+
* @param elementName - The specific element name in your repository.
|
|
127
|
+
* @returns The trimmed string, or an empty string if null.
|
|
128
|
+
*/
|
|
129
|
+
getText(pageName: string, elementName: string): Promise<string | null>;
|
|
130
|
+
/**
|
|
131
|
+
* Retrieves the value of a specified attribute (e.g., 'href', 'aria-pressed') from an element.
|
|
132
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
133
|
+
* @param elementName - The specific element name in your repository.
|
|
134
|
+
* @param attributeName - The name of the attribute to retrieve.
|
|
135
|
+
* @returns The attribute value as a string, or null if it doesn't exist.
|
|
136
|
+
*/
|
|
137
|
+
getAttribute(pageName: string, elementName: string, attributeName: string): Promise<string | null>;
|
|
74
138
|
/**
|
|
75
139
|
* Asserts that a specified element is attached to the DOM and is visible.
|
|
76
|
-
*
|
|
140
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
77
141
|
* @param elementName - The specific element name in your repository.
|
|
78
142
|
*/
|
|
79
143
|
verifyPresence(pageName: string, elementName: string): Promise<void>;
|
|
80
144
|
/**
|
|
81
145
|
* Asserts that a specified element is hidden or completely detached from the DOM.
|
|
82
|
-
*
|
|
146
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
83
147
|
* @param elementName - The specific element name in your repository.
|
|
84
148
|
*/
|
|
85
149
|
verifyAbsence(pageName: string, elementName: string): Promise<void>;
|
|
86
150
|
/**
|
|
87
|
-
* Asserts that the specified element exactly matches the expected text.
|
|
88
|
-
*
|
|
151
|
+
* Asserts that the specified element exactly matches the expected text, or optionally checks if it is not empty.
|
|
152
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
153
|
+
* @param elementName - The specific element name in your repository.
|
|
154
|
+
* @param expectedText - The exact string expected inside the element (optional if checking 'notEmpty').
|
|
155
|
+
* @param options - Configuration to alter the verification behavior.
|
|
156
|
+
*/
|
|
157
|
+
verifyText(pageName: string, elementName: string, expectedText?: string, options?: TextVerifyOptions): Promise<void>;
|
|
158
|
+
/**
|
|
159
|
+
* Asserts the number of elements matching the locator based on the provided conditions.
|
|
160
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
89
161
|
* @param elementName - The specific element name in your repository.
|
|
90
|
-
* @param
|
|
162
|
+
* @param options - Configuration specifying 'exact', 'greaterThan', or 'lessThan' logic.
|
|
91
163
|
*/
|
|
92
|
-
|
|
164
|
+
verifyCount(pageName: string, elementName: string, options: CountVerifyOptions): Promise<void>;
|
|
93
165
|
/**
|
|
94
166
|
* Performs a rigorous verification of one or more images.
|
|
95
167
|
* Asserts visibility, checks for a valid 'src' attribute, ensures a positive 'naturalWidth',
|
|
96
168
|
* and evaluates the native browser `decode()` promise to ensure the image isn't broken.
|
|
97
|
-
*
|
|
169
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
98
170
|
* @param elementName - The specific element name in your repository.
|
|
99
171
|
* @param scroll - Whether to smoothly scroll the image(s) into view before verifying (default: true).
|
|
100
172
|
*/
|
|
101
173
|
verifyImages(pageName: string, elementName: string, scroll?: boolean): Promise<void>;
|
|
102
174
|
/**
|
|
103
175
|
* Asserts that the current browser URL contains the expected substring.
|
|
104
|
-
*
|
|
176
|
+
* @param text - The substring expected to be present within the active URL.
|
|
105
177
|
*/
|
|
106
178
|
verifyUrlContains(text: string): Promise<void>;
|
|
179
|
+
/**
|
|
180
|
+
* Waits for an element to reach a specific state in the DOM.
|
|
181
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
182
|
+
* @param elementName - The specific element name in your repository.
|
|
183
|
+
* @param state - The state to wait for: 'visible' | 'attached' | 'hidden' | 'detached'. Defaults to 'visible'.
|
|
184
|
+
*/
|
|
185
|
+
waitForState(pageName: string, elementName: string, state?: 'visible' | 'attached' | 'hidden' | 'detached'): Promise<void>;
|
|
107
186
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Steps = void 0;
|
|
4
|
-
const ElementInteractions_1 = require("../ElementInteractions");
|
|
4
|
+
const ElementInteractions_1 = require("../interactions/facade/ElementInteractions");
|
|
5
5
|
/**
|
|
6
6
|
* The `Steps` class serves as a unified Facade for test orchestration.
|
|
7
7
|
* It combines element acquisition (via `pw-element-repository`) with
|
|
@@ -13,26 +13,31 @@ class Steps {
|
|
|
13
13
|
repo;
|
|
14
14
|
interact;
|
|
15
15
|
navigate;
|
|
16
|
+
extract;
|
|
16
17
|
verify;
|
|
18
|
+
utils;
|
|
17
19
|
/**
|
|
18
20
|
* Initializes the Steps class with the required Playwright page and element repository.
|
|
19
|
-
*
|
|
21
|
+
* @param page - The current Playwright Page object.
|
|
20
22
|
* @param repo - An initialized instance of `ElementRepository` containing your locators.
|
|
23
|
+
* @param timeout - Optional global timeout override (in milliseconds).
|
|
21
24
|
*/
|
|
22
|
-
constructor(page, repo) {
|
|
25
|
+
constructor(page, repo, timeout) {
|
|
23
26
|
this.page = page;
|
|
24
27
|
this.repo = repo;
|
|
25
|
-
const interactions = new ElementInteractions_1.ElementInteractions(page);
|
|
28
|
+
const interactions = new ElementInteractions_1.ElementInteractions(page, timeout);
|
|
26
29
|
this.interact = interactions.interact;
|
|
27
30
|
this.navigate = interactions.navigate;
|
|
31
|
+
this.extract = interactions.extract;
|
|
28
32
|
this.verify = interactions.verify;
|
|
33
|
+
this.utils = interactions.utils;
|
|
29
34
|
}
|
|
30
35
|
// ==========================================
|
|
31
36
|
// 🧭 NAVIGATION STEPS
|
|
32
37
|
// ==========================================
|
|
33
38
|
/**
|
|
34
39
|
* Navigates the browser to the specified URL.
|
|
35
|
-
*
|
|
40
|
+
* @param url - The absolute or relative URL to navigate to.
|
|
36
41
|
*/
|
|
37
42
|
async navigateTo(url) {
|
|
38
43
|
console.log(`[Step] -> Navigating to URL: "${url}"`);
|
|
@@ -45,12 +50,31 @@ class Steps {
|
|
|
45
50
|
console.log(`[Step] -> Refreshing the current page`);
|
|
46
51
|
await this.navigate.reload();
|
|
47
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Navigates the browser history stack either backwards or forwards.
|
|
55
|
+
* Mirrors the behavior of the browser's native Back and Forward buttons.
|
|
56
|
+
* @param direction - The direction to move in history: either 'BACKWARDS' or 'FORWARDS'.
|
|
57
|
+
*/
|
|
58
|
+
async backOrForward(direction) {
|
|
59
|
+
console.log(`[Step] -> Navigating browser: "${direction}"`);
|
|
60
|
+
await this.navigate.backOrForward(direction);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Resizes the browser viewport to the specified dimensions.
|
|
64
|
+
* Useful for simulating different device screen sizes or responsive breakpoints.
|
|
65
|
+
* @param width - The desired width of the viewport in pixels.
|
|
66
|
+
* @param height - The desired height of the viewport in pixels.
|
|
67
|
+
*/
|
|
68
|
+
async setViewport(width, height) {
|
|
69
|
+
console.log(`[Step] -> Setting viewport to ${width}x${height}`);
|
|
70
|
+
await this.navigate.setViewport(width, height);
|
|
71
|
+
}
|
|
48
72
|
// ==========================================
|
|
49
73
|
// 🖱️ INTERACTION STEPS
|
|
50
74
|
// ==========================================
|
|
51
75
|
/**
|
|
52
76
|
* Retrieves an element from the repository and performs a standard click.
|
|
53
|
-
*
|
|
77
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
54
78
|
* @param elementName - The specific element name in your repository.
|
|
55
79
|
*/
|
|
56
80
|
async click(pageName, elementName) {
|
|
@@ -58,10 +82,21 @@ class Steps {
|
|
|
58
82
|
const locator = await this.repo.get(this.page, pageName, elementName);
|
|
59
83
|
await this.interact.click(locator);
|
|
60
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Retrieves an element and dispatches a native 'click' event directly to it.
|
|
87
|
+
* Bypasses default scrolling and intersection checks. Useful for obscured elements.
|
|
88
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
89
|
+
* @param elementName - The specific element name in your repository.
|
|
90
|
+
*/
|
|
91
|
+
async clickWithoutScrolling(pageName, elementName) {
|
|
92
|
+
console.log(`[Step] -> Clicking (no scroll) on '${elementName}' in '${pageName}'`);
|
|
93
|
+
const locator = await this.repo.get(this.page, pageName, elementName);
|
|
94
|
+
await this.interact.clickWithoutScrolling(locator);
|
|
95
|
+
}
|
|
61
96
|
/**
|
|
62
97
|
* Retrieves a random element from a resolved list of locators and clicks it.
|
|
63
98
|
* Useful for clicking random items in a list or grid (e.g., product cards).
|
|
64
|
-
*
|
|
99
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
65
100
|
* @param elementName - The specific element name in your repository representing multiple elements.
|
|
66
101
|
*/
|
|
67
102
|
async clickRandom(pageName, elementName) {
|
|
@@ -72,7 +107,7 @@ class Steps {
|
|
|
72
107
|
/**
|
|
73
108
|
* Retrieves an element and clicks it only if it is visible.
|
|
74
109
|
* Prevents test failures on optional elements like cookie banners or promotional pop-ups.
|
|
75
|
-
*
|
|
110
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
76
111
|
* @param elementName - The specific element name in your repository.
|
|
77
112
|
*/
|
|
78
113
|
async clickIfPresent(pageName, elementName) {
|
|
@@ -80,9 +115,29 @@ class Steps {
|
|
|
80
115
|
const locator = await this.repo.get(this.page, pageName, elementName);
|
|
81
116
|
await this.interact.clickIfPresent(locator);
|
|
82
117
|
}
|
|
118
|
+
/**
|
|
119
|
+
* Retrieves an element and hovers over it. Useful for triggering dropdowns or tooltips.
|
|
120
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
121
|
+
* @param elementName - The specific element name in your repository.
|
|
122
|
+
*/
|
|
123
|
+
async hover(pageName, elementName) {
|
|
124
|
+
console.log(`[Step] -> Hovering over '${elementName}' in '${pageName}'`);
|
|
125
|
+
const locator = await this.repo.get(this.page, pageName, elementName);
|
|
126
|
+
await this.interact.hover(locator);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Retrieves an element and scrolls it into view if it is not already visible.
|
|
130
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
131
|
+
* @param elementName - The specific element name in your repository.
|
|
132
|
+
*/
|
|
133
|
+
async scrollIntoView(pageName, elementName) {
|
|
134
|
+
console.log(`[Step] -> Scrolling '${elementName}' in '${pageName}' into view`);
|
|
135
|
+
const locator = await this.repo.get(this.page, pageName, elementName);
|
|
136
|
+
await this.interact.scrollIntoView(locator);
|
|
137
|
+
}
|
|
83
138
|
/**
|
|
84
139
|
* Retrieves an input field and fills it with the provided text, replacing any existing value.
|
|
85
|
-
*
|
|
140
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
86
141
|
* @param elementName - The specific element name in your repository.
|
|
87
142
|
* @param text - The text to type into the input field.
|
|
88
143
|
*/
|
|
@@ -93,7 +148,7 @@ class Steps {
|
|
|
93
148
|
}
|
|
94
149
|
/**
|
|
95
150
|
* Retrieves an input element of type `file` and sets its files.
|
|
96
|
-
*
|
|
151
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
97
152
|
* @param elementName - The specific element name in your repository.
|
|
98
153
|
* @param filePath - The local file path of the file to be uploaded.
|
|
99
154
|
*/
|
|
@@ -105,7 +160,7 @@ class Steps {
|
|
|
105
160
|
/**
|
|
106
161
|
* Retrieves a `<select>` dropdown element and selects an option based on the provided strategy.
|
|
107
162
|
* Defaults to selecting a random, non-disabled option if no strategy is specified.
|
|
108
|
-
*
|
|
163
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
109
164
|
* @param elementName - The specific element name in your repository.
|
|
110
165
|
* @param options - Configuration specifying whether to select by 'random', 'index', or 'value'.
|
|
111
166
|
* @returns The exact value attribute of the selected option.
|
|
@@ -116,12 +171,60 @@ class Steps {
|
|
|
116
171
|
const locator = await this.repo.get(this.page, pageName, elementName);
|
|
117
172
|
return await this.interact.selectDropdown(locator, options);
|
|
118
173
|
}
|
|
174
|
+
/**
|
|
175
|
+
* Drags an element either to a specified target element, a target element with an offset, or by a coordinate offset.
|
|
176
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
177
|
+
* @param elementName - The specific element name in your repository (the element to drag).
|
|
178
|
+
* @param options - Configuration specifying a 'targetLocator', offsets, or both.
|
|
179
|
+
*/
|
|
180
|
+
async dragAndDrop(pageName, elementName, options) {
|
|
181
|
+
console.log(`[Step] -> Dragging and dropping '${elementName}' in '${pageName}'`);
|
|
182
|
+
const locator = await this.repo.get(this.page, pageName, elementName);
|
|
183
|
+
await this.interact.dragAndDrop(locator, options);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Drags an element either to a specified target element, a target element with an offset, or by a coordinate offset.
|
|
187
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
188
|
+
* @param elementName - The specific element name in your repository (the element to drag).
|
|
189
|
+
* @param options - Configuration specifying a 'targetLocator', offsets, or both.
|
|
190
|
+
*/
|
|
191
|
+
async dragAndDropListedElement(pageName, elementName, elementText, options) {
|
|
192
|
+
console.log(`[Step] -> Dragging and dropping '${elementText}' in '${pageName}'`);
|
|
193
|
+
const locator = await this.repo.getByText(this.page, pageName, elementName, elementText);
|
|
194
|
+
await this.interact.dragAndDrop(locator, options);
|
|
195
|
+
}
|
|
196
|
+
// ==========================================
|
|
197
|
+
// 📊 DATA EXTRACTION STEPS
|
|
198
|
+
// ==========================================
|
|
199
|
+
/**
|
|
200
|
+
* Safely retrieves and trims the text content of a specified element.
|
|
201
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
202
|
+
* @param elementName - The specific element name in your repository.
|
|
203
|
+
* @returns The trimmed string, or an empty string if null.
|
|
204
|
+
*/
|
|
205
|
+
async getText(pageName, elementName) {
|
|
206
|
+
console.log(`[Step] -> Getting text from '${elementName}' in '${pageName}'`);
|
|
207
|
+
const locator = await this.repo.get(this.page, pageName, elementName);
|
|
208
|
+
return await this.extract.getText(locator);
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Retrieves the value of a specified attribute (e.g., 'href', 'aria-pressed') from an element.
|
|
212
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
213
|
+
* @param elementName - The specific element name in your repository.
|
|
214
|
+
* @param attributeName - The name of the attribute to retrieve.
|
|
215
|
+
* @returns The attribute value as a string, or null if it doesn't exist.
|
|
216
|
+
*/
|
|
217
|
+
async getAttribute(pageName, elementName, attributeName) {
|
|
218
|
+
console.log(`[Step] -> Getting attribute '${attributeName}' from '${elementName}' in '${pageName}'`);
|
|
219
|
+
const locator = await this.repo.get(this.page, pageName, elementName);
|
|
220
|
+
return await this.extract.getAttribute(locator, attributeName);
|
|
221
|
+
}
|
|
119
222
|
// ==========================================
|
|
120
223
|
// ✅ VERIFICATION STEPS
|
|
121
224
|
// ==========================================
|
|
122
225
|
/**
|
|
123
226
|
* Asserts that a specified element is attached to the DOM and is visible.
|
|
124
|
-
*
|
|
227
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
125
228
|
* @param elementName - The specific element name in your repository.
|
|
126
229
|
*/
|
|
127
230
|
async verifyPresence(pageName, elementName) {
|
|
@@ -131,30 +234,43 @@ class Steps {
|
|
|
131
234
|
}
|
|
132
235
|
/**
|
|
133
236
|
* Asserts that a specified element is hidden or completely detached from the DOM.
|
|
134
|
-
*
|
|
237
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
135
238
|
* @param elementName - The specific element name in your repository.
|
|
136
239
|
*/
|
|
137
240
|
async verifyAbsence(pageName, elementName) {
|
|
138
241
|
console.log(`[Step] -> Verifying absence of '${elementName}' in '${pageName}'`);
|
|
242
|
+
const selector = await this.repo.getSelector(pageName, elementName);
|
|
243
|
+
await this.verify.absence(selector);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Asserts that the specified element exactly matches the expected text, or optionally checks if it is not empty.
|
|
247
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
248
|
+
* @param elementName - The specific element name in your repository.
|
|
249
|
+
* @param expectedText - The exact string expected inside the element (optional if checking 'notEmpty').
|
|
250
|
+
* @param options - Configuration to alter the verification behavior.
|
|
251
|
+
*/
|
|
252
|
+
async verifyText(pageName, elementName, expectedText, options) {
|
|
253
|
+
const logDetail = options?.notEmpty ? `is not empty` : `matches: "${expectedText}"`;
|
|
254
|
+
console.log(`[Step] -> Verifying text of '${elementName}' in '${pageName}' ${logDetail}`);
|
|
139
255
|
const locator = await this.repo.get(this.page, pageName, elementName);
|
|
140
|
-
await this.verify.
|
|
256
|
+
await this.verify.text(locator, expectedText, options);
|
|
141
257
|
}
|
|
142
258
|
/**
|
|
143
|
-
* Asserts
|
|
144
|
-
*
|
|
259
|
+
* Asserts the number of elements matching the locator based on the provided conditions.
|
|
260
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
145
261
|
* @param elementName - The specific element name in your repository.
|
|
146
|
-
* @param
|
|
262
|
+
* @param options - Configuration specifying 'exact', 'greaterThan', or 'lessThan' logic.
|
|
147
263
|
*/
|
|
148
|
-
async
|
|
149
|
-
console.log(`[Step] -> Verifying
|
|
264
|
+
async verifyCount(pageName, elementName, options) {
|
|
265
|
+
console.log(`[Step] -> Verifying count for '${elementName}' in '${pageName}' with options: ${JSON.stringify(options)}`);
|
|
150
266
|
const locator = await this.repo.get(this.page, pageName, elementName);
|
|
151
|
-
await this.verify.
|
|
267
|
+
await this.verify.count(locator, options);
|
|
152
268
|
}
|
|
153
269
|
/**
|
|
154
270
|
* Performs a rigorous verification of one or more images.
|
|
155
271
|
* Asserts visibility, checks for a valid 'src' attribute, ensures a positive 'naturalWidth',
|
|
156
272
|
* and evaluates the native browser `decode()` promise to ensure the image isn't broken.
|
|
157
|
-
*
|
|
273
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
158
274
|
* @param elementName - The specific element name in your repository.
|
|
159
275
|
* @param scroll - Whether to smoothly scroll the image(s) into view before verifying (default: true).
|
|
160
276
|
*/
|
|
@@ -165,11 +281,22 @@ class Steps {
|
|
|
165
281
|
}
|
|
166
282
|
/**
|
|
167
283
|
* Asserts that the current browser URL contains the expected substring.
|
|
168
|
-
*
|
|
284
|
+
* @param text - The substring expected to be present within the active URL.
|
|
169
285
|
*/
|
|
170
286
|
async verifyUrlContains(text) {
|
|
171
287
|
console.log(`[Step] -> Verifying current URL contains: "${text}"`);
|
|
172
288
|
await this.verify.urlContains(text);
|
|
173
289
|
}
|
|
290
|
+
/**
|
|
291
|
+
* Waits for an element to reach a specific state in the DOM.
|
|
292
|
+
* @param pageName - The page or component grouping name in your repository.
|
|
293
|
+
* @param elementName - The specific element name in your repository.
|
|
294
|
+
* @param state - The state to wait for: 'visible' | 'attached' | 'hidden' | 'detached'. Defaults to 'visible'.
|
|
295
|
+
*/
|
|
296
|
+
async waitForState(pageName, elementName, state = 'visible') {
|
|
297
|
+
console.log(`[Step] -> Waiting for '${elementName}' in '${pageName}' to be '${state}'`);
|
|
298
|
+
const locator = await this.repo.get(this.page, pageName, elementName);
|
|
299
|
+
await this.utils.waitForState(locator, state);
|
|
300
|
+
}
|
|
174
301
|
}
|
|
175
302
|
exports.Steps = Steps;
|
|
@@ -7,19 +7,15 @@ class DateUtilities {
|
|
|
7
7
|
* Mirrors the Java DateUtilities.reformatDateString method.
|
|
8
8
|
*/
|
|
9
9
|
static reformatDateString(rawDate, format) {
|
|
10
|
-
// Parse the raw date string into a JS Date object
|
|
11
10
|
const date = new Date(rawDate);
|
|
12
|
-
// Guard clause: Check if the date is valid before formatting
|
|
13
11
|
if (isNaN(date.getTime())) {
|
|
14
12
|
throw new Error(`Invalid date string provided: ${rawDate}`);
|
|
15
13
|
}
|
|
16
14
|
const yyyy = date.getFullYear().toString();
|
|
17
15
|
const MM = String(date.getMonth() + 1).padStart(2, '0');
|
|
18
16
|
const dd = String(date.getDate()).padStart(2, '0');
|
|
19
|
-
// Unpadded variables for single-digit months/days
|
|
20
17
|
const M = String(date.getMonth() + 1);
|
|
21
18
|
const d = String(date.getDate());
|
|
22
|
-
// You can expand this switch/if statement as your framework's formatting needs grow
|
|
23
19
|
switch (format) {
|
|
24
20
|
case 'yyyy-MM-dd':
|
|
25
21
|
return `${yyyy}-${MM}-${dd}`;
|
|
@@ -28,7 +24,7 @@ class DateUtilities {
|
|
|
28
24
|
case 'dd MMM yyyy':
|
|
29
25
|
const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
30
26
|
return `${dd} ${monthNames[date.getMonth()]} ${yyyy}`;
|
|
31
|
-
case 'yyyy-M-d':
|
|
27
|
+
case 'yyyy-M-d':
|
|
32
28
|
return `${yyyy}-${M}-${d}`;
|
|
33
29
|
default:
|
|
34
30
|
console.warn(`Format ${format} not fully supported, returning ISO date.`);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Locator } from '@playwright/test';
|
|
2
|
+
/**
|
|
3
|
+
* Utility class to handle standardized waiting logic across the framework.
|
|
4
|
+
*/
|
|
5
|
+
export declare class Utils {
|
|
6
|
+
private readonly timeout;
|
|
7
|
+
/**
|
|
8
|
+
* @param timeout - Optional timeout in milliseconds. Defaults to 30000.
|
|
9
|
+
*/
|
|
10
|
+
constructor(timeout?: number);
|
|
11
|
+
/**
|
|
12
|
+
* Returns the current timeout value.
|
|
13
|
+
*/
|
|
14
|
+
getTimeout(): number;
|
|
15
|
+
/**
|
|
16
|
+
* Standardized wait logic for element states.
|
|
17
|
+
* Does not fail the test on timeout; logs a warning instead.
|
|
18
|
+
* If the locator resolves to multiple elements (strict mode violation),
|
|
19
|
+
* the wait is retried automatically on the first matched element.
|
|
20
|
+
* @param locator - The Playwright Locator to wait on.
|
|
21
|
+
* @param state - The DOM state to wait for. Defaults to `'visible'`.
|
|
22
|
+
* @returns A Promise that resolves when the element reaches the desired state,
|
|
23
|
+
* or silently continues if the timeout is exceeded.
|
|
24
|
+
*/
|
|
25
|
+
waitForState(locator: Locator, state?: 'visible' | 'attached' | 'hidden' | 'detached'): Promise<void>;
|
|
26
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Utils = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Utility class to handle standardized waiting logic across the framework.
|
|
6
|
+
*/
|
|
7
|
+
class Utils {
|
|
8
|
+
timeout;
|
|
9
|
+
/**
|
|
10
|
+
* @param timeout - Optional timeout in milliseconds. Defaults to 30000.
|
|
11
|
+
*/
|
|
12
|
+
constructor(timeout = 30000) {
|
|
13
|
+
this.timeout = timeout;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Returns the current timeout value.
|
|
17
|
+
*/
|
|
18
|
+
getTimeout() {
|
|
19
|
+
return this.timeout;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Standardized wait logic for element states.
|
|
23
|
+
* Does not fail the test on timeout; logs a warning instead.
|
|
24
|
+
* If the locator resolves to multiple elements (strict mode violation),
|
|
25
|
+
* the wait is retried automatically on the first matched element.
|
|
26
|
+
* @param locator - The Playwright Locator to wait on.
|
|
27
|
+
* @param state - The DOM state to wait for. Defaults to `'visible'`.
|
|
28
|
+
* @returns A Promise that resolves when the element reaches the desired state,
|
|
29
|
+
* or silently continues if the timeout is exceeded.
|
|
30
|
+
*/
|
|
31
|
+
async waitForState(locator, state = 'visible') {
|
|
32
|
+
try {
|
|
33
|
+
await locator.waitFor({ state, timeout: this.timeout });
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
37
|
+
if (message.includes('strict mode violation')) {
|
|
38
|
+
console.warn(`[Warning] -> Locator resolved to multiple elements. Waiting on first element instead.`);
|
|
39
|
+
try {
|
|
40
|
+
await locator.first().waitFor({ state, timeout: this.timeout });
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
console.warn(`[Warning] -> First element failed to reach state '${state}' within ${this.timeout}ms. Proceeding...`);
|
|
44
|
+
}
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
console.warn(`[Warning] -> Element failed to reach state '${state}' within ${this.timeout}ms. Proceeding...`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.Utils = Utils;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pw-element-interactions",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "A robust, readable interaction and assertion Facade for Playwright. Abstract away boilerplate into semantic, English-like methods, making your test automation framework cleaner, easier to maintain, and accessible to non-developers.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -14,10 +14,12 @@
|
|
|
14
14
|
"dist"
|
|
15
15
|
],
|
|
16
16
|
"peerDependencies": {
|
|
17
|
+
"@civitas-cerebrum/context-store": ">=0.0.2",
|
|
17
18
|
"@playwright/test": ">=1.0.0",
|
|
18
19
|
"pw-element-repository": ">=0.0.3"
|
|
19
20
|
},
|
|
20
21
|
"devDependencies": {
|
|
22
|
+
"@civitas-cerebrum/context-store": "^0.0.2",
|
|
21
23
|
"@playwright/test": "^1.58.2",
|
|
22
24
|
"@types/node": "^20.0.0",
|
|
23
25
|
"pw-element-repository": "^0.0.3",
|
|
@@ -43,4 +45,4 @@
|
|
|
43
45
|
},
|
|
44
46
|
"author": "Umut Ay Bora",
|
|
45
47
|
"license": "MIT"
|
|
46
|
-
}
|
|
48
|
+
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { Page } from '@playwright/test';
|
|
2
|
-
import { Interactions } from './interactions/Interaction';
|
|
3
|
-
import { Navigation } from './interactions/Navigation';
|
|
4
|
-
import { Verifications } from './interactions/Verification';
|
|
5
|
-
export declare class ElementInteractions {
|
|
6
|
-
navigate: Navigation;
|
|
7
|
-
interact: Interactions;
|
|
8
|
-
verify: Verifications;
|
|
9
|
-
constructor(page: Page);
|
|
10
|
-
}
|