From 15798ff9a952591d190a899230c8bb4a560e4058 Mon Sep 17 00:00:00 2001
From: Dariusz Rybicki <dariusz@elixxir.io>
Date: Wed, 7 Sep 2022 15:18:40 +0200
Subject: [PATCH] Fetch my facts in SendRequestFeature

---
 .../AppFeature/AppEnvironment+Live.swift      |  7 +-
 .../SendRequestFeature.swift                  | 46 ++++++++++++-
 .../SendRequestFeatureTests.swift             | 68 +++++++++++++++++++
 3 files changed, 118 insertions(+), 3 deletions(-)

diff --git a/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift b/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift
index 9b298c38..298cb9f6 100644
--- a/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift
+++ b/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift
@@ -63,7 +63,12 @@ extension AppEnvironment {
                   mainQueue: mainQueue,
                   bgQueue: bgQueue,
                   sendRequest: {
-                    SendRequestEnvironment()
+                    SendRequestEnvironment(
+                      messenger: messenger,
+                      db: dbManager.getDB,
+                      mainQueue: mainQueue,
+                      bgQueue: bgQueue
+                    )
                   }
                 )
               }
diff --git a/Examples/xx-messenger/Sources/SendRequestFeature/SendRequestFeature.swift b/Examples/xx-messenger/Sources/SendRequestFeature/SendRequestFeature.swift
index cefd80d3..8740c744 100644
--- a/Examples/xx-messenger/Sources/SendRequestFeature/SendRequestFeature.swift
+++ b/Examples/xx-messenger/Sources/SendRequestFeature/SendRequestFeature.swift
@@ -1,6 +1,9 @@
+import AppCore
 import ComposableArchitecture
+import Foundation
 import XCTestDynamicOverlay
 import XXClient
+import XXMessengerClient
 import XXModels
 
 public struct SendRequestState: Equatable {
@@ -35,22 +38,60 @@ public enum SendRequestAction: Equatable, BindableAction {
   case start
   case sendTapped
   case binding(BindingAction<SendRequestState>)
+  case myContactFetched(XXClient.Contact?)
 }
 
 public struct SendRequestEnvironment {
-  public init() {}
+  public init(
+    messenger: Messenger,
+    db: DBManagerGetDB,
+    mainQueue: AnySchedulerOf<DispatchQueue>,
+    bgQueue: AnySchedulerOf<DispatchQueue>
+  ) {
+    self.messenger = messenger
+    self.db = db
+    self.mainQueue = mainQueue
+    self.bgQueue = bgQueue
+  }
+
+  public var messenger: Messenger
+  public var db: DBManagerGetDB
+  public var mainQueue: AnySchedulerOf<DispatchQueue>
+  public var bgQueue: AnySchedulerOf<DispatchQueue>
 }
 
 #if DEBUG
 extension SendRequestEnvironment {
-  public static let unimplemented = SendRequestEnvironment()
+  public static let unimplemented = SendRequestEnvironment(
+    messenger: .unimplemented,
+    db: .unimplemented,
+    mainQueue: .unimplemented,
+    bgQueue: .unimplemented
+  )
 }
 #endif
 
 public let sendRequestReducer = Reducer<SendRequestState, SendRequestAction, SendRequestEnvironment>
 { state, action, env in
+  enum DBFetchEffectID {}
+
   switch action {
   case .start:
+    return Effect
+      .catching { try env.messenger.e2e.tryGet().getContact().getId() }
+      .tryMap { try env.db().fetchContactsPublisher(.init(id: [$0])) }
+      .flatMap { $0 }
+      .assertNoFailure()
+      .map(\.first)
+      .map { $0?.marshaled.map { XXClient.Contact.live($0) } }
+      .map(SendRequestAction.myContactFetched)
+      .subscribe(on: env.bgQueue)
+      .receive(on: env.mainQueue)
+      .eraseToEffect()
+      .cancellable(id: DBFetchEffectID.self, cancelInFlight: true)
+
+  case .myContactFetched(let contact):
+    state.myContact = contact
     return .none
 
   case .sendTapped:
@@ -60,3 +101,4 @@ public let sendRequestReducer = Reducer<SendRequestState, SendRequestAction, Sen
     return .none
   }
 }
+.binding()
diff --git a/Examples/xx-messenger/Tests/SendRequestFeatureTests/SendRequestFeatureTests.swift b/Examples/xx-messenger/Tests/SendRequestFeatureTests/SendRequestFeatureTests.swift
index a67a241c..a0a7750f 100644
--- a/Examples/xx-messenger/Tests/SendRequestFeatureTests/SendRequestFeatureTests.swift
+++ b/Examples/xx-messenger/Tests/SendRequestFeatureTests/SendRequestFeatureTests.swift
@@ -1,5 +1,8 @@
+import Combine
 import ComposableArchitecture
 import XCTest
+import XXClient
+import XXModels
 @testable import SendRequestFeature
 
 final class SendRequestFeatureTests: XCTestCase {
@@ -12,6 +15,71 @@ final class SendRequestFeatureTests: XCTestCase {
       environment: .unimplemented
     )
 
+    var dbDidFetchContacts: [XXModels.Contact.Query] = []
+    let dbContactsPublisher = PassthroughSubject<[XXModels.Contact], Error>()
+
+    store.environment.mainQueue = .immediate
+    store.environment.bgQueue = .immediate
+    store.environment.messenger.e2e.get = {
+      var e2e: E2E = .unimplemented
+      e2e.getContact.run = {
+        var contact: XXClient.Contact = .unimplemented("my-contact-data".data(using: .utf8)!)
+        contact.getIdFromContact.run = { _ in "my-contact-id".data(using: .utf8)! }
+        return contact
+      }
+      return e2e
+    }
+    store.environment.db.run = {
+      var db: Database = .failing
+      db.fetchContactsPublisher.run = { query in
+        dbDidFetchContacts.append(query)
+        return dbContactsPublisher.eraseToAnyPublisher()
+      }
+      return db
+    }
+
     store.send(.start)
+
+    XCTAssertNoDifference(dbDidFetchContacts, [.init(id: ["my-contact-id".data(using: .utf8)!])])
+
+    dbContactsPublisher.send([])
+
+    store.receive(.myContactFetched(nil))
+
+    var myDbContact = XXModels.Contact(id: "my-contact-id".data(using: .utf8)!)
+    myDbContact.marshaled = "my-contact-data".data(using: .utf8)!
+    dbContactsPublisher.send([myDbContact])
+
+    store.receive(.myContactFetched(.live("my-contact-data".data(using: .utf8)!))) {
+      $0.myContact = .live("my-contact-data".data(using: .utf8)!)
+    }
+
+    dbContactsPublisher.send(completion: .finished)
+  }
+
+  func testSendRequest() {
+    var myContact: XXClient.Contact = .unimplemented("my-contact-data".data(using: .utf8)!)
+    myContact.getFactsFromContact.run = { _ in
+      [
+        Fact(fact: "my-username", type: 0),
+        Fact(fact: "my-email", type: 1),
+        Fact(fact: "my-phone", type: 2),
+      ]
+    }
+
+    let store = TestStore(
+      initialState: SendRequestState(
+        contact: .unimplemented("contact-data".data(using: .utf8)!),
+        myContact: myContact
+      ),
+      reducer: sendRequestReducer,
+      environment: .unimplemented
+    )
+
+    store.send(.set(\.$sendPhone, false)) {
+      $0.sendPhone = false
+    }
+
+    store.send(.sendTapped)
   }
 }
-- 
GitLab