Interaktions-API
Vitest implementiert einen Teil der APIs von @testing-library/user-event
. Dabei werden das Chrome DevTools Protocol oder webdriver anstatt gefälschter Ereignisse verwendet. Dies führt zu einem zuverlässigeren Browserverhalten, das besser mit der Art und Weise übereinstimmt, wie Benutzer mit einer Seite interagieren.
import { userEvent } from '@vitest/browser/context';
await userEvent.click(document.querySelector('.button'));
Fast jede Methode von userEvent
erbt die Optionen des Providers. Um alle verfügbaren Optionen in Ihrer IDE zu sehen, fügen Sie die Typen für webdriver
oder playwright
(abhängig von Ihrem Provider) zu Ihrer tsconfig.json
-Datei hinzu:
{
"compilerOptions": {
"types": ["@vitest/browser/providers/playwright"]
}
}
{
"compilerOptions": {
"types": ["@vitest/browser/providers/webdriverio"]
}
}
userEvent.setup
function setup(): UserEvent;
Erstellt eine neue userEvent
-Instanz. Dies ist nützlich, um den Zustand der Tastatur beizubehalten und Tasten korrekt zu drücken und wieder loszulassen.
WARNING
Im Gegensatz zu @testing-library/user-event
wird die Standard-userEvent
-Instanz von @vitest/browser/context
einmal erstellt und nicht bei jedem Aufruf ihrer Methoden. Den Unterschied in der Funktionsweise können Sie in diesem Snippet sehen:
import { userEvent as vitestUserEvent } from '@vitest/browser/context';
import { userEvent as originalUserEvent } from '@testing-library/user-event';
await vitestUserEvent.keyboard('{Shift}'); // Shift drücken, ohne sie loszulassen
await vitestUserEvent.keyboard('{/Shift}'); // Shift wieder loslassen
await originalUserEvent.keyboard('{Shift}'); // Shift drücken, ohne loszulassen
await originalUserEvent.keyboard('{/Shift}'); // Shift wurde NICHT losgelassen, da der Zustand anders ist
Dieses Verhalten ist nützlicher, da wir die Tastatur nicht emulieren, sondern tatsächlich die Shift-Taste drücken. Das Beibehalten des ursprünglichen Verhaltens würde zu unerwarteten Problemen beim Tippen in das Feld führen.
userEvent.click
function click(
element: Element | Locator,
options?: UserEventClickOptions
): Promise<void>;
Klickt auf ein Element. Erbt die Optionen des Providers. Bitte beachten Sie die Dokumentation Ihres Providers für eine detaillierte Erklärung, wie diese Methode funktioniert.
import { page, userEvent } from '@vitest/browser/context';
test('clicks on an element', async () => {
const logo = page.getByRole('img', { name: /logo/ });
await userEvent.click(logo);
// oder Sie können direkt über den Locator darauf zugreifen
await logo.click();
});
Referenzen:
userEvent.dblClick
function dblClick(
element: Element | Locator,
options?: UserEventDoubleClickOptions
): Promise<void>;
Löst ein Doppelklickereignis auf einem Element aus.
Bitte beachten Sie die Dokumentation Ihres Providers für eine detaillierte Erklärung, wie diese Methode funktioniert.
import { page, userEvent } from '@vitest/browser/context';
test('triggers a double click on an element', async () => {
const logo = page.getByRole('img', { name: /logo/ });
await userEvent.dblClick(logo);
// oder Sie können direkt über den Locator darauf zugreifen
await logo.dblClick();
});
Referenzen:
userEvent.tripleClick
function tripleClick(
element: Element | Locator,
options?: UserEventTripleClickOptions
): Promise<void>;
Löst ein Dreifachklickereignis auf einem Element aus. Da die Browser-API kein tripleclick
unterstützt, löst diese Methode drei Klick-Ereignisse hintereinander aus. Sie müssen daher das Detail des Klick-Ereignisses überprüfen, um das Ereignis zu filtern: evt.detail === 3
.
Bitte beachten Sie die Dokumentation Ihres Providers für eine detaillierte Erklärung, wie diese Methode funktioniert.
import { page, userEvent } from '@vitest/browser/context';
test('triggers a triple click on an element', 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);
// oder Sie können direkt über den Locator darauf zugreifen
await logo.tripleClick();
expect(tripleClickFired).toBe(true);
});
Referenzen:
- Playwright
locator.click
API: implementiert überclick
mitclickCount: 3
. - WebdriverIO
browser.action
API: implementiert über die Actions API mitmove
plus dreidown + up + pause
Ereignissen hintereinander - testing-library
tripleClick
API
userEvent.fill
function fill(element: Element | Locator, text: string): Promise<void>;
Setzt einen Wert in das input
-, textarea
- oder contenteditable
-Feld. Dadurch wird jeglicher vorhandener Text im Eingabefeld entfernt, bevor der neue Wert gesetzt wird.
import { page, userEvent } from '@vitest/browser/context';
test('update input', async () => {
const input = page.getByRole('input');
await userEvent.fill(input, 'foo'); // input.value == foo
await userEvent.fill(input, '{{a[['); // input.value == {{a[[
await userEvent.fill(input, '{Shift}'); // input.value == {Shift}
// oder Sie können direkt über den Locator darauf zugreifen
await input.fill('foo'); // input.value == foo
});
Diese Methode fokussiert das Element, füllt es und löst nach dem Füllen ein input
-Ereignis aus. Sie können einen leeren String verwenden, um das Feld zu leeren.
TIP
Diese API ist schneller als die Verwendung von userEvent.type
oder userEvent.keyboard
, aber sie unterstützt nicht die keyboard
-Syntax von user-event (z. B. {Shift}{selectall}
).
Wir empfehlen die Verwendung dieser API anstelle von userEvent.type
in Situationen, in denen Sie keine Sonderzeichen eingeben oder keine granulare Kontrolle über Tastenanschlagereignisse benötigen.
Referenzen:
userEvent.keyboard
function keyboard(text: string): Promise<void>;
Mit userEvent.keyboard
können Sie Tastaturanschläge auslösen. Wenn ein Eingabefeld den Fokus hat, werden die Zeichen in dieses Eingabefeld eingegeben. Andernfalls werden Tastaturereignisse auf dem aktuell fokussierten Element ausgelöst (document.body
, wenn keine Elemente fokussiert sind).
Diese API unterstützt die keyboard
-Syntax von user-event.
import { userEvent } from '@vitest/browser/context';
test('trigger keystrokes', async () => {
await userEvent.keyboard('foo'); // entspricht: f, o, o
await userEvent.keyboard('{{a[['); // entspricht: {, a, [
await userEvent.keyboard('{Shift}{f}{o}{o}'); // entspricht: Shift, f, o, o
await userEvent.keyboard('{a>5}'); // a drücken, ohne sie loszulassen, und 5 `keydown`-Ereignisse auslösen
await userEvent.keyboard('{a>5/}'); // a für 5 `keydown`-Ereignisse drücken und dann wieder loslassen
});
Referenzen:
userEvent.tab
function tab(options?: UserEventTabOptions): Promise<void>;
Sendet ein Tab
-Tastenereignis. Dies ist eine Abkürzung für userEvent.keyboard('{tab}')
.
import { page, userEvent } from '@vitest/browser/context';
test('tab works', 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();
});
Referenzen:
userEvent.type
function type(
element: Element | Locator,
text: string,
options?: UserEventTypeOptions
): Promise<void>;
WARNING
Wenn Sie nicht auf Sonderzeichen (z. B. {shift}
oder {selectall}
) angewiesen sind, wird empfohlen, stattdessen userEvent.fill
für eine bessere Leistung zu verwenden.
Die type
-Methode implementiert das type
-Utility von @testing-library/user-event
, das auf der keyboard
-API aufbaut.
Diese Funktion ermöglicht es Ihnen, Zeichen in ein input
-, textarea
- oder contenteditable
-Element einzugeben. Sie unterstützt die keyboard
-Syntax von user-event.
Wenn Sie nur Zeichen ohne Eingabe drücken müssen, verwenden Sie die userEvent.keyboard
-API.
import { page, userEvent } from '@vitest/browser/context';
test('update input', async () => {
const input = page.getByRole('input');
await userEvent.type(input, 'foo'); // input.value == foo
await userEvent.type(input, '{{a[['); // input.value == foo{a[
await userEvent.type(input, '{Shift}'); // input.value == foo{a[
});
INFO
Vitest stellt die .type
-Methode nicht auf dem Locator wie input.type
zur Verfügung, da sie nur zur Kompatibilität mit der userEvent
-Bibliothek existiert. Erwägen Sie stattdessen die Verwendung von .fill
, da dies schneller ist.
Referenzen:
userEvent.clear
function clear(element: Element | Locator): Promise<void>;
Diese Methode löscht den Inhalt des Eingabeelements.
import { page, userEvent } from '@vitest/browser/context';
test('clears input', async () => {
const input = page.getByRole('input');
await userEvent.fill(input, 'foo');
expect(input).toHaveValue('foo');
await userEvent.clear(input);
// oder Sie können direkt über den Locator darauf zugreifen
await input.clear();
expect(input).toHaveValue('');
});
Referenzen:
userEvent.selectOptions
function selectOptions(
element: Element | Locator,
values: HTMLElement | HTMLElement[] | Locator | Locator[] | string | string[],
options?: UserEventSelectOptions
): Promise<void>;
Mit userEvent.selectOptions
können Sie einen Wert in einem <select>
-Element auswählen.
WARNING
Wenn das <select>
-Element kein multiple
-Attribut hat, wählt Vitest nur das erste Element im Array aus.
Im Gegensatz zu @testing-library
unterstützt Vitest derzeit keine listbox
, aber wir planen, dies in Zukunft hinzuzufügen.
import { page, userEvent } from '@vitest/browser/context';
test('clears input', async () => {
const select = page.getByRole('select');
await userEvent.selectOptions(select, 'Option 1');
// oder Sie können direkt über den Locator darauf zugreifen
await select.selectOptions('Option 1');
expect(select).toHaveValue('option-1');
await userEvent.selectOptions(select, 'option-1');
expect(select).toHaveValue('option-1');
await userEvent.selectOptions(select, [
page.getByRole('option', { name: 'Option 1' }),
page.getByRole('option', { name: 'Option 2' }),
]);
expect(select).toHaveValue(['option-1', 'option-2']);
});
WARNING
Der webdriverio
-Provider unterstützt die Auswahl mehrerer Elemente nicht, da er keine API dafür bereitstellt.
Referenzen:
- Playwright
locator.selectOption
API - WebdriverIO
element.selectByIndex
API - testing-library
selectOptions
API
userEvent.hover
function hover(
element: Element | Locator,
options?: UserEventHoverOptions
): Promise<void>;
Diese Methode bewegt die Cursorposition auf das ausgewählte Element. Bitte beachten Sie die Dokumentation Ihres Providers für eine detaillierte Erklärung, wie diese Methode funktioniert.
WARNING
Wenn Sie den webdriverio
-Provider verwenden, bewegt sich der Cursor standardmäßig in die Mitte des Elements.
Wenn Sie den playwright
-Provider verwenden, bewegt sich der Cursor zu einem "sichtbaren" Punkt des Elements.
import { page, userEvent } from '@vitest/browser/context';
test('hovers logo element', async () => {
const logo = page.getByRole('img', { name: /logo/ });
await userEvent.hover(logo);
// oder Sie können direkt über den Locator darauf zugreifen
await logo.hover();
});
Referenzen:
userEvent.unhover
function unhover(
element: Element | Locator,
options?: UserEventHoverOptions
): Promise<void>;
Dies funktioniert genauso wie userEvent.hover
, bewegt den Cursor jedoch stattdessen zum document.body
-Element.
WARNING
Standardmäßig befindet sich die Cursorposition an einem "sichtbaren" Ort (im playwright
-Provider) oder in der Mitte (im webdriverio
-Provider) des Body-Elements. Wenn sich das aktuell überfahrene Element bereits an derselben Position befindet, hat diese Methode keine Auswirkung.
import { page, userEvent } from '@vitest/browser/context';
test('unhover logo element', async () => {
const logo = page.getByRole('img', { name: /logo/ });
await userEvent.unhover(logo);
// oder Sie können direkt über den Locator darauf zugreifen
await logo.unhover();
});
Referenzen:
userEvent.upload
function upload(
element: Element | Locator,
files: string[] | string | File[] | File
): Promise<void>;
Ändert ein Dateieingabeelement, um die angegebenen Dateien zu enthalten.
import { page, userEvent } from '@vitest/browser/context';
test('can upload a file', async () => {
const input = page.getByRole('button', { name: /Upload files/ });
const file = new File(['file'], 'file.png', { type: 'image/png' });
await userEvent.upload(input, file);
// oder Sie können direkt über den Locator darauf zugreifen
await input.upload(file);
// Sie können auch Dateipfade relativ zur Testdatei verwenden
await userEvent.upload(input, '../fixtures/file.png');
});
WARNING
Der webdriverio
-Provider unterstützt diesen Befehl derzeit nur in den Browsern chrome
und edge
. Er unterstützt derzeit auch nur String-Typen.
Referenzen:
userEvent.dragAndDrop
function dragAndDrop(
source: Element | Locator,
target: Element | Locator,
options?: UserEventDragAndDropOptions
): Promise<void>;
Zieht das Quellenelement auf das Zielelement. Vergessen Sie nicht, dass das source
-Element das Attribut draggable
auf true
gesetzt haben muss.
import { page, userEvent } from '@vitest/browser/context';
test('drag and drop works', async () => {
const source = page.getByRole('img', { name: /logo/ });
const target = page.getByTestId('logo-target');
await userEvent.dragAndDrop(source, target);
// oder Sie können direkt über den Locator darauf zugreifen
await source.dropTo(target);
await expect.element(target).toHaveTextContent('Logo is processed');
});
WARNING
Diese API wird vom Standard-preview
-Provider nicht unterstützt.
Referenzen: