diff --git a/Docs/XXMessengerClient.md b/Docs/XXMessengerClient.md index c2f407c3702f5a04620dd5df035323cda3743ac1..5d4983122ecf46711d8a34f965d65a906fda99c7 100644 --- a/Docs/XXMessengerClient.md +++ b/Docs/XXMessengerClient.md @@ -98,6 +98,9 @@ let ud = messenger.ud() // get Backup: let backup = messenger.backup() + +// get GroupChat +let groupChat = messenger.groupChat() ``` ## 💾 Backup @@ -217,3 +220,26 @@ let transferId = try messenger.sendFile(.init(file: file, recipientId: ...)) { i } } ``` + +## 💬 Group Chat + +### Setup + +```swift +// register callbacks: +let groupRequestsCancellable = messenger.registerGroupRequestHandler(.init { group in + // handle group request... +}) +let groupChatProcessorCancellable = messenger.registerGroupChatProcessor(.init { result in + switch result { + case .success(let callback): + // handle group chat processor callback... + + case .failure(let error): + // handle error... + } +}) + +// start group chat manager: +try messenger.startGroupChat() +``` \ No newline at end of file diff --git a/Sources/XXClient/Callbacks/GroupChatProcessor.swift b/Sources/XXClient/Callbacks/GroupChatProcessor.swift index f303aae49186ab75df7a796f735e129027367ec6..a43ec39786fcab1de0d0ceaec978446b57c821c3 100644 --- a/Sources/XXClient/Callbacks/GroupChatProcessor.swift +++ b/Sources/XXClient/Callbacks/GroupChatProcessor.swift @@ -2,6 +2,8 @@ import Bindings import XCTestDynamicOverlay public struct GroupChatProcessor { + public typealias Result = Swift.Result<Callback, NSError> + public struct Callback: Equatable { public init( decryptedMessage: GroupChatMessage, @@ -29,14 +31,14 @@ public struct GroupChatProcessor { public init( name: String = "GroupChatProcessor", - handle: @escaping (Result<Callback, NSError>) -> Void + handle: @escaping (Result) -> Void ) { self.name = name self.handle = handle } public var name: String - public var handle: (Result<Callback, NSError>) -> Void + public var handle: (Result) -> Void } extension GroupChatProcessor { diff --git a/Sources/XXMessengerClient/Messenger/Functions/MessengerDestroy.swift b/Sources/XXMessengerClient/Messenger/Functions/MessengerDestroy.swift index b2b18a4dd28110e05e9490b3e1e8556fbf5e6b7d..392c882068d67b026f70bff9c23ead518e5e8323 100644 --- a/Sources/XXMessengerClient/Messenger/Functions/MessengerDestroy.swift +++ b/Sources/XXMessengerClient/Messenger/Functions/MessengerDestroy.swift @@ -19,6 +19,7 @@ extension MessengerDestroy { env.sleep(1) } } + env.groupChat.set(nil) env.fileTransfer.set(nil) env.backup.set(nil) env.ud.set(nil) diff --git a/Sources/XXMessengerClient/Messenger/Functions/MessengerRegisterGroupChatProcessor.swift b/Sources/XXMessengerClient/Messenger/Functions/MessengerRegisterGroupChatProcessor.swift new file mode 100644 index 0000000000000000000000000000000000000000..2830dd1ae3d2ba28bb6e66d0753abb96b5bb8ad8 --- /dev/null +++ b/Sources/XXMessengerClient/Messenger/Functions/MessengerRegisterGroupChatProcessor.swift @@ -0,0 +1,24 @@ +import XCTestDynamicOverlay +import XXClient + +public struct MessengerRegisterGroupChatProcessor { + public var run: (GroupChatProcessor) -> Cancellable + + public func callAsFunction(_ processor: GroupChatProcessor) -> Cancellable { + run(processor) + } +} + +extension MessengerRegisterGroupChatProcessor { + public static func live(_ env: MessengerEnvironment) -> MessengerRegisterGroupChatProcessor { + MessengerRegisterGroupChatProcessor { processor in + env.groupChatProcessors.register(processor) + } + } +} + +extension MessengerRegisterGroupChatProcessor { + public static let unimplemented = MessengerRegisterGroupChatProcessor( + run: XCTUnimplemented("\(Self.self)", placeholder: Cancellable {}) + ) +} diff --git a/Sources/XXMessengerClient/Messenger/Functions/MessengerRegisterGroupRequestHandler.swift b/Sources/XXMessengerClient/Messenger/Functions/MessengerRegisterGroupRequestHandler.swift new file mode 100644 index 0000000000000000000000000000000000000000..d298952da0e610cf321643139ef30e076ce6287a --- /dev/null +++ b/Sources/XXMessengerClient/Messenger/Functions/MessengerRegisterGroupRequestHandler.swift @@ -0,0 +1,24 @@ +import XCTestDynamicOverlay +import XXClient + +public struct MessengerRegisterGroupRequestHandler { + public var run: (GroupRequest) -> Cancellable + + public func callAsFunction(_ handler: GroupRequest) -> Cancellable { + run(handler) + } +} + +extension MessengerRegisterGroupRequestHandler { + public static func live(_ env: MessengerEnvironment) -> MessengerRegisterGroupRequestHandler { + MessengerRegisterGroupRequestHandler { handler in + env.groupRequests.register(handler) + } + } +} + +extension MessengerRegisterGroupRequestHandler { + public static let unimplemented = MessengerRegisterGroupRequestHandler( + run: XCTUnimplemented("\(Self.self)", placeholder: Cancellable {}) + ) +} diff --git a/Sources/XXMessengerClient/Messenger/Functions/MessengerStartGroupChat.swift b/Sources/XXMessengerClient/Messenger/Functions/MessengerStartGroupChat.swift new file mode 100644 index 0000000000000000000000000000000000000000..4ae282b80df87e730b01ea6464aa89e19f34042d --- /dev/null +++ b/Sources/XXMessengerClient/Messenger/Functions/MessengerStartGroupChat.swift @@ -0,0 +1,36 @@ +import XXClient +import XCTestDynamicOverlay + +public struct MessengerStartGroupChat { + public enum Error: Swift.Error, Equatable { + case notConnected + } + + public var run: () throws -> Void + + public func callAsFunction() throws { + try run() + } +} + +extension MessengerStartGroupChat { + public static func live(_ env: MessengerEnvironment) -> MessengerStartGroupChat { + MessengerStartGroupChat { + guard let e2e = env.e2e.get() else { + throw Error.notConnected + } + let groupChat = try env.newGroupChat( + e2eId: e2e.getId(), + groupRequest: env.groupRequests.registered(), + groupChatProcessor: env.groupChatProcessors.registered() + ) + env.groupChat.set(groupChat) + } + } +} + +extension MessengerStartGroupChat { + public static let unimplemented = MessengerStartGroupChat( + run: XCTestDynamicOverlay.unimplemented("\(Self.self)") + ) +} diff --git a/Sources/XXMessengerClient/Messenger/Messenger.swift b/Sources/XXMessengerClient/Messenger/Messenger.swift index 9261d26467400a3f34fc9852c08dd5df1baf0b5d..44b213cb05805352ecffd0d7e07ca6f4880a42a7 100644 --- a/Sources/XXMessengerClient/Messenger/Messenger.swift +++ b/Sources/XXMessengerClient/Messenger/Messenger.swift @@ -6,6 +6,7 @@ public struct Messenger { public var ud: Stored<UserDiscovery?> public var backup: Stored<Backup?> public var fileTransfer: Stored<FileTransfer?> + public var groupChat: Stored<GroupChat?> public var isCreated: MessengerIsCreated public var create: MessengerCreate public var restoreBackup: MessengerRestoreBackup @@ -48,6 +49,9 @@ public struct Messenger { public var receiveFile: MessengerReceiveFile public var trackServices: MessengerTrackServices public var getNotificationReports: MessengerGetNotificationReports + public var registerGroupRequestHandler: MessengerRegisterGroupRequestHandler + public var registerGroupChatProcessor: MessengerRegisterGroupChatProcessor + public var startGroupChat: MessengerStartGroupChat } extension Messenger { @@ -58,6 +62,7 @@ extension Messenger { ud: env.ud, backup: env.backup, fileTransfer: env.fileTransfer, + groupChat: env.groupChat, isCreated: .live(env), create: .live(env), restoreBackup: .live(env), @@ -99,7 +104,10 @@ extension Messenger { sendFile: .live(env), receiveFile: .live(env), trackServices: .live(env), - getNotificationReports: .live(env) + getNotificationReports: .live(env), + registerGroupRequestHandler: .live(env), + registerGroupChatProcessor: .live(env), + startGroupChat: .live(env) ) } } @@ -111,6 +119,7 @@ extension Messenger { ud: .unimplemented(), backup: .unimplemented(), fileTransfer: .unimplemented(), + groupChat: .unimplemented(), isCreated: .unimplemented, create: .unimplemented, restoreBackup: .unimplemented, @@ -152,6 +161,9 @@ extension Messenger { sendFile: .unimplemented, receiveFile: .unimplemented, trackServices: .unimplemented, - getNotificationReports: .unimplemented + getNotificationReports: .unimplemented, + registerGroupRequestHandler: .unimplemented, + registerGroupChatProcessor: .unimplemented, + startGroupChat: .unimplemented ) } diff --git a/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift b/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift index 76707e352ad472aed566118f10963e6bb8600177..dc146e2f89461ac29cc726d44af0753d7f95d1e6 100644 --- a/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift +++ b/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift @@ -18,6 +18,9 @@ public struct MessengerEnvironment { public var getFileTransferParams: GetFileTransferParams public var getNotificationsReport: GetNotificationsReport public var getSingleUseParams: GetSingleUseParams + public var groupChat: Stored<GroupChat?> + public var groupChatProcessors: GroupChatProcessorRegistry + public var groupRequests: GroupRequestCallbacksRegistry public var initFileTransfer: InitFileTransfer public var initializeBackup: InitializeBackup public var isListeningForMessages: Stored<Bool> @@ -31,6 +34,7 @@ public struct MessengerEnvironment { public var ndfEnvironment: NDFEnvironment public var newCMix: NewCMix public var newCMixFromBackup: NewCMixFromBackup + public var newGroupChat: NewGroupChat public var newOrLoadUd: NewOrLoadUd public var newUdManagerFromBackup: NewUdManagerFromBackup public var passwordStorage: PasswordStorage @@ -71,6 +75,9 @@ extension MessengerEnvironment { getFileTransferParams: .liveDefault, getNotificationsReport: .live, getSingleUseParams: .liveDefault, + groupChat: .inMemory(), + groupChatProcessors: .live(), + groupRequests: .live(), initFileTransfer: .live, initializeBackup: .live, isListeningForMessages: .inMemory(false), @@ -84,6 +91,7 @@ extension MessengerEnvironment { ndfEnvironment: .mainnet, newCMix: .live, newCMixFromBackup: .live, + newGroupChat: .live, newOrLoadUd: .live, newUdManagerFromBackup: .live, passwordStorage: .keychain, @@ -119,6 +127,9 @@ extension MessengerEnvironment { getFileTransferParams: .unimplemented, getNotificationsReport: .unimplemented, getSingleUseParams: .unimplemented, + groupChat: .unimplemented(), + groupChatProcessors: .unimplemented, + groupRequests: .unimplemented, initFileTransfer: .unimplemented, initializeBackup: .unimplemented, isListeningForMessages: .unimplemented(placeholder: false), @@ -132,6 +143,7 @@ extension MessengerEnvironment { ndfEnvironment: .unimplemented, newCMix: .unimplemented, newCMixFromBackup: .unimplemented, + newGroupChat: .unimplemented, newOrLoadUd: .unimplemented, newUdManagerFromBackup: .unimplemented, passwordStorage: .unimplemented, diff --git a/Sources/XXMessengerClient/Utils/GroupChatProcessorRegistry.swift b/Sources/XXMessengerClient/Utils/GroupChatProcessorRegistry.swift new file mode 100644 index 0000000000000000000000000000000000000000..48390cea619ea81dc76f990b5bce6d6db2de04ca --- /dev/null +++ b/Sources/XXMessengerClient/Utils/GroupChatProcessorRegistry.swift @@ -0,0 +1,45 @@ +import Foundation +import XCTestDynamicOverlay +import XXClient + +public struct GroupChatProcessorRegistry { + public var register: (GroupChatProcessor) -> Cancellable + public var registered: () -> GroupChatProcessor +} + +extension GroupChatProcessorRegistry { + public static func live() -> GroupChatProcessorRegistry { + class Registry { + var items: [UUID: GroupChatProcessor] = [:] + } + let registry = Registry() + return GroupChatProcessorRegistry( + register: { processor in + let id = UUID() + registry.items[id] = processor + return Cancellable { registry.items[id] = nil } + }, + registered: { + GroupChatProcessor( + name: "GroupChatProcessorRegistry.registered", + handle: { result in + registry.items.values.forEach { $0.handle(result) } + } + ) + } + ) + } +} + +extension GroupChatProcessorRegistry { + public static let unimplemented = GroupChatProcessorRegistry( + register: XCTestDynamicOverlay.unimplemented( + "\(Self.self).register", + placeholder: Cancellable {} + ), + registered: XCTestDynamicOverlay.unimplemented( + "\(Self.self).registered", + placeholder: .unimplemented + ) + ) +} diff --git a/Sources/XXMessengerClient/Utils/GroupRequestCallbacksRegistry.swift b/Sources/XXMessengerClient/Utils/GroupRequestCallbacksRegistry.swift new file mode 100644 index 0000000000000000000000000000000000000000..06aff544a89ca68d345fcead12e43662d692e8a1 --- /dev/null +++ b/Sources/XXMessengerClient/Utils/GroupRequestCallbacksRegistry.swift @@ -0,0 +1,42 @@ +import Foundation +import XCTestDynamicOverlay +import XXClient + +public struct GroupRequestCallbacksRegistry { + public var register: (GroupRequest) -> Cancellable + public var registered: () -> GroupRequest +} + +extension GroupRequestCallbacksRegistry { + public static func live() -> GroupRequestCallbacksRegistry { + class Registry { + var items: [UUID: GroupRequest] = [:] + } + let registry = Registry() + return GroupRequestCallbacksRegistry( + register: { groupRequest in + let id = UUID() + registry.items[id] = groupRequest + return Cancellable { registry.items[id] = nil } + }, + registered: { + GroupRequest { group in + registry.items.values.forEach { $0.handle(group) } + } + } + ) + } +} + +extension GroupRequestCallbacksRegistry { + public static let unimplemented = GroupRequestCallbacksRegistry( + register: XCTestDynamicOverlay.unimplemented( + "\(Self.self).register", + placeholder: Cancellable {} + ), + registered: XCTestDynamicOverlay.unimplemented( + "\(Self.self).registered", + placeholder: .unimplemented + ) + ) +} diff --git a/Sources/XXMessengerClient/Utils/ListenersRegistry.swift b/Sources/XXMessengerClient/Utils/ListenersRegistry.swift index 6378e3b00295483ec3cc14607ae0a90d8e7e632d..ca311d312866133d317622709d9d1606dcdd4bab 100644 --- a/Sources/XXMessengerClient/Utils/ListenersRegistry.swift +++ b/Sources/XXMessengerClient/Utils/ListenersRegistry.swift @@ -31,9 +31,6 @@ extension ListenersRegistry { 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 } - )) + registered: XCTUnimplemented("\(Self.self).registered", placeholder: .unimplemented) ) } diff --git a/Tests/XXMessengerClientTests/Messenger/Functions/MessengerDestroyTests.swift b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerDestroyTests.swift index 3f87cacb3204fd02488a76dfe2b07f219dba8095..9a784a16cf733eec148b14b30e12e0e83faa90af 100644 --- a/Tests/XXMessengerClientTests/Messenger/Functions/MessengerDestroyTests.swift +++ b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerDestroyTests.swift @@ -10,6 +10,7 @@ final class MessengerDestroyTests: XCTestCase { var didStopNetworkFollower = 0 var didSleep: [TimeInterval] = [] var didRemoveItem: [String] = [] + var didSetGroupChat: [GroupChat?] = [] var didSetFileTransfer: [FileTransfer?] = [] var didSetBackup: [Backup?] = [] var didSetUD: [UserDiscovery?] = [] @@ -29,6 +30,7 @@ final class MessengerDestroyTests: XCTestCase { } env.sleep = { didSleep.append($0) } env.storageDir = storageDir + env.groupChat.set = { didSetGroupChat.append($0) } env.fileTransfer.set = { didSetFileTransfer.append($0) } env.backup.set = { didSetBackup.append($0) } env.ud.set = { didSetUD.append($0) } @@ -44,6 +46,7 @@ final class MessengerDestroyTests: XCTestCase { XCTAssertNoDifference(didStopNetworkFollower, 1) XCTAssertNoDifference(didSleep, [1, 1]) + XCTAssertNoDifference(didSetGroupChat.map { $0 == nil }, [true]) XCTAssertNoDifference(didSetFileTransfer.map { $0 == nil }, [true]) XCTAssertNoDifference(didSetBackup.map { $0 == nil }, [true]) XCTAssertNoDifference(didSetUD.map { $0 == nil }, [true]) @@ -76,6 +79,7 @@ final class MessengerDestroyTests: XCTestCase { func testRemoveDirectoryFailure() { struct Error: Swift.Error, Equatable {} let error = Error() + var didSetGroupChat: [GroupChat?] = [] var didSetFileTransfer: [FileTransfer?] = [] var didSetBackup: [Backup?] = [] var didSetUD: [UserDiscovery?] = [] @@ -86,6 +90,7 @@ final class MessengerDestroyTests: XCTestCase { var env: MessengerEnvironment = .unimplemented env.cMix.get = { nil } + env.groupChat.set = { didSetGroupChat.append($0) } env.fileTransfer.set = { didSetFileTransfer.append($0) } env.backup.set = { didSetBackup.append($0) } env.ud.set = { didSetUD.append($0) } @@ -99,6 +104,7 @@ final class MessengerDestroyTests: XCTestCase { XCTAssertThrowsError(try destroy()) { err in XCTAssertEqual(err as? Error, error) } + XCTAssertNoDifference(didSetGroupChat.map { $0 == nil }, [true]) XCTAssertNoDifference(didSetFileTransfer.map { $0 == nil }, [true]) XCTAssertNoDifference(didSetBackup.map { $0 == nil }, [true]) XCTAssertNoDifference(didSetUD.map { $0 == nil }, [true]) @@ -113,6 +119,7 @@ final class MessengerDestroyTests: XCTestCase { let error = Error() let storageDir = "test-storage-dir" var didRemoveItem: [String] = [] + var didSetGroupChat: [GroupChat?] = [] var didSetFileTransfer: [FileTransfer?] = [] var didSetBackup: [Backup?] = [] var didSetUD: [UserDiscovery?] = [] @@ -123,6 +130,7 @@ final class MessengerDestroyTests: XCTestCase { var env: MessengerEnvironment = .unimplemented env.cMix.get = { nil } + env.groupChat.set = { didSetGroupChat.append($0) } env.fileTransfer.set = { didSetFileTransfer.append($0) } env.backup.set = { didSetBackup.append($0) } env.ud.set = { didSetUD.append($0) } @@ -138,6 +146,7 @@ final class MessengerDestroyTests: XCTestCase { XCTAssertThrowsError(try destroy()) { err in XCTAssertEqual(err as? Error, error) } + XCTAssertNoDifference(didSetGroupChat.map { $0 == nil }, [true]) XCTAssertNoDifference(didSetFileTransfer.map { $0 == nil }, [true]) XCTAssertNoDifference(didSetBackup.map { $0 == nil }, [true]) XCTAssertNoDifference(didSetUD.map { $0 == nil }, [true]) diff --git a/Tests/XXMessengerClientTests/Messenger/Functions/MessengerRegisterGroupChatProcessorTests.swift b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerRegisterGroupChatProcessorTests.swift new file mode 100644 index 0000000000000000000000000000000000000000..ca517a3c4959b97644659f1e866118789905423c --- /dev/null +++ b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerRegisterGroupChatProcessorTests.swift @@ -0,0 +1,34 @@ +import XCTest +import XXClient +@testable import XXMessengerClient + +final class MessengerRegisterGroupChatProcessorTests: XCTestCase { + func testRegister() { + var registered: [GroupChatProcessor] = [] + var didHandle: [GroupChatProcessor.Result] = [] + var didCancel = 0 + + var env: MessengerEnvironment = .unimplemented + env.groupChatProcessors.register = { processor in + registered.append(processor) + return Cancellable { didCancel += 1 } + } + let register: MessengerRegisterGroupChatProcessor = .live(env) + let cancellable = register(.init { result in + didHandle.append(result) + }) + + XCTAssertEqual(registered.count, 1) + + let result = GroupChatProcessor.Result.success(.stub()) + registered.forEach { processor in + processor.handle(result) + } + + XCTAssertEqual(didHandle, [result]) + + cancellable.cancel() + + XCTAssertEqual(didCancel, 1) + } +} diff --git a/Tests/XXMessengerClientTests/Messenger/Functions/MessengerRegisterGroupRequestHandlerTests.swift b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerRegisterGroupRequestHandlerTests.swift new file mode 100644 index 0000000000000000000000000000000000000000..0bca164c2de9af82b45a33e600e1f2261c892cc4 --- /dev/null +++ b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerRegisterGroupRequestHandlerTests.swift @@ -0,0 +1,34 @@ +import XCTest +import XXClient +@testable import XXMessengerClient + +final class MessengerRegisterGroupRequestHandlerTests: XCTestCase { + func testRegister() { + var registered: [GroupRequest] = [] + var didHandle: [Group] = [] + var didCancel = 0 + + var env: MessengerEnvironment = .unimplemented + env.groupRequests.register = { handler in + registered.append(handler) + return Cancellable { didCancel += 1 } + } + let register: MessengerRegisterGroupRequestHandler = .live(env) + let cancellable = register(.init { group in + didHandle.append(group) + }) + + XCTAssertEqual(registered.count, 1) + + let group = Group.stub(1) + registered.forEach { handler in + handler.handle(group) + } + + XCTAssertEqual(didHandle.map { $0.getId() }, [group.getId()]) + + cancellable.cancel() + + XCTAssertEqual(didCancel, 1) + } +} diff --git a/Tests/XXMessengerClientTests/Messenger/Functions/MessengerStartGroupChatTests.swift b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerStartGroupChatTests.swift new file mode 100644 index 0000000000000000000000000000000000000000..aaf31929afab3119079b3c29fe0fbb286dc9191e --- /dev/null +++ b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerStartGroupChatTests.swift @@ -0,0 +1,44 @@ +import CustomDump +import XXClient +import XCTest +@testable import XXMessengerClient + +final class MessengerStartGroupChatTests: XCTestCase { + func testStart() throws { + var didCreateNewGroupChatWithE2eId: [Int] = [] + var didSetGroupChat: [GroupChat?] = [] + + let e2eId = 123 + var env: MessengerEnvironment = .unimplemented + env.e2e.get = { + var e2e: E2E = .unimplemented + e2e.getId.run = { e2eId } + return e2e + } + env.groupRequests.registered = { .unimplemented } + env.groupChatProcessors.registered = { .unimplemented } + env.newGroupChat.run = { e2eId, _, _ in + didCreateNewGroupChatWithE2eId.append(e2eId) + return .unimplemented + } + env.groupChat.set = { groupChat in + didSetGroupChat.append(groupChat) + } + let start: MessengerStartGroupChat = .live(env) + + try start() + + XCTAssertEqual(didCreateNewGroupChatWithE2eId, [e2eId]) + XCTAssertEqual(didSetGroupChat.map { $0 != nil }, [true]) + } + + func testStartWithoutE2E() throws { + var env: MessengerEnvironment = .unimplemented + env.e2e.get = { nil } + let start: MessengerStartGroupChat = .live(env) + + XCTAssertThrowsError(try start()) { error in + XCTAssertEqual(error as? MessengerStartGroupChat.Error, .notConnected) + } + } +} diff --git a/Tests/XXMessengerClientTests/TestHelpers/TestDoubles.swift b/Tests/XXMessengerClientTests/TestHelpers/TestDoubles.swift index d36ad479f5f865ad5ff2e06656938740054b5676..df7a6271d72996ba549bc4928628124a5dc5c811 100644 --- a/Tests/XXMessengerClientTests/TestHelpers/TestDoubles.swift +++ b/Tests/XXMessengerClientTests/TestHelpers/TestDoubles.swift @@ -55,3 +55,36 @@ extension MessageService { ) } } + +extension Group { + static func stub(_ id: Int) -> Group { + var group = Group.unimplemented + group.getId.run = { "group-\(id)".data(using: .utf8)! } + return group + } +} + +extension GroupChatMessage { + static func stub() -> GroupChatMessage { + GroupChatMessage( + groupId: "\(Int.random(in: 100...999))".data(using: .utf8)!, + senderId: "\(Int.random(in: 100...999))".data(using: .utf8)!, + messageId: "\(Int.random(in: 100...999))".data(using: .utf8)!, + payload: "\(Int.random(in: 100...999))".data(using: .utf8)!, + timestamp: Int64.random(in: 100...999) + ) + } +} + +extension GroupChatProcessor.Callback { + static func stub() -> GroupChatProcessor.Callback { + GroupChatProcessor.Callback( + decryptedMessage: .stub(), + msg: "\(Int.random(in: 100...999))".data(using: .utf8)!, + receptionId: "\(Int.random(in: 100...999))".data(using: .utf8)!, + ephemeralId: Int64.random(in: 100...999), + roundId: Int64.random(in: 100...999), + roundUrl: "\(Int.random(in: 100...999))" + ) + } +} diff --git a/Tests/XXMessengerClientTests/Utils/GroupChatProcessorRegistryTests.swift b/Tests/XXMessengerClientTests/Utils/GroupChatProcessorRegistryTests.swift new file mode 100644 index 0000000000000000000000000000000000000000..85ab46d913d117adad8bd0b9140f0f299c3a7a7d --- /dev/null +++ b/Tests/XXMessengerClientTests/Utils/GroupChatProcessorRegistryTests.swift @@ -0,0 +1,48 @@ +import CustomDump +import XCTest +import XXClient +@testable import XXMessengerClient + +final class GroupChatProcessorRegistryTests: XCTestCase { + func testRegistry() { + var firstProcessorDidHandle: [GroupChatProcessor.Result] = [] + var secondProcessorDidHandle: [GroupChatProcessor.Result] = [] + + let firstProcessor = GroupChatProcessor( + name: "first", + handle: { firstProcessorDidHandle.append($0) } + ) + let secondProcessor = GroupChatProcessor( + name: "second", + handle: { secondProcessorDidHandle.append($0) } + ) + let registry: GroupChatProcessorRegistry = .live() + let registeredProcessors = registry.registered() + let firstProcessorCancellable = registry.register(firstProcessor) + let secondProcessorCancellable = registry.register(secondProcessor) + + let firstResult = GroupChatProcessor.Result.success(.stub()) + registeredProcessors.handle(firstResult) + + XCTAssertNoDifference(firstProcessorDidHandle, [firstResult]) + XCTAssertNoDifference(secondProcessorDidHandle, [firstResult]) + + firstProcessorDidHandle = [] + secondProcessorDidHandle = [] + firstProcessorCancellable.cancel() + let secondResult = GroupChatProcessor.Result.success(.stub()) + registeredProcessors.handle(secondResult) + + XCTAssertNoDifference(firstProcessorDidHandle, []) + XCTAssertNoDifference(secondProcessorDidHandle, [secondResult]) + + firstProcessorDidHandle = [] + secondProcessorDidHandle = [] + secondProcessorCancellable.cancel() + let thirdResult = GroupChatProcessor.Result.success(.stub()) + registeredProcessors.handle(thirdResult) + + XCTAssertNoDifference(firstProcessorDidHandle, []) + XCTAssertNoDifference(secondProcessorDidHandle, []) + } +} diff --git a/Tests/XXMessengerClientTests/Utils/GroupRequestCallbacksRegistryTests.swift b/Tests/XXMessengerClientTests/Utils/GroupRequestCallbacksRegistryTests.swift new file mode 100644 index 0000000000000000000000000000000000000000..386f9d46ad5f95d276d8f812452b4a95f3a772ae --- /dev/null +++ b/Tests/XXMessengerClientTests/Utils/GroupRequestCallbacksRegistryTests.swift @@ -0,0 +1,46 @@ +import CustomDump +import XCTest +import XXClient +@testable import XXMessengerClient + +final class GroupRequestCallbacksRegistryTests: XCTestCase { + func testRegistry() { + var firstCallbackDidHandle: [Group] = [] + var secondCallbackDidHandle: [Group] = [] + + let firstCallback = GroupRequest { group in + firstCallbackDidHandle.append(group) + } + let secondCallback = GroupRequest { group in + secondCallbackDidHandle.append(group) + } + let registry: GroupRequestCallbacksRegistry = .live() + let registeredCallbacks = registry.registered() + let firstCallbackCancellable = registry.register(firstCallback) + let secondCallbackCancellable = registry.register(secondCallback) + + let firstGroup = Group.stub(1) + registeredCallbacks.handle(firstGroup) + + XCTAssertNoDifference(firstCallbackDidHandle.map { $0.getId() }, [firstGroup.getId()]) + XCTAssertNoDifference(secondCallbackDidHandle.map { $0.getId() }, [firstGroup.getId()]) + + firstCallbackDidHandle = [] + secondCallbackDidHandle = [] + firstCallbackCancellable.cancel() + let secondGroup = Group.stub(2) + registeredCallbacks.handle(secondGroup) + + XCTAssertNoDifference(firstCallbackDidHandle.map { $0.getId() }, []) + XCTAssertNoDifference(secondCallbackDidHandle.map { $0.getId() }, [secondGroup.getId()]) + + firstCallbackDidHandle = [] + secondCallbackDidHandle = [] + secondCallbackCancellable.cancel() + let thirdGroup = Group.stub(3) + registeredCallbacks.handle(thirdGroup) + + XCTAssertNoDifference(firstCallbackDidHandle.map { $0.getId() }, []) + XCTAssertNoDifference(secondCallbackDidHandle.map { $0.getId() }, []) + } +}