     }
     
     func testWhenRootModuleIndicatesUserNeedsToWitnessTutorialTheTutorialModuleIsSetOntoRootNavigationController() {
-        context.rootModuleFactory.simulateTutorialShouldBePresented()
-        XCTAssertEqual([context.tutorialModuleFactory.stubInterface], context.rootNavigationController.viewControllers)
+        context.rootModule.simulateTutorialShouldBePresented()
+        XCTAssertEqual([context.tutorialModule.stubInterface], context.rootNavigationController.viewControllers)
     }
     
     func testWhenRootModuleIndicatesStoreShouldPreloadThePreloadModuleIsSetAsRoot() {
-        context.rootModuleFactory.simulateStoreShouldBeRefreshed()
-        XCTAssertEqual([context.preloadModuleFactory.stubInterface], context.rootNavigationController.viewControllers)
+        context.rootModule.simulateStoreShouldBeRefreshed()
+        XCTAssertEqual([context.preloadModule.stubInterface], context.rootNavigationController.viewControllers)
     }
     
     func testWhenTheTutorialFinishesThePreloadModuleIsSetAsRoot() {
-        context.rootModuleFactory.simulateTutorialShouldBePresented()
-        context.tutorialModuleFactory.simulateTutorialFinished()
-        
-        XCTAssertEqual([context.preloadModuleFactory.stubInterface], context.rootNavigationController.viewControllers)
+        context.rootModule.simulateTutorialShouldBePresented()
+        context.tutorialModule.simulateTutorialFinished()
+        
+        XCTAssertEqual([context.preloadModule.stubInterface], context.rootNavigationController.viewControllers)
     }
     
     func testWhenPreloadingFailsAfterFinishingTutorialTheTutorialIsRedisplayed() {
-        context.rootModuleFactory.simulateTutorialShouldBePresented()
-        context.tutorialModuleFactory.simulateTutorialFinished()
-        context.preloadModuleFactory.simulatePreloadCancelled()
-        
-        XCTAssertEqual([context.tutorialModuleFactory.stubInterface], context.rootNavigationController.viewControllers)
+        context.rootModule.simulateTutorialShouldBePresented()
+        context.tutorialModule.simulateTutorialFinished()
+        context.preloadModule.simulatePreloadCancelled()
+        
+        XCTAssertEqual([context.tutorialModule.stubInterface], context.rootNavigationController.viewControllers)
     }
     
     func testWhenPreloadingSucceedsAfterFinishingTutorialTheTabWireframeIsSetAsTheRoot() {
-        context.rootModuleFactory.simulateTutorialShouldBePresented()
-        context.tutorialModuleFactory.simulateTutorialFinished()
-        context.preloadModuleFactory.simulatePreloadFinished()
-        
-        XCTAssertEqual([context.tabModuleFactory.stubInterface], context.rootNavigationController.viewControllers)
+        context.rootModule.simulateTutorialShouldBePresented()
+        context.tutorialModule.simulateTutorialFinished()
+        context.preloadModule.simulatePreloadFinished()
+        
+        XCTAssertEqual([context.tabModule.stubInterface], context.rootNavigationController.viewControllers)
     }
     
     func testWhenPresentingTabControllerTheDissolveTransitionIsUsed() {
-        context.rootModuleFactory.simulateTutorialShouldBePresented()
-        context.tutorialModuleFactory.simulateTutorialFinished()
-        context.preloadModuleFactory.simulatePreloadFinished()
-        let transition = context.rootNavigationController.delegate?.navigationController?(context.rootNavigationController, animationControllerFor: .push, from: context.preloadModuleFactory.stubInterface, to: context.tabModuleFactory.stubInterface)
+        context.rootModule.simulateTutorialShouldBePresented()
+        context.tutorialModule.simulateTutorialFinished()
+        context.preloadModule.simulatePreloadFinished()
+        let transition = context.rootNavigationController.delegate?.navigationController?(context.rootNavigationController, animationControllerFor: .push, from: context.preloadModule.stubInterface, to: context.tabModule.stubInterface)
 
         XCTAssertTrue(transition is ViewControllerDissolveTransitioning)
     }

            }
            
            func makeExpectedTabViewControllerRoots() -> [UIViewController] {
                return [newsModuleFactory.stubInterface, knowledgeListModuleProviding.stubInterface]
            }
            
            func rootNavigationTabControllers() -> [UINavigationController] {
                return tabModuleFactory.capturedTabModules.flatMap({ $0 as? UINavigationController })
            }
            
        }
        
        private let director: ApplicationDirector
        private let rootModuleFactory: StubRootModuleFactory
        private let tutorialModuleFactory: StubTutorialModuleFactory
        private let preloadModuleFactory: StubPreloadModuleFactory
        private let tabModuleFactory: StubTabModuleFactory
        private let newsModuleFactory: StubNewsModuleFactory
        private let messagesModuleFactory: StubMessagesModuleFactory
        private let loginModuleFactory: StubLoginModuleFactory
        private let windowWireframe: CapturingWindowWireframe
        private let messageDetailModuleFactory: StubMessageDetailModuleProviding
        private let knowledgeListModuleProviding: StubKnowledgeListModuleProviding
        private let knowledgeDetailModuleProviding: StubKnowledgeDetailModuleProviding
        private let linkRouter: StubLinkRouter
        private let webModuleProviding: StubWebMobuleProviding
        private let urlOpener: CapturingURLOpener
        
        init() {
            rootModuleFactory = StubRootModuleFactory()
            tutorialModuleFactory = StubTutorialModuleFactory()
            preloadModuleFactory = StubPreloadModuleFactory()
            windowWireframe = CapturingWindowWireframe()
            tabModuleFactory = StubTabModuleFactory()
            newsModuleFactory = StubNewsModuleFactory()
            messagesModuleFactory = StubMessagesModuleFactory()
            loginModuleFactory = StubLoginModuleFactory()
            messageDetailModuleFactory = StubMessageDetailModuleProviding()
            knowledgeListModuleProviding = StubKnowledgeListModuleProviding()
            knowledgeDetailModuleProviding = StubKnowledgeDetailModuleProviding()
            linkRouter = StubLinkRouter()
            webModuleProviding = StubWebMobuleProviding()
            urlOpener = CapturingURLOpener()

    
    func testWhenTheNewsModuleRequestsLoginTheMessagesControllerIsPushedOntoItsNavigationController() {
        context.navigateToTabController()
        let newsNavigationController = context.navigationController(for: context.newsModule.stubInterface)
        context.newsModule.simulateLoginRequested()
        
        XCTAssertEqual(context.messages.stubInterface, newsNavigationController?.pushedViewControllers.last)
    }
    
    func testWhenTheNewsModuleRequestsShowingPrivateMessagesTheMessagesControllerIsPushedOntoItsNavigationController() {
        context.navigateToTabController()
        let newsNavigationController = context.navigationController(for: context.newsModule.stubInterface)
        context.newsModule.simulatePrivateMessagesDisplayRequested()
        
        XCTAssertEqual(context.messages.stubInterface, newsNavigationController?.pushedViewControllers.last)
    }
    
    func testWhenTheMessagesModuleRequestsDismissalItIsDismissedFromTheTabController() {
        context.navigateToTabController()
        context.newsModule.simulatePrivateMessagesDisplayRequested()
        context.messages.simulateDismissalRequested()
        
        XCTAssertTrue(context.tabModule.stubInterface.didDismissViewController)
    }
    
    func testWhenTheMessagesModuleRequestsDismissalTheNewsNavigationControllersPopsToTheNewsModule() {
        context.navigateToTabController()
        let newsNavigationController = context.navigationController(for: context.newsModule.stubInterface)
        context.newsModule.simulatePrivateMessagesDisplayRequested()
        context.messages.simulateDismissalRequested()
        
        XCTAssertEqual(context.newsModule.stubInterface, newsNavigationController?.viewControllerPoppedTo)
    }
    
    func testWhenTheMessagesModuleRequestsResolutionForUserTheLoginModuleIsPresentedOnTopOfTheTabController() {
        context.navigateToTabController()
        context.newsModule.simulatePrivateMessagesDisplayRequested()
        context.messages.simulateResolutionForUser( { _ in })
        let navController = context.tabModule.stubInterface.capturedPresentedViewController as? UINavigationController
        
        XCTAssertEqual(navController?.topViewController, context.loginModule.stubInterface)
    }
    
    func testWhenTheMessagesModuleRequestsResolutionForUserTheLoginModuleIsPresentedUsingTheFormSheetModalPresentationStyle() {
        context.navigateToTabController()
        context.newsModule.simulatePrivateMessagesDisplayRequested()
        context.messages.simulateResolutionForUser({ _ in })
        
        XCTAssertEqual(context.loginModule.stubInterface.modalPresentationStyle, .formSheet)
    }
    
    func testWhenShowingLoginForMessagesControllerWhenModuleCancelsLoginTheMessagesModuleIsToldResolutionFailed() {
        context.navigateToTabController()
        context.newsModule.simulatePrivateMessagesDisplayRequested()
        var userResolved = true
        context.messages.simulateResolutionForUser({ userResolved = $0 })
        context.loginModule.simulateLoginCancelled()
        
        XCTAssertFalse(userResolved)
    }
    
    func testWhenShowingLoginForMessagesControllerTheMessagesModuleIsNotToldResolutionFailedBeforeLoginIsCancelled() {
        context.navigateToTabController()
        context.newsModule.simulatePrivateMessagesDisplayRequested()
        var userResolved = true
        context.messages.simulateResolutionForUser({ userResolved = $0 })
        
        XCTAssertTrue(userResolved)
    }
    
    func testWhenShowingLoginForMessagesControllerWhenModuleLogsInTheMessagesModuleIsToldResolutionSucceeded() {
        context.navigateToTabController()
        context.newsModule.simulatePrivateMessagesDisplayRequested()
        var userResolved = false
        context.messages.simulateResolutionForUser({ userResolved = $0 })
        context.loginModule.simulateLoginSucceeded()
        
        XCTAssertTrue(userResolved)
    }
    
    func testWhenShowingLoginForMessagesControllerTheMessagesModuleIsNotToldResolutionSucceededBeforeUserLogsIn() {
        context.navigateToTabController()
        context.newsModule.simulatePrivateMessagesDisplayRequested()
        var userResolved = false
        context.messages.simulateResolutionForUser({ userResolved = $0 })
        
        XCTAssertFalse(userResolved)
    }
    
    func testWhenShowingLoginForMessagesControllerWhenLoginSucceedsItIsDismissed() {
        context.navigateToTabController()
        context.newsModule.simulatePrivateMessagesDisplayRequested()
        context.messages.simulateResolutionForUser { (_) in }
        context.loginModule.simulateLoginSucceeded()
        
        XCTAssertTrue(context.tabModule.stubInterface.didDismissViewController)
    }
    
    func testWhenMessagesModuleRequestsPresentationForMessageTheMessageDetailModuleIsBuiltUsingChosenMessage() {
        context.navigateToTabController()
        context.newsModule.simulatePrivateMessagesDisplayRequested()
        let message = AppDataBuilder.makeMessage()
        context.messages.simulateMessagePresentationRequested(message)
        
        XCTAssertEqual(message, context.messageDetailModule.capturedMessage)
    }
    
    func testWhenMessagesModuleRequestsPresentationForMessageTheMessageDetailModuleInterfaceIsPushedOntoMessagesNavigationController() {
        context.navigateToTabController()
        context.newsModule.simulatePrivateMessagesDisplayRequested()
        context.messages.simulateMessagePresentationRequested(AppDataBuilder.makeMessage())
        let navigationController = context.messages.stubInterface.navigationController
        
        XCTAssertEqual(context.messageDetailModule.stubInterface, navigationController?.topViewController)
    }
    
    func testWhenSelectingKnowledgeEntryTheKnowledgeEntryModuleIsPresented() {
        context.navigateToTabController()
        let knowledgeNavigationController = context.navigationController(for: context.knowledgeListModule.stubInterface)
        let entry = KnowledgeEntry2.random
        context.knowledgeListModule.simulateKnowledgeEntrySelected(entry)
        
        XCTAssertEqual(context.knowledgeDetailModule.stubInterface, knowledgeNavigationController?.topViewController)
        XCTAssertEqual(entry, context.knowledgeDetailModule.capturedModel)
    }
    
    func testWhenKnowledgeEntrySelectsWebLinkTheWebModuleIsPresentedOntoTheTabInterface() {
        context.navigateToTabController()
        let entry = KnowledgeEntry2.random
        context.knowledgeListModule.simulateKnowledgeEntrySelected(entry)
        let link = entry.links.randomElement().element
        let url = URL.random
        context.linkRouter.stubbedLinkActions[link] = .web(url)
        context.knowledgeDetailModule.simulateLinkSelected(link)
        let webModuleForURL = context.webModuleProviding.producedWebModules[url]
        
        XCTAssertNotNil(webModuleForURL)
        XCTAssertEqual(webModuleForURL, context.tabModule.stubInterface.capturedPresentedViewController)
    }
    
    func testWhenKnowledgeEntrySelectsExternalAppLinkTheURLLauncherIsToldToHandleTheURL() {
        context.navigateToTabController()
        let entry = KnowledgeEntry2.random
        context.knowledgeListModule.simulateKnowledgeEntrySelected(entry)
        let link = entry.links.randomElement().element
        let url = URL.random
        context.linkRouter.stubbedLinkActions[link] = .externalURL(url)
        context.knowledgeDetailModule.simulateLinkSelected(link)
        
        XCTAssertEqual(url, context.urlOpener.capturedURLToOpen)
    }
