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
package/README.md
CHANGED
|
@@ -10,6 +10,32 @@ A robust set of Playwright steps for readable interaction and assertions.
|
|
|
10
10
|
|
|
11
11
|
With the introduction of the `Steps` class, you can now combine your element repository and interactions into a single, flattened Facade. This eliminates repetitive locator fetching and transforms your tests into clean, plain-English steps.
|
|
12
12
|
|
|
13
|
+
### 🤖 AI-Friendly Test Development & Boilerplate Reduction
|
|
14
|
+
|
|
15
|
+
Stop writing the same three lines of code for every single interaction. This library handles the fetching, waiting, and acting automatically.
|
|
16
|
+
|
|
17
|
+
Because the API is highly semantic and completely decoupled from the DOM, it is an **ideal framework for AI coding assistants**. AI models can easily generate robust test flows using plain-English strings (`'CheckoutPage'`, `'submitButton'`) without hallucinating complex CSS selectors, writing flaky interactions, or forgetting critical `waitFor` states.
|
|
18
|
+
|
|
19
|
+
**Before (Raw Playwright):**
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
// 1. Hardcode or manage raw locators inside your test
|
|
23
|
+
const submitBtn = page.locator('button[data-test="submit-order"]');
|
|
24
|
+
|
|
25
|
+
// 2. Explicitly wait for DOM stability and visibility
|
|
26
|
+
await submitBtn.waitFor({ state: 'visible', timeout: 30000 });
|
|
27
|
+
|
|
28
|
+
// 3. Perform the interaction
|
|
29
|
+
await submitBtn.click();
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Now (with pw-element-interactions):**
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
// 1. Locate, wait, and interact in a single, readable, AI-friendly line
|
|
36
|
+
await steps.click('CheckoutPage', 'submitButton');
|
|
37
|
+
```
|
|
38
|
+
|
|
13
39
|
---
|
|
14
40
|
|
|
15
41
|
## 📦 Installation
|
|
@@ -30,8 +56,11 @@ This package requires `@playwright/test` to be installed in your project. If you
|
|
|
30
56
|
* **Zero Locator Boilerplate:** The new `Steps` API fetches elements and interacts with them in a single method call.
|
|
31
57
|
* **Separation of Concerns:** Keep your interaction logic entirely detached from how elements are found on the page.
|
|
32
58
|
* **Readable Tests:** Abstract away Playwright boilerplate into semantic methods (`clickIfPresent`, `verifyPresence`, `selectDropdown`).
|
|
59
|
+
* **Standardized Waiting:** Easily wait for elements to reach specific DOM states (visible, hidden, attached, detached) with built-in utility methods.
|
|
33
60
|
* **Advanced Visual Checks:** Includes a highly reliable `verifyImages` method that evaluates actual browser decoding and `naturalWidth` to ensure images aren't just in the DOM, but are properly rendered.
|
|
34
61
|
* **Smart Dropdowns:** Easily select dropdown options by value, index, or completely randomly (skipping disabled or empty options automatically).
|
|
62
|
+
* **Flexible Verifications:** Easily verify exact text, non-empty text, or dynamic element counts (greater than, less than, or exact).
|
|
63
|
+
* **Advanced Drag & Drop:** Seamlessly drag elements to other elements, drop them at specific coordinate offsets, or combine both strategies natively.
|
|
35
64
|
|
|
36
65
|
---
|
|
37
66
|
|
|
@@ -44,7 +73,7 @@ Initialize the `Steps` class by passing the current Playwright `page` object and
|
|
|
44
73
|
```ts
|
|
45
74
|
import { test } from '@playwright/test';
|
|
46
75
|
import { ElementRepository } from 'pw-element-repository';
|
|
47
|
-
import { Steps } from 'pw-element-interactions';
|
|
76
|
+
import { Steps, DropdownSelectType } from 'pw-element-interactions';
|
|
48
77
|
|
|
49
78
|
test('Add random product and verify image gallery', async ({ page }) => {
|
|
50
79
|
// 1. Initialize Repository & Steps
|
|
@@ -62,11 +91,122 @@ test('Add random product and verify image gallery', async ({ page }) => {
|
|
|
62
91
|
await steps.verifyUrlContains('/product/');
|
|
63
92
|
|
|
64
93
|
// 5. Smart Dropdown Interaction
|
|
65
|
-
const selectedSize = await steps.selectDropdown('ProductDetailsPage', 'size-selector', {
|
|
94
|
+
const selectedSize = await steps.selectDropdown('ProductDetailsPage', 'size-selector', {
|
|
95
|
+
type: DropdownSelectType.RANDOM
|
|
96
|
+
});
|
|
66
97
|
console.log(`Selected size: ${selectedSize}`);
|
|
67
98
|
|
|
68
|
-
// 6.
|
|
99
|
+
// 6. Flexible Assertions & Data Extraction
|
|
100
|
+
await steps.verifyCount('ProductDetailsPage', 'gallery-images', { greaterThan: 0 });
|
|
101
|
+
await steps.verifyText('ProductDetailsPage', 'product-title', undefined, { notEmpty: true });
|
|
102
|
+
|
|
103
|
+
// 7. Advanced Image Verification
|
|
69
104
|
await steps.verifyImages('ProductDetailsPage', 'gallery-images');
|
|
105
|
+
|
|
106
|
+
// 8. Explicit Waits
|
|
107
|
+
await steps.waitForState('CheckoutPage', 'confirmation-modal', 'visible');
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## 🔧 Fixtures: Zero-Setup Tests (Recommended)
|
|
114
|
+
|
|
115
|
+
For larger projects, manually initializing `repo` and `steps` inside every test quickly becomes repetitive. `pw-element-interactions` ships a `baseFixture` factory that injects all core dependencies automatically via Playwright's fixture system.
|
|
116
|
+
|
|
117
|
+
### What's included
|
|
118
|
+
|
|
119
|
+
| Fixture | Type | Description |
|
|
120
|
+
|---|---|---|
|
|
121
|
+
| `steps` | `Steps` | The full Steps API, ready to use |
|
|
122
|
+
| `repo` | `ElementRepository` | Direct repository access for advanced locator queries |
|
|
123
|
+
| `interactions` | `ElementInteractions` | Raw interactions API for custom locators |
|
|
124
|
+
| `contextStore` | `ContextStore` | Shared in-memory store for passing data between steps |
|
|
125
|
+
|
|
126
|
+
### 1. Create your fixture file
|
|
127
|
+
|
|
128
|
+
Call `baseFixture` once, passing your own `test` base and the path to your locator repository:
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
// tests/fixtures/base.ts
|
|
132
|
+
import { test as base, expect } from '@playwright/test';
|
|
133
|
+
import { baseFixture } from 'pw-element-interactions';
|
|
134
|
+
|
|
135
|
+
export const test = baseFixture(base, 'tests/data/page-repository.json');
|
|
136
|
+
export { expect };
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### 2. Use fixtures in your tests
|
|
140
|
+
|
|
141
|
+
Import `test` from your fixture file. All four fixtures are available as named parameters — no setup code required:
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
// tests/checkout.spec.ts
|
|
145
|
+
import { test, expect } from '../fixtures/base';
|
|
146
|
+
import { DropdownSelectType } from 'pw-element-interactions';
|
|
147
|
+
|
|
148
|
+
test('Complete checkout flow', async ({ steps }) => {
|
|
149
|
+
await steps.navigateTo('/');
|
|
150
|
+
await steps.click('HomePage', 'category-accessories');
|
|
151
|
+
await steps.clickRandom('AccessoriesPage', 'product-cards');
|
|
152
|
+
await steps.verifyUrlContains('/product/');
|
|
153
|
+
|
|
154
|
+
const selectedSize = await steps.selectDropdown('ProductDetailsPage', 'size-selector', {
|
|
155
|
+
type: DropdownSelectType.RANDOM,
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
await steps.verifyImages('ProductDetailsPage', 'gallery-images');
|
|
159
|
+
await steps.click('ProductDetailsPage', 'add-to-cart-button');
|
|
160
|
+
await steps.waitForState('CheckoutPage', 'confirmation-modal', 'visible');
|
|
161
|
+
});
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### 3. Access `repo` directly when needed
|
|
165
|
+
|
|
166
|
+
For advanced queries like resolving a locator by visible text, destructure `repo` alongside `steps`:
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
test('Navigate to Forms category', async ({ page, repo, steps }) => {
|
|
170
|
+
await steps.navigateTo('/');
|
|
171
|
+
|
|
172
|
+
const formsLink = await repo.getByText(page, 'HomePage', 'categories', 'Forms');
|
|
173
|
+
await formsLink?.click();
|
|
174
|
+
|
|
175
|
+
await steps.verifyAbsence('HomePage', 'categories');
|
|
176
|
+
});
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### 4. Extend with your own fixtures
|
|
180
|
+
|
|
181
|
+
Because `baseFixture` returns a standard Playwright `test` object, you can chain your own fixtures on top of it cleanly:
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
// tests/fixtures/base.ts
|
|
185
|
+
import { test as base } from '@playwright/test';
|
|
186
|
+
import { baseFixture } from 'pw-element-interactions';
|
|
187
|
+
import { AuthService } from '../services/AuthService';
|
|
188
|
+
|
|
189
|
+
type MyFixtures = {
|
|
190
|
+
authService: AuthService;
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const testWithBase = baseFixture(base, 'tests/data/page-repository.json');
|
|
194
|
+
|
|
195
|
+
export const test = testWithBase.extend<MyFixtures>({
|
|
196
|
+
authService: async ({ page }, use) => {
|
|
197
|
+
await use(new AuthService(page));
|
|
198
|
+
},
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
export { expect } from '@playwright/test';
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
All fixtures are then available together in any test:
|
|
205
|
+
|
|
206
|
+
```ts
|
|
207
|
+
test('Authenticated flow', async ({ steps, authService }) => {
|
|
208
|
+
await authService.login('user@test.com', 'secret');
|
|
209
|
+
await steps.verifyUrlContains('/dashboard');
|
|
70
210
|
});
|
|
71
211
|
```
|
|
72
212
|
|
|
@@ -78,31 +218,43 @@ The `Steps` class automatically handles fetching the Playwright `Locator` using
|
|
|
78
218
|
|
|
79
219
|
### 🧭 Navigation
|
|
80
220
|
|
|
81
|
-
* **`
|
|
221
|
+
* **`navigateTo(url: string)`**: Navigates the browser to the specified absolute or relative URL.
|
|
82
222
|
* **`refresh()`**: Reloads the current page.
|
|
223
|
+
* **`backOrForward(direction: 'BACKWARDS' | 'FORWARDS')`**: Navigates the browser history stack either backwards or forwards. Mirrors the behavior of the browser's native Back and Forward buttons.
|
|
224
|
+
* **`setViewport(width: number, height: number)`**: Resizes the browser viewport to the specified pixel dimensions. Useful for simulating different device screen sizes or responsive breakpoints.
|
|
83
225
|
|
|
84
226
|
### 🖱️ Interaction
|
|
85
227
|
|
|
86
|
-
* **`click(pageName: string, elementName: string)`**: Retrieves an element from the repository and performs a standard click. Automatically waits for
|
|
228
|
+
* **`click(pageName: string, elementName: string)`**: Retrieves an element from the repository and performs a standard Playwright click. Automatically waits for the element to be attached, visible, stable, and actionable.
|
|
229
|
+
* **`clickWithoutScrolling(pageName: string, elementName: string)`**: Dispatches a native `click` event directly to the element, bypassing Playwright's default scrolling and intersection observer checks. Highly useful for clicking elements obscured by sticky headers or transparent overlays.
|
|
230
|
+
* **`clickIfPresent(pageName: string, elementName: string)`**: Checks if an element is visible before attempting to click it. Safely skips the action without failing the test if the element is hidden. Great for optional elements like cookie banners.
|
|
87
231
|
* **`clickRandom(pageName: string, elementName: string)`**: Retrieves a random element from a resolved list of locators and clicks it. Useful for clicking random items in a list or grid.
|
|
88
|
-
* **`
|
|
89
|
-
* **`
|
|
90
|
-
* **`
|
|
91
|
-
* **`
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
* `{ type:
|
|
232
|
+
* **`hover(pageName: string, elementName: string)`**: Retrieves an element and hovers over it. Useful for triggering dropdowns or tooltips.
|
|
233
|
+
* **`scrollIntoView(pageName: string, elementName: string)`**: Retrieves an element and smoothly scrolls it into the viewport if it is not already visible.
|
|
234
|
+
* **`dragAndDrop(pageName: string, elementName: string, options: DragAndDropOptions)`**: Drags an element to a specified destination. Supports dropping onto another element (`{ target: Locator }`), dragging by coordinates (`{ xOffset: number, yOffset: number }`), or dropping onto a target at a specific offset.
|
|
235
|
+
* **`dragAndDropListedElement(pageName: string, elementName: string, elementText: string, options: DragAndDropOptions)`**: Finds a specific element by its text from a list of elements and drags it to a specified destination based on the provided options.
|
|
236
|
+
* **`fill(pageName: string, elementName: string, text: string)`**: Clears any existing value in the target input field and types the provided text.
|
|
237
|
+
* **`uploadFile(pageName: string, elementName: string, filePath: string)`**: Uploads a local file from the provided `filePath` to an `<input type="file">` element.
|
|
238
|
+
* **`selectDropdown(pageName: string, elementName: string, options?: DropdownSelectOptions)`**: Selects an option from a `<select>` element and returns its `value`. Defaults to a random, non-disabled option (`{ type: DropdownSelectType.RANDOM }`). Alternatively, select by exact value (`{ type: DropdownSelectType.VALUE, value: '...' }`) or zero-based index (`{ type: DropdownSelectType.INDEX, index: 1 }`).
|
|
95
239
|
|
|
240
|
+
### 📊 Data Extraction
|
|
96
241
|
|
|
242
|
+
* **`getText(pageName: string, elementName: string)`**: Safely retrieves and trims the text content of a specified element. Returns an empty string if null.
|
|
243
|
+
* **`getAttribute(pageName: string, elementName: string, attributeName: string)`**: Retrieves the value of a specified HTML attribute (e.g., `href`, `aria-pressed`) from an element. Returns `null` if the attribute doesn't exist.
|
|
97
244
|
|
|
98
245
|
### ✅ Verification
|
|
99
246
|
|
|
100
247
|
* **`verifyPresence(pageName: string, elementName: string)`**: Asserts that a specified element is attached to the DOM and is visible.
|
|
101
248
|
* **`verifyAbsence(pageName: string, elementName: string)`**: Asserts that a specified element is hidden or completely detached from the DOM.
|
|
102
|
-
* **`verifyText(pageName: string, elementName: string, expectedText
|
|
249
|
+
* **`verifyText(pageName: string, elementName: string, expectedText?: string, options?: TextVerifyOptions)`**: Asserts the text of an element. Provide `expectedText` for an exact match, or pass `{ notEmpty: true }` in the options to simply assert that the dynamically generated text is not blank.
|
|
250
|
+
* **`verifyCount(pageName: string, elementName: string, options: CountVerifyOptions)`**: Asserts the number of elements matching the locator. Accepts a configuration object to evaluate: `{ exact: number }`, `{ greaterThan: number }`, or `{ lessThan: number }`.
|
|
103
251
|
* **`verifyImages(pageName: string, elementName: string, scroll?: boolean)`**: Performs a rigorous verification of one or more images. Asserts visibility, checks for a valid `src` attribute, ensures `naturalWidth > 0`, and evaluates the native browser `decode()` promise. Smoothly scrolls into view by default (`scroll: true`).
|
|
104
252
|
* **`verifyUrlContains(text: string)`**: Asserts that the active browser URL contains the expected substring.
|
|
105
253
|
|
|
254
|
+
### ⏳ Wait
|
|
255
|
+
|
|
256
|
+
* **`waitForState(pageName: string, elementName: string, state?: 'visible' | 'attached' | 'hidden' | 'detached')`**: Waits for an element to reach a specific state in the DOM. Defaults to `'visible'`.
|
|
257
|
+
|
|
106
258
|
---
|
|
107
259
|
|
|
108
260
|
## 🧱 Advanced Usage: Raw Interactions API
|
|
@@ -118,7 +270,7 @@ const interactions = new ElementInteractions(page);
|
|
|
118
270
|
// Pass Playwright Locators directly
|
|
119
271
|
const customLocator = page.locator('button.dynamic-class');
|
|
120
272
|
await interactions.interact.clickWithoutScrolling(customLocator);
|
|
121
|
-
await interactions.verify.
|
|
273
|
+
await interactions.verify.count(customLocator, { greaterThan: 2 });
|
|
122
274
|
```
|
|
123
275
|
|
|
124
|
-
*Note: All core interaction (`interact`), verification (`verify`), and navigation (`
|
|
276
|
+
*Note: All core interaction (`interact`), verification (`verify`), and navigation (`navigate`) methods are also available when using `ElementInteractions` directly.*
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Locator } from '@playwright/test';
|
|
2
|
+
/**
|
|
3
|
+
* Defines the strategy for selecting an option from a dropdown element.
|
|
4
|
+
*/
|
|
5
|
+
export declare enum DropdownSelectType {
|
|
6
|
+
/** Selects a completely random, non-disabled option with a valid value. */
|
|
7
|
+
RANDOM = "random",
|
|
8
|
+
/** Selects an option based on its zero-based index in the dropdown. */
|
|
9
|
+
INDEX = "index",
|
|
10
|
+
/** Selects an option based on its exact 'value' attribute. */
|
|
11
|
+
VALUE = "value"
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Configuration options for the `selectDropdown` method.
|
|
15
|
+
*/
|
|
16
|
+
export interface DropdownSelectOptions {
|
|
17
|
+
/** The selection strategy to use. Defaults to RANDOM. */
|
|
18
|
+
type?: DropdownSelectType;
|
|
19
|
+
/** The specific value attribute to select (Required if type is VALUE). */
|
|
20
|
+
value?: string;
|
|
21
|
+
/** The index of the option to select (Required if type is INDEX). */
|
|
22
|
+
index?: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Configuration options for the `text` verification method.
|
|
26
|
+
*/
|
|
27
|
+
export interface TextVerifyOptions {
|
|
28
|
+
/** If true, asserts that the element has text content, ignoring 'expectedText' */
|
|
29
|
+
notEmpty?: boolean;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Configuration options for the `count` verification method.
|
|
33
|
+
*/
|
|
34
|
+
export interface CountVerifyOptions {
|
|
35
|
+
/** Asserts that the element count exactly matches this value */
|
|
36
|
+
exactly?: number;
|
|
37
|
+
/** Asserts that the element count is strictly greater than this value */
|
|
38
|
+
greaterThan?: number;
|
|
39
|
+
/** Asserts that the element count is strictly less than this value */
|
|
40
|
+
lessThan?: number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Configuration options for the `dragAndDrop` method.
|
|
44
|
+
* You must provide either a `targetLocator` OR both `xOffset` and `yOffset`.
|
|
45
|
+
*/
|
|
46
|
+
export interface DragAndDropOptions {
|
|
47
|
+
/** The destination element to drop the dragged element onto. */
|
|
48
|
+
target?: Locator;
|
|
49
|
+
/** The horizontal offset from the center of the element (positive moves right). */
|
|
50
|
+
xOffset?: number;
|
|
51
|
+
/** The vertical offset from the center of the element (positive moves down). */
|
|
52
|
+
yOffset?: number;
|
|
53
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DropdownSelectType = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Defines the strategy for selecting an option from a dropdown element.
|
|
6
|
+
*/
|
|
7
|
+
var DropdownSelectType;
|
|
8
|
+
(function (DropdownSelectType) {
|
|
9
|
+
/** Selects a completely random, non-disabled option with a valid value. */
|
|
10
|
+
DropdownSelectType["RANDOM"] = "random";
|
|
11
|
+
/** Selects an option based on its zero-based index in the dropdown. */
|
|
12
|
+
DropdownSelectType["INDEX"] = "index";
|
|
13
|
+
/** Selects an option based on its exact 'value' attribute. */
|
|
14
|
+
DropdownSelectType["VALUE"] = "value";
|
|
15
|
+
})(DropdownSelectType || (exports.DropdownSelectType = DropdownSelectType = {}));
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ElementInteractions } from '../interactions/facade/ElementInteractions';
|
|
2
|
+
import { ContextStore } from '@civitas-cerebrum/context-store';
|
|
3
|
+
import { ElementRepository } from 'pw-element-repository';
|
|
4
|
+
import { test as base } from '@playwright/test';
|
|
5
|
+
import { Steps } from '../steps/CommonSteps';
|
|
6
|
+
type StepFixture = {
|
|
7
|
+
interactions: ElementInteractions;
|
|
8
|
+
contextStore: ContextStore;
|
|
9
|
+
repo: ElementRepository;
|
|
10
|
+
steps: Steps;
|
|
11
|
+
};
|
|
12
|
+
export declare function baseFixture<T extends {}>(baseTest: ReturnType<typeof base.extend<T>>, locatorPath: string): import("@playwright/test").TestType<import("@playwright/test").PlaywrightTestArgs & import("@playwright/test").PlaywrightTestOptions & StepFixture, import("@playwright/test").PlaywrightWorkerArgs & import("@playwright/test").PlaywrightWorkerOptions>;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.baseFixture = baseFixture;
|
|
4
|
+
const ElementInteractions_1 = require("../interactions/facade/ElementInteractions");
|
|
5
|
+
const context_store_1 = require("@civitas-cerebrum/context-store");
|
|
6
|
+
const pw_element_repository_1 = require("pw-element-repository");
|
|
7
|
+
const CommonSteps_1 = require("../steps/CommonSteps");
|
|
8
|
+
function baseFixture(baseTest, locatorPath) {
|
|
9
|
+
return baseTest.extend({
|
|
10
|
+
repo: async ({}, use) => {
|
|
11
|
+
await use(new pw_element_repository_1.ElementRepository(locatorPath));
|
|
12
|
+
},
|
|
13
|
+
steps: async ({ page }, use) => {
|
|
14
|
+
const repo = new pw_element_repository_1.ElementRepository(locatorPath);
|
|
15
|
+
await use(new CommonSteps_1.Steps(page, repo));
|
|
16
|
+
},
|
|
17
|
+
interactions: async ({ page }, use) => {
|
|
18
|
+
await use(new ElementInteractions_1.ElementInteractions(page));
|
|
19
|
+
},
|
|
20
|
+
contextStore: async ({}, use) => {
|
|
21
|
+
await use(new context_store_1.ContextStore());
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
export
|
|
2
|
-
export { Interactions, DropdownSelectType, DropdownSelectOptions } from './interactions/Interaction';
|
|
1
|
+
export * from './enum/Options';
|
|
3
2
|
export { Navigation } from './interactions/Navigation';
|
|
4
3
|
export { Verifications } from './interactions/Verification';
|
|
4
|
+
export { Interactions } from './interactions/Interaction';
|
|
5
|
+
export { Extractions } from './interactions/Extraction';
|
|
5
6
|
export { DateUtilities } from './utils/DateUtilities';
|
|
7
|
+
export { Utils } from './utils/ElementUtilities';
|
|
8
|
+
export { ElementInteractions } from './interactions/facade/ElementInteractions';
|
|
6
9
|
export { Steps } from './steps/CommonSteps';
|
package/dist/index.js
CHANGED
|
@@ -1,21 +1,39 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
2
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Steps = exports.
|
|
4
|
-
//
|
|
5
|
-
|
|
6
|
-
Object.defineProperty(exports, "ElementInteractions", { enumerable: true, get: function () { return ElementInteractions_1.ElementInteractions; } });
|
|
7
|
-
// Interaction logic and associated Types/Enums
|
|
8
|
-
var Interaction_1 = require("./interactions/Interaction");
|
|
9
|
-
Object.defineProperty(exports, "Interactions", { enumerable: true, get: function () { return Interaction_1.Interactions; } });
|
|
10
|
-
Object.defineProperty(exports, "DropdownSelectType", { enumerable: true, get: function () { return Interaction_1.DropdownSelectType; } });
|
|
17
|
+
exports.Steps = exports.ElementInteractions = exports.Utils = exports.DateUtilities = exports.Extractions = exports.Interactions = exports.Verifications = exports.Navigation = void 0;
|
|
18
|
+
// Enums
|
|
19
|
+
__exportStar(require("./enum/Options"), exports);
|
|
11
20
|
// Supporting Action Classes
|
|
12
21
|
var Navigation_1 = require("./interactions/Navigation");
|
|
13
22
|
Object.defineProperty(exports, "Navigation", { enumerable: true, get: function () { return Navigation_1.Navigation; } });
|
|
14
23
|
var Verification_1 = require("./interactions/Verification");
|
|
15
24
|
Object.defineProperty(exports, "Verifications", { enumerable: true, get: function () { return Verification_1.Verifications; } });
|
|
25
|
+
var Interaction_1 = require("./interactions/Interaction");
|
|
26
|
+
Object.defineProperty(exports, "Interactions", { enumerable: true, get: function () { return Interaction_1.Interactions; } });
|
|
27
|
+
var Extraction_1 = require("./interactions/Extraction");
|
|
28
|
+
Object.defineProperty(exports, "Extractions", { enumerable: true, get: function () { return Extraction_1.Extractions; } });
|
|
16
29
|
// Utilities
|
|
17
|
-
var DateUtilities_1 = require("./utils/DateUtilities");
|
|
30
|
+
var DateUtilities_1 = require("./utils/DateUtilities");
|
|
18
31
|
Object.defineProperty(exports, "DateUtilities", { enumerable: true, get: function () { return DateUtilities_1.DateUtilities; } });
|
|
19
|
-
|
|
32
|
+
var ElementUtilities_1 = require("./utils/ElementUtilities");
|
|
33
|
+
Object.defineProperty(exports, "Utils", { enumerable: true, get: function () { return ElementUtilities_1.Utils; } });
|
|
34
|
+
// Element Interactions Facade
|
|
35
|
+
var ElementInteractions_1 = require("./interactions/facade/ElementInteractions");
|
|
36
|
+
Object.defineProperty(exports, "ElementInteractions", { enumerable: true, get: function () { return ElementInteractions_1.ElementInteractions; } });
|
|
37
|
+
// Test Steps Facade
|
|
20
38
|
var CommonSteps_1 = require("./steps/CommonSteps");
|
|
21
39
|
Object.defineProperty(exports, "Steps", { enumerable: true, get: function () { return CommonSteps_1.Steps; } });
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Page, Locator } from '@playwright/test';
|
|
2
|
+
export declare class Extractions {
|
|
3
|
+
private page;
|
|
4
|
+
private ELEMENT_TIMEOUT;
|
|
5
|
+
private utils;
|
|
6
|
+
/**
|
|
7
|
+
* Initializes the Extractions class.
|
|
8
|
+
* @param page - The current Playwright Page object.
|
|
9
|
+
* @param timeout - Optional override for the default element timeout.
|
|
10
|
+
*/
|
|
11
|
+
constructor(page: Page, timeout?: number);
|
|
12
|
+
/**
|
|
13
|
+
* Safely retrieves and trims the text content of an element.
|
|
14
|
+
* @param locator - The Playwright Locator pointing to the target element.
|
|
15
|
+
* @returns The trimmed string, or an empty string if null.
|
|
16
|
+
*/
|
|
17
|
+
getText(locator: Locator): Promise<string | null>;
|
|
18
|
+
/**
|
|
19
|
+
* Retrieves the value of a specified attribute (e.g., 'href', 'aria-pressed').
|
|
20
|
+
* @param locator - The Playwright Locator pointing to the target element.
|
|
21
|
+
* @param attributeName - The name of the attribute to retrieve.
|
|
22
|
+
* @returns The attribute value as a string, or null if it doesn't exist.
|
|
23
|
+
*/
|
|
24
|
+
getAttribute(locator: Locator, attributeName: string): Promise<string | null>;
|
|
25
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Extractions = void 0;
|
|
4
|
+
const ElementUtilities_1 = require("../utils/ElementUtilities");
|
|
5
|
+
class Extractions {
|
|
6
|
+
page;
|
|
7
|
+
ELEMENT_TIMEOUT;
|
|
8
|
+
utils;
|
|
9
|
+
/**
|
|
10
|
+
* Initializes the Extractions class.
|
|
11
|
+
* @param page - The current Playwright Page object.
|
|
12
|
+
* @param timeout - Optional override for the default element timeout.
|
|
13
|
+
*/
|
|
14
|
+
constructor(page, timeout = 30000) {
|
|
15
|
+
this.page = page;
|
|
16
|
+
this.ELEMENT_TIMEOUT = timeout;
|
|
17
|
+
this.utils = new ElementUtilities_1.Utils(this.ELEMENT_TIMEOUT);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Safely retrieves and trims the text content of an element.
|
|
21
|
+
* @param locator - The Playwright Locator pointing to the target element.
|
|
22
|
+
* @returns The trimmed string, or an empty string if null.
|
|
23
|
+
*/
|
|
24
|
+
async getText(locator) {
|
|
25
|
+
await this.utils.waitForState(locator, 'attached');
|
|
26
|
+
const text = await locator.textContent({ timeout: this.ELEMENT_TIMEOUT });
|
|
27
|
+
return text?.trim() ?? null;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Retrieves the value of a specified attribute (e.g., 'href', 'aria-pressed').
|
|
31
|
+
* @param locator - The Playwright Locator pointing to the target element.
|
|
32
|
+
* @param attributeName - The name of the attribute to retrieve.
|
|
33
|
+
* @returns The attribute value as a string, or null if it doesn't exist.
|
|
34
|
+
*/
|
|
35
|
+
async getAttribute(locator, attributeName) {
|
|
36
|
+
await this.utils.waitForState(locator, 'attached');
|
|
37
|
+
return await locator.getAttribute(attributeName, { timeout: this.ELEMENT_TIMEOUT });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.Extractions = Extractions;
|
|
@@ -1,26 +1,5 @@
|
|
|
1
1
|
import { Page, Locator } from '@playwright/test';
|
|
2
|
-
|
|
3
|
-
* Defines the strategy for selecting an option from a dropdown element.
|
|
4
|
-
*/
|
|
5
|
-
export declare enum DropdownSelectType {
|
|
6
|
-
/** Selects a completely random, non-disabled option with a valid value. */
|
|
7
|
-
RANDOM = "random",
|
|
8
|
-
/** Selects an option based on its zero-based index in the dropdown. */
|
|
9
|
-
INDEX = "index",
|
|
10
|
-
/** Selects an option based on its exact 'value' attribute. */
|
|
11
|
-
VALUE = "value"
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Configuration options for the `selectDropdown` method.
|
|
15
|
-
*/
|
|
16
|
-
export interface DropdownSelectOptions {
|
|
17
|
-
/** The selection strategy to use. Defaults to RANDOM. */
|
|
18
|
-
type?: DropdownSelectType;
|
|
19
|
-
/** The specific value attribute to select (Required if type is VALUE). */
|
|
20
|
-
value?: string;
|
|
21
|
-
/** The index of the option to select (Required if type is INDEX). */
|
|
22
|
-
index?: number;
|
|
23
|
-
}
|
|
2
|
+
import { DropdownSelectOptions, DragAndDropOptions } from '../enum/Options';
|
|
24
3
|
/**
|
|
25
4
|
* The `Interactions` class provides a robust set of methods for interacting
|
|
26
5
|
* with DOM elements via Playwright Locators. It abstracts away common boilerplate
|
|
@@ -28,11 +7,14 @@ export interface DropdownSelectOptions {
|
|
|
28
7
|
*/
|
|
29
8
|
export declare class Interactions {
|
|
30
9
|
private page;
|
|
10
|
+
private ELEMENT_TIMEOUT;
|
|
11
|
+
private utils;
|
|
31
12
|
/**
|
|
32
13
|
* Initializes the Interactions class.
|
|
33
14
|
* @param page - The current Playwright Page object.
|
|
15
|
+
* @param timeout - Optional override for the default element timeout.
|
|
34
16
|
*/
|
|
35
|
-
constructor(page: Page);
|
|
17
|
+
constructor(page: Page, timeout?: number);
|
|
36
18
|
/**
|
|
37
19
|
* Performs a standard Playwright click on the given locator.
|
|
38
20
|
* Automatically waits for the element to be attached, visible, stable, and actionable.
|
|
@@ -68,10 +50,37 @@ export declare class Interactions {
|
|
|
68
50
|
/**
|
|
69
51
|
* Unified method to interact with `<select>` dropdown elements based on the specified `DropdownSelectType`.
|
|
70
52
|
* If no options are provided, it safely defaults to randomly selecting an enabled, non-empty option.
|
|
71
|
-
*
|
|
53
|
+
* @param locator - The Playwright Locator pointing to the `<select>` element.
|
|
72
54
|
* @param options - Configuration specifying whether to select by 'random', 'index', or 'value'.
|
|
73
55
|
* @returns A promise that resolves to the exact 'value' attribute of the newly selected option.
|
|
74
56
|
* @throws Error if 'value' or 'index' is missing when their respective types are chosen, or if no enabled options exist.
|
|
75
57
|
*/
|
|
76
58
|
selectDropdown(locator: Locator, options?: DropdownSelectOptions): Promise<string>;
|
|
59
|
+
/**
|
|
60
|
+
* Hovers over the specified element. Useful for triggering dropdowns or tooltips.
|
|
61
|
+
* @param locator - The Playwright Locator pointing to the target element.
|
|
62
|
+
*/
|
|
63
|
+
hover(locator: Locator): Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* Scrolls the element into view if it is not already visible in the viewport.
|
|
66
|
+
* @param locator - The Playwright Locator pointing to the target element.
|
|
67
|
+
*/
|
|
68
|
+
scrollIntoView(locator: Locator): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Drags an element either to a specified target element, a target element with an offset, or by a coordinate offset.
|
|
71
|
+
* @param locator - The Playwright Locator pointing to the element to drag.
|
|
72
|
+
* @param options - Configuration specifying a 'targetLocator', offsets, or both.
|
|
73
|
+
*/
|
|
74
|
+
dragAndDrop(locator: Locator, options: DragAndDropOptions): Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* Filters a locator list and returns the first element that contains the specified text.
|
|
77
|
+
* If the element is not found, it prints the available text contents of the base locator for debugging.
|
|
78
|
+
* @param baseLocator The base Playwright Locator.
|
|
79
|
+
* @param pageName The name of the page block in the JSON repository.
|
|
80
|
+
* @param elementName The specific element name to look up.
|
|
81
|
+
* @param desiredText The string of text to search for within the elements.
|
|
82
|
+
* @param strict If true, throws an error if the element is not found. Defaults to false.
|
|
83
|
+
* @returns A promise that resolves to the matched Playwright Locator, or null if not found.
|
|
84
|
+
*/
|
|
85
|
+
getByText(baseLocator: Locator, pageName: string, elementName: string, desiredText: string, strict?: boolean): Promise<ReturnType<Page['locator']> | null>;
|
|
77
86
|
}
|