Saltar al contenido
SDETRole
SDETRole

Aprender / Hoja de referencia

Hoja de referencia de Playwright

Las APIs de Playwright Test que usas a diario, en una sola hoja. Los locators aparecen en el orden que recomienda Playwright: rol, etiqueta y texto antes que los test ids, y CSS o XPath al final. Todas las assertions de esta hoja son web-first: reintentan hasta pasar o agotar el timeout, así que no necesitas esperas manuales.

Revisada con Playwright Test 1.5x, TypeScript

Ejecutar y depurar

TareaCódigo
Proyecto nuevo npm init playwright@latest
Ejecutar todos los tests npx playwright test
Un archivo, una línea npx playwright test tests/login.spec.ts:12
Por título o tag npx playwright test --grep @smoke
Un solo proyecto de navegador npx playwright test --project=chromium
Ver el navegador npx playwright test --headed
Ir paso a paso con el inspector npx playwright test --debug
Modo UI (watch, viaje en el tiempo) npx playwright test --ui
Solo los fallos de la última ejecución npx playwright test --last-failed
Cazar un test flaky npx playwright test my.spec.ts --repeat-each=20
Repartir (shard) entre máquinas de CI npx playwright test --shard=1/4
Abrir el informe HTML npx playwright show-report
Abrir un trace npx playwright show-trace trace.zip
Grabar un script npx playwright codegen https://example.com

Locators (los preferidos primero)

TareaCódigo
Por rol y nombre accesible page.getByRole('button', { name: 'Sign in' })
Campo de formulario por su etiqueta page.getByLabel('Email')
Por placeholder page.getByPlaceholder('Search')
Por texto (exacto) page.getByText('Welcome back', { exact: true })
Por test id (data-testid) page.getByTestId('checkout-submit')
CSS page.locator('#orders tbody tr')
XPath page.locator('xpath=//table[@id="orders"]//tr')
Filtrar por texto page.getByRole('row').filter({ hasText: 'Mei Lin' })
Filtrar por elemento hijo page.getByRole('listitem').filter({ has: page.getByRole('button', { name: 'Buy' }) })
Encadenar dentro de un resultado row.getByRole('button', { name: 'Cancel' })
Elegir uno de varios .first() .last() .nth(2)
Dentro de un iframe page.frameLocator('#payment').getByLabel('Card number')

Los locators son lazy: no se busca nada hasta que actúas o haces una assertion, así que defínelos una vez y reutilízalos.

Acciones

TareaCódigo
Navegar (relativo a baseURL) await page.goto('/login')
Clic await locator.click()
Reemplazar el valor de un input await locator.fill('mei@example.com')
Escribir tecla a tecla await locator.pressSequentially('abc', { delay: 50 })
Pulsar una tecla await locator.press('Enter')
Checkbox o radio await locator.check() / await locator.uncheck()
Seleccionar una opción await page.getByLabel('Country').selectOption('UK')
Subir un archivo await locator.setInputFiles('fixtures/invoice.pdf')
Pasar el ratón por encima await locator.hover()
Arrastrar y soltar await source.dragTo(target)
Aceptar el siguiente diálogo page.once('dialog', (d) => d.accept())

Web-first assertions

TareaCódigo
Visible / oculto await expect(locator).toBeVisible() / .toBeHidden()
Texto exacto await expect(locator).toHaveText('Order placed')
El texto contiene await expect(locator).toContainText('placed')
Valor de un input await expect(input).toHaveValue('42')
Número de coincidencias await expect(page.getByRole('row')).toHaveCount(5)
Habilitado / deshabilitado / marcado toBeEnabled() toBeDisabled() toBeChecked()
Atributo await expect(menu).toHaveAttribute('aria-expanded', 'true')
URL y título await expect(page).toHaveURL(/dashboard/) / .toHaveTitle('Orders')
Negar await expect(spinner).not.toBeVisible()
Seguir tras un fallo await expect.soft(total).toHaveText('£40.00')
Reintentar cualquier comprobación asíncrona await expect.poll(async () => (await api.get(url)).status()).toBe(200)
Comparación visual await expect(page).toHaveScreenshot('home.png')

Red y API

TareaCódigo
Simular (mock) una respuesta await page.route('**/api/orders', (r) => r.fulfill({ json: [] }))
Hacer fallar una petición await page.route('**/api/orders', (r) => r.abort())
Modificar una respuesta real await page.route('**/api/me', async (r) => { const res = await r.fetch(); const json = await res.json(); await r.fulfill({ response: res, json: { ...json, plan: 'pro' } }); })
Esperar una respuesta
const res = page.waitForResponse('**/api/orders');
await page.getByRole('button', { name: 'Save' }).click();
expect((await res).ok()).toBeTruthy();
Test de API
test('list users', async ({ request }) => {
  const res = await request.get('/api/users');
  await expect(res).toBeOK();
  expect(await res.json()).toHaveLength(3);
});

Estructura, fixtures y hooks

TareaCódigo
Agrupar tests test.describe('checkout', () => { /* tests */ })
Ejecutar antes de cada test test.beforeEach(async ({ page }) => { await page.goto('/'); })
Etiquetar un test test('pays by card', { tag: '@smoke' }, async ({ page }) => { /* ... */ })
Saltar según una condición test.skip(browserName === 'webkit', 'Not supported on WebKit')
En paralelo dentro de un archivo test.describe.configure({ mode: 'parallel' })
Fixture personalizada
export const test = base.extend<{ loginPage: LoginPage }>({
  loginPage: async ({ page }, use) => { await use(new LoginPage(page)); },
});
Reutilizar una sesión iniciada test.use({ storageState: 'playwright/.auth/user.json' })
Nombrar un paso en el informe await test.step('add to cart', async () => { /* ... */ })

playwright.config.ts

AjusteEjemplo
URL base para page.goto use: { baseURL: 'http://localhost:3000' }
Evidencias en caso de fallo use: { trace: 'on-first-retry', screenshot: 'only-on-failure', video: 'retain-on-failure' }
Reintentos solo en CI retries: process.env.CI ? 2 : 0
Paralelismo fullyParallel: true, workers: process.env.CI ? 2 : undefined
Fallar si se hace commit de test.only forbidOnly: !!process.env.CI
Arrancar antes la app webServer: { command: 'npm run start', url: 'http://localhost:3000', reuseExistingServer: !process.env.CI }
Navegadores projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }]
Timeouts por defecto timeout: 30_000, expect: { timeout: 5_000 }

Practica y profundiza

Más hojas de referencia

Escribe para buscar en todo SDETRole.

Búsqueda de texto completo con Pagefind · se ejecuta en tu navegador Abrir la página de búsqueda →