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.
Files changed (117) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +5 -5
  3. package/dist/index.d.mts +91 -989
  4. package/dist/index.d.ts +91 -989
  5. package/dist/index.js +627 -1887
  6. package/dist/index.mjs +633 -1888
  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 -693
  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.getByAltText.spec.ts +0 -23
  58. package/intTestV2/tests/locatorRegistry/add/add.getById.spec.ts +0 -45
  59. package/intTestV2/tests/locatorRegistry/add/add.getByLabel.spec.ts +0 -23
  60. package/intTestV2/tests/locatorRegistry/add/add.getByPlaceholder.spec.ts +0 -23
  61. package/intTestV2/tests/locatorRegistry/add/add.getByRole.spec.ts +0 -23
  62. package/intTestV2/tests/locatorRegistry/add/add.getByTestId.spec.ts +0 -23
  63. package/intTestV2/tests/locatorRegistry/add/add.getByText.spec.ts +0 -23
  64. package/intTestV2/tests/locatorRegistry/add/add.getByTitle.spec.ts +0 -23
  65. package/intTestV2/tests/locatorRegistry/add/add.locator.spec.ts +0 -23
  66. package/intTestV2/tests/locatorRegistry/add/add.reuseExisting.spec.ts +0 -66
  67. package/intTestV2/tests/locatorRegistry/add/add.reuseReusable.spec.ts +0 -311
  68. package/intTestV2/tests/locatorRegistry/add/add.spec.ts +0 -159
  69. package/intTestV2/tests/locatorRegistry/filter.cycle.spec.ts +0 -39
  70. package/intTestV2/tests/locatorRegistry/getLocator/getLocator.spec.ts +0 -253
  71. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.clearSteps.spec.ts +0 -105
  72. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.describe.spec.ts +0 -23
  73. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.filter.spec.ts +0 -368
  74. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.getLocator.spec.ts +0 -56
  75. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.getNestedLocator.spec.ts +0 -175
  76. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.nth.spec.ts +0 -60
  77. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.remove.spec.ts +0 -32
  78. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.replace.spec.ts +0 -24
  79. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.spec.ts +0 -110
  80. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.update.spec.ts +0 -322
  81. package/intTestV2/tests/locatorRegistry/getNestedLocator/getNestedLocator.spec.ts +0 -412
  82. package/intTestV2/tests/locatorRegistry/registry/registry.binding.spec.ts +0 -50
  83. package/intTestV2/tests/locatorRegistry/validation/validation.locatorSchemaPath.spec.ts +0 -115
  84. package/intTestV2/tests/locatorRegistry/validation/validation.sub-path.spec.ts +0 -45
  85. package/intTestV2/tests/step/step.spec.ts +0 -49
  86. package/intTestV2/tests/testApp/color.spec.ts +0 -15
  87. package/intTestV2/tests/testApp/iframe.spec.ts +0 -57
  88. package/intTestV2/tests/testApp/testFilters.spec.ts +0 -24
  89. package/intTestV2/tests/testApp/testPage.spec.ts +0 -161
  90. package/intTestV2/tests/testApp/testPath.spec.ts +0 -18
  91. package/pack-build.sh +0 -11
  92. package/pack-test-v2.sh +0 -36
  93. package/playwright.base.ts +0 -42
  94. package/skills/README.md +0 -56
  95. package/skills/pomwright-v1-5-bridge-migration/SKILL.md +0 -40
  96. package/skills/pomwright-v1-5-bridge-migration/references/call-site-migration.md +0 -178
  97. package/skills/pomwright-v1-5-bridge-migration/references/schema-translation.md +0 -183
  98. package/skills/pomwright-v2-migration/SKILL.md +0 -63
  99. package/skills/pomwright-v2-migration/references/call-site-migration.md +0 -265
  100. package/skills/pomwright-v2-migration/references/class-migration.md +0 -266
  101. package/skills/pomwright-v2-migration/references/fixture-and-helpers.md +0 -423
  102. package/skills/pomwright-v2-migration/references/locator-registration.md +0 -344
  103. package/srcV2/fixture/base.fixtures.ts +0 -23
  104. package/srcV2/helpers/navigation.ts +0 -153
  105. package/srcV2/helpers/playwrightReportLogger.ts +0 -196
  106. package/srcV2/helpers/sessionStorage.ts +0 -251
  107. package/srcV2/helpers/stepDecorator.ts +0 -106
  108. package/srcV2/locators/index.ts +0 -15
  109. package/srcV2/locators/locatorQueryBuilder.ts +0 -427
  110. package/srcV2/locators/locatorRegistrationBuilder.ts +0 -558
  111. package/srcV2/locators/locatorRegistry.ts +0 -541
  112. package/srcV2/locators/locatorUpdateBuilder.ts +0 -602
  113. package/srcV2/locators/reusableLocatorBuilder.ts +0 -200
  114. package/srcV2/locators/types.ts +0 -256
  115. package/srcV2/locators/utils.ts +0 -309
  116. package/srcV2/locators/v1SchemaTranslator.ts +0 -178
  117. package/srcV2/pageObject.ts +0 -105
