Interaktions-API
Vitest implementiert eine Teilmenge der @testing-library/user-event
APIs. Dies geschieht unter Verwendung des Chrome DevTools Protocol oder Webdriver, anstatt Ereignisse zu simulieren. Dadurch wird das Browserverhalten zuverlässiger und konsistenter mit der Art und Weise, 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 ihres jeweiligen Anbieters. Um alle verfügbaren Optionen in Ihrer IDE anzuzeigen, fügen Sie webdriver
- oder playwright
-Typen (abhängig von Ihrem Anbieter) zu Ihrer Setup-Datei oder einer Konfigurationsdatei hinzu (je nachdem, was in included
in Ihrer tsconfig.json
definiert ist):
/// <reference types="@vitest/browser/providers/playwright" />
/// <reference types="@vitest/browser/providers/webdriverio" />
userEvent.setup
function setup(): UserEvent;
Erstellt eine neue User-Event-Instanz. Dies ist nützlich, um den Zustand der Tastatur beizubehalten, damit Tasten korrekt gedrückt und losgelassen werden können.
WARNING
Im Gegensatz zu @testing-library/user-event
wird die Standard userEvent
-Instanz von @vitest/browser/context
einmal erstellt und nicht bei jedem Methodenaufruf neu initialisiert! 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-Taste gedrückt halten
await vitestUserEvent.keyboard('{/Shift}'); // Shift loslassen
await originalUserEvent.keyboard('{Shift}'); // Shift-Taste gedrückt halten
await originalUserEvent.keyboard('{/Shift}'); // Shift WURDE NICHT losgelassen, da der Zustand abweicht
Dieses Verhalten ist vorteilhafter, da wir die Tastatur nicht emulieren, sondern tatsächlich die Shift-Taste drücken. Das Beibehalten des ursprünglichen Verhaltens könnte unerwartete Probleme beim Tippen in ein Feld verursachen.
userEvent.click
function click(
element: Element | Locator,
options?: UserEventClickOptions
): Promise<void>;
Klickt auf ein bestimmtes Element. Erbt die Optionen des Anbieters. Eine detaillierte Erklärung der Funktionsweise dieser Methode finden Sie in der Dokumentation Ihres Anbieters.
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 den Locator verwenden
await logo.click();
});
Referenzen:
userEvent.dblClick
function dblClick(
element: Element | Locator,
options?: UserEventDoubleClickOptions
): Promise<void>;
Führt einen Doppelklick auf einem Element aus.
Bitte beachten Sie die Dokumentation Ihres Anbieters 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 den Locator verwenden
await logo.dblClick();
});
Referenzen:
userEvent.tripleClick
function tripleClick(
element: Element | Locator,
options?: UserEventTripleClickOptions
): Promise<void>;
Löst einen Dreifachklick auf einem Element aus. Da die Browser-API keinen tripleclick
unterstützt, löst diese Methode drei Klick-Ereignisse hintereinander aus. Sie müssen daher das Klick-Ereignisdetail überprüfen, um das Ereignis zu filtern: evt.detail === 3
.
Bitte beachten Sie die Dokumentation Ihres Anbieters 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 den Locator verwenden
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 den Locator verwenden
await input.fill('foo'); // input.value == foo
});
Diese Methode fokussiert das Element, füllt es und löst anschließend 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 user-event keyboard
Syntax (z.B. {Shift}{selectall}
).
Wir empfehlen, diese API anstelle von userEvent.type
zu verwenden, wenn Sie keine Sonderzeichen eingeben oder keine detaillierte Kontrolle über Tastenanschläge benötigen.
Referenzen:
userEvent.keyboard
function keyboard(text: string): Promise<void>;
userEvent.keyboard
ermöglicht es Ihnen, Tastaturanschläge auszulösen. Wenn ein Eingabefeld den Fokus hat, werden 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 user-event keyboard
Syntax.
import { userEvent } from '@vitest/browser/context';
test('trigger keystrokes', async () => {
await userEvent.keyboard('foo'); // wird übersetzt zu: f, o, o
await userEvent.keyboard('{{a[['); // wird übersetzt zu: {, a, [
await userEvent.keyboard('{Shift}{f}{o}{o}'); // wird übersetzt zu: Shift, f, o, o
await userEvent.keyboard('{a>5}'); // drückt 'a' ohne es loszulassen und löst 5 Keydown-Ereignisse aus
await userEvent.keyboard('{a>5/}'); // drückt 'a' für 5 Keydown-Ereignisse und lässt es dann los
});
Referenzen:
userEvent.tab
function tab(options?: UserEventTabOptions): Promise<void>;
Sendet ein Tab
-Tastenereignis. Dies ist eine Kurzform 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
-Dienstprogramm 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 user-event keyboard
Syntax.
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 direkt 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,
options?: UserEventClearOptions
): 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 den Locator verwenden
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>;
userEvent.selectOptions
ermöglicht die Auswahl eines Wertes in einem <select>
-Element.
WARNING
Wenn das <select>
-Element kein multiple
-Attribut besitzt, 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 den Locator verwenden
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
-Anbieter 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 zum ausgewählten Element. Bitte beachten Sie die Dokumentation Ihres Anbieters für eine detaillierte Erklärung, wie diese Methode funktioniert.
WARNING
Wenn Sie den webdriverio
-Anbieter verwenden, bewegt sich der Cursor standardmäßig in die Mitte des Elements.
Wenn Sie den playwright
-Anbieter verwenden, bewegt sich der Cursor zu einem beliebigen 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 den Locator verwenden
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 beliebigen sichtbaren Punkt (im playwright
-Anbieter) oder in der Mitte (im webdriverio
-Anbieter) des Body-Elements. Wenn sich das aktuell gehoverte 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 den Locator verwenden
await logo.unhover();
});
Referenzen:
userEvent.upload
function upload(
element: Element | Locator,
files: string[] | string | File[] | File,
options?: UserEventUploadOptions
): 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 den Locator verwenden
await input.upload(file);
// Sie können auch Dateipfade relativ zum Projektstamm verwenden
await userEvent.upload(input, './fixtures/file.png');
});
WARNING
Der webdriverio
-Anbieter unterstützt diesen Befehl nur in den Browsern chrome
und edge
. Er unterstützt derzeit auch nur Zeichenketten.
Referenzen:
userEvent.dragAndDrop
function dragAndDrop(
source: Element | Locator,
target: Element | Locator,
options?: UserEventDragAndDropOptions
): Promise<void>;
Zieht das Quellelement auf das Zielelement. Beachten Sie, 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 den Locator verwenden
await source.dropTo(target);
await expect.element(target).toHaveTextContent('Logo is processed');
});
WARNING
Diese API wird im Standard-preview
-Anbieter nicht unterstützt.
Referenzen:
userEvent.copy
function copy(): Promise<void>;
Kopiert den aktuell ausgewählten Text in die Zwischenablage.
import { page, userEvent } from '@vitest/browser/context';
test('copy and paste', async () => {
// In 'source' schreiben
await userEvent.click(page.getByPlaceholder('source'));
await userEvent.keyboard('hello');
// 'source' auswählen und kopieren
await userEvent.dblClick(page.getByPlaceholder('source'));
await userEvent.copy();
// In 'target' einfügen
await userEvent.click(page.getByPlaceholder('target'));
await userEvent.paste();
await expect
.element(page.getByPlaceholder('source'))
.toHaveTextContent('hello');
await expect
.element(page.getByPlaceholder('target'))
.toHaveTextContent('hello');
});
Referenzen:
userEvent.cut
function cut(): Promise<void>;
Schneidet den aktuell ausgewählten Text in die Zwischenablage.
import { page, userEvent } from '@vitest/browser/context';
test('copy and paste', async () => {
// In 'source' schreiben
await userEvent.click(page.getByPlaceholder('source'));
await userEvent.keyboard('hello');
// 'source' auswählen und ausschneiden
await userEvent.dblClick(page.getByPlaceholder('source'));
await userEvent.cut();
// In 'target' einfügen
await userEvent.click(page.getByPlaceholder('target'));
await userEvent.paste();
await expect.element(page.getByPlaceholder('source')).toHaveTextContent('');
await expect
.element(page.getByPlaceholder('target'))
.toHaveTextContent('hello');
});
Referenzen:
userEvent.paste
function paste(): Promise<void>;
Fügt den Text aus der Zwischenablage ein. Siehe userEvent.copy
und userEvent.cut
für Anwendungsbeispiele.
Referenzen: