# @e2e-dev/mobile 中文文档

规范地址：https://npmcn.com/package/%40e2e-dev/mobile/

版本：0\.12\.7
npm 元数据更新时间：2026-11-13T13:27:37.327Z
中文译文更新时间：2026-11-13T13:32:12.267Z
软件包许可：Apache-2\.0

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40e2e-dev/mobile
原文对照：https://npmcn.com/package/%40e2e-dev/mobile/?lang=original
项目主页：https://github.com/e2e-inc/e2e/tree/main/packages/mobile#readme
源码仓库：https://github.com/e2e-inc/e2e

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：359 kB，53 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：^22\.22\.3 \|\| \>=24\.8\.0
- 运行依赖：3 个
- peer 依赖：ai ^7\.0\.0，e2e \>=0\.22\.1 \<1
- 首次发布：2026-09-28T18:46:29.941Z
- 最新版本发布：2026-11-13T13:27:36.926Z
- 近 30 天下载量：483891（2026-10-13 至 2026-11-11，npm 官方下载统计）
- 已发布版本数：54（近 12 个月 54 个）

## 中文简介

用于e2e代理端到端测试的移动引擎(iOS和Android),以代理端到端设备为基础

## 安装

```sh
npm install @e2e-dev/mobile
```

也可以使用：`pnpm add @e2e-dev/mobile`、`yarn add @e2e-dev/mobile`、`bun add @e2e-dev/mobile`

## README

# @e2e-dev/移动

用于 [`e2e`](https://www.npmjs.com/package/e2e),在 [代理设备](https://github.com/callstack/agent-device):iOS模拟器, Android 模拟器,和连接的电话通过相同的 `e2e/engine` 订约浏览器引擎 执行。 一个测试写到 `screen`, (中文(简体) ), `expect`, (中文(简体) ), `app`,以及 `agent` 运行 设备目标不变;无 `e2e` 核心知道此软件包存在.

## 安装

运行 `npx e2e init` 选择 **移动(iOS/Android)** 设置 以可选的 AI 测试为例。 在macOS和Android上默认使用iOS 其它位置; 更改平台 `e2e.config.ts` 需要的时候. 或将软件包添加到已有工程中 :

```bash
npm install --save-dev e2e @e2e-dev/mobile
```

`agent-device` 需要使用 iOS 模拟器运行时间的 Xcode, 或 Android SDK 与一个模范。 电话需要开发者模式和运行者在iOS上签名,或 Android上授权的USB调试(参见 [物理装置](https://e2e.com/docs/mobile#physical-devices)) (中文(简体) ). 运行 `npx e2e doctor` 以检查设置 一个跑步.

```ts
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` 开车 `n`th. 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` 从此软件包中输入.

```ts
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`。它可以在任何释放中改变 (单位:千美元)[参考文献](https://e2e.com/docs/reference/mobile#unstable_raw)) (中文(简体) ).

`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` (单位:千美元)[参考文献](https://e2e.com/docs/reference/mobile#unstable_devicesession)) (中文(简体) ).

## 秘诀

`type_secret` 财务报告和审定财务报表 `screen.getByLabel(...).fill(secret)` 填充公开的秘密 在设备上: 证书密码进入安全字段, a `secrets` 条目 输入可编辑的输入。 模型从不看价值,截图是 其余的尝试被扣留.

## 文档

完整文档生活于 [e2e.com/文档](https://e2e.com/docs)。 。 。 .

## 常见问题

### @e2e-dev/mobile 是什么？

用于e2e代理端到端测试的移动引擎\(iOS和Android\),以代理端到端设备为基础

### 如何安装 @e2e-dev/mobile？

在项目目录运行 npm install @e2e-dev/mobile，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：e2e（\>=0\.22\.1 \<1）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @e2e-dev/mobile 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @e2e-dev/mobile 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @e2e-dev/mobile 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js ^22\.22\.3 \|\| \>=24\.8\.0。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @e2e-dev/mobile 可以商用吗？

@e2e-dev/mobile 使用 Apache-2\.0 许可。宽松许可：允许商业使用、修改和再分发，并附带明确的专利授权；分发时需保留许可与 NOTICE 文件，修改过的文件要注明改动。以上为概括，不构成法律意见，请以许可原文为准。

### @e2e-dev/mobile 的下载量有多少？

根据 npm 官方下载统计，@e2e-dev/mobile 在 2026/10/13 – 2026/11/11 这 30 天内被下载 483,891 次，日均约 16,130 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @e2e-dev/mobile 还在维护吗？

最新版本 0\.12\.7 发布于 2026/11/13（今天）；至今共发布 54 个版本，其中过去 12 个月发布了 54 个；首次发布于 2026/09/29。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

