From 641eed0540eb45a70e4749b1a877af55dda4ddaa Mon Sep 17 00:00:00 2001 From: Jaclyn Chen Date: Fri, 4 Nov 2022 14:04:43 +0800 Subject: [PATCH 1/7] Update `Coordinator.navigationController` to readonly because there is no use case in the app so far. --- .../Authentication/Epilogue/StorePickerCoordinator.swift | 3 ++- .../Store Creation/LoggedOutStoreCreationCoordinator.swift | 2 +- .../Store Creation/StoreCreationCoordinator.swift | 2 +- WooCommerce/Classes/Tools/Coordinator.swift | 2 +- .../Classes/ViewRelated/Hub Menu/HubMenuCoordinator.swift | 2 +- .../Order Creation/FlowCoordinator/AddOrderCoordinator.swift | 2 +- .../Products/Add Product/AddProductCoordinator.swift | 2 +- .../SKU Scanner/ProductSKUBarcodeScannerCoordinator.swift | 2 +- .../Classes/ViewRelated/Reviews/ReviewsCoordinator.swift | 2 +- 9 files changed, 10 insertions(+), 9 deletions(-) diff --git a/WooCommerce/Classes/Authentication/Epilogue/StorePickerCoordinator.swift b/WooCommerce/Classes/Authentication/Epilogue/StorePickerCoordinator.swift index 75b5caee673..e11dc168d8e 100644 --- a/WooCommerce/Classes/Authentication/Epilogue/StorePickerCoordinator.swift +++ b/WooCommerce/Classes/Authentication/Epilogue/StorePickerCoordinator.swift @@ -7,7 +7,7 @@ import Yosemite /// final class StorePickerCoordinator: Coordinator { - unowned var navigationController: UINavigationController + unowned private(set) var navigationController: UINavigationController /// Determines how the store picker should initialized /// @@ -162,6 +162,7 @@ private extension StorePickerCoordinator { } } +// TODO Add tests private extension StorePickerCoordinator { /// How the store picker view is presented. enum PresentationStyle { diff --git a/WooCommerce/Classes/Authentication/Store Creation/LoggedOutStoreCreationCoordinator.swift b/WooCommerce/Classes/Authentication/Store Creation/LoggedOutStoreCreationCoordinator.swift index c4e252d5884..69ac77c637f 100644 --- a/WooCommerce/Classes/Authentication/Store Creation/LoggedOutStoreCreationCoordinator.swift +++ b/WooCommerce/Classes/Authentication/Store Creation/LoggedOutStoreCreationCoordinator.swift @@ -11,7 +11,7 @@ final class LoggedOutStoreCreationCoordinator: Coordinator { } /// Mutable to conform to `Coordinator` protocol. - var navigationController: UINavigationController + let navigationController: UINavigationController private var storePickerCoordinator: StorePickerCoordinator? diff --git a/WooCommerce/Classes/Authentication/Store Creation/StoreCreationCoordinator.swift b/WooCommerce/Classes/Authentication/Store Creation/StoreCreationCoordinator.swift index 01ca91a7e7f..95f3cdf4b4d 100644 --- a/WooCommerce/Classes/Authentication/Store Creation/StoreCreationCoordinator.swift +++ b/WooCommerce/Classes/Authentication/Store Creation/StoreCreationCoordinator.swift @@ -13,7 +13,7 @@ final class StoreCreationCoordinator: Coordinator { case storePicker } - var navigationController: UINavigationController + let navigationController: UINavigationController @Published private var possibleSiteURLsFromStoreCreation: Set = [] private var possibleSiteURLsFromStoreCreationSubscription: AnyCancellable? diff --git a/WooCommerce/Classes/Tools/Coordinator.swift b/WooCommerce/Classes/Tools/Coordinator.swift index 65d80bd6d4e..0263c030c72 100644 --- a/WooCommerce/Classes/Tools/Coordinator.swift +++ b/WooCommerce/Classes/Tools/Coordinator.swift @@ -5,7 +5,7 @@ import UIKit /// See: http://khanlou.com/2015/01/the-coordinator/ /// protocol Coordinator { - var navigationController: UINavigationController { get set } + var navigationController: UINavigationController { get } func start() } diff --git a/WooCommerce/Classes/ViewRelated/Hub Menu/HubMenuCoordinator.swift b/WooCommerce/Classes/ViewRelated/Hub Menu/HubMenuCoordinator.swift index 54b2562fa92..26abcbadb58 100644 --- a/WooCommerce/Classes/ViewRelated/Hub Menu/HubMenuCoordinator.swift +++ b/WooCommerce/Classes/ViewRelated/Hub Menu/HubMenuCoordinator.swift @@ -10,7 +10,7 @@ import protocol Yosemite.StoresManager /// Coordinator for the HubMenu tab. /// final class HubMenuCoordinator: Coordinator { - var navigationController: UINavigationController + let navigationController: UINavigationController var hubMenuController: HubMenuViewController? private let pushNotificationsManager: PushNotesManager diff --git a/WooCommerce/Classes/ViewRelated/Orders/Order Creation/FlowCoordinator/AddOrderCoordinator.swift b/WooCommerce/Classes/ViewRelated/Orders/Order Creation/FlowCoordinator/AddOrderCoordinator.swift index 3a141766e34..aef056aae9b 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/Order Creation/FlowCoordinator/AddOrderCoordinator.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/Order Creation/FlowCoordinator/AddOrderCoordinator.swift @@ -7,7 +7,7 @@ import WordPressUI /// Manages the different navigation flows that start from the Orders main tab /// final class AddOrderCoordinator: Coordinator { - var navigationController: UINavigationController + let navigationController: UINavigationController private let siteID: Int64 private let sourceBarButtonItem: UIBarButtonItem? diff --git a/WooCommerce/Classes/ViewRelated/Products/Add Product/AddProductCoordinator.swift b/WooCommerce/Classes/ViewRelated/Products/Add Product/AddProductCoordinator.swift index 62958d810d9..d575046b154 100644 --- a/WooCommerce/Classes/ViewRelated/Products/Add Product/AddProductCoordinator.swift +++ b/WooCommerce/Classes/ViewRelated/Products/Add Product/AddProductCoordinator.swift @@ -11,7 +11,7 @@ import class Networking.ProductsRemote /// coordinator.start() /// final class AddProductCoordinator: Coordinator { - var navigationController: UINavigationController + let navigationController: UINavigationController private let siteID: Int64 private let sourceBarButtonItem: UIBarButtonItem? diff --git a/WooCommerce/Classes/ViewRelated/Products/SKU Scanner/ProductSKUBarcodeScannerCoordinator.swift b/WooCommerce/Classes/ViewRelated/Products/SKU Scanner/ProductSKUBarcodeScannerCoordinator.swift index a328c7d2326..813357b1f75 100644 --- a/WooCommerce/Classes/ViewRelated/Products/SKU Scanner/ProductSKUBarcodeScannerCoordinator.swift +++ b/WooCommerce/Classes/ViewRelated/Products/SKU Scanner/ProductSKUBarcodeScannerCoordinator.swift @@ -3,7 +3,7 @@ import UIKit /// Coordinates navigation for product SKU barcode scanner based on camera permission. final class ProductSKUBarcodeScannerCoordinator: Coordinator { - var navigationController: UINavigationController + let navigationController: UINavigationController private let permissionChecker: CaptureDevicePermissionChecker private let onSKUBarcodeScanned: (_ barcode: String) -> Void diff --git a/WooCommerce/Classes/ViewRelated/Reviews/ReviewsCoordinator.swift b/WooCommerce/Classes/ViewRelated/Reviews/ReviewsCoordinator.swift index 13db7fee1d4..a659b6cd8d8 100644 --- a/WooCommerce/Classes/ViewRelated/Reviews/ReviewsCoordinator.swift +++ b/WooCommerce/Classes/ViewRelated/Reviews/ReviewsCoordinator.swift @@ -10,7 +10,7 @@ import protocol Yosemite.StoresManager /// Coordinator for the Reviews tab. /// final class ReviewsCoordinator: Coordinator { - var navigationController: UINavigationController + let navigationController: UINavigationController private let pushNotificationsManager: PushNotesManager private let storesManager: StoresManager From d0a5f306b180dad3e5e28ad6168dca6aac36799f Mon Sep 17 00:00:00 2001 From: Jaclyn Chen Date: Fri, 4 Nov 2022 15:10:55 +0800 Subject: [PATCH 2/7] Add unit tests for `StoreCreationCoordinator` and `StorePickerCoordinator` with `storeCreationFromLogin` configuration. --- .../Epilogue/StorePickerCoordinator.swift | 1 - .../WooCommerce.xcodeproj/project.pbxproj | 8 ++ .../StoreCreationCoordinatorTests.swift | 73 +++++++++++++++++++ .../StorePickerCoordinatorTests.swift | 45 ++++++++++++ 4 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 WooCommerce/WooCommerceTests/Authentication/StoreCreationCoordinatorTests.swift create mode 100644 WooCommerce/WooCommerceTests/Authentication/StorePickerCoordinatorTests.swift diff --git a/WooCommerce/Classes/Authentication/Epilogue/StorePickerCoordinator.swift b/WooCommerce/Classes/Authentication/Epilogue/StorePickerCoordinator.swift index e11dc168d8e..23d312bfdef 100644 --- a/WooCommerce/Classes/Authentication/Epilogue/StorePickerCoordinator.swift +++ b/WooCommerce/Classes/Authentication/Epilogue/StorePickerCoordinator.swift @@ -162,7 +162,6 @@ private extension StorePickerCoordinator { } } -// TODO Add tests private extension StorePickerCoordinator { /// How the store picker view is presented. enum PresentationStyle { diff --git a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj index 14def4dc5db..acdfa10b100 100644 --- a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj +++ b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj @@ -46,6 +46,7 @@ 020BE77523B4A7EC007FE54C /* AztecSourceCodeFormatBarCommandTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 020BE77423B4A7EC007FE54C /* AztecSourceCodeFormatBarCommandTests.swift */; }; 020BE77723B4A9D9007FE54C /* AztecLinkFormatBarCommandTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 020BE77623B4A9D9007FE54C /* AztecLinkFormatBarCommandTests.swift */; }; 020C908424C84652001E2BEB /* ProductListMultiSelectorSearchUICommandTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 020C908324C84652001E2BEB /* ProductListMultiSelectorSearchUICommandTests.swift */; }; + 020D0BFD2914E92800BB3DCE /* StorePickerCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 020D0BFC2914E92800BB3DCE /* StorePickerCoordinatorTests.swift */; }; 020DD48A23229495005822B1 /* ProductsTabProductTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 020DD48923229495005822B1 /* ProductsTabProductTableViewCell.swift */; }; 020DD48D2322A617005822B1 /* ProductsTabProductViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 020DD48C2322A617005822B1 /* ProductsTabProductViewModel.swift */; }; 020DD48F232392C9005822B1 /* UIViewController+AppReview.swift in Sources */ = {isa = PBXBuildFile; fileRef = 020DD48E232392C9005822B1 /* UIViewController+AppReview.swift */; }; @@ -229,6 +230,7 @@ 0269576A23726304001BA0BF /* KeyboardFrameObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0269576923726304001BA0BF /* KeyboardFrameObserver.swift */; }; 0269576D23726401001BA0BF /* KeyboardFrameObserverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0269576C23726401001BA0BF /* KeyboardFrameObserverTests.swift */; }; 02695770237281A9001BA0BF /* AztecTextViewAttachmentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0269576F237281A9001BA0BF /* AztecTextViewAttachmentHandler.swift */; }; + 0269A5E72913FD22003B20EB /* StoreCreationCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0269A5E62913FD22003B20EB /* StoreCreationCoordinatorTests.swift */; }; 0269A63C2581D26C007B49ED /* ShippingLabelPrintingStepListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0269A63B2581D26C007B49ED /* ShippingLabelPrintingStepListView.swift */; }; 026B3C57249A046E00F7823C /* TextFieldTextAlignment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 026B3C56249A046E00F7823C /* TextFieldTextAlignment.swift */; }; 026B80CF289A5E0B001960E4 /* LoginOnboardingSurveyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 026B80CE289A5E0B001960E4 /* LoginOnboardingSurveyView.swift */; }; @@ -1998,6 +2000,7 @@ 020BE77423B4A7EC007FE54C /* AztecSourceCodeFormatBarCommandTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AztecSourceCodeFormatBarCommandTests.swift; sourceTree = ""; }; 020BE77623B4A9D9007FE54C /* AztecLinkFormatBarCommandTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AztecLinkFormatBarCommandTests.swift; sourceTree = ""; }; 020C908324C84652001E2BEB /* ProductListMultiSelectorSearchUICommandTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductListMultiSelectorSearchUICommandTests.swift; sourceTree = ""; }; + 020D0BFC2914E92800BB3DCE /* StorePickerCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorePickerCoordinatorTests.swift; sourceTree = ""; }; 020DD48923229495005822B1 /* ProductsTabProductTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductsTabProductTableViewCell.swift; sourceTree = ""; }; 020DD48C2322A617005822B1 /* ProductsTabProductViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductsTabProductViewModel.swift; sourceTree = ""; }; 020DD48E232392C9005822B1 /* UIViewController+AppReview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+AppReview.swift"; sourceTree = ""; }; @@ -2181,6 +2184,7 @@ 0269576923726304001BA0BF /* KeyboardFrameObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardFrameObserver.swift; sourceTree = ""; }; 0269576C23726401001BA0BF /* KeyboardFrameObserverTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardFrameObserverTests.swift; sourceTree = ""; }; 0269576F237281A9001BA0BF /* AztecTextViewAttachmentHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AztecTextViewAttachmentHandler.swift; sourceTree = ""; }; + 0269A5E62913FD22003B20EB /* StoreCreationCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreCreationCoordinatorTests.swift; sourceTree = ""; }; 0269A63B2581D26C007B49ED /* ShippingLabelPrintingStepListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShippingLabelPrintingStepListView.swift; sourceTree = ""; }; 026B3C56249A046E00F7823C /* TextFieldTextAlignment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextFieldTextAlignment.swift; sourceTree = ""; }; 026B80CE289A5E0B001960E4 /* LoginOnboardingSurveyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginOnboardingSurveyView.swift; sourceTree = ""; }; @@ -6153,6 +6157,8 @@ DE61979428A25842005E4362 /* StorePickerViewModelTests.swift */, DE3404E928B4C1D000CF0D97 /* NonAtomicSiteViewModelTests.swift */, DE50295228BF4A8A00551736 /* JetpackConnectionWebViewModelTests.swift */, + 0269A5E62913FD22003B20EB /* StoreCreationCoordinatorTests.swift */, + 020D0BFC2914E92800BB3DCE /* StorePickerCoordinatorTests.swift */, ); path = Authentication; sourceTree = ""; @@ -10737,6 +10743,7 @@ CC53FB402759042600C4CA4F /* ProductSelectorViewModelTests.swift in Sources */, DE0A2EB1281BED38007A8015 /* ProductCategorySelectorViewModelTests.swift in Sources */, 03AA16602719B83D005CCB7B /* ReceiptActionCoordinatorTests.swift in Sources */, + 020D0BFD2914E92800BB3DCE /* StorePickerCoordinatorTests.swift in Sources */, CEEC9B6621E7C5200055EEF0 /* AppRatingManagerTests.swift in Sources */, 263EB409242C58EA00F3A15F /* ProductFormActionsFactoryTests.swift in Sources */, 02BA23C022EE9DAF009539E7 /* AsyncDictionaryTests.swift in Sources */, @@ -10760,6 +10767,7 @@ DEC51AA0274F9922009F3DF4 /* JetpackInstallStepsViewModelTests.swift in Sources */, E1068058285C787100668B46 /* BetaFeaturesTests.swift in Sources */, 26C6E8E426E2D87C00C7BB0F /* CountrySelectorViewModelTests.swift in Sources */, + 0269A5E72913FD22003B20EB /* StoreCreationCoordinatorTests.swift in Sources */, 02CE4307276994920006EAEF /* ProductSKUBarcodeScannerCoordinatorTests.swift in Sources */, 0999877427D2819F00F82C65 /* BulkUpdateViewControllerTests.swift in Sources */, 3190D61D26D6E97B00EF364D /* CardPresentModalRetryableErrorTests.swift in Sources */, diff --git a/WooCommerce/WooCommerceTests/Authentication/StoreCreationCoordinatorTests.swift b/WooCommerce/WooCommerceTests/Authentication/StoreCreationCoordinatorTests.swift new file mode 100644 index 00000000000..7b20e45e71b --- /dev/null +++ b/WooCommerce/WooCommerceTests/Authentication/StoreCreationCoordinatorTests.swift @@ -0,0 +1,73 @@ +import TestKit +import XCTest +@testable import WooCommerce + +final class StoreCreationCoordinatorTests: XCTestCase { + private var stores: MockStoresManager! + private var analyticsProvider: MockAnalyticsProvider! + private var analytics: WooAnalytics! + private var navigationController: UINavigationController! + private let window = UIWindow(frame: UIScreen.main.bounds) + + override func setUp() { + super.setUp() + stores = MockStoresManager(sessionManager: SessionManager.makeForTesting()) + analyticsProvider = MockAnalyticsProvider() + analytics = WooAnalytics(analyticsProvider: analyticsProvider) + + window.makeKeyAndVisible() + navigationController = .init() + window.rootViewController = navigationController + } + + override func tearDown() { + navigationController = nil + window.resignKey() + window.rootViewController = nil + analytics = nil + analyticsProvider = nil + stores = nil + super.tearDown() + } + + // MARK: - Presentation in different states + + func test_AuthenticatedWebViewController_is_presented_when_navigationController_is_presenting_another_view() throws { + // Given + let coordinator = StoreCreationCoordinator(source: .storePicker, navigationController: navigationController) + waitFor { promise in + self.navigationController.present(.init(), animated: false) { + promise(()) + } + } + XCTAssertNotNil(navigationController.presentedViewController) + + // When + coordinator.start() + + // Then + waitUntil { + self.navigationController.presentedViewController is WooNavigationController + } + let storeCreationNavigationController = try XCTUnwrap(navigationController.presentedViewController as? UINavigationController) + assertThat(storeCreationNavigationController.topViewController, isAnInstanceOf: AuthenticatedWebViewController.self) + } + + func test_AuthenticatedWebViewController_is_presented_when_navigationController_is_showing_another_view() throws { + // Given + navigationController.show(.init(), sender: nil) + let coordinator = StoreCreationCoordinator(source: .loggedOut(source: .loginEmailError), navigationController: navigationController) + XCTAssertNotNil(navigationController.topViewController) + XCTAssertNil(navigationController.presentedViewController) + + // When + coordinator.start() + + // Then + waitUntil { + self.navigationController.presentedViewController is WooNavigationController + } + let storeCreationNavigationController = try XCTUnwrap(navigationController.presentedViewController as? UINavigationController) + assertThat(storeCreationNavigationController.topViewController, isAnInstanceOf: AuthenticatedWebViewController.self) + } +} diff --git a/WooCommerce/WooCommerceTests/Authentication/StorePickerCoordinatorTests.swift b/WooCommerce/WooCommerceTests/Authentication/StorePickerCoordinatorTests.swift new file mode 100644 index 00000000000..e9aee7e8e01 --- /dev/null +++ b/WooCommerce/WooCommerceTests/Authentication/StorePickerCoordinatorTests.swift @@ -0,0 +1,45 @@ +import WordPressAuthenticator +import TestKit +import XCTest +@testable import WooCommerce + +final class StorePickerCoordinatorTests: XCTestCase { + private var navigationController: UINavigationController! + private let window = UIWindow(frame: UIScreen.main.bounds) + + override func setUp() { + super.setUp() + + window.makeKeyAndVisible() + navigationController = .init() + window.rootViewController = navigationController + + WordPressAuthenticator.initializeAuthenticator() + } + + override func tearDown() { + navigationController = nil + window.resignKey() + window.rootViewController = nil + + super.tearDown() + } + + func test_storeCreationFromLogin_configuration_shows_storePicker_then_presents_storeCreation() throws { + // Given + let coordinator = StorePickerCoordinator(navigationController, config: .storeCreationFromLogin(source: .prologue)) + + // When + coordinator.start() + + // Then + waitUntil { + self.navigationController.presentedViewController is WooNavigationController + } + // Store picker should be pushed to the navigation stack. + assertThat(navigationController.topViewController, isAnInstanceOf: StorePickerViewController.self) + + let storeCreationNavigationController = try XCTUnwrap(navigationController.presentedViewController as? UINavigationController) + assertThat(storeCreationNavigationController.topViewController, isAnInstanceOf: AuthenticatedWebViewController.self) + } +} From 19cb3da6145d6d12278bedd1e52f0e9a324064ba Mon Sep 17 00:00:00 2001 From: Jaclyn Chen Date: Fri, 4 Nov 2022 15:27:12 +0800 Subject: [PATCH 3/7] StorePickerCoordinator: add two test cases for `standard` and `switchingStores` configurations. --- .../StorePickerCoordinatorTests.swift | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/WooCommerce/WooCommerceTests/Authentication/StorePickerCoordinatorTests.swift b/WooCommerce/WooCommerceTests/Authentication/StorePickerCoordinatorTests.swift index e9aee7e8e01..2fa29f3e3e2 100644 --- a/WooCommerce/WooCommerceTests/Authentication/StorePickerCoordinatorTests.swift +++ b/WooCommerce/WooCommerceTests/Authentication/StorePickerCoordinatorTests.swift @@ -42,4 +42,38 @@ final class StorePickerCoordinatorTests: XCTestCase { let storeCreationNavigationController = try XCTUnwrap(navigationController.presentedViewController as? UINavigationController) assertThat(storeCreationNavigationController.topViewController, isAnInstanceOf: AuthenticatedWebViewController.self) } + + func test_standard_configuration_presents_storePicker() throws { + // Given + let coordinator = StorePickerCoordinator(navigationController, config: .standard) + + // When + coordinator.start() + + // Then + waitUntil { + self.navigationController.presentedViewController is WooNavigationController + } + XCTAssertNil(navigationController.topViewController) + + let storePickerNavigationController = try XCTUnwrap(navigationController.presentedViewController as? UINavigationController) + assertThat(storePickerNavigationController.topViewController, isAnInstanceOf: StorePickerViewController.self) + } + + func test_switchingStores_configuration_presents_storePicker() throws { + // Given + let coordinator = StorePickerCoordinator(navigationController, config: .switchingStores) + + // When + coordinator.start() + + // Then + waitUntil { + self.navigationController.presentedViewController is WooNavigationController + } + XCTAssertNil(navigationController.topViewController) + + let storePickerNavigationController = try XCTUnwrap(navigationController.presentedViewController as? UINavigationController) + assertThat(storePickerNavigationController.topViewController, isAnInstanceOf: StorePickerViewController.self) + } } From 78db231ca1aab76b39a99bec4b38598e664e6909 Mon Sep 17 00:00:00 2001 From: Jaclyn Chen Date: Fri, 4 Nov 2022 15:28:21 +0800 Subject: [PATCH 4/7] Remove outdated comment in `LoggedOutStoreCreationCoordinator`. --- .../Store Creation/LoggedOutStoreCreationCoordinator.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/WooCommerce/Classes/Authentication/Store Creation/LoggedOutStoreCreationCoordinator.swift b/WooCommerce/Classes/Authentication/Store Creation/LoggedOutStoreCreationCoordinator.swift index 69ac77c637f..c2ddc6cd7df 100644 --- a/WooCommerce/Classes/Authentication/Store Creation/LoggedOutStoreCreationCoordinator.swift +++ b/WooCommerce/Classes/Authentication/Store Creation/LoggedOutStoreCreationCoordinator.swift @@ -10,7 +10,6 @@ final class LoggedOutStoreCreationCoordinator: Coordinator { case loginEmailError } - /// Mutable to conform to `Coordinator` protocol. let navigationController: UINavigationController private var storePickerCoordinator: StorePickerCoordinator? From ab8bf0343f2f1639f308d9822d36ea15c7e1d9b6 Mon Sep 17 00:00:00 2001 From: Jaclyn Chen Date: Fri, 4 Nov 2022 15:38:31 +0800 Subject: [PATCH 5/7] Add a test case for `LoggedOutStoreCreationCoordinator`. --- .../WooCommerce.xcodeproj/project.pbxproj | 4 +++ ...ggedOutStoreCreationCoordinatorTests.swift | 36 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 WooCommerce/WooCommerceTests/Authentication/LoggedOutStoreCreationCoordinatorTests.swift diff --git a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj index acdfa10b100..df86aa9a927 100644 --- a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj +++ b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj @@ -47,6 +47,7 @@ 020BE77723B4A9D9007FE54C /* AztecLinkFormatBarCommandTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 020BE77623B4A9D9007FE54C /* AztecLinkFormatBarCommandTests.swift */; }; 020C908424C84652001E2BEB /* ProductListMultiSelectorSearchUICommandTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 020C908324C84652001E2BEB /* ProductListMultiSelectorSearchUICommandTests.swift */; }; 020D0BFD2914E92800BB3DCE /* StorePickerCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 020D0BFC2914E92800BB3DCE /* StorePickerCoordinatorTests.swift */; }; + 020D0BFF2914F6BA00BB3DCE /* LoggedOutStoreCreationCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 020D0BFE2914F6BA00BB3DCE /* LoggedOutStoreCreationCoordinatorTests.swift */; }; 020DD48A23229495005822B1 /* ProductsTabProductTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 020DD48923229495005822B1 /* ProductsTabProductTableViewCell.swift */; }; 020DD48D2322A617005822B1 /* ProductsTabProductViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 020DD48C2322A617005822B1 /* ProductsTabProductViewModel.swift */; }; 020DD48F232392C9005822B1 /* UIViewController+AppReview.swift in Sources */ = {isa = PBXBuildFile; fileRef = 020DD48E232392C9005822B1 /* UIViewController+AppReview.swift */; }; @@ -2001,6 +2002,7 @@ 020BE77623B4A9D9007FE54C /* AztecLinkFormatBarCommandTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AztecLinkFormatBarCommandTests.swift; sourceTree = ""; }; 020C908324C84652001E2BEB /* ProductListMultiSelectorSearchUICommandTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductListMultiSelectorSearchUICommandTests.swift; sourceTree = ""; }; 020D0BFC2914E92800BB3DCE /* StorePickerCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorePickerCoordinatorTests.swift; sourceTree = ""; }; + 020D0BFE2914F6BA00BB3DCE /* LoggedOutStoreCreationCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggedOutStoreCreationCoordinatorTests.swift; sourceTree = ""; }; 020DD48923229495005822B1 /* ProductsTabProductTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductsTabProductTableViewCell.swift; sourceTree = ""; }; 020DD48C2322A617005822B1 /* ProductsTabProductViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductsTabProductViewModel.swift; sourceTree = ""; }; 020DD48E232392C9005822B1 /* UIViewController+AppReview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+AppReview.swift"; sourceTree = ""; }; @@ -6159,6 +6161,7 @@ DE50295228BF4A8A00551736 /* JetpackConnectionWebViewModelTests.swift */, 0269A5E62913FD22003B20EB /* StoreCreationCoordinatorTests.swift */, 020D0BFC2914E92800BB3DCE /* StorePickerCoordinatorTests.swift */, + 020D0BFE2914F6BA00BB3DCE /* LoggedOutStoreCreationCoordinatorTests.swift */, ); path = Authentication; sourceTree = ""; @@ -11085,6 +11088,7 @@ 579CDF01274D811D00E8903D /* StoreStatsUsageTracksEventEmitterTests.swift in Sources */, 262A2C2B2537A3330086C1BE /* MockRefunds.swift in Sources */, 027F240C258371150021DB06 /* RefundShippingLabelViewModelTests.swift in Sources */, + 020D0BFF2914F6BA00BB3DCE /* LoggedOutStoreCreationCoordinatorTests.swift in Sources */, D85136DD231E613900DD0539 /* ReviewsViewModelTests.swift in Sources */, DEFD6E61264990FB00E51E0D /* SitePluginListViewModelTests.swift in Sources */, 02B2C831249C4C8D0040C83C /* TextFieldTextAlignmentTests.swift in Sources */, diff --git a/WooCommerce/WooCommerceTests/Authentication/LoggedOutStoreCreationCoordinatorTests.swift b/WooCommerce/WooCommerceTests/Authentication/LoggedOutStoreCreationCoordinatorTests.swift new file mode 100644 index 00000000000..8962ec00b2f --- /dev/null +++ b/WooCommerce/WooCommerceTests/Authentication/LoggedOutStoreCreationCoordinatorTests.swift @@ -0,0 +1,36 @@ +import TestKit +import XCTest +@testable import WooCommerce + +final class LoggedOutStoreCreationCoordinatorTests: XCTestCase { + private var navigationController: UINavigationController! + private let window = UIWindow(frame: UIScreen.main.bounds) + + override func setUp() { + super.setUp() + + window.makeKeyAndVisible() + navigationController = .init() + window.rootViewController = navigationController + } + + override func tearDown() { + navigationController = nil + window.resignKey() + window.rootViewController = nil + + super.tearDown() + } + + func test_start_shows_AccountCreationFormHostingController() throws { + // Given + let coordinator = LoggedOutStoreCreationCoordinator(source: .prologue, navigationController: navigationController) + XCTAssertNil(navigationController.topViewController) + + // When + coordinator.start() + + // Then + assertThat(navigationController.topViewController, isAnInstanceOf: AccountCreationFormHostingController.self) + } +} From baf1826a1d9ac657c97c5bdeb004bc95ab2b7459 Mon Sep 17 00:00:00 2001 From: Jaclyn Chen Date: Fri, 4 Nov 2022 15:40:30 +0800 Subject: [PATCH 6/7] Remove unused dependencies and reorder imports. --- .../Authentication/StoreCreationCoordinatorTests.swift | 10 +--------- .../Authentication/StorePickerCoordinatorTests.swift | 2 +- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/WooCommerce/WooCommerceTests/Authentication/StoreCreationCoordinatorTests.swift b/WooCommerce/WooCommerceTests/Authentication/StoreCreationCoordinatorTests.swift index 7b20e45e71b..3f5aef1c6ef 100644 --- a/WooCommerce/WooCommerceTests/Authentication/StoreCreationCoordinatorTests.swift +++ b/WooCommerce/WooCommerceTests/Authentication/StoreCreationCoordinatorTests.swift @@ -3,17 +3,11 @@ import XCTest @testable import WooCommerce final class StoreCreationCoordinatorTests: XCTestCase { - private var stores: MockStoresManager! - private var analyticsProvider: MockAnalyticsProvider! - private var analytics: WooAnalytics! private var navigationController: UINavigationController! private let window = UIWindow(frame: UIScreen.main.bounds) override func setUp() { super.setUp() - stores = MockStoresManager(sessionManager: SessionManager.makeForTesting()) - analyticsProvider = MockAnalyticsProvider() - analytics = WooAnalytics(analyticsProvider: analyticsProvider) window.makeKeyAndVisible() navigationController = .init() @@ -24,9 +18,7 @@ final class StoreCreationCoordinatorTests: XCTestCase { navigationController = nil window.resignKey() window.rootViewController = nil - analytics = nil - analyticsProvider = nil - stores = nil + super.tearDown() } diff --git a/WooCommerce/WooCommerceTests/Authentication/StorePickerCoordinatorTests.swift b/WooCommerce/WooCommerceTests/Authentication/StorePickerCoordinatorTests.swift index 2fa29f3e3e2..c34bbcf41f8 100644 --- a/WooCommerce/WooCommerceTests/Authentication/StorePickerCoordinatorTests.swift +++ b/WooCommerce/WooCommerceTests/Authentication/StorePickerCoordinatorTests.swift @@ -1,5 +1,5 @@ -import WordPressAuthenticator import TestKit +import WordPressAuthenticator import XCTest @testable import WooCommerce From 378f5d9eb0db6c611253869fe29fc3e610cd082f Mon Sep 17 00:00:00 2001 From: Jaclyn Chen Date: Fri, 4 Nov 2022 15:50:14 +0800 Subject: [PATCH 7/7] StorePickerCoordinator: add two test cases for the remaining store picker configurations. --- .../StorePickerCoordinatorTests.swift | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/WooCommerce/WooCommerceTests/Authentication/StorePickerCoordinatorTests.swift b/WooCommerce/WooCommerceTests/Authentication/StorePickerCoordinatorTests.swift index c34bbcf41f8..605e6e32395 100644 --- a/WooCommerce/WooCommerceTests/Authentication/StorePickerCoordinatorTests.swift +++ b/WooCommerce/WooCommerceTests/Authentication/StorePickerCoordinatorTests.swift @@ -76,4 +76,30 @@ final class StorePickerCoordinatorTests: XCTestCase { let storePickerNavigationController = try XCTUnwrap(navigationController.presentedViewController as? UINavigationController) assertThat(storePickerNavigationController.topViewController, isAnInstanceOf: StorePickerViewController.self) } + + func test_login_configuration_shows_storePicker() throws { + // Given + let coordinator = StorePickerCoordinator(navigationController, config: .login) + + // When + coordinator.start() + + // Then + waitUntil { + self.navigationController.topViewController is StorePickerViewController + } + } + + func test_listStores_configuration_shows_storePicker() throws { + // Given + let coordinator = StorePickerCoordinator(navigationController, config: .listStores) + + // When + coordinator.start() + + // Then + waitUntil { + self.navigationController.topViewController is StorePickerViewController + } + } }