Skip to content

Commit e42611f

Browse files
authored
feat(ats): remove auto ODP identify events from legacy APIs (#473)
1 parent 5a6a782 commit e42611f

File tree

4 files changed

+53
-15
lines changed

4 files changed

+53
-15
lines changed

Sources/Optimizely+Decide/OptimizelyClient+Decide.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,20 @@ extension OptimizelyClient {
4545
attributes: (attributes ?? [:]) as [String: Any])
4646
}
4747

48+
49+
/// Create a user context to be used internally without sending an ODP identify event.
50+
///
51+
/// - Parameters:
52+
/// - userId: The user ID to be used for bucketing.
53+
/// - attributes: A map of attribute names to current user attribute values.
54+
/// - Returns: An OptimizelyUserContext associated with this OptimizelyClient
55+
func makeInternalUserContext(userId: String,
56+
attributes: OptimizelyAttributes? = nil) -> OptimizelyUserContext {
57+
return OptimizelyUserContext(optimizely: self, userId: userId,
58+
attributes: (attributes ?? [:]) as [String: Any],
59+
identify: false)
60+
}
61+
4862
func decide(user: OptimizelyUserContext,
4963
key: String,
5064
options: [OptimizelyDecideOption]? = nil) -> OptimizelyDecision {

Sources/Optimizely/OptimizelyClient.swift

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -317,8 +317,7 @@ open class OptimizelyClient: NSObject {
317317

318318
let variation = decisionService.getVariation(config: config,
319319
experiment: experiment,
320-
user: createUserContext(userId: userId,
321-
attributes: attributes),
320+
user: makeInternalUserContext(userId: userId, attributes: attributes),
322321
options: nil).result
323322

324323
let decisionType: Constants.DecisionType = config.isFeatureExperiment(id: experiment.id) ? .featureTest : .abTest
@@ -401,8 +400,7 @@ open class OptimizelyClient: NSObject {
401400

402401
let pair = decisionService.getVariationForFeature(config: config,
403402
featureFlag: featureFlag,
404-
user: createUserContext(userId: userId,
405-
attributes: attributes),
403+
user: makeInternalUserContext(userId: userId, attributes: attributes),
406404
options: nil).result
407405

408406
let source = pair?.source ?? Constants.DecisionSource.rollout.rawValue
@@ -553,8 +551,7 @@ open class OptimizelyClient: NSObject {
553551

554552
let decision = decisionService.getVariationForFeature(config: config,
555553
featureFlag: featureFlag,
556-
user: createUserContext(userId: userId,
557-
attributes: attributes),
554+
user: makeInternalUserContext(userId: userId, attributes: attributes),
558555
options: nil).result
559556
if let decision = decision {
560557
if let featureVariable = decision.variation.variables?.filter({$0.id == variable.id}).first {
@@ -645,8 +642,7 @@ open class OptimizelyClient: NSObject {
645642

646643
let decision = decisionService.getVariationForFeature(config: config,
647644
featureFlag: featureFlag,
648-
user: createUserContext(userId: userId,
649-
attributes: attributes),
645+
user: makeInternalUserContext(userId: userId, attributes: attributes),
650646
options: nil).result
651647
if let featureEnabled = decision?.variation.featureEnabled {
652648
enabled = featureEnabled

Tests/OptimizelyTests-Common/OptimizelyUserContextTests_ODP.swift

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,25 +33,38 @@ class OptimizelyUserContextTests_ODP: XCTestCase {
3333

3434
optimizely = OptimizelyClient(sdkKey: sdkKey)
3535
optimizely.odpManager = odpManager
36-
37-
user = optimizely.createUserContext(userId: kUserId)
3836
}
3937

4038
// MARK: - identify
4139

4240
func testIdentifyCalledAutomatically() {
41+
user = optimizely.createUserContext(userId: kUserId)
4342
sleep(1)
44-
XCTAssertEqual(true, odpManager.identifyCalled, "identifyUser is implicitly called on UserContext init")
43+
XCTAssert(odpManager.identifyCalled, "identifyUser is implicitly called on UserContext init")
4544
XCTAssertEqual(kUserId, odpManager.userId)
4645
}
4746

47+
func testIdentifyNotCalledForLegacyAPIs() {
48+
try? optimizely.start(datafile: datafile)
49+
_ = try? optimizely.activate(experimentKey: "experiment-segment", userId: kUserId)
50+
_ = try? optimizely.getVariation(experimentKey: "experiment-segment", userId: kUserId)
51+
_ = try? optimizely.getAllFeatureVariables(featureKey: "flag-segment", userId: kUserId)
52+
_ = optimizely.isFeatureEnabled(featureKey: "flag-segment", userId: kUserId)
53+
try? optimizely.track(eventKey: "event1", userId: kUserId)
54+
55+
sleep(1)
56+
XCTAssertFalse(odpManager.identifyCalled, "identifyUser is implicitly called on UserContext init")
57+
}
58+
4859
// MARK: - isQualifiedFor
4960

5061
func testIsQualifiedFor() {
62+
user = optimizely.createUserContext(userId: kUserId)
63+
5164
XCTAssertFalse(user.isQualifiedFor(segment: "a"))
5265

5366
user.qualifiedSegments = ["a", "b"]
54-
XCTAssertTrue(user.isQualifiedFor(segment: "a"))
67+
XCTAssert(user.isQualifiedFor(segment: "a"))
5568
XCTAssertFalse(user.isQualifiedFor(segment: "x"))
5669

5770
user.qualifiedSegments = []
@@ -62,6 +75,7 @@ class OptimizelyUserContextTests_ODP: XCTestCase {
6275

6376
func testFetchQualifiedSegments_successDefaultUser() {
6477
try? optimizely.start(datafile: datafile)
78+
user = optimizely.createUserContext(userId: kUserId)
6579

6680
let sem = DispatchSemaphore(value: 0)
6781
user.fetchQualifiedSegments { segments, error in
@@ -76,6 +90,7 @@ class OptimizelyUserContextTests_ODP: XCTestCase {
7690
// MARK: - Failure
7791

7892
func testFetchQualifiedSegments_sdkNotReady() {
93+
user = optimizely.createUserContext(userId: kUserId)
7994
user.optimizely = nil
8095
user.qualifiedSegments = ["dummy"]
8196

@@ -90,6 +105,7 @@ class OptimizelyUserContextTests_ODP: XCTestCase {
90105
}
91106

92107
func testFetchQualifiedSegments_fetchFailed() {
108+
user = optimizely.createUserContext(userId: kUserId)
93109
user.qualifiedSegments = ["dummy"]
94110

95111
// ODP apiKey is not available
@@ -108,7 +124,8 @@ class OptimizelyUserContextTests_ODP: XCTestCase {
108124

109125
func testFetchQualifiedSegments_segmentsToCheck_validAfterStart() {
110126
try? optimizely.start(datafile: datafile)
111-
127+
user = optimizely.createUserContext(userId: kUserId)
128+
112129
let sem = DispatchSemaphore(value: 0)
113130
user.fetchQualifiedSegments { _, _ in
114131
sem.signal()
@@ -121,7 +138,8 @@ class OptimizelyUserContextTests_ODP: XCTestCase {
121138
func testFetchQualifiedSegments_segmentsNotUsed() {
122139
let datafile = OTUtils.loadJSONDatafile("odp_integrated_no_segments")!
123140
try? optimizely.start(datafile: datafile)
124-
141+
user = optimizely.createUserContext(userId: kUserId)
142+
125143
let sem = DispatchSemaphore(value: 0)
126144
user.fetchQualifiedSegments { segments, error in
127145
XCTAssertNil(error)
@@ -139,6 +157,7 @@ extension OptimizelyUserContextTests_ODP {
139157

140158
func testFetchQualifiedSegments_parameters() {
141159
try? optimizely.start(datafile: datafile)
160+
user = optimizely.createUserContext(userId: kUserId)
142161

143162
let sem = DispatchSemaphore(value: 0)
144163
user.fetchQualifiedSegments(options: [.ignoreCache]) { segments, error in
@@ -158,6 +177,7 @@ extension OptimizelyUserContextTests_ODP {
158177
XCTAssertNil(odpManager.odpConfig.apiHost)
159178

160179
try? optimizely.start(datafile: "invalid")
180+
user = optimizely.createUserContext(userId: kUserId)
161181

162182
XCTAssertNil(odpManager.odpConfig.apiKey)
163183
XCTAssertNil(odpManager.odpConfig.apiHost)

Tests/TestData/odp/decide_audience_segments.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,14 @@
202202
}
203203
],
204204
"accountId": "10367498574",
205-
"events": [],
205+
"events": [
206+
{
207+
"experimentIds": [
208+
"10420810910"
209+
],
210+
"id": "10404198134",
211+
"key": "event1"
212+
}
213+
],
206214
"revision": "101"
207215
}

0 commit comments

Comments
 (0)