package com.mopub.mobileads;
import android.app.Activity;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v4.content.LocalBroadcastManager;
import com.mopub.common.DataKeys;
import com.mopub.common.test.support.SdkTestRunner;
import com.mopub.mobileads.factories.CustomEventInterstitialAdapterFactory;
import org.fest.util.Sets;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.shadows.ShadowLocalBroadcastManager;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import static com.mopub.mobileads.CustomEventInterstitial.CustomEventInterstitialListener;
import static com.mopub.mobileads.EventForwardingBroadcastReceiver.ACTION_INTERSTITIAL_CLICK;
import static com.mopub.mobileads.EventForwardingBroadcastReceiver.ACTION_INTERSTITIAL_DISMISS;
import static com.mopub.mobileads.EventForwardingBroadcastReceiver.ACTION_INTERSTITIAL_FAIL;
import static com.mopub.mobileads.EventForwardingBroadcastReceiver.ACTION_INTERSTITIAL_SHOW;
import static com.mopub.mobileads.EventForwardingBroadcastReceiver.getHtmlInterstitialIntentFilter;
import static com.mopub.mobileads.MoPubInterstitial.InterstitialAdListener;
import static org.fest.assertions.api.Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@RunWith(SdkTestRunner.class)
public class EventForwardingBroadcastReceiverTest {
private CustomEventInterstitialListener customEventInterstitialListener;
private EventForwardingBroadcastReceiver subject;
private Activity context;
private int broadcastIdentifier;
@Before
public void setUp() throws Exception {
customEventInterstitialListener = mock(CustomEventInterstitialListener.class);
broadcastIdentifier = 27027027;
subject = new EventForwardingBroadcastReceiver(customEventInterstitialListener, broadcastIdentifier);
context = new Activity();
}
@Ignore("Difficult with the number of test factories and mocking involved.")
@Test
public void twoDifferentInterstitials_shouldNotHearEachOthersBroadcasts() throws Exception {
final MoPubInterstitial interstitialA = new MoPubInterstitial(context, "adunitid");
final InterstitialAdListener listenerA = mock(InterstitialAdListener.class);
interstitialA.setInterstitialAdListener(listenerA);
final MoPubInterstitial interstitialB = new MoPubInterstitial(context, "adunitid");
final InterstitialAdListener listenerB = mock(InterstitialAdListener.class);
interstitialB.setInterstitialAdListener(listenerB);
Map<String, String> serverExtras = new HashMap<String, String>();
serverExtras.put(DataKeys.HTML_RESPONSE_BODY_KEY, "response");
final CustomEventInterstitialAdapter customEventInterstitialAdapter =
CustomEventInterstitialAdapterFactory.create(
interstitialA,
"com.mopub.mobileads.HtmlInterstitial",
serverExtras, broadcastIdentifier, null);
customEventInterstitialAdapter.loadInterstitial();
verify(listenerA).onInterstitialLoaded(interstitialA);
verify(listenerB, never()).onInterstitialLoaded(any(MoPubInterstitial.class));
interstitialA.onCustomEventInterstitialShown();
verify(listenerA).onInterstitialLoaded(interstitialA);
verify(listenerB, never()).onInterstitialShown(any(MoPubInterstitial.class));
interstitialA.onCustomEventInterstitialClicked();
verify(listenerA).onInterstitialClicked(interstitialA);
verify(listenerB, never()).onInterstitialClicked(any(MoPubInterstitial.class));
interstitialA.onCustomEventInterstitialDismissed();
verify(listenerA).onInterstitialDismissed(interstitialA);
verify(listenerB, never()).onInterstitialDismissed(any(MoPubInterstitial.class));
}
@Test
public void constructor_shouldSetIntentFilter() throws Exception {
Set<String> expectedActions = Sets.newLinkedHashSet(
ACTION_INTERSTITIAL_FAIL,
ACTION_INTERSTITIAL_SHOW,
ACTION_INTERSTITIAL_DISMISS,
ACTION_INTERSTITIAL_CLICK
);
final IntentFilter intentFilter = EventForwardingBroadcastReceiver.getHtmlInterstitialIntentFilter();
final Iterator<String> actionIterator = intentFilter.actionsIterator();
assertThat(intentFilter.countActions()).isEqualTo(4);
while (actionIterator.hasNext()) {
assertThat(expectedActions.contains(actionIterator.next()));
}
}
@Test
public void onReceive_whenActionInterstitialFail_shouldNotifyListener() throws Exception {
Intent intent = getIntentForActionAndIdentifier(ACTION_INTERSTITIAL_CLICK, broadcastIdentifier);
subject.onReceive(context, intent);
verify(customEventInterstitialListener).onInterstitialClicked();
}
@Test
public void onReceive_whenActionInterstitialShow_shouldNotifyListener() throws Exception {
Intent intent = getIntentForActionAndIdentifier(ACTION_INTERSTITIAL_SHOW, broadcastIdentifier);
subject.onReceive(context, intent);
verify(customEventInterstitialListener).onInterstitialShown();
}
@Test
public void onReceive_whenActionInterstitialDismiss_shouldNotifyListener() throws Exception {
Intent intent = getIntentForActionAndIdentifier(ACTION_INTERSTITIAL_DISMISS, broadcastIdentifier);
subject.onReceive(context, intent);
verify(customEventInterstitialListener).onInterstitialDismissed();
}
@Test
public void onReceive_whenActionInterstitialClick_shouldNotifyListener() throws Exception {
Intent intent = getIntentForActionAndIdentifier(ACTION_INTERSTITIAL_CLICK, broadcastIdentifier);
subject.onReceive(context, intent);
verify(customEventInterstitialListener).onInterstitialClicked();
}
@Test
public void onReceive_withIncorrectBroadcastIdentifier_shouldDoNothing() throws Exception {
long incorrectBroadcastIdentifier = broadcastIdentifier + 1;
Intent fail = getIntentForActionAndIdentifier(ACTION_INTERSTITIAL_FAIL, incorrectBroadcastIdentifier);
Intent show = getIntentForActionAndIdentifier(ACTION_INTERSTITIAL_SHOW, incorrectBroadcastIdentifier);
Intent click = getIntentForActionAndIdentifier(ACTION_INTERSTITIAL_CLICK, incorrectBroadcastIdentifier);
Intent dismiss = getIntentForActionAndIdentifier(ACTION_INTERSTITIAL_DISMISS, incorrectBroadcastIdentifier);
subject.onReceive(context, fail);
subject.onReceive(context, show);
subject.onReceive(context, click);
subject.onReceive(context, dismiss);
verifyNoMoreInteractions(customEventInterstitialListener);
}
@Test
public void onReceiver_whenCustomEventInterstitialListenerIsNull_shouldNotBlowUp() throws Exception {
Intent intent = new Intent(ACTION_INTERSTITIAL_SHOW);
subject = new EventForwardingBroadcastReceiver(null, broadcastIdentifier);
subject.onReceive(context, intent);
// pass
}
@Test
public void register_shouldEnableReceivingBroadcasts() throws Exception {
subject.register(context);
Intent intent = getIntentForActionAndIdentifier(ACTION_INTERSTITIAL_SHOW, broadcastIdentifier);
ShadowLocalBroadcastManager.getInstance(context).sendBroadcast(intent);
verify(customEventInterstitialListener).onInterstitialShown();
}
@Test
public void unregister_shouldDisableReceivingBroadcasts() throws Exception {
subject.register(context);
subject.unregister();
Intent intent = getIntentForActionAndIdentifier(ACTION_INTERSTITIAL_SHOW, broadcastIdentifier);
ShadowLocalBroadcastManager.getInstance(context).sendBroadcast(intent);
verify(customEventInterstitialListener, never()).onInterstitialShown();
}
@Test
public void unregister_whenNotRegistered_shouldNotBlowUp() throws Exception {
subject.unregister();
// pass
}
@Test
public void unregister_shouldNotLeakTheContext() throws Exception {
subject.register(context);
subject.unregister();
LocalBroadcastManager.getInstance(context).registerReceiver(subject, getHtmlInterstitialIntentFilter());
subject.unregister();
// Unregister shouldn't know the context any more and so should not have worked
Intent intent = getIntentForActionAndIdentifier(ACTION_INTERSTITIAL_SHOW, broadcastIdentifier);
ShadowLocalBroadcastManager.getInstance(context).sendBroadcast(intent);
verify(customEventInterstitialListener).onInterstitialShown();
}
public static Intent getIntentForActionAndIdentifier(final String action, final long broadcastIdentifier) {
final Intent intent = new Intent(action);
intent.putExtra("broadcastIdentifier", broadcastIdentifier);
return intent;
}
}