diff --git a/Sources/XXClient/CMix/CMix.swift b/Sources/XXClient/CMix/CMix.swift index 4571f0dbf1017fcb8ee7366439add0a7e8b752f4..9ec8007ec8fa3a555988c6fd749913eabc08b398 100644 --- a/Sources/XXClient/CMix/CMix.swift +++ b/Sources/XXClient/CMix/CMix.swift @@ -19,6 +19,8 @@ public struct CMix { public var addHealthCallback: CMixAddHealthCallback public var waitForRoundResult: CMixWaitForRoundResult public var connect: CMixConnect + public var trackServices: CMixTrackServices + public var trackServicesWithIdentity: CMixTrackServicesWithIdentity } extension CMix { @@ -41,7 +43,9 @@ extension CMix { registerClientErrorCallback: .live(bindingsCMix), addHealthCallback: .live(bindingsCMix), waitForRoundResult: .live(bindingsCMix), - connect: .live(bindingsCMix) + connect: .live(bindingsCMix), + trackServices: .live(bindingsCMix), + trackServicesWithIdentity: .live(bindingsCMix) ) } } @@ -65,6 +69,8 @@ extension CMix { registerClientErrorCallback: .unimplemented, addHealthCallback: .unimplemented, waitForRoundResult: .unimplemented, - connect: .unimplemented + connect: .unimplemented, + trackServices: .unimplemented, + trackServicesWithIdentity: .unimplemented ) } diff --git a/Sources/XXClient/CMix/Functions/CMixTrackServicesWithIdentity.swift b/Sources/XXClient/CMix/Functions/CMixTrackServicesWithIdentity.swift new file mode 100644 index 0000000000000000000000000000000000000000..a3393e6e02e8d93c697c21d85ed1997a1e006466 --- /dev/null +++ b/Sources/XXClient/CMix/Functions/CMixTrackServicesWithIdentity.swift @@ -0,0 +1,30 @@ +import Bindings +import XCTestDynamicOverlay + +public struct CMixTrackServicesWithIdentity { + public var run: (Int, TrackServicesCallback) throws -> Void + + public func callAsFunction( + e2eId: Int, + callback: TrackServicesCallback + ) throws -> Void { + try run(e2eId, callback) + } +} + +extension CMixTrackServicesWithIdentity { + public static func live(_ bindingsCMix: BindingsCmix) -> CMixTrackServicesWithIdentity { + CMixTrackServicesWithIdentity { e2eId, callback in + try bindingsCMix.trackServices( + withIdentity: e2eId, + cb: callback.makeBindingsHealthCallback() + ) + } + } +} + +extension CMixTrackServicesWithIdentity { + public static let unimplemented = CMixTrackServicesWithIdentity( + run: XCTUnimplemented("\(Self.self)") + ) +} diff --git a/Sources/XXClient/Models/NotificationReport.swift b/Sources/XXClient/Models/NotificationReport.swift index 31c106a34f5a083478522acf542d8b608544a333..06eb1d89c273fcfec99e8d4615936a1d9b8ff237 100644 --- a/Sources/XXClient/Models/NotificationReport.swift +++ b/Sources/XXClient/Models/NotificationReport.swift @@ -1,7 +1,7 @@ import Foundation public struct NotificationReport: Equatable { - public enum ReportType: String, Equatable { + public enum ReportType: String, Equatable, CaseIterable { case `default` case request case reset diff --git a/Sources/XXMessengerClient/Messenger/Functions/MessengerDestroy.swift b/Sources/XXMessengerClient/Messenger/Functions/MessengerDestroy.swift index c7ee476c543c7096c7bcf8dca8716c607775faff..b2b18a4dd28110e05e9490b3e1e8556fbf5e6b7d 100644 --- a/Sources/XXMessengerClient/Messenger/Functions/MessengerDestroy.swift +++ b/Sources/XXMessengerClient/Messenger/Functions/MessengerDestroy.swift @@ -25,6 +25,7 @@ extension MessengerDestroy { env.e2e.set(nil) env.cMix.set(nil) env.isListeningForMessages.set(false) + env.serviceList.set(nil) try env.fileManager.removeItem(env.storageDir) try env.passwordStorage.remove() } diff --git a/Sources/XXMessengerClient/Messenger/Functions/MessengerGetNotificationReport.swift b/Sources/XXMessengerClient/Messenger/Functions/MessengerGetNotificationReport.swift new file mode 100644 index 0000000000000000000000000000000000000000..a7f04ff91554e2982cfb082cb49a9c289985dd6f --- /dev/null +++ b/Sources/XXMessengerClient/Messenger/Functions/MessengerGetNotificationReport.swift @@ -0,0 +1,34 @@ +import XXClient +import XCTestDynamicOverlay + +public struct MessengerGetNotificationReport { + public enum Error: Swift.Error, Equatable { + case serviceListMissing + } + + public var run: (String) throws -> NotificationReport + + public func callAsFunction(notificationCSV: String) throws -> NotificationReport { + try run(notificationCSV) + } +} + +extension MessengerGetNotificationReport { + public static func live(_ env: MessengerEnvironment) -> MessengerGetNotificationReport { + MessengerGetNotificationReport { notificationCSV in + guard let serviceList = env.serviceList() else { + throw Error.serviceListMissing + } + return try env.getNotificationsReport( + notificationCSV: notificationCSV, + services: serviceList + ) + } + } +} + +extension MessengerGetNotificationReport { + public static let unimplemented = MessengerGetNotificationReport( + run: XCTUnimplemented("\(Self.self)") + ) +} diff --git a/Sources/XXMessengerClient/Messenger/Functions/MessengerListenForMessages.swift b/Sources/XXMessengerClient/Messenger/Functions/MessengerListenForMessages.swift index 62b9a600a58eb7c279a518aff0b23d7110aaaaf5..e0d96caf7ce8744992a9a6f3f66e4dc725c777f5 100644 --- a/Sources/XXMessengerClient/Messenger/Functions/MessengerListenForMessages.swift +++ b/Sources/XXMessengerClient/Messenger/Functions/MessengerListenForMessages.swift @@ -2,7 +2,7 @@ import XCTestDynamicOverlay import XXClient public struct MessengerListenForMessages { - public enum Error: Swift.Error { + public enum Error: Swift.Error, Equatable { case notConnected } diff --git a/Sources/XXMessengerClient/Messenger/Functions/MessengerMyContact.swift b/Sources/XXMessengerClient/Messenger/Functions/MessengerMyContact.swift index bcedd164fb985724f90f743ce5d417180f39b067..47f4ed2469aca16838fec99c89b7021a84d78851 100644 --- a/Sources/XXMessengerClient/Messenger/Functions/MessengerMyContact.swift +++ b/Sources/XXMessengerClient/Messenger/Functions/MessengerMyContact.swift @@ -7,7 +7,7 @@ public struct MessengerMyContact { case types(Set<FactType>) } - public enum Error: Swift.Error { + public enum Error: Swift.Error, Equatable { case notConnected case notLoggedIn } diff --git a/Sources/XXMessengerClient/Messenger/Functions/MessengerStart.swift b/Sources/XXMessengerClient/Messenger/Functions/MessengerStart.swift index cc3363ec543ee2c3ed6c2414ac79d1ceaa0ccc33..d911fe665dc9fba901aa2defd26cac969e9f3098 100644 --- a/Sources/XXMessengerClient/Messenger/Functions/MessengerStart.swift +++ b/Sources/XXMessengerClient/Messenger/Functions/MessengerStart.swift @@ -2,7 +2,7 @@ import XXClient import XCTestDynamicOverlay public struct MessengerStart { - public enum Error: Swift.Error { + public enum Error: Swift.Error, Equatable { case notLoaded } diff --git a/Sources/XXMessengerClient/Messenger/Functions/MessengerStop.swift b/Sources/XXMessengerClient/Messenger/Functions/MessengerStop.swift index 6e49054fbf45c7feaced41449712da617680d9e9..249cea792241e78f2be4d9df2e4e4da82b5cd5ea 100644 --- a/Sources/XXMessengerClient/Messenger/Functions/MessengerStop.swift +++ b/Sources/XXMessengerClient/Messenger/Functions/MessengerStop.swift @@ -16,7 +16,7 @@ public struct MessengerStop { public var retries: Int } - public enum Error: Swift.Error { + public enum Error: Swift.Error, Equatable { case notLoaded case timedOut } diff --git a/Sources/XXMessengerClient/Messenger/Functions/MessengerTrackServices.swift b/Sources/XXMessengerClient/Messenger/Functions/MessengerTrackServices.swift new file mode 100644 index 0000000000000000000000000000000000000000..d16cd2b3125f6eea9c6e97026ac56798a4d47756 --- /dev/null +++ b/Sources/XXMessengerClient/Messenger/Functions/MessengerTrackServices.swift @@ -0,0 +1,49 @@ +import XCTestDynamicOverlay +import XXClient + +public struct MessengerTrackServices { + public enum Error: Swift.Error, Equatable { + case notLoaded + case notConnected + } + + public typealias OnError = (Swift.Error) -> Void + + public var run: (@escaping OnError) throws -> Void + + public func callAsFunction(onError: @escaping OnError) throws { + try run(onError) + } +} + +extension MessengerTrackServices { + public static func live(_ env: MessengerEnvironment) -> MessengerTrackServices { + MessengerTrackServices { onError in + guard let cMix = env.cMix() else { + throw Error.notLoaded + } + guard let e2e = env.e2e() else { + throw Error.notConnected + } + let callback = TrackServicesCallback { result in + switch result { + case .success(let serviceList): + env.serviceList.set(serviceList) + case .failure(let error): + env.serviceList.set(nil) + onError(error) + } + } + try cMix.trackServicesWithIdentity( + e2eId: e2e.getId(), + callback: callback + ) + } + } +} + +extension MessengerTrackServices { + public static let unimplemented = MessengerTrackServices( + run: XCTUnimplemented("\(Self.self)") + ) +} diff --git a/Sources/XXMessengerClient/Messenger/Functions/MessengerWaitForNetwork.swift b/Sources/XXMessengerClient/Messenger/Functions/MessengerWaitForNetwork.swift index 8fe8cf3e4750f1d3bff8a7191574a143639466c7..d0ddb199170902f8dc0d38ff98a341e3f7bee974 100644 --- a/Sources/XXMessengerClient/Messenger/Functions/MessengerWaitForNetwork.swift +++ b/Sources/XXMessengerClient/Messenger/Functions/MessengerWaitForNetwork.swift @@ -2,7 +2,7 @@ import XXClient import XCTestDynamicOverlay public struct MessengerWaitForNetwork { - public enum Error: Swift.Error { + public enum Error: Swift.Error, Equatable { case notLoaded case timeout } diff --git a/Sources/XXMessengerClient/Messenger/Functions/MessengerWaitForNodes.swift b/Sources/XXMessengerClient/Messenger/Functions/MessengerWaitForNodes.swift index 3494df5038485e75f297f6e034859754c6b290ad..d4fd91a6a5ab282e103b9de5381c5282b4bcc5ff 100644 --- a/Sources/XXMessengerClient/Messenger/Functions/MessengerWaitForNodes.swift +++ b/Sources/XXMessengerClient/Messenger/Functions/MessengerWaitForNodes.swift @@ -5,7 +5,7 @@ import XCTestDynamicOverlay public struct MessengerWaitForNodes { public typealias Progress = (NodeRegistrationReport) -> Void - public enum Error: Swift.Error { + public enum Error: Swift.Error, Equatable { case notLoaded case timeout } diff --git a/Sources/XXMessengerClient/Messenger/Messenger.swift b/Sources/XXMessengerClient/Messenger/Messenger.swift index a6f1ee0d3eb409f6c18fca2c0c62860a97721dfb..d0bf6e46b814ce1c10a3194d627cd46707528530 100644 --- a/Sources/XXMessengerClient/Messenger/Messenger.swift +++ b/Sources/XXMessengerClient/Messenger/Messenger.swift @@ -46,6 +46,8 @@ public struct Messenger { public var startFileTransfer: MessengerStartFileTransfer public var sendFile: MessengerSendFile public var receiveFile: MessengerReceiveFile + public var trackServices: MessengerTrackServices + public var getNotificationReport: MessengerGetNotificationReport } extension Messenger { @@ -95,7 +97,9 @@ extension Messenger { isFileTransferRunning: .live(env), startFileTransfer: .live(env), sendFile: .live(env), - receiveFile: .live(env) + receiveFile: .live(env), + trackServices: .live(env), + getNotificationReport: .live(env) ) } } @@ -146,6 +150,8 @@ extension Messenger { isFileTransferRunning: .unimplemented, startFileTransfer: .unimplemented, sendFile: .unimplemented, - receiveFile: .unimplemented + receiveFile: .unimplemented, + trackServices: .unimplemented, + getNotificationReport: .unimplemented ) } diff --git a/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift b/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift index a1ab1517817248c93ce78bb435ceb621d5449fa6..76707e352ad472aed566118f10963e6bb8600177 100644 --- a/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift +++ b/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift @@ -16,6 +16,7 @@ public struct MessengerEnvironment { public var getE2EFileTransferParams: GetE2EFileTransferParams public var getE2EParams: GetE2EParams public var getFileTransferParams: GetFileTransferParams + public var getNotificationsReport: GetNotificationsReport public var getSingleUseParams: GetSingleUseParams public var initFileTransfer: InitFileTransfer public var initializeBackup: InitializeBackup @@ -38,6 +39,7 @@ public struct MessengerEnvironment { public var registerLogWriter: RegisterLogWriter public var resumeBackup: ResumeBackup public var searchUD: SearchUD + public var serviceList: Stored<MessageServiceList?> public var setLogLevel: SetLogLevel public var sleep: (TimeInterval) -> Void public var storageDir: String @@ -67,6 +69,7 @@ extension MessengerEnvironment { getE2EFileTransferParams: .liveDefault, getE2EParams: .liveDefault, getFileTransferParams: .liveDefault, + getNotificationsReport: .live, getSingleUseParams: .liveDefault, initFileTransfer: .live, initializeBackup: .live, @@ -89,6 +92,7 @@ extension MessengerEnvironment { registerLogWriter: .live, resumeBackup: .live, searchUD: .live, + serviceList: .inMemory(), setLogLevel: .live, sleep: { Thread.sleep(forTimeInterval: $0) }, storageDir: MessengerEnvironment.defaultStorageDir, @@ -113,6 +117,7 @@ extension MessengerEnvironment { getE2EFileTransferParams: .unimplemented, getE2EParams: .unimplemented, getFileTransferParams: .unimplemented, + getNotificationsReport: .unimplemented, getSingleUseParams: .unimplemented, initFileTransfer: .unimplemented, initializeBackup: .unimplemented, @@ -135,6 +140,7 @@ extension MessengerEnvironment { registerLogWriter: .unimplemented, resumeBackup: .unimplemented, searchUD: .unimplemented, + serviceList: .unimplemented(), setLogLevel: .unimplemented, sleep: XCTUnimplemented("\(Self.self).sleep"), storageDir: "unimplemented", diff --git a/Sources/XXMessengerClient/Utils/Stored.swift b/Sources/XXMessengerClient/Utils/Stored.swift index 052d638705c6dce4a619fbe18d0d55cf2159733c..ab0de7e1db138d121b2f4a9228f6bb61900d84c4 100644 --- a/Sources/XXMessengerClient/Utils/Stored.swift +++ b/Sources/XXMessengerClient/Utils/Stored.swift @@ -1,3 +1,4 @@ +import Foundation import XCTestDynamicOverlay public struct Stored<Value> { @@ -31,6 +32,26 @@ private final class Memory<Value> { var value: Value } +extension Stored { + public static func userDefaults<T>( + key: String, + userDefaults: UserDefaults = .standard + ) -> Stored<T?> where T: Codable { + let encoder = JSONEncoder() + let decoder = JSONDecoder() + return Stored<T?>( + get: { + guard let data = userDefaults.data(forKey: key) else { return nil } + return try? decoder.decode(T.self, from: data) + }, + set: { newValue in + let data = try? encoder.encode(newValue) + userDefaults.set(data, forKey: key) + } + ) + } +} + extension Stored { public struct MissingValueError: Error, Equatable { public init(typeDescription: String) { diff --git a/Tests/XXMessengerClientTests/Messenger/Functions/MessengerDestroyTests.swift b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerDestroyTests.swift index 927bc9e3c247814be28172cb97407d4b7f843ad7..3f87cacb3204fd02488a76dfe2b07f219dba8095 100644 --- a/Tests/XXMessengerClientTests/Messenger/Functions/MessengerDestroyTests.swift +++ b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerDestroyTests.swift @@ -17,6 +17,7 @@ final class MessengerDestroyTests: XCTestCase { var didSetCMix: [CMix?] = [] var didRemovePassword = 0 var didSetIsListeningForMessages: [Bool] = [] + var didSetServiceList: [MessageServiceList?] = [] var env: MessengerEnvironment = .unimplemented env.cMix.get = { @@ -34,6 +35,7 @@ final class MessengerDestroyTests: XCTestCase { env.e2e.set = { didSetE2E.append($0) } env.cMix.set = { didSetCMix.append($0) } env.isListeningForMessages.set = { didSetIsListeningForMessages.append($0) } + env.serviceList.set = { didSetServiceList.append($0) } env.fileManager.removeItem = { didRemoveItem.append($0) } env.passwordStorage.remove = { didRemovePassword += 1 } let destroy: MessengerDestroy = .live(env) @@ -48,6 +50,7 @@ final class MessengerDestroyTests: XCTestCase { XCTAssertNoDifference(didSetE2E.map { $0 == nil }, [true]) XCTAssertNoDifference(didSetCMix.map { $0 == nil }, [true]) XCTAssertNoDifference(didSetIsListeningForMessages, [false]) + XCTAssertNoDifference(didSetServiceList.map { $0 == nil }, [true]) XCTAssertNoDifference(didRemoveItem, [storageDir]) XCTAssertNoDifference(didRemovePassword, 1) } @@ -79,6 +82,7 @@ final class MessengerDestroyTests: XCTestCase { var didSetE2E: [E2E?] = [] var didSetCMix: [CMix?] = [] var didSetIsListeningForMessages: [Bool] = [] + var didSetServiceList: [MessageServiceList?] = [] var env: MessengerEnvironment = .unimplemented env.cMix.get = { nil } @@ -88,6 +92,7 @@ final class MessengerDestroyTests: XCTestCase { env.e2e.set = { didSetE2E.append($0) } env.cMix.set = { didSetCMix.append($0) } env.isListeningForMessages.set = { didSetIsListeningForMessages.append($0) } + env.serviceList.set = { didSetServiceList.append($0) } env.fileManager.removeItem = { _ in throw error } let destroy: MessengerDestroy = .live(env) @@ -100,6 +105,7 @@ final class MessengerDestroyTests: XCTestCase { XCTAssertNoDifference(didSetE2E.map { $0 == nil }, [true]) XCTAssertNoDifference(didSetCMix.map { $0 == nil }, [true]) XCTAssertNoDifference(didSetIsListeningForMessages, [false]) + XCTAssertNoDifference(didSetServiceList.map { $0 == nil }, [true]) } func testRemovePasswordFailure() { @@ -113,6 +119,7 @@ final class MessengerDestroyTests: XCTestCase { var didSetE2E: [E2E?] = [] var didSetCMix: [CMix?] = [] var didSetIsListeningForMessages: [Bool] = [] + var didSetServiceList: [MessageServiceList?] = [] var env: MessengerEnvironment = .unimplemented env.cMix.get = { nil } @@ -122,6 +129,7 @@ final class MessengerDestroyTests: XCTestCase { env.e2e.set = { didSetE2E.append($0) } env.cMix.set = { didSetCMix.append($0) } env.isListeningForMessages.set = { didSetIsListeningForMessages.append($0) } + env.serviceList.set = { didSetServiceList.append($0) } env.storageDir = storageDir env.fileManager.removeItem = { didRemoveItem.append($0) } env.passwordStorage.remove = { throw error } @@ -136,6 +144,7 @@ final class MessengerDestroyTests: XCTestCase { XCTAssertNoDifference(didSetE2E.map { $0 == nil }, [true]) XCTAssertNoDifference(didSetCMix.map { $0 == nil }, [true]) XCTAssertNoDifference(didSetIsListeningForMessages, [false]) + XCTAssertNoDifference(didSetServiceList.map { $0 == nil }, [true]) XCTAssertNoDifference(didRemoveItem, [storageDir]) } } diff --git a/Tests/XXMessengerClientTests/Messenger/Functions/MessengerGetNotificationReportTests.swift b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerGetNotificationReportTests.swift new file mode 100644 index 0000000000000000000000000000000000000000..eed49be16789ec70d6179e9b5c0a8c5fc2e2e171 --- /dev/null +++ b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerGetNotificationReportTests.swift @@ -0,0 +1,66 @@ +import CustomDump +import XCTest +import XCTestDynamicOverlay +import XXClient +@testable import XXMessengerClient + +final class MessengerGetNotificationReportTests: XCTestCase { + func testGetReport() throws { + let serviceList = MessageServiceList.stub() + let notificationCSV = "notification-csv" + let notificationReport = NotificationReport.stub() + + struct GetNotificationsReportParams: Equatable { + var notificationCSV: String + var serviceList: MessageServiceList + } + var didGetNotificationsReport: [GetNotificationsReportParams] = [] + + var env: MessengerEnvironment = .unimplemented + env.serviceList.get = { + serviceList + } + env.getNotificationsReport.run = { notificationCSV, serviceList in + didGetNotificationsReport.append(.init( + notificationCSV: notificationCSV, + serviceList: serviceList + )) + return notificationReport + } + let getReport: MessengerGetNotificationReport = .live(env) + + let report = try getReport(notificationCSV: notificationCSV) + + XCTAssertNoDifference(didGetNotificationsReport, [ + .init( + notificationCSV: notificationCSV, + serviceList: serviceList + ) + ]) + XCTAssertNoDifference(report, notificationReport) + } + + func testGetReportWhenServiceListMissing() { + var env: MessengerEnvironment = .unimplemented + env.e2e.get = { .unimplemented } + env.serviceList.get = { nil } + let getReport: MessengerGetNotificationReport = .live(env) + + XCTAssertThrowsError(try getReport(notificationCSV: "")) { error in + XCTAssertNoDifference( + error as? MessengerGetNotificationReport.Error, + .serviceListMissing + ) + } + } +} + +extension NotificationReport { + static func stub() -> NotificationReport { + NotificationReport( + forMe: .random(), + type: ReportType.allCases.randomElement()!, + source: "source-\(Int.random(in: 100...999))".data(using: .utf8)! + ) + } +} diff --git a/Tests/XXMessengerClientTests/Messenger/Functions/MessengerTrackServicesTests.swift b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerTrackServicesTests.swift new file mode 100644 index 0000000000000000000000000000000000000000..55fc5e3156cf0dc880a094bf0a12e98da824cdff --- /dev/null +++ b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerTrackServicesTests.swift @@ -0,0 +1,87 @@ +import CustomDump +import XCTest +import XCTestDynamicOverlay +import XXClient +@testable import XXMessengerClient + +final class MessengerTrackServicesTests: XCTestCase { + func testTrack() throws { + struct Failure: Error, Equatable {} + let failure = Failure() + let serviceList = MessageServiceList.stub() + let e2eId = 123 + + var didTrackServicesWithIdentity: [Int] = [] + var didSetServiceList: [MessageServiceList?] = [] + var didReceiveError: [Error] = [] + var callbacks: [TrackServicesCallback] = [] + + var env: MessengerEnvironment = .unimplemented + env.serviceList.set = { serviceList in + didSetServiceList.append(serviceList) + } + env.cMix.get = { + var cMix: CMix = .unimplemented + cMix.trackServicesWithIdentity.run = { e2eId, callback in + didTrackServicesWithIdentity.append(e2eId) + callbacks.append(callback) + } + return cMix + } + env.e2e.get = { + var e2e: E2E = .unimplemented + e2e.getId.run = { e2eId } + return e2e + } + let track: MessengerTrackServices = .live(env) + + try track(onError: { error in + didReceiveError.append(error) + }) + + XCTAssertNoDifference(didTrackServicesWithIdentity, [e2eId]) + XCTAssertEqual(callbacks.count, 1) + + didSetServiceList = [] + didReceiveError = [] + callbacks.first?.handle(.success(serviceList)) + + XCTAssertNoDifference(didSetServiceList, [serviceList]) + XCTAssertEqual(didReceiveError.count, 0) + + didSetServiceList = [] + didReceiveError = [] + callbacks.first?.handle(.failure(failure)) + + XCTAssertNoDifference(didSetServiceList, [nil]) + XCTAssertEqual(didReceiveError.count, 1) + XCTAssertNoDifference(didReceiveError.first as? Failure, failure) + } + + func testTrackWhenNotLoaded() { + var env: MessengerEnvironment = .unimplemented + env.cMix.get = { nil } + let track: MessengerTrackServices = .live(env) + + XCTAssertThrowsError(try track(onError: unimplemented())) { error in + XCTAssertNoDifference( + error as? MessengerTrackServices.Error, + .notLoaded + ) + } + } + + func testTrackWhenNotConnected() { + var env: MessengerEnvironment = .unimplemented + env.cMix.get = { .unimplemented } + env.e2e.get = { nil } + let track: MessengerTrackServices = .live(env) + + XCTAssertThrowsError(try track(onError: unimplemented())) { error in + XCTAssertNoDifference( + error as? MessengerTrackServices.Error, + .notConnected + ) + } + } +} diff --git a/Tests/XXMessengerClientTests/TestHelpers/TestDoubles.swift b/Tests/XXMessengerClientTests/TestHelpers/TestDoubles.swift index e43d76accbb65a1f7f58528e4f5a6c443f48e394..d36ad479f5f865ad5ff2e06656938740054b5676 100644 --- a/Tests/XXMessengerClientTests/TestHelpers/TestDoubles.swift +++ b/Tests/XXMessengerClientTests/TestHelpers/TestDoubles.swift @@ -30,3 +30,28 @@ extension ReceivedFile { ) } } + +extension MessageServiceList { + static func stub() -> MessageServiceList { + (1...3).map { .stub($0) } + } +} + +extension MessageServiceListElement { + static func stub(_ id: Int) -> MessageServiceListElement { + MessageServiceListElement( + id: "id-\(id)".data(using: .utf8)!, + services: (1...3).map { $0 + 10 * id }.map { .stub($0) } + ) + } +} + +extension MessageService { + static func stub(_ id: Int) -> MessageService { + MessageService( + identifier: "identifier-\(id)".data(using: .utf8)!, + tag: "tag-\(id)", + metadata: "metadata-\(id)".data(using: .utf8)! + ) + } +} diff --git a/Tests/XXMessengerClientTests/Utils/StoredTests.swift b/Tests/XXMessengerClientTests/Utils/StoredTests.swift index 154f61967627500def1526f2944aeb074792c748..834097ef9e870d7b9e297d3131c246c6a068c48a 100644 --- a/Tests/XXMessengerClientTests/Utils/StoredTests.swift +++ b/Tests/XXMessengerClientTests/Utils/StoredTests.swift @@ -1,8 +1,9 @@ +import CustomDump import XCTest @testable import XXMessengerClient final class StoredTests: XCTestCase { - func testInMemory() throws { + func testInMemory() { let stored: Stored<String?> = .inMemory() XCTAssertNil(stored()) @@ -15,4 +16,35 @@ final class StoredTests: XCTestCase { XCTAssertNil(stored()) } + + func testUserDefaults() { + struct Value: Equatable, Codable { + var id = UUID() + } + + let key = "key" + let userDefaults = UserDefaults(suiteName: "XXMessengerClient_StoredTests")! + userDefaults.removeObject(forKey: key) + let stored: Stored<Value?> = .userDefaults( + key: key, + userDefaults: userDefaults + ) + + XCTAssertNoDifference(stored.get(), nil) + + let value = Value() + stored.set(value) + + XCTAssertNoDifference( + userDefaults.data(forKey: key).map { data in + try? JSONDecoder().decode(Value.self, from: data) + }, + value + ) + XCTAssertNoDifference(stored.get(), value) + + userDefaults.set(nil, forKey: key) + + XCTAssertNoDifference(stored.get(), nil) + } }