pomwright 1.5.1 → 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.
Files changed (119) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +5 -5
  3. package/dist/index.d.mts +75 -970
  4. package/dist/index.d.ts +75 -970
  5. package/dist/index.js +585 -1872
  6. package/dist/index.mjs +598 -1880
  7. package/package.json +9 -11
  8. package/AGENTS.md +0 -37
  9. package/docs/v1/BaseApi-explanation.md +0 -63
  10. package/docs/v1/BasePage-explanation.md +0 -96
  11. package/docs/v1/LocatorSchema-explanation.md +0 -271
  12. package/docs/v1/LocatorSchemaPath-explanation.md +0 -165
  13. package/docs/v1/PlaywrightReportLogger-explanation.md +0 -56
  14. package/docs/v1/get-locator-methods-explanation.md +0 -250
  15. package/docs/v1/intro-to-using-pomwright.md +0 -899
  16. package/docs/v1/sessionStorage-methods-explanation.md +0 -38
  17. package/docs/v1/tips-folder-structure.md +0 -38
  18. package/docs/v1-to-v2-migration/bridge-migration-guide.md +0 -159
  19. package/docs/v1-to-v2-migration/direct-migration-guide.md +0 -238
  20. package/docs/v1-to-v2-migration/v1-to-v2-comparison.md +0 -547
  21. package/docs/v2/PageObject.md +0 -293
  22. package/docs/v2/composing-locator-modules.md +0 -93
  23. package/docs/v2/locator-registry.md +0 -695
  24. package/docs/v2/logging.md +0 -168
  25. package/docs/v2/overview.md +0 -515
  26. package/docs/v2/session-storage.md +0 -160
  27. package/index.ts +0 -75
  28. package/intTestV2/.env +0 -0
  29. package/intTestV2/fixtures/testApp.fixtures.ts +0 -43
  30. package/intTestV2/package.json +0 -22
  31. package/intTestV2/page-object-models/testApp/pages/iframe/iframe.locatorSchema.ts +0 -24
  32. package/intTestV2/page-object-models/testApp/pages/iframe/iframe.page.ts +0 -17
  33. package/intTestV2/page-object-models/testApp/pages/testPage.locatorSchema.ts +0 -32
  34. package/intTestV2/page-object-models/testApp/pages/testPage.page.ts +0 -119
  35. package/intTestV2/page-object-models/testApp/pages/testPath/[color]/color.locatorSchema.ts +0 -29
  36. package/intTestV2/page-object-models/testApp/pages/testPath/[color]/color.page.ts +0 -48
  37. package/intTestV2/page-object-models/testApp/pages/testPath/testPath.locatorSchema.ts +0 -9
  38. package/intTestV2/page-object-models/testApp/pages/testPath/testPath.page.ts +0 -23
  39. package/intTestV2/page-object-models/testApp/pages/testfilters/testfilters.locatorSchema.ts +0 -114
  40. package/intTestV2/page-object-models/testApp/pages/testfilters/testfilters.page.ts +0 -23
  41. package/intTestV2/page-object-models/testApp/testApp.base.ts +0 -20
  42. package/intTestV2/playwright.config.ts +0 -54
  43. package/intTestV2/server.js +0 -216
  44. package/intTestV2/test-data/staticPage/index.html +0 -280
  45. package/intTestV2/test-data/staticPage/w3images/avatar2.png +0 -0
  46. package/intTestV2/test-data/staticPage/w3images/avatar3.png +0 -0
  47. package/intTestV2/test-data/staticPage/w3images/avatar5.png +0 -0
  48. package/intTestV2/test-data/staticPage/w3images/avatar6.png +0 -0
  49. package/intTestV2/test-data/staticPage/w3images/forest.jpg +0 -0
  50. package/intTestV2/test-data/staticPage/w3images/lights.jpg +0 -0
  51. package/intTestV2/test-data/staticPage/w3images/mountains.jpg +0 -0
  52. package/intTestV2/test-data/staticPage/w3images/nature.jpg +0 -0
  53. package/intTestV2/test-data/staticPage/w3images/snow.jpg +0 -0
  54. package/intTestV2/tests/locatorRegistry/add/add.describe.spec.ts +0 -54
  55. package/intTestV2/tests/locatorRegistry/add/add.filter.spec.ts +0 -143
  56. package/intTestV2/tests/locatorRegistry/add/add.frameLocator.spec.ts +0 -23
  57. package/intTestV2/tests/locatorRegistry/add/add.get.clone.spec.ts +0 -76
  58. package/intTestV2/tests/locatorRegistry/add/add.getByAltText.spec.ts +0 -23
  59. package/intTestV2/tests/locatorRegistry/add/add.getById.spec.ts +0 -45
  60. package/intTestV2/tests/locatorRegistry/add/add.getByLabel.spec.ts +0 -23
  61. package/intTestV2/tests/locatorRegistry/add/add.getByPlaceholder.spec.ts +0 -23
  62. package/intTestV2/tests/locatorRegistry/add/add.getByRole.spec.ts +0 -23
  63. package/intTestV2/tests/locatorRegistry/add/add.getByTestId.spec.ts +0 -23
  64. package/intTestV2/tests/locatorRegistry/add/add.getByText.spec.ts +0 -23
  65. package/intTestV2/tests/locatorRegistry/add/add.getByTitle.spec.ts +0 -23
  66. package/intTestV2/tests/locatorRegistry/add/add.locator.spec.ts +0 -23
  67. package/intTestV2/tests/locatorRegistry/add/add.reuseExisting.spec.ts +0 -107
  68. package/intTestV2/tests/locatorRegistry/add/add.reuseReusable.spec.ts +0 -311
  69. package/intTestV2/tests/locatorRegistry/add/add.spec.ts +0 -159
  70. package/intTestV2/tests/locatorRegistry/filter.cycle.spec.ts +0 -39
  71. package/intTestV2/tests/locatorRegistry/getLocator/getLocator.spec.ts +0 -253
  72. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.clearSteps.spec.ts +0 -105
  73. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.describe.spec.ts +0 -23
  74. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.filter.spec.ts +0 -368
  75. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.getLocator.spec.ts +0 -56
  76. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.getNestedLocator.spec.ts +0 -175
  77. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.nth.spec.ts +0 -60
  78. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.remove.spec.ts +0 -32
  79. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.replace.spec.ts +0 -24
  80. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.spec.ts +0 -110
  81. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.update.spec.ts +0 -322
  82. package/intTestV2/tests/locatorRegistry/getNestedLocator/getNestedLocator.spec.ts +0 -412
  83. package/intTestV2/tests/locatorRegistry/registry/registry.binding.spec.ts +0 -50
  84. package/intTestV2/tests/locatorRegistry/validation/validation.locatorSchemaPath.spec.ts +0 -115
  85. package/intTestV2/tests/locatorRegistry/validation/validation.locatorSchemaPath.typecheck.ts +0 -86
  86. package/intTestV2/tests/locatorRegistry/validation/validation.sub-path.spec.ts +0 -45
  87. package/intTestV2/tests/step/step.spec.ts +0 -49
  88. package/intTestV2/tests/testApp/color.spec.ts +0 -15
  89. package/intTestV2/tests/testApp/iframe.spec.ts +0 -57
  90. package/intTestV2/tests/testApp/testFilters.spec.ts +0 -24
  91. package/intTestV2/tests/testApp/testPage.spec.ts +0 -161
  92. package/intTestV2/tests/testApp/testPath.spec.ts +0 -18
  93. package/pack-build.sh +0 -11
  94. package/pack-test-v2.sh +0 -36
  95. package/playwright.base.ts +0 -42
  96. package/skills/README.md +0 -56
  97. package/skills/pomwright-v1-5-bridge-migration/SKILL.md +0 -40
  98. package/skills/pomwright-v1-5-bridge-migration/references/call-site-migration.md +0 -178
  99. package/skills/pomwright-v1-5-bridge-migration/references/schema-translation.md +0 -183
  100. package/skills/pomwright-v2-migration/SKILL.md +0 -63
  101. package/skills/pomwright-v2-migration/references/call-site-migration.md +0 -265
  102. package/skills/pomwright-v2-migration/references/class-migration.md +0 -266
  103. package/skills/pomwright-v2-migration/references/fixture-and-helpers.md +0 -423
  104. package/skills/pomwright-v2-migration/references/locator-registration.md +0 -344
  105. package/srcV2/fixture/base.fixtures.ts +0 -23
  106. package/srcV2/helpers/navigation.ts +0 -153
  107. package/srcV2/helpers/playwrightReportLogger.ts +0 -196
  108. package/srcV2/helpers/sessionStorage.ts +0 -251
  109. package/srcV2/helpers/stepDecorator.ts +0 -106
  110. package/srcV2/locators/index.ts +0 -15
  111. package/srcV2/locators/locatorQueryBuilder.ts +0 -427
  112. package/srcV2/locators/locatorRegistrationBuilder.ts +0 -558
  113. package/srcV2/locators/locatorRegistry.ts +0 -583
  114. package/srcV2/locators/locatorUpdateBuilder.ts +0 -602
  115. package/srcV2/locators/reusableLocatorBuilder.ts +0 -200
  116. package/srcV2/locators/types.ts +0 -256
  117. package/srcV2/locators/utils.ts +0 -309
  118. package/srcV2/locators/v1SchemaTranslator.ts +0 -178
  119. package/srcV2/pageObject.ts +0 -105
