diff --git a/Docs/XXMessengerClient.md b/Docs/XXMessengerClient.md index c8fc3e7dd8b6ba45738f1e0914fa758f6b5a0d28..05afa4aaa33cb74d114d0548faf8c157e00678ce 100644 --- a/Docs/XXMessengerClient.md +++ b/Docs/XXMessengerClient.md @@ -27,8 +27,9 @@ let messenger: Messenger = .live(environment) Example: ```swift -// allow cancellation of auth callbacks registration: +// allow cancellation of callbacks: var authCallbacksCancellable: Cancellable? +var messageListenerCancellable: Cancellable? func start(messenger: Messenger) throws { // check if messenger is loaded: @@ -51,11 +52,20 @@ func start(messenger: Messenger) throws { // implement auth callbacks handling }) ) + + // register message listener before connecting: + messageListenerCancellable = messenger.registerMessageListener( + Listener(handle: { message in + // handle incoming message + }) + ) // check if messenger is connected: if messenger.isConnected() == false { // start end-to-end connection: try messenger.connect() + // start listening for messanges: + try messener.listenForMessages() } // check if messenger is logged in with user-discovery: diff --git a/Sources/XXMessengerClient/Messenger/Functions/MessengerListenForMessages.swift b/Sources/XXMessengerClient/Messenger/Functions/MessengerListenForMessages.swift new file mode 100644 index 0000000000000000000000000000000000000000..90fa02dab3cf84d85e50e3d696fe0a5a226d4884 --- /dev/null +++ b/Sources/XXMessengerClient/Messenger/Functions/MessengerListenForMessages.swift @@ -0,0 +1,35 @@ +import XCTestDynamicOverlay +import XXClient + +public struct MessengerListenForMessages { + public enum Error: Swift.Error { + case notConnected + } + + public var run: () throws -> Void + + public func callAsFunction() throws -> Void { + try run() + } +} + +extension MessengerListenForMessages { + public static func live(_ env: MessengerEnvironment) -> MessengerListenForMessages { + MessengerListenForMessages { + guard let e2e = env.e2e() else { + throw Error.notConnected + } + try e2e.registerListener( + senderId: nil, + messageType: 2, + callback: env.messageListeners.registered() + ) + } + } +} + +extension MessengerListenForMessages { + public static let unimplemented = MessengerListenForMessages( + run: XCTUnimplemented("\(Self.self)") + ) +} diff --git a/Sources/XXMessengerClient/Messenger/Functions/MessengerRegisterMessageListener.swift b/Sources/XXMessengerClient/Messenger/Functions/MessengerRegisterMessageListener.swift new file mode 100644 index 0000000000000000000000000000000000000000..666e26345e03b3be620959a37333bba566d991ad --- /dev/null +++ b/Sources/XXMessengerClient/Messenger/Functions/MessengerRegisterMessageListener.swift @@ -0,0 +1,24 @@ +import XCTestDynamicOverlay +import XXClient + +public struct MessengerRegisterMessageListener { + public var run: (Listener) -> Cancellable + + public func callAsFunction(_ listener: Listener) -> Cancellable { + run(listener) + } +} + +extension MessengerRegisterMessageListener { + public static func live(_ env: MessengerEnvironment) -> MessengerRegisterMessageListener { + MessengerRegisterMessageListener { listener in + env.messageListeners.register(listener) + } + } +} + +extension MessengerRegisterMessageListener { + public static let unimplemented = MessengerRegisterMessageListener( + run: XCTUnimplemented("\(Self.self)", placeholder: Cancellable {}) + ) +} diff --git a/Sources/XXMessengerClient/Messenger/Functions/MessengerSendMessage.swift b/Sources/XXMessengerClient/Messenger/Functions/MessengerSendMessage.swift new file mode 100644 index 0000000000000000000000000000000000000000..118ca046b341bd4699be6e0066c327243c9ffb37 --- /dev/null +++ b/Sources/XXMessengerClient/Messenger/Functions/MessengerSendMessage.swift @@ -0,0 +1,85 @@ +import Foundation +import XCTestDynamicOverlay +import XXClient + +public struct MessengerSendMessage { + public struct DeliveryReport: Equatable { + public enum Result: Equatable { + case delivered + case notDelivered(timedOut: Bool) + case failure(NSError) + } + + public init( + report: E2ESendReport, + result: Result + ) { + self.report = report + self.result = result + } + + public var report: E2ESendReport + public var result: Result + } + + public typealias DeliveryCallback = (DeliveryReport) -> Void + + public enum Error: Swift.Error, Equatable { + case notLoaded + case notConnected + } + + public var run: (Data, Data, DeliveryCallback?) throws -> E2ESendReport + + public func callAsFunction( + recipientId: Data, + payload: Data, + deliveryCallback: DeliveryCallback? + ) throws -> E2ESendReport { + try run(recipientId, payload, deliveryCallback) + } +} + +extension MessengerSendMessage { + public static func live(_ env: MessengerEnvironment) -> MessengerSendMessage { + MessengerSendMessage { recipientId, payload, deliveryCallback in + guard let cMix = env.cMix() else { + throw Error.notLoaded + } + guard let e2e = env.e2e() else { + throw Error.notConnected + } + let report = try e2e.send( + messageType: 2, + recipientId: recipientId, + payload: payload, + e2eParams: env.getE2EParams() + ) + if let deliveryCallback = deliveryCallback { + do { + try cMix.waitForRoundResult( + roundList: try report.encode(), + timeoutMS: 30_000, + callback: .init { result in + switch result { + case .delivered(_): + deliveryCallback(.init(report: report, result: .delivered)) + case .notDelivered(let timedOut): + deliveryCallback(.init(report: report, result: .notDelivered(timedOut: timedOut))) + } + } + ) + } catch { + deliveryCallback(.init(report: report, result: .failure(error as NSError))) + } + } + return report + } + } +} + +extension MessengerSendMessage { + public static let unimplemented = MessengerSendMessage( + run: XCTUnimplemented("\(Self.self)") + ) +} diff --git a/Sources/XXMessengerClient/Messenger/Messenger.swift b/Sources/XXMessengerClient/Messenger/Messenger.swift index e2d31f69350c83022d18d8b5dd3698eddff59255..4995f9a14c02e1b1b0c5fe8181d02cb0f689704c 100644 --- a/Sources/XXMessengerClient/Messenger/Messenger.swift +++ b/Sources/XXMessengerClient/Messenger/Messenger.swift @@ -9,9 +9,11 @@ public struct Messenger { public var isLoaded: MessengerIsLoaded public var load: MessengerLoad public var registerAuthCallbacks: MessengerRegisterAuthCallbacks + public var registerMessageListener: MessengerRegisterMessageListener public var start: MessengerStart public var isConnected: MessengerIsConnected public var connect: MessengerConnect + public var listenForMessages: MessengerListenForMessages public var isRegistered: MessengerIsRegistered public var register: MessengerRegister public var isLoggedIn: MessengerIsLoggedIn @@ -22,6 +24,7 @@ public struct Messenger { public var searchUsers: MessengerSearchUsers public var registerForNotifications: MessengerRegisterForNotifications public var verifyContact: MessengerVerifyContact + public var sendMessage: MessengerSendMessage } extension Messenger { @@ -35,9 +38,11 @@ extension Messenger { isLoaded: .live(env), load: .live(env), registerAuthCallbacks: .live(env), + registerMessageListener: .live(env), start: .live(env), isConnected: .live(env), connect: .live(env), + listenForMessages: .live(env), isRegistered: .live(env), register: .live(env), isLoggedIn: .live(env), @@ -47,7 +52,8 @@ extension Messenger { destroy: .live(env), searchUsers: .live(env), registerForNotifications: .live(env), - verifyContact: .live(env) + verifyContact: .live(env), + sendMessage: .live(env) ) } } @@ -62,9 +68,11 @@ extension Messenger { isLoaded: .unimplemented, load: .unimplemented, registerAuthCallbacks: .unimplemented, + registerMessageListener: .unimplemented, start: .unimplemented, isConnected: .unimplemented, connect: .unimplemented, + listenForMessages: .unimplemented, isRegistered: .unimplemented, register: .unimplemented, isLoggedIn: .unimplemented, @@ -74,6 +82,7 @@ extension Messenger { destroy: .unimplemented, searchUsers: .unimplemented, registerForNotifications: .unimplemented, - verifyContact: .unimplemented + verifyContact: .unimplemented, + sendMessage: .unimplemented ) } diff --git a/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift b/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift index 9c4837748fa35628fdfd87bdbcc0e746d745f77e..b4ff607ed6238450cdbf05aec918376c833060cb 100644 --- a/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift +++ b/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift @@ -16,6 +16,7 @@ public struct MessengerEnvironment { public var loadCMix: LoadCMix public var login: Login public var lookupUD: LookupUD + public var messageListeners: ListenersRegistry public var ndfEnvironment: NDFEnvironment public var newCMix: NewCMix public var newOrLoadUd: NewOrLoadUd @@ -52,6 +53,7 @@ extension MessengerEnvironment { loadCMix: .live, login: .live, lookupUD: .live, + messageListeners: .live(), ndfEnvironment: .mainnet, newCMix: .live, newOrLoadUd: .live, @@ -83,6 +85,7 @@ extension MessengerEnvironment { loadCMix: .unimplemented, login: .unimplemented, lookupUD: .unimplemented, + messageListeners: .unimplemented, ndfEnvironment: .unimplemented, newCMix: .unimplemented, newOrLoadUd: .unimplemented, diff --git a/Sources/XXMessengerClient/Utils/AuthCallbacksRegistry.swift b/Sources/XXMessengerClient/Utils/AuthCallbacksRegistry.swift index d0c50b8149c77ecd54e208858d895285c6d7408c..1f85ad1763201ce553281ac65ff5b56af03d128e 100644 --- a/Sources/XXMessengerClient/Utils/AuthCallbacksRegistry.swift +++ b/Sources/XXMessengerClient/Utils/AuthCallbacksRegistry.swift @@ -1,6 +1,6 @@ -import XXClient -import XCTestDynamicOverlay import Foundation +import XCTestDynamicOverlay +import XXClient public struct AuthCallbacksRegistry { public var register: (AuthCallbacks) -> Cancellable diff --git a/Sources/XXMessengerClient/Utils/ListenersRegistry.swift b/Sources/XXMessengerClient/Utils/ListenersRegistry.swift new file mode 100644 index 0000000000000000000000000000000000000000..6378e3b00295483ec3cc14607ae0a90d8e7e632d --- /dev/null +++ b/Sources/XXMessengerClient/Utils/ListenersRegistry.swift @@ -0,0 +1,39 @@ +import Foundation +import XCTestDynamicOverlay +import XXClient + +public struct ListenersRegistry { + public var register: (Listener) -> Cancellable + public var registered: () -> Listener +} + +extension ListenersRegistry { + public static func live() -> ListenersRegistry { + class Registry { + var listeners: [UUID: Listener] = [:] + } + let registry = Registry() + return ListenersRegistry( + register: { listener in + let id = UUID() + registry.listeners[id] = listener + return Cancellable { registry.listeners[id] = nil } + }, + registered: { + Listener(name: "listeners-registry") { message in + registry.listeners.values.forEach { $0.handle(message) } + } + } + ) + } +} + +extension ListenersRegistry { + public static let unimplemented = ListenersRegistry( + register: XCTUnimplemented("\(Self.self).register", placeholder: Cancellable {}), + registered: XCTUnimplemented("\(Self.self).registered", placeholder: Listener( + name: "unimplemented", + handle: { _ in } + )) + ) +} diff --git a/Tests/XXMessengerClientTests/Messenger/Functions/MessengerListenForMessagesTests.swift b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerListenForMessagesTests.swift new file mode 100644 index 0000000000000000000000000000000000000000..948ee33e3d668fdb0eff4a4cfad72f82b908c395 --- /dev/null +++ b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerListenForMessagesTests.swift @@ -0,0 +1,69 @@ +import CustomDump +import XCTest +import XXClient +@testable import XXMessengerClient + +final class MessengerListenForMessagesTests: XCTestCase { + func testListen() throws { + struct RegisterListenerParams: Equatable { + var senderId: Data? + var messageType: Int + } + var didRegisterListenerWithParams: [RegisterListenerParams] = [] + var didRegisterListenerWithCallback: [Listener] = [] + var didHandleMessage: [Message] = [] + + var env: MessengerEnvironment = .unimplemented + env.e2e.get = { + var e2e: E2E = .unimplemented + e2e.registerListener.run = { senderId, messageType, callback in + didRegisterListenerWithParams.append(.init(senderId: senderId, messageType: messageType)) + didRegisterListenerWithCallback.append(callback) + } + return e2e + } + env.messageListeners.registered = { + Listener { message in didHandleMessage.append(message) } + } + let listen: MessengerListenForMessages = .live(env) + + try listen() + + XCTAssertNoDifference(didRegisterListenerWithParams, [ + .init(senderId: nil, messageType: 2) + ]) + + let message = Message.stub(123) + didRegisterListenerWithCallback.first?.handle(message) + + XCTAssertNoDifference(didHandleMessage, [message]) + } + + func testListenWhenNotLoggedIn() { + var env: MessengerEnvironment = .unimplemented + env.e2e.get = { nil } + let listen: MessengerListenForMessages = .live(env) + + XCTAssertThrowsError(try listen()) { error in + XCTAssertNoDifference(error as? MessengerListenForMessages.Error, .notConnected) + } + } + + func testListenFailure() { + struct Failure: Error, Equatable {} + let error = Failure() + + var env: MessengerEnvironment = .unimplemented + env.e2e.get = { + var e2e: E2E = .unimplemented + e2e.registerListener.run = { _, _, _ in throw error } + return e2e + } + env.messageListeners.registered = { Listener.unimplemented } + let listen: MessengerListenForMessages = .live(env) + + XCTAssertThrowsError(try listen()) { err in + XCTAssertNoDifference(err as? Failure, error) + } + } +} diff --git a/Tests/XXMessengerClientTests/Messenger/Functions/MessengerRegisterAuthCallbacksTests.swift b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerRegisterAuthCallbacksTests.swift index d7903e2f1b73e03dbe8268561c1ef586bf8a4583..17b1b94dd4e77347f7959960f1cc286d3d9198c7 100644 --- a/Tests/XXMessengerClientTests/Messenger/Functions/MessengerRegisterAuthCallbacksTests.swift +++ b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerRegisterAuthCallbacksTests.swift @@ -1,7 +1,7 @@ +import CustomDump import XCTest import XXClient @testable import XXMessengerClient -import CustomDump final class MessengerRegisterAuthCallbacksTests: XCTestCase { func testRegisterAuthCallbacks() { diff --git a/Tests/XXMessengerClientTests/Messenger/Functions/MessengerRegisterMessageListenerTests.swift b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerRegisterMessageListenerTests.swift new file mode 100644 index 0000000000000000000000000000000000000000..0deedefba66819555f25a883185f52856d7aead1 --- /dev/null +++ b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerRegisterMessageListenerTests.swift @@ -0,0 +1,34 @@ +import CustomDump +import XCTest +import XXClient +@testable import XXMessengerClient + +final class MessengerRegisterMessageListenerTests: XCTestCase { + func testRegisterAuthCallbacks() { + var registeredListeners: [Listener] = [] + var didHandleMessage: [Message] = [] + var didCancelRegisteredListener = 0 + + var env: MessengerEnvironment = .unimplemented + env.messageListeners.register = { listener in + registeredListeners.append(listener) + return Cancellable { didCancelRegisteredListener += 1 } + } + let registerMessageListener: MessengerRegisterMessageListener = .live(env) + let cancellable = registerMessageListener(Listener { message in + didHandleMessage.append(message) + }) + + XCTAssertEqual(registeredListeners.count, 1) + + registeredListeners.forEach { listener in + listener.handle(Message.stub(123)) + } + + XCTAssertNoDifference(didHandleMessage, [Message.stub(123)]) + + cancellable.cancel() + + XCTAssertEqual(didCancelRegisteredListener, 1) + } +} diff --git a/Tests/XXMessengerClientTests/Messenger/Functions/MessengerSendMessageTests.swift b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerSendMessageTests.swift new file mode 100644 index 0000000000000000000000000000000000000000..c429c74218d28bfd69c2c58bb6cb3e8d623c6f87 --- /dev/null +++ b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerSendMessageTests.swift @@ -0,0 +1,233 @@ +import CustomDump +import XCTest +import XXClient +@testable import XXMessengerClient + +final class MessengerSendMessageTests: XCTestCase { + func testSend() throws { + struct E2ESendParams: Equatable { + var messageType: Int + var recipientId: Data + var payload: Data + var e2eParams: Data + } + var e2eDidSendWithParams: [E2ESendParams] = [] + + let e2eSendReport = E2ESendReport( + rounds: [1, 2, 3], + roundURL: "round-url", + messageId: "message-id".data(using: .utf8)!, + timestamp: 123, + keyResidue: "key-residue".data(using: .utf8)! + ) + + var env: MessengerEnvironment = .unimplemented + env.getE2EParams.run = { "e2e-params".data(using: .utf8)! } + env.cMix.get = { .unimplemented } + env.e2e.get = { + var e2e: E2E = .unimplemented + e2e.send.run = { messageType, recipientId, payload, e2eParams in + e2eDidSendWithParams.append(.init( + messageType: messageType, + recipientId: recipientId, + payload: payload, + e2eParams: e2eParams + )) + return e2eSendReport + } + return e2e + } + let send: MessengerSendMessage = .live(env) + + let report = try send( + recipientId: "recipient-id".data(using: .utf8)!, + payload: "payload".data(using: .utf8)!, + deliveryCallback: nil + ) + + XCTAssertNoDifference(e2eDidSendWithParams, [.init( + messageType: 2, + recipientId: "recipient-id".data(using: .utf8)!, + payload: "payload".data(using: .utf8)!, + e2eParams: "e2e-params".data(using: .utf8)! + )]) + + XCTAssertNoDifference(report, e2eSendReport) + } + + func testSendWithDeliveryCallback() throws { + struct WaitForRoundResultsParams: Equatable { + var roundList: Data + var timeoutMS: Int + } + var didWaitForRoundResultsWithParams: [WaitForRoundResultsParams] = [] + var didWaitForRoundResultsWithCallback: [MessageDeliveryCallback] = [] + var didReceiveDeliveryReport: [MessengerSendMessage.DeliveryReport] = [] + + let e2eSendReport = E2ESendReport( + rounds: [1, 2, 3], + roundURL: "round-url", + messageId: "message-id".data(using: .utf8)!, + timestamp: 123, + keyResidue: "key-residue".data(using: .utf8)! + ) + + var env: MessengerEnvironment = .unimplemented + env.getE2EParams.run = { "e2e-params".data(using: .utf8)! } + env.cMix.get = { + var cMix: CMix = .unimplemented + cMix.waitForRoundResult.run = { roundList, timeoutMS, callback in + didWaitForRoundResultsWithParams.append(.init(roundList: roundList, timeoutMS: timeoutMS)) + didWaitForRoundResultsWithCallback.append(callback) + } + return cMix + } + env.e2e.get = { + var e2e: E2E = .unimplemented + e2e.send.run = { _, _, _, _ in e2eSendReport } + return e2e + } + let send: MessengerSendMessage = .live(env) + + let report = try send( + recipientId: "recipient-id".data(using: .utf8)!, + payload: "payload".data(using: .utf8)!, + deliveryCallback: .init { deliveryReport in + didReceiveDeliveryReport.append(deliveryReport) + } + ) + + XCTAssertNoDifference(report, e2eSendReport) + + XCTAssertNoDifference(didWaitForRoundResultsWithParams, [ + .init(roundList: try! e2eSendReport.encode(), timeoutMS: 30_000), + ]) + + didWaitForRoundResultsWithCallback.first?.handle(.delivered(roundResults: [1, 2, 3])) + + XCTAssertNoDifference(didReceiveDeliveryReport, [ + .init(report: report, result: .delivered) + ]) + + didReceiveDeliveryReport.removeAll() + didWaitForRoundResultsWithCallback.first?.handle(.notDelivered(timedOut: false)) + + XCTAssertNoDifference(didReceiveDeliveryReport, [ + .init(report: report, result: .notDelivered(timedOut: false)) + ]) + + didReceiveDeliveryReport.removeAll() + didWaitForRoundResultsWithCallback.first?.handle(.notDelivered(timedOut: true)) + + XCTAssertNoDifference(didReceiveDeliveryReport, [ + .init(report: report, result: .notDelivered(timedOut: true)) + ]) + } + + func testSendWhenNotLoaded() { + var env: MessengerEnvironment = .unimplemented + env.cMix.get = { nil } + let send: MessengerSendMessage = .live(env) + + XCTAssertThrowsError( + try send( + recipientId: Data(), + payload: Data(), + deliveryCallback: nil + ) + ) { error in + XCTAssertNoDifference( + error as? MessengerSendMessage.Error, + .notLoaded + ) + } + } + + func testSendWhenNotConnected() { + var env: MessengerEnvironment = .unimplemented + env.cMix.get = { .unimplemented } + env.e2e.get = { nil } + let send: MessengerSendMessage = .live(env) + + XCTAssertThrowsError( + try send( + recipientId: Data(), + payload: Data(), + deliveryCallback: nil + ) + ) { error in + XCTAssertNoDifference( + error as? MessengerSendMessage.Error, + .notConnected + ) + } + } + + func testSendFailure() { + struct Failure: Error, Equatable {} + let error = Failure() + + var env: MessengerEnvironment = .unimplemented + env.getE2EParams.run = { "e2e-params".data(using: .utf8)! } + env.cMix.get = { .unimplemented } + env.e2e.get = { + var e2e: E2E = .unimplemented + e2e.send.run = { _, _, _, _ in throw error } + return e2e + } + let send: MessengerSendMessage = .live(env) + + XCTAssertThrowsError( + try send( + recipientId: "recipient-id".data(using: .utf8)!, + payload: "payload".data(using: .utf8)!, + deliveryCallback: nil + ) + ) { err in + XCTAssertNoDifference(err as? Failure, error) + } + } + + func testSendDeliveryFailure() throws { + let e2eSendReport = E2ESendReport( + rounds: [1, 2, 3], + roundURL: "round-url", + messageId: "message-id".data(using: .utf8)!, + timestamp: 123, + keyResidue: "key-residue".data(using: .utf8)! + ) + + struct Failure: Error {} + let error = Failure() + + var didReceiveDeliveryReport: [MessengerSendMessage.DeliveryReport] = [] + + var env: MessengerEnvironment = .unimplemented + env.getE2EParams.run = { "e2e-params".data(using: .utf8)! } + env.cMix.get = { + var cMix: CMix = .unimplemented + cMix.waitForRoundResult.run = { _, _, _ in throw error } + return cMix + } + env.e2e.get = { + var e2e: E2E = .unimplemented + e2e.send.run = { _, _, _, _ in e2eSendReport } + return e2e + } + let send: MessengerSendMessage = .live(env) + + let report = try send( + recipientId: "recipient-id".data(using: .utf8)!, + payload: "payload".data(using: .utf8)!, + deliveryCallback: .init { deliveryReport in + didReceiveDeliveryReport.append(deliveryReport) + } + ) + + XCTAssertNoDifference(report, e2eSendReport) + + XCTAssertNoDifference(didReceiveDeliveryReport, [ + .init(report: report, result: .failure(error as NSError)) + ]) + } +} diff --git a/Tests/XXMessengerClientTests/TestHelpers/Message+stubs.swift b/Tests/XXMessengerClientTests/TestHelpers/Message+stubs.swift new file mode 100644 index 0000000000000000000000000000000000000000..e10bea4a6298544c2e4c4d01ba267a00d2dcc167 --- /dev/null +++ b/Tests/XXMessengerClientTests/TestHelpers/Message+stubs.swift @@ -0,0 +1,18 @@ +import XXClient + +extension Message { + static func stub(_ stubId: Int) -> Message { + .init( + messageType: stubId, + id: "id-\(stubId)".data(using: .utf8)!, + payload: "payload-\(stubId)".data(using: .utf8)!, + sender: "sender-\(stubId)".data(using: .utf8)!, + recipientId: "recipientId-\(stubId)".data(using: .utf8)!, + ephemeralId: stubId, + timestamp: stubId, + encrypted: stubId % 2 == 0, + roundId: stubId, + roundURL: "roundURL-\(stubId)" + ) + } +} diff --git a/Tests/XXMessengerClientTests/Utils/AuthCallbacksRegistryTests.swift b/Tests/XXMessengerClientTests/Utils/AuthCallbacksRegistryTests.swift index 1d1ba7b2f6226e9283fc60d8656dbe0b317113a1..d2a72c351ca269576b8e2e8eb5a714d84a18e514 100644 --- a/Tests/XXMessengerClientTests/Utils/AuthCallbacksRegistryTests.swift +++ b/Tests/XXMessengerClientTests/Utils/AuthCallbacksRegistryTests.swift @@ -1,7 +1,7 @@ +import CustomDump import XCTest import XXClient @testable import XXMessengerClient -import CustomDump final class AuthCallbacksRegistryTests: XCTestCase { func testRegistry() { diff --git a/Tests/XXMessengerClientTests/Utils/ListenersRegistryTests.swift b/Tests/XXMessengerClientTests/Utils/ListenersRegistryTests.swift new file mode 100644 index 0000000000000000000000000000000000000000..763f92b69aea1b2be78c47a31250ab8a9229fe22 --- /dev/null +++ b/Tests/XXMessengerClientTests/Utils/ListenersRegistryTests.swift @@ -0,0 +1,43 @@ +import CustomDump +import XCTest +import XXClient +@testable import XXMessengerClient + +final class ListenersRegistryTestsTests: XCTestCase { + func testRegistry() { + var firstListenerDidHandle: [Message] = [] + var secondListenerDidHandle: [Message] = [] + + let firstListener = Listener { message in + firstListenerDidHandle.append(message) + } + let secondListener = Listener { message in + secondListenerDidHandle.append(message) + } + let listenersRegistry: ListenersRegistry = .live() + let registeredListeners = listenersRegistry.registered() + let firstListenerCancellable = listenersRegistry.register(firstListener) + let secondListenerCancellable = listenersRegistry.register(secondListener) + + let firstMessage = Message.stub(1) + registeredListeners.handle(firstMessage) + + XCTAssertNoDifference(firstListenerDidHandle, [firstMessage]) + XCTAssertNoDifference(secondListenerDidHandle, [firstMessage]) + + firstListenerCancellable.cancel() + let secondMessage = Message.stub(2) + registeredListeners.handle(secondMessage) + + XCTAssertNoDifference(firstListenerDidHandle, [firstMessage]) + XCTAssertNoDifference(secondListenerDidHandle, [firstMessage, secondMessage]) + + secondListenerCancellable.cancel() + + let thirdMessage = Message.stub(3) + registeredListeners.handle(thirdMessage) + + XCTAssertNoDifference(firstListenerDidHandle, [firstMessage]) + XCTAssertNoDifference(secondListenerDidHandle, [firstMessage, secondMessage]) + } +}