移动应用商店截图测试工具¶
面向维护者。正在使用 T3 Code?请参阅 docs/user。
该截图测试工具会针对三个一次性的本地 T3 环境运行真实的移动应用。它为每个环境创建隔离的基目录和服务器、内容确定性的真实 Git 项目、预置的编排投影,以及持久化的终端历史。应用通过其正常连接流程与每台服务器配对,React Navigation 会打开生产环境的 Home、Thread、ThreadTerminal、ThreadReview 和 SettingsEnvironments 路由。
没有任何截图专用的屏幕会重新创建应用 UI。EXPO_PUBLIC_SHOWCASE=1 只会启用不参与渲染的配对/就绪协调器,禁用终端自动聚焦,以便截图不包含软键盘,并向真实的 Environments 屏幕提供确定性的 T3 Connect 发现行。本地环境卡片始终来自真实配对的服务器。
捕获默认矩阵¶
在仓库根目录下:
pnpm screenshots:mobile
该命令:
- 创建三个临时 T3 基目录,并在可用端口上为每个目录启动一个本地服务器。
- 创建 T3 Code、React 和 Linux Git 仓库,包含可识别的 favicon、功能分支,以及确定性的 T3 Code 审查 diff。
- 在每台服务器已迁移的 SQLite 数据库中预置趣味性的线程、消息、活动和终端历史,然后添加两个等待发送的持久化移动端发件箱任务。
- 启动隔离的 Metro 服务器,构建所选原生应用,并启动每台设备。
- 将每个干净安装的应用与 Moonbase Terminal、Suspense Station 和 Kernel Cabin 配对。
- 为每个请求的场景导航到真实应用路由。
- 设置请求的系统外观和调色板,标准化状态栏,将截图转换为无 alpha 的 24 位 RGB PNG,并在成功前验证尺寸、宽高比、文件大小和截图数量。
- 在
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
自定义预置环境¶
- 项目仓库、线程投射、对话、终端记录和 Git 更改: mobile-showcase-environment.ts
- 设备和捕获矩阵: mobile-showcase.config.ts
- 模拟器/仿真器编排: mobile-showcase.ts
固定数据的时间戳是相对于捕获启动时生成的,因此每个路由都会显示稳定的相对标签,同时服务器仍能收到有效的当前数据。同一组确定性的三环境组合服务于 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