Localisateurs
Un localisateur représente un élément ou un ensemble d'éléments sur une page. Chaque localisateur est défini par une chaîne de caractères appelée sélecteur. Vitest simplifie l'utilisation de ces sélecteurs en fournissant des méthodes pratiques qui les génèrent en arrière-plan.
L'API des localisateurs utilise une version dérivée des localisateurs de Playwright nommée Ivya. Cependant, Vitest rend cette API disponible pour tous les fournisseurs, et pas seulement pour Playwright.
TIP
Cette page décrit l'utilisation de l'API. Pour une compréhension plus approfondie des localisateurs et de leur fonctionnement, veuillez consulter la documentation "Locators" de Playwright.
getByRole
function getByRole(
role: ARIARole | string,
options?: LocatorByRoleOptions
): Locator;
Crée un localisateur pour trouver un élément en fonction de son rôle ARIA, de ses attributs ARIA et de son nom accessible.
TIP
Si vous cherchez un seul élément avec getByText('Le nom')
, il est souvent préférable d'utiliser getByRole(roleAttendu, { name: 'Le nom' })
. La recherche par nom accessible ne remplace pas d'autres requêtes comme *ByAltText
ou *ByTitle
. Bien que le nom accessible puisse correspondre à ces attributs, il n'en remplace pas la fonctionnalité.
Considérez la structure DOM suivante :
<h3>Sign up</h3>
<label>
Login
<input type="text" />
</label>
<label>
Password
<input type="password" />
</label>
<br />
<button>Submit</button>
Vous pouvez localiser chaque élément en fonction de son rôle implicite :
await expect
.element(page.getByRole('heading', { name: 'Sign up' }))
.toBeVisible();
await page.getByRole('textbox', { name: 'Login' }).fill('admin');
await page.getByRole('textbox', { name: 'Password' }).fill('admin');
await page.getByRole('button', { name: /submit/i }).click();
WARNING
Les rôles sont comparés par égalité de chaîne, sans tenir compte de la hiérarchie des rôles ARIA. Par conséquent, une requête pour un rôle de superclasse comme checkbox
n'inclura pas les éléments avec un rôle de sous-classe comme switch
.
Par défaut, de nombreux éléments sémantiques en HTML possèdent un rôle (par exemple, <input type="radio">
a le rôle "radio"). Les éléments non sémantiques en HTML n'ont pas de rôle ; <div>
et <span>
sans sémantique ajoutée retournent null
. L'attribut role
peut ajouter de la sémantique.
Attribuer des rôles via les attributs role
ou aria-*
à des éléments HTML natifs qui possèdent déjà un rôle implicite est fortement déconseillé par les directives ARIA.
Options
exact: boolean
Indique si le
name
doit correspondre exactement : sensible à la casse et correspondance de chaîne complète. Désactivé par défaut. Cette option est ignorée siname
est une expression régulière. Notez que la correspondance exacte ignore toujours les espaces blancs.tsx<button>Hello World</button>; page.getByRole('button', { name: 'hello world' }); // ✅ page.getByRole('button', { name: 'hello world', exact: true }); // ❌ page.getByRole('button', { name: 'Hello World', exact: true }); // ✅
checked: boolean
Indique si les éléments cochés (définis par
aria-checked
ou<input type="checkbox"/>
) doivent être inclus. Par défaut, ce filtre n'est pas appliqué.Voir
aria-checked
pour plus d'informations.tsx<> <button role="checkbox" aria-checked="true" /> <input type="checkbox" checked /> </>; page.getByRole('checkbox', { checked: true }); // ✅ page.getByRole('checkbox', { checked: false }); // ❌
disabled: boolean
Indique si les éléments désactivés doivent être inclus. Par défaut, ce filtre n'est pas appliqué. Notez que, contrairement à d'autres attributs, la propriété
disabled
est héritée.Voir
aria-disabled
pour plus d'informations.tsx<input type="text" disabled />; page.getByRole('textbox', { disabled: true }); // ✅ page.getByRole('textbox', { disabled: false }); // ❌
expanded: boolean
Indique si les éléments étendus doivent être inclus. Par défaut, ce filtre n'est pas appliqué.
Voir
aria-expanded
pour plus d'informations.tsx<a aria-expanded="true" href="example.com"> Link </a>; page.getByRole('link', { expanded: true }); // ✅ page.getByRole('link', { expanded: false }); // ❌
includeHidden: boolean
Indique si les éléments normalement exclus de l'arbre d'accessibilité doivent être interrogés. Par défaut, seuls les éléments non masqués correspondent au sélecteur de rôle.
Notez que les rôles
none
etpresentation
sont toujours inclus.tsx<button style="display: none" />; page.getByRole('button'); // ❌ page.getByRole('button', { includeHidden: false }); // ❌ page.getByRole('button', { includeHidden: true }); // ✅
level: number
Un attribut numérique généralement présent pour les rôles
heading
,listitem
,row
,treeitem
avec des valeurs par défaut pour les éléments<h1>-<h6>
. Par défaut, ce filtre n'est pas appliqué.Voir
aria-level
pour plus d'informations.tsx<> <h1>Heading Level One</h1> <div role="heading" aria-level="1"> Second Heading Level One </div> </>; page.getByRole('heading', { level: 1 }); // ✅ page.getByRole('heading', { level: 2 }); // ❌
name: string | RegExp
Un nom accessible. Par défaut, la correspondance est insensible à la casse et effectue une recherche de sous-chaîne. Utilisez l'option
exact
pour contrôler ce comportement.tsx<button>Click Me!</button>; page.getByRole('button', { name: 'Click Me!' }); // ✅ page.getByRole('button', { name: 'click me!' }); // ✅ page.getByRole('button', { name: 'Click Me?' }); // ❌
pressed: boolean
Indique si les éléments pressés doivent être inclus. Par défaut, ce filtre n'est pas appliqué.
Voir
aria-pressed
pour plus d'informations.tsx<button aria-pressed="true">👍</button>; page.getByRole('button', { pressed: true }); // ✅ page.getByRole('button', { pressed: false }); // ❌
selected: boolean
Indique si les éléments sélectionnés doivent être inclus. Par défaut, ce filtre n'est pas appliqué.
Voir
aria-selected
pour plus d'informations.tsx<button role="tab" aria-selected="true"> Vue </button>; page.getByRole('button', { selected: true }); // ✅ page.getByRole('button', { selected: false }); // ❌
Voir aussi
getByAltText
function getByAltText(text: string | RegExp, options?: LocatorOptions): Locator;
Crée un localisateur capable de trouver un élément avec un attribut alt
qui correspond au texte. Contrairement à l'implémentation de testing-library, Vitest correspondra à tout élément ayant un attribut alt
correspondant.
<img alt="Incredibles 2 Poster" src="/incredibles-2.png" />;
page.getByAltText(/incredibles.*? poster/i); // ✅
page.getByAltText('non existing alt text'); // ❌
Options
exact: boolean
Indique si le
text
doit correspondre exactement : sensible à la casse et correspondance de chaîne complète. Désactivé par défaut. Cette option est ignorée sitext
est une expression régulière. Notez que la correspondance exacte ignore toujours les espaces blancs.
Voir aussi
getByLabelText
function getByLabelText(
text: string | RegExp,
options?: LocatorOptions
): Locator;
Crée un localisateur capable de trouver un élément associé à une étiquette.
Le localisateur page.getByLabelText('Username')
trouvera tous les champs de saisie dans l'exemple ci-dessous :
// Relation `for`/`htmlFor` entre l'étiquette et l'ID de l'élément de formulaire
<label for="username-input">Username</label>
<input id="username-input" />
// Attribut `aria-labelledby` avec les éléments de formulaire
<label id="username-label">Username</label>
<input aria-labelledby="username-label" />
// Étiquettes englobantes
<label>Username <input /></label>
// Étiquettes englobantes où le texte de l'étiquette se trouve dans un autre élément enfant
<label>
<span>Username</span>
<input />
</label>
// Attribut `aria-label`
// Attention : ce n'est pas une étiquette visible par les utilisateurs sur la page. L'objectif de votre champ de saisie doit donc être évident pour les utilisateurs visuels.
<input aria-label="Username" />
Options
exact: boolean
Indique si le
text
doit correspondre exactement : sensible à la casse et correspondance de chaîne complète. Désactivé par défaut. Cette option est ignorée sitext
est une expression régulière. Notez que la correspondance exacte ignore toujours les espaces blancs.
Voir aussi
getByPlaceholder
function getByPlaceholder(
text: string | RegExp,
options?: LocatorOptions
): Locator;
Crée un localisateur capable de trouver un élément qui possède l'attribut placeholder
spécifié. Vitest correspondra à tout élément ayant un attribut placeholder
correspondant, pas seulement les éléments input
.
<input placeholder="Username" />;
page.getByPlaceholder('Username'); // ✅
page.getByPlaceholder('not found'); // ❌
WARNING
Il est généralement préférable de privilégier une étiquette en utilisant getByLabelText
plutôt qu'un placeholder.
Options
exact: boolean
Indique si le
text
doit correspondre exactement : sensible à la casse et correspondance de chaîne complète. Désactivé par default. Cette option est ignorée sitext
est une expression régulière. Notez que la correspondance exacte ignore toujours les espaces blancs.
Voir aussi
getByText
function getByText(text: string | RegExp, options?: LocatorOptions): Locator;
Crée un localisateur capable de trouver un élément qui contient le texte spécifié. Le texte sera mis en correspondance avec le nodeValue
d'un TextNode
ou la valeur d'un champ de saisie si le type est button
ou reset
. La correspondance par texte normalise toujours les espaces blancs, même avec une correspondance exacte. Par exemple, elle transforme plusieurs espaces en un seul, les sauts de ligne en espaces, et ignore les espaces blancs de début et de fin.
<a href="/about">About ℹ️</a>;
page.getByText(/about/i); // ✅
page.getByText('about', { exact: true }); // ❌
TIP
Ce localisateur est utile pour localiser des éléments non interactifs. Si vous avez besoin de localiser un élément interactif, comme un bouton ou un champ de saisie, préférez getByRole
.
Options
exact: boolean
Indique si le
text
doit correspondre exactement : sensible à la casse et correspondance de chaîne complète. Désactivé par défaut. Cette option est ignorée sitext
est une expression régulière. Notez que la correspondance exacte ignore toujours les espaces blancs.
Voir aussi
getByTitle
function getByTitle(text: string | RegExp, options?: LocatorOptions): Locator;
Crée un localisateur capable de trouver un élément qui possède l'attribut title
spécifié. Contrairement à getByTitle
de testing-library, Vitest ne peut pas trouver les éléments title
à l'intérieur d'un SVG.
<span title="Delete" id="2"></span>;
page.getByTitle('Delete'); // ✅
page.getByTitle('Create'); // ❌
Options
exact: boolean
Indique si le
text
doit correspondre exactement : sensible à la casse et correspondance de chaîne complète. Désactivé par défaut. Cette option est ignorée sitext
est une expression régulière. Notez que la correspondance exacte ignore toujours les espaces blancs.
Voir aussi
getByTestId
function getByTestId(text: string | RegExp): Locator;
Crée un localisateur capable de trouver un élément qui correspond à l'attribut d'ID de test spécifié. Vous pouvez configurer le nom de l'attribut avec browser.locators.testIdAttribute
.
<div data-testid="custom-element" />;
page.getByTestId('custom-element'); // ✅
page.getByTestId('non-existing-element'); // ❌
WARNING
Il est recommandé de n'utiliser cette méthode que si les autres localisateurs ne conviennent pas à votre cas d'utilisation. L'utilisation d'attributs data-testid
ne reflète pas la manière dont votre logiciel est utilisé et devrait être évitée si possible.
Options
exact: boolean
Indique si le
text
doit correspondre exactement : sensible à la casse et correspondance de chaîne complète. Désactivé par défaut. Cette option est ignorée sitext
est une expression régulière. Notez que la correspondance exacte ignore toujours les espaces blancs.
Voir aussi
nth
function nth(index: number): Locator;
Cette méthode renvoie un nouveau localisateur qui ne correspond qu'à un index spécifique dans un résultat de requête multi-éléments. L'indexation commence à zéro, nth(0)
sélectionne le premier élément. Contrairement à elements()[n]
, le localisateur nth
sera réessayé jusqu'à ce que l'élément soit présent.
<div aria-label="one"><input /><input /><input /></div>
<div aria-label="two"><input /></div>
page.getByRole('textbox').nth(0); // ✅
page.getByRole('textbox').nth(4); // ❌
TIP
Avant de recourir à nth
, vous pourriez trouver utile d'utiliser des localisateurs chaînés pour affiner votre recherche. Parfois, il n'y a pas de meilleure façon de distinguer les éléments que par leur position ; bien que cela puisse entraîner des flakes (tests instables), c'est mieux que rien.
page.getByLabel('two').getByRole('input'); // ✅ meilleure alternative à page.getByRole('textbox').nth(3)
page.getByLabel('one').getByRole('input'); // ❌ trop ambigu
page.getByLabel('one').getByRole('input').nth(1); // ✅ compromis pragmatique
first
function first(): Locator;
Cette méthode renvoie un nouveau localisateur qui ne correspond qu'au premier élément d'un résultat de requête multi-éléments. C'est un raccourci pour nth(0)
.
<input /> <input /> <input />
page.getByRole('textbox').first(); // ✅
last
function last(): Locator;
Cette méthode renvoie un nouveau localisateur qui ne correspond qu'au dernier élément d'un résultat de requête multi-éléments. C'est un raccourci pour nth(-1)
.
<input /> <input /> <input />
page.getByRole('textbox').last(); // ✅
and
function and(locator: Locator): Locator;
Cette méthode crée un nouveau localisateur qui correspond à la fois au localisateur parent et au localisateur fourni. L'exemple suivant trouve un bouton avec un titre spécifique :
page.getByRole('button').and(page.getByTitle('Subscribe'));
or
function or(locator: Locator): Locator;
Cette méthode crée un nouveau localisateur qui correspond à l'un ou l'autre des localisateurs, ou aux deux.
WARNING
Notez que si le localisateur correspond à plus d'un élément, l'appel d'une autre méthode peut déclencher une erreur si elle attend un seul élément :
<>
<button>Click me</button>
<a href="https://vitest.dev">Error happened!</a>
</>;
page.getByRole('button').or(page.getByRole('link')).click(); // ❌ correspond à plusieurs éléments
filter
function filter(options: LocatorOptions): Locator;
Cette méthode affine le localisateur en fonction des options, comme le filtrage par texte. Elle peut être chaînée pour appliquer plusieurs filtres.
has
- Type :
Locator
Cette option affine le sélecteur pour qu'il corresponde aux éléments contenant d'autres éléments correspondant au localisateur fourni. Par exemple, avec ce HTML :
<article>
<div>Vitest</div>
</article>
<article>
<div>Rolldown</div>
</article>
Nous pouvons affiner le localisateur pour ne trouver que l'article
contenant le texte Vitest
:
page.getByRole('article').filter({ has: page.getByText('Vitest') }); // ✅
WARNING
Le localisateur fourni (page.getByText('Vitest')
dans l'exemple) doit être relatif au localisateur parent (page.getByRole('article')
dans l'exemple). Il sera interrogé à partir du localisateur parent, et non de la racine du document.
Cela signifie que vous ne pouvez pas passer un localisateur qui interroge un élément en dehors du localisateur parent :
page.getByText('Vitest').filter({ has: page.getByRole('article') }); // ❌
Cet exemple échouera car l'élément article
est en dehors de l'élément avec le texte Vitest
.
TIP
Cette méthode peut être chaînée pour affiner davantage l'élément :
page
.getByRole('article')
.filter({ has: page.getByRole('button', { name: 'delete row' }) })
.filter({ has: page.getByText('Vitest') });
hasNot
- Type :
Locator
Cette option affine le sélecteur pour qu'il corresponde aux éléments qui ne contiennent pas d'autres éléments correspondant au localisateur fourni. Par exemple, avec ce HTML :
<article>
<div>Vitest</div>
</article>
<article>
<div>Rolldown</div>
</article>
Nous pouvons affiner le localisateur pour ne trouver que l'article
qui ne contient pas Rolldown
.
page.getByRole('article').filter({ hasNot: page.getByText('Rolldown') }); // ✅
page.getByRole('article').filter({ hasNot: page.getByText('Vitest') }); // ❌
WARNING
Notez que le localisateur fourni est interrogé par rapport au parent, et non à la racine du document, tout comme l'option has
.
hasText
- Type :
string | RegExp
Cette option affine le sélecteur pour qu'il ne corresponde qu'aux éléments qui contiennent le texte fourni quelque part à l'intérieur. Lorsque la string
est passée, la correspondance est insensible à la casse et effectue une recherche de sous-chaîne.
<article>
<div>Vitest</div>
</article>
<article>
<div>Rolldown</div>
</article>
Les deux localisateurs trouveront le même élément car la recherche est insensible à la casse :
page.getByRole('article').filter({ hasText: 'Vitest' }); // ✅
page.getByRole('article').filter({ hasText: 'Vite' }); // ✅
hasNotText
- Type :
string | RegExp
Cette option affine le sélecteur pour qu'il ne corresponde qu'aux éléments qui ne contiennent pas le texte fourni quelque part à l'intérieur. Lorsque la string
est passée, la correspondance est insensible à la casse et effectue une recherche de sous-chaîne.
Méthodes
Toutes les méthodes sont asynchrones et doivent être attendues. Depuis Vitest 3, les tests échoueront si une méthode n'est pas attendue.
click
function click(options?: UserEventClickOptions): Promise<void>;
Clique sur un élément. Vous pouvez utiliser les options pour définir la position du curseur.
import { page } from '@vitest/browser/context';
await page.getByRole('img', { name: 'Rose' }).click();
dblClick
function dblClick(options?: UserEventDoubleClickOptions): Promise<void>;
Déclenche un événement de double-clic sur un élément. Vous pouvez utiliser les options pour définir la position du curseur.
import { page } from '@vitest/browser/context';
await page.getByRole('img', { name: 'Rose' }).dblClick();
tripleClick
function tripleClick(options?: UserEventTripleClickOptions): Promise<void>;
Déclenche un événement de triple-clic sur un élément. Comme il n'y a pas de tripleclick
dans l'API du navigateur, cette méthode déclenchera trois événements de clic consécutifs.
import { page } from '@vitest/browser/context';
await page.getByRole('img', { name: 'Rose' }).tripleClick();
clear
function clear(options?: UserEventClearOptions): Promise<void>;
Efface le contenu de l'élément d'entrée.
import { page } from '@vitest/browser/context';
await page.getByRole('textbox', { name: 'Full Name' }).clear();
hover
function hover(options?: UserEventHoverOptions): Promise<void>;
Déplace la position du curseur vers l'élément sélectionné.
import { page } from '@vitest/browser/context';
await page.getByRole('img', { name: 'Rose' }).hover();
unhover
function unhover(options?: UserEventHoverOptions): Promise<void>;
Cette méthode fonctionne de la même manière que locator.hover
, mais déplace le curseur vers l'élément document.body
à la place.
import { page } from '@vitest/browser/context';
await page.getByRole('img', { name: 'Rose' }).unhover();
fill
function fill(text: string, options?: UserEventFillOptions): Promise<void>;
Définit la valeur du champ input
, textarea
ou de l'élément contenteditable
actuel.
import { page } from '@vitest/browser/context';
await page.getByRole('input', { name: 'Full Name' }).fill('Mr. Bean');
dropTo
function dropTo(
target: Locator,
options?: UserEventDragAndDropOptions
): Promise<void>;
Fait glisser l'élément actuel vers l'emplacement cible.
import { page } from '@vitest/browser/context';
const paris = page.getByText('Paris');
const france = page.getByText('France');
await paris.dropTo(france);
selectOptions
function selectOptions(
values: HTMLElement | HTMLElement[] | Locator | Locator[] | string | string[],
options?: UserEventSelectOptions
): Promise<void>;
Permet de choisir une ou plusieurs valeurs dans un élément <select>
.
import { page } from '@vitest/browser/context';
const languages = page.getByRole('select', { name: 'Languages' });
await languages.selectOptions('EN');
await languages.selectOptions(['ES', 'FR']);
await languages.selectOptions([
languages.getByRole('option', { name: 'Spanish' }),
languages.getByRole('option', { name: 'French' }),
]);
screenshot
function screenshot(
options: LocatorScreenshotOptions & { save: false }
): Promise<string>;
function screenshot(
options: LocatorScreenshotOptions & { base64: true }
): Promise<{
path: string;
base64: string;
}>;
function screenshot(
options?: LocatorScreenshotOptions & { base64?: false }
): Promise<string>;
Crée une capture d'écran de l'élément correspondant au sélecteur du localisateur.
Vous pouvez spécifier l'emplacement de sauvegarde de la capture d'écran à l'aide de l'option path
, qui est relative au fichier de test actuel. Si l'option path
n'est pas définie, Vitest utilisera par défaut browser.screenshotDirectory
(__screenshot__
par défaut), ainsi que les noms du fichier et du test pour déterminer le chemin d'accès de la capture d'écran.
Si vous avez également besoin du contenu de la capture d'écran, vous pouvez spécifier base64: true
pour le retourner avec le chemin du fichier où la capture d'écran est enregistrée.
import { page } from '@vitest/browser/context';
const button = page.getByRole('button', { name: 'Click Me!' });
const path = await button.screenshot();
const { path, base64 } = await button.screenshot({
path: './button-click-me.png',
base64: true, // retourne aussi la chaîne encodée en base64
});
// path - chemin complet vers la capture d'écran
// base64 - chaîne encodée en base64 de la capture d'écran
ATTENTION 3.2.0+
Notez que screenshot
retournera toujours une chaîne base64 si save
est défini sur false
. Le path
est également ignoré dans ce cas.
query
function query(): Element | null;
Cette méthode renvoie un seul élément correspondant au sélecteur du localisateur ou null
si aucun élément n'est trouvé.
Si plusieurs éléments correspondent au sélecteur, cette méthode déclenchera une erreur. Utilisez .elements()
lorsque vous avez besoin de tous les éléments DOM correspondants ou .all()
si vous avez besoin d'un tableau de localisateurs correspondant au sélecteur.
Considérez la structure DOM suivante :
<div>Hello <span>World</span></div>
<div>Hello</div>
Ces localisateurs ne déclencheront pas d'erreur :
page.getByText('Hello World').query(); // ✅ HTMLDivElement
page.getByText('Hello Germany').query(); // ✅ null
page.getByText('World').query(); // ✅ HTMLSpanElement
page.getByText('Hello', { exact: true }).query(); // ✅ HTMLSpanElement
Ces localisateurs déclencheront une erreur :
// retourne plusieurs éléments
page.getByText('Hello').query(); // ❌
page.getByText(/^Hello/).query(); // ❌
element
function element(): Element;
Cette méthode renvoie un seul élément correspondant au sélecteur du localisateur.
Si aucun élément ne correspond au sélecteur, une erreur est déclenchée. Envisagez d'utiliser .query()
lorsque vous avez juste besoin de vérifier si l'élément existe.
Si plusieurs éléments correspondent au sélecteur, une erreur est déclenchée. Utilisez .elements()
lorsque vous avez besoin de tous les éléments DOM correspondants ou .all()
si vous avez besoin d'un tableau de localisateurs correspondant au sélecteur.
TIP
Cette méthode peut être utile si vous devez la transmettre à une bibliothèque externe. Elle est appelée automatiquement lorsque le localisateur est utilisé avec expect.element
chaque fois que l'assertion est réessayée :
await expect.element(page.getByRole('button')).toBeDisabled();
Considérez la structure DOM suivante :
<div>Hello <span>World</span></div>
<div>Hello Germany</div>
<div>Hello</div>
Ces localisateurs ne déclencheront pas d'erreur :
page.getByText('Hello World').element(); // ✅
page.getByText('Hello Germany').element(); // ✅
page.getByText('World').element(); // ✅
page.getByText('Hello', { exact: true }).element(); // ✅
Ces localisateurs déclencheront une erreur :
// retourne plusieurs éléments
page.getByText('Hello').element(); // ❌
page.getByText(/^Hello/).element(); // ❌
// ne retourne aucun élément
page.getByText('Hello USA').element(); // ❌
elements
function elements(): Element[];
Cette méthode renvoie un tableau d'éléments correspondant au sélecteur du localisateur.
Cette fonction ne déclenche jamais d'erreur. S'il n'y a aucun élément correspondant au sélecteur, cette méthode renverra un tableau vide.
Considérez la structure DOM suivante :
<div>Hello <span>World</span></div>
<div>Hello</div>
Ces localisateurs réussiront toujours :
page.getByText('Hello World').elements(); // ✅ [HTMLElement]
page.getByText('World').elements(); // ✅ [HTMLElement]
page.getByText('Hello', { exact: true }).elements(); // ✅ [HTMLElement]
page.getByText('Hello').element(); // ✅ [HTMLElement, HTMLElement]
page.getByText('Hello USA').elements(); // ✅ []
all
function all(): Locator[];
Cette méthode renvoie un tableau de nouveaux localisateurs qui correspondent au sélecteur.
En interne, cette méthode appelle .elements
et enveloppe chaque élément en utilisant page.elementLocator
.
Propriétés
selector
Le selector
est une chaîne de caractères qui sera utilisée pour localiser l'élément par le fournisseur de navigateur. Playwright utilisera une syntaxe de localisateur playwright
tandis que preview
et webdriverio
utiliseront CSS.
DANGER
Vous ne devez pas utiliser cette chaîne directement dans votre code de test. La chaîne selector
ne doit être utilisée que lorsque vous travaillez avec l'API Commands :
import type { BrowserCommand } from 'vitest/node';
const test: BrowserCommand<string> = function test(context, selector) {
// playwright
await context.iframe.locator(selector).click();
// webdriverio
await context.browser.$(selector).click();
};
import { test } from 'vitest';
import { commands, page } from '@vitest/browser/context';
test('works correctly', async () => {
await commands.test(page.getByText('Hello').selector); // ✅
// Vitest le convertira automatiquement en une chaîne
await commands.test(page.getByText('Hello')); // ✅
});
Localisateurs personnalisés 3.2.0+ avancé
Vous pouvez étendre l'API des localisateurs intégrés en définissant un objet de fabriques de localisateurs. Ces méthodes existeront en tant que méthodes sur l'objet page
et sur tout localisateur créé.
Ces localisateurs peuvent être utiles si les localisateurs intégrés ne suffisent pas, par exemple, lorsque vous utilisez un framework personnalisé pour votre interface utilisateur.
La fabrique de localisateurs doit retourner une chaîne de sélecteur ou un localisateur lui-même.
TIP
La syntaxe du sélecteur est identique à celle des localisateurs Playwright. Veuillez lire leur guide pour mieux comprendre comment les utiliser.
import { locators } from '@vitest/browser/context';
locators.extend({
getByArticleTitle(title) {
return `[data-title="${title}"]`;
},
getByArticleCommentsCount(count) {
return `.comments :text("${count} comments")`;
},
async previewComments() {
// Notez que si la méthode a été appelée sur `page`, `this` sera `page`,
// et non le localisateur !
if (this !== page) {
await this.click();
}
// ...
},
});
// Si vous utilisez TypeScript, vous pouvez étendre l'interface LocatorSelectors
// pour avoir l'autocomplétion dans les méthodes locators.extend, page.* et locator.*
declare module '@vitest/browser/context' {
interface LocatorSelectors {
// Si la méthode personnalisée retourne une chaîne, elle sera convertie en localisateur.
// Si elle retourne autre chose, alors elle sera retournée telle quelle.
getByArticleTitle(title: string): Locator;
getByArticleCommentsCount(count: number): Locator;
// Vitest retournera une promesse et n'essaiera pas de la convertir en localisateur.
previewComments(this: Locator): Promise<void>;
}
}
Si la méthode est appelée sur l'objet page
global, le sélecteur sera appliqué à toute la page. Dans l'exemple ci-dessous, getByArticleTitle
trouvera tous les éléments avec un attribut data-title
dont la valeur est title
. Cependant, si la méthode est appelée sur un localisateur, elle sera limitée à ce localisateur.
<article data-title="Hello, World!">
Hello, World!
<button id="comments">2 comments</button>
</article>
<article data-title="Hello, Vitest!">
Hello, Vitest!
<button id="comments">0 comments</button>
</article>
const articles = page.getByRole('article');
const worldArticle = page.getByArticleTitle('Hello, World!'); // ✅
const commentsElement = worldArticle.getByArticleCommentsCount(2); // ✅
const wrongCommentsElement = worldArticle.getByArticleCommentsCount(0); // ❌
const wrongElement = page.getByArticleTitle('No Article!'); // ❌
await commentsElement.previewComments(); // ✅
await wrongCommentsElement.previewComments(); // ❌