API de Asserções
O Vitest oferece uma ampla gama de asserções DOM prontas para uso, baseadas na biblioteca @testing-library/jest-dom
, com suporte adicional para localizadores e re-tentativas automáticas integradas.
Suporte a TypeScript
Se você estiver usando TypeScript ou quiser ter dicas de tipo corretas em expect
, certifique-se de que @vitest/browser/context
esteja referenciado em algum lugar. Se você nunca importou de lá, pode adicionar um comentário de reference
em qualquer arquivo coberto pelo seu tsconfig.json
:
/// <reference types="@vitest/browser/context" />
Testes no navegador podem falhar inconsistentemente devido à sua natureza assíncrona. Por isso, é importante garantir que as asserções sejam bem-sucedidas, mesmo que a condição sofra atrasos (por um tempo limite, solicitação de rede ou animação, por exemplo). Para esse propósito, o Vitest oferece asserções com capacidade de re-tentativa prontas para uso através das APIs expect.poll
e expect.element
:
import { expect, test } from 'vitest';
import { page } from '@vitest/browser/context';
test('error banner is rendered', async () => {
triggerError();
// Isso cria um localizador que tentará encontrar o elemento quando qualquer um de seus métodos for chamado.
// Esta chamada por si só não verifica a existência do elemento.
const banner = page.getByRole('alert', {
name: /error/i,
});
// O Vitest fornece `expect.element` com capacidade de re-tentativa integrada.
// Ele verificará repetidamente se o elemento existe no DOM e se o conteúdo de `element.textContent` é igual a "Error!" até que todas as condições sejam atendidas.
await expect.element(banner).toHaveTextContent('Error!');
});
Recomendamos sempre usar expect.element
com localizadores page.getBy*
para reduzir a instabilidade (flakiness) dos testes. Observe que expect.element
aceita uma segunda opção:
interface ExpectPollOptions {
// O intervalo para re-tentar a asserção em milissegundos.
// O padrão é a opção de configuração "expect.poll.interval".
interval?: number;
// Tempo para re-tentar a asserção em milissegundos.
// O padrão é a opção de configuração "expect.poll.timeout".
timeout?: number;
// A mensagem exibida quando a asserção falha.
message?: string;
}
TIP
expect.element
é um atalho para expect.poll(() => element)
e funciona exatamente da mesma maneira.
toHaveTextContent
e todas as outras asserções ainda estão disponíveis em um expect
regular sem um mecanismo de re-tentativa integrado:
// falhará imediatamente se .textContent não for `'Error!'`
expect(banner).toHaveTextContent('Error!');
toBeDisabled
function toBeDisabled(): Promise<void>;
Permite verificar se um elemento está desabilitado da perspectiva do usuário.
Corresponde se o elemento é um controle de formulário e o atributo disabled
é especificado neste elemento, ou se o elemento é um descendente de um elemento de formulário com um atributo disabled
.
Observe que apenas elementos de controle nativos como HTML button
, input
, select
, textarea
, option
, optgroup
podem ser desabilitados definindo o atributo "disabled". O atributo "disabled" em outros elementos é ignorado, a menos que seja um elemento personalizado.
<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>;
Permite verificar se um elemento não está desabilitado da perspectiva do usuário.
É equivalente a not.toBeDisabled()
. Use este matcher para evitar dupla negação em seus testes.
<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>;
Isso permite que você afirme que um elemento não tem conteúdo visível para o usuário. Ele ignora comentários, mas falhará se o elemento contiver espaços.
<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>;
Afirma que um elemento está presente no documento ou não.
<svg data-testid="svg-element"></svg>
await expect.element(getByTestId('svg-element')).toBeInTheDocument();
await expect.element(getByTestId('does-not-exist')).not.toBeInTheDocument();
WARNING
Este matcher não encontra elementos desanexados. O elemento deve ser adicionado ao documento para ser encontrado por toBeInTheDocument
. Se você deseja pesquisar em um elemento desanexado, use: toContainElement
.
toBeInvalid
function toBeInvalid(): Promise<void>;
Isso permite que você verifique se um elemento está atualmente inválido.
Um elemento é inválido se tiver um atributo aria-invalid
sem um valor ou com valor "true"
, ou se o retorno de checkValidity()
for 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>;
Isso permite que você verifique se um elemento de formulário é atualmente obrigatório.
Um elemento é obrigatório se possuir um atributo required
ou 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>;
Isso permite que você verifique se o valor de um elemento é atualmente válido.
Um elemento é válido se não tiver um atributo aria-invalid
ou um valor de atributo igual a "false". O retorno de checkValidity()
também deve ser true
para elementos de formulário.
<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>;
Isso permite que você verifique se um elemento está atualmente visível para o usuário.
Um elemento é considerado visível quando tem uma caixa delimitadora com dimensões e não tem o estilo computado visibility:hidden
.
Observe que, de acordo com esta definição:
- Elementos de tamanho zero não são considerados visíveis.
- Elementos com
display:none
não são considerados visíveis. - Elementos com
opacity:0
são considerados visíveis.
Para verificar se pelo menos um elemento da lista está visível, use locator.first()
.
// Um elemento específico é visível.
await expect.element(page.getByText('Welcome')).toBeVisible();
// Pelo menos um item na lista é visível.
await expect.element(page.getByTestId('todo-item').first()).toBeVisible();
// Pelo menos um dos dois elementos é visível, possivelmente ambos.
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>;
Isso permite que você afirme se um elemento contém outro elemento como descendente ou não.
<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>;
Afirma que uma string que representa um elemento HTML está contida em outro elemento. A string deve conter HTML válido, e não HTML que esteja incompleto.
<span data-testid="parent"><span data-testid="child"></span></span>
// Estes são usos válidos
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 />');
// Estes não funcionarão
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
Você provavelmente não precisará usar este matcher. Recomendamos testar a partir da perspectiva de como o usuário percebe o aplicativo em um navegador. É por isso que testar contra uma estrutura DOM específica não é recomendado.
Pode ser útil em situações em que o código testado renderiza HTML obtido de uma fonte externa, e você deseja validar se esse código HTML foi usado como pretendido.
Não deve ser usado para verificar a estrutura DOM que você controla. Prefira usar toContainElement
em vez disso.
toHaveAccessibleDescription
function toHaveAccessibleDescription(
description?: string | RegExp
): Promise<void>;
Isso permite que você afirme que um elemento possui a descrição acessível esperada.
Você pode passar a string exata da descrição acessível esperada, ou fazer uma correspondência parcial passando uma expressão regular, ou ainda usando expect.stringContaining
ou 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>;
Isso permite que você afirme que um elemento possui a mensagem de erro acessível esperada.
Você pode passar a string exata da mensagem de erro acessível esperada. Alternativamente, você pode realizar uma correspondência parcial passando uma expressão regular ou ainda usando expect.stringContaining
ou 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"
/>
// Inputs com mensagens de erro válidas
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!');
// Inputs sem mensagens de erro válidas
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>;
Isso permite que você afirme que um elemento possui o nome acessível esperado. É útil, por exemplo, para verificar se elementos de formulário e botões estão devidamente rotulados.
Você pode passar a string exata do nome acessível esperado, ou fazer uma correspondência parcial passando uma expressão regular, ou ainda usando expect.stringContaining
ou 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>;
Isso permite que você verifique se o elemento dado possui um atributo. Você também pode, opcionalmente, verificar se o atributo tem um valor esperado específico ou se corresponde parcialmente usando expect.stringContaining
ou 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>;
Isso permite que você verifique se o elemento dado possui certas classes dentro de seu atributo class
. Você deve fornecer pelo menos uma classe, a menos que esteja afirmando que o elemento não possui classes.
A lista de nomes de classe pode incluir strings e expressões regulares. As expressões regulares são comparadas com cada classe individual no elemento de destino, e NÃO com o valor completo do atributo class
.
WARNING
Observe que você não pode usar a opção exact: true
quando apenas expressões regulares são usadas.
<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/);
// ⚠️ regexp faz a correspondência com classes individuais, não com a lista de classes inteira
await expect.element(deleteButton).not.toHaveClass(/btn extra/);
// o elemento tem EXATAMENTE um conjunto de classes (em qualquer ordem)
await expect.element(deleteButton).toHaveClass('btn-danger extra btn', {
exact: true,
});
// se tiver mais do que o esperado, falhará
await expect.element(deleteButton).not.toHaveClass('btn-danger extra', {
exact: true,
});
await expect.element(noClasses).not.toHaveClass();
toHaveFocus
function toHaveFocus(): Promise<void>;
Isso permite que você afirme se um elemento tem foco ou não.
<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>;
Isso permite que você verifique se um formulário ou fieldset contém controles de formulário para cada nome dado, e que possuem o valor especificado.
TIP
É importante ressaltar que este matcher só pode ser usado em um elemento form ou fieldset.
Isso permite que ele aproveite a propriedade .elements
em form
e fieldset
para recuperar de forma confiável todos os controles de formulário dentro deles.
Isso também evita a possibilidade de que os usuários forneçam um contêiner que contenha mais de um form
, o que misturaria controles de formulário não relacionados e que poderiam até mesmo entrar em conflito entre si.
Este matcher abstrai as particularidades de como um valor de controle de formulário é obtido dependendo do tipo de controle de formulário. Por exemplo, elementos <input>
têm um atributo value
, mas elementos <select>
não. Aqui está uma lista de todos os casos cobertos:
- Elementos
<input type="number">
retornam o valor como um número, ao invés de uma string. - Elementos
<input type="checkbox">
:- se houver apenas um com o atributo
name
dado, ele é tratado como um booleano, retornandotrue
se a caixa de seleção estiver marcada,false
se estiver desmarcada. - se houver mais de uma caixa de seleção com o mesmo atributo
name
, elas são todas tratadas coletivamente como um único controle de formulário, que retorna o valor como um array contendo todos os valores das caixas de seleção selecionadas.
- se houver apenas um com o atributo
- Elementos
<input type="radio">
são agrupados pelo atributoname
, e tal grupo é tratado como um único controle de formulário. Este controle de formulário retorna o valor como uma string correspondente ao atributovalue
do botão de rádio selecionado. - Elementos
<input type="text">
retornam o valor como uma string. Isso também se aplica a elementos<input>
que possuem qualquer outro atributotype
possível que não esteja explicitamente coberto nas regras anteriores (por exemplo,search
,email
,date
,password
,hidden
, etc.) - Elementos
<select>
sem o atributomultiple
retornam o valor como uma string correspondente ao atributovalue
daoption
selecionada, ouundefined
caso nenhuma opção esteja selecionada. - Elementos
<select multiple>
retornam o valor como um array contendo todos os valores das opções selecionadas. - Elementos
<textarea>
retornam seu valor como uma string. O valor é o conteúdo do seu nó.
As regras acima facilitam, por exemplo, a transição de um único controle de seleção para um grupo de botões de rádio. Ou a mudança de um controle de seleção múltipla para um grupo de caixas de seleção. O conjunto resultante de valores de formulário que este matcher usa para comparação seria o mesmo.
<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>;
Isso permite que você verifique se um determinado elemento possui algumas propriedades CSS específicas com valores específicos aplicados. Ele corresponde apenas se o elemento possuir todas as propriedades esperadas aplicadas, não apenas algumas delas.
<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',
});
Isso também funciona com regras que são aplicadas ao elemento através de um nome de classe onde algumas regras são definidas em uma folha de estilo atualmente ativa no documento. As regras usuais de precedência CSS se aplicam.
toHaveTextContent
function toHaveTextContent(
text: string | RegExp,
options?: { normalizeWhitespace: boolean }
): Promise<void>;
Isso permite que você verifique se o nó dado possui um conteúdo de texto ou não. Isso funciona com elementos, mas também com nós de texto e fragmentos.
Quando um argumento string
é passado, ele realizará uma correspondência parcial sensível a maiúsculas e minúsculas com o conteúdo do nó.
Para realizar uma correspondência case-insensitive, você pode usar uma RegExp
com o modificador /i
.
Se você quiser fazer a correspondência com todo o conteúdo, você pode usar uma RegExp
para isso.
<span data-testid="text-content">Text Content</span>
const element = getByTestId('text-content');
await expect.element(element).toHaveTextContent('Content');
// para corresponder a todo o conteúdo
await expect.element(element).toHaveTextContent(/^Text Content$/);
// para usar correspondência que não diferencia maiúsculas de minúsculas
await expect.element(element).toHaveTextContent(/content$/i);
await expect.element(element).not.toHaveTextContent('content');
toHaveValue
function toHaveValue(value: string | string[] | number | null): Promise<void>;
Isso permite que você verifique se o elemento de formulário dado possui o valor especificado. Ele aceita elementos <input>
, <select>
e <textarea>
, com exceção de <input type="checkbox">
e <input type="radio">
, que podem ser verificados de forma mais apropriada apenas usando toBeChecked
ou toHaveFormValues
.
Ele também aceita elementos com os papéis meter
, progressbar
, slider
ou spinbutton
e verifica o atributo aria-valuenow
(como um número).
Para todos os outros elementos de formulário, o valor é correspondido usando o mesmo algoritmo que o toHaveFormValues
usa.
<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>;
Isso permite que você verifique se o elemento de formulário dado possui o valor exibido especificado (aquele que o usuário final verá). Ele aceita elementos <input>
, <select>
e <textarea>
, com exceção de <input type="checkbox">
e <input type="radio">
, que podem ser verificados de forma mais apropriada apenas usando toBeChecked
ou 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>;
Isso permite que você verifique se o elemento dado está selecionado. Ele aceita um input
do tipo checkbox
ou radio
e elementos com um role
de checkbox
, radio
ou switch
com um atributo aria-checked
válido, sendo "true"
ou "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>;
Isso permite que você verifique se o elemento dado está parcialmente selecionado. Ele aceita um input
do tipo checkbox
e elementos com um role
de checkbox
com o atributo aria-checked
definido como "mixed"
, ou input
do tipo checkbox
com indeterminate
definido como true
.
<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>;
Isso permite que você afirme que um elemento possui o papel esperado.
Isso é útil em casos em que você já tem acesso a um elemento por meio de alguma consulta que não seja o próprio papel, e deseja fazer afirmações adicionais sobre sua acessibilidade.
O papel pode corresponder a um papel explícito (através do atributo role
) ou a um implícito por meio da semântica ARIA implícita.
<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
Os papéis são correspondidos literalmente por comparação exata de string, sem herdar da hierarquia de papéis ARIA. Consequentemente, consultar um papel de superclasse como checkbox
não incluirá elementos com um papel de subclasse como switch
.
Observe também que, ao contrário do testing-library
, o Vitest ignora todos os papéis personalizados, com exceção do primeiro válido, seguindo o comportamento do 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>;
Isso permite afirmar que um elemento possui uma seleção de texto.
Isso é útil para verificar se o texto ou uma parte do texto está selecionado dentro de um elemento. O elemento pode ser um campo de entrada de texto, um textarea, ou qualquer outro elemento que contenha texto, como um parágrafo, span, div etc.
WARNING
A seleção esperada é uma string, não permite a verificação de índices de intervalo da seleção.
<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);
// a seleção do filho também se estende ao pai
range.selectNodeContents(getByTestId('child').element());
await expect.element(getByTestId('child')).toHaveSelection('selected');
await expect.element(getByTestId('parent')).toHaveSelection('selected');
// seleção que se estende do elemento 'prev', passando pelo texto do pai antes do filho, e incluindo parte do filho.
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();
// seleção que se estende de parte do filho, passando pelo texto do pai depois do filho, e incluindo parte do próximo elemento.
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');