package com.mopub.mobileads; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.view.View; import android.view.ViewGroup; import android.webkit.WebViewClient; import android.widget.FrameLayout; import com.mopub.common.AdReport; import com.mopub.common.test.support.SdkTestRunner; import com.mopub.mobileads.test.support.TestHtmlInterstitialWebViewFactory; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.robolectric.Robolectric; import org.robolectric.shadows.ShadowLocalBroadcastManager; 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.EventForwardingBroadcastReceiverTest.getIntentForActionAndIdentifier; import static com.mopub.common.DataKeys.CLICKTHROUGH_URL_KEY; import static com.mopub.common.DataKeys.HTML_RESPONSE_BODY_KEY; import static com.mopub.common.DataKeys.REDIRECT_URL_KEY; import static com.mopub.common.DataKeys.SCROLLABLE_KEY; import static com.mopub.mobileads.HtmlInterstitialWebView.MoPubUriJavascriptFireFinishLoadListener; import static com.mopub.mobileads.MoPubErrorCode.UNSPECIFIED; import static org.fest.assertions.api.Assertions.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.robolectric.Robolectric.shadowOf; @RunWith(SdkTestRunner.class) public class MoPubActivityTest { private static final String EXPECTED_HTML_DATA = "htmlData"; private static final boolean EXPECTED_IS_SCROLLABLE = true; @Mock private AdReport mockAdReport; private static final String EXPECTED_REDIRECT_URL = "redirectUrl"; private static final String EXPECTED_CLICKTHROUGH_URL = "http://expected_url"; @Mock private BroadcastReceiver broadcastReceiver; private long testBroadcastIdentifier = 2222; private HtmlInterstitialWebView htmlInterstitialWebView; private CustomEventInterstitialListener customEventInterstitialListener; private MoPubActivity subject; @Before public void setUp() throws Exception { htmlInterstitialWebView = TestHtmlInterstitialWebViewFactory.getSingletonMock(); resetMockedView(htmlInterstitialWebView); Context context = Robolectric.buildActivity(Activity.class).create().get(); Intent moPubActivityIntent = MoPubActivity.createIntent(context, EXPECTED_HTML_DATA, mockAdReport, EXPECTED_IS_SCROLLABLE, EXPECTED_REDIRECT_URL, EXPECTED_CLICKTHROUGH_URL, testBroadcastIdentifier); subject = Robolectric.buildActivity(MoPubActivity.class).withIntent(moPubActivityIntent).create().get(); customEventInterstitialListener = mock(CustomEventInterstitialListener.class); resetMockedView(htmlInterstitialWebView); } @Test public void preRenderHtml_shouldPreloadTheHtml() throws Exception { String htmlData = "this is nonsense"; MoPubActivity.preRenderHtml(subject, mockAdReport, customEventInterstitialListener, htmlData); verify(htmlInterstitialWebView).enablePlugins(eq(false)); verify(htmlInterstitialWebView).addMoPubUriJavascriptInterface(any(MoPubUriJavascriptFireFinishLoadListener.class)); verify(htmlInterstitialWebView).loadHtmlResponse(htmlData); } @Test public void preRenderHtml_shouldHaveAWebViewClientThatForwardsFinishLoad() throws Exception { MoPubActivity.preRenderHtml(subject, mockAdReport, customEventInterstitialListener, null); ArgumentCaptor<WebViewClient> webViewClientCaptor = ArgumentCaptor.forClass(WebViewClient.class); verify(htmlInterstitialWebView).setWebViewClient(webViewClientCaptor.capture()); WebViewClient webViewClient = webViewClientCaptor.getValue(); webViewClient.shouldOverrideUrlLoading(null, "mopub://finishLoad"); verify(customEventInterstitialListener).onInterstitialLoaded(); verify(customEventInterstitialListener, never()).onInterstitialFailed(any(MoPubErrorCode.class)); } @Test public void preRenderHtml_shouldHaveAWebViewClientThatForwardsFailLoad() throws Exception { MoPubActivity.preRenderHtml(subject, mockAdReport, customEventInterstitialListener, null); ArgumentCaptor<WebViewClient> webViewClientCaptor = ArgumentCaptor.forClass(WebViewClient.class); verify(htmlInterstitialWebView).setWebViewClient(webViewClientCaptor.capture()); WebViewClient webViewClient = webViewClientCaptor.getValue(); webViewClient.shouldOverrideUrlLoading(null, "mopub://failLoad"); verify(customEventInterstitialListener, never()).onInterstitialLoaded(); verify(customEventInterstitialListener).onInterstitialFailed(any(MoPubErrorCode.class)); } @Test public void preRenderHtml_shouldHaveAMoPubUriInterfaceThatForwardsOnInterstitialLoaded() throws Exception { MoPubActivity.preRenderHtml(subject, mockAdReport, customEventInterstitialListener, null); ArgumentCaptor<MoPubUriJavascriptFireFinishLoadListener> moPubUriJavascriptFireFinishLoadListenerCaptor = ArgumentCaptor.forClass(MoPubUriJavascriptFireFinishLoadListener.class); verify(htmlInterstitialWebView).addMoPubUriJavascriptInterface(moPubUriJavascriptFireFinishLoadListenerCaptor.capture()); MoPubUriJavascriptFireFinishLoadListener moPubUriJavascriptFireFinishLoadListener = moPubUriJavascriptFireFinishLoadListenerCaptor.getValue(); moPubUriJavascriptFireFinishLoadListener.onInterstitialLoaded(); verify(customEventInterstitialListener).onInterstitialLoaded(); } @Test public void onCreate_shouldSetContentView() throws Exception { subject.onCreate(null); assertThat(getContentView().getChildCount()).isEqualTo(1); } @Test public void onCreate_shouldLayoutWebView() throws Exception { subject.onCreate(null); ArgumentCaptor<FrameLayout.LayoutParams> captor = ArgumentCaptor.forClass(FrameLayout.LayoutParams.class); verify(htmlInterstitialWebView).setLayoutParams(captor.capture()); FrameLayout.LayoutParams actualLayoutParams = captor.getValue(); assertThat(actualLayoutParams.width).isEqualTo(FrameLayout.LayoutParams.MATCH_PARENT); assertThat(actualLayoutParams.height).isEqualTo(FrameLayout.LayoutParams.MATCH_PARENT); } @Test public void getAdView_shouldReturnPopulatedHtmlWebView() throws Exception { View adView = subject.getAdView(); assertThat(adView).isSameAs(htmlInterstitialWebView); assertThat(TestHtmlInterstitialWebViewFactory.getLatestListener()).isNotNull(); assertThat(TestHtmlInterstitialWebViewFactory.getLatestIsScrollable()).isEqualTo(EXPECTED_IS_SCROLLABLE); assertThat(TestHtmlInterstitialWebViewFactory.getLatestClickthroughUrl()).isEqualTo(EXPECTED_CLICKTHROUGH_URL); assertThat(TestHtmlInterstitialWebViewFactory.getLatestRedirectUrl()).isEqualTo(EXPECTED_REDIRECT_URL); verify(htmlInterstitialWebView).loadHtmlResponse(EXPECTED_HTML_DATA); } @Test public void onDestroy_shouldDestroyMoPubView() throws Exception { subject.onCreate(null); subject.onDestroy(); verify(htmlInterstitialWebView).destroy(); assertThat(getContentView().getChildCount()).isEqualTo(0); } @Test public void onDestroy_shouldFireJavascriptWebviewDidClose() throws Exception { subject.onCreate(null); subject.onDestroy(); verify(htmlInterstitialWebView).loadUrl(eq("javascript:webviewDidClose();")); } @Test public void start_shouldStartMoPubActivityWithCorrectParameters() throws Exception { MoPubActivity.start(subject, "expectedResponse", mockAdReport, true, "redirectUrl", "clickthroughUrl", testBroadcastIdentifier); Intent nextStartedActivity = Robolectric.getShadowApplication().getNextStartedActivity(); assertThat(nextStartedActivity.getStringExtra(HTML_RESPONSE_BODY_KEY)).isEqualTo("expectedResponse"); assertThat(nextStartedActivity.getBooleanExtra(SCROLLABLE_KEY, false)).isTrue(); assertThat(nextStartedActivity.getStringExtra(REDIRECT_URL_KEY)).isEqualTo("redirectUrl"); assertThat(nextStartedActivity.getStringExtra(CLICKTHROUGH_URL_KEY)).isEqualTo("clickthroughUrl"); assertThat(nextStartedActivity.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK).isNotEqualTo(0); assertThat(nextStartedActivity.getComponent().getClassName()).isEqualTo("com.mopub.mobileads.MoPubActivity"); } @Test public void getAdView_shouldCreateHtmlInterstitialWebViewAndLoadResponse() throws Exception { subject.getAdView(); assertThat(TestHtmlInterstitialWebViewFactory.getLatestListener()).isNotNull(); assertThat(TestHtmlInterstitialWebViewFactory.getLatestIsScrollable()).isEqualTo(EXPECTED_IS_SCROLLABLE); assertThat(TestHtmlInterstitialWebViewFactory.getLatestRedirectUrl()).isEqualTo(EXPECTED_REDIRECT_URL); assertThat(TestHtmlInterstitialWebViewFactory.getLatestClickthroughUrl()).isEqualTo(EXPECTED_CLICKTHROUGH_URL); verify(htmlInterstitialWebView).loadHtmlResponse(EXPECTED_HTML_DATA); } @Test public void getAdView_shouldSetUpForBroadcastingClicks() throws Exception { subject.getAdView(); BroadcastReceiver broadcastReceiver = mock(BroadcastReceiver.class); ShadowLocalBroadcastManager.getInstance(subject).registerReceiver(broadcastReceiver, getHtmlInterstitialIntentFilter()); TestHtmlInterstitialWebViewFactory.getLatestListener().onInterstitialClicked(); ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); verify(broadcastReceiver).onReceive(any(Context.class), intentCaptor.capture()); Intent intent = intentCaptor.getValue(); assertThat(intent.getAction()).isEqualTo(ACTION_INTERSTITIAL_CLICK); } @Test public void getAdView_shouldSetUpForBroadcastingFail() throws Exception { subject.getAdView(); BroadcastReceiver broadcastReceiver = mock(BroadcastReceiver.class); ShadowLocalBroadcastManager.getInstance(subject).registerReceiver(broadcastReceiver, getHtmlInterstitialIntentFilter()); TestHtmlInterstitialWebViewFactory.getLatestListener().onInterstitialFailed(UNSPECIFIED); ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); verify(broadcastReceiver).onReceive(any(Context.class), intentCaptor.capture()); Intent intent = intentCaptor.getValue(); assertThat(intent.getAction()).isEqualTo(ACTION_INTERSTITIAL_FAIL); assertThat(shadowOf(subject).isFinishing()).isTrue(); } @Test public void broadcastingInterstitialListener_onInterstitialLoaded_shouldCallJavascriptWebViewDidAppear() throws Exception { MoPubActivity.BroadcastingInterstitialListener broadcastingInterstitialListener = ((MoPubActivity) subject).new BroadcastingInterstitialListener(); broadcastingInterstitialListener.onInterstitialLoaded(); verify(htmlInterstitialWebView).loadUrl(eq("javascript:webviewDidAppear();")); } @Test public void broadcastingInterstitialListener_onInterstitialFailed_shouldBroadcastFailAndFinish() throws Exception { Intent expectedIntent = getIntentForActionAndIdentifier(ACTION_INTERSTITIAL_FAIL, testBroadcastIdentifier); ShadowLocalBroadcastManager.getInstance(subject).registerReceiver(broadcastReceiver, getHtmlInterstitialIntentFilter()); MoPubActivity.BroadcastingInterstitialListener broadcastingInterstitialListener = ((MoPubActivity) subject).new BroadcastingInterstitialListener(); broadcastingInterstitialListener.onInterstitialFailed(null); verify(broadcastReceiver).onReceive(any(Context.class), eq(expectedIntent)); assertThat(shadowOf(subject).isFinishing()).isTrue(); } @Test public void broadcastingInterstitialListener_onInterstitialClicked_shouldBroadcastClick() throws Exception { Intent expectedIntent = getIntentForActionAndIdentifier(ACTION_INTERSTITIAL_CLICK, testBroadcastIdentifier); ShadowLocalBroadcastManager.getInstance(subject).registerReceiver(broadcastReceiver, getHtmlInterstitialIntentFilter()); MoPubActivity.BroadcastingInterstitialListener broadcastingInterstitialListener = ((MoPubActivity) subject).new BroadcastingInterstitialListener(); broadcastingInterstitialListener.onInterstitialClicked(); verify(broadcastReceiver).onReceive(any(Context.class), eq(expectedIntent)); } @Test public void onCreate_shouldBroadcastInterstitialShow() throws Exception { Intent expectedIntent = getIntentForActionAndIdentifier(ACTION_INTERSTITIAL_SHOW, testBroadcastIdentifier); ShadowLocalBroadcastManager.getInstance(subject).registerReceiver(broadcastReceiver, getHtmlInterstitialIntentFilter()); subject.onCreate(null); verify(broadcastReceiver).onReceive(any(Context.class), eq(expectedIntent)); } @Test public void onDestroy_shouldBroadcastInterstitialDismiss() throws Exception { Intent expectedIntent = getIntentForActionAndIdentifier(ACTION_INTERSTITIAL_DISMISS, testBroadcastIdentifier); ShadowLocalBroadcastManager.getInstance(subject).registerReceiver(broadcastReceiver, getHtmlInterstitialIntentFilter()); subject.onCreate(null); subject.onDestroy(); verify(broadcastReceiver).onReceive(any(Context.class), eq(expectedIntent)); } private FrameLayout getContentView() { return (FrameLayout) ((ViewGroup) subject.findViewById(android.R.id.content)).getChildAt(0); } protected void resetMockedView(View view) { reset(view); when(view.getLayoutParams()).thenReturn( new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT)); } }