feat(ios): W4 app wiring — DI graph, event fan-out, lifecycle, privacy shade
T-iOS-15: AppEnvironment production DI (real Keychain/probe/transports), EventFanOut (engine.events → TerminalVM + GateVM + activity bridge), scenePhase lifecycle (.background→close, suspend→rebuild+reopen reclaims size), privacy shade on != .active, spike screen deleted, cold-start routing Walkthrough proxies: hosted live-server smoke over the production DI graph (probe→store→ attach→echo→close) + real-Keychain kSecAttrAccessible assertion (closes T-iOS-7 deferral) Deviation closed: TerminalViewModel.lastSentDims (valid-only) + alive-engine .active → notifyForegrounded(dims:) (orchestrator fix on behalf of T-iOS-11 owner) Env finding: repo under ~/Documents → TCC blocks sim-spawned node; SimServerHarness dual-mode (self-bootstrap / WEBTERM_SERVER_URL via simctl launchctl setenv) Verified: 214 pkg + 76 app + 10 integration tests green; verify agent 8/8 PASS
This commit is contained in:
65
ios/App/WebTermTests/ColdStartPolicyTests.swift
Normal file
65
ios/App/WebTermTests/ColdStartPolicyTests.swift
Normal file
@@ -0,0 +1,65 @@
|
||||
import Foundation
|
||||
import HostRegistry
|
||||
import Testing
|
||||
import WireProtocol
|
||||
@testable import WebTerm
|
||||
|
||||
/// T-iOS-15 · Cold-start selection logic (pure): which root screen boots, and
|
||||
/// whether the session list should highlight "继续上次" for the active host.
|
||||
@MainActor
|
||||
@Suite("ColdStartPolicy")
|
||||
struct ColdStartPolicyTests {
|
||||
private final class StubLastSessionStore: LastSessionStore, @unchecked Sendable {
|
||||
private let stored: [UUID: UUID]
|
||||
init(stored: [UUID: UUID] = [:]) { self.stored = stored }
|
||||
func lastSessionId(host: UUID) -> UUID? { stored[host] }
|
||||
func setLastSessionId(_ id: UUID?, host: UUID) {}
|
||||
}
|
||||
|
||||
private static func makeHost(name: String = "mac") throws -> HostRegistry.Host {
|
||||
let url = try #require(URL(string: "http://192.168.1.5:3000"))
|
||||
let endpoint = try #require(HostEndpoint(baseURL: url))
|
||||
return HostRegistry.Host(id: UUID(), name: name, endpoint: endpoint)
|
||||
}
|
||||
|
||||
// MARK: - Root route: no paired host → Pairing; else SessionList
|
||||
|
||||
@Test("无配对 host → 冷启动进 Pairing")
|
||||
func noHostsBootsIntoPairing() {
|
||||
#expect(ColdStartPolicy.initialRoute(pairedHostCount: 0) == .pairing)
|
||||
}
|
||||
|
||||
@Test("有配对 host → 冷启动进 SessionList")
|
||||
func pairedHostsBootIntoSessionList() {
|
||||
#expect(ColdStartPolicy.initialRoute(pairedHostCount: 1) == .sessions)
|
||||
#expect(ColdStartPolicy.initialRoute(pairedHostCount: 3) == .sessions)
|
||||
}
|
||||
|
||||
// MARK: - "继续上次" highlight
|
||||
|
||||
@Test("active host 存有 lastSessionId → 给出继续上次目标")
|
||||
func continueLastReturnsStoredSession() throws {
|
||||
let host = try Self.makeHost()
|
||||
let sessionId = UUID()
|
||||
let store = StubLastSessionStore(stored: [host.id: sessionId])
|
||||
|
||||
let target = ColdStartPolicy.continueLastSessionId(activeHost: host, store: store)
|
||||
|
||||
#expect(target == sessionId)
|
||||
}
|
||||
|
||||
@Test("该 host 无记录 → 无继续上次高亮")
|
||||
func continueLastNilWithoutRecord() throws {
|
||||
let host = try Self.makeHost()
|
||||
let other = UUID()
|
||||
let store = StubLastSessionStore(stored: [other: UUID()])
|
||||
|
||||
#expect(ColdStartPolicy.continueLastSessionId(activeHost: host, store: store) == nil)
|
||||
}
|
||||
|
||||
@Test("尚无 active host(hosts 未加载/为空)→ 无高亮")
|
||||
func continueLastNilWithoutActiveHost() {
|
||||
let store = StubLastSessionStore()
|
||||
#expect(ColdStartPolicy.continueLastSessionId(activeHost: nil, store: store) == nil)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user