Skip to content

Commit 044f507

Browse files
Integrate/bucketing/listeners (#180)
* integrate with optimizely java sdk 1.9 * update with bucketing id and notification listener tests * cleanup unused imports and comment on event payload case * added a couple more of listener unit tests
1 parent 0a53b02 commit 044f507

File tree

10 files changed

+351
-58
lines changed

10 files changed

+351
-58
lines changed

android-sdk/src/androidTest/java/com/optimizely/ab/android/sdk/OptimizelyClientEngineTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import android.support.test.runner.AndroidJUnit4;
2525

2626
import com.optimizely.ab.event.internal.payload.Event;
27+
import com.optimizely.ab.event.internal.payload.EventBatch;
2728

2829
import org.junit.Test;
2930
import org.junit.runner.RunWith;
@@ -41,7 +42,7 @@ public void testGetClientEngineFromContextAndroidTV() {
4142
UiModeManager uiModeManager = mock(UiModeManager.class);
4243
when(context.getSystemService(Context.UI_MODE_SERVICE)).thenReturn(uiModeManager);
4344
when(uiModeManager.getCurrentModeType()).thenReturn(Configuration.UI_MODE_TYPE_TELEVISION);
44-
assertEquals(Event.ClientEngine.ANDROID_TV_SDK, OptimizelyClientEngine.getClientEngineFromContext(context));
45+
assertEquals(EventBatch.ClientEngine.ANDROID_TV_SDK, OptimizelyClientEngine.getClientEngineFromContext(context));
4546
}
4647

4748
@RequiresApi(api = Build.VERSION_CODES.HONEYCOMB_MR2)
@@ -51,6 +52,6 @@ public void testGetClientEngineFromContextAndroid() {
5152
UiModeManager uiModeManager = mock(UiModeManager.class);
5253
when(context.getSystemService(Context.UI_MODE_SERVICE)).thenReturn(uiModeManager);
5354
when(uiModeManager.getCurrentModeType()).thenReturn(Configuration.UI_MODE_TYPE_NORMAL);
54-
assertEquals(Event.ClientEngine.ANDROID_SDK, OptimizelyClientEngine.getClientEngineFromContext(context));
55+
assertEquals(EventBatch.ClientEngine.ANDROID_SDK, OptimizelyClientEngine.getClientEngineFromContext(context));
5556
}
5657
}

android-sdk/src/androidTest/java/com/optimizely/ab/android/sdk/OptimizelyClientTest.java

Lines changed: 174 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@
2929
import com.optimizely.ab.config.parser.ConfigParseException;
3030
import com.optimizely.ab.event.EventHandler;
3131
import com.optimizely.ab.event.LogEvent;
32+
import com.optimizely.ab.notification.ActivateNotificationListener;
33+
import com.optimizely.ab.notification.NotificationCenter;
3234
import com.optimizely.ab.notification.NotificationListener;
35+
import com.optimizely.ab.notification.TrackNotificationListener;
3336

3437
import org.junit.Assert;
3538
import org.junit.Test;
@@ -46,6 +49,8 @@
4649
import java.util.HashMap;
4750
import java.util.Map;
4851

52+
import javax.annotation.Nonnull;
53+
4954
import static com.optimizely.ab.android.sdk.OptimizelyManager.loadRawResource;
5055
import static junit.framework.Assert.assertEquals;
5156
import static junit.framework.Assert.assertFalse;
@@ -173,6 +178,61 @@ public void testGoodActivation() {
173178

174179
}
175180

181+
@Test
182+
public void testGoodActivationWithListener() {
183+
OptimizelyClient optimizelyClient = new OptimizelyClient(optimizely,
184+
logger);
185+
final boolean[] callbackCalled = new boolean[1];
186+
final Variation[] callbackVariation = new Variation[1];
187+
188+
callbackCalled[0] = false;
189+
int notificationId = optimizelyClient.getNotificationCenter().addNotification(NotificationCenter.NotificationType.Activate, new ActivateNotificationListener() {
190+
@Override
191+
public void onActivate(@Nonnull Experiment experiment, @Nonnull String userId, @Nonnull Map<String, String> attributes, @Nonnull Variation variation, @Nonnull LogEvent event) {
192+
callbackCalled[0] = true;
193+
callbackVariation[0] = variation;
194+
}
195+
});
196+
197+
Variation v = optimizelyClient.activate(FEATURE_ANDROID_EXPERIMENT_KEY, GENERIC_USER_ID);
198+
199+
if (datafileVersion == 3) {
200+
assertEquals(v, callbackVariation[0]);
201+
assertEquals(true, callbackCalled[0]);
202+
assertEquals(1, notificationId);
203+
assertTrue(optimizelyClient.getNotificationCenter().removeNotification(notificationId));
204+
}
205+
else {
206+
assertNull(v);
207+
assertEquals(false, callbackCalled[0]);
208+
assertEquals(1, notificationId);
209+
assertTrue(optimizelyClient.getNotificationCenter().removeNotification(notificationId));
210+
}
211+
212+
}
213+
214+
@Test
215+
public void testBadActivationWithListener() {
216+
OptimizelyClient optimizelyClient = new OptimizelyClient(optimizely,
217+
logger);
218+
final boolean[] callbackCalled = new boolean[1];
219+
220+
callbackCalled[0] = false;
221+
int notificationId = optimizelyClient.getNotificationCenter().addNotification(NotificationCenter.NotificationType.Activate, new TrackNotificationListener() {
222+
@Override
223+
public void onTrack(@Nonnull String eventKey, @Nonnull String userId, @Nonnull Map<String, String> attributes, @Nonnull Map<String, ?> eventTags, @Nonnull LogEvent event) {
224+
callbackCalled[0] = true;
225+
}
226+
});
227+
228+
Variation v = optimizelyClient.activate(FEATURE_ANDROID_EXPERIMENT_KEY, GENERIC_USER_ID);
229+
230+
assertEquals(false, callbackCalled[0]);
231+
assertTrue(notificationId <= 0);
232+
assertFalse(optimizelyClient.getNotificationCenter().removeNotification(notificationId));
233+
234+
}
235+
176236
@Test
177237
public void testGoodForcedActivation() {
178238

@@ -244,7 +304,18 @@ public void testGoodActivationAttribute() {
244304
}
245305

246306
@Test
247-
public void testBadForcedActivationAttribute() {
307+
public void testGoodActivationBucketingId() {
308+
OptimizelyClient optimizelyClient = new OptimizelyClient(optimizely, logger);
309+
final HashMap<String, String> attributes = new HashMap<>();
310+
String bucketingId = "1";
311+
Experiment experiment = optimizelyClient.getProjectConfig().getExperimentKeyMapping().get(FEATURE_ANDROID_EXPERIMENT_KEY);
312+
attributes.put(DecisionService.BUCKETING_ATTRIBUTE, bucketingId);
313+
Variation v = optimizelyClient.activate(FEATURE_ANDROID_EXPERIMENT_KEY, GENERIC_USER_ID, attributes);
314+
verify(bucketer).bucket( experiment, bucketingId);
315+
}
316+
317+
@Test
318+
public void testBadForcedActivationAttribute() {
248319
OptimizelyClient optimizelyClient = new OptimizelyClient(null, logger);
249320
boolean didSetForced = optimizelyClient.setForcedVariation(FEATURE_ANDROID_EXPERIMENT_KEY, GENERIC_USER_ID, "var_2");
250321

@@ -297,7 +368,10 @@ public void testGoodForcedTrack() {
297368
LogEvent logEvent = logEventArgumentCaptor.getValue();
298369

299370
// id of var_2
300-
assertTrue(logEvent.getBody().contains("\"variationId\":\"8505434669\""));
371+
// the new event backend accepts both camel case and snake case
372+
// https://logx.optimizely.com/v1/events
373+
assertTrue(logEvent.getBody().contains("\"variationId\":\"8505434669\"") ||
374+
logEvent.getBody().contains("\"variation_id\":\"8505434669\""));
301375

302376
verify(config).getForcedVariation(FEATURE_ANDROID_EXPERIMENT_KEY, GENERIC_USER_ID);
303377

@@ -320,6 +394,69 @@ public void testGoodTrack() {
320394
verifyZeroInteractions(logger);
321395
}
322396

397+
@Test
398+
public void testBadTrackWithListener() {
399+
OptimizelyClient optimizelyClient = new OptimizelyClient(optimizely,
400+
logger);
401+
402+
final boolean[] numberOfCalls = new boolean[1];
403+
numberOfCalls[0]= false;
404+
405+
int notificationId = optimizelyClient.getNotificationCenter().addNotification(NotificationCenter.NotificationType.Activate,
406+
new TrackNotificationListener() {
407+
@Override
408+
public void onTrack(@Nonnull String eventKey, @Nonnull String userId, @Nonnull Map<String, String> attributes, @Nonnull Map<String, ?> eventTags, @Nonnull LogEvent event) {
409+
numberOfCalls[0] = true;
410+
}
411+
});
412+
optimizelyClient.track("test_event", GENERIC_USER_ID);
413+
assertTrue(notificationId <= 0);
414+
assertFalse(optimizelyClient.getNotificationCenter().removeNotification(notificationId));
415+
assertEquals(false, numberOfCalls[0]);
416+
verifyZeroInteractions(logger);
417+
418+
}
419+
420+
@Test
421+
public void testGoodTrackWithListener() {
422+
OptimizelyClient optimizelyClient = new OptimizelyClient(optimizely,
423+
logger);
424+
425+
final boolean[] numberOfCalls = new boolean[1];
426+
numberOfCalls[0]= false;
427+
428+
int notificationId = optimizelyClient.getNotificationCenter().addNotification(NotificationCenter.NotificationType.Track,
429+
new TrackNotificationListener() {
430+
@Override
431+
public void onTrack(@Nonnull String eventKey, @Nonnull String userId, @Nonnull Map<String, String> attributes, @Nonnull Map<String, ?> eventTags, @Nonnull LogEvent event) {
432+
numberOfCalls[0] = true;
433+
}
434+
});
435+
optimizelyClient.track("test_event", GENERIC_USER_ID);
436+
assertTrue(notificationId > 0);
437+
assertTrue(optimizelyClient.getNotificationCenter().removeNotification(notificationId));
438+
if (datafileVersion == 3) {
439+
assertEquals(true, numberOfCalls[0]);
440+
}
441+
else {
442+
assertEquals(false, numberOfCalls[0]);
443+
}
444+
verifyZeroInteractions(logger);
445+
446+
}
447+
448+
@Test
449+
public void testGoodTrackBucketing() {
450+
OptimizelyClient optimizelyClient = new OptimizelyClient(optimizely, logger);
451+
Map<String,String> attributes = new HashMap<>();
452+
String bucketingId = "1";
453+
Experiment experiment = optimizelyClient.getProjectConfig().getExperimentsForEventKey("test_event").get(0);
454+
attributes.put(DecisionService.BUCKETING_ATTRIBUTE, bucketingId);
455+
optimizelyClient.track("test_event", "userId", attributes);
456+
verify(bucketer).bucket(experiment, bucketingId);
457+
verifyZeroInteractions(logger);
458+
}
459+
323460
@Test
324461
public void testBadTrack() {
325462
OptimizelyClient optimizelyClient = new OptimizelyClient(null, logger);
@@ -373,8 +510,11 @@ public void testGoodForcedTrackAttribute() {
373510
}
374511
LogEvent logEvent = logEventArgumentCaptor.getValue();
375512

513+
// the new event backend accepts both camel case and snake case
514+
// https://logx.optimizely.com/v1/events
376515
// id of var_2
377-
assertTrue(logEvent.getBody().contains("\"variationId\":\"8505434669\""));
516+
assertTrue(logEvent.getBody().contains("\"variationId\":\"8505434669\"") ||
517+
logEvent.getBody().contains("\"variation_id\":\"8505434669\""));
378518

379519
verify(config).getForcedVariation(FEATURE_ANDROID_EXPERIMENT_KEY, GENERIC_USER_ID);
380520

@@ -473,8 +613,11 @@ public void testGoodForcedTrackEventVal() {
473613
}
474614
LogEvent logEvent = logEventArgumentCaptor.getValue();
475615

616+
// the new event backend accepts both camel case and snake case
617+
// https://logx.optimizely.com/v1/events
476618
// id of var_2
477-
assertTrue(logEvent.getBody().contains("\"variationId\":\"8505434669\""));
619+
assertTrue(logEvent.getBody().contains("\"variationId\":\"8505434669\"") ||
620+
logEvent.getBody().contains("\"variation_id\":\"8505434669\""));
478621

479622
verify(config).getForcedVariation(FEATURE_ANDROID_EXPERIMENT_KEY, GENERIC_USER_ID);
480623

@@ -559,8 +702,11 @@ public void testGoodForcedTrackAttributeEventVal() {
559702
}
560703
LogEvent logEvent = logEventArgumentCaptor.getValue();
561704

705+
// the new event backend accepts both camel case and snake case
706+
// https://logx.optimizely.com/v1/events
562707
// id of var_2
563-
assertTrue(logEvent.getBody().contains("\"variationId\":\"8505434669\""));
708+
assertTrue(logEvent.getBody().contains("\"variationId\":\"8505434669\"") ||
709+
logEvent.getBody().contains("\"variation_id\":\"8505434669\""));
564710

565711
verify(config).getForcedVariation(FEATURE_ANDROID_EXPERIMENT_KEY, GENERIC_USER_ID);
566712

@@ -646,8 +792,11 @@ public void testForcedTrackWithEventTags() {
646792
}
647793
LogEvent logEvent = logEventArgumentCaptor.getValue();
648794

795+
// the new event backend accepts both camel case and snake case
796+
// https://logx.optimizely.com/v1/events
649797
// id of var_2
650-
assertTrue(logEvent.getBody().contains("\"variationId\":\"8505434669\""));
798+
assertTrue(logEvent.getBody().contains("\"variationId\":\"8505434669\"") ||
799+
logEvent.getBody().contains("\"variation_id\":\"8505434669\""));
651800

652801
verifyZeroInteractions(logger);
653802

@@ -678,6 +827,17 @@ public void testGoodGetVariation1() {
678827
}
679828
}
680829

830+
@Test
831+
public void testGoodGetVariationBucketingId() {
832+
OptimizelyClient optimizelyClient = new OptimizelyClient(optimizely, logger);
833+
Experiment experiment = optimizelyClient.getProjectConfig().getExperimentKeyMapping().get("android_experiment_key");
834+
String bucketingId = "1";
835+
Map<String, String> attributes = new HashMap<>();
836+
attributes.put(DecisionService.BUCKETING_ATTRIBUTE, bucketingId);
837+
Variation v = optimizelyClient.getVariation("android_experiment_key", "userId", attributes);
838+
verify(bucketer).bucket(experiment, bucketingId);
839+
}
840+
681841
@Test
682842
public void testGoodGetVariation1Forced() {
683843
OptimizelyClient optimizelyClient = new OptimizelyClient(optimizely,
@@ -884,6 +1044,9 @@ public void onExperimentActivated(Experiment experiment,
8841044
Map<String, String> map,
8851045
Variation variation) {
8861046
}
1047+
1048+
@Override
1049+
public void notify(Object... args) {}
8871050
};
8881051
optimizelyClient.addNotificationListener(listener);
8891052
optimizelyClient.removeNotificationListener(listener);
@@ -900,6 +1063,9 @@ public void onExperimentActivated(Experiment experiment,
9001063
Map<String, String> map,
9011064
Variation variation) {
9021065
}
1066+
1067+
@Override
1068+
public void notify(Object... args) {}
9031069
};
9041070
optimizelyClient.addNotificationListener(listener);
9051071
verify(logger).warn("Optimizely is not initialized, could not add notification listener");
@@ -915,6 +1081,8 @@ public void onExperimentActivated(Experiment experiment,
9151081
Map<String, String> map,
9161082
Variation variation) {
9171083
}
1084+
@Override
1085+
public void notify(Object... args) {}
9181086
};
9191087
optimizelyClient.removeNotificationListener(listener);
9201088
verify(logger).warn("Optimizely is not initialized, could not remove notification listener");

0 commit comments

Comments
 (0)