Skip to content
Snippets Groups Projects
Commit 772919eb authored by Dariusz Rybicki's avatar Dariusz Rybicki
Browse files

Merge branch 'feature/notifications' into 'development'

Notifications

See merge request elixxir/elixxir-dapps-sdk-swift!138
parents 82343313 7c35364b
No related branches found
No related tags found
2 merge requests!138Notifications,!102Release 1.0.0
Showing
with 384 additions and 12 deletions
...@@ -19,6 +19,8 @@ public struct CMix { ...@@ -19,6 +19,8 @@ public struct CMix {
public var addHealthCallback: CMixAddHealthCallback public var addHealthCallback: CMixAddHealthCallback
public var waitForRoundResult: CMixWaitForRoundResult public var waitForRoundResult: CMixWaitForRoundResult
public var connect: CMixConnect public var connect: CMixConnect
public var trackServices: CMixTrackServices
public var trackServicesWithIdentity: CMixTrackServicesWithIdentity
} }
extension CMix { extension CMix {
...@@ -41,7 +43,9 @@ extension CMix { ...@@ -41,7 +43,9 @@ extension CMix {
registerClientErrorCallback: .live(bindingsCMix), registerClientErrorCallback: .live(bindingsCMix),
addHealthCallback: .live(bindingsCMix), addHealthCallback: .live(bindingsCMix),
waitForRoundResult: .live(bindingsCMix), waitForRoundResult: .live(bindingsCMix),
connect: .live(bindingsCMix) connect: .live(bindingsCMix),
trackServices: .live(bindingsCMix),
trackServicesWithIdentity: .live(bindingsCMix)
) )
} }
} }
...@@ -65,6 +69,8 @@ extension CMix { ...@@ -65,6 +69,8 @@ extension CMix {
registerClientErrorCallback: .unimplemented, registerClientErrorCallback: .unimplemented,
addHealthCallback: .unimplemented, addHealthCallback: .unimplemented,
waitForRoundResult: .unimplemented, waitForRoundResult: .unimplemented,
connect: .unimplemented connect: .unimplemented,
trackServices: .unimplemented,
trackServicesWithIdentity: .unimplemented
) )
} }
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)")
)
}
import Foundation import Foundation
public struct NotificationReport: Equatable { public struct NotificationReport: Equatable {
public enum ReportType: String, Equatable { public enum ReportType: String, Equatable, CaseIterable {
case `default` case `default`
case request case request
case reset case reset
......
...@@ -25,6 +25,7 @@ extension MessengerDestroy { ...@@ -25,6 +25,7 @@ extension MessengerDestroy {
env.e2e.set(nil) env.e2e.set(nil)
env.cMix.set(nil) env.cMix.set(nil)
env.isListeningForMessages.set(false) env.isListeningForMessages.set(false)
env.serviceList.set(nil)
try env.fileManager.removeItem(env.storageDir) try env.fileManager.removeItem(env.storageDir)
try env.passwordStorage.remove() try env.passwordStorage.remove()
} }
......
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)")
)
}
...@@ -2,7 +2,7 @@ import XCTestDynamicOverlay ...@@ -2,7 +2,7 @@ import XCTestDynamicOverlay
import XXClient import XXClient
public struct MessengerListenForMessages { public struct MessengerListenForMessages {
public enum Error: Swift.Error { public enum Error: Swift.Error, Equatable {
case notConnected case notConnected
} }
......
...@@ -7,7 +7,7 @@ public struct MessengerMyContact { ...@@ -7,7 +7,7 @@ public struct MessengerMyContact {
case types(Set<FactType>) case types(Set<FactType>)
} }
public enum Error: Swift.Error { public enum Error: Swift.Error, Equatable {
case notConnected case notConnected
case notLoggedIn case notLoggedIn
} }
......
...@@ -2,7 +2,7 @@ import XXClient ...@@ -2,7 +2,7 @@ import XXClient
import XCTestDynamicOverlay import XCTestDynamicOverlay
public struct MessengerStart { public struct MessengerStart {
public enum Error: Swift.Error { public enum Error: Swift.Error, Equatable {
case notLoaded case notLoaded
} }
......
...@@ -16,7 +16,7 @@ public struct MessengerStop { ...@@ -16,7 +16,7 @@ public struct MessengerStop {
public var retries: Int public var retries: Int
} }
public enum Error: Swift.Error { public enum Error: Swift.Error, Equatable {
case notLoaded case notLoaded
case timedOut case timedOut
} }
......
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)")
)
}
...@@ -2,7 +2,7 @@ import XXClient ...@@ -2,7 +2,7 @@ import XXClient
import XCTestDynamicOverlay import XCTestDynamicOverlay
public struct MessengerWaitForNetwork { public struct MessengerWaitForNetwork {
public enum Error: Swift.Error { public enum Error: Swift.Error, Equatable {
case notLoaded case notLoaded
case timeout case timeout
} }
......
...@@ -5,7 +5,7 @@ import XCTestDynamicOverlay ...@@ -5,7 +5,7 @@ import XCTestDynamicOverlay
public struct MessengerWaitForNodes { public struct MessengerWaitForNodes {
public typealias Progress = (NodeRegistrationReport) -> Void public typealias Progress = (NodeRegistrationReport) -> Void
public enum Error: Swift.Error { public enum Error: Swift.Error, Equatable {
case notLoaded case notLoaded
case timeout case timeout
} }
......
...@@ -46,6 +46,8 @@ public struct Messenger { ...@@ -46,6 +46,8 @@ public struct Messenger {
public var startFileTransfer: MessengerStartFileTransfer public var startFileTransfer: MessengerStartFileTransfer
public var sendFile: MessengerSendFile public var sendFile: MessengerSendFile
public var receiveFile: MessengerReceiveFile public var receiveFile: MessengerReceiveFile
public var trackServices: MessengerTrackServices
public var getNotificationReport: MessengerGetNotificationReport
} }
extension Messenger { extension Messenger {
...@@ -95,7 +97,9 @@ extension Messenger { ...@@ -95,7 +97,9 @@ extension Messenger {
isFileTransferRunning: .live(env), isFileTransferRunning: .live(env),
startFileTransfer: .live(env), startFileTransfer: .live(env),
sendFile: .live(env), sendFile: .live(env),
receiveFile: .live(env) receiveFile: .live(env),
trackServices: .live(env),
getNotificationReport: .live(env)
) )
} }
} }
...@@ -146,6 +150,8 @@ extension Messenger { ...@@ -146,6 +150,8 @@ extension Messenger {
isFileTransferRunning: .unimplemented, isFileTransferRunning: .unimplemented,
startFileTransfer: .unimplemented, startFileTransfer: .unimplemented,
sendFile: .unimplemented, sendFile: .unimplemented,
receiveFile: .unimplemented receiveFile: .unimplemented,
trackServices: .unimplemented,
getNotificationReport: .unimplemented
) )
} }
...@@ -16,6 +16,7 @@ public struct MessengerEnvironment { ...@@ -16,6 +16,7 @@ public struct MessengerEnvironment {
public var getE2EFileTransferParams: GetE2EFileTransferParams public var getE2EFileTransferParams: GetE2EFileTransferParams
public var getE2EParams: GetE2EParams public var getE2EParams: GetE2EParams
public var getFileTransferParams: GetFileTransferParams public var getFileTransferParams: GetFileTransferParams
public var getNotificationsReport: GetNotificationsReport
public var getSingleUseParams: GetSingleUseParams public var getSingleUseParams: GetSingleUseParams
public var initFileTransfer: InitFileTransfer public var initFileTransfer: InitFileTransfer
public var initializeBackup: InitializeBackup public var initializeBackup: InitializeBackup
...@@ -38,6 +39,7 @@ public struct MessengerEnvironment { ...@@ -38,6 +39,7 @@ public struct MessengerEnvironment {
public var registerLogWriter: RegisterLogWriter public var registerLogWriter: RegisterLogWriter
public var resumeBackup: ResumeBackup public var resumeBackup: ResumeBackup
public var searchUD: SearchUD public var searchUD: SearchUD
public var serviceList: Stored<MessageServiceList?>
public var setLogLevel: SetLogLevel public var setLogLevel: SetLogLevel
public var sleep: (TimeInterval) -> Void public var sleep: (TimeInterval) -> Void
public var storageDir: String public var storageDir: String
...@@ -67,6 +69,7 @@ extension MessengerEnvironment { ...@@ -67,6 +69,7 @@ extension MessengerEnvironment {
getE2EFileTransferParams: .liveDefault, getE2EFileTransferParams: .liveDefault,
getE2EParams: .liveDefault, getE2EParams: .liveDefault,
getFileTransferParams: .liveDefault, getFileTransferParams: .liveDefault,
getNotificationsReport: .live,
getSingleUseParams: .liveDefault, getSingleUseParams: .liveDefault,
initFileTransfer: .live, initFileTransfer: .live,
initializeBackup: .live, initializeBackup: .live,
...@@ -89,6 +92,7 @@ extension MessengerEnvironment { ...@@ -89,6 +92,7 @@ extension MessengerEnvironment {
registerLogWriter: .live, registerLogWriter: .live,
resumeBackup: .live, resumeBackup: .live,
searchUD: .live, searchUD: .live,
serviceList: .inMemory(),
setLogLevel: .live, setLogLevel: .live,
sleep: { Thread.sleep(forTimeInterval: $0) }, sleep: { Thread.sleep(forTimeInterval: $0) },
storageDir: MessengerEnvironment.defaultStorageDir, storageDir: MessengerEnvironment.defaultStorageDir,
...@@ -113,6 +117,7 @@ extension MessengerEnvironment { ...@@ -113,6 +117,7 @@ extension MessengerEnvironment {
getE2EFileTransferParams: .unimplemented, getE2EFileTransferParams: .unimplemented,
getE2EParams: .unimplemented, getE2EParams: .unimplemented,
getFileTransferParams: .unimplemented, getFileTransferParams: .unimplemented,
getNotificationsReport: .unimplemented,
getSingleUseParams: .unimplemented, getSingleUseParams: .unimplemented,
initFileTransfer: .unimplemented, initFileTransfer: .unimplemented,
initializeBackup: .unimplemented, initializeBackup: .unimplemented,
...@@ -135,6 +140,7 @@ extension MessengerEnvironment { ...@@ -135,6 +140,7 @@ extension MessengerEnvironment {
registerLogWriter: .unimplemented, registerLogWriter: .unimplemented,
resumeBackup: .unimplemented, resumeBackup: .unimplemented,
searchUD: .unimplemented, searchUD: .unimplemented,
serviceList: .unimplemented(),
setLogLevel: .unimplemented, setLogLevel: .unimplemented,
sleep: XCTUnimplemented("\(Self.self).sleep"), sleep: XCTUnimplemented("\(Self.self).sleep"),
storageDir: "unimplemented", storageDir: "unimplemented",
......
import Foundation
import XCTestDynamicOverlay import XCTestDynamicOverlay
public struct Stored<Value> { public struct Stored<Value> {
...@@ -31,6 +32,26 @@ private final class Memory<Value> { ...@@ -31,6 +32,26 @@ private final class Memory<Value> {
var value: 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 { extension Stored {
public struct MissingValueError: Error, Equatable { public struct MissingValueError: Error, Equatable {
public init(typeDescription: String) { public init(typeDescription: String) {
......
...@@ -17,6 +17,7 @@ final class MessengerDestroyTests: XCTestCase { ...@@ -17,6 +17,7 @@ final class MessengerDestroyTests: XCTestCase {
var didSetCMix: [CMix?] = [] var didSetCMix: [CMix?] = []
var didRemovePassword = 0 var didRemovePassword = 0
var didSetIsListeningForMessages: [Bool] = [] var didSetIsListeningForMessages: [Bool] = []
var didSetServiceList: [MessageServiceList?] = []
var env: MessengerEnvironment = .unimplemented var env: MessengerEnvironment = .unimplemented
env.cMix.get = { env.cMix.get = {
...@@ -34,6 +35,7 @@ final class MessengerDestroyTests: XCTestCase { ...@@ -34,6 +35,7 @@ final class MessengerDestroyTests: XCTestCase {
env.e2e.set = { didSetE2E.append($0) } env.e2e.set = { didSetE2E.append($0) }
env.cMix.set = { didSetCMix.append($0) } env.cMix.set = { didSetCMix.append($0) }
env.isListeningForMessages.set = { didSetIsListeningForMessages.append($0) } env.isListeningForMessages.set = { didSetIsListeningForMessages.append($0) }
env.serviceList.set = { didSetServiceList.append($0) }
env.fileManager.removeItem = { didRemoveItem.append($0) } env.fileManager.removeItem = { didRemoveItem.append($0) }
env.passwordStorage.remove = { didRemovePassword += 1 } env.passwordStorage.remove = { didRemovePassword += 1 }
let destroy: MessengerDestroy = .live(env) let destroy: MessengerDestroy = .live(env)
...@@ -48,6 +50,7 @@ final class MessengerDestroyTests: XCTestCase { ...@@ -48,6 +50,7 @@ final class MessengerDestroyTests: XCTestCase {
XCTAssertNoDifference(didSetE2E.map { $0 == nil }, [true]) XCTAssertNoDifference(didSetE2E.map { $0 == nil }, [true])
XCTAssertNoDifference(didSetCMix.map { $0 == nil }, [true]) XCTAssertNoDifference(didSetCMix.map { $0 == nil }, [true])
XCTAssertNoDifference(didSetIsListeningForMessages, [false]) XCTAssertNoDifference(didSetIsListeningForMessages, [false])
XCTAssertNoDifference(didSetServiceList.map { $0 == nil }, [true])
XCTAssertNoDifference(didRemoveItem, [storageDir]) XCTAssertNoDifference(didRemoveItem, [storageDir])
XCTAssertNoDifference(didRemovePassword, 1) XCTAssertNoDifference(didRemovePassword, 1)
} }
...@@ -79,6 +82,7 @@ final class MessengerDestroyTests: XCTestCase { ...@@ -79,6 +82,7 @@ final class MessengerDestroyTests: XCTestCase {
var didSetE2E: [E2E?] = [] var didSetE2E: [E2E?] = []
var didSetCMix: [CMix?] = [] var didSetCMix: [CMix?] = []
var didSetIsListeningForMessages: [Bool] = [] var didSetIsListeningForMessages: [Bool] = []
var didSetServiceList: [MessageServiceList?] = []
var env: MessengerEnvironment = .unimplemented var env: MessengerEnvironment = .unimplemented
env.cMix.get = { nil } env.cMix.get = { nil }
...@@ -88,6 +92,7 @@ final class MessengerDestroyTests: XCTestCase { ...@@ -88,6 +92,7 @@ final class MessengerDestroyTests: XCTestCase {
env.e2e.set = { didSetE2E.append($0) } env.e2e.set = { didSetE2E.append($0) }
env.cMix.set = { didSetCMix.append($0) } env.cMix.set = { didSetCMix.append($0) }
env.isListeningForMessages.set = { didSetIsListeningForMessages.append($0) } env.isListeningForMessages.set = { didSetIsListeningForMessages.append($0) }
env.serviceList.set = { didSetServiceList.append($0) }
env.fileManager.removeItem = { _ in throw error } env.fileManager.removeItem = { _ in throw error }
let destroy: MessengerDestroy = .live(env) let destroy: MessengerDestroy = .live(env)
...@@ -100,6 +105,7 @@ final class MessengerDestroyTests: XCTestCase { ...@@ -100,6 +105,7 @@ final class MessengerDestroyTests: XCTestCase {
XCTAssertNoDifference(didSetE2E.map { $0 == nil }, [true]) XCTAssertNoDifference(didSetE2E.map { $0 == nil }, [true])
XCTAssertNoDifference(didSetCMix.map { $0 == nil }, [true]) XCTAssertNoDifference(didSetCMix.map { $0 == nil }, [true])
XCTAssertNoDifference(didSetIsListeningForMessages, [false]) XCTAssertNoDifference(didSetIsListeningForMessages, [false])
XCTAssertNoDifference(didSetServiceList.map { $0 == nil }, [true])
} }
func testRemovePasswordFailure() { func testRemovePasswordFailure() {
...@@ -113,6 +119,7 @@ final class MessengerDestroyTests: XCTestCase { ...@@ -113,6 +119,7 @@ final class MessengerDestroyTests: XCTestCase {
var didSetE2E: [E2E?] = [] var didSetE2E: [E2E?] = []
var didSetCMix: [CMix?] = [] var didSetCMix: [CMix?] = []
var didSetIsListeningForMessages: [Bool] = [] var didSetIsListeningForMessages: [Bool] = []
var didSetServiceList: [MessageServiceList?] = []
var env: MessengerEnvironment = .unimplemented var env: MessengerEnvironment = .unimplemented
env.cMix.get = { nil } env.cMix.get = { nil }
...@@ -122,6 +129,7 @@ final class MessengerDestroyTests: XCTestCase { ...@@ -122,6 +129,7 @@ final class MessengerDestroyTests: XCTestCase {
env.e2e.set = { didSetE2E.append($0) } env.e2e.set = { didSetE2E.append($0) }
env.cMix.set = { didSetCMix.append($0) } env.cMix.set = { didSetCMix.append($0) }
env.isListeningForMessages.set = { didSetIsListeningForMessages.append($0) } env.isListeningForMessages.set = { didSetIsListeningForMessages.append($0) }
env.serviceList.set = { didSetServiceList.append($0) }
env.storageDir = storageDir env.storageDir = storageDir
env.fileManager.removeItem = { didRemoveItem.append($0) } env.fileManager.removeItem = { didRemoveItem.append($0) }
env.passwordStorage.remove = { throw error } env.passwordStorage.remove = { throw error }
...@@ -136,6 +144,7 @@ final class MessengerDestroyTests: XCTestCase { ...@@ -136,6 +144,7 @@ final class MessengerDestroyTests: XCTestCase {
XCTAssertNoDifference(didSetE2E.map { $0 == nil }, [true]) XCTAssertNoDifference(didSetE2E.map { $0 == nil }, [true])
XCTAssertNoDifference(didSetCMix.map { $0 == nil }, [true]) XCTAssertNoDifference(didSetCMix.map { $0 == nil }, [true])
XCTAssertNoDifference(didSetIsListeningForMessages, [false]) XCTAssertNoDifference(didSetIsListeningForMessages, [false])
XCTAssertNoDifference(didSetServiceList.map { $0 == nil }, [true])
XCTAssertNoDifference(didRemoveItem, [storageDir]) XCTAssertNoDifference(didRemoveItem, [storageDir])
} }
} }
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)!
)
}
}
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
)
}
}
}
...@@ -30,3 +30,28 @@ extension ReceivedFile { ...@@ -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)!
)
}
}
import CustomDump
import XCTest import XCTest
@testable import XXMessengerClient @testable import XXMessengerClient
final class StoredTests: XCTestCase { final class StoredTests: XCTestCase {
func testInMemory() throws { func testInMemory() {
let stored: Stored<String?> = .inMemory() let stored: Stored<String?> = .inMemory()
XCTAssertNil(stored()) XCTAssertNil(stored())
...@@ -15,4 +16,35 @@ final class StoredTests: XCTestCase { ...@@ -15,4 +16,35 @@ final class StoredTests: XCTestCase {
XCTAssertNil(stored()) 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)
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment