From 3635f9e5a388c19cde0fd986adabab6ff7e0429e Mon Sep 17 00:00:00 2001 From: Jae Kim Date: Tue, 26 Jan 2021 16:09:31 -0800 Subject: [PATCH 1/6] fix tests for decisionEventDispatched flag --- .../DecisionListenerTests.swift | 68 +++++++++++++++++++ .../OptimizelyUserContextTests_Decide.swift | 31 ++++++++- 2 files changed, 97 insertions(+), 2 deletions(-) diff --git a/Tests/OptimizelyTests-Common/DecisionListenerTests.swift b/Tests/OptimizelyTests-Common/DecisionListenerTests.swift index 948d0316..292c2e47 100644 --- a/Tests/OptimizelyTests-Common/DecisionListenerTests.swift +++ b/Tests/OptimizelyTests-Common/DecisionListenerTests.swift @@ -958,11 +958,79 @@ extension DecisionListenerTests { XCTAssertNil(decisionInfo[Constants.DecisionInfoKeys.variationKey]) XCTAssertNil(decisionInfo[Constants.DecisionInfoKeys.ruleKey]) XCTAssertNotNil(decisionInfo[Constants.DecisionInfoKeys.reasons]) + XCTAssertEqual(decisionInfo[Constants.DecisionInfoKeys.decisionEventDispatched] as! Bool, false) + exp.fulfill() + } + _ = user.decide(key: kFeatureKey) + + wait(for: [exp], timeout: 1) + } + + func testDecisionListener_DecisionEventDispatched_withSendFlagDecisions() { + let user = optimizely.createUserContext(userId: kUserId, attributes:["country": "US"]) + + // set for feature-test + + let experiment: Experiment = (self.optimizely.config?.allExperiments.first)! + var variation: Variation = (experiment.variations.first)! + variation.featureEnabled = true + variation.variables?.append(Variable(id: "2696150066", value: "123")) + self.optimizely.setDecisionServiceData(experiment: experiment, variation: variation, source: "") + + // (1) sendFlagDecision = false. feature-test. + + optimizely.config?.project.sendFlagDecisions = false + + var exp = expectation(description: "x") + notificationCenter.clearAllNotificationListeners() + _ = notificationCenter.addDecisionNotificationListener { (type, userId, attributes, decisionInfo) in XCTAssertEqual(decisionInfo[Constants.DecisionInfoKeys.decisionEventDispatched] as! Bool, true) exp.fulfill() } _ = user.decide(key: kFeatureKey) + wait(for: [exp], timeout: 1) + + // (2) sendFlagDecision = true. feature-test. + optimizely.config?.project.sendFlagDecisions = true + + exp = expectation(description: "x") + notificationCenter.clearAllNotificationListeners() + _ = notificationCenter.addDecisionNotificationListener { (type, userId, attributes, decisionInfo) in + XCTAssertEqual(decisionInfo[Constants.DecisionInfoKeys.decisionEventDispatched] as! Bool, true) + exp.fulfill() + } + _ = user.decide(key: kFeatureKey) + wait(for: [exp], timeout: 1) + + // set for rollout (null variation) + + self.optimizely.setDecisionServiceData(experiment: nil, variation: nil, source: "") + + // (3) sendFlagDecisions = false. rollout. + + optimizely.config?.project.sendFlagDecisions = false + + exp = expectation(description: "x") + notificationCenter.clearAllNotificationListeners() + _ = notificationCenter.addDecisionNotificationListener { (type, userId, attributes, decisionInfo) in + XCTAssertEqual(decisionInfo[Constants.DecisionInfoKeys.decisionEventDispatched] as! Bool, false) + exp.fulfill() + } + _ = user.decide(key: kFeatureKey) + wait(for: [exp], timeout: 1) + + // (3) sendFlagDecisions = true. rollout. + + optimizely.config?.project.sendFlagDecisions = true + + exp = expectation(description: "x") + notificationCenter.clearAllNotificationListeners() + _ = notificationCenter.addDecisionNotificationListener { (type, userId, attributes, decisionInfo) in + XCTAssertEqual(decisionInfo[Constants.DecisionInfoKeys.decisionEventDispatched] as! Bool, true) + exp.fulfill() + } + _ = user.decide(key: kFeatureKey) wait(for: [exp], timeout: 1) } diff --git a/Tests/OptimizelyTests-Common/OptimizelyUserContextTests_Decide.swift b/Tests/OptimizelyTests-Common/OptimizelyUserContextTests_Decide.swift index 84fd5ffa..d8c34c29 100644 --- a/Tests/OptimizelyTests-Common/OptimizelyUserContextTests_Decide.swift +++ b/Tests/OptimizelyTests-Common/OptimizelyUserContextTests_Decide.swift @@ -170,8 +170,8 @@ extension OptimizelyUserContextTests_Decide { XCTAssertEqual(metadata.variationKey, "") XCTAssertEqual(metadata.enabled, false) } - - func testDecide_doNotSendImpression() { + + func testDecideError_doNotSendImpression() { let featureKey = "invalid" // invalid flag let user = optimizely.createUserContext(userId: kUserId) @@ -183,7 +183,34 @@ extension OptimizelyUserContextTests_Decide { XCTAssertFalse(decision.enabled) XCTAssertNil(eventDispatcher.eventSent) } + + // sendFlagDecisions = false + func testDecide_sendImpression_withSendFlagDecisionsOff() { + optimizely.config?.project.sendFlagDecisions = false + + let featureKey = "feature_2" + + let user = optimizely.createUserContext(userId: kUserId) + let decision = user.decide(key: featureKey) + + optimizely.eventLock.sync{} + + XCTAssertNotNil(eventDispatcher.eventSent) + } + + func testDecide_shouldNotSendImpressionForRollout_withSendFlagDecisionsOff() { + optimizely.config?.project.sendFlagDecisions = false + + let featureKey = "feature_3" + let user = optimizely.createUserContext(userId: kUserId) + _ = user.decide(key: featureKey) + + optimizely.eventLock.sync{} + + XCTAssertNil(eventDispatcher.eventSent) + } + } // MARK: - decideForKeys API From 4245dc93a51e231866e2c796bcddd11e8414dbab Mon Sep 17 00:00:00 2001 From: Jae Kim Date: Tue, 26 Jan 2021 17:56:35 -0800 Subject: [PATCH 2/6] fix decisionEventDispatched false set --- .../Events/BatchEventBuilder.swift | 4 --- .../OptimizelyClient+Decide.swift | 19 +++++----- Sources/Optimizely/OptimizelyClient.swift | 18 ++++++---- .../BatchEventBuilderTests_Events.swift | 36 ------------------- .../DecisionListenerTests.swift | 32 ++++++++--------- 5 files changed, 38 insertions(+), 71 deletions(-) diff --git a/Sources/Implementation/Events/BatchEventBuilder.swift b/Sources/Implementation/Events/BatchEventBuilder.swift index e1decfc9..4aac4aaa 100644 --- a/Sources/Implementation/Events/BatchEventBuilder.swift +++ b/Sources/Implementation/Events/BatchEventBuilder.swift @@ -32,10 +32,6 @@ class BatchEventBuilder { ruleType: String, enabled: Bool) -> Data? { - if (ruleType == Constants.DecisionSource.rollout.rawValue || variation == nil) && !config.sendFlagDecisions { - return nil - } - let metaData = DecisionMetadata(ruleType: ruleType, ruleKey: experiment?.key ?? "", flagKey: flagKey, variationKey: variation?.key ?? "", enabled: enabled) let decision = Decision(variationID: variation?.id ?? "", diff --git a/Sources/Optimizely+Decide/OptimizelyClient+Decide.swift b/Sources/Optimizely+Decide/OptimizelyClient+Decide.swift index 98aabaf5..2451c1d4 100644 --- a/Sources/Optimizely+Decide/OptimizelyClient+Decide.swift +++ b/Sources/Optimizely+Decide/OptimizelyClient+Decide.swift @@ -62,14 +62,17 @@ extension OptimizelyClient { } if !allOptions.contains(.disableDecisionEvent) { - sendImpressionEvent(experiment: decision?.experiment, - variation: decision?.variation, - userId: userId, - attributes: attributes, - flagKey: feature.key, - ruleType: decision?.source ?? Constants.DecisionSource.rollout.rawValue, - enabled: enabled) - decisionEventDispatched = true + let ruleType = decision?.source ?? Constants.DecisionSource.rollout.rawValue + if (ruleType == Constants.DecisionSource.featureTest.rawValue && decision?.variation != nil) || config.sendFlagDecisions { + sendImpressionEvent(experiment: decision?.experiment, + variation: decision?.variation, + userId: userId, + attributes: attributes, + flagKey: feature.key, + ruleType: ruleType, + enabled: enabled) + decisionEventDispatched = true + } } var variableMap = [String: Any]() diff --git a/Sources/Optimizely/OptimizelyClient.swift b/Sources/Optimizely/OptimizelyClient.swift index 4c8d4df5..06b2e086 100644 --- a/Sources/Optimizely/OptimizelyClient.swift +++ b/Sources/Optimizely/OptimizelyClient.swift @@ -404,13 +404,15 @@ open class OptimizelyClient: NSObject { logger.i(.featureNotEnabledForUser(featureKey, userId)) } - sendImpressionEvent(experiment: pair?.experiment, - variation: pair?.variation, - userId: userId, - attributes: attributes, - flagKey: featureKey, - ruleType: source, - enabled: featureEnabled) + if (source == Constants.DecisionSource.featureTest.rawValue && pair?.variation != nil) || config.sendFlagDecisions { + sendImpressionEvent(experiment: pair?.experiment, + variation: pair?.variation, + userId: userId, + attributes: attributes, + flagKey: featureKey, + ruleType: source, + enabled: featureEnabled) + } sendDecisionNotification(userId: userId, attributes: attributes, @@ -798,6 +800,8 @@ extension OptimizelyClient { event: event, async: false) } + + return } } diff --git a/Tests/OptimizelyTests-Common/BatchEventBuilderTests_Events.swift b/Tests/OptimizelyTests-Common/BatchEventBuilderTests_Events.swift index cfd088c8..2dd79813 100644 --- a/Tests/OptimizelyTests-Common/BatchEventBuilderTests_Events.swift +++ b/Tests/OptimizelyTests-Common/BatchEventBuilderTests_Events.swift @@ -99,42 +99,6 @@ class BatchEventBuilderTests_Events: XCTestCase { XCTAssertNil(de["value"]) } - func testCreateImpressionEventWithSendFlagDecisions() { - let scenarios: [String: Bool] = [ - "experiment": true, - "anything-else": true, - Constants.DecisionSource.featureTest.rawValue: true, - Constants.DecisionSource.rollout.rawValue: false - ] - let attributes: [String: Any] = [ - "s_foo": "foo", - "b_true": true, - "i_42": 42, - "d_4_2": 4.2 - ] - let experiment = optimizely.config?.getExperiment(id: "10390977714") - let variation = experiment?.getVariation(id: "10416523162") - - for scenario in scenarios { - let event = BatchEventBuilder.createImpressionEvent(config: optimizely.config!, experiment: experiment!, variation: variation, userId: userId, attributes: attributes, flagKey: experiment!.key, ruleType: scenario.key, enabled: true) - scenario.value ? XCTAssertNotNil(event): XCTAssertNil(event) - } - - // nil variation should always return nil - for scenario in scenarios { - let event = BatchEventBuilder.createImpressionEvent(config: optimizely.config!, experiment: experiment!, variation: nil, userId: userId, attributes: attributes, flagKey: experiment!.key, ruleType: scenario.key, enabled: true) - XCTAssertNil(event) - } - - // should always return a event if sendFlagDecisions is set - optimizely.config?.project.sendFlagDecisions = true - for scenario in scenarios { - let event = BatchEventBuilder.createImpressionEvent(config: optimizely.config!, experiment: experiment!, variation: nil, userId: userId, attributes: attributes, flagKey: experiment!.key, ruleType: scenario.key, enabled: true) - XCTAssertNotNil(event) - } - optimizely.config?.project.sendFlagDecisions = nil - } - func testCreateImpressionEventWithoutVariation() { let attributes: [String: Any] = [ "s_foo": "foo", diff --git a/Tests/OptimizelyTests-Common/DecisionListenerTests.swift b/Tests/OptimizelyTests-Common/DecisionListenerTests.swift index 292c2e47..086721af 100644 --- a/Tests/OptimizelyTests-Common/DecisionListenerTests.swift +++ b/Tests/OptimizelyTests-Common/DecisionListenerTests.swift @@ -79,7 +79,7 @@ class DecisionListenerTests: XCTestCase { func testDecisionListenerGetFeatureVariableBooleanWithUserNotInExperimentAndRollout() { let exp = expectation(description: "x") - self.optimizely.setDecisionServiceData(experiment: nil, variation: nil, source: "") + self.optimizely.setDecisionServiceData(experiment: nil, variation: nil, source: Constants.DecisionSource.rollout.rawValue) notificationCenter.clearAllNotificationListeners() _ = notificationCenter.addDecisionNotificationListener { (_, _, _, decisionInfo) in XCTAssertEqual(decisionInfo[Constants.DecisionInfoKeys.featureEnabled] as! Bool, false) @@ -98,7 +98,7 @@ class DecisionListenerTests: XCTestCase { func testDecisionListenerGetFeatureVariableDoubleWithUserNotInExperimentAndRollout() { let exp = expectation(description: "x") - self.optimizely.setDecisionServiceData(experiment: nil, variation: nil, source: "") + self.optimizely.setDecisionServiceData(experiment: nil, variation: nil, source: Constants.DecisionSource.rollout.rawValue) notificationCenter.clearAllNotificationListeners() _ = notificationCenter.addDecisionNotificationListener { (_, _, _, decisionInfo) in XCTAssertEqual(decisionInfo[Constants.DecisionInfoKeys.featureEnabled] as! Bool, false) @@ -117,7 +117,7 @@ class DecisionListenerTests: XCTestCase { func testDecisionListenerGetFeatureVariableIntegerWithUserNotInExperimentAndRollout() { let exp = expectation(description: "x") - self.optimizely.setDecisionServiceData(experiment: nil, variation: nil, source: "") + self.optimizely.setDecisionServiceData(experiment: nil, variation: nil, source: Constants.DecisionSource.rollout.rawValue) notificationCenter.clearAllNotificationListeners() _ = notificationCenter.addDecisionNotificationListener { (_, _, _, decisionInfo) in XCTAssertEqual(decisionInfo[Constants.DecisionInfoKeys.featureEnabled] as! Bool, false) @@ -136,7 +136,7 @@ class DecisionListenerTests: XCTestCase { func testDecisionListenerGetFeatureVariableStringWithUserNotInExperimentAndRollout() { let exp = expectation(description: "x") - self.optimizely.setDecisionServiceData(experiment: nil, variation: nil, source: "") + self.optimizely.setDecisionServiceData(experiment: nil, variation: nil, source: Constants.DecisionSource.rollout.rawValue) notificationCenter.clearAllNotificationListeners() _ = notificationCenter.addDecisionNotificationListener { (_, _, _, decisionInfo) in XCTAssertEqual(decisionInfo[Constants.DecisionInfoKeys.featureEnabled] as! Bool, false) @@ -155,7 +155,7 @@ class DecisionListenerTests: XCTestCase { func testDecisionListenerGetFeatureVariableJSONWithUserNotInExperimentAndRollout() { let exp = expectation(description: "x") - self.optimizely.setDecisionServiceData(experiment: nil, variation: nil, source: "") + self.optimizely.setDecisionServiceData(experiment: nil, variation: nil, source: Constants.DecisionSource.rollout.rawValue) notificationCenter.clearAllNotificationListeners() _ = notificationCenter.addDecisionNotificationListener { (_, _, _, decisionInfo) in XCTAssertEqual(decisionInfo[Constants.DecisionInfoKeys.featureEnabled] as! Bool, false) @@ -174,7 +174,7 @@ class DecisionListenerTests: XCTestCase { func testDecisionListenerGetAllFeatureVariablesWithUserNotInExperimentAndRollout() { let exp = expectation(description: "x") - self.optimizely.setDecisionServiceData(experiment: nil, variation: nil, source: "") + self.optimizely.setDecisionServiceData(experiment: nil, variation: nil, source: Constants.DecisionSource.rollout.rawValue) notificationCenter.clearAllNotificationListeners() _ = notificationCenter.addDecisionNotificationListener { (type, _, _, decisionInfo) in XCTAssertEqual(type, Constants.DecisionType.allFeatureVariables.rawValue) @@ -765,7 +765,7 @@ class DecisionListenerTests: XCTestCase { func testDecisionListenerWithUserNotInExperimentAndRollout() { let exp = expectation(description: "x") - self.optimizely.setDecisionServiceData(experiment: nil, variation: nil, source: "") + self.optimizely.setDecisionServiceData(experiment: nil, variation: nil, source: Constants.DecisionSource.rollout.rawValue) notificationCenter.clearAllNotificationListeners() _ = notificationCenter.addDecisionNotificationListener { (_, _, _, decisionInfo) in XCTAssertEqual(decisionInfo[Constants.DecisionInfoKeys.featureEnabled] as! Bool, false) @@ -865,7 +865,7 @@ extension DecisionListenerTests { var variation: Variation = (experiment.variations.first)! variation.featureEnabled = true variation.variables?.append(Variable(id: "2696150066", value: "123")) - self.optimizely.setDecisionServiceData(experiment: experiment, variation: variation, source: "") + self.optimizely.setDecisionServiceData(experiment: experiment, variation: variation, source: Constants.DecisionSource.featureTest.rawValue) notificationCenter.clearAllNotificationListeners() _ = notificationCenter.addDecisionNotificationListener { (type, userId, attributes, decisionInfo) in @@ -903,7 +903,7 @@ extension DecisionListenerTests { let experiment: Experiment = (self.optimizely.config?.allExperiments.first)! var variation: Variation = (experiment.variations.first)! variation.featureEnabled = false - self.optimizely.setDecisionServiceData(experiment: experiment, variation: variation, source: "") + self.optimizely.setDecisionServiceData(experiment: experiment, variation: variation, source: Constants.DecisionSource.featureTest.rawValue) notificationCenter.clearAllNotificationListeners() _ = notificationCenter.addDecisionNotificationListener { (_, _, _, decisionInfo) in @@ -935,7 +935,7 @@ extension DecisionListenerTests { let user = optimizely.createUserContext(userId: kUserId, attributes:["country": "US"]) - self.optimizely.setDecisionServiceData(experiment: nil, variation: nil, source: "") + self.optimizely.setDecisionServiceData(experiment: nil, variation: nil, source: Constants.DecisionSource.rollout.rawValue) notificationCenter.clearAllNotificationListeners() _ = notificationCenter.addDecisionNotificationListener { (type, userId, attributes, decisionInfo) in @@ -975,7 +975,7 @@ extension DecisionListenerTests { var variation: Variation = (experiment.variations.first)! variation.featureEnabled = true variation.variables?.append(Variable(id: "2696150066", value: "123")) - self.optimizely.setDecisionServiceData(experiment: experiment, variation: variation, source: "") + self.optimizely.setDecisionServiceData(experiment: experiment, variation: variation, source: Constants.DecisionSource.featureTest.rawValue) // (1) sendFlagDecision = false. feature-test. @@ -1005,7 +1005,7 @@ extension DecisionListenerTests { // set for rollout (null variation) - self.optimizely.setDecisionServiceData(experiment: nil, variation: nil, source: "") + self.optimizely.setDecisionServiceData(experiment: nil, variation: nil, source: Constants.DecisionSource.rollout.rawValue) // (3) sendFlagDecisions = false. rollout. @@ -1042,7 +1042,7 @@ extension DecisionListenerTests { var variation: Variation = (experiment.variations.first)! variation.featureEnabled = true variation.variables?.append(Variable(id: "2696150066", value: "123")) - self.optimizely.setDecisionServiceData(experiment: experiment, variation: variation, source: "") + self.optimizely.setDecisionServiceData(experiment: experiment, variation: variation, source: Constants.DecisionSource.featureTest.rawValue) notificationCenter.clearAllNotificationListeners() _ = notificationCenter.addDecisionNotificationListener { (_, _, _, decisionInfo) in @@ -1076,7 +1076,7 @@ extension DecisionListenerTests { let experiment: Experiment = (self.optimizely.config?.allExperiments.first)! var variation: Variation = (experiment.variations.first)! variation.featureEnabled = false - self.optimizely.setDecisionServiceData(experiment: experiment, variation: variation, source: "") + self.optimizely.setDecisionServiceData(experiment: experiment, variation: variation, source: Constants.DecisionSource.featureTest.rawValue) notificationCenter.clearAllNotificationListeners() _ = notificationCenter.addDecisionNotificationListener { (_, _, _, decisionInfo) in @@ -1111,7 +1111,7 @@ extension DecisionListenerTests { let experiment: Experiment = (self.optimizely.config?.allExperiments.first)! let variation: Variation = (experiment.variations.first)! - self.optimizely.setDecisionServiceData(experiment: experiment, variation: variation, source: "") + self.optimizely.setDecisionServiceData(experiment: experiment, variation: variation, source: Constants.DecisionSource.featureTest.rawValue) notificationCenter.clearAllNotificationListeners() _ = notificationCenter.addDecisionNotificationListener { (type, userId, attributes, decisionInfo) in @@ -1165,7 +1165,7 @@ extension DecisionListenerTests { XCTAssertNil(decisionInfo[Constants.DecisionInfoKeys.variationKey]) XCTAssertNil(decisionInfo[Constants.DecisionInfoKeys.ruleKey]) XCTAssertNotNil(decisionInfo[Constants.DecisionInfoKeys.reasons]) - XCTAssertEqual(decisionInfo[Constants.DecisionInfoKeys.decisionEventDispatched] as! Bool, true) + XCTAssertEqual(decisionInfo[Constants.DecisionInfoKeys.decisionEventDispatched] as! Bool, false) exp.fulfill() } From 9c93f97701becde7c9874b6509663f6c95d59333 Mon Sep 17 00:00:00 2001 From: Jae Kim Date: Wed, 27 Jan 2021 16:06:46 -0800 Subject: [PATCH 3/6] pretty print for OptimizelyDecision and OptimizelyUserContext --- DemoSwiftApp/AppDelegate.swift | 1 + .../OptimizelyDecision.swift | 23 +++++++++++++++++++ .../OptimizelyUserContext.swift | 6 +++++ Sources/Optimizely/OptimizelyError.swift | 2 ++ Sources/Optimizely/OptimizelyJSON.swift | 6 +++++ 5 files changed, 38 insertions(+) diff --git a/DemoSwiftApp/AppDelegate.swift b/DemoSwiftApp/AppDelegate.swift index 961fd1ce..16e075e5 100644 --- a/DemoSwiftApp/AppDelegate.swift +++ b/DemoSwiftApp/AppDelegate.swift @@ -181,6 +181,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { self.user = self.optimizely.createUserContext(userId: self.userId, attributes: self.attributes) let decision = self.user.decide(key: self.featureKey, options: [.includeReasons]) + print("DECISION = \(decision)") if let variationKey = decision.variationKey { self.openVariationView(variationKey: variationKey) } else { diff --git a/Sources/Optimizely+Decide/OptimizelyDecision.swift b/Sources/Optimizely+Decide/OptimizelyDecision.swift index 3681931e..3474ec0e 100644 --- a/Sources/Optimizely+Decide/OptimizelyDecision.swift +++ b/Sources/Optimizely+Decide/OptimizelyDecision.swift @@ -68,3 +68,26 @@ extension OptimizelyDecision: Equatable { lhs.reasons == rhs.reasons } } + +extension OptimizelyDecision: CustomStringConvertible { + public var description: String { + let variationKey = self.variationKey == nil ? "nil" : ("\"" + self.variationKey! + "\"") + let ruleKey = self.ruleKey == nil ? "nil" : ("\"" + self.ruleKey! + "\"") + + return """ + { + variationKey: \(variationKey) + enabled: \(enabled) + variables: \(variables) + ruleKey: \(ruleKey) + flagKey: "\(flagKey)" + userContext: \(userContext) + reasons: [ + """ + + (reasons.isEmpty ? "" : reasons.reduce("\n") {$0 + " - \($1)\n"}) + + """ + ] + } + """ + } +} diff --git a/Sources/Optimizely+Decide/OptimizelyUserContext.swift b/Sources/Optimizely+Decide/OptimizelyUserContext.swift index 755dc9ae..f74f1109 100644 --- a/Sources/Optimizely+Decide/OptimizelyUserContext.swift +++ b/Sources/Optimizely+Decide/OptimizelyUserContext.swift @@ -139,3 +139,9 @@ extension OptimizelyUserContext: Equatable { } } + +extension OptimizelyUserContext: CustomStringConvertible { + public var description: String { + return "{ userId: \(userId), attributes: \(attributes) }" + } +} diff --git a/Sources/Optimizely/OptimizelyError.swift b/Sources/Optimizely/OptimizelyError.swift index 3fc56ad6..e335567e 100644 --- a/Sources/Optimizely/OptimizelyError.swift +++ b/Sources/Optimizely/OptimizelyError.swift @@ -97,11 +97,13 @@ extension OptimizelyError: CustomStringConvertible, ReasonProtocol { switch self { case .generic: message = "Unknown reason." + // DO NOT CHANGE these critical error messages - FSC will validate exact-wordings of these messages. case .sdkNotReady: message = "Optimizely SDK not configured properly yet." case .featureKeyInvalid(let key): message = "No flag was found for key \"\(key)\"." case .variableValueInvalid(let key): message = "Variable value for key \"\(key)\" is invalid or wrong type." case .invalidJSONVariable: message = "Invalid variables for OptimizelyJSON." + // These error messages not validated by FSC case .experimentKeyInvalid(let key): message = "Experiment key (\(key)) is not in datafile. It is either invalid, paused, or archived." case .experimentIdInvalid(let id): message = "Experiment ID (\(id)) is not in datafile." case .experimentHasNoTrafficAllocation(let key): message = "No traffic allocation rules are defined for experiement (\(key))." diff --git a/Sources/Optimizely/OptimizelyJSON.swift b/Sources/Optimizely/OptimizelyJSON.swift index b079beb6..0377eb02 100644 --- a/Sources/Optimizely/OptimizelyJSON.swift +++ b/Sources/Optimizely/OptimizelyJSON.swift @@ -199,3 +199,9 @@ extension OptimizelyJSON { } } + +extension OptimizelyJSON { + public override var description: String { + return "\(map)" + } +} From e9bcdb9a21fcf9e56af51475cf0efb61d5de069c Mon Sep 17 00:00:00 2001 From: Jae Kim Date: Wed, 27 Jan 2021 16:26:41 -0800 Subject: [PATCH 4/6] clean up --- Sources/Optimizely+Decide/OptimizelyClient+Decide.swift | 2 +- Sources/Optimizely/OptimizelyClient.swift | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Sources/Optimizely+Decide/OptimizelyClient+Decide.swift b/Sources/Optimizely+Decide/OptimizelyClient+Decide.swift index 2451c1d4..e24aea22 100644 --- a/Sources/Optimizely+Decide/OptimizelyClient+Decide.swift +++ b/Sources/Optimizely+Decide/OptimizelyClient+Decide.swift @@ -63,7 +63,7 @@ extension OptimizelyClient { if !allOptions.contains(.disableDecisionEvent) { let ruleType = decision?.source ?? Constants.DecisionSource.rollout.rawValue - if (ruleType == Constants.DecisionSource.featureTest.rawValue && decision?.variation != nil) || config.sendFlagDecisions { + if shouldSendDecisionEvent(source: ruleType, decision: decision) { sendImpressionEvent(experiment: decision?.experiment, variation: decision?.variation, userId: userId, diff --git a/Sources/Optimizely/OptimizelyClient.swift b/Sources/Optimizely/OptimizelyClient.swift index 06b2e086..468c22ed 100644 --- a/Sources/Optimizely/OptimizelyClient.swift +++ b/Sources/Optimizely/OptimizelyClient.swift @@ -404,7 +404,7 @@ open class OptimizelyClient: NSObject { logger.i(.featureNotEnabledForUser(featureKey, userId)) } - if (source == Constants.DecisionSource.featureTest.rawValue && pair?.variation != nil) || config.sendFlagDecisions { + if shouldSendDecisionEvent(source: source, decision: pair) { sendImpressionEvent(experiment: pair?.experiment, variation: pair?.variation, userId: userId, @@ -762,6 +762,11 @@ open class OptimizelyClient: NSObject { extension OptimizelyClient { + func shouldSendDecisionEvent(source: String, decision: FeatureDecision?) -> Bool { + guard let config = self.config else { return false } + return (source == Constants.DecisionSource.featureTest.rawValue && decision?.variation != nil) || config.sendFlagDecisions + } + func sendImpressionEvent(experiment: Experiment?, variation: Variation?, userId: String, From fab3095ea7d49f15bf63aa078d6fbd7509058621 Mon Sep 17 00:00:00 2001 From: Jae Kim Date: Wed, 27 Jan 2021 16:34:01 -0800 Subject: [PATCH 5/6] fix copyright years --- Sources/Implementation/Events/BatchEventBuilder.swift | 2 +- .../OptimizelyTests-Common/BatchEventBuilderTests_Events.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Implementation/Events/BatchEventBuilder.swift b/Sources/Implementation/Events/BatchEventBuilder.swift index 4aac4aaa..2c49fae1 100644 --- a/Sources/Implementation/Events/BatchEventBuilder.swift +++ b/Sources/Implementation/Events/BatchEventBuilder.swift @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright 2019-2020, Optimizely, Inc. and contributors * + * Copyright 2019-2021, Optimizely, Inc. and contributors * * * * Licensed under the Apache License, Version 2.0 (the "License"); * * you may not use this file except in compliance with the License. * diff --git a/Tests/OptimizelyTests-Common/BatchEventBuilderTests_Events.swift b/Tests/OptimizelyTests-Common/BatchEventBuilderTests_Events.swift index 2dd79813..e7f88069 100644 --- a/Tests/OptimizelyTests-Common/BatchEventBuilderTests_Events.swift +++ b/Tests/OptimizelyTests-Common/BatchEventBuilderTests_Events.swift @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright 2019-2020, Optimizely, Inc. and contributors * + * Copyright 2019-2021, Optimizely, Inc. and contributors * * * * Licensed under the Apache License, Version 2.0 (the "License"); * * you may not use this file except in compliance with the License. * From 21729ba65d5448cdcd85218782c33e328101e208 Mon Sep 17 00:00:00 2001 From: Jae Kim Date: Wed, 27 Jan 2021 16:37:02 -0800 Subject: [PATCH 6/6] fix copyright years --- Sources/Optimizely/OptimizelyClient.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/Sources/Optimizely/OptimizelyClient.swift b/Sources/Optimizely/OptimizelyClient.swift index 468c22ed..e39a76ba 100644 --- a/Sources/Optimizely/OptimizelyClient.swift +++ b/Sources/Optimizely/OptimizelyClient.swift @@ -805,8 +805,6 @@ extension OptimizelyClient { event: event, async: false) } - - return } }