@@ -450,6 +450,148 @@ It is sugar for `nth(-1)`.
450
450
page.getByRole('textbox').last() // ✅
451
451
` ` `
452
452
453
+ ## and
454
+
455
+ ` ` ` ts
456
+ function and(locator: Locator): Locator
457
+ ` ` `
458
+
459
+ This method creates a new locator that matches both the parent and provided locator . The following example finds a button with a specific title :
460
+
461
+ ` ` ` ts
462
+ page.getByRole('button').and(page.getByTitle('Subscribe'))
463
+ ` ` `
464
+
465
+ ## or
466
+
467
+ ` ` ` ts
468
+ function or(locator: Locator): Locator
469
+ ` ` `
470
+
471
+ This method creates a new locator that matches either one or both locators .
472
+
473
+ ::: warning
474
+ Note that if locator matches more than a single element , calling another method might throw an error if it expects a single element :
475
+
476
+ ` ` ` tsx
477
+ <>
478
+ <button>Click me</button>
479
+ <a href="https://vitest.dev">Error happened!</a>
480
+ </>
481
+
482
+ page.getByRole('button')
483
+ .or(page.getByRole('link'))
484
+ .click() // ❌ matches multiple elements
485
+ ` ` `
486
+ :::
487
+
488
+ ## filter
489
+
490
+ ` ` ` ts
491
+ function filter(options: LocatorOptions): Locator
492
+ ` ` `
493
+
494
+ This methods narrows down the locator according to the options , such as filtering by text . It can be chained to apply multiple filters .
495
+
496
+ ### has
497
+
498
+ - ** Type :** ` Locator `
499
+
500
+ This options narrows down the selector to match elements that contain other elements matching provided locator . For example , with this HTML :
501
+
502
+ ` ` ` html{1,3}
503
+ <article>
504
+ <div>Vitest</div>
505
+ </article>
506
+ <article>
507
+ <div>Rolldown</div>
508
+ </article>
509
+ ` ` `
510
+
511
+ We can narrow down the locator to only find the ` article ` with ` Vitest ` text inside :
512
+
513
+ ` ` ` ts
514
+ page.getByRole('article').filter({ has: page.getByText('Vitest') }) // ✅
515
+ ` ` `
516
+
517
+ ::: warning
518
+ Provided locator (` page.getByText('Vitest') ` in the example ) must be relative to the parent locator (` page.getByRole('article') ` in the example ). It will be queried starting with the parent locator , not the document root .
519
+
520
+ Meaning , you cannot pass down a locator that queries the element outside of the parent locator :
521
+
522
+ ` ` ` ts
523
+ page.getByText('Vitest').filter({ has: page.getByRole('article') }) // ❌
524
+ ` ` `
525
+
526
+ This example will fail because the ` article ` element is outside the element with ` Vitest ` text .
527
+ :::
528
+
529
+ ::: tip
530
+ This method can be chained to narrow down the element even further :
531
+
532
+ ` ` ` ts
533
+ page.getByRole('article')
534
+ .filter({ has: page.getByRole('button', { name: 'delete row' }) })
535
+ .filter({ has: page.getByText('Vitest') })
536
+ ` ` `
537
+ :::
538
+
539
+ ### hasNot
540
+
541
+ - ** Type :** ` Locator `
542
+
543
+ This option narrows down the selector to match elements that do not contain other elements matching provided locator . For example , with this HTML :
544
+
545
+ ` ` ` html{1,3}
546
+ <article>
547
+ <div>Vitest</div>
548
+ </article>
549
+ <article>
550
+ <div>Rolldown</div>
551
+ </article>
552
+ ` ` `
553
+
554
+ We can narrow down the locator to only find the ` article ` that doesn ' t have `Rolldown` inside.
555
+
556
+ ` ` ` ts
557
+ page.getByRole('article')
558
+ .filter({ hasNot: page.getByText('Rolldown') }) // ✅
559
+ page.getByRole('article')
560
+ .filter({ hasNot: page.getByText('Vitest') }) // ❌
561
+ ` ` `
562
+
563
+ ::: warning
564
+ Note that provided locator is queried against the parent , not the document root , just like [` has ` ](#has ) option .
565
+ :::
566
+
567
+ ### hasText
568
+
569
+ - ** Type :** ` string | RegExp `
570
+
571
+ This options narrows down the selector to only match elements that contain provided text somewhere inside . When the ` string ` is passed , matching is case - insensitive and searches for a substring .
572
+
573
+ ` ` ` html{1,3}
574
+ <article>
575
+ <div>Vitest</div>
576
+ </article>
577
+ <article>
578
+ <div>Rolldown</div>
579
+ </article>
580
+ ` ` `
581
+
582
+ Both locators will find the same element because the search is case - insensitive :
583
+
584
+ ` ` ` ts
585
+ page.getByRole('article').filter({ hasText: 'Vitest' }) // ✅
586
+ page.getByRole('article').filter({ hasText: 'Vite' }) // ✅
587
+ ` ` `
588
+
589
+ ### hasNotText
590
+
591
+ - ** Type :** ` string | RegExp `
592
+
593
+ This options narrows down the selector to only match elements that do not contain provided text somewhere inside . When the ` string ` is passed , matching is case - insensitive and searches for a substring .
594
+
453
595
## Methods
454
596
455
597
All methods are asynchronous and must be awaited . Since Vitest 3 , tests will fail if a method is not awaited .
0 commit comments