diff --git a/Sources/XXClient/Models/FactType.swift b/Sources/XXClient/Models/FactType.swift index cbae1a7ebdeaf510440dfcffb631848f3fbe4353..2d55ff855cf7fd25046d489bf7ac14fb10ff6f8a 100644 --- a/Sources/XXClient/Models/FactType.swift +++ b/Sources/XXClient/Models/FactType.swift @@ -1,6 +1,6 @@ import Foundation -public enum FactType: Equatable { +public enum FactType: Equatable, Hashable { public static let knownTypes: [FactType] = [.username, .email, .phone] case username diff --git a/Sources/XXMessengerClient/Messenger/Functions/MessengerMyContact.swift b/Sources/XXMessengerClient/Messenger/Functions/MessengerMyContact.swift new file mode 100644 index 0000000000000000000000000000000000000000..bcedd164fb985724f90f743ce5d417180f39b067 --- /dev/null +++ b/Sources/XXMessengerClient/Messenger/Functions/MessengerMyContact.swift @@ -0,0 +1,51 @@ +import XCTestDynamicOverlay +import XXClient + +public struct MessengerMyContact { + public enum IncludeFacts: Equatable { + case all + case types(Set<FactType>) + } + + public enum Error: Swift.Error { + case notConnected + case notLoggedIn + } + + public var run: (IncludeFacts?) throws -> XXClient.Contact + + public func callAsFunction(includeFacts: IncludeFacts? = .all) throws -> XXClient.Contact { + try run(includeFacts) + } +} + +extension MessengerMyContact { + public static func live(_ env: MessengerEnvironment) -> MessengerMyContact { + MessengerMyContact { includeFacts in + guard let e2e = env.e2e() else { + throw Error.notConnected + } + var contact = e2e.getContact() + if let includeFacts { + guard let ud = env.ud() else { + throw Error.notLoggedIn + } + let udFacts = try ud.getFacts() + switch includeFacts { + case .all: + try contact.setFacts(udFacts) + + case .types(let types): + try contact.setFacts(udFacts.filter { types.contains($0.type) }) + } + } + return contact + } + } +} + +extension MessengerMyContact { + public static let unimplemented = MessengerMyContact( + run: XCTUnimplemented("\(Self.self)") + ) +} diff --git a/Sources/XXMessengerClient/Messenger/Messenger.swift b/Sources/XXMessengerClient/Messenger/Messenger.swift index 41c61329b4a538c0945f38affc62c365aeff312f..692d81fd9bdb7ee8cb540b9a4f1a844e7541966d 100644 --- a/Sources/XXMessengerClient/Messenger/Messenger.swift +++ b/Sources/XXMessengerClient/Messenger/Messenger.swift @@ -22,6 +22,7 @@ public struct Messenger { public var register: MessengerRegister public var isLoggedIn: MessengerIsLoggedIn public var logIn: MessengerLogIn + public var myContact: MessengerMyContact public var waitForNetwork: MessengerWaitForNetwork public var waitForNodes: MessengerWaitForNodes public var destroy: MessengerDestroy @@ -63,6 +64,7 @@ extension Messenger { register: .live(env), isLoggedIn: .live(env), logIn: .live(env), + myContact: .live(env), waitForNetwork: .live(env), waitForNodes: .live(env), destroy: .live(env), @@ -105,6 +107,7 @@ extension Messenger { register: .unimplemented, isLoggedIn: .unimplemented, logIn: .unimplemented, + myContact: .unimplemented, waitForNetwork: .unimplemented, waitForNodes: .unimplemented, destroy: .unimplemented, diff --git a/Tests/XXMessengerClientTests/Messenger/Functions/MessengerMyContactTests.swift b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerMyContactTests.swift new file mode 100644 index 0000000000000000000000000000000000000000..113677612ceb36dd8d08e8c35965c890c2586d9c --- /dev/null +++ b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerMyContactTests.swift @@ -0,0 +1,121 @@ +import CustomDump +import XCTest +import XXClient +@testable import XXMessengerClient + +final class MessengerMyContactTests: XCTestCase { + func testMyContactWithAllFacts() throws { + let e2eContactData = "e2e-contact-data".data(using: .utf8)! + var e2eContactSetFacts: [[Fact]] = [] + let e2eContactWithFactsData = "e2e-contact-with-facts-data".data(using: .utf8)! + let udFacts = [ + Fact(type: .username, value: "ud-fact-username"), + Fact(type: .email, value: "ud-fact-email"), + Fact(type: .phone, value: "ud-fact-phone"), + ] + var env: MessengerEnvironment = .unimplemented + env.e2e.get = { + var e2e: E2E = .unimplemented + e2e.getContact.run = { + var contact: Contact = .unimplemented(e2eContactData) + contact.setFactsOnContact.run = { _, facts in + e2eContactSetFacts.append(facts) + return e2eContactWithFactsData + } + return contact + } + return e2e + } + env.ud.get = { + var ud: UserDiscovery = .unimplemented + ud.getFacts.run = { udFacts } + return ud + } + let myContact: MessengerMyContact = .live(env) + + let contact = try myContact() + + XCTAssertNoDifference(e2eContactSetFacts, [udFacts]) + XCTAssertNoDifference(contact, .unimplemented(e2eContactWithFactsData)) + } + + func testMyContactWithoutFacts() throws { + let e2eContactData = "e2e-contact-data".data(using: .utf8)! + var env: MessengerEnvironment = .unimplemented + env.e2e.get = { + var e2e: E2E = .unimplemented + e2e.getContact.run = { .unimplemented(e2eContactData) } + return e2e + } + let myContact: MessengerMyContact = .live(env) + + let contact = try myContact(includeFacts: .none) + + XCTAssertNoDifference(contact, .unimplemented(e2eContactData)) + } + + func testMyContactWithFactTypes() throws { + let e2eContactData = "e2e-contact-data".data(using: .utf8)! + var e2eContactSetFacts: [[Fact]] = [] + let e2eContactWithFactsData = "e2e-contact-with-facts-data".data(using: .utf8)! + let udFactUsername = Fact(type: .username, value: "ud-fact-username") + let udFactEmail = Fact(type: .email, value: "ud-fact-email") + let udFactPhone = Fact(type: .phone, value: "ud-fact-phone") + let udFacts = [udFactUsername, udFactEmail, udFactPhone] + var env: MessengerEnvironment = .unimplemented + env.e2e.get = { + var e2e: E2E = .unimplemented + e2e.getContact.run = { + var contact: Contact = .unimplemented(e2eContactData) + contact.setFactsOnContact.run = { _, facts in + e2eContactSetFacts.append(facts) + return e2eContactWithFactsData + } + return contact + } + return e2e + } + env.ud.get = { + var ud: UserDiscovery = .unimplemented + ud.getFacts.run = { udFacts } + return ud + } + let myContact: MessengerMyContact = .live(env) + + let contact = try myContact(includeFacts: .types([.username, .phone])) + + XCTAssertNoDifference(e2eContactSetFacts, [[udFactUsername, udFactPhone]]) + XCTAssertNoDifference(contact, .unimplemented(e2eContactWithFactsData)) + } + + func testMyContactWhenNotConnected() { + var env: MessengerEnvironment = .unimplemented + env.e2e.get = { nil } + let myContact: MessengerMyContact = .live(env) + + XCTAssertThrowsError(try myContact()) { error in + XCTAssertNoDifference( + error as NSError, + MessengerMyContact.Error.notConnected as NSError + ) + } + } + + func testMyContactWithFactsWhenNotLoggedIn() { + var env: MessengerEnvironment = .unimplemented + env.e2e.get = { + var e2e: E2E = .unimplemented + e2e.getContact.run = { .unimplemented(Data()) } + return e2e + } + env.ud.get = { nil } + let myContact: MessengerMyContact = .live(env) + + XCTAssertThrowsError(try myContact()) { error in + XCTAssertNoDifference( + error as NSError, + MessengerMyContact.Error.notLoggedIn as NSError + ) + } + } +}