From fccbe606f3b49ed556ca938359451ab36e9b8ef5 Mon Sep 17 00:00:00 2001
From: Dariusz Rybicki <dariusz@elixxir.io>
Date: Wed, 3 Aug 2022 13:24:08 +0100
Subject: [PATCH] Update LandingFeature

---
 Example/example-app/Package.swift             |   4 +
 .../LandingFeature/LandingFeature.swift       | 107 ++++++------
 .../Sources/LandingFeature/LandingView.swift  |  30 ++--
 .../LandingFeatureTests.swift                 | 158 +++++++++---------
 4 files changed, 148 insertions(+), 151 deletions(-)

diff --git a/Example/example-app/Package.swift b/Example/example-app/Package.swift
index 64bcd4ba..1d3dc343 100644
--- a/Example/example-app/Package.swift
+++ b/Example/example-app/Package.swift
@@ -140,6 +140,10 @@ let package = Package(
           name: "ElixxirDAppsSDK",
           package: "elixxir-dapps-sdk-swift"
         ),
+        .product(
+          name: "XCTestDynamicOverlay",
+          package: "xctest-dynamic-overlay"
+        ),
       ],
       swiftSettings: swiftSettings
     ),
diff --git a/Example/example-app/Sources/LandingFeature/LandingFeature.swift b/Example/example-app/Sources/LandingFeature/LandingFeature.swift
index 511b1107..f8fa2d9d 100644
--- a/Example/example-app/Sources/LandingFeature/LandingFeature.swift
+++ b/Example/example-app/Sources/LandingFeature/LandingFeature.swift
@@ -2,58 +2,59 @@ import Combine
 import ComposableArchitecture
 import ElixxirDAppsSDK
 import ErrorFeature
