From 6d8016da7726878a0131540c6c6a7f060a69fcad Mon Sep 17 00:00:00 2001
From: Dariusz Rybicki <dariusz@elixxir.io>
Date: Fri, 21 Oct 2022 10:46:35 +0200
Subject: [PATCH] Migrate ContactLookupFeature to ReducerProtocol

---
 .../ContactLookupComponent.swift              | 62 ++++++++++++++
 .../ContactLookupFeature.swift                | 83 -------------------
 .../ContactLookupView.swift                   | 11 ++-
 ...wift => ContactLookupComponentTests.swift} | 24 +++---
 4 files changed, 78 insertions(+), 102 deletions(-)
 create mode 100644 Examples/xx-messenger/Sources/ContactLookupFeature/ContactLookupComponent.swift
 delete mode 100644 Examples/xx-messenger/Sources/ContactLookupFeature/ContactLookupFeature.swift
 rename Examples/xx-messenger/Tests/ContactLookupFeatureTests/{ContactLookupFeatureTests.swift => ContactLookupComponentTests.swift} (60%)

diff --git a/Examples/xx-messenger/Sources/ContactLookupFeature/ContactLookupComponent.swift b/Examples/xx-messenger/Sources/ContactLookupFeature/ContactLookupComponent.swift
new file mode 100644
index 00000000..b581f3f0
--- /dev/null
+++ b/Examples/xx-messenger/Sources/ContactLookupFeature/ContactLookupComponent.swift
@@ -0,0 +1,62 @@
+import ComposableArchitecture
+import Foundation
+import XCTestDynamicOverlay
+import XXClient
+import XXMessengerClient
+
+public struct ContactLookupComponent: ReducerProtocol {
+  public struct State: Equatable {
+    public init(
+      id: Data,
+      isLookingUp: Bool = false,
+      failure: String? = nil
+    ) {
+      self.id = id
+      self.isLookingUp = isLookingUp
+      self.failure = failure
+    }
+
+    public var id: Data
+    public var isLookingUp: Bool
+    public var failure: String?
+  }
+
+  public enum Action: Equatable {
+    case lookupTapped
+    case didLookup(XXClient.Contact)
+    case didFail(NSError)
+  }
+
+  @Dependency(\.appDependencies.messenger) var messenger
+  @Dependency(\.appDependencies.mainQueue) var mainQueue
+  @Dependency(\.appDependencies.bgQueue) var bgQueue
+
+  public func reduce(into state: inout State, action: Action) -> EffectTask<Action> {
+    switch action {
+    case .lookupTapped:
+      state.isLookingUp = true
+      state.failure = nil
+      return Effect.result { [state] in
+        do {
+          let contact = try messenger.lookupContact(id: state.id)
+          return .success(.didLookup(contact))
+        } catch {
+          return .success(.didFail(error as NSError))
+        }
+      }
+      .subscribe(on: bgQueue)
+      .receive(on: mainQueue)
+      .eraseToEffect()
+
+    case .didLookup(_):
+      state.isLookingUp = false
+      state.failure = nil
+      return .none
+
+    case .didFail(let error):
+      state.isLookingUp = false
+      state.failure = error.localizedDescription
+      return .none
+    }
+  }
+}
diff --git a/Examples/xx-messenger/Sources/ContactLookupFeature/ContactLookupFeature.swift b/Examples/xx-messenger/Sources/ContactLookupFeature/ContactLookupFeature.swift
deleted file mode 100644
index 0b6f92dd..00000000
--- a/Examples/xx-messenger/Sources/ContactLookupFeature/ContactLookupFeature.swift
+++ /dev/null
@@ -1,83 +0,0 @@
-import ComposableArchitecture
-import Foundation
-import XCTestDynamicOverlay
-import XXClient
-import XXMessengerClient
-
-public struct ContactLookupState: Equatable {
-  public init(
-    id: Data,
-    isLookingUp: Bool = false,
-    failure: String? = nil
-  ) {
-    self.id = id
-    self.isLookingUp = isLookingUp
-    self.failure = failure
-  }
-
-  public var id: Data
-  public var isLookingUp: Bool
-  public var failure: String?
-}
-
-public enum ContactLookupAction: Equatable {
-  case lookupTapped
-  case didLookup(XXClient.Contact)
-  case didFail(NSError)
-}
-
-public struct ContactLookupEnvironment {
-  public init(
-    messenger: Messenger,
-    mainQueue: AnySchedulerOf<DispatchQueue>,
-    bgQueue: AnySchedulerOf<DispatchQueue>
-  ) {
-    self.messenger = messenger
-    self.mainQueue = mainQueue
-    self.bgQueue = bgQueue
-  }
-
-  public var messenger: Messenger
-  public var mainQueue: AnySchedulerOf<DispatchQueue>
-  public var bgQueue: AnySchedulerOf<DispatchQueue>
-}
-
-#if DEBUG
-extension ContactLookupEnvironment {
-  public static let unimplemented = ContactLookupEnvironment(
-    messenger: .unimplemented,
-    mainQueue: .unimplemented,
-    bgQueue: .unimplemented
-  )
-}
-#endif
-
-public let contactLookupReducer = Reducer<ContactLookupState, ContactLookupAction, ContactLookupEnvironment>
-{ state, action, env in
-  switch action {
-  case .lookupTapped:
-    state.isLookingUp = true
-    state.failure = nil
-    return Effect.result { [state] in
-      do {
-        let contact = try env.messenger.lookupContact(id: state.id)
-        return .success(.didLookup(contact))
-      } catch {
-        return .success(.didFail(error as NSError))
-      }
-    }
-    .subscribe(on: env.bgQueue)
-    .receive(on: env.mainQueue)
-    .eraseToEffect()
-
-  case .didLookup(_):
-    state.isLookingUp = false
-    state.failure = nil
-    return .none
-
-  case .didFail(let error):
-    state.isLookingUp = false
-    state.failure = error.localizedDescription
-    return .none
-  }
-}
diff --git a/Examples/xx-messenger/Sources/ContactLookupFeature/ContactLookupView.swift b/Examples/xx-messenger/Sources/ContactLookupFeature/ContactLookupView.swift
index 6ce83eda..c4850fab 100644
--- a/Examples/xx-messenger/Sources/ContactLookupFeature/ContactLookupView.swift
+++ b/Examples/xx-messenger/Sources/ContactLookupFeature/ContactLookupView.swift
@@ -3,14 +3,14 @@ import ComposableArchitecture
 import SwiftUI
 
 public struct ContactLookupView: View {
-  public init(store: Store<ContactLookupState, ContactLookupAction>) {
+  public init(store: StoreOf<ContactLookupComponent>) {
     self.store = store
   }
 
-  let store: Store<ContactLookupState, ContactLookupAction>
+  let store: StoreOf<ContactLookupComponent>
 
   struct ViewState: Equatable {
-    init(state: ContactLookupState) {
+    init(state: ContactLookupComponent.State) {
       id = state.id
       isLookingUp = state.isLookingUp
       failure = state.failure
@@ -64,11 +64,10 @@ public struct ContactLookupView_Previews: PreviewProvider {
   public static var previews: some View {
     NavigationView {
       ContactLookupView(store: Store(
-        initialState: ContactLookupState(
+        initialState: ContactLookupComponent.State(
           id: "1234".data(using: .utf8)!
         ),
-        reducer: .empty,
-        environment: ()
+        reducer: EmptyReducer()
       ))
     }
   }
diff --git a/Examples/xx-messenger/Tests/ContactLookupFeatureTests/ContactLookupFeatureTests.swift b/Examples/xx-messenger/Tests/ContactLookupFeatureTests/ContactLookupComponentTests.swift
similarity index 60%
rename from Examples/xx-messenger/Tests/ContactLookupFeatureTests/ContactLookupFeatureTests.swift
rename to Examples/xx-messenger/Tests/ContactLookupFeatureTests/ContactLookupComponentTests.swift
index 76dde8d0..dcbb3622 100644
--- a/Examples/xx-messenger/Tests/ContactLookupFeatureTests/ContactLookupFeatureTests.swift
+++ b/Examples/xx-messenger/Tests/ContactLookupFeatureTests/ContactLookupComponentTests.swift
@@ -3,20 +3,19 @@ import XCTest
 import XXClient
 @testable import ContactLookupFeature
 
-final class ContactLookupFeatureTests: XCTestCase {
+final class ContactLookupComponentTests: XCTestCase {
   func testLookup() {
     let id: Data = "1234".data(using: .utf8)!
     var didLookupId: [Data] = []
     let lookedUpContact = Contact.unimplemented("123data".data(using: .utf8)!)
 
     let store = TestStore(
-      initialState: ContactLookupState(id: id),
-      reducer: contactLookupReducer,
-      environment: .unimplemented
+      initialState: ContactLookupComponent.State(id: id),
+      reducer: ContactLookupComponent()
     )
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.lookupContact.run = { id in
+    store.dependencies.appDependencies.mainQueue = .immediate
+    store.dependencies.appDependencies.bgQueue = .immediate
+    store.dependencies.appDependencies.messenger.lookupContact.run = { id in
       didLookupId.append(id)
       return lookedUpContact
     }
@@ -39,13 +38,12 @@ final class ContactLookupFeatureTests: XCTestCase {
     let failure = NSError(domain: "test", code: 0)
 
     let store = TestStore(
-      initialState: ContactLookupState(id: id),
-      reducer: contactLookupReducer,
-      environment: .unimplemented
+      initialState: ContactLookupComponent.State(id: id),
+      reducer: ContactLookupComponent()
     )
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.lookupContact.run = { _ in throw failure }
+    store.dependencies.appDependencies.mainQueue = .immediate
+    store.dependencies.appDependencies.bgQueue = .immediate
+    store.dependencies.appDependencies.messenger.lookupContact.run = { _ in throw failure }
 
     store.send(.lookupTapped) {
       $0.isLookingUp = true
-- 
GitLab