Playwright 设备与浏览器模拟
本章介绍如何在 Playwright 中模拟移动设备、地理位置、时区、语言、颜色方案等浏览器环境参数。
移动端设备模拟
Playwright 内置了大量设备预设,可以模拟各种手机和平板的视口、User-Agent 和触控行为。
使用 devices 预设
通过 devices 对象可以快速模拟特定设备。
实例
import { chromium, devices } from 'playwright';
// 模拟 iPhone 15
const browser = await chromium.launch();
const context = await browser.newContext(devices['iPhone 15']);
const page = await context.newPage();
await page.goto('https://www.runoob.com/');
// 页面将以 iPhone 15 的视口和 UA 渲染
// 模拟 iPhone 15
const browser = await chromium.launch();
const context = await browser.newContext(devices['iPhone 15']);
const page = await context.newPage();
await page.goto('https://www.runoob.com/');
// 页面将以 iPhone 15 的视口和 UA 渲染
在配置文件中使用设备预设:
实例
// 文件路径:playwright.config.ts
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
projects: [
{
name: 'mobile',
use: { ...devices['Pixel 7'] },
},
],
});
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
projects: [
{
name: 'mobile',
use: { ...devices['Pixel 7'] },
},
],
});
手动配置视口
如果你不需要完整的设备预设,也可以手动指定视口大小。
实例
const context = await browser.newContext({
viewport: { width: 375, height: 812 }, // 视口大小
deviceScaleFactor: 3, // 设备像素比(Retina 屏)
isMobile: true, // 启用移动端模式
hasTouch: true, // 启用触控模拟
userAgent: 'Mozilla/5.0 ... Mobile ...', // 自定义 UA
});
viewport: { width: 375, height: 812 }, // 视口大小
deviceScaleFactor: 3, // 设备像素比(Retina 屏)
isMobile: true, // 启用移动端模式
hasTouch: true, // 启用触控模拟
userAgent: 'Mozilla/5.0 ... Mobile ...', // 自定义 UA
});
地理位置模拟
Playwright 可以模拟设备的 GPS 位置信息。
实例
test('模拟北京位置', async ({ context, page }) => {
// 授予地理位置权限
await context.grantPermissions(['geolocation']);
// 设置具体经纬度(北京坐标)
await context.setGeolocation({
latitude: 39.9042,
longitude: 116.4074,
});
await page.goto('https://www.runoob.com/map');
// 页面将获取到北京的位置信息
});
// 授予地理位置权限
await context.grantPermissions(['geolocation']);
// 设置具体经纬度(北京坐标)
await context.setGeolocation({
latitude: 39.9042,
longitude: 116.4074,
});
await page.goto('https://www.runoob.com/map');
// 页面将获取到北京的位置信息
});
时区与语言模拟
通过设置 locale 和 timezone 来验证国际化和时区相关的功能。
实例
const context = await browser.newContext({
locale: 'zh-CN', // 浏览器语言设置为简体中文
timezone: 'Asia/Shanghai', // 时区设置为上海(UTC+8)
});
// 在配置文件中全局设置
export default defineConfig({
use: {
locale: 'en-US',
timezone: 'America/New_York',
},
});
locale: 'zh-CN', // 浏览器语言设置为简体中文
timezone: 'Asia/Shanghai', // 时区设置为上海(UTC+8)
});
// 在配置文件中全局设置
export default defineConfig({
use: {
locale: 'en-US',
timezone: 'America/New_York',
},
});
常用的 locale 值:
| locale | 语言/地区 |
|---|---|
'zh-CN' | 简体中文(中国) |
'zh-TW' | 繁体中文(台湾) |
'en-US' | 英语(美国) |
'ja-JP' | 日语 |
'ko-KR' | 韩语 |
颜色方案模拟
模拟浅色或深色模式,测试 prefers-color-scheme 媒体查询的效果。
实例
// 测试深色模式
const darkContext = await browser.newContext({
colorScheme: 'dark',
});
// 可选值:'light'、'dark'、'no-preference'
const darkContext = await browser.newContext({
colorScheme: 'dark',
});
// 可选值:'light'、'dark'、'no-preference'
在配置文件中为不同项目设置不同的颜色方案:
实例
// 文件路径:playwright.config.ts
export default defineConfig({
projects: [
{
name: 'chromium-light',
use: { colorScheme: 'light' },
},
{
name: 'chromium-dark',
use: { colorScheme: 'dark' },
},
],
});
export default defineConfig({
projects: [
{
name: 'chromium-light',
use: { colorScheme: 'light' },
},
{
name: 'chromium-dark',
use: { colorScheme: 'dark' },
},
],
});
权限模拟
使用 context.grantPermissions() 来授予浏览器权限。
实例
await context.grantPermissions([
'geolocation', // 地理位置
'notifications', // 通知
'camera', // 摄像头
'microphone', // 麦克风
'clipboard-read', // 读取剪贴板
'clipboard-write', // 写入剪贴板
]);
// 清除所有权限
await context.clearPermissions();
'geolocation', // 地理位置
'notifications', // 通知
'camera', // 摄像头
'microphone', // 麦克风
'clipboard-read', // 读取剪贴板
'clipboard-write', // 写入剪贴板
]);
// 清除所有权限
await context.clearPermissions();
Cookie 操作
通过 BrowserContext 可以读取、添加和清除 Cookie。
实例
// 添加 Cookie
await context.addCookies([
{
name: 'runoob_session',
value: 'session_token_value',
domain: 'www.runoob.com',
path: '/',
httpOnly: true,
secure: true,
sameSite: 'Lax',
},
]);
// 获取所有 Cookie
const cookies = await context.cookies();
console.log(cookies);
// 获取特定 URL 的 Cookie
const siteCookies = await context.cookies('https://www.runoob.com');
// 清除所有 Cookie
await context.clearCookies();
await context.addCookies([
{
name: 'runoob_session',
value: 'session_token_value',
domain: 'www.runoob.com',
path: '/',
httpOnly: true,
secure: true,
sameSite: 'Lax',
},
]);
// 获取所有 Cookie
const cookies = await context.cookies();
console.log(cookies);
// 获取特定 URL 的 Cookie
const siteCookies = await context.cookies('https://www.runoob.com');
// 清除所有 Cookie
await context.clearCookies();
Cookie 参数说明
| 字段 | 类型 | 说明 |
|---|---|---|
name | string | Cookie 名称 |
value | string | Cookie 值 |
domain | string | 生效的域名 |
path | string | 生效的路径,默认 '/' |
expires | number | 过期时间(Unix timestamp) |
httpOnly | boolean | 是否仅 HTTP 可访问 |
secure | boolean | 是否仅 HTTPS 传输 |
sameSite | string | SameSite 策略:'Strict' | 'Lax' | 'None' |
localStorage 与 SessionStorage 操作
通过 page.evaluate() 在页面上下文操作存储。
实例
// 设置 localStorage
await page.evaluate(() => {
localStorage.setItem('runoob_key', 'runoob_value');
});
// 读取 localStorage
const value = await page.evaluate(() => {
return localStorage.getItem('runoob_key');
});
console.log(value); // 'runoob_value'
// 清除 localStorage
await page.evaluate(() => {
localStorage.clear();
});
await page.evaluate(() => {
localStorage.setItem('runoob_key', 'runoob_value');
});
// 读取 localStorage
const value = await page.evaluate(() => {
return localStorage.getItem('runoob_key');
});
console.log(value); // 'runoob_value'
// 清除 localStorage
await page.evaluate(() => {
localStorage.clear();
});
Cookie 和 Storage 操作都应该在
page.goto()之前完成,确保页面加载时就能使用这些数据。
