Skip to content

Commit e2e4a4b

Browse files
authored
Merge pull request #8003 from woocommerce/issue/8002-onboarding-banner-experiment
Products Onboarding: Add the banner experiment to the app
2 parents 5f8125e + 5440aad commit e2e4a4b

File tree

5 files changed

+32
-30
lines changed

5 files changed

+32
-30
lines changed

Experiments/Experiments/ABTest.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ 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 for the Products Onboarding banner on the My Store dashboard.
20+
/// Experiment ref: pbxNRc-26F-p2
21+
case productsOnboardingBanner = "woocommerceios_products_onboarding_first_product_banner"
22+
1923
/// Returns a variation for the given experiment
2024
public var variation: Variation {
2125
ExPlat.shared?.experiment(rawValue) ?? .control
@@ -26,7 +30,7 @@ public enum ABTest: String, CaseIterable {
2630
/// When adding a new experiment, add it to the appropriate case depending on its context (logged-in or logged-out experience).
2731
public var context: ExperimentContext {
2832
switch self {
29-
case .aaTestLoggedIn202210:
33+
case .aaTestLoggedIn202210, .productsOnboardingBanner:
3034
return .loggedIn
3135
case .aaTestLoggedOut:
3236
return .loggedOut

WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewModel.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import Yosemite
22
import enum Networking.DotcomError
33
import enum Storage.StatsVersion
44
import protocol Experiments.FeatureFlagService
5+
import enum Experiments.ABTest
56

67
/// Syncs data for dashboard stats UI and determines the state of the dashboard UI based on stats version.
78
final class DashboardViewModel {
@@ -124,7 +125,7 @@ final class DashboardViewModel {
124125
if isEligible {
125126
ServiceLocator.analytics.track(event: .ProductsOnboarding.storeIsEligible())
126127

127-
if self?.featureFlagService.isFeatureFlagEnabled(.productsOnboarding) == true {
128+
if ABTest.productsOnboardingBanner.variation == .treatment(nil) {
128129
let viewModel = ProductsOnboardingAnnouncementCardViewModel(onCTATapped: { [weak self] in
129130
self?.announcementViewModel = nil // Dismiss announcement
130131
MainTabBarController.presentAddProductFlow()

WooCommerce/WooCommerce.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1388,6 +1388,7 @@
13881388
CC3B35DB28E5A6830036B097 /* ReviewReply.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC3B35DA28E5A6830036B097 /* ReviewReply.swift */; };
13891389
CC3B35DD28E5A6EA0036B097 /* ReviewReplyViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC3B35DC28E5A6EA0036B097 /* ReviewReplyViewModel.swift */; };
13901390
CC3B35DF28E5BE6F0036B097 /* ReviewReplyViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC3B35DE28E5BE6F0036B097 /* ReviewReplyViewModelTests.swift */; };
1391+
CC3DB1DC291188CA00425961 /* MockABTesting.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC3DB1DB291188CA00425961 /* MockABTesting.swift */; };
13911392
CC440E1E2770C6AF0074C264 /* ProductInOrderViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC440E1D2770C6AF0074C264 /* ProductInOrderViewModel.swift */; };
13921393
CC4A4E962655273D00B75DCD /* ShippingLabelPaymentMethods.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC4A4E952655273D00B75DCD /* ShippingLabelPaymentMethods.swift */; };
13931394
CC4A4ED82655478D00B75DCD /* ShippingLabelPaymentMethodsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC4A4ED72655478D00B75DCD /* ShippingLabelPaymentMethodsViewModel.swift */; };
@@ -3338,6 +3339,7 @@
33383339
CC3B35DA28E5A6830036B097 /* ReviewReply.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReviewReply.swift; sourceTree = "<group>"; };
33393340
CC3B35DC28E5A6EA0036B097 /* ReviewReplyViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReviewReplyViewModel.swift; sourceTree = "<group>"; };
33403341
CC3B35DE28E5BE6F0036B097 /* ReviewReplyViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReviewReplyViewModelTests.swift; sourceTree = "<group>"; };
3342+
CC3DB1DB291188CA00425961 /* MockABTesting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockABTesting.swift; sourceTree = "<group>"; };
33413343
CC440E1D2770C6AF0074C264 /* ProductInOrderViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductInOrderViewModel.swift; sourceTree = "<group>"; };
33423344
CC4A4E952655273D00B75DCD /* ShippingLabelPaymentMethods.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShippingLabelPaymentMethods.swift; sourceTree = "<group>"; };
33433345
CC4A4ED72655478D00B75DCD /* ShippingLabelPaymentMethodsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShippingLabelPaymentMethodsViewModel.swift; sourceTree = "<group>"; };
@@ -6331,6 +6333,7 @@
63316333
B958A7D728B5316A00823EEF /* MockURLOpener.swift */,
63326334
EE8DCA7F28BF964700F23B23 /* MockAuthentication.swift */,
63336335
AEB4DB98290AE8F300AE4340 /* MockCookieJar.swift */,
6336+
CC3DB1DB291188CA00425961 /* MockABTesting.swift */,
63346337
);
63356338
path = Mocks;
63366339
sourceTree = "<group>";
@@ -10799,6 +10802,7 @@
1079910802
31F21B02263C8E150035B50A /* CardReaderSettingsSearchingViewModelTests.swift in Sources */,
1080010803
45EF798624509B4C00B22BA2 /* ArrayIndexPathTests.swift in Sources */,
1080110804
D8610BDD256F5ABF00A5DF27 /* JetpackErrorViewModelTests.swift in Sources */,
10805+
CC3DB1DC291188CA00425961 /* MockABTesting.swift in Sources */,
1080210806
746791632108D7C0007CF1DC /* WooAnalyticsTests.swift in Sources */,
1080310807
2667BFDD252F61C5008099D4 /* RefundShippingDetailsViewModelTests.swift in Sources */,
1080410808
DE7B479727A3C4980018742E /* CouponDetailsViewModelTests.swift in Sources */,
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import Foundation
2+
import enum AutomatticTracks.Variation
3+
import enum Experiments.ABTest
4+
5+
struct MockABTesting {
6+
/// Sets the provided A/B Test variation in `UserDefaults`, to mock a given experiment assignment
7+
///
8+
static func setVariation(_ variation: AutomatticTracks.Variation, for experiment: ABTest) {
9+
let newVariation: String?
10+
switch variation {
11+
case .control:
12+
newVariation = "control"
13+
case .treatment(let type):
14+
newVariation = type ?? "treatment"
15+
}
16+
17+
let assignment = [experiment.rawValue: newVariation]
18+
UserDefaults.standard.setValue(assignment, forKey: "ab-testing-assignments")
19+
}
20+
}

WooCommerce/WooCommerceTests/ViewRelated/Dashboard/DashboardViewModelTests.swift

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ final class DashboardViewModelTests: XCTestCase {
8383

8484
func test_products_onboarding_announcements_take_precedence() {
8585
// Given
86+
MockABTesting.setVariation(.treatment(nil), for: .productsOnboardingBanner)
8687
let stores = MockStoresManager(sessionManager: .makeForTesting())
8788
stores.whenReceivingAction(ofType: ProductAction.self) { action in
8889
switch action {
@@ -164,32 +165,4 @@ final class DashboardViewModelTests: XCTestCase {
164165
// Then
165166
XCTAssertNil(viewModel.announcementViewModel)
166167
}
167-
168-
func test_no_announcement_synced_when_feature_flags_disabled() {
169-
// Given
170-
let stores = MockStoresManager(sessionManager: .makeForTesting())
171-
stores.whenReceivingAction(ofType: ProductAction.self) { action in
172-
switch action {
173-
case let .checkProductsOnboardingEligibility(_, completion):
174-
completion(.success(true))
175-
default:
176-
XCTFail("Received unsupported action: \(action)")
177-
}
178-
}
179-
stores.whenReceivingAction(ofType: JustInTimeMessageAction.self) { action in
180-
switch action {
181-
case let .loadMessage(_, _, _, completion):
182-
completion(.success(Yosemite.JustInTimeMessage.fake()))
183-
default:
184-
XCTFail("Received unsupported action: \(action)")
185-
}
186-
}
187-
let viewModel = DashboardViewModel(stores: stores, featureFlags: MockFeatureFlagService())
188-
189-
// When
190-
viewModel.syncAnnouncements(for: sampleSiteID)
191-
192-
// Then
193-
XCTAssertNil(viewModel.announcementViewModel)
194-
}
195168
}

0 commit comments

Comments
 (0)