@e2e-dev/移动
用于 e2e,在
代理设备:iOS模拟器,
Android 模拟器,和连接的电话通过相同的 e2e/engine 订约浏览器引擎
执行。 一个测试写到 screen, (中文(简体) ), expect, (中文(简体) ), app,以及 agent 运行
设备目标不变;无 e2e 核心知道此软件包存在.
安装
运行 npx e2e init 选择 移动(iOS/Android) 设置
以可选的 AI 测试为例。 在macOS和Android上默认使用iOS
其它位置; 更改平台 e2e.config.ts 需要的时候.
或将软件包添加到已有工程中 :
npm install --save-dev e2e @e2e-dev/mobile
agent-device 需要使用 iOS 模拟器运行时间的 Xcode, 或 Android SDK
与一个模范。 电话需要开发者模式和运行者在iOS上签名,或
Android上授权的USB调试(参见 物理装置) (中文(简体) ). 运行 npx e2e doctor 以检查设置
一个跑步.
import type { E2EConfig } from 'e2e';
import { mobile } from '@e2e-dev/mobile';
import { mobileTools } from '@e2e-dev/mobile/tools';
import { gateway } from 'ai';
const iphone = mobile({ platform: 'ios' });
const pixel = mobile({ platform: 'android' });
export default {
targets: [
{ name: 'iphone', engine: iphone, app: { bundleId: 'Settings' } },
{ name: 'pixel', engine: pixel, app: { bundleId: 'com.android.settings' } },
],
workers: 1,
agents: {
default: {
model: gateway('openai/gpt-6-luna-fast'),
tools: mobileTools(iphone, pixel),
},
},
} satisfies E2EConfig;
一个测试写到 agent, (中文(简体) ), app, (中文(简体) ), screen,以及 device 运行在两个
目标不变。 只有名为平台标签的检查( Q)General 在iOS上,
Network & internet (Android)的需要 platforms: ['ios'] 或者说
platforms: ['android'] 在测试.
测试中的应用程序是目标 app;引擎只驱动它. A 类
设备目标需求 bundleId 或者说 appPath数字 :
| 密钥 | 含义 |
|---|---|
bundleId | 软件包、软件包或显示名称 app.open(), (中文(简体) ), app.restart(),以及 app.clearState() 发射新鲜; 尝试没有自行发射. |
appPath | 一个iOS .app 捆绑或安卓 .apk,根据项目根解决。 引擎没有安装它: 套房呼叫 device.installApp() (没有路径,这个构建)每个设备一次,除非设备提供者已经安装了它. 无 bundleId,已安装的捆绑 id 或包是应用程序 app.open() 发射. |
launchArguments | 争辩每一次新推出被绑起的应用程序载体(app.open(), (中文(简体) ), app.restart(), (中文(简体) ), app.clearState():iOS上的流程参数, am start android上的论点。 热身没有通过. |
permissions | 允许每一次新发射 都有固定的应用, { camera: 'grant', location: 'deny', notifications: 'reset' },设置在应用程序开始前,然后放回去 app.clearState() 重置他们. |
app.url 尚未在设备目标上支持,并且 mobile({ app }) 财务报告和审定财务报表
其他旧的应用程序选项是 INVALID_CONFIG 在其密钥下命名 app。 。 。 .
mobile() 选项:
| 选项 | 含义 |
|---|---|
platform | 'ios' 或者说 'android'。 。 。 . |
device | 模拟器或模拟器名称或UDID,或连接的手机名称. 名单是池子:每个入口一个工人,一个工人档位 n 开车 nth. Ocondition,平台上每个被启动的装置都是"池",所跑道有槽的也一样多. |
session | 代理设备会话名称, 工人槽前: 槽 n 驱动设备在 <session>-<n>, (中文(简体) ), e2e-<target name>-<n> 默认。 每届1跑. |
snapshot | 'full' (默认,包括静态文本)或 'interactive' (只有可行动节点). |
settle | 在代理方再次观察前, UI 必须在代理方行动后仍然持有毫秒, 默认值 150· ; false 跳过等待。 测试步骤不能解决,除非 device.back()· ; expect 核实结果. |
transition | 对于一个测试的步骤: 毫秒的控件会随着最后一个动作出现或移动, 在操作前到达, 默认 500。只有当键盘可见度不变时,才立即对未移动的控件采取行动。 打开或关闭键盘也使用所余预算. 测试中的屏幕刷新在滚动前等待剩余预算. |
videoTouches | 用于录制移动引擎(不是设备提供者自己录制的), 视频是否绘制代理设备的触摸指示器, 默认 true。 。 。 . false 记录平面屏幕, 并跳过在录音停止后绘制指示器, 在主机守护进程上可以超过 cleanupTimeout。 。 。 . |
每个可选 mobile() 值也接受 undefined,所以一个配置通过
device: process.env.E2E_DEVICE 直接通过,没有条件
展开.
引擎声明什么
- 意见: 无障碍树, 投放到角色词汇中
(监督厅)
Button变成button, (中文(简体) ),TextField变成textbox, (中文(简体) ),Cell变成listitem; 机器人android.widget.TextView变成text, (中文(简体) ),EditText变成textbox, (中文(简体) ),Switch变成switch),带有矩形,取景口,以及 请求时将所有安全字段涂上像素 。 元素标识符 (单位:千美元)ABOUT, (中文(简体) ),android:id/title)是节点的testId,怎样getByTestId火柴。 比赛. - 行动:自拍、双自拍、长按、填充、清空、检查/不检查(何时)
树会像两个平台的开关一样暴露检查状态,
注重可编辑字段,
Enter,单字符键,在节点内切换,拖动.selectOption, (中文(简体) ),setInputFiles, (中文(简体) ),scrollIntoView, (中文(简体) ),secondaryTap, (中文(简体) ),modifiers打开tap或者说doubleTap,聚焦于控件,而其他密钥失败UNSUPPORTED_CAPABILITY。 。 。 . - 地点: 每一个
screen查询,加上代理设备选择器device.locator('role=navigation-bar id=General')。 。 。 . - 视图口切换, (中文(简体) ),
app.back(), (中文(简体) ),app.restart(), (中文(简体) ),app.clearState(),以及 尝试文物目录下的已编辑截图: 在保存文件前,每个安全字段被漆成黑色,并且 a 不能编辑的截图不会被写入 。 没有state能力:a 模拟器没有便携式会话快照 . - App 类型: 目标与
app.bundleId或者说app.appPath是一个native-app因此,一个便携式套房可以requires: ['native-app']。 。 。 .
重放缓存
跑步缓存 agent.act 并有一个设备
没有地址栏。 这个引擎报告一个反正: <bundle id> / <screen title>,标题读取了 iOS 上的导航栏和崩溃
工具栏。 应用程序身份是位置的一部分,所以两个应用程序与
a"General"屏幕从不共享主播. 记录的一步
com.apple.Preferences / General 只在应用程序在上面时重放
屏幕,并保留在水龙头、键入和滚动回放中的流程
零型号呼叫。 声明 app.bundleId 打电话 app.open() 首先,步骤开始
同样的屏幕,和
宁可使用语法而不是 open_app 步骤中的工具:工具调用是
重放间隙.
这个 device 固定图
决定性设备管理,记录为 device.<method> 步骤。 导入
test 从此软件包中输入.
import { test } from '@e2e-dev/mobile';
import { expect } from 'e2e';
test('shows the version in dark mode', async ({ agent, device, screen }) => {
await device.setAppearance('dark');
await agent.act('go to General, then About');
await expect(screen.getByRole('button', /^iOS Version/)).toBeVisible();
await expect(device.locator('role=navigation-bar id=About')).toBeVisible();
});
方法: setNetwork, (中文(简体) ), setAirplaneMode, (中文(简体) ), setPermission, (中文(简体) ), setLocation, (中文(简体) ),
clearLocation, (中文(简体) ), setAppearance, (中文(简体) ), setOrientation, (中文(简体) ), fold, (中文(简体) ), setBiometrics, (中文(简体) ),
enrollBiometrics, (中文(简体) ), installApp, (中文(简体) ), openApp, (中文(简体) ), openLink, (中文(简体) ), closeApp, (中文(简体) ),
clearKeychain, (中文(简体) ), foregroundApp, (中文(简体) ), home, (中文(简体) ), back, (中文(简体) ), alert, (中文(简体) ), dismissKeyboard, (中文(简体) ),
clipboard, (中文(简体) ), setClipboard,则 locator 访问者.
device.unstable_raw 是原始驱动进程,因为方法没有
掩护 内容 client 电话不是步骤:报告并追踪,
缓存不会重放它们,它们的论点会到达驱动程序未编辑的,
没有什么等待 屏幕解决。 工后再读
处理会话 INVALID_STATE。它可以在任何释放中改变
(单位:千美元)参考文献) (中文(简体) ).
setNetwork('offline') 财务报告和审定财务报表 setAirplaneMode(true) 仅是Android。 一个iOS
模拟器共享Mac的网络,模拟器只能改变其状态
栏,因此在iOS上都失败了 UNSUPPORTED_CAPABILITY; 返回在线
在那里什么都没有做, 所以共享清理钩通过。 关于Android,
setNetwork('offline') 单独关闭Wi-Fi, 这样应用程序就可以在线
过细胞; setAirplaneMode(true) (Android 11 或以后)拿它来
离线.
installApp(appPath, { app, reinstall }) 在设备上加一个构件
测试,用于升级和新安装路径 app.appPath 无法
运算.
平面安装取代二进制并保存其数据; reinstall: true
删除名为 app (默认:被绑定的app)首先. 它决心
捆绑的id或软件包 openApp 建筑由, 否则 app 传入;
未报告身份和身份 app失败 ENGINE_FAILURE。 。 。 . openApp 使用一个应用id,
永远没有联系; openLink 在导航规则下打开一个.
代理工具
@e2e-dev/mobile/tools 出口 mobileTools(...engines)数字 : open_app, (中文(简体) ),
swipe (free-form,以逻辑像素表示),并 alert (接受或驳回)
系统警报。 这至少需要一个引擎。 通过每个设备引擎
配置声明: 工具名称是固定的, 所以两个包无法合并, 而
将每个呼叫发送到正在运行的引擎。 工具为
探测到这些引擎的平台, 所以一个混合网络和装置的套房
目标可以把包交给一个特工 tools。 。 。 .
带有原始驱动程序的自定义工具
unstable_deviceSession(...engines) 从 @e2e-dev/mobile/tools 给出一个
运行尝试的原始驱动程序会话的自定义工具, 用于 e2e 能力
尚未结束。 它的客户端与引擎的守护进程,租赁,和
届会。 客户端输入为 DeviceSessionClient从 @e2e-dev/mobile。 。 。 .
此 API 可以在任何发行中更改, 如 device.unstable_raw
(单位:千美元)参考文献) (中文(简体) ).
秘诀
type_secret 财务报告和审定财务报表 screen.getByLabel(...).fill(secret) 填充公开的秘密
在设备上: 证书密码进入安全字段, a secrets 条目
输入可编辑的输入。 模型从不看价值,截图是
其余的尝试被扣留.
文档
完整文档生活于 e2e.com/文档。 。 。 .