pomwright 1.5.0 → 2.0.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 +36 -0
- package/README.md +5 -5
- package/dist/index.d.mts +91 -989
- package/dist/index.d.ts +91 -989
- package/dist/index.js +627 -1887
- package/dist/index.mjs +633 -1888
- package/package.json +9 -11
- package/AGENTS.md +0 -37
- package/docs/v1/BaseApi-explanation.md +0 -63
- package/docs/v1/BasePage-explanation.md +0 -96
- package/docs/v1/LocatorSchema-explanation.md +0 -271
- package/docs/v1/LocatorSchemaPath-explanation.md +0 -165
- package/docs/v1/PlaywrightReportLogger-explanation.md +0 -56
- package/docs/v1/get-locator-methods-explanation.md +0 -250
- package/docs/v1/intro-to-using-pomwright.md +0 -899
- package/docs/v1/sessionStorage-methods-explanation.md +0 -38
- package/docs/v1/tips-folder-structure.md +0 -38
- package/docs/v1-to-v2-migration/bridge-migration-guide.md +0 -159
- package/docs/v1-to-v2-migration/direct-migration-guide.md +0 -238
- package/docs/v1-to-v2-migration/v1-to-v2-comparison.md +0 -547
- package/docs/v2/PageObject.md +0 -293
- package/docs/v2/composing-locator-modules.md +0 -93
- package/docs/v2/locator-registry.md +0 -693
- package/docs/v2/logging.md +0 -168
- package/docs/v2/overview.md +0 -515
- package/docs/v2/session-storage.md +0 -160
- package/index.ts +0 -75
- package/intTestV2/.env +0 -0
- package/intTestV2/fixtures/testApp.fixtures.ts +0 -43
- package/intTestV2/package.json +0 -22
- package/intTestV2/page-object-models/testApp/pages/iframe/iframe.locatorSchema.ts +0 -24
- package/intTestV2/page-object-models/testApp/pages/iframe/iframe.page.ts +0 -17
- package/intTestV2/page-object-models/testApp/pages/testPage.locatorSchema.ts +0 -32
- package/intTestV2/page-object-models/testApp/pages/testPage.page.ts +0 -119
- package/intTestV2/page-object-models/testApp/pages/testPath/[color]/color.locatorSchema.ts +0 -29
- package/intTestV2/page-object-models/testApp/pages/testPath/[color]/color.page.ts +0 -48
- package/intTestV2/page-object-models/testApp/pages/testPath/testPath.locatorSchema.ts +0 -9
- package/intTestV2/page-object-models/testApp/pages/testPath/testPath.page.ts +0 -23
- package/intTestV2/page-object-models/testApp/pages/testfilters/testfilters.locatorSchema.ts +0 -114
- package/intTestV2/page-object-models/testApp/pages/testfilters/testfilters.page.ts +0 -23
- package/intTestV2/page-object-models/testApp/testApp.base.ts +0 -20
- package/intTestV2/playwright.config.ts +0 -54
- package/intTestV2/server.js +0 -216
- package/intTestV2/test-data/staticPage/index.html +0 -280
- package/intTestV2/test-data/staticPage/w3images/avatar2.png +0 -0
- package/intTestV2/test-data/staticPage/w3images/avatar3.png +0 -0
- package/intTestV2/test-data/staticPage/w3images/avatar5.png +0 -0
- package/intTestV2/test-data/staticPage/w3images/avatar6.png +0 -0
- package/intTestV2/test-data/staticPage/w3images/forest.jpg +0 -0
- package/intTestV2/test-data/staticPage/w3images/lights.jpg +0 -0
- package/intTestV2/test-data/staticPage/w3images/mountains.jpg +0 -0
- package/intTestV2/test-data/staticPage/w3images/nature.jpg +0 -0
- package/intTestV2/test-data/staticPage/w3images/snow.jpg +0 -0
- package/intTestV2/tests/locatorRegistry/add/add.describe.spec.ts +0 -54
- package/intTestV2/tests/locatorRegistry/add/add.filter.spec.ts +0 -143
- package/intTestV2/tests/locatorRegistry/add/add.frameLocator.spec.ts +0 -23
- package/intTestV2/tests/locatorRegistry/add/add.getByAltText.spec.ts +0 -23
- package/intTestV2/tests/locatorRegistry/add/add.getById.spec.ts +0 -45
- package/intTestV2/tests/locatorRegistry/add/add.getByLabel.spec.ts +0 -23
- package/intTestV2/tests/locatorRegistry/add/add.getByPlaceholder.spec.ts +0 -23
- package/intTestV2/tests/locatorRegistry/add/add.getByRole.spec.ts +0 -23
- package/intTestV2/tests/locatorRegistry/add/add.getByTestId.spec.ts +0 -23
- package/intTestV2/tests/locatorRegistry/add/add.getByText.spec.ts +0 -23
- package/intTestV2/tests/locatorRegistry/add/add.getByTitle.spec.ts +0 -23
- package/intTestV2/tests/locatorRegistry/add/add.locator.spec.ts +0 -23
- package/intTestV2/tests/locatorRegistry/add/add.reuseExisting.spec.ts +0 -66
- package/intTestV2/tests/locatorRegistry/add/add.reuseReusable.spec.ts +0 -311
- package/intTestV2/tests/locatorRegistry/add/add.spec.ts +0 -159
- package/intTestV2/tests/locatorRegistry/filter.cycle.spec.ts +0 -39
- package/intTestV2/tests/locatorRegistry/getLocator/getLocator.spec.ts +0 -253
- package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.clearSteps.spec.ts +0 -105
- package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.describe.spec.ts +0 -23
- package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.filter.spec.ts +0 -368
- package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.getLocator.spec.ts +0 -56
- package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.getNestedLocator.spec.ts +0 -175
- package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.nth.spec.ts +0 -60
- package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.remove.spec.ts +0 -32
- package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.replace.spec.ts +0 -24
- package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.spec.ts +0 -110
- package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.update.spec.ts +0 -322
- package/intTestV2/tests/locatorRegistry/getNestedLocator/getNestedLocator.spec.ts +0 -412
- package/intTestV2/tests/locatorRegistry/registry/registry.binding.spec.ts +0 -50
- package/intTestV2/tests/locatorRegistry/validation/validation.locatorSchemaPath.spec.ts +0 -115
- package/intTestV2/tests/locatorRegistry/validation/validation.sub-path.spec.ts +0 -45
- package/intTestV2/tests/step/step.spec.ts +0 -49
- package/intTestV2/tests/testApp/color.spec.ts +0 -15
- package/intTestV2/tests/testApp/iframe.spec.ts +0 -57
- package/intTestV2/tests/testApp/testFilters.spec.ts +0 -24
- package/intTestV2/tests/testApp/testPage.spec.ts +0 -161
- package/intTestV2/tests/testApp/testPath.spec.ts +0 -18
- package/pack-build.sh +0 -11
- package/pack-test-v2.sh +0 -36
- package/playwright.base.ts +0 -42
- package/skills/README.md +0 -56
- package/skills/pomwright-v1-5-bridge-migration/SKILL.md +0 -40
- package/skills/pomwright-v1-5-bridge-migration/references/call-site-migration.md +0 -178
- package/skills/pomwright-v1-5-bridge-migration/references/schema-translation.md +0 -183
- package/skills/pomwright-v2-migration/SKILL.md +0 -63
- package/skills/pomwright-v2-migration/references/call-site-migration.md +0 -265
- package/skills/pomwright-v2-migration/references/class-migration.md +0 -266
- package/skills/pomwright-v2-migration/references/fixture-and-helpers.md +0 -423
- package/skills/pomwright-v2-migration/references/locator-registration.md +0 -344
- package/srcV2/fixture/base.fixtures.ts +0 -23
- package/srcV2/helpers/navigation.ts +0 -153
- package/srcV2/helpers/playwrightReportLogger.ts +0 -196
- package/srcV2/helpers/sessionStorage.ts +0 -251
- package/srcV2/helpers/stepDecorator.ts +0 -106
- package/srcV2/locators/index.ts +0 -15
- package/srcV2/locators/locatorQueryBuilder.ts +0 -427
- package/srcV2/locators/locatorRegistrationBuilder.ts +0 -558
- package/srcV2/locators/locatorRegistry.ts +0 -541
- package/srcV2/locators/locatorUpdateBuilder.ts +0 -602
- package/srcV2/locators/reusableLocatorBuilder.ts +0 -200
- package/srcV2/locators/types.ts +0 -256
- package/srcV2/locators/utils.ts +0 -309
- package/srcV2/locators/v1SchemaTranslator.ts +0 -178
- package/srcV2/pageObject.ts +0 -105
package/docs/v2/PageObject.md
DELETED
|
@@ -1,293 +0,0 @@
|
|
|
1
|
-
# PageObject (v2)
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
`PageObject` is the core v2 abstraction that wires a Playwright `Page` to:
|
|
6
|
-
|
|
7
|
-
- A typed locator registry (`add`, `getLocator`, `getNestedLocator`, `getLocatorSchema`).
|
|
8
|
-
- The navigation helper (`navigation`).
|
|
9
|
-
- The session storage helper (`sessionStorage`).
|
|
10
|
-
|
|
11
|
-
It is intentionally minimal: you provide locator definitions and any post-navigation actions, then compose additional behavior on top.
|
|
12
|
-
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
## Constructor and generics
|
|
16
|
-
|
|
17
|
-
```ts
|
|
18
|
-
export abstract class PageObject<
|
|
19
|
-
LocatorSchemaPathType extends string,
|
|
20
|
-
Options extends UrlTypeOptions = { baseUrlType: string; urlPathType: string },
|
|
21
|
-
> {
|
|
22
|
-
protected constructor(
|
|
23
|
-
page: Page,
|
|
24
|
-
baseUrl: BaseUrlTypeFromOptions<Options>,
|
|
25
|
-
urlPath: UrlPathTypeFromOptions<Options>,
|
|
26
|
-
options?: { label?: string; navOptions?: NavigationOptions },
|
|
27
|
-
)
|
|
28
|
-
}
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
### `LocatorSchemaPathType`
|
|
32
|
-
|
|
33
|
-
A literal union of dot-delimited locator paths. The registry validates this union at compile time and runtime.
|
|
34
|
-
|
|
35
|
-
```ts
|
|
36
|
-
type Paths =
|
|
37
|
-
| "common.spinner"
|
|
38
|
-
| "main"
|
|
39
|
-
| "main.form@login"
|
|
40
|
-
| "main.form@login.input@username"
|
|
41
|
-
| "main.form@login.input@password"
|
|
42
|
-
| "main.button@login";
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
### `Options` (`UrlTypeOptions`)
|
|
46
|
-
|
|
47
|
-
`UrlTypeOptions` controls how `baseUrl`, `urlPath`, and `fullUrl` are typed and interpreted:
|
|
48
|
-
|
|
49
|
-
```ts
|
|
50
|
-
type UrlTypeOptions = {
|
|
51
|
-
baseUrlType?: string | RegExp;
|
|
52
|
-
urlPathType?: string | RegExp;
|
|
53
|
-
};
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
- If both are strings, `fullUrl` is a string and all navigation methods are available.
|
|
57
|
-
- If either is `RegExp`, `fullUrl` is a `RegExp`, and navigation is limited to URL assertions (`expectThisPage`, `expectAnotherPage`).
|
|
58
|
-
|
|
59
|
-
### Constructor options
|
|
60
|
-
|
|
61
|
-
- `label`: Optional label used in navigation and session storage step titles. Defaults to the class name.
|
|
62
|
-
- `navOptions`: Default `NavigationOptions` (`waitUntil`, `waitForLoadState`) used by the navigation helper.
|
|
63
|
-
|
|
64
|
-
---
|
|
65
|
-
|
|
66
|
-
## Required abstract methods
|
|
67
|
-
|
|
68
|
-
### `defineLocators()`
|
|
69
|
-
|
|
70
|
-
Define every locator path for the page using the v2 registry DSL (`add(...).getByRole(...)`, etc.). This is called in the constructor before navigation is created.
|
|
71
|
-
|
|
72
|
-
### `pageActionsToPerformAfterNavigation()`
|
|
73
|
-
|
|
74
|
-
Return a list of async callbacks to run after `gotoThisPage()` and `expectThisPage()`.
|
|
75
|
-
|
|
76
|
-
- Return `[]` to run no actions.
|
|
77
|
-
- Return `null` to skip the actions list entirely.
|
|
78
|
-
|
|
79
|
-
---
|
|
80
|
-
|
|
81
|
-
## Public properties
|
|
82
|
-
|
|
83
|
-
| Property | Type | Purpose |
|
|
84
|
-
| --- | --- | --- |
|
|
85
|
-
| `page` | `Page` | Playwright `Page` instance. |
|
|
86
|
-
| `baseUrl` / `urlPath` / `fullUrl` | `string` or `RegExp` | URL values typed based on `UrlTypeOptions`. |
|
|
87
|
-
| `label` | `string` | Label used for navigation and session storage steps. |
|
|
88
|
-
| `sessionStorage` | `SessionStorage` | Session storage helper, labeled with `label`. |
|
|
89
|
-
| `navigation` | `ExtractNavigationType<FullUrlType>` | Navigation helper (methods vary by URL type). |
|
|
90
|
-
| `add` | `AddAccessor<Paths>` | Registry `add` method for locator definitions. |
|
|
91
|
-
| `getLocator` | `GetLocatorAccessor<Paths>` | Terminal locator resolver. |
|
|
92
|
-
| `getNestedLocator` | `GetNestedLocatorAccessor<Paths>` | Full chained locator resolver. |
|
|
93
|
-
| `getLocatorSchema` | `GetLocatorSchemaAccessor<Paths>` | Builder clone for filters/indices/updates. |
|
|
94
|
-
|
|
95
|
-
---
|
|
96
|
-
|
|
97
|
-
## Example: basic `PageObject` class
|
|
98
|
-
|
|
99
|
-
```ts
|
|
100
|
-
import { expect, type Page } from "@playwright/test";
|
|
101
|
-
import { PageObject, step } from "pomwright";
|
|
102
|
-
import type { User } from "testData";
|
|
103
|
-
|
|
104
|
-
type Paths =
|
|
105
|
-
| "common.spinner"
|
|
106
|
-
| "main"
|
|
107
|
-
| "main.form@login"
|
|
108
|
-
| "main.form@login.input@username"
|
|
109
|
-
| "main.form@login.input@password"
|
|
110
|
-
| "main.button@login";
|
|
111
|
-
|
|
112
|
-
export class LoginPage extends PageObject<Paths> {
|
|
113
|
-
constructor(page: Page) {
|
|
114
|
-
super(page, "https://example.com", "/login", { label: "LoginPage" });
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
protected defineLocators(): void {
|
|
118
|
-
this.add("common.spinner").getByTestId("loading-spinner");
|
|
119
|
-
this.add("main").locator("main");
|
|
120
|
-
this.add("main.form@login").getByRole("form", { name: "Login" });
|
|
121
|
-
this.add("main.form@login.input@username").getByLabel("Username");
|
|
122
|
-
this.add("main.form@login.input@password").getByLabel("Password");
|
|
123
|
-
this.add("main.button@login").getByRole("button", { name: "Login" });
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
protected pageActionsToPerformAfterNavigation() {
|
|
127
|
-
return [
|
|
128
|
-
async () => {
|
|
129
|
-
await expect(this.getLocator("common.spinner")).toHaveCount(0);
|
|
130
|
-
await this.getNestedLocator("main.form@login").waitFor({ state: "visible" });
|
|
131
|
-
},
|
|
132
|
-
];
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
@step()
|
|
136
|
-
async loginAsUser(user: User) {
|
|
137
|
-
await this.getNestedLocator("main.form@login.input@username").fill(user.username);
|
|
138
|
-
await this.getNestedLocator("main.form@login.input@password").fill(user.password);
|
|
139
|
-
await this.getNestedLocator("main.button@login").click();
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
---
|
|
145
|
-
|
|
146
|
-
## Navigation helper details
|
|
147
|
-
|
|
148
|
-
The navigation helper is created automatically and exposed as `pageObject.navigation`.
|
|
149
|
-
|
|
150
|
-
### When `fullUrl` is a string
|
|
151
|
-
|
|
152
|
-
Available methods:
|
|
153
|
-
|
|
154
|
-
- `goto(urlPathOrUrl, options?)` – resolves paths starting with `/` against `baseUrl`.
|
|
155
|
-
- `gotoThisPage(options?)` – navigates to `fullUrl` and runs `pageActionsToPerformAfterNavigation()`.
|
|
156
|
-
- `expectThisPage(options?)` – waits for `fullUrl` and runs actions.
|
|
157
|
-
- `expectAnotherPage(options?)` – waits for a non-matching URL.
|
|
158
|
-
|
|
159
|
-
### When `fullUrl` is a `RegExp`
|
|
160
|
-
|
|
161
|
-
Available methods:
|
|
162
|
-
|
|
163
|
-
- `expectThisPage(options?)` – matches against the regex.
|
|
164
|
-
- `expectAnotherPage(options?)` – asserts URL does not match.
|
|
165
|
-
|
|
166
|
-
### Default vs per-call options
|
|
167
|
-
|
|
168
|
-
You can pass `navOptions` into the `PageObject` constructor and override per call:
|
|
169
|
-
|
|
170
|
-
```ts
|
|
171
|
-
class OrdersPage extends PageObject<"main"> {
|
|
172
|
-
constructor(page: Page) {
|
|
173
|
-
super(page, "https://example.com", "/orders", {
|
|
174
|
-
label: "OrdersPage",
|
|
175
|
-
navOptions: { waitUntil: "domcontentloaded", waitForLoadState: "domcontentloaded" },
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
protected defineLocators() {
|
|
180
|
-
this.add("main").locator("main");
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
protected pageActionsToPerformAfterNavigation() {
|
|
184
|
-
return [];
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
await ordersPage.navigation.gotoThisPage({ waitUntil: "load" });
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
---
|
|
192
|
-
|
|
193
|
-
## URL typing examples
|
|
194
|
-
|
|
195
|
-
### All-string URLs (full navigation support)
|
|
196
|
-
|
|
197
|
-
```ts
|
|
198
|
-
class ProfilePage extends PageObject<"main"> {
|
|
199
|
-
constructor(page: Page) {
|
|
200
|
-
super(page, "https://example.com", "/profile", { label: "ProfilePage" });
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
protected defineLocators() {
|
|
204
|
-
this.add("main").locator("main");
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
protected pageActionsToPerformAfterNavigation() {
|
|
208
|
-
return [];
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
### RegExp URL path (assert-only navigation)
|
|
214
|
-
|
|
215
|
-
```ts
|
|
216
|
-
type UrlOptions = { baseUrlType: string; urlPathType: RegExp };
|
|
217
|
-
|
|
218
|
-
class AccountPage extends PageObject<"main", UrlOptions> {
|
|
219
|
-
constructor(page: Page) {
|
|
220
|
-
super(page, "https://example.com", /\/account\/.+/, { label: "AccountPage" });
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
protected defineLocators() {
|
|
224
|
-
this.add("main").locator("main");
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
protected pageActionsToPerformAfterNavigation() {
|
|
228
|
-
return [];
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
await accountPage.navigation.expectThisPage();
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
---
|
|
236
|
-
|
|
237
|
-
## Accessing locators
|
|
238
|
-
|
|
239
|
-
- `getLocator(path)` returns the **terminal** locator only (no ancestor chaining).
|
|
240
|
-
- `getNestedLocator(path)` returns the **fully chained** locator.
|
|
241
|
-
- `getLocatorSchema(path)` returns a mutable clone to add filters, indices, or update/replace definitions before resolving.
|
|
242
|
-
|
|
243
|
-
```ts
|
|
244
|
-
const terminal = loginPage.getLocator("main.form@login.input@username");
|
|
245
|
-
const chained = loginPage.getNestedLocator("main.form@login.input@username");
|
|
246
|
-
|
|
247
|
-
const filtered = loginPage
|
|
248
|
-
.getLocatorSchema("main.form@login.input@username")
|
|
249
|
-
.filter("main.form@login.input@username", { hasText: /User/i })
|
|
250
|
-
.getNestedLocator();
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
---
|
|
254
|
-
|
|
255
|
-
## SessionStorage helper
|
|
256
|
-
|
|
257
|
-
`PageObject` constructs `SessionStorage` with `label` as a prefix, so step titles are easy to track.
|
|
258
|
-
|
|
259
|
-
```ts
|
|
260
|
-
await loginPage.sessionStorage.set({ token: "abc" }, { reload: true });
|
|
261
|
-
await loginPage.sessionStorage.setOnNextNavigation({ theme: "dark" });
|
|
262
|
-
const data = await loginPage.sessionStorage.get(["token", "theme"], { waitForContext: true });
|
|
263
|
-
await loginPage.sessionStorage.clear(["token"], { waitForContext: true });
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
---
|
|
267
|
-
|
|
268
|
-
## Fixture wiring example
|
|
269
|
-
|
|
270
|
-
```ts
|
|
271
|
-
import { test as base } from "@playwright/test";
|
|
272
|
-
import type { Page } from "@playwright/test";
|
|
273
|
-
import { LoginPage } from "./login.page";
|
|
274
|
-
|
|
275
|
-
type Fixtures = { loginPage: LoginPage };
|
|
276
|
-
|
|
277
|
-
export const test = base.extend<Fixtures>({
|
|
278
|
-
loginPage: async ({ page }, use) => {
|
|
279
|
-
await use(new LoginPage(page as Page));
|
|
280
|
-
},
|
|
281
|
-
});
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
---
|
|
285
|
-
|
|
286
|
-
## Key differences vs v1
|
|
287
|
-
|
|
288
|
-
- `PageObject` replaces `BasePage` and does **not** carry Playwright `testInfo` or a logger.
|
|
289
|
-
- Registry APIs are fluent (`add(...).getByRole(...)`) instead of schema objects.
|
|
290
|
-
- `getLocator`/`getNestedLocator` are synchronous and do not accept index maps; use `getLocatorSchema(...).nth(...)`.
|
|
291
|
-
- Navigation is built into the base class and depends on URL typing.
|
|
292
|
-
|
|
293
|
-
See the migration docs in `docs/v1-to-v2-migration` for a step-by-step guide.
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
# Composing locator modules
|
|
2
|
-
|
|
3
|
-
When you split locator registration across `*.locators.ts` files, type child modules with
|
|
4
|
-
an inline generic so they accept parent registries with supersets of paths while keeping full fluent
|
|
5
|
-
type precision:
|
|
6
|
-
|
|
7
|
-
```ts
|
|
8
|
-
// alert.locator.ts
|
|
9
|
-
import type { LocatorRegistry } from "pomwright";
|
|
10
|
-
|
|
11
|
-
type Paths = "common.alert" | "common.alert.message";
|
|
12
|
-
|
|
13
|
-
export function defineLocators<Extra extends string = never>(registry: LocatorRegistry<Paths | Extra>) {
|
|
14
|
-
registry.add("common.alert").locator(".alert-container");
|
|
15
|
-
registry.add("common.alert.message").locator(".alert-message");
|
|
16
|
-
}
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
```ts
|
|
20
|
-
// nav.locator.ts
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
```ts
|
|
24
|
-
// footer.locator.ts
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
Intermediary parent modules can then pass their full registry directly without casts:
|
|
28
|
-
|
|
29
|
-
```ts
|
|
30
|
-
// common.locators.ts
|
|
31
|
-
import type { LocatorRegistry } from "pomwright";
|
|
32
|
-
import { type Paths as Alert, defineLocators as addAlert } from "./alert.locators";
|
|
33
|
-
import { type Paths as Nav, defineLocators as addNav } from "./nav.locators";
|
|
34
|
-
import { type Paths as Footer, defineLocators as addFooter } from "./footer.locators";
|
|
35
|
-
|
|
36
|
-
type Paths = Alert | Nav | Footer | "main";
|
|
37
|
-
|
|
38
|
-
export function defineLocators<Extra extends string = never>(registry: LocatorRegistry<Paths | Extra>) {
|
|
39
|
-
addAlert(registry);
|
|
40
|
-
addNav(registry);
|
|
41
|
-
addFooter(registry);
|
|
42
|
-
registry.add("main").locator("main");
|
|
43
|
-
}
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
Parent modules can then pass their full registry directly without casts:
|
|
47
|
-
|
|
48
|
-
```ts
|
|
49
|
-
// login.locators.ts
|
|
50
|
-
import type { LocatorRegistry } from "pomwright";
|
|
51
|
-
import { type Paths as Common, defineLocators as addCommon } from "../common.locators";
|
|
52
|
-
|
|
53
|
-
export type Paths =
|
|
54
|
-
| Common
|
|
55
|
-
| "main.form@login"
|
|
56
|
-
| "main.form@login.input@username"
|
|
57
|
-
| "main.form@login.input@password"
|
|
58
|
-
| "main.button@login";
|
|
59
|
-
|
|
60
|
-
export function defineLocators(registry: LocatorRegistry<Paths>) {
|
|
61
|
-
addCommon(registry);
|
|
62
|
-
registry.add("main.form@login").getByRole("form", { name: "Login" });
|
|
63
|
-
registry.add("main.form@login.input@username").getByLabel("Username");
|
|
64
|
-
registry.add("main.form@login.input@password").getByLabel("Password");
|
|
65
|
-
registry.add("main.button@login").getByRole("button", { name: "Login" });
|
|
66
|
-
}
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
```ts
|
|
70
|
-
// login.page.ts
|
|
71
|
-
import { type Page, expect } from "@playwright/test";
|
|
72
|
-
import { PageObject } from "pomwright";
|
|
73
|
-
import { type Paths, defineLocators } from "./login.locators.ts";
|
|
74
|
-
|
|
75
|
-
export class LoginPage extends PageObject<Paths> {
|
|
76
|
-
constructor(page: Page) {
|
|
77
|
-
super(page, "https://example.com", "/login");
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
protected defineLocators(): void {
|
|
81
|
-
defineLocators(this.locatorRegistry);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
protected pageActionsToPerformAfterNavigation() {
|
|
85
|
-
return [
|
|
86
|
-
async () => {
|
|
87
|
-
await this.getNestedLocator("common.nav.logo").waitFor({ state: "visible" });
|
|
88
|
-
await this.getNestedLocator("main.form@login").waitFor({ state: "visible" });
|
|
89
|
-
},
|
|
90
|
-
];
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
```
|