Lokatory 2.1.0+
Lokator reprezentuje pojedynczy element lub grupę elementów. Każdy lokator jest definiowany przez ciąg znaków zwany selektorem. Vitest ukrywa ten selektor, udostępniając wygodne metody, które generują te selektory automatycznie.
API lokatorów wykorzystuje rozwidlenie lokatorów Playwright o nazwie Ivya. Jednak Vitest udostępnia to API każdemu dostawcy.
getByRole
function getByRole(
role: ARIARole | string,
options?: LocatorByRoleOptions
): Locator;
Umożliwia zlokalizowanie elementu według jego roli ARIA, atrybutów ARIA i dostępnej nazwy.
TIP
Jeśli szukasz pojedynczego elementu za pomocą getByText('Nazwa')
, często lepszym rozwiązaniem jest użycie getByRole(oczekiwanaRola, { name: 'Nazwa' })
. Wyszukiwanie po dostępnej nazwie nie zastępuje innych metod wyszukiwania, takich jak *ByAltText
czy *ByTitle
. Chociaż dostępna nazwa może być równa tym atrybutom, nie zastępuje funkcjonalności tych atrybutów.
Rozważ następującą strukturę DOM:
<h3>Sign up</h3>
<label>
Login
<input type="text" />
</label>
<label>
Password
<input type="password" />
</label>
<br />
<button>Submit</button>
Możesz zlokalizować każdy element na podstawie jego niejawnej roli:
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 są dopasowywane przez dokładne dopasowanie ciągów znaków, bez dziedziczenia z hierarchii ról ARIA. W rezultacie zapytanie o rolę nadklasy, taką jak checkbox
, nie będzie zawierać elementów z rolą podklasy, taką jak switch
.
Domyślnie wiele elementów semantycznych HTML ma przypisaną rolę; na przykład <input type="radio">
ma rolę "radio". Elementy niesemantyczne w HTML nie mają roli; <div>
i <span>
bez dodanej semantyki zwracają null
. Atrybut role
może zapewnić semantykę.
Nadawanie ról za pomocą atrybutów role
lub aria-*
elementom wbudowanym, które już mają niejawną rolę, jest wysoce odradzane przez wytyczne ARIA.
Opcje
exact: boolean
Czy
name
jest dopasowywane dokładnie: z uwzględnieniem wielkości liter oraz całego ciągu znaków. Domyślnie wyłączone. Ta opcja jest ignorowana, jeśliname
jest wyrażeniem regularnym. Należy pamiętać, że nawet przy dokładnym dopasowaniu białe znaki są usuwane.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
Czy elementy zaznaczone (ustawione przez
aria-checked
lub<input type="checkbox"/>
) powinny być uwzględniane, czy nie. Domyślnie filtr nie jest stosowany.Zobacz
aria-checked
aby uzyskać więcej informacji.tsx<> <button role="checkbox" aria-checked="true" /> <input type="checkbox" checked /> </>; page.getByRole('checkbox', { checked: true }); // ✅ page.getByRole('checkbox', { checked: false }); // ❌
disabled: boolean
Czy elementy wyłączone powinny być uwzględniane, czy nie. Domyślnie filtr nie jest stosowany. Zauważ, że w przeciwieństwie do innych atrybutów, stan wyłączenia jest dziedziczony.
Zobacz
aria-disabled
aby uzyskać więcej informacji.tsx<input type="text" disabled />; page.getByRole('textbox', { disabled: true }); // ✅ page.getByRole('textbox', { disabled: false }); // ❌
expanded: boolean
Czy elementy rozwinięte powinny być uwzględniane, czy nie. Domyślnie filtr nie jest stosowany.
Zobacz
aria-expanded
aby uzyskać więcej informacji.tsx<a aria-expanded="true" href="example.com"> Link </a>; page.getByRole('link', { expanded: true }); // ✅ page.getByRole('link', { expanded: false }); // ❌
includeHidden: boolean
Czy elementy, które są normalnie wykluczone z drzewa dostępności, powinny być wyszukiwane? Domyślnie tylko elementy widoczne są dopasowywane przez selektor roli.
Zauważ, że role
none
orazpresentation
są zawsze uwzględniane.tsx<button style="display: none" />; page.getByRole('button'); // ❌ page.getByRole('button', { includeHidden: false }); // ❌ page.getByRole('button', { includeHidden: true }); // ✅
level: number
Atrybut liczbowy, który zazwyczaj występuje dla ról
heading
,listitem
,row
,treeitem
, z wartościami domyślnymi dla elementów<h1>-<h6>
. Domyślnie filtr nie jest stosowany.Zobacz
aria-level
aby uzyskać więcej informacji.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
Dostępna nazwa. Domyślnie dopasowanie jest bez uwzględniania wielkości liter i wyszukuje podciąg. Użyj opcji
exact
, aby kontrolować to zachowanie.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
Czy elementy naciśnięte powinny być uwzględniane, czy nie. Domyślnie filtr nie jest stosowany.
Zobacz
aria-pressed
aby uzyskać więcej informacji.tsx<button aria-pressed="true">👍</button>; page.getByRole('button', { pressed: true }); // ✅ page.getByRole('button', { pressed: false }); // ❌
selected: boolean
Czy elementy zaznaczone powinny być uwzględniane, czy nie. Domyślnie filtr nie jest stosowany.
Zobacz
aria-selected
aby uzyskać więcej informacji.tsx<button role="tab" aria-selected="true"> Vue </button>; page.getByRole('button', { selected: true }); // ✅ page.getByRole('button', { selected: false }); // ❌
Zobacz także
getByAltText
function getByAltText(text: string | RegExp, options?: LocatorOptions): Locator;
Umożliwia znalezienie elementu z atrybutem alt
, który pasuje do tekstu. W przeciwieństwie do implementacji testing-library, Vitest dopasuje każdy element, który ma pasujący atrybut alt
.
<img alt="Incredibles 2 Poster" src="/incredibles-2.png" />;
page.getByAltText(/incredibles.*? poster/i); // ✅
page.getByAltText('non existing alt text'); // ❌
Opcje
exact: boolean
Czy
text
jest dopasowywane dokładnie: z uwzględnieniem wielkości liter oraz całego ciągu znaków. Domyślnie wyłączone. Ta opcja jest ignorowana, jeślitext
jest wyrażeniem regularnym. Należy pamiętać, że nawet przy dokładnym dopasowaniu białe znaki są usuwane.
Zobacz także
getByLabelText
function getByLabelText(
text: string | RegExp,
options?: LocatorOptions
): Locator;
Umożliwia znalezienie elementu, który ma powiązaną etykietę.
Lokator page.getByLabelText('Nazwa użytkownika')
znajdzie każdy element input w poniższym przykładzie:
<!-- relacja for/htmlFor między etykietą a id elementu formularza -->
<label for="username-input">Username</label>
<input id="username-input" />
<!-- Atrybut aria-labelledby z elementami formularza -->
<label id="username-label">Username</label>
<input aria-labelledby="username-label" />
<!-- Etykiety opakowujące -->
<label>Username <input /></label>
<!-- Etykiety opakowujące, gdzie tekst etykiety znajduje się w innym elemencie potomnym -->
<label>
<span>Username</span>
<input />
</label>
<!-- Atrybuty aria-label -->
<!-- Uważaj, ponieważ nie jest to etykieta, którą użytkownicy mogą zobaczyć na stronie, -->
<!-- więc cel twojego inputu musi być oczywisty dla użytkowników widzących. -->
<input aria-label="Username" />
Opcje
exact: boolean
Czy
text
jest dopasowywane dokładnie: z uwzględnieniem wielkości liter oraz całego ciągu znaków. Domyślnie wyłączone. Ta opcja jest ignorowana, jeślitext
jest wyrażeniem regularnym. Należy pamiętać, że nawet przy dokładnym dopasowaniu białe znaki są usuwane.
Zobacz także
getByPlaceholder
function getByPlaceholder(
text: string | RegExp,
options?: LocatorOptions
): Locator;
Umożliwia znalezienie elementu, który ma określony atrybut placeholder
. Vitest dopasuje każdy element, który ma pasujący atrybut placeholder
, nie tylko input
.
<input placeholder="Username" />;
page.getByPlaceholder('Username'); // ✅
page.getByPlaceholder('not found'); // ❌
WARNING
Ogólnie lepiej jest polegać na etykiecie przy użyciu getByLabelText
niż na placeholderze.
Opcje
exact: boolean
Czy
text
jest dopasowywane dokładnie: z uwzględnieniem wielkości liter oraz całego ciągu znaków. Domyślnie wyłączone. Ta opcja jest ignorowana, jeślitext
jest wyrażeniem regularnym. Należy pamiętać, że nawet przy dokładnym dopasowaniu białe znaki są usuwane.
Zobacz także
getByText
function getByText(text: string | RegExp, options?: LocatorOptions): Locator;
Umożliwia znalezienie elementu, który zawiera określony tekst. Tekst będzie dopasowywany do nodeValue
TextNode lub wartości inputu, jeśli typ to button
lub reset
. Dopasowanie według tekstu zawsze normalizuje białe znaki, nawet w przypadku dokładnego dopasowania. Na przykład, zamienia wiele spacji w jedną, zamienia znaki końca linii w spacje i ignoruje wiodące i końcowe białe znaki.
<a href="/about">About ℹ️</a>;
page.getByText(/about/i); // ✅
page.getByText('about', { exact: true }); // ❌
TIP
Ten lokator jest przydatny do lokalizowania elementów nieinteraktywnych. Jeśli musisz zlokalizować element interaktywny, taki jak przycisk lub input, preferuj getByRole
.
Opcje
exact: boolean
Czy
text
jest dopasowywane dokładnie: z uwzględnieniem wielkości liter oraz całego ciągu znaków. Domyślnie wyłączone. Ta opcja jest ignorowana, jeślitext
jest wyrażeniem regularnym. Należy pamiętać, że nawet przy dokładnym dopasowaniu białe znaki są usuwane.
Zobacz także
getByTitle
function getByTitle(text: string | RegExp, options?: LocatorOptions): Locator;
Umożliwia znalezienie elementu, który ma określony atrybut title
. W przeciwieństwie do getByTitle
w testing-library, Vitest nie może znaleźć elementów title
wewnątrz SVG.
<span title="Delete" id="2"></span>;
page.getByTitle('Delete'); // ✅
page.getByTitle('Create'); // ❌
Opcje
exact: boolean
Czy
text
jest dopasowywane dokładnie: z uwzględnieniem wielkości liter oraz całego ciągu znaków. Domyślnie wyłączone. Ta opcja jest ignorowana, jeślitext
jest wyrażeniem regularnym. Należy pamiętać, że nawet przy dokładnym dopasowaniu białe znaki są usuwane.
Zobacz także
getByTestId
function getByTestId(text: string | RegExp): Locator;
Umożliwia znalezienie elementu pasującego do określonego atrybutu testowego id. Możesz skonfigurować nazwę atrybutu za pomocą browser.locators.testIdAttribute
.
<div data-testid="custom-element" />;
page.getByTestId('custom-element'); // ✅
page.getByTestId('non-existing-element'); // ❌
WARNING
Zaleca się używanie tego tylko wtedy, gdy inne lokatory nie działają w twoim przypadku. Używanie atrybutów data-testid
nie odzwierciedla sposobu używania twojego oprogramowania i powinno być unikane, jeśli to możliwe.
Opcje
exact: boolean
Czy
text
jest dopasowywane dokładnie: z uwzględnieniem wielkości liter oraz całego ciągu znaków. Domyślnie wyłączone. Ta opcja jest ignorowana, jeślitext
jest wyrażeniem regularnym. Należy pamiętać, że nawet przy dokładnym dopasowaniu białe znaki są usuwane.
Zobacz także
Metody
Wszystkie metody są asynchroniczne i muszą być oczekiwane. Od wersji Vitest 2.2 testy zakończą się niepowodzeniem, jeśli metoda nie zostanie oczekiwana.
click
function click(options?: UserEventClickOptions): Promise<void>;
Kliknij na element. Możesz użyć opcji do ustawienia pozycji kursora.
import { page } from '@vitest/browser/context';
await page.getByRole('img', { name: 'Rose' }).click();
dblClick
function dblClick(options?: UserEventDoubleClickOptions): Promise<void>;
Wyzwala zdarzenie podwójnego kliknięcia na danym elemencie. Możesz użyć opcji do ustawienia pozycji kursora.
import { page } from '@vitest/browser/context';
await page.getByRole('img', { name: 'Rose' }).dblClick();
tripleClick
function tripleClick(options?: UserEventTripleClickOptions): Promise<void>;
Wyzwala zdarzenie potrójnego kliknięcia na danym elemencie. Ponieważ w API przeglądarki nie ma tripleclick
, ta metoda wywoła trzy zdarzenia kliknięcia z rzędu.
import { page } from '@vitest/browser/context';
await page.getByRole('img', { name: 'Rose' }).tripleClick();
clear
function clear(): Promise<void>;
Czyści zawartość elementu input.
import { page } from '@vitest/browser/context';
await page.getByRole('textbox', { name: 'Full Name' }).clear();
hover
function hover(options?: UserEventHoverOptions): Promise<void>;
Przesuwa pozycję kursora do wybranego elementu.
import { page } from '@vitest/browser/context';
await page.getByRole('img', { name: 'Rose' }).hover();
unhover
function unhover(options?: UserEventHoverOptions): Promise<void>;
Działa tak samo jak locator.hover
, ale zamiast tego przesuwa kursor do elementu document.body
.
import { page } from '@vitest/browser/context';
await page.getByRole('img', { name: 'Rose' }).unhover();
fill
function fill(text: string, options?: UserEventFillOptions): Promise<void>;
Ustawia wartość bieżącego elementu input
, textarea
lub 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>;
Przeciąga bieżący element do docelowej lokalizacji.
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>;
Wybierz jedną lub więcej wartości z elementu <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 & { base64: true }
): Promise<{
path: string;
base64: string;
}>;
function screenshot(
options?: LocatorScreenshotOptions & { base64?: false }
): Promise<string>;
Tworzy zrzut ekranu elementu pasującego do selektora lokatora.
Możesz określić lokalizację zapisu zrzutu ekranu za pomocą opcji path
, która jest względna w stosunku do bieżącego pliku testowego. Jeśli opcja path
nie jest ustawiona, Vitest domyślnie użyje browser.screenshotDirectory
(domyślnie __screenshot__
), wraz z nazwami pliku i testu, aby określić ścieżkę pliku zrzutu ekranu.
Jeśli potrzebujesz również zawartości zrzutu ekranu, możesz określić base64: true
, aby zwrócić ją wraz ze ścieżką pliku, w której zrzut ekranu jest zapisany.
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, // also return base64 string
});
// path - pełna ścieżka do zrzutu ekranu
// base64 - łańcuch znaków zakodowany w base64 zrzutu ekranu
query
function query(): Element | null;
Ta metoda zwraca pojedynczy element pasujący do selektora lokatora lub null
, jeśli nie znaleziono żadnego elementu.
Gdy wiele elementów pasuje do selektora, metoda zgłasza błąd. Użyj .elements()
, gdy potrzebujesz wszystkich pasujących elementów DOM, lub .all()
, jeśli potrzebujesz tablicy lokatorów pasujących do selektora.
Rozważ poniższą strukturę DOM:
<div>Hello <span>World</span></div>
<div>Hello</div>
Te lokatory nie zgłoszą błędu:
page.getByText('Hello World').query(); // ✅ HTMLDivElement
page.getByText('Hello Germany').query(); // ✅ null
page.getByText('World').query(); // ✅ HTMLSpanElement
page.getByText('Hello', { exact: true }).query(); // ✅ HTMLSpanElement
Te lokatory zgłoszą błąd:
// zwraca wiele elementów
page.getByText('Hello').query(); // ❌
page.getByText(/^Hello/).query(); // ❌
element
function element(): Element;
Ta metoda zwraca pojedynczy element pasujący do selektora lokatora.
Jeśli żaden element nie pasuje do selektora, zgłaszany jest błąd. Rozważ użycie .query()
, gdy potrzebujesz tylko sprawdzić, czy element istnieje.
Jeśli wiele elementów pasuje do selektora, zgłaszany jest błąd. Użyj .elements()
, gdy potrzebujesz wszystkich pasujących elementów DOM, lub .all()
, jeśli potrzebujesz tablicy lokatorów pasujących do selektora.
TIP
Ta metoda może być przydatna, jeśli musisz przekazać ją do zewnętrznej biblioteki. Jest wywoływana automatycznie, gdy lokator jest używany z expect.element
za każdym razem, gdy asercja jest ponawiana:
await expect.element(page.getByRole('button')).toBeDisabled();
Rozważ poniższą strukturę DOM:
<div>Hello <span>World</span></div>
<div>Hello Germany</div>
<div>Hello</div>
Te lokatory nie zgłoszą błędu:
page.getByText('Hello World').element(); // ✅
page.getByText('Hello Germany').element(); // ✅
page.getByText('World').element(); // ✅
page.getByText('Hello', { exact: true }).element(); // ✅
Te lokatory zgłoszą błąd:
// zwraca wiele elementów
page.getByText('Hello').element(); // ❌
page.getByText(/^Hello/).element(); // ❌
// nie zwraca żadnych elementów
page.getByText('Hello USA').element(); // ❌
elements
function elements(): Element[];
Ta metoda zwraca tablicę elementów pasujących do selektora lokatora.
Ta funkcja nigdy nie zgłasza błędu. Jeśli nie ma elementów pasujących do selektora, ta metoda zwróci pustą tablicę.
Rozważ poniższą strukturę DOM:
<div>Hello <span>World</span></div>
<div>Hello</div>
Te lokatory zawsze zakończą się sukcesem:
page.getByText('Hello World').elements(); // ✅ [HTMLElement]
page.getByText('World').elements(); // ✅ [HTMLElement]
page.getByText('Hello', { exact: true }).elements(); // ✅ [HTMLElement]
page.getByText('Hello').elements(); // ✅ [HTMLElement, HTMLElement]
page.getByText('Hello USA').elements(); // ✅ []
all
function all(): Locator[];
Ta metoda zwraca tablicę nowych lokatorów, które pasują do selektora.
Wewnętrznie ta metoda wywołuje .elements
i opakowuje każdy element za pomocą page.elementLocator
.