Skip to content

Commit 7905089

Browse files
authored
Merge pull request #5628 from woocommerce/issue/5621-explat-integration
Analytics: Integrate ExPlat into Experiments framework
2 parents 19b0d7e + b076017 commit 7905089

File tree

8 files changed

+228
-11
lines changed

8 files changed

+228
-11
lines changed

Experiments/Experiments.xcodeproj/project.pbxproj

Lines changed: 118 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
archiveVersion = 1;
44
classes = {
55
};
6-
objectVersion = 50;
6+
objectVersion = 51;
77
objects = {
88

99
/* Begin PBXBuildFile section */
@@ -13,6 +13,9 @@
1313
0270C0A327069B7800FC799F /* FeatureFlagService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0270C0A227069B7800FC799F /* FeatureFlagService.swift */; };
1414
0270C0A527069B8900FC799F /* DefaultFeatureFlagService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0270C0A427069B8900FC799F /* DefaultFeatureFlagService.swift */; };
1515
0270C0A727069BA500FC799F /* BuildConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0270C0A627069BA500FC799F /* BuildConfiguration.swift */; };
16+
BC10218D75FEA979BDA1E68C /* Pods_Experiments.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 33CEC0C5283FD4C9EF8C6A3C /* Pods_Experiments.framework */; };
17+
C8E16F0EE6954B58A1C402F0 /* Pods_ExperimentsTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AAC7C082DD376957B4676401 /* Pods_ExperimentsTests.framework */; };
18+
CC53FB48275E426900C4CA4F /* ABTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC53FB47275E426900C4CA4F /* ABTest.swift */; };
1619
/* End PBXBuildFile section */
1720

1821
/* Begin PBXContainerItemProxy section */
@@ -35,13 +38,23 @@
3538
0270C0A427069B8900FC799F /* DefaultFeatureFlagService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultFeatureFlagService.swift; sourceTree = "<group>"; };
3639
0270C0A627069BA500FC799F /* BuildConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuildConfiguration.swift; sourceTree = "<group>"; };
3740
02AB82EE27069D93008D7334 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
41+
2B7FCE683D4058A7A16F7946 /* Pods-Experiments.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Experiments.debug.xcconfig"; path = "Target Support Files/Pods-Experiments/Pods-Experiments.debug.xcconfig"; sourceTree = "<group>"; };
42+
3022E2766134CE2735C73FC6 /* Pods-ExperimentsTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ExperimentsTests.debug.xcconfig"; path = "Target Support Files/Pods-ExperimentsTests/Pods-ExperimentsTests.debug.xcconfig"; sourceTree = "<group>"; };
43+
33CEC0C5283FD4C9EF8C6A3C /* Pods_Experiments.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Experiments.framework; sourceTree = BUILT_PRODUCTS_DIR; };
44+
3F9DB5FBFF7A42EFBCB746F3 /* Pods-ExperimentsTests.release-alpha.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ExperimentsTests.release-alpha.xcconfig"; path = "Target Support Files/Pods-ExperimentsTests/Pods-ExperimentsTests.release-alpha.xcconfig"; sourceTree = "<group>"; };
45+
7C831644164B49828A485590 /* Pods-ExperimentsTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ExperimentsTests.release.xcconfig"; path = "Target Support Files/Pods-ExperimentsTests/Pods-ExperimentsTests.release.xcconfig"; sourceTree = "<group>"; };
46+
8CB554DFAAD3EF41D17099C4 /* Pods-Experiments.release-alpha.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Experiments.release-alpha.xcconfig"; path = "Target Support Files/Pods-Experiments/Pods-Experiments.release-alpha.xcconfig"; sourceTree = "<group>"; };
47+
AAC7C082DD376957B4676401 /* Pods_ExperimentsTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ExperimentsTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
48+
AF72D9DB7771E7A5105C88B0 /* Pods-Experiments.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Experiments.release.xcconfig"; path = "Target Support Files/Pods-Experiments/Pods-Experiments.release.xcconfig"; sourceTree = "<group>"; };
49+
CC53FB47275E426900C4CA4F /* ABTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ABTest.swift; sourceTree = "<group>"; };
3850
/* End PBXFileReference section */
3951

