Files
web-terminal/ios/Packages/WireProtocol/Tests/WireProtocolTests/TimelineEventTests.swift
Yaojia Wang cbaa08daba feat(ios): W0 scaffold + day-1 spike + WireProtocol frozen contract + TestSupport doubles
T-iOS-1: ios/ XcodeGen project (iOS 17, Swift 6 strict concurrency, ATS per PLAN §5.2), 5 SPM package shells, CI skeleton
T-iOS-2: Origin spike vs real server — URLSessionWebSocketTask custom Origin CONFIRMED (no Starscream); 16MiB replay + EMSGSIZE(40) errno correction written back to plan
T-iOS-3: WireProtocol frozen contract, 59 tests, 100% line coverage, cross-impl vectors vs src/protocol.ts via tsx
T-iOS-4: FakeTransport/FakeClock/FakeHTTPTransport doubles
Verify: independent agent re-ran all acceptance — 6/6 PASS
2026-07-04 21:19:30 +02:00

78 lines
2.6 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Foundation
import Testing
import WireProtocol
// T-iOS-3 · TimelineEventGET /live-sessions/:id/events src/types.ts:428-433
// decodeList throw/ class
@Test("TimelineEvent合法条目全字段解码")
func decodesValidEntryWithAllFields() throws {
// Arrange
let json = Data("{\"at\":1751600000000,\"class\":\"tool\",\"toolName\":\"Bash\",\"label\":\"ran Bash\"}".utf8)
// Act
let event = try JSONDecoder().decode(TimelineEvent.self, from: json)
// Assert
#expect(event == TimelineEvent(at: 1_751_600_000_000, class: "tool", toolName: "Bash", label: "ran Bash"))
#expect(event.hasKnownClass)
}
@Test("TimelineEventtoolName 可选缺省")
func decodesEntryWithoutToolName() throws {
// Arrange
let json = Data("{\"at\":1,\"class\":\"waiting\",\"label\":\"waiting for approval\"}".utf8)
// Act
let event = try JSONDecoder().decode(TimelineEvent.self, from: json)
// Assert
#expect(event.toolName == nil)
#expect(event.hasKnownClass)
}
@Test("knownClasses 与服务器 TimelineClass 全集一致src/types.ts:423")
func knownClassesMirrorServerUnion() {
#expect(TimelineEvent.knownClasses == ["tool", "waiting", "done", "stuck", "user"])
}
@Test("decodeList未知 class 条目被丢弃,合法条目保留(消费方丢弃语义)")
func decodeListDropsUnknownClassEntries() {
// Arrange 1 + 1 class + 1 label + 1
let json = Data("""
[{"at":1,"class":"tool","label":"ran Bash"},
{"at":2,"class":"alien","label":"???"},
{"at":3,"class":"done"},
42]
""".utf8)
// Act
let events = TimelineEvent.decodeList(from: json)
// Assert
#expect(events == [TimelineEvent(at: 1, class: "tool", toolName: nil, label: "ran Bash")])
}
@Test("decodeList5 个已知 class 全部保留")
func decodeListKeepsAllKnownClasses() {
// Arrange
let json = Data("""
[{"at":1,"class":"tool","label":"a"},{"at":2,"class":"waiting","label":"b"},
{"at":3,"class":"done","label":"c"},{"at":4,"class":"stuck","label":"d"},
{"at":5,"class":"user","label":"e"}]
""".utf8)
// Act
let events = TimelineEvent.decodeList(from: json)
// Assert
#expect(events.count == 5)
#expect(events.allSatisfy { $0.hasKnownClass })
}
@Test("decodeList坏 JSON / 顶层非数组 → 空数组,永不 throw",
arguments: ["not json", "{\"at\":1}", "42", ""])
func decodeListNeverThrowsOnMalformedInput(text: String) {
#expect(TimelineEvent.decodeList(from: Data(text.utf8)) == [])
}