@@ -1,558 +0,0 @@
1
- import type { Page } from "@playwright/test";
2
- import type { LocatorRegistryInternal } from "./locatorRegistry";
3
- import type {
4
- AltTextDefinition,
5
- FilterDefinition,
6
- IdDefinition,
7
- IndexSelector,
8
- LabelDefinition,
9
- LocatorDefinition,
10
- LocatorDescription,
11
- LocatorSchemaRecord,
12
- LocatorStep,
13
- LocatorStrategyDefinition,
14
- LocatorStrategyDefinitionPatch,
15
- PlaceholderDefinition,
16
- RegistryPath,
17
- RoleDefinition,
18
- TextDefinition,
19
- TitleDefinition,
20
- } from "./types";
21
- import { applyDefinitionPatch, normalizeIdValue, normalizeSteps } from "./utils";
22
-
23
- export type LocatorRegistrationPostDefinitionBuilder<
24
- LocatorSchemaPathType extends string,
25
- Path extends RegistryPath<LocatorSchemaPathType>,
26
- > = {
27
- filter: (
28
- filter: FilterDefinition<RegistryPath<LocatorSchemaPathType>, RegistryPath<LocatorSchemaPathType>>,
29
- ) => LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path>;
30
- nth: (index: IndexSelector) => LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path>;
31
- describe: (description: LocatorDescription) => LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path>;
32
- };
33
-
34
- export class LocatorRegistrationBuilder<
35
- LocatorSchemaPathType extends string,
36
- Path extends RegistryPath<LocatorSchemaPathType>,
37
- Seeded extends boolean = false,
38
- > {
39
- private steps: LocatorStep<LocatorSchemaPathType, RegistryPath<LocatorSchemaPathType>>[] = [];
40
- private definition?: LocatorStrategyDefinition;
41
- private description?: LocatorDescription;
42
- private registered = false;
43
- private readonly reuseType?: LocatorStrategyDefinition["type"];
44
- private readonly seededDefinition: boolean;
45
- private overrideApplied = false;
46
- private postDefinitionView?: LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path>;
47
-
48
- constructor(
49
- private readonly registry: LocatorRegistryInternal<LocatorSchemaPathType>,
50
- private readonly path: Path,
51
- seed?: {
52
- initialDefinition?: LocatorStrategyDefinition;
53
- initialSteps?: LocatorStep<LocatorSchemaPathType, RegistryPath<LocatorSchemaPathType>>[];
54
- reuseType?: LocatorStrategyDefinition["type"];
55
- initialDescription?: LocatorDescription;
56
- },
57
- ) {
58
- if (seed?.initialSteps) {
59
- this.steps = normalizeSteps<LocatorSchemaPathType, RegistryPath<LocatorSchemaPathType>>(seed.initialSteps);
60
- }
61
-
62
- if (seed?.initialDefinition) {
63
- this.definition = seed.initialDefinition;
64
- this.seededDefinition = true;
65
- } else {
66
- this.seededDefinition = false;
67
- }
68
-
69
- this.reuseType = seed?.reuseType;
70
- this.description = seed?.initialDescription;
71
- }
72
-
73
- persistSeededDefinition() {
74
- if (this.seededDefinition && !this.registered) {
75
- this.persist();
76
- }
77
- return this;
78
- }
79
-
80
- /**
81
- * Records a Playwright-style filter on the locator being registered. Filters are applied in the
82
- * order they are chained and can include `has`/`hasNot` locator references. Requires that a
83
- * locator strategy has already been set for this registration.
84
- *
85
- * @example
86
- * ```ts
87
- * registry.add("list.item").locator("li").filter({ hasText: /Row/ });
88
- * ```
89
- */
90
- filter(
91
- filter: FilterDefinition<RegistryPath<LocatorSchemaPathType>, RegistryPath<LocatorSchemaPathType>>,
92
- ): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path> {
93
- this.applyFilter(filter);
94
- return this.getPostDefinitionView();
95
- }
96
-
97
- /**
98
- * Adds an index selector for the locator being registered. Indices are applied in the order they
99
- * are chained and require a locator definition to have been set first.
100
- *
101
- * @example
102
- * ```ts
103
- * registry.add("table.rows").locator("tr").nth(0);
104
- * ```
105
- */
106
- nth(index: IndexSelector): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path> {
107
- this.applyIndex(index);
108
- return this.getPostDefinitionView();
109
- }
110
-
111
- describe(description: LocatorDescription): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path> {
112
- this.description = description;
113
- this.persist();
114
- return this.getPostDefinitionView();
115
- }
116
-
117
- /**
118
- * Uses Playwright `getByRole` semantics to define the locator strategy. Accepts a role and
119
- * optional options; when seeded via `{ reuse }`, an options-only call patches the seeded role.
120
- *
121
- * @example
122
- * ```ts
123
- * registry.add("nav.home").getByRole("link", { name: "Home" });
124
- * ```
125
- */
126
- getByRole(
127
- role: RoleDefinition["role"],
128
- options: RoleDefinition["options"],
129
- ): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path>;
130
- getByRole(role: RoleDefinition["role"]): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path>;
131
- getByRole(
132
- options: Seeded extends true ? RoleDefinition["options"] : never,
133
- ): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path>;
134
- getByRole(roleOrOptions: RoleDefinition["role"] | RoleDefinition["options"], options?: RoleDefinition["options"]) {
135
- const definition: LocatorStrategyDefinitionPatch =
136
- typeof roleOrOptions === "string"
137
- ? options !== undefined
138
- ? { type: "role", role: roleOrOptions, options }
139
- : { type: "role", role: roleOrOptions }
140
- : { type: "role", options: roleOrOptions };
141
-
142
- return this.commit(definition);
143
- }
144
-
145
- /**
146
- * Uses Playwright `getByText` semantics to define the locator strategy. Accepts string/RegExp
147
- * text and optional options; when seeded, an options-only call patches the seeded text.
148
- *
149
- * @example
150
- * ```ts
151
- * registry.add("alert.error").getByText(/failed/i);
152
- * ```
153
- */
154
- getByText(
155
- text: Parameters<Page["getByText"]>[0],
156
- options: Parameters<Page["getByText"]>[1],
157
- ): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path>;
158
- getByText(
159
- text: Parameters<Page["getByText"]>[0],
160
- ): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path>;
161
- getByText(
162
- options: Seeded extends true ? Parameters<Page["getByText"]>[1] : never,
163
- ): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path>;
164
- getByText(
165
- textOrOptions: Parameters<Page["getByText"]>[0] | Parameters<Page["getByText"]>[1],
166
- options?: Parameters<Page["getByText"]>[1],
167
- ) {
168
- const definition: LocatorStrategyDefinitionPatch =
169
- typeof textOrOptions === "string" || textOrOptions instanceof RegExp
170
- ? options !== undefined
171
- ? ({ type: "text", text: textOrOptions, options } as TextDefinition)
172
- : ({ type: "text", text: textOrOptions } as TextDefinition)
173
- : { type: "text", options: textOrOptions };
174
-
175
- return this.commit(definition);
176
- }
177
-
178
- /**
179
- * Uses Playwright `getByLabel` semantics to define the locator strategy. Accepts label text and
180
- * optional options; when seeded, an options-only call patches the seeded text.
181
- *
182
- * @example
183
- * ```ts
184
- * registry.add("form.email").getByLabel("Email", { exact: true });
185
- * ```
186
- */
187
- getByLabel(
188
- text: Parameters<Page["getByLabel"]>[0],
189
- options: Parameters<Page["getByLabel"]>[1],
190
- ): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path>;
191
- getByLabel(
192
- text: Parameters<Page["getByLabel"]>[0],
193
- ): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path>;
194
- getByLabel(
195
- options: Seeded extends true ? Parameters<Page["getByLabel"]>[1] : never,
196
- ): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path>;
197
- getByLabel(
198
- textOrOptions: Parameters<Page["getByLabel"]>[0] | Parameters<Page["getByLabel"]>[1],
199
- options?: Parameters<Page["getByLabel"]>[1],
200
- ) {
201
- const definition: LocatorStrategyDefinitionPatch =
202
- typeof textOrOptions === "string" || textOrOptions instanceof RegExp
203
- ? options !== undefined
204
- ? ({ type: "label", text: textOrOptions, options } as LabelDefinition)
205
- : ({ type: "label", text: textOrOptions } as LabelDefinition)
206
- : { type: "label", options: textOrOptions };
207
-
208
- return this.commit(definition);
209
- }
210
-
211
- /**
212
- * Uses Playwright `getByPlaceholder` semantics to define the locator strategy. Accepts placeholder
213
- * text and optional options; when seeded, an options-only call patches the seeded text.
214
- *
215
- * @example
216
- * ```ts
217
- * registry.add("form.search").getByPlaceholder("Search", { exact: true });
218
- * ```
219
- */
220
- getByPlaceholder(
221
- text: Parameters<Page["getByPlaceholder"]>[0],
222
- options: Parameters<Page["getByPlaceholder"]>[1],
223
- ): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path>;
224
- getByPlaceholder(
225
- text: Parameters<Page["getByPlaceholder"]>[0],
226
- ): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path>;
227
- getByPlaceholder(
228
- options: Seeded extends true ? Parameters<Page["getByPlaceholder"]>[1] : never,
229
- ): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path>;
230
- getByPlaceholder(
231
- textOrOptions: Parameters<Page["getByPlaceholder"]>[0] | Parameters<Page["getByPlaceholder"]>[1],
232
- options?: Parameters<Page["getByPlaceholder"]>[1],
233
- ) {
234
- const definition: LocatorStrategyDefinitionPatch =
235
- typeof textOrOptions === "string" || textOrOptions instanceof RegExp
236
- ? options !== undefined
237
- ? ({ type: "placeholder", text: textOrOptions, options } as PlaceholderDefinition)
238
- : ({ type: "placeholder", text: textOrOptions } as PlaceholderDefinition)
239
- : { type: "placeholder", options: textOrOptions };
240
-
241
- return this.commit(definition);
242
- }
243
-
244
- /**
245
- * Uses Playwright `getByAltText` semantics to define the locator strategy. Accepts alt text and
246
- * optional options; when seeded, an options-only call patches the seeded text.
247
- *
248
- * @example
249
- * ```ts
250
- * registry.add("image.logo").getByAltText(/brand/);
251
- * ```
252
- */
253
- getByAltText(
254
- text: Parameters<Page["getByAltText"]>[0],
255
- options: Parameters<Page["getByAltText"]>[1],
256
- ): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path>;
257
- getByAltText(
258
- text: Parameters<Page["getByAltText"]>[0],
259
- ): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path>;
260
- getByAltText(
261
- options: Seeded extends true ? Parameters<Page["getByAltText"]>[1] : never,
262
- ): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path>;
263
- getByAltText(
264
- textOrOptions: Parameters<Page["getByAltText"]>[0] | Parameters<Page["getByAltText"]>[1],
265
- options?: Parameters<Page["getByAltText"]>[1],
266
- ) {
267
- const definition: LocatorStrategyDefinitionPatch =
268
- typeof textOrOptions === "string" || textOrOptions instanceof RegExp
269
- ? options !== undefined
270
- ? ({ type: "altText", text: textOrOptions, options } as AltTextDefinition)
271
- : ({ type: "altText", text: textOrOptions } as AltTextDefinition)
272
- : { type: "altText", options: textOrOptions };
273
-
274
- return this.commit(definition);
275
- }
276
-
277
- /**
278
- * Uses Playwright `getByTitle` semantics to define the locator strategy. Accepts title text and
279
- * optional options; when seeded, an options-only call patches the seeded text.
280
- *
281
- * @example
282
- * ```ts
283
- * registry.add("icon.info").getByTitle("Info");
284
- * ```
285
- */
286
- getByTitle(
287
- text: Parameters<Page["getByTitle"]>[0],
288
- options: Parameters<Page["getByTitle"]>[1],
289
- ): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path>;
290
- getByTitle(
291
- text: Parameters<Page["getByTitle"]>[0],
292
- ): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path>;
293
- getByTitle(
294
- options: Seeded extends true ? Parameters<Page["getByTitle"]>[1] : never,
295
- ): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path>;
296
- getByTitle(
297
- textOrOptions: Parameters<Page["getByTitle"]>[0] | Parameters<Page["getByTitle"]>[1],
298
- options?: Parameters<Page["getByTitle"]>[1],
299
- ) {
300
- const definition: LocatorStrategyDefinitionPatch =
301
- typeof textOrOptions === "string" || textOrOptions instanceof RegExp
302
- ? options !== undefined
303
- ? ({ type: "title", text: textOrOptions, options } as TitleDefinition)
304
- : ({ type: "title", text: textOrOptions } as TitleDefinition)
305
- : { type: "title", options: textOrOptions };
306
-
307
- return this.commit(definition);
308
- }
309
-
310
- /**
311
- * Uses Playwright `locator` semantics to define the locator strategy. Accepts a selector and
312
- * optional options; when seeded, an options-only call patches the seeded selector by merging
313
- * options while inheriting the selector.
314
- *
315
- * @example
316
- * ```ts
317
- * registry.add("list.items").locator("ul > li");
318
- * ```
319
- */
320
- locator(
321
- selector: Parameters<Page["locator"]>[0],
322
- options: Parameters<Page["locator"]>[1],
323
- ): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path>;
324
- locator(
325
- selector: Parameters<Page["locator"]>[0],
326
- ): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path>;
327
- locator(
328
- options: Seeded extends true ? Parameters<Page["locator"]>[1] : never,
329
- ): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path>;
330
- locator(
331
- selectorOrOptions: Parameters<Page["locator"]>[0] | Parameters<Page["locator"]>[1],
332
- options?: Parameters<Page["locator"]>[1],
333
- ) {
334
- const definition: LocatorStrategyDefinitionPatch =
335
- typeof selectorOrOptions === "string"
336
- ? options !== undefined
337
- ? ({ type: "locator", selector: selectorOrOptions, options } as LocatorDefinition)
338
- : ({ type: "locator", selector: selectorOrOptions } as LocatorDefinition)
339
- : { type: "locator", options: selectorOrOptions };
340
-
341
- return this.commit(definition);
342
- }
343
-
344
- /**
345
- * Uses Playwright `frameLocator` semantics to define the locator strategy, entering the targeted
346
- * frame for subsequent chained locators. When seeded, `selector` may be omitted to retain the
347
- * existing selector while overriding options elsewhere.
348
- *
349
- * @example
350
- * ```ts
351
- * registry.add("frame.login").frameLocator("iframe.auth");
352
- * ```
353
- */
354
- frameLocator(
355
- selector: Seeded extends true
356
- ? Parameters<Page["frameLocator"]>[0] | undefined
357
- : Parameters<Page["frameLocator"]>[0],
358
- ): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path> {
359
- const definition: LocatorStrategyDefinitionPatch = selector
360
- ? { type: "frameLocator", selector }
361
- : { type: "frameLocator" };
362
- return this.commit(definition);
363
- }
364
-
365
- /**
366
- * Uses Playwright `getByTestId` semantics to define the locator strategy. When seeded, omitting
367
- * the argument inherits the seeded `testId` while allowing options from other overrides.
368
- *
369
- * @example
370
- * ```ts
371
- * registry.add("card.title").getByTestId("card-title");
372
- * ```
373
- */
374
- getByTestId(
375
- testId: Seeded extends true ? Parameters<Page["getByTestId"]>[0] | undefined : Parameters<Page["getByTestId"]>[0],
376
- ): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path> {
377
- const definition: LocatorStrategyDefinitionPatch = testId ? { type: "testId", testId } : { type: "testId" };
378
- return this.commit(definition);
379
- }
380
-
381
- /**
382
- * Targets elements by `id`, normalizing string or RegExp input. When seeded, the argument can be
383
- * omitted to inherit the seeded id.
384
- *
385
- * @example
386
- * ```ts
387
- * registry.add("modal.close").getById("close-modal");
388
- * ```
389
- */
390
- getById(
391
- id: Seeded extends true ? string | RegExp | undefined : string | RegExp,
392
- ): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path> {
393
- const definition: LocatorStrategyDefinitionPatch = id
394
- ? { type: "id", id: normalizeIdValue(id) as IdDefinition["id"] }
395
- : { type: "id" };
396
- return this.commit(definition);
397
- }
398
-
399
- private commit(
400
- definition: LocatorStrategyDefinition | LocatorStrategyDefinitionPatch,
401
- ): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path> {
402
- this.ensureDefinitionAllowedWithRollback(definition as LocatorStrategyDefinition);
403
- const mergedDefinition = this.seededDefinition
404
- ? applyDefinitionPatch(this.definition as LocatorStrategyDefinition, definition)
405
- : (definition as LocatorStrategyDefinition);
406
- this.definition = mergedDefinition;
407
- if (this.reuseType && this.seededDefinition) {
408
- this.overrideApplied = true;
409
- }
410
- this.persist();
411
- return this.getPostDefinitionView();
412
- }
413
-
414
- private applyFilter(
415
- filter: FilterDefinition<RegistryPath<LocatorSchemaPathType>, RegistryPath<LocatorSchemaPathType>>,
416
- ) {
417
- this.ensureDefinition();
418
- this.steps.push({ kind: "filter", filter });
419
- this.persist();
420
- }
421
-
422
- private applyIndex(index: IndexSelector) {
423
- this.ensureDefinition();
424
- this.steps.push({ kind: "index", index });
425
- this.persist();
426
- }
427
-
428
- private ensureDefinitionAllowedWithRollback(definition: LocatorStrategyDefinition) {
429
- if (this.seededDefinition) {
430
- if (definition.type !== this.reuseType) {
431
- this.rollbackSeededRegistration();
432
- throw new Error(
433
- `The locator definition for "${this.path}" must use the "${this.reuseType}" strategy when reusing a locator.`,
434
- );
435
- }
436
-
437
- if (this.overrideApplied) {
438
- throw new Error(
439
- `A locator definition for "${this.path}" was already provided from reuse; only one matching override is allowed.`,
440
- );
441
- }
442
-
443
- return;
444
- }
445
-
446
- if (this.definition) {
447
- throw new Error(
448
- `A locator definition for "${this.path}" has already been provided; only one locator type can be set for a registration.`,
449
- );
450
- }
451
- }
452
-
453
- private ensureDefinition() {
454
- if (!this.definition) {
455
- throw new Error(`A locator definition must be provided before applying filters or indices for "${this.path}".`);
456
- }
457
- }
458
-
459
- private persist() {
460
- if (!this.definition) {
461
- throw new Error(`No locator schema definition provided for path "${this.path}".`);
462
- }
463
-
464
- const record: LocatorSchemaRecord<LocatorSchemaPathType, RegistryPath<LocatorSchemaPathType>> = {
465
- locatorSchemaPath: this.path,
466
- definition: this.definition,
467
- steps: normalizeSteps<LocatorSchemaPathType, RegistryPath<LocatorSchemaPathType>>(this.steps),
468
- ...(this.description !== undefined ? { description: this.description } : {}),
469
- };
470
-
471
- if (this.registered) {
472
- this.registry.replace(this.path, record);
473
- } else {
474
- this.registry.register(this.path, record);
475
- this.registered = true;
476
- }
477
- }
478
-
479
- private rollbackSeededRegistration() {
480
- if (this.seededDefinition && this.registered) {
481
- this.registry.unregister(this.path);
482
- this.registered = false;
483
- }
484
- }
485
-
486
- private getPostDefinitionView(): LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path> {
487
- if (this.postDefinitionView) {
488
- return this.postDefinitionView;
489
- }
490
-
491
- const view: LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path> = {
492
- filter: (filter: FilterDefinition<RegistryPath<LocatorSchemaPathType>, RegistryPath<LocatorSchemaPathType>>) => {
493
- this.applyFilter(filter);
494
- return view;
495
- },
496
- nth: (index: IndexSelector) => {
497
- this.applyIndex(index);
498
- return view;
499
- },
500
- describe: (description: LocatorDescription) => {
501
- this.description = description;
502
- this.persist();
503
- return view;
504
- },
505
- };
506
-
507
- this.postDefinitionView = view;
508
- return view;
509
- }
510
- }
511
-
512
- export type LocatorRegistrationPreDefinitionBuilder<
513
- LocatorSchemaPathType extends string,
514
- Path extends RegistryPath<LocatorSchemaPathType>,
515
- Seeded extends boolean = false,
516
- > = LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path> &
517
- Pick<
518
- LocatorRegistrationBuilder<LocatorSchemaPathType, Path, Seeded>,
519
- | "getByRole"
520
- | "getByText"
521
- | "getByLabel"
522
- | "getByPlaceholder"
523
- | "getByAltText"
524
- | "getByTitle"
525
- | "locator"
526
- | "frameLocator"
527
- | "getByTestId"
528
- | "getById"
529
- >;
530
-
531
- type LocatorMethodForType<Type extends LocatorStrategyDefinition["type"]> = Type extends "role"
532
- ? "getByRole"
533
- : Type extends "text"
534
- ? "getByText"
535
- : Type extends "label"
536
- ? "getByLabel"
537
- : Type extends "placeholder"
538
- ? "getByPlaceholder"
539
- : Type extends "altText"
540
- ? "getByAltText"
541
- : Type extends "title"
542
- ? "getByTitle"
543
- : Type extends "locator"
544
- ? "locator"
545
- : Type extends "frameLocator"
546
- ? "frameLocator"
547
- : Type extends "testId"
548
- ? "getByTestId"
549
- : Type extends "id"
550
- ? "getById"
551
- : never;
552
-
553
- export type LocatorRegistrationSeededBuilderForType<
554
- LocatorSchemaPathType extends string,
555
- Path extends RegistryPath<LocatorSchemaPathType>,
556
- SeededType extends LocatorStrategyDefinition["type"],
557
- > = LocatorRegistrationPostDefinitionBuilder<LocatorSchemaPathType, Path> &
558
- Pick<LocatorRegistrationBuilder<LocatorSchemaPathType, Path, true>, LocatorMethodForType<SeededType>>;