0
# Mobile Testing
1
2
Emulate mobile devices, tablets, and various screen configurations with pre-configured device profiles, touch interaction, and mobile-specific features.
3
4
## Capabilities
5
6
### Device Emulation
7
8
Emulate mobile devices using predefined device profiles or custom configurations.
9
10
```python { .api }
11
class Playwright:
12
devices: Dict[str, Dict[str, Any]]
13
"""Pre-configured device profiles (iPhone, iPad, Android, etc.)"""
14
15
class BrowserContext:
16
def set_geolocation(self, geolocation: Optional[Geolocation]) -> None:
17
"""
18
Set device geolocation.
19
20
Args:
21
geolocation: GPS coordinates (None to clear)
22
"""
23
24
def grant_permissions(
25
self,
26
permissions: List[str],
27
origin: Optional[str] = None
28
) -> None:
29
"""
30
Grant device permissions.
31
32
Args:
33
permissions: Permission names (geolocation, camera, microphone, etc.)
34
origin: Origin to grant permissions for
35
"""
36
37
def clear_permissions(self) -> None:
38
"""Clear all granted permissions."""
39
40
def set_offline(self, offline: bool) -> None:
41
"""
42
Simulate offline mode.
43
44
Args:
45
offline: True for offline mode
46
"""
47
```
48
49
### Touch Interaction
50
51
Touch-based interaction for mobile interfaces.
52
53
```python { .api }
54
class Page:
55
touchscreen: Touchscreen
56
57
class Touchscreen:
58
def tap(self, x: float, y: float) -> None:
59
"""
60
Tap at coordinates.
61
62
Args:
63
x: X coordinate
64
y: Y coordinate
65
"""
66
```
67
68
### Mobile-Specific Context Options
69
70
Browser context options for mobile emulation.
71
72
```python { .api }
73
class Browser:
74
def new_context(
75
self,
76
viewport: Optional[ViewportSize] = None,
77
device_scale_factor: Optional[float] = None,
78
is_mobile: Optional[bool] = None,
79
has_touch: Optional[bool] = None,
80
user_agent: Optional[str] = None,
81
geolocation: Optional[Geolocation] = None,
82
permissions: Optional[List[str]] = None,
83
color_scheme: Optional[str] = None,
84
reduced_motion: Optional[str] = None,
85
**kwargs
86
) -> BrowserContext:
87
"""
88
Create mobile-configured browser context.
89
90
Mobile-specific args:
91
viewport: Screen size (width, height)
92
device_scale_factor: Device pixel ratio
93
is_mobile: Enable mobile viewport
94
has_touch: Enable touch events
95
user_agent: Mobile user agent string
96
geolocation: GPS coordinates
97
permissions: Mobile permissions
98
color_scheme: 'light', 'dark', 'no-preference'
99
reduced_motion: 'reduce', 'no-preference'
100
"""
101
```
102
103
## Usage Examples
104
105
### iPhone Emulation
106
107
```python
108
from playwright.sync_api import sync_playwright
109
110
with sync_playwright() as p:
111
# Use predefined iPhone device
112
iphone = p.devices["iPhone 12"]
113
114
browser = p.webkit.launch()
115
context = browser.new_context(**iphone)
116
page = context.new_page()
117
118
page.goto("https://example.com")
119
120
# Touch interactions
121
page.touchscreen.tap(100, 200)
122
123
# Mobile-specific assertions
124
viewport = page.viewport_size
125
assert viewport["width"] == 390 # iPhone 12 width
126
127
browser.close()
128
```
129
130
### Custom Mobile Configuration
131
132
```python
133
with sync_playwright() as p:
134
browser = p.chromium.launch()
135
136
# Custom mobile setup
137
context = browser.new_context(
138
viewport={"width": 412, "height": 915},
139
device_scale_factor=2.625,
140
is_mobile=True,
141
has_touch=True,
142
user_agent="Mozilla/5.0 (Linux; Android 10) Mobile",
143
geolocation={"latitude": 37.7749, "longitude": -122.4194},
144
permissions=["geolocation"]
145
)
146
147
page = context.new_page()
148
page.goto("https://maps.google.com")
149
150
# Verify mobile viewport
151
is_mobile = page.evaluate("window.innerWidth < 768")
152
assert is_mobile
153
154
browser.close()
155
```
156
157
### Location-Based Testing
158
159
```python
160
with sync_playwright() as p:
161
browser = p.chromium.launch()
162
context = browser.new_context(**p.devices["Pixel 5"])
163
164
# Set location to New York
165
context.set_geolocation({
166
"latitude": 40.7128,
167
"longitude": -74.0060
168
})
169
170
context.grant_permissions(["geolocation"])
171
172
page = context.new_page()
173
page.goto("https://weather.com")
174
175
# Wait for location-based content
176
page.wait_for_selector("[data-testid='location-name']")
177
location = page.locator("[data-testid='location-name']").text_content()
178
179
assert "New York" in location
180
181
browser.close()
182
```
183
184
### Responsive Design Testing
185
186
```python
187
with sync_playwright() as p:
188
browser = p.chromium.launch()
189
190
# Test multiple devices
191
devices_to_test = [
192
"iPhone 12",
193
"iPad Pro",
194
"Pixel 5",
195
"Galaxy S9+"
196
]
197
198
for device_name in devices_to_test:
199
device = p.devices[device_name]
200
201
context = browser.new_context(**device)
202
page = context.new_page()
203
204
page.goto("https://responsive-site.com")
205
206
# Take device-specific screenshot
207
page.screenshot(path=f"screenshot-{device_name.replace(' ', '-')}.png")
208
209
# Test device-specific features
210
if device.get("is_mobile"):
211
# Mobile-specific tests
212
hamburger_menu = page.locator(".mobile-menu-toggle")
213
assert hamburger_menu.is_visible()
214
else:
215
# Tablet/desktop tests
216
desktop_nav = page.locator(".desktop-navigation")
217
assert desktop_nav.is_visible()
218
219
context.close()
220
221
browser.close()
222
```
223
224
### Offline Testing
225
226
```python
227
with sync_playwright() as p:
228
browser = p.chromium.launch()
229
context = browser.new_context(**p.devices["iPhone 12"])
230
page = context.new_page()
231
232
# Load page while online
233
page.goto("https://pwa-app.com")
234
235
# Verify online functionality
236
online_indicator = page.locator(".online-status")
237
assert online_indicator.text_content() == "Online"
238
239
# Go offline
240
context.set_offline(True)
241
242
# Test offline functionality
243
page.reload()
244
offline_indicator = page.locator(".offline-status")
245
assert offline_indicator.is_visible()
246
247
# Test cached content still works
248
cached_content = page.locator(".cached-article")
249
assert cached_content.is_visible()
250
251
browser.close()
252
```