From 9d1fe1364c2100dddacee80bb51186f9458a62ef Mon Sep 17 00:00:00 2001 From: Gaston Thea Date: Wed, 8 Nov 2023 10:57:35 -0300 Subject: [PATCH 1/3] New methods parsing in iOS; new fields in SplitView --- splitio_ios/ios/Classes/Constants.swift | 6 ++ splitio_ios/ios/Classes/Extensions.swift | 5 +- .../ios/Classes/SplitMethodParser.swift | 86 ++++++++++++++++--- splitio_ios/ios/Classes/SplitWrapper.swift | 24 +++--- .../lib/split_view.dart | 11 ++- 5 files changed, 104 insertions(+), 28 deletions(-) diff --git a/splitio_ios/ios/Classes/Constants.swift b/splitio_ios/ios/Classes/Constants.swift index bea9d65..ea6e2e6 100644 --- a/splitio_ios/ios/Classes/Constants.swift +++ b/splitio_ios/ios/Classes/Constants.swift @@ -13,6 +13,10 @@ enum Method: String { case getTreatments = "getTreatments" case getTreatmentWithConfig = "getTreatmentWithConfig" case getTreatmentsWithConfig = "getTreatmentsWithConfig" + case getTreatmentsByFlagSet = "getTreatmentsByFlagSet" + case getTreatmentsByFlagSets = "getTreatmentsByFlagSets" + case getTreatmentsWithConfigByFlagSet = "getTreatmentsWithConfigByFlagSet" + case getTreatmentsWithConfigByFlagSets = "getTreatmentsWithConfigByFlagSets" case track = "track" case getAttribute = "getAttribute" case getAllAttributes = "getAllAttributes" @@ -40,4 +44,6 @@ enum Argument: String { case value = "value" case properties = "properties" case attributeName = "attributeName" + case flagSet = "flagSet" + case flagSets = "flagSets" } diff --git a/splitio_ios/ios/Classes/Extensions.swift b/splitio_ios/ios/Classes/Extensions.swift index 5ff3bc7..d17250c 100644 --- a/splitio_ios/ios/Classes/Extensions.swift +++ b/splitio_ios/ios/Classes/Extensions.swift @@ -22,7 +22,10 @@ extension SplitView { "killed": splitView.killed, "treatments": splitView.treatments, "changeNumber": splitView.changeNumber, - "configs": splitView.configs] + "configs": splitView.configs, + "defaultTreatment": splitView.defaultTreatment, + "sets": splitView.sets + ] } else { return [:] } diff --git a/splitio_ios/ios/Classes/SplitMethodParser.swift b/splitio_ios/ios/Classes/SplitMethodParser.swift index 6c8a216..d54abd6 100644 --- a/splitio_ios/ios/Classes/SplitMethodParser.swift +++ b/splitio_ios/ios/Classes/SplitMethodParser.swift @@ -75,6 +75,34 @@ class DefaultSplitMethodParser: SplitMethodParser { splits: argumentParser.getStringListArgument(argumentName: .splitName, arguments: arguments), attributes: argumentParser.getMapArgument(argumentName: .attributes, arguments: arguments) as [String: Any])) break + case .getTreatmentsByFlagSet: + result(getTreatmentsByFlagSet( + matchingKey: argumentParser.getStringArgument(argumentName: .matchingKey, arguments: arguments) ?? "", + bucketingKey: argumentParser.getStringArgument(argumentName: .bucketingKey, arguments: arguments), + flagSet: argumentParser.getStringArgument(argumentName: .flagSet, arguments: arguments) ?? "", + attributes: argumentParser.getMapArgument(argumentName: .attributes, arguments: arguments) as [String: Any])) + break + case .getTreatmentsByFlagSets: + result(getTreatmentsByFlagSets( + matchingKey: argumentParser.getStringArgument(argumentName: .matchingKey, arguments: arguments) ?? "", + bucketingKey: argumentParser.getStringArgument(argumentName: .bucketingKey, arguments: arguments), + flagSets: argumentParser.getStringListArgument(argumentName: .flagSets, arguments: arguments), + attributes: argumentParser.getMapArgument(argumentName: .attributes, arguments: arguments) as [String: Any])) + break + case .getTreatmentsWithConfigByFlagSet: + result(getTreatmentsWithConfigByFlagSet( + matchingKey: argumentParser.getStringArgument(argumentName: .matchingKey, arguments: arguments) ?? "", + bucketingKey: argumentParser.getStringArgument(argumentName: .bucketingKey, arguments: arguments), + flagSet: argumentParser.getStringArgument(argumentName: .flagSet, arguments: arguments) ?? "", + attributes: argumentParser.getMapArgument(argumentName: .attributes, arguments: arguments) as [String: Any])) + break + case .getTreatmentsWithConfigByFlagSets: + result(getTreatmentsWithConfigByFlagSets( + matchingKey: argumentParser.getStringArgument(argumentName: .matchingKey, arguments: arguments) ?? "", + bucketingKey: argumentParser.getStringArgument(argumentName: .bucketingKey, arguments: arguments), + flagSets: argumentParser.getStringListArgument(argumentName: .flagSets, arguments: arguments), + attributes: argumentParser.getMapArgument(argumentName: .attributes, arguments: arguments) as [String: Any])) + break case .track: result(track(matchingKey: argumentParser.getStringArgument(argumentName: .matchingKey, arguments: arguments) ?? "", bucketingKey: argumentParser.getStringArgument(argumentName: .bucketingKey, arguments: arguments), @@ -215,6 +243,50 @@ class DefaultSplitMethodParser: SplitMethodParser { } } + private func getTreatmentsByFlagSet(matchingKey: String, bucketingKey: String? = nil, flagSet: String, attributes: [String: Any]? = [:]) -> [String: String] { + guard let splitWrapper = getSplitWrapper() else { + return [:] + } + + let treatments = splitWrapper.getTreatmentsByFlagSet(matchingKey: matchingKey, flagSet: flagSet, bucketingKey: bucketingKey, attributes: attributes) + + return treatments + } + + private func getTreatmentsByFlagSets(matchingKey: String, bucketingKey: String? = nil, flagSets: [String], attributes: [String: Any]? = [:]) -> [String: String] { + guard let splitWrapper = getSplitWrapper() else { + return [:] + } + + let treatments = splitWrapper.getTreatmentsByFlagSets(matchingKey: matchingKey, flagSets: flagSets, bucketingKey: bucketingKey, attributes: attributes) + + return treatments + } + + private func getTreatmentsWithConfigByFlagSet(matchingKey: String, bucketingKey: String? = nil, flagSet: String, attributes: [String: Any]? = [:]) -> [String: [String: String?]] { + guard let splitWrapper = getSplitWrapper() else { + return [:] + } + + let treatments = splitWrapper.getTreatmentsWithConfigByFlagSet(matchingKey: matchingKey, flagSet: flagSet, bucketingKey: bucketingKey, attributes: attributes) + + return treatments.mapValues { + ["treatment": $0.treatment, "config": $0.config] + } + } + + private func getTreatmentsWithConfigByFlagSets(matchingKey: String, bucketingKey: String? = nil, flagSets: [String], attributes: [String: Any]? = [:]) -> [String: [String: String?]] { + guard let splitWrapper = getSplitWrapper() else { + return [:] + } + + let treatments = splitWrapper.getTreatmentsWithConfigByFlagSets(matchingKey: matchingKey, flagSets: flagSets, bucketingKey: bucketingKey, attributes: attributes) + + return treatments.mapValues { + ["treatment": $0.treatment, "config": $0.config] + } + } + private func track(matchingKey: String, bucketingKey: String? = nil, eventType: String, trafficType: String? = nil, value: Double? = nil, properties: [String: Any?]) -> Bool { guard let splitWrapper = getSplitWrapper() else { return false @@ -320,18 +392,4 @@ class DefaultSplitMethodParser: SplitMethodParser { return splitWrapper } - - private func getSplitViewAsMap(splitView: SplitView?) -> [String: Any?] { - if let splitView = splitView { - return [ - "name": splitView.name, - "trafficType": splitView.trafficType, - "killed": splitView.killed, - "treatments": splitView.treatments, - "changeNumber": splitView.changeNumber, - "configs": splitView.configs] - } else { - return [:] - } - } } diff --git a/splitio_ios/ios/Classes/SplitWrapper.swift b/splitio_ios/ios/Classes/SplitWrapper.swift index 924ed4b..b25f9d2 100644 --- a/splitio_ios/ios/Classes/SplitWrapper.swift +++ b/splitio_ios/ios/Classes/SplitWrapper.swift @@ -32,13 +32,13 @@ protocol EvaluationWrapper { func getTreatmentsWithConfig(matchingKey: String, splits: [String], bucketingKey: String?, attributes: [String: Any]?) -> [String: SplitResult] - func getTreatmentsByFlagSet(matchingKey: String, flagSet: String, bucketingKey: String?, attributes: [String: Any]?) -> [String: String]? + func getTreatmentsByFlagSet(matchingKey: String, flagSet: String, bucketingKey: String?, attributes: [String: Any]?) -> [String: String] - func getTreatmentsByFlagSets(matchingKey: String, flagSets: [String], bucketingKey: String?, attributes: [String: Any]?) -> [String: String]? + func getTreatmentsByFlagSets(matchingKey: String, flagSets: [String], bucketingKey: String?, attributes: [String: Any]?) -> [String: String] - func getTreatmentsWithConfigByFlagSet(matchingKey: String, flagSet: String, bucketingKey: String?, attributes: [String: Any]?) -> [String: SplitResult]? + func getTreatmentsWithConfigByFlagSet(matchingKey: String, flagSet: String, bucketingKey: String?, attributes: [String: Any]?) -> [String: SplitResult] - func getTreatmentsWithConfigByFlagSets(matchingKey: String, flagSets: [String], bucketingKey: String?, attributes: [String: Any]?) -> [String: SplitResult]? + func getTreatmentsWithConfigByFlagSets(matchingKey: String, flagSets: [String], bucketingKey: String?, attributes: [String: Any]?) -> [String: SplitResult] } protocol AttributesWrapper { @@ -129,33 +129,33 @@ class DefaultSplitWrapper: SplitWrapper { return client.getTreatmentsWithConfig(splits: splits, attributes: attributes) } - func getTreatmentsByFlagSet(matchingKey: String, flagSet: String, bucketingKey: String? = nil, attributes: [String: Any]? = [:]) -> [String: String]? { + func getTreatmentsByFlagSet(matchingKey: String, flagSet: String, bucketingKey: String? = nil, attributes: [String: Any]? = [:]) -> [String: String] { guard let client = getInitializedClient(matchingKey: matchingKey, bucketingKey: bucketingKey) else { - return nil + return [:] } return client.getTreatmentsByFlagSet(flagSet, attributes: attributes) } - func getTreatmentsByFlagSets(matchingKey: String, flagSets: [String], bucketingKey: String? = nil, attributes: [String: Any]? = [:]) -> [String: String]? { + func getTreatmentsByFlagSets(matchingKey: String, flagSets: [String], bucketingKey: String? = nil, attributes: [String: Any]? = [:]) -> [String: String] { guard let client = getInitializedClient(matchingKey: matchingKey, bucketingKey: bucketingKey) else { - return nil + return [:] } return client.getTreatmentsByFlagSets(flagSets, attributes: attributes) } - func getTreatmentsWithConfigByFlagSet(matchingKey: String, flagSet: String, bucketingKey: String? = nil, attributes: [String: Any]? = [:]) -> [String: SplitResult]? { + func getTreatmentsWithConfigByFlagSet(matchingKey: String, flagSet: String, bucketingKey: String? = nil, attributes: [String: Any]? = [:]) -> [String: SplitResult] { guard let client = getInitializedClient(matchingKey: matchingKey, bucketingKey: bucketingKey) else { - return nil + return [:] } return client.getTreatmentsWithConfigByFlagSet(flagSet, attributes: attributes) } - func getTreatmentsWithConfigByFlagSets(matchingKey: String, flagSets: [String], bucketingKey: String? = nil, attributes: [String: Any]? = [:]) -> [String: SplitResult]? { + func getTreatmentsWithConfigByFlagSets(matchingKey: String, flagSets: [String], bucketingKey: String? = nil, attributes: [String: Any]? = [:]) -> [String: SplitResult] { guard let client = getInitializedClient(matchingKey: matchingKey, bucketingKey: bucketingKey) else { - return nil + return [:] } return client.getTreatmentsWithConfigByFlagSets(flagSets, attributes: attributes) diff --git a/splitio_platform_interface/lib/split_view.dart b/splitio_platform_interface/lib/split_view.dart index 023ec0a..789daa1 100644 --- a/splitio_platform_interface/lib/split_view.dart +++ b/splitio_platform_interface/lib/split_view.dart @@ -24,6 +24,14 @@ class SplitView { mappedConfig.addAll({entry.key.toString(): entry.value.toString()}) }); + if (entry['treatments'] == null) { + entry['treatments'] = entry['treatments'] ?? []; + } + + if (entry['sets'] == null) { + entry['sets'] = []; + } + return SplitView( entry['name'], entry['trafficType'], @@ -32,7 +40,8 @@ class SplitView { entry['changeNumber'], mappedConfig, entry['defaultTreatment'] ?? '', - (entry['sets'] ?? [] as List).map((el) => el as String).toList()); + (entry['sets'] as List).map((el) => el as String).toList() + ); } @override From d1b1744171ae5e448c65f817ddc88b23e4eb7db0 Mon Sep 17 00:00:00 2001 From: Gaston Thea Date: Wed, 8 Nov 2023 15:36:49 -0300 Subject: [PATCH 2/3] Missing tests --- .../SplitTests/SplitMethodParserTests.swift | 69 ++++++++++++++++--- 1 file changed, 61 insertions(+), 8 deletions(-) diff --git a/splitio_ios/example/ios/SplitTests/SplitMethodParserTests.swift b/splitio_ios/example/ios/SplitTests/SplitMethodParserTests.swift index 61243b9..fd2c688 100644 --- a/splitio_ios/example/ios/SplitTests/SplitMethodParserTests.swift +++ b/splitio_ios/example/ios/SplitTests/SplitMethodParserTests.swift @@ -86,6 +86,59 @@ class SplitMethodParserTests: XCTestCase { } } + func testGetTreatmentsByFlagSet() { + methodParser?.onMethodCall(methodName: "getTreatmentsByFlagSet", arguments: ["matchingKey": "user-key", "bucketingKey": "bucketing-key", "flagSet": "set_1", "attributes": ["age": 50]], result: { (_: Any?) in + return + }) + + if let splitWrapper = (splitWrapper as? SplitWrapperStub) { + XCTAssert(splitWrapper.matchingKeyValue == "user-key") + XCTAssert(splitWrapper.bucketingKeyValue == "bucketing-key") + XCTAssert(splitWrapper.flagSetValue == "set_1") + print(splitWrapper.attributesValue) + XCTAssert(NSDictionary(dictionary: ["age": 50]).isEqual(to: splitWrapper.attributesValue!)) + } + } + + func testGetTreatmentsByFlagSets() { + methodParser?.onMethodCall(methodName: "getTreatmentsByFlagSets", arguments: ["matchingKey": "user-key", "bucketingKey": "bucketing-key", "flagSets": ["set_1", "set_2"], "attributes": ["age": 50]], result: { (_: Any?) in + return + }) + + if let splitWrapper = (splitWrapper as? SplitWrapperStub) { + XCTAssert(splitWrapper.matchingKeyValue == "user-key") + XCTAssert(splitWrapper.bucketingKeyValue == "bucketing-key") + XCTAssert(splitWrapper.flagSetsValue == ["set_1", "set_2"]) + XCTAssert(NSDictionary(dictionary: ["age": 50]).isEqual(to: splitWrapper.attributesValue!)) + } + } + + func testGetTreatmentsWithConfigByFlagSet() { + methodParser?.onMethodCall(methodName: "getTreatmentsWithConfigByFlagSet", arguments: ["matchingKey": "user-key", "bucketingKey": "bucketing-key", "flagSet": "set_1", "attributes": ["age": 50]], result: { (_: Any?) in + return + }) + + if let splitWrapper = (splitWrapper as? SplitWrapperStub) { + XCTAssert(splitWrapper.matchingKeyValue == "user-key") + XCTAssert(splitWrapper.bucketingKeyValue == "bucketing-key") + XCTAssert(splitWrapper.flagSetValue == "set_1") + XCTAssert(NSDictionary(dictionary: ["age": 50]).isEqual(to: splitWrapper.attributesValue!)) + } + } + + func testGetTreatmentsWithConfigByFlagSets() { + methodParser?.onMethodCall(methodName: "getTreatmentsWithConfigByFlagSets", arguments: ["matchingKey": "user-key", "bucketingKey": "bucketing-key", "flagSets": ["set_1", "set_2"], "attributes": ["age": 50]], result: { (_: Any?) in + return + }) + + if let splitWrapper = (splitWrapper as? SplitWrapperStub) { + XCTAssert(splitWrapper.matchingKeyValue == "user-key") + XCTAssert(splitWrapper.bucketingKeyValue == "bucketing-key") + XCTAssert(splitWrapper.flagSetsValue == ["set_1", "set_2"]) + XCTAssert(NSDictionary(dictionary: ["age": 50]).isEqual(to: splitWrapper.attributesValue!)) + } + } + func testTrackWithValue() { methodParser?.onMethodCall(methodName: "track", arguments: ["matchingKey": "user-key", "bucketingKey": "bucketing-key", "eventType": "my_event", "value": 25.20], result: { (_: Any?) in return @@ -391,38 +444,38 @@ class SplitWrapperStub: SplitWrapper { return result } - func getTreatmentsByFlagSet(matchingKey: String, flagSet: String, bucketingKey: String?, attributes: [String : Any]?) -> [String : String]? { + func getTreatmentsByFlagSet(matchingKey: String, flagSet: String, bucketingKey: String?, attributes: [String : Any]?) -> [String : String] { matchingKeyValue = matchingKey bucketingKeyValue = bucketingKey flagSetValue = flagSet - attributeValue = attributes + attributesValue = attributes return [:] } - func getTreatmentsByFlagSets(matchingKey: String, flagSets: [String], bucketingKey: String?, attributes: [String : Any]?) -> [String : String]? { + func getTreatmentsByFlagSets(matchingKey: String, flagSets: [String], bucketingKey: String?, attributes: [String : Any]?) -> [String : String] { matchingKeyValue = matchingKey bucketingKeyValue = bucketingKey flagSetsValue = flagSets - attributeValue = attributes + attributesValue = attributes return [:] } - func getTreatmentsWithConfigByFlagSet(matchingKey: String, flagSet: String, bucketingKey: String?, attributes: [String : Any]?) -> [String : SplitResult]? { + func getTreatmentsWithConfigByFlagSet(matchingKey: String, flagSet: String, bucketingKey: String?, attributes: [String : Any]?) -> [String : SplitResult] { matchingKeyValue = matchingKey bucketingKeyValue = bucketingKey flagSetValue = flagSet - attributeValue = attributes + attributesValue = attributes return [:] } - func getTreatmentsWithConfigByFlagSets(matchingKey: String, flagSets: [String], bucketingKey: String?, attributes: [String : Any]?) -> [String : SplitResult]? { + func getTreatmentsWithConfigByFlagSets(matchingKey: String, flagSets: [String], bucketingKey: String?, attributes: [String : Any]?) -> [String : SplitResult] { matchingKeyValue = matchingKey bucketingKeyValue = bucketingKey flagSetsValue = flagSets - attributeValue = attributes + attributesValue = attributes return [:] } From d23fd6a2227e3e6750c7535579aafcfd3f5d5360 Mon Sep 17 00:00:00 2001 From: Gaston Thea Date: Wed, 8 Nov 2023 16:12:46 -0300 Subject: [PATCH 3/3] Retrigger checks