Mobile Emulation
Mobile emulation simulates viewport size, touch events, user agent, and device scale factor — catching responsive layout bugs without physical devices.
Device Presets
Import devices from @playwright/test — includes iPhone, Pixel, iPad presets with viewport, userAgent, and touch settings.
Define mobile projects in config alongside desktop for parallel mobile regression.
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
projects: [
{ name: 'Desktop Chrome', use: { ...devices['Desktop Chrome'] } },
{ name: 'Mobile Safari', use: { ...devices['iPhone 14'] } },
],
});
devices['iPhone 14'] sets viewport, isMobile, hasTouch, userAgent.
Custom Mobile Context
use: {
viewport: { width: 390, height: 844 },
isMobile: true,
hasTouch: true,
deviceScaleFactor: 3,
}
isMobile affects hover media queries and touch defaults. hasTouch enables touch event simulation. - Orientation: set viewport height/width swapped.
- Geolocation pairs with permissions for map apps.
Mobile Emulation Reference
Common device configs.
| Device | Preset |
| iPhone 14 | devices['iPhone 14'] |
| Pixel 7 | devices['Pixel 7'] |
| iPad | devices['iPad Pro 11'] |
| Custom | viewport + isMobile + hasTouch |
| Landscape | Swap viewport dimensions |
| Run mobile only | --project='Mobile Safari' |
Testing Mobile Navigation
await page.getByRole('button', { name: 'Menu' }).click();
await expect(page.getByRole('navigation')).toBeVisible();
Hamburger menus often exist only in mobile viewport — test both projects.
Touch vs Click
Mobile presets enable touch. Some components respond only to tap — use locator.tap() when click does not trigger mobile handlers.
Common Mistakes
- Only testing desktop viewport for responsive apps.
- Confusing emulation with real device cloud — different value, both useful.
- Forgetting isMobile for touch-only UI.
- Same snapshot for desktop and mobile layouts.
Key Takeaways
- devices presets configure realistic mobile contexts.
- Mobile projects catch responsive and touch UI bugs.
- isMobile and hasTouch affect event and CSS behavior.
- Run mobile projects in CI for responsive-critical apps.
Pro Tip
Use page.emulateMedia({ colorScheme: 'dark' }) inside mobile projects to catch dark-mode responsive issues too.