pomwright 1.1.1 → 1.3.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 CHANGED
@@ -1,5 +1,617 @@
1
1
  # pomwright
2
2
 
3
+ ## 1.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#33](https://github.com/DyHex/POMWright/pull/33) [`ca192bf`](https://github.com/DyHex/POMWright/commit/ca192bf587725a0eeba623e074d2e2e8347a5766) Thanks [@DyHex](https://github.com/DyHex)! - # Highlights
8
+
9
+ 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.
10
+
11
+ ## Documentation
12
+
13
+ ### Onboarding & Patterns
14
+
15
+ - 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.
16
+
17
+ ### Reference Guides
18
+
19
+ - Documented the BasePage API, covering its generics, constructor contract, required overrides, helper methods, and recommendations for layering domain-specific base classes.
20
+ - Explained LocatorSchemaPath rules, duplication safeguards, readability conventions (including @ suffixes), and how sub-paths power IntelliSense and targeted updates.
21
+ - 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.
22
+ - Clarified how to use getLocator, getNestedLocator, and getLocatorSchema chains, including update/filter patterns, index migration guidance, and reuse techniques.
23
+ - 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.
24
+ - Shared a recommended folder layout for fixtures, page objects, and tests to help teams standardise project structure as they adopt the framework.
25
+
26
+ ## Other improvements
27
+
28
+ - Fix: Intended LocatorSchemaPath string format now fully enforced.
29
+ - Add new tests, updated and fixed some existing tests
30
+ - CI/CD improvements
31
+
32
+ ## 1.2.0
33
+
34
+ ### Minor Changes
35
+
36
+ - [#31](https://github.com/DyHex/POMWright/pull/31) [`bc29062`](https://github.com/DyHex/POMWright/commit/bc2906258a88acde1dd1479d7a000d036912f45a) Thanks [@DyHex](https://github.com/DyHex)! - # LocatorSchema Enhancements: `filter` Property, `.addFilter()`, Updated `.update()`, and Enhanced `getNestedLocator()`
37
+
38
+ ## Overview
39
+
40
+ This release introduces several key enhancements to the POMWright. These improvements aim to provide greater flexibility, maintainability, and type safety when constructing and managing locators in your Page Object Models (POMs). The main updates include:
41
+
42
+ - **New `filter` Property**: Extends filtering capabilities beyond the `locator` method.
43
+ - **New `.addFilter()` Method**: Facilitates dynamic addition of filters to locators.
44
+ - **Updated `.update()` Method**: Replaces deprecated `.update` and `.updates` methods with a more intuitive interface (none-breaking).
45
+ - **Enhanced `getNestedLocator()` Method**: Shifts from index-based to subPath-based indexing for better readability and maintainability.
46
+ - **Export of `LocatorSchemaWithoutPath`**: Enables partial or full reuse of locator schemas across different contexts.
47
+
48
+ ## Changes
49
+
50
+ ### 1. New `filter` Property for `LocatorSchema`
51
+
52
+ #### Purpose
53
+
54
+ The existing `locatorOptions` property in `LocatorSchema` is specific to the `locator` method, limiting its applicability. The newly introduced `filter` property extends filtering capabilities to all locator types (e.g., `role`, `label`, `placeholder`, `testid`, `id`, etc.), excluding `frameLocator`.
55
+
56
+ #### Behavior
57
+
58
+ - **Global Applicability**: Unlike `locatorOptions`, the `filter` property can be applied to various locator methods, enhancing versatility.
59
+ - **Priority Application**: When a `filter` is defined, it is always applied and will always be the first filter applied to the locator created from that LocatorSchema, the only exception is `locatorOptions` used with `locator`. This ensures consistent and prioritized filtering across different locator types.
60
+
61
+ #### Usage Examples
62
+
63
+ **Before: Using `locatorOptions` (Limited to `locator` method)**
64
+
65
+ ```typescript
66
+ this.locators.addSchema("main.products.radio@junior", {
67
+ locator: "radio",
68
+ locatorOptions: { hasText: "some text" },
69
+ locatorMethod: GetByMethod.locator,
70
+ });
71
+ ```
72
+
73
+ **After: Using `filter` (Applicable to Multiple Locator Methods)**
74
+
75
+ ```typescript
76
+ this.locators.addSchema("main.products.radio@junior", {
77
+ locator: "input",
78
+ filter: { hasText: "some text" },
79
+ locatorMethod: GetByMethod.locator,
80
+ });
81
+ ```
82
+
83
+ **With `role` Locator Method:**
84
+
85
+ ```typescript
86
+ this.locators.addSchema("main.products.radio@junior", {
87
+ role: "radio",
88
+ filter: { hasText: "some text" },
89
+ locatorMethod: GetByMethod.role,
90
+ });
91
+ ```
92
+
93
+ **Combined Example:**
94
+
95
+ ```typescript
96
+ this.locators.addSchema("main.subscription.form.item.section@header", {
97
+ role: "region",
98
+ roleOptions: { name: "Subscription Details" },
99
+ filter: { hasText: "Mobile 2 GB" },
100
+ locatorMethod: GetByMethod.role,
101
+ });
102
+ ```
103
+
104
+ #### Benefits
105
+
106
+ - **Enhanced Flexibility**: Apply default filters to various LocatorSchema.
107
+ - **Improved Locator Precision**: Chain multiple filters to narrow down locators based on complex criteria.
108
+ - **Backward Compatibility**: Existing `locatorOptions` works the same way as before, ensuring no disruption to current implementations.
109
+
110
+ ### 2. New `.addFilter()` Method for `.getLocatorSchema()`
111
+
112
+ #### Purpose
113
+
114
+ The `.addFilter()` method allows dynamic addition of filters to any part of the locator chain, enhancing flexibility in locator construction without modifying the original `LocatorSchema` at any point in a test.
115
+
116
+ #### Method Signature
117
+
118
+ ```typescript
119
+ .addFilter(
120
+ subPath: SubPaths<LocatorSchemaPathType, LocatorSubstring>,
121
+ filterData: FilterEntry
122
+ ): LocatorSchemaWithMethods<LocatorSchemaPathType, LocatorSubstring>
123
+ ```
124
+
125
+ #### Parameters
126
+
127
+ - `subPath`: A valid sub-path within the `LocatorSchemaPath` argument to .getLocatorSchema().
128
+ - `filterData`: An object defining the filter criteria, which can include:
129
+ - `has?: Locator`
130
+ - `hasNot?: Locator`
131
+ - `hasText?: string | RegExp`
132
+ - `hasNotText?: string | RegExp`
133
+
134
+ #### Usage Examples
135
+
136
+ **Adding Filters to Specific Sub-Paths:**
137
+
138
+ ```typescript
139
+ const allCheckboxesForBrandFilters = await poc
140
+ .getLocatorSchema("main.products.searchControls.filterType.label.checkbox")
141
+ .addFilter("main.products.searchControls.filterType", {
142
+ hasText: /Producer/i,
143
+ })
144
+ .getNestedLocator();
145
+ ```
146
+
147
+ **Chaining Multiple Filters:**
148
+
149
+ ```typescript
150
+ const refinedCheckboxes = await poc
151
+ .getLocatorSchema("main.products.searchControls.filterType.label.checkbox")
152
+ .addFilter("main.products.searchControls.filterType", {
153
+ hasText: /Producer/i,
154
+ hasNotText: /discontinued/i,
155
+ })
156
+ .addFilter("main.products.searchControls.filterType.label", {
157
+ hasText: "Samsung",
158
+ })
159
+ .addFilter("main.products.searchControls.filterType.label", {
160
+ has: poc.page.getByRole("checkbox"),
161
+ })
162
+ .getNestedLocator();
163
+ ```
164
+
165
+ **Combining `filter` Property and `.addFilter()`:**
166
+
167
+ ```typescript
168
+ this.locators.addSchema("main.subscription.form.item.section@header", {
169
+ role: "region",
170
+ roleOptions: { name: "Subscription Details" },
171
+ filter: { hasText: "Mobile 2 GB" },
172
+ locatorMethod: GetByMethod.role,
173
+ });
174
+
175
+ const specificSection = await poc
176
+ .getLocatorSchema("main.subscription.form.item.section@header")
177
+ .addFilter("main.subscription.form.item.section@header", {
178
+ hasText: "Additional Services",
179
+ })
180
+ .getNestedLocator();
181
+ ```
182
+
183
+ #### Benefits
184
+
185
+ - **Dynamic Filtering**: Add or modify filters on-the-fly without altering the original schema definitions.
186
+ - **Chainability**: Easily chain multiple `.addFilter()` calls to build complex locator chains.
187
+ - **Error Handling**: Attempts to add filters to invalid sub-paths will throw descriptive errors (compile & run-time), ensuring only valid paths are modified.
188
+
189
+ ### 3. Updated `.update()` Method
190
+
191
+ #### Purpose
192
+
193
+ The existing `.update` and `.updates` methods are deprecated and will be removed in version 2.0.0. `.update` could only update the last LocatorSchema in the chain and `.updates` relied on index-based updates, which posed maintainability challenges, especially when renaming `LocatorSchemaPath` strings. The new `.update` method leverages valid `subPaths` of `LocatorSchemaPath` instead of indices, enhancing readability and reducing manual maintenance.
194
+
195
+ #### New Method Signature
196
+
197
+ ```typescript
198
+ .update(
199
+ subPath: SubPaths<LocatorSchemaPathType, LocatorSubstring>,
200
+ modifiedSchema: Partial<LocatorSchemaWithoutPath>
201
+ ): LocatorSchemaWithMethods<LocatorSchemaPathType, LocatorSubstring>
202
+ ```
203
+
204
+ #### Deprecation of Old Methods
205
+
206
+ - **Old `.update(updates: Partial<LocatorSchemaWithoutPath>): LocatorSchemaWithMethods`**
207
+ - **Old `.updates(indexedUpdates: { [index: number]: Partial<LocatorSchemaWithoutPath> | null }): LocatorSchemaWithMethods`**
208
+
209
+ These methods are marked as deprecated and will be removed in version 2.0.0.
210
+
211
+ #### Usage Examples
212
+
213
+ **Case A: Update the Last `LocatorSchema` in the Chain**
214
+
215
+ ```typescript
216
+ const editBtn = await profile
217
+ .getLocatorSchema("content.region.details.button.edit")
218
+ .update("content.region.details.button.edit", {
219
+ roleOptions: { name: "new accessibility name" },
220
+ })
221
+ .getNestedLocator();
222
+ ```
223
+
224
+ **Case B: Update a `LocatorSchema` Earlier in the Chain**
225
+
226
+ ```typescript
227
+ const editBtn = await profile
228
+ .getLocatorSchema("content.region.details.button.edit")
229
+ .update("content.region.details", {
230
+ roleOptions: { name: "new accessibility name" },
231
+ })
232
+ .getNestedLocator();
233
+ ```
234
+
235
+ **Case C: Update Multiple `LocatorSchema` in the Chain**
236
+
237
+ ```typescript
238
+ const editBtn = await profile
239
+ .getLocatorSchema("content.region.details.button.edit")
240
+ .update("content", { roleOptions: { name: "new accessibility name" } })
241
+ .update("content.region", {
242
+ roleOptions: { name: "new accessibility name" },
243
+ })
244
+ .update("content.region.details", {
245
+ roleOptions: { name: "new accessibility name" },
246
+ })
247
+ .update("content.region.details.button", {
248
+ roleOptions: { name: "new accessibility name" },
249
+ })
250
+ .update("content.region.details.button.edit", {
251
+ roleOptions: { name: "new accessibility name" },
252
+ })
253
+ .getNestedLocator();
254
+ ```
255
+
256
+ #### Benefits
257
+
258
+ - **Enhanced Readability**: Using `LocatorSchemaPath` strings makes the code more intuitive and easier to understand.
259
+ - **Reduced Maintenance**: Eliminates the need to manage index-based references, especially when `LocatorSchemaPath` strings are renamed or restructured.
260
+ - **Type Safety**: Leverages TypeScript's type system to ensure only valid `subPath` strings are used, enhancing developer experience with accurate Intellisense suggestions.
261
+
262
+ ### 4. Enhanced `getNestedLocator()` Method
263
+
264
+ #### Purpose
265
+
266
+ The `getNestedLocator()` method has been updated to utilize valid `subPath`'s of `LocatorSchemaPath` instead of numeric indices when specifying `.nth(n)` occurrences within a locator chain. The old index-based method is deprecated and will be removed in version 2.0.0.
267
+
268
+ #### New Method Signature
269
+
270
+ ```typescript
271
+ getNestedLocator(
272
+ subPathIndices?: { [K in SubPaths<LocatorSchemaPathType, LocatorSubstring>]: number | null }
273
+ ): Promise<Locator>
274
+ ```
275
+
276
+ #### Deprecation of Old Method
277
+
278
+ - **Old `getNestedLocator(indices?: { [key: number]: number | null }): Promise<Locator>`**
279
+
280
+ This method is marked as deprecated and will be removed in version 2.0.0.
281
+
282
+ #### Usage Examples
283
+
284
+ **Old Usage (Deprecated):**
285
+
286
+ ```typescript
287
+ const saveBtn = await profile.getNestedLocator(
288
+ "content.region.details.button.save",
289
+ { 4: 2 }
290
+ );
291
+
292
+ const editBtn = await profile
293
+ .getLocatorSchema("content.region.details.button.edit")
294
+ .getNestedLocator({ 2: index });
295
+ ```
296
+
297
+ **New Usage:**
298
+
299
+ ```typescript
300
+ const saveBtn = await profile.getNestedLocator(
301
+ "content.region.details.button.save",
302
+ {
303
+ "content.region.details.button.save": 2,
304
+ }
305
+ );
306
+
307
+ const editBtn = await profile
308
+ .getLocatorSchema("content.region.details.button.edit")
309
+ .getNestedLocator({ "content.region.details": index });
310
+ ```
311
+
312
+ #### Benefits
313
+
314
+ - **Improved Readability**: SubPath-based indexing is more intuitive and aligns with the hierarchical nature of locator paths.
315
+ - **Enhanced Maintainability**: Reduces confusion and manual updates when `LocatorSchemaPath` strings are modified.
316
+ - **Type Safety and Intellisense**: TypeScript provides accurate suggestions for valid `subPath` keys, enhancing the developer experience and reducing errors.
317
+
318
+ ### 5. Export of `LocatorSchemaWithoutPath`
319
+
320
+ #### Purpose
321
+
322
+ The `LocatorSchemaWithoutPath` type is now exported through `index.ts`, enabling full or partial reuse of `LocatorSchema` definitions across different `addSchema` calls within the same or different `initLocatorSchemas` functions.
323
+
324
+ #### Usage Example
325
+
326
+ ```typescript
327
+ import { GetByMethod, LocatorSchemaWithoutPath } from "pomwright";
328
+ import { missingInputError } from "@common/page-components/errors.locatorSchema.ts";
329
+
330
+ export type LocatorSchemaPath =
331
+ | "body"
332
+ | "body.main"
333
+ | "body.main.section"
334
+ | "body.main.section@products"
335
+ | "body.main.section@userInfo"
336
+ | "body.main.section@userInfo.input@email"
337
+ | "body.main.section@userInfo.inputError"
338
+ | "body.main.section@deliveryInfo";
339
+
340
+ export function initLocatorSchemas(
341
+ locators: GetLocatorBase<LocatorSchemaPath>
342
+ ) {
343
+ locators.addSchema("body", {
344
+ locator: "body",
345
+ locatorMethod: GetByMethod.locator,
346
+ });
347
+
348
+ locators.addSchema("body.main", {
349
+ locator: "main",
350
+ locatorMethod: GetByMethod.locator,
351
+ });
352
+
353
+ const region: LocatorSchemaWithoutPath = {
354
+ role: "region",
355
+ locatorMethod: GetByMethod.role,
356
+ };
357
+
358
+ locators.addSchema("body.main.section", {
359
+ ...region,
360
+ });
361
+
362
+ locators.addSchema("body.main.section@products", {
363
+ ...region,
364
+ roleOptions: { name: "Products" },
365
+ });
366
+
367
+ locators.addSchema("body.main.section@userInfo", {
368
+ ...region,
369
+ roleOptions: { name: "Contact Info" },
370
+ filter: { hasText: /e-mail/i },
371
+ });
372
+
373
+ locators.addSchema("body.main.section@userInfo.input@email", {
374
+ role: "textbox",
375
+ roleOptions: { name: "Input your e-mail" },
376
+ locatorMethod: GetByMethod.role,
377
+ });
378
+
379
+ locators.addSchema("body.main.section@userInfo.inputError", {
380
+ ...missingInputError,
381
+ });
382
+
383
+ locators.addSchema("body.main.section@deliveryInfo", {
384
+ ...region,
385
+ roleOptions: { name: "Delivery Info" },
386
+ });
387
+ }
388
+ ```
389
+
390
+ #### Benefits
391
+
392
+ - **Code Reusability**: Facilitates the reuse of common locator schema fragments across different contexts, reducing redundancy.
393
+ - **Modular Definitions**: Encourages a modular approach to defining locators, enhancing organization and scalability.
394
+
395
+ ## Deprecations
396
+
397
+ ### 1. Deprecated `.update` and `.updates` Methods
398
+
399
+ - **Old `.update(updates: Partial<LocatorSchemaWithoutPath>): LocatorSchemaWithMethods`**
400
+ - **Old `.updates(indexedUpdates: { [index: number]: Partial<LocatorSchemaWithoutPath> | null }): LocatorSchemaWithMethods`**
401
+
402
+ **Reason:**
403
+ `.updates` relied on index-based updates, which are prone to errors and require manual maintenance, especially when `LocatorSchemaPath` strings are renamed or restructured. While the old `.update` method could only update the last LocatorSchema in the path. Confusing with multiple methods instead of just one.
404
+
405
+ **Replacement:**
406
+ Use the new `.update(subPath, modifiedSchema)` method, which leverages `subpath`'s of valid `LocatorSchemaPath` strings for more intuitive and maintainable updates.
407
+
408
+ **Removal Schedule:**
409
+ These methods are deprecated and will be removed in version 2.0.0.
410
+
411
+ ### 2. Deprecated Old `getNestedLocator` Method
412
+
413
+ - **Old `getNestedLocator(indices?: { [key: number]: number | null }): Promise<Locator>`**
414
+
415
+ **Reason:**
416
+ Index-based indexing is less readable and requires manual updates when `LocatorSchemaPath` strings change.
417
+
418
+ **Replacement:**
419
+ Use the updated `getNestedLocator(subPathIndices?: { [K in SubPaths<LocatorSchemaPathType, LocatorSubstring>]: number | null }): Promise<Locator>` method, which utilizes `LocatorSchemaPath` strings for indexing.
420
+
421
+ **Removal Schedule:**
422
+ This method is deprecated and will be removed in version 2.0.0.
423
+
424
+ ## Migration Guide
425
+
426
+ ### Updating `.update` and `.updates` Methods
427
+
428
+ **Old Usage:**
429
+
430
+ ```typescript
431
+ const allCheckboxes = await poc
432
+ .getLocatorSchema("main.products.searchControls.filterType.label.checkbox")
433
+ .updates({ 3: { locatorOptions: { hasText: /Producer/i } } })
434
+ .getNestedLocator();
435
+ ```
436
+
437
+ **New Usage:**
438
+
439
+ ```typescript
440
+ const allCheckboxes = await poc
441
+ .getLocatorSchema("main.products.searchControls.filterType.label.checkbox")
442
+ .update("main.products.searchControls.filterType", {
443
+ locatorOptions: { hasText: /Producer/i },
444
+ })
445
+ .getNestedLocator();
446
+ ```
447
+
448
+ ### Updating `getNestedLocator` Method
449
+
450
+ **Old Usage (Deprecated):**
451
+
452
+ ```typescript
453
+ const saveBtn = await profile.getNestedLocator(
454
+ "content.region.details.button.save",
455
+ { 4: 2 }
456
+ );
457
+
458
+ const editBtn = await profile
459
+ .getLocatorSchema("content.region.details.button.edit")
460
+ .getNestedLocator({ 2: index });
461
+ ```
462
+
463
+ **New Usage:**
464
+
465
+ ```typescript
466
+ const saveBtn = await profile.getNestedLocator(
467
+ "content.region.details.button.save",
468
+ {
469
+ "content.region.details.button.save": 2,
470
+ }
471
+ );
472
+
473
+ const editBtn = await profile
474
+ .getLocatorSchema("content.region.details.button.edit")
475
+ .getNestedLocator({ "content.region.details": index });
476
+ ```
477
+
478
+ ### Utilizing `LocatorSchemaPath` Instead of Indices
479
+
480
+ Transition from index-based to `LocatorSchemaPath`-based indexing to improve code readability and maintainability.
481
+
482
+ **Old Example:**
483
+
484
+ ```typescript
485
+ const allCheckboxes = await poc
486
+ .getLocatorSchema("main.form.item.checkbox")
487
+ .updates({ 3: { locatorOptions: { hasText: /Producer/i } } })
488
+ .getNestedLocator();
489
+ ```
490
+
491
+ **New Example:**
492
+
493
+ ```typescript
494
+ const allCheckboxes = await poc
495
+ .getLocatorSchema("main.form.item.checkbox")
496
+ .update("main.form.item", { locatorOptions: { hasText: /Producer/i } })
497
+ .getNestedLocator();
498
+ ```
499
+
500
+ ## Example in Context
501
+
502
+ ### Defining a LocatorSchema with `filter` and Using `.addFilter()`
503
+
504
+ ```typescript
505
+ // Defining LocatorSchemas
506
+ this.locators.addSchema("body.main.section@userInfo", {
507
+ role: "region",
508
+ roleOptions: { name: "Contact Info" },
509
+ filter: { hasText: /e-mail/i },
510
+ locatorMethod: GetByMethod.role,
511
+ });
512
+
513
+ // Dynamically adding additional filters using `.addFilter()`
514
+ const specificSection = await poc
515
+ .getLocatorSchema("body.main.section@userInfo")
516
+ .addFilter("body.main.section@userInfo", { hasText: "Additional Services" })
517
+ .getNestedLocator();
518
+ ```
519
+
520
+ ### Updating LocatorSchemas with the New `.update()` Method
521
+
522
+ ```typescript
523
+ const editBtn = await profile
524
+ .getLocatorSchema("content.region.details.button.edit")
525
+ .update("content.region.details.button.edit", {
526
+ roleOptions: { name: "new accessibility name" },
527
+ })
528
+ .getNestedLocator();
529
+ ```
530
+
531
+ ### Reusing LocatorSchemas with `LocatorSchemaWithoutPath`
532
+
533
+ ```typescript
534
+ import { GetByMethod, LocatorSchemaWithoutPath } from "pomwright";
535
+ import { missingInputError } from "@common/page-components/errors.locatorSchema.ts";
536
+
537
+ export type LocatorSchemaPath =
538
+ | "body"
539
+ | "body.main"
540
+ | "body.main.section"
541
+ | "body.main.section@products"
542
+ | "body.main.section@userInfo"
543
+ | "body.main.section@userInfo.input@email"
544
+ | "body.main.section@userInfo.inputError"
545
+ | "body.main.section@deliveryInfo";
546
+
547
+ export function initLocatorSchemas(
548
+ locators: GetLocatorBase<LocatorSchemaPath>
549
+ ) {
550
+ locators.addSchema("body", {
551
+ locator: "body",
552
+ locatorMethod: GetByMethod.locator,
553
+ });
554
+
555
+ locators.addSchema("body.main", {
556
+ locator: "main",
557
+ locatorMethod: GetByMethod.locator,
558
+ });
559
+
560
+ const region: LocatorSchemaWithoutPath = {
561
+ role: "region",
562
+ locatorMethod: GetByMethod.role,
563
+ };
564
+
565
+ locators.addSchema("body.main.section", {
566
+ ...region,
567
+ });
568
+
569
+ locators.addSchema("body.main.section@products", {
570
+ ...region,
571
+ roleOptions: { name: "Products" },
572
+ });
573
+
574
+ locators.addSchema("body.main.section@userInfo", {
575
+ ...region,
576
+ roleOptions: { name: "Contact Info" },
577
+ filter: { hasText: /e-mail/i },
578
+ });
579
+
580
+ locators.addSchema("body.main.section@userInfo.input@email", {
581
+ role: "textbox",
582
+ roleOptions: { name: "Input your e-mail" },
583
+ locatorMethod: GetByMethod.role,
584
+ });
585
+
586
+ locators.addSchema("body.main.section@userInfo.inputError", {
587
+ ...missingInputError,
588
+ });
589
+
590
+ locators.addSchema("body.main.section@deliveryInfo", {
591
+ ...region,
592
+ roleOptions: { name: "Delivery Info" },
593
+ });
594
+ }
595
+ ```
596
+
597
+ ## Notes
598
+
599
+ - **Filter Application Order:**
600
+ The `filter` property in `LocatorSchema` is always applied first, followed by any filters added via `.addFilter()`. This ensures that predefined filters have priority over dynamically added ones.
601
+
602
+ - **Exclusion of `frameLocator`:**
603
+ The `filter` property does not apply to `frameLocator` locators. If you need to filter within frames, use the appropriate Playwright frame methods.
604
+
605
+ - **Type Safety and Intellisense:**
606
+ The new `.update()` and enhanced `getNestedLocator()` methods leverage TypeScript's type system to provide accurate Intellisense suggestions, enhancing developer experience and reducing errors.
607
+
608
+ ## Conclusion
609
+
610
+ These enhancements to `LocatorSchema` and its associated methods significantly improve the flexibility, readability, and maintainability of locator management within your POMs. By adopting the new `filter` property, `.addFilter()` method, and updated `.update()` & `getNestedLocator()` methods, you can construct more precise and adaptable locators, facilitating robust and scalable test automation.
611
+
612
+ **Note:**
613
+ Ensure to migrate away from the deprecated `.update`, `.updates`, and old `getNestedLocator` methods before upgrading to version 2.0.0 to maintain compatibility and leverage the full benefits of these enhancements.
614
+
3
615
  ## 1.1.1
4
616
 
5
617
  ### Patch Changes