Interaktivní API
Vitest implementuje podmnožinu API @testing-library/user-event
pomocí Chrome DevTools Protocol nebo webdriver. Tím se namísto simulace událostí dosahuje spolehlivějšího a konzistentnějšího chování prohlížeče, které lépe odpovídá interakci uživatelů na stránce.
import { userEvent } from '@vitest/browser/context';
await userEvent.click(document.querySelector('.button'));
Téměř každá metoda userEvent
přebírá možnosti od svého poskytovatele. Chcete-li vidět všechny dostupné možnosti ve vašem IDE, přidejte typy webdriver
nebo playwright
(podle vašeho poskytovatele) do souboru nastavení nebo konfiguračního souboru (v závislosti na obsahu sekce included
ve vašem tsconfig.json
):
/// <reference types="@vitest/browser/providers/playwright" />
/// <reference types="@vitest/browser/providers/webdriverio" />
userEvent.setup
function setup(): UserEvent;
Vytvoří novou instanci události uživatele. To je užitečné, pokud potřebujete udržet stav klávesnice pro správnou simulaci stisku a uvolnění kláves.
WARNING
Na rozdíl od @testing-library/user-event
je výchozí instance userEvent
z @vitest/browser/context
vytvořena jednou, nikoli pokaždé, když jsou volány její metody! Rozdíl v tom, jak to funguje, můžete vidět v tomto úryvku:
import { userEvent as vitestUserEvent } from '@vitest/browser/context';
import { userEvent as originalUserEvent } from '@testing-library/user-event';
await vitestUserEvent.keyboard('{Shift}'); // stiskne Shift bez uvolnění
await vitestUserEvent.keyboard('{/Shift}'); // uvolní Shift
await originalUserEvent.keyboard('{Shift}'); // stiskne Shift bez uvolnění
await originalUserEvent.keyboard('{/Shift}'); // neuvolnil Shift, protože stav je jiný
Toto chování je užitečnější, protože klávesnici neemulujeme, ale skutečně stiskneme Shift. Zachování původního chování by tak mohlo způsobit neočekávané problémy při psaní do pole.
userEvent.click
function click(
element: Element | Locator,
options?: UserEventClickOptions
): Promise<void>;
Klikne na element. Dědí možnosti poskytovatele. Podrobné vysvětlení, jak tato metoda funguje, naleznete v dokumentaci vašeho poskytovatele.
import { page, userEvent } from '@vitest/browser/context';
test('clicks on an element', async () => {
const logo = page.getByRole('img', { name: /logo/ });
await userEvent.click(logo);
// nebo k němu můžete přistupovat přímo na lokátoru
await logo.click();
});
Reference:
userEvent.dblClick
function dblClick(
element: Element | Locator,
options?: UserEventDoubleClickOptions
): Promise<void>;
Spustí událost dvojitého kliknutí na elementu.
Podrobné vysvětlení, jak tato metoda funguje, naleznete v dokumentaci vašeho poskytovatele.
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);
// nebo k němu můžete přistupovat přímo na lokátoru
await logo.dblClick();
});
Reference:
userEvent.tripleClick
function tripleClick(
element: Element | Locator,
options?: UserEventTripleClickOptions
): Promise<void>;
Spustí událost trojkliku na prvku. Protože v API prohlížeče neexistuje tripleclick
, tato metoda spustí tři události kliknutí za sebou. Proto musíte zkontrolovat podrobnosti události kliknutí a událost filtrovat pomocí: evt.detail === 3
.
Podrobné vysvětlení, jak tato metoda funguje, naleznete v dokumentaci vašeho poskytovatele.
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);
// nebo k němu můžete přistupovat přímo na lokátoru
await logo.tripleClick();
expect(tripleClickFired).toBe(true);
});
Reference:
- Playwright
locator.click
API: implementováno pomocíclick
sclickCount: 3
. - WebdriverIO
browser.action
API: implementováno pomocí akčního API smove
plus třemi událostmidown + up + pause
za sebou - testing-library
tripleClick
API
userEvent.fill
function fill(element: Element | Locator, text: string): Promise<void>;
Nastaví hodnotu do prvku input
/textarea
/contenteditable
. Před nastavením nové hodnoty odstraní veškerý existující text ve vstupním poli.
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}
// nebo k němu můžete přistupovat přímo na lokátoru
await input.fill('foo'); // input.value == foo
});
Tato metoda přesune focus na prvek, vyplní jej a po vyplnění vyvolá událost input
. Pro vymazání pole můžete použít prázdný řetězec.
TIP
Toto rozhraní je rychlejší než použití userEvent.type
nebo userEvent.keyboard
, ale nepodporuje syntaxi keyboard
uživatelské události (např. {Shift}{selectall}
).
Doporučujeme používat toto API namísto userEvent.type
v situacích, kdy nepotřebujete zadávat speciální znaky nebo mít granulární kontrolu nad událostmi stisku kláves.
Reference:
userEvent.keyboard
function keyboard(text: string): Promise<void>;
userEvent.keyboard
umožňuje simulovat stisky kláves. Pokud je zaostřeno nějaké vstupní pole, bude do něj psát znaky. Jinak spustí události klávesnice na aktuálně zaostřeném prvku (document.body
, pokud žádné prvky zaostřené nejsou).
Toto API podporuje syntaxi keyboard
uživatelské události.
import { userEvent } from '@vitest/browser/context';
test('trigger keystrokes', async () => {
await userEvent.keyboard('foo'); // převede na: f, o, o
await userEvent.keyboard('{{a[['); // převede na: {, a, [
await userEvent.keyboard('{Shift}{f}{o}{o}'); // převede na: Shift, f, o, o
await userEvent.keyboard('{a>5}'); // stiskne a bez uvolnění a spustí 5 stisků kláves
await userEvent.keyboard('{a>5/}'); // stiskne a pro 5 stisků kláves a poté uvolní
});
Reference:
userEvent.tab
function tab(options?: UserEventTabOptions): Promise<void>;
Vyvolá událost stisku klávesy Tab
. Toto je zkratka pro 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();
});
Reference:
userEvent.type
function type(
element: Element | Locator,
text: string,
options?: UserEventTypeOptions
): Promise<void>;
WARNING
Pokud se nespoléháte na speciální znaky (např. {shift}
nebo {selectall}
), doporučuje se použít místo toho userEvent.fill
pro lepší výkon.
Metoda type
implementuje utilitu @testing-library/user-event
type
postavenou na API keyboard
.
Tato funkce umožňuje psát znaky do prvku input
/textarea
/contenteditable
. Podporuje syntaxi keyboard
uživatelské události.
Pokud potřebujete pouze stisknout znaky, aniž byste je zadávali do vstupního pole, použijte API userEvent.keyboard
.
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 nezpřístupňuje metodu .type
přímo na lokátoru (např. input.type
), protože tato metoda existuje pouze pro kompatibilitu s knihovnou userEvent
. Zvažte místo toho použití .fill
, protože je rychlejší.
Reference:
userEvent.clear
function clear(
element: Element | Locator,
options?: UserEventClearOptions
): Promise<void>;
Tato metoda vymaže obsah vstupního pole.
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);
// nebo k němu můžete přistupovat přímo na lokátoru
await input.clear();
expect(input).toHaveValue('');
});
Reference:
userEvent.selectOptions
function selectOptions(
element: Element | Locator,
values: HTMLElement | HTMLElement[] | Locator | Locator[] | string | string[],
options?: UserEventSelectOptions
): Promise<void>;
userEvent.selectOptions
umožňuje vybrat hodnotu v elementu <select>
.
WARNING
Pokud element select nemá atribut multiple
, Vitest vybere pouze první prvek v poli.
Na rozdíl od @testing-library
Vitest v současnosti nepodporuje listbox, ale jeho podporu plánujeme přidat v budoucnu.
import { page, userEvent } from '@vitest/browser/context';
test('clears input', async () => {
const select = page.getByRole('select');
await userEvent.selectOptions(select, 'Option 1');
// nebo k němu můžete přistupovat přímo na lokátoru
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
Poskytovatel webdriverio
nepodporuje výběr více prvků, protože neposkytuje API k tomu.
Reference:
- Playwright
locator.selectOption
API - WebdriverIO
element.selectByIndex
API - testing-library
selectOptions
API
userEvent.hover
function hover(
element: Element | Locator,
options?: UserEventHoverOptions
): Promise<void>;
Tato metoda přesune pozici kurzoru na vybraný prvek. Podrobné vysvětlení, jak tato metoda funguje, naleznete v dokumentaci vašeho poskytovatele.
WARNING
Pokud používáte poskytovatele webdriverio
, kurzor se standardně přesune do středu prvku.
Pokud používáte poskytovatele playwright
, kurzor se přesune na libovolný viditelný bod prvku.
import { page, userEvent } from '@vitest/browser/context';
test('hovers logo element', async () => {
const logo = page.getByRole('img', { name: /logo/ });
await userEvent.hover(logo);
// nebo k němu můžete přistupovat přímo na lokátoru
await logo.hover();
});
Reference:
userEvent.unhover
function unhover(
element: Element | Locator,
options?: UserEventHoverOptions
): Promise<void>;
Toto funguje stejně jako userEvent.hover
, ale místo toho přesune kurzor na prvek document.body
.
WARNING
Ve výchozím nastavení je pozice kurzoru na libovolném viditelném místě (u poskytovatele playwright
) nebo ve středu (u poskytovatele webdriverio
) elementu body. Pokud je tedy aktuálně najetý prvek již na stejné pozici, tato metoda nebude mít žádný účinek.
import { page, userEvent } from '@vitest/browser/context';
test('unhover logo element', async () => {
const logo = page.getByRole('img', { name: /logo/ });
await userEvent.unhover(logo);
// nebo k němu můžete přistupovat přímo na lokátoru
await logo.unhover();
});
Reference:
userEvent.upload
function upload(
element: Element | Locator,
files: string[] | string | File[] | File,
options?: UserEventUploadOptions
): Promise<void>;
Změní souborový vstupní prvek tak, aby obsahoval zadané soubory.
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);
// nebo k němu můžete přistupovat přímo na lokátoru
await input.upload(file);
// můžete také použít cesty k souborům relativní ke kořenu projektu
await userEvent.upload(input, './fixtures/file.png');
});
WARNING
Poskytovatel webdriverio
podporuje tento příkaz pouze v prohlížečích chrome
a edge
. V současné době také podporuje pouze řetězcové typy.
Reference:
userEvent.dragAndDrop
function dragAndDrop(
source: Element | Locator,
target: Element | Locator,
options?: UserEventDragAndDropOptions
): Promise<void>;
Přesune zdrojový element na cílový element. Nezapomeňte, že zdrojový prvek musí mít atribut draggable
nastaven na hodnotu true
.
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);
// nebo k němu můžete přistupovat přímo na lokátoru
await source.dropTo(target);
await expect.element(target).toHaveTextContent('Logo is processed');
});
WARNING
Toto API není podporováno výchozím poskytovatelem 'preview'.
Reference:
userEvent.copy
function copy(): Promise<void>;
Zkopíruje označený text do systémové schránky.
import { page, userEvent } from '@vitest/browser/context';
test('copy and paste', async () => {
// zapsat do 'source'
await userEvent.click(page.getByPlaceholder('source'));
await userEvent.keyboard('hello');
// vybrat a zkopírovat 'source'
await userEvent.dblClick(page.getByPlaceholder('source'));
await userEvent.copy();
// vložit do 'target'
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');
});
Reference:
userEvent.cut
function cut(): Promise<void>;
Vyřízne označený text do systémové schránky.
import { page, userEvent } from '@vitest/browser/context';
test('copy and paste', async () => {
// zapsat do 'source'
await userEvent.click(page.getByPlaceholder('source'));
await userEvent.keyboard('hello');
// vybrat a vyříznout 'source'
await userEvent.dblClick(page.getByPlaceholder('source'));
await userEvent.cut();
// vložit do 'target'
await userEvent.click(page.getByPlaceholder('target'));
await userEvent.paste();
await expect.element(page.getByPlaceholder('source')).toHaveTextContent('');
await expect
.element(page.getByPlaceholder('target'))
.toHaveTextContent('hello');
});
Reference:
userEvent.paste
function paste(): Promise<void>;
Vloží text ze systémové schránky. Příklady použití viz userEvent.copy
a userEvent.cut
.
Reference: