Skip to content

Commit f3719a1

Browse files
wip: impression event testcases added for holdout
1 parent 059837f commit f3719a1

File tree

2 files changed

+114
-5
lines changed

2 files changed

+114
-5
lines changed

Sources/Optimizely/OptimizelyClient.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -801,7 +801,11 @@ extension OptimizelyClient {
801801

802802
func shouldSendDecisionEvent(source: String, decision: FeatureDecision?) -> Bool {
803803
guard let config = self.config else { return false }
804-
return (source == Constants.DecisionSource.featureTest.rawValue && decision?.variation != nil) || config.sendFlagDecisions
804+
let allowedSources: [String] = [
805+
Constants.DecisionSource.featureTest.rawValue,
806+
Constants.DecisionSource.holdout.rawValue
807+
]
808+
return (allowedSources.contains(source) && decision?.variation != nil) || config.sendFlagDecisions
805809
}
806810

807811
func sendImpressionEvent(experiment: ExperimentCore?,

Tests/OptimizelyTests-Common/BatchEventBuilderTests_Events.swift

Lines changed: 109 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,13 @@ extension BatchEventBuilderTests_Events {
480480
fakeOptimizelyManager.config!.project!.sendFlagDecisions = nil
481481
}
482482

483-
func testImpressionEventWithUserInHoldout() {
483+
484+
}
485+
486+
// MARK:- Holdouts
487+
488+
extension BatchEventBuilderTests_Events {
489+
func testImpressionEvent_UserInHoldout() {
484490
let eventDispatcher2 = MockEventDispatcher()
485491
let optimizely = OptimizelyClient(sdkKey: "12345", eventDispatcher: eventDispatcher2)
486492

@@ -490,9 +496,41 @@ extension BatchEventBuilderTests_Events {
490496
optimizely.config?.project.holdouts = [holdout]
491497

492498
let exp = expectation(description: "Wait for event to dispatch")
493-
optimizely.config!.project!.sendFlagDecisions = true
499+
let user = optimizely.createUserContext(userId: userId)
500+
_ = user.decide(key: featureKey)
501+
502+
let result = XCTWaiter.wait(for: [exp], timeout: 0.1)
503+
if result == XCTWaiter.Result.timedOut {
504+
let event = getFirstEventJSON(dispatcher: eventDispatcher2)!
505+
let visitor = (event["visitors"] as! Array<Dictionary<String, Any>>)[0]
506+
let snapshot = (visitor["snapshots"] as! Array<Dictionary<String, Any>>)[0]
507+
let decision = (snapshot["decisions"] as! Array<Dictionary<String, Any>>)[0]
508+
509+
let metaData = decision["metadata"] as! Dictionary<String, Any>
510+
XCTAssertEqual(metaData["rule_type"] as! String, Constants.DecisionSource.holdout.rawValue)
511+
XCTAssertEqual(metaData["rule_key"] as! String, "holdout_key")
512+
XCTAssertEqual(metaData["flag_key"] as! String, "feature_1")
513+
XCTAssertEqual(metaData["variation_key"] as! String, "holdout_a")
514+
XCTAssertFalse(metaData["enabled"] as! Bool)
515+
} else {
516+
XCTFail("No event found")
517+
}
518+
}
519+
520+
func testImpressionEvent_UserInHoldout_IncludedFlags() {
521+
let eventDispatcher2 = MockEventDispatcher()
522+
let optimizely = OptimizelyClient(sdkKey: "12345", eventDispatcher: eventDispatcher2)
523+
524+
try! optimizely.start(datafile: datafile)
525+
526+
var holdout: Holdout = try! OTUtils.model(from: sampleHoldout)
527+
holdout.includedFlags = ["4482920077"]
528+
optimizely.config?.project.holdouts = [holdout]
529+
530+
let exp = expectation(description: "Wait for event to dispatch")
494531

495-
_ = optimizely.isFeatureEnabled(featureKey: featureKey, userId: userId)
532+
let user = optimizely.createUserContext(userId: userId)
533+
_ = user.decide(key: featureKey)
496534

497535
let result = XCTWaiter.wait(for: [exp], timeout: 0.1)
498536
if result == XCTWaiter.Result.timedOut {
@@ -510,7 +548,74 @@ extension BatchEventBuilderTests_Events {
510548
} else {
511549
XCTFail("No event found")
512550
}
513-
optimizely.config!.project!.sendFlagDecisions = nil
551+
}
552+
553+
func testImpressionEvent_UserNotInHoldout_ExcludedFlags() {
554+
let eventDispatcher2 = MockEventDispatcher()
555+
let optimizely = OptimizelyClient(sdkKey: "12345", eventDispatcher: eventDispatcher2)
556+
557+
try! optimizely.start(datafile: datafile)
558+
559+
var holdout: Holdout = try! OTUtils.model(from: sampleHoldout)
560+
holdout.excludedFlags = ["4482920077"]
561+
optimizely.config?.project.holdouts = [holdout]
562+
563+
let exp = expectation(description: "Wait for event to dispatch")
564+
565+
let user = optimizely.createUserContext(userId: userId)
566+
_ = user.decide(key: featureKey)
567+
568+
let result = XCTWaiter.wait(for: [exp], timeout: 0.1)
569+
if result == XCTWaiter.Result.timedOut {
570+
let event = getFirstEventJSON(dispatcher: eventDispatcher2)!
571+
let visitor = (event["visitors"] as! Array<Dictionary<String, Any>>)[0]
572+
let snapshot = (visitor["snapshots"] as! Array<Dictionary<String, Any>>)[0]
573+
let decision = (snapshot["decisions"] as! Array<Dictionary<String, Any>>)[0]
574+
575+
let metaData = decision["metadata"] as! Dictionary<String, Any>
576+
XCTAssertEqual(metaData["rule_type"] as! String, Constants.DecisionSource.featureTest.rawValue)
577+
XCTAssertEqual(metaData["rule_key"] as! String, "exp_with_audience")
578+
XCTAssertEqual(metaData["flag_key"] as! String, "feature_1")
579+
XCTAssertEqual(metaData["variation_key"] as! String, "a")
580+
XCTAssertTrue(metaData["enabled"] as! Bool)
581+
} else {
582+
XCTFail("No event found")
583+
}
584+
}
585+
586+
func testImpressionEvent_UserNotInHoldout_MissesTrafficAllocation() {
587+
let eventDispatcher2 = MockEventDispatcher()
588+
let optimizely = OptimizelyClient(sdkKey: "12345", eventDispatcher: eventDispatcher2)
589+
590+
try! optimizely.start(datafile: datafile)
591+
592+
var holdout: Holdout = try! OTUtils.model(from: sampleHoldout)
593+
/// Set traffic allocation to gero
594+
holdout.trafficAllocation[0].endOfRange = 0
595+
holdout.includedFlags = ["4482920077"]
596+
optimizely.config?.project.holdouts = [holdout]
597+
598+
let exp = expectation(description: "Wait for event to dispatch")
599+
600+
let user = optimizely.createUserContext(userId: userId)
601+
_ = user.decide(key: featureKey)
602+
603+
let result = XCTWaiter.wait(for: [exp], timeout: 0.1)
604+
if result == XCTWaiter.Result.timedOut {
605+
let event = getFirstEventJSON(dispatcher: eventDispatcher2)!
606+
let visitor = (event["visitors"] as! Array<Dictionary<String, Any>>)[0]
607+
let snapshot = (visitor["snapshots"] as! Array<Dictionary<String, Any>>)[0]
608+
let decision = (snapshot["decisions"] as! Array<Dictionary<String, Any>>)[0]
609+
610+
let metaData = decision["metadata"] as! Dictionary<String, Any>
611+
XCTAssertEqual(metaData["rule_type"] as! String, Constants.DecisionSource.featureTest.rawValue)
612+
XCTAssertEqual(metaData["rule_key"] as! String, "exp_with_audience")
613+
XCTAssertEqual(metaData["flag_key"] as! String, "feature_1")
614+
XCTAssertEqual(metaData["variation_key"] as! String, "a")
615+
XCTAssertTrue(metaData["enabled"] as! Bool)
616+
} else {
617+
XCTFail("No event found")
618+
}
514619
}
515620
}
516621

0 commit comments

Comments
 (0)