Skip to content

[FSSDK-10759] feat: make vuid optln #78

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 9 commits into from
Nov 28, 2024
Merged
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
25 changes: 25 additions & 0 deletions .github/workflows/flutter.yml
Original file line number Diff line number Diff line change
@@ -5,6 +5,16 @@ on:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
# workflow_dispatch:
# inputs:
# sdk_branch:
# description: "Specify the SDK branch"
# required: false
# default: "master"
# testapp_branch:
# description: "Specify the test app branch"
# required: false
# default: "master"

jobs:
unit_test_coverage:
@@ -36,6 +46,21 @@ jobs:
repository: 'optimizely/travisci-tools'
path: 'home/runner/travisci-tools'
ref: 'master'
# Set SDK Branch based on input or PR/Push
# - name: Set SDK Branch and Test App Branch
# run: |
# # If manually triggered
# if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
# echo "SDK_BRANCH=${{ github.event.inputs.sdk_branch || 'master' }}" >> $GITHUB_ENV
# echo "TESTAPP_BRANCH=${{ github.event.inputs.testapp_branch || 'master' }}" >> $GITHUB_ENV
# # If triggered by PR
# elif [[ "${{ github.event_name }}" == "pull_request" ]]; then
# echo "SDK_BRANCH=${{ github.head_ref }}" >> $GITHUB_ENV
# # If triggered by push
# else
# echo "SDK_BRANCH=${{ github.ref_name }}" >> $GITHUB_ENV
# echo "TRAVIS_BRANCH=${{ github.ref_name }}" >> $GITHUB_ENV
# fi
- name: set SDK Branch if PR
env:
HEAD_REF: ${{ github.head_ref }}
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
@@ -74,7 +74,7 @@ dependencies {
implementation 'org.slf4j:slf4j-api:2.0.7'

implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.10"
implementation "com.optimizely.ab:android-sdk:4.0.0"
implementation "com.optimizely.ab:android-sdk:5.0.0"
implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.4'
implementation ('com.google.guava:guava:19.0') {
exclude group:'com.google.guava', module:'listenablefuture'
Original file line number Diff line number Diff line change
@@ -55,6 +55,7 @@

import static com.optimizely.optimizely_flutter_sdk.helper_classes.Constants.*;
import static com.optimizely.optimizely_flutter_sdk.helper_classes.Constants.RequestParameterKey.DISABLE_ODP;
import static com.optimizely.optimizely_flutter_sdk.helper_classes.Constants.RequestParameterKey.ENABLE_VUID;
import static com.optimizely.optimizely_flutter_sdk.helper_classes.Constants.RequestParameterKey.SEGMENTS_CACHE_SIZE;
import static com.optimizely.optimizely_flutter_sdk.helper_classes.Constants.RequestParameterKey.SEGMENTS_CACHE_TIMEOUT_IN_SECONDS;
import static com.optimizely.optimizely_flutter_sdk.helper_classes.Constants.RequestParameterKey.TIMEOUT_FOR_ODP_EVENT_IN_SECONDS;
@@ -144,6 +145,7 @@ protected void initializeOptimizely(@NonNull ArgumentsParser argumentsParser, @N
int timeoutForSegmentFetchInSecs = 10;
int timeoutForOdpEventInSecs = 10;
boolean disableOdp = false;
boolean enableVuid = false;
Map<String, Object> sdkSettings = argumentsParser.getOptimizelySdkSettings();
if (sdkSettings != null) {
if (sdkSettings.containsKey(SEGMENTS_CACHE_SIZE)) {
@@ -161,6 +163,9 @@ protected void initializeOptimizely(@NonNull ArgumentsParser argumentsParser, @N
if (sdkSettings.containsKey(DISABLE_ODP)) {
disableOdp = (boolean) sdkSettings.get(DISABLE_ODP);
}
if (sdkSettings.containsKey(ENABLE_VUID)) {
enableVuid = (boolean) sdkSettings.get(ENABLE_VUID);
}
}
// Creating new instance
OptimizelyManager.Builder optimizelyManagerBuilder = OptimizelyManager.builder()
@@ -179,6 +184,9 @@ protected void initializeOptimizely(@NonNull ArgumentsParser argumentsParser, @N
if (disableOdp) {
optimizelyManagerBuilder.withODPDisabled();
}
if (enableVuid) {
optimizelyManagerBuilder.withVuidEnabled();
}
OptimizelyManager optimizelyManager = optimizelyManagerBuilder.build(context);

optimizelyManager.initialize(context, null, (OptimizelyClient client) -> {
@@ -471,7 +479,7 @@ protected void getVuid(ArgumentsParser argumentsParser, @NonNull Result result)
if (!isOptimizelyClientValid(sdkKey, optimizelyClient, result)) {
return;
}
result.success(createResponse(true, Collections.singletonMap(RequestParameterKey.VUID, optimizelyClient.getVuid()), ""));
result.success(createResponse(optimizelyClient.getVuid() != null, Collections.singletonMap(RequestParameterKey.VUID, optimizelyClient.getVuid()), ""));
}

/// Checks if the user is qualified for the given segment.
Original file line number Diff line number Diff line change
@@ -96,6 +96,7 @@ public static class RequestParameterKey {
public static final String TIMEOUT_FOR_SEGMENT_FETCH_IN_SECONDS = "timeoutForSegmentFetchInSecs";
public static final String TIMEOUT_FOR_ODP_EVENT_IN_SECONDS = "timeoutForOdpEventInSecs";
public static final String DISABLE_ODP = "disableOdp";
public static final String ENABLE_VUID = "enableVuid";
}

public static class ErrorMessage {
1 change: 1 addition & 0 deletions ios/Classes/HelperClasses/Constants.swift
Original file line number Diff line number Diff line change
@@ -114,6 +114,7 @@ struct RequestParameterKey {
static let timeoutForSegmentFetchInSecs = "timeoutForSegmentFetchInSecs"
static let timeoutForOdpEventInSecs = "timeoutForOdpEventInSecs"
static let disableOdp = "disableOdp"
static let enableVuid = "enableVuid"
static let sdkVersion = "sdkVersion";
}

10 changes: 7 additions & 3 deletions ios/Classes/SwiftOptimizelyFlutterSdkPlugin.swift
Original file line number Diff line number Diff line change
@@ -118,6 +118,7 @@ public class SwiftOptimizelyFlutterSdkPlugin: NSObject, FlutterPlugin {
var timeoutForSegmentFetchInSecs: Int = 10
var timeoutForOdpEventInSecs: Int = 10
var disableOdp: Bool = false
var enableVuid: Bool = false
var sdkVersion = parameters[RequestParameterKey.sdkVersion] as? String
var sdkName = Utils.sdkName

@@ -137,8 +138,11 @@ public class SwiftOptimizelyFlutterSdkPlugin: NSObject, FlutterPlugin {
if let isOdpDisabled = sdkSettings[RequestParameterKey.disableOdp] as? Bool {
disableOdp = isOdpDisabled
}
if let isEnableVuid = sdkSettings[RequestParameterKey.enableVuid] as? Bool {
enableVuid = isEnableVuid
}
}
let optimizelySdkSettings = OptimizelySdkSettings(segmentsCacheSize: segmentsCacheSize, segmentsCacheTimeoutInSecs: segmentsCacheTimeoutInSecs, timeoutForSegmentFetchInSecs: timeoutForSegmentFetchInSecs, timeoutForOdpEventInSecs: timeoutForOdpEventInSecs, disableOdp: disableOdp, sdkName: sdkName, sdkVersion: sdkVersion)
let optimizelySdkSettings = OptimizelySdkSettings(segmentsCacheSize: segmentsCacheSize, segmentsCacheTimeoutInSecs: segmentsCacheTimeoutInSecs, timeoutForSegmentFetchInSecs: timeoutForSegmentFetchInSecs, timeoutForOdpEventInSecs: timeoutForOdpEventInSecs, disableOdp: disableOdp, enableVuid: enableVuid, sdkName: sdkName, sdkVersion: sdkVersion)

// Datafile Download Interval
var datafilePeriodicDownloadInterval = 10 * 60 // seconds
@@ -374,7 +378,7 @@ public class SwiftOptimizelyFlutterSdkPlugin: NSObject, FlutterPlugin {
} else {
userContextsTracker[sdkKey] = [userContextId: userContext]
}
result(self.createResponse(success: true, result: [RequestParameterKey.userContextId: userContextId]))
result(self.createResponse(success: userContext != nil, result: [RequestParameterKey.userContextId: userContextId]))
}

/// Returns userId for the user context.
@@ -442,7 +446,7 @@ public class SwiftOptimizelyFlutterSdkPlugin: NSObject, FlutterPlugin {
guard let optimizelyClient = getOptimizelyClient(sdkKey: sdkKey, result: result) else {
return
}
result(self.createResponse(success: true, result: [RequestParameterKey.vuid: optimizelyClient.vuid]))
result(self.createResponse(success: optimizelyClient.vuid != nil, result: [RequestParameterKey.vuid: optimizelyClient.vuid]))
}

/// Checks if the user is qualified for the given segment.
2 changes: 1 addition & 1 deletion ios/optimizely_flutter_sdk.podspec
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ Pod::Spec.new do |s|
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.dependency 'Flutter'
s.dependency 'OptimizelySwiftSDK', '4.0.0'
s.dependency 'OptimizelySwiftSDK', '5.0.0'
s.platform = :ios, '10.0'
# Flutter.framework does not contain a i386 slice.
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
2 changes: 1 addition & 1 deletion lib/src/data_objects/get_vuid_response.dart
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ import 'package:optimizely_flutter_sdk/src/data_objects/base_response.dart';
import 'package:optimizely_flutter_sdk/src/utils/constants.dart';

class GetVuidResponse extends BaseResponse {
String vuid = "";
String? vuid;

GetVuidResponse(Map<String, dynamic> json) : super(json) {
if (json[Constants.responseResult] is Map<dynamic, dynamic>) {
3 changes: 3 additions & 0 deletions lib/src/data_objects/sdk_settings.dart
Original file line number Diff line number Diff line change
@@ -25,6 +25,8 @@ class SDKSettings {
final int timeoutForOdpEventInSecs;
// Set this flag to true (default = false) to disable ODP features
final bool disableOdp;
// Set this flag to true (default = false) to enable VUID feature
final bool enableVuid;

const SDKSettings({
this.segmentsCacheSize = 100, // Default segmentsCacheSize
@@ -33,5 +35,6 @@ class SDKSettings {
10, // Default timeoutForSegmentFetchInSecs
this.timeoutForOdpEventInSecs = 10, // Default timeoutForOdpEventInSecs
this.disableOdp = false, // Default disableOdp
this.enableVuid = false, // Default disableVuid
});
}
1 change: 1 addition & 0 deletions lib/src/optimizely_client_wrapper.dart
Original file line number Diff line number Diff line change
@@ -90,6 +90,7 @@ class OptimizelyClientWrapper {
sdkSettings.timeoutForSegmentFetchInSecs,
Constants.timeoutForOdpEventInSecs: sdkSettings.timeoutForOdpEventInSecs,
Constants.disableOdp: sdkSettings.disableOdp,
Constants.enableVuid: sdkSettings.enableVuid,
};
requestDict[Constants.optimizelySdkSettings] = optimizelySdkSettings;

1 change: 1 addition & 0 deletions lib/src/utils/constants.dart
Original file line number Diff line number Diff line change
@@ -131,6 +131,7 @@ class Constants {
"timeoutForSegmentFetchInSecs";
static const String timeoutForOdpEventInSecs = "timeoutForOdpEventInSecs";
static const String disableOdp = "disableOdp";
static const String enableVuid = "enableVuid";

// Response keys
static const String responseSuccess = "success";
48 changes: 40 additions & 8 deletions test/optimizely_flutter_sdk_test.dart
Original file line number Diff line number Diff line change
@@ -56,7 +56,6 @@ void main() {
SDKSettings sdkSettings = const SDKSettings();
int datafilePeriodicDownloadInterval = 0;
String defaultLogLevel = "error";

const MethodChannel channel = MethodChannel("optimizely_flutter_sdk");
dynamic mockOptimizelyConfig;

@@ -106,6 +105,7 @@ void main() {
timeoutForOdpEventInSecs:
settings[Constants.timeoutForOdpEventInSecs],
disableOdp: settings[Constants.disableOdp],
enableVuid: settings[Constants.enableVuid],
);
}

@@ -175,17 +175,27 @@ void main() {
};
case Constants.createUserContextMethod:
expect(methodCall.arguments[Constants.sdkKey], isNotEmpty);
if (methodCall.arguments[Constants.userId] != null) {
var resultUserId = userContextId;
if (methodCall.arguments[Constants.userId] == null) {
if (sdkSettings.enableVuid) {
resultUserId = vuid;
} else {
return {
Constants.responseSuccess: false,
};
}
} else if (methodCall.arguments[Constants.userId] != null) {
expect(methodCall.arguments[Constants.userId], equals(userId));
}

if (methodCall.arguments[Constants.attributes]["abc"] != null) {
expect(methodCall.arguments[Constants.attributes]["abc"],
equals(attributes["abc"]));
}
expect(methodCall.arguments[Constants.userContextId], isNull);
return {
Constants.responseSuccess: true,
Constants.responseResult: {Constants.userContextId: userContextId},
Constants.responseResult: {Constants.userContextId: resultUserId},
};
case Constants.getUserIdMethod:
expect(methodCall.arguments[Constants.sdkKey], isNotEmpty);
@@ -266,6 +276,8 @@ void main() {
case Constants.getVuidMethod:
expect(methodCall.arguments[Constants.sdkKey], isNotEmpty);
expect(methodCall.arguments[Constants.userContextId], isNull);
expect(methodCall.arguments[Constants.vuid], isNull);
var vuid = sdkSettings.enableVuid ? "vuid_123" : null;
return {
Constants.responseSuccess: true,
Constants.responseResult: {Constants.vuid: vuid},
@@ -376,6 +388,7 @@ void main() {

tearDown(() {
tester?.setMockMethodCallHandler(channel, null);
sdkSettings = const SDKSettings();
});

group("Integration: OptimizelyFlutterSdk MethodChannel", () {
@@ -650,8 +663,17 @@ void main() {
expect(userContext, isNotNull);
});

test("should succeed null userId", () async {
test("should fail when disable vuid and userId null", () async {
var sdk = OptimizelyFlutterSdk(testSDKKey);
sdk.initializeClient();
var userContext = await sdk.createUserContext(attributes: attributes);
expect(userContext, isNull);
});

test("should succed when enable vuid and userId null", () async {
const settings = SDKSettings(enableVuid: true);
var sdk = OptimizelyFlutterSdk(testSDKKey, sdkSettings: settings);
sdk.initializeClient();
var userContext = await sdk.createUserContext(attributes: attributes);
expect(userContext, isNotNull);
});
@@ -662,10 +684,11 @@ void main() {
expect(userContext, isNotNull);
});

test("should succeed null userId and attributes", () async {
test("should not succeed null userId and attributes", () async {
var sdk = OptimizelyFlutterSdk(testSDKKey);
sdk.initializeClient();
var userContext = await sdk.createUserContext();
expect(userContext, isNotNull);
expect(userContext, isNull);
});
});

@@ -769,11 +792,20 @@ void main() {
});

group("getVuid()", () {
test("should succeed", () async {
test("by default should return null vuid", () async {
var sdk = OptimizelyFlutterSdk(testSDKKey);
sdk.initializeClient();
var response = await sdk.getVuid();
expect(response.success, isTrue);
expect(response.vuid, isNull);
});
test("should return vuid when enableVuid true", () async {
const settings = SDKSettings(enableVuid: true);
var sdk = OptimizelyFlutterSdk(testSDKKey, sdkSettings: settings);
sdk.initializeClient();
var response = await sdk.getVuid();
expect(response.success, isTrue);
expect(response.vuid, equals(vuid));
expect(response.vuid, "vuid_123");
});
});