Skip to content

Commit b7fdae8

Browse files
authored
test(realtime): add tests for optional refs handling in message serialization (#868)
Add comprehensive tests for nil ref scenarios to verify and document that optional ref and joinRef fields are properly handled in JSON encoding/decoding. The Swift SDK already has the correct implementation with optional types, but these tests prevent regressions and ensure SDK parity with other language implementations. - Added tests for messages with nil refs - Added tests for heartbeat messages with nil joinRef - Added tests for JSON encoding/decoding with nil values - Added documentation comments to RealtimeMessageV2 struct Closes SDK-532
1 parent 2777bdf commit b7fdae8

File tree

2 files changed

+82
-0
lines changed

2 files changed

+82
-0
lines changed

Sources/Realtime/RealtimeMessageV2.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
import Foundation
22

3+
/// A message sent over the Realtime WebSocket connection.
4+
///
5+
/// Both `joinRef` and `ref` are optional because certain messages like heartbeats
6+
/// don't require a join reference as they don't refer to a specific channel.
37
public struct RealtimeMessageV2: Hashable, Codable, Sendable {
8+
/// Optional join reference. Nil for messages like heartbeats that don't belong to a specific channel.
49
public let joinRef: String?
10+
/// Optional message reference. Can be nil for certain message types.
511
public let ref: String?
612
public let topic: String
713
public let event: String

Tests/RealtimeTests/RealtimeMessageV2Tests.swift

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,80 @@ final class RealtimeMessageV2Tests: XCTestCase {
7676
joinRef: nil, ref: nil, topic: "topic", event: "unknown_event", payload: payloadWithNoStatus)
7777
XCTAssertNil(unknownEventMessage._eventType)
7878
}
79+
80+
func testMessageWithNilRefs() throws {
81+
let message = RealtimeMessageV2(
82+
joinRef: nil,
83+
ref: nil,
84+
topic: "phoenix",
85+
event: "heartbeat",
86+
payload: [:]
87+
)
88+
// Verify JSON encoding works
89+
let encoded = try JSONEncoder().encode(message)
90+
let decoded = try JSONDecoder().decode(RealtimeMessageV2.self, from: encoded)
91+
XCTAssertNil(decoded.joinRef)
92+
XCTAssertNil(decoded.ref)
93+
XCTAssertEqual(decoded.topic, "phoenix")
94+
XCTAssertEqual(decoded.event, "heartbeat")
95+
}
96+
97+
func testHeartbeatMessageWithNilJoinRef() throws {
98+
let message = RealtimeMessageV2(
99+
joinRef: nil, // Heartbeats don't have joinRef
100+
ref: "123",
101+
topic: "phoenix",
102+
event: "heartbeat",
103+
payload: [:]
104+
)
105+
let encoded = try JSONEncoder().encode(message)
106+
let decoded = try JSONDecoder().decode(RealtimeMessageV2.self, from: encoded)
107+
XCTAssertNil(decoded.joinRef)
108+
XCTAssertEqual(decoded.ref, "123")
109+
}
110+
111+
func testMessageJSONEncodingWithNilRefs() throws {
112+
let message = RealtimeMessageV2(
113+
joinRef: nil,
114+
ref: nil,
115+
topic: "test",
116+
event: "custom",
117+
payload: ["key": "value"]
118+
)
119+
let encoded = try JSONEncoder().encode(message)
120+
let jsonString = String(data: encoded, encoding: .utf8)!
121+
// Verify nil values are encoded as null in JSON
122+
XCTAssertTrue(jsonString.contains("\"join_ref\":null") || !jsonString.contains("join_ref"))
123+
XCTAssertTrue(jsonString.contains("\"ref\":null") || !jsonString.contains("ref"))
124+
}
125+
126+
func testMessageWithBothRefAndJoinRef() throws {
127+
let message = RealtimeMessageV2(
128+
joinRef: "join-456",
129+
ref: "ref-789",
130+
topic: "room:lobby",
131+
event: "join",
132+
payload: ["user_id": "123"]
133+
)
134+
let encoded = try JSONEncoder().encode(message)
135+
let decoded = try JSONDecoder().decode(RealtimeMessageV2.self, from: encoded)
136+
XCTAssertEqual(decoded.joinRef, "join-456")
137+
XCTAssertEqual(decoded.ref, "ref-789")
138+
XCTAssertEqual(decoded.topic, "room:lobby")
139+
}
140+
141+
func testMessageWithRefButNilJoinRef() throws {
142+
let message = RealtimeMessageV2(
143+
joinRef: nil,
144+
ref: "ref-999",
145+
topic: "room:lobby",
146+
event: "leave",
147+
payload: [:]
148+
)
149+
let encoded = try JSONEncoder().encode(message)
150+
let decoded = try JSONDecoder().decode(RealtimeMessageV2.self, from: encoded)
151+
XCTAssertNil(decoded.joinRef)
152+
XCTAssertEqual(decoded.ref, "ref-999")
153+
XCTAssertEqual(decoded.topic, "room:lobby")
154+
}
79155
}

0 commit comments

Comments
 (0)