pomwright 1.4.0 → 1.5.1

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/AGENTS.md +37 -0
  2. package/CHANGELOG.md +193 -0
  3. package/README.md +316 -34
  4. package/dist/index.d.mts +1049 -30
  5. package/dist/index.d.ts +1049 -30
  6. package/dist/index.js +2290 -65
  7. package/dist/index.mjs +2287 -67
  8. package/docs/v1-to-v2-migration/bridge-migration-guide.md +159 -0
  9. package/docs/v1-to-v2-migration/direct-migration-guide.md +238 -0
  10. package/docs/v1-to-v2-migration/v1-to-v2-comparison.md +547 -0
  11. package/docs/v2/PageObject.md +293 -0
  12. package/docs/v2/composing-locator-modules.md +93 -0
  13. package/docs/v2/locator-registry.md +695 -0
  14. package/docs/v2/logging.md +168 -0
  15. package/docs/v2/overview.md +515 -0
  16. package/docs/v2/session-storage.md +160 -0
  17. package/index.ts +61 -9
  18. package/intTestV2/.env +0 -0
  19. package/intTestV2/fixtures/testApp.fixtures.ts +43 -0
  20. package/intTestV2/package.json +22 -0
  21. package/intTestV2/page-object-models/testApp/pages/iframe/iframe.locatorSchema.ts +24 -0
  22. package/intTestV2/page-object-models/testApp/pages/iframe/iframe.page.ts +17 -0
  23. package/intTestV2/page-object-models/testApp/pages/testPage.locatorSchema.ts +32 -0
  24. package/intTestV2/page-object-models/testApp/pages/testPage.page.ts +119 -0
  25. package/intTestV2/page-object-models/testApp/pages/testPath/[color]/color.locatorSchema.ts +29 -0
  26. package/intTestV2/page-object-models/testApp/pages/testPath/[color]/color.page.ts +48 -0
  27. package/intTestV2/page-object-models/testApp/pages/testPath/testPath.locatorSchema.ts +9 -0
  28. package/intTestV2/page-object-models/testApp/pages/testPath/testPath.page.ts +23 -0
  29. package/intTestV2/page-object-models/testApp/pages/testfilters/testfilters.locatorSchema.ts +114 -0
  30. package/intTestV2/page-object-models/testApp/pages/testfilters/testfilters.page.ts +23 -0
  31. package/intTestV2/page-object-models/testApp/testApp.base.ts +20 -0
  32. package/intTestV2/playwright.config.ts +54 -0
  33. package/intTestV2/server.js +216 -0
  34. package/intTestV2/test-data/staticPage/index.html +280 -0
  35. package/intTestV2/test-data/staticPage/w3images/avatar2.png +0 -0
  36. package/intTestV2/test-data/staticPage/w3images/avatar3.png +0 -0
  37. package/intTestV2/test-data/staticPage/w3images/avatar5.png +0 -0
  38. package/intTestV2/test-data/staticPage/w3images/avatar6.png +0 -0
  39. package/intTestV2/test-data/staticPage/w3images/forest.jpg +0 -0
  40. package/intTestV2/test-data/staticPage/w3images/lights.jpg +0 -0
  41. package/intTestV2/test-data/staticPage/w3images/mountains.jpg +0 -0
  42. package/intTestV2/test-data/staticPage/w3images/nature.jpg +0 -0
  43. package/intTestV2/test-data/staticPage/w3images/snow.jpg +0 -0
  44. package/intTestV2/tests/locatorRegistry/add/add.describe.spec.ts +54 -0
  45. package/intTestV2/tests/locatorRegistry/add/add.filter.spec.ts +143 -0
  46. package/intTestV2/tests/locatorRegistry/add/add.frameLocator.spec.ts +23 -0
  47. package/intTestV2/tests/locatorRegistry/add/add.get.clone.spec.ts +76 -0
  48. package/intTestV2/tests/locatorRegistry/add/add.getByAltText.spec.ts +23 -0
  49. package/intTestV2/tests/locatorRegistry/add/add.getById.spec.ts +45 -0
  50. package/intTestV2/tests/locatorRegistry/add/add.getByLabel.spec.ts +23 -0
  51. package/intTestV2/tests/locatorRegistry/add/add.getByPlaceholder.spec.ts +23 -0
  52. package/intTestV2/tests/locatorRegistry/add/add.getByRole.spec.ts +23 -0
  53. package/intTestV2/tests/locatorRegistry/add/add.getByTestId.spec.ts +23 -0
  54. package/intTestV2/tests/locatorRegistry/add/add.getByText.spec.ts +23 -0
  55. package/intTestV2/tests/locatorRegistry/add/add.getByTitle.spec.ts +23 -0
  56. package/intTestV2/tests/locatorRegistry/add/add.locator.spec.ts +23 -0
  57. package/intTestV2/tests/locatorRegistry/add/add.reuseExisting.spec.ts +107 -0
  58. package/intTestV2/tests/locatorRegistry/add/add.reuseReusable.spec.ts +311 -0
  59. package/intTestV2/tests/locatorRegistry/add/add.spec.ts +159 -0
  60. package/intTestV2/tests/locatorRegistry/filter.cycle.spec.ts +39 -0
  61. package/intTestV2/tests/locatorRegistry/getLocator/getLocator.spec.ts +253 -0
  62. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.clearSteps.spec.ts +105 -0
  63. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.describe.spec.ts +23 -0
  64. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.filter.spec.ts +368 -0
  65. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.getLocator.spec.ts +56 -0
  66. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.getNestedLocator.spec.ts +175 -0
  67. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.nth.spec.ts +60 -0
  68. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.remove.spec.ts +32 -0
  69. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.replace.spec.ts +24 -0
  70. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.spec.ts +110 -0
  71. package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.update.spec.ts +322 -0
  72. package/intTestV2/tests/locatorRegistry/getNestedLocator/getNestedLocator.spec.ts +412 -0
  73. package/intTestV2/tests/locatorRegistry/registry/registry.binding.spec.ts +50 -0
  74. package/intTestV2/tests/locatorRegistry/validation/validation.locatorSchemaPath.spec.ts +115 -0
  75. package/intTestV2/tests/locatorRegistry/validation/validation.locatorSchemaPath.typecheck.ts +86 -0
  76. package/intTestV2/tests/locatorRegistry/validation/validation.sub-path.spec.ts +45 -0
  77. package/intTestV2/tests/step/step.spec.ts +49 -0
  78. package/intTestV2/tests/testApp/color.spec.ts +15 -0
  79. package/intTestV2/tests/testApp/iframe.spec.ts +57 -0
  80. package/intTestV2/tests/testApp/testFilters.spec.ts +24 -0
  81. package/intTestV2/tests/testApp/testPage.spec.ts +161 -0
  82. package/intTestV2/tests/testApp/testPath.spec.ts +18 -0
  83. package/pack-build.sh +11 -0
  84. package/pack-test-v2.sh +36 -0
  85. package/package.json +10 -3
  86. package/playwright.base.ts +42 -0
  87. package/skills/README.md +56 -0
  88. package/skills/pomwright-v1-5-bridge-migration/SKILL.md +40 -0
  89. package/skills/pomwright-v1-5-bridge-migration/references/call-site-migration.md +178 -0
  90. package/skills/pomwright-v1-5-bridge-migration/references/schema-translation.md +183 -0
  91. package/skills/pomwright-v2-migration/SKILL.md +63 -0
  92. package/skills/pomwright-v2-migration/references/call-site-migration.md +265 -0
  93. package/skills/pomwright-v2-migration/references/class-migration.md +266 -0
  94. package/skills/pomwright-v2-migration/references/fixture-and-helpers.md +423 -0
  95. package/skills/pomwright-v2-migration/references/locator-registration.md +344 -0
  96. package/srcV2/fixture/base.fixtures.ts +23 -0
  97. package/srcV2/helpers/navigation.ts +153 -0
  98. package/srcV2/helpers/playwrightReportLogger.ts +196 -0
  99. package/srcV2/helpers/sessionStorage.ts +251 -0
  100. package/srcV2/helpers/stepDecorator.ts +106 -0
  101. package/srcV2/locators/index.ts +15 -0
  102. package/srcV2/locators/locatorQueryBuilder.ts +427 -0
  103. package/srcV2/locators/locatorRegistrationBuilder.ts +558 -0
  104. package/srcV2/locators/locatorRegistry.ts +583 -0
  105. package/srcV2/locators/locatorUpdateBuilder.ts +602 -0
  106. package/srcV2/locators/reusableLocatorBuilder.ts +200 -0
  107. package/srcV2/locators/types.ts +256 -0
  108. package/srcV2/locators/utils.ts +309 -0
  109. package/srcV2/locators/v1SchemaTranslator.ts +178 -0
  110. package/srcV2/pageObject.ts +105 -0
  111. /package/docs/{BaseApi-explanation.md → v1/BaseApi-explanation.md} +0 -0
  112. /package/docs/{BasePage-explanation.md → v1/BasePage-explanation.md} +0 -0
  113. /package/docs/{LocatorSchema-explanation.md → v1/LocatorSchema-explanation.md} +0 -0
  114. /package/docs/{LocatorSchemaPath-explanation.md → v1/LocatorSchemaPath-explanation.md} +0 -0
  115. /package/docs/{PlaywrightReportLogger-explanation.md → v1/PlaywrightReportLogger-explanation.md} +0 -0
  116. /package/docs/{get-locator-methods-explanation.md → v1/get-locator-methods-explanation.md} +0 -0
  117. /package/docs/{intro-to-using-pomwright.md → v1/intro-to-using-pomwright.md} +0 -0
  118. /package/docs/{sessionStorage-methods-explanation.md → v1/sessionStorage-methods-explanation.md} +0 -0
  119. /package/docs/{tips-folder-structure.md → v1/tips-folder-structure.md} +0 -0
