元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
入门指南
Playwright安装与配置
环境要求与验证
第一个自动化测试脚本
▶
核心概念
Browser对象详解
Page对象操作指南
Frame与上下文管理
网络请求拦截与Mock
▶
元素定位与操作
CSS选择器实战
XPath高级定位技巧
文本定位与正则匹配
动态元素等待策略
▶
高级操作指南
文件上传下载处理
多标签页与弹窗管理
浏览器上下文隔离
设备模拟与地理定位
▶
测试框架集成
Jest集成配置
Mocha测试报告生成
持续集成CI/CD配置
▶
最佳实践
测试用例组织结构
性能优化策略
跨浏览器测试方案
▶
疑难解答
常见错误代码解析
元素定位失败分析
浏览器启动问题排查
▶
录制功能指南
录制功能基础入门
录制脚本生成与编辑
高级录制配置与技巧
录制脚本调试与优化
发布时间:
2025-03-27 19:16
↑
☰
# 设备模拟与地理定位 本文将详细介绍如何在Playwright中模拟不同设备和地理位置,帮助你实现移动设备测试和位置相关的测试场景。 ## 设备模拟 ### 1. 预设设备 ```typescript // 使用预设设备 const iPhone = devices['iPhone 13']; const context = await browser.newContext({ ...iPhone }); // 使用iPad const iPad = devices['iPad Pro 11']; const context = await browser.newContext({ ...iPad }); // 使用Android设备 const pixel = devices['Pixel 5']; const context = await browser.newContext({ ...pixel }); ``` ### 2. 自定义设备 ```typescript // 自定义设备配置 const context = await browser.newContext({ viewport: { width: 375, height: 667 }, deviceScaleFactor: 2, isMobile: true, hasTouch: true, userAgent: 'Custom Mobile Browser' }); // 设置屏幕方向 const context = await browser.newContext({ viewport: { width: 667, height: 375 }, isMobile: true, hasTouch: true, isLandscape: true }); ``` ## 地理定位 ### 1. 基本定位 ```typescript // 设置地理位置 await context.grantPermissions(['geolocation']); await page.setGeolocation({ latitude: 31.2304, longitude: 121.4737 }); // 模拟多个位置 const locations = [ { latitude: 31.2304, longitude: 121.4737 }, { latitude: 39.9042, longitude: 116.4074 } ]; for (const location of locations) { await page.setGeolocation(location); await page.reload(); } ``` ### 2. 高级定位 ```typescript // 设置精确位置 await page.setGeolocation({ latitude: 31.2304, longitude: 121.4737, accuracy: 100 // 精确度(米) }); // 模拟位置移动 async function simulateMovement(page, start, end, steps = 10) { const latStep = (end.latitude - start.latitude) / steps; const lngStep = (end.longitude - start.longitude) / steps; for (let i = 0; i <= steps; i++) { await page.setGeolocation({ latitude: start.latitude + latStep * i, longitude: start.longitude + lngStep * i }); await page.waitForTimeout(1000); } } ``` ## 设备功能 ### 1. 触摸事件 ```typescript // 模拟触摸操作 await page.touchscreen.tap(100, 200); // 模拟滑动 await page.touchscreen.swipe(100, 200, 100, 400, { steps: 10 // 滑动的平滑度 }); // 多点触控 await page.touchscreen.multiTouchPoints([ { x: 100, y: 200 }, { x: 300, y: 400 } ]); ``` ### 2. 传感器模拟 ```typescript // 模拟加速度传感器 await page.evaluate(() => { window.dispatchEvent(new DeviceMotionEvent('devicemotion', { acceleration: { x: 1, y: 2, z: 3 } })); }); // 模拟方向传感器 await page.evaluate(() => { window.dispatchEvent(new DeviceOrientationEvent('deviceorientation', { alpha: 0, // Z轴旋转 beta: 90, // X轴旋转 gamma: 0 // Y轴旋转 })); }); ``` ## 最佳实践 ### 1. 设备测试 ```typescript // 创建设备测试工具 class DeviceTester { constructor(browser) { this.browser = browser; this.contexts = new Map(); } async testOnDevice(deviceName, url) { const device = devices[deviceName]; const context = await this.browser.newContext({ ...device, permissions: ['geolocation'] }); const page = await context.newPage(); await page.goto(url); this.contexts.set(deviceName, context); return page; } async cleanup() { for (const context of this.contexts.values()) { await context.close(); } } } ``` ### 2. 位置测试 ```typescript // 创建位置测试工具 class LocationTester { constructor(page) { this.page = page; } async testAtLocation(location) { await this.page.setGeolocation(location); await this.page.reload(); await this.page.waitForLoadState(); } async testRoute(locations) { for (const location of locations) { await this.testAtLocation(location); await this.page.waitForTimeout(2000); } } } ``` ## 调试技巧 ### 1. 设备调试 ```typescript // 打印设备信息 const deviceInfo = await page.evaluate(() => ({ userAgent: navigator.userAgent, viewport: { width: window.innerWidth, height: window.innerHeight }, devicePixelRatio: window.devicePixelRatio })); console.log('设备信息:', deviceInfo); // 检查触摸事件 page.on('console', msg => { if (msg.text().includes('touch')) { console.log('触摸事件:', msg.text()); } }); ``` ### 2. 位置调试 ```typescript // 监控位置变化 page.on('console', msg => { if (msg.text().includes('geolocation')) { console.log('位置更新:', msg.text()); } }); // 验证位置权限 const hasPermission = await page.evaluate(() => { return navigator.permissions.query({ name: 'geolocation' }); }); console.log('地理位置权限:', hasPermission.state); ``` ## 常见问题 ### 1. 设备问题 ```typescript // 处理设备不支持 try { const context = await browser.newContext({ ...devices['iPhone 13'] }); } catch (error) { console.error('设备模拟失败:', error); // 使用默认移动设备配置 const context = await browser.newContext({ viewport: { width: 375, height: 667 }, isMobile: true }); } // 处理触摸事件失败 try { await page.touchscreen.tap(100, 200); } catch (error) { console.error('触摸事件失败:', error); // 使用鼠标点击代替 await page.mouse.click(100, 200); } ``` ### 2. 位置问题 ```typescript // 处理位置权限 try { await context.grantPermissions(['geolocation']); await page.setGeolocation({ latitude: 31.2304, longitude: 121.4737 }); } catch (error) { console.error('位置设置失败:', error); // 模拟位置API await page.evaluate(() => { navigator.geolocation.getCurrentPosition = cb => cb({ coords: { latitude: 31.2304, longitude: 121.4737 } }); }); } ``` ## 下一步 1. 探索[Jest集成配置](/article/playwright/integration/jest) 2. 学习[Mocha测试报告生成](/article/playwright/integration/mocha) 3. 了解[持续集成CI/CD配置](/article/playwright/integration/ci-cd) ## 参考资料 - [Playwright设备模拟](https://playwright.dev/docs/emulation) - [Playwright地理位置](https://playwright.dev/docs/geolocation) - [移动设备测试](https://playwright.dev/docs/mobile)