0
# Locators
1
2
Powerful element location system supporting CSS selectors, accessibility queries, chaining, and filtering for robust element targeting in browser tests.
3
4
## Capabilities
5
6
### Locator Interface
7
8
Main interface for locating and interacting with elements on the page.
9
10
```typescript { .api }
11
interface Locator {
12
/** Selector string that will be used to locate the element by the browser provider */
13
readonly selector: string;
14
15
// Selector methods
16
/** Creates a locator by ARIA role and optional attributes */
17
getByRole(role: string, options?: LocatorByRoleOptions): Locator;
18
/** Creates a locator by label text */
19
getByLabelText(text: string | RegExp, options?: LocatorOptions): Locator;
20
/** Creates a locator by alt text (matches any element with alt attribute) */
21
getByAltText(text: string | RegExp, options?: LocatorOptions): Locator;
22
/** Creates a locator by placeholder text */
23
getByPlaceholder(text: string | RegExp, options?: LocatorOptions): Locator;
24
/** Creates a locator by text content (matches TextNode nodeValue or input value) */
25
getByText(text: string | RegExp, options?: LocatorOptions): Locator;
26
/** Creates a locator by title attribute */
27
getByTitle(text: string | RegExp, options?: LocatorOptions): Locator;
28
/** Creates a locator by test ID attribute (configurable via browser.locators.testIdAttribute) */
29
getByTestId(text: string | RegExp): Locator;
30
31
// Interaction methods
32
/** Click on an element */
33
click(options?: UserEventClickOptions): Promise<void>;
34
/** Triggers a double click event on an element */
35
dblClick(options?: UserEventDoubleClickOptions): Promise<void>;
36
/** Triggers a triple click event on an element */
37
tripleClick(options?: UserEventTripleClickOptions): Promise<void>;
38
/** Clears the input element content */
39
clear(options?: UserEventClearOptions): Promise<void>;
40
/** Moves the cursor position to the selected element */
41
hover(options?: UserEventHoverOptions): Promise<void>;
42
/** Moves the cursor to the document.body element */
43
unhover(options?: UserEventHoverOptions): Promise<void>;
44
/** Sets the value of the current input, textarea or contenteditable element */
45
fill(text: string, options?: UserEventFillOptions): Promise<void>;
46
/** Drags the current element to the target location */
47
dropTo(target: Locator, options?: UserEventDragAndDropOptions): Promise<void>;
48
/** Choose one or more values from a <select> element */
49
selectOptions(
50
values: HTMLElement | HTMLElement[] | Locator | Locator[] | string | string[],
51
options?: UserEventSelectOptions
52
): Promise<void>;
53
/** Change a file input element to have the specified files */
54
upload(files: File | File[] | string | string[], options?: UserEventUploadOptions): Promise<void>;
55
56
// Screenshot
57
/** Make a screenshot of an element matching the locator */
58
screenshot(options?: LocatorScreenshotOptions): Promise<string>;
59
screenshot(options: Omit<LocatorScreenshotOptions, 'base64'> & { base64: true }): Promise<{
60
path: string;
61
base64: string;
62
}>;
63
64
// Query methods
65
/** Returns an element matching the selector (throws if not found) */
66
element(): Element;
67
/** Returns an array of elements matching the selector */
68
elements(): Element[];
69
/** Returns an element matching the selector or null if not found */
70
query(): Element | null;
71
/** Wraps an array of .elements() matching the selector in new Locators */
72
all(): Locator[];
73
74
// Filtering methods
75
/** Returns a locator for the nth element matching the selector */
76
nth(index: number): Locator;
77
/** Returns a locator for the first element matching the selector */
78
first(): Locator;
79
/** Returns a locator for the last element matching the selector */
80
last(): Locator;
81
/** Returns a locator that matches both the current locator and the provided locator */
82
and(locator: Locator): Locator;
83
/** Returns a locator that matches either the current locator or the provided locator */
84
or(locator: Locator): Locator;
85
/** Narrows existing locator according to the options */
86
filter(options: LocatorFilterOptions): Locator;
87
}
88
```
89
90
**Usage Examples:**
91
92
```typescript
93
import { page } from "@vitest/browser/context";
94
95
// Basic element location
96
const submitButton = page.getByRole("button", { name: "Submit" });
97
const usernameInput = page.getByLabelText("Username");
98
const errorMessage = page.getByText("Invalid credentials");
99
100
// Chaining locators
101
const formButton = page
102
.getByRole("form")
103
.getByRole("button", { name: "Submit" });
104
105
// Using filter options
106
const activeTab = page
107
.getByRole("tab")
108
.filter({ hasText: "Active" });
109
110
// Complex selectors
111
const specificItem = page
112
.getByRole("listitem")
113
.filter({ hasText: "Important" })
114
.first();
115
116
// Direct element access
117
const element = submitButton.element(); // throws if not found
118
const maybeElement = submitButton.query(); // returns null if not found
119
const allButtons = page.getByRole("button").elements();
120
```
121
122
### Selector Methods
123
124
Individual selector methods for different element targeting strategies.
125
126
#### getByRole
127
128
```typescript { .api }
129
/**
130
* Creates a locator by ARIA role, ARIA attributes and accessible name
131
* @param role - ARIA role or custom role string
132
* @param options - Role-specific options for filtering
133
* @returns Locator for elements matching the role criteria
134
*/
135
getByRole(role: string, options?: LocatorByRoleOptions): Locator;
136
137
interface LocatorByRoleOptions extends LocatorOptions {
138
/** Should checked elements be included or not */
139
checked?: boolean;
140
/** Should disabled elements be included or not */
141
disabled?: boolean;
142
/** Should expanded elements be included or not */
143
expanded?: boolean;
144
/** Should normally excluded elements be queried */
145
includeHidden?: boolean;
146
/** Number attribute for heading, listitem, row, treeitem roles */
147
level?: number;
148
/** Accessible name to match */
149
name?: string | RegExp;
150
/** Should pressed elements be included or not */
151
pressed?: boolean;
152
/** Should selected elements be included or not */
153
selected?: boolean;
154
}
155
```
156
157
**Usage Examples:**
158
159
```typescript
160
// Basic roles
161
page.getByRole("button");
162
page.getByRole("textbox");
163
page.getByRole("link");
164
165
// With name matching
166
page.getByRole("button", { name: "Submit Form" });
167
page.getByRole("button", { name: /submit/i });
168
169
// With state filtering
170
page.getByRole("checkbox", { checked: true });
171
page.getByRole("button", { disabled: false });
172
page.getByRole("tab", { selected: true });
173
174
// With level (for headings)
175
page.getByRole("heading", { level: 2 });
176
```
177
178
#### getByText
179
180
```typescript { .api }
181
/**
182
* Creates a locator by text content. Matches against TextNode's nodeValue
183
* or input's value if type is button or reset. Always normalizes whitespace.
184
* @param text - Text to search for (string or RegExp)
185
* @param options - Text matching options
186
* @returns Locator for elements containing the text
187
*/
188
getByText(text: string | RegExp, options?: LocatorOptions): Locator;
189
```
190
191
**Usage Examples:**
192
193
```typescript
194
// Exact text matching
195
page.getByText("Welcome back");
196
197
// Partial text matching (default)
198
page.getByText("Welcome"); // matches "Welcome back"
199
200
// Exact matching
201
page.getByText("Welcome", { exact: true }); // only matches "Welcome"
202
203
// Regular expressions
204
page.getByText(/welcome/i); // case insensitive
205
page.getByText(/error.*occurred/); // pattern matching
206
```
207
208
#### getByLabelText
209
210
```typescript { .api }
211
/**
212
* Creates a locator by label text association. Finds form controls
213
* associated with labels containing the specified text.
214
* @param text - Label text to search for
215
* @param options - Label matching options
216
* @returns Locator for form controls with matching labels
217
*/
218
getByLabelText(text: string | RegExp, options?: LocatorOptions): Locator;
219
```
220
221
**Usage Examples:**
222
223
```typescript
224
// Form inputs with labels
225
page.getByLabelText("Email address");
226
page.getByLabelText("Password");
227
page.getByLabelText("Remember me"); // checkbox
228
229
// Partial matching
230
page.getByLabelText("Email"); // matches "Email address"
231
232
// Case insensitive with RegExp
233
page.getByLabelText(/email/i);
234
```
235
236
#### getByTestId
237
238
```typescript { .api }
239
/**
240
* Creates a locator by test ID attribute. Uses the configured test ID attribute
241
* from browser.locators.testIdAttribute (default: "data-testid").
242
* @param testId - Test ID value to match
243
* @returns Locator for elements with matching test ID
244
*/
245
getByTestId(testId: string | RegExp): Locator;
246
```
247
248
**Usage Examples:**
249
250
```typescript
251
// Standard test IDs
252
page.getByTestId("submit-button");
253
page.getByTestId("user-profile");
254
255
// Pattern matching
256
page.getByTestId(/button-\d+/);
257
258
// Custom test ID attribute (configured in vitest.config.js)
259
// browser: { locators: { testIdAttribute: "data-cy" } }
260
page.getByTestId("login-form"); // looks for data-cy="login-form"
261
```
262
263
### Filtering and Chaining
264
265
Methods for refining and combining locators.
266
267
#### Filter Method
268
269
```typescript { .api }
270
/**
271
* Narrows existing locator according to filter criteria
272
* @param options - Filter criteria
273
* @returns New locator with applied filters
274
*/
275
filter(options: LocatorFilterOptions): Locator;
276
277
interface LocatorFilterOptions {
278
/** Text content that element should have */
279
hasText?: string | RegExp;
280
/** Text content that element should NOT have */
281
hasNotText?: string | RegExp;
282
/** Child locator that element should contain */
283
has?: Locator;
284
/** Child locator that element should NOT contain */
285
hasNot?: Locator;
286
}
287
```
288
289
**Usage Examples:**
290
291
```typescript
292
// Filter by text content
293
page.getByRole("listitem").filter({ hasText: "Active" });
294
page.getByRole("button").filter({ hasNotText: "Disabled" });
295
296
// Filter by child elements
297
page.getByRole("article").filter({
298
has: page.getByRole("button", { name: "Edit" })
299
});
300
301
// Combined filters
302
page.getByRole("row").filter({
303
hasText: "John",
304
has: page.getByRole("cell", { name: "Active" })
305
});
306
```
307
308
#### Logical Operators
309
310
```typescript { .api }
311
/**
312
* Returns a locator that matches both the current locator and the provided locator
313
*/
314
and(locator: Locator): Locator;
315
316
/**
317
* Returns a locator that matches either the current locator or the provided locator
318
*/
319
or(locator: Locator): Locator;
320
```
321
322
**Usage Examples:**
323
324
```typescript
325
// Element must match both conditions
326
const specificButton = page
327
.getByRole("button")
328
.and(page.getByText("Submit"));
329
330
// Element can match either condition
331
const anyInput = page
332
.getByRole("textbox")
333
.or(page.getByRole("searchbox"));
334
```
335
336
#### Position Methods
337
338
```typescript { .api }
339
/**
340
* Returns a locator for the nth element matching the selector
341
*/
342
nth(index: number): Locator;
343
344
/**
345
* Returns a locator for the first element matching the selector
346
*/
347
first(): Locator;
348
349
/**
350
* Returns a locator for the last element matching the selector
351
*/
352
last(): Locator;
353
```
354
355
**Usage Examples:**
356
357
```typescript
358
// Positional selection
359
page.getByRole("listitem").first();
360
page.getByRole("listitem").last();
361
page.getByRole("listitem").nth(2); // third item (0-indexed)
362
page.getByRole("listitem").nth(-1); // last item
363
364
// Multiple elements
365
const allItems = page.getByRole("listitem").all();
366
for (const item of allItems) {
367
await item.click();
368
}
369
```
370
371
### Query Methods
372
373
Methods for retrieving actual DOM elements from locators.
374
375
```typescript { .api }
376
/**
377
* Returns an element matching the selector. Throws if not found or multiple elements match.
378
*/
379
element(): Element;
380
381
/**
382
* Returns an array of elements matching the selector. Returns empty array if none found.
383
*/
384
elements(): Element[];
385
386
/**
387
* Returns an element matching the selector or null if not found. Throws if multiple elements match.
388
*/
389
query(): Element | null;
390
391
/**
392
* Wraps an array of elements matching the selector in new Locators
393
*/
394
all(): Locator[];
395
```
396
397
**Usage Examples:**
398
399
```typescript
400
import { page } from "@vitest/browser/context";
401
402
// Get single element (throws if not found)
403
const button = page.getByRole("button").element();
404
button.click(); // direct DOM API usage
405
406
// Safe element access
407
const maybeButton = page.getByRole("button").query();
408
if (maybeButton) {
409
maybeButton.click();
410
}
411
412
// Get all matching elements
413
const inputs = page.getByRole("textbox").elements();
414
inputs.forEach(input => {
415
console.log(input.value);
416
});
417
418
// Get locators for all elements
419
const itemLocators = page.getByRole("listitem").all();
420
for (const locator of itemLocators) {
421
await locator.click(); // use locator API
422
}
423
```
424
425
## Types
426
427
Core locator option interfaces:
428
429
```typescript { .api }
430
interface LocatorOptions {
431
/** Whether to find an exact match: case-sensitive and whole-string */
432
exact?: boolean;
433
}
434
435
interface LocatorFilterOptions {
436
/** Text content that element should have */
437
hasText?: string | RegExp;
438
/** Text content that element should NOT have */
439
hasNotText?: string | RegExp;
440
/** Child locator that element should contain */
441
has?: Locator;
442
/** Child locator that element should NOT contain */
443
hasNot?: Locator;
444
}
445
446
interface LocatorScreenshotOptions extends Omit<ScreenshotOptions, 'element'> {
447
path?: string;
448
base64?: boolean;
449
save?: boolean;
450
}
451
```