4052
/* Begin PBXFrameworksBuildPhase section */
4153
0270C07E27069A8900FC799F /* Frameworks */ = {
4254
isa = PBXFrameworksBuildPhase;
4355
buildActionMask = 2147483647;
4456
files = (
57+
BC10218D75FEA979BDA1E68C /* Pods_Experiments.framework in Frameworks */,
4558
);
4659
runOnlyForDeploymentPostprocessing = 0;
4760
};
@@ -50,6 +63,7 @@
5063
buildActionMask = 2147483647;
5164
files = (
5265
0270C08B27069A8900FC799F /* Experiments.framework in Frameworks */,
66+
C8E16F0EE6954B58A1C402F0 /* Pods_ExperimentsTests.framework in Frameworks */,
5367
);
5468
runOnlyForDeploymentPostprocessing = 0;
5569
};
@@ -62,6 +76,8 @@
6276
0270C08327069A8900FC799F /* Experiments */,
6377
0270C08E27069A8900FC799F /* ExperimentsTests */,
6478
0270C08227069A8900FC799F /* Products */,
79+
4E1989AAB68578443A38332F /* Pods */,
80+
6F0EE5A69BC4E0719C6AE8AC /* Frameworks */,
6581
);
6682
sourceTree = "<group>";
6783
};
@@ -83,6 +99,7 @@
8399
0270C0A227069B7800FC799F /* FeatureFlagService.swift */,
84100
0270C0A427069B8900FC799F /* DefaultFeatureFlagService.swift */,
85101
0270C0A627069BA500FC799F /* BuildConfiguration.swift */,
102+
CC53FB47275E426900C4CA4F /* ABTest.swift */,
86103
);
87104
path = Experiments;
88105
sourceTree = "<group>";
@@ -95,6 +112,29 @@
95112
path = ExperimentsTests;
96113
sourceTree = "<group>";
97114
};
115+
4E1989AAB68578443A38332F /* Pods */ = {
116+
isa = PBXGroup;
117+
children = (
118+
2B7FCE683D4058A7A16F7946 /* Pods-Experiments.debug.xcconfig */,
119+
AF72D9DB7771E7A5105C88B0 /* Pods-Experiments.release.xcconfig */,
120+
8CB554DFAAD3EF41D17099C4 /* Pods-Experiments.release-alpha.xcconfig */,
121+
3022E2766134CE2735C73FC6 /* Pods-ExperimentsTests.debug.xcconfig */,
122+
7C831644164B49828A485590 /* Pods-ExperimentsTests.release.xcconfig */,
123+
3F9DB5FBFF7A42EFBCB746F3 /* Pods-ExperimentsTests.release-alpha.xcconfig */,
124+
);
125+
name = Pods;
126+
path = ../Pods;
127+
sourceTree = "<group>";
128+
};
129+
6F0EE5A69BC4E0719C6AE8AC /* Frameworks */ = {
130+
isa = PBXGroup;
131+
children = (
132+
33CEC0C5283FD4C9EF8C6A3C /* Pods_Experiments.framework */,
133+
AAC7C082DD376957B4676401 /* Pods_ExperimentsTests.framework */,
134+
);
135+
name = Frameworks;
136+
sourceTree = "<group>";
137+
};
98138
/* End PBXGroup section */
99139

100140
/* Begin PBXHeadersBuildPhase section */
@@ -113,6 +153,7 @@
113153
isa = PBXNativeTarget;
114154
buildConfigurationList = 0270C09527069A8900FC799F /* Build configuration list for PBXNativeTarget "Experiments" */;
115155
buildPhases = (
156+
620F249CED3F18B3ACC4F79A /* [CP] Check Pods Manifest.lock */,
116157
0270C07C27069A8900FC799F /* Headers */,
117158
0270C07D27069A8900FC799F /* Sources */,
118159
0270C07E27069A8900FC799F /* Frameworks */,
@@ -131,9 +172,11 @@
131172
isa = PBXNativeTarget;
132173
buildConfigurationList = 0270C09827069A8900FC799F /* Build configuration list for PBXNativeTarget "ExperimentsTests" */;
133174
buildPhases = (
175+
97E6ECC11AE05E56176EF2BA /* [CP] Check Pods Manifest.lock */,
134176
0270C08627069A8900FC799F /* Sources */,
135177
0270C08727069A8900FC799F /* Frameworks */,
136178
0270C08827069A8900FC799F /* Resources */,
179+
3AB0CD346AF01D971274BF7B /* [CP] Embed Pods Frameworks */,
137180
);
138181
buildRules = (
139182
);
@@ -199,6 +242,70 @@
199242
};
200243
/* End PBXResourcesBuildPhase section */
201244

