package com.mopub.mobileads;
import android.app.Activity;
import android.os.Build.VERSION_CODES;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import com.mopub.common.AdReport;
import com.mopub.common.test.support.SdkTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.robolectric.Robolectric;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowWebView;
import static android.webkit.WebSettings.PluginState;
import static org.fest.assertions.api.Assertions.assertThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.robolectric.Robolectric.shadowOf;
@RunWith(SdkTestRunner.class)
public class BaseHtmlWebViewTest {
@Mock
AdReport mockAdReport;
private BaseHtmlWebView subject;
private MotionEvent touchDown;
private MotionEvent touchUp;
@Before
public void setUp() throws Exception {
subject = new BaseHtmlWebView(Robolectric.buildActivity(Activity.class).create().get(), mockAdReport);
touchDown = createMotionEvent(MotionEvent.ACTION_DOWN);
touchUp = createMotionEvent(MotionEvent.ACTION_UP);
}
@Config(reportSdk = VERSION_CODES.JELLY_BEAN_MR2)
@Test
public void pluginState_atLeastJellybeanMr2_shouldDefaultToOff_shouldNeverBeEnabled() {
subject = new BaseHtmlWebView(Robolectric.buildActivity(Activity.class).create().get(), mockAdReport);
assertThat(subject.getSettings().getPluginState()).isEqualTo(PluginState.OFF);
subject.enablePlugins(true);
assertThat(subject.getSettings().getPluginState()).isEqualTo(PluginState.OFF);
}
@Config(reportSdk = VERSION_CODES.ICE_CREAM_SANDWICH)
@Test
public void pluginState_atLeastIcsButBelowJellybeanMr2_shouldDefaultToOn_shouldAllowToggling() {
subject = new BaseHtmlWebView(Robolectric.buildActivity(Activity.class).create().get(), mockAdReport);
assertThat(subject.getSettings().getPluginState()).isEqualTo(PluginState.ON);
subject.enablePlugins(false);
assertThat(subject.getSettings().getPluginState()).isEqualTo(PluginState.OFF);
subject.enablePlugins(true);
assertThat(subject.getSettings().getPluginState()).isEqualTo(PluginState.ON);
}
@Config(reportSdk = VERSION_CODES.GINGERBREAD_MR1)
@Test
public void pluginState_beforeIcs_shouldDefaultToOff_shouldAllowToggling() {
subject = new BaseHtmlWebView(Robolectric.buildActivity(Activity.class).create().get(), mockAdReport);
assertThat(subject.getSettings().getPluginState()).isEqualTo(PluginState.OFF);
subject.enablePlugins(true);
assertThat(subject.getSettings().getPluginState()).isEqualTo(PluginState.ON);
subject.enablePlugins(false);
assertThat(subject.getSettings().getPluginState()).isEqualTo(PluginState.OFF);
}
@Test
public void init_shouldSetWebViewScrollability() throws Exception {
subject.init(false);
assertThat(shadowOf(subject).getOnTouchListener()).isNotNull();
subject.init(true);
assertThat(shadowOf(subject).getOnTouchListener()).isNotNull();
}
@Test
public void loadUrl_shouldAcceptNullParameter() throws Exception {
subject.loadUrl(null);
// pass
}
@Test
public void loadUrl_whenUrlIsJavascript_shouldCallSuperLoadUrl() throws Exception {
String javascriptUrl = "javascript:function() {alert(\"guy\")};";
subject.loadUrl(javascriptUrl);
assertThat(shadowOf(subject).getLastLoadedUrl()).isEqualTo(javascriptUrl);
}
@Test
public void loadHtmlResponse_shouldCallLoadDataWithBaseURL() throws Exception {
String htmlResponse = "some random html response";
subject.loadHtmlResponse(htmlResponse);
ShadowWebView.LoadDataWithBaseURL lastLoadData = shadowOf(subject).getLastLoadDataWithBaseURL();
assertThat(lastLoadData.baseUrl).isEqualTo("http://ads.mopub.com/");
assertThat(lastLoadData.data).isEqualTo(htmlResponse);
assertThat(lastLoadData.mimeType).isEqualTo("text/html");
assertThat(lastLoadData.encoding).isEqualTo("utf-8");
assertThat(lastLoadData.historyUrl).isNull();
}
@Test
public void sendTouchEvent_withScrollingDisabled_shouldSetUserClicked() throws Exception {
assertThat(subject.wasClicked()).isFalse();
subject.initializeOnTouchListener(false);
View.OnTouchListener onTouchListener = shadowOf(subject).getOnTouchListener();
onTouchListener.onTouch(subject, touchUp);
assertThat(subject.wasClicked()).isTrue();
}
@Test
public void sendTouchEvent_withScrollingEnabled_shouldSetUserClicked() throws Exception {
assertThat(subject.wasClicked()).isFalse();
subject.initializeOnTouchListener(true);
View.OnTouchListener onTouchListener = shadowOf(subject).getOnTouchListener();
onTouchListener.onTouch(subject, touchUp);
assertThat(subject.wasClicked()).isTrue();
}
@Test
public void sendTouchEvent_withScrollingDisabled_withLotsOfRandomMotionEvents_shouldEventuallySetUserClicked() throws Exception {
subject.initializeOnTouchListener(false);
View.OnTouchListener onTouchListener = shadowOf(subject).getOnTouchListener();
onTouchListener.onTouch(subject, touchDown);
assertThat(subject.wasClicked()).isFalse();
onTouchListener.onTouch(subject, createMotionEvent(MotionEvent.ACTION_CANCEL));
assertThat(subject.wasClicked()).isFalse();
onTouchListener.onTouch(subject, createMotionEvent(MotionEvent.ACTION_MOVE));
assertThat(subject.wasClicked()).isFalse();
onTouchListener.onTouch(subject, touchUp);
assertThat(subject.wasClicked()).isTrue();
onTouchListener.onTouch(subject, touchDown);
assertThat(subject.wasClicked()).isTrue();
onTouchListener.onTouch(subject, createMotionEvent(MotionEvent.ACTION_CANCEL));
assertThat(subject.wasClicked()).isTrue();
onTouchListener.onTouch(subject, createMotionEvent(MotionEvent.ACTION_MOVE));
assertThat(subject.wasClicked()).isTrue();
}
@Test
public void sendTouchEvent_withScrollingEnabled_withLotsOfRandomMotionEvents_shouldEventuallySetUserClicked() throws Exception {
subject.initializeOnTouchListener(true);
View.OnTouchListener onTouchListener = shadowOf(subject).getOnTouchListener();
onTouchListener.onTouch(subject, touchDown);
assertThat(subject.wasClicked()).isFalse();
onTouchListener.onTouch(subject, createMotionEvent(MotionEvent.ACTION_CANCEL));
assertThat(subject.wasClicked()).isFalse();
onTouchListener.onTouch(subject, createMotionEvent(MotionEvent.ACTION_MOVE));
assertThat(subject.wasClicked()).isFalse();
onTouchListener.onTouch(subject, touchUp);
assertThat(subject.wasClicked()).isTrue();
onTouchListener.onTouch(subject, touchDown);
assertThat(subject.wasClicked()).isTrue();
onTouchListener.onTouch(subject, createMotionEvent(MotionEvent.ACTION_CANCEL));
assertThat(subject.wasClicked()).isTrue();
onTouchListener.onTouch(subject, createMotionEvent(MotionEvent.ACTION_MOVE));
assertThat(subject.wasClicked()).isTrue();
}
@Test
public void onResetClicked_shouldonResetClicked() throws Exception {
subject.initializeOnTouchListener(false);
View.OnTouchListener onTouchListener = shadowOf(subject).getOnTouchListener();
onTouchListener.onTouch(subject, touchDown);
onTouchListener.onTouch(subject, touchUp);
assertThat(subject.wasClicked()).isTrue();
subject.onResetUserClick();
assertThat(subject.wasClicked()).isFalse();
}
@Test
public void onResetClicked_whenTouchStateIsUnset_shouldKeepTouchStateUnset() throws Exception {
subject.initializeOnTouchListener(false);
assertThat(subject.wasClicked()).isFalse();
subject.onResetUserClick();
assertThat(subject.wasClicked()).isFalse();
}
@Test
public void setWebViewScrollingEnabled_whenScrollableIsTrue_onTouchListenerShouldAlwaysReturnFalse() throws Exception {
subject.initializeOnTouchListener(true);
View.OnTouchListener onTouchListener = shadowOf(subject).getOnTouchListener();
// ACTION_DOWN is guaranteed to be run before ACTION_MOVE
onTouchListener.onTouch(subject, createMotionEvent(MotionEvent.ACTION_DOWN));
boolean shouldConsumeTouch = onTouchListener.onTouch(subject, createMotionEvent(MotionEvent.ACTION_MOVE));
assertThat(shouldConsumeTouch).isFalse();
}
@Test
public void setWebViewScrollingEnabled_whenScrollableIsFalse_whenActionMove_onTouchListenerShouldReturnTrue() throws Exception {
subject.initializeOnTouchListener(false);
View.OnTouchListener onTouchListener = shadowOf(subject).getOnTouchListener();
boolean shouldConsumeTouch = onTouchListener.onTouch(subject, createMotionEvent(MotionEvent.ACTION_MOVE));
assertThat(shouldConsumeTouch).isTrue();
}
@Test
public void setWebViewScrollingEnabled_whenScrollableIsFalse_whenMotionEventIsNotActionMove_onTouchListenerShouldReturnFalse() throws Exception {
subject.initializeOnTouchListener(false);
View.OnTouchListener onTouchListener = shadowOf(subject).getOnTouchListener();
boolean shouldConsumeTouch = onTouchListener.onTouch(subject, touchUp);
assertThat(shouldConsumeTouch).isFalse();
shouldConsumeTouch = onTouchListener.onTouch(subject, touchDown);
assertThat(shouldConsumeTouch).isFalse();
shouldConsumeTouch = onTouchListener.onTouch(subject, createMotionEvent(MotionEvent.ACTION_CANCEL));
assertThat(shouldConsumeTouch).isFalse();
}
@Test
public void destroy_shouldRemoveSelfFromParent() throws Exception {
ViewGroup parentView = mock(ViewGroup.class);
ShadowWebView shadow = shadowOf(subject);
shadow.setMyParent(parentView);
subject.destroy();
verify(parentView).removeView(eq(subject));
assertThat(shadow.wasDestroyCalled());
}
private static MotionEvent createMotionEvent(int action) {
return MotionEvent.obtain(0, 0, action, 0, 0, 0);
}
}