多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Detox 中使用 TypeScript:配置 Jest、解决 expect 冲突与编写类型化 E2E 测试

Detox 中使用 TypeScript:配置 Jest、解决 expect 冲突与编写类型化 E2E 测试 Detox 中使用 TypeScript配置 Jest、解决 expect 冲突与编写类型化 E2E 测试【免费下载链接】DetoxGray box end-to-end testing and automation framework for mobile apps项目地址: https://gitcode.com/gh_mirrors/de/DetoxDetox 默认以 Jest 作为测试运行器因此如何让 Detox 跑 TypeScript 测试本质上就是如何让 Jest 理解 TypeScript。本篇指南基于 Detox 仓库的官方文档 docs/guide/typescript.md结合仓库内的类型声明体系detox/index.d.ts、detox/globals.d.ts与官方 TypeScript 示例工程examples/demo-react-native带你完成从ts-jest接入、testMatch修正到编写类型安全的 Detox 测试用例的全过程并剖析 Detox 与 Jest 之间expect命名冲突这一经典坑位的成因与规避方案。前置条件开始之前请确保满足以下两个前提已有一份可正常运行的 Detox 测试环境且测试运行器为 Jest这也是 Detox 默认、官方推荐的集成方式。项目中已安装 TypeScript。如果你使用自定义测试运行器如 Mocha、Cucumber 等而非 Jest本指南中的 Jest 相关配置不再适用需要参考对应测试运行器自身关于 TypeScript 的接入文档。Detox 仓库中也保留了针对其他运行器的适配层例如 detox/runners/mocha但 TypeScript 的编译接入仍需由运行器本身承担。初始化 TypeScript自 React Native 0.71 起默认的 React Native 项目模板已经内置了 TypeScript 支持。如果你的项目还没有 TypeScript可以通过以下命令快速初始化npm install --save-dev typescript tsc --inittsc --init会生成一份默认的tsconfig.json之后你可以按项目需要修改它例如调整strict、target、module等编译选项。解决command not found: tsc如果你在执行tsc时遇到如下报错command not found: tsc通常是因为node_modules/.bin没有进入 PATH。可以按下面任一方式解决export PATH$PATH:./node_modules/.binbash或zsh环境set PATH%PATH%;./node_modules/.binWindows 命令提示符直接使用npx tsc --init代替tsc --init或采用其他让node_modules/.bin下可执行文件可被调用的方案如配置 npm scripts。配置完成后建议先确认 TypeScript 能无报错地编译通过tsc # 生成编译产物 tsc --noEmit # 仅做类型检查不输出文件在继续后续步骤之前保证tsc通过可以把配置问题与测试代码问题隔离开便于后续排查。让 Jest 支持 TypeScript安装 ts-jest 与类型包Jest 原生只认识 JavaScript要无缝编译 TypeScript需要安装ts-jest以及类型声明包npm install --save-dev ts-jest types/jest types/nodets-jestJest 的 TypeScript 预处理器在测试运行时对.ts/.tsx文件做转译与类型转换types/jest为 Jest 的全局断言 APIdescribe、it、expect等提供类型声明types/node提供 Node.js 环境的类型声明供测试中可能用到的process、path等模块使用。修改 Jest 配置preset、testMatch 与 Detox 集成项编辑你的 Jest 配置文件默认位于e2e/jest.config.js具体位置以你的项目为准加入 TypeScript 支持/** type {import(jest/types).Config.InitialOptions} */ module.exports { preset: ts-jest, // (1) rootDir: .., testMatch: [rootDir/e2e/**/*.test.ts], // (2) testTimeout: 120000, maxWorkers: 1, globalSetup: detox/runners/jest/globalSetup, globalTeardown: detox/runners/jest/globalTeardown, reporters: [detox/runners/jest/reporter], testEnvironment: detox/runners/jest/testEnvironment, verbose: true, };preset: ts-jest这是整个 TypeScript 接入中最重要的配置。它告诉 Jest 使用ts-jest编译.ts文件等价于在transform字段中手动注册ts-jest转换器。这样 Jest 才能识别并执行*.test.ts测试文件。testMatch必须包含 TypeScript 文件默认的testMatch只匹配*.test.js如果不更新Jest 会找不到任何测试No tests found, exiting with code 1 Run with --passWithNoTests to exit with code 0 In /path/to/your/project 60 files checked. testMatch: /path/to/your/project/e2e/**/*.test.js - 0 matches testPathIgnorePatterns: /node_modules/ - 60 matches testRegex: - 0 matches Pattern: - 0 matches配置中其余几项是 Detox 与 Jest 集成的关键注入点务必备齐globalSetup: detox/runners/jest/globalSetup与globalTeardown: detox/runners/jest/globalTeardown在 Jest 全局生命周期中启动/停止 Detox 会话testEnvironment: detox/runners/jest/testEnvironment让测试运行在 Detox 的专用环境该环境负责初始化device、element、expect等全局对象对应源码见 detox/runners/jest/testEnvironmentreporters: [detox/runners/jest/reporter]使用 Detox 的专用 reporter 输出测试进度testTimeout、maxWorkers等按需保留例如maxWorkers: 1可保证单设备串行执行避免多 worker 争抢同一台模拟器。另一种等价写法显式 transform除了preset: ts-jest也可以像官方示例工程 examples/demo-react-native/e2e/jest.config.js 那样通过显式的transform注册ts-jest效果等价/** type {import(jest).Config} */ module.exports { maxWorkers: 1, globalSetup: ./globalSetup.ts, globalTeardown: detox/runners/jest/globalTeardown, testEnvironment: detox/runners/jest/testEnvironment, setupFilesAfterEnv: [./setup.ts], testRunner: jest-circus/runner, testTimeout: 120000, testMatch: [**/*.test.ts], transform: { \\.tsx?$: ts-jest }, reporters: [detox/runners/jest/reporter], verbose: true };从源码结构看preset: ts-jest本质上就是把上面transform的注册逻辑封装成了预设当你的配置中同时需要多个转换器、或希望精细控制转换范围时显式transform写法更直观。示例工程中还通过setupFilesAfterEnv: [./setup.ts]挂载了初始化脚本这与 Detox 文档中的preset写法并不冲突可以按项目习惯选择。编写 TypeScript 测试用例完成上述配置后只需把测试文件扩展名从.js改为.ts即可开始编写类型化的 Detox 测试。官方文档给出的登录场景示例如下import { expect } from detox; describe(Login Screen, () { it(should login with correct credentials, async () { const email: string testexample.com; const password: string password123; await element(by.id(emailInput)).typeText(email); await element(by.id(passwordInput)).typeText(password); await element(by.id(loginButton)).tap(); expect(await element(by.id(welcomeMessage))).toBeVisible(); }); });这段代码展示了 TypeScript 带来的典型收益测试数据email、password拥有明确的类型标注element(by.id(...))、typeText、tap、toBeVisible等 API 都能获得完整的智能提示与编译期校验从而显著降低因拼写错误、参数类型不匹配导致的运行时失败。仓库中的官方示例 examples/demo-react-native/e2e/suite1.test.ts 采用了同样的模式只是导入面更完整import { by, device, element, expect } from detox; describe(Test suite 1, () { beforeAll(async () { await device.relaunchApp(); }); it(should have welcome screen, async () { await expect(element(by.id(welcome))).toBeVisible(); }); it(should show hello screen after tap, async () { await element(by.id(hello_button)).tap(); await expect(element(by.text(Hello!!!))).toBeVisible(); }); });注意这里同时从detox导入了by、device、element、expect——这并非冗余而是规避下文所述的命名冲突问题的标准做法。避开经典坑位Jest 与 Detox 的 expect 冲突请特别留意上面示例中被重点标注的那一行import { expect } from detox;。在 TypeScript 场景下Jest 与 Detox 各自都导出了名为expect的全局对象二者存在一个尚未解决的命名冲突Detox 官方 issue 中有详细记录。具体表现是如果你直接使用 Jest 的全局expect去调用 Detox 专属的匹配器会触发类似下面的编译错误error TS2339: Property toBeVisible does not exist on type JestMatchersIndexableNativeElement.原因很直接toBeVisible()、toHaveText()、toExist()等是 Detox 在 detox/detox.d.ts 中为ExpectFacade扩展的匹配器而 Jest 自带的JestMatchers类型并不认识它们。在官方修复该冲突之前最稳妥的规避方式就是在测试文件中显式地从detox导入expect覆盖掉全局的 Jestexpect。值得注意的是await的用法也体现了 Detoxexpect的异步语义expect(await element(by.id(welcomeMessage)))先把元素匹配结果取回再断言确保在断言前 UI 已处于稳定状态。全局 API 与类型声明的底层支撑Detox 之所以能在不显式导入的情况下提供device、element、waitFor、by、web、system等全局对象是因为它在包内自带了类型声明detox/package.json 中声明了types: ./index.d.ts使 TypeScript 能自动识别 Detox 的类型入口detox/index.d.ts 通过/// reference pathdetox.d.ts /与/// reference pathglobals.d.ts /引入两个核心声明文件detox/globals.d.ts 在declare global中声明了detox、device、element、waitFor、expect、by、web、system、copilot、pilot等全局常量并把它们同步挂到NodeJS.Global命名空间上detox/detox.d.ts 则定义了完整的Detox命名空间包括DetoxConfig、DetoxAppConfig、DetoxDeviceConfig、各平台驱动配置ios.simulator、android.emulator、android.attached、android.genycloud、DetoxArtifactsConfig、DetoxBehaviorConfig、DetoxLoggerConfig、DetoxSessionConfig等以及Device、ElementFacade、ExpectFacade、ByFacade等运行时 API 的完整签名。因此在测试文件顶部为jest.config.js添加 JSDoc 类型注释/** type {import(jest/types).Config.InitialOptions} */、为detox.config.js添加/** type {Detox.DetoxConfig} */参考官方示例 examples/demo-react-native/detox.config.js都能获得完整的配置项补全与校验。类型声明的守护者仓库中的类型测试为了确保上述.d.ts声明文件长期可用Detox 仓库在 detox/test/types 目录下维护了专门针对全局 API 的类型测试如 detox/test/types/detox-global-tests.ts。这些文件并不在运行时执行而是通过编译期类型断言的方式验证device、element、expect等全局对象的签名是否与文档和实现保持一致。例如其中会直接调用device.appLaunchArgs.shared.modify({ ourMockServerPort: 9999 })、device.setStatusBar({ time: 12:34 })等 API并借助assertTypeT(value)之类的辅助函数核对返回类型。当你在自己的测试工程里发现某个 Detox API 的类型与文档不符时可以到该目录下确认对应签名它既是类型契约的测试用例也是排查类型问题的参考标本。完整落地参照官方 TypeScript 示例工程如果你希望看到一套开箱即用的完整参考仓库中的 examples/demo-react-native 就是一个 React Native 0.85 TypeScript Detox 的官方示例依赖层面package.json 的devDependencies中同时包含了typescript、ts-jest、types/jest并安装了detoxworkspace 引用测试目录e2e/下包含 jest.config.js、globalSetup.ts、setup.ts 以及两个.test.ts用例文件顶层配置 detox.config.js 通过testRunner.args.config: e2e/jest.config.js指定 Jest 配置入口并同时管理 iOS/Android 多套构建配置与detox build/detox test命令的映射。照着这个工程的结构搭建你自己的项目可以最大程度避免配置遗漏。就绪后运行detox test --configuration your-configuration即可用ts-jest编译并执行e2e/**/*.test.ts中的全部测试。常见问题速查症状原因解决方案No tests found, exiting with code 1testMatch仍指向*.test.js将testMatch改为匹配*.test.tsProperty toBeVisible does not exist on type JestMatchers...使用了 Jest 全局expect而非 Detox 的expect在测试文件中显式import { expect } from detox;command not found: tscnode_modules/.bin未加入 PATH使用npx tsc --init或按前文方式调整 PATH全局device/element无类型提示未安装detox的类型入口或未更新tsconfig.json的types确认detox版本自带index.d.ts其types字段已指向它并将e2e目录纳入编译范围结语让 Detox 支持 TypeScript核心工作就是让 Jest 能编译.ts文件安装ts-jest与类型包、配置preset或transform、更新testMatch并保留 Detox 的globalSetup/testEnvironment/reporter等集成项。在此基础上借助 Detox 自带的完整类型声明detox/index.d.ts、detox/detox.d.ts、detox/globals.d.ts你的 E2E 测试将获得静态类型的加持——更健壮、更易读、更不容易出错而这一切只需要记住一个小约定从detox显式导入expect。【免费下载链接】DetoxGray box end-to-end testing and automation framework for mobile apps项目地址: https://gitcode.com/gh_mirrors/de/Detox创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表