Skip to content

Commit c6839a6

Browse files
authored
Merge pull request #7759 from woocommerce/issue/7745-wrongaccounterrorviewmodel-tests
Login: More unit tests for WrongAccountErrorViewModel
2 parents 83f79f2 + a5aa0be commit c6839a6

File tree

6 files changed

+327
-11
lines changed

6 files changed

+327
-11
lines changed

WooCommerce/Classes/Authentication/AuthenticationManager.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,7 @@ private extension AuthenticationManager {
679679
}
680680

681681
/// Jetpack is required. Present an error if we don't detect a valid installation.
682-
guard site.hasJetpack && site.isJetpackActive else {
682+
guard site.isJetpackConnected else {
683683
return jetpackErrorUI(for: site.url, with: matcher, in: navigationController)
684684
}
685685

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import Foundation
2+
import WordPressAuthenticator
3+
4+
/// An interface used for mocking `WordPressAuthenticator` in unit tests.
5+
/// It's not complete for now since this is used for testing `WrongAccountErrorViewModel` only at the time of writing.
6+
/// Update this further if necessary.
7+
///
8+
protocol Authenticator {
9+
/// Used to present the site credential login flow directly from the delegate.
10+
///
11+
/// - Parameters:
12+
/// - presenter: The view controller that presents the site credential login flow.
13+
/// - siteURL: The URL of the site to log in to.
14+
/// - onCompletion: The closure to be trigged when the login succeeds with the input credentials.
15+
///
16+
static func showSiteCredentialLogin(from presenter: UIViewController, siteURL: String, onCompletion: @escaping (WordPressOrgCredentials) -> Void)
17+
18+
/// A helper method to fetch site info for a given URL.
19+
/// - Parameters:
20+
/// - siteURL: The URL of the site to fetch information for.
21+
/// - onCompletion: The closure to be triggered when fetching site info is done.
22+
///
23+
static func fetchSiteInfo(for siteURL: String, onCompletion: @escaping (Result<WordPressComSiteInfo, Error>) -> Void)
24+
}
25+
26+
/// Makes `WordPressAuthenticator` conform to the interface for mocking.
27+
///
28+
extension WordPressAuthenticator: Authenticator {}

WooCommerce/Classes/Authentication/Navigation Exceptions/WrongAccountErrorViewModel.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ final class WrongAccountErrorViewModel: ULAccountMismatchViewModel {
1717
private let analytics: Analytics
1818
private let jetpackSetupCompletionHandler: (_ email: String, _ xmlrpc: String) -> Void
1919
private let authentication: Authentication
20+
private let authenticatorType: Authenticator.Type
2021

2122
private var storePickerCoordinator: StorePickerCoordinator?
2223
private var siteXMLRPC: String = ""
@@ -32,18 +33,19 @@ final class WrongAccountErrorViewModel: ULAccountMismatchViewModel {
3233
init(siteURL: String?,
3334
showsConnectedStores: Bool,
3435
siteCredentials: WordPressOrgCredentials?,
35-
sessionManager: SessionManagerProtocol = ServiceLocator.stores.sessionManager,
36+
authenticatorType: Authenticator.Type = WordPressAuthenticator.self,
3637
storesManager: StoresManager = ServiceLocator.stores,
3738
analytics: Analytics = ServiceLocator.analytics,
3839
authentication: Authentication = ServiceLocator.authenticationManager,
3940
onJetpackSetupCompletion: @escaping (String, String) -> Void) {
4041
self.siteURL = siteURL ?? Localization.yourSite
4142
self.showsConnectedStores = showsConnectedStores
42-
self.defaultAccount = sessionManager.defaultAccount
43+
self.defaultAccount = storesManager.sessionManager.defaultAccount
4344
self.storesManager = storesManager
4445
self.analytics = analytics
4546
self.authentication = authentication
4647
self.jetpackSetupCompletionHandler = onJetpackSetupCompletion
48+
self.authenticatorType = authenticatorType
4749

4850
if let credentials = siteCredentials {
4951
siteUsername = credentials.username
@@ -181,7 +183,7 @@ private extension WrongAccountErrorViewModel {
181183
///
182184
func fetchSiteInfo() {
183185
activityIndicatorLoadingSubject.send(true)
184-
WordPressAuthenticator.fetchSiteInfo(for: siteURL) { [weak self] result in
186+
authenticatorType.fetchSiteInfo(for: siteURL) { [weak self] result in
185187
guard let self = self else { return }
186188
self.activityIndicatorLoadingSubject.send(false)
187189

@@ -229,7 +231,7 @@ private extension WrongAccountErrorViewModel {
229231
}
230232

231233
func showSiteCredentialLoginAndJetpackConnection(from viewController: UIViewController) {
232-
WordPressAuthenticator.showSiteCredentialLogin(from: viewController, siteURL: siteURL) { [weak self] credentials in
234+
authenticatorType.showSiteCredentialLogin(from: viewController, siteURL: siteURL) { [weak self] credentials in
233235
guard let self = self else { return }
234236
// dismisses the site credential login flow
235237
viewController.dismiss(animated: true)

WooCommerce/WooCommerce.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1669,6 +1669,7 @@
16691669
DE3404E828B4B96800CF0D97 /* NonAtomicSiteViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE3404E728B4B96800CF0D97 /* NonAtomicSiteViewModel.swift */; };
16701670
DE3404EA28B4C1D000CF0D97 /* NonAtomicSiteViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE3404E928B4C1D000CF0D97 /* NonAtomicSiteViewModelTests.swift */; };
16711671
DE34771327F174C8009CA300 /* StatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE34771227F174C8009CA300 /* StatusView.swift */; };
1672+
DE37517C28DC5FC6000163CB /* Authenticator.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE37517B28DC5FC6000163CB /* Authenticator.swift */; };
16721673
DE3877E0283B68CF0075D87E /* DiscountTypeBottomSheetListSelectorCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE3877DF283B68CF0075D87E /* DiscountTypeBottomSheetListSelectorCommand.swift */; };
16731674
DE3877E2283CCBC20075D87E /* BottomSheetListSelector.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE3877E1283CCBC20075D87E /* BottomSheetListSelector.swift */; };
16741675
DE3877E4283E35E80075D87E /* DiscountTypeBottomSheetListSelectorCommandTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE3877E3283E35E80075D87E /* DiscountTypeBottomSheetListSelectorCommandTests.swift */; };
@@ -3587,6 +3588,7 @@
35873588
DE3404E728B4B96800CF0D97 /* NonAtomicSiteViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NonAtomicSiteViewModel.swift; sourceTree = "<group>"; };
35883589
DE3404E928B4C1D000CF0D97 /* NonAtomicSiteViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NonAtomicSiteViewModelTests.swift; sourceTree = "<group>"; };
35893590
DE34771227F174C8009CA300 /* StatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusView.swift; sourceTree = "<group>"; };
3591+
DE37517B28DC5FC6000163CB /* Authenticator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Authenticator.swift; sourceTree = "<group>"; };
35903592
DE3877DF283B68CF0075D87E /* DiscountTypeBottomSheetListSelectorCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscountTypeBottomSheetListSelectorCommand.swift; sourceTree = "<group>"; };
35913593
DE3877E1283CCBC20075D87E /* BottomSheetListSelector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BottomSheetListSelector.swift; sourceTree = "<group>"; };
35923594
DE3877E3283E35E80075D87E /* DiscountTypeBottomSheetListSelectorCommandTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscountTypeBottomSheetListSelectorCommandTests.swift; sourceTree = "<group>"; };
@@ -7004,6 +7006,7 @@
70047006
262C922026F1370000011F92 /* StorePickerError.swift */,
70057007
45527A402472C6160078D609 /* SwitchStoreUseCase.swift */,
70067008
45A4221924ACC79C003B1E4C /* SwitchStoreNoticePresenter.swift */,
7009+
DE37517B28DC5FC6000163CB /* Authenticator.swift */,
70077010
);
70087011
path = Epilogue;
70097012
sourceTree = "<group>";
@@ -9704,6 +9707,7 @@
97049707
03EF250228C615A5006A033E /* InPersonPaymentsMenuViewModel.swift in Sources */,
97059708
0212275C244972660042161F /* BottomSheetListSelectorSectionHeaderView.swift in Sources */,
97069709
DEC6C51A2747758D006832D3 /* JetpackInstallView.swift in Sources */,
9710+
DE37517C28DC5FC6000163CB /* Authenticator.swift in Sources */,
97079711
AED089F227C794BC0020AE10 /* View+CurrencySymbol.swift in Sources */,
97089712
D85806292642BA5400A8AB6C /* PaymentCaptureOrchestrator.swift in Sources */,
97099713
E1E636BB26FB467A00C9D0D7 /* Comparable+Woo.swift in Sources */,

WooCommerce/WooCommerceTests/Authentication/AuthenticationManagerTests.swift

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,40 @@ final class AuthenticationManagerTests: XCTestCase {
159159
// Given
160160
let manager = AuthenticationManager()
161161
let testSite = "http://test.com"
162-
let siteInfo = WordPressComSiteInfo(remote: ["isWordPress": true, "hasJetpack": false, "urlAfterRedirects": testSite])
162+
let siteInfo = siteInfo(url: testSite,
163+
exists: true,
164+
hasWordPress: true,
165+
isWordPressCom: false,
166+
hasJetpack: false,
167+
isJetpackActive: false,
168+
isJetpackConnected: false)
169+
let wpcomCredentials = WordPressComCredentials(authToken: "abc", isJetpackLogin: false, multifactor: false, siteURL: testSite)
170+
let credentials = AuthenticatorCredentials(wpcom: wpcomCredentials, wporg: nil)
171+
let navigationController = UINavigationController()
172+
173+
// When
174+
manager.shouldPresentUsernamePasswordController(for: siteInfo, onCompletion: { _ in })
175+
manager.presentLoginEpilogue(in: navigationController, for: credentials, onDismiss: {})
176+
waitUntil {
177+
navigationController.viewControllers.isNotEmpty
178+
}
179+
180+
// Then
181+
let rootController = navigationController.viewControllers.first
182+
XCTAssertTrue(rootController is ULErrorViewController)
183+
}
184+
185+
func test_it_shows_error_upon_login_epilogue_if_the_site_has_active_jetpack_but_not_connected() {
186+
// Given
187+
let manager = AuthenticationManager()
188+
let testSite = "http://test.com"
189+
let siteInfo = siteInfo(url: testSite,
190+
exists: true,
191+
hasWordPress: true,
192+
isWordPressCom: false,
193+
hasJetpack: true,
194+
isJetpackActive: true,
195+
isJetpackConnected: false)
163196
let wpcomCredentials = WordPressComCredentials(authToken: "abc", isJetpackLogin: false, multifactor: false, siteURL: testSite)
164197
let credentials = AuthenticatorCredentials(wpcom: wpcomCredentials, wporg: nil)
165198
let navigationController = UINavigationController()
@@ -366,10 +399,28 @@ final class AuthenticationManagerTests: XCTestCase {
366399
XCTAssertTrue(topController is ULErrorViewController)
367400
}
368401

402+
func test_troubleshootSite_displays_error_screen_if_site_is_self_hosted_with_jetpack_not_connected() {
403+
// Given
404+
let navigationController = UINavigationController()
405+
let siteInfo = siteInfo(exists: true, hasWordPress: true, isWordPressCom: false, hasJetpack: true, isJetpackActive: true, isJetpackConnected: false)
406+
let storage = MockStorageManager()
407+
let manager = AuthenticationManager(storageManager: storage)
408+
409+
// When
410+
manager.troubleshootSite(siteInfo, in: navigationController)
411+
412+
// Then
413+
waitUntil {
414+
navigationController.viewControllers.isNotEmpty
415+
}
416+
let topController = navigationController.topViewController
417+
XCTAssertTrue(topController is ULErrorViewController)
418+
}
419+
369420
func test_troubleshootSite_displays_account_mismatch_screen_if_site_is_self_hosted_with_jetpack() {
370421
// Given
371422
let navigationController = UINavigationController()
372-
let siteInfo = siteInfo(exists: true, hasWordPress: true, isWordPressCom: false, hasJetpack: true)
423+
let siteInfo = siteInfo(exists: true, hasWordPress: true, isWordPressCom: false, hasJetpack: true, isJetpackActive: true, isJetpackConnected: true)
373424
let storage = MockStorageManager()
374425
let manager = AuthenticationManager(storageManager: storage)
375426

@@ -386,12 +437,19 @@ final class AuthenticationManagerTests: XCTestCase {
386437
}
387438

388439
private extension AuthenticationManagerTests {
389-
func siteInfo(exists: Bool = false, hasWordPress: Bool = false, isWordPressCom: Bool = false, hasJetpack: Bool = false) -> WordPressComSiteInfo {
390-
WordPressComSiteInfo(remote: ["exists": exists,
440+
func siteInfo(url: String = "",
441+
exists: Bool = false,
442+
hasWordPress: Bool = false,
443+
isWordPressCom: Bool = false,
444+
hasJetpack: Bool = false,
445+
isJetpackActive: Bool = false,
446+
isJetpackConnected: Bool = false) -> WordPressComSiteInfo {
447+
WordPressComSiteInfo(remote: ["urlAfterRedirects": url,
448+
"exists": exists,
391449
"isWordPress": hasWordPress,
392450
"hasJetpack": hasJetpack,
393-
"isJetpackActive": hasJetpack,
394-
"isJetpackConnected": hasJetpack,
451+
"isJetpackActive": isJetpackActive,
452+
"isJetpackConnected": isJetpackConnected,
395453
"isWordPressDotCom": isWordPressCom])
396454
}
397455
}

0 commit comments

Comments
 (0)