245+
/* Begin PBXShellScriptBuildPhase section */
246+
3AB0CD346AF01D971274BF7B /* [CP] Embed Pods Frameworks */ = {
247+
isa = PBXShellScriptBuildPhase;
248+
buildActionMask = 2147483647;
249+
files = (
250+
);
251+
inputFileListPaths = (
252+
"${PODS_ROOT}/Target Support Files/Pods-ExperimentsTests/Pods-ExperimentsTests-frameworks-${CONFIGURATION}-input-files.xcfilelist",
253+
);
254+
name = "[CP] Embed Pods Frameworks";
255+
outputFileListPaths = (
256+
"${PODS_ROOT}/Target Support Files/Pods-ExperimentsTests/Pods-ExperimentsTests-frameworks-${CONFIGURATION}-output-files.xcfilelist",
257+
);
258+
runOnlyForDeploymentPostprocessing = 0;
259+
shellPath = /bin/sh;
260+
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ExperimentsTests/Pods-ExperimentsTests-frameworks.sh\"\n";
261+
showEnvVarsInLog = 0;
262+
};
263+
620F249CED3F18B3ACC4F79A /* [CP] Check Pods Manifest.lock */ = {
264+
isa = PBXShellScriptBuildPhase;
265+
buildActionMask = 2147483647;
266+
files = (
267+
);
268+
inputFileListPaths = (
269+
);
270+
inputPaths = (
271+
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
272+
"${PODS_ROOT}/Manifest.lock",
273+
);
274+
name = "[CP] Check Pods Manifest.lock";
275+
outputFileListPaths = (
276+
);
277+
outputPaths = (
278+
"$(DERIVED_FILE_DIR)/Pods-Experiments-checkManifestLockResult.txt",
279+
);
280+
runOnlyForDeploymentPostprocessing = 0;
281+
shellPath = /bin/sh;
282+
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
283+
showEnvVarsInLog = 0;
284+
};
285+
97E6ECC11AE05E56176EF2BA /* [CP] Check Pods Manifest.lock */ = {
286+
isa = PBXShellScriptBuildPhase;
287+
buildActionMask = 2147483647;
288+
files = (
289+
);
290+
inputFileListPaths = (
291+
);
292+
inputPaths = (
293+
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
294+
"${PODS_ROOT}/Manifest.lock",
295+
);
296+
name = "[CP] Check Pods Manifest.lock";
297+
outputFileListPaths = (
298+
);
299+
outputPaths = (
300+
"$(DERIVED_FILE_DIR)/Pods-ExperimentsTests-checkManifestLockResult.txt",
301+
);
302+
runOnlyForDeploymentPostprocessing = 0;
303+
shellPath = /bin/sh;
304+
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
305+
showEnvVarsInLog = 0;
306+
};
307+
/* End PBXShellScriptBuildPhase section */
308+
202309
/* Begin PBXSourcesBuildPhase section */
203310
0270C07D27069A8900FC799F /* Sources */ = {
204311
isa = PBXSourcesBuildPhase;
@@ -208,6 +315,7 @@
208315
0270C0A527069B8900FC799F /* DefaultFeatureFlagService.swift in Sources */,
209316
0270C09C27069AE700FC799F /* FeatureFlag.swift in Sources */,
210317
0270C0A727069BA500FC799F /* BuildConfiguration.swift in Sources */,
318+
CC53FB48275E426900C4CA4F /* ABTest.swift in Sources */,
211319
);
212320
runOnlyForDeploymentPostprocessing = 0;
213321
};
@@ -353,6 +461,7 @@
353461
};
354462
0270C09627069A8900FC799F /* Debug */ = {
355463
isa = XCBuildConfiguration;
464+
baseConfigurationReference = 2B7FCE683D4058A7A16F7946 /* Pods-Experiments.debug.xcconfig */;
356465
buildSettings = {
357466
CLANG_ENABLE_MODULES = YES;
358467
CODE_SIGN_STYLE = Automatic;
@@ -378,6 +487,7 @@
378487
};
379488
0270C09727069A8900FC799F /* Release */ = {
380489
isa = XCBuildConfiguration;
490+
baseConfigurationReference = AF72D9DB7771E7A5105C88B0 /* Pods-Experiments.release.xcconfig */;
381491
buildSettings = {
382492
CLANG_ENABLE_MODULES = YES;
383493
CODE_SIGN_STYLE = Automatic;
@@ -402,8 +512,9 @@
402512
};
403513
0270C09927069A8900FC799F /* Debug */ = {
404514
isa = XCBuildConfiguration;
515+
baseConfigurationReference = 3022E2766134CE2735C73FC6 /* Pods-ExperimentsTests.debug.xcconfig */;
405516
buildSettings = {
406-
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
517+
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "${inherited}";
407518
CODE_SIGN_STYLE = Automatic;
408519
INFOPLIST_FILE = ExperimentsTests/Info.plist;
409520
LD_RUNPATH_SEARCH_PATHS = (
@@ -420,8 +531,9 @@
420531
};
421532
0270C09A27069A8900FC799F /* Release */ = {
422533
isa = XCBuildConfiguration;
534+
baseConfigurationReference = 7C831644164B49828A485590 /* Pods-ExperimentsTests.release.xcconfig */;
423535
buildSettings = {
424-
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
536+
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "${inherited}";
425537
CODE_SIGN_STYLE = Automatic;
426538
INFOPLIST_FILE = ExperimentsTests/Info.plist;
427539
LD_RUNPATH_SEARCH_PATHS = (
@@ -497,6 +609,7 @@
497609
};
498610
02AB82F12706A9EA008D7334 /* Release-Alpha */ = {
499611
isa = XCBuildConfiguration;
612+
baseConfigurationReference = 8CB554DFAAD3EF41D17099C4 /* Pods-Experiments.release-alpha.xcconfig */;
500613
buildSettings = {
501614
CLANG_ENABLE_MODULES = YES;
502615
CODE_SIGN_STYLE = Automatic;
@@ -521,8 +634,9 @@
521634
};
522635
02AB82F22706A9EA008D7334 /* Release-Alpha */ = {
523636
isa = XCBuildConfiguration;
637+
baseConfigurationReference = 3F9DB5FBFF7A42EFBCB746F3 /* Pods-ExperimentsTests.release-alpha.xcconfig */;
524638
buildSettings = {
525-
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
639+
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "${inherited}";
526640
CODE_SIGN_STYLE = Automatic;
527641
INFOPLIST_FILE = ExperimentsTests/Info.plist;
528642
LD_RUNPATH_SEARCH_PATHS = (
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import AutomatticTracks
2+
3+
/// ABTest adds A/B testing experiments and runs the tests based on their variations from the ExPlat service.
4+
///
5+
public enum ABTest: String, CaseIterable {
6+
/// Throwaway case, to prevent a compiler error:
7+
/// `An enum with no cases cannot declare a raw type`
8+
case null
9+
10+
/// Returns a variation for the given experiment
11+
var variation: Variation {
12+
return ExPlat.shared?.experiment(self.rawValue) ?? .control
13+
}
14+
}
15+
16+
public extension ABTest {
17+
/// Start the AB Testing platform if any experiment exists
18+
///
19+
static func start() {
20+
guard ABTest.allCases.count > 1 else {
21+
return
22+
}
23+
24+
let experimentNames = ABTest.allCases.filter { $0 != .null }.map { $0.rawValue }
25+
ExPlat.shared?.register(experiments: experimentNames)
26+
27+
ExPlat.shared?.refresh()
28+
}
29+
}

Podfile

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,31 @@ target 'SampleReceiptPrinter' do
196196
hardware_pods
197197
end
198198

199+
# Experiments Layer:
200+
# ==================
201+
#
202+
def experiments_pods
203+
pod 'Automattic-Tracks-iOS', '~> 0.9.1'
204+
pod 'CocoaLumberjack', '~> 3.5'
205+
pod 'CocoaLumberjack/Swift', '~> 3.5'
206+
end
207+
208+
# Experiments Target:
209+
# ===================
210+
#
211+
target 'Experiments' do
212+
project 'Experiments/Experiments.xcodeproj'
213+
experiments_pods
214+
end
215+
216+
# Unit Tests
217+
# ==========
218+
#
219+
target 'ExperimentsTests' do
220+
project 'Experiments/Experiments.xcodeproj'
221+
experiments_pods
222+
end
223+
199224
# Workarounds:
200225
# ============
201226
#

Podfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,6 @@ SPEC CHECKSUMS:
197197
ZendeskSupportProvidersSDK: 2bdf8544f7cd0fd4c002546f5704b813845beb2a
198198
ZendeskSupportSDK: 3a8e508ab1d9dd22dc038df6c694466414e037ba
199199

200-
PODFILE CHECKSUM: f0f2a1a361d8c0e253b703da6a333ecb1cce7fff
200+
PODFILE CHECKSUM: ace980f03f7b80fe9f6ed45f764c0c894be396f7
201201

202202
COCOAPODS: 1.11.2

WooCommerce/Classes/Analytics/TracksProvider.swift

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,18 +64,29 @@ public extension TracksProvider {
6464
private extension TracksProvider {
6565
func switchTracksUsersIfNeeded() {
6666
let currentAnalyticsUsername = UserDefaults.standard[.analyticsUsername] as? String ?? ""
67-
if ServiceLocator.stores.isAuthenticated, let account = ServiceLocator.stores.sessionManager.defaultAccount {
67+
if ServiceLocator.stores.isAuthenticated,
68+
let account = ServiceLocator.stores.sessionManager.defaultAccount,
69+
let credentials = ServiceLocator.stores.sessionManager.defaultCredentials {
6870
if currentAnalyticsUsername.isEmpty {
6971
// No previous username logged
7072
UserDefaults.standard[.analyticsUsername] = account.username
71-
tracksService.switchToAuthenticatedUser(withUsername: account.username, userID: String(account.userID), skipAliasEventCreation: false)
73+
tracksService.switchToAuthenticatedUser(withUsername: account.username,
74+
userID: String(account.userID),
75+
wpComToken: credentials.authToken,
76+
skipAliasEventCreation: false)
7277
} else if currentAnalyticsUsername == account.username {
7378
// Username did not change - just make sure Tracks client has it
74-
tracksService.switchToAuthenticatedUser(withUsername: account.username, userID: String(account.userID), skipAliasEventCreation: true)
79+
tracksService.switchToAuthenticatedUser(withUsername: account.username,
80+
userID: String(account.userID),
81+
wpComToken: credentials.authToken,
82+
skipAliasEventCreation: true)
7583
} else {
7684
// Username changed for some reason - switch back to anonymous first
7785
tracksService.switchToAnonymousUser(withAnonymousID: ServiceLocator.stores.sessionManager.anonymousUserID)
78-
tracksService.switchToAuthenticatedUser(withUsername: account.username, userID: String(account.userID), skipAliasEventCreation: false)
86+
tracksService.switchToAuthenticatedUser(withUsername: account.username,
87+
userID: String(account.userID),
88+
wpComToken: credentials.authToken,
89+
skipAliasEventCreation: false)
7990
}
8091
} else {
8192
UserDefaults.standard[.analyticsUsername] = nil

WooCommerce/Classes/AppDelegate.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import UIKit
22
import CoreData
33
import Storage
44
import class Networking.UserAgent
5+
import Experiments
56

67
import CocoaLumberjack
78
import KeychainAccess
@@ -74,6 +75,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
7475

7576
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
7677

78+
startABTesting()
79+
7780
// Setup the Interface!
7881
setupMainWindow()
7982
setupComponentsAppearance()
@@ -318,6 +321,15 @@ private extension AppDelegate {
318321
UIApplication.shared.currentKeyWindow?.layer.speed = 100
319322
}
320323
}
324+
325+
/// Starts the AB testing platform
326+
///
327+
func startABTesting() {
328+
guard ServiceLocator.stores.isAuthenticated else {
329+
return
330+
}
331+
ABTest.start()
332+
}
321333
}
322334

323335

0 commit comments

Comments
 (0)