Skip to content

Commit 1e984d6

Browse files
authored
Featureflag client (#214)
* add feature flags on client * unit tests for feature flags * remove unneeded line and add missed nullability to countAggregator.h file * add tests for parsing counters and feature flags * break down tests for isFeatureFlagEnabled * add should parse counters and feature flags tests * add types to Set and Dict declarations
1 parent c7b07d6 commit 1e984d6

File tree

12 files changed

+200
-33
lines changed

12 files changed

+200
-33
lines changed

Example/Leanplum-SDK.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; };
8888
6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; };
8989
6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5B8195388D20070C39A /* InfoPlist.strings */; };
90+
653192A121517D4F00D7DDDC /* LPFeatureFlagManagerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 653192A021517D4F00D7DDDC /* LPFeatureFlagManagerTest.m */; };
9091
65E53E982148786C00A05040 /* LPCountAggregatorTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 65E53E962148786C00A05040 /* LPCountAggregatorTest.m */; };
9192
873B8AEB1B1F5CCA007FD442 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */; };
9293
9CB691DE1F15FFF5002D83D8 /* batch_response.json in Resources */ = {isa = PBXBuildFile; fileRef = 9CB691DD1F15FFF5002D83D8 /* batch_response.json */; };
@@ -187,6 +188,7 @@
187188
6003F5B7195388D20070C39A /* Tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Tests-Info.plist"; sourceTree = "<group>"; };
188189
6003F5B9195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
189190
606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Tests-Prefix.pch"; sourceTree = "<group>"; };
191+
653192A021517D4F00D7DDDC /* LPFeatureFlagManagerTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LPFeatureFlagManagerTest.m; sourceTree = "<group>"; };
190192
65E53E962148786C00A05040 /* LPCountAggregatorTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LPCountAggregatorTest.m; sourceTree = "<group>"; };
191193
73B565AA61D6B6A4E92607C4 /* Pods-Leanplum-SDK_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Leanplum-SDK_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-Leanplum-SDK_Tests/Pods-Leanplum-SDK_Tests.release.xcconfig"; sourceTree = "<group>"; };
192194
74C2EA3F2D53CAE77A03BFFA /* Pods-Leanplum-tvOS-SDK_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Leanplum-tvOS-SDK_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-Leanplum-tvOS-SDK_Example/Pods-Leanplum-tvOS-SDK_Example.release.xcconfig"; sourceTree = "<group>"; };
@@ -256,6 +258,7 @@
256258
07E5C86E1F052B7800A4B092 /* ExceptionsTest.m */,
257259
9CB691E01F1601BA002D83D8 /* LPEventCallbackManagerTest.m */,
258260
65E53E962148786C00A05040 /* LPCountAggregatorTest.m */,
261+
653192A021517D4F00D7DDDC /* LPFeatureFlagManagerTest.m */,
259262
07E5C86F1F052B7800A4B092 /* Extensions */,
260263
07E5C87B1F052B7800A4B092 /* LPFileManagerTest.m */,
261264
07E5C87E1F052B7800A4B092 /* LeanplumTest.m */,
@@ -826,6 +829,7 @@
826829
07E5C8AC1F052B7800A4B092 /* LPAppIconManagerTest.m in Sources */,
827830
07E5C8BA1F052B7800A4B092 /* NewsfeedTest.m in Sources */,
828831
07E5C8AB1F052B7800A4B092 /* LPActionManagerTest.m in Sources */,
832+
653192A121517D4F00D7DDDC /* LPFeatureFlagManagerTest.m in Sources */,
829833
07E5C8B71F052B7800A4B092 /* LPJSONTest.m in Sources */,
830834
07E5C8AF1F052B7800A4B092 /* LeanplumReachability+Category.m in Sources */,
831835
9CB691E11F1601BA002D83D8 /* LPEventCallbackManagerTest.m in Sources */,

Example/Tests/Classes/LPCountAggregatorTest.m

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@
3232
*/
3333
@interface LPCountAggregator(UnitTest)
3434

35-
@property (nonatomic, strong) NSMutableDictionary *counts;
35+
@property (nonatomic, strong) NSMutableDictionary<NSString *, NSNumber *> *counts;
3636

37-
- (NSDictionary *)getAndClearCounts;
38-
- (NSMutableDictionary *)makeParams:(nonnull NSString *)name withCount:(int) count;
37+
- (NSDictionary<NSString *, NSNumber *> *)getAndClearCounts;
38+
- (NSMutableDictionary<NSString *, id> *)makeParams:(nonnull NSString *)name withCount:(int) count;
3939

4040
@end
4141

@@ -109,7 +109,7 @@ - (void)test_getAndClearCounts {
109109
[countAggregator incrementCount:testString by:2];
110110
[countAggregator incrementCount:testString2 by:15];
111111

112-
NSDictionary *previousCounts = [countAggregator getAndClearCounts];
112+
NSDictionary<NSString *, NSNumber *> *previousCounts = [countAggregator getAndClearCounts];
113113

114114
//test counts is empty after clearing
115115
XCTAssert([countAggregator.counts count] == 0);
@@ -121,7 +121,7 @@ - (void)test_getAndClearCounts {
121121
- (void)test_makeParams {
122122
LPCountAggregator *countAggregator = [[LPCountAggregator alloc] init];
123123
NSString *testString = @"test";
124-
NSMutableDictionary *params = [countAggregator makeParams:testString withCount:2];
124+
NSMutableDictionary<NSString *, id> *params = [countAggregator makeParams:testString withCount:2];
125125

126126
XCTAssert([params[LP_PARAM_TYPE] isEqualToString:LP_VALUE_SDK_COUNT]);
127127
XCTAssert([params[LP_PARAM_MESSAGE] isEqualToString:testString]);
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//
2+
// LPFeatureFlagsManagerTest.m
3+
// Leanplum-SDK_Tests
4+
//
5+
// Created by Grace on 9/18/18.
6+
// Copyright © 2018 Leanplum. All rights reserved.
7+
//
8+
9+
#import <XCTest/XCTest.h>
10+
#import "LPFeatureFlagManager.h"
11+
#import "Constants.h"
12+
13+
@interface LPFeatureFlagManagerTest : XCTestCase
14+
15+
@end
16+
17+
@implementation LPFeatureFlagManagerTest
18+
19+
- (void)setUp {
20+
[super setUp];
21+
}
22+
23+
- (void)tearDown {
24+
[super tearDown];
25+
}
26+
27+
- (void)test_isFeatureFlagEnabledShouldBeTrueForEnabledFlag {
28+
LPFeatureFlagManager *featureFlagManager = [[LPFeatureFlagManager alloc] init];
29+
NSString *testString = @"test";
30+
featureFlagManager.enabledFeatureFlags = [NSSet setWithObjects:testString, nil];
31+
XCTAssert([featureFlagManager isFeatureFlagEnabled:testString] == true);
32+
}
33+
34+
- (void)test_isFeatureFlagEnabledShouldBeFalseForDisabledFlag {
35+
LPFeatureFlagManager *featureFlagManager = [[LPFeatureFlagManager alloc] init];
36+
NSString *testString = @"test";
37+
XCTAssert([featureFlagManager isFeatureFlagEnabled:testString] == false);
38+
}
39+
40+
- (void)test_isFeatureFlagEnabledShouldResetWhenSetToNil {
41+
LPFeatureFlagManager *featureFlagManager = [[LPFeatureFlagManager alloc] init];
42+
NSString *testString = @"test";
43+
featureFlagManager.enabledFeatureFlags = [NSSet setWithObjects:testString, nil];
44+
XCTAssert([featureFlagManager isFeatureFlagEnabled:testString] == true);
45+
featureFlagManager.enabledFeatureFlags = nil;
46+
XCTAssert([featureFlagManager isFeatureFlagEnabled:testString] == false);
47+
}
48+
49+
@end

Example/Tests/Classes/LeanplumTest.m

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
#import "LeanplumReachability+Category.h"
3333
#import "Leanplum+Extensions.h"
3434
#import "LPActionManager.h"
35+
#import "LPCountaggregator.h"
36+
#import "LPFeatureFlagManager.h"
3537
#import "Constants.h"
3638
#import "LPRegisterDevice.h"
3739

@@ -40,6 +42,13 @@
4042
* and validate whether sdk properly parses the response and calls appropriate methods
4143
* the test all verifies whether request is properly packed with all necessary data.
4244
*/
45+
@interface Leanplum (Test)
46+
47+
+ (NSSet<NSString *> *)parseEnabledCountersFromResponse:(NSDictionary *)response;
48+
+ (NSSet<NSString *> *)parseEnabledFeatureFlagsFromResponse:(NSDictionary *)response;
49+
50+
@end
51+
4352
@interface LeanplumTest : XCTestCase
4453

4554
@end
@@ -1673,6 +1682,86 @@ - (void)test_configuration
16731682
XCTAssertEqual([LPConstantsState sharedState].networkTimeoutSecondsForDownloads, timeout);
16741683
}
16751684

1685+
- (void)testStartResponseShouldParseCounters
1686+
{
1687+
//Given: start request
1688+
// This stub have to be removed when start command is successfully executed.
1689+
id<OHHTTPStubsDescriptor> startStub = [OHHTTPStubs stubRequestsPassingTest:
1690+
^BOOL(NSURLRequest * _Nonnull request) {
1691+
return [request.URL.host isEqualToString:API_HOST];
1692+
} withStubResponse:^OHHTTPStubsResponse * _Nonnull(NSURLRequest * _Nonnull request) {
1693+
NSString* response_file = OHPathForFile(@"simple_start_response.json", self.class);
1694+
return [OHHTTPStubsResponse responseWithFileAtPath:response_file statusCode:200
1695+
headers:@{@"Content-Type":@"application/json"}];
1696+
}];
1697+
1698+
[LeanplumHelper setup_development_test];
1699+
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
1700+
[Leanplum startWithResponseHandler:^(BOOL success) {
1701+
XCTAssertTrue(success);
1702+
[OHHTTPStubs removeStub:startStub];
1703+
// Then: enabledCounters should be parsed
1704+
XCTAssertNotNil([[LPCountAggregator sharedAggregator] enabledCounters]);
1705+
NSSet *enabledCounters = [[LPCountAggregator sharedAggregator] enabledCounters];
1706+
NSSet *expected = [NSSet setWithArray:@[@"testCounter1", @"testCounter2"]];
1707+
XCTAssertEqualObjects(expected, enabledCounters);
1708+
1709+
dispatch_semaphore_signal(semaphore);
1710+
}];
1711+
dispatch_semaphore_wait(semaphore, [LeanplumHelper default_dispatch_time]);
1712+
}
1713+
1714+
- (void)testStartResponseShouldParseFeatureFlags
1715+
{
1716+
//Given: start request
1717+
// This stub have to be removed when start command is successfully executed.
1718+
id<OHHTTPStubsDescriptor> startStub = [OHHTTPStubs stubRequestsPassingTest:
1719+
^BOOL(NSURLRequest * _Nonnull request) {
1720+
return [request.URL.host isEqualToString:API_HOST];
1721+
} withStubResponse:^OHHTTPStubsResponse * _Nonnull(NSURLRequest * _Nonnull request) {
1722+
NSString* response_file = OHPathForFile(@"simple_start_response.json", self.class);
1723+
return [OHHTTPStubsResponse responseWithFileAtPath:response_file statusCode:200
1724+
headers:@{@"Content-Type":@"application/json"}];
1725+
}];
1726+
1727+
[LeanplumHelper setup_development_test];
1728+
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
1729+
[Leanplum startWithResponseHandler:^(BOOL success) {
1730+
XCTAssertTrue(success);
1731+
[OHHTTPStubs removeStub:startStub];
1732+
// Then: enabledFeatureFlags should be parsed
1733+
XCTAssertNotNil([[LPFeatureFlagManager sharedManager] enabledFeatureFlags]);
1734+
NSSet<NSString *> *enabledFeatureFlags = [[LPFeatureFlagManager sharedManager] enabledFeatureFlags];
1735+
NSSet<NSString *> *expected = [NSSet setWithArray:@[@"testFeatureFlag1", @"testFeatureFlag2"]];
1736+
XCTAssertEqualObjects(expected, enabledFeatureFlags);
1737+
1738+
dispatch_semaphore_signal(semaphore);
1739+
}];
1740+
dispatch_semaphore_wait(semaphore, [LeanplumHelper default_dispatch_time]);
1741+
}
1742+
1743+
- (void)test_parseEnabledCounters
1744+
{
1745+
NSMutableDictionary *response = [[NSMutableDictionary alloc] init];
1746+
NSSet<NSString *> *enabledCounters = [Leanplum parseEnabledCountersFromResponse:response];
1747+
XCTAssertNil(enabledCounters);
1748+
1749+
[response setObject:@[@"test"] forKey:LP_KEY_ENABLED_COUNTERS];
1750+
enabledCounters = [Leanplum parseEnabledCountersFromResponse:response];
1751+
XCTAssertEqualObjects([NSSet setWithArray:@[@"test"]], enabledCounters);
1752+
}
1753+
1754+
- (void)test_parseEnabledFeatureFlags
1755+
{
1756+
NSMutableDictionary *response = [[NSMutableDictionary alloc] init];
1757+
NSSet<NSString *> *enabledFeatureFlags = [Leanplum parseEnabledFeatureFlagsFromResponse:response];
1758+
XCTAssertNil(enabledFeatureFlags);
1759+
1760+
[response setObject:@[@"test"] forKey:LP_KEY_ENABLED_FEATURE_FLAGS];
1761+
enabledFeatureFlags = [Leanplum parseEnabledFeatureFlagsFromResponse:response];
1762+
XCTAssertEqualObjects([NSSet setWithArray:@[@"test"]], enabledFeatureFlags);
1763+
}
1764+
16761765
#pragma mark - Selectors
16771766

16781767
/**

Example/Tests/Resources/Responses/simple_start_response.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,14 @@
243243
"token": "beIU7isQQsCFFkd4R1e6l4ODGfBfKEJLiHQ6ZRPUfOY",
244244
"variants": [
245245

246+
],
247+
"enabledSdkCounters": [
248+
"testCounter1",
249+
"testCounter2"
250+
],
251+
"enabledFeatureFlags": [
252+
"testFeatureFlag1",
253+
"testFeatureFlag2"
246254
],
247255
"syncNewsfeed": false,
248256
"success": true,
@@ -494,6 +502,14 @@
494502
"token": "SXUUsSC6Qsee4ICToRvH5zUuQur8GUQvk9yf5PLhjq8",
495503
"variants": [
496504

505+
],
506+
"enabledSdkCounters": [
507+
"testCounter1",
508+
"testCounter2"
509+
],
510+
"enabledFeatureFlags": [
511+
"testFeatureFlag1",
512+
"testFeatureFlag2"
497513
],
498514
"syncNewsfeed": false,
499515
"success": true,
@@ -745,6 +761,14 @@
745761
"token": "juKUmiXERlO4kmTfEL6xEsfUMpg9WUlFrHOvp6H2w4Q",
746762
"variants": [
747763

764+
],
765+
"enabledSdkCounters": [
766+
"testCounter1",
767+
"testCounter2"
768+
],
769+
"enabledFeatureFlags": [
770+
"testFeatureFlag1",
771+
"testFeatureFlag2"
748772
],
749773
"syncNewsfeed": false,
750774
"success": true,

Leanplum-SDK/Classes/Internal/Constants.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ OBJC_EXPORT NSString *LP_KEY_INBOX_MESSAGES;
253253
OBJC_EXPORT NSString *LP_KEY_UNREAD_COUNT;
254254
OBJC_EXPORT NSString *LP_KEY_VARIANT_DEBUG_INFO;
255255
OBJC_EXPORT NSString *LP_KEY_ENABLED_COUNTERS;
256+
OBJC_EXPORT NSString *LP_KEY_ENABLED_FEATURE_FLAGS;
256257
OBJC_EXPORT NSString *LP_KEY_SYNC_INBOX;
257258
OBJC_EXPORT NSString *LP_KEY_LOGGING_ENABLED;
258259
OBJC_EXPORT NSString *LP_KEY_MESSAGE_DATA;

Leanplum-SDK/Classes/Internal/Constants.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ - (id)init {
187187
NSString *LP_KEY_VARIANTS = @"variants";
188188
NSString *LP_KEY_VARIANT_DEBUG_INFO = @"variantDebugInfo";
189189
NSString *LP_KEY_ENABLED_COUNTERS = @"enabledSdkCounters";
190+
NSString *LP_KEY_ENABLED_FEATURE_FLAGS = @"enabledFeatureFlags";
190191
NSString *LP_KEY_INBOX_MESSAGES = @"newsfeedMessages";
191192
NSString *LP_KEY_UNREAD_COUNT = @"unreadCount";
192193
NSString *LP_KEY_SYNC_INBOX = @"syncNewsfeed";

Leanplum-SDK/Classes/Internal/FeatureFlag/LPFeatureFlagManager.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@
1010

1111
@interface LPFeatureFlagManager : NSObject
1212

13+
@property (nonatomic, strong) NSSet<NSString *> * _Nullable enabledFeatureFlags;
14+
1315
+ (_Nonnull instancetype)sharedManager;
1416

15-
-(void)refreshEnabledFeatureFlags:(nullable NSArray<NSString *> *)featureFlags;
16-
-(BOOL)isFeatureFlagEnabled:(nonnull NSString *)featureFlagName;
17+
- (BOOL)isFeatureFlagEnabled:(nonnull NSString *)featureFlagName;
1718

1819
@end

Leanplum-SDK/Classes/Internal/FeatureFlag/LPFeatureFlagManager.m

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,6 @@
77

88
#import "LPFeatureFlagManager.h"
99

10-
@interface LPFeatureFlagManager()
11-
12-
@property (strong, nonatomic) NSSet *enabledFeatureFlags;
13-
14-
@end
15-
1610
@implementation LPFeatureFlagManager
1711

1812
static LPFeatureFlagManager *sharedFeatureFlagManager = nil;
@@ -25,13 +19,7 @@ + (instancetype)sharedManager {
2519
return sharedFeatureFlagManager;
2620
}
2721

28-
-(void)refreshEnabledFeatureFlags:(nullable NSArray<NSString *> *)featureFlags {
29-
if (featureFlags != nil) {
30-
self.enabledFeatureFlags = [NSSet setWithArray:featureFlags];
31-
}
32-
}
33-
34-
-(BOOL)isFeatureFlagEnabled:(nonnull NSString *)featureFlagName {
22+
- (BOOL)isFeatureFlagEnabled:(nonnull NSString *)featureFlagName {
3523
return [self.enabledFeatureFlags containsObject:featureFlagName];
3624
}
3725

Leanplum-SDK/Classes/Internal/Leanplum.m

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -878,8 +878,10 @@ + (void)startWithUserId:(NSString *)userId
878878
NSDictionary *regions = response[LP_KEY_REGIONS];
879879
NSDictionary *variantDebugInfo = [self parseVariantDebugInfoFromResponse:response];
880880
[[LPVarCache sharedCache] setVariantDebugInfo:variantDebugInfo];
881-
NSSet *enabledCounters = [self parseEnabledCountersFromResponse:response];
881+
NSSet<NSString *> *enabledCounters = [self parseEnabledCountersFromResponse:response];
882882
[LPCountAggregator sharedAggregator].enabledCounters = enabledCounters;
883+
NSSet<NSString *> *enabledFeatureFlags = [self parseEnabledFeatureFlagsFromResponse:response];
884+
[LPFeatureFlagManager sharedManager].enabledFeatureFlags = enabledFeatureFlags;
883885

884886
[[LPAPIConfig sharedConfig] setToken:token];
885887
[[LPAPIConfig sharedConfig] saveToken];
@@ -2662,12 +2664,20 @@ + (NSDictionary *)parseVariantDebugInfoFromResponse:(NSDictionary *)response
26622664
return nil;
26632665
}
26642666

2665-
+ (NSSet *)parseEnabledCountersFromResponse:(NSDictionary *)response
2667+
+ (NSSet<NSString *> *)parseEnabledCountersFromResponse:(NSDictionary *)response
26662668
{
26672669
if ([response objectForKey:LP_KEY_ENABLED_COUNTERS]) {
26682670
return [NSSet setWithArray:response[LP_KEY_ENABLED_COUNTERS]];
26692671
}
26702672
return nil;
26712673
}
26722674

2675+
+ (NSSet<NSString *> *)parseEnabledFeatureFlagsFromResponse:(NSDictionary *)response
2676+
{
2677+
if ([response objectForKey:LP_KEY_ENABLED_FEATURE_FLAGS]) {
2678+
return [NSSet setWithArray:response[LP_KEY_ENABLED_FEATURE_FLAGS]];
2679+
}
2680+
return nil;
2681+
}
2682+
26732683
@end

0 commit comments

Comments
 (0)