From f0504c6c5a57556258b10b070bd184a62647867c Mon Sep 17 00:00:00 2001 From: Nathan Shayefar Date: Wed, 19 Feb 2014 18:09:11 -0800 Subject: [PATCH] Release: version 1.17.2.0 --- CHANGELOG.md | 7 + README.md | 8 +- .../src/com/mopub/mobileads/InMobiBanner.java | 21 ++- .../mopub/mobileads/InMobiInterstitial.java | 21 ++- .../com/mopub/mobileads/AdViewController.java | 1 + .../com/mopub/mobileads/DiskLruCache.java | 5 +- .../main/java/com/mopub/mobileads/MoPub.java | 2 +- .../mobileads/MraidDisplayController.java | 29 +--- .../java/com/mopub/mobileads/MraidView.java | 38 ++++- .../com/mopub/mobileads/AdLoadTaskTest.java | 36 +++-- .../com/mopub/mobileads/DiskLruCacheTest.java | 11 ++ .../mobileads/MraidDisplayControllerTest.java | 2 - .../com/mopub/mobileads/MraidViewTest.java | 130 ++++++++++++++++++ .../mobileads/test/support/JsonUtils.java | 40 ++++++ 14 files changed, 277 insertions(+), 74 deletions(-) create mode 100644 mopub-sdk/src/test/java/com/mopub/mobileads/test/support/JsonUtils.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e79a8d99..70dd9e1fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,13 @@ - All `WebView`s are removed from their parents before `destroy()`; fixes [GitHub issue #38](https://github.com/mopub/mopub-android-sdk/issues/38) - Removed previously-deprecated `HTML5AdView` +### Version 1.17.2 (Feb 20, 2014) + + - Updated InMobi custom events to support InMobi SDK 4.0.3+ only + - MRAID viewable property now correctly updates on viewability change + - `MraidView` properly handles null schemes; fixes [GitHub issue #63](https://github.com/mopub/mopub-android-sdk/pull/63) + - Internal disk LRU cache correctly hashes keys when checking for existing files + ### Version 1.17.1 (Jan 23, 2014) - Added custom events for Google Play Services. `GooglePlayServicesBanner` and `GooglePlayServicesInterstitial` can be found in the extras directory of the SDK (`/extras/src/com/mopub/mobileads`) diff --git a/README.md b/README.md index d1426887d..4465e0d9e 100644 --- a/README.md +++ b/README.md @@ -27,9 +27,11 @@ Integration instructions are available on the [wiki](https://github.com/mopub/mo Please view the [changelog](https://github.com/mopub/mopub-android-sdk/blob/master/CHANGELOG.md) for details. - - Added custom events for Google Play Services. `GooglePlayServicesBanner` and `GooglePlayServicesInterstitial` can be found in the extras directory of the SDK (`/extras/src/com/mopub/mobileads`) - - Resolved issues with missing annotations on `addJavascriptInterface` when `targetSdkVersion` is set to API level 17 or above - - Updated MoPub sample application to allow in-app text entry of ad unit IDs + - Updated InMobi custom events + - Bug fixes + +### Changes to InMobi Custom Event Integrations +**Important**: As of version 1.17.2.0, the InMobi custom events packaged with the MoPub SDK only support InMobi version 4.0.3 and up. Follow the instructions [here](https://www.inmobi.com/support/integration/23817448/22051163/android-sdk-integration-guide/) to integrate InMobi version 4.0.3 and up. If you would like to continue to use a prior version of the InMobi SDK, do not update the custom event files and follow the instructions [here](https://www.inmobi.com/support/art/23806682/22095493/mopub-adaptor-android-sdk-integration-guide/) to integrate. ## Requirements diff --git a/extras/src/com/mopub/mobileads/InMobiBanner.java b/extras/src/com/mopub/mobileads/InMobiBanner.java index 61c60bcc4..f1248a915 100644 --- a/extras/src/com/mopub/mobileads/InMobiBanner.java +++ b/extras/src/com/mopub/mobileads/InMobiBanner.java @@ -4,7 +4,6 @@ import android.content.Context; import com.inmobi.commons.InMobi; import com.inmobi.commons.InMobi.LOG_LEVEL; -import com.inmobi.mediation.adapter.inmobi.InMobiExtras; import com.inmobi.monetization.IMBanner; import com.inmobi.monetization.IMBannerListener; import com.inmobi.monetization.IMErrorCode; @@ -16,7 +15,7 @@ import java.util.*; /* - * Tested with InMobi SDK 4.0.0 + * Tested with InMobi SDK 4.1.1 */ public class InMobiBanner extends CustomEventBanner implements IMBannerListener { @@ -38,9 +37,9 @@ protected void loadBanner(Context context, mBannerListener.onBannerFailed(null); return; } - if (!isAppIntialize) { + if (!isAppInitialized) { InMobi.initialize(activity, inMobiAppId); - isAppIntialize = true; + isAppInitialized = true; } /* @@ -50,12 +49,10 @@ protected void loadBanner(Context context, iMBanner = new IMBanner(activity, inMobiAppId, IMBanner.INMOBI_AD_UNIT_320X50); - Map map = new HashMap(); - InMobiExtras extras = new InMobiExtras(); - map.put("tp", "c_mopub"); - map.put("tp-ver", MoPub.SDK_VERSION); - extras.setRequestParams(map); - iMBanner.addNetworkExtras(extras); + Map map = new HashMap(); + map.put("tp", "c_mopub"); + map.put("tp-ver", MoPub.SDK_VERSION); + iMBanner.setRequestParams(map); InMobi.setLogLevel(LOG_LEVEL.VERBOSE); iMBanner.setIMBannerListener(this); iMBanner.setRefreshInterval(-1); @@ -65,7 +62,7 @@ protected void loadBanner(Context context, private CustomEventBannerListener mBannerListener; private IMBanner iMBanner; - private static boolean isAppIntialize = false; + private static boolean isAppInitialized = false; /* * Abstract methods from CustomEventBanner @@ -73,8 +70,8 @@ protected void loadBanner(Context context, @Override public void onInvalidate() { - iMBanner.setIMBannerListener(null); if (iMBanner != null) { + iMBanner.setIMBannerListener(null); Views.removeFromParent(iMBanner); iMBanner.destroy(); } diff --git a/extras/src/com/mopub/mobileads/InMobiInterstitial.java b/extras/src/com/mopub/mobileads/InMobiInterstitial.java index 5346357ea..2de8eac29 100644 --- a/extras/src/com/mopub/mobileads/InMobiInterstitial.java +++ b/extras/src/com/mopub/mobileads/InMobiInterstitial.java @@ -3,7 +3,6 @@ import android.app.Activity; import android.content.Context; import com.inmobi.commons.InMobi; -import com.inmobi.mediation.adapter.inmobi.InMobiExtras; import com.inmobi.monetization.IMErrorCode; import com.inmobi.monetization.IMInterstitial; import com.inmobi.monetization.IMInterstitialListener; @@ -14,7 +13,7 @@ import java.util.*; /* - * Tested with InMobi SDK 4.0.0 + * Tested with InMobi SDK 4.1.1 */ public class InMobiInterstitial extends CustomEventInterstitial implements IMInterstitialListener { @@ -42,25 +41,23 @@ protected void loadInterstitial(Context context, * You may also pass this String down in the serverExtras Map by * specifying Custom Event Data in MoPub's web interface. */ - if (!isAppIntialize) { + if (!isAppInitialized) { InMobi.initialize(activity, inMobiAppId); - isAppIntialize = true; + isAppInitialized = true; } this.iMInterstitial = new IMInterstitial(activity, inMobiAppId); - Map map = new HashMap(); - InMobiExtras extras = new InMobiExtras(); - map.put("tp", "c_mopub"); - map.put("tp-ver", MoPub.SDK_VERSION); - extras.setRequestParams(map); - iMInterstitial.addNetworkExtras(extras); + Map map = new HashMap(); + map.put("tp", "c_mopub"); + map.put("tp-ver", MoPub.SDK_VERSION); + iMInterstitial.setRequestParams(map); iMInterstitial.setIMInterstitialListener(this); iMInterstitial.loadInterstitial(); } private CustomEventInterstitialListener mInterstitialListener; private IMInterstitial iMInterstitial; - private static boolean isAppIntialize = false; + private static boolean isAppInitialized = false; /* * Abstract methods from CustomEventInterstitial @@ -76,8 +73,8 @@ public void showInterstitial() { @Override public void onInvalidate() { - iMInterstitial.setIMInterstitialListener(null); if (iMInterstitial != null) { + iMInterstitial.setIMInterstitialListener(null); iMInterstitial.destroy(); } } diff --git a/mopub-sdk/src/main/java/com/mopub/mobileads/AdViewController.java b/mopub-sdk/src/main/java/com/mopub/mobileads/AdViewController.java index de2a61109..96b0ca30c 100644 --- a/mopub-sdk/src/main/java/com/mopub/mobileads/AdViewController.java +++ b/mopub-sdk/src/main/java/com/mopub/mobileads/AdViewController.java @@ -135,6 +135,7 @@ public void loadAd() { mLocation = getLastKnownLocation(); } + // tested (remove me when the rest of this is tested) String adUrl = generateAdUrl(); loadNonJavascript(adUrl); } diff --git a/mopub-sdk/src/main/java/com/mopub/mobileads/DiskLruCache.java b/mopub-sdk/src/main/java/com/mopub/mobileads/DiskLruCache.java index 22ddcd1d2..ec31cb65c 100644 --- a/mopub-sdk/src/main/java/com/mopub/mobileads/DiskLruCache.java +++ b/mopub-sdk/src/main/java/com/mopub/mobileads/DiskLruCache.java @@ -59,12 +59,11 @@ synchronized boolean putStream(final String fileName, final InputStream content) return false; } - String hashedFileName = Utils.sha1(fileName); - - if (getUri(hashedFileName) != null) { + if (getUri(fileName) != null) { return false; } + String hashedFileName = Utils.sha1(fileName); File file = createFile(hashedFileName, content); if (file == null || !file.exists()) { diff --git a/mopub-sdk/src/main/java/com/mopub/mobileads/MoPub.java b/mopub-sdk/src/main/java/com/mopub/mobileads/MoPub.java index 8fbee2985..b4c237693 100644 --- a/mopub-sdk/src/main/java/com/mopub/mobileads/MoPub.java +++ b/mopub-sdk/src/main/java/com/mopub/mobileads/MoPub.java @@ -33,6 +33,6 @@ package com.mopub.mobileads; public class MoPub { - public static final String SDK_VERSION = "1.17.1.1"; + public static final String SDK_VERSION = "1.17.2.0"; } diff --git a/mopub-sdk/src/main/java/com/mopub/mobileads/MraidDisplayController.java b/mopub-sdk/src/main/java/com/mopub/mobileads/MraidDisplayController.java index 637423420..02a6118cf 100644 --- a/mopub-sdk/src/main/java/com/mopub/mobileads/MraidDisplayController.java +++ b/mopub-sdk/src/main/java/com/mopub/mobileads/MraidDisplayController.java @@ -128,22 +128,6 @@ class MraidDisplayController extends MraidAbstractController { // A reference to the root view. private FrameLayout mRootView; - // Tracks whether this controller's view is currently on-screen. - private boolean mIsViewable; - - // Task that periodically checks whether this controller's view is on-screen. - private Runnable mCheckViewabilityTask = new Runnable() { - public void run() { - boolean currentViewable = checkViewable(); - if (mIsViewable != currentViewable) { - mIsViewable = currentViewable; - getMraidView().fireChangeEventForProperty( - MraidViewableProperty.createWithViewable(mIsViewable)); - } - mHandler.postDelayed(this, VIEWABILITY_TIMER_MILLIS); - } - }; - // Handler for scheduling viewability checks. private Handler mHandler = new Handler(); @@ -199,7 +183,6 @@ public void run() { private void initialize() { mViewState = ViewState.LOADING; initializeScreenMetrics(); - initializeViewabilityTimer(); mOrientationBroadcastReceiver.register(getContext()); } @@ -227,11 +210,6 @@ private void initializeScreenMetrics() { mScreenHeight = (int) (heightPixels * (160.0 / metrics.densityDpi)); } - private void initializeViewabilityTimer() { - mHandler.removeCallbacks(mCheckViewabilityTask); - mHandler.post(mCheckViewabilityTask); - } - private int getDisplayRotation() { WindowManager wm = (WindowManager) getContext() .getSystemService(Context.WINDOW_SERVICE); @@ -245,7 +223,6 @@ private void onOrientationChanged(int currentRotation) { } public void destroy() { - mHandler.removeCallbacks(mCheckViewabilityTask); try { mOrientationBroadcastReceiver.unregister(); } catch (IllegalArgumentException e) { @@ -258,7 +235,7 @@ public void destroy() { protected void initializeJavaScriptState() { ArrayList properties = new ArrayList(); properties.add(MraidScreenSizeProperty.createWithSize(mScreenWidth, mScreenHeight)); - properties.add(MraidViewableProperty.createWithViewable(mIsViewable)); + properties.add(MraidViewableProperty.createWithViewable(getMraidView().getIsVisible())); getMraidView().fireChangeEventForProperties(properties); mViewState = ViewState.DEFAULT; @@ -770,10 +747,6 @@ protected void useCustomClose(boolean shouldUseCustomCloseButton) { } } - protected boolean checkViewable() { - return true; - } - FrameLayout createAdContainerLayout() { return new FrameLayout(getContext()); } diff --git a/mopub-sdk/src/main/java/com/mopub/mobileads/MraidView.java b/mopub-sdk/src/main/java/com/mopub/mobileads/MraidView.java index 3928acab9..88ad2f5c5 100644 --- a/mopub-sdk/src/main/java/com/mopub/mobileads/MraidView.java +++ b/mopub-sdk/src/main/java/com/mopub/mobileads/MraidView.java @@ -73,6 +73,7 @@ public class MraidView extends BaseWebView implements UserClickListener { private final PlacementType mPlacementType; private ViewGestureDetector mViewGestureDetector; private AdConfiguration mAdConfiguration; + private boolean mIsVisible; static class MraidListenerInfo { private MraidListener mMraidListener; @@ -118,6 +119,8 @@ public MraidView(Context context, AdConfiguration adConfiguration, ExpansionStyl mViewGestureDetector = new ViewGestureDetector(context, this, adConfiguration); mViewGestureDetector.setUserClickListener(this); + mIsVisible = (getVisibility() == View.VISIBLE); + initialize(expStyle, buttonStyle); } @@ -343,10 +346,15 @@ public void onReceivedError(WebView view, int errorCode, String description, Str @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { Uri uri = Uri.parse(url); + + // Note that scheme will be null when we are passed a relative Uri String scheme = uri.getScheme(); - - if (scheme.equals("mopub")) return true; - if (scheme.equals("mraid")) { + + if ("mopub".equals(scheme)) { + return true; + } + + if ("mraid".equals(scheme)) { tryCommand(URI.create(url)); // java.net.URI, not android.net.Uri return true; } @@ -377,6 +385,8 @@ public void onPageFinished(WebView view, String url) { if (getMraidListener() != null) { getMraidListener().onReady(MraidView.this); } + mIsVisible = (getVisibility() == View.VISIBLE); + fireChangeEventForProperty(MraidViewableProperty.createWithViewable(mIsVisible)); mHasFiredReadyEvent = true; } } @@ -409,6 +419,28 @@ public interface OnOpenListener { public void onOpen(MraidView view); } + public boolean getIsVisible() { + return mIsVisible; + } + + @Override + protected void onVisibilityChanged (View changedView, int visibility) { + super.onVisibilityChanged(changedView, visibility); + + boolean newIsVisible = (visibility == View.VISIBLE); + if (newIsVisible != mIsVisible) { + mIsVisible = newIsVisible; + if (mHasFiredReadyEvent) { + fireChangeEventForProperty(MraidViewableProperty.createWithViewable(mIsVisible)); + } + } + } + + @Deprecated // for testing + void setHasFiredReadyEvent(boolean hasFired) { + mHasFiredReadyEvent = hasFired; + } + @Deprecated // for testing WebViewClient getMraidWebViewClient() { return mWebViewClient; diff --git a/mopub-sdk/src/test/java/com/mopub/mobileads/AdLoadTaskTest.java b/mopub-sdk/src/test/java/com/mopub/mobileads/AdLoadTaskTest.java index 72d5cb37c..fd493f50f 100644 --- a/mopub-sdk/src/test/java/com/mopub/mobileads/AdLoadTaskTest.java +++ b/mopub-sdk/src/test/java/com/mopub/mobileads/AdLoadTaskTest.java @@ -32,6 +32,7 @@ package com.mopub.mobileads; +import com.mopub.mobileads.test.support.JsonUtils; import com.mopub.mobileads.test.support.SdkTestRunner; import com.mopub.mobileads.test.support.TestHttpResponseWithHeaders; import org.apache.http.Header; @@ -64,12 +65,11 @@ public class AdLoadTaskTest { private AdViewController adViewController; private HttpResponse response; private String standardExpectedJson; - private AdConfiguration adConfiguration; @Before public void setup() { adViewController = mock(AdViewController.class); - adConfiguration = mock(AdConfiguration.class); + AdConfiguration adConfiguration = mock(AdConfiguration.class); stub(adViewController.getAdConfiguration()).toReturn(adConfiguration); response = new TestHttpResponseWithHeaders(200, ""); standardExpectedJson = "{\"Scrollable\":\"false\",\"Redirect-Url\":\"redirect\",\"Clickthrough-Url\":\"clickthrough\",\"Html-Response-Body\":\"%3Chtml%3E%3C%2Fhtml%3E\"}"; @@ -111,7 +111,9 @@ public void fromHttpResponse_whenMraidBanner_shouldCreateAnEncodedJsonString() t AdLoadTask.CustomEventAdLoadTask customEventTask = (AdLoadTask.CustomEventAdLoadTask) AdLoadTask.fromHttpResponse(response, adViewController); assertThat(customEventTask.getParamsMap().get(CUSTOM_EVENT_NAME.getKey())).isEqualTo(MRAID_BANNER.toString()); - assertThat(customEventTask.getParamsMap().get(CUSTOM_EVENT_DATA.getKey())).isEqualTo(standardExpectedJson); + + String actualJsonData = customEventTask.getParamsMap().get(CUSTOM_EVENT_DATA.getKey()); + JsonUtils.assertJsonStringMapsEqual(actualJsonData, standardExpectedJson); } @Test @@ -123,7 +125,9 @@ public void fromHttpResponse_whenMraidInterstitial_shouldCreateAnEncodedJsonStri AdLoadTask.CustomEventAdLoadTask customEventTask = (AdLoadTask.CustomEventAdLoadTask) AdLoadTask.fromHttpResponse(response, adViewController); assertThat(customEventTask.getParamsMap().get(CUSTOM_EVENT_NAME.getKey())).isEqualTo(MRAID_INTERSTITIAL.toString()); - assertThat(customEventTask.getParamsMap().get(CUSTOM_EVENT_DATA.getKey())).isEqualTo(standardExpectedJson); + + String actualJsonData = customEventTask.getParamsMap().get(CUSTOM_EVENT_DATA.getKey()); + JsonUtils.assertJsonStringMapsEqual(actualJsonData, standardExpectedJson); } @Test @@ -134,7 +138,9 @@ public void fromHttpResponse_whenCustomEventDelegate_shouldConvertAdMobToCustomE AdLoadTask.CustomEventAdLoadTask customEventTask = (AdLoadTask.CustomEventAdLoadTask) AdLoadTask.fromHttpResponse(response, adViewController); assertThat(customEventTask.getParamsMap().get(CUSTOM_EVENT_NAME.getKey())).isEqualTo(ADMOB_BANNER.toString()); - assertThat(customEventTask.getParamsMap().get(CUSTOM_EVENT_DATA.getKey())).isEqualTo(expectedNativeParams); + + String actualNativeParams = customEventTask.getParamsMap().get(CUSTOM_EVENT_DATA.getKey()); + JsonUtils.assertJsonStringMapsEqual(actualNativeParams, expectedNativeParams); } @Test @@ -145,7 +151,9 @@ public void fromHttpResponse_whenHtmlBanner_shouldConvertToCustomEventBanner() t AdLoadTask.CustomEventAdLoadTask customEventTask = (AdLoadTask.CustomEventAdLoadTask) AdLoadTask.fromHttpResponse(response, adViewController); assertThat(customEventTask.getParamsMap().get(CUSTOM_EVENT_NAME.getKey())).isEqualTo(HTML_BANNER.toString()); - assertThat(customEventTask.getParamsMap().get(CUSTOM_EVENT_DATA.getKey())).isEqualTo(standardExpectedJson); + + String actualJsonData = customEventTask.getParamsMap().get(CUSTOM_EVENT_DATA.getKey()); + JsonUtils.assertJsonStringMapsEqual(actualJsonData, standardExpectedJson); } @Test @@ -157,7 +165,9 @@ public void fromHttpResponse_whenHtmlInterstitial_shouldConvertToCustomEventInte AdLoadTask.CustomEventAdLoadTask customEventTask = (AdLoadTask.CustomEventAdLoadTask) AdLoadTask.fromHttpResponse(response, adViewController); assertThat(customEventTask.getParamsMap().get(CUSTOM_EVENT_NAME.getKey())).isEqualTo(HTML_INTERSTITIAL.toString()); - assertThat(customEventTask.getParamsMap().get(CUSTOM_EVENT_DATA.getKey())).isEqualTo(standardExpectedJson); + + String actualJsonData = customEventTask.getParamsMap().get(CUSTOM_EVENT_DATA.getKey()); + JsonUtils.assertJsonStringMapsEqual(actualJsonData, standardExpectedJson); } @Test @@ -174,7 +184,9 @@ public HttpEntity getEntity() { AdLoadTask.CustomEventAdLoadTask customEventTask = (AdLoadTask.CustomEventAdLoadTask) AdLoadTask.fromHttpResponse(response, adViewController); assertThat(customEventTask.getParamsMap().get(CUSTOM_EVENT_NAME.getKey())).isEqualTo(HTML_BANNER.toString()); - assertThat(customEventTask.getParamsMap().get(CUSTOM_EVENT_DATA.getKey())).isEqualTo(expectedJson); + + String actualJsonData = customEventTask.getParamsMap().get(CUSTOM_EVENT_DATA.getKey()); + JsonUtils.assertJsonStringMapsEqual(actualJsonData, expectedJson); } @Test @@ -186,7 +198,9 @@ public void fromHttpResponse_whenScrollableIsOne_shouldBeReflectedInJson() throw AdLoadTask.CustomEventAdLoadTask customEventTask = (AdLoadTask.CustomEventAdLoadTask) AdLoadTask.fromHttpResponse(response, adViewController); assertThat(customEventTask.getParamsMap().get(CUSTOM_EVENT_NAME.getKey())).isEqualTo(HTML_BANNER.toString()); - assertThat(customEventTask.getParamsMap().get(CUSTOM_EVENT_DATA.getKey())).isEqualTo(expectedJson); + + String actualJsonData = customEventTask.getParamsMap().get(CUSTOM_EVENT_DATA.getKey()); + JsonUtils.assertJsonStringMapsEqual(actualJsonData, expectedJson); } @Test @@ -196,7 +210,9 @@ public void fromHttpResponse_whenScrollableIsNotSpecified_shouldDefaultToFalseIn AdLoadTask.CustomEventAdLoadTask customEventTask = (AdLoadTask.CustomEventAdLoadTask) AdLoadTask.fromHttpResponse(response, adViewController); assertThat(customEventTask.getParamsMap().get(CUSTOM_EVENT_NAME.getKey())).isEqualTo(HTML_BANNER.toString()); - assertThat(customEventTask.getParamsMap().get(CUSTOM_EVENT_DATA.getKey())).isEqualTo(expectedJson); + + String actualJsonData = customEventTask.getParamsMap().get(CUSTOM_EVENT_DATA.getKey()); + JsonUtils.assertJsonStringMapsEqual(actualJsonData, expectedJson); } private void addExpectedResponseHeaders(String adType) { diff --git a/mopub-sdk/src/test/java/com/mopub/mobileads/DiskLruCacheTest.java b/mopub-sdk/src/test/java/com/mopub/mobileads/DiskLruCacheTest.java index 40d392b29..dcc1b9197 100644 --- a/mopub-sdk/src/test/java/com/mopub/mobileads/DiskLruCacheTest.java +++ b/mopub-sdk/src/test/java/com/mopub/mobileads/DiskLruCacheTest.java @@ -217,6 +217,17 @@ public void putStream_withNullInputStream_shouldNotAddKeyValuePairToCache() thro assertThat(success).isFalse(); assertThat(subject.snapshot().isEmpty()).isTrue(); } + + @Test + public void putStream_whenHashedFilenameAlreadyInCache_shouldNotReturnFalsePositive() throws Exception { + final String fileName = "just a generic filename"; + final String hashedFileName = Utils.sha1(fileName); + + subject.putStream(hashedFileName, createByteArrayInputStream(10)); + boolean result = subject.putStream(fileName, createByteArrayInputStream(10)); + + assertThat(result).isTrue(); + } @Test public void putStream_canHandleFileNamesWithSymbols() throws Exception { diff --git a/mopub-sdk/src/test/java/com/mopub/mobileads/MraidDisplayControllerTest.java b/mopub-sdk/src/test/java/com/mopub/mobileads/MraidDisplayControllerTest.java index 72ddda7ba..453f51be8 100644 --- a/mopub-sdk/src/test/java/com/mopub/mobileads/MraidDisplayControllerTest.java +++ b/mopub-sdk/src/test/java/com/mopub/mobileads/MraidDisplayControllerTest.java @@ -154,8 +154,6 @@ public void initialization_shouldSetupStartingState() throws Exception { @Test public void initializeJavaScriptState_shouldSetMraidSupportsProperties() throws Exception { - verify(mraidView).fireChangeEventForProperty(any(MraidProperty.class)); - subject.initializeJavaScriptState(); verify(mraidView).fireChangeEventForProperty(isA(MraidSupportsProperty.class)); } diff --git a/mopub-sdk/src/test/java/com/mopub/mobileads/MraidViewTest.java b/mopub-sdk/src/test/java/com/mopub/mobileads/MraidViewTest.java index 61081b84e..d145cf61f 100644 --- a/mopub-sdk/src/test/java/com/mopub/mobileads/MraidViewTest.java +++ b/mopub-sdk/src/test/java/com/mopub/mobileads/MraidViewTest.java @@ -35,13 +35,17 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.view.View; import android.view.ViewGroup; import android.webkit.WebViewClient; + import com.mopub.mobileads.resource.MraidJavascript; import com.mopub.mobileads.test.support.SdkTestRunner; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; import org.robolectric.Robolectric; import org.robolectric.shadows.ShadowWebView; @@ -51,11 +55,13 @@ import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.isA; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.times; import static org.robolectric.Robolectric.shadowOf; @RunWith(SdkTestRunner.class) @@ -84,6 +90,103 @@ public void setUp() throws Exception { interstitialWebViewClient = interstitialSubject.getMraidWebViewClient(); } + @Test + public void viewSetToVisibleBeforeReady_shouldNotTriggerMRAIDEvent() throws Exception { + MraidView mraidViewSpy = spy(bannerSubject); + mraidViewSpy.setHasFiredReadyEvent(false); + mraidViewSpy.setVisibility(View.INVISIBLE); + + mraidViewSpy.setVisibility(View.VISIBLE); + + assertThat(mraidViewSpy.getIsVisible()).isTrue(); + + verify(mraidViewSpy, never()).fireChangeEventForProperty(any(MraidViewableProperty.class)); + } + + @Test + public void viewSetToVisibleAfterReady_shouldTriggerMRAIDEvent() throws Exception { + MraidView mraidViewSpy = spy(bannerSubject); + mraidViewSpy.setHasFiredReadyEvent(true); + mraidViewSpy.setVisibility(View.INVISIBLE); + reset(mraidViewSpy); + + mraidViewSpy.setVisibility(View.VISIBLE); + + assertThat(mraidViewSpy.getIsVisible()).isTrue(); + + MraidViewableProperty mraidViewableProperty = captureAndVerifyViewablePropertyChangeEventFired(mraidViewSpy); + assertThat(mraidViewableProperty.toJsonPair()).isEqualTo("viewable: true"); + } + + @Test + public void viewSetToVisibleAndThenInvisibleAfterReady_shouldTriggerTwoMRAIDEvents() throws Exception { + MraidView mraidViewSpy = spy(bannerSubject); + mraidViewSpy.setHasFiredReadyEvent(true); + mraidViewSpy.setVisibility(View.INVISIBLE); + reset(mraidViewSpy); + + mraidViewSpy.setVisibility(View.VISIBLE); + + MraidViewableProperty mraidViewableProperty = captureAndVerifyViewablePropertyChangeEventFired(mraidViewSpy); + assertThat(mraidViewableProperty.toJsonPair()).isEqualTo("viewable: true"); + reset(mraidViewSpy); + + mraidViewSpy.setVisibility(View.INVISIBLE); + + assertThat(mraidViewSpy.getIsVisible()).isFalse(); + + mraidViewableProperty = captureAndVerifyViewablePropertyChangeEventFired(mraidViewSpy); + assertThat(mraidViewableProperty.toJsonPair()).isEqualTo("viewable: false"); + } + + @Test + public void viewSetToVisibleAndThenGoneAfterReady_shouldTriggerTwoMRAIDEvents() throws Exception { + MraidView mraidViewSpy = spy(bannerSubject); + mraidViewSpy.setHasFiredReadyEvent(true); + mraidViewSpy.setVisibility(View.INVISIBLE); + reset(mraidViewSpy); + + mraidViewSpy.setVisibility(View.VISIBLE); + + MraidViewableProperty mraidViewableProperty = captureAndVerifyViewablePropertyChangeEventFired(mraidViewSpy); + assertThat(mraidViewableProperty.toJsonPair()).isEqualTo("viewable: true"); + reset(mraidViewSpy); + + mraidViewSpy.setVisibility(View.GONE); + + assertThat(mraidViewSpy.getIsVisible()).isFalse(); + + mraidViewableProperty = captureAndVerifyViewablePropertyChangeEventFired(mraidViewSpy); + assertThat(mraidViewableProperty.toJsonPair()).isEqualTo("viewable: false"); + } + + @Test + public void viewSetToVisibleAndThenInvisibleAndThenVisibleAfterReady_shouldTriggerThreeMRAIDEvents() throws Exception { + MraidView mraidViewSpy = spy(bannerSubject); + mraidViewSpy.setHasFiredReadyEvent(true); + mraidViewSpy.setVisibility(View.INVISIBLE); + reset(mraidViewSpy); + + mraidViewSpy.setVisibility(View.VISIBLE); + + MraidViewableProperty mraidViewableProperty = captureAndVerifyViewablePropertyChangeEventFired(mraidViewSpy); + assertThat(mraidViewableProperty.toJsonPair()).isEqualTo("viewable: true"); + reset(mraidViewSpy); + + mraidViewSpy.setVisibility(View.INVISIBLE); + + mraidViewableProperty = captureAndVerifyViewablePropertyChangeEventFired(mraidViewSpy); + assertThat(mraidViewableProperty.toJsonPair()).isEqualTo("viewable: false"); + reset(mraidViewSpy); + + mraidViewSpy.setVisibility(View.VISIBLE); + + assertThat(mraidViewSpy.getIsVisible()).isTrue(); + + mraidViewableProperty = captureAndVerifyViewablePropertyChangeEventFired(mraidViewSpy); + assertThat(mraidViewableProperty.toJsonPair()).isEqualTo("viewable: true"); + } + @Test public void loadHtmlData_whenDataIsNull_shouldNotBlowUp() throws Exception { MraidView mraidViewSpy = spy(bannerSubject); @@ -234,6 +337,27 @@ public void shouldOverrideUrlLoading_withRedirectUrl_withUserClick_shouldOpenNew assertThat(consumeUrlLoading).isTrue(); } + @Test + public void shouldOverrideUrlLoading_withRelativeUrl_andUserClick_shouldReturnTrue() throws Exception { + String relativeUrl = "www.blah.com"; + bannerSubject.onUserClick(); + + boolean consumeUrlLoading = bannerWebViewClient.shouldOverrideUrlLoading(null, relativeUrl); + + Intent startedIntent = Robolectric.getShadowApplication().getNextStartedActivity(); + assertThat(startedIntent).isNotNull(); + assertThat(consumeUrlLoading).isTrue(); + } + + @Test + public void shouldOverrideUrlLoading_withRelativeUrl_andNoUserClick_shouldReturnFalse() throws Exception { + String relativeUrl = "www.blah.com"; + + boolean consumeUrlLoading = bannerWebViewClient.shouldOverrideUrlLoading(null, relativeUrl); + + assertThat(consumeUrlLoading).isFalse(); + } + @Test public void destroy_shouldRemoveSelfFromParent_beforeCallingDestroy() throws Exception { ViewGroup parent = mock(ViewGroup.class); @@ -245,4 +369,10 @@ public void destroy_shouldRemoveSelfFromParent_beforeCallingDestroy() throws Exc verify(parent).removeView(eq(bannerSubject)); assertThat(shadow.wasDestroyCalled()).isTrue(); } + + private MraidViewableProperty captureAndVerifyViewablePropertyChangeEventFired(MraidView mraidView) { + ArgumentCaptor mraidViewablePropertyCaptor = ArgumentCaptor.forClass(MraidViewableProperty.class); + verify(mraidView).fireChangeEventForProperty(mraidViewablePropertyCaptor.capture()); + return mraidViewablePropertyCaptor.getValue(); + } } diff --git a/mopub-sdk/src/test/java/com/mopub/mobileads/test/support/JsonUtils.java b/mopub-sdk/src/test/java/com/mopub/mobileads/test/support/JsonUtils.java new file mode 100644 index 000000000..1569764a3 --- /dev/null +++ b/mopub-sdk/src/test/java/com/mopub/mobileads/test/support/JsonUtils.java @@ -0,0 +1,40 @@ +package com.mopub.mobileads.test.support; + +import com.mopub.mobileads.util.Json; + +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +import static org.fest.assertions.api.Assertions.assertThat; +import static org.fest.assertions.api.Assertions.fail; + +public class JsonUtils { + // Assert that two shallow jsonStrings representing maps are equal + public static void assertJsonStringMapsEqual(String a, String b) { + Map mapA = Collections.emptyMap(); + Map mapB = Collections.emptyMap(); + + try { + mapA = Json.jsonStringToMap(a); + } catch (Exception e) { + fail("Unable to turn json into map: " + a); + } + + try { + mapB = Json.jsonStringToMap(b); + } catch (Exception e) { + fail("Unable to turn json into map: " + b); + } + + assertThat(mapA.size()).isEqualTo(mapB.size()); + + Set keysA = mapA.keySet(); + Set keysB = mapB.keySet(); + assertThat(keysA).isEqualTo(keysB); + + for (final String key : keysA) { + assertThat(mapA.get(key)).isEqualTo(mapB.get(key)); + } + } +}