Skip to content

Commit

Permalink
Prepare for release 10.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
chshapiro committed Aug 24, 2021
1 parent bddf02d commit b9a25f8
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 22 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 10.0.0

##### Breaking
- Updated to [Braze Android SDK 15.0.0](https://github.com/Appboy/appboy-android-sdk/blob/master/CHANGELOG.md#1500).
- A track call with event name "Completed Order" will now be treated as a purchase event for backwards compatibility with Segment eCommerce v1 API.

## 9.0.0

##### Breaking
Expand Down
2 changes: 1 addition & 1 deletion appboy-segment-integration/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ dependencies {

compileOnly 'com.segment.analytics.android:analytics:4.3.1'

api 'com.appboy:android-sdk-ui:14.0.0'
api 'com.appboy:android-sdk-ui:15.0.0'

testImplementation 'junit:junit:4.12'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@
import androidx.annotation.VisibleForTesting;

import com.appboy.Appboy;
import com.appboy.AppboyUser;
import com.appboy.IAppboy;
import com.appboy.enums.Gender;
import com.appboy.enums.Month;
import com.appboy.enums.SdkFlavor;
import com.appboy.models.outgoing.AppboyProperties;
import com.appboy.models.outgoing.AttributionData;
import com.appboy.support.StringUtils;
import com.appboy.ui.inappmessage.AppboyInAppMessageManager;
import com.braze.BrazeUser;
import com.braze.configuration.BrazeConfig;
import com.braze.ui.inappmessage.BrazeInAppMessageManager;
import com.segment.analytics.Analytics;
import com.segment.analytics.Properties;
import com.segment.analytics.Traits;
Expand All @@ -30,8 +30,10 @@
import org.json.JSONObject;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
Expand All @@ -40,9 +42,9 @@

public class AppboyIntegration extends Integration<Appboy> {
private static final String APPBOY_KEY = "Appboy";
private static final Set<String> MALE_TOKENS = new HashSet(Arrays.asList("M",
private static final Set<String> MALE_TOKENS = new HashSet<>(Arrays.asList("M",
"MALE"));
private static final Set<String> FEMALE_TOKENS = new HashSet(Arrays.asList("F",
private static final Set<String> FEMALE_TOKENS = new HashSet<>(Arrays.asList("F",
"FEMALE"));
private static final String DEFAULT_CURRENCY_CODE = "USD";
private static final String API_KEY_KEY = "apiKey";
Expand All @@ -64,7 +66,7 @@ public Integration<?> create(ValueMap settings, Analytics analytics) {
settings.getBoolean(AUTOMATIC_IN_APP_MESSAGE_REGISTRATION_ENABLED, true);

if (StringUtils.isNullOrBlank(API_KEY_KEY)) {
logger.info("Appboy+Segment integration attempted to initialize without api key.");
logger.info("Braze+Segment integration attempted to initialize without api key.");
return null;
}
String customEndpoint = settings.getString(CUSTOM_ENDPOINT_KEY);
Expand All @@ -78,7 +80,7 @@ public Integration<?> create(ValueMap settings, Analytics analytics) {
final Context applicationContext = analytics.getApplication().getApplicationContext();
Appboy.configure(applicationContext, builder.build());
Appboy appboy = Appboy.getInstance(applicationContext);
logger.verbose("Configured Appboy+Segment integration and initialized Appboy.");
logger.verbose("Configured Braze+Segment integration and initialized Appboy.");
return new AppboyIntegration(appboy, apiKey, logger, inAppMessageRegistrationEnabled);
}

Expand Down Expand Up @@ -134,7 +136,7 @@ public void identify(IdentifyPayload identify) {

Traits traits = identify.traits();

AppboyUser currentUser = mAppboy.getCurrentUser();
BrazeUser currentUser = mAppboy.getCurrentUser();
if (currentUser == null) {
mLogger.info("Appboy.getCurrentUser() was null, aborting identify");
return;
Expand Down Expand Up @@ -213,9 +215,21 @@ public void identify(IdentifyPayload identify) {
currentUser.setCustomUserAttribute(key, (String) value);
} else if (value instanceof String[]) {
currentUser.setCustomAttributeArray(key, (String[]) value);
} else if (value instanceof List<?>) {
ArrayList<Object> valueArrayList = new ArrayList<Object>((Collection<Object>) value);
List<String> stringValueList = new ArrayList<>();
for (Object objectValue : valueArrayList) {
if (objectValue instanceof String) {
stringValueList.add((String) objectValue);
}
}
if (stringValueList.size() > 0) {
String[] arrayValue = new String[stringValueList.size()];
currentUser.setCustomAttributeArray(key, stringValueList.toArray(arrayValue));
}
}
else {
mLogger.info("Appboy can't map segment value for custom Appboy user "
mLogger.info("Braze can't map segment value for custom Braze user "
+ "attribute with key %s and value %s", key, value);
}
}
Expand All @@ -239,7 +253,7 @@ public void track(TrackPayload track) {
try {
if (event.equals("Install Attributed")) {
ValueMap campaignProps = (ValueMap) properties.get("campaign");
AppboyUser currentUser = mAppboy.getCurrentUser();
BrazeUser currentUser = mAppboy.getCurrentUser();
if (campaignProps != null && currentUser != null) {
currentUser.setAttributionData(new AttributionData(
campaignProps.getString("source"),
Expand All @@ -255,7 +269,7 @@ public void track(TrackPayload track) {
}
JSONObject propertiesJson = properties.toJsonObject();
double revenue = properties.revenue();
if (revenue != 0 || event.equals("Order Completed")) {
if (revenue != 0 || event.equals("Order Completed") || event.equals("Completed Order")) {
String currencyCode = StringUtils.isNullOrBlank(properties.currency()) ? DEFAULT_CURRENCY_CODE
: properties.currency();
propertiesJson.remove(REVENUE_KEY);
Expand Down Expand Up @@ -296,15 +310,15 @@ public void onActivityStopped(Activity activity) {
public void onActivityResumed(Activity activity) {
super.onActivityResumed(activity);
if (mAutomaticInAppMessageRegistrationEnabled) {
AppboyInAppMessageManager.getInstance().registerInAppMessageManager(activity);
BrazeInAppMessageManager.getInstance().registerInAppMessageManager(activity);
}
}

@Override
public void onActivityPaused(Activity activity) {
super.onActivityPaused(activity);
if (mAutomaticInAppMessageRegistrationEnabled) {
AppboyInAppMessageManager.getInstance().unregisterInAppMessageManager(activity);
BrazeInAppMessageManager.getInstance().unregisterInAppMessageManager(activity);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@

import androidx.test.core.app.ApplicationProvider;

import com.appboy.AppboyUser;
import com.appboy.IAppboy;
import com.appboy.enums.Gender;
import com.appboy.models.outgoing.AppboyProperties;
import com.braze.BrazeUser;
import com.segment.analytics.Analytics;
import com.segment.analytics.Properties;
import com.segment.analytics.Traits;
Expand All @@ -27,11 +27,14 @@
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.LooperMode;

import java.util.ArrayList;
import java.math.BigDecimal;

import static com.segment.analytics.Utils.createTraits;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.AdditionalMatchers.*;
import static org.mockito.ArgumentMatchers.refEq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
Expand All @@ -42,7 +45,7 @@
@RunWith(RobolectricTestRunner.class)
public class AppboyTest {
private IAppboy mAppboy;
private AppboyUser mAppboyUser;
private BrazeUser mAppboyUser;
private AppboyIntegration mIntegration;
private Analytics mAnalytics;

Expand All @@ -53,7 +56,7 @@ public void setUp() {
Mockito.when(mockApplication.getApplicationContext()).thenReturn(getContext());
Mockito.when(mAnalytics.getApplication()).thenReturn(mockApplication);
mAppboy = spy(new MockAppboy());
mAppboyUser = mock(AppboyUser.class);
mAppboyUser = mock(BrazeUser.class);

when(mAppboy.getCurrentUser()).thenReturn(mAppboyUser);
Logger logger = Logger.with(Analytics.LogLevel.DEBUG);
Expand Down Expand Up @@ -121,6 +124,8 @@ public void testIdentifyFields() {
traits.put("float", 5.0f);
traits.put("long", 15L);
traits.put("string", "value");
final String[] testStringArray = {"Test Value 1", "Test Value 2"};
traits.put("array", testStringArray);
traits.put("unknown", new Object());
traits.put("userId", "id1");
traits.put("anonymousId", "id2");
Expand All @@ -139,12 +144,43 @@ public void testIdentifyFields() {
verify(mAppboyUser).setCustomUserAttribute("float", new Float(5.0));
verify(mAppboyUser).setCustomUserAttribute("long", 15L);
verify(mAppboyUser).setCustomUserAttribute("string", "value");
verify(mAppboyUser).setCustomAttributeArray("array", testStringArray);
verify(mAppboyUser, Mockito.never()).setCustomUserAttribute("userId", "id1");
verify(mAppboyUser, Mockito.never()).setCustomUserAttribute("anonymousId", "id2");
verify(mAppboy, Mockito.times(1)).changeUser("userId");
verify(mAppboy, Mockito.times(1)).getCurrentUser();
}

@Test
public void testIdentifyArrayList() {
Traits traits = createTraits("userId");
ArrayList<String> testArrayList = new ArrayList<>();
testArrayList.add("Test Value 1");
testArrayList.add("Test Value 2");
final String[] stringArray = {"Test Value 1", "Test Value 2"};
final String testName = "testArrayList";
traits.put(testName, testArrayList);
IdentifyPayload identifyPayload = getBasicIdentifyPayloadWithTraits(traits);
mIntegration.identify(identifyPayload);
verify(mAppboyUser).setCustomAttributeArray(refEq(testName), aryEq(stringArray));
}

@Test
public void testIdentifyArrayListWithListInt() {
Traits traits = createTraits("userId");
ArrayList<Integer> testArrayList = new ArrayList<>();
testArrayList.add(1);
testArrayList.add(2);
final String[] stringArray = {"1", "2"};
final String[] emptyArray = {};
final String testName = "testArrayList";
traits.put(testName, testArrayList);
IdentifyPayload identifyPayload = getBasicIdentifyPayloadWithTraits(traits);
mIntegration.identify(identifyPayload);
verify(mAppboyUser, Mockito.never()).setCustomAttributeArray(refEq(testName), aryEq(stringArray));
verify(mAppboyUser, Mockito.never()).setCustomAttributeArray(refEq(testName), aryEq(emptyArray));
}

@Test
public void testIdentifyGender() {
Traits traits = createTraits("userId");
Expand Down Expand Up @@ -216,6 +252,14 @@ public void testTrackLogsPurchaseForOrderCompletedEvent() {
verifyNoMoreAppboyInteractions();
}

@Test
public void testTrackLogsPurchaseForCompletedOrderEvent() {
TrackPayload trackPayload = getBasicTrackPayloadWithEventAndProps("Completed Order", null);
mIntegration.track(trackPayload);
verify(mAppboy).logPurchase("Completed Order", "USD", new BigDecimal("0.0"));
verifyNoMoreAppboyInteractions();
}

@Test
public void testTrackLogsPurchaseForEventWithRevenue() {
Properties purchaseProperties = new Properties();
Expand All @@ -237,6 +281,17 @@ public void testTrackLogsPurchasesForOrderCompletedEventWithProducts() {
verifyNoMoreAppboyInteractions();
}

@Test
public void testTrackLogsPurchasesForCompletedOrderEventWithProducts() {
Properties purchaseProperties = new Properties();
purchaseProperties.putProducts(new Properties.Product("id1", "sku1", 10), new Properties.Product("id2", "sku2", 12));
TrackPayload trackPayload = getBasicTrackPayloadWithEventAndProps("Completed Order", purchaseProperties);
mIntegration.track(trackPayload);
verify(mAppboy).logPurchase(Mockito.eq("id1"), Mockito.eq("USD"), Mockito.eq(new BigDecimal("10.0")), Mockito.any(AppboyProperties.class));
verify(mAppboy).logPurchase(Mockito.eq("id2"), Mockito.eq("USD"), Mockito.eq(new BigDecimal("12.0")), Mockito.any(AppboyProperties.class));
verifyNoMoreAppboyInteractions();
}

@Test
public void testTrackLogsPurchasesForEventWithRevenueWithProducts() {
Properties purchaseProperties = new Properties();
Expand All @@ -259,6 +314,16 @@ public void testTrackLogsPurchaseForOrderCompletedEventWithCustomCurrency() {
verifyNoMoreAppboyInteractions();
}

@Test
public void testTrackLogsPurchaseForCompletedOrderEventWithCustomCurrency() {
Properties purchaseProperties = new Properties();
purchaseProperties.putCurrency("JPY");
TrackPayload trackPayload = getBasicTrackPayloadWithEventAndProps("Completed Order", purchaseProperties);
mIntegration.track(trackPayload);
verify(mAppboy).logPurchase("Completed Order", "JPY", new BigDecimal("0.0"));
verifyNoMoreAppboyInteractions();
}

@Test
public void testTrackLogsPurchaseForEventWithRevenueWithCustomCurrency() {
Properties purchaseProperties = new Properties();
Expand Down
Loading

0 comments on commit b9a25f8

Please sign in to comment.