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.
- package/CHANGELOG.md +22 -0
- package/README.md +5 -5
- package/dist/index.d.mts +75 -970
- package/dist/index.d.ts +75 -970
- package/dist/index.js +585 -1872
- package/dist/index.mjs +598 -1880
- package/package.json +9 -11
- package/AGENTS.md +0 -37
- package/docs/v1/BaseApi-explanation.md +0 -63
- package/docs/v1/BasePage-explanation.md +0 -96
- package/docs/v1/LocatorSchema-explanation.md +0 -271
- package/docs/v1/LocatorSchemaPath-explanation.md +0 -165
- package/docs/v1/PlaywrightReportLogger-explanation.md +0 -56
- package/docs/v1/get-locator-methods-explanation.md +0 -250
- package/docs/v1/intro-to-using-pomwright.md +0 -899
- package/docs/v1/sessionStorage-methods-explanation.md +0 -38
- package/docs/v1/tips-folder-structure.md +0 -38
- package/docs/v1-to-v2-migration/bridge-migration-guide.md +0 -159
- package/docs/v1-to-v2-migration/direct-migration-guide.md +0 -238
- package/docs/v1-to-v2-migration/v1-to-v2-comparison.md +0 -547
- package/docs/v2/PageObject.md +0 -293
- package/docs/v2/composing-locator-modules.md +0 -93
- package/docs/v2/locator-registry.md +0 -695
- package/docs/v2/logging.md +0 -168
- package/docs/v2/overview.md +0 -515
- package/docs/v2/session-storage.md +0 -160
- package/index.ts +0 -75
- package/intTestV2/.env +0 -0
- package/intTestV2/fixtures/testApp.fixtures.ts +0 -43
- package/intTestV2/package.json +0 -22
- package/intTestV2/page-object-models/testApp/pages/iframe/iframe.locatorSchema.ts +0 -24
- package/intTestV2/page-object-models/testApp/pages/iframe/iframe.page.ts +0 -17
- package/intTestV2/page-object-models/testApp/pages/testPage.locatorSchema.ts +0 -32
- package/intTestV2/page-object-models/testApp/pages/testPage.page.ts +0 -119
- package/intTestV2/page-object-models/testApp/pages/testPath/[color]/color.locatorSchema.ts +0 -29
- package/intTestV2/page-object-models/testApp/pages/testPath/[color]/color.page.ts +0 -48
- package/intTestV2/page-object-models/testApp/pages/testPath/testPath.locatorSchema.ts +0 -9
- package/intTestV2/page-object-models/testApp/pages/testPath/testPath.page.ts +0 -23
- package/intTestV2/page-object-models/testApp/pages/testfilters/testfilters.locatorSchema.ts +0 -114
- package/intTestV2/page-object-models/testApp/pages/testfilters/testfilters.page.ts +0 -23
- package/intTestV2/page-object-models/testApp/testApp.base.ts +0 -20
- package/intTestV2/playwright.config.ts +0 -54
- package/intTestV2/server.js +0 -216
- package/intTestV2/test-data/staticPage/index.html +0 -280
- package/intTestV2/test-data/staticPage/w3images/avatar2.png +0 -0
- package/intTestV2/test-data/staticPage/w3images/avatar3.png +0 -0
- package/intTestV2/test-data/staticPage/w3images/avatar5.png +0 -0
- package/intTestV2/test-data/staticPage/w3images/avatar6.png +0 -0
- package/intTestV2/test-data/staticPage/w3images/forest.jpg +0 -0
- package/intTestV2/test-data/staticPage/w3images/lights.jpg +0 -0
- package/intTestV2/test-data/staticPage/w3images/mountains.jpg +0 -0
- package/intTestV2/test-data/staticPage/w3images/nature.jpg +0 -0
- package/intTestV2/test-data/staticPage/w3images/snow.jpg +0 -0
- package/intTestV2/tests/locatorRegistry/add/add.describe.spec.ts +0 -54
- package/intTestV2/tests/locatorRegistry/add/add.filter.spec.ts +0 -143
- package/intTestV2/tests/locatorRegistry/add/add.frameLocator.spec.ts +0 -23
- package/intTestV2/tests/locatorRegistry/add/add.get.clone.spec.ts +0 -76
- package/intTestV2/tests/locatorRegistry/add/add.getByAltText.spec.ts +0 -23
- package/intTestV2/tests/locatorRegistry/add/add.getById.spec.ts +0 -45
- package/intTestV2/tests/locatorRegistry/add/add.getByLabel.spec.ts +0 -23
- package/intTestV2/tests/locatorRegistry/add/add.getByPlaceholder.spec.ts +0 -23
- package/intTestV2/tests/locatorRegistry/add/add.getByRole.spec.ts +0 -23
- package/intTestV2/tests/locatorRegistry/add/add.getByTestId.spec.ts +0 -23
- package/intTestV2/tests/locatorRegistry/add/add.getByText.spec.ts +0 -23
- package/intTestV2/tests/locatorRegistry/add/add.getByTitle.spec.ts +0 -23
- package/intTestV2/tests/locatorRegistry/add/add.locator.spec.ts +0 -23
- package/intTestV2/tests/locatorRegistry/add/add.reuseExisting.spec.ts +0 -107
- package/intTestV2/tests/locatorRegistry/add/add.reuseReusable.spec.ts +0 -311
- package/intTestV2/tests/locatorRegistry/add/add.spec.ts +0 -159
- package/intTestV2/tests/locatorRegistry/filter.cycle.spec.ts +0 -39
- package/intTestV2/tests/locatorRegistry/getLocator/getLocator.spec.ts +0 -253
- package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.clearSteps.spec.ts +0 -105
- package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.describe.spec.ts +0 -23
- package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.filter.spec.ts +0 -368
- package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.getLocator.spec.ts +0 -56
- package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.getNestedLocator.spec.ts +0 -175
- package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.nth.spec.ts +0 -60
- package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.remove.spec.ts +0 -32
- package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.replace.spec.ts +0 -24
- package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.spec.ts +0 -110
- package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.update.spec.ts +0 -322
- package/intTestV2/tests/locatorRegistry/getNestedLocator/getNestedLocator.spec.ts +0 -412
- package/intTestV2/tests/locatorRegistry/registry/registry.binding.spec.ts +0 -50
- package/intTestV2/tests/locatorRegistry/validation/validation.locatorSchemaPath.spec.ts +0 -115
- package/intTestV2/tests/locatorRegistry/validation/validation.locatorSchemaPath.typecheck.ts +0 -86
- package/intTestV2/tests/locatorRegistry/validation/validation.sub-path.spec.ts +0 -45
- package/intTestV2/tests/step/step.spec.ts +0 -49
- package/intTestV2/tests/testApp/color.spec.ts +0 -15
- package/intTestV2/tests/testApp/iframe.spec.ts +0 -57
- package/intTestV2/tests/testApp/testFilters.spec.ts +0 -24
- package/intTestV2/tests/testApp/testPage.spec.ts +0 -161
- package/intTestV2/tests/testApp/testPath.spec.ts +0 -18
- package/pack-build.sh +0 -11
- package/pack-test-v2.sh +0 -36
- package/playwright.base.ts +0 -42
- package/skills/README.md +0 -56
- package/skills/pomwright-v1-5-bridge-migration/SKILL.md +0 -40
- package/skills/pomwright-v1-5-bridge-migration/references/call-site-migration.md +0 -178
- package/skills/pomwright-v1-5-bridge-migration/references/schema-translation.md +0 -183
- package/skills/pomwright-v2-migration/SKILL.md +0 -63
- package/skills/pomwright-v2-migration/references/call-site-migration.md +0 -265
- package/skills/pomwright-v2-migration/references/class-migration.md +0 -266
- package/skills/pomwright-v2-migration/references/fixture-and-helpers.md +0 -423
- package/skills/pomwright-v2-migration/references/locator-registration.md +0 -344
- package/srcV2/fixture/base.fixtures.ts +0 -23
- package/srcV2/helpers/navigation.ts +0 -153
- package/srcV2/helpers/playwrightReportLogger.ts +0 -196
- package/srcV2/helpers/sessionStorage.ts +0 -251
- package/srcV2/helpers/stepDecorator.ts +0 -106
- package/srcV2/locators/index.ts +0 -15
- package/srcV2/locators/locatorQueryBuilder.ts +0 -427
- package/srcV2/locators/locatorRegistrationBuilder.ts +0 -558
- package/srcV2/locators/locatorRegistry.ts +0 -583
- package/srcV2/locators/locatorUpdateBuilder.ts +0 -602
- package/srcV2/locators/reusableLocatorBuilder.ts +0 -200
- package/srcV2/locators/types.ts +0 -256
- package/srcV2/locators/utils.ts +0 -309
- package/srcV2/locators/v1SchemaTranslator.ts +0 -178
- package/srcV2/pageObject.ts +0 -105
|
@@ -1,602 +0,0 @@
|
|
|
1
|
-
import type { Page } from "@playwright/test";
|
|
2
|
-
import type { LocatorQueryBuilder } from "./locatorQueryBuilder";
|
|
3
|
-
import type {
|
|
4
|
-
LocatorChainPaths,
|
|
5
|
-
LocatorStrategyDefinition,
|
|
6
|
-
LocatorUpdate,
|
|
7
|
-
RegistryPath,
|
|
8
|
-
RoleDefinition,
|
|
9
|
-
} from "./types";
|
|
10
|
-
import { normalizeIdValue } from "./utils";
|
|
11
|
-
|
|
12
|
-
const parseUpdateArguments = <Primary, OptionsType>(
|
|
13
|
-
primaryOrOptions?: Primary | OptionsType,
|
|
14
|
-
options?: OptionsType,
|
|
15
|
-
optionsProvided?: boolean,
|
|
16
|
-
) => {
|
|
17
|
-
let primary: Primary | undefined;
|
|
18
|
-
let parsedOptions: OptionsType | undefined;
|
|
19
|
-
let hasOptions = optionsProvided ?? false;
|
|
20
|
-
|
|
21
|
-
if (options !== undefined) {
|
|
22
|
-
parsedOptions = options;
|
|
23
|
-
hasOptions = true;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (primaryOrOptions !== undefined) {
|
|
27
|
-
const treatAsOptions =
|
|
28
|
-
!hasOptions &&
|
|
29
|
-
options === undefined &&
|
|
30
|
-
typeof primaryOrOptions === "object" &&
|
|
31
|
-
!(primaryOrOptions instanceof RegExp);
|
|
32
|
-
|
|
33
|
-
if (treatAsOptions) {
|
|
34
|
-
parsedOptions = primaryOrOptions as OptionsType;
|
|
35
|
-
hasOptions = true;
|
|
36
|
-
} else {
|
|
37
|
-
primary = primaryOrOptions as Primary;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return { primary, options: parsedOptions, hasOptions };
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
const mergeOptions = <OptionsType>(
|
|
45
|
-
currentOptions: OptionsType | undefined,
|
|
46
|
-
updates: { options?: OptionsType } | undefined,
|
|
47
|
-
) => {
|
|
48
|
-
if (updates && "options" in updates) {
|
|
49
|
-
const updateOptions = updates.options;
|
|
50
|
-
if (updateOptions && typeof updateOptions === "object") {
|
|
51
|
-
return {
|
|
52
|
-
...(typeof currentOptions === "object" && currentOptions !== null ? currentOptions : {}),
|
|
53
|
-
...updateOptions,
|
|
54
|
-
} as OptionsType;
|
|
55
|
-
}
|
|
56
|
-
return updateOptions as OptionsType;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
return currentOptions as OptionsType;
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
type UpdateArgsWithOptions<Primary, Options> = [] | [Primary] | [Options] | [Primary, Options];
|
|
63
|
-
|
|
64
|
-
type UpdateArgsWithoutOptions<Primary> = [] | [Primary];
|
|
65
|
-
|
|
66
|
-
const mergeLocatorDefinition = (
|
|
67
|
-
current: LocatorStrategyDefinition,
|
|
68
|
-
updates: LocatorUpdate,
|
|
69
|
-
path: string,
|
|
70
|
-
preferredSource?: LocatorStrategyDefinition,
|
|
71
|
-
baseline?: LocatorStrategyDefinition,
|
|
72
|
-
): LocatorStrategyDefinition => {
|
|
73
|
-
if (!updates || typeof updates !== "object" || !("type" in updates)) {
|
|
74
|
-
throw new Error(`Locator update for "${path}" requires a "type" property.`);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const source = <TType extends LocatorStrategyDefinition["type"]>(targetType: TType) => {
|
|
78
|
-
if (current.type === targetType) {
|
|
79
|
-
return current as Extract<LocatorStrategyDefinition, { type: TType }>;
|
|
80
|
-
}
|
|
81
|
-
if (preferredSource?.type === targetType) {
|
|
82
|
-
return preferredSource as Extract<LocatorStrategyDefinition, { type: TType }>;
|
|
83
|
-
}
|
|
84
|
-
if (baseline?.type === targetType) {
|
|
85
|
-
return baseline as Extract<LocatorStrategyDefinition, { type: TType }>;
|
|
86
|
-
}
|
|
87
|
-
return undefined;
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
switch (updates.type) {
|
|
91
|
-
case "role": {
|
|
92
|
-
const roleSource = source("role");
|
|
93
|
-
const role = updates.role ?? roleSource?.role;
|
|
94
|
-
if (role === undefined) {
|
|
95
|
-
throw new Error(`Locator update for "${path}" of type "role" requires a "role" value.`);
|
|
96
|
-
}
|
|
97
|
-
const options = mergeOptions(roleSource?.options, updates);
|
|
98
|
-
return options !== undefined
|
|
99
|
-
? ({ type: "role", role, options } as RoleDefinition)
|
|
100
|
-
: ({ type: "role", role } as RoleDefinition);
|
|
101
|
-
}
|
|
102
|
-
case "text": {
|
|
103
|
-
const textSource = source("text");
|
|
104
|
-
const text = updates.text ?? textSource?.text;
|
|
105
|
-
if (text === undefined) {
|
|
106
|
-
throw new Error(`Locator update for "${path}" of type "text" requires a "text" value.`);
|
|
107
|
-
}
|
|
108
|
-
const options = mergeOptions(textSource?.options, updates);
|
|
109
|
-
return options !== undefined
|
|
110
|
-
? ({ type: "text", text, options } as LocatorStrategyDefinition)
|
|
111
|
-
: ({ type: "text", text } as LocatorStrategyDefinition);
|
|
112
|
-
}
|
|
113
|
-
case "label": {
|
|
114
|
-
const textSource = source("label");
|
|
115
|
-
const text = updates.text ?? textSource?.text;
|
|
116
|
-
if (text === undefined) {
|
|
117
|
-
throw new Error(`Locator update for "${path}" of type "label" requires a "text" value.`);
|
|
118
|
-
}
|
|
119
|
-
const options = mergeOptions(textSource?.options, updates);
|
|
120
|
-
return options !== undefined
|
|
121
|
-
? ({ type: "label", text, options } as LocatorStrategyDefinition)
|
|
122
|
-
: ({ type: "label", text } as LocatorStrategyDefinition);
|
|
123
|
-
}
|
|
124
|
-
case "placeholder": {
|
|
125
|
-
const textSource = source("placeholder");
|
|
126
|
-
const text = updates.text ?? textSource?.text;
|
|
127
|
-
if (text === undefined) {
|
|
128
|
-
throw new Error(`Locator update for "${path}" of type "placeholder" requires a "text" value.`);
|
|
129
|
-
}
|
|
130
|
-
const options = mergeOptions(textSource?.options, updates);
|
|
131
|
-
return options !== undefined
|
|
132
|
-
? ({ type: "placeholder", text, options } as LocatorStrategyDefinition)
|
|
133
|
-
: ({ type: "placeholder", text } as LocatorStrategyDefinition);
|
|
134
|
-
}
|
|
135
|
-
case "altText": {
|
|
136
|
-
const textSource = source("altText");
|
|
137
|
-
const text = updates.text ?? textSource?.text;
|
|
138
|
-
if (text === undefined) {
|
|
139
|
-
throw new Error(`Locator update for "${path}" of type "altText" requires a "text" value.`);
|
|
140
|
-
}
|
|
141
|
-
const options = mergeOptions(textSource?.options, updates);
|
|
142
|
-
return options !== undefined
|
|
143
|
-
? ({ type: "altText", text, options } as LocatorStrategyDefinition)
|
|
144
|
-
: ({ type: "altText", text } as LocatorStrategyDefinition);
|
|
145
|
-
}
|
|
146
|
-
case "title": {
|
|
147
|
-
const textSource = source("title");
|
|
148
|
-
const text = updates.text ?? textSource?.text;
|
|
149
|
-
if (text === undefined) {
|
|
150
|
-
throw new Error(`Locator update for "${path}" of type "title" requires a "text" value.`);
|
|
151
|
-
}
|
|
152
|
-
const options = mergeOptions(textSource?.options, updates);
|
|
153
|
-
return options !== undefined
|
|
154
|
-
? ({ type: "title", text, options } as LocatorStrategyDefinition)
|
|
155
|
-
: ({ type: "title", text } as LocatorStrategyDefinition);
|
|
156
|
-
}
|
|
157
|
-
case "locator": {
|
|
158
|
-
const selectorSource = source("locator");
|
|
159
|
-
const selector = updates.selector ?? selectorSource?.selector;
|
|
160
|
-
if (selector === undefined) {
|
|
161
|
-
throw new Error(`Locator update for "${path}" of type "locator" requires a "selector" value.`);
|
|
162
|
-
}
|
|
163
|
-
const options = mergeOptions(selectorSource?.options, updates);
|
|
164
|
-
return options !== undefined
|
|
165
|
-
? ({ type: "locator", selector, options } as LocatorStrategyDefinition)
|
|
166
|
-
: ({ type: "locator", selector } as LocatorStrategyDefinition);
|
|
167
|
-
}
|
|
168
|
-
case "frameLocator": {
|
|
169
|
-
const selectorSource = source("frameLocator");
|
|
170
|
-
const selector = updates.selector ?? selectorSource?.selector;
|
|
171
|
-
if (selector === undefined) {
|
|
172
|
-
throw new Error(`Locator update for "${path}" of type "frameLocator" requires a "selector" value.`);
|
|
173
|
-
}
|
|
174
|
-
return { type: "frameLocator", selector } as LocatorStrategyDefinition;
|
|
175
|
-
}
|
|
176
|
-
case "testId": {
|
|
177
|
-
const testIdSource = source("testId");
|
|
178
|
-
const testId = updates.testId ?? testIdSource?.testId;
|
|
179
|
-
if (testId === undefined) {
|
|
180
|
-
throw new Error(`Locator update for "${path}" of type "testId" requires a "testId" value.`);
|
|
181
|
-
}
|
|
182
|
-
return { type: "testId", testId } as LocatorStrategyDefinition;
|
|
183
|
-
}
|
|
184
|
-
case "id": {
|
|
185
|
-
const idSource = source("id");
|
|
186
|
-
const rawId = updates.id ?? idSource?.id;
|
|
187
|
-
const id = normalizeIdValue(rawId);
|
|
188
|
-
if (id === undefined) {
|
|
189
|
-
throw new Error(`Locator update for "${path}" of type "id" requires an "id" value.`);
|
|
190
|
-
}
|
|
191
|
-
return { type: "id", id } as LocatorStrategyDefinition;
|
|
192
|
-
}
|
|
193
|
-
default: {
|
|
194
|
-
const exhaustive: never = updates;
|
|
195
|
-
return exhaustive;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
const buildReplacementDefinition = (updates: LocatorUpdate, path: string): LocatorStrategyDefinition => {
|
|
201
|
-
if (!updates || typeof updates !== "object" || !("type" in updates)) {
|
|
202
|
-
throw new Error(`Locator replace for "${path}" requires a "type" property.`);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
switch (updates.type) {
|
|
206
|
-
case "role": {
|
|
207
|
-
const { role, options } = updates;
|
|
208
|
-
if (role === undefined) {
|
|
209
|
-
throw new Error(`Locator replace for "${path}" of type "role" requires a "role" value.`);
|
|
210
|
-
}
|
|
211
|
-
return options !== undefined
|
|
212
|
-
? ({ type: "role", role, options } as RoleDefinition)
|
|
213
|
-
: ({ type: "role", role } as RoleDefinition);
|
|
214
|
-
}
|
|
215
|
-
case "text": {
|
|
216
|
-
const { text, options } = updates;
|
|
217
|
-
if (text === undefined) {
|
|
218
|
-
throw new Error(`Locator replace for "${path}" of type "text" requires a "text" value.`);
|
|
219
|
-
}
|
|
220
|
-
return options !== undefined
|
|
221
|
-
? ({ type: "text", text, options } as LocatorStrategyDefinition)
|
|
222
|
-
: ({ type: "text", text } as LocatorStrategyDefinition);
|
|
223
|
-
}
|
|
224
|
-
case "label": {
|
|
225
|
-
const { text, options } = updates;
|
|
226
|
-
if (text === undefined) {
|
|
227
|
-
throw new Error(`Locator replace for "${path}" of type "label" requires a "text" value.`);
|
|
228
|
-
}
|
|
229
|
-
return options !== undefined
|
|
230
|
-
? ({ type: "label", text, options } as LocatorStrategyDefinition)
|
|
231
|
-
: ({ type: "label", text } as LocatorStrategyDefinition);
|
|
232
|
-
}
|
|
233
|
-
case "placeholder": {
|
|
234
|
-
const { text, options } = updates;
|
|
235
|
-
if (text === undefined) {
|
|
236
|
-
throw new Error(`Locator replace for "${path}" of type "placeholder" requires a "text" value.`);
|
|
237
|
-
}
|
|
238
|
-
return options !== undefined
|
|
239
|
-
? ({ type: "placeholder", text, options } as LocatorStrategyDefinition)
|
|
240
|
-
: ({ type: "placeholder", text } as LocatorStrategyDefinition);
|
|
241
|
-
}
|
|
242
|
-
case "altText": {
|
|
243
|
-
const { text, options } = updates;
|
|
244
|
-
if (text === undefined) {
|
|
245
|
-
throw new Error(`Locator replace for "${path}" of type "altText" requires a "text" value.`);
|
|
246
|
-
}
|
|
247
|
-
return options !== undefined
|
|
248
|
-
? ({ type: "altText", text, options } as LocatorStrategyDefinition)
|
|
249
|
-
: ({ type: "altText", text } as LocatorStrategyDefinition);
|
|
250
|
-
}
|
|
251
|
-
case "title": {
|
|
252
|
-
const { text, options } = updates;
|
|
253
|
-
if (text === undefined) {
|
|
254
|
-
throw new Error(`Locator replace for "${path}" of type "title" requires a "text" value.`);
|
|
255
|
-
}
|
|
256
|
-
return options !== undefined
|
|
257
|
-
? ({ type: "title", text, options } as LocatorStrategyDefinition)
|
|
258
|
-
: ({ type: "title", text } as LocatorStrategyDefinition);
|
|
259
|
-
}
|
|
260
|
-
case "locator": {
|
|
261
|
-
const { selector, options } = updates;
|
|
262
|
-
if (selector === undefined) {
|
|
263
|
-
throw new Error(`Locator replace for "${path}" of type "locator" requires a "selector" value.`);
|
|
264
|
-
}
|
|
265
|
-
return options !== undefined
|
|
266
|
-
? ({ type: "locator", selector, options } as LocatorStrategyDefinition)
|
|
267
|
-
: ({ type: "locator", selector } as LocatorStrategyDefinition);
|
|
268
|
-
}
|
|
269
|
-
case "frameLocator": {
|
|
270
|
-
const { selector } = updates;
|
|
271
|
-
if (selector === undefined) {
|
|
272
|
-
throw new Error(`Locator replace for "${path}" of type "frameLocator" requires a "selector" value.`);
|
|
273
|
-
}
|
|
274
|
-
return { type: "frameLocator", selector } as LocatorStrategyDefinition;
|
|
275
|
-
}
|
|
276
|
-
case "testId": {
|
|
277
|
-
const { testId } = updates;
|
|
278
|
-
if (testId === undefined) {
|
|
279
|
-
throw new Error(`Locator replace for "${path}" of type "testId" requires a "testId" value.`);
|
|
280
|
-
}
|
|
281
|
-
return { type: "testId", testId } as LocatorStrategyDefinition;
|
|
282
|
-
}
|
|
283
|
-
case "id": {
|
|
284
|
-
const rawId = updates.id;
|
|
285
|
-
const id = normalizeIdValue(rawId);
|
|
286
|
-
if (id === undefined) {
|
|
287
|
-
throw new Error(`Locator replace for "${path}" of type "id" requires an "id" value.`);
|
|
288
|
-
}
|
|
289
|
-
return { type: "id", id } as LocatorStrategyDefinition;
|
|
290
|
-
}
|
|
291
|
-
default: {
|
|
292
|
-
const exhaustive: never = updates;
|
|
293
|
-
return exhaustive;
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
};
|
|
297
|
-
export class LocatorUpdateBuilder<
|
|
298
|
-
LocatorSchemaPathType extends string,
|
|
299
|
-
LocatorSubstring extends RegistryPath<LocatorSchemaPathType>,
|
|
300
|
-
SubPath extends LocatorChainPaths<RegistryPath<LocatorSchemaPathType>, LocatorSubstring>,
|
|
301
|
-
> {
|
|
302
|
-
constructor(
|
|
303
|
-
private readonly parent: LocatorQueryBuilder<LocatorSchemaPathType, LocatorSubstring>,
|
|
304
|
-
private readonly subPath: SubPath,
|
|
305
|
-
private readonly mode: "update" | "replace" = "update",
|
|
306
|
-
) {}
|
|
307
|
-
|
|
308
|
-
/**
|
|
309
|
-
* Defines or patches a `getByRole` locator strategy for the target subpath. In `update` mode the
|
|
310
|
-
* `role` and `options` arguments are optional (PATCH semantics); in `replace` mode they follow
|
|
311
|
-
* Playwright requirements (POST semantics) and `role` is required.
|
|
312
|
-
*
|
|
313
|
-
* @example
|
|
314
|
-
* ```ts
|
|
315
|
-
* getLocatorSchema("form.button")
|
|
316
|
-
* .update("form.button")
|
|
317
|
-
* .getByRole({ name: "Save" })
|
|
318
|
-
* .getNestedLocator();
|
|
319
|
-
* ```
|
|
320
|
-
*/
|
|
321
|
-
getByRole(...args: UpdateArgsWithOptions<RoleDefinition["role"], RoleDefinition["options"]>) {
|
|
322
|
-
const [roleOrOptions, options] = args;
|
|
323
|
-
const {
|
|
324
|
-
primary: role,
|
|
325
|
-
options: parsedOptions,
|
|
326
|
-
hasOptions,
|
|
327
|
-
} = parseUpdateArguments<RoleDefinition["role"], RoleDefinition["options"]>(
|
|
328
|
-
roleOrOptions,
|
|
329
|
-
options,
|
|
330
|
-
args.length >= 2,
|
|
331
|
-
);
|
|
332
|
-
|
|
333
|
-
const definition: LocatorUpdate = {
|
|
334
|
-
type: "role",
|
|
335
|
-
...(role !== undefined ? { role } : {}),
|
|
336
|
-
...(hasOptions ? { options: parsedOptions } : {}),
|
|
337
|
-
};
|
|
338
|
-
|
|
339
|
-
return this.commit(definition);
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
/**
|
|
343
|
-
* Defines or patches a `getByText` locator strategy for the target subpath. In `update` mode,
|
|
344
|
-
* text/options are optional; in `replace` mode text is required.
|
|
345
|
-
*
|
|
346
|
-
* @example
|
|
347
|
-
* ```ts
|
|
348
|
-
* getLocatorSchema("banner.message")
|
|
349
|
-
* .replace("banner.message")
|
|
350
|
-
* .getByText(/Updated/, { exact: false })
|
|
351
|
-
* .getNestedLocator();
|
|
352
|
-
* ```
|
|
353
|
-
*/
|
|
354
|
-
getByText(...args: UpdateArgsWithOptions<Parameters<Page["getByText"]>[0], Parameters<Page["getByText"]>[1]>) {
|
|
355
|
-
const [textOrOptions, options] = args;
|
|
356
|
-
const {
|
|
357
|
-
primary: text,
|
|
358
|
-
options: parsedOptions,
|
|
359
|
-
hasOptions,
|
|
360
|
-
} = parseUpdateArguments<Parameters<Page["getByText"]>[0], Parameters<Page["getByText"]>[1]>(
|
|
361
|
-
textOrOptions,
|
|
362
|
-
options,
|
|
363
|
-
args.length >= 2,
|
|
364
|
-
);
|
|
365
|
-
|
|
366
|
-
const definition: LocatorUpdate = {
|
|
367
|
-
type: "text",
|
|
368
|
-
...(text !== undefined ? { text } : {}),
|
|
369
|
-
...(hasOptions ? { options: parsedOptions } : {}),
|
|
370
|
-
};
|
|
371
|
-
|
|
372
|
-
return this.commit(definition);
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
/**
|
|
376
|
-
* Defines or patches a `getByLabel` locator strategy for the target subpath. In `update` mode the
|
|
377
|
-
* label text/options are optional; in `replace` mode text is required.
|
|
378
|
-
*
|
|
379
|
-
* @example
|
|
380
|
-
* ```ts
|
|
381
|
-
* getLocatorSchema("form.email").update("form.email").getByLabel({ exact: true }).getNestedLocator();
|
|
382
|
-
* ```
|
|
383
|
-
*/
|
|
384
|
-
getByLabel(...args: UpdateArgsWithOptions<Parameters<Page["getByLabel"]>[0], Parameters<Page["getByLabel"]>[1]>) {
|
|
385
|
-
const [textOrOptions, options] = args;
|
|
386
|
-
const {
|
|
387
|
-
primary: text,
|
|
388
|
-
options: parsedOptions,
|
|
389
|
-
hasOptions,
|
|
390
|
-
} = parseUpdateArguments<Parameters<Page["getByLabel"]>[0], Parameters<Page["getByLabel"]>[1]>(
|
|
391
|
-
textOrOptions,
|
|
392
|
-
options,
|
|
393
|
-
args.length >= 2,
|
|
394
|
-
);
|
|
395
|
-
|
|
396
|
-
const definition: LocatorUpdate = {
|
|
397
|
-
type: "label",
|
|
398
|
-
...(text !== undefined ? { text } : {}),
|
|
399
|
-
...(hasOptions ? { options: parsedOptions } : {}),
|
|
400
|
-
};
|
|
401
|
-
|
|
402
|
-
return this.commit(definition);
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
/**
|
|
406
|
-
* Defines or patches a `getByPlaceholder` locator strategy for the target subpath. In `update`
|
|
407
|
-
* mode text/options are optional; in `replace` mode text is required.
|
|
408
|
-
*
|
|
409
|
-
* @example
|
|
410
|
-
* ```ts
|
|
411
|
-
* getLocatorSchema("form.search").update("form.search").getByPlaceholder({ exact: true }).getNestedLocator();
|
|
412
|
-
* ```
|
|
413
|
-
*/
|
|
414
|
-
getByPlaceholder(
|
|
415
|
-
...args: UpdateArgsWithOptions<Parameters<Page["getByPlaceholder"]>[0], Parameters<Page["getByPlaceholder"]>[1]>
|
|
416
|
-
) {
|
|
417
|
-
const [textOrOptions, options] = args;
|
|
418
|
-
const {
|
|
419
|
-
primary: text,
|
|
420
|
-
options: parsedOptions,
|
|
421
|
-
hasOptions,
|
|
422
|
-
} = parseUpdateArguments<Parameters<Page["getByPlaceholder"]>[0], Parameters<Page["getByPlaceholder"]>[1]>(
|
|
423
|
-
textOrOptions,
|
|
424
|
-
options,
|
|
425
|
-
args.length >= 2,
|
|
426
|
-
);
|
|
427
|
-
|
|
428
|
-
const definition: LocatorUpdate = {
|
|
429
|
-
type: "placeholder",
|
|
430
|
-
...(text !== undefined ? { text } : {}),
|
|
431
|
-
...(hasOptions ? { options: parsedOptions } : {}),
|
|
432
|
-
};
|
|
433
|
-
|
|
434
|
-
return this.commit(definition);
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
/**
|
|
438
|
-
* Defines or patches a `getByAltText` locator strategy for the target subpath. In `update` mode
|
|
439
|
-
* text/options are optional; in `replace` mode text is required.
|
|
440
|
-
*
|
|
441
|
-
* @example
|
|
442
|
-
* ```ts
|
|
443
|
-
* getLocatorSchema("image.logo").replace("image.logo").getByAltText("Logo").getNestedLocator();
|
|
444
|
-
* ```
|
|
445
|
-
*/
|
|
446
|
-
getByAltText(
|
|
447
|
-
...args: UpdateArgsWithOptions<Parameters<Page["getByAltText"]>[0], Parameters<Page["getByAltText"]>[1]>
|
|
448
|
-
) {
|
|
449
|
-
const [textOrOptions, options] = args;
|
|
450
|
-
const {
|
|
451
|
-
primary: text,
|
|
452
|
-
options: parsedOptions,
|
|
453
|
-
hasOptions,
|
|
454
|
-
} = parseUpdateArguments<Parameters<Page["getByAltText"]>[0], Parameters<Page["getByAltText"]>[1]>(
|
|
455
|
-
textOrOptions,
|
|
456
|
-
options,
|
|
457
|
-
args.length >= 2,
|
|
458
|
-
);
|
|
459
|
-
|
|
460
|
-
const definition: LocatorUpdate = {
|
|
461
|
-
type: "altText",
|
|
462
|
-
...(text !== undefined ? { text } : {}),
|
|
463
|
-
...(hasOptions ? { options: parsedOptions } : {}),
|
|
464
|
-
};
|
|
465
|
-
|
|
466
|
-
return this.commit(definition);
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
/**
|
|
470
|
-
* Defines or patches a `getByTitle` locator strategy for the target subpath. In `update` mode
|
|
471
|
-
* text/options are optional; in `replace` mode text is required.
|
|
472
|
-
*
|
|
473
|
-
* @example
|
|
474
|
-
* ```ts
|
|
475
|
-
* getLocatorSchema("icon.info").update("icon.info").getByTitle({ exact: true }).getNestedLocator();
|
|
476
|
-
* ```
|
|
477
|
-
*/
|
|
478
|
-
getByTitle(...args: UpdateArgsWithOptions<Parameters<Page["getByTitle"]>[0], Parameters<Page["getByTitle"]>[1]>) {
|
|
479
|
-
const [textOrOptions, options] = args;
|
|
480
|
-
const {
|
|
481
|
-
primary: text,
|
|
482
|
-
options: parsedOptions,
|
|
483
|
-
hasOptions,
|
|
484
|
-
} = parseUpdateArguments<Parameters<Page["getByTitle"]>[0], Parameters<Page["getByTitle"]>[1]>(
|
|
485
|
-
textOrOptions,
|
|
486
|
-
options,
|
|
487
|
-
args.length >= 2,
|
|
488
|
-
);
|
|
489
|
-
|
|
490
|
-
const definition: LocatorUpdate = {
|
|
491
|
-
type: "title",
|
|
492
|
-
...(text !== undefined ? { text } : {}),
|
|
493
|
-
...(hasOptions ? { options: parsedOptions } : {}),
|
|
494
|
-
};
|
|
495
|
-
|
|
496
|
-
return this.commit(definition);
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
/**
|
|
500
|
-
* Defines or patches a `locator` strategy for the target subpath. In `update` mode selector and
|
|
501
|
-
* options are optional and merge with the existing definition; in `replace` mode selector is
|
|
502
|
-
* required.
|
|
503
|
-
*
|
|
504
|
-
* @example
|
|
505
|
-
* ```ts
|
|
506
|
-
* getLocatorSchema("list.items")
|
|
507
|
-
* .replace("list.items")
|
|
508
|
-
* .locator("ul > li", { hasText: /Row/ })
|
|
509
|
-
* .getNestedLocator();
|
|
510
|
-
* ```
|
|
511
|
-
*/
|
|
512
|
-
locator(...args: UpdateArgsWithOptions<Parameters<Page["locator"]>[0], Parameters<Page["locator"]>[1]>) {
|
|
513
|
-
const [selectorOrOptions, options] = args;
|
|
514
|
-
const {
|
|
515
|
-
primary: selector,
|
|
516
|
-
options: parsedOptions,
|
|
517
|
-
hasOptions,
|
|
518
|
-
} = parseUpdateArguments<Parameters<Page["locator"]>[0], Parameters<Page["locator"]>[1]>(
|
|
519
|
-
selectorOrOptions,
|
|
520
|
-
options,
|
|
521
|
-
args.length >= 2,
|
|
522
|
-
);
|
|
523
|
-
|
|
524
|
-
const definition: LocatorUpdate = {
|
|
525
|
-
type: "locator",
|
|
526
|
-
...(selector !== undefined ? { selector } : {}),
|
|
527
|
-
...(hasOptions ? { options: parsedOptions } : {}),
|
|
528
|
-
};
|
|
529
|
-
|
|
530
|
-
return this.commit(definition);
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
/**
|
|
534
|
-
* Defines or patches a `frameLocator` strategy for the target subpath. In `update` mode the
|
|
535
|
-
* selector is optional and, when omitted, inherits the existing selector; in `replace` mode the
|
|
536
|
-
* selector is required.
|
|
537
|
-
*
|
|
538
|
-
* @example
|
|
539
|
-
* ```ts
|
|
540
|
-
* getLocatorSchema("frame.login").replace("frame.login").frameLocator("iframe.auth").getNestedLocator();
|
|
541
|
-
* ```
|
|
542
|
-
*/
|
|
543
|
-
frameLocator(...args: UpdateArgsWithoutOptions<Parameters<Page["frameLocator"]>[0]>) {
|
|
544
|
-
const [selector] = args;
|
|
545
|
-
|
|
546
|
-
const definition: LocatorUpdate = {
|
|
547
|
-
type: "frameLocator",
|
|
548
|
-
...(selector !== undefined ? { selector } : {}),
|
|
549
|
-
};
|
|
550
|
-
|
|
551
|
-
return this.commit(definition);
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
/**
|
|
555
|
-
* Defines or patches a `getByTestId` locator strategy for the target subpath. In `update` mode
|
|
556
|
-
* `testId` is optional and merges with existing options; in `replace` mode it is required.
|
|
557
|
-
*
|
|
558
|
-
* @example
|
|
559
|
-
* ```ts
|
|
560
|
-
* getLocatorSchema("card.title").update("card.title").getByTestId().getNestedLocator();
|
|
561
|
-
* ```
|
|
562
|
-
*/
|
|
563
|
-
getByTestId(...args: UpdateArgsWithoutOptions<Parameters<Page["getByTestId"]>[0]>) {
|
|
564
|
-
const [testId] = args;
|
|
565
|
-
|
|
566
|
-
const definition: LocatorUpdate = {
|
|
567
|
-
type: "testId",
|
|
568
|
-
...(testId !== undefined ? { testId } : {}),
|
|
569
|
-
};
|
|
570
|
-
|
|
571
|
-
return this.commit(definition);
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
/**
|
|
575
|
-
* Defines or patches an `id` locator strategy for the target subpath. In `update` mode the id is
|
|
576
|
-
* optional and will be normalized if provided; in `replace` mode the id is required.
|
|
577
|
-
*
|
|
578
|
-
* @example
|
|
579
|
-
* ```ts
|
|
580
|
-
* getLocatorSchema("modal.close").update("modal.close").getById().getNestedLocator();
|
|
581
|
-
* ```
|
|
582
|
-
*/
|
|
583
|
-
getById(...args: UpdateArgsWithoutOptions<string | RegExp>) {
|
|
584
|
-
const [idValue] = args;
|
|
585
|
-
const id = idValue !== undefined ? normalizeIdValue(idValue) : undefined;
|
|
586
|
-
|
|
587
|
-
const definition: LocatorUpdate = {
|
|
588
|
-
type: "id",
|
|
589
|
-
...(id !== undefined ? { id } : {}),
|
|
590
|
-
};
|
|
591
|
-
|
|
592
|
-
return this.commit(definition);
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
private commit(definition: LocatorUpdate) {
|
|
596
|
-
return this.mode === "replace"
|
|
597
|
-
? this.parent.applyReplacement(this.subPath, definition)
|
|
598
|
-
: this.parent.applyUpdate(this.subPath, definition);
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
export { buildReplacementDefinition, mergeLocatorDefinition };
|