pomwright 1.2.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +43 -0
- package/README.md +38 -494
- package/dist/index.d.mts +11 -103
- package/dist/index.d.ts +11 -103
- package/dist/index.js +46 -115
- package/dist/index.mjs +43 -112
- package/docs/BaseApi-explanation.md +63 -0
- package/docs/BasePage-explanation.md +96 -0
- package/docs/LocatorSchema-explanation.md +271 -0
- package/docs/LocatorSchemaPath-explanation.md +165 -0
- package/docs/PlaywrightReportLogger-explanation.md +56 -0
- package/docs/get-locator-methods-explanation.md +250 -0
- package/docs/intro-to-using-pomwright.md +899 -0
- package/docs/sessionStorage-methods-explanation.md +38 -0
- package/docs/tips-folder-structure.md +38 -0
- package/package.json +8 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,48 @@
|
|
|
1
1
|
# pomwright
|
|
2
2
|
|
|
3
|
+
## 1.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#36](https://github.com/DyHex/POMWright/pull/36) [`e307d0e`](https://github.com/DyHex/POMWright/commit/e307d0e871bce4b69f12fa17fa673af3dad8f874) Thanks [@DyHex](https://github.com/DyHex)! - # v1.4.0
|
|
8
|
+
|
|
9
|
+
## Removed
|
|
10
|
+
|
|
11
|
+
- Dropped deprecated locator schema helpers (legacy numeric indexing and update/updates overloads). Use sub-path keyed indices and `update(subPath, updates)` instead.
|
|
12
|
+
|
|
13
|
+
## Changed
|
|
14
|
+
|
|
15
|
+
- Simplified nested locator debug logging to count-only checks to avoid CSP-restricted pages failing when `evaluateAll` is blocked.
|
|
16
|
+
|
|
17
|
+
## 1.3.0
|
|
18
|
+
|
|
19
|
+
### Minor Changes
|
|
20
|
+
|
|
21
|
+
- [#33](https://github.com/DyHex/POMWright/pull/33) [`ca192bf`](https://github.com/DyHex/POMWright/commit/ca192bf587725a0eeba623e074d2e2e8347a5766) Thanks [@DyHex](https://github.com/DyHex)! - # Highlights
|
|
22
|
+
|
|
23
|
+
Updated the README to surface the expanded documentation set, making it easier to discover the new onboarding and reference guides from the project landing page.
|
|
24
|
+
|
|
25
|
+
## Documentation
|
|
26
|
+
|
|
27
|
+
### Onboarding & Patterns
|
|
28
|
+
|
|
29
|
+
- Added a comprehensive “Using POMWright” tutorial that walks through building a page object, defining locator schemas, moving definitions into shared files, wiring custom fixtures, and extracting common logic into abstract base classes for reuse across domains.
|
|
30
|
+
|
|
31
|
+
### Reference Guides
|
|
32
|
+
|
|
33
|
+
- Documented the BasePage API, covering its generics, constructor contract, required overrides, helper methods, and recommendations for layering domain-specific base classes.
|
|
34
|
+
- Explained LocatorSchemaPath rules, duplication safeguards, readability conventions (including @ suffixes), and how sub-paths power IntelliSense and targeted updates.
|
|
35
|
+
- Expanded the LocatorSchema reference with Playwright parity for every selector strategy, POMWright-specific helpers like dataCy and id, the new filter property, and a reusable schema example.
|
|
36
|
+
- Clarified how to use getLocator, getNestedLocator, and getLocatorSchema chains, including update/filter patterns, index migration guidance, and reuse techniques.
|
|
37
|
+
- Added focused primers for the BaseApi helper, the shared PlaywrightReportLogger, and the sessionStorage wrapper so teams can integrate API utilities, logging, and state management consistently.
|
|
38
|
+
- Shared a recommended folder layout for fixtures, page objects, and tests to help teams standardise project structure as they adopt the framework.
|
|
39
|
+
|
|
40
|
+
## Other improvements
|
|
41
|
+
|
|
42
|
+
- Fix: Intended LocatorSchemaPath string format now fully enforced.
|
|
43
|
+
- Add new tests, updated and fixed some existing tests
|
|
44
|
+
- CI/CD improvements
|
|
45
|
+
|
|
3
46
|
## 1.2.0
|
|
4
47
|
|
|
5
48
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -1,514 +1,58 @@
|
|
|
1
|
-
---
|
|
2
|
-
"pomwright": minor
|
|
3
|
-
---
|
|
4
|
-
|
|
5
1
|
# POMWright
|
|
6
2
|
|
|
7
|
-

|
|
3
|
+

|
|
4
|
+
[](https://www.npmjs.com/package/pomwright)
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+
[](https://www.npmjs.com/package/playwright)
|
|
8
|
+
[](https://www.ice.no/)
|
|
8
9
|
|
|
9
|
-
POMWright is a TypeScript
|
|
10
|
+
POMWright is a lightweight TypeScript framework that layers the Page Object Model on top of Playwright. It keeps locators, page objects, and fixtures organised so that UI tests stay readable and maintainable.
|
|
10
11
|
|
|
11
12
|
POMWright provides a way of abstracting the implementation details of a web page and encapsulating them into a reusable page object. This approach makes the tests easier to read, write, and maintain, and helps reduce duplicated code by breaking down the code into smaller, reusable components, making the code more maintainable and organized.
|
|
12
13
|
|
|
13
|
-
##
|
|
14
|
-
|
|
15
|
-
### Easy Creation of Page Object Classes
|
|
16
|
-
|
|
17
|
-
Simply extend a class with `BasePage` to create a Page Object Class (POC).
|
|
18
|
-
|
|
19
|
-
### Support for Multiple Domains/BaseURLs
|
|
20
|
-
|
|
21
|
-
Define different base URLs by extending an abstract class with `BasePage` per domain and have your POCs for each domain extend the abstract classes.
|
|
22
|
-
|
|
23
|
-
### Custom Playwright Fixture Integration
|
|
24
|
-
|
|
25
|
-
Seamlessly integrate custom Playwright Fixtures with your POMWright POCs.
|
|
26
|
-
|
|
27
|
-
### LocatorSchema Interface
|
|
28
|
-
|
|
29
|
-
Define comprehensive locators for each POC and share common locators between them.
|
|
30
|
-
|
|
31
|
-
### Advanced Locator Management
|
|
14
|
+
## Key capabilities
|
|
32
15
|
|
|
33
|
-
|
|
16
|
+
- Quickly build maintainable Page Object Classes.
|
|
17
|
+
- Define any Playwright Locator through type-safe LocatorSchemas.
|
|
18
|
+
- Automatic chaining of locators with dot-delimited paths that map directly to Playwright locator methods.
|
|
19
|
+
- Auto-completion of LocatorSchemaPaths and sub-paths.
|
|
20
|
+
- Adjust locators on the fly without mutating the original definitions.
|
|
21
|
+
- Attach structured logs directly to the Playwright HTML report.
|
|
22
|
+
- Manage `sessionStorage` for browser setup and state hand‑off.
|
|
23
|
+
- Multiple Domains/BaseURLs
|
|
24
|
+
- Validate elements position in DOM through chaining
|
|
34
25
|
|
|
35
|
-
|
|
26
|
+
## Why POMWright?
|
|
36
27
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
Ensure that original `LocatorSchemas` remain immutable and reusable across tests.
|
|
42
|
-
|
|
43
|
-
### Custom HTML Logger
|
|
44
|
-
|
|
45
|
-
Gain insights with detailed logs for nested locators, integrated with Playwright's HTML report. Or use the Log fixture throughout your own POCs and tests to easily attach them to the HTML report based on log levels.
|
|
46
|
-
|
|
47
|
-
### SessionStorage Handling
|
|
48
|
-
|
|
49
|
-
Enhance your tests with advanced `sessionStorage` handling capabilities.
|
|
50
|
-
|
|
51
|
-
### Enhanced Locator Filtering
|
|
52
|
-
|
|
53
|
-
- **New `filter` Property**: Apply filters across various locator types beyond just the `locator` method.
|
|
54
|
-
- **New `.addFilter()` Method**: Dynamically add filters to any part of the locator chain.
|
|
28
|
+
- **Stronger reliability** – centralised locator definitions reduce brittle inline selectors and make refactors visible at compile time.
|
|
29
|
+
- **Faster authoring** – strongly typed schema paths provide instant auto-complete, even for deeply nested segments and reusable fragments.
|
|
30
|
+
- **Easier maintenance** – shared helper patterns keep page objects, fixtures, and API clients aligned so teams can extend coverage without duplicating boilerplate.
|
|
31
|
+
- **Incremental adoption** – each helper sits on top of Playwright primitives, making it straightforward to migrate existing tests component by component.
|
|
55
32
|
|
|
56
33
|
## Installation
|
|
57
34
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
```bash
|
|
61
|
-
npm install pomwright --save-dev
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
or
|
|
65
|
-
|
|
66
|
-
```bash
|
|
67
|
-
pnpm i -D pomwright
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
## Playwright Example Project
|
|
71
|
-
|
|
72
|
-
Explore POMWright in action by diving into the example project located in the "example" folder. Follow these steps to get started:
|
|
73
|
-
|
|
74
|
-
### Install
|
|
75
|
-
|
|
76
|
-
Navigate to the "example" folder and install the necessary dependencies:
|
|
77
|
-
|
|
78
|
-
```bash
|
|
79
|
-
pnpm install
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
### Playwright Browsers
|
|
83
|
-
|
|
84
|
-
Install or update Playwright browsers:
|
|
85
|
-
|
|
86
|
-
```bash
|
|
87
|
-
pnpm playwright install --with-deps
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
### Run Tests
|
|
91
|
-
|
|
92
|
-
Execute tests across Chromium, Firefox, and WebKit:
|
|
35
|
+
Install POMWright alongside Playwright:
|
|
93
36
|
|
|
94
37
|
```bash
|
|
95
|
-
pnpm
|
|
38
|
+
pnpm add -D pomwright
|
|
39
|
+
# or
|
|
40
|
+
npm install --save-dev pomwright
|
|
96
41
|
```
|
|
97
42
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
Control parallel test execution. By default, up to 4 tests run in parallel. Modify this setting as needed:
|
|
101
|
-
|
|
102
|
-
```bash
|
|
103
|
-
pnpm playwright test --workers 2 # Set the number of parallel workers
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
### Reports
|
|
107
|
-
|
|
108
|
-
After the tests complete, a Playwright HTML report is available in `./example/playwright-report`. Open the `index.html` file in your browser to view the results.
|
|
109
|
-
|
|
110
|
-
## Usage
|
|
111
|
-
|
|
112
|
-
Dive into using POMWright with these examples:
|
|
113
|
-
|
|
114
|
-
### Create a Page Object Class (POC)
|
|
115
|
-
|
|
116
|
-
```typescript
|
|
117
|
-
import { Page, TestInfo } from "@playwright/test";
|
|
118
|
-
import { BasePage, PlaywrightReportLogger, GetByMethod } from "pomwright";
|
|
119
|
-
|
|
120
|
-
type LocatorSchemaPath =
|
|
121
|
-
| "content"
|
|
122
|
-
| "content.heading"
|
|
123
|
-
| "content.region.details"
|
|
124
|
-
| "content.region.details.button.edit";
|
|
125
|
-
|
|
126
|
-
export default class Profile extends BasePage<LocatorSchemaPath> {
|
|
127
|
-
constructor(page: Page, testInfo: TestInfo, pwrl: PlaywrightReportLogger) {
|
|
128
|
-
super(page, testInfo, "https://someDomain.com", "/profile", Profile.name, pwrl);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
protected initLocatorSchemas() {
|
|
132
|
-
this.locators.addSchema("content", {
|
|
133
|
-
locator: ".main-content",
|
|
134
|
-
locatorMethod: GetByMethod.locator
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
this.locators.addSchema("content.heading", {
|
|
138
|
-
role: "heading",
|
|
139
|
-
roleOptions: {
|
|
140
|
-
name: "Your Profile"
|
|
141
|
-
},
|
|
142
|
-
locatorMethod: GetByMethod.role
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
this.locators.addSchema("content.region.details", {
|
|
146
|
-
role: "region",
|
|
147
|
-
roleOptions: {
|
|
148
|
-
name: "Profile Details"
|
|
149
|
-
},
|
|
150
|
-
locatorMethod: GetByMethod.role
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
this.locators.addSchema("content.region.details.button.edit", {
|
|
154
|
-
role: "button",
|
|
155
|
-
roleOptions: {
|
|
156
|
-
name: "Edit"
|
|
157
|
-
},
|
|
158
|
-
locatorMethod: GetByMethod.role
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// add your helper methods here...
|
|
163
|
-
}
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
### Creating a Custom Playwright Fixture
|
|
167
|
-
|
|
168
|
-
```typescript
|
|
169
|
-
import { test as base } from "pomwright";
|
|
170
|
-
import Profile from "...";
|
|
171
|
-
|
|
172
|
-
type fixtures = {
|
|
173
|
-
profile: Profile;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
export const test = base.extend<fixtures>({
|
|
177
|
-
profile: async ({ page, log }, use, testInfo) => {
|
|
178
|
-
const profile = new Profile(page, testInfo, log);
|
|
179
|
-
await use(profile);
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
### Using the Fixture in Playwright Tests
|
|
185
|
-
|
|
186
|
-
#### Click Edit Button with a Single Locator
|
|
187
|
-
|
|
188
|
-
```typescript
|
|
189
|
-
import { test } from ".../fixtures";
|
|
190
|
-
|
|
191
|
-
test("click edit button with a single locator", async ({ profile }) => {
|
|
192
|
-
// perform setup/navigation...
|
|
193
|
-
|
|
194
|
-
await profile.page.waitForURL(profile.fullUrl);
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* returns the locator resolving to the full locatorSchemaPath
|
|
198
|
-
*/
|
|
199
|
-
const editBtn = await profile.getLocator("content.region.details.button.edit");
|
|
200
|
-
|
|
201
|
-
await editBtn.click();
|
|
202
|
-
});
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
#### Click Edit Button with a Nested Locator
|
|
206
|
-
|
|
207
|
-
```typescript
|
|
208
|
-
import { test } from ".../fixtures";
|
|
209
|
-
|
|
210
|
-
test("click edit button with a nested locator", async ({ profile }) => {
|
|
211
|
-
// perform setup/navigation...
|
|
212
|
-
|
|
213
|
-
await profile.page.waitForURL(profile.fullUrl);
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* returns a nested/chained locator consisting of the 3 locators:
|
|
217
|
-
* content,
|
|
218
|
-
* content.region.details
|
|
219
|
-
* content.region.details.button.edit
|
|
220
|
-
*/
|
|
221
|
-
const editBtn = await profile.getNestedLocator("content.region.details.button.edit");
|
|
222
|
-
|
|
223
|
-
await editBtn.click();
|
|
224
|
-
});
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
#### Specify Index for Nested Locators
|
|
228
|
-
|
|
229
|
-
```typescript
|
|
230
|
-
import { test } from ".../fixtures";
|
|
43
|
+
## Documentation
|
|
231
44
|
|
|
232
|
-
|
|
233
|
-
// perform setup/navigation...
|
|
45
|
+
Start with the introduction and continue through the topics:
|
|
234
46
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
"content.region.details": 0,
|
|
245
|
-
"content.region.details.button.edit": 1
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
await editBtn.click();
|
|
249
|
-
});
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
#### Update a Locator Before Use
|
|
253
|
-
|
|
254
|
-
```typescript
|
|
255
|
-
import { test } from ".../fixtures";
|
|
256
|
-
|
|
257
|
-
test("update a locator before use", async ({ profile }) => {
|
|
258
|
-
// perform setup/navigation...
|
|
259
|
-
|
|
260
|
-
await profile.page.waitForURL(profile.fullUrl);
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* returns a nested/chained locator consisting of the 3 locators:
|
|
264
|
-
* content,
|
|
265
|
-
* content.region.details
|
|
266
|
-
* content.region.details.button.edit (updated)
|
|
267
|
-
*/
|
|
268
|
-
const editBtn = await profile.getLocatorSchema("content.region.details.button.edit")
|
|
269
|
-
.update("content.region.details.button.edit", {
|
|
270
|
-
roleOptions: { name: "Edit details" }
|
|
271
|
-
})
|
|
272
|
-
.getNestedLocator();
|
|
273
|
-
|
|
274
|
-
await editBtn.click();
|
|
275
|
-
});
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
#### Update a Nested Locator Before Use
|
|
279
|
-
|
|
280
|
-
```typescript
|
|
281
|
-
import { test } from ".../fixtures";
|
|
282
|
-
|
|
283
|
-
test("update a nested locator before use", async ({ profile }) => {
|
|
284
|
-
// perform setup/navigation...
|
|
285
|
-
|
|
286
|
-
await profile.page.waitForURL(profile.fullUrl);
|
|
287
|
-
|
|
288
|
-
/**
|
|
289
|
-
* returns a nested/chained locator consisting of the 3 locators:
|
|
290
|
-
* content,
|
|
291
|
-
* content.region.details (updated)
|
|
292
|
-
* content.region.details.button.edit
|
|
293
|
-
*/
|
|
294
|
-
const editBtn = await profile.getLocatorSchema("content.region.details.button.edit")
|
|
295
|
-
.update("content.region.details", {
|
|
296
|
-
locator: ".profile-details",
|
|
297
|
-
locatorMethod: GetByMethod.locator
|
|
298
|
-
})
|
|
299
|
-
.getNestedLocator();
|
|
300
|
-
|
|
301
|
-
await editBtn.click();
|
|
302
|
-
});
|
|
303
|
-
```
|
|
304
|
-
|
|
305
|
-
#### Make Multiple Versions of a Locator
|
|
306
|
-
|
|
307
|
-
```typescript
|
|
308
|
-
import { test } from ".../fixtures";
|
|
309
|
-
|
|
310
|
-
test("make multiple versions of a locator", async ({ profile }) => {
|
|
311
|
-
// perform setup/navigation...
|
|
312
|
-
|
|
313
|
-
await profile.page.waitForURL(profile.fullUrl);
|
|
314
|
-
|
|
315
|
-
const editBtnSchema = profile.getLocatorSchema("content.region.details.button.edit");
|
|
316
|
-
|
|
317
|
-
const editBtn = await editBtnSchema.getLocator();
|
|
318
|
-
await editBtn.click();
|
|
319
|
-
|
|
320
|
-
editBtnSchema.update("content.region.details.button.edit", { roleOptions: { name: "Edit details" } });
|
|
321
|
-
|
|
322
|
-
const editBtnUpdated = await editBtnSchema.getNestedLocator();
|
|
323
|
-
await editBtnUpdated.click();
|
|
324
|
-
|
|
325
|
-
/**
|
|
326
|
-
* Calling profile.getLocatorSchema("content.region.details.button.edit") again
|
|
327
|
-
* will return a new deepCopy of the original LocatorSchema
|
|
328
|
-
*/
|
|
329
|
-
});
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
## Deprecations
|
|
333
|
-
|
|
334
|
-
### 1. Deprecated `.update` and `.updates` Methods
|
|
335
|
-
|
|
336
|
-
- **Old `.update(updates: Partial<LocatorSchemaWithoutPath>): LocatorSchemaWithMethods`**
|
|
337
|
-
- **Old `.updates(indexedUpdates: { [index: number]: Partial<LocatorSchemaWithoutPath> | null }): LocatorSchemaWithMethods`**
|
|
338
|
-
|
|
339
|
-
**Reason:**
|
|
340
|
-
The `.updates` method relied on index-based updates, which are prone to errors and require manual maintenance, especially when `LocatorSchemaPath` strings are renamed or restructured. Additionally, the old `.update` method could only update the last `LocatorSchema` in the chain, making it less flexible.
|
|
341
|
-
|
|
342
|
-
**Replacement:**
|
|
343
|
-
Use the new `.update(subPath, modifiedSchema)` method, which leverages valid `subPath`s of `LocatorSchemaPath` strings for more intuitive and maintainable updates.
|
|
344
|
-
|
|
345
|
-
**Removal Schedule:**
|
|
346
|
-
These methods are deprecated and will be removed in version 2.0.0.
|
|
347
|
-
|
|
348
|
-
### 2. Deprecated Old `getNestedLocator` Method
|
|
349
|
-
|
|
350
|
-
- **Old `getNestedLocator(indices?: { [key: number]: number | null }): Promise<Locator>`**
|
|
351
|
-
|
|
352
|
-
**Reason:**
|
|
353
|
-
Index-based indexing is less readable and requires manual updates when `LocatorSchemaPath` strings change.
|
|
354
|
-
|
|
355
|
-
**Replacement:**
|
|
356
|
-
Use the updated `getNestedLocator(subPathIndices?: { [K in SubPaths<LocatorSchemaPathType, LocatorSubstring>]: number | null }): Promise<Locator>` method, which utilizes `LocatorSchemaPath` strings for indexing.
|
|
357
|
-
|
|
358
|
-
**Removal Schedule:**
|
|
359
|
-
This method is deprecated and will be removed in version 2.0.0.
|
|
360
|
-
|
|
361
|
-
## Migration Guide
|
|
362
|
-
|
|
363
|
-
### Updating `.update` and `.updates` Methods
|
|
364
|
-
|
|
365
|
-
**Old Usage:**
|
|
366
|
-
```typescript
|
|
367
|
-
const allCheckboxes = await poc
|
|
368
|
-
.getLocatorSchema("main.products.searchControls.filterType.label.checkbox")
|
|
369
|
-
.updates({ 3: { locatorOptions: { hasText: /Producer/i } } })
|
|
370
|
-
.getNestedLocator();
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
**New Usage:**
|
|
374
|
-
```typescript
|
|
375
|
-
const allCheckboxes = await poc
|
|
376
|
-
.getLocatorSchema("main.products.searchControls.filterType.label.checkbox")
|
|
377
|
-
.update("main.products.searchControls.filterType", { locatorOptions: { hasText: /Producer/i } })
|
|
378
|
-
.getNestedLocator();
|
|
379
|
-
```
|
|
380
|
-
|
|
381
|
-
### Updating `getNestedLocator` Method
|
|
382
|
-
|
|
383
|
-
**Old Usage (Deprecated):**
|
|
384
|
-
```typescript
|
|
385
|
-
const saveBtn = await profile.getNestedLocator("content.region.details.button.save", { 4: 2 });
|
|
386
|
-
|
|
387
|
-
const editBtn = await profile.getLocatorSchema("content.region.details.button.edit")
|
|
388
|
-
.getNestedLocator({ 2: index });
|
|
389
|
-
```
|
|
390
|
-
|
|
391
|
-
**New Usage:**
|
|
392
|
-
```typescript
|
|
393
|
-
const saveBtn = await profile.getNestedLocator("content.region.details.button.save", {
|
|
394
|
-
"content.region.details.button.save": 2
|
|
395
|
-
});
|
|
396
|
-
|
|
397
|
-
const editBtn = await profile.getLocatorSchema("content.region.details.button.edit")
|
|
398
|
-
.getNestedLocator({ "content.region.details": index });
|
|
399
|
-
```
|
|
400
|
-
|
|
401
|
-
### Utilizing `LocatorSchemaPath` Instead of Indices
|
|
402
|
-
|
|
403
|
-
Transition from index-based to `LocatorSchemaPath`-based indexing to improve code readability and maintainability.
|
|
404
|
-
|
|
405
|
-
**Old Example:**
|
|
406
|
-
```typescript
|
|
407
|
-
const allCheckboxes = await poc
|
|
408
|
-
.getLocatorSchema("main.form.item.checkbox")
|
|
409
|
-
.updates({ 3: { locatorOptions: { hasText: /Producer/i } } })
|
|
410
|
-
.getNestedLocator();
|
|
411
|
-
```
|
|
412
|
-
|
|
413
|
-
**New Example:**
|
|
414
|
-
```typescript
|
|
415
|
-
const allCheckboxes = await poc
|
|
416
|
-
.getLocatorSchema("main.form.item.checkbox")
|
|
417
|
-
.update("main.form.item", { locatorOptions: { hasText: /Producer/i } })
|
|
418
|
-
.getNestedLocator();
|
|
419
|
-
```
|
|
420
|
-
|
|
421
|
-
## Example in Context
|
|
422
|
-
|
|
423
|
-
### Defining a LocatorSchema with `filter` and Using `.addFilter()`
|
|
424
|
-
|
|
425
|
-
```typescript
|
|
426
|
-
// Defining LocatorSchemas
|
|
427
|
-
this.locators.addSchema("body.main.section@userInfo", {
|
|
428
|
-
role: "region",
|
|
429
|
-
roleOptions: { name: "Contact Info" },
|
|
430
|
-
filter: { hasText: /e-mail/i },
|
|
431
|
-
locatorMethod: GetByMethod.role
|
|
432
|
-
});
|
|
433
|
-
|
|
434
|
-
// Dynamically adding additional filters using `.addFilter()`
|
|
435
|
-
const specificSection = await poc
|
|
436
|
-
.getLocatorSchema("body.main.section@userInfo")
|
|
437
|
-
.addFilter("body.main.section@userInfo", { hasText: "Additional Services" })
|
|
438
|
-
.getNestedLocator();
|
|
439
|
-
```
|
|
440
|
-
|
|
441
|
-
### Updating LocatorSchemas with the New `.update()` Method
|
|
442
|
-
|
|
443
|
-
```typescript
|
|
444
|
-
const editBtn = await profile
|
|
445
|
-
.getLocatorSchema("content.region.details.button.edit")
|
|
446
|
-
.update("content.region.details.button.edit", {
|
|
447
|
-
roleOptions: { name: "new accessibility name" }
|
|
448
|
-
})
|
|
449
|
-
.getNestedLocator();
|
|
450
|
-
```
|
|
451
|
-
|
|
452
|
-
### Reusing LocatorSchemas with `LocatorSchemaWithoutPath`
|
|
453
|
-
|
|
454
|
-
```typescript
|
|
455
|
-
import { GetByMethod, LocatorSchemaWithoutPath } from "pomwright";
|
|
456
|
-
import { missingInputError } from "@common/page-components/errors.locatorSchema.ts";
|
|
457
|
-
|
|
458
|
-
export type LocatorSchemaPath =
|
|
459
|
-
| "body"
|
|
460
|
-
| "body.main"
|
|
461
|
-
| "body.main.section"
|
|
462
|
-
| "body.main.section@products"
|
|
463
|
-
| "body.main.section@userInfo"
|
|
464
|
-
| "body.main.section@userInfo.input@email"
|
|
465
|
-
| "body.main.section@userInfo.inputError"
|
|
466
|
-
| "body.main.section@deliveryInfo";
|
|
467
|
-
|
|
468
|
-
export function initLocatorSchemas(locators: GetLocatorBase<LocatorSchemaPath>) {
|
|
469
|
-
locators.addSchema("body", {
|
|
470
|
-
locator: "body",
|
|
471
|
-
locatorMethod: GetByMethod.locator,
|
|
472
|
-
});
|
|
473
|
-
|
|
474
|
-
locators.addSchema("body.main", {
|
|
475
|
-
locator: "main",
|
|
476
|
-
locatorMethod: GetByMethod.locator,
|
|
477
|
-
});
|
|
478
|
-
|
|
479
|
-
const region: LocatorSchemaWithoutPath = { role: "region", locatorMethod: GetByMethod.role };
|
|
480
|
-
|
|
481
|
-
locators.addSchema("body.main.section", {
|
|
482
|
-
...region,
|
|
483
|
-
});
|
|
484
|
-
|
|
485
|
-
locators.addSchema("body.main.section@products", {
|
|
486
|
-
...region,
|
|
487
|
-
roleOptions: { name: "Products" },
|
|
488
|
-
});
|
|
489
|
-
|
|
490
|
-
locators.addSchema("body.main.section@userInfo", {
|
|
491
|
-
...region,
|
|
492
|
-
roleOptions: { name: "Contact Info" },
|
|
493
|
-
filter: { hasText: /e-mail/i },
|
|
494
|
-
});
|
|
495
|
-
|
|
496
|
-
locators.addSchema("body.main.section@userInfo.input@email", {
|
|
497
|
-
role: "textbox",
|
|
498
|
-
roleOptions: { name: "Input your e-mail" },
|
|
499
|
-
locatorMethod: GetByMethod.role,
|
|
500
|
-
});
|
|
501
|
-
|
|
502
|
-
locators.addSchema("body.main.section@userInfo.inputError", {
|
|
503
|
-
...missingInputError,
|
|
504
|
-
});
|
|
505
|
-
|
|
506
|
-
locators.addSchema("body.main.section@deliveryInfo", {
|
|
507
|
-
...region,
|
|
508
|
-
roleOptions: { name: "Delivery Info" },
|
|
509
|
-
});
|
|
510
|
-
}
|
|
511
|
-
```
|
|
47
|
+
1. [Intro to using POMWright](./docs/intro-to-using-pomwright.md)
|
|
48
|
+
2. [BasePage](./docs/BasePage-explanation.md)
|
|
49
|
+
3. [LocatorSchemaPath](./docs/LocatorSchemaPath-explanation.md)
|
|
50
|
+
4. [LocatorSchema](./docs/LocatorSchema-explanation.md)
|
|
51
|
+
5. [Locator schema helper methods](./docs/get-locator-methods-explanation.md)
|
|
52
|
+
6. [BaseApi](./docs/BaseApi-explanation.md)
|
|
53
|
+
7. [PlaywrightReportLogger](./docs/PlaywrightReportLogger-explanation.md)
|
|
54
|
+
8. [Session storage helpers](./docs/sessionStorage-methods-explanation.md)
|
|
55
|
+
9. [Tips for structuring locator files](./docs/tips-folder-structure.md)
|
|
512
56
|
|
|
513
57
|
## Troubleshooting and Support
|
|
514
58
|
|
|
@@ -520,4 +64,4 @@ Pull Requests are welcome! Please open an issue or submit a pull request for any
|
|
|
520
64
|
|
|
521
65
|
## License
|
|
522
66
|
|
|
523
|
-
POMWright is open-source software licensed under the [Apache-2.0 license](https://github.com/DyHex/POMWright/blob/main/LICENSE).
|
|
67
|
+
POMWright is open-source software licensed under the [Apache-2.0 license](https://github.com/DyHex/POMWright/blob/main/LICENSE).
|