@@ -0,0 +1,200 @@
1
+ import type { Page } from "@playwright/test";
2
+ import type {
3
+ AltTextDefinition,
4
+ FilterDefinition,
5
+ IdDefinition,
6
+ IndexSelector,
7
+ LabelDefinition,
8
+ LocatorDefinition,
9
+ LocatorDescription,
10
+ LocatorStep,
11
+ LocatorStrategyDefinition,
12
+ PlaceholderDefinition,
13
+ RegistryPath,
14
+ ReusableLocator,
15
+ RoleDefinition,
16
+ TextDefinition,
17
+ TitleDefinition,
18
+ } from "./types";
19
+ import { normalizeIdValue, normalizeSteps } from "./utils";
20
+
21
+ export class ReusableLocatorBuilder<
22
+ LocatorSchemaPathType extends string,
23
+ AllowedPaths extends string = RegistryPath<LocatorSchemaPathType>,
24
+ Type extends LocatorStrategyDefinition["type"] = LocatorStrategyDefinition["type"],
25
+ > implements ReusableLocator<LocatorSchemaPathType, AllowedPaths, Type>
26
+ {
27
+ private readonly stepsList: LocatorStep<LocatorSchemaPathType, AllowedPaths>[];
28
+ private readonly definitionValue: Extract<LocatorStrategyDefinition, { type: Type }>;
29
+ private descriptionValue?: LocatorDescription;
30
+
31
+ readonly type: Type;
32
+
33
+ constructor(
34
+ definition: Extract<LocatorStrategyDefinition, { type: Type }>,
35
+ steps: LocatorStep<LocatorSchemaPathType, AllowedPaths>[] = [],
36
+ ) {
37
+ this.definitionValue = definition;
38
+ this.type = definition.type;
39
+ this.stepsList = normalizeSteps<LocatorSchemaPathType, AllowedPaths>(steps);
40
+ }
41
+
42
+ filter(filter: FilterDefinition<RegistryPath<LocatorSchemaPathType>, AllowedPaths>) {
43
+ this.stepsList.push({ kind: "filter", filter });
44
+ return this;
45
+ }
46
+
47
+ nth(index: IndexSelector) {
48
+ this.stepsList.push({ kind: "index", index });
49
+ return this;
50
+ }
51
+
52
+ describe(description: LocatorDescription) {
53
+ this.descriptionValue = description;
54
+ return this;
55
+ }
56
+
57
+ get definition() {
58
+ return this.definitionValue;
59
+ }
60
+
61
+ get steps() {
62
+ return normalizeSteps<LocatorSchemaPathType, AllowedPaths>(this.stepsList);
63
+ }
64
+
65
+ get description() {
66
+ return this.descriptionValue;
67
+ }
68
+ }
69
+
70
+ export class ReusableLocatorFactory<LocatorSchemaPathType extends string> {
71
+ getByRole(
72
+ role: RoleDefinition["role"],
73
+ options: RoleDefinition["options"],
74
+ ): ReusableLocatorBuilder<LocatorSchemaPathType, RegistryPath<LocatorSchemaPathType>, "role">;
75
+ getByRole(
76
+ role: RoleDefinition["role"],
77
+ ): ReusableLocatorBuilder<LocatorSchemaPathType, RegistryPath<LocatorSchemaPathType>, "role">;
78
+ getByRole(role: RoleDefinition["role"], options?: RoleDefinition["options"]) {
79
+ const definition =
80
+ options !== undefined
81
+ ? ({ type: "role", role, options } as RoleDefinition)
82
+ : ({ type: "role", role } as RoleDefinition);
83
+
84
+ return this.create(definition);
85
+ }
86
+
87
+ getByText(
88
+ text: Parameters<Page["getByText"]>[0],
89
+ options: Parameters<Page["getByText"]>[1],
90
+ ): ReusableLocatorBuilder<LocatorSchemaPathType, RegistryPath<LocatorSchemaPathType>, "text">;
91
+ getByText(
92
+ text: Parameters<Page["getByText"]>[0],
93
+ ): ReusableLocatorBuilder<LocatorSchemaPathType, RegistryPath<LocatorSchemaPathType>, "text">;
94
+ getByText(text: Parameters<Page["getByText"]>[0], options?: Parameters<Page["getByText"]>[1]) {
95
+ const definition =
96
+ options !== undefined
97
+ ? ({ type: "text", text, options } as TextDefinition)
98
+ : ({ type: "text", text } as TextDefinition);
99
+
100
+ return this.create(definition);
101
+ }
102
+
103
+ getByLabel(
104
+ text: Parameters<Page["getByLabel"]>[0],
105
+ options: Parameters<Page["getByLabel"]>[1],
106
+ ): ReusableLocatorBuilder<LocatorSchemaPathType, RegistryPath<LocatorSchemaPathType>, "label">;
107
+ getByLabel(
108
+ text: Parameters<Page["getByLabel"]>[0],
109
+ ): ReusableLocatorBuilder<LocatorSchemaPathType, RegistryPath<LocatorSchemaPathType>, "label">;
110
+ getByLabel(text: Parameters<Page["getByLabel"]>[0], options?: Parameters<Page["getByLabel"]>[1]) {
111
+ const definition =
112
+ options !== undefined
113
+ ? ({ type: "label", text, options } as LabelDefinition)
114
+ : ({ type: "label", text } as LabelDefinition);
115
+
116
+ return this.create(definition);
117
+ }
118
+
119
+ getByPlaceholder(
120
+ text: Parameters<Page["getByPlaceholder"]>[0],
121
+ options: Parameters<Page["getByPlaceholder"]>[1],
122
+ ): ReusableLocatorBuilder<LocatorSchemaPathType, RegistryPath<LocatorSchemaPathType>, "placeholder">;
123
+ getByPlaceholder(
124
+ text: Parameters<Page["getByPlaceholder"]>[0],
125
+ ): ReusableLocatorBuilder<LocatorSchemaPathType, RegistryPath<LocatorSchemaPathType>, "placeholder">;
126
+ getByPlaceholder(text: Parameters<Page["getByPlaceholder"]>[0], options?: Parameters<Page["getByPlaceholder"]>[1]) {
127
+ const definition =
128
+ options !== undefined
129
+ ? ({ type: "placeholder", text, options } as PlaceholderDefinition)
130
+ : ({ type: "placeholder", text } as PlaceholderDefinition);
131
+
132
+ return this.create(definition);
133
+ }
134
+
135
+ getByAltText(
136
+ text: Parameters<Page["getByAltText"]>[0],
137
+ options: Parameters<Page["getByAltText"]>[1],
138
+ ): ReusableLocatorBuilder<LocatorSchemaPathType, RegistryPath<LocatorSchemaPathType>, "altText">;
139
+ getByAltText(
140
+ text: Parameters<Page["getByAltText"]>[0],
141
+ ): ReusableLocatorBuilder<LocatorSchemaPathType, RegistryPath<LocatorSchemaPathType>, "altText">;
142
+ getByAltText(text: Parameters<Page["getByAltText"]>[0], options?: Parameters<Page["getByAltText"]>[1]) {
143
+ const definition =
144
+ options !== undefined
145
+ ? ({ type: "altText", text, options } as AltTextDefinition)
146
+ : ({ type: "altText", text } as AltTextDefinition);
147
+
148
+ return this.create(definition);
149
+ }
150
+
151
+ getByTitle(
152
+ text: Parameters<Page["getByTitle"]>[0],
153
+ options: Parameters<Page["getByTitle"]>[1],
154
+ ): ReusableLocatorBuilder<LocatorSchemaPathType, RegistryPath<LocatorSchemaPathType>, "title">;
155
+ getByTitle(
156
+ text: Parameters<Page["getByTitle"]>[0],
157
+ ): ReusableLocatorBuilder<LocatorSchemaPathType, RegistryPath<LocatorSchemaPathType>, "title">;
158
+ getByTitle(text: Parameters<Page["getByTitle"]>[0], options?: Parameters<Page["getByTitle"]>[1]) {
159
+ const definition =
160
+ options !== undefined
161
+ ? ({ type: "title", text, options } as TitleDefinition)
162
+ : ({ type: "title", text } as TitleDefinition);
163
+
164
+ return this.create(definition);
165
+ }
166
+
167
+ locator(
168
+ selector: Parameters<Page["locator"]>[0],
169
+ options: Parameters<Page["locator"]>[1],
170
+ ): ReusableLocatorBuilder<LocatorSchemaPathType, RegistryPath<LocatorSchemaPathType>, "locator">;
171
+ locator(
172
+ selector: Parameters<Page["locator"]>[0],
173
+ ): ReusableLocatorBuilder<LocatorSchemaPathType, RegistryPath<LocatorSchemaPathType>, "locator">;
174
+ locator(selector: Parameters<Page["locator"]>[0], options?: Parameters<Page["locator"]>[1]) {
175
+ const definition =
176
+ options !== undefined
177
+ ? ({ type: "locator", selector, options } as LocatorDefinition)
178
+ : ({ type: "locator", selector } as LocatorDefinition);
179
+
180
+ return this.create(definition);
181
+ }
182
+
183
+ frameLocator(selector: Parameters<Page["frameLocator"]>[0]) {
184
+ return this.create({ type: "frameLocator", selector });
185
+ }
186
+
187
+ getByTestId(testId: Parameters<Page["getByTestId"]>[0]) {
188
+ return this.create({ type: "testId", testId });
189
+ }
190
+
191
+ getById(id: string | RegExp) {
192
+ return this.create({ type: "id", id: normalizeIdValue(id) as IdDefinition["id"] });
193
+ }
194
+
195
+ private create<Type extends LocatorStrategyDefinition["type"]>(
196
+ definition: Extract<LocatorStrategyDefinition, { type: Type }>,
197
+ ) {
198
+ return new ReusableLocatorBuilder<LocatorSchemaPathType, RegistryPath<LocatorSchemaPathType>, Type>(definition);
199
+ }
200
+ }
@@ -0,0 +1,256 @@
1
+ import type { FrameLocator, Locator, Page } from "@playwright/test";
2
+ // All Unicode characters with White_Space=Yes (UAX #44)
3
+ // Kept in one place so TS and runtime stay conceptually aligned. No trolling in tests allowed.
4
+ export type UnicodeWhitespaceChar =
5
+ | "\u0009" // CHARACTER TABULATION: "\t"
6
+ | "\u000A" // LINE FEED: "\n"
7
+ | "\u000B" // LINE TABULATION: "\v"
8
+ | "\u000C" // FORM FEED: "\f"
9
+ | "\u000D" // CARRIAGE RETURN: "\r"
10
+ | "\u0020" // SPACE: " "
11
+ | "\u0085" // NEXT LINE: ""
12
+ | "\u00A0" // NO-BREAK SPACE: " "
13
+ | "\u1680" // OGHAM SPACE MARK: " "
14
+ | "\u2000" // EN QUAD: " "
15
+ | "\u2001" // EM QUAD: " "
16
+ | "\u2002" // EN SPACE: " "
17
+ | "\u2003" // EM SPACE: " "
18
+ | "\u2004" // THREE-PER-EM SPACE: " "
19
+ | "\u2005" // FOUR-PER-EM SPACE: " "
20
+ | "\u2006" // SIX-PER-EM SPACE: " "
21
+ | "\u2007" // FIGURE SPACE: " "
22
+ | "\u2008" // PUNCTUATION SPACE: " "
23
+ | "\u2009" // THIN SPACE: " "
24
+ | "\u200A" // HAIR SPACE: " "
25
+ | "\u2028" // LINE SEPARATOR: vscode says no
26
+ | "\u2029" // PARAGRAPH SEPARATOR: vscode says no
27
+ | "\u202F" // NARROW NO-BREAK SPACE: " "
28
+ | "\u205F" // MEDIUM MATHEMATICAL SPACE: " "
29
+ | "\u3000"; // IDEOGRAPHIC SPACE: " "
30
+
31
+ export type LocatorSchemaPathError<S extends string, Reason extends string> = [
32
+ "Invalid locator schema path",
33
+ Reason,
34
+ S,
35
+ ];
36
+
37
+ export type LocatorSchemaPathFormat<S extends string> = string extends S
38
+ ? // If S is a wide string (not a literal union), don't try to deeply validate
39
+ S
40
+ : S extends ""
41
+ ? LocatorSchemaPathError<S, "String can't be empty">
42
+ : _LocatorSchemaPathFormat<S, S, true, false>;
43
+
44
+ type _LocatorSchemaPathFormat<
45
+ Original extends string,
46
+ Rest extends string,
47
+ AtStart extends boolean,
48
+ PrevDot extends boolean,
49
+ > = Rest extends ""
50
+ ? PrevDot extends true
51
+ ? LocatorSchemaPathError<Original, "String can't end with '.'">
52
+ : Original
53
+ : Rest extends `${infer C}${infer Tail}`
54
+ ? C extends UnicodeWhitespaceChar
55
+ ? LocatorSchemaPathError<Original, "String can't contain whitespace chars">
56
+ : C extends "."
57
+ ? AtStart extends true
58
+ ? LocatorSchemaPathError<Original, "String can't start with '.'">
59
+ : PrevDot extends true
60
+ ? LocatorSchemaPathError<Original, "String can't contain consecutive '.'">
61
+ : _LocatorSchemaPathFormat<Original, Tail, false, true>
62
+ : _LocatorSchemaPathFormat<Original, Tail, false, false>
63
+ : never;
64
+
65
+ export type LocatorSchemaPathErrors<Paths extends string> = Exclude<LocatorSchemaPathFormat<Paths>, Paths>;
66
+
67
+ export type LocatorSchemaPathValid<Path extends string> = Path extends unknown
68
+ ? LocatorSchemaPathFormat<Path> extends Path
69
+ ? Path
70
+ : never
71
+ : never;
72
+
73
+ export type RegistryPath<LocatorSchemaPathType extends string> = LocatorSchemaPathType &
74
+ LocatorSchemaPathValid<LocatorSchemaPathType>;
75
+
76
+ export type ValidLocatorPath<LocatorSchemaPathType extends string> = LocatorSchemaPathType &
77
+ LocatorSchemaPathValid<LocatorSchemaPathType>;
78
+
79
+ export type ExtractSubPaths<Path extends string> = Path extends `${infer Head}.${infer Tail}`
80
+ ? Head | `${Head}.${ExtractSubPaths<Tail>}`
81
+ : Path;
82
+
83
+ export type LocatorChainPaths<
84
+ LocatorSchemaPathType extends string,
85
+ LocatorSubstring extends LocatorSchemaPathType | undefined,
86
+ > = LocatorSubstring extends string
87
+ ? Extract<LocatorSchemaPathType, LocatorSubstring | ExtractSubPaths<LocatorSubstring>>
88
+ : never;
89
+
90
+ export type LocatorSchemaPathAlias<LocatorSchemaPathType extends string> = LocatorSchemaPathType &
91
+ LocatorSchemaPathValid<LocatorSchemaPathType>;
92
+
93
+ export type RoleDefinition = {
94
+ type: "role";
95
+ role: Parameters<Page["getByRole"]>[0];
96
+ options?: Parameters<Page["getByRole"]>[1];
97
+ };
98
+
99
+ export type TextDefinition = {
100
+ type: "text";
101
+ text: Parameters<Page["getByText"]>[0];
102
+ options?: Parameters<Page["getByText"]>[1];
103
+ };
104
+
105
+ export type LabelDefinition = {
106
+ type: "label";
107
+ text: Parameters<Page["getByLabel"]>[0];
108
+ options?: Parameters<Page["getByLabel"]>[1];
109
+ };
110
+
111
+ export type PlaceholderDefinition = {
112
+ type: "placeholder";
113
+ text: Parameters<Page["getByPlaceholder"]>[0];
114
+ options?: Parameters<Page["getByPlaceholder"]>[1];
115
+ };
116
+
117
+ export type AltTextDefinition = {
118
+ type: "altText";
119
+ text: Parameters<Page["getByAltText"]>[0];
120
+ options?: Parameters<Page["getByAltText"]>[1];
121
+ };
122
+
123
+ export type TitleDefinition = {
124
+ type: "title";
125
+ text: Parameters<Page["getByTitle"]>[0];
126
+ options?: Parameters<Page["getByTitle"]>[1];
127
+ };
128
+
129
+ export type LocatorDefinition = {
130
+ type: "locator";
131
+ selector: Parameters<Page["locator"]>[0];
132
+ options?: Parameters<Page["locator"]>[1];
133
+ };
134
+
135
+ export type FrameLocatorDefinition = {
136
+ type: "frameLocator";
137
+ selector: Parameters<Page["frameLocator"]>[0];
138
+ };
139
+
140
+ export type TestIdDefinition = {
141
+ type: "testId";
142
+ testId: Parameters<Page["getByTestId"]>[0];
143
+ };
144
+
145
+ export type IdDefinition = {
146
+ type: "id";
147
+ id: string | RegExp;
148
+ };
149
+
150
+ export type LocatorStrategyDefinition =
151
+ | RoleDefinition
152
+ | TextDefinition
153
+ | LabelDefinition
154
+ | PlaceholderDefinition
155
+ | AltTextDefinition
156
+ | TitleDefinition
157
+ | LocatorDefinition
158
+ | FrameLocatorDefinition
159
+ | TestIdDefinition
160
+ | IdDefinition;
161
+
162
+ export type LocatorStrategyDefinitionPatch =
163
+ | { type: "role"; role?: RoleDefinition["role"]; options?: RoleDefinition["options"] }
164
+ | { type: "text"; text?: TextDefinition["text"]; options?: TextDefinition["options"] }
165
+ | { type: "label"; text?: LabelDefinition["text"]; options?: LabelDefinition["options"] }
166
+ | { type: "placeholder"; text?: PlaceholderDefinition["text"]; options?: PlaceholderDefinition["options"] }
167
+ | { type: "altText"; text?: AltTextDefinition["text"]; options?: AltTextDefinition["options"] }
168
+ | { type: "title"; text?: TitleDefinition["text"]; options?: TitleDefinition["options"] }
169
+ | { type: "locator"; selector?: LocatorDefinition["selector"]; options?: LocatorDefinition["options"] }
170
+ | { type: "frameLocator"; selector?: FrameLocatorDefinition["selector"] }
171
+ | { type: "testId"; testId?: TestIdDefinition["testId"] }
172
+ | { type: "id"; id?: IdDefinition["id"] };
173
+
174
+ export type PlaywrightFilterDefinition = NonNullable<Parameters<Locator["filter"]>[0]>;
175
+ export type ResolvedFilterDefinition = PlaywrightFilterDefinition;
176
+ export type LocatorDescription = Parameters<Locator["describe"]>[0];
177
+
178
+ export type LocatorStep<
179
+ LocatorSchemaPathType extends string = string,
180
+ AllowedPaths extends string = LocatorSchemaPathAlias<LocatorSchemaPathType>,
181
+ > =
182
+ | { kind: "filter"; filter: FilterDefinition<LocatorSchemaPathType, AllowedPaths> }
183
+ | { kind: "index"; index: IndexSelector | null };
184
+
185
+ export type ReusableLocator<
186
+ LocatorSchemaPathType extends string = string,
187
+ AllowedPaths extends string = LocatorSchemaPathAlias<LocatorSchemaPathType>,
188
+ Type extends LocatorStrategyDefinition["type"] = LocatorStrategyDefinition["type"],
189
+ > = {
190
+ type: Type;
191
+ definition: Extract<LocatorStrategyDefinition, { type: Type }>;
192
+ steps: LocatorStep<LocatorSchemaPathType, AllowedPaths>[];
193
+ description?: LocatorDescription;
194
+ };
195
+
196
+ export type FilterLocatorReference<
197
+ LocatorSchemaPathType extends string,
198
+ AllowedPaths extends string = LocatorSchemaPathAlias<LocatorSchemaPathType>,
199
+ > = Locator | AllowedPaths;
200
+
201
+ export type FilterDefinition<
202
+ LocatorSchemaPathType extends string,
203
+ AllowedPaths extends string = LocatorSchemaPathAlias<LocatorSchemaPathType>,
204
+ > =
205
+ | PlaywrightFilterDefinition
206
+ | (Omit<PlaywrightFilterDefinition, "has" | "hasNot"> & {
207
+ has?: PlaywrightFilterDefinition["has"] | FilterLocatorReference<LocatorSchemaPathType, AllowedPaths>;
208
+ hasNot?: PlaywrightFilterDefinition["hasNot"] | FilterLocatorReference<LocatorSchemaPathType, AllowedPaths>;
209
+ });
210
+
211
+ export type FilterPatch<
212
+ LocatorSchemaPathType extends string,
213
+ AllowedPaths extends string = LocatorSchemaPathAlias<LocatorSchemaPathType>,
214
+ > =
215
+ | FilterDefinition<LocatorSchemaPathType, AllowedPaths>[]
216
+ | {
217
+ append?:
218
+ | FilterDefinition<LocatorSchemaPathType, AllowedPaths>
219
+ | FilterDefinition<LocatorSchemaPathType, AllowedPaths>[];
220
+ replace?:
221
+ | FilterDefinition<LocatorSchemaPathType, AllowedPaths>
222
+ | FilterDefinition<LocatorSchemaPathType, AllowedPaths>[];
223
+ clear?: boolean;
224
+ };
225
+
226
+ export type LocatorBuilderTarget = Page | Locator | FrameLocator;
227
+
228
+ export type LocatorSchemaRecord<
229
+ LocatorSchemaPathType extends string = string,
230
+ AllowedPaths extends string = LocatorSchemaPathAlias<LocatorSchemaPathType>,
231
+ > = {
232
+ locatorSchemaPath: LocatorSchemaPathAlias<LocatorSchemaPathType>;
233
+ definition: LocatorStrategyDefinition;
234
+ steps?: LocatorStep<LocatorSchemaPathType, AllowedPaths>[];
235
+ description?: LocatorDescription;
236
+ };
237
+
238
+ type LocatorUpdateFor<Definition extends LocatorStrategyDefinition> = { type: Definition["type"] } & Partial<
239
+ Omit<Definition, "type">
240
+ >;
241
+
242
+ export type LocatorUpdate =
243
+ | LocatorUpdateFor<RoleDefinition>
244
+ | LocatorUpdateFor<TextDefinition>
245
+ | LocatorUpdateFor<LabelDefinition>
246
+ | LocatorUpdateFor<PlaceholderDefinition>
247
+ | LocatorUpdateFor<AltTextDefinition>
248
+ | LocatorUpdateFor<TitleDefinition>
249
+ | LocatorUpdateFor<LocatorDefinition>
250
+ | LocatorUpdateFor<FrameLocatorDefinition>
251
+ | LocatorUpdateFor<TestIdDefinition>
252
+ | LocatorUpdateFor<IdDefinition>;
253
+
254
+ export type IndexSelector = number | "first" | "last";
255
+
256
+ export type PathIndexMap = Partial<Record<string, IndexSelector | null | undefined>>;