From 0b5c4ce0e7a61e22fd420479c5380e26b877fe63 Mon Sep 17 00:00:00 2001 From: Jae Kim Date: Wed, 27 Mar 2019 17:45:32 -0700 Subject: [PATCH] fix feature variable when feature disabled (#3707) --- .../Optimizely/OptimizelyManager.swift | 21 ++-- .../project.pbxproj | 4 + .../OptimizelyManagerTests_Variables.swift | 107 ++++++++++++++++++ 3 files changed, 124 insertions(+), 8 deletions(-) create mode 100644 OptimizelySDK/OptimizelyTests/OptimizelyTests-APIs/OptimizelyManagerTests_Variables.swift diff --git a/OptimizelySDK/Optimizely/OptimizelyManager.swift b/OptimizelySDK/Optimizely/OptimizelyManager.swift index 041bcf30e..790cb13a8 100644 --- a/OptimizelySDK/Optimizely/OptimizelyManager.swift +++ b/OptimizelySDK/Optimizely/OptimizelyManager.swift @@ -532,16 +532,21 @@ open class OptimizelyManager: NSObject { throw OptimizelyError.variableUnknown } - // TODO: [Jae] optional? fallback to empty string is OK? - var defaultValue = variable.defaultValue ?? "" + var featureValue = variable.defaultValue ?? "" var _attributes = OptimizelyAttributes() if attributes != nil { _attributes = attributes! } if let decision = self.decisionService.getVariationForFeature(config: config, featureFlag: featureFlag, userId: userId, attributes: _attributes) { - if let featureVariableUsage = decision.variation?.variables?.filter({$0.id == variable.id}).first { - defaultValue = featureVariableUsage.value + if let variation = decision.variation, + let featureVariableUsage = variation.variables?.filter({$0.id == variable.id}).first + { + if let featureEnabled = variation.featureEnabled, featureEnabled { + featureValue = featureVariableUsage.value + } else { + // add standard log message here + } } } @@ -551,16 +556,16 @@ open class OptimizelyManager: NSObject { switch T.self { case is String.Type: typeName = "string" - valueParsed = defaultValue as? T + valueParsed = featureValue as? T case is Int.Type: typeName = "integer" - valueParsed = Int(defaultValue) as? T + valueParsed = Int(featureValue) as? T case is Double.Type: typeName = "double" - valueParsed = Double(defaultValue) as? T + valueParsed = Double(featureValue) as? T case is Bool.Type: typeName = "boolean" - valueParsed = Bool(defaultValue) as? T + valueParsed = Bool(featureValue) as? T default: break } diff --git a/OptimizelySDK/OptimizelySwiftSDK.xcodeproj/project.pbxproj b/OptimizelySDK/OptimizelySwiftSDK.xcodeproj/project.pbxproj index 9b5b0241d..aa4740e54 100644 --- a/OptimizelySDK/OptimizelySwiftSDK.xcodeproj/project.pbxproj +++ b/OptimizelySDK/OptimizelySwiftSDK.xcodeproj/project.pbxproj @@ -543,6 +543,7 @@ 6E8B6A49221CBBC5006EA8A6 /* GroupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E8B6A47221CBBC5006EA8A6 /* GroupTests.swift */; }; 6E8B6A4B221CC2D6006EA8A6 /* ProjectTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E8B6A4A221CC2D6006EA8A6 /* ProjectTests.swift */; }; 6E8B6A4C221CC2D6006EA8A6 /* ProjectTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E8B6A4A221CC2D6006EA8A6 /* ProjectTests.swift */; }; + 6E8CB5C9224C461A00B8CB7A /* OptimizelyManagerTests_Variables.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E8CB5C8224C461A00B8CB7A /* OptimizelyManagerTests_Variables.swift */; }; 6E95C8B62217F10800B6EE06 /* ConditionLeaf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E95C8B52217F10800B6EE06 /* ConditionLeaf.swift */; }; 6E95C8B92217F9B100B6EE06 /* ConditionLeaf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E95C8B52217F10800B6EE06 /* ConditionLeaf.swift */; }; 6E95C8BA2217F9B200B6EE06 /* ConditionLeaf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E95C8B52217F10800B6EE06 /* ConditionLeaf.swift */; }; @@ -1270,6 +1271,7 @@ 6E852C69221A7E3300C41F94 /* ExperimentTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExperimentTests.swift; sourceTree = ""; }; 6E8B6A47221CBBC5006EA8A6 /* GroupTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupTests.swift; sourceTree = ""; }; 6E8B6A4A221CC2D6006EA8A6 /* ProjectTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProjectTests.swift; sourceTree = ""; }; + 6E8CB5C8224C461A00B8CB7A /* OptimizelyManagerTests_Variables.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OptimizelyManagerTests_Variables.swift; sourceTree = ""; }; 6E95C8A822176EA500B6EE06 /* AudienceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AudienceTests.swift; sourceTree = ""; }; 6E95C8AA2217736000B6EE06 /* ConditionHolderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConditionHolderTests.swift; sourceTree = ""; }; 6E95C8B12217C92E00B6EE06 /* ConditionHolderTests_Evaluate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConditionHolderTests_Evaluate.swift; sourceTree = ""; }; @@ -1678,6 +1680,7 @@ 6E636C162236CB6D00AF3CEF /* OptimizelyManagerTests_Valid.swift */, 6EC5D3612231C19200BF9D77 /* OptimizelyManagerTests_Invalid.swift */, 6E636C5D223708B000AF3CEF /* OptimizelyManagerTests_ForcedVariation.swift */, + 6E8CB5C8224C461A00B8CB7A /* OptimizelyManagerTests_Variables.swift */, 0B8F537B223FFB0500C56082 /* OptimizelyManagerTests_Group.swift */, 0B2D48FE2245670C0024A661 /* OptimizelyManagerTests_Threading.swift */, ); @@ -2705,6 +2708,7 @@ 6E636BF32236C9BC00AF3CEF /* Variable.swift in Sources */, 6E636BBC2236C99300AF3CEF /* DataStoreFile.swift in Sources */, 6E636BAF2236C98300AF3CEF /* DefaultEventDispatcher.swift in Sources */, + 6E8CB5C9224C461A00B8CB7A /* OptimizelyManagerTests_Variables.swift in Sources */, 6E636BA92236C97E00AF3CEF /* OptimizelyLogLevel.swift in Sources */, 6E636BE02236C9B700AF3CEF /* Audience.swift in Sources */, 6E636C022236C9C500AF3CEF /* EventForDispatch+Extension.swift in Sources */, diff --git a/OptimizelySDK/OptimizelyTests/OptimizelyTests-APIs/OptimizelyManagerTests_Variables.swift b/OptimizelySDK/OptimizelyTests/OptimizelyTests-APIs/OptimizelyManagerTests_Variables.swift new file mode 100644 index 000000000..e2ab43a67 --- /dev/null +++ b/OptimizelySDK/OptimizelyTests/OptimizelyTests-APIs/OptimizelyManagerTests_Variables.swift @@ -0,0 +1,107 @@ +// +// OptimizelyManagerTests_Variables.swift +// OptimizelyTests-APIs-iOS +// +// Created by Jae Kim on 3/11/19. +// Copyright © 2019 Optimizely. All rights reserved. +// + +import XCTest + +class OptimizelyManagerTests_Variables: XCTestCase { + + let kVariableId = "1111" + let kVariableDefaultValue = 20 + let kVariableValueA = 30 + + let kUserId = "12345" + let kExperimentId = "11111" + + var sampleExperimentData: [String: Any] { return + [ + "status": "Running", + "id": kExperimentId, + "key": "43432134", + "layerId": "10420273888", + "trafficAllocation": [ + [ + "entityId": "10389729780", + "endOfRange": 10000 + ] + ], + "audienceIds": [], + "variations": [ + [ + "variables": [ + ["id": kVariableId, "value": String(kVariableValueA)] + ], + "id": "10389729780", + "key": "16456523121" + ] + ], + "forcedVariations":[:] + ] + } + var sampleFeatureFlagData: [String: Any] { return + [ + "id": "553339214", + "key": "house", + "experimentIds":[kExperimentId], + "rolloutId": "", + "variables": [ + [ + "defaultValue": String(kVariableDefaultValue), + "type": "integer", + "id": kVariableId, + "key": "window" + ] + ] + ] + } + + var optimizely: OptimizelyManager! + var experiment: Experiment! + var featureFlag: FeatureFlag! + + override func setUp() { + super.setUp() + + optimizely = OTUtils.createOptimizely(datafileName: "empty_datafile", + clearUserProfileService: true)! + + let featureFlag: FeatureFlag = try! OTUtils.model(from: sampleFeatureFlagData) + optimizely.config!.project.featureFlags = [featureFlag] + } + + + func testFeatureVariableWhenFeatureEnabled() { + var experiment: Experiment = try! OTUtils.model(from: sampleExperimentData) + experiment.variations[0].featureEnabled = true + optimizely.config!.project.experiments = [experiment] + + let value = try! optimizely.getFeatureVariableInteger(featureKey: "house", variableKey: "window", userId: kUserId) + + XCTAssertEqual(value, kVariableValueA) + } + + func testFeatureVariableWhenFeatureDisabled() { + var experiment: Experiment = try! OTUtils.model(from: sampleExperimentData) + experiment.variations[0].featureEnabled = false + optimizely.config!.project.experiments = [experiment] + + let value = try! optimizely.getFeatureVariableInteger(featureKey: "house", variableKey: "window", userId: kUserId) + + XCTAssertEqual(value, kVariableDefaultValue) + } + + func testFeatureVariableWhenFeatureEnabledNil() { + var experiment: Experiment = try! OTUtils.model(from: sampleExperimentData) + experiment.variations[0].featureEnabled = nil + optimizely.config!.project.experiments = [experiment] + + let value = try! optimizely.getFeatureVariableInteger(featureKey: "house", variableKey: "window", userId: kUserId) + + XCTAssertEqual(value, kVariableDefaultValue) + } + +}