Skip to content

Commit ebbde3c

Browse files
CmabService testcases added for sync getDecision function
1 parent f342ae2 commit ebbde3c

File tree

1 file changed

+195
-0
lines changed

1 file changed

+195
-0
lines changed

Tests/OptimizelyTests-Common/CmabServiceTests.swift

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,3 +462,198 @@ class DefaultCmabServiceTests: XCTestCase {
462462
}
463463
}
464464

465+
extension DefaultCmabServiceTests {
466+
func testSyncFetchDecision() {
467+
cmabClient.fetchDecisionResult = .success("variation-123")
468+
469+
let result = cmabService.getDecision(
470+
config: config,
471+
userContext: userContext,
472+
ruleId: "exp-123",
473+
options: []
474+
)
475+
476+
switch result {
477+
case .success(let decision):
478+
XCTAssertEqual(decision.variationId, "variation-123")
479+
XCTAssertEqual(self.cmabClient.lastRuleId, "exp-123")
480+
XCTAssertEqual(self.cmabClient.lastUserId, "test-user")
481+
XCTAssertEqual(self.cmabClient.lastAttributes?.count, 2)
482+
XCTAssertEqual(self.cmabClient.lastAttributes?["age"] as? Int, 25)
483+
XCTAssertEqual(self.cmabClient.lastAttributes?["location"] as? String, "San Francisco")
484+
485+
// Verify it was cached
486+
let cacheKey = "9-test-user-exp-123"
487+
XCTAssertNotNil(self.cmabCache.lookup(key: cacheKey))
488+
489+
case .failure(let error):
490+
XCTFail("Expected success but got error: \(error)")
491+
}
492+
}
493+
494+
func testSyncCachedDecision() {
495+
// First, put something in the cache
496+
let attributesHash = cmabService.hashAttributes(["age": 25, "location": "San Francisco"])
497+
let cacheKey = "9-test-user-exp-123"
498+
let cacheValue = CmabCacheValue(
499+
attributesHash: attributesHash,
500+
variationId: "cached-variation",
501+
cmabUUID: "cached-uuid"
502+
)
503+
cmabCache.save(key: cacheKey, value: cacheValue)
504+
505+
let result = cmabService.getDecision(
506+
config: config,
507+
userContext: userContext,
508+
ruleId: "exp-123",
509+
options: []
510+
)
511+
512+
switch result {
513+
case .success(let decision):
514+
XCTAssertEqual(decision.variationId, "cached-variation")
515+
XCTAssertEqual(decision.cmabUUID, "cached-uuid")
516+
XCTAssertFalse(self.cmabClient.fetchDecisionCalled, "Should not call API when cache hit")
517+
518+
case .failure(let error):
519+
XCTFail("Expected success but got error: \(error)")
520+
}
521+
}
522+
523+
func testSyncFailedFetch() {
524+
let testError = CmabClientError.fetchFailed("Test error")
525+
cmabClient.fetchDecisionResult = .failure(testError)
526+
527+
let result = cmabService.getDecision(
528+
config: config,
529+
userContext: userContext,
530+
ruleId: "exp-123",
531+
options: []
532+
)
533+
534+
switch result {
535+
case .success:
536+
XCTFail("Expected failure but got success")
537+
538+
case .failure(let error):
539+
XCTAssertEqual((error as? CmabClientError)?.message, "Test error")
540+
541+
// Verify no caching of failed results
542+
let cacheKey = "9-test-user-exp-123"
543+
XCTAssertNil(self.cmabCache.lookup(key: cacheKey))
544+
}
545+
}
546+
547+
func testSyncIgnoreCmabCacheOption() {
548+
// First, put something in the cache
549+
let attributesHash = cmabService.hashAttributes(["age": 25, "location": "San Francisco"])
550+
let cacheKey = "9-test-user-exp-123"
551+
let cacheValue = CmabCacheValue(
552+
attributesHash: attributesHash,
553+
variationId: "cached-variation",
554+
cmabUUID: "cached-uuid"
555+
)
556+
cmabCache.save(key: cacheKey, value: cacheValue)
557+
558+
cmabClient.fetchDecisionResult = .success("new-variation")
559+
560+
let result = cmabService.getDecision(
561+
config: config,
562+
userContext: userContext,
563+
ruleId: "exp-123",
564+
options: [.ignoreCmabCache]
565+
)
566+
567+
switch result {
568+
case .success(let decision):
569+
XCTAssertEqual(decision.variationId, "new-variation")
570+
XCTAssertTrue(self.cmabClient.fetchDecisionCalled, "Should always call API when ignoreCmabCache option is set")
571+
572+
case .failure(let error):
573+
XCTFail("Expected success but got error: \(error)")
574+
}
575+
}
576+
577+
func testSyncResetCmabCacheOption() {
578+
// First, put something in the cache
579+
let attributesHash = cmabService.hashAttributes(["age": 25, "location": "San Francisco"])
580+
let cacheKey = "9-test-user-exp-123"
581+
let cacheValue = CmabCacheValue(
582+
attributesHash: attributesHash,
583+
variationId: "cached-variation",
584+
cmabUUID: "cached-uuid"
585+
)
586+
cmabCache.save(key: cacheKey, value: cacheValue)
587+
588+
// Also add another item to verify it's cleared
589+
let otherCacheKey = "other-key"
590+
cmabCache.save(key: otherCacheKey, value: cacheValue)
591+
592+
cmabClient.fetchDecisionResult = .success("new-variation")
593+
594+
let result = cmabService.getDecision(
595+
config: config,
596+
userContext: userContext,
597+
ruleId: "exp-123",
598+
options: [.resetCmabCache]
599+
)
600+
601+
switch result {
602+
case .success(let decision):
603+
XCTAssertEqual(decision.variationId, "new-variation")
604+
XCTAssertTrue(self.cmabClient.fetchDecisionCalled, "Should call API after resetting cache")
605+
606+
// Verify the entire cache was reset
607+
XCTAssertNil(self.cmabCache.lookup(key: otherCacheKey))
608+
609+
// But the new decision should be cached
610+
XCTAssertNotNil(self.cmabCache.lookup(key: cacheKey))
611+
612+
case .failure(let error):
613+
XCTFail("Expected success but got error: \(error)")
614+
}
615+
}
616+
617+
func testSyncInvalidateUserCmabCacheOption() {
618+
// First, put something in the cache
619+
let attributesHash = cmabService.hashAttributes(["age": 25, "location": "San Francisco"])
620+
let userCacheKey = "9-test-user-exp-123"
621+
let otherUserCacheKey = "other-user-key"
622+
623+
let cacheValue = CmabCacheValue(
624+
attributesHash: attributesHash,
625+
variationId: "cached-variation",
626+
cmabUUID: "cached-uuid"
627+
)
628+
629+
// Cache for both current user and another user
630+
cmabCache.save(key: userCacheKey, value: cacheValue)
631+
cmabCache.save(key: otherUserCacheKey, value: cacheValue)
632+
633+
cmabClient.fetchDecisionResult = .success("new-variation")
634+
635+
let result = cmabService.getDecision(
636+
config: config,
637+
userContext: userContext,
638+
ruleId: "exp-123",
639+
options: [.invalidateUserCmabCache]
640+
)
641+
642+
switch result {
643+
case .success(let decision):
644+
XCTAssertEqual(decision.variationId, "new-variation")
645+
XCTAssertTrue(self.cmabClient.fetchDecisionCalled, "Should call API after invalidating user cache")
646+
647+
// Verify only the specific user's cache was invalidated
648+
XCTAssertNotNil(self.cmabCache.lookup(key: otherUserCacheKey), "Other users' cache should remain intact")
649+
650+
// The new decision should be cached for the current user
651+
XCTAssertNotNil(self.cmabCache.lookup(key: userCacheKey))
652+
XCTAssertEqual(self.cmabCache.lookup(key: userCacheKey)?.variationId, "new-variation")
653+
654+
case .failure(let error):
655+
XCTFail("Expected success but got error: \(error)")
656+
}
657+
}
658+
659+
}

0 commit comments

Comments
 (0)