Skip to content

Commit 487990a

Browse files
authored
feat(experimental): support browser.locators.exact option (#10013)
1 parent d0f042f commit 487990a

File tree

16 files changed

+212
-32
lines changed

16 files changed

+212
-32
lines changed

docs/config/browser/locators.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,17 @@ Options for built-in [browser locators](/api/browser/locators).
1313
- **Default:** `data-testid`
1414

1515
Attribute used to find elements with `getByTestId` locator.
16+
17+
## browser.locators.exact <Version type="experimental">4.1.3</Version> {#browser-locators-exact}
18+
19+
- **Type:** `boolean`
20+
- **Default:** `false`
21+
22+
When set to `true`, [locators](/api/browser/locators) will match text exactly by default, requiring a full, case-sensitive match. Individual locator calls can override this default via their own `exact` option.
23+
24+
```ts
25+
// With exact: false (default), this matches "Hello, World!", "Say Hello, World", etc.
26+
// With exact: true, this only matches the string "Hello, World" exactly.
27+
const locator = page.getByText('Hello, World', { exact: true })
28+
await locator.click()
29+
```

docs/guide/cli-generated.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,13 @@ Control if Vitest catches uncaught exceptions so they can be reported (default:
429429

430430
Enable trace view mode. Supported: "on", "off", "on-first-retry", "on-all-retries", "retain-on-failure".
431431

432+
### browser.locators.exact
433+
434+
- **CLI:** `--browser.locators.exact`
435+
- **Config:** [browser.locators.exact](/config/browser/locators#locators-exact)
436+
437+
Should locators match the text exactly by default (default: `false`)
438+
432439
### pool
433440

434441
- **CLI:** `--pool <pool>`

packages/browser/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@
8787
"@vitest/runner": "workspace:*",
8888
"birpc": "catalog:",
8989
"flatted": "catalog:",
90-
"ivya": "^1.7.1",
90+
"ivya": "^1.8.0",
9191
"mime": "^4.1.0",
9292
"pathe": "catalog:",
9393
"vitest": "workspace:*"

packages/browser/src/client/tester/locators/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ function sleep(ms: number): Promise<void> {
5252
return new Promise(resolve => setTimeout(resolve, ms))
5353
}
5454

55-
// we prefer using playwright locators because they are more powerful and support Shadow DOM
5655
export const selectorEngine: Ivya = Ivya.create({
56+
exact: server.config.browser.locators.exact,
5757
browser: ((name: string) => {
5858
switch (name) {
5959
case 'edge':

packages/vitest/src/node/cli/cli-config.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,22 @@ export const cliOptionsConfig: VitestCLIOptions = {
418418
viewport: null,
419419
screenshotDirectory: null,
420420
screenshotFailures: null,
421-
locators: null,
421+
locators: {
422+
description: 'Options for how locators should be handled by default',
423+
argument: '<options>',
424+
subcommands: {
425+
testIdAttribute: null,
426+
exact: {
427+
description: 'Should locators match the text exactly by default (default: `false`)',
428+
},
429+
},
430+
transform(val) {
431+
if (typeof val !== 'object' || val == null) {
432+
return {}
433+
}
434+
return val
435+
},
436+
},
422437
testerHtmlPath: null,
423438
instances: null,
424439
expect: null,

packages/vitest/src/node/config/resolveConfig.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -835,6 +835,7 @@ export function resolveConfig(
835835

836836
resolved.browser.locators ??= {} as any
837837
resolved.browser.locators.testIdAttribute ??= 'data-testid'
838+
resolved.browser.locators.exact ??= false
838839

839840
if (typeof resolved.browser.provider === 'string') {
840841
const source = `@vitest/browser-${resolved.browser.provider}`

packages/vitest/src/node/config/serializeConfig.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ export function serializeConfig(project: TestProject): SerializedConfig {
113113
screenshotFailures: browser.screenshotFailures,
114114
locators: {
115115
testIdAttribute: browser.locators.testIdAttribute,
116+
exact: browser.locators.exact,
116117
},
117118
providerOptions: provider?.name === 'playwright'
118119
? {

packages/vitest/src/node/projects/resolveProjects.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ function cloneConfig(project: TestProject, { browser, ...config }: BrowserInstan
293293
locators: locators
294294
? {
295295
testIdAttribute: locators.testIdAttribute ?? currentConfig.locators.testIdAttribute,
296+
exact: locators.exact ?? currentConfig.locators.exact,
296297
}
297298
: project.config.browser.locators,
298299
viewport: viewport ?? currentConfig.viewport,

packages/vitest/src/node/types/browser.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,11 @@ export interface BrowserConfigOptions {
200200
* @default 'data-testid'
201201
*/
202202
testIdAttribute?: string
203+
/**
204+
* Should locators match the text exactly by default
205+
* @default false
206+
*/
207+
exact?: boolean
203208
}
204209

205210
/**
@@ -394,6 +399,7 @@ export interface ResolvedBrowserOptions extends BrowserConfigOptions {
394399
screenshotFailures: boolean
395400
locators: {
396401
testIdAttribute: string
402+
exact: boolean
397403
}
398404
trace: {
399405
mode: BrowserTraceViewMode

packages/vitest/src/runtime/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ export interface SerializedConfig {
105105
}
106106
locators: {
107107
testIdAttribute: string
108+
exact: boolean
108109
}
109110
screenshotFailures: boolean
110111
providerOptions: {

0 commit comments

Comments
 (0)