import ComposableArchitecture import HomeFeature import RestoreFeature import WelcomeFeature import XCTest @testable import AppFeature final class AppFeatureTests: XCTestCase { func testStartWithoutMessengerCreated() { let store = TestStore( initialState: AppState(), reducer: appReducer, environment: .unimplemented ) let mainQueue = DispatchQueue.test let bgQueue = DispatchQueue.test var didMakeDB = 0 store.environment.mainQueue = mainQueue.eraseToAnyScheduler() store.environment.bgQueue = bgQueue.eraseToAnyScheduler() store.environment.dbManager.hasDB.run = { false } store.environment.dbManager.makeDB.run = { didMakeDB += 1 } store.environment.messenger.isLoaded.run = { false } store.environment.messenger.isCreated.run = { false } store.send(.start) bgQueue.advance() XCTAssertNoDifference(didMakeDB, 1) mainQueue.advance() store.receive(.set(\.$screen, .welcome(WelcomeState()))) { $0.screen = .welcome(WelcomeState()) } } func testStartWithMessengerCreated() { let store = TestStore( initialState: AppState(), reducer: appReducer, environment: .unimplemented ) let mainQueue = DispatchQueue.test let bgQueue = DispatchQueue.test var didMakeDB = 0 var messengerDidLoad = 0 store.environment.mainQueue = mainQueue.eraseToAnyScheduler() store.environment.bgQueue = bgQueue.eraseToAnyScheduler() store.environment.dbManager.hasDB.run = { false } store.environment.dbManager.makeDB.run = { didMakeDB += 1 } store.environment.messenger.isLoaded.run = { false } store.environment.messenger.isCreated.run = { true } store.environment.messenger.load.run = { messengerDidLoad += 1 } store.send(.start) bgQueue.advance() XCTAssertNoDifference(didMakeDB, 1) XCTAssertNoDifference(messengerDidLoad, 1) mainQueue.advance() store.receive(.set(\.$screen, .home(HomeState()))) { $0.screen = .home(HomeState()) } } func testWelcomeFinished() { let store = TestStore( initialState: AppState( screen: .welcome(WelcomeState()) ), reducer: appReducer, environment: .unimplemented ) let mainQueue = DispatchQueue.test let bgQueue = DispatchQueue.test var messengerDidLoad = 0 store.environment.mainQueue = mainQueue.eraseToAnyScheduler() store.environment.bgQueue = bgQueue.eraseToAnyScheduler() store.environment.dbManager.hasDB.run = { true } store.environment.messenger.isLoaded.run = { false } store.environment.messenger.isCreated.run = { true } store.environment.messenger.load.run = { messengerDidLoad += 1 } store.send(.welcome(.finished)) { $0.screen = .loading } bgQueue.advance() XCTAssertNoDifference(messengerDidLoad, 1) mainQueue.advance() store.receive(.set(\.$screen, .home(HomeState()))) { $0.screen = .home(HomeState()) } } func testRestoreFinished() { let store = TestStore( initialState: AppState( screen: .restore(RestoreState()) ), reducer: appReducer, environment: .unimplemented ) let mainQueue = DispatchQueue.test let bgQueue = DispatchQueue.test var messengerDidLoad = 0 store.environment.mainQueue = mainQueue.eraseToAnyScheduler() store.environment.bgQueue = bgQueue.eraseToAnyScheduler() store.environment.dbManager.hasDB.run = { true } store.environment.messenger.isLoaded.run = { false } store.environment.messenger.isCreated.run = { true } store.environment.messenger.load.run = { messengerDidLoad += 1 } store.send(.restore(.finished)) { $0.screen = .loading } bgQueue.advance() XCTAssertNoDifference(messengerDidLoad, 1) mainQueue.advance() store.receive(.set(\.$screen, .home(HomeState()))) { $0.screen = .home(HomeState()) } } func testHomeDidDeleteAccount() { let store = TestStore( initialState: AppState( screen: .home(HomeState()) ), reducer: appReducer, environment: .unimplemented ) let mainQueue = DispatchQueue.test let bgQueue = DispatchQueue.test store.environment.mainQueue = mainQueue.eraseToAnyScheduler() store.environment.bgQueue = bgQueue.eraseToAnyScheduler() store.environment.dbManager.hasDB.run = { true } store.environment.messenger.isLoaded.run = { false } store.environment.messenger.isCreated.run = { false } store.send(.home(.didDeleteAccount)) { $0.screen = .loading } bgQueue.advance() mainQueue.advance() store.receive(.set(\.$screen, .welcome(WelcomeState()))) { $0.screen = .welcome(WelcomeState()) } } func testWelcomeRestoreTapped() { let store = TestStore( initialState: AppState( screen: .welcome(WelcomeState()) ), reducer: appReducer, environment: .unimplemented ) store.send(.welcome(.restoreTapped)) { $0.screen = .restore(RestoreState()) } } func testWelcomeFailed() { let store = TestStore( initialState: AppState( screen: .welcome(WelcomeState()) ), reducer: appReducer, environment: .unimplemented ) let failure = "Something went wrong" store.send(.welcome(.failed(failure))) { $0.screen = .failure(failure) } } func testStartDatabaseMakeFailure() { let store = TestStore( initialState: AppState(), reducer: appReducer, environment: .unimplemented ) struct Failure: Error {} let error = Failure() store.environment.mainQueue = .immediate store.environment.bgQueue = .immediate store.environment.dbManager.hasDB.run = { false } store.environment.dbManager.makeDB.run = { throw error } store.send(.start) store.receive(.set(\.$screen, .failure(error.localizedDescription))) { $0.screen = .failure(error.localizedDescription) } } func testStartMessengerLoadFailure() { let store = TestStore( initialState: AppState(), reducer: appReducer, environment: .unimplemented ) struct Failure: Error {} let error = Failure() store.environment.mainQueue = .immediate store.environment.bgQueue = .immediate store.environment.dbManager.hasDB.run = { true } store.environment.messenger.isLoaded.run = { false } store.environment.messenger.isCreated.run = { true } store.environment.messenger.load.run = { throw error } store.send(.start) store.receive(.set(\.$screen, .failure(error.localizedDescription))) { $0.screen = .failure(error.localizedDescription) } } }