Skip to content

Commit 458585a

Browse files
committed
Add reaction tests.
1 parent 02b8d33 commit 458585a

File tree

3 files changed

+70
-17
lines changed

3 files changed

+70
-17
lines changed

Sources/AblyChat/DefaultRoomReactions.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ internal final class DefaultRoomReactions: RoomReactions {
1111
try await implementation.send(params: params)
1212
}
1313

14+
@discardableResult
1415
internal func subscribe(_ callback: @escaping @MainActor (Reaction) -> Void) -> SubscriptionProtocol {
1516
implementation.subscribe(callback)
1617
}

Tests/AblyChatTests/DefaultRoomReactionsTests.swift

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,73 @@ struct DefaultRoomReactionsTests {
2929
#expect(channel.publishedMessages.last?.extras == ["headers": ["someHeadersKey": "someHeadersValue"], "ephemeral": true])
3030
}
3131

32-
// @spec CHA-ER4
32+
// @spec CHA-ER4a
33+
// @spec CHA-ER4b
3334
@Test
34-
func subscribe_returnsSubscription() async throws {
35-
// all setup values here are arbitrary
35+
func subscriptionCanBeRegisteredToReceiveReactionEvents() async throws {
3636
// Given
37-
let channel = MockRealtimeChannel(name: "basketball::$chat")
37+
func generateMessage(serial: String, reactionType: String) -> ARTMessage {
38+
let message = ARTMessage()
39+
message.action = .create // arbitrary
40+
message.serial = serial // arbitrary
41+
message.clientId = "" // arbitrary
42+
message.data = [
43+
"type": reactionType,
44+
]
45+
message.version = "0"
46+
return message
47+
}
3848

39-
// When
49+
let channel = MockRealtimeChannel(
50+
messageToEmitOnSubscribe: generateMessage(serial: "1", reactionType: ":like:")
51+
)
4052
let defaultRoomReactions = DefaultRoomReactions(channel: channel, clientID: "mockClientId", roomID: "basketball", logger: TestLogger())
4153

4254
// When
43-
let subscription: SubscriptionAsyncSequence<Reaction>? = defaultRoomReactions.subscribe()
55+
let subscription = defaultRoomReactions.subscribe { reaction in
56+
// Then
57+
#expect(reaction.type == ":like:")
58+
}
4459

45-
// Then
46-
#expect(subscription != nil)
60+
// CHA-ER4b
61+
subscription.unsubscribe()
62+
63+
// will not be received and expectations above will not fail
64+
channel.simulateIncomingMessage(
65+
generateMessage(serial: "2", reactionType: ":dislike:"),
66+
for: RoomReactionEvents.reaction.rawValue
67+
)
68+
}
69+
70+
// CHA-ER4c is currently untestable due to not subscribing to those events on lower level
71+
// @spec CHA-ER4d
72+
@Test
73+
func malformedRealtimeEventsShallNotBeEmittedToSubscribers() async throws {
74+
// Given
75+
let channel = MockRealtimeChannel(
76+
messageToEmitOnSubscribe: {
77+
let message = ARTMessage()
78+
message.action = .create // arbitrary
79+
message.serial = "123" // arbitrary
80+
message.clientId = "" // arbitrary
81+
message.data = [
82+
"type": ":like:",
83+
]
84+
message.extras = [:] as any ARTJsonCompatible
85+
message.version = "0"
86+
return message
87+
}()
88+
)
89+
let defaultRoomReactions = DefaultRoomReactions(channel: channel, clientID: "mockClientId", roomID: "basketball", logger: TestLogger())
90+
91+
// When
92+
defaultRoomReactions.subscribe { reaction in
93+
#expect(reaction.type == ":like:")
94+
}
95+
// will not be received and expectations above will not fail
96+
channel.simulateIncomingMessage(
97+
ARTMessage(), // malformed message
98+
for: RealtimeMessageName.chatMessage.rawValue
99+
)
47100
}
48101
}

Tests/AblyChatTests/Helpers/Helpers.swift

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -150,17 +150,16 @@ class MockMethodCallRecorder: @unchecked Sendable {
150150
}
151151

152152
func hasRecord(matching signature: String, arguments: [String: Any]) -> Bool {
153-
mutex.lock()
154-
let result = records.contains { record in
155-
guard record.signature == signature else {
156-
return false
153+
mutex.withLock {
154+
records.contains { record in
155+
guard record.signature == signature else {
156+
return false
157+
}
158+
let args1 = record.arguments.sorted()
159+
let args2 = arguments.map { MethodArgument(name: $0.key, value: $0.value) }.sorted()
160+
return args1 == args2
157161
}
158-
let args1 = record.arguments.sorted()
159-
let args2 = arguments.map { MethodArgument(name: $0.key, value: $0.value) }.sorted()
160-
return args1 == args2
161162
}
162-
mutex.unlock()
163-
return result
164163
}
165164
}
166165

0 commit comments

Comments
 (0)