Skip to content

feat: added GetFeatureVariableJSON. #317

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 36 additions & 2 deletions Sources/Data Model/FeatureVariable.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/****************************************************************************
* Copyright 2019, Optimizely, Inc. and contributors *
* Copyright 2019-2020, 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. *
Expand All @@ -20,6 +20,40 @@ struct FeatureVariable: Codable, Equatable {
var id: String
var key: String
var type: String
// datafile schema rquires this, but test has "null" value case. keep optional for FSC
var subType: String?
// datafile schema requires this, but test has "null" value case. keep optional for FSC
var defaultValue: String?

enum CodingKeys: String, CodingKey {
case id
case key
case type
case subType
case defaultValue
}

Comment on lines +27 to +34
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can drop this since all default names

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CodingKeys (Even if exactly the same as defaultNames) are required to be defined if we override init(from decoder: Decoder).

init(id: String, key: String, type: String, subType: String?, defaultValue: String?) {
self.id = id
self.key = key
self.type = type
self.subType = subType
self.defaultValue = defaultValue
overrideTypeIfJSON()
}

init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(String.self, forKey: .id)
key = try container.decode(String.self, forKey: .key)
type = try container.decode(String.self, forKey: .type)
subType = try container.decodeIfPresent(String.self, forKey: .subType)
defaultValue = try container.decodeIfPresent(String.self, forKey: .defaultValue)
overrideTypeIfJSON()
}

mutating func overrideTypeIfJSON() {
if type == "string" && subType == "json" {
type = "json"
}
Comment on lines +55 to +57
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same mapping should be in the other init() as well?

}
}
21 changes: 21 additions & 0 deletions Sources/Optimizely/OptimizelyClient+ObjC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,27 @@ extension OptimizelyClient {
attributes: attributes)
}

@available(swift, obsoleted: 1.0)
@objc(getFeatureVariableJSONWithFeatureKey:variableKey:userId:attributes:error:)
/// Gets json feature variable value.
///
/// - Parameters:
/// - featureKey: The key for the feature flag.
/// - variableKey: The key for the variable.
/// - userId: The user ID to be used for bucketing.
/// - attributes: The user's attributes.
/// - Returns: feature variable value of type OptimizelyJSON.
/// - Throws: `OptimizelyError` if feature parameter is not valid
public func objcGetFeatureVariableJSON(featureKey: String,
variableKey: String,
userId: String,
attributes: [String: Any]?) throws -> OptimizelyJSON {
return try self.getFeatureVariableJSON(featureKey: featureKey,
variableKey: variableKey,
userId: userId,
attributes: attributes)
}

@available(swift, obsoleted: 1.0)
@objc(getEnabledFeaturesWithUserId:attributes:)
/// Get array of features that are enabled for the user.
Expand Down
29 changes: 27 additions & 2 deletions Sources/Optimizely/OptimizelyClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,26 @@ open class OptimizelyClient: NSObject {
attributes: attributes)
}

/// Gets json feature variable value.
///
/// - Parameters:
/// - featureKey: The key for the feature flag.
/// - variableKey: The key for the variable.
/// - userId: The user ID to be used for bucketing.
/// - attributes: The user's attributes.
/// - Returns: feature variable value of type OptimizelyJSON.
/// - Throws: `OptimizelyError` if feature parameter is not valid
public func getFeatureVariableJSON(featureKey: String,
variableKey: String,
userId: String,
attributes: OptimizelyAttributes? = nil) throws -> OptimizelyJSON {

return try getFeatureVariable(featureKey: featureKey,
variableKey: variableKey,
userId: userId,
attributes: attributes)
}

func getFeatureVariable<T>(featureKey: String,
variableKey: String,
userId: String,
Expand Down Expand Up @@ -543,13 +563,18 @@ open class OptimizelyClient: NSObject {
case is Bool.Type:
typeName = "boolean"
valueParsed = Bool(featureValue) as? T
case is OptimizelyJSON.Type:
typeName = "json"
if let optimizelyJSON = OptimizelyJSON(payload: featureValue) {
valueParsed = optimizelyJSON as? T
}
default:
break
}

guard let value = valueParsed,
variable.type == typeName else {
throw OptimizelyError.variableValueInvalid(variableKey)
throw OptimizelyError.variableValueInvalid(variableKey)
}

// Decision Notification
Expand All @@ -568,7 +593,7 @@ open class OptimizelyClient: NSObject {
variableKey: variableKey,
variableType: typeName,
variableValue: value)

return value
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/****************************************************************************
* Copyright 2019, Optimizely, Inc. and contributors *
* Copyright 2019-2020, 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. *
Expand Down Expand Up @@ -97,6 +97,13 @@ extension OptimizelyClientTests_Invalid {
XCTAssertNil(result)
}

func testGetFeatureVariableJSON_WhenManagerNonInitialized() {
let result: OptimizelyJSON? = try? self.optimizely.getFeatureVariableJSON(featureKey: kFeatureKey,
variableKey: kVariableKey,
userId: kUserId)
XCTAssertNil(result)
}

func testGetEnabledFeatures_WhenManagerNonInitialized() {
let result = self.optimizely.getEnabledFeatures(userId: kUserId)
XCTAssert(result.count == 0)
Expand Down
13 changes: 12 additions & 1 deletion Tests/OptimizelyTests-APIs/OptimizelyClientTests_ObjcAPIs.m
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/****************************************************************************
* Copyright 2019, Optimizely, Inc. and contributors *
* Copyright 2019-2020, 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. *
Expand Down Expand Up @@ -31,11 +31,13 @@
static NSString * const kVariableKeyInt = @"i_42";
static NSString * const kVariableKeyDouble = @"d_4_2";
static NSString * const kVariableKeyBool = @"b_true";
static NSString * const kVariableKeyJSON = @"j_1";

static NSString * const kVariableValueString = @"foo";
static const int kVariableValueInt = 42;
static const double kVariableValueDouble = 4.2;
static const BOOL kVariableValueBool = true;
static NSString * const kVariableValueJSON = @"{\"value\":1}";

static NSString * const kEventKey = @"event1";

Expand Down Expand Up @@ -191,6 +193,15 @@ - (void)testGetFeatureVariableString {
error:nil];
XCTAssertEqualObjects(result, kVariableValueString);
}

- (void)testGetFeatureVariableJSON {
OptimizelyJSON *result = [self.optimizely getFeatureVariableJSONWithFeatureKey:kFeatureKey
variableKey:kVariableKeyJSON
userId:kUserId
attributes:self.attributes
error:nil];
XCTAssertEqualObjects([result toString], kVariableValueJSON);
}

- (void)testGetEnabledFeatures {
NSArray *result = [self.optimizely getEnabledFeaturesWithUserId:kUserId
Expand Down
21 changes: 20 additions & 1 deletion Tests/OptimizelyTests-APIs/OptimizelyClientTests_Others.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/****************************************************************************
* Copyright 2019, Optimizely, Inc. and contributors *
* Copyright 2019-2020, 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. *
Expand Down Expand Up @@ -28,6 +28,9 @@ class OptimizelyClientTests_Others: XCTestCase {

let kVariableKeyString = "s_foo"
let kInvalidVariableKeyString = "invalid_key"

let kVariableKeyJSON = "j_1"
let kInvalidVariableKeyJSON = "invalid_key"

let kUserId = "user"
let kNotRealSdkKey = "notrealkey123"
Expand Down Expand Up @@ -74,6 +77,14 @@ class OptimizelyClientTests_Others: XCTestCase {
value = try? optimizely.getFeatureVariableString(featureKey: kInvalidFeatureKey, variableKey: kVariableKeyString, userId: kUserId)
XCTAssertNil(value)
}

func testGetFeatureVariableJSON_InvalidFeatureKey() {
var value = try? optimizely.getFeatureVariableJSON(featureKey: kFeatureKey, variableKey: kVariableKeyJSON, userId: kUserId)
XCTAssertNotNil(value)

value = try? optimizely.getFeatureVariableJSON(featureKey: kInvalidFeatureKey, variableKey: kVariableKeyJSON, userId: kUserId)
XCTAssertNil(value)
}

func testGetFeatureVariableString_InvalidVariableKey() {
var value = try? optimizely.getFeatureVariableString(featureKey: kFeatureKey, variableKey: kVariableKeyString, userId: kUserId)
Expand All @@ -83,6 +94,14 @@ class OptimizelyClientTests_Others: XCTestCase {
XCTAssertNil(value)
}

func testGetFeatureVariableJSON_InvalidVariableKey() {
var value = try? optimizely.getFeatureVariableJSON(featureKey: kFeatureKey, variableKey: kVariableKeyJSON, userId: kUserId)
XCTAssertNotNil(value)

value = try? optimizely.getFeatureVariableJSON(featureKey: kFeatureKey, variableKey: kInvalidVariableKeyJSON, userId: kUserId)
XCTAssertNil(value)
}

func testGetFeatureVariable_WrongType() {
// read integer for string-type variable
let value = try? optimizely.getFeatureVariableInteger(featureKey: kFeatureKey, variableKey: kVariableKeyString, userId: kUserId)
Expand Down
15 changes: 14 additions & 1 deletion Tests/OptimizelyTests-APIs/OptimizelyClientTests_Valid.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/****************************************************************************
* Copyright 2019, Optimizely, Inc. and contributors *
* Copyright 2019-2020, 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. *
Expand Down Expand Up @@ -32,11 +32,13 @@ class OptimizelyClientTests_Valid: XCTestCase {
let kVariableKeyInt = "i_42"
let kVariableKeyDouble = "d_4_2"
let kVariableKeyBool = "b_true"
let kVariableKeyJSON = "j_1"

let kVariableValueString = "foo"
let kVariableValueInt = 42
let kVariableValueDouble = 4.2
let kVariableValueBool = true
let kVariableValueJSON = "{\"value\":1}"

let kEventKey = "event1"

Expand Down Expand Up @@ -134,6 +136,17 @@ class OptimizelyClientTests_Valid: XCTestCase {
XCTAssert(result == kVariableValueString)
}

func testGetFeatureVariableJSON() {
let result: OptimizelyJSON? = try? self.optimizely.getFeatureVariableJSON(featureKey: kFeatureKey,
variableKey: kVariableKeyJSON,
userId: kUserId)
XCTAssert(result?.toString() == kVariableValueJSON)
XCTAssert((result?.toMap()["value"] as! Int) == 1)
var intValue: Int = 0
XCTAssertTrue(result!.getValue(jsonPath: "value", schema: &intValue))
XCTAssert(intValue == 1)
}

func testGetEnabledFeatures() {
let result: [String] = self.optimizely.getEnabledFeatures(userId: kUserId)
XCTAssert(result == [kFeatureKey])
Expand Down
Loading