+import XCTestDynamicOverlay
 
 public struct LandingState: Equatable {
   public init(
     id: UUID,
-    hasStoredClient: Bool = false,
-    isMakingClient: Bool = false,
-    isRemovingClient: Bool = false,
+    hasStoredCmix: Bool = false,
+    isMakingCmix: Bool = false,
+    isRemovingCmix: Bool = false,
     error: ErrorState? = nil
   ) {
     self.id = id
-    self.hasStoredClient = hasStoredClient
-    self.isMakingClient = isMakingClient
-    self.isRemovingClient = isRemovingClient
+    self.hasStoredCmix = hasStoredCmix
+    self.isMakingCmix = isMakingCmix
+    self.isRemovingCmix = isRemovingCmix
     self.error = error
   }
 
   var id: UUID
-  var hasStoredClient: Bool
-  var isMakingClient: Bool
-  var isRemovingClient: Bool
+  var hasStoredCmix: Bool
+  var isMakingCmix: Bool
+  var isRemovingCmix: Bool
   var error: ErrorState?
 }
 
 public enum LandingAction: Equatable {
   case viewDidLoad
-  case makeClient
-  case didMakeClient
-  case didFailMakingClient(NSError)
-  case removeStoredClient
-  case didRemoveStoredClient
-  case didFailRemovingStoredClient(NSError)
+  case makeCmix
+  case didMakeCmix
+  case didFailMakingCmix(NSError)
+  case removeStoredCmix
+  case didRemoveStoredCmix
+  case didFailRemovingStoredCmix(NSError)
   case didDismissError
   case error(ErrorAction)
 }
 
 public struct LandingEnvironment {
   public init(
-    clientStorage: ClientStorage,
-    setClient: @escaping (Client) -> Void,
+    cmixManager: CmixManager,
+    setCmix: @escaping (Cmix) -> Void,
     bgScheduler: AnySchedulerOf<DispatchQueue>,
     mainScheduler: AnySchedulerOf<DispatchQueue>,
     error: ErrorEnvironment
   ) {
-    self.clientStorage = clientStorage
-    self.setClient = setClient
+    self.cmixManager = cmixManager
+    self.setCmix = setCmix
     self.bgScheduler = bgScheduler
     self.mainScheduler = mainScheduler
     self.error = error
   }
 
-  public var clientStorage: ClientStorage
-  public var setClient: (Client) -> Void
+  public var cmixManager: CmixManager
+  public var setCmix: (Cmix) -> Void
   public var bgScheduler: AnySchedulerOf<DispatchQueue>
   public var mainScheduler: AnySchedulerOf<DispatchQueue>
   public var error: ErrorEnvironment
@@ -63,60 +64,60 @@ public let landingReducer = Reducer<LandingState, LandingAction, LandingEnvironm
 { state, action, env in
   switch action {
   case .viewDidLoad:
-    state.hasStoredClient = env.clientStorage.hasStoredClient()
+    state.hasStoredCmix = env.cmixManager.hasStorage()
     return .none
 
-  case .makeClient:
-    state.isMakingClient = true
+  case .makeCmix:
+    state.isMakingCmix = true
     return Effect.future { fulfill in
       do {
-        if env.clientStorage.hasStoredClient() {
-          env.setClient(try env.clientStorage.loadClient())
+        if env.cmixManager.hasStorage() {
+          env.setCmix(try env.cmixManager.load())
         } else {
-          env.setClient(try env.clientStorage.createClient())
+          env.setCmix(try env.cmixManager.create())
         }
-        fulfill(.success(.didMakeClient))
+        fulfill(.success(.didMakeCmix))
       } catch {
-        fulfill(.success(.didFailMakingClient(error as NSError)))
+        fulfill(.success(.didFailMakingCmix(error as NSError)))
       }
     }
     .subscribe(on: env.bgScheduler)
     .receive(on: env.mainScheduler)
     .eraseToEffect()
 
-  case .didMakeClient:
-    state.isMakingClient = false
-    state.hasStoredClient = env.clientStorage.hasStoredClient()
+  case .didMakeCmix:
+    state.isMakingCmix = false
+    state.hasStoredCmix = env.cmixManager.hasStorage()
     return .none
 
-  case .didFailMakingClient(let error):
-    state.isMakingClient = false
-    state.hasStoredClient = env.clientStorage.hasStoredClient()
+  case .didFailMakingCmix(let error):
+    state.isMakingCmix = false
+    state.hasStoredCmix = env.cmixManager.hasStorage()
     state.error = ErrorState(error: error)
     return .none
 
-  case .removeStoredClient:
-    state.isRemovingClient = true
+  case .removeStoredCmix:
+    state.isRemovingCmix = true
     return Effect.future { fulfill in
       do {
-        try env.clientStorage.removeClient()
-        fulfill(.success(.didRemoveStoredClient))
+        try env.cmixManager.remove()
+        fulfill(.success(.didRemoveStoredCmix))
       } catch {
-        fulfill(.success(.didFailRemovingStoredClient(error as NSError)))
+        fulfill(.success(.didFailRemovingStoredCmix(error as NSError)))
       }
     }
     .subscribe(on: env.bgScheduler)
     .receive(on: env.mainScheduler)
     .eraseToEffect()
 
-  case .didRemoveStoredClient:
-    state.isRemovingClient = false
-    state.hasStoredClient = env.clientStorage.hasStoredClient()
+  case .didRemoveStoredCmix:
+    state.isRemovingCmix = false
+    state.hasStoredCmix = env.cmixManager.hasStorage()
     return .none
 
-  case .didFailRemovingStoredClient(let error):
-    state.isRemovingClient = false
-    state.hasStoredClient = env.clientStorage.hasStoredClient()
+  case .didFailRemovingStoredCmix(let error):
+    state.isRemovingCmix = false
+    state.hasStoredCmix = env.cmixManager.hasStorage()
     state.error = ErrorState(error: error)
     return .none
 
@@ -133,14 +134,12 @@ public let landingReducer = Reducer<LandingState, LandingAction, LandingEnvironm
   environment: \.error
 )
 
-#if DEBUG
 extension LandingEnvironment {
-  public static let failing = LandingEnvironment(
-    clientStorage: .failing,
-    setClient: { _ in fatalError() },
-    bgScheduler: .failing,
-    mainScheduler: .failing,
-    error: .failing
+  public static let unimplemented = LandingEnvironment(
+    cmixManager: .unimplemented,
+    setCmix: XCTUnimplemented("\(Self.self).setCmix"),
+    bgScheduler: .unimplemented,
+    mainScheduler: .unimplemented,
+    error: .unimplemented
   )
 }
-#endif
diff --git a/Example/example-app/Sources/LandingFeature/LandingView.swift b/Example/example-app/Sources/LandingFeature/LandingView.swift
index 4a45669a..f52aeebb 100644
--- a/Example/example-app/Sources/LandingFeature/LandingView.swift
+++ b/Example/example-app/Sources/LandingFeature/LandingView.swift
@@ -11,19 +11,19 @@ public struct LandingView: View {
   let store: Store<LandingState, LandingAction>
 
   struct ViewState: Equatable {
-    let hasStoredClient: Bool
-    let isMakingClient: Bool
-    let isRemovingClient: Bool
+    let hasStoredCmix: Bool
+    let isMakingCmix: Bool
+    let isRemovingCmix: Bool
 
     init(state: LandingState) {
-      hasStoredClient = state.hasStoredClient
-      isMakingClient = state.isMakingClient
-      isRemovingClient = state.isRemovingClient
+      hasStoredCmix = state.hasStoredCmix
+      isMakingCmix = state.isMakingCmix
+      isRemovingCmix = state.isRemovingCmix
     }
 
     var isLoading: Bool {
-      isMakingClient ||
-      isRemovingClient
+      isMakingCmix ||
+      isRemovingCmix
     }
   }
 
@@ -31,25 +31,25 @@ public struct LandingView: View {
     WithViewStore(store.scope(state: ViewState.init)) { viewStore in
       Form {
         Button {
-          viewStore.send(.makeClient)
+          viewStore.send(.makeCmix)
         } label: {
           HStack {
-            Text(viewStore.hasStoredClient ? "Load stored client" : "Create new client")
+            Text(viewStore.hasStoredCmix ? "Load stored cMix" : "Create new cMix")
             Spacer()
-            if viewStore.isMakingClient {
+            if viewStore.isMakingCmix {
               ProgressView()
             }
           }
         }
 
-        if viewStore.hasStoredClient {
+        if viewStore.hasStoredCmix {
           Button(role: .destructive) {
-            viewStore.send(.removeStoredClient)
+            viewStore.send(.removeStoredCmix)
           } label: {
             HStack {
-              Text("Remove stored client")
+              Text("Remove stored cMix")
               Spacer()
-              if viewStore.isRemovingClient {
+              if viewStore.isRemovingCmix {
                 ProgressView()
               }
             }
diff --git a/Example/example-app/Tests/LandingFeatureTests/LandingFeatureTests.swift b/Example/example-app/Tests/LandingFeatureTests/LandingFeatureTests.swift
index c5b56f98..cb52fb7b 100644
--- a/Example/example-app/Tests/LandingFeatureTests/LandingFeatureTests.swift
+++ b/Example/example-app/Tests/LandingFeatureTests/LandingFeatureTests.swift
@@ -5,183 +5,177 @@ import XCTest
 
 final class LandingFeatureTests: XCTestCase {
   func testViewDidLoad() throws {
-    var env = LandingEnvironment.failing
-    env.clientStorage.hasStoredClient = { true }
-
     let store = TestStore(
       initialState: LandingState(id: UUID()),
       reducer: landingReducer,
-      environment: env
+      environment: .unimplemented
     )
 
+    store.environment.cmixManager.hasStorage.run = { true }
+
     store.send(.viewDidLoad) {
-      $0.hasStoredClient = true
+      $0.hasStoredCmix = true
     }
   }
 
-  func testCreateClient() {
-    var hasStoredClient = false
-    var didSetClient = false
+  func testCreateCmix() {
+    var hasStoredCmix = false
+    var didSetCmix = false
     let bgScheduler = DispatchQueue.test
     let mainScheduler = DispatchQueue.test
 
-    var env = LandingEnvironment.failing
-    env.clientStorage.hasStoredClient = { hasStoredClient }
-    env.clientStorage.createClient = { .failing }
-    env.setClient = { _ in didSetClient = true }
-    env.bgScheduler = bgScheduler.eraseToAnyScheduler()
-    env.mainScheduler = mainScheduler.eraseToAnyScheduler()
-
     let store = TestStore(
       initialState: LandingState(id: UUID()),
       reducer: landingReducer,
-      environment: env
+      environment: .unimplemented
     )
 
-    store.send(.makeClient) {
-      $0.isMakingClient = true
+    store.environment.cmixManager.hasStorage.run = { hasStoredCmix }
+    store.environment.cmixManager.create.run = { .unimplemented }
+    store.environment.setCmix = { _ in didSetCmix = true }
+    store.environment.bgScheduler = bgScheduler.eraseToAnyScheduler()
+    store.environment.mainScheduler = mainScheduler.eraseToAnyScheduler()
+
+    store.send(.makeCmix) {
+      $0.isMakingCmix = true
     }
 
     bgScheduler.advance()
 
-    XCTAssertTrue(didSetClient)
+    XCTAssertTrue(didSetCmix)
 
-    hasStoredClient = true
+    hasStoredCmix = true
     mainScheduler.advance()
 
-    store.receive(.didMakeClient) {
-      $0.isMakingClient = false
-      $0.hasStoredClient = true
+    store.receive(.didMakeCmix) {
+      $0.isMakingCmix = false
+      $0.hasStoredCmix = true
     }
   }
 
-  func testLoadStoredClient() {
-    var didSetClient = false
+  func testLoadStoredCmix() {
+    var didSetCmix = false
     let bgScheduler = DispatchQueue.test
     let mainScheduler = DispatchQueue.test
 
-    var env = LandingEnvironment.failing
-    env.clientStorage.hasStoredClient = { true }
-    env.clientStorage.loadClient = { .failing }
-    env.setClient = { _ in didSetClient = true }
-    env.bgScheduler = bgScheduler.eraseToAnyScheduler()
-    env.mainScheduler = mainScheduler.eraseToAnyScheduler()
-
     let store = TestStore(
       initialState: LandingState(id: UUID()),
       reducer: landingReducer,
-      environment: env
+      environment: .unimplemented
     )
 
-    store.send(.makeClient) {
-      $0.isMakingClient = true
+    store.environment.cmixManager.hasStorage.run = { true }
+    store.environment.cmixManager.load.run = { .unimplemented }
+    store.environment.setCmix = { _ in didSetCmix = true }
+    store.environment.bgScheduler = bgScheduler.eraseToAnyScheduler()
+    store.environment.mainScheduler = mainScheduler.eraseToAnyScheduler()
+
+    store.send(.makeCmix) {
+      $0.isMakingCmix = true
     }
 
     bgScheduler.advance()
 
-    XCTAssertTrue(didSetClient)
+    XCTAssertTrue(didSetCmix)
 
     mainScheduler.advance()
 
-    store.receive(.didMakeClient) {
-      $0.isMakingClient = false
-      $0.hasStoredClient = true
+    store.receive(.didMakeCmix) {
+      $0.isMakingCmix = false
+      $0.hasStoredCmix = true
     }
   }
 
-  func testMakeClientFailure() {
+  func testMakeCmixFailure() {
     let error = NSError(domain: "test", code: 1234)
     let bgScheduler = DispatchQueue.test
     let mainScheduler = DispatchQueue.test
 
-    var env = LandingEnvironment.failing
-    env.clientStorage.hasStoredClient = { false }
-    env.clientStorage.createClient = { throw error }
-    env.bgScheduler = bgScheduler.eraseToAnyScheduler()
-    env.mainScheduler = mainScheduler.eraseToAnyScheduler()
-
     let store = TestStore(
       initialState: LandingState(id: UUID()),
       reducer: landingReducer,
-      environment: env
+      environment: .unimplemented
     )
 
-    store.send(.makeClient) {
-      $0.isMakingClient = true
+    store.environment.cmixManager.hasStorage.run = { false }
+    store.environment.cmixManager.create.run = { throw error }
+    store.environment.bgScheduler = bgScheduler.eraseToAnyScheduler()
+    store.environment.mainScheduler = mainScheduler.eraseToAnyScheduler()
+
+    store.send(.makeCmix) {
+      $0.isMakingCmix = true
     }
 
     bgScheduler.advance()
     mainScheduler.advance()
 
-    store.receive(.didFailMakingClient(error)) {
-      $0.isMakingClient = false
-      $0.hasStoredClient = false
+    store.receive(.didFailMakingCmix(error)) {
+      $0.isMakingCmix = false
+      $0.hasStoredCmix = false
       $0.error = ErrorState(error: error)
     }
   }
 
-  func testRemoveStoredClient() {
-    var hasStoredClient = true
-    var didRemoveClient = false
+  func testRemoveStoredCmix() {
+    var hasStoredCmix = true
+    var didRemoveCmix = false
     let bgScheduler = DispatchQueue.test
     let mainScheduler = DispatchQueue.test
 
-    var env = LandingEnvironment.failing
-    env.clientStorage.hasStoredClient = { hasStoredClient }
-    env.clientStorage.removeClient = { didRemoveClient = true }
-    env.bgScheduler = bgScheduler.eraseToAnyScheduler()
-    env.mainScheduler = mainScheduler.eraseToAnyScheduler()
-
     let store = TestStore(
       initialState: LandingState(id: UUID()),
       reducer: landingReducer,
-      environment: env
+      environment: .unimplemented
     )
 
-    store.send(.removeStoredClient) {
-      $0.isRemovingClient = true
+    store.environment.cmixManager.hasStorage.run = { hasStoredCmix }
+    store.environment.cmixManager.remove.run = { didRemoveCmix = true }
+    store.environment.bgScheduler = bgScheduler.eraseToAnyScheduler()
+    store.environment.mainScheduler = mainScheduler.eraseToAnyScheduler()
+
+    store.send(.removeStoredCmix) {
+      $0.isRemovingCmix = true
     }
 
     bgScheduler.advance()
 
-    XCTAssertTrue(didRemoveClient)
+    XCTAssertTrue(didRemoveCmix)
 
-    hasStoredClient = false
+    hasStoredCmix = false
     mainScheduler.advance()
 
-    store.receive(.didRemoveStoredClient) {
-      $0.isRemovingClient = false
-      $0.hasStoredClient = false
+    store.receive(.didRemoveStoredCmix) {
+      $0.isRemovingCmix = false
+      $0.hasStoredCmix = false
     }
   }
 
-  func testRemoveStoredClientFailure() {
+  func testRemoveStoredCmixFailure() {
     let error = NSError(domain: "test", code: 1234)
     let bgScheduler = DispatchQueue.test
     let mainScheduler = DispatchQueue.test
 
-    var env = LandingEnvironment.failing
-    env.clientStorage.hasStoredClient = { true }
-    env.clientStorage.removeClient = { throw error }
-    env.bgScheduler = bgScheduler.eraseToAnyScheduler()
-    env.mainScheduler = mainScheduler.eraseToAnyScheduler()
-
     let store = TestStore(
       initialState: LandingState(id: UUID()),
       reducer: landingReducer,
-      environment: env
+      environment: .unimplemented
     )
 
-    store.send(.removeStoredClient) {
-      $0.isRemovingClient = true
+    store.environment.cmixManager.hasStorage.run = { true }
+    store.environment.cmixManager.remove.run = { throw error }
+    store.environment.bgScheduler = bgScheduler.eraseToAnyScheduler()
+    store.environment.mainScheduler = mainScheduler.eraseToAnyScheduler()
+
+    store.send(.removeStoredCmix) {
+      $0.isRemovingCmix = true
     }
 
     bgScheduler.advance()
     mainScheduler.advance()
 
-    store.receive(.didFailRemovingStoredClient(error)) {
-      $0.isRemovingClient = false
-      $0.hasStoredClient = true
+    store.receive(.didFailRemovingStoredCmix(error)) {
+      $0.isRemovingCmix = false
+      $0.hasStoredCmix = true
       $0.error = ErrorState(error: error)
     }
   }
-- 
GitLab