API d'interaction
Vitest implémente un sous-ensemble des API de @testing-library/user-event
en utilisant le Chrome DevTools Protocol ou webdriver. Cette approche, qui privilégie l'interaction réelle plutôt que la simulation d'événements, garantit un comportement plus fiable et plus proche de celui d'un utilisateur dans le navigateur.
import { userEvent } from '@vitest/browser/context';
await userEvent.click(document.querySelector('.button'));
La plupart des méthodes userEvent
héritent des options de leur fournisseur sous-jacent. Pour bénéficier de l'autocomplétion et afficher toutes les options disponibles dans votre IDE, ajoutez les types webdriver
ou playwright
(selon le fournisseur que vous utilisez) à votre fichier tsconfig.json
:
{
"compilerOptions": {
"types": ["@vitest/browser/providers/playwright"]
}
}
{
"compilerOptions": {
"types": ["@vitest/browser/providers/webdriverio"]
}
}
userEvent.setup
function setup(): UserEvent;
Crée une nouvelle instance d'événement utilisateur. Cette fonction est utile si vous avez besoin de maintenir l'état du clavier pour gérer correctement les appuis et relâchements de touches.
WARNING
Contrairement à @testing-library/user-event
, l'instance userEvent
par défaut de @vitest/browser/context
est créée une seule fois et non à chaque appel de ses méthodes. L'exemple suivant illustre cette différence de comportement :
import { userEvent as vitestUserEvent } from '@vitest/browser/context';
import { userEvent as originalUserEvent } from '@testing-library/user-event';
await vitestUserEvent.keyboard('{Shift}'); // Appuie sur Shift sans relâcher
await vitestUserEvent.keyboard('{/Shift}'); // Relâche Shift
await originalUserEvent.keyboard('{Shift}'); // Appuie sur Shift sans relâcher
await originalUserEvent.keyboard('{/Shift}'); // NE relâche PAS la touche Shift car l'état du clavier est différent
Ce comportement est plus pertinent dans Vitest car nous interagissons réellement avec la touche Shift au lieu de l'émuler. Conserver le comportement original pourrait entraîner des problèmes inattendus lors de la saisie.
userEvent.click
function click(
element: Element | Locator,
options?: UserEventClickOptions
): Promise<void>;
Clique sur un élément. Cette méthode hérite des options du fournisseur. Consultez la documentation de votre fournisseur pour une explication détaillée de son fonctionnement.
import { page, userEvent } from '@vitest/browser/context';
test('clique sur un élément', async () => {
const logo = page.getByRole('img', { name: /logo/ });
await userEvent.click(logo);
// Vous pouvez également appeler la méthode directement sur le localisateur
await logo.click();
});
Références :
userEvent.dblClick
function dblClick(
element: Element | Locator,
options?: UserEventDoubleClickOptions
): Promise<void>;
Déclenche un événement de double-clic sur un élément.
Consultez la documentation de votre fournisseur pour une explication détaillée de son fonctionnement.
import { page, userEvent } from '@vitest/browser/context';
test('déclenche un double-clic sur un élément', async () => {
const logo = page.getByRole('img', { name: /logo/ });
await userEvent.dblClick(logo);
// Vous pouvez également appeler la méthode directement sur le localisateur
await logo.dblClick();
});
Références :
userEvent.tripleClick
function tripleClick(
element: Element | Locator,
options?: UserEventTripleClickOptions
): Promise<void>;
Déclenche un événement de triple-clic sur un élément. Comme il n'existe pas d'événement tripleclick
natif dans l'API du navigateur, cette méthode déclenche trois événements de clic consécutifs. Pour distinguer un triple-clic, vous devez vérifier la propriété detail
de l'événement click : evt.detail === 3
.
Consultez la documentation de votre fournisseur pour une explication détaillée de son fonctionnement.
import { page, userEvent } from '@vitest/browser/context';
test('déclenche un triple-clic sur un élément', async () => {
const logo = page.getByRole('img', { name: /logo/ });
let tripleClickFired = false;
logo.addEventListener('click', evt => {
if (evt.detail === 3) {
tripleClickFired = true;
}
});
await userEvent.tripleClick(logo);
// Vous pouvez également appeler la méthode directement sur le localisateur
await logo.tripleClick();
expect(tripleClickFired).toBe(true);
});
Références :
- API Playwright
locator.click
: Implémenté viaclick
avec l'optionclickCount: 3
. - API WebdriverIO
browser.action
: Implémenté via l'API actions avec unmove
suivi de trois séquencesdown + up + pause
. - API testing-library
tripleClick
userEvent.fill
function fill(element: Element | Locator, text: string): Promise<void>;
Définit la valeur d'un champ input
, textarea
ou d'un élément avec contenteditable
. Cette méthode supprime tout texte existant dans l'élément avant de définir la nouvelle valeur.
import { page, userEvent } from '@vitest/browser/context';
test('met à jour l\'entrée', async () => {
const input = page.getByRole('input');
await userEvent.fill(input, 'foo'); // input.value devient 'foo'
await userEvent.fill(input, '{{a[['); // input.value devient '{{a[['
await userEvent.fill(input, '{Shift}'); // input.value devient '{Shift}'
// Vous pouvez également appeler la méthode directement sur le localisateur
await input.fill('foo'); // input.value devient 'foo'
});
Cette méthode met l'élément au premier plan, le remplit et déclenche un événement input
après le remplissage. Vous pouvez utiliser une chaîne vide pour effacer le champ.
TIP
Cette API est plus rapide que l'utilisation de userEvent.type
ou userEvent.keyboard
, mais elle ne prend pas en charge la syntaxe keyboard
de user-event (par exemple, {Shift}{selectall}
).
Nous recommandons d'utiliser cette API plutôt que userEvent.type
lorsque vous n'avez pas besoin de saisir des caractères spéciaux ou d'un contrôle granulaire sur les événements de frappe.
Références :
userEvent.keyboard
function keyboard(text: string): Promise<void>;
La méthode userEvent.keyboard
permet de déclencher des frappes au clavier. Si un champ de saisie a le focus, les caractères seront tapés dans ce champ. Sinon, les événements clavier seront déclenchés sur l'élément ayant actuellement le focus (ou document.body
s'il n'y a pas d'élément ciblé).
Cette API prend en charge la syntaxe keyboard
de user-event.
import { userEvent } from '@vitest/browser/context';
test('déclenche des frappes au clavier', async () => {
await userEvent.keyboard('foo'); // Simule la frappe de 'f', 'o', 'o'
await userEvent.keyboard('{{a[['); // Simule la frappe de '{', 'a', '['
await userEvent.keyboard('{Shift}{f}{o}{o}'); // Simule l'appui sur Shift, puis la frappe de 'f', 'o', 'o'
await userEvent.keyboard('{a>5}'); // Maintient la touche 'a' enfoncée et déclenche 5 événements keydown
await userEvent.keyboard('{a>5/}'); // Appuie sur 'a' pendant 5 événements keydown, puis relâche la touche
});
Références :
userEvent.tab
function tab(options?: UserEventTabOptions): Promise<void>;
Envoie un événement de touche Tab
. C'est un raccourci pour userEvent.keyboard('{tab}')
.
import { page, userEvent } from '@vitest/browser/context';
test('la tabulation fonctionne', async () => {
const [input1, input2] = page.getByRole('input').elements();
expect(input1).toHaveFocus();
await userEvent.tab();
expect(input2).toHaveFocus();
await userEvent.tab({ shift: true });
expect(input1).toHaveFocus();
});
Références :
userEvent.type
function type(
element: Element | Locator,
text: string,
options?: UserEventTypeOptions
): Promise<void>;
WARNING
Si vous n'avez pas besoin d'utiliser les caractères spéciaux (par exemple, {shift}
ou {selectall}
), il est recommandé d'utiliser userEvent.fill
à la place pour de meilleures performances.
La méthode type
implémente l'utilitaire type
de @testing-library/user-event
, basé sur l'API keyboard
.
Cette fonction permet de taper des caractères dans un élément input, textarea ou un élément avec contenteditable
. Elle prend en charge la syntaxe keyboard
de user-event.
Si vous avez uniquement besoin de simuler des frappes au clavier sans cibler un champ de saisie spécifique, utilisez l'API userEvent.keyboard
.
import { page, userEvent } from '@vitest/browser/context';
test('met à jour l\'entrée', async () => {
const input = page.getByRole('input');
await userEvent.type(input, 'foo'); // input.value devient 'foo'
await userEvent.type(input, '{{a[['); // input.value devient 'foo{a['
await userEvent.type(input, '{Shift}'); // input.value reste 'foo{a[' (Shift n'est pas un caractère tapable)
});
INFO
Vitest n'expose pas la méthode .type
directement sur le localisateur (comme input.type
) car elle est principalement présente pour la compatibilité avec la bibliothèque userEvent
. Envisagez d'utiliser .fill
à la place, car elle est plus rapide.
Références :
userEvent.clear
function clear(element: Element | Locator): Promise<void>;
Cette méthode efface le contenu d'un élément d'entrée.
import { page, userEvent } from '@vitest/browser/context';
test('efface l\'entrée', async () => {
const input = page.getByRole('input');
await userEvent.fill(input, 'foo');
expect(input).toHaveValue('foo');
await userEvent.clear(input);
// Vous pouvez également appeler la méthode directement sur le localisateur
await input.clear();
expect(input).toHaveValue('');
});
Références :
userEvent.selectOptions
function selectOptions(
element: Element | Locator,
values: HTMLElement | HTMLElement[] | Locator | Locator[] | string | string[],
options?: UserEventSelectOptions
): Promise<void>;
La méthode userEvent.selectOptions
permet de sélectionner une ou plusieurs options dans un élément <select>
.
WARNING
Si l'élément select n'a pas l'attribut multiple
, Vitest ne sélectionnera que le premier élément fourni dans le tableau de valeurs.
Contrairement à @testing-library
, Vitest ne prend pas encore en charge les listbox, mais cette fonctionnalité est prévue pour l'avenir.
import { page, userEvent } from '@vitest/browser/context';
test('sélectionne des options', async () => {
const select = page.getByRole('select');
await userEvent.selectOptions(select, 'Option 1');
// Vous pouvez également appeler la méthode directement sur le localisateur
await select.selectOptions('Option 1');
expect(select).toHaveValue('option-1');
await userEvent.selectOptions(select, 'option-1'); // Sélection par valeur
expect(select).toHaveValue('option-1');
await userEvent.selectOptions(select, [
page.getByRole('option', { name: 'Option 1' }),
page.getByRole('option', { name: 'Option 2' }),
]); // Sélection par éléments ou localisateurs
expect(select).toHaveValue(['option-1', 'option-2']);
});
WARNING
Le fournisseur webdriverio
ne prend pas en charge la sélection de plusieurs éléments car son API sous-jacente ne le permet pas.
Références :
- API Playwright
locator.selectOption
- API WebdriverIO
element.selectByIndex
- API testing-library
selectOptions
userEvent.hover
function hover(
element: Element | Locator,
options?: UserEventHoverOptions
): Promise<void>;
Cette méthode déplace le curseur de la souris vers l'élément spécifié. Consultez la documentation de votre fournisseur pour une explication détaillée de son fonctionnement.
WARNING
Si vous utilisez le fournisseur webdriverio
, le curseur se déplacera par défaut au centre de l'élément.
Si vous utilisez le fournisseur playwright
, le curseur se positionne sur un point visible quelconque de l'élément.
import { page, userEvent } from '@vitest/browser/context';
test('survole l\'élément logo', async () => {
const logo = page.getByRole('img', { name: /logo/ });
await userEvent.hover(logo);
// Vous pouvez également appeler la méthode directement sur le localisateur
await logo.hover();
});
Références :
userEvent.unhover
function unhover(
element: Element | Locator,
options?: UserEventHoverOptions
): Promise<void>;
Cette méthode fonctionne de manière similaire à userEvent.hover
, mais déplace le curseur vers l'élément document.body
.
WARNING
Par défaut, la position du curseur est à un endroit visible "quelconque" (avec le fournisseur playwright
) ou au centre (avec le fournisseur webdriverio
) de l'élément body. Par conséquent, si l'élément actuellement survolé est déjà à cette position, cette méthode n'aura aucun effet.
import { page, userEvent } from '@vitest/browser/context';
test('désurvole l\'élément logo', async () => {
const logo = page.getByRole('img', { name: /logo/ });
await userEvent.unhover(logo);
// Vous pouvez également appeler la méthode directement sur le localisateur
await logo.unhover();
});
Références :
userEvent.upload
function upload(
element: Element | Locator,
files: string[] | string | File[] | File
): Promise<void>;
Modifie un élément d'entrée de type file
pour qu'il contienne les fichiers spécifiés.
import { page, userEvent } from '@vitest/browser/context';
test('peut télécharger un fichier', async () => {
const input = page.getByRole('button', { name: /Upload files/ });
const file = new File(['file'], 'file.png', { type: 'image/png' });
await userEvent.upload(input, file);
// Vous pouvez également appeler la méthode directement sur le localisateur
await input.upload(file);
// Vous pouvez également utiliser des chemins de fichiers relatifs au fichier de test
await userEvent.upload(input, '../fixtures/file.png');
});
WARNING
Le fournisseur webdriverio
ne prend en charge cette commande que dans les navigateurs chrome
et edge
. Il ne prend également en charge que les chemins de fichiers (types de chaînes de caractères) pour le moment.
Références :
userEvent.dragAndDrop
function dragAndDrop(
source: Element | Locator,
target: Element | Locator,
options?: UserEventDragAndDropOptions
): Promise<void>;
Fait glisser l'élément source sur l'élément cible. Notez que l'élément source
doit avoir l'attribut draggable
défini sur true
.
import { page, userEvent } from '@vitest/browser/context';
test('le glisser-déposer fonctionne', async () => {
const source = page.getByRole('img', { name: /logo/ });
const target = page.getByTestId('logo-target');
await userEvent.dragAndDrop(source, target);
// Vous pouvez également appeler la méthode directement sur le localisateur
await source.dropTo(target);
await expect.element(target).toHaveTextContent('Logo is processed');
});
WARNING
Cette API n'est pas supportée par le fournisseur preview
par défaut.
Références :