Lección 1 de 7 · 2 min
Locators accesibles y web-first assertions
Al terminar sabrás
10 min- Aplicar la jerarquía de locators de Playwright (getByRole primero)
- Usar web-first assertions que reintentan en vez de evaluar una vez
- Reconocer cómo los locators accesibles te auditan accesibilidad gratis
Construyes: Un set de locators robustos para una página real, escritos sin CSS frágil ni test-id.
La jerarquía de locators de Playwright
En orden de preferencia oficial (y con razón):
page.getByRole('button', { name: 'Reservar hora' }) // 1º semántica accesible
page.getByLabel('Teléfono') // 2º formularios
page.getByPlaceholder('+56 9 ...') // 3º si no hay label (mal HTML)
page.getByText('Reserva confirmada') // 4º contenido estático
page.getByTestId('booking-submit') // 5º cuando nada semántico aplica
page.locator('css=...') // último recurso
getByRole usa el árbol de accesibilidad, no el DOM. Si el botón cambia de button a a estilizado con role correcto, el test sigue pasando — porque la experiencia del usuario no cambió.
Efecto secundario valioso: si getByRole no encuentra tu elemento, tu HTML probablemente tampoco funciona con lector de pantalla. Los tests te auditan accesibilidad gratis.
Encadenar y filtrar
// La card de "Corte" y su botón, sin CSS frágil
const card = page.getByRole('listitem').filter({ hasText: 'Corte de pelo' });
await card.getByRole('button', { name: 'Reservar' }).click();
Web-first assertions: la diferencia clave
// ❌ Evalúa UNA vez — race condition garantizada
expect(await page.locator('.total').textContent()).toBe('$18.500');
// ✅ Reintenta hasta 5s — espera a que la UI se estabilice
await expect(page.locator('.total')).toHaveText('$18.500');
La regla: expect(locator) con matchers to* asíncronos siempre que el sujeto sea la página. expect(valor) solo para datos ya extraídos.
Auto-waiting: qué cubre y qué no
Antes de cada acción, Playwright espera solo que el elemento esté visible, estable, habilitado y reciba eventos. No espera que tu app termine de cargar datos — eso lo declaras con assertions:
await page.getByRole('button', { name: 'Buscar' }).click();
// El click no espera los resultados; esto sí:
await expect(page.getByRole('list', { name: 'Resultados' })).toBeVisible();
Y por eso waitForTimeout() no tiene lugar en una suite seria: siempre hay una condición concreta que esperar.
Fija los conceptos con el quiz y escribe tus propios locators en el reto.
Compruébalo
0/3Responde sin mirar atrás. Verás la explicación al instante.
1. ¿Cuál es el locator de primera preferencia en Playwright?
2. ¿Cuál es la forma correcta de afirmar el total mostrado en pantalla?
3. getByRole no encuentra tu elemento. ¿Qué te dice eso, además del test?
Reto: locators solo con semántica
Elige una página pública y escribe 5 locators para sus elementos principales usando solo los niveles 1–4 de la jerarquía (sin test-id ni CSS).
Si alguno es imposible, anota por qué.