Lokátory
Lokátor představuje jeden nebo více prvků. Každý lokátor je definován pomocí řetězce, který se nazývá selektor. Vitest tento selektor abstrahuje a poskytuje pohodlné metody, které jej generují na pozadí.
API lokátorů využívá fork lokátorů Playwrightu s názvem Ivya. Vitest však toto API zpřístupňuje každému poskytovateli prohlížeče, nejen Playwrightu.
TIP
Tato stránka se zaměřuje na použití API. Pro hlubší pochopení lokátorů a jejich fungování si přečtěte dokumentaci Playwrightu "Locators".
getByRole
function getByRole(
role: ARIARole | string,
options?: LocatorByRoleOptions
): Locator;
Umožňuje lokalizovat prvek podle jeho role ARIA, atributů ARIA a přístupného názvu.
TIP
Pokud dotazujete pouze jeden prvek pomocí getByText('The name')
, je často vhodnější použít getByRole(expectedRole, { name: 'The name' })
. Dotazování podle přístupného názvu nenahrazuje jiné dotazy, jako jsou *ByAltText
nebo *ByTitle
. I když se přístupný název může shodovat s těmito atributy, nenahrazuje jejich funkčnost.
Zde je příklad struktury DOM:
<h3>Sign up</h3>
<label>
Login
<input type="text" />
</label>
<label>
Password
<input type="password" />
</label>
<br />
<button>Submit</button>
Každý prvek můžete najít podle jeho implicitní role:
await expect
.element(page.getByRole('heading', { name: 'Sign up' }))
.toBeVisible();
await page.getByRole('textbox', { name: 'Login' }).fill('admin');
await page.getByRole('textbox', { name: 'Password' }).fill('admin');
await page.getByRole('button', { name: /submit/i }).click();
WARNING
Role se porovnávají na základě rovnosti řetězců a nedědí se z hierarchie rolí ARIA. V důsledku toho dotazování na nadřazenou roli, jako je checkbox
, nezahrne prvky s podřazenou rolí, jako je switch
.
Ve výchozím nastavení mají mnohé sémantické prvky v HTML implicitní roli. Například <input type="radio">
má roli "radio". Nesémantické prvky v HTML roli nemají; <div>
a <span>
bez přidané sémantiky vrátí null
. Atribut role
může poskytnout sémantiku.
Poskytování rolí pomocí atributů role
nebo aria-*
vestavěným prvkům, které již mají implicitní roli, je silně nedoporučeno podle pokynů ARIA.
Možnosti
exact: boolean
Určuje, zda je
name
porovnáván přesně: rozlišuje malá a velká písmena a celý řetězec. Ve výchozím nastavení je zakázáno. Tato možnost je ignorována, pokud jename
regulární výraz. Všimněte si, že přesná shoda stále odstraňuje počáteční a koncové mezery.tsx<button>Hello World</button>; page.getByRole('button', { name: 'hello world' }); // ✅ page.getByRole('button', { name: 'hello world', exact: true }); // ❌ page.getByRole('button', { name: 'Hello World', exact: true }); // ✅
checked: boolean
Určuje, zda mají být zahrnuty zaškrtnuté prvky (nastavené pomocí
aria-checked
nebo<input type="checkbox"/>
). Ve výchozím nastavení se filtr nepoužije.Další informace viz
aria-checked
tsx<> <button role="checkbox" aria-checked="true" /> <input type="checkbox" checked /> </>; page.getByRole('checkbox', { checked: true }); // ✅ page.getByRole('checkbox', { checked: false }); // ❌
disabled: boolean
Určuje, zda mají být zahrnuty zakázané prvky. Ve výchozím nastavení se filtr nepoužije. Všimněte si, že na rozdíl od jiných atributů se stav
disabled
dědí.Další informace viz
aria-disabled
tsx<input type="text" disabled />; page.getByRole('textbox', { disabled: true }); // ✅ page.getByRole('textbox', { disabled: false }); // ❌
expanded: boolean
Určuje, zda mají být zahrnuty rozbalené prvky. Ve výchozím nastavení se filtr nepoužije.
Další informace viz
aria-expanded
tsx<a aria-expanded="true" href="example.com"> Link </a>; page.getByRole('link', { expanded: true }); // ✅ page.getByRole('link', { expanded: false }); // ❌
includeHidden: boolean
Určuje, zda mají být dotazovány prvky, které jsou normálně vyloučeny z přístupnostního stromu. Ve výchozím nastavení selektor rolí porovnává pouze viditelné prvky.
Všimněte si, že role
none
apresentation
jsou vždy zahrnuty.tsx<button style="display: none" />; page.getByRole('button'); // ❌ page.getByRole('button', { includeHidden: false }); // ❌ page.getByRole('button', { includeHidden: true }); // ✅
level: number
Číselný atribut, který je obvykle přítomen pro role
heading
,listitem
,row
,treeitem
s výchozími hodnotami pro prvky<h1>-<h6>
. Ve výchozím nastavení se filtr nepoužije.Další informace viz
aria-level
tsx<> <h1>Heading Level One</h1> <div role="heading" aria-level="1"> Second Heading Level One </div> </>; page.getByRole('heading', { level: 1 }); // ✅ page.getByRole('heading', { level: 2 }); // ❌
name: string | RegExp
Přístupný název. Ve výchozím nastavení je porovnávání bez rozlišení malých a velkých písmen a hledá podřetězec. Pro ovládání tohoto chování použijte možnost
exact
.tsx<button>Click Me!</button>; page.getByRole('button', { name: 'Click Me!' }); // ✅ page.getByRole('button', { name: 'click me!' }); // ✅ page.getByRole('button', { name: 'Click Me?' }); // ❌
pressed: boolean
Určuje, zda mají být zahrnuty stisknuté prvky. Ve výchozím nastavení se filtr nepoužije.
Další informace viz
aria-pressed
tsx<button aria-pressed="true">👍</button>; page.getByRole('button', { pressed: true }); // ✅ page.getByRole('button', { pressed: false }); // ❌
selected: boolean
Určuje, zda mají být zahrnuty vybrané prvky. Ve výchozím nastavení se filtr nepoužije.
Další informace viz
aria-selected
tsx<button role="tab" aria-selected="true"> Vue </button>; page.getByRole('button', { selected: true }); // ✅ page.getByRole('button', { selected: false }); // ❌
Viz také
getByAltText
function getByAltText(text: string | RegExp, options?: LocatorOptions): Locator;
Vytvoří lokátor schopný najít prvek s atributem alt
, který odpovídá zadanému textu. Na rozdíl od implementace testing-library bude Vitest porovnávat jakýkoli prvek, který má odpovídající atribut alt
.
<img alt="Incredibles 2 Poster" src="/incredibles-2.png" />;
page.getByAltText(/incredibles.*? poster/i); // ✅
page.getByAltText('non existing alt text'); // ❌
Možnosti
exact: boolean
Určuje, zda je
text
porovnáván přesně: rozlišuje malá a velká písmena a celý řetězec. Ve výchozím nastavení je zakázáno. Tato možnost je ignorována, pokud jetext
regulární výraz. Všimněte si, že přesná shoda stále odstraňuje počáteční a koncové mezery.
Viz také
getByLabelText
function getByLabelText(
text: string | RegExp,
options?: LocatorOptions
): Locator;
Vytvoří lokátor schopný najít prvek, který má přidružený popisek.
Lokátor page.getByLabelText('Username')
najde všechny vstupy v níže uvedeném příkladu:
// for/htmlFor vztah mezi labelem a id formulářového prvku
<label for="username-input">Username</label>
<input id="username-input" />
// Atribut aria-labelledby s formulářovými prvky
<label id="username-label">Username</label>
<input aria-labelledby="username-label" />
// Obalové labely
<label>Username <input /></label>
// Obalové labely, kde je text labelu v jiném podřízeném prvku
<label>
<span>Username</span>
<input />
</label>
// atributy aria-label
// Buďte opatrní, protože toto není popisek, který uživatelé vidí na stránce, takže účel vašeho vstupu musí být pro vizuální uživatele zřejmý.
<input aria-label="Username" />
Možnosti
exact: boolean
Určuje, zda je
text
porovnáván přesně: rozlišuje malá a velká písmena a celý řetězec. Ve výchozím nastavení je zakázáno. Tato možnost je ignorována, pokud jetext
regulární výraz. Všimněte si, že přesná shoda stále odstraňuje počáteční a koncové mezery.
Viz také
getByPlaceholder
function getByPlaceholder(
text: string | RegExp,
options?: LocatorOptions
): Locator;
Vytvoří lokátor schopný najít prvek, který má zadaný atribut placeholder
. Vitest bude porovnávat jakýkoli prvek, který má odpovídající atribut placeholder
, nejen input
.
<input placeholder="Username" />;
page.getByPlaceholder('Username'); // ✅
page.getByPlaceholder('not found'); // ❌
WARNING
Obecně je lepší spoléhat se na popisek pomocí getByLabelText
než na zástupný text.
Možnosti
exact: boolean
Určuje, zda je
text
porovnáván přesně: rozlišuje malá a velká písmena a celý řetězec. Ve výchozím nastavení je zakázáno. Tato možnost je ignorována, pokud jetext
regulární výraz. Všimněte si, že přesná shoda stále odstraňuje počáteční a koncové mezery.
Viz také
getByText
function getByText(text: string | RegExp, options?: LocatorOptions): Locator;
Vytvoří lokátor schopný najít prvek, který obsahuje zadaný text. Text bude porovnáván s nodeValue
uzlu TextNode nebo s hodnotou vstupu, pokud je typ button
nebo reset
. Při porovnávání podle textu jsou mezery vždy normalizovány, a to i při přesné shodě. Například, více mezer se změní na jednu, zalomení řádků se změní na mezery a ignorují se úvodní a koncové mezery.
<a href="/about">About ℹ️</a>;
page.getByText(/about/i); // ✅
page.getByText('about', { exact: true }); // ❌
TIP
Tento lokátor je vhodný pro hledání neinteraktivních prvků. Pokud potřebujete lokalizovat interaktivní prvek, jako je tlačítko nebo vstup, preferujte getByRole
.
Možnosti
exact: boolean
Určuje, zda je
text
porovnáván přesně: rozlišuje malá a velká písmena a celý řetězec. Ve výchozím nastavení je zakázáno. Tato možnost je ignorována, pokud jetext
regulární výraz. Všimněte si, že přesná shoda stále odstraňuje počáteční a koncové mezery.
Viz také
getByTitle
function getByTitle(text: string | RegExp, options?: LocatorOptions): Locator;
Vytvoří lokátor schopný najít prvek, který má zadaný atribut title
. Na rozdíl od getByTitle
z testing-library, Vitest nemůže najít prvky title
uvnitř SVG.
<span title="Delete" id="2"></span>;
page.getByTitle('Delete'); // ✅
page.getByTitle('Create'); // ❌
Možnosti
exact: boolean
Určuje, zda je
text
porovnáván přesně: rozlišuje malá a velká písmena a celý řetězec. Ve výchozím nastavení je zakázáno. Tato možnost je ignorována, pokud jetext
regulární výraz. Všimněte si, že přesná shoda stále odstraňuje počáteční a koncové mezery.
Viz také
getByTestId
function getByTestId(text: string | RegExp): Locator;
Vytvoří lokátor schopný najít prvek, který odpovídá zadanému atributu testovacího ID. Název atributu můžete nakonfigurovat pomocí browser.locators.testIdAttribute
.
<div data-testid="custom-element" />;
page.getByTestId('custom-element'); // ✅
page.getByTestId('non-existing-element'); // ❌
WARNING
Doporučuje se to použít pouze tehdy, když ostatní lokátory nefungují pro váš případ použití. Používání atributů data-testid
neodpovídá tomu, jak je váš software používán, a pokud je to možné, mělo by se mu vyhnout.
Možnosti
exact: boolean
Určuje, zda je
text
porovnáván přesně: rozlišuje malá a velká písmena a celý řetězec. Ve výchozím nastavení je zakázáno. Tato možnost je ignorována, pokud jetext
regulární výraz. Všimněte si, že přesná shoda stále odstraňuje počáteční a koncové mezery.
Viz také
nth
function nth(index: number): Locator;
Tato metoda vrací nový lokátor, který odpovídá pouze konkrétnímu indexu ve výsledku dotazu s více prvky. Indexování je založeno na nule, nth(0)
vybere první prvek. Na rozdíl od elements()[n]
bude lokátor nth
opakovaně zkoušen, dokud se prvek neobjeví.
<div aria-label="one"><input /><input /><input /></div>
<div aria-label="two"><input /></div>
page.getByRole('textbox').nth(0); // ✅
page.getByRole('textbox').nth(4); // ❌
TIP
Než se uchýlíte k nth
, může být užitečné použít zřetězené lokátory k zúžení vyhledávání. Někdy neexistuje lepší způsob, jak rozlišit než podle pozice prvku; i když to může vést k nestabilitě, je to lepší než nic.
page.getByLabel('two').getByRole('input'); // ✅ lepší alternativa k page.getByRole('textbox').nth(3)
page.getByLabel('one').getByRole('input'); // ❌ příliš nejednoznačné
page.getByLabel('one').getByRole('input').nth(1); // ✅ pragmatický kompromis
first
function first(): Locator;
Tato metoda vrací nový lokátor, který odpovídá pouze prvnímu prvku ve výsledku dotazu s více prvky. Je to zkratka pro nth(0)
.
<input /> <input /> <input />
page.getByRole('textbox').first(); // ✅
last
function last(): Locator;
Tato metoda vrací nový lokátor, který odpovídá pouze poslednímu prvku ve výsledku dotazu s více prvky. Je to zkratka pro nth(-1)
.
<input /> <input /> <input />
page.getByRole('textbox').last(); // ✅
and
function and(locator: Locator): Locator;
Tato metoda vytvoří nový lokátor, který odpovídá jak rodičovskému, tak poskytnutému lokátoru. Následující příklad najde tlačítko s konkrétním názvem:
page.getByRole('button').and(page.getByTitle('Subscribe'));
or
function or(locator: Locator): Locator;
Tato metoda vytvoří nový lokátor, který odpovídá jednomu nebo oběma lokátorům.
WARNING
Všimněte si, že pokud lokátor odpovídá více než jednomu prvku, volání jiné metody může vyvolat chybu, pokud očekává jeden prvek:
<>
<button>Click me</button>
<a href="https://vitest.dev">Error happened!</a>
</>;
page.getByRole('button').or(page.getByRole('link')).click(); // ❌ odpovídá více prvkům
filter
function filter(options: LocatorOptions): Locator;
Tato metoda zužuje lokátor podle možností, jako je filtrování podle textu. Lze ji zřetězit pro aplikaci více filtrů.
has
- Typ:
Locator
Tato možnost zužuje selektor tak, aby odpovídal prvkům, které obsahují jiné prvky odpovídající zadanému lokátoru. Například s tímto HTML:
<article>
<div>Vitest</div>
</article>
<article>
<div>Rolldown</div>
</article>
Můžeme zúžit lokátor tak, aby našel pouze article
s textem Vitest
uvnitř:
page.getByRole('article').filter({ has: page.getByText('Vitest') }); // ✅
WARNING
Zadaný lokátor (page.getByText('Vitest')
v příkladu) musí být relativní k rodičovskému lokátoru (page.getByRole('article')
v příkladu). Bude dotazován počínaje rodičovským lokátorem, nikoli kořenem dokumentu.
To znamená, že nemůžete předat lokátor, který dotazuje prvek mimo rodičovský lokátor:
page.getByText('Vitest').filter({ has: page.getByRole('article') }); // ❌
Tento příklad selže, protože prvek article
je mimo prvek s textem Vitest
.
TIP
Tuto metodu lze zřetězit pro další zúžení prvku:
page
.getByRole('article')
.filter({ has: page.getByRole('button', { name: 'delete row' }) })
.filter({ has: page.getByText('Vitest') });
hasNot
- Typ:
Locator
Tato možnost zužuje selektor tak, aby odpovídal prvkům, které neobsahují jiné prvky odpovídající zadanému lokátoru. Například s tímto HTML:
<article>
<div>Vitest</div>
</article>
<article>
<div>Rolldown</div>
</article>
Můžeme zúžit lokátor tak, aby našel pouze article
, který neobsahuje Rolldown
.
page.getByRole('article').filter({ hasNot: page.getByText('Rolldown') }); // ✅
page.getByRole('article').filter({ hasNot: page.getByText('Vitest') }); // ❌
WARNING
Všimněte si, že zadaný lokátor je dotazován proti rodiči, nikoli kořenu dokumentu, stejně jako možnost has
.
hasText
- Typ:
string | RegExp
Tato možnost zužuje selektor tak, aby odpovídal pouze prvkům, které někde uvnitř obsahují zadaný text. Pokud je předán string
, porovnávání je bez rozlišení malých a velkých písmen a hledá podřetězec.
<article>
<div>Vitest</div>
</article>
<article>
<div>Rolldown</div>
</article>
Oba lokátory najdou stejný prvek, protože vyhledávání nerozlišuje malá a velká písmena:
page.getByRole('article').filter({ hasText: 'Vitest' }); // ✅
page.getByRole('article').filter({ hasText: 'Vite' }); // ✅
hasNotText
- Typ:
string | RegExp
Tato možnost zužuje selektor tak, aby odpovídal pouze prvkům, které někde uvnitř neobsahují zadaný text. Pokud je předán string
, porovnávání je bez rozlišení malých a velkých písmen a hledá podřetězec.
Metody
Všechny metody jsou asynchronní a je nutné na ně čekat (await). Od Vitest 3 testy selžou, pokud se na metodu nečeká.
click
function click(options?: UserEventClickOptions): Promise<void>;
Klikne na prvek. Pomocí možností můžete nastavit pozici kurzoru.
import { page } from '@vitest/browser/context';
await page.getByRole('img', { name: 'Rose' }).click();
dblClick
function dblClick(options?: UserEventDoubleClickOptions): Promise<void>;
Spustí událost dvojkliku na prvku. Pomocí možností můžete nastavit pozici kurzoru.
import { page } from '@vitest/browser/context';
await page.getByRole('img', { name: 'Rose' }).dblClick();
tripleClick
function tripleClick(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.
import { page } from '@vitest/browser/context';
await page.getByRole('img', { name: 'Rose' }).tripleClick();
clear
function clear(options?: UserEventClearOptions): Promise<void>;
Vymaže obsah vstupního prvku.
import { page } from '@vitest/browser/context';
await page.getByRole('textbox', { name: 'Full Name' }).clear();
hover
function hover(options?: UserEventHoverOptions): Promise<void>;
Přesune pozici kurzoru na vybraný prvek.
import { page } from '@vitest/browser/context';
await page.getByRole('img', { name: 'Rose' }).hover();
unhover
function unhover(options?: UserEventHoverOptions): Promise<void>;
Funguje podobně jako locator.hover
, ale místo toho přesune kurzor na prvek document.body
.
import { page } from '@vitest/browser/context';
await page.getByRole('img', { name: 'Rose' }).unhover();
fill
function fill(text: string, options?: UserEventFillOptions): Promise<void>;
Nastaví hodnotu aktuálního prvku input
, textarea
nebo contenteditable
.
import { page } from '@vitest/browser/context';
await page.getByRole('input', { name: 'Full Name' }).fill('Mr. Bean');
dropTo
function dropTo(
target: Locator,
options?: UserEventDragAndDropOptions
): Promise<void>;
Přetáhne aktuální prvek na cílové místo.
import { page } from '@vitest/browser/context';
const paris = page.getByText('Paris');
const france = page.getByText('France');
await paris.dropTo(france);
selectOptions
function selectOptions(
values: HTMLElement | HTMLElement[] | Locator | Locator[] | string | string[],
options?: UserEventSelectOptions
): Promise<void>;
Vyberte jednu nebo více hodnot z prvku <select>
.
import { page } from '@vitest/browser/context';
const languages = page.getByRole('select', { name: 'Languages' });
await languages.selectOptions('EN');
await languages.selectOptions(['ES', 'FR']);
await languages.selectOptions([
languages.getByRole('option', { name: 'Spanish' }),
languages.getByRole('option', { name: 'French' }),
]);
screenshot
function screenshot(
options: LocatorScreenshotOptions & { save: false }
): Promise<string>;
function screenshot(
options: LocatorScreenshotOptions & { base64: true }
): Promise<{
path: string;
base64: string;
}>;
function screenshot(
options?: LocatorScreenshotOptions & { base64?: false }
): Promise<string>;
Vytvoří snímek obrazovky prvku odpovídajícího selektoru lokátoru.
Umístění pro uložení snímku obrazovky můžete zadat pomocí možnosti path
, která je relativní k aktuálnímu testovacímu souboru. Pokud možnost path
není nastavena, Vitest ve výchozím nastavení použije browser.screenshotDirectory
(standardně __screenshot__
), spolu s názvy souboru a testu k určení cesty k souboru snímku obrazovky.
Pokud potřebujete také obsah snímku obrazovky, můžete zadat base64: true
, aby se vrátil spolu s cestou k souboru, kde je snímek obrazovky uložen.
import { page } from '@vitest/browser/context';
const button = page.getByRole('button', { name: 'Click Me!' });
const path = await button.screenshot();
const { path, base64 } = await button.screenshot({
path: './button-click-me.png',
base64: true, // také vrátí řetězec base64
});
// path - úplná cesta k snímku obrazovky
// base64 - řetězec snímku obrazovky kódovaný v base64
VAROVÁNÍ 3.2.0+
Všimněte si, že screenshot
vždy vrátí řetězec base64, pokud je save
nastaveno na false
. V takovém případě je path
také ignorována.
query
function query(): Element | null;
Tato metoda vrací jeden prvek odpovídající selektoru lokátoru nebo null
, pokud není nalezen žádný.
Pokud selektoru odpovídá více prvků, tato metoda vyvolá chybu. Použijte .elements()
, když potřebujete všechny odpovídající prvky DOM, nebo .all()
, pokud potřebujete pole lokátorů odpovídajících selektoru.
Zvažte následující strukturu DOM:
<div>Hello <span>World</span></div>
<div>Hello</div>
Tyto lokátory nevyvolají chybu:
page.getByText('Hello World').query(); // ✅ HTMLDivElement
page.getByText('Hello Germany').query(); // ✅ null
page.getByText('World').query(); // ✅ HTMLSpanElement
page.getByText('Hello', { exact: true }).query(); // ✅ HTMLSpanElement
Tyto lokátory vyvolají chybu:
// vrátí více prvků
page.getByText('Hello').query(); // ❌
page.getByText(/^Hello/).query(); // ❌
element
function element(): Element;
Tato metoda vrací jeden prvek odpovídající selektoru lokátoru.
Pokud selektoru neodpovídá žádný prvek, je vyhozena chyba. Zvažte použití .query()
, když potřebujete pouze zkontrolovat, zda prvek existuje.
Pokud selektoru odpovídá více prvků, je vyhozena chyba. Použijte .elements()
, když potřebujete všechny odpovídající prvky DOM, nebo .all()
, pokud potřebujete pole lokátorů odpovídajících selektoru.
TIP
Tato metoda je vhodná, když potřebujete předat prvek externí knihovně. Je volána automaticky, když je lokátor použit s expect.element
pokaždé, když je tvrzení opakováno:
await expect.element(page.getByRole('button')).toBeDisabled();
Zvažte následující strukturu DOM:
<div>Hello <span>World</span></div>
<div>Hello Germany</div>
<div>Hello</div>
Tyto lokátory nevyvolají chybu:
page.getByText('Hello World').element(); // ✅
page.getByText('Hello Germany').element(); // ✅
page.getByText('World').element(); // ✅
page.getByText('Hello', { exact: true }).element(); // ✅
Tyto lokátory vyvolají chybu:
// vrátí více prvků
page.getByText('Hello').element(); // ❌
page.getByText(/^Hello/).element(); // ❌
// nevrátí žádné prvky
page.getByText('Hello USA').element(); // ❌
elements
function elements(): Element[];
Tato metoda vrací pole prvků odpovídajících selektoru lokátoru.
Tato funkce nikdy nevyvolá chybu. Pokud selektoru neodpovídají žádné prvky, tato metoda vrátí prázdné pole.
Zvažte následující strukturu DOM:
<div>Hello <span>World</span></div>
<div>Hello</div>
Tyto lokátory budou vždy úspěšné:
page.getByText('Hello World').elements(); // ✅ [HTMLElement]
page.getByText('World').elements(); // ✅ [HTMLElement]
page.getByText('Hello', { exact: true }).elements(); // ✅ [HTMLElement]
page.getByText('Hello').element(); // ✅ [HTMLElement, HTMLElement]
page.getByText('Hello USA').elements(); // ✅ []
all
function all(): Locator[];
Tato metoda vrací pole nových lokátorů, které odpovídají selektoru.
Interně tato metoda volá .elements
a obaluje každý prvek pomocí page.elementLocator
.
Vlastnosti
selector
selector
je řetězec, který bude použit k lokalizaci prvku poskytovatelem prohlížeče. Playwright použije syntaxi lokátoru playwright
, zatímco preview
a webdriverio
použijí CSS.
DANGER
Tento řetězec byste neměli přímo používat v testovacím kódu. Řetězec selector
by měl být použit pouze při práci s Commands API:
import type { BrowserCommand } from 'vitest/node';
const test: BrowserCommand<string> = function test(context, selector) {
// playwright
await context.iframe.locator(selector).click();
// webdriverio
await context.browser.$(selector).click();
};
import { test } from 'vitest';
import { commands, page } from '@vitest/browser/context';
test('works correctly', async () => {
await commands.test(page.getByText('Hello').selector); // ✅
// vitest to automaticky rozbalí na řetězec.
await commands.test(page.getByText('Hello')); // ✅
});
Vlastní lokátory 3.2.0+ pokročilé
Vestavěné API lokátorů můžete rozšířit definováním objektu s továrními funkcemi pro lokátory. Tyto metody pak budou dostupné jak na objektu page
, tak na všech vytvořených lokátorech.
Tyto lokátory mohou být užitečné, pokud vestavěné lokátory nestačí. Například, když používáte vlastní framework pro své UI.
Tovární funkce lokátoru musí vrátit řetězec selektoru nebo samotný lokátor.
TIP
Syntaxe selektoru je identická s lokátory Playwrightu. Přečtěte si prosím jejich průvodce, abyste lépe pochopili, jak s nimi pracovat.
import { locators } from '@vitest/browser/context';
locators.extend({
getByArticleTitle(title) {
return `[data-title="${title}"]`;
},
getByArticleCommentsCount(count) {
return `.comments :text("${count} comments")`;
},
async previewComments() {
// máte přístup k aktuálnímu lokátoru přes "this"
// pozor - pokud je metoda volána na `page`, pak `this` odkazuje na `page`,
// ne na lokátor!
if (this !== page) {
await this.click();
}
// ...
},
});
// pokud používáte typescript, můžete rozšířit rozhraní LocatorSelectors
// pro automatické doplňování v metodách locators.extend, page.* a locator.*
declare module '@vitest/browser/context' {
interface LocatorSelectors {
// pokud vlastní metoda vrátí řetězec, bude převeden na lokátor
// pokud vrátí cokoli jiného, pak to bude vráceno jako obvykle
getByArticleTitle(title: string): Locator;
getByArticleCommentsCount(count: number): Locator;
// Vitest vrátí promise a nebude se ji snažit převést na lokátor
previewComments(this: Locator): Promise<void>;
}
}
Pokud je metoda volána na globálním objektu page
, pak se selektor aplikuje na celou stránku. V níže uvedeném příkladu getByArticleTitle
najde všechny prvky s atributem data-title
s hodnotou title
. Pokud je však metoda volána na lokátoru, pak bude omezena na tento lokátor.
<article data-title="Hello, World!">
Hello, World!
<button id="comments">2 comments</button>
</article>
<article data-title="Hello, Vitest!">
Hello, Vitest!
<button id="comments">0 comments</button>
</article>
const articles = page.getByRole('article');
const worldArticle = page.getByArticleTitle('Hello, World!'); // ✅
const commentsElement = worldArticle.getByArticleCommentsCount(2); // ✅
const wrongCommentsElement = worldArticle.getByArticleCommentsCount(0); // ❌
const wrongElement = page.getByArticleTitle('No Article!'); // ❌
await commentsElement.previewComments(); // ✅
await wrongCommentsElement.previewComments(); // ❌