@@ -1,178 +0,0 @@
1
- # Call-Site Migration: v1 -> v2 accessor syntax
2
-
3
- ## getLocator / getNestedLocator (async -> sync)
4
-
5
- v1 returns `Promise<Locator>`. v2 returns `Locator` synchronously. Remove `await`.
6
-
7
- ```ts
8
- // v1
9
- const btn = await poc.getLocator("navbar.button@login");
10
- await btn.click();
11
-
12
- const nested = await poc.getNestedLocator("navbar.button@logout");
13
- await nested.click();
14
-
15
- // v2
16
- await poc.getLocator("navbar.button@login").click();
17
- await poc.getNestedLocator("navbar.button@logout").click();
18
- ```
19
-
20
- ## getNestedLocator with index maps -> getLocatorSchema + nth
21
-
22
- v1 accepted an optional index map object as second argument. v2 does not; use `getLocatorSchema` with `.nth()` instead.
23
-
24
- ```ts
25
- // v1
26
- const submit = await poc.getNestedLocator("main.form.button@submit", {
27
- "main.form": 0,
28
- });
29
-
30
- // v2
31
- const submit = poc
32
- .getLocatorSchema("main.form.button@submit")
33
- .nth("main.form", 0)
34
- .getNestedLocator();
35
- ```
36
-
37
- Multiple indices:
38
-
39
- ```ts
40
- // v1
41
- const item = await poc.getNestedLocator("main.list.item.detail", {
42
- "main.list": 0,
43
- "main.list.item": 2,
44
- });
45
-
46
- // v2
47
- const item = poc
48
- .getLocatorSchema("main.list.item.detail")
49
- .nth("main.list", 0)
50
- .nth("main.list.item", 2)
51
- .getNestedLocator();
52
- ```
53
-
54
- ## addFilter -> filter
55
-
56
- v1 `addFilter` on `getLocatorSchema()` becomes v2 `filter`. Method name and argument shape changed.
57
-
58
- ```ts
59
- // v1
60
- const filtered = await poc
61
- .getLocatorSchema("main.list.item")
62
- .addFilter("main.list", { hasText: "list" })
63
- .addFilter("main.list.item", { hasText: "Row" })
64
- .getNestedLocator({ "main.list": 0, "main.list.item": -1 });
65
-
66
- // v2
67
- const filtered = poc
68
- .getLocatorSchema("main.list.item")
69
- .filter("main.list", { hasText: "list" })
70
- .nth("main.list", 0)
71
- .filter({ hasText: "Row" }) // omitted subPath defaults to terminal path
72
- .nth(-1) // omitted subPath defaults to terminal path
73
- .getNestedLocator();
74
- ```
75
-
76
- Key difference: v2 `filter` and `nth` can be interleaved in any order. v1 required all filters first, then one index map at the end.
77
-
78
- ## update (schema mutation)
79
-
80
- v1 `update` accepted a partial schema object. v2 `update` returns a sub-builder where you chain the locator method with override options.
81
-
82
- ```ts
83
- // v1
84
- const patched = await poc
85
- .getLocatorSchema("main.button@login")
86
- .update("main.button@login", { roleOptions: { name: "Sign in" } })
87
- .getNestedLocator();
88
-
89
- // v2
90
- const patched = poc
91
- .getLocatorSchema("main.button@login")
92
- .update() // defaults to terminal path
93
- .getByRole({ name: "Sign in" }) // PATCH-style: only override options
94
- .getNestedLocator();
95
- ```
96
-
97
- v2 also adds `replace` (full replacement) and `remove` (drop a subpath from chain):
98
-
99
- ```ts
100
- // replace the entire locator strategy for a subpath
101
- const replaced = poc
102
- .getLocatorSchema("main.button@login")
103
- .replace()
104
- .getByText("Sign in")
105
- .getNestedLocator();
106
-
107
- // remove a segment from the chain
108
- const removed = poc
109
- .getLocatorSchema("main.button@login")
110
- .remove("main")
111
- .getNestedLocator();
112
- ```
113
-
114
- ## getLocatorSchema().getLocator() / .getNestedLocator()
115
-
116
- v1 terminal resolution was async. v2 is sync.
117
-
118
- ```ts
119
- // v1
120
- const loc = await poc.getLocatorSchema("main.button@login").getLocator();
121
- const nested = await poc.getLocatorSchema("main.button@login").getNestedLocator();
122
-
123
- // v2
124
- const loc = poc.getLocatorSchema("main.button@login").getLocator();
125
- const nested = poc.getLocatorSchema("main.button@login").getNestedLocator();
126
- ```
127
-
128
- ## describe (v2 only, no v1 equivalent)
129
-
130
- ```ts
131
- const btn = poc
132
- .getLocatorSchema("main.region@security.button@edit")
133
- .filter({ hasText: "Change password" })
134
- .describe("Change password")
135
- .getNestedLocator();
136
- ```
137
-
138
- ## SessionStorage signature changes
139
-
140
- ```ts
141
- // v1
142
- await poc.sessionStorage.set({ token: "abc" }, true); // boolean reload
143
- await poc.sessionStorage.get(["token"]);
144
- await poc.sessionStorage.clear();
145
-
146
- // v2
147
- await poc.sessionStorage.set({ token: "abc" }, { reload: true });
148
- await poc.sessionStorage.get(["token"], { waitForContext: true });
149
- await poc.sessionStorage.clear(); // clears all
150
- await poc.sessionStorage.clear(["token"]); // clears specific keys
151
- ```
152
-
153
- ## Import changes
154
-
155
- ```ts
156
- // v1
157
- import { BasePage, GetByMethod } from "pomwright";
158
-
159
- // v1.5 bridge
160
- import { BasePageV1toV2, GetByMethod } from "pomwright";
161
-
162
- // When all schemas moved to defineLocators, remove GetByMethod import.
163
- ```
164
-
165
- ## filter has/hasNot value changes
166
-
167
- v1 `filter.has`/`filter.hasNot` accepted `Locator` instances. v2 accepts **registry path strings** or `Locator` instances from `getLocator`/`getNestedLocator`.
168
-
169
- ```ts
170
- // v1 (Locator instance in filter)
171
- .addFilter("main.card", { has: someLocator })
172
-
173
- // v2 (path string reference)
174
- .filter("main.card", { has: "main.card.badge" })
175
-
176
- // v2 (Locator instance from registry)
177
- .filter("main.card", { has: poc.getNestedLocator("main.card.badge") })
178
- ```
@@ -1,183 +0,0 @@
1
- # Schema Translation: v1 addSchema -> v2 add() DSL
2
-
3
- ## GetByMethod mapping
4
-
5
- | v1 `locatorMethod` | v1 schema field | v1 options field | v2 method | v2 arguments |
6
- |---|---|---|---|---|
7
- | `GetByMethod.role` | `role` | `roleOptions` | `getByRole(role, options?)` | role value, roleOptions as second arg |
8
- | `GetByMethod.text` | `text` | `textOptions` | `getByText(text, options?)` | text value, textOptions as second arg |
9
- | `GetByMethod.label` | `label` | `labelOptions` | `getByLabel(text, options?)` | label value, labelOptions as second arg |
10
- | `GetByMethod.placeholder` | `placeholder` | `placeholderOptions` | `getByPlaceholder(text, options?)` | placeholder value, placeholderOptions |
11
- | `GetByMethod.altText` | `altText` | `altTextOptions` | `getByAltText(text, options?)` | altText value, altTextOptions |
12
- | `GetByMethod.title` | `title` | `titleOptions` | `getByTitle(text, options?)` | title value, titleOptions |
13
- | `GetByMethod.locator` | `locator` (string) | `locatorOptions` | `locator(selector, options?)` | locator string, locatorOptions |
14
- | `GetByMethod.frameLocator` | `frameLocator` | - | `frameLocator(selector)` | frameLocator string |
15
- | `GetByMethod.testId` | `testId` | - | `getByTestId(testId)` | testId value |
16
- | `GetByMethod.id` | `id` | - | `getById(id)` | id string or RegExp |
17
- | `GetByMethod.dataCy` | `dataCy` | - | `locator('[data-cy="value"]')` | CSS attribute selector string |
18
-
19
- ## Translation examples
20
-
21
- ### Role
22
-
23
- ```ts
24
- // v1
25
- this.locators.addSchema("main.button@login", {
26
- role: "button",
27
- roleOptions: { name: "Login" },
28
- locatorMethod: GetByMethod.role,
29
- });
30
-
31
- // v2
32
- this.add("main.button@login").getByRole("button", { name: "Login" });
33
- ```
34
-
35
- ### Locator (CSS/XPath)
36
-
37
- ```ts
38
- // v1
39
- this.locators.addSchema("main", {
40
- locator: "main",
41
- locatorMethod: GetByMethod.locator,
42
- });
43
-
44
- // v2
45
- this.add("main").locator("main");
46
- ```
47
-
48
- ### Locator with options
49
-
50
- ```ts
51
- // v1
52
- this.locators.addSchema("body.section@playground", {
53
- locator: "section",
54
- locatorOptions: { hasText: /Playground/i },
55
- locatorMethod: GetByMethod.locator,
56
- });
57
-
58
- // v2
59
- this.add("body.section@playground").locator("section", { hasText: /Playground/i });
60
- ```
61
-
62
- ### Label
63
-
64
- ```ts
65
- // v1
66
- this.locators.addSchema("main.form.input@username", {
67
- label: "Username",
68
- locatorMethod: GetByMethod.label,
69
- });
70
-
71
- // v2
72
- this.add("main.form.input@username").getByLabel("Username");
73
- ```
74
-
75
- ### FrameLocator
76
-
77
- ```ts
78
- // v1
79
- this.locators.addSchema("main.frame@login", {
80
- frameLocator: "#auth",
81
- locatorMethod: GetByMethod.frameLocator,
82
- });
83
-
84
- // v2
85
- this.add("main.frame@login").frameLocator("#auth");
86
- ```
87
-
88
- Note: terminal frameLocator paths in v2 resolve to `frameLocator.owner()` (the iframe element), not the frame itself. Non-terminal frames scope into the frame for subsequent segments.
89
-
90
- ### dataCy (removed in v2)
91
-
92
- ```ts
93
- // v1
94
- this.locators.addSchema("main.widget", {
95
- dataCy: "my-widget",
96
- locatorMethod: GetByMethod.dataCy,
97
- });
98
-
99
- // v2 (translate to CSS attribute selector)
100
- this.add("main.widget").locator('[data-cy="my-widget"]');
101
- ```
102
-
103
- ### getById
104
-
105
- ```ts
106
- // v1
107
- this.locators.addSchema("main.modal@close", {
108
- id: "close-modal",
109
- locatorMethod: GetByMethod.id,
110
- });
111
-
112
- // v2
113
- this.add("main.modal@close").getById("close-modal");
114
- ```
115
-
116
- Note: v1 regex IDs use prefix match `*[id^="pattern"]`; v2 regex IDs use substring match `[id*="pattern"]` with CSS escaping. Results may differ for edge cases.
117
-
118
- ## Filter translation
119
-
120
- v1 `filter` property on schema -> v2 chained `.filter()` call:
121
-
122
- ```ts
123
- // v1
124
- this.locators.addSchema("body.section@playground", {
125
- locator: "section",
126
- locatorMethod: GetByMethod.locator,
127
- filter: { hasText: /Playground/i },
128
- });
129
-
130
- // v2
131
- this.add("body.section@playground").locator("section").filter({ hasText: /Playground/i });
132
-
133
- // OR, if the filter only has hasText/hasNotText, use locator options instead:
134
- this.add("body.section@playground").locator("section", { hasText: /Playground/i });
135
- ```
136
-
137
- v2 `filter` accepts `has`/`hasNot` as **registry path strings or Playwright Locator instances**. Path strings are often preferred for registry-native references:
138
-
139
- ```ts
140
- // v2 filter with has/hasNot as path references
141
- this.add("main.card").locator(".card").filter({
142
- has: "main.card.badge", // path string, not Locator
143
- hasText: "Active",
144
- });
145
- ```
146
-
147
- ## Reusable locator patterns
148
-
149
- ### v1: LocatorSchemaWithoutPath + spread
150
-
151
- ```ts
152
- const buttonSchema: LocatorSchemaWithoutPath = {
153
- role: "button",
154
- locatorMethod: GetByMethod.role,
155
- };
156
-
157
- this.locators.addSchema("main.button@submit", { ...buttonSchema, roleOptions: { name: "Submit" } });
158
- this.locators.addSchema("main.button@cancel", { ...buttonSchema, roleOptions: { name: "Cancel" } });
159
- ```
160
-
161
- ### v2: createReusable or path reuse
162
-
163
- ```ts
164
- // Option A: createReusable
165
- const button = this.locatorRegistry.createReusable.getByRole("button");
166
- this.add("main.button@submit", { reuse: button }).getByRole({ name: "Submit" });
167
- this.add("main.button@cancel", { reuse: button }).getByRole({ name: "Cancel" });
168
-
169
- // Option B: reuse by path (exact clone, no override chaining; returns void so no follow-up chain)
170
- this.add("main.button@submit").getByRole("button", { name: "Submit" });
171
- this.add("main.button@cancel", { reuse: "main.button@submit" });
172
- ```
173
-
174
- > Bridge note: when `BasePageV1toV2` translates remaining v1 schemas, any path already registered in `defineLocators()` is skipped (not overwritten). Keep `defineLocators()` as the source of truth and remove stale duplicates from `initLocatorSchemas()`.
175
-
176
- ## Registration with filter + nth at definition time
177
-
178
- ```ts
179
- // v2 supports chaining filter and nth on add():
180
- this.add("one.two").locator("div.two").filter({ hasText: "two" }).nth(0);
181
- ```
182
-
183
- This registers the locator with a filter step and an nth step baked in.
@@ -1,63 +0,0 @@
1
- ---
2
- name: pomwright-v2-migration
3
- description: >
4
- Migrate POMWright page objects to v2 PageObject from either v1 BasePage or the v1.5 bridge
5
- (BasePageV1toV2). Use when asked to migrate, convert, or upgrade POMWright page objects to v2,
6
- or when working with PageObject. Covers: changing class inheritance and constructor signature,
7
- translating addSchema/initLocatorSchemas to defineLocators with v2 DSL, adding
8
- pageActionsToPerformAfterNavigation, updating call-site syntax (getLocator, getNestedLocator,
9
- getLocatorSchema), updating filter/index/update/mutation patterns, migrating fixtures, navigation,
10
- sessionStorage, logging, and adopting the @step decorator.
11
- ---
12
-
13
- # POMWright v2 Migration (BasePage / BasePageV1toV2 -> PageObject)
14
-
15
- Migrate page objects to `PageObject` from either v1 `BasePage` or the v1.5 bridge `BasePageV1toV2`.
16
- This is the final migration target; `PageObject` is the stable v2 API.
17
-
18
- ## Determine source version
19
-
20
- Before starting, identify which base class the POC currently extends:
21
-
22
- | Current base class | Source version | Key differences from v2 |
23
- |---|---|---|
24
- | `BasePage` | v1 | Constructor requires `testInfo`, `pocName`, `PlaywrightReportLogger`; uses `initLocatorSchemas` with `addSchema`; async locator accessors; `addFilter` + index maps |
25
- | `BasePageV1toV2` | v1.5 bridge | Same constructor as v1; may have both `initLocatorSchemas` and `defineLocators`; v2 accessors already available but async removed only partially |
26
-
27
- If the source is v1 `BasePage` and has not yet been migrated through the bridge, this skill handles
28
- the direct migration. All schema translation and call-site changes still apply.
29
-
30
- ## Workflow
31
-
32
- 1. **Inventory** the target POC file and its consumers (tests, fixtures, helpers that import it).
33
- 2. **Migrate the class declaration and constructor.** See [references/class-migration.md](references/class-migration.md).
34
- 3. **Migrate locator definitions** into `defineLocators()` using the v2 `add()` DSL. See [references/locator-registration.md](references/locator-registration.md).
35
- 4. **Remove `initLocatorSchemas()`** once all schemas are moved to `defineLocators()`.
36
- 5. **Add `pageActionsToPerformAfterNavigation()`** (required abstract method). See [references/class-migration.md](references/class-migration.md).
37
- 6. **Update call-site syntax** in tests, fixtures, and helpers. See [references/call-site-migration.md](references/call-site-migration.md).
38
- 7. **Migrate fixtures and helpers** (navigation, sessionStorage, logging, @step). See [references/fixture-and-helpers.md](references/fixture-and-helpers.md).
39
- 8. **Remove v1 imports** (`GetByMethod`, `BasePage`, `BasePageV1toV2`, `BasePageOptions`, `ExtractUrlPathType`, `ExtractBaseUrlType`, `ExtractFullUrlType`, `GetLocatorBase`, `LocatorSchemaWithoutPath`).
40
- 9. **Verify** by running tests.
41
-
42
- ## Key rules
43
-
44
- - v2 `PageObject` constructor takes `(page, baseUrl, urlPath, options?)` - no `testInfo`, no `pocName`, no `PlaywrightReportLogger`.
45
- - `pocName` is replaced by `options.label` (defaults to class name, so often omittable).
46
- - `testInfo` and `PlaywrightReportLogger` are no longer injected into PageObject. Use the `log` fixture from `pomwright` instead if logging is needed.
47
- - `defineLocators()` is required; `initLocatorSchemas()` does not exist in v2.
48
- - `pageActionsToPerformAfterNavigation()` is a required abstract method; return `null` or an array of async callbacks.
49
- - v2 `getLocator`/`getNestedLocator`/`getLocatorSchema` are **synchronous** (no `await`).
50
- - v2 `getNestedLocator` does not accept index maps. Use `getLocatorSchema(path).nth(subPath, index).getNestedLocator()` instead.
51
- - `filter` replaces v1 `addFilter`. `nth` replaces v1 index maps. Both can be chained in any order.
52
- - v2 `filter.has`/`filter.hasNot` accept **registry path strings** in addition to Locator instances.
53
- - `navigation` helper is exposed on PageObject: `this.navigation.gotoThisPage()`, `this.navigation.expectThisPage()`, etc.
54
- - `sessionStorage` API changed: boolean parameters replaced by options objects.
55
- - `@step` decorator is available for wrapping methods in Playwright test steps.
56
- - v1 URL type helpers renamed: `ExtractBaseUrlType` -> `BaseUrlTypeFromOptions`, `ExtractUrlPathType` -> `UrlPathTypeFromOptions`, `ExtractFullUrlType` -> `FullUrlTypeFromOptions`. The options shape flattened from `{ urlOptions: { ... } }` to `{ baseUrlType, urlPathType }`.
57
-
58
- ## References
59
-
60
- - **Class migration**: [references/class-migration.md](references/class-migration.md) - Inheritance, constructor, generics, abstract methods, base class hierarchy
61
- - **Locator registration**: [references/locator-registration.md](references/locator-registration.md) - defineLocators, add() DSL mapping, reusable locators, filter/nth at registration, frameLocator changes
62
- - **Call-site migration**: [references/call-site-migration.md](references/call-site-migration.md) - getLocator, getNestedLocator, getLocatorSchema, filter, nth, update, replace, remove, describe
63
- - **Fixtures and helpers**: [references/fixture-and-helpers.md](references/fixture-and-helpers.md) - Fixture setup, navigation helper, sessionStorage, @step decorator, logging
@@ -1,265 +0,0 @@
1
- # Call-Site Migration: v1 -> v2 accessor syntax
2
-
3
- ## getLocator / getNestedLocator (async -> sync)
4
-
5
- v1 returns `Promise<Locator>`. v2 returns `Locator` synchronously. Remove `await`.
6
-
7
- ```ts
8
- // v1
9
- const btn = await poc.getLocator("navbar.button@login");
10
- await btn.click();
11
-
12
- const nested = await poc.getNestedLocator("navbar.button@logout");
13
- await nested.click();
14
-
15
- // v2
16
- await poc.getLocator("navbar.button@login").click();
17
- await poc.getNestedLocator("navbar.button@logout").click();
18
- ```
19
-
20
- ## getNestedLocator with index maps -> getLocatorSchema + nth
21
-
22
- v1 accepted an optional index map object as second argument. v2 does not; use `getLocatorSchema` with `.nth()` instead.
23
-
24
- ```ts
25
- // v1
26
- const submit = await poc.getNestedLocator("main.form.button@submit", {
27
- "main.form": 0,
28
- });
29
-
30
- // v2
31
- const submit = poc
32
- .getLocatorSchema("main.form.button@submit")
33
- .nth("main.form", 0)
34
- .getNestedLocator();
35
- ```
36
-
37
- Multiple indices:
38
-
39
- ```ts
40
- // v1
41
- const item = await poc.getNestedLocator("main.list.item.detail", {
42
- "main.list": 0,
43
- "main.list.item": 2,
44
- });
45
-
46
- // v2
47
- const item = poc
48
- .getLocatorSchema("main.list.item.detail")
49
- .nth("main.list", 0)
50
- .nth("main.list.item", 2)
51
- .getNestedLocator();
52
- ```
53
-
54
- v2 also supports named index positions:
55
-
56
- ```ts
57
- const first = poc
58
- .getLocatorSchema("main.list.item")
59
- .nth("first") // omitted subPath defaults to terminal path
60
- .getNestedLocator();
61
-
62
- const last = poc
63
- .getLocatorSchema("main.list.item")
64
- .nth("last")
65
- .getNestedLocator();
66
- ```
67
-
68
- ## addFilter -> filter
69
-
70
- v1 `addFilter` on `getLocatorSchema()` becomes v2 `filter`. Method name and argument shape changed.
71
-
72
- ```ts
73
- // v1
74
- const filtered = await poc
75
- .getLocatorSchema("main.list.item")
76
- .addFilter("main.list", { hasText: "list" })
77
- .addFilter("main.list.item", { hasText: "Row" })
78
- .getNestedLocator({ "main.list": 0, "main.list.item": -1 });
79
-
80
- // v2
81
- const filtered = poc
82
- .getLocatorSchema("main.list.item")
83
- .filter("main.list", { hasText: "list" })
84
- .nth("main.list", 0)
85
- .filter({ hasText: "Row" }) // omitted subPath defaults to terminal path
86
- .nth(-1) // omitted subPath defaults to terminal path
87
- .getNestedLocator();
88
- ```
89
-
90
- Key differences:
91
- - `addFilter` renamed to `filter`
92
- - v2 `filter` and `nth` can be interleaved in any order
93
- - v1 required all filters first, then one index map at the end
94
- - Omitting `subPath` on `filter`/`nth` defaults to the terminal path (the path supplied to `getLocatorSchema`)
95
-
96
- ## clearSteps
97
-
98
- v2 adds `clearSteps()` to remove all runtime steps (filter + nth) from a query builder:
99
-
100
- ```ts
101
- const schema = poc.getLocatorSchema("main.list.item")
102
- .filter({ hasText: "Active" })
103
- .nth(0);
104
-
105
- // Clear all steps and start fresh
106
- const reset = schema.clearSteps().filter({ hasText: "Inactive" }).getNestedLocator();
107
-
108
- // Clear steps for a specific subPath only
109
- const partial = schema.clearSteps("main.list").getNestedLocator();
110
- ```
111
-
112
- ## update (schema mutation)
113
-
114
- v1 `update` accepted a partial schema object. v2 `update` returns a sub-builder where you chain the locator method with override options (PATCH-style merge).
115
-
116
- ```ts
117
- // v1
118
- const patched = await poc
119
- .getLocatorSchema("main.button@login")
120
- .update("main.button@login", { roleOptions: { name: "Sign in" } })
121
- .getNestedLocator();
122
-
123
- // v2
124
- const patched = poc
125
- .getLocatorSchema("main.button@login")
126
- .update() // defaults to terminal path
127
- .getByRole({ name: "Sign in" }) // PATCH-style: only override options
128
- .getNestedLocator();
129
- ```
130
-
131
- With explicit subPath:
132
-
133
- ```ts
134
- // v2
135
- const patched = poc
136
- .getLocatorSchema("main.form.button@login")
137
- .update("main.form")
138
- .locator(".login-form-v2") // override selector for the form segment
139
- .getNestedLocator();
140
- ```
141
-
142
- ## replace (full replacement)
143
-
144
- v2 adds `replace` for POST-style full replacement of a locator strategy:
145
-
146
- ```ts
147
- // v2 only
148
- const replaced = poc
149
- .getLocatorSchema("main.button@login")
150
- .replace()
151
- .getByText("Sign in") // entirely replaces the role strategy with text
152
- .getNestedLocator();
153
-
154
- // With subPath
155
- const replaced = poc
156
- .getLocatorSchema("main.form.button@login")
157
- .replace("main.form")
158
- .getByRole("region", { name: "Login" })
159
- .getNestedLocator();
160
- ```
161
-
162
- ## remove (drop segment from chain)
163
-
164
- v2 adds `remove` to soft-delete a segment from the locator chain:
165
-
166
- ```ts
167
- // v2 only
168
- const removed = poc
169
- .getLocatorSchema("main.form.button@login")
170
- .remove("main") // skips "main" when building the chain
171
- .getNestedLocator();
172
- ```
173
-
174
- Without subPath, `remove()` targets the terminal segment. Resolving immediately will throw unless the terminal definition is replaced/updated before resolve:
175
-
176
- ```ts
177
- // Throws: terminal path was removed
178
- expect(() =>
179
- poc.getLocatorSchema("main.form.button@login").remove().getNestedLocator()
180
- ).toThrow(/No locator schema registered/);
181
-
182
- // Repair terminal path before resolve
183
- const repaired = poc
184
- .getLocatorSchema("main.form.button@login")
185
- .remove()
186
- .replace("main.form.button@login")
187
- .getByRole("button", { name: "Sign in" })
188
- .getNestedLocator();
189
- ```
190
-
191
- ## getLocatorSchema().getLocator() / .getNestedLocator()
192
-
193
- v1 terminal resolution was async. v2 is sync.
194
-
195
- ```ts
196
- // v1
197
- const loc = await poc.getLocatorSchema("main.button@login").getLocator();
198
- const nested = await poc.getLocatorSchema("main.button@login").getNestedLocator();
199
-
200
- // v2
201
- const loc = poc.getLocatorSchema("main.button@login").getLocator();
202
- const nested = poc.getLocatorSchema("main.button@login").getNestedLocator();
203
- ```
204
-
205
- ## describe (v2 only, no v1 equivalent)
206
-
207
- Adds a descriptive label to the locator at runtime:
208
-
209
- ```ts
210
- const btn = poc
211
- .getLocatorSchema("main.region@security.button@edit")
212
- .filter({ hasText: "Change password" })
213
- .describe("Change password")
214
- .getNestedLocator();
215
- ```
216
-
217
- ## filter has/hasNot value changes
218
-
219
- v1 `filter.has`/`filter.hasNot` accepted `Locator` instances. v2 accepts **registry path strings** or `Locator` instances from `getLocator`/`getNestedLocator`.
220
-
221
- ```ts
222
- // v1 (Locator instance in filter)
223
- .addFilter("main.card", { has: someLocator })
224
-
225
- // v2 (path string reference - preferred)
226
- .filter("main.card", { has: "main.card.badge" })
227
-
228
- // v2 (Locator instance from registry - also valid)
229
- .filter("main.card", { has: poc.getNestedLocator("main.card.badge") })
230
- ```
231
-
232
- ## SessionStorage signature changes
233
-
234
- ```ts
235
- // v1
236
- await poc.sessionStorage.set({ token: "abc" }, true); // boolean reload
237
- await poc.sessionStorage.get(["token"]);
238
- await poc.sessionStorage.clear();
239
-
240
- // v2
241
- await poc.sessionStorage.set({ token: "abc" }, { reload: true });
242
- await poc.sessionStorage.get(["token"], { waitForContext: true });
243
- await poc.sessionStorage.clear(); // clears all
244
- await poc.sessionStorage.clear("token"); // clears specific key
245
- await poc.sessionStorage.clear(["token", "theme"]); // clears specific keys
246
- ```
247
-
248
- Key changes:
249
- - Boolean `reload` parameter -> `{ reload: true }` options object
250
- - New `{ waitForContext: true }` option on `get` and `clear` for handling navigation boundaries
251
- - `clear` now supports clearing specific keys (string or string array)
252
-
253
- ## Import changes
254
-
255
- ```ts
256
- // v1
257
- import { BasePage, GetByMethod } from "pomwright";
258
-
259
- // v1.5 bridge
260
- import { BasePageV1toV2, GetByMethod } from "pomwright";
261
-
262
- // v2
263
- import { PageObject } from "pomwright";
264
- // GetByMethod is no longer needed - remove the import
265
- ```