// // RoutingTests.swift // MullvadVPNTests // // Created by pronebird on 14/08/2023. // Copyright © 2025 Mullvad VPN AB. All rights reserved. // import XCTest @testable import Routing @MainActor final class RoutingTests: XCTestCase { private func createDelegate(shouldPresent: Bool = true) -> RouterBlockDelegate { let delegate = RouterBlockDelegate() delegate.handleRoute = { _, _, completion in completion(Coordinator()) } delegate.shouldPresent = { _ in shouldPresent } return delegate } // MARK: Horizontal flow tests func testPresentHorizontalRoute() throws { enum TestRoute: AppRouteProtocol { case one var isExclusive: Bool { false } var supportsSubNavigation: Bool { false } var routeGroup: TestRouteGroup { .horizontal } } let delegate: RouterBlockDelegate = createDelegate() let router = ApplicationRouter(delegate) router.present(.one) XCTAssertTrue(router.isPresenting(route: .one)) } func testShouldDropHorizontalRoute() throws { enum TestRoute: AppRouteProtocol { case one var isExclusive: Bool { false } var supportsSubNavigation: Bool { false } var routeGroup: TestRouteGroup { .horizontal } } let delegate: RouterBlockDelegate = createDelegate(shouldPresent: false) let router = ApplicationRouter(delegate) router.present(.one) XCTAssertFalse(router.isPresenting(route: .one)) } func testShouldDropIdenticalHorizontalRouteInSequence() throws { enum TestRoute: AppRouteProtocol { case one var isExclusive: Bool { false } var supportsSubNavigation: Bool { false } var routeGroup: TestRouteGroup { .horizontal } } let delegate: RouterBlockDelegate = createDelegate() let router = ApplicationRouter(delegate) router.present(.one) router.present(.one) XCTAssertEqual(router.presentedRoutes[.horizontal]?.count, 1) } // MARK: Modal flow tests func testPresentModalRoutesOfDifferentLevels() throws { enum TestRoute: AppRouteProtocol { case one, two var isExclusive: Bool { false } var supportsSubNavigation: Bool { false } var routeGroup: TestRouteGroup { self == .one ? .modalOne : .modalTwo } } let delegate: RouterBlockDelegate = createDelegate() let router = ApplicationRouter(delegate) router.present(.one) router.present(.two) XCTAssertEqual(router.modalStack.count, 2) } func testPresentModalRoutesOfDifferentLevelsInWrongOrder() throws { enum TestRoute: AppRouteProtocol { case one, two var isExclusive: Bool { false } var supportsSubNavigation: Bool { false } var routeGroup: TestRouteGroup { self == .one ? .modalOne : .modalTwo } } let delegate: RouterBlockDelegate = createDelegate() let router = ApplicationRouter(delegate) router.present(.two) router.present(.one) XCTAssertTrue(router.isPresenting(route: .two)) XCTAssertEqual(router.modalStack.count, 1) } func testShouldDropSameLevelModalRouteIfPreceededByExclusive() throws { enum TestRoute: AppRouteProtocol { case one, two var isExclusive: Bool { self == .one } var supportsSubNavigation: Bool { false } var routeGroup: TestRouteGroup { .modalOne } } let delegate: RouterBlockDelegate = createDelegate() let router = ApplicationRouter(delegate) router.present(.one) router.present(.two) XCTAssertTrue(router.isPresenting(route: .one)) XCTAssertEqual(router.modalStack.count, 1) } } enum TestRouteGroup: AppRouteGroupProtocol { case horizontal, modalOne, modalTwo var isModal: Bool { switch self { case .horizontal: return false case .modalOne, .modalTwo: return true } } var modalLevel: Int { switch self { case .horizontal: return 0 case .modalOne: return 1 case .modalTwo: return 2 } } }