La emulación de dispositivos de Playwright configura viewport, pixel ratio, user agent y eventos táctiles juntos, pero no testea motores de navegador móviles reales: sigues corriendo Chromium independientemente de si seleccionaste devices['iPhone 14']. El atajo setViewportSize cambia solo el viewport, no el user agent ni el comportamiento táctil, lo que es suficiente para tests de layout responsive pero incorrecto para cualquier cosa que verifique CSS específico de móvil o sniffing del user agent. Este artículo cubre los presets de dispositivos, la emulación por test, la diferencia entre setViewportSize y la emulación completa con newContext, eventos táctiles, regresión visual para móvil, y qué escenarios justifican un proyecto de test de móvil dedicado.
Qué hace (y qué no hace) la emulación de móvil
La emulación de Playwright simula:
- Dimensiones del viewport
- Pixel ratio del dispositivo (pantallas retina)
- Cadena de user agent
- Eventos táctiles (reemplaza a los eventos de mouse)
- Geolocalización (opcional)
- Locale y zona horaria (opcional)
Lo que no testea:
- Rendimiento real del dispositivo
- Motores de navegador móvil reales (sigues en Chromium, Firefox o WebKit)
- Renderizado específico del hardware
- Aplicaciones móviles nativas
Para testing en dispositivos reales necesitas servicios como BrowserStack o Sauce Labs. La emulación cubre la necesidad más común: verificar que tu aplicación se comporta correctamente en tamaños de viewport móvil y responde al toque.
Usar los presets de dispositivos integrados
Playwright incluye una librería de presets de dispositivos. Úsalos en tu configuración:
// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
projects: [
{
name: 'chromium-desktop',
use: { ...devices['Desktop Chrome'] },
},
{
name: 'mobile-chrome',
use: { ...devices['Pixel 7'] },
},
{
name: 'mobile-safari',
use: { ...devices['iPhone 14'] },
},
{
name: 'tablet',
use: { ...devices['iPad Pro 11'] },
},
],
});Ejecutar solo los tests de móvil:
npx playwright test --project=mobile-chromeVer todos los dispositivos disponibles:
npx playwright --list-devicesLa lista incluye unos 80 presets: dispositivos Pixel, iPhones, teléfonos Galaxy, iPads, tablets Surface.
Emulación de dispositivo por test
Sobreescribe la emulación para un solo test sin cambiar la configuración:
import { test, expect, devices } from '@playwright/test';
test('la navegación móvil funciona', async ({ browser }) => {
const context = await browser.newContext({
...devices['iPhone 14'],
});
const page = await context.newPage();
await page.goto('/');
// El menú hamburguesa debería ser visible en móvil
await expect(page.getByRole('button', { name: 'Menú' })).toBeVisible();
await page.getByRole('button', { name: 'Menú' }).click();
await expect(page.getByRole('navigation')).toBeVisible();
await context.close();
});Eventos táctiles
En dispositivos móviles, Playwright usa eventos táctiles en lugar de eventos de mouse. La mayoría de las interacciones funcionan de forma idéntica: click(), fill(), type() se traducen correctamente. Donde el toque importa:
// Tap (igual que clic en móvil)
await page.getByRole('button').tap();
// Gesto de deslizamiento
await page.touchscreen.tap(100, 200);Para carruseles de deslizamiento, pull-to-refresh o gestos complejos, puede que necesites page.evaluate() para despachar eventos táctiles personalizados. La mayoría de las interacciones móviles simples funcionan con los métodos de locator normales.
Testear comportamiento responsive
El uso más práctico: verificar tu layout en diferentes breakpoints.
test.describe('layout responsive', () => {
test('el escritorio muestra la navegación completa', async ({ page }) => {
await page.setViewportSize({ width: 1280, height: 720 });
await page.goto('/');
await expect(page.getByRole('navigation')).toBeVisible();
await expect(page.getByRole('button', { name: 'Menú' })).not.toBeVisible();
});
test('el móvil muestra el hamburger', async ({ page }) => {
await page.setViewportSize({ width: 375, height: 812 });
await page.goto('/');
await expect(page.getByRole('button', { name: 'Menú' })).toBeVisible();
await expect(page.getByRole('navigation')).not.toBeVisible();
});
});setViewportSize cambia solo el viewport: no cambia el user agent. Para simulación completa del dispositivo, usa los presets de devices o un contexto con viewport + userAgent + deviceScaleFactor configurados juntos.
Viewport vs. configuración use
// Solo viewport: no cambia user agent ni eventos táctiles
await page.setViewportSize({ width: 375, height: 812 });
// Emulación completa: viewport + user agent + toque + pixel ratio
const context = await browser.newContext({
viewport: { width: 390, height: 844 },
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X)...',
deviceScaleFactor: 3,
isMobile: true,
hasTouch: true,
});Para tests responsive que verifican solo el layout, setViewportSize está bien. Para tests que verifican comportamiento específico de móvil (eventos táctiles, CSS específico de móvil, sniffing del user agent), usa emulación completa del dispositivo vía presets de devices.
Comparación de screenshots para testing responsive
La regresión visual es especialmente valiosa para móvil: los bugs de layout a menudo son invisibles en las aserciones de test pero evidentes en un screenshot:
test('el homepage en móvil coincide con la línea base', async ({ page }) => {
await page.setViewportSize({ width: 375, height: 812 });
await page.goto('/');
await expect(page).toHaveScreenshot('mobile-homepage.png', {
fullPage: true,
});
});Córrelo una vez para generar la línea base. Las ejecuciones siguientes comparan contra ella. Un corrimiento de layout de un solo píxel hace fallar el test.
Qué testear específicamente en móvil
No todo test necesita una versión para móvil. Prioriza:
- Navegación (menús hamburguesa, drawers móviles)
- Formularios (el teclado virtual no cubre el botón de envío, los tap targets son suficientemente grandes)
- Tablas (scroll horizontal vs. layout apilado)
- Imágenes (
srcsetresponsive, sin overflow) - Flujos de pago (ruta crítica, botones aptos para toque)
- Modales (contenido scrolleable, botón de cierre accesible)
Salta los tests de móvil para dashboards de administración que explícitamente no soportan móvil, tests que verifican comportamiento idéntico independientemente del viewport, y tests de API y tests unitarios.
→ See also: Pruebas Entre Navegadores con Playwright: Chrome, Firefox, Safari | Estrategias de Testing Cruzado de Navegadores: Cuándo y Cómo Probar Múltiples Navegadores | Archivo de Configuración de Playwright Explicado: Todas las Opciones