跳转至

移动应用商店截图测试工具

面向维护者。正在使用 T3 Code?请参阅 docs/user。

该截图测试工具会针对三个一次性的本地 T3 环境运行真实的移动应用。它为每个环境创建隔离的基目录和服务器、内容确定性的真实 Git 项目、预置的编排投影,以及持久化的终端历史。应用通过其正常连接流程与每台服务器配对,React Navigation 会打开生产环境的 Home、Thread、ThreadTerminal、ThreadReview 和 SettingsEnvironments 路由。

没有任何截图专用的屏幕会重新创建应用 UI。EXPO_PUBLIC_SHOWCASE=1 只会启用不参与渲染的配对/就绪协调器,禁用终端自动聚焦,以便截图不包含软键盘,并向真实的 Environments 屏幕提供确定性的 T3 Connect 发现行。本地环境卡片始终来自真实配对的服务器。

捕获默认矩阵

在仓库根目录下:

pnpm screenshots:mobile

该命令:

  1. 创建三个临时 T3 基目录,并在可用端口上为每个目录启动一个本地服务器。
  2. 创建 T3 Code、React 和 Linux Git 仓库,包含可识别的 favicon、功能分支,以及确定性的 T3 Code 审查 diff。
  3. 在每台服务器已迁移的 SQLite 数据库中预置趣味性的线程、消息、活动和终端历史,然后添加两个等待发送的持久化移动端发件箱任务。
  4. 启动隔离的 Metro 服务器,构建所选原生应用,并启动每台设备。
  5. 将每个干净安装的应用与 Moonbase Terminal、Suspense Station 和 Kernel Cabin 配对。
  6. 为每个请求的场景导航到真实应用路由。
  7. 设置请求的系统外观和调色板,标准化状态栏,将截图转换为无 alpha 的 24 位 RGB PNG,并在成功前验证尺寸、宽高比、文件大小和截图数量。
  8. 在 artifacts/app-store/screenshots/ 下写入商店就绪文件夹,可直接上传到 App Store Connect 或 Google Play Console。

运行器启动的服务器、Metro、临时根目录和设备会在截图后清理。传入 --keep-running 可保留它们以供检查;运行器会打印基目录路径和服务器端口。

截图会等待真实环境快照完成水合,并等待请求的路由变为活动状态。两个平台都会在模拟器/仿真器应用容器中记录就绪状态。最后的稳定延迟让原生终端和 Git 审查数据完成渲染。

完整截图会在构建前使用 Expo 的干净生产预构建重新生成所选原生项目。首次构建后,重复截图可使用 --skip-build。

该测试工具使用固定的 Metro 端口 8199,这使其与 Expo 的常规默认端口区分开,但在每个检出之间共享。就绪检查仅验证端口是否打开,并不验证进程归属。因此,不同工作树中并发的截图测试工具可能会冲突或连接到错误的 Metro 进程。

每台配置的设备默认使用深色外观和 t3-code 调色板,因此直接运行 pnpm screenshots:mobile 会生成 45 张深色 PNG。传入 --appearance light、--appearance dark 或 --appearance both 可覆盖配置的外观;both 会生成 90 张 PNG。

传入 --theme <id>(可重复)或 --theme all 可截取应用的其他调色板:t3-code、t3-chat、grove、ocean、ember 和 iris。运行器将调色板作为启动参数传递给应用,应用会将其应用到两种配色方案;场景只有在请求的调色板激活后才会报告就绪——因此截图绝不会显示之前的主题。--theme all 会使运行次数乘以六;只有原生构建是共享的。

默认矩阵如下:

Output folder Capture target Upload dimensions Store slot
apple/iphone-6.9/dark/t3-code/ disposable iPhone 17 Pro Max 1320×2868 App Store Connect iPhone 6.9-inch
apple/iphone-6.5/dark/t3-code/ disposable iPhone 14 Plus 1284×2778 App Store Connect iPhone 6.5-inch
apple/iphone-duo-closed/dark/t3-code/ iPhone Duo, folded portrait 1398×2034 App Store Connect iPhone Duo
apple/iphone-duo-open/dark/t3-code/ iPhone Duo, unfolded landscape 2853×2007 App Store Connect iPhone Duo
apple/ipad-13/dark/t3-code/ iPad Pro 13-inch (M5) 2752×2064 App Store Connect iPad 13-inch, landscape
google-play/phone/dark/t3-code/ Pixel AVD at 420 dpi 1080×1920 Google Play phone, portrait 9:16
google-play/tablet-7/dark/t3-code/ Pixel AVD at 600dp width 1080×1920 Google Play 7-inch tablet, portrait 9:16
google-play/tablet-10/dark/t3-code/ Pixel AVD at 800dp width 1440×2560 Google Play 10-inch tablet, portrait 9:16

每个目标都会截取线程、终端、审查、线程列表和环境;除 iPad 和 Duo 外的每个目标还会截取代理活动。每个调色板文件夹中的五或六张截图满足配置的 Apple 1–10 张限制、Google 手机 2–8 张要求,以及 Google 平板推荐/槽位最少 4 张、最多 8 张的要求。两个 Duo 文件夹各包含五个场景,并上传到同一个 iPhone Duo 槽位(共十张图片)。它们省略代理活动,以保持在共享限制内。Duo 截图需要已安装的、支持 iPhone Duo 的 iOS 运行时,并且 PATH 中有 agent-device,或 AGENT_DEVICE_PATH 指向其可执行文件;它会在启动应用前设置并验证模拟器的折叠姿势。

每个调色板都有自己的独立文件夹,因此一个上传槽位绝不会混入多个主题,而且每个文件夹都保持商店允许的截图数量。

代理活动场景展示的是用户离开应用后看到的内容。应用会为四个预设线程编排中继(relay)将要发布的同一个实时活动(Live Activity,iOS)或持续实时更新(Live Update,Android)。在 iOS 上,运行器随后锁定模拟器,并通过 simctl push 推送匹配的批准提醒;在 Android 上,预置更新携带提醒内容,运行器打开通知栏。锁定模拟器以及响应通知权限提示使用的是 AXe,因此请先安装它(brew tap cameroncooke/axe && brew install axe),或者在捕获 iOS 截图前设置 AXE_PATH。iPad 会跳过此场景,因为锁屏不会跟随应用自身的横向自动旋转。

生成的目录结构与商店上传字段刻意保持一致:

artifacts/app-store/screenshots/
├── apple/
│   ├── iphone-6.9/dark/t3-code/{thread,terminal,review,threads,environments,agent-activity}.png
│   ├── iphone-6.5/dark/t3-code/{thread,terminal,review,threads,environments,agent-activity}.png
│   ├── iphone-duo-closed/dark/t3-code/{thread,terminal,review,threads,environments}.png
│   ├── iphone-duo-open/dark/t3-code/{thread,terminal,review,threads,environments}.png
│   └── ipad-13/dark/t3-code/{thread,terminal,review,threads,environments}.png
└── google-play/
    ├── phone/dark/t3-code/{thread,terminal,review,threads,environments,agent-activity}.png
    ├── tablet-7/dark/t3-code/{thread,terminal,review,threads,environments,agent-activity}.png
    └── tablet-10/dark/t3-code/{thread,terminal,review,threads,environments,agent-activity}.png

仅浅色模式的运行会在 light/ 下写出同样的目录结构;--appearance both 会同时写出两种外观的文件夹,而每个被请求的调色板都会在 t3-code/ 旁边新增一个同级文件夹。

编辑 mobile-showcase.config.ts 可以更改模拟器或 AVD 名称、浅色/深色外观、默认调色板、iOS 方向、场景、输出目录、捕获延迟、Android ABI 或视口。可选的调色板 ID 来自 themePalettes.ts 中的 MOBILE_THEME_IDS,因此测试框架与应用的外观设置永远不会彼此脱节。

在 GitHub Actions 中捕获

从 GitHub 的 Actions 标签页运行 Mobile Showcase Screenshots 工作流,选择 all、ios 或 android,再选择 light、dark 或 both,然后挑选一个调色板(或选择 all,这会把每个任务的超时时间从 60 分钟提升到 300 分钟)。默认手动触发的分发会捕获 t3-code 调色板的两种外观,并让 iOS 与 Android 并行运行:iPhone 和 iPad 捕获运行在 12 个 vCPU 的 Blacksmith macOS 运行器上,而 Android 手机、7 英寸平板和 10 英寸平板捕获运行在 16 个 vCPU 的 Blacksmith Linux 运行器上,使用 KVM 加速的 x86_64 模拟器。

即使捕获失败,每个任务也都会上传其 PNG,这使得部分运行结果对诊断很有用。单独的校验步骤以成功为门槛:它只在捕获成功时才在上传前运行。如果捕获失败,always() 上传仍会发布部分 PNG,而不会重新校验它们。请从工作流运行的 Artifacts 部分下载 app-store-connect-screenshots 和 google-play-screenshots。工件保留 14 天。

该工作流使用与本地捕获相同的已入库设备和场景矩阵。Android 在本地 Apple Silicon 开发中默认仍为 ARM64;CI 设置 T3_SHOWCASE_ANDROID_ABI=x86_64,以便调试 APK 与其加速模拟器匹配。

快速迭代

捕获单个场景或设备:

pnpm screenshots:mobile --device iphone-duo-closed --device iphone-duo-open
pnpm screenshots:mobile --device iphone-6.9 --scene thread
pnpm screenshots:mobile --platform android --scene review

覆盖已配置的外观或同时捕获两种变体:

pnpm screenshots:mobile --appearance light
pnpm screenshots:mobile --appearance dark
pnpm screenshots:mobile --appearance both

捕获其他调色板:

pnpm screenshots:mobile --device iphone-6.9 --theme ocean
pnpm screenshots:mobile --device iphone-6.9 --theme ocean --theme ember
pnpm screenshots:mobile --device iphone-6.9 --theme all

复用原生构建并保留一次性环境:

pnpm screenshots:mobile --device ipad-13 --skip-build --keep-running

默认情况下,让截图运行器在端口 8199 上启动 Metro。若要在单独的终端中运行 Metro,请使用相同的展示环境和显式测试框架端口启动它:

cd apps/mobile
APP_VARIANT=development EXPO_PUBLIC_SHOWCASE=1 pnpm exec expo start --dev-client --port 8199

然后从仓库根目录运行捕获:

pnpm screenshots:mobile --skip-build --skip-metro --device iphone-6.9

pnpm --filter @t3tools/mobile showcase 会在其正常端口上启动 Expo,因此它与测试框架的 --skip-metro 模式不兼容。

列出矩阵和标志:

pnpm screenshots:mobile --list

在不禁用 Metro、服务器、模拟器或仿真器的情况下校验现有文件:

pnpm screenshots:mobile --validate-only
pnpm screenshots:mobile --platform ios --validate-only

自定义预置环境

固定数据的时间戳是相对于捕获启动时生成的,因此每个路由都会显示稳定的相对标签,同时服务器仍能收到有效的当前数据。同一组确定性的三环境组合服务于 iPhone、iPad、Android 手机和 Android 平板的捕获;响应式差异完全来自生产应用布局。

待处理(Pending)行使用生产环境离线发件箱,并指向真实的 T3 Code 和 React fixture 项目。与当前正在编辑的任务一样,Showcase 协调逻辑会将这两个条目保留在发件箱中以供捕获;这样,重新连接预置环境也无法在截图拍摄之前投递并移除它们。

Environments 截图将三个本地 fixture 传输通道分别呈现为 Tailscale HTTPS 主机名、Helsinki VPS 主机名和 Tailnet IPv4 地址。这种仅用于显示的替换让卡片保持远程优先(remote-first),同时测试装置(harness)仍与其临时服务器保持可靠的回环连接。

本地前置要求

  • iOS:Xcode 命令行工具、已配置的模拟器运行时,以及已安装的 CocoaPods。
  • Android:SDK 解析会依次检查 ANDROID_HOME、ANDROID_SDK_ROOT,然后默认使用 macOS 上的 $HOME/Library/Android/sdk 或其他平台上的 $HOME/Android/Sdk。解析出的 SDK 必须提供 adb 和 emulator,并且配置的 AVD 必须存在。

测试装置是上传尺寸的事实来源(source of truth);请勿调整其输出。如果商店规则发生变化,请更新目标的 storeAsset 规范。当 PNG 尺寸不正确、包含 alpha 通道、不是 8 位 RGB、超过配置的文件大小上限、违反 Google Play 的 9:16 形状/边界,或导致完整输出集低于商店最低要求时,捕获将失败。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 t3/t3code