Interaktivní API
Vitest implementuje podmnožinu API z @testing-library/user-event pomocí Chrome DevTools Protocol nebo webdriver namísto simulace událostí. Tím je chování prohlížeče spolehlivější a konzistentnější s tím, jak uživatelé interagují se stránkou.
import { userEvent } from '@vitest/browser/context';
await userEvent.click(document.querySelector('.button'));Téměř každá metoda userEvent dědí možnosti od svého poskytovatele. Pro zobrazení všech dostupných možností ve vašem IDE přidejte typy webdriver nebo playwright (v závislosti na vašem poskytovateli) do souboru tsconfig.json.
{
"compilerOptions": {
"types": ["@vitest/browser/providers/playwright"]
}
}{
"compilerOptions": {
"types": ["@vitest/browser/providers/webdriverio"]
}
}userEvent.setup
function setup(): UserEvent;Vytvoří novou instanci uživatelské události. To je užitečné, pokud potřebujete zachovat stav klávesnice pro správné stisknutí 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 chování 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}'); // podrží Shift stisknutý
await vitestUserEvent.keyboard('{/Shift}'); // uvolní Shift
await originalUserEvent.keyboard('{Shift}'); // podrží Shift stisknutý
await originalUserEvent.keyboard('{/Shift}'); // NEUvolní Shift, protože stav je jinýToto chování je užitečnější, protože neemulujeme klávesnici, ale skutečně stiskneme Shift. Zachování původního chování by způsobilo neočekávané problémy při psaní do pole.
userEvent.click
function click(
element: Element | Locator,
options?: UserEventClickOptions
): Promise<void>;Klikne na prvek. Dědí možnosti od poskytovatele. Podrobné vysvětlení, jak tato metoda funguje, najdete 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 dvojkliku na elementu.
Podrobné vysvětlení, jak tato metoda funguje, najdete 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. Jelikož v API prohlížeče neexistuje tripleclick, tato metoda spustí tři události kliknutí za sebou. Proto musíte zkontrolovat detail události kliknutí pro filtrování události: evt.detail === 3.
Podrobné vysvětlení, jak tato metoda funguje, najdete 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.clickAPI: implementováno pomocíclicksclickCount: 3. - WebdriverIO
browser.actionAPI: implementováno pomocí actions API smoveplus třemi událostmidown + up + pauseza sebou. - testing-library
tripleClickAPI
userEvent.fill
function fill(element: Element | Locator, text: string): Promise<void>;Nastaví hodnotu do pole input/textarea/contenteditable. Tím se před nastavením nové hodnoty odstraní veškerý existující text v inputu.
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 zaostřuje prvek, naplní jej a po vyplnění spustí událost input. Prázdný řetězec můžete použít k vymazání pole.
TIP
Toto API je rychlejší než použití userEvent.type nebo userEvent.keyboard, ale nepodporuje syntaxi keyboard z user-event (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 detailní kontrolu nad událostmi stisku kláves.
Reference:
userEvent.keyboard
function keyboard(text: string): Promise<void>;userEvent.keyboard vám umožňuje spouštět stisky kláves. Pokud je zaostřen jakýkoli input, bude do něj psát znaky. Jinak spustí události klávesnice na aktuálně zaostřeném prvku (document.body, pokud nejsou žádné zaostřené prvky).
Toto API podporuje syntaxi keyboard z user-event.
import { userEvent } from '@vitest/browser/context';
test('trigger keystrokes', async () => {
await userEvent.keyboard('foo'); // odpovídá: f, o, o
await userEvent.keyboard('{{a[['); // odpovídá: {, a, [
await userEvent.keyboard('{Shift}{f}{o}{o}'); // odpovídá: Shift, f, o, o
await userEvent.keyboard('{a>5}'); // podrží 'a' stisknuté a spustí 5 keydown
await userEvent.keyboard('{a>5/}'); // stiskne 'a' pro 5 keydown a poté jej uvolní
});Reference:
userEvent.tab
function tab(options?: UserEventTabOptions): Promise<void>;Odešle událost 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 místo toho použít userEvent.fill pro lepší výkon.
Metoda type implementuje utilitu type z @testing-library/user-event postavenou na API keyboard.
Tato funkce vám umožňuje psát znaky do prvku input/textarea/contenteditable. Podporuje syntaxi keyboard z user-event.
Pokud potřebujete pouze stisknout znaky bez inputu, 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 na lokátoru jako input.type, protože 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): Promise<void>;Tato metoda vymaže obsah input elementu.
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 prvku <select>.
WARNING
Pokud prvek select nemá atribut multiple, Vitest vybere pouze první prvek v poli.
Na rozdíl od @testing-library Vitest v současné době nepodporuje listbox, ale plánujeme přidat podporu 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 k tomu neposkytuje API.
Reference:
- Playwright
locator.selectOptionAPI - WebdriverIO
element.selectByIndexAPI - testing-library
selectOptionsAPI
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, najdete v dokumentaci vašeho poskytovatele.
WARNING
Pokud používáte poskytovatele webdriverio, kurzor se ve výchozím nastavení přesune do středu prvku.
Pokud používáte poskytovatele playwright, kurzor se přesune na "nějaký" 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 "nějakém" viditelném místě (u poskytovatele playwright) nebo ve středu (u poskytovatele webdriverio) prvku body. Pokud je aktuálně prvek pod kurzorem 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
): Promise<void>;Změní vstupní prvek typu file 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í k testovacímu souboru
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 typy string.
Reference:
userEvent.dragAndDrop
function dragAndDrop(
source: Element | Locator,
target: Element | Locator,
options?: UserEventDragAndDropOptions
): Promise<void>;Přetáhne zdrojový prvek na cílový prvek. Nezapomeňte, že zdrojový prvek musí mít atribut draggable nastaven na 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: