API asercji
Vitest zapewnia szeroki zakres asercji DOM dostępnych od razu po instalacji, zaczerpniętych z biblioteki @testing-library/jest-dom
, z dodatkowym wsparciem dla lokatorów oraz wbudowaną ponawialnością.
Wsparcie dla TypeScript
Jeśli używasz TypeScript lub chcesz mieć poprawne podpowiedzi typów w expect
, upewnij się, że masz odwołanie do @vitest/browser/context
w swoim projekcie. Jeśli nigdy stamtąd nie importowałeś, możesz dodać komentarz reference
w dowolnym pliku, który jest objęty twoim tsconfig.json
:
/// <reference types="@vitest/browser/context" />
Testy w przeglądarce mogą czasami nie powodzić się niespójnie ze względu na ich asynchroniczną naturę. Z tego powodu ważne jest, aby mieć sposób na zagwarantowanie, że asercje powiodą się, nawet jeśli warunek jest opóźniony (na przykład z powodu limitu czasu, żądania sieciowego lub animacji). W tym celu Vitest oferuje asercje z możliwością ponawiania prób, dostępne od razu po zainstalowaniu, za pośrednictwem API expect.poll
i expect.element
:
import { expect, test } from 'vitest';
import { page } from '@vitest/browser/context';
test('error banner is rendered', async () => {
triggerError();
// To tworzy lokator, który spróbuje znaleźć element gdy wywołana zostanie którakolwiek z jego metod.
// To wywołanie samo w sobie nie sprawdza istnienia elementu.
const banner = page.getByRole('alert', {
name: /error/i,
});
// Vitest zapewnia `expect.element` z wbudowaną ponawialnością.
// Będzie on wielokrotnie sprawdzał, czy element istnieje w DOM i czy zawartość `element.textContent` jest równa "Error!" aż wszystkie warunki zostaną spełnione
await expect.element(banner).toHaveTextContent('Error!');
});
Zalecamy, aby zawsze używać expect.element
podczas pracy z lokatorami page.getBy*
, aby zredukować niestabilność testów. Należy zauważyć, że expect.element
akceptuje drugi argument:
interface ExpectPollOptions {
// Interwał ponawiania asercji (w milisekundach)
// Domyślnie: opcja konfiguracyjna "expect.poll.interval"
interval?: number;
// Czas ponawiania asercji (w milisekundach)
// Domyślnie: opcja konfiguracyjna "expect.poll.timeout"
timeout?: number;
// Wiadomość, która zostanie wyświetlona, gdy asercja się nie powiedzie
message?: string;
}
TIP
expect.element
to skrót dla expect.poll(() => element)
i działa dokładnie w ten sam sposób.
toHaveTextContent
i wszystkie inne asercje są nadal dostępne w zwykłym expect
bez wbudowanego mechanizmu ponawiania prób:
// natychmiast zawiedzie, jeśli .textContent nie jest równe `'Error!'`
expect(banner).toHaveTextContent('Error!');
toBeDisabled
function toBeDisabled(): Promise<void>;
Pozwala sprawdzić, czy element jest wyłączony z perspektywy użytkownika.
Pasuje, jeśli element jest kontrolką formularza, a atrybut disabled
jest ustawiony dla tego elementu lub element jest potomkiem elementu formularza z atrybutem disabled
.
Zauważ, że tylko natywne elementy sterujące, takie jak HTML button
, input
, select
, textarea
, option
, optgroup
, mogą być wyłączone poprzez ustawienie atrybutu "disabled". Atrybut "disabled" na innych elementach jest ignorowany, chyba że są to elementy niestandardowe.
<button data-testid="button" type="submit" disabled>submit</button>
await expect.element(getByTestId('button')).toBeDisabled(); // ✅
await expect.element(getByTestId('button')).not.toBeDisabled(); // ❌
toBeEnabled
function toBeEnabled(): Promise<void>;
Pozwala sprawdzić, czy element nie jest wyłączony z perspektywy użytkownika.
Działa jak not.toBeDisabled()
. Użyj tego dopasowania, aby uniknąć podwójnego zaprzeczenia w testach.
<button data-testid="button" type="submit" disabled>submit</button>
await expect.element(getByTestId('button')).toBeEnabled(); // ✅
await expect.element(getByTestId('button')).not.toBeEnabled(); // ❌
toBeEmptyDOMElement
function toBeEmptyDOMElement(): Promise<void>;
Pozwala sprawdzić, czy element nie ma widocznej zawartości dla użytkownika. Ignoruje komentarze, ale zawiedzie, jeśli element zawiera białe znaki.
<span data-testid="not-empty"><span data-testid="empty"></span></span>
<span data-testid="with-whitespace"> </span>
<span data-testid="with-comment"><!-- comment --></span>
await expect.element(getByTestId('empty')).toBeEmptyDOMElement();
await expect.element(getByTestId('not-empty')).not.toBeEmptyDOMElement();
await expect.element(getByTestId('with-whitespace')).not.toBeEmptyDOMElement();
toBeInTheDocument
function toBeInTheDocument(): Promise<void>;
Sprawdź, czy element jest obecny w dokumencie.
<svg data-testid="svg-element"></svg>
await expect.element(getByTestId('svg-element')).toBeInTheDocument();
await expect.element(getByTestId('does-not-exist')).not.toBeInTheDocument();
WARNING
Ta funkcja dopasowująca nie znajduje odłączonych elementów. Element musi być dodany do dokumentu, aby został znaleziony przez toBeInTheDocument
. Jeśli chcesz wyszukać w odłączonym elemencie, użyj: toContainElement
.
toBeInvalid
function toBeInvalid(): Promise<void>;
Pozwala sprawdzić, czy element jest obecnie nieprawidłowy.
Element jest nieprawidłowy, jeśli ma atrybut aria-invalid
bez wartości lub z wartością "true"
, lub jeśli wynik checkValidity()
jest false
.
<input data-testid="no-aria-invalid" />
<input data-testid="aria-invalid" aria-invalid />
<input data-testid="aria-invalid-value" aria-invalid="true" />
<input data-testid="aria-invalid-false" aria-invalid="false" />
<form data-testid="valid-form">
<input />
</form>
<form data-testid="invalid-form">
<input required />
</form>
await expect.element(getByTestId('no-aria-invalid')).not.toBeInvalid();
await expect.element(getByTestId('aria-invalid')).toBeInvalid();
await expect.element(getByTestId('aria-invalid-value')).toBeInvalid();
await expect.element(getByTestId('aria-invalid-false')).not.toBeInvalid();
await expect.element(getByTestId('valid-form')).not.toBeInvalid();
await expect.element(getByTestId('invalid-form')).toBeInvalid();
toBeRequired
function toBeRequired(): Promise<void>;
Pozwala sprawdzić, czy element formularza jest obecnie wymagany.
Element jest wymagany, jeśli posiada atrybut required
lub aria-required="true"
.
<input data-testid="required-input" required />
<input data-testid="aria-required-input" aria-required="true" />
<input data-testid="conflicted-input" required aria-required="false" />
<input data-testid="aria-not-required-input" aria-required="false" />
<input data-testid="optional-input" />
<input data-testid="unsupported-type" type="image" required />
<select data-testid="select" required></select>
<textarea data-testid="textarea" required></textarea>
<div data-testid="supported-role" role="tree" required></div>
<div data-testid="supported-role-aria" role="tree" aria-required="true"></div>
await expect.element(getByTestId('required-input')).toBeRequired();
await expect.element(getByTestId('aria-required-input')).toBeRequired();
await expect.element(getByTestId('conflicted-input')).toBeRequired();
await expect.element(getByTestId('aria-not-required-input')).not.toBeRequired();
await expect.element(getByTestId('optional-input')).not.toBeRequired();
await expect.element(getByTestId('unsupported-type')).not.toBeRequired();
await expect.element(getByTestId('select')).toBeRequired();
await expect.element(getByTestId('textarea')).toBeRequired();
await expect.element(getByTestId('supported-role')).not.toBeRequired();
await expect.element(getByTestId('supported-role-aria')).toBeRequired();
toBeValid
function toBeValid(): Promise<void>;
Pozwala sprawdzić, czy wartość elementu jest obecnie prawidłowa.
Element jest prawidłowy, jeśli nie ma atrybutu aria-invalid
lub ma wartość atrybutu "false". Wynik checkValidity()
musi być również true
, jeśli jest to element formularza.
<input data-testid="no-aria-invalid" />
<input data-testid="aria-invalid" aria-invalid />
<input data-testid="aria-invalid-value" aria-invalid="true" />
<input data-testid="aria-invalid-false" aria-invalid="false" />
<form data-testid="valid-form">
<input />
</form>
<form data-testid="invalid-form">
<input required />
</form>
await expect.element(getByTestId('no-aria-invalid')).toBeValid();
await expect.element(getByTestId('aria-invalid')).not.toBeValid();
await expect.element(getByTestId('aria-invalid-value')).not.toBeValid();
await expect.element(getByTestId('aria-invalid-false')).toBeValid();
await expect.element(getByTestId('valid-form')).toBeValid();
await expect.element(getByTestId('invalid-form')).not.toBeValid();
toBeVisible
function toBeVisible(): Promise<void>;
Pozwala sprawdzić, czy element jest obecnie widoczny dla użytkownika.
Element uznaje się za widoczny, gdy ma niepuste pole ograniczające i nie ma obliczonego stylu visibility:hidden
.
Zauważ, że zgodnie z tą definicją:
- Elementy o zerowym rozmiarze nie są uważane za widoczne.
- Elementy z
display:none
nie są uważane za widoczne. - Elementy z
opacity:0
są uważane za widoczne.
Aby sprawdzić, czy co najmniej jeden element z listy jest widoczny, użyj locator.first()
.
// Określony element jest widoczny.
await expect.element(page.getByText('Welcome')).toBeVisible();
// Co najmniej jeden element na liście jest widoczny.
await expect.element(page.getByTestId('todo-item').first()).toBeVisible();
// Co najmniej jeden z dwóch elementów jest widoczny, być może oba.
await expect
.element(
page
.getByRole('button', { name: 'Sign in' })
.or(page.getByRole('button', { name: 'Sign up' }))
.first()
)
.toBeVisible();
toContainElement
function toContainElement(
element: HTMLElement | SVGElement | null
): Promise<void>;
Pozwala sprawdzić, czy element zawiera inny element jako potomka.
<span data-testid="ancestor"><span data-testid="descendant"></span></span>
const ancestor = getByTestId('ancestor');
const descendant = getByTestId('descendant');
const nonExistantElement = getByTestId('does-not-exist');
await expect.element(ancestor).toContainElement(descendant);
await expect.element(descendant).not.toContainElement(ancestor);
await expect.element(ancestor).not.toContainElement(nonExistantElement);
toContainHTML
function toContainHTML(htmlText: string): Promise<void>;
Sprawdź, czy ciąg znaków reprezentujący element HTML jest zawarty w innym elemencie. Ciąg powinien być prawidłowym, kompletnym kodem HTML.
<span data-testid="parent"><span data-testid="child"></span></span>
// To są prawidłowe użycia
await expect
.element(getByTestId('parent'))
.toContainHTML('<span data-testid="child"></span>');
await expect
.element(getByTestId('parent'))
.toContainHTML('<span data-testid="child" />');
await expect.element(getByTestId('parent')).not.toContainHTML('<br />');
// To nie zadziała
await expect
.element(getByTestId('parent'))
.toContainHTML('data-testid="child"');
await expect.element(getByTestId('parent')).toContainHTML('data-testid');
await expect.element(getByTestId('parent')).toContainHTML('</span>');
WARNING
Prawdopodobnie nie musisz używać tej funkcji dopasowującej. Zachęcamy do testowania z perspektywy tego, jak użytkownik postrzega aplikację w przeglądarce. Dlatego testowanie w oparciu o konkretną strukturę DOM nie jest zalecane.
Może być przydatne w sytuacjach, gdy testowany kod renderuje HTML uzyskany ze źródła zewnętrznego, a chcesz sprawdzić, czy ten kod HTML został wykorzystany zgodnie z zamierzeniem.
Nie należy go używać do sprawdzania struktury DOM, którą kontrolujesz. Zamiast tego użyj toContainElement
.
toHaveAccessibleDescription
function toHaveAccessibleDescription(
description?: string | RegExp
): Promise<void>;
Pozwala sprawdzić, czy element ma oczekiwany dostępny opis.
Możesz przekazać dokładny ciąg znaków oczekiwanego dostępnego opisu, dokonać częściowego dopasowania, przekazując wyrażenie regularne, lub używając expect.stringContaining
lub expect.stringMatching
.
<a
data-testid="link"
href="/"
aria-label="Home page"
title="A link to start over"
>Start</a
>
<a data-testid="extra-link" href="/about" aria-label="About page">About</a>
<img src="avatar.jpg" data-testid="avatar" alt="User profile pic" />
<img
src="logo.jpg"
data-testid="logo"
alt="Company logo"
aria-describedby="t1"
/>
<span id="t1" role="presentation">The logo of Our Company</span>
<img
src="logo.jpg"
data-testid="logo2"
alt="Company logo"
aria-description="The logo of Our Company"
/>
await expect.element(getByTestId('link')).toHaveAccessibleDescription();
await expect
.element(getByTestId('link'))
.toHaveAccessibleDescription('A link to start over');
await expect
.element(getByTestId('link'))
.not.toHaveAccessibleDescription('Home page');
await expect
.element(getByTestId('extra-link'))
.not.toHaveAccessibleDescription();
await expect.element(getByTestId('avatar')).not.toHaveAccessibleDescription();
await expect
.element(getByTestId('logo'))
.not.toHaveAccessibleDescription('Company logo');
await expect
.element(getByTestId('logo'))
.toHaveAccessibleDescription('The logo of Our Company');
await expect
.element(getByTestId('logo2'))
.toHaveAccessibleDescription('The logo of Our Company');
toHaveAccessibleErrorMessage
function toHaveAccessibleErrorMessage(message?: string | RegExp): Promise<void>;
Pozwala sprawdzić, czy element ma oczekiwany dostępny komunikat o błędzie.
Możesz przekazać dokładny ciąg znaków oczekiwanego dostępnego komunikatu o błędzie. Alternatywnie, możesz dopasować częściowo, przekazując wyrażenie regularne lub używając expect.stringContaining
lub expect.stringMatching
.
<input
aria-label="Has Error"
aria-invalid="true"
aria-errormessage="error-message"
/>
<div id="error-message" role="alert">This field is invalid</div>
<input aria-label="No Error Attributes" />
<input
aria-label="Not Invalid"
aria-invalid="false"
aria-errormessage="error-message"
/>
// Pola wejściowe z prawidłowymi komunikatami o błędach
await expect
.element(getByRole('textbox', { name: 'Has Error' }))
.toHaveAccessibleErrorMessage();
await expect
.element(getByRole('textbox', { name: 'Has Error' }))
.toHaveAccessibleErrorMessage('This field is invalid');
await expect
.element(getByRole('textbox', { name: 'Has Error' }))
.toHaveAccessibleErrorMessage(/invalid/i);
await expect
.element(getByRole('textbox', { name: 'Has Error' }))
.not.toHaveAccessibleErrorMessage('This field is absolutely correct!');
// Pola wejściowe bez prawidłowych komunikatów o błędach
await expect
.element(getByRole('textbox', { name: 'No Error Attributes' }))
.not.toHaveAccessibleErrorMessage();
await expect
.element(getByRole('textbox', { name: 'Not Invalid' }))
.not.toHaveAccessibleErrorMessage();
toHaveAccessibleName
function toHaveAccessibleName(name?: string | RegExp): Promise<void>;
Pozwala sprawdzić, czy element ma oczekiwaną dostępną nazwę. Jest to przydatne, na przykład, do sprawdzenia, czy elementy formularza i przyciski są prawidłowo etykietowane.
Możesz przekazać dokładny ciąg znaków oczekiwanej dostępnej nazwy, lub możesz dokonać częściowego dopasowania, przekazując wyrażenie regularne, lub używając expect.stringContaining
lub expect.stringMatching
.
<img data-testid="img-alt" src="" alt="Test alt" />
<img data-testid="img-empty-alt" src="" alt="" />
<svg data-testid="svg-title"><title>Test title</title></svg>
<button data-testid="button-img-alt"><img src="" alt="Test" /></button>
<p><img data-testid="img-paragraph" src="" alt="" /> Test content</p>
<button data-testid="svg-button"><svg><title>Test</title></svg></p>
<div><svg data-testid="svg-without-title"></svg></div>
<input data-testid="input-title" title="test" />
await expect.element(getByTestId('img-alt')).toHaveAccessibleName('Test alt');
await expect.element(getByTestId('img-empty-alt')).not.toHaveAccessibleName();
await expect
.element(getByTestId('svg-title'))
.toHaveAccessibleName('Test title');
await expect.element(getByTestId('button-img-alt')).toHaveAccessibleName();
await expect.element(getByTestId('img-paragraph')).not.toHaveAccessibleName();
await expect.element(getByTestId('svg-button')).toHaveAccessibleName();
await expect
.element(getByTestId('svg-without-title'))
.not.toHaveAccessibleName();
await expect.element(getByTestId('input-title')).toHaveAccessibleName();
toHaveAttribute
function toHaveAttribute(attribute: string, value?: unknown): Promise<void>;
Pozwala sprawdzić, czy dany element ma atrybut, czy nie. Możesz również opcjonalnie sprawdzić, czy atrybut ma określoną oczekiwaną wartość lub czy częściowo pasuje za pomocą expect.stringContaining
lub expect.stringMatching
.
<button data-testid="ok-button" type="submit" disabled>ok</button>
const button = getByTestId('ok-button');
await expect.element(button).toHaveAttribute('disabled');
await expect.element(button).toHaveAttribute('type', 'submit');
await expect.element(button).not.toHaveAttribute('type', 'button');
await expect
.element(button)
.toHaveAttribute('type', expect.stringContaining('sub'));
await expect
.element(button)
.toHaveAttribute('type', expect.not.stringContaining('but'));
toHaveClass
function toHaveClass(
...classNames: string[],
options?: { exact: boolean }
): Promise<void>;
function toHaveClass(...classNames: (string | RegExp)[]): Promise<void>;
Pozwala sprawdzić, czy dany element ma określone klasy w swoim atrybucie class
. Musisz podać co najmniej jedną klasę, chyba że chcesz sprawdzić, czy element nie ma żadnych klas.
Lista nazw klas może zawierać ciągi znaków i wyrażenia regularne. Wyrażenia regularne są dopasowywane do każdej pojedynczej klasy w elemencie docelowym i nie dopasowują się do całej wartości atrybutu class
.
WARNING
Zauważ, że nie możesz użyć opcji exact: true
, gdy podane są tylko wyrażenia regularne.
<button data-testid="delete-button" class="btn extra btn-danger">
Delete item
</button>
<button data-testid="no-classes">No Classes</button>
const deleteButton = getByTestId('delete-button');
const noClasses = getByTestId('no-classes');
await expect.element(deleteButton).toHaveClass('extra');
await expect.element(deleteButton).toHaveClass('btn-danger btn');
await expect.element(deleteButton).toHaveClass(/danger/, 'btn');
await expect.element(deleteButton).toHaveClass('btn-danger', 'btn');
await expect.element(deleteButton).not.toHaveClass('btn-link');
await expect.element(deleteButton).not.toHaveClass(/link/);
// ⚠️ wyrażenie regularne pasuje do pojedynczych klas, a nie do całej listy klas
await expect.element(deleteButton).not.toHaveClass(/btn extra/);
// element ma DOKŁADNIE zestaw klas (w dowolnej kolejności)
await expect.element(deleteButton).toHaveClass('btn-danger extra btn', {
exact: true,
});
// jeśli ma więcej niż oczekiwano, to zawiedzie
await expect.element(deleteButton).not.toHaveClass('btn-danger extra', {
exact: true,
});
await expect.element(noClasses).not.toHaveClass();
toHaveFocus
function toHaveFocus(): Promise<void>;
Pozwala sprawdzić, czy element ma fokus, czy nie.
<div><input type="text" data-testid="element-to-focus" /></div>
const input = page.getByTestId('element-to-focus');
input.element().focus();
await expect.element(input).toHaveFocus();
input.element().blur();
await expect.element(input).not.toHaveFocus();
toHaveFormValues
function toHaveFormValues(
expectedValues: Record<string, unknown>
): Promise<void>;
Pozwala sprawdzić, czy formularz lub fieldset
zawiera kontrolki formularza dla każdej podanej nazwy i ma określoną wartość.
TIP
Ważne jest, aby podkreślić, że ta funkcja dopasowująca może być wywołana tylko na elemencie formularza lub fieldset.
Pozwala to wykorzystać właściwość .elements
w form
i fieldset
do niezawodnego pobierania wszystkich kontrolek formularza w ich obrębie.
Zapobiega to również sytuacji, w której użytkownicy dostarczają kontener zawierający więcej niż jeden form
, co mogłoby prowadzić do pomieszania niepowiązanych ze sobą kontrolek formularza, a nawet do ich kolizji.
Ta funkcja dopasowująca abstrahuje od specyfiki sposobu uzyskiwania wartości kontrolki formularza, w zależności od jej typu. Na przykład, elementy <input>
mają atrybut value
, ale elementy <select>
nie. Oto lista wszystkich objętych przypadków:
- Elementy
<input type="number">
zwracają wartość jako liczbę, a nie ciąg znaków. - Elementy
<input type="checkbox">
:- jeśli istnieje tylko jeden z danym atrybutem
name
, jest traktowany jako boolean, zwracającytrue
, jeśli pole wyboru jest zaznaczone,false
, jeśli odznaczone. - jeśli istnieje więcej niż jedno pole wyboru z tym samym atrybutem
name
, są one traktowane zbiorowo jako pojedyncza kontrolka formularza, która zwraca wartość jako tablicę zawierającą wszystkie wartości zaznaczonych pól wyboru.
- jeśli istnieje tylko jeden z danym atrybutem
- Elementy
<input type="radio">
są grupowane według atrybutuname
, a taka grupa jest traktowana jako pojedyncza kontrolka formularza, która zwraca wartość jako ciąg znaków odpowiadający atrybutowivalue
zaznaczonego przycisku radiowego w grupie. - Elementy
<input type="text">
zwracają wartość jako ciąg znaków. Dotyczy to również elementów<input>
posiadających dowolny inny atrybuttype
, który nie jest wyraźnie objęty powyższymi regułami (np.search
,email
,date
,password
,hidden
itp.) - Elementy
<select>
bez atrybutumultiple
zwracają wartość jako ciąg znaków odpowiadający atrybutowivalue
wybranejoption
, lubundefined
, jeśli żadna opcja nie jest wybrana. - Elementy
<select multiple>
zwracają wartość jako tablicę zawierającą wszystkie wartości zaznaczonych opcji. - Elementy
<textarea>
zwracają swoją wartość jako ciąg znaków. Wartość odpowiada ich zawartości węzła.
Powyższe zasady ułatwiają, na przykład, przełączanie się z używania pojedynczego elementu select
na używanie grupy przycisków radiowych. Lub przełączanie się z elementu select multiple
na używanie grupy pól wyboru. Wynikowy zestaw wartości formularza używany przez ten matcher do porównania byłby taki sam.
<form data-testid="login-form">
<input type="text" name="username" value="jane.doe" />
<input type="password" name="password" value="12345678" />
<input type="checkbox" name="rememberMe" checked />
<button type="submit">Sign in</button>
</form>
await expect.element(getByTestId('login-form')).toHaveFormValues({
username: 'jane.doe',
rememberMe: true,
});
toHaveStyle
function toHaveStyle(css: string | Partial<CSSStyleDeclaration>): Promise<void>;
Pozwala sprawdzić, czy dany element posiada zastosowane określone właściwości CSS z określonymi wartościami. Dopasowuje tylko wtedy, gdy element posiada wszystkie oczekiwane właściwości, a nie tylko niektóre z nich.
<button
data-testid="delete-button"
style="display: none; background-color: red"
>
Delete item
</button>
const button = getByTestId('delete-button');
await expect.element(button).toHaveStyle('display: none');
await expect.element(button).toHaveStyle({ display: 'none' });
await expect.element(button).toHaveStyle(`
background-color: red;
display: none;
`);
await expect.element(button).toHaveStyle({
backgroundColor: 'red',
display: 'none',
});
await expect.element(button).not.toHaveStyle(`
background-color: blue;
display: none;
`);
await expect.element(button).not.toHaveStyle({
backgroundColor: 'blue',
display: 'none',
});
Działa to również w przypadku reguł CSS, które są stosowane do elementu za pośrednictwem nazwy klasy, a które są zdefiniowane w aktualnie aktywnym arkuszu stylów w dokumencie. Obowiązują zwykłe zasady pierwszeństwa CSS.
toHaveTextContent
function toHaveTextContent(
text: string | RegExp,
options?: { normalizeWhitespace: boolean }
): Promise<void>;
Pozwala sprawdzić, czy dany węzeł ma zawartość tekstową. Obsługuje elementy, ale także węzły tekstowe i fragmenty.
Gdy przekazany zostanie argument string
, zostanie on częściowo dopasowany z uwzględnieniem wielkości liter do zawartości węzła.
Aby dopasować bez uwzględniania wielkości liter, możesz użyć RegExp
z modyfikatorem /i
.
Jeśli chcesz dopasować całą zawartość, możesz użyć RegExp
.
<span data-testid="text-content">Text Content</span>
const element = getByTestId('text-content');
await expect.element(element).toHaveTextContent('Content');
// aby dopasować całą zawartość
await expect.element(element).toHaveTextContent(/^Text Content$/);
// aby użyć dopasowania bez uwzględniania wielkości liter
await expect.element(element).toHaveTextContent(/content$/i);
await expect.element(element).not.toHaveTextContent('content');
toHaveValue
function toHaveValue(value: string | string[] | number | null): Promise<void>;
Pozwala sprawdzić, czy dany element formularza ma określoną wartość. Akceptuje elementy <input>
, <select>
i <textarea>
, z wyjątkiem <input type="checkbox>
i <input type="radio>
, które można skutecznie dopasować tylko za pomocą toBeChecked
lub toHaveFormValues
.
Akceptuje również elementy z rolami meter
, progressbar
, slider
lub spinbutton
i sprawdza ich atrybut aria-valuenow
(traktowany jako liczba).
Dla wszystkich innych elementów formularza wartość jest dopasowywana przy użyciu tego samego algorytmu, co w toHaveFormValues
.
<input type="text" value="text" data-testid="input-text" />
<input type="number" value="5" data-testid="input-number" />
<input type="text" data-testid="input-empty" />
<select multiple data-testid="select-number">
<option value="first">First Value</option>
<option value="second" selected>Second Value</option>
<option value="third" selected>Third Value</option>
</select>
const textInput = getByTestId('input-text');
const numberInput = getByTestId('input-number');
const emptyInput = getByTestId('input-empty');
const selectInput = getByTestId('select-number');
await expect.element(textInput).toHaveValue('text');
await expect.element(numberInput).toHaveValue(5);
await expect.element(emptyInput).not.toHaveValue();
await expect.element(selectInput).toHaveValue(['second', 'third']);
toHaveDisplayValue
function toHaveDisplayValue(
value: string | RegExp | (string | RegExp)[]
): Promise<void>;
Pozwala sprawdzić, czy dany element formularza ma określoną wyświetlaną wartość (widoczną dla użytkownika). Akceptuje elementy <input>
, <select>
i <textarea>
, z wyjątkiem <input type="checkbox>
i <input type="radio>
, które mogą być sensownie dopasowane tylko za pomocą toBeChecked
lub toHaveFormValues
.
<label for="input-example">First name</label>
<input type="text" id="input-example" value="Luca" />
<label for="textarea-example">Description</label>
<textarea id="textarea-example">An example description here.</textarea>
<label for="single-select-example">Fruit</label>
<select id="single-select-example">
<option value="">Select a fruit...</option>
<option value="banana">Banana</option>
<option value="ananas">Ananas</option>
<option value="avocado">Avocado</option>
</select>
<label for="multiple-select-example">Fruits</label>
<select id="multiple-select-example" multiple>
<option value="">Select a fruit...</option>
<option value="banana" selected>Banana</option>
<option value="ananas">Ananas</option>
<option value="avocado" selected>Avocado</option>
</select>
const input = page.getByLabelText('First name');
const textarea = page.getByLabelText('Description');
const selectSingle = page.getByLabelText('Fruit');
const selectMultiple = page.getByLabelText('Fruits');
await expect.element(input).toHaveDisplayValue('Luca');
await expect.element(input).toHaveDisplayValue(/Luc/);
await expect
.element(textarea)
.toHaveDisplayValue('An example description here.');
await expect.element(textarea).toHaveDisplayValue(/example/);
await expect.element(selectSingle).toHaveDisplayValue('Select a fruit...');
await expect.element(selectSingle).toHaveDisplayValue(/Select/);
await expect.element(selectMultiple).toHaveDisplayValue([/Avocado/, 'Banana']);
toBeChecked
function toBeChecked(): Promise<void>;
Pozwala sprawdzić, czy dany element jest zaznaczony. Akceptuje input
typu checkbox
lub radio
oraz elementy z rolą checkbox
, radio
lub switch
posiadające prawidłowy atrybut aria-checked
o wartości "true"
lub "false"
.
<input type="checkbox" checked data-testid="input-checkbox-checked" />
<input type="checkbox" data-testid="input-checkbox-unchecked" />
<div role="checkbox" aria-checked="true" data-testid="aria-checkbox-checked" />
<div
role="checkbox"
aria-checked="false"
data-testid="aria-checkbox-unchecked"
/>
<input type="radio" checked value="foo" data-testid="input-radio-checked" />
<input type="radio" value="foo" data-testid="input-radio-unchecked" />
<div role="radio" aria-checked="true" data-testid="aria-radio-checked" />
<div role="radio" aria-checked="false" data-testid="aria-radio-unchecked" />
<div role="switch" aria-checked="true" data-testid="aria-switch-checked" />
<div role="switch" aria-checked="false" data-testid="aria-switch-unchecked" />
const inputCheckboxChecked = getByTestId('input-checkbox-checked');
const inputCheckboxUnchecked = getByTestId('input-checkbox-unchecked');
const ariaCheckboxChecked = getByTestId('aria-checkbox-checked');
const ariaCheckboxUnchecked = getByTestId('aria-checkbox-unchecked');
await expect.element(inputCheckboxChecked).toBeChecked();
await expect.element(inputCheckboxUnchecked).not.toBeChecked();
await expect.element(ariaCheckboxChecked).toBeChecked();
await expect.element(ariaCheckboxUnchecked).not.toBeChecked();
const inputRadioChecked = getByTestId('input-radio-checked');
const inputRadioUnchecked = getByTestId('input-radio-unchecked');
const ariaRadioChecked = getByTestId('aria-radio-checked');
const ariaRadioUnchecked = getByTestId('aria-radio-unchecked');
await expect.element(inputRadioChecked).toBeChecked();
await expect.element(inputRadioUnchecked).not.toBeChecked();
await expect.element(ariaRadioChecked).toBeChecked();
await expect.element(ariaRadioUnchecked).not.toBeChecked();
const ariaSwitchChecked = getByTestId('aria-switch-checked');
const ariaSwitchUnchecked = getByTestId('aria-switch-unchecked');
await expect.element(ariaSwitchChecked).toBeChecked();
await expect.element(ariaSwitchUnchecked).not.toBeChecked();
toBePartiallyChecked
function toBePartiallyChecked(): Promise<void>;
Pozwala sprawdzić, czy dany element jest częściowo zaznaczony. Akceptuje input
typu checkbox
i elementy z rolą checkbox
z aria-checked="mixed"
, lub input
typu checkbox
z ustawionym na true
atrybutem indeterminate
.
<input type="checkbox" aria-checked="mixed" data-testid="aria-checkbox-mixed" />
<input type="checkbox" checked data-testid="input-checkbox-checked" />
<input type="checkbox" data-testid="input-checkbox-unchecked" />
<div role="checkbox" aria-checked="true" data-testid="aria-checkbox-checked" />
<div
role="checkbox"
aria-checked="false"
data-testid="aria-checkbox-unchecked"
/>
<input type="checkbox" data-testid="input-checkbox-indeterminate" />
const ariaCheckboxMixed = getByTestId('aria-checkbox-mixed');
const inputCheckboxChecked = getByTestId('input-checkbox-checked');
const inputCheckboxUnchecked = getByTestId('input-checkbox-unchecked');
const ariaCheckboxChecked = getByTestId('aria-checkbox-checked');
const ariaCheckboxUnchecked = getByTestId('aria-checkbox-unchecked');
const inputCheckboxIndeterminate = getByTestId('input-checkbox-indeterminate');
await expect.element(ariaCheckboxMixed).toBePartiallyChecked();
await expect.element(inputCheckboxChecked).not.toBePartiallyChecked();
await expect.element(inputCheckboxUnchecked).not.toBePartiallyChecked();
await expect.element(ariaCheckboxChecked).not.toBePartiallyChecked();
await expect.element(ariaCheckboxUnchecked).not.toBePartiallyChecked();
inputCheckboxIndeterminate.element().indeterminate = true;
await expect.element(inputCheckboxIndeterminate).toBePartiallyChecked();
toHaveRole
function toHaveRole(role: ARIARole): Promise<void>;
Pozwala sprawdzić, czy element ma oczekiwaną rolę.
Jest to przydatne w przypadkach, gdy masz już dostęp do elementu za pomocą innego zapytania niż sama rola i chcesz wykonać dodatkowe asercje dotyczące jego dostępności.
Rola może odpowiadać zarówno roli jawnej (poprzez atrybut role
), jak i roli niejawnej, zgodnie z niejawną semantyką ARIA.
<button data-testid="button">Continue</button>
<div role="button" data-testid="button-explicit">Continue</button>
<button role="switch button" data-testid="button-explicit-multiple">Continue</button>
<a href="/about" data-testid="link">About</a>
<a data-testid="link-invalid">Invalid link<a/>
await expect.element(getByTestId('button')).toHaveRole('button');
await expect.element(getByTestId('button-explicit')).toHaveRole('button');
await expect
.element(getByTestId('button-explicit-multiple'))
.toHaveRole('button');
await expect
.element(getByTestId('button-explicit-multiple'))
.toHaveRole('switch');
await expect.element(getByTestId('link')).toHaveRole('link');
await expect.element(getByTestId('link-invalid')).not.toHaveRole('link');
await expect.element(getByTestId('link-invalid')).toHaveRole('generic');
WARNING
Role są dopasowywane dosłownie, na podstawie równości ciągów znaków, bez dziedziczenia z hierarchii ról ARIA. W rezultacie zapytanie o rolę nadrzędną, taką jak checkbox
, nie obejmie elementów z rolą podrzędną, taką jak switch
.
Zauważ również, że w przeciwieństwie do testing-library
, Vitest ignoruje wszystkie niestandardowe role z wyjątkiem pierwszej prawidłowej, co jest zgodne z zachowaniem Playwright:
<div data-testid="switch" role="switch alert"></div>;
await expect.element(getByTestId('switch')).toHaveRole('switch'); // ✅
await expect.element(getByTestId('switch')).toHaveRole('alert'); // ❌
toHaveSelection
function toHaveSelection(selection?: string): Promise<void>;
Pozwala sprawdzić, czy element ma selekcję tekstu.
Jest to przydatne do sprawdzenia, czy tekst lub jego część jest zaznaczona w elemencie. Elementem może być input
typu tekstowego, textarea
lub dowolny inny element zawierający tekst, taki jak p
, span
, div
itp.
WARNING
Oczekiwane zaznaczenie to ciąg znaków; nie pozwala na sprawdzenie indeksów zakresu selekcji.
<div>
<input type="text" value="text selected text" data-testid="text" />
<textarea data-testid="textarea">text selected text</textarea>
<p data-testid="prev">prev</p>
<p data-testid="parent">
text <span data-testid="child">selected</span> text
</p>
<p data-testid="next">next</p>
</div>
getByTestId('text').element().setSelectionRange(5, 13);
await expect.element(getByTestId('text')).toHaveSelection('selected');
getByTestId('textarea').element().setSelectionRange(0, 5);
await expect.element('textarea').toHaveSelection('text ');
const selection = document.getSelection();
const range = document.createRange();
selection.removeAllRanges();
selection.empty();
selection.addRange(range);
// zaznaczenie dziecka wpływa również na rodzica
range.selectNodeContents(getByTestId('child').element());
await expect.element(getByTestId('child')).toHaveSelection('selected');
await expect.element(getByTestId('parent')).toHaveSelection('selected');
// zaznaczenie obejmujące cały poprzedni element, tekst rodzica przed dzieckiem i część dziecka.
range.setStart(getByTestId('prev').element(), 0);
range.setEnd(getByTestId('child').element().childNodes[0], 3);
await expect.element(queryByTestId('prev')).toHaveSelection('prev');
await expect.element(queryByTestId('child')).toHaveSelection('sel');
await expect.element(queryByTestId('parent')).toHaveSelection('text sel');
await expect.element(queryByTestId('next')).not.toHaveSelection();
// zaznaczenie obejmujące część dziecka, tekst rodzica po dziecku i część następnego elementu.
range.setStart(getByTestId('child').element().childNodes[0], 3);
range.setEnd(getByTestId('next').element().childNodes[0], 2);
await expect.element(queryByTestId('child')).toHaveSelection('ected');
await expect.element(queryByTestId('parent')).toHaveSelection('ected text');
await expect.element(queryByTestId('prev')).not.toHaveSelection();
await expect.element(queryByTestId('next')).toHaveSelection('ne');