Created
June 4, 2025 11:33
-
-
Save vrutberg/124a26d5e1e3f2fcdbbf50574b653bad to your computer and use it in GitHub Desktop.
Navigator unit test
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@MainActor | |
struct ContinueOnboardingFlowViewModelTests { | |
let services: Services | |
let testCoreDataStack: TestCoreDataStack | |
var managedObjectContext: NSManagedObjectContext { | |
testCoreDataStack.persistentContainer.viewContext | |
} | |
init() { | |
self.services = .mock | |
self.testCoreDataStack = TestCoreDataStack() | |
} | |
@Test | |
func happyPath() async throws { | |
let navigator = InspectableNavigator().typed( | |
to: ContinueOnboardingFlowViewModel.NavigationDestination.self | |
) | |
let viewModel = ContinueOnboardingFlowViewModel( | |
email: "[email protected]", | |
services: services, | |
premiumManager: PremiumManagerMock(), | |
trackEvent: { _ in }, | |
managedObjectContext: managedObjectContext, | |
navigator: navigator | |
) | |
viewModel.continueOnboardingViewModel.didPressContinue() | |
let setPasswordViewModel = try #require(navigator.lastItem(\.setPassword)) | |
#expect(setPasswordViewModel.input == .enterPassword) | |
setPasswordViewModel.onComplete(.passwordEntered(password: "hejhopp123")) | |
let setPasswordViewModel2 = try #require(navigator.lastItem(\.setPassword)) | |
#expect(setPasswordViewModel2.input == .confirmPassword(password: "hejhopp123")) | |
setPasswordViewModel2.onComplete(.passwordSet) | |
let setupNotificationsViewModel = try #require(navigator.lastItem(\.setupNotifications)) | |
setupNotificationsViewModel.didFinish(.notificationsEnabled) | |
#expect(navigator.lastItem.is(\.success)) | |
} | |
} | |
/// A navigator that allows inspection of the navigation path for testing purposes. | |
class InspectableNavigator: Navigator { | |
var inspectableNavigationPath = [any Hashable]() | |
override func push<T: Hashable>(_ value: T) { | |
super.push(value) | |
inspectableNavigationPath.append(value) | |
} | |
override func pop() { | |
super.pop() | |
inspectableNavigationPath.removeLast() | |
} | |
override func popToRoot() { | |
super.popToRoot() | |
inspectableNavigationPath.removeAll() | |
} | |
func typed<Destination: CasePathable>( | |
to: Destination.Type | |
) -> TypedInspectableNavigator<Destination> { | |
TypedInspectableNavigator<Destination>(navigator: self) | |
} | |
} | |
/// A typed navigator that allows inspection of the navigation path for testing purposes. | |
/// It won't interfere with pushing or popping items, but it will allow you to retrieve the last item of a specific type. | |
class TypedInspectableNavigator<Destination: CasePathable & Hashable>: Navigator { | |
private let navigator: InspectableNavigator | |
init(navigator: InspectableNavigator) { | |
self.navigator = navigator | |
} | |
override func push<T: Hashable>(_ value: T) { | |
navigator.push(value) | |
} | |
override func pop() { | |
navigator.pop() | |
} | |
override func popToRoot() { | |
navigator.popToRoot() | |
} | |
var lastItem: Destination? { | |
navigator.inspectableNavigationPath.last as? Destination | |
} | |
func lastItem<Value>( | |
_ casePath: CaseKeyPath<Destination, Value> | |
) -> Value? { | |
lastItem?[case: casePath] | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment