diff --git a/Source/ARTRealtimeChannel.m b/Source/ARTRealtimeChannel.m index ec5912dbf..e64e43869 100644 --- a/Source/ARTRealtimeChannel.m +++ b/Source/ARTRealtimeChannel.m @@ -405,7 +405,7 @@ - (void)onMessage:(ARTProtocolMessage *)message { ARTDataEncoder *dataEncoder = self.dataEncoder; for (ARTMessage *m in message.messages) { ARTMessage *msg = m; - if (dataEncoder) { + if (msg.data && dataEncoder) { NSError *error = nil; msg = [msg decodeWithEncoder:dataEncoder error:&error]; if (error != nil) { @@ -434,7 +434,7 @@ - (void)onPresence:(ARTProtocolMessage *)message { ARTDataEncoder *dataEncoder = self.dataEncoder; for (ARTPresenceMessage *p in message.presence) { ARTPresenceMessage *presence = p; - if (dataEncoder) { + if (presence.data && dataEncoder) { NSError *error = nil; presence = [p decodeWithEncoder:dataEncoder error:&error]; if (error != nil) { diff --git a/Spec/RealtimeClientPresence.swift b/Spec/RealtimeClientPresence.swift index fa9222100..17df6341d 100644 --- a/Spec/RealtimeClientPresence.swift +++ b/Spec/RealtimeClientPresence.swift @@ -2038,6 +2038,61 @@ class RealtimeClientPresence: QuickSpec { expect(transport.protocolMessagesReceived.filter({ $0.action == .Sync })).to(haveCount(3)) } + // RTP14 + context("enterClient") { + + // RTP14a, RTP14b, RTP14c, RTP14d + it("enters into presence on a channel on behalf of another clientId") { + let client = ARTRealtime(options: AblyTests.commonAppSetup()) + defer { client.close() } + let channel = client.channels.get("test") + expect(channel.presenceMap.members).to(haveCount(0)) + + let expectedData = ["test":1] + + var encodeNumberOfCalls = 0 + let hookEncode = channel.dataEncoder.testSuite_injectIntoMethodAfter(#selector(ARTDataEncoder.encode(_:))) { + encodeNumberOfCalls += 1 + } + defer { hookEncode.remove() } + + var decodeNumberOfCalls = 0 + let hookDecode = channel.dataEncoder.testSuite_injectIntoMethodAfter(#selector(ARTDataEncoder.decode(_:encoding:))) { + decodeNumberOfCalls += 1 + } + defer { hookDecode.remove() } + + + waitUntil(timeout: testTimeout) { done in + channel.presence.enterClient("test", data: expectedData) { error in + expect(error).to(beNil()) + done() + } + } + + channel.presence.enterClient("john", data: nil) + channel.presence.enterClient("sara", data: nil) + expect(channel.presenceMap.members).toEventually(haveCount(3), timeout: testTimeout) + + waitUntil(timeout: testTimeout) { done in + channel.presence.get() { members, error in + guard let members = members?.reduce([String:ARTPresenceMessage](), combine: { (dictionary, item) in + return dictionary + [item.clientId ?? "":item] + }) else { fail("No members"); done(); return } + + expect(members["test"]!.data as? NSDictionary).to(equal(expectedData)) + expect(members["john"]).toNot(beNil()) + expect(members["sara"]).toNot(beNil()) + done() + } + } + + expect(encodeNumberOfCalls).to(equal(1)) + expect(decodeNumberOfCalls).to(equal(1)) + } + + } + } } } diff --git a/Spec/TestUtilities.swift b/Spec/TestUtilities.swift index 9da1b3a2f..bd04ed263 100644 --- a/Spec/TestUtilities.swift +++ b/Spec/TestUtilities.swift @@ -670,6 +670,22 @@ extension SequenceType where Generator.Element: NSData { } +func + (left: Dictionary, right: Dictionary?) -> Dictionary { + guard let right = right else { return left } + return left.reduce(right) { + var new = $0 as [K:V] + new.updateValue($1.1, forKey: $1.0) + return new + } +} + +func += (inout left: Dictionary, right: Dictionary?) { + guard let right = right else { return } + right.forEach { key, value in + left.updateValue(value, forKey: key) + } +} + extension ARTMessage { public override func isEqual(object: AnyObject?) -> Bool {