Files
openclaw/apps/ios/Tests/IOSGatewayChatTransportTests.swift
Colin Johnson f6e51ff99a feat(ios): refresh pro UI and gateway flows (#87367)
Summary:
- Replace the legacy iOS shell with Pro Command, Chat, Agents, and Settings tabs.
- Wire iOS chat/session/settings/diagnostics and realtime Talk flows through gateway-backed APIs.
- Add gateway/session and shared chat coverage for the new iOS flow.

Verification:
- git diff --check
- node scripts/run-vitest.mjs src/gateway/server.sessions.create.test.ts src/gateway/talk-realtime-relay.test.ts
- swift test --filter ChatViewModelTests (apps/shared/OpenClawKit)
- xcodebuild build for Nimrod's iPhone succeeded; install succeeded; launch was blocked because the phone was locked

Known follow-up:
- Preserve traceLevel in sessions.create parent runtime inheritance and keep the changelog credit in the follow-up patch.
2026-05-28 17:23:26 +03:00

89 lines
3.8 KiB
Swift

import Foundation
import OpenClawKit
import Testing
@testable import OpenClaw
@Suite struct IOSGatewayChatTransportTests {
private func object(from json: String) throws -> [String: Any] {
let data = try #require(json.data(using: .utf8))
let value = try JSONSerialization.jsonObject(with: data)
return try #require(value as? [String: Any])
}
@Test func agentWaitTreatsSuccessAsCompletion() {
#expect(IOSGatewayChatTransport.isAgentWaitCompletionStatus("success"))
#expect(IOSGatewayChatTransport.isAgentWaitCompletionStatus(" ok "))
#expect(IOSGatewayChatTransport.isAgentWaitCompletionStatus("completed"))
#expect(IOSGatewayChatTransport.isAgentWaitCompletionStatus("succeeded"))
#expect(!IOSGatewayChatTransport.isAgentWaitCompletionStatus("timeout"))
#expect(!IOSGatewayChatTransport.isAgentWaitCompletionStatus("failed"))
}
@Test func agentWaitTimeoutAddsGatewayMargin() {
#expect(IOSGatewayChatTransport.agentWaitRequestTimeoutSeconds(timeoutMs: 1) == 6)
#expect(IOSGatewayChatTransport.agentWaitRequestTimeoutSeconds(timeoutMs: 1000) == 6)
#expect(IOSGatewayChatTransport.agentWaitRequestTimeoutSeconds(timeoutMs: 30000) == 35)
}
@Test func agentWaitCompletionDecodesFallbackRunId() throws {
let data = Data(#"{"status":"completed"}"#.utf8)
let completion = try IOSGatewayChatTransport.decodeAgentWaitCompletion(data, fallbackRunId: "run-local")
#expect(completion.runId == "run-local")
#expect(completion.status == "completed")
#expect(completion.completed)
}
@Test func listSessionsParamsIncludeGlobalSessionsButNotUnknown() throws {
let params = try self.object(from: IOSGatewayChatTransport.makeListSessionsParamsJSON(limit: 12))
#expect(params["includeGlobal"] as? Bool == true)
#expect(params["includeUnknown"] as? Bool == false)
#expect(params["limit"] as? Int == 12)
}
@Test func chatSendParamsOmitEmptyAttachmentsAndKeepSessionFields() throws {
let params = try self.object(
from: IOSGatewayChatTransport.makeChatSendParamsJSON(
sessionKey: "agent:main",
message: "hello",
thinking: "low",
idempotencyKey: "send-1",
attachments: []))
#expect(params["sessionKey"] as? String == "agent:main")
#expect(params["message"] as? String == "hello")
#expect(params["thinking"] as? String == "low")
#expect(params["idempotencyKey"] as? String == "send-1")
#expect(params["timeoutMs"] as? Int == IOSGatewayChatTransport.defaultChatSendTimeoutMs)
#expect(params["attachments"] == nil)
}
@Test func requestsFailFastWhenGatewayNotConnected() async {
let gateway = GatewayNodeSession()
let transport = IOSGatewayChatTransport(gateway: gateway)
do {
_ = try await transport.requestHistory(sessionKey: "node-test")
Issue.record("Expected requestHistory to throw when gateway not connected")
} catch {}
do {
_ = try await transport.sendMessage(
sessionKey: "node-test",
message: "hello",
thinking: "low",
idempotencyKey: "idempotency",
attachments: [])
Issue.record("Expected sendMessage to throw when gateway not connected")
} catch {}
do {
_ = try await transport.requestHealth(timeoutMs: 250)
Issue.record("Expected requestHealth to throw when gateway not connected")
} catch {}
do {
try await transport.resetSession(sessionKey: "node-test")
Issue.record("Expected resetSession to throw when gateway not connected")
} catch {}
}
}