package com.mopub.mraid;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.webkit.WebViewClient;
import com.mopub.common.AdReport;
import com.mopub.common.test.support.SdkTestRunner;
import com.mopub.mraid.MraidBridge.MraidBridgeListener;
import com.mopub.mraid.MraidBridge.MraidWebView;
import com.mopub.mraid.MraidNativeCommandHandler.MraidCommandFailureListener;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.robolectric.Robolectric;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import static org.fest.assertions.api.Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyMapOf;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.startsWith;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(SdkTestRunner.class)
public class MraidBridgeTest {
@Mock MraidNativeCommandHandler mockNativeCommandHandler;
@Mock MraidBridgeListener mockBridgeListener;
@Mock AdReport mockAdReport;
@Mock(answer = Answers.RETURNS_DEEP_STUBS) MraidWebView mockBannerWebView;
@Mock(answer = Answers.RETURNS_DEEP_STUBS) MraidWebView mockInterstitialWebView;
@Captor ArgumentCaptor<WebViewClient> bannerWebViewClientCaptor;
private Activity activity;
private MraidBridge subjectBanner;
private MraidBridge subjectInterstitial;
@Before
public void setUp() {
activity = Robolectric.buildActivity(Activity.class).create().get();
subjectBanner = new MraidBridge(mockAdReport, PlacementType.INLINE, mockNativeCommandHandler);
subjectBanner.setMraidBridgeListener(mockBridgeListener);
subjectBanner.attachView(mockBannerWebView);
subjectInterstitial = new MraidBridge(mockAdReport, PlacementType.INTERSTITIAL, mockNativeCommandHandler);
subjectInterstitial.setMraidBridgeListener(mockBridgeListener);
subjectInterstitial.attachView(mockInterstitialWebView);
verify(mockBannerWebView).setWebViewClient(bannerWebViewClientCaptor.capture());
reset(mockBannerWebView);
}
@Test
public void attachView_thenDetach_shouldSetMRaidWebView_thenShouldClear() {
assertThat(subjectBanner.getMraidWebView()).isEqualTo(mockBannerWebView);
subjectBanner.detach();
assertThat(subjectBanner.getMraidWebView()).isNull();
}
@Test
public void attachView_thenOnPageFinished_shouldFireReady() {
bannerWebViewClientCaptor.getValue().onPageFinished(mockBannerWebView, "fake://url");
verify(mockBridgeListener).onPageLoaded();
}
@Test
public void attachView_thenOnPageFinished_twice_shouldNotFireReadySecondTime() {
bannerWebViewClientCaptor.getValue().onPageFinished(mockBannerWebView, "fake://url");
bannerWebViewClientCaptor.getValue().onPageFinished(mockBannerWebView, "fake://url2");
verify(mockBridgeListener, times(1)).onPageLoaded();
}
@Test
public void attachView_thenSetContentHtml_shouldCallLoadDataWithBaseURL() {
subjectBanner.setContentHtml("test-html");
verify(mockBannerWebView).loadDataWithBaseURL(
null, "test-html", "text/html", "UTF-8", null);
}
@Test
public void handleShouldOverrideUrl_invalidUrl_shouldFireErrorEvent() {
boolean result = subjectBanner.handleShouldOverrideUrl("bad bad bad");
verify(mockBannerWebView).loadUrl(startsWith(
"javascript:window.mraidbridge.notifyErrorEvent"));
assertThat(result).isTrue();
}
@Test
public void handleShouldOverrideUrl_mopubUrl_shouldNeverLoadUrl_shouldReturnTrue() {
boolean result = subjectBanner.handleShouldOverrideUrl("mopub://special-mopub-command");
verify(mockBannerWebView, never()).loadUrl(anyString());
assertThat(result).isTrue();
}
@Test
public void handleShouldOverrideUrl_mraidUrl_invalid_shouldFireErrorEvent_shouldReturnTrue() {
boolean result = subjectBanner.handleShouldOverrideUrl("mraid://bad-command");
verify(mockBannerWebView).loadUrl(startsWith(
"javascript:window.mraidbridge.notifyErrorEvent"));
assertThat(result).isTrue();
}
@Test
public void handleShouldOverrideUrl_smsUrl_notClicked_shouldReturnFalse() {
boolean result = subjectBanner.handleShouldOverrideUrl("sms://123456789");
assertThat(result).isFalse();
}
@Test
public void handleShouldOverrideUrl_smsUrl_clicked_shouldStartActivity() {
subjectBanner.setClicked(true);
reset(mockBannerWebView);
when(mockBannerWebView.getContext()).thenReturn(activity);
boolean result = subjectBanner.handleShouldOverrideUrl("sms://123456789");
Intent startedIntent = Robolectric.getShadowApplication().getNextStartedActivity();
assertThat(startedIntent).isNotNull();
assertThat(startedIntent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK).isNotEqualTo(0);
assertThat(startedIntent.getComponent()).isNull();
assertThat(result).isTrue();
}
@Test
public void handleShouldOverrideUrl_normalUrl_shouldReturnFalse() {
boolean result = subjectBanner.handleShouldOverrideUrl("http://www.mopub.com");
assertThat(result).isFalse();
}
@Test(expected = MraidCommandException.class)
public void runCommand_requiresClick_notClicked_shouldThrowException()
throws MraidCommandException {
subjectBanner = new MraidBridge(mockAdReport, PlacementType.INLINE);
subjectBanner.attachView(mockBannerWebView);
subjectBanner.setClicked(false);
Map<String, String> params = new HashMap<String, String>();
params.put("uri", "http://valid-url");
subjectBanner.runCommand(MraidJavascriptCommand.PLAY_VIDEO, params);
}
public void runCommand_requiresClick_clicked_shouldNotThrowException()
throws MraidCommandException {
subjectBanner.setClicked(true);
Map<String, String> params = new HashMap<String, String>();
params.put("uri", "http://valid-url");
subjectBanner.runCommand(MraidJavascriptCommand.PLAY_VIDEO, params);
}
@Test(expected = MraidCommandException.class)
public void runCommand_interstitial_requiresClick_notClicked_shouldThrowException()
throws MraidCommandException {
subjectInterstitial.setClicked(false);
Map<String, String> params = new HashMap<String, String>();
params.put("uri", "http://valid-url");
subjectInterstitial.runCommand(MraidJavascriptCommand.OPEN, params);
}
@Test
public void runCommand_interstitial_requiresClick_clicked_shouldNotThrowException()
throws MraidCommandException {
subjectInterstitial.setClicked(true);
Map<String, String> params = new HashMap<String, String>();
params.put("url", "http://valid-url");
subjectInterstitial.runCommand(MraidJavascriptCommand.OPEN, params);
}
@Test
public void runCommand_close_shouldCallListener()
throws MraidCommandException {
Map<String, String> params = new HashMap<String, String>();
subjectBanner.runCommand(MraidJavascriptCommand.CLOSE, params);
verify(mockBridgeListener).onClose();
}
@Test
public void runCommand_expand_shouldCallListener()
throws MraidCommandException {
subjectBanner.setClicked(true);
Map<String, String> params = new HashMap<String, String>();
params.put("shouldUseCustomClose", "true");
subjectBanner.runCommand(MraidJavascriptCommand.EXPAND, params);
verify(mockBridgeListener).onExpand(null, true);
}
@Test
public void runCommand_expand_withUrl_shouldCallListener()
throws MraidCommandException {
subjectBanner.setClicked(true);
Map<String, String> params = new HashMap<String, String>();
params.put("url", "http://valid-url");
params.put("shouldUseCustomClose", "true");
subjectBanner.runCommand(MraidJavascriptCommand.EXPAND, params);
ArgumentCaptor<URI> uriCaptor = ArgumentCaptor.forClass(URI.class);
verify(mockBridgeListener).onExpand(
uriCaptor.capture(), eq(true));
assertThat(uriCaptor.getValue().toString()).isEqualTo("http://valid-url");
}
@Test
public void runCommand_playVideo_shouldCallListener()
throws MraidCommandException {
subjectBanner.setClicked(true);
Map<String, String> params = new HashMap<String, String>();
params.put("uri", "http://valid-url");
subjectBanner.runCommand(MraidJavascriptCommand.PLAY_VIDEO, params);
ArgumentCaptor<URI> uriCaptor = ArgumentCaptor.forClass(URI.class);
verify(mockBridgeListener).onPlayVideo(uriCaptor.capture());
assertThat(uriCaptor.getValue().toString()).isEqualTo("http://valid-url");
}
@Test
public void runCommand_storePicture_shouldCallListener()
throws MraidCommandException {
subjectBanner.setClicked(true);
Map<String, String> params = new HashMap<String, String>();
params.put("uri", "http://valid-url");
subjectBanner.runCommand(MraidJavascriptCommand.STORE_PICTURE, params);
verify(mockNativeCommandHandler).storePicture(any(Context.class), eq("http://valid-url"),
any(MraidCommandFailureListener.class));
}
@Test
public void runCommand_createCalendarEvent_shouldCallListener()
throws MraidCommandException {
subjectBanner.setClicked(true);
Map<String, String> params = new HashMap<String, String>();
params.put("eventName", "Dinner at my house");
subjectBanner.runCommand(MraidJavascriptCommand.CREATE_CALENDAR_EVENT, params);
verify(mockNativeCommandHandler).createCalendarEvent(any(Context.class),
anyMapOf(String.class, String.class));
}
}