iOS E2E
從 checkout 根目錄開始工作。本地的 .mobilebuildmcp/config.yaml(設定)提供了專案、scheme 和 DerivedData,因此 mobilebuildmcp 指令不需要專案旗標。
兩個會重複出現的值:
$sim:模擬器 UDID(pnpm ios:sim:pair會印出一個)。將--simulator-id "$sim"傳遞給每個mobilebuildmcp呼叫;若不提供,則設定檔預設會鎖定名為iPhone 17的模擬器。$bundle:Bundle ID,取決於簽署的團隊。從建置中讀取:bundle=$(/usr/libexec/PlistBuddy -c 'Print :CFBundleIdentifier' apps/ios/build/DerivedData/Build/Products/Debug-iphonesimulator/OpenClaw.app/Info.plist)。
建置與執行
-
建置:
mobilebuildmcp simulator build。編輯apps/ios/project.yml後,先執行pnpm ios:gen。 -
使用
simctl安裝並啟動,可傳遞啟動參數(pnpm ios:run不接受參數):xcrun simctl install "$sim" apps/ios/build/DerivedData/Build/Products/Debug-iphonesimulator/OpenClaw.app xcrun simctl launch --terminate-running-process "$sim" "$bundle" --openclaw-reset-onboardingmobilebuildmcp simulator build-and-run和launch-app會附加一個永不退出的日誌擷取功能。 -
偵錯啟動參數:
grep -rhoE '"--openclaw-[a-z-]+"' apps/ios/Sources | sort -u。--openclaw-screenshot-mode加上--openclaw-*-fixture旗標可以在沒有 Gateway 的情況下顯示一個固定畫面;-AppleLanguages "(de)" -AppleLocale de_DE可以切換語言。除錯 URL scheme 為openclaw-debug://。
驅動 UI
mobilebuildmcp ui-automation snapshot-ui --style minimal會以ref|action|role|label|value|id的格式列出可點擊的目標。非控制項的文字(聊天氣泡、列標題)只會在加上--output json時出現。- 對某個 ref 執行操作,可使用
tap、type-text、long-press(--duration單位為毫秒)、swipe或gesture。使用wait-for-ui進行等待:對元素使用--predicate exists --label '…' --role button,對文字使用--predicate textContains --text '…'。一個符合多個元素的等待選擇器會失敗;請加上--role或--identifier。保持--timeout-ms低於 30000:daemon 會在 30 秒後以DAEMON_TRANSPORT_FAILED` 終止任何請求;若要等待更長時間,請重複執行等待。 - Refs 屬於單一快照;每次畫面變更後都要重新拍攝快照。
- 查看畫面:
mobilebuildmcp simulator screenshot,然後讀取印出的 JPEG。
注意事項:
- 引導畫面 (Onboarding) 和 sheet 也會列出背後的畫面;請透過 label 或 id 進行比對,並選取最後一個符合的項目。
- 在 iPhone 上,側邊欄會覆蓋內容:在其行項目之前,先點選
RootTabs.Sidebar.Show。 xcrun simctl openurl每次呼叫都會將一個系統的「在 OpenClaw 中打開?」警示加入佇列;請為每個警示點選「打開」或「取消」。- 應用程式行程之外的系统 UI(照片挑選器、分享 sheet)不會出現在快照中。請使用 MobileBuildMCP 內含的 AXe 二進位檔,透過座標來點擊:
"$(brew --prefix mobilebuildmcp)/libexec/bundled/axe" tap -x <x> -y <y> --udid "$sim"。座標是點數:螢幕截圖畫素 × 螢幕寬度(點數)÷ 螢幕截圖寬度。
日誌與崩潰
先執行操作,再讀取一個有界的時間視窗:
xcrun simctl spawn "$sim" log show --last 2m --style compact --predicate 'subsystem BEGINSWITH "ai.openclaw"'
崩潰報告會存放在 ~/Library/Logs/DiagnosticReports/OpenClaw-*.ips;triggered 執行緒的第一個 OpenClaw 框架指出了問題來源。應用程式偏好設定和資料庫位於應用程式容器中(xcrun simctl get_app_container "$sim" "$bundle" data);simctl spawn … defaults read 無法讀取它們。LLDB 和 xctrace:請參閱 DEBUG.md。
測試
- 執行受影響的測試套件:
pnpm ios:test <Suite>(選擇器和IOS_SIM:請參閱apps/ios/README.md)。 - 證明新的回歸測試在基底版本上是紅燈:提交變更,將已變更的原始檔切換回基底版本(
git checkout <base> -- <paths>),執行測試套件,然後git checkout HEAD -- <paths>。
**完成條件:**受影響的測試套件通過,且每個新的回歸測試在基底版本上失敗。
端到端證明變更
- 以長時間執行的服務啟動隔離的 Gateway(設定中的一次性設定檔):
node scripts/run-node.mjs --profile ios-sim gateway --bind loopback。它永遠不會接觸到操作者的 Gateway 或~/.openclaw。當它執行時,使用node openclaw.mjs --profile ios-sim …來呼叫 CLI;run-node在 Gateway 執行中時會拒絕重建。 - 透過真實的引導 UI 配對一個全新的模擬器:
sim=$(pnpm --silent ios:sim:pair | tail -1)(使用--app指定另一個建置,使用--profile指定另一個設定檔)。 - 透過可見的控制項來驗證變更。一個聊天往返流程:在
chat-message-input中輸入文字,點選chat-send-message,然後等待回覆中出現的唯一詞彙。 - 比較建置:在
main分支和變更分支上執行相同的步驟,各自使用一個全新的模擬器,並搭配相符的螢幕截圖。 - 停止 Gateway 並刪除模擬器。
Node 指令、權限、認證失敗、服務中斷、拒絕發送、升級和 iPad 佈局:請參閱 PROOF.md,其中也列出了只有實體裝置才能證明的事項。
**完成條件:**螢幕截圖或錄製的輸出顯示變更後的行為,而在 main 分支上則沒有該行為;Gateway 連接埠已關閉,且沒有殘留的 openclaw-pair-* 模擬器。
設定
每台機器只需設定一次;每個步驟結束時需進行檢查。
-
Xcode、模擬器執行環境、
xcodegen和 Watch Rust 工具鏈:請參閱apps/ios/README.md的先決條件。檢查:xcrun simctl list devices available顯示了iPhone 17。 -
在版本庫指定的版本安裝 SwiftFormat 和 SwiftLint:
scripts/install-swift-tools.sh <dir on PATH>。檢查:scripts/check-swift-tools.sh退出碼為 0。 -
MobileBuildMCP、Sentry 的 XcodeBuildMCP CLI:
brew tap getsentry/xcodebuildmcp && brew install getsentry/xcodebuildmcp/mobilebuildmcp。這些步驟是針對 2.7.1 版本編寫的。檢查:mobilebuildmcp --version。 -
Checkout:
pnpm install --frozen-lockfile,然後執行pnpm ios:gen(Xcode 專案是產生的,不會提交)。然後建立.mobilebuildmcp/config.yaml,並將/.mobilebuildmcp/加入.git/info/exclude:schemaVersion: 1 enabledWorkflows: [simulator, simulator-management, ui-automation, debugging] sentryDisabled: true sessionDefaults: projectPath: ./apps/ios/OpenClaw.xcodeproj scheme: OpenClaw configuration: Debug platform: iOS simulatorName: iPhone 17 derivedDataPath: ./apps/ios/build/DerivedData # 與 pnpm ios:run 共用檢查:
mobilebuildmcp simulator list-schemes列出OpenClaw,且mobilebuildmcp simulator build成功。 -
ios-simGateway 設定檔,Gateway 需為停止狀態(oc=node openclaw.mjs --profile ios-sim):oc config set gateway.mode local、oc config set gateway.port 19031、oc config set gateway.auth.mode token、oc config set gateway.auth.token "$(openssl rand -hex 24)"。聊天回覆需要為其mainagent 提供一個模型:oc models auth login或使用測試憑證add。檢查:Gateway 成功啟動,且pnpm ios:sim:pair在聊天畫面結束。