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.
- package/CHANGELOG.md +36 -0
- package/README.md +5 -5
- package/dist/index.d.mts +91 -989
- package/dist/index.d.ts +91 -989
- package/dist/index.js +627 -1887
- package/dist/index.mjs +633 -1888
- 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 -693
- 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.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 -66
- 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.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 -541
- 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,368 +0,0 @@
|
|
|
1
|
-
import { expect, test } from "@fixtures-v2/testApp.fixtures";
|
|
2
|
-
import type { Page } from "@playwright/test";
|
|
3
|
-
import {
|
|
4
|
-
type FilterDefinition,
|
|
5
|
-
LocatorRegistryInternal,
|
|
6
|
-
type LocatorStrategyDefinition,
|
|
7
|
-
} from "../../../../srcV2/locators";
|
|
8
|
-
|
|
9
|
-
test("filter adds an additional filter per sub-path", async ({ testFilters }) => {
|
|
10
|
-
const filtered = testFilters
|
|
11
|
-
.getLocatorSchema("body.section")
|
|
12
|
-
.filter("body", { hasText: "Playground" })
|
|
13
|
-
.filter("body.section", { hasText: "Primary Colors Playground" })
|
|
14
|
-
.getNestedLocator();
|
|
15
|
-
|
|
16
|
-
expect(`${filtered}`).toEqual(
|
|
17
|
-
"locator('body').filter({ hasText: 'Playground' }).locator('section').filter({ hasText: 'Primary Colors Playground' })",
|
|
18
|
-
);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
test("filter with has locator", async ({ testFilters }) => {
|
|
22
|
-
const heading = testFilters.getLocator("body.section.heading");
|
|
23
|
-
|
|
24
|
-
const filtered = testFilters
|
|
25
|
-
.getLocatorSchema("fictional.filter@hasNotText")
|
|
26
|
-
.filter("fictional.filter@hasNotText", { has: heading })
|
|
27
|
-
.getNestedLocator();
|
|
28
|
-
|
|
29
|
-
expect(`${filtered}`).toEqual(
|
|
30
|
-
"getByRole('button').filter({ hasNotText: 'hasNotText' }).filter({ has: getByRole('heading', { level: 2 }) })",
|
|
31
|
-
);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
test("filter chaining is non-destructive", async ({ testFilters }) => {
|
|
35
|
-
const base = testFilters.getNestedLocator("body.section");
|
|
36
|
-
|
|
37
|
-
const filtered = testFilters
|
|
38
|
-
.getLocatorSchema("body.section")
|
|
39
|
-
.filter("body.section", { hasText: /Playground/i })
|
|
40
|
-
.getNestedLocator();
|
|
41
|
-
|
|
42
|
-
expect(`${filtered}`).toEqual("locator('body').locator('section').filter({ hasText: /Playground/i })");
|
|
43
|
-
|
|
44
|
-
const unchanged = testFilters.getNestedLocator("body.section");
|
|
45
|
-
expect(`${unchanged}`).toEqual(`${base}`);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
test("filter preserves call order when multiple filters target the same sub-path", async ({ testFilters }) => {
|
|
49
|
-
const locator = testFilters
|
|
50
|
-
.getLocatorSchema("body.section@playground.button@reset")
|
|
51
|
-
.filter("body.section@playground.button@reset", { hasText: /Reset/i })
|
|
52
|
-
.filter("body.section@playground.button@reset", { hasText: /Color/i })
|
|
53
|
-
.getNestedLocator();
|
|
54
|
-
|
|
55
|
-
expect(`${locator}`).toEqual(
|
|
56
|
-
"locator('body').locator('section').filter({ hasText: /Playground/i }).getByRole('button', { name: 'Reset Color' }).filter({ hasText: /Reset/i }).filter({ hasText: /Color/i })",
|
|
57
|
-
);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
test("filter can layer ancestor and descendant filters simultaneously", async ({ testFilters }) => {
|
|
61
|
-
const locator = testFilters
|
|
62
|
-
.getLocatorSchema("body.section@playground.button@red")
|
|
63
|
-
.filter("body.section@playground.button@red", { hasText: /Red/i })
|
|
64
|
-
.filter("body", { hasText: /Playground/i })
|
|
65
|
-
.filter("body.section@playground", { hasText: /Primary Colors/i })
|
|
66
|
-
.getNestedLocator();
|
|
67
|
-
|
|
68
|
-
expect(`${locator}`).toEqual(
|
|
69
|
-
"locator('body').filter({ hasText: /Playground/i }).locator('section').filter({ hasText: /Playground/i }).filter({ hasText: /Primary Colors/i }).getByRole('button', { name: 'Red' }).filter({ hasText: /Red/i })",
|
|
70
|
-
);
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
test("filter accepts registry path strings for has/hasNot", async ({ testFilters }) => {
|
|
74
|
-
const locator = testFilters
|
|
75
|
-
.getLocatorSchema("body.section@playground.button@reset")
|
|
76
|
-
.filter("body.section@playground.button@reset", { has: "body.section.heading" })
|
|
77
|
-
.filter("body.section@playground.button@reset", {
|
|
78
|
-
hasNot: "body.section@playground.button@red",
|
|
79
|
-
})
|
|
80
|
-
.getNestedLocator();
|
|
81
|
-
|
|
82
|
-
expect(`${locator}`).toEqual(
|
|
83
|
-
"locator('body').locator('section').filter({ hasText: /Playground/i }).getByRole('button', { name: 'Reset Color' }).filter({ has: getByRole('heading', { level: 2 }) }).filter({ hasNot: getByRole('button', { name: 'Red' }) })",
|
|
84
|
-
);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
test("filter accepts Playwright locators for has/hasNot", async ({ testFilters }) => {
|
|
88
|
-
const hasLocator = testFilters.getLocator("body.section.heading");
|
|
89
|
-
const hasNotLocator = testFilters.getLocator("body.section@playground.button@red");
|
|
90
|
-
|
|
91
|
-
const locator = testFilters
|
|
92
|
-
.getLocatorSchema("body.section@playground")
|
|
93
|
-
.filter("body.section@playground", { has: hasLocator })
|
|
94
|
-
.filter("body.section@playground", { hasNot: hasNotLocator })
|
|
95
|
-
.getNestedLocator();
|
|
96
|
-
|
|
97
|
-
expect(`${locator}`).toEqual(
|
|
98
|
-
"locator('body').locator('section').filter({ hasText: /Playground/i }).filter({ has: getByRole('heading', { level: 2 }) }).filter({ hasNot: getByRole('button', { name: 'Red' }) })",
|
|
99
|
-
);
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
test("filters accept frame owner locators for has/hasNot", async ({ testFilters }) => {
|
|
103
|
-
const locator = testFilters
|
|
104
|
-
.getLocatorSchema("fictional.filter@hasNotText")
|
|
105
|
-
.filter("fictional.filter@hasNotText", {
|
|
106
|
-
has: testFilters.page.frameLocator("iframe").owner(),
|
|
107
|
-
})
|
|
108
|
-
.getNestedLocator();
|
|
109
|
-
|
|
110
|
-
const manual = testFilters.page.getByRole("button").filter({
|
|
111
|
-
hasNotText: "hasNotText",
|
|
112
|
-
has: testFilters.page.frameLocator("iframe").owner(),
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
expect(`${locator}`).toEqual(`${manual}`);
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
test("multiple nesting/chaining retains filters across the chain", async ({ testFilters }) => {
|
|
119
|
-
const multiChain = testFilters
|
|
120
|
-
.getLocatorSchema("fictional.filter@hasNotText.filter@hasText.filter@hasNotText.filter@hasText")
|
|
121
|
-
.update("fictional.filter@hasNotText")
|
|
122
|
-
.getByRole("button", { name: "roleOptions" })
|
|
123
|
-
.update("fictional.filter@hasNotText.filter@hasText")
|
|
124
|
-
.locator("locator", {
|
|
125
|
-
hasText: "locatorOptionsHasText",
|
|
126
|
-
hasNotText: "locatorOptionshasNotText",
|
|
127
|
-
})
|
|
128
|
-
.update("fictional.filter@hasNotText.filter@hasText.filter@hasNotText")
|
|
129
|
-
.getByTestId("testId")
|
|
130
|
-
.update("fictional.filter@hasNotText.filter@hasText.filter@hasNotText.filter@hasText")
|
|
131
|
-
.getByLabel("label", { exact: true })
|
|
132
|
-
.getNestedLocator();
|
|
133
|
-
|
|
134
|
-
expect(`${multiChain}`).toEqual(
|
|
135
|
-
"getByRole('button', { name: 'roleOptions' }).filter({ hasNotText: 'hasNotText' }).locator('locator').filter({ hasText: 'locatorOptionsHasText' }).filter({ hasNotText: 'locatorOptionshasNotText' }).filter({ hasText: 'hasText' }).getByTestId('testId').filter({ hasNotText: 'hasNotText' }).getByLabel('label', { exact: true }).filter({ hasText: 'hasText' })",
|
|
136
|
-
);
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
test("filter definitions that omit options stay stable", async ({ testFilters }) => {
|
|
140
|
-
const nested = testFilters.getNestedLocator("fictional.filter@optionsUndefined");
|
|
141
|
-
expect(`${nested}`).toEqual("getByRole('button')");
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
test("schema filters resolve path string references", async ({ testFilters, page }) => {
|
|
145
|
-
const nested = testFilters.getNestedLocator("fictional.locatorAndOptionsWithfilter@allOptions");
|
|
146
|
-
|
|
147
|
-
const manual = page.getByRole("button", { name: "roleOptions" }).filter({
|
|
148
|
-
has: page.getByRole("heading", { level: 2 }),
|
|
149
|
-
hasNot: page.getByRole("button"),
|
|
150
|
-
hasText: "hasText",
|
|
151
|
-
hasNotText: "hasNotText",
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
expect(`${nested}`).toEqual(`${manual}`);
|
|
155
|
-
|
|
156
|
-
const has = page.getByRole("heading", { level: 2 });
|
|
157
|
-
const hasNot = page.getByRole("button");
|
|
158
|
-
|
|
159
|
-
const manual2 = page.getByRole("button", { name: "roleOptions" }).filter({
|
|
160
|
-
has: has,
|
|
161
|
-
hasNot: hasNot,
|
|
162
|
-
hasText: "hasText",
|
|
163
|
-
hasNotText: "hasNotText",
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
expect(`${nested}`).toEqual(`${manual2}`);
|
|
167
|
-
|
|
168
|
-
expect(`${nested}`).toEqual(
|
|
169
|
-
"getByRole('button', { name: 'roleOptions' }).filter({ hasText: 'hasText' }).filter({ hasNotText: 'hasNotText' }).filter({ has: getByRole('heading', { level: 2 }) }).filter({ hasNot: getByRole('button') })",
|
|
170
|
-
);
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
test("frameLocator keeps the chain inside the frame and skips frame-level filters", async ({ testFilters, page }) => {
|
|
174
|
-
const frameTerminalBuilder = testFilters
|
|
175
|
-
.getLocatorSchema("fictional.filter@hasNotText.filter@hasText")
|
|
176
|
-
.update("fictional.filter@hasNotText.filter@hasText")
|
|
177
|
-
.frameLocator('iframe[title="name"]');
|
|
178
|
-
|
|
179
|
-
const directFrameLocator = frameTerminalBuilder.getLocator();
|
|
180
|
-
const manualFrame = page.frameLocator('iframe[title="name"]').owner();
|
|
181
|
-
|
|
182
|
-
expect(`${directFrameLocator}`).toEqual(`${manualFrame}`);
|
|
183
|
-
|
|
184
|
-
const nestedBuilder = testFilters
|
|
185
|
-
.getLocatorSchema("fictional.filter@hasNotText.filter@hasText.filter@hasNotText")
|
|
186
|
-
.update("fictional.filter@hasNotText.filter@hasText")
|
|
187
|
-
.frameLocator('iframe[title="name"]')
|
|
188
|
-
.update("fictional.filter@hasNotText.filter@hasText.filter@hasNotText")
|
|
189
|
-
.getByRole("button", { name: "inside frame" });
|
|
190
|
-
|
|
191
|
-
const nested = nestedBuilder.getNestedLocator();
|
|
192
|
-
const manualNested = page
|
|
193
|
-
.getByRole("button")
|
|
194
|
-
.filter({ hasNotText: "hasNotText" })
|
|
195
|
-
.frameLocator('iframe[title="name"]')
|
|
196
|
-
.getByRole("button", { name: "inside frame" })
|
|
197
|
-
.filter({ hasNotText: "hasNotText" });
|
|
198
|
-
|
|
199
|
-
expect(`${nested}`).toEqual(`${manualNested}`);
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
test.describe("getNestedLocator for locatorSchema with filter property", () => {
|
|
203
|
-
type TestCase = {
|
|
204
|
-
definition: LocatorStrategyDefinition;
|
|
205
|
-
expected: string;
|
|
206
|
-
label: string;
|
|
207
|
-
};
|
|
208
|
-
|
|
209
|
-
const testCases: TestCase[] = [
|
|
210
|
-
{ label: "role", definition: { type: "role", role: "button" }, expected: "getByRole('button')" },
|
|
211
|
-
{ label: "text", definition: { type: "text", text: "text" }, expected: "getByText('text')" },
|
|
212
|
-
{ label: "label", definition: { type: "label", text: "label" }, expected: "getByLabel('label')" },
|
|
213
|
-
{
|
|
214
|
-
label: "placeholder",
|
|
215
|
-
definition: { type: "placeholder", text: "placeholder" },
|
|
216
|
-
expected: "getByPlaceholder('placeholder')",
|
|
217
|
-
},
|
|
218
|
-
{ label: "altText", definition: { type: "altText", text: "altText" }, expected: "getByAltText('altText')" },
|
|
219
|
-
{ label: "title", definition: { type: "title", text: "title" }, expected: "getByTitle('title')" },
|
|
220
|
-
{ label: "locator", definition: { type: "locator", selector: "locator" }, expected: "locator('locator')" },
|
|
221
|
-
{ label: "testId", definition: { type: "testId", testId: "testId" }, expected: "getByTestId('testId')" },
|
|
222
|
-
{ label: "id", definition: { type: "id", id: "id" }, expected: "locator('#id')" },
|
|
223
|
-
];
|
|
224
|
-
|
|
225
|
-
for (const { definition, expected, label } of testCases) {
|
|
226
|
-
test(`definition ${label}: should apply filter`, async ({ testFilters }) => {
|
|
227
|
-
const builder = testFilters.getLocatorSchema("fictional.filter@undefined").update("fictional.filter@undefined");
|
|
228
|
-
|
|
229
|
-
const query = (() => {
|
|
230
|
-
switch (definition.type) {
|
|
231
|
-
case "role":
|
|
232
|
-
return builder.getByRole(definition.role, definition.options);
|
|
233
|
-
case "text":
|
|
234
|
-
return builder.getByText(definition.text, definition.options);
|
|
235
|
-
case "label":
|
|
236
|
-
return builder.getByLabel(definition.text, definition.options);
|
|
237
|
-
case "placeholder":
|
|
238
|
-
return builder.getByPlaceholder(definition.text, definition.options);
|
|
239
|
-
case "altText":
|
|
240
|
-
return builder.getByAltText(definition.text, definition.options);
|
|
241
|
-
case "title":
|
|
242
|
-
return builder.getByTitle(definition.text, definition.options);
|
|
243
|
-
case "locator":
|
|
244
|
-
return builder.locator(definition.selector, definition.options);
|
|
245
|
-
case "testId":
|
|
246
|
-
return builder.getByTestId(definition.testId);
|
|
247
|
-
case "id":
|
|
248
|
-
return builder.getById(definition.id);
|
|
249
|
-
case "frameLocator":
|
|
250
|
-
return builder.frameLocator(definition.selector);
|
|
251
|
-
default:
|
|
252
|
-
throw new Error(`Unhandled definition type ${(definition as { type: string }).type}`);
|
|
253
|
-
}
|
|
254
|
-
})();
|
|
255
|
-
|
|
256
|
-
const nested = query.getNestedLocator();
|
|
257
|
-
|
|
258
|
-
expect(`${nested}`).toEqual(expected);
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
const createTestRegistry = <Paths extends string>(page: Page) => new LocatorRegistryInternal<Paths>(page);
|
|
264
|
-
|
|
265
|
-
test("getLocatorSchema.filter supports Playwright Locator instances for has/hasNot", async ({ page }) => {
|
|
266
|
-
type LocatorSchemaPaths = "item";
|
|
267
|
-
|
|
268
|
-
const registry = createTestRegistry<LocatorSchemaPaths>(page);
|
|
269
|
-
|
|
270
|
-
registry.add("item").getByRole("button");
|
|
271
|
-
|
|
272
|
-
const locator = registry
|
|
273
|
-
.getLocatorSchema("item")
|
|
274
|
-
.filter({ has: page.getByRole("heading", { level: 2 }) })
|
|
275
|
-
.filter({ hasNot: page.getByRole("heading", { level: 3 }) })
|
|
276
|
-
.getLocator();
|
|
277
|
-
|
|
278
|
-
expect(`${locator}`).toEqual(
|
|
279
|
-
"getByRole('button').filter({ has: getByRole('heading', { level: 2 }) }).filter({ hasNot: getByRole('heading', { level: 3 }) })",
|
|
280
|
-
);
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
test("getLocatorSchema.filter supports registry path strings for has/hasNot", async ({ page }) => {
|
|
284
|
-
type LocatorSchemaPaths = "item" | "heading.primary" | "heading.secondary";
|
|
285
|
-
|
|
286
|
-
const registry = createTestRegistry<LocatorSchemaPaths>(page);
|
|
287
|
-
|
|
288
|
-
registry.add("heading.primary").getByRole("heading", { level: 2 });
|
|
289
|
-
registry.add("heading.secondary").getByRole("heading", { level: 3 });
|
|
290
|
-
registry.add("item").getByRole("button");
|
|
291
|
-
|
|
292
|
-
const locator = registry
|
|
293
|
-
.getLocatorSchema("item")
|
|
294
|
-
.filter({ has: "heading.primary" })
|
|
295
|
-
.filter({ hasNot: "heading.secondary" })
|
|
296
|
-
.getLocator();
|
|
297
|
-
|
|
298
|
-
expect(`${locator}`).toEqual(
|
|
299
|
-
"getByRole('button').filter({ has: getByRole('heading', { level: 2 }) }).filter({ hasNot: getByRole('heading', { level: 3 }) })",
|
|
300
|
-
);
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
test("getLocatorSchema.filter rejects inline locator strategy definitions for has/hasNot", async ({ page }) => {
|
|
304
|
-
type LocatorSchemaPaths = "item";
|
|
305
|
-
|
|
306
|
-
const registry = createTestRegistry<LocatorSchemaPaths>(page);
|
|
307
|
-
|
|
308
|
-
registry.add("item").getByRole("button");
|
|
309
|
-
registry.getLocatorSchema("item");
|
|
310
|
-
// @ts-expect-error inline locator definitions are no longer supported
|
|
311
|
-
registry.getLocatorSchema("item").filter({ has: { type: "locator", selector: "section" } });
|
|
312
|
-
|
|
313
|
-
const unsafeFilter = {
|
|
314
|
-
has: { type: "locator", selector: "section" },
|
|
315
|
-
} as unknown as FilterDefinition<LocatorSchemaPaths, LocatorSchemaPaths>;
|
|
316
|
-
|
|
317
|
-
expect(() => registry.getLocatorSchema("item").filter(unsafeFilter).getLocator()).toThrow(
|
|
318
|
-
/Unsupported filter reference/,
|
|
319
|
-
);
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
test("getLocatorSchema.filter rejects locator wrappers for has/hasNot", async ({ page }) => {
|
|
323
|
-
type LocatorSchemaPaths = "item";
|
|
324
|
-
|
|
325
|
-
const registry = createTestRegistry<LocatorSchemaPaths>(page);
|
|
326
|
-
|
|
327
|
-
registry.add("item").getByRole("button");
|
|
328
|
-
// @ts-expect-error locator wrapper is no longer supported
|
|
329
|
-
registry.getLocatorSchema("item").filter({ has: { locator: { type: "locator", selector: "section" } } });
|
|
330
|
-
|
|
331
|
-
const unsafeFilter = {
|
|
332
|
-
has: { locator: { type: "locator", selector: "section" } },
|
|
333
|
-
} as unknown as FilterDefinition<LocatorSchemaPaths, LocatorSchemaPaths>;
|
|
334
|
-
|
|
335
|
-
expect(() => registry.getLocatorSchema("item").filter(unsafeFilter).getLocator()).toThrow(
|
|
336
|
-
/Unsupported filter reference/,
|
|
337
|
-
);
|
|
338
|
-
});
|
|
339
|
-
|
|
340
|
-
test("getLocatorSchema.filter rejects locatorPath wrappers for has/hasNot", async ({ page }) => {
|
|
341
|
-
type LocatorSchemaPaths = "item";
|
|
342
|
-
|
|
343
|
-
const registry = createTestRegistry<LocatorSchemaPaths>(page);
|
|
344
|
-
|
|
345
|
-
registry.add("item").getByRole("button");
|
|
346
|
-
// @ts-expect-error locatorPath wrapper is no longer supported
|
|
347
|
-
registry.getLocatorSchema("item").filter({ has: { locatorPath: "item" } });
|
|
348
|
-
|
|
349
|
-
const unsafeFilter = {
|
|
350
|
-
has: { locatorPath: "item" },
|
|
351
|
-
} as unknown as FilterDefinition<LocatorSchemaPaths, LocatorSchemaPaths>;
|
|
352
|
-
|
|
353
|
-
expect(() => registry.getLocatorSchema("item").filter(unsafeFilter).getLocator()).toThrow(
|
|
354
|
-
/Unsupported filter reference/,
|
|
355
|
-
);
|
|
356
|
-
});
|
|
357
|
-
|
|
358
|
-
test("getLocatorSchema.filter supports visible true/false", async ({ page }) => {
|
|
359
|
-
type LocatorSchemaPaths = "item";
|
|
360
|
-
|
|
361
|
-
const registry = createTestRegistry<LocatorSchemaPaths>(page);
|
|
362
|
-
|
|
363
|
-
registry.add("item").getByRole("button");
|
|
364
|
-
|
|
365
|
-
const locator = registry.getLocatorSchema("item").filter({ visible: true }).filter({ visible: false }).getLocator();
|
|
366
|
-
|
|
367
|
-
expect(`${locator}`).toEqual("getByRole('button').filter({ visible: true }).filter({ visible: false })");
|
|
368
|
-
});
|
package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.getLocator.spec.ts
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { expect, test } from "@fixtures-v2/testApp.fixtures";
|
|
2
|
-
|
|
3
|
-
test("getLocator fluent wrapper supports update and clearSteps", async ({ testFilters }) => {
|
|
4
|
-
const updated = testFilters
|
|
5
|
-
.getLocatorSchema("body.section.heading")
|
|
6
|
-
.update("body.section.heading")
|
|
7
|
-
.getByRole("heading", { level: 3 })
|
|
8
|
-
.getLocator();
|
|
9
|
-
|
|
10
|
-
expect(`${updated}`).toEqual("getByRole('heading', { level: 3 })");
|
|
11
|
-
|
|
12
|
-
const cleared = testFilters
|
|
13
|
-
.getLocatorSchema("fictional.filter@hasText")
|
|
14
|
-
.clearSteps("fictional.filter@hasText")
|
|
15
|
-
.getLocator();
|
|
16
|
-
|
|
17
|
-
expect(`${cleared}`).toEqual("getByRole('button')");
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
test("getLocator update accepts partial patch arguments", async ({ testFilters }) => {
|
|
21
|
-
const baseline = testFilters.getLocator("body.section.heading");
|
|
22
|
-
|
|
23
|
-
expect(`${baseline}`).toEqual("getByRole('heading', { level: 2 })");
|
|
24
|
-
|
|
25
|
-
const noArgs = testFilters
|
|
26
|
-
.getLocatorSchema("body.section.heading")
|
|
27
|
-
.update("body.section.heading")
|
|
28
|
-
.getByRole()
|
|
29
|
-
.getLocator();
|
|
30
|
-
|
|
31
|
-
expect(`${noArgs}`).toEqual("getByRole('heading', { level: 2 })");
|
|
32
|
-
|
|
33
|
-
const optionsOnly = testFilters
|
|
34
|
-
.getLocatorSchema("body.section.heading")
|
|
35
|
-
.update("body.section.heading")
|
|
36
|
-
.getByRole({ level: 4 })
|
|
37
|
-
.getLocator();
|
|
38
|
-
|
|
39
|
-
expect(`${optionsOnly}`).toEqual("getByRole('heading', { level: 4 })");
|
|
40
|
-
|
|
41
|
-
const roleOnly = testFilters
|
|
42
|
-
.getLocatorSchema("body.section.heading")
|
|
43
|
-
.update("body.section.heading")
|
|
44
|
-
.getByRole("heading")
|
|
45
|
-
.getLocator();
|
|
46
|
-
|
|
47
|
-
expect(`${roleOnly}`).toEqual("getByRole('heading', { level: 2 })");
|
|
48
|
-
|
|
49
|
-
const roleAndOptions = testFilters
|
|
50
|
-
.getLocatorSchema("body.section.heading")
|
|
51
|
-
.update("body.section.heading")
|
|
52
|
-
.getByRole("heading", { level: 5 })
|
|
53
|
-
.getLocator();
|
|
54
|
-
|
|
55
|
-
expect(`${roleAndOptions}`).toEqual("getByRole('heading', { level: 5 })");
|
|
56
|
-
});
|
package/intTestV2/tests/locatorRegistry/getLocatorSchema/getLocatorSchema.getNestedLocator.spec.ts
DELETED
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
import { expect, test } from "@fixtures-v2/testApp.fixtures";
|
|
2
|
-
|
|
3
|
-
test("getNestedLocator fluent wrapper records filters and indices in call order", async ({ testFilters }) => {
|
|
4
|
-
const chained = testFilters
|
|
5
|
-
.getLocatorSchema("fictional.filter@hasText")
|
|
6
|
-
.filter("fictional.filter@hasText", { hasText: "extra" })
|
|
7
|
-
.nth("fictional.filter@hasText", 1)
|
|
8
|
-
.getNestedLocator();
|
|
9
|
-
|
|
10
|
-
expect(`${chained}`).toEqual(
|
|
11
|
-
"getByRole('button').filter({ hasText: 'hasText' }).filter({ hasText: 'extra' }).nth(1)",
|
|
12
|
-
);
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
test("getNestedLocator fluent wrapper supports update and clearSteps", async ({ testFilters }) => {
|
|
16
|
-
const updated = testFilters
|
|
17
|
-
.getLocatorSchema("body.section.heading")
|
|
18
|
-
.update("body.section.heading")
|
|
19
|
-
.getByRole("heading", { level: 3 })
|
|
20
|
-
.getNestedLocator();
|
|
21
|
-
|
|
22
|
-
expect(`${updated}`).toEqual("locator('body').locator('section').getByRole('heading', { level: 3 })");
|
|
23
|
-
|
|
24
|
-
const cleared = testFilters
|
|
25
|
-
.getLocatorSchema("fictional.filter@hasText")
|
|
26
|
-
.clearSteps("fictional.filter@hasText")
|
|
27
|
-
.getNestedLocator();
|
|
28
|
-
|
|
29
|
-
expect(`${cleared}`).toEqual("getByRole('button')");
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
test("getNestedLocator fluent update can switch strategies without a terminator", async ({ testFilters }) => {
|
|
33
|
-
const locator = testFilters
|
|
34
|
-
.getLocatorSchema("body.section.heading")
|
|
35
|
-
.update("body.section.heading")
|
|
36
|
-
.getByText("Updated heading")
|
|
37
|
-
.getNestedLocator();
|
|
38
|
-
|
|
39
|
-
expect(`${locator}`).toEqual("locator('body').locator('section').getByText('Updated heading')");
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
test("getNestedLocator update accepts partial patch arguments", async ({ testFilters }) => {
|
|
43
|
-
const baseline = testFilters.getNestedLocator("body.section.heading");
|
|
44
|
-
|
|
45
|
-
expect(`${baseline}`).toEqual("locator('body').locator('section').getByRole('heading', { level: 2 })");
|
|
46
|
-
|
|
47
|
-
const noArgs = testFilters
|
|
48
|
-
.getLocatorSchema("body.section.heading")
|
|
49
|
-
.update("body.section.heading")
|
|
50
|
-
.getByRole()
|
|
51
|
-
.getNestedLocator();
|
|
52
|
-
|
|
53
|
-
expect(`${noArgs}`).toEqual("locator('body').locator('section').getByRole('heading', { level: 2 })");
|
|
54
|
-
|
|
55
|
-
const optionsOnly = testFilters
|
|
56
|
-
.getLocatorSchema("body.section.heading")
|
|
57
|
-
.update("body.section.heading")
|
|
58
|
-
.getByRole({ level: 4 })
|
|
59
|
-
.getNestedLocator();
|
|
60
|
-
|
|
61
|
-
expect(`${optionsOnly}`).toEqual("locator('body').locator('section').getByRole('heading', { level: 4 })");
|
|
62
|
-
|
|
63
|
-
const roleOnly = testFilters
|
|
64
|
-
.getLocatorSchema("body.section.heading")
|
|
65
|
-
.update("body.section.heading")
|
|
66
|
-
.getByRole("heading")
|
|
67
|
-
.getNestedLocator();
|
|
68
|
-
|
|
69
|
-
expect(`${roleOnly}`).toEqual("locator('body').locator('section').getByRole('heading', { level: 2 })");
|
|
70
|
-
|
|
71
|
-
const roleAndOptions = testFilters
|
|
72
|
-
.getLocatorSchema("body.section.heading")
|
|
73
|
-
.update("body.section.heading")
|
|
74
|
-
.getByRole("heading", { level: 5 })
|
|
75
|
-
.getNestedLocator();
|
|
76
|
-
|
|
77
|
-
expect(`${roleAndOptions}`).toEqual("locator('body').locator('section').getByRole('heading', { level: 5 })");
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
test("getNestedLocator resolves has/hasNot path string references", async ({ testFilters }) => {
|
|
81
|
-
const nested = testFilters
|
|
82
|
-
.getLocatorSchema("fictional.filter@hasNotText")
|
|
83
|
-
.filter("fictional.filter@hasNotText", { has: "body.section.heading" })
|
|
84
|
-
.filter("fictional.filter@hasNotText", { hasNot: "body.section@playground.button@red" })
|
|
85
|
-
.getNestedLocator();
|
|
86
|
-
|
|
87
|
-
expect(`${nested}`).toEqual(
|
|
88
|
-
"getByRole('button').filter({ hasNotText: 'hasNotText' }).filter({ has: getByRole('heading', { level: 2 }) }).filter({ hasNot: getByRole('button', { name: 'Red' }) })",
|
|
89
|
-
);
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
test("getNestedLocator resolves Playwright locators for has/hasNot", async ({ testFilters }) => {
|
|
93
|
-
const sectionLocator = testFilters.page.locator("section");
|
|
94
|
-
const missingLocator = testFilters.page.locator("[data-cy=missing]");
|
|
95
|
-
|
|
96
|
-
const nested = testFilters
|
|
97
|
-
.getLocatorSchema("fictional.filter@hasNotText")
|
|
98
|
-
.filter("fictional.filter@hasNotText", { has: sectionLocator })
|
|
99
|
-
.filter("fictional.filter@hasNotText", { hasNot: missingLocator })
|
|
100
|
-
.getNestedLocator();
|
|
101
|
-
|
|
102
|
-
expect(`${nested}`).toEqual(
|
|
103
|
-
"getByRole('button').filter({ hasNotText: 'hasNotText' }).filter({ has: locator('section') }).filter({ hasNot: locator('[data-cy=missing]') })",
|
|
104
|
-
);
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
const fullPath = "fictional.filter@hasNotText.filter@hasText.filter@hasNotText.filter@hasText" as const;
|
|
108
|
-
const expectedChain =
|
|
109
|
-
"getByRole('button').filter({ hasNotText: 'hasNotText' }).nth(2).getByRole('button').filter({ hasText: 'hasText' }).getByRole('button').filter({ hasNotText: 'hasNotText' }).getByRole('button').filter({ hasText: 'hasText' })";
|
|
110
|
-
|
|
111
|
-
test("getNestedLocator applies chained indices", async ({ testFilters }) => {
|
|
112
|
-
const locator = testFilters.getLocatorSchema(fullPath).nth("fictional.filter@hasNotText", 2).getNestedLocator();
|
|
113
|
-
|
|
114
|
-
expect(`${locator}`).toContain(".nth(2)");
|
|
115
|
-
expect(`${locator}`).toEqual(expectedChain);
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
test("getLocatorSchema.getNestedLocator applies chained indices", async ({ testFilters }) => {
|
|
119
|
-
const locator = testFilters.getLocatorSchema(fullPath).nth("fictional.filter@hasNotText", 2).getNestedLocator();
|
|
120
|
-
|
|
121
|
-
expect(`${locator}`).toContain(".nth(2)");
|
|
122
|
-
expect(`${locator}`).toEqual(expectedChain);
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
test("getNestedLocator honors chained filters and indices", async ({ testFilters }) => {
|
|
126
|
-
const locator = testFilters
|
|
127
|
-
.getLocatorSchema("fictional.filter@hasText")
|
|
128
|
-
.filter("fictional.filter@hasText", { hasText: "extra" })
|
|
129
|
-
.nth("fictional.filter@hasText", 1)
|
|
130
|
-
.filter("fictional.filter@hasText", { hasNotText: "tail" })
|
|
131
|
-
.getNestedLocator();
|
|
132
|
-
|
|
133
|
-
expect(`${locator}`).toEqual(
|
|
134
|
-
"getByRole('button').filter({ hasText: 'hasText' }).filter({ hasText: 'extra' }).nth(1).filter({ hasNotText: 'tail' })",
|
|
135
|
-
);
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
test("getNestedLocator supports explicit last() selection", async ({ testFilters }) => {
|
|
139
|
-
const locator = testFilters.getLocatorSchema(fullPath).nth("fictional.filter@hasNotText", "last").getNestedLocator();
|
|
140
|
-
|
|
141
|
-
expect(`${locator}`).toEqual(
|
|
142
|
-
"getByRole('button').filter({ hasNotText: 'hasNotText' }).last().getByRole('button').filter({ hasText: 'hasText' }).getByRole('button').filter({ hasNotText: 'hasNotText' }).getByRole('button').filter({ hasText: 'hasText' })",
|
|
143
|
-
);
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
test('getNestedLocator accepts "first" and "last" selections', async ({ testFilters }) => {
|
|
147
|
-
const locator = testFilters
|
|
148
|
-
.getLocatorSchema(fullPath)
|
|
149
|
-
.nth("fictional.filter@hasNotText", "first")
|
|
150
|
-
.nth("fictional.filter@hasNotText.filter@hasText.filter@hasNotText", "last")
|
|
151
|
-
.getNestedLocator();
|
|
152
|
-
|
|
153
|
-
expect(`${locator}`).toContain("first()");
|
|
154
|
-
expect(`${locator}`).toContain("last()");
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
test("getNestedLocator rejects chained steps for unknown sub-paths", async ({ testFilters }) => {
|
|
158
|
-
expect(() => {
|
|
159
|
-
// @ts-expect-error Testing invalid argument
|
|
160
|
-
testFilters.getLocatorSchema(fullPath).nth("fictional", 1).getNestedLocator();
|
|
161
|
-
}).toThrow(
|
|
162
|
-
'"fictional" is not a valid sub-path of "fictional.filter@hasNotText.filter@hasText.filter@hasNotText.filter@hasText".',
|
|
163
|
-
);
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
test("getLocatorSchema.getNestedLocator rejects chained steps for partially matching paths", async ({
|
|
167
|
-
testFilters,
|
|
168
|
-
}) => {
|
|
169
|
-
expect(() => {
|
|
170
|
-
// @ts-expect-error Testing invalid argument
|
|
171
|
-
testFilters.getLocatorSchema(fullPath).nth("fictional.filter@has", 1).getNestedLocator();
|
|
172
|
-
}).toThrow(
|
|
173
|
-
'"fictional.filter@has" is not a valid sub-path of "fictional.filter@hasNotText.filter@hasText.filter@hasNotText.filter@hasText".',
|
|
174
|
-
);
|
|
175
|
-
});
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { expect, test } from "@fixtures-v2/testApp.fixtures";
|
|
2
|
-
|
|
3
|
-
test("nth applies numeric index to targeted sub-path", async ({ testFilters }) => {
|
|
4
|
-
const locator = testFilters.getLocatorSchema("body.section.button").nth("body.section.button", 1).getNestedLocator();
|
|
5
|
-
|
|
6
|
-
expect(`${locator}`).toEqual("locator('body').locator('section').getByRole('button').nth(1)");
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
test('nth supports "first" and "last" selectors', async ({ testFilters }) => {
|
|
10
|
-
const first = testFilters
|
|
11
|
-
.getLocatorSchema("body.section.button")
|
|
12
|
-
.nth("body.section.button", "first")
|
|
13
|
-
.getNestedLocator();
|
|
14
|
-
|
|
15
|
-
expect(`${first}`).toEqual("locator('body').locator('section').getByRole('button').first()");
|
|
16
|
-
|
|
17
|
-
const last = testFilters
|
|
18
|
-
.getLocatorSchema("body.section.button")
|
|
19
|
-
.nth("body.section.button", "last")
|
|
20
|
-
.getNestedLocator();
|
|
21
|
-
|
|
22
|
-
expect(`${last}`).toEqual("locator('body').locator('section').getByRole('button').last()");
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
test("nth can target intermediate sub-paths", async ({ testFilters }) => {
|
|
26
|
-
const locator = testFilters
|
|
27
|
-
.getLocatorSchema("body.section.heading")
|
|
28
|
-
.nth("body", 0)
|
|
29
|
-
.nth("body.section", 1)
|
|
30
|
-
.nth("body.section.heading", -1)
|
|
31
|
-
.getNestedLocator();
|
|
32
|
-
|
|
33
|
-
expect(`${locator}`).toEqual(
|
|
34
|
-
"locator('body').first().locator('section').nth(1).getByRole('heading', { level: 2 }).last()",
|
|
35
|
-
);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
test("nth overrides are scoped to each builder instance", async ({ testFilters }) => {
|
|
39
|
-
const builder = testFilters.getLocatorSchema("body.section.button");
|
|
40
|
-
const first = builder.nth("body.section.button", "first").getNestedLocator();
|
|
41
|
-
const second = testFilters.getLocatorSchema("body.section.button").getNestedLocator();
|
|
42
|
-
|
|
43
|
-
expect(`${first}`).toEqual("locator('body').locator('section').getByRole('button').first()");
|
|
44
|
-
expect(`${second}`).toEqual("locator('body').locator('section').getByRole('button')");
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
test("filter and nth ordering apply per sub-path when chained on getLocatorSchema", async ({ testFilters }) => {
|
|
48
|
-
const locator = testFilters
|
|
49
|
-
.getLocatorSchema("one.two")
|
|
50
|
-
.clearSteps("one.two")
|
|
51
|
-
.filter("one", { hasText: "outer" })
|
|
52
|
-
.nth("one", "first")
|
|
53
|
-
.filter("one.two", { hasText: "inner" })
|
|
54
|
-
.nth("one.two", "last")
|
|
55
|
-
.getNestedLocator();
|
|
56
|
-
|
|
57
|
-
expect(`${locator}`).toEqual(
|
|
58
|
-
"locator('div.one').filter({ hasText: 'outer' }).first().locator('div.two').filter({ hasText: 'inner' }).last()",
|
|
59
|
-
);
|
|
60
|
-
});
|