Skip to content

Commit 47784c5

Browse files
authored
Merge pull request #7996 from woocommerce/issue/7904-simplified-login-ab-testing
Simplified login: Apply A/B test
2 parents b5234ea + 2351b0b commit 47784c5

File tree

8 files changed

+31
-135
lines changed

8 files changed

+31
-135
lines changed

Experiments/Experiments/ABTest.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ public enum ABTest: String, CaseIterable {
1616
/// Experiment ref: pbxNRc-1S0-p2
1717
case aaTestLoggedOut = "woocommerceios_explat_aa_test_logged_out_202211"
1818

19+
/// A/B test to measure the sign-in success rate when only WPCom login is enabled.
20+
/// Experiment ref: pbxNRc-27s-p2
21+
///
22+
case abTestLoginWithWPComOnly = "woocommerceios_login_wpcom_only"
23+
1924
/// A/B test for the Products Onboarding banner on the My Store dashboard.
2025
/// Experiment ref: pbxNRc-26F-p2
2126
case productsOnboardingBanner = "woocommerceios_products_onboarding_first_product_banner"
@@ -32,7 +37,7 @@ public enum ABTest: String, CaseIterable {
3237
switch self {
3338
case .aaTestLoggedIn202210, .productsOnboardingBanner:
3439
return .loggedIn
35-
case .aaTestLoggedOut:
40+
case .aaTestLoggedOut, .abTestLoginWithWPComOnly:
3641
return .loggedOut
3742
case .null:
3843
return .none

Experiments/Experiments/DefaultFeatureFlagService.swift

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,11 @@ public struct DefaultFeatureFlagService: FeatureFlagService {
3434
case .searchProductsBySKU:
3535
return true
3636
case .wpcomSignup:
37-
guard isFeatureFlagEnabled(.simplifiedLoginFlowI1) else {
38-
return buildConfig == .localDeveloper || buildConfig == .alpha
39-
}
40-
// To disable automatically sending signup link for unknown email IDs
4137
return false
4238
case .inAppPurchases:
4339
return buildConfig == .localDeveloper || buildConfig == .alpha
4440
case .storeCreationMVP:
4541
return buildConfig == .localDeveloper || buildConfig == .alpha
46-
case .simplifiedLoginFlowI1:
47-
return buildConfig == .localDeveloper || buildConfig == .alpha
4842
case .justInTimeMessagesOnDashboard:
4943
return buildConfig == .localDeveloper || buildConfig == .alpha
5044
case .productsOnboarding:

Experiments/Experiments/FeatureFlag.swift

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,6 @@ public enum FeatureFlag: Int {
8282
///
8383
case storeCreationMVP
8484

85-
/// Temporary feature flag for the simplified login flow.
86-
/// TODO: replace with A/B testing.
87-
///
88-
case simplifiedLoginFlowI1
89-
9085
/// Just In Time Messages on Dashboard
9186
///
9287
case justInTimeMessagesOnDashboard

WooCommerce/Classes/Authentication/AuthenticationManager.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class AuthenticationManager: Authentication {
5555
func initialize(loggedOutAppSettings: LoggedOutAppSettingsProtocol) {
5656
let isWPComMagicLinkPreferredToPassword = ServiceLocator.featureFlagService.isFeatureFlagEnabled(.loginMagicLinkEmphasis)
5757
let isWPComMagicLinkShownAsSecondaryActionOnPasswordScreen = ServiceLocator.featureFlagService.isFeatureFlagEnabled(.loginMagicLinkEmphasisM2)
58-
let isSimplifiedLoginI1Enabled = ServiceLocator.featureFlagService.isFeatureFlagEnabled(.simplifiedLoginFlowI1)
58+
let isSimplifiedLoginI1Enabled = ABTest.abTestLoginWithWPComOnly.variation != .control
5959
let isStoreCreationMVPEnabled = ServiceLocator.featureFlagService.isFeatureFlagEnabled(.storeCreationMVP)
6060
let configuration = WordPressAuthenticatorConfiguration(wpcomClientId: ApiCredentials.dotcomAppId,
6161
wpcomSecret: ApiCredentials.dotcomSecret,
@@ -81,9 +81,9 @@ class AuthenticationManager: Authentication {
8181
enableWPComLoginOnlyInPrologue: isSimplifiedLoginI1Enabled,
8282
enableSiteCreation: isStoreCreationMVPEnabled,
8383
enableSocialLogin: !isSimplifiedLoginI1Enabled,
84-
emphasizeEmailForWPComPassword: isSimplifiedLoginI1Enabled,
85-
wpcomPasswordInstructions: isSimplifiedLoginI1Enabled ?
86-
AuthenticationConstants.wpcomPasswordInstructions : nil)
84+
emphasizeEmailForWPComPassword: true,
85+
wpcomPasswordInstructions:
86+
AuthenticationConstants.wpcomPasswordInstructions)
8787

8888
let systemGray3LightModeColor = UIColor(red: 199/255.0, green: 199/255.0, blue: 204/255.0, alpha: 1)
8989
let systemLabelLightModeColor = UIColor(red: 0, green: 0, blue: 0, alpha: 1)

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

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@ final class NotWPAccountViewModel: ULErrorViewModel {
2121

2222
let isPrimaryButtonHidden: Bool
2323

24-
var secondaryButtonTitle: String {
25-
isSimplifiedLoginI1Enabled ? Localization.tryAnotherAddress : Localization.restartLogin
26-
}
24+
let secondaryButtonTitle = Localization.tryAnotherAddress
2725
let isSecondaryButtonHidden: Bool
2826

2927
private weak var viewController: UIViewController?
@@ -42,15 +40,13 @@ final class NotWPAccountViewModel: ULErrorViewModel {
4240
return button
4341
}()
4442

45-
private let isSimplifiedLoginI1Enabled: Bool
4643
private let analytics: Analytics
4744
private var storePickerCoordinator: StorePickerCoordinator?
4845

4946
init(error: Error,
5047
analytics: Analytics = ServiceLocator.analytics,
5148
featureFlagService: FeatureFlagService = ServiceLocator.featureFlagService) {
5249
self.analytics = analytics
53-
self.isSimplifiedLoginI1Enabled = featureFlagService.isFeatureFlagEnabled(.simplifiedLoginFlowI1)
5450
if let error = error as? SignInError,
5551
case let .invalidWPComEmail(source) = error,
5652
source == .wpComSiteAddress {
@@ -60,23 +56,14 @@ final class NotWPAccountViewModel: ULErrorViewModel {
6056
} else {
6157
isSecondaryButtonHidden = false
6258

63-
if isSimplifiedLoginI1Enabled {
64-
primaryButtonTitle = Localization.createAnAccount
65-
isPrimaryButtonHidden = !featureFlagService.isFeatureFlagEnabled(.storeCreationMVP)
66-
} else {
67-
primaryButtonTitle = Localization.loginWithSiteAddress
68-
isPrimaryButtonHidden = false
69-
}
59+
primaryButtonTitle = Localization.createAnAccount
60+
isPrimaryButtonHidden = !featureFlagService.isFeatureFlagEnabled(.storeCreationMVP)
7061
}
7162
}
7263

7364
// MARK: - Actions
7465
func didTapPrimaryButton(in viewController: UIViewController?) {
75-
if isSimplifiedLoginI1Enabled {
76-
createAnAccountButtonTapped(in: viewController)
77-
} else {
78-
loginWithSiteAddressButtonTapped()
79-
}
66+
createAnAccountButtonTapped(in: viewController)
8067
}
8168

8269
func didTapSecondaryButton(in viewController: UIViewController?) {
@@ -110,11 +97,6 @@ private extension NotWPAccountViewModel {
11097
viewController?.present(fancyAlert, animated: true)
11198
}
11299

113-
func loginWithSiteAddressButtonTapped() {
114-
let popCommand = NavigateToEnterSite()
115-
popCommand.execute(from: viewController)
116-
}
117-
118100
func createAnAccountButtonTapped(in viewController: UIViewController?) {
119101
analytics.track(.createAccountOnInvalidEmailScreenTapped)
120102
guard let viewController,
@@ -141,10 +123,6 @@ private extension NotWPAccountViewModel {
141123
comment: "Button linking to webview that explains what Jetpack is"
142124
+ "Presented when logging in with a site address that does not have a valid Jetpack installation")
143125

144-
static let loginWithSiteAddress = NSLocalizedString("Log in with your store address",
145-
comment: "Action button linking to instructions for enter another store."
146-
+ "Presented when logging in with an email address that is not a WordPress.com account")
147-
148126
static let createAnAccount = NSLocalizedString("Create An Account",
149127
comment: "Action button linking to create WooCommerce store flow."
150128
+ "Presented when logging in with an email address that is not a WordPress.com account")

WooCommerce/Classes/Authentication/Prologue/LoginPrologueViewController.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ final class LoginPrologueViewController: UIViewController {
1212
private let isFeatureCarouselShown: Bool
1313
private let analytics: Analytics
1414
private let featureFlagService: FeatureFlagService
15+
private let isSimplifiedLogin: Bool
1516

1617
/// Background View, to be placed surrounding the bottom area.
1718
///
@@ -44,6 +45,7 @@ final class LoginPrologueViewController: UIViewController {
4445
self.isFeatureCarouselShown = isFeatureCarouselShown
4546
self.analytics = analytics
4647
self.featureFlagService = featureFlagService
48+
self.isSimplifiedLogin = ABTest.abTestLoginWithWPComOnly.variation != .control
4749
super.init(nibName: nil, bundle: nil)
4850
}
4951

@@ -97,7 +99,7 @@ private extension LoginPrologueViewController {
9799
let pageTypes: [LoginProloguePageType] = {
98100
if isFeatureCarouselShown {
99101
return [.stats, .orderManagement, .products, .reviews]
100-
} else if featureFlagService.isFeatureFlagEnabled(.simplifiedLoginFlowI1) {
102+
} else if isSimplifiedLogin {
101103
return [.simplifiedLoginI1Intro]
102104
} else {
103105
return [.getStarted]
@@ -125,7 +127,7 @@ private extension LoginPrologueViewController {
125127
guard isNewToWooCommerceButtonShown else {
126128
return newToWooCommerceButton.isHidden = true
127129
}
128-
let title = featureFlagService.isFeatureFlagEnabled(.simplifiedLoginFlowI1) ? Localization.learnMoreAboutWoo : Localization.newToWooCommerce
130+
let title = isSimplifiedLogin ? Localization.learnMoreAboutWoo : Localization.newToWooCommerce
129131
newToWooCommerceButton.setTitle(title, for: .normal)
130132
newToWooCommerceButton.applyLinkButtonStyle()
131133
newToWooCommerceButton.titleLabel?.numberOfLines = 0

WooCommerce/WooCommerceTests/Authentication/NotWPAccountViewModelTests.swift

Lines changed: 13 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -67,24 +67,9 @@ final class NotWPAccountViewModelTests: XCTestCase {
6767
XCTAssertEqual(auxiliaryButtonTitle, AuthenticationConstants.whatIsWPComLinkTitle)
6868
}
6969

70-
func test_viewmodel_provides_expected_title_for_primary_button_when_simplified_login_feature_flag_is_off() {
70+
func test_viewmodel_provides_expected_title_for_primary_button() {
7171
// Given
72-
let featureFlagService = MockFeatureFlagService(isSimplifiedLoginFlowI1Enabled: false)
73-
let viewModel = NotWPAccountViewModel(error: SignInError.invalidWPComEmail(source: .wpCom),
74-
featureFlagService: featureFlagService)
75-
76-
// When
77-
let primaryButtonTitle = viewModel.primaryButtonTitle
78-
79-
// Then
80-
XCTAssertEqual(primaryButtonTitle, Expectations.loginWithSiteAddressTitle)
81-
}
82-
83-
func test_viewmodel_provides_expected_title_for_primary_button_when_simplified_login_feature_flag_is_on() {
84-
// Given
85-
let featureFlagService = MockFeatureFlagService(isSimplifiedLoginFlowI1Enabled: true)
86-
let viewModel = NotWPAccountViewModel(error: SignInError.invalidWPComEmail(source: .wpCom),
87-
featureFlagService: featureFlagService)
72+
let viewModel = NotWPAccountViewModel(error: SignInError.invalidWPComEmail(source: .wpCom))
8873
// When
8974
let primaryButtonTitle = viewModel.primaryButtonTitle
9075

@@ -105,23 +90,9 @@ final class NotWPAccountViewModelTests: XCTestCase {
10590
XCTAssertEqual(primaryButtonTitle, Expectations.restartLoginTitle)
10691
}
10792

108-
func test_primary_button_title_is_login_with_site_address_for_invalidWPComEmail_from_wpCom_error_when_simplified_login_feature_flag_is_off() {
109-
// Given
110-
let featureFlagService = MockFeatureFlagService(isSimplifiedLoginFlowI1Enabled: false)
111-
let viewModel = NotWPAccountViewModel(error: SignInError.invalidWPComEmail(source: .wpCom),
112-
featureFlagService: featureFlagService)
113-
// When
114-
let primaryButtonTitle = viewModel.primaryButtonTitle
115-
116-
// Then
117-
XCTAssertEqual(primaryButtonTitle, Expectations.loginWithSiteAddressTitle)
118-
}
119-
120-
func test_primary_button_title_is_create_an_account_for_invalidWPComEmail_from_wpCom_error_when_simplified_login_feature_flag_is_on() {
93+
func test_primary_button_title_is_create_an_account_for_invalidWPComEmail_from_wpCom_error() {
12194
// Given
122-
let featureFlagService = MockFeatureFlagService(isSimplifiedLoginFlowI1Enabled: true)
123-
let viewModel = NotWPAccountViewModel(error: SignInError.invalidWPComEmail(source: .wpCom),
124-
featureFlagService: featureFlagService)
95+
let viewModel = NotWPAccountViewModel(error: SignInError.invalidWPComEmail(source: .wpCom))
12596
// When
12697
let primaryButtonTitle = viewModel.primaryButtonTitle
12798

@@ -139,29 +110,18 @@ final class NotWPAccountViewModelTests: XCTestCase {
139110
XCTAssertFalse(viewModel.isPrimaryButtonHidden)
140111
}
141112

142-
func test_primary_button_is_not_hidden_for_invalidWPComEmail_from_wpCom_error_when_simplified_login_feature_flag_is_off() {
113+
func test_primary_button_is_not_hidden_for_invalidWPComEmail_from_wpCom_error_when_store_creation_is_on() {
143114
// Given
144-
let featureFlagService = MockFeatureFlagService(isSimplifiedLoginFlowI1Enabled: false)
115+
let featureFlagService = MockFeatureFlagService(isStoreCreationMVPEnabled: true)
145116
let viewModel = NotWPAccountViewModel(error: SignInError.invalidWPComEmail(source: .wpCom),
146117
featureFlagService: featureFlagService)
147118
// Then
148119
XCTAssertFalse(viewModel.isPrimaryButtonHidden)
149120
}
150121

151-
func test_primary_button_is_not_hidden_for_invalidWPComEmail_from_wpCom_error_when_simplified_login_is_on_and_store_creation_is_on() {
122+
func test_primary_button_is_hidden_for_invalidWPComEmail_from_wpCom_error_when_store_creation_is_off() {
152123
// Given
153-
let featureFlagService = MockFeatureFlagService(isSimplifiedLoginFlowI1Enabled: true,
154-
isStoreCreationMVPEnabled: true)
155-
let viewModel = NotWPAccountViewModel(error: SignInError.invalidWPComEmail(source: .wpCom),
156-
featureFlagService: featureFlagService)
157-
// Then
158-
XCTAssertFalse(viewModel.isPrimaryButtonHidden)
159-
}
160-
161-
func test_primary_button_is_hidden_for_invalidWPComEmail_from_wpCom_error_when_simplified_login_is_on_and_store_creation_is_off() {
162-
// Given
163-
let featureFlagService = MockFeatureFlagService(isSimplifiedLoginFlowI1Enabled: true,
164-
isStoreCreationMVPEnabled: false)
124+
let featureFlagService = MockFeatureFlagService(isStoreCreationMVPEnabled: false)
165125
let viewModel = NotWPAccountViewModel(error: SignInError.invalidWPComEmail(source: .wpCom),
166126
featureFlagService: featureFlagService)
167127
// Then
@@ -188,24 +148,9 @@ final class NotWPAccountViewModelTests: XCTestCase {
188148

189149
// MARK: - `secondaryButtonTitle`
190150

191-
func test_viewmodel_provides_expected_title_for_secondary_button_when_simplified_login_feature_flag_is_off() {
192-
// Given
193-
let featureFlagService = MockFeatureFlagService(isSimplifiedLoginFlowI1Enabled: false)
194-
let viewModel = NotWPAccountViewModel(error: SignInError.invalidWPComEmail(source: .wpCom),
195-
featureFlagService: featureFlagService)
196-
197-
// When
198-
let secondaryButtonTitle = viewModel.secondaryButtonTitle
199-
200-
// Then
201-
XCTAssertEqual(secondaryButtonTitle, Expectations.restartLoginTitle)
202-
}
203-
204-
func test_viewmodel_provides_expected_title_for_secondary_button_when_simplified_login_feature_flag_is_on() {
151+
func test_viewmodel_provides_expected_title_for_secondary_button() {
205152
// Given
206-
let featureFlagService = MockFeatureFlagService(isSimplifiedLoginFlowI1Enabled: true)
207-
let viewModel = NotWPAccountViewModel(error: SignInError.invalidWPComEmail(source: .wpCom),
208-
featureFlagService: featureFlagService)
153+
let viewModel = NotWPAccountViewModel(error: SignInError.invalidWPComEmail(source: .wpCom))
209154
// When
210155
let secondaryButtonTitle = viewModel.secondaryButtonTitle
211156

@@ -232,10 +177,8 @@ final class NotWPAccountViewModelTests: XCTestCase {
232177

233178
func test_tapping_auxiliary_button_tracks_what__is_wordpress_com_event() {
234179
// Given
235-
let featureFlagService = MockFeatureFlagService(isSimplifiedLoginFlowI1Enabled: true)
236180
let viewModel = NotWPAccountViewModel(error: SignInError.invalidWPComEmail(source: .wpCom),
237-
analytics: analytics,
238-
featureFlagService: featureFlagService)
181+
analytics: analytics)
239182

240183
// When
241184
viewModel.didTapAuxiliaryButton(in: nil)
@@ -244,26 +187,10 @@ final class NotWPAccountViewModelTests: XCTestCase {
244187
XCTAssertNotNil(analyticsProvider.receivedEvents.first(where: { $0 == "what_is_wordpress_com_on_invalid_email_screen" }))
245188
}
246189

247-
func test_tapping_primary_button_does_not_track_create_account_event_when_simplified_login_feature_flag_is_off() {
190+
func test_tapping_primary_button_tracks_create_account_event() {
248191
// Given
249-
let featureFlagService = MockFeatureFlagService(isSimplifiedLoginFlowI1Enabled: false)
250192
let viewModel = NotWPAccountViewModel(error: SignInError.invalidWPComEmail(source: .wpCom),
251-
analytics: analytics,
252-
featureFlagService: featureFlagService)
253-
254-
// When
255-
viewModel.didTapPrimaryButton(in: nil)
256-
257-
// Then
258-
XCTAssertNil(analyticsProvider.receivedEvents.first(where: { $0 == "create_account_on_invalid_email_screen" }))
259-
}
260-
261-
func test_tapping_primary_button_tracks_create_account_event_when_simplified_login_feature_flag_is_on() {
262-
// Given
263-
let featureFlagService = MockFeatureFlagService(isSimplifiedLoginFlowI1Enabled: true)
264-
let viewModel = NotWPAccountViewModel(error: SignInError.invalidWPComEmail(source: .wpCom),
265-
analytics: analytics,
266-
featureFlagService: featureFlagService)
193+
analytics: analytics)
267194

268195
// When
269196
viewModel.didTapPrimaryButton(in: nil)

0 commit comments

Comments
 (0)