Skip to content

Commit 4ed034a

Browse files
feat: support feature flags with variants (#1230)
Jira ID: MOB-14684 --------- Co-authored-by: Ahmed Elrefaey <[email protected]>
1 parent 5fcd6c1 commit 4ed034a

File tree

9 files changed

+91
-212
lines changed

9 files changed

+91
-212
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,13 @@
44

55
### Added
66

7+
- Add support for Feature Flags APIs `Instabug.addFeatureFlags`, `Instabug.removeFeatureFlags` and `Instabug.clearAllFeatureFlags` ([#1230](https://github.com/Instabug/Instabug-React-Native/pull/1230)).
78
- Export `uploadSourcemaps` and `uploadSoFiles` utilities in the `instabug-reactnative/upload` sub-package for usage in custom Node.js upload scripts ([#1252](https://github.com/Instabug/Instabug-React-Native/pull/1252)).
89

10+
### Deprecated
11+
12+
- Deprecate Experiments APIs `Instabug.addExperiments`, `Instabug.removeExperiments` and `Instabug.clearAllExperiments` in favor of the new Feature Flags APIs ([#1230](https://github.com/Instabug/Instabug-React-Native/pull/1230)).
13+
914
### Fixed
1015

1116
- Fix APM network logging on Android ([#1253](https://github.com/Instabug/Instabug-React-Native/pull/1253)).

android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java

Lines changed: 1 addition & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import android.util.Log;
99
import android.view.View;
1010

11-
import androidx.annotation.NonNull;
1211
import androidx.annotation.UiThread;
1312

1413
import com.facebook.react.bridge.Arguments;
@@ -23,8 +22,6 @@
2322
import com.facebook.react.bridge.WritableNativeArray;
2423
import com.facebook.react.bridge.WritableNativeMap;
2524
import com.facebook.react.uimanager.UIManagerModule;
26-
import com.instabug.apm.InternalAPM;
27-
import com.instabug.apm.configuration.cp.APMFeature;
2825
import com.instabug.library.Feature;
2926
import com.instabug.library.Instabug;
3027
import com.instabug.library.InstabugColorTheme;
@@ -33,10 +30,6 @@
3330
import com.instabug.library.LogLevel;
3431
import com.instabug.library.ReproConfigurations;
3532
import com.instabug.library.core.InstabugCore;
36-
import com.instabug.library.internal.crossplatform.CoreFeature;
37-
import com.instabug.library.internal.crossplatform.CoreFeaturesState;
38-
import com.instabug.library.internal.crossplatform.FeaturesStateListener;
39-
import com.instabug.library.internal.crossplatform.InternalCore;
4033
import com.instabug.library.featuresflags.model.IBGFeatureFlag;
4134
import com.instabug.library.internal.module.InstabugLocale;
4235
import com.instabug.library.invocation.InstabugInvocationEvent;
@@ -1035,7 +1028,7 @@ public void run() {
10351028
}
10361029

10371030
/**
1038-
* @deprecated see @link #addFeatureFlags(ReadableArray)
1031+
* @deprecated see {@link #addFeatureFlags(ReadableArray)}
10391032
*/
10401033
@ReactMethod
10411034
public void addExperiments(final ReadableArray experiments) {
@@ -1155,105 +1148,6 @@ public void run() {
11551148
}
11561149
});
11571150
}
1158-
/**
1159-
* Register a listener for W3C flags value change
1160-
*/
1161-
@ReactMethod
1162-
public void registerW3CFlagsChangeListener(){
1163-
1164-
MainThreadHandler.runOnMainThread(new Runnable() {
1165-
@Override
1166-
public void run() {
1167-
try {
1168-
InternalCore.INSTANCE._setFeaturesStateListener(new FeaturesStateListener() {
1169-
@Override
1170-
public void invoke(@NonNull CoreFeaturesState featuresState) {
1171-
WritableMap params = Arguments.createMap();
1172-
params.putBoolean("isW3ExternalTraceIDEnabled", featuresState.isW3CExternalTraceIdEnabled());
1173-
params.putBoolean("isW3ExternalGeneratedHeaderEnabled", featuresState.isAttachingGeneratedHeaderEnabled());
1174-
params.putBoolean("isW3CaughtHeaderEnabled", featuresState.isAttachingCapturedHeaderEnabled());
1175-
1176-
sendEvent(Constants.IBG_ON_NEW_W3C_FLAGS_UPDATE_RECEIVED_CALLBACK, params);
1177-
}
1178-
});
1179-
}
1180-
catch (Exception e) {
1181-
e.printStackTrace();
1182-
}
1183-
1184-
}
1185-
1186-
});
1187-
}
1188-
1189-
1190-
/**
1191-
* Get first time Value of W3ExternalTraceID flag
1192-
*/
1193-
@ReactMethod
1194-
public void isW3ExternalTraceIDEnabled(Promise promise){
1195-
1196-
MainThreadHandler.runOnMainThread(new Runnable() {
1197-
@Override
1198-
public void run() {
1199-
try {
1200-
promise.resolve(InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_EXTERNAL_TRACE_ID));
1201-
}
1202-
catch (Exception e) {
1203-
e.printStackTrace();
1204-
promise.resolve(null);
1205-
}
1206-
1207-
}
1208-
1209-
});
1210-
}
1211-
1212-
1213-
/**
1214-
* Get first time Value of W3ExternalGeneratedHeader flag
1215-
*/
1216-
@ReactMethod
1217-
public void isW3ExternalGeneratedHeaderEnabled(Promise promise){
1218-
1219-
MainThreadHandler.runOnMainThread(new Runnable() {
1220-
@Override
1221-
public void run() {
1222-
try {
1223-
promise.resolve(InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_ATTACHING_GENERATED_HEADER));
1224-
}
1225-
catch (Exception e) {
1226-
e.printStackTrace();
1227-
promise.resolve(null);
1228-
}
1229-
1230-
}
1231-
1232-
});
1233-
}
1234-
1235-
/**
1236-
* Get first time Value of W3CaughtHeader flag
1237-
*/
1238-
@ReactMethod
1239-
public void isW3CaughtHeaderEnabled(Promise promise){
1240-
1241-
MainThreadHandler.runOnMainThread(new Runnable() {
1242-
@Override
1243-
public void run() {
1244-
try {
1245-
promise.resolve(InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_ATTACHING_CAPTURED_HEADER));
1246-
}
1247-
catch (Exception e) {
1248-
e.printStackTrace();
1249-
promise.resolve(null);
1250-
}
1251-
1252-
}
1253-
1254-
});
1255-
}
1256-
12571151

12581152
/**
12591153
* Map between the exported JS constant and the arg key in {@link ArgsRegistry}.

android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818
import com.instabug.library.IssueType;
1919
import com.instabug.library.ReproConfigurations;
2020
import com.instabug.library.ReproMode;
21-
import com.instabug.library.internal.crossplatform.CoreFeature;
22-
import com.instabug.library.internal.crossplatform.InternalCore;
2321
import com.instabug.library.featuresflags.model.IBGFeatureFlag;
2422
import com.instabug.library.internal.module.InstabugLocale;
2523
import com.instabug.library.ui.onboarding.WelcomeMessage;
@@ -637,28 +635,4 @@ public void testWillRedirectToStore() {
637635
// then
638636
mockInstabug.verify(() -> Instabug.willRedirectToStore());
639637
}
640-
@Test
641-
public void testW3CExternalTraceIDFlag(){
642-
Promise promise = mock(Promise.class);
643-
InternalCore internalAPM = mock(InternalCore.class);
644-
rnModule.isW3ExternalTraceIDEnabled(promise);
645-
boolean expected=internalAPM._isFeatureEnabled(CoreFeature.W3C_EXTERNAL_TRACE_ID);
646-
verify(promise).resolve(expected);
647-
}
648-
@Test
649-
public void testW3CExternalGeneratedHeaderFlag(){
650-
Promise promise = mock(Promise.class);
651-
InternalCore internalAPM = mock(InternalCore.class);
652-
rnModule.isW3ExternalGeneratedHeaderEnabled(promise);
653-
boolean expected=internalAPM._isFeatureEnabled(CoreFeature.W3C_ATTACHING_GENERATED_HEADER);
654-
verify(promise).resolve(expected);
655-
}
656-
@Test
657-
public void testW3CCaughtHeaderFlag(){
658-
Promise promise = mock(Promise.class);
659-
InternalCore internalAPM = mock(InternalCore.class);
660-
rnModule.isW3CaughtHeaderEnabled(promise);
661-
boolean expected=internalAPM._isFeatureEnabled(CoreFeature.W3C_ATTACHING_CAPTURED_HEADER);
662-
verify(promise).resolve(expected);
663-
}
664638
}

examples/default/ios/InstabugTests/InstabugSampleTests.m

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ - (void)testInit {
7373
NSArray *invocationEvents = [NSArray arrayWithObjects:[NSNumber numberWithInteger:floatingButtonInvocationEvent], nil];
7474
BOOL useNativeNetworkInterception = YES;
7575
IBGSDKDebugLogsLevel sdkDebugLogsLevel = IBGSDKDebugLogsLevelDebug;
76-
76+
7777
OCMStub([mock setCodePushVersion:codePushVersion]);
7878

7979
[self.instabugBridge init:appToken invocationEvents:invocationEvents debugLogsLevel:sdkDebugLogsLevel useNativeNetworkInterception:useNativeNetworkInterception codePushVersion:codePushVersion];
@@ -85,9 +85,9 @@ - (void)testInit {
8585
- (void)testSetCodePushVersion {
8686
id mock = OCMClassMock([Instabug class]);
8787
NSString *codePushVersion = @"123";
88-
88+
8989
[self.instabugBridge setCodePushVersion:codePushVersion];
90-
90+
9191
OCMVerify([mock setCodePushVersion:codePushVersion]);
9292
}
9393

@@ -498,4 +498,43 @@ - (void)testClearAllExperiments {
498498
OCMVerify([mock clearAllExperiments]);
499499
}
500500

501+
- (void)testAddFeatureFlags {
502+
id mock = OCMClassMock([Instabug class]);
503+
NSDictionary *featureFlagsMap = @{ @"key13" : @"value1", @"key2" : @"value2"};
504+
505+
OCMStub([mock addFeatureFlags :[OCMArg any]]);
506+
[self.instabugBridge addFeatureFlags:featureFlagsMap];
507+
OCMVerify([mock addFeatureFlags: [OCMArg checkWithBlock:^(id value) {
508+
NSArray<IBGFeatureFlag *> *featureFlags = value;
509+
NSString* firstFeatureFlagName = [featureFlags objectAtIndex:0 ].name;
510+
NSString* firstFeatureFlagKey = [[featureFlagsMap allKeys] objectAtIndex:0] ;
511+
if([ firstFeatureFlagKey isEqualToString: firstFeatureFlagName]){
512+
return YES;
513+
}
514+
return NO;
515+
}]]);
516+
}
517+
518+
- (void)testRemoveFeatureFlags {
519+
id mock = OCMClassMock([Instabug class]);
520+
NSArray *featureFlags = @[@"exp1", @"exp2"];
521+
[self.instabugBridge removeFeatureFlags:featureFlags];
522+
OCMVerify([mock removeFeatureFlags: [OCMArg checkWithBlock:^(id value) {
523+
NSArray<IBGFeatureFlag *> *featureFlagsObJ = value;
524+
NSString* firstFeatureFlagName = [featureFlagsObJ objectAtIndex:0 ].name;
525+
NSString* firstFeatureFlagKey = [featureFlags firstObject] ;
526+
if([ firstFeatureFlagKey isEqualToString: firstFeatureFlagName]){
527+
return YES;
528+
}
529+
return NO;
530+
}]]);
531+
}
532+
533+
- (void)testRemoveAllFeatureFlags {
534+
id mock = OCMClassMock([Instabug class]);
535+
OCMStub([mock removeAllFeatureFlags]);
536+
[self.instabugBridge removeAllFeatureFlags];
537+
OCMVerify([mock removeAllFeatureFlags]);
538+
}
539+
501540
@end

ios/RNInstabug/InstabugReactBridge.h

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#import <Instabug/Instabug.h>
1313
#import <Instabug/IBGBugReporting.h>
1414
#import <Instabug/IBGCrashReporting.h>
15+
#import <Instabug/IBGSurveys.h>
1516
#import <Instabug/IBGLog.h>
1617
#import <Instabug/IBGTypes.h>
1718
#import "ArgsRegistry.h"
@@ -105,26 +106,6 @@
105106
*/
106107

107108
- (void)setNetworkLoggingEnabled:(BOOL)isEnabled;
108-
- (void)isW3ExternalTraceIDEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject;
109-
- (void)isW3ExternalGeneratedHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject;
110-
- (void)isW3CaughtHeaderEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject;
111-
- (void)networkLogIOS:(NSString * _Nonnull)url
112-
method:(NSString * _Nonnull)method
113-
requestBody:(NSString * _Nonnull)requestBody
114-
requestBodySize:(double)requestBodySize
115-
responseBody:(NSString * _Nonnull)responseBody
116-
responseBodySize:(double)responseBodySize
117-
responseCode:(double)responseCode
118-
requestHeaders:(NSDictionary * _Nonnull)requestHeaders
119-
responseHeaders:(NSDictionary * _Nonnull)responseHeaders
120-
contentType:(NSString * _Nonnull)contentType
121-
errorDomain:(NSString * _Nullable)errorDomain
122-
errorCode:(double)errorCode
123-
startTime:(double)startTime
124-
duration:(double)duration
125-
gqlQueryName:(NSString * _Nullable)gqlQueryName
126-
serverErrorMessage:(NSString * _Nullable)serverErrorMessage
127-
w3cExternalTraceAttributes:(NSDictionary * _Nullable)w3cExternalTraceAttributes;
128109

129110
- (void)networkLogIOS:(NSString * _Nonnull)url
130111
method:(NSString * _Nonnull)method
@@ -152,7 +133,6 @@ w3cExternalTraceAttributes:(NSDictionary * _Nullable)w3cExternalTraceAttributes;
152133
- (void)addExperiments:(NSArray *)experiments;
153134
- (void)removeExperiments:(NSArray *)experiments;
154135
- (void)clearAllExperiments;
155-
156136
- (void)addFeatureFlags:(NSDictionary *)featureFlagsMap;
157137
- (void)removeFeatureFlags:(NSArray *)featureFlags;
158138
- (void)removeAllFeatureFlags;

ios/RNInstabug/InstabugReactBridge.m

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,38 @@ - (dispatch_queue_t)methodQueue {
355355
[Instabug clearAllExperiments];
356356
}
357357

358+
RCT_EXPORT_METHOD(addFeatureFlags:(NSDictionary *)featureFlagsMap) {
359+
NSMutableArray<IBGFeatureFlag *> *featureFlags = [NSMutableArray array];
360+
for(id key in featureFlagsMap){
361+
NSString* variant =[featureFlagsMap objectForKey:key];
362+
if ([variant length]==0) {
363+
[featureFlags addObject:[[IBGFeatureFlag alloc] initWithName:key]];
364+
} else{
365+
[featureFlags addObject:[[IBGFeatureFlag alloc] initWithName:key variant:variant]];
366+
}
367+
}
368+
369+
[Instabug addFeatureFlags:featureFlags];
370+
}
371+
372+
RCT_EXPORT_METHOD(removeFeatureFlags:(NSArray *)featureFlags) {
373+
NSMutableArray<IBGFeatureFlag *> *features = [NSMutableArray array];
374+
for(id item in featureFlags){
375+
[features addObject:[[IBGFeatureFlag alloc] initWithName:item]];
376+
}
377+
378+
@try {
379+
[Instabug removeFeatureFlags:features];
380+
}
381+
@catch (NSException *exception) {
382+
NSLog(@"%@", exception);
383+
}
384+
}
385+
386+
RCT_EXPORT_METHOD(removeAllFeatureFlags) {
387+
[Instabug removeAllFeatureFlags];
388+
}
389+
358390
RCT_EXPORT_METHOD(willRedirectToStore){
359391
[Instabug willRedirectToAppStore];
360392
}

src/native/NativeInstabug.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,12 @@ export interface InstabugNativeModule extends NativeModule {
118118
removeExperiments(experiments: string[]): void;
119119
clearAllExperiments(): void;
120120

121+
addFeatureFlags(featureFlags: Record<string, string | undefined>): void;
122+
123+
removeFeatureFlags(featureFlags: string[]): void;
124+
125+
removeAllFeatureFlags(): void;
126+
121127
// Files APIs //
122128
setFileAttachment(filePath: string, fileName?: string): void;
123129

test/mocks/mockInstabug.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ const mockInstabug: InstabugNativeModule = {
5454
clearAllExperiments: jest.fn(),
5555
networkLogIOS: jest.fn(),
5656
networkLogAndroid: jest.fn(),
57+
addFeatureFlags: jest.fn(),
58+
removeFeatureFlags: jest.fn(),
59+
removeAllFeatureFlags: jest.fn(),
5760
appendTagToReport: jest.fn(),
5861
appendConsoleLogToReport: jest.fn(),
5962
setUserAttributeToReport: jest.fn(),

0 commit comments

Comments
 (0)