Creando nuestro primer test E2E

En esta clase damos el salto de “esto compila” a “esto funciona de verdad”. Vamos a escribir nuestro primer test E2E con Playwright simulando el flujo real de una persona:

  • Entra a la web
  • Usa el buscador para filtrar empleos
  • Hace click en botones
  • Comprueba que aparecen resultados
  • Inicia sesión y aplica a una oferta

La idea clave: un E2E prueba la aplicación completa - UI, navegación, API y comportamiento del usuario.

Arrancando el test: navegar como un usuario

Lo primero es abrir la app en el navegador de Playwright usando page.goto() (en el vídeo está en localhost:5173).

import { test, expect } from '@playwright/test'

test('buscar y aplicar a una oferta', async ({ page }) => {
  await page.goto('http://localhost:5173')
})

A partir de aquí, todo lo que hacemos es interacción de usuario.

Localizar elementos: la jerarquía que deberías seguir

En la clase se recomienda esta prioridad para localizar elementos (de mejor a peor opción):

  1. Roles (ARIA) - lo más estable
  2. Texto / labels / placeholders
  3. data-testid (cuando no queda otra)
  4. Selectores CSS (último recurso, se rompen fácil)

¿La razón? Los roles cambian poco, pero el CSS se reestructura cada dos semanas “porque ahora sí que sí, refactor final”.

Buscar el input del buscador con getByRole

Intentamos encontrar el buscador con:

const searchInput = page.getByRole('searchbox')
await searchInput.fill('React')

Pero aquí aparece un clásico: falla porque el input no tiene el rol correcto. En el vídeo se muestra que el input era type="text" y por eso Playwright no lo detecta como searchbox.

Arreglo: el HTML importa (y mucho)

La solución es ajustar el input para que sea de tipo búsqueda:

<input type="search" name="search" required />

Con type="search" el rol searchbox se asigna automáticamente y el test ya puede encontrar el elemento.

Hacer click en el botón “Buscar”

Una vez rellenado el input, recuperamos el botón por rol y nombre accesible:

await page.getByRole('button', { name: 'Buscar' }).click()

Esto es exactamente lo que quieres en un E2E: que el selector se parezca a lo que “vería” una persona (botón con texto Buscar).

Verificar resultados: expect + locator

Ahora necesitamos comprobar que aparece al menos un resultado y que es visible.

const jobCards = page.locator('.job-listing-card')
await expect(jobCards.first()).toBeVisible()

En el vídeo también se muestra una verificación del título del primer resultado (por ejemplo con un heading nivel 3) y comprobar texto esperado si controlas datos de prueba.

const firstJobTitle = jobCards.first().getByRole('heading', { level: 3 })
await expect(firstJobTitle).toHaveText(/desarrollador/i)

La gracia de E2E es que no tienen que ser “tests mini” - puedes simular un flujo completo de usuario.

Continuar el flujo: iniciar sesión y aplicar

El test sigue como si fuese una persona:

  1. Click en “Iniciar sesión”
  2. Click en “Aplicar” en la primera oferta
  3. Verificar que el botón cambia a “Aplicado”
await page.getByRole('button', { name: 'Iniciar sesión' }).click()

const applyButton = page.getByRole('button', { name: 'Aplicar' }).first()
await applyButton.click()

await expect(page.getByRole('button', { name: 'Aplicado' })).toBeVisible()

El punto importante es comprobar el cambio de estado en UI: aplicar -> aplicado.

Ejecutar con UI: headed, depurar y entender fallos

En el vídeo se ve que a veces el test va demasiado rápido y conviene lanzarlo con interfaz para observar paso a paso (modo “con navegador”) y entender qué pasa.

Además aparece algo muy útil: Playwright puede avisarte de errores en consola aunque el test haya pasado, lo que ayuda a detectar problemas reales de la app.

Configuración clave en playwright.config

Se comentan varias opciones interesantes:

  • Ejecutar en paralelo, número de intentos, etc.
  • Proyectos para correr en distintos navegadores y dispositivos (Chromium, móvil…)
  • Poder usar tu navegador con tu sesión/cookies
  • headless: false para ver siempre la ventana
  • Ajustar viewport por proyecto

Ejemplo típico:

// playwright.config.js (idea general)
export default {
  use: {
    headless: false,
    viewport: { width: 1280, height: 720 },
  },
  projects: [{ name: 'chromium', use: { browserName: 'chromium' } }],
}

En la clase se simplifica dejando solo Chromium para empezar.

Lo que hemos aprendido

  • Qué es un test E2E y por qué valida navegación, API y UI a la vez.
  • Cómo simular a un usuario con goto, fill y click.
  • Cómo localizar elementos correctamente y en qué orden (roles primero).
  • Por qué un input type="search" mejora accesibilidad y hace tus tests más robustos.
  • Cómo depurar ejecutando con UI y revisando errores de consola.

Con esto ya puedes construir flujos E2E completos y, lo más importante, con selectores que no se rompan cada vez que alguien dice “solo era un cambio de CSS pequeñito”.