From a8031c0769a5b1c7003bdb70ccf9ccffd5434033 Mon Sep 17 00:00:00 2001
From: Dariusz Rybicki <dariusz@elixxir.io>
Date: Fri, 21 Oct 2022 11:24:00 +0200
Subject: [PATCH] Migrate CheckContactAuthFeature to ReducerProtocol

---
 .../CheckContactAuthComponent.swift           | 72 ++++++++++++++
 .../CheckContactAuthFeature.swift             | 94 -------------------
 .../CheckContactAuthView.swift                | 13 ++-
 ...t => CheckContactAuthComponentTests.swift} | 39 ++++----
 4 files changed, 96 insertions(+), 122 deletions(-)
 create mode 100644 Examples/xx-messenger/Sources/CheckContactAuthFeature/CheckContactAuthComponent.swift
 delete mode 100644 Examples/xx-messenger/Sources/CheckContactAuthFeature/CheckContactAuthFeature.swift
 rename Examples/xx-messenger/Tests/CheckContactAuthFeatureTests/{CheckContactAuthFeatureTests.swift => CheckContactAuthComponentTests.swift} (80%)

diff --git a/Examples/xx-messenger/Sources/CheckContactAuthFeature/CheckContactAuthComponent.swift b/Examples/xx-messenger/Sources/CheckContactAuthFeature/CheckContactAuthComponent.swift
new file mode 100644
index 00000000..5c62fa8f
--- /dev/null
+++ b/Examples/xx-messenger/Sources/CheckContactAuthFeature/CheckContactAuthComponent.swift
@@ -0,0 +1,72 @@
+import AppCore
+import ComposableArchitecture
+import Foundation
+import XCTestDynamicOverlay
+import XXClient
+import XXMessengerClient
+import XXModels
+
+public struct CheckContactAuthComponent: ReducerProtocol {
+  public struct State: Equatable {
+    public enum Result: Equatable {
+      case success(Bool)
+      case failure(String)
+    }
+
+    public init(
+      contact: XXClient.Contact,
+      isChecking: Bool = false,
+      result: Result? = nil
+    ) {
+      self.contact = contact
+      self.isChecking = isChecking
+      self.result = result
+    }
+
+    public var contact: XXClient.Contact
+    public var isChecking: Bool
+    public var result: Result?
+  }
+
+  public enum Action: Equatable {
+    case checkTapped
+    case didCheck(State.Result)
+  }
+
+  @Dependency(\.app.messenger) var messenger: Messenger
+  @Dependency(\.app.dbManager.getDB) var db: DBManagerGetDB
+  @Dependency(\.app.mainQueue) var mainQueue: AnySchedulerOf<DispatchQueue>
+  @Dependency(\.app.bgQueue) var bgQueue: AnySchedulerOf<DispatchQueue>
+
+  public init() {}
+
+  public func reduce(into state: inout State, action: Action) -> EffectTask<Action> {
+    switch action {
+    case .checkTapped:
+      state.isChecking = true
+      state.result = nil
+      return Effect.result { [state] in
+        do {
+          let e2e = try messenger.e2e.tryGet()
+          let contactId = try state.contact.getId()
+          let result = try e2e.hasAuthenticatedChannel(partnerId: contactId)
+          try db().bulkUpdateContacts.callAsFunction(
+            .init(id: [contactId]),
+            .init(authStatus: result ? .friend : .stranger)
+          )
+          return .success(.didCheck(.success(result)))
+        } catch {
+          return .success(.didCheck(.failure(error.localizedDescription)))
+        }
+      }
+      .subscribe(on: bgQueue)
+      .receive(on: mainQueue)
+      .eraseToEffect()
+
+    case .didCheck(let result):
+      state.isChecking = false
+      state.result = result
+      return .none
+    }
+  }
+}
diff --git a/Examples/xx-messenger/Sources/CheckContactAuthFeature/CheckContactAuthFeature.swift b/Examples/xx-messenger/Sources/CheckContactAuthFeature/CheckContactAuthFeature.swift
deleted file mode 100644
index 1f768be8..00000000
--- a/Examples/xx-messenger/Sources/CheckContactAuthFeature/CheckContactAuthFeature.swift
+++ /dev/null
@@ -1,94 +0,0 @@
-import AppCore
-import ComposableArchitecture
-import Foundation
-import XCTestDynamicOverlay
-import XXClient
-import XXMessengerClient
-import XXModels
-
-public struct CheckContactAuthState: Equatable {
-  public enum Result: Equatable {
-    case success(Bool)
-    case failure(String)
-  }
-
-  public init(
-    contact: XXClient.Contact,
-    isChecking: Bool = false,
-    result: Result? = nil
-  ) {
-    self.contact = contact
-    self.isChecking = isChecking
-    self.result = result
-  }
-
-  public var contact: XXClient.Contact
-  public var isChecking: Bool
-  public var result: Result?
-}
-
-public enum CheckContactAuthAction: Equatable {
-  case checkTapped
-  case didCheck(CheckContactAuthState.Result)
-}
-
-public struct CheckContactAuthEnvironment {
-  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 CheckContactAuthEnvironment {
-  public static let unimplemented = CheckContactAuthEnvironment(
-    messenger: .unimplemented,
-    db: .unimplemented,
-    mainQueue: .unimplemented,
-    bgQueue: .unimplemented
-  )
-}
-#endif
-
-public let checkContactAuthReducer = Reducer<CheckContactAuthState, CheckContactAuthAction, CheckContactAuthEnvironment>
-{ state, action, env in
-  switch action {
-  case .checkTapped:
-    state.isChecking = true
-    state.result = nil
-    return Effect.result { [state] in
-      do {
-        let e2e = try env.messenger.e2e.tryGet()
-        let contactId = try state.contact.getId()
-        let result = try e2e.hasAuthenticatedChannel(partnerId: contactId)
-        try env.db().bulkUpdateContacts.callAsFunction(
-          .init(id: [contactId]),
-          .init(authStatus: result ? .friend : .stranger)
-        )
-        return .success(.didCheck(.success(result)))
-      } catch {
-        return .success(.didCheck(.failure(error.localizedDescription)))
-      }
-    }
-    .subscribe(on: env.bgQueue)
-    .receive(on: env.mainQueue)
-    .eraseToEffect()
-
-  case .didCheck(let result):
-    state.isChecking = false
-    state.result = result
-    return .none
-  }
-}
diff --git a/Examples/xx-messenger/Sources/CheckContactAuthFeature/CheckContactAuthView.swift b/Examples/xx-messenger/Sources/CheckContactAuthFeature/CheckContactAuthView.swift
index dd2e7894..b4b75bbc 100644
--- a/Examples/xx-messenger/Sources/CheckContactAuthFeature/CheckContactAuthView.swift
+++ b/Examples/xx-messenger/Sources/CheckContactAuthFeature/CheckContactAuthView.swift
@@ -3,20 +3,20 @@ import SwiftUI
 import XXClient
 
 public struct CheckContactAuthView: View {
-  public init(store: Store<CheckContactAuthState, CheckContactAuthAction>) {
+  public init(store: StoreOf<CheckContactAuthComponent>) {
     self.store = store
   }
 
-  let store: Store<CheckContactAuthState, CheckContactAuthAction>
+  let store: StoreOf<CheckContactAuthComponent>
 
   struct ViewState: Equatable {
     var username: String?
     var email: String?
     var phone: String?
     var isChecking: Bool
-    var result: CheckContactAuthState.Result?
+    var result: CheckContactAuthComponent.State.Result?
 
-    init(state: CheckContactAuthState) {
+    init(state: CheckContactAuthComponent.State) {
       username = try? state.contact.getFact(.username)?.value
       email = try? state.contact.getFact(.email)?.value
       phone = try? state.contact.getFact(.phone)?.value
@@ -90,11 +90,10 @@ public struct CheckContactAuthView: View {
 public struct CheckContactAuthView_Previews: PreviewProvider {
   public static var previews: some View {
     CheckContactAuthView(store: Store(
-      initialState: CheckContactAuthState(
+      initialState: CheckContactAuthComponent.State(
         contact: .unimplemented("contact-data".data(using: .utf8)!)
       ),
-      reducer: .empty,
-      environment: ()
+      reducer: EmptyReducer()
     ))
   }
 }
diff --git a/Examples/xx-messenger/Tests/CheckContactAuthFeatureTests/CheckContactAuthFeatureTests.swift b/Examples/xx-messenger/Tests/CheckContactAuthFeatureTests/CheckContactAuthComponentTests.swift
similarity index 80%
rename from Examples/xx-messenger/Tests/CheckContactAuthFeatureTests/CheckContactAuthFeatureTests.swift
rename to Examples/xx-messenger/Tests/CheckContactAuthFeatureTests/CheckContactAuthComponentTests.swift
index a13645f2..78031cb5 100644
--- a/Examples/xx-messenger/Tests/CheckContactAuthFeatureTests/CheckContactAuthFeatureTests.swift
+++ b/Examples/xx-messenger/Tests/CheckContactAuthFeatureTests/CheckContactAuthComponentTests.swift
@@ -5,27 +5,26 @@ import XXClient
 import XXModels
 @testable import CheckContactAuthFeature
 
-final class CheckContactAuthFeatureTests: XCTestCase {
+final class CheckContactAuthComponentTests: XCTestCase {
   func testCheck() {
     var contact = XXClient.Contact.unimplemented("contact-data".data(using: .utf8)!)
     let contactId = "contact-id".data(using: .utf8)!
     contact.getIdFromContact.run = { _ in contactId }
 
     let store = TestStore(
-      initialState: CheckContactAuthState(
+      initialState: CheckContactAuthComponent.State(
         contact: contact
       ),
-      reducer: checkContactAuthReducer,
-      environment: .unimplemented
+      reducer: CheckContactAuthComponent()
     )
 
     var didCheckPartnerId: [Data] = []
     var didBulkUpdateContactsWithQuery: [XXModels.Contact.Query] = []
     var didBulkUpdateContactsWithAssignments: [XXModels.Contact.Assignments] = []
 
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.e2e.get = {
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.messenger.e2e.get = {
       var e2e: E2E = .unimplemented
       e2e.hasAuthenticatedChannel.run = { partnerId in
         didCheckPartnerId.append(partnerId)
@@ -33,7 +32,7 @@ final class CheckContactAuthFeatureTests: XCTestCase {
       }
       return e2e
     }
-    store.environment.db.run = {
+    store.dependencies.app.dbManager.getDB.run = {
       var db: Database = .unimplemented
       db.bulkUpdateContacts.run = { query, assignments in
         didBulkUpdateContactsWithQuery.append(query)
@@ -64,20 +63,19 @@ final class CheckContactAuthFeatureTests: XCTestCase {
     contact.getIdFromContact.run = { _ in contactId }
 
     let store = TestStore(
-      initialState: CheckContactAuthState(
+      initialState: CheckContactAuthComponent.State(
         contact: contact
       ),
-      reducer: checkContactAuthReducer,
-      environment: .unimplemented
+      reducer: CheckContactAuthComponent()
     )
 
     var didCheckPartnerId: [Data] = []
     var didBulkUpdateContactsWithQuery: [XXModels.Contact.Query] = []
     var didBulkUpdateContactsWithAssignments: [XXModels.Contact.Assignments] = []
 
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.e2e.get = {
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.messenger.e2e.get = {
       var e2e: E2E = .unimplemented
       e2e.hasAuthenticatedChannel.run = { partnerId in
         didCheckPartnerId.append(partnerId)
@@ -85,7 +83,7 @@ final class CheckContactAuthFeatureTests: XCTestCase {
       }
       return e2e
     }
-    store.environment.db.run = {
+    store.dependencies.app.dbManager.getDB.run = {
       var db: Database = .unimplemented
       db.bulkUpdateContacts.run = { query, assignments in
         didBulkUpdateContactsWithQuery.append(query)
@@ -116,19 +114,18 @@ final class CheckContactAuthFeatureTests: XCTestCase {
     contact.getIdFromContact.run = { _ in contactId }
 
     let store = TestStore(
-      initialState: CheckContactAuthState(
+      initialState: CheckContactAuthComponent.State(
         contact: contact
       ),
-      reducer: checkContactAuthReducer,
-      environment: .unimplemented
+      reducer: CheckContactAuthComponent()
     )
 
     struct Failure: Error {}
     let error = Failure()
 
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.e2e.get = {
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.messenger.e2e.get = {
       var e2e: E2E = .unimplemented
       e2e.hasAuthenticatedChannel.run = { _ in throw error }
       return e2e
-- 
GitLab