Testing Library: componente ca un user
Query-uri după rol și label, get/query/find, user-event.
Actualizat
Ce este Testing Library
React Testing Library (RTL) e o librărie pentru testarea componentelor cum le folosește un om: găsești elemente după ce vezi (text, label, rol), dai click, scrii — și verifici ce apare pe ecran. Nu te uiți la state-ul intern sau la props.
Principiul ei: „Cu cât testele seamănă mai mult cu felul în care e folosit software-ul, cu atât îți dau mai multă încredere.”
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
test('adaugă un todo', async () => {
const user = userEvent.setup()
render(<TodoApp />)
await user.type(screen.getByLabelText('Task nou'), 'Învață RTL')
await user.click(screen.getByRole('button', { name: 'Adaugă' }))
expect(screen.getByText('Învață RTL')).toBeInTheDocument()
})Query-urile — ordinea de prioritate
Alege primul din listă care funcționează. Ordinea reflectă cât de accesibilă e componenta:
| Prioritate | Query | Găsește după | Exemplu |
|---|---|---|---|
| 1 | getByRole |
rol + nume accesibil | getByRole('button', { name: 'Salvează' }) |
| 2 | getByLabelText |
label-ul unui câmp | getByLabelText('Email') |
| 3 | getByPlaceholderText |
placeholder | dacă nu există label |
| 4 | getByText |
textul vizibil | paragrafe, mesaje |
| 5 | getByDisplayValue |
valoarea unui input | formulare pre-completate |
| 6 | getByAltText / getByTitle |
alt / title |
imagini |
| ultima | getByTestId |
data-testid |
doar când nimic altceva nu merge |
Bonus: dacă nu găsești un element cu getByRole, de cele mai multe ori componenta ta are o problemă de accesibilitate. Testele te împing spre HTML mai bun.
Variantele: get, query, find
| Prefix | Dacă nu găsește | Async | Când |
|---|---|---|---|
getBy |
aruncă eroare | nu | elementul trebuie să existe acum |
queryBy |
returnează null |
nu | verifici că nu există: expect(queryByText('Eroare')).toBeNull() |
findBy |
aruncă după timeout | da | elementul apare mai târziu (după fetch, setTimeout) |
getAllBy... / queryAllBy... / findAllBy... pentru mai multe elemente.
user-event vs fireEvent
userEvent |
fireEvent |
|
|---|---|---|
| Simulează | interacțiunea completă (focus, keydown, input, keyup, click) | un singur eveniment DOM |
| Realism | mare | mic |
| Când | implicit | cazuri speciale |
Ce să nu faci
- Să testezi state-ul intern (
component.state.count). container.querySelector('.btn-primary')— clasele sunt detalii de implementare.- Snapshot-uri uriașe pe care nimeni nu le citește.
Pe scurt
- RTL testează componente ca un user: găsești după rol, label, text.
- Prioritate:
getByRole→getByLabelText→ … →getByTestId. get= trebuie să existe,query= poate lipsi,find= va apărea.