From fbd4586c9c8b3aaa4f0dac3dd1ce9998bb8e1c2e Mon Sep 17 00:00:00 2001 From: Tyler Thompson Date: Sat, 5 Oct 2019 14:19:57 -0600 Subject: [PATCH] [ci skip] Add tests around the rest of the workflow example - TT --- Workflow.xcodeproj/project.pbxproj | 28 +++++++++++ WorkflowExample/Base.lproj/Main.storyboard | 2 +- WorkflowExample/SetupViewController.swift | 2 +- .../EnterAddressViewControllerTests.swift | 34 +++++++++++++ .../Mocks/MockPresenter.swift | 23 +++++++++ .../Mocks/WorkflowListener.swift | 42 ++++++++++++++++ .../PickupOrDeliveryViewControllerTests.swift | 43 ---------------- .../ReviewOrderViewControllerTests.swift | 49 +++++++++++++++++++ .../SetupViewControllerTests.swift | 28 +++++++++++ WorkflowExampleTests/TestFinder.swift | 3 ++ 10 files changed, 209 insertions(+), 45 deletions(-) create mode 100644 WorkflowExampleTests/EnterAddressViewControllerTests.swift create mode 100644 WorkflowExampleTests/Mocks/MockPresenter.swift create mode 100644 WorkflowExampleTests/Mocks/WorkflowListener.swift create mode 100644 WorkflowExampleTests/ReviewOrderViewControllerTests.swift create mode 100644 WorkflowExampleTests/SetupViewControllerTests.swift diff --git a/Workflow.xcodeproj/project.pbxproj b/Workflow.xcodeproj/project.pbxproj index 43d92a797..4003642f1 100644 --- a/Workflow.xcodeproj/project.pbxproj +++ b/Workflow.xcodeproj/project.pbxproj @@ -23,6 +23,11 @@ AD79EC4523491F2200F86101 /* TestFinder.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD79EC4423491F2200F86101 /* TestFinder.swift */; }; AD79EC472349210000F86101 /* MenuSelectionViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD79EC462349210000F86101 /* MenuSelectionViewControllerTests.swift */; }; AD79EC49234926D000F86101 /* FoodSelectionViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD79EC48234926D000F86101 /* FoodSelectionViewControllerTests.swift */; }; + AD79EC4B23492B6F00F86101 /* ReviewOrderViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD79EC4A23492B6F00F86101 /* ReviewOrderViewControllerTests.swift */; }; + AD79EC4D23492EDD00F86101 /* EnterAddressViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD79EC4C23492EDD00F86101 /* EnterAddressViewControllerTests.swift */; }; + AD79EC4F2349306100F86101 /* SetupViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD79EC4E2349306100F86101 /* SetupViewControllerTests.swift */; }; + AD79EC522349319300F86101 /* MockPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD79EC512349319300F86101 /* MockPresenter.swift */; }; + AD79EC54234931A400F86101 /* WorkflowListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD79EC53234931A400F86101 /* WorkflowListener.swift */; }; AD8B6C772319E8B200781B01 /* Screen.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD8B6C762319E8B200781B01 /* Screen.swift */; }; AD8BEBE42318303A0071A83D /* AnyPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD8BEBE32318303A0071A83D /* AnyPresenter.swift */; }; AD8BEBE6231830860071A83D /* BasePresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD8BEBE5231830860071A83D /* BasePresenter.swift */; }; @@ -112,6 +117,11 @@ AD79EC4423491F2200F86101 /* TestFinder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestFinder.swift; sourceTree = ""; }; AD79EC462349210000F86101 /* MenuSelectionViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuSelectionViewControllerTests.swift; sourceTree = ""; }; AD79EC48234926D000F86101 /* FoodSelectionViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FoodSelectionViewControllerTests.swift; sourceTree = ""; }; + AD79EC4A23492B6F00F86101 /* ReviewOrderViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReviewOrderViewControllerTests.swift; sourceTree = ""; }; + AD79EC4C23492EDD00F86101 /* EnterAddressViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnterAddressViewControllerTests.swift; sourceTree = ""; }; + AD79EC4E2349306100F86101 /* SetupViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetupViewControllerTests.swift; sourceTree = ""; }; + AD79EC512349319300F86101 /* MockPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockPresenter.swift; sourceTree = ""; }; + AD79EC53234931A400F86101 /* WorkflowListener.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkflowListener.swift; sourceTree = ""; }; AD8B6C762319E8B200781B01 /* Screen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Screen.swift; sourceTree = ""; }; AD8BEBE32318303A0071A83D /* AnyPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyPresenter.swift; sourceTree = ""; }; AD8BEBE5231830860071A83D /* BasePresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BasePresenter.swift; sourceTree = ""; }; @@ -242,6 +252,15 @@ path = WorkflowExample; sourceTree = ""; }; + AD79EC502349317C00F86101 /* Mocks */ = { + isa = PBXGroup; + children = ( + AD79EC512349319300F86101 /* MockPresenter.swift */, + AD79EC53234931A400F86101 /* WorkflowListener.swift */, + ); + path = Mocks; + sourceTree = ""; + }; AD8BEBE72318308C0071A83D /* Models */ = { isa = PBXGroup; children = ( @@ -364,6 +383,7 @@ ADEE7750233BAA6C007E9FD2 /* WorkflowExampleTests */ = { isa = PBXGroup; children = ( + AD79EC502349317C00F86101 /* Mocks */, ADEE7753233BAA6C007E9FD2 /* Info.plist */, ADEE7759233BAB27007E9FD2 /* LocationsViewControllerTests.swift */, ADEE775B233BC7F0007E9FD2 /* ViewControllerTest.swift */, @@ -372,6 +392,9 @@ AD79EC4423491F2200F86101 /* TestFinder.swift */, AD79EC462349210000F86101 /* MenuSelectionViewControllerTests.swift */, AD79EC48234926D000F86101 /* FoodSelectionViewControllerTests.swift */, + AD79EC4A23492B6F00F86101 /* ReviewOrderViewControllerTests.swift */, + AD79EC4C23492EDD00F86101 /* EnterAddressViewControllerTests.swift */, + AD79EC4E2349306100F86101 /* SetupViewControllerTests.swift */, ); path = WorkflowExampleTests; sourceTree = ""; @@ -783,10 +806,15 @@ AD79EC4523491F2200F86101 /* TestFinder.swift in Sources */, AD79EC49234926D000F86101 /* FoodSelectionViewControllerTests.swift in Sources */, ADEE775A233BAB27007E9FD2 /* LocationsViewControllerTests.swift in Sources */, + AD79EC4D23492EDD00F86101 /* EnterAddressViewControllerTests.swift in Sources */, + AD79EC4F2349306100F86101 /* SetupViewControllerTests.swift in Sources */, AD79EC472349210000F86101 /* MenuSelectionViewControllerTests.swift in Sources */, + AD79EC54234931A400F86101 /* WorkflowListener.swift in Sources */, ADEE7760233BC960007E9FD2 /* Convenience.swift in Sources */, ADEE775C233BC7F0007E9FD2 /* ViewControllerTest.swift in Sources */, + AD79EC522349319300F86101 /* MockPresenter.swift in Sources */, ADEE775E233BC901007E9FD2 /* PickupOrDeliveryViewControllerTests.swift in Sources */, + AD79EC4B23492B6F00F86101 /* ReviewOrderViewControllerTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/WorkflowExample/Base.lproj/Main.storyboard b/WorkflowExample/Base.lproj/Main.storyboard index e36261466..bf0e94622 100644 --- a/WorkflowExample/Base.lproj/Main.storyboard +++ b/WorkflowExample/Base.lproj/Main.storyboard @@ -13,7 +13,7 @@ - + diff --git a/WorkflowExample/SetupViewController.swift b/WorkflowExample/SetupViewController.swift index b7066baa8..4b759b595 100644 --- a/WorkflowExample/SetupViewController.swift +++ b/WorkflowExample/SetupViewController.swift @@ -9,7 +9,7 @@ import Foundation import UIKit -class SetupViewController: UIViewController { +class SetupViewController: UIViewController, StoryboardLoadable { @IBAction func launchMultiLocationWorkflow() { let locations = [ Location(name: "Just Pickup w/ just catering", diff --git a/WorkflowExampleTests/EnterAddressViewControllerTests.swift b/WorkflowExampleTests/EnterAddressViewControllerTests.swift new file mode 100644 index 000000000..4b6ccee34 --- /dev/null +++ b/WorkflowExampleTests/EnterAddressViewControllerTests.swift @@ -0,0 +1,34 @@ +// +// EnterAddressViewControllerTests.swift +// WorkflowExampleTests +// +// Created by Tyler Thompson on 10/5/19. +// Copyright © 2019 Tyler Thompson. All rights reserved. +// + +import Foundation +import XCTest + +@testable import WorkflowExample + +class EnterAddressViewControllerTests: ViewControllerTest { + func testViewShouldAlwaysLoad() { + let order = Order(location: nil) + XCTAssert(testViewController.shouldLoad(with: order)) + } + + func testSavingAddressProceedsInWorkflow() { + var proceedInWorkflowCalled = false + let order = Order(location: nil) + testViewController.order = order + + testViewController.callback = { data in + proceedInWorkflowCalled = true + XCTAssertEqual((data as? Order)?.orderType, .delivery(Address())) + } + + testViewController.saveAddress() + + XCTAssert(proceedInWorkflowCalled) + } +} diff --git a/WorkflowExampleTests/Mocks/MockPresenter.swift b/WorkflowExampleTests/Mocks/MockPresenter.swift new file mode 100644 index 000000000..05acd4c0a --- /dev/null +++ b/WorkflowExampleTests/Mocks/MockPresenter.swift @@ -0,0 +1,23 @@ +// +// MockPresenter.swift +// WorkflowExampleTests +// +// Created by Tyler Thompson on 10/5/19. +// Copyright © 2019 Tyler Thompson. All rights reserved. +// + +import Foundation +@testable import DynamicWorkflow + +class MockPresenter: Presenter { + var abandonCalled = 0 + var lastWorkflow:Workflow? + var lastAnimated:Bool? + func abandon(_ workflow: Workflow, animated: Bool, onFinish: (() -> Void)?) { + abandonCalled += 1 + lastWorkflow = workflow + lastAnimated = animated + onFinish?() + } + required init() { } +} diff --git a/WorkflowExampleTests/Mocks/WorkflowListener.swift b/WorkflowExampleTests/Mocks/WorkflowListener.swift new file mode 100644 index 000000000..6c0b516ad --- /dev/null +++ b/WorkflowExampleTests/Mocks/WorkflowListener.swift @@ -0,0 +1,42 @@ +// +// WorkflowListener.swift +// WorkflowExampleTests +// +// Created by Tyler Thompson on 10/5/19. +// Copyright © 2019 Tyler Thompson. All rights reserved. +// + +import Foundation +import XCTest + +@testable import DynamicWorkflow + +class WorkflowListener { + var workflow:Workflow? + var launchStyle:PresentationType? + var args:Any? + var launchedFrom:AnyFlowRepresentable? + var onFinish:((Any?) -> Void)? + init() { + NotificationCenter.default.addObserver(self, selector: #selector(workflowLaunched(notification:)), name: .workflowLaunched, object: nil) + } + + @objc func workflowLaunched(notification: Notification) { + let dict = notification.object as? [String:Any?] + workflow = dict?["workflow"] as? Workflow + launchStyle = dict?["style"] as? PresentationType + onFinish = dict?["onFinish"] as? ((Any?) -> Void) + launchedFrom = dict?["launchFrom"] as? AnyFlowRepresentable + args = dict?["args"] as Any? + } +} + +func XCTAssertWorkflowLaunched(listener: WorkflowListener, expectedFlowRepresentables:[AnyFlowRepresentable.Type]) { + XCTAssertNotNil(listener.workflow, "No workflow found") + guard let workflow = listener.workflow, expectedFlowRepresentables.count == workflow.count else { + XCTFail("workflow does not contain correct representables: \(String(describing: listener.workflow?.compactMap { String(describing: $0.value) }) )") + return + } + XCTAssertEqual(workflow.compactMap { String(describing: $0.value) }, + expectedFlowRepresentables.map { String(describing: $0) }) +} diff --git a/WorkflowExampleTests/PickupOrDeliveryViewControllerTests.swift b/WorkflowExampleTests/PickupOrDeliveryViewControllerTests.swift index d8acd7a58..a66cc6948 100644 --- a/WorkflowExampleTests/PickupOrDeliveryViewControllerTests.swift +++ b/WorkflowExampleTests/PickupOrDeliveryViewControllerTests.swift @@ -80,46 +80,3 @@ class PickupOrDeliveryViewConrollerTests:ViewControllerTest Void)?) { - abandonCalled += 1 - lastWorkflow = workflow - lastAnimated = animated - onFinish?() - } - required init() { } -} - -class WorkflowListener { - var workflow:Workflow? - var launchStyle:PresentationType? - var args:Any? - var launchedFrom:AnyFlowRepresentable? - var onFinish:((Any?) -> Void)? - init() { - NotificationCenter.default.addObserver(self, selector: #selector(workflowLaunched(notification:)), name: .workflowLaunched, object: nil) - } - - @objc func workflowLaunched(notification: Notification) { - let dict = notification.object as? [String:Any?] - workflow = dict?["workflow"] as? Workflow - launchStyle = dict?["style"] as? PresentationType - onFinish = dict?["onFinish"] as? ((Any?) -> Void) - launchedFrom = dict?["launchFrom"] as? AnyFlowRepresentable - args = dict?["args"] as Any? - } -} diff --git a/WorkflowExampleTests/ReviewOrderViewControllerTests.swift b/WorkflowExampleTests/ReviewOrderViewControllerTests.swift new file mode 100644 index 000000000..45b2e31da --- /dev/null +++ b/WorkflowExampleTests/ReviewOrderViewControllerTests.swift @@ -0,0 +1,49 @@ +// +// ReviewOrderViewControllerTests.swift +// WorkflowExampleTests +// +// Created by Tyler Thompson on 10/5/19. +// Copyright © 2019 Tyler Thompson. All rights reserved. +// + +import Foundation +import XCTest + +@testable import WorkflowExample + +class ReviewOrderViewControllerTests: ViewControllerTest { + + var locationNameLabel:UILabel! + var menuLabel:UILabel! + var orderTypeLabel:UILabel! + var foodChoiceLabel:UILabel! + + override func afterLoadFromStoryboard() { + locationNameLabel = testViewController.locationNameLabel + menuLabel = testViewController.menuLabel + orderTypeLabel = testViewController.orderTypeLabel + foodChoiceLabel = testViewController.foodChoiceLabel + } + + func testShouldLoad() { + let order = Order(location: Location(name: "", address: Address(), orderTypes: [], menuTypes: [])) + XCTAssert(testViewController.shouldLoad(with: order)) + } + + func testShowOrderInformation() { + let locationName = UUID().uuidString + var order = Order(location: Location(name: locationName, address: Address(), orderTypes: [.delivery(Address())], menuTypes: [.catering])) + order.menuType = .catering + order.shoppingCart.append(Food(name: "Combo #1")) + order.shoppingCart.append(Food(name: "Combo #2")) + loadFromStoryboard { + XCTAssert($0.shouldLoad(with: order)) + } + + XCTAssertEqual(locationNameLabel.text, locationName) + XCTAssertEqual(menuLabel.text, "Catering Menu") + XCTAssertEqual(orderTypeLabel.text, "Delivery") + XCTAssertEqual(foodChoiceLabel.text, "Combo #1, Combo #2") + } + +} diff --git a/WorkflowExampleTests/SetupViewControllerTests.swift b/WorkflowExampleTests/SetupViewControllerTests.swift new file mode 100644 index 000000000..62d576a71 --- /dev/null +++ b/WorkflowExampleTests/SetupViewControllerTests.swift @@ -0,0 +1,28 @@ +// +// SetupViewControllerTests.swift +// WorkflowExampleTests +// +// Created by Tyler Thompson on 10/5/19. +// Copyright © 2019 Tyler Thompson. All rights reserved. +// + +import Foundation +import XCTest + +@testable import WorkflowExample + +class SetupViewControllerTests: ViewControllerTest { + func testLaunchingMultiLocationWorkflow() { + let listener = WorkflowListener() + + testViewController.launchMultiLocationWorkflow() + + XCTAssertWorkflowLaunched(listener: listener, expectedFlowRepresentables: [ + LocationsViewController.self, + PickupOrDeliveryViewController.self, + MenuSelectionViewController.self, + FoodSelectionViewController.self, + ReviewOrderViewController.self, + ]) + } +} diff --git a/WorkflowExampleTests/TestFinder.swift b/WorkflowExampleTests/TestFinder.swift index 4ddc73f67..91b9ba341 100644 --- a/WorkflowExampleTests/TestFinder.swift +++ b/WorkflowExampleTests/TestFinder.swift @@ -17,6 +17,9 @@ class TestFinder: XCTestCase { XCTestSuite(forTestCaseClass: PickupOrDeliveryViewConrollerTests.self).tests.forEach { suite.addTest($0) } XCTestSuite(forTestCaseClass: MenuSelectionViewControllerTests.self).tests.forEach { suite.addTest($0) } XCTestSuite(forTestCaseClass: FoodSelectionViewControllerTests.self).tests.forEach { suite.addTest($0) } + XCTestSuite(forTestCaseClass: ReviewOrderViewControllerTests.self).tests.forEach { suite.addTest($0) } + XCTestSuite(forTestCaseClass: EnterAddressViewControllerTests.self).tests.forEach { suite.addTest($0) } + XCTestSuite(forTestCaseClass: SetupViewControllerTests.self).tests.forEach { suite.addTest($0) } return suite }