Files
2026-07-13 21:36:47 +08:00

482 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 设备和环境模拟
> **适用场景**:无需物理设备,全部在 CLI 中测试应用在不同设备、屏幕尺寸、地理位置、语言区域、时区、配色方案和网络条件下的表现。
> **前置条件**[core-commands.md](core-commands.md) 了解基本 CLI 用法,[running-custom-code.md](running-custom-code.md) 了解 `run-code` 语法
## 快速参考
```bash
# 通过配置文件模拟设备
playwright-cli open https://example.com --config=iphone.json
# 调整视口大小
playwright-cli resize 375 812 # iPhone 视口
playwright-cli resize 1920 1080 # 桌面视口
# 地理位置
playwright-cli run-code "async page => {
await page.context().grantPermissions(['geolocation']);
await page.context().setGeolocation({ latitude: 40.7128, longitude: -74.0060 });
}"
# 配色方案
playwright-cli run-code "async page => {
await page.emulateMedia({ colorScheme: 'dark' });
}"
```
## 视口模拟
设备测试的最简单形式——将视口大小设置为目标设备的尺寸:
### 常见视口尺寸
```bash
# 桌面
playwright-cli resize 1920 1080 # Full HD 显示器
playwright-cli resize 1440 900 # MacBook Pro 15"
playwright-cli resize 1366 768 # 常见笔记本电脑
playwright-cli resize 2560 1440 # QHD / 2K 显示器
# 平板
playwright-cli resize 1024 768 # iPad 横屏
playwright-cli resize 768 1024 # iPad 竖屏
playwright-cli resize 834 1194 # iPad Pro 11"
playwright-cli resize 1194 834 # iPad Pro 11" 横屏
playwright-cli resize 820 1180 # iPad Air
# 手机
playwright-cli resize 430 932 # iPhone 14 Pro Max
playwright-cli resize 393 852 # iPhone 14 Pro
playwright-cli resize 390 844 # iPhone 14 / 13 / 12
playwright-cli resize 375 812 # iPhone X / 11
playwright-cli resize 360 800 # Samsung Galaxy S21
playwright-cli resize 412 915 # Pixel 7
playwright-cli resize 320 568 # iPhone SE(第 1 代)
```
### 测试响应式断点
```bash
# 常见 CSS 断点
playwright-cli resize 320 568 # xs: 特小屏
playwright-cli screenshot --filename=responsive-xs.png
playwright-cli resize 576 768 # sm: 小屏
playwright-cli screenshot --filename=responsive-sm.png
playwright-cli resize 768 1024 # md: 中屏
playwright-cli screenshot --filename=responsive-md.png
playwright-cli resize 992 768 # lg: 大屏
playwright-cli screenshot --filename=responsive-lg.png
playwright-cli resize 1200 900 # xl: 特大屏
playwright-cli screenshot --filename=responsive-xl.png
playwright-cli resize 1400 900 # xxl: 超大屏
playwright-cli screenshot --filename=responsive-xxl.png
```
## 完整设备模拟
要进行精确的设备测试,仅设置视口是不够的——还需要设备缩放因子、User Agent、触摸支持和移动端行为。请使用配置文件或 `run-code`
### 配置文件方式
为特定设备创建配置文件:
**`iphone14.json`**
```json
{
"viewport": { "width": 390, "height": 844 },
"deviceScaleFactor": 3,
"userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1",
"isMobile": true,
"hasTouch": true
}
```
```bash
playwright-cli open https://example.com --config=iphone14.json
```
**`pixel7.json`**
```json
{
"viewport": { "width": 412, "height": 915 },
"deviceScaleFactor": 2.625,
"userAgent": "Mozilla/5.0 (Linux; Android 13; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36",
"isMobile": true,
"hasTouch": true
}
```
**`ipad-pro.json`**
```json
{
"viewport": { "width": 834, "height": 1194 },
"deviceScaleFactor": 2,
"userAgent": "Mozilla/5.0 (iPad; CPU OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1",
"isMobile": true,
"hasTouch": true
}
```
### 程序化设备模拟
使用 `run-code` 检查或修改设备属性:
```bash
# 检查当前设备属性
playwright-cli run-code "async page => {
return await page.evaluate(() => ({
userAgent: navigator.userAgent,
viewport: { width: window.innerWidth, height: window.innerHeight },
devicePixelRatio: window.devicePixelRatio,
touchSupport: 'ontouchstart' in window,
platform: navigator.platform
}));
}"
```
## 地理位置
覆盖浏览器报告的 GPS 位置——测试门店定位器、配送区域、基于位置的内容。
### 设置位置
```bash
# 纽约
playwright-cli run-code "async page => {
await page.context().grantPermissions(['geolocation']);
await page.context().setGeolocation({ latitude: 40.7128, longitude: -74.0060 });
}"
# 伦敦
playwright-cli run-code "async page => {
await page.context().grantPermissions(['geolocation']);
await page.context().setGeolocation({ latitude: 51.5074, longitude: -0.1278 });
}"
# 东京
playwright-cli run-code "async page => {
await page.context().grantPermissions(['geolocation']);
await page.context().setGeolocation({ latitude: 35.6762, longitude: 139.6503 });
}"
# 悉尼
playwright-cli run-code "async page => {
await page.context().grantPermissions(['geolocation']);
await page.context().setGeolocation({ latitude: -33.8688, longitude: 151.2093 });
}"
# 圣保罗
playwright-cli run-code "async page => {
await page.context().grantPermissions(['geolocation']);
await page.context().setGeolocation({ latitude: -23.5505, longitude: -46.6333 });
}"
```
### 在会话中更新位置
模拟用户在不同位置之间移动:
```bash
# 从旧金山开始
playwright-cli run-code "async page => {
await page.context().grantPermissions(['geolocation']);
await page.context().setGeolocation({ latitude: 37.7749, longitude: -122.4194 });
}"
playwright-cli goto https://example.com/nearby-stores
playwright-cli screenshot --filename=sf-stores.png
# 移动到洛杉矶
playwright-cli run-code "async page => {
await page.context().setGeolocation({ latitude: 34.0522, longitude: -118.2437 });
}"
playwright-cli reload
playwright-cli screenshot --filename=la-stores.png
```
### 清除地理位置覆盖
```bash
playwright-cli run-code "async page => {
await page.context().clearPermissions();
}"
```
### 通过配置文件设置地理位置
在打开浏览器时设置地理位置:
**`geo-nyc.json`**
```json
{
"geolocation": { "latitude": 40.7128, "longitude": -74.006 },
"permissions": ["geolocation"]
}
```
```bash
playwright-cli open https://example.com --config=geo-nyc.json
```
## 语言区域和时区
通过更改浏览器的语言区域和时区来测试国际化。
### 通过配置文件
**`locale-de.json`**
```json
{
"locale": "de-DE",
"timezoneId": "Europe/Berlin"
}
```
**`locale-ja.json`**
```json
{
"locale": "ja-JP",
"timezoneId": "Asia/Tokyo"
}
```
```bash
playwright-cli open https://example.com --config=locale-de.json
```
### 验证语言区域和时区
```bash
playwright-cli run-code "async page => {
return await page.evaluate(() => ({
language: navigator.language,
languages: navigator.languages,
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
dateFormat: new Date('2024-01-15').toLocaleDateString(),
numberFormat: (1234567.89).toLocaleString(),
currencyFormat: new Intl.NumberFormat(navigator.language, {
style: 'currency',
currency: 'USD'
}).format(1234.56)
}));
}"
```
### 常见语言区域 + 时区组合
| 区域 | 语言区域 | 时区 |
| --------- | -------- | ---------------------- |
| 美国东部 | `en-US` | `America/New_York` |
| 美国西部 | `en-US` | `America/Los_Angeles` |
| 英国 | `en-GB` | `Europe/London` |
| 德国 | `de-DE` | `Europe/Berlin` |
| 法国 | `fr-FR` | `Europe/Paris` |
| 日本 | `ja-JP` | `Asia/Tokyo` |
| 中国 | `zh-CN` | `Asia/Shanghai` |
| 印度 | `hi-IN` | `Asia/Kolkata` |
| 巴西 | `pt-BR` | `America/Sao_Paulo` |
| 澳大利亚 | `en-AU` | `Australia/Sydney` |
| 阿拉伯地区 | `ar-SA` | `Asia/Riyadh` |
## 配色方案
测试深色模式、浅色模式和高对比度:
```bash
# 深色模式
playwright-cli run-code "async page => {
await page.emulateMedia({ colorScheme: 'dark' });
}"
playwright-cli screenshot --filename=dark-mode.png
# 浅色模式
playwright-cli run-code "async page => {
await page.emulateMedia({ colorScheme: 'light' });
}"
playwright-cli screenshot --filename=light-mode.png
# 系统偏好(不覆盖)
playwright-cli run-code "async page => {
await page.emulateMedia({ colorScheme: 'no-preference' });
}"
```
## 减少动画
测试偏好减少动画的用户的可访问性:
```bash
# 启用减少动画
playwright-cli run-code "async page => {
await page.emulateMedia({ reducedMotion: 'reduce' });
}"
# 检查你的 CSS 是否遵循该设置
playwright-cli run-code "async page => {
return await page.evaluate(() =>
window.matchMedia('(prefers-reduced-motion: reduce)').matches
);
}"
```
## 强制颜色(高对比度)
测试 Windows 高对比度模式:
```bash
playwright-cli run-code "async page => {
await page.emulateMedia({ forcedColors: 'active' });
}"
playwright-cli screenshot --filename=high-contrast.png
```
## 权限
授予或拒绝浏览器权限:
```bash
# 授予多个权限
playwright-cli run-code "async page => {
await page.context().grantPermissions([
'geolocation',
'notifications',
'camera',
'microphone'
]);
}"
# 为特定来源授予权限
playwright-cli run-code "async page => {
await page.context().grantPermissions(['notifications'], {
origin: 'https://example.com'
});
}"
# 清除所有权限(重置为默认值)
playwright-cli run-code "async page => {
await page.context().clearPermissions();
}"
```
可用权限:`geolocation``notifications``camera``microphone``clipboard-read``clipboard-write``payment-handler``midi``midi-sysex``ambient-light-sensor``accelerometer``gyroscope``magnetometer``background-sync`
## 网络条件模拟
模拟慢速网络以测试加载状态和性能:
```bash
# 模拟慢速 3G
playwright-cli run-code "async page => {
const client = await page.context().newCDPSession(page);
await client.send('Network.emulateNetworkConditions', {
offline: false,
downloadThroughput: 500 * 1024 / 8, // 500 kbps
uploadThroughput: 500 * 1024 / 8, // 500 kbps
latency: 400 // 400ms RTT
});
}"
# 模拟离线模式
playwright-cli run-code "async page => {
const client = await page.context().newCDPSession(page);
await client.send('Network.emulateNetworkConditions', {
offline: true,
downloadThroughput: 0,
uploadThroughput: 0,
latency: 0
});
}"
# 恢复正常网络
playwright-cli run-code "async page => {
const client = await page.context().newCDPSession(page);
await client.send('Network.emulateNetworkConditions', {
offline: false,
downloadThroughput: -1,
uploadThroughput: -1,
latency: 0
});
}"
```
**注意**:CDP 会话仅适用于基于 Chromium 的浏览器。
## 常见模式
### 多设备截图套件
```bash
#!/bin/bash
URL="https://example.com"
playwright-cli open $URL
devices=("1920:1080:desktop" "768:1024:tablet" "375:812:mobile")
for device in "${devices[@]}"; do
IFS=':' read -r w h name <<< "$device"
playwright-cli resize $w $h
playwright-cli screenshot --filename="device-$name.png"
done
playwright-cli close
```
### 基于地理位置的内容测试
```bash
locations=("40.7128:-74.0060:nyc" "51.5074:-0.1278:london" "35.6762:139.6503:tokyo")
for loc in "${locations[@]}"; do
IFS=':' read -r lat lng name <<< "$loc"
playwright-cli run-code "async page => {
await page.context().grantPermissions(['geolocation']);
await page.context().setGeolocation({ latitude: $lat, longitude: $lng });
}"
playwright-cli reload
playwright-cli screenshot --filename="geo-$name.png"
done
```
### 可访问性模拟套件
```bash
playwright-cli open https://example.com
# 标准视图
playwright-cli screenshot --filename=a11y-standard.png
# 深色模式
playwright-cli run-code "async page => { await page.emulateMedia({ colorScheme: 'dark' }); }"
playwright-cli screenshot --filename=a11y-dark.png
# 高对比度
playwright-cli run-code "async page => { await page.emulateMedia({ forcedColors: 'active' }); }"
playwright-cli screenshot --filename=a11y-high-contrast.png
# 减少动画
playwright-cli run-code "async page => { await page.emulateMedia({ reducedMotion: 'reduce', forcedColors: 'none' }); }"
playwright-cli screenshot --filename=a11y-reduced-motion.png
playwright-cli close
```
## 提示
- **仅设置视口不等于设备模拟**——真正的设备测试需要通过配置文件设置 User Agent、触摸支持和设备缩放因子
- **地理位置需要权限**——在 `setGeolocation()` 之前务必先调用 `grantPermissions(['geolocation'])`
- **语言区域/时区必须在打开时设置**——使用配置文件,因为会话中途无法更改
- **CDP 功能仅限 Chromium**——通过 CDP 实现的网络限速在 Firefox 或 WebKit 中不适用
- **测试组合场景**——深色模式 + 减少动画 + 特定语言区域组合在一起时,能发现单独测试无法暴露的问题