From 9157c5e52afb50817d9f82ae8adc109fc02fac15 Mon Sep 17 00:00:00 2001
From: Dariusz Rybicki <dariusz@elixxir.io>
Date: Fri, 30 Sep 2022 13:36:19 +0200
Subject: [PATCH] Add MessengerMyContact function

---
 .../Functions/MessengerMyContact.swift        |  51 ++++++++
 .../Messenger/Messenger.swift                 |   3 +
 .../Functions/MessengerMyContactTests.swift   | 121 ++++++++++++++++++
 3 files changed, 175 insertions(+)
 create mode 100644 Sources/XXMessengerClient/Messenger/Functions/MessengerMyContact.swift
 create mode 100644 Tests/XXMessengerClientTests/Messenger/Functions/MessengerMyContactTests.swift

diff --git a/Sources/XXMessengerClient/Messenger/Functions/MessengerMyContact.swift b/Sources/XXMessengerClient/Messenger/Functions/MessengerMyContact.swift
new file mode 100644
index 00000000..bcedd164
--- /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 41c61329..692d81fd 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 00000000..11367761
--- /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
+      )
+    }
+  }
+}
-- 
GitLab