package bf.io.openshop;
import android.content.Context;
import android.os.Bundle;
import com.facebook.appevents.AppEventsLogger;
import com.google.android.gms.analytics.GoogleAnalytics;
import com.google.android.gms.analytics.Tracker;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import bf.io.openshop.entities.Shop;
import bf.io.openshop.entities.cart.Cart;
import bf.io.openshop.entities.cart.CartProductItem;
import bf.io.openshop.entities.cart.CartProductItemVariant;
import bf.io.openshop.entities.delivery.Shipping;
import bf.io.openshop.utils.Analytics;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyDouble;
import static org.mockito.Matchers.anyMap;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.notNull;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.powermock.api.mockito.PowerMockito.doNothing;
import static org.powermock.api.mockito.PowerMockito.doReturn;
import static org.powermock.api.mockito.PowerMockito.verifyPrivate;
import static org.powermock.api.mockito.PowerMockito.verifyStatic;
import static org.powermock.api.mockito.PowerMockito.when;
/**
* Simple unit tests for {@link Analytics} class.
* <p/>
* Careful: Because it is testing static class with static methods and static fields.
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({Analytics.class, GoogleAnalytics.class, AppEventsLogger.class, SettingsMy.class})
public class AnalyticsUnitTest {
@Mock
Context mockContext;
@Mock
GoogleAnalytics mockAnalytics;
@Mock
Tracker mockTracker;
@Mock
Tracker mockTrackerApp;
@Mock
AppEventsLogger mockAppEventsLogger;
Shop testShop = new Shop("testShop", "UA-test");
@Before
public void preparation() throws Exception {
// clean up
MockitoAnnotations.initMocks(this); // for case them used another runner
PowerMockito.spy(Analytics.class);
Whitebox.setInternalState(Analytics.class, "mTrackers", new HashMap<>());
Whitebox.setInternalState(Analytics.class, "facebookLogger", (Object[]) null);
Whitebox.setInternalState(Analytics.class, "campaignUri", (Object[]) null);
}
private void prepareMockedFields() throws Exception {
// Mock responses
PowerMockito.mockStatic(GoogleAnalytics.class);
PowerMockito.mockStatic(AppEventsLogger.class);
doReturn(mockAnalytics).when(GoogleAnalytics.class, "getInstance", mockContext);
doReturn(mockAppEventsLogger).when(AppEventsLogger.class, "newLogger", anyObject());
when(mockAnalytics.newTracker(R.xml.global_tracker)).thenReturn(mockTracker);
when(mockAnalytics.newTracker(testShop.getGoogleUa())).thenReturn(mockTrackerApp);
}
@Test
public void prepareGlobalTrackerAndFbLoggerTest() throws Exception {
// Mock responses
PowerMockito.mockStatic(GoogleAnalytics.class);
PowerMockito.mockStatic(AppEventsLogger.class);
doReturn(mockAnalytics).when(GoogleAnalytics.class, "getInstance", mockContext);
doReturn(mockAppEventsLogger).when(AppEventsLogger.class, "newLogger", anyObject());
when(mockAnalytics.newTracker(R.xml.global_tracker)).thenReturn(mockTracker);
// Tested method invocation
Analytics.prepareTrackersAndFbLogger(null, mockContext);
// Verify results
verifyStatic(times(1));
GoogleAnalytics.getInstance(mockContext);
verifyStatic(times(1));
Analytics.deleteAppTrackers();
verify(mockAnalytics, times(1)).newTracker(R.xml.global_tracker);
verify(mockTracker, times(1)).enableAutoActivityTracking(true);
verify(mockTracker, times(1)).enableExceptionReporting(true);
verify(mockTracker, times(1)).enableAdvertisingIdCollection(true);
verifyNoMoreInteractions(mockTracker);
HashMap<String, Tracker> trackersField = Whitebox.getInternalState(Analytics.class, "mTrackers");
assertEquals(trackersField.size(), 1);
AppEventsLogger appEventsLoggerField = Whitebox.getInternalState(Analytics.class, "facebookLogger");
assertNotEquals(appEventsLoggerField, null);
}
@Test
public void prepareTrackersAndFbLoggerTest() throws Exception {
prepareMockedFields();
// Tested method invocation
Analytics.prepareTrackersAndFbLogger(testShop, mockContext);
// Verify results
verifyStatic(times(1));
GoogleAnalytics.getInstance(mockContext);
verifyStatic(never());
Analytics.deleteAppTrackers();
verify(mockAnalytics, times(1)).newTracker(testShop.getGoogleUa());
verify(mockAnalytics, times(1)).newTracker(R.xml.global_tracker);
verify(mockTrackerApp, times(1)).enableAutoActivityTracking(true);
verify(mockTrackerApp, times(1)).enableExceptionReporting(false);
verify(mockTrackerApp, times(1)).enableAdvertisingIdCollection(true);
verifyNoMoreInteractions(mockTrackerApp);
verify(mockTracker, times(1)).enableAutoActivityTracking(true);
verify(mockTracker, times(1)).enableExceptionReporting(true);
verify(mockTracker, times(1)).enableAdvertisingIdCollection(true);
verifyNoMoreInteractions(mockTracker);
HashMap<String, Tracker> trackersField = Whitebox.getInternalState(Analytics.class, "mTrackers");
assertEquals(trackersField.size(), 2);
AppEventsLogger appEventsLoggerField = Whitebox.getInternalState(Analytics.class, "facebookLogger");
assertNotEquals(appEventsLoggerField, null);
}
@Test
public void deleteAppTrackersTest() throws Exception {
prepareMockedFields();
Analytics.prepareTrackersAndFbLogger(testShop, mockContext);
// Check size before deletion
HashMap<String, Tracker> trackersField = Whitebox.getInternalState(Analytics.class, "mTrackers");
assertEquals(trackersField.size(), 2);
// Tested method invocation
Analytics.deleteAppTrackers();
// Verify final size
trackersField = Whitebox.getInternalState(Analytics.class, "mTrackers");
assertEquals(trackersField.size(), 1);
}
@Test
public void setCampaignUriStringTest() throws Exception {
String testCampaignUri = "www.site.com&utm_medium=email&utm_source=Newsletter";
doNothing().when(Analytics.class, "sendCampaignInfo");
// Check before set
String campaignUriField = Whitebox.getInternalState(Analytics.class, "campaignUri");
assertEquals(campaignUriField, null);
Analytics.setCampaignUriString(testCampaignUri);
verifyPrivate(Analytics.class, never()).invoke("sendCampaignInfo");
campaignUriField = Whitebox.getInternalState(Analytics.class, "campaignUri");
assertEquals(campaignUriField, testCampaignUri);
}
@Test
public void setCampaignUriStringTest2() throws Exception {
prepareMockedFields();
Analytics.prepareTrackersAndFbLogger(testShop, mockContext);
String testCampaignUri = "www.site.com&utm_medium=email&utm_source=Newsletter";
// Check before set
String campaignUriField = Whitebox.getInternalState(Analytics.class, "campaignUri");
assertEquals(campaignUriField, null);
Analytics.setCampaignUriString(testCampaignUri);
// Verify values
campaignUriField = Whitebox.getInternalState(Analytics.class, "campaignUri");
assertEquals(campaignUriField, testCampaignUri);
verifyPrivate(Analytics.class, times(2)).invoke("sendCampaignInfo");
// Verify corresponding tracker calls
verify(mockTracker, times(1)).send(anyMap());
verify(mockTrackerApp, times(1)).send(anyMap());
}
@Test
public void logProductViewTest() throws Exception {
prepareMockedFields();
Analytics.prepareTrackersAndFbLogger(testShop, mockContext);
long testRemoteId = 123456;
String testName = "test product";
Analytics.logProductView(testRemoteId, testName);
verify(mockAppEventsLogger, times(1)).logEvent((String) notNull(), (Bundle) notNull());
verify(mockTracker, times(1)).send((Map<String, String>) notNull());
verify(mockTrackerApp, times(1)).send((Map<String, String>) notNull());
}
@Test
public void logAddProductToCartTest() throws Exception {
prepareMockedFields();
Analytics.prepareTrackersAndFbLogger(testShop, mockContext);
long testRemoteId = 123456;
String testName = "test product";
double testDiscountPrice = 52.35;
Analytics.logAddProductToCart(testRemoteId, testName, testDiscountPrice);
verify(mockAppEventsLogger, times(1)).logEvent((String) notNull(), anyDouble(), (Bundle) notNull());
verify(mockTracker, times(1)).send((Map<String, String>) notNull());
verify(mockTrackerApp, times(1)).send((Map<String, String>) notNull());
}
@Test
public void logShopChangeTest() throws Exception {
prepareMockedFields();
Analytics.prepareTrackersAndFbLogger(testShop, mockContext);
Shop testShop1 = new Shop("shop1", null);
Shop testShop2 = new Shop("shop2", null);
Analytics.logShopChange(testShop1, testShop2);
verify(mockAppEventsLogger, times(1)).logEvent((String) notNull(), (Bundle) notNull());
verify(mockTracker, times(1)).send((Map<String, String>) notNull());
verify(mockTrackerApp, times(1)).send((Map<String, String>) notNull());
}
@Test
public void logOpenedByNotificationTest() throws Exception {
prepareMockedFields();
Analytics.prepareTrackersAndFbLogger(testShop, mockContext);
Analytics.logOpenedByNotification("testContent");
PowerMockito.verifyNoMoreInteractions(mockAppEventsLogger);
verify(mockTracker, times(1)).send((Map<String, String>) notNull());
verify(mockTrackerApp, times(1)).send((Map<String, String>) notNull());
}
@Test
public void logCategoryViewBadFormatTest() throws Exception {
prepareMockedFields();
Analytics.prepareTrackersAndFbLogger(testShop, mockContext);
String testName = "test product";
Analytics.logCategoryView(0, testName, false);
PowerMockito.verifyNoMoreInteractions(mockAppEventsLogger);
verify(mockTracker, never()).send((Map<String, String>) notNull());
verify(mockTrackerApp, never()).send((Map<String, String>) notNull());
}
@Test
public void logCategoryViewOkTest() throws Exception {
prepareMockedFields();
Analytics.prepareTrackersAndFbLogger(testShop, mockContext);
String testName = "test product";
Analytics.logCategoryView(123, testName, false);
verify(mockAppEventsLogger, times(1)).logEvent((String) notNull(), (Bundle) notNull());
verify(mockTracker, times(1)).send((Map<String, String>) notNull());
verify(mockTrackerApp, times(1)).send((Map<String, String>) notNull());
}
@Test
public void logOrderCreatedEventTest() throws Exception {
prepareMockedFields();
Analytics.prepareTrackersAndFbLogger(testShop, mockContext);
PowerMockito.mockStatic(SettingsMy.class);
doReturn(testShop).when(SettingsMy.class, "getActualNonNullShop", any());
// Prepare data
Shipping testShipping = new Shipping();
testShipping.setPrice(100);
Cart testCart = new Cart();
testCart.setCurrency("EUR");
List<CartProductItem> testCartProductItems = new ArrayList<>();
CartProductItem cartProductItem1 = new CartProductItem();
cartProductItem1.setId(111);
cartProductItem1.setQuantity(2);
CartProductItemVariant cartProductItemVariant1 = new CartProductItemVariant();
cartProductItemVariant1.setName("variant1");
cartProductItemVariant1.setPrice(100);
cartProductItemVariant1.setDiscountPrice(50);
cartProductItemVariant1.setRemoteId(1111);
cartProductItemVariant1.setCategory(11);
cartProductItem1.setVariant(cartProductItemVariant1);
testCartProductItems.add(cartProductItem1);
CartProductItem cartProductItem2 = new CartProductItem();
cartProductItem2.setId(112);
cartProductItem2.setQuantity(2);
CartProductItemVariant cartProductItemVariant2 = new CartProductItemVariant();
cartProductItemVariant2.setName("variant2");
cartProductItemVariant2.setPrice(150);
cartProductItemVariant2.setDiscountPrice(0);
cartProductItemVariant2.setRemoteId(1122);
cartProductItemVariant2.setCategory(11);
cartProductItem2.setVariant(cartProductItemVariant2);
testCartProductItems.add(cartProductItem2);
testCart.setItems(testCartProductItems);
// Execute
Analytics.logOrderCreatedEvent(testCart, "123456", (double) 500, testShipping);
// Verify
verify(mockAppEventsLogger, times(4)).logEvent((String) notNull(), anyDouble(), (Bundle) notNull());
verify(mockTracker, times(4)).send((Map<String, String>) notNull());
verify(mockTrackerApp, times(4)).send((Map<String, String>) notNull());
}
}