From a1cf891fb30d985c9eb59895a06c0f19c2534e8f Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Thu, 14 Nov 2024 16:33:16 +0100 Subject: [PATCH 1/9] Point to branch repositories of WordPressAuthentication and WordPressKit --- Podfile | 6 ++++-- Podfile.lock | 19 ++++++++++++------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/Podfile b/Podfile index c72330c674f..f1f4264cfee 100644 --- a/Podfile +++ b/Podfile @@ -92,10 +92,12 @@ target 'WooCommerce' do # To allow pod to pick up beta versions use -beta. E.g., 1.1.7-beta.1 # pod 'WordPressAuthenticator', '~> 9.10.0' - # pod 'WordPressAuthenticator', git: 'https://github.com/wordpress-mobile/WordPressAuthenticator-iOS.git', branch: '' - pod 'WordPressAuthenticator', git: 'https://github.com/wordpress-mobile/WordPressAuthenticator-iOS.git', commit: 'f591b6e0442f9f153ad3842efdb8c81d26235c44' + pod 'WordPressAuthenticator', git: 'https://github.com/wordpress-mobile/WordPressAuthenticator-iOS.git', branch: 'magic-link-create-account' + # pod 'WordPressAuthenticator', git: 'https://github.com/wordpress-mobile/WordPressAuthenticator-iOS.git', commit: 'f591b6e0442f9f153ad3842efdb8c81d26235c44' # pod 'WordPressAuthenticator', path: '../WordPressAuthenticator-iOS' + pod 'WordPressKit', git: 'https://github.com/wordpress-mobile/WordPressKit-iOS.git', branch: 'magic-link-create-account' + wordpress_shared pod 'WordPressUI', '~> 1.15' diff --git a/Podfile.lock b/Podfile.lock index 7f0e7a46b7e..1b90493e8a3 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -67,7 +67,8 @@ DEPENDENCIES: - StripeTerminal (~> 3.9.1) - SwiftLint (= 0.54.0) - WordPress-Editor-iOS (~> 1.19) - - WordPressAuthenticator (from `https://github.com/wordpress-mobile/WordPressAuthenticator-iOS.git`, commit `f591b6e0442f9f153ad3842efdb8c81d26235c44`) + - WordPressAuthenticator (from `https://github.com/wordpress-mobile/WordPressAuthenticator-iOS.git`, branch `magic-link-create-account`) + - WordPressKit (from `https://github.com/wordpress-mobile/WordPressKit-iOS.git`, branch `magic-link-create-account`) - WordPressShared (~> 2.1) - WordPressUI (~> 1.15) - Wormholy (~> 1.6.6) @@ -75,8 +76,6 @@ DEPENDENCIES: - ZendeskSupportSDK (~> 9.0.0) SPEC REPOS: - https://github.com/wordpress-mobile/cocoapods-specs.git: - - WordPressKit trunk: - Alamofire - Automattic-Tracks-iOS @@ -110,13 +109,19 @@ SPEC REPOS: EXTERNAL SOURCES: WordPressAuthenticator: - :commit: f591b6e0442f9f153ad3842efdb8c81d26235c44 + :branch: magic-link-create-account :git: https://github.com/wordpress-mobile/WordPressAuthenticator-iOS.git + WordPressKit: + :branch: magic-link-create-account + :git: https://github.com/wordpress-mobile/WordPressKit-iOS.git CHECKOUT OPTIONS: WordPressAuthenticator: - :commit: f591b6e0442f9f153ad3842efdb8c81d26235c44 + :commit: 75b4296b07278be64f070ee06db826bf59b4931f :git: https://github.com/wordpress-mobile/WordPressAuthenticator-iOS.git + WordPressKit: + :commit: f731cfaf2ccdb26604c9ac251d1a87d488910f4c + :git: https://github.com/wordpress-mobile/WordPressKit-iOS.git SPEC CHECKSUMS: Alamofire: 3ca42e259043ee0dc5c0cdd76c4bc568b8e42af7 @@ -137,7 +142,7 @@ SPEC CHECKSUMS: WordPress-Aztec-iOS: 8eaa928fb3a5694924ed3befac64beaae5656e12 WordPress-Editor-iOS: 98ce1fc542c3a09e48ddc9423405b1d1e48240f1 WordPressAuthenticator: d151cc7ebc1cfcbf5c28bb2c9afe760a75b49ba6 - WordPressKit: de44094b3be8998504a3a57700bc3e96e3b46f57 + WordPressKit: 98809cdb460bacc6634b49079335a5ccace34e59 WordPressShared: 0aa459e5257a77184db87805a998f447443c9706 WordPressUI: 700e3ec5a9f77b6920c8104c338c85788036ab3c Wormholy: 09da0b876f9276031fd47383627cb75e194fc068 @@ -151,6 +156,6 @@ SPEC CHECKSUMS: ZendeskSupportProvidersSDK: 281acf2bb731d2a67f913cfe653ed0da9f5b2f42 ZendeskSupportSDK: b512cfc74b6bf8490e589f02cf52e27ed4f2bebe -PODFILE CHECKSUM: 51f5cabba416d490c8f90395fa0a86fde13dd931 +PODFILE CHECKSUM: ffd26a573a14b02a6b210b3e3d32a9de1d4ac7c6 COCOAPODS: 1.16.1 From ced1d21048313f338b8ea34a4c54ef2daf176c02 Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Thu, 14 Nov 2024 16:38:24 +0100 Subject: [PATCH 2/9] Update protocol to match the updated implementation --- .../WPComLogin/WPComEmailLoginViewModel.swift | 7 +++++-- .../Authentication/WPComLogin/WPComLoginCoordinator.swift | 5 ++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/WooCommerce/Classes/Authentication/WPComLogin/WPComEmailLoginViewModel.swift b/WooCommerce/Classes/Authentication/WPComLogin/WPComEmailLoginViewModel.swift index 834055fadf5..744486c9189 100644 --- a/WooCommerce/Classes/Authentication/WPComLogin/WPComEmailLoginViewModel.swift +++ b/WooCommerce/Classes/Authentication/WPComLogin/WPComEmailLoginViewModel.swift @@ -6,7 +6,7 @@ import protocol WooFoundation.Analytics /// A protocol used to mock `WordPressComAccountService` for unit tests. protocol WordPressComAccountServiceProtocol { func isPasswordlessAccount(username: String, success: @escaping (Bool) -> Void, failure: @escaping (Error) -> Void) - func requestAuthenticationLink(for email: String, jetpackLogin: Bool, success: @escaping () -> Void, failure: @escaping (Error) -> Void) + func requestAuthenticationLink(for email: String, jetpackLogin: Bool, createAccountIfNotFound: Bool, success: @escaping () -> Void, failure: @escaping (Error) -> Void) } /// Conformance @@ -96,7 +96,10 @@ final class WPComEmailLoginViewModel: ObservableObject { func requestAuthenticationLink(email: String) async { do { try await withCheckedThrowingContinuation { continuation in - accountService.requestAuthenticationLink(for: email, jetpackLogin: false, success: { + accountService.requestAuthenticationLink(for: email, + jetpackLogin: false, + createAccountIfNotFound: false, + success: { continuation.resume() }, failure: { error in continuation.resume(throwing: error) diff --git a/WooCommerce/Classes/Authentication/WPComLogin/WPComLoginCoordinator.swift b/WooCommerce/Classes/Authentication/WPComLogin/WPComLoginCoordinator.swift index 70f74402166..26b5440d434 100644 --- a/WooCommerce/Classes/Authentication/WPComLogin/WPComLoginCoordinator.swift +++ b/WooCommerce/Classes/Authentication/WPComLogin/WPComLoginCoordinator.swift @@ -151,7 +151,10 @@ private extension WPComLoginCoordinator { @MainActor func requestAuthenticationLink(email: String) async throws { try await withCheckedThrowingContinuation { continuation in - accountService.requestAuthenticationLink(for: email, jetpackLogin: false, success: { + accountService.requestAuthenticationLink(for: email, + jetpackLogin: false, + createAccountIfNotFound: false, + success: { continuation.resume() }, failure: { error in continuation.resume(throwing: error) From b80ceb741512b0d3ac8b6fe49e8fa2ec183963f7 Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Thu, 14 Nov 2024 16:58:02 +0100 Subject: [PATCH 3/9] Add a new feature flag --- Experiments/Experiments/DefaultFeatureFlagService.swift | 2 ++ Experiments/Experiments/FeatureFlag.swift | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/Experiments/Experiments/DefaultFeatureFlagService.swift b/Experiments/Experiments/DefaultFeatureFlagService.swift index 39ea8e9353d..0b419afd0f9 100644 --- a/Experiments/Experiments/DefaultFeatureFlagService.swift +++ b/Experiments/Experiments/DefaultFeatureFlagService.swift @@ -93,6 +93,8 @@ public struct DefaultFeatureFlagService: FeatureFlagService { return buildConfig == .localDeveloper case .displayInfiniteScrollingUIDetailsInPointOfSale: return buildConfig == .localDeveloper || buildConfig == .alpha + case .jetpackSetupWPComAccountCreation: + return buildConfig == .localDeveloper || buildConfig == .alpha default: return true } diff --git a/Experiments/Experiments/FeatureFlag.swift b/Experiments/Experiments/FeatureFlag.swift index 7dafa9611fb..56bf7cb457e 100644 --- a/Experiments/Experiments/FeatureFlag.swift +++ b/Experiments/Experiments/FeatureFlag.swift @@ -200,4 +200,8 @@ public enum FeatureFlag: Int { /// Enables UI-related aspects of infinite scrolling in POS. It does not affect the actual infinite scrolling behaviour. /// case displayInfiniteScrollingUIDetailsInPointOfSale + + /// Enables WPCom account creation during Jetpack setup + /// + case jetpackSetupWPComAccountCreation } From c5583672d739e445dda23d660ac151961c2f1937 Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Thu, 14 Nov 2024 17:22:36 +0100 Subject: [PATCH 4/9] Launch signup using magic link when account is not found --- .../WPComLogin/WPComEmailLoginView.swift | 1 + .../WPComLogin/WPComEmailLoginViewModel.swift | 22 +++++++++++++++---- .../JetpackSetupCoordinator.swift | 7 +++++- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/WooCommerce/Classes/Authentication/WPComLogin/WPComEmailLoginView.swift b/WooCommerce/Classes/Authentication/WPComLogin/WPComEmailLoginView.swift index be4d93ca551..288ab2f3c2a 100644 --- a/WooCommerce/Classes/Authentication/WPComLogin/WPComEmailLoginView.swift +++ b/WooCommerce/Classes/Authentication/WPComLogin/WPComEmailLoginView.swift @@ -134,6 +134,7 @@ struct WPComEmailLoginView_Previews: PreviewProvider { static var previews: some View { WPComEmailLoginView(viewModel: .init(siteURL: "https://example.com", requiresConnectionOnly: true, + allowAccountCreation: false, onPasswordUIRequest: { _ in }, onMagicLinkUIRequest: { _ in }, onError: { _ in })) diff --git a/WooCommerce/Classes/Authentication/WPComLogin/WPComEmailLoginViewModel.swift b/WooCommerce/Classes/Authentication/WPComLogin/WPComEmailLoginViewModel.swift index 744486c9189..7ad394ac81b 100644 --- a/WooCommerce/Classes/Authentication/WPComLogin/WPComEmailLoginViewModel.swift +++ b/WooCommerce/Classes/Authentication/WPComLogin/WPComEmailLoginViewModel.swift @@ -2,6 +2,8 @@ import Combine import UIKit import WordPressAuthenticator import protocol WooFoundation.Analytics +import enum WordPressKit.WordPressAPIError +import struct WordPressKit.WordPressComRestApiEndpointError /// A protocol used to mock `WordPressComAccountService` for unit tests. protocol WordPressComAccountServiceProtocol { @@ -21,6 +23,7 @@ final class WPComEmailLoginViewModel: ObservableObject { let termsAttributedString: NSAttributedString + private let allowAccountCreation: Bool private let accountService: WordPressComAccountServiceProtocol private let analytics: Analytics private let onPasswordUIRequest: (String) -> Void @@ -31,12 +34,14 @@ final class WPComEmailLoginViewModel: ObservableObject { init(siteURL: String, requiresConnectionOnly: Bool, + allowAccountCreation: Bool, debounceDuration: Double = Constants.fieldDebounceDuration, accountService: WordPressComAccountServiceProtocol = WordPressComAccountService(), analytics: Analytics = ServiceLocator.analytics, onPasswordUIRequest: @escaping (String) -> Void, onMagicLinkUIRequest: @escaping (String) -> Void, onError: @escaping (String) -> Void) { + self.allowAccountCreation = allowAccountCreation self.analytics = analytics self.accountService = accountService self.onPasswordUIRequest = onPasswordUIRequest @@ -78,8 +83,16 @@ final class WPComEmailLoginViewModel: ObservableObject { } await startAuthentication(email: email, isPasswordlessAccount: passwordless) } catch { - analytics.track(event: .JetpackSetup.loginFlow(step: .emailAddress, failure: error)) - onError(error.localizedDescription) + if allowAccountCreation, + let apiError = error as? WordPressAPIError, + case let .endpointError(endpointError) = apiError, + endpointError.apiErrorCode == Constants.unknownUserErrorCode { + // The user does not exist yet, trigger magic link flow for account creation + await requestAuthenticationLink(email: email, forAccountCreation: true) + } else { + analytics.track(event: .JetpackSetup.loginFlow(step: .emailAddress, failure: error)) + onError(error.localizedDescription) + } } } @@ -93,12 +106,12 @@ final class WPComEmailLoginViewModel: ObservableObject { } @MainActor - func requestAuthenticationLink(email: String) async { + func requestAuthenticationLink(email: String, forAccountCreation: Bool = false) async { do { try await withCheckedThrowingContinuation { continuation in accountService.requestAuthenticationLink(for: email, jetpackLogin: false, - createAccountIfNotFound: false, + createAccountIfNotFound: forAccountCreation, success: { continuation.resume() }, failure: { error in @@ -119,6 +132,7 @@ extension WPComEmailLoginViewModel { static let jetpackTermsURL = "https://jetpack.com/redirect/?source=wpcom-tos&site=" static let jetpackShareDetailsURL = "https://jetpack.com/redirect/?source=jetpack-support-what-data-does-jetpack-sync&site=" static let wpcomErrorCodeKey = "WordPressComRestApiErrorCodeKey" + static let unknownUserErrorCode = "unknown_user" } enum Localization { diff --git a/WooCommerce/Classes/ViewRelated/JetpackSetup/JetpackSetupCoordinator.swift b/WooCommerce/Classes/ViewRelated/JetpackSetup/JetpackSetupCoordinator.swift index 6a39bf71323..eecb4449bcc 100644 --- a/WooCommerce/Classes/ViewRelated/JetpackSetup/JetpackSetupCoordinator.swift +++ b/WooCommerce/Classes/ViewRelated/JetpackSetup/JetpackSetupCoordinator.swift @@ -1,4 +1,5 @@ import UIKit +import Experiments import Yosemite import enum Networking.NetworkError import class Networking.AlamofireNetwork @@ -16,6 +17,7 @@ final class JetpackSetupCoordinator { private var jetpackConnectedEmail: String? private let stores: StoresManager private let analytics: Analytics + private let featureFlagService: FeatureFlagService private let dotcomAuthScheme: String private var loginNavigationController: LoginNavigationController? @@ -24,6 +26,7 @@ final class JetpackSetupCoordinator { private lazy var emailLoginViewModel: WPComEmailLoginViewModel = { .init(siteURL: site.url, requiresConnectionOnly: requiresConnectionOnly, + allowAccountCreation: featureFlagService.isFeatureFlagEnabled(.jetpackSetupWPComAccountCreation), onPasswordUIRequest: showPasswordUI(email:), onMagicLinkUIRequest: showMagicLinkUI(email:), onError: { [weak self] message in @@ -40,13 +43,15 @@ final class JetpackSetupCoordinator { dotcomAuthScheme: String = ApiCredentials.dotcomAuthScheme, rootViewController: UIViewController, stores: StoresManager = ServiceLocator.stores, - analytics: Analytics = ServiceLocator.analytics) { + analytics: Analytics = ServiceLocator.analytics, + featureFlagService: FeatureFlagService = ServiceLocator.featureFlagService) { self.site = site self.dotcomAuthScheme = dotcomAuthScheme self.requiresConnectionOnly = false // to be updated later after fetching Jetpack status self.rootViewController = rootViewController self.stores = stores self.analytics = analytics + self.featureFlagService = featureFlagService /// the authenticator needs to be initialized with configs /// to be used for requesting authentication link and handle login later. From 25f2815fe5774c38c9db623338d97b1d9e1c9030 Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Thu, 14 Nov 2024 17:22:48 +0100 Subject: [PATCH 5/9] Add and update tests --- .../MockWordPressComAccountService.swift | 6 +- .../WPComEmailLoginViewModelTests.swift | 61 +++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/WooCommerce/WooCommerceTests/Mocks/MockWordPressComAccountService.swift b/WooCommerce/WooCommerceTests/Mocks/MockWordPressComAccountService.swift index a3cb9344f07..f04a4b62e39 100644 --- a/WooCommerce/WooCommerceTests/Mocks/MockWordPressComAccountService.swift +++ b/WooCommerce/WooCommerceTests/Mocks/MockWordPressComAccountService.swift @@ -17,7 +17,11 @@ final class MockWordPressComAccountService: WordPressComAccountServiceProtocol { failure(passwordlessAccountCheckError) } - func requestAuthenticationLink(for email: String, jetpackLogin: Bool, success: @escaping () -> Void, failure: @escaping (Error) -> Void) { + func requestAuthenticationLink(for email: String, + jetpackLogin: Bool, + createAccountIfNotFound: Bool, + success: @escaping () -> Void, + failure: @escaping (Error) -> Void) { triggeredRequestAuthenticationLink = true guard let authenticationLinkRequestError else { return success() diff --git a/WooCommerce/WooCommerceTests/ViewRelated/JetpackSetup/WPComLogin/WPComEmailLoginViewModelTests.swift b/WooCommerce/WooCommerceTests/ViewRelated/JetpackSetup/WPComLogin/WPComEmailLoginViewModelTests.swift index 866db08a807..198a08f012f 100644 --- a/WooCommerce/WooCommerceTests/ViewRelated/JetpackSetup/WPComLogin/WPComEmailLoginViewModelTests.swift +++ b/WooCommerce/WooCommerceTests/ViewRelated/JetpackSetup/WPComLogin/WPComEmailLoginViewModelTests.swift @@ -1,4 +1,5 @@ import XCTest +@testable import WordPressKit @testable import WooCommerce final class WPComEmailLoginViewModelTests: XCTestCase { @@ -8,6 +9,7 @@ final class WPComEmailLoginViewModelTests: XCTestCase { let siteURL = "https://example.com" let viewModel = WPComEmailLoginViewModel(siteURL: siteURL, requiresConnectionOnly: false, + allowAccountCreation: false, onPasswordUIRequest: { _ in }, onMagicLinkUIRequest: { _ in }, onError: { _ in }) @@ -24,6 +26,7 @@ final class WPComEmailLoginViewModelTests: XCTestCase { let siteURL = "https://example.com" let viewModel = WPComEmailLoginViewModel(siteURL: siteURL, requiresConnectionOnly: true, + allowAccountCreation: false, onPasswordUIRequest: { _ in }, onMagicLinkUIRequest: { _ in }, onError: { _ in }) @@ -40,6 +43,7 @@ final class WPComEmailLoginViewModelTests: XCTestCase { let siteURL = "https://example.com" let viewModel = WPComEmailLoginViewModel(siteURL: siteURL, requiresConnectionOnly: false, + allowAccountCreation: false, onPasswordUIRequest: { _ in }, onMagicLinkUIRequest: { _ in }, onError: { _ in }) @@ -56,6 +60,7 @@ final class WPComEmailLoginViewModelTests: XCTestCase { let siteURL = "https://example.com" let viewModel = WPComEmailLoginViewModel(siteURL: siteURL, requiresConnectionOnly: true, + allowAccountCreation: false, onPasswordUIRequest: { _ in }, onMagicLinkUIRequest: { _ in }, onError: { _ in }) @@ -72,6 +77,7 @@ final class WPComEmailLoginViewModelTests: XCTestCase { let siteURL = "https://example.com" let viewModel = WPComEmailLoginViewModel(siteURL: siteURL, requiresConnectionOnly: true, + allowAccountCreation: false, onPasswordUIRequest: { _ in }, onMagicLinkUIRequest: { _ in }, onError: { _ in }) @@ -92,6 +98,7 @@ final class WPComEmailLoginViewModelTests: XCTestCase { mockAccountService.shouldReturnPasswordlessAccount = true let viewModel = WPComEmailLoginViewModel(siteURL: "https://example.com", requiresConnectionOnly: true, + allowAccountCreation: false, accountService: mockAccountService, onPasswordUIRequest: { _ in }, onMagicLinkUIRequest: { _ in }, @@ -115,6 +122,7 @@ final class WPComEmailLoginViewModelTests: XCTestCase { var triggeredOnError = false let viewModel = WPComEmailLoginViewModel(siteURL: "https://example.com", requiresConnectionOnly: true, + allowAccountCreation: false, accountService: mockAccountService, onPasswordUIRequest: { _ in }, onMagicLinkUIRequest: { _ in }, @@ -133,6 +141,7 @@ final class WPComEmailLoginViewModelTests: XCTestCase { var triggeredPasswordUIRequest = false let viewModel = WPComEmailLoginViewModel(siteURL: "https://example.com", requiresConnectionOnly: true, + allowAccountCreation: false, accountService: mockAccountService, onPasswordUIRequest: { _ in triggeredPasswordUIRequest = true }, onMagicLinkUIRequest: { _ in }, @@ -150,6 +159,7 @@ final class WPComEmailLoginViewModelTests: XCTestCase { var triggeredOnMagicLinkUIRequest = false let viewModel = WPComEmailLoginViewModel(siteURL: "https://example.com", requiresConnectionOnly: true, + allowAccountCreation: false, accountService: mockAccountService, onPasswordUIRequest: { _ in }, onMagicLinkUIRequest: { _ in triggeredOnMagicLinkUIRequest = true }, @@ -168,6 +178,7 @@ final class WPComEmailLoginViewModelTests: XCTestCase { var triggeredOnError = false let viewModel = WPComEmailLoginViewModel(siteURL: "https://example.com", requiresConnectionOnly: true, + allowAccountCreation: false, accountService: mockAccountService, onPasswordUIRequest: { _ in }, onMagicLinkUIRequest: { _ in }, @@ -178,4 +189,54 @@ final class WPComEmailLoginViewModelTests: XCTestCase { // Then XCTAssertTrue(triggeredOnError) } + + func test_given_unknown_email_when_allowAccountCreation_true_then_create_account() async { + // Given + let mockAccountService = MockWordPressComAccountService() + mockAccountService.passwordlessAccountCheckError = WordPressAPIError.endpointError( + WordPressComRestApiEndpointError( + code: WordPressComRestApiErrorCode.unknown, + apiErrorCode: "unknown_user" + ) + ) + var triggeredOnMagicLinkUIRequest = false + let viewModel = WPComEmailLoginViewModel(siteURL: "https://example.com", + requiresConnectionOnly: true, + allowAccountCreation: true, + accountService: mockAccountService, + onPasswordUIRequest: { _ in }, + onMagicLinkUIRequest: { _ in triggeredOnMagicLinkUIRequest = true }, + onError: { _ in }) + + // When + await viewModel.checkWordPressComAccount(email: "mail@example.com") + + // Then + XCTAssertTrue(triggeredOnMagicLinkUIRequest) + } + + func test_given_unknown_email_when_allowAccountCreation_false_then_trigger_onError() async { + // Given + let mockAccountService = MockWordPressComAccountService() + mockAccountService.passwordlessAccountCheckError = WordPressAPIError.endpointError( + WordPressComRestApiEndpointError( + code: WordPressComRestApiErrorCode.unknown, + apiErrorCode: "unknown_user" + ) + ) + var triggeredOnError = false + let viewModel = WPComEmailLoginViewModel(siteURL: "https://example.com", + requiresConnectionOnly: true, + allowAccountCreation: false, + accountService: mockAccountService, + onPasswordUIRequest: { _ in }, + onMagicLinkUIRequest: { _ in }, + onError: { _ in triggeredOnError = true }) + + // When + await viewModel.checkWordPressComAccount(email: "mail@example.com") + + // Then + XCTAssertTrue(triggeredOnError) + } } From aa7a58781179a35b0c50e28800f06034a0c655e3 Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Fri, 15 Nov 2024 09:59:14 +0100 Subject: [PATCH 6/9] Fix lint issue --- .../WPComLogin/WPComEmailLoginViewModel.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/WooCommerce/Classes/Authentication/WPComLogin/WPComEmailLoginViewModel.swift b/WooCommerce/Classes/Authentication/WPComLogin/WPComEmailLoginViewModel.swift index 7ad394ac81b..7528dace106 100644 --- a/WooCommerce/Classes/Authentication/WPComLogin/WPComEmailLoginViewModel.swift +++ b/WooCommerce/Classes/Authentication/WPComLogin/WPComEmailLoginViewModel.swift @@ -8,7 +8,11 @@ import struct WordPressKit.WordPressComRestApiEndpointError /// A protocol used to mock `WordPressComAccountService` for unit tests. protocol WordPressComAccountServiceProtocol { func isPasswordlessAccount(username: String, success: @escaping (Bool) -> Void, failure: @escaping (Error) -> Void) - func requestAuthenticationLink(for email: String, jetpackLogin: Bool, createAccountIfNotFound: Bool, success: @escaping () -> Void, failure: @escaping (Error) -> Void) + func requestAuthenticationLink(for email: String, + jetpackLogin: Bool, + createAccountIfNotFound: Bool, + success: @escaping () -> Void, + failure: @escaping (Error) -> Void) } /// Conformance From 99ad008f9269d0b2f94e423bcaeffd6118e2e60f Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Tue, 19 Nov 2024 11:46:19 +0100 Subject: [PATCH 7/9] Use guard instead of if else --- .../WPComLogin/WPComEmailLoginViewModel.swift | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/WooCommerce/Classes/Authentication/WPComLogin/WPComEmailLoginViewModel.swift b/WooCommerce/Classes/Authentication/WPComLogin/WPComEmailLoginViewModel.swift index 7528dace106..d5ef7b62337 100644 --- a/WooCommerce/Classes/Authentication/WPComLogin/WPComEmailLoginViewModel.swift +++ b/WooCommerce/Classes/Authentication/WPComLogin/WPComEmailLoginViewModel.swift @@ -87,16 +87,16 @@ final class WPComEmailLoginViewModel: ObservableObject { } await startAuthentication(email: email, isPasswordlessAccount: passwordless) } catch { - if allowAccountCreation, - let apiError = error as? WordPressAPIError, - case let .endpointError(endpointError) = apiError, - endpointError.apiErrorCode == Constants.unknownUserErrorCode { - // The user does not exist yet, trigger magic link flow for account creation - await requestAuthenticationLink(email: email, forAccountCreation: true) - } else { + guard allowAccountCreation, + let apiError = error as? WordPressAPIError, + case .endpointError(let endpointError) = apiError, + endpointError.apiErrorCode == Constants.unknownUserErrorCode else { analytics.track(event: .JetpackSetup.loginFlow(step: .emailAddress, failure: error)) onError(error.localizedDescription) + return } + + await requestAuthenticationLink(email: email, forAccountCreation: true) } } From f910f7638da0d66a5e5dbf79addbffd79fa2f617 Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Thu, 21 Nov 2024 17:45:30 +1100 Subject: [PATCH 8/9] Point WordPressAuthenticator to commit on `trunk` including changes See https://github.com/wordpress-mobile/WordPressAuthenticator-iOS/pull/861 --- Podfile | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Podfile b/Podfile index f1f4264cfee..86a31392fd4 100644 --- a/Podfile +++ b/Podfile @@ -92,12 +92,10 @@ target 'WooCommerce' do # To allow pod to pick up beta versions use -beta. E.g., 1.1.7-beta.1 # pod 'WordPressAuthenticator', '~> 9.10.0' - pod 'WordPressAuthenticator', git: 'https://github.com/wordpress-mobile/WordPressAuthenticator-iOS.git', branch: 'magic-link-create-account' - # pod 'WordPressAuthenticator', git: 'https://github.com/wordpress-mobile/WordPressAuthenticator-iOS.git', commit: 'f591b6e0442f9f153ad3842efdb8c81d26235c44' + # pod 'WordPressAuthenticator', git: 'https://github.com/wordpress-mobile/WordPressAuthenticator-iOS.git', branch: '' + pod 'WordPressAuthenticator', git: 'https://github.com/wordpress-mobile/WordPressAuthenticator-iOS.git', commit: 'cd53ee3d6209619be6f7bb61f1707fbebf77798c' # pod 'WordPressAuthenticator', path: '../WordPressAuthenticator-iOS' - pod 'WordPressKit', git: 'https://github.com/wordpress-mobile/WordPressKit-iOS.git', branch: 'magic-link-create-account' - wordpress_shared pod 'WordPressUI', '~> 1.15' From 74eff52ba50d1a2826052c3ca8f3123303f74b44 Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Thu, 21 Nov 2024 17:58:31 +1100 Subject: [PATCH 9/9] =?UTF-8?q?Track=20`Podfile.lock`=20update=20after=20r?= =?UTF-8?q?unning=20`pod=20install`=20=F0=9F=A4=A6=E2=80=8D=E2=99=82?= =?UTF-8?q?=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I can't believe I forgot this step in the previous commit... --- Podfile.lock | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/Podfile.lock b/Podfile.lock index 1b90493e8a3..550573d1fa7 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -28,10 +28,10 @@ PODS: - Gridicons (~> 1.0) - "NSURL+IDN (= 0.4)" - SVProgressHUD (~> 2.2.5) - - WordPressKit (~> 17.0) + - WordPressKit (~> 17.3) - WordPressShared (~> 2.1-beta) - WordPressUI (~> 1.7-beta) - - WordPressKit (17.2.0): + - WordPressKit (17.3.0): - NSObject-SafeExpectations (~> 0.0.4) - UIDeviceIdentifier (~> 2.0) - WordPressShared (~> 2.0-beta) @@ -67,8 +67,7 @@ DEPENDENCIES: - StripeTerminal (~> 3.9.1) - SwiftLint (= 0.54.0) - WordPress-Editor-iOS (~> 1.19) - - WordPressAuthenticator (from `https://github.com/wordpress-mobile/WordPressAuthenticator-iOS.git`, branch `magic-link-create-account`) - - WordPressKit (from `https://github.com/wordpress-mobile/WordPressKit-iOS.git`, branch `magic-link-create-account`) + - WordPressAuthenticator (from `https://github.com/wordpress-mobile/WordPressAuthenticator-iOS.git`, commit `cd53ee3d6209619be6f7bb61f1707fbebf77798c`) - WordPressShared (~> 2.1) - WordPressUI (~> 1.15) - Wormholy (~> 1.6.6) @@ -94,6 +93,7 @@ SPEC REPOS: - UIDeviceIdentifier - WordPress-Aztec-iOS - WordPress-Editor-iOS + - WordPressKit - WordPressShared - WordPressUI - Wormholy @@ -109,19 +109,13 @@ SPEC REPOS: EXTERNAL SOURCES: WordPressAuthenticator: - :branch: magic-link-create-account + :commit: cd53ee3d6209619be6f7bb61f1707fbebf77798c :git: https://github.com/wordpress-mobile/WordPressAuthenticator-iOS.git - WordPressKit: - :branch: magic-link-create-account - :git: https://github.com/wordpress-mobile/WordPressKit-iOS.git CHECKOUT OPTIONS: WordPressAuthenticator: - :commit: 75b4296b07278be64f070ee06db826bf59b4931f + :commit: cd53ee3d6209619be6f7bb61f1707fbebf77798c :git: https://github.com/wordpress-mobile/WordPressAuthenticator-iOS.git - WordPressKit: - :commit: f731cfaf2ccdb26604c9ac251d1a87d488910f4c - :git: https://github.com/wordpress-mobile/WordPressKit-iOS.git SPEC CHECKSUMS: Alamofire: 3ca42e259043ee0dc5c0cdd76c4bc568b8e42af7 @@ -141,8 +135,8 @@ SPEC CHECKSUMS: UIDeviceIdentifier: 442b65b4ff1832d4ca9c2a157815cb29ad981b17 WordPress-Aztec-iOS: 8eaa928fb3a5694924ed3befac64beaae5656e12 WordPress-Editor-iOS: 98ce1fc542c3a09e48ddc9423405b1d1e48240f1 - WordPressAuthenticator: d151cc7ebc1cfcbf5c28bb2c9afe760a75b49ba6 - WordPressKit: 98809cdb460bacc6634b49079335a5ccace34e59 + WordPressAuthenticator: 0f4f47d6f71cfa763cb636876d69170a3c710002 + WordPressKit: faf8c6de7c2acfe71cf95b4db896901060967089 WordPressShared: 0aa459e5257a77184db87805a998f447443c9706 WordPressUI: 700e3ec5a9f77b6920c8104c338c85788036ab3c Wormholy: 09da0b876f9276031fd47383627cb75e194fc068 @@ -156,6 +150,6 @@ SPEC CHECKSUMS: ZendeskSupportProvidersSDK: 281acf2bb731d2a67f913cfe653ed0da9f5b2f42 ZendeskSupportSDK: b512cfc74b6bf8490e589f02cf52e27ed4f2bebe -PODFILE CHECKSUM: ffd26a573a14b02a6b210b3e3d32a9de1d4ac7c6 +PODFILE CHECKSUM: f02fa3bd6b4c798923cccc4fbe03de910e60891b COCOAPODS: 1.16.1