/* * Copyright (c) 2016 Uber Technologies, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.uber.sdk.android.rides; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.webkit.WebResourceError; import android.webkit.WebResourceRequest; import android.webkit.WebResourceResponse; import android.webkit.WebView; import com.google.common.collect.ImmutableList; import com.uber.sdk.core.auth.AccessToken; import com.uber.sdk.core.auth.Scope; import com.uber.sdk.rides.client.AccessTokenSession; import com.uber.sdk.rides.client.SessionConfiguration; import org.junit.Before; import org.junit.Test; import org.robolectric.Robolectric; import org.robolectric.RuntimeEnvironment; import org.robolectric.shadows.ShadowActivity; import java.io.IOException; import java.util.Map; import static com.uber.sdk.android.rides.TestUtils.readUriResourceWithUserAgentParam; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.robolectric.Shadows.shadowOf; /** * Tests {@link RideRequestView} */ public class RideRequestViewTest extends RobolectricTestBase { private static final String CLIENT_ID = "clientId"; private static final String PRODUCT_ID = "productId"; private static final Double PICKUP_LAT = 32.1234; private static final Double PICKUP_LONG = -122.3456; private static final String PICKUP_NICK = "pickupNick"; private static final String PICKUP_ADDR = "Pickup Address"; private static final Double DROPOFF_LAT = 32.5678; private static final Double DROPOFF_LONG = -122.6789; private static final String DROPOFF_NICK = "pickupNick"; private static final String DROPOFF_ADDR = "Dropoff Address"; private static final String TOKEN_STRING = "thisIsAnAccessToken"; private static final String USER_AGENT_RIDE_VIEW = "rides-android-v0.6.1-ride_request_view"; private AccessToken accessToken; private RideRequestView rideRequestView; private RideRequestView.RideRequestWebViewClient client; private RideRequestView.RideRequestWebViewClientCallback callback; private Context context; @Before public void setup() { context = RuntimeEnvironment.application; accessToken = new AccessToken(2592000, ImmutableList.of(Scope.RIDE_WIDGETS), TOKEN_STRING, "refreshToken", "Bearer"); rideRequestView = new RideRequestView(Robolectric.setupActivity(Activity.class)); callback = mock(RideRequestView.RideRequestWebViewClientCallback.class); client = rideRequestView.new RideRequestWebViewClient(callback); } @Test public void onBuildUrl_inDefaultRegion_shouldHaveUrlWithDefaultDomain() throws IOException { String path = "src/test/resources/riderequestviewuris/default_uri"; String expectedUri = readUriResourceWithUserAgentParam(path, USER_AGENT_RIDE_VIEW); RideParameters rideParameters = new RideParameters.Builder().build(); SessionConfiguration configuration = new SessionConfiguration.Builder() .setClientId("clientId") .build(); String result = RideRequestView.buildUrlFromRideParameters(context, rideParameters, configuration); assertEquals(expectedUri, result); } @Test public void onBuildUrl_inSandboxMode_shouldHaveUrlWithSandboxParam() throws IOException { RideParameters rideParameters = new RideParameters.Builder().build(); SessionConfiguration configuration = new SessionConfiguration.Builder() .setClientId("clientId") .setEnvironment(SessionConfiguration.Environment.SANDBOX) .build(); String result = RideRequestView.buildUrlFromRideParameters(context, rideParameters, configuration); assertTrue(result.contains("&env=sandbox")); } @Test public void onBuildUrl_withRideParams_shouldHaveRideParamsQueryParams() throws IOException { String path = "src/test/resources/riderequestviewuris/full_details_uri"; String expectedUri = readUriResourceWithUserAgentParam(path, USER_AGENT_RIDE_VIEW); RideParameters rideParameters = new RideParameters.Builder() .setPickupLocation(PICKUP_LAT, PICKUP_LONG, PICKUP_NICK, PICKUP_ADDR) .setDropoffLocation(DROPOFF_LAT, DROPOFF_LONG, DROPOFF_NICK, DROPOFF_ADDR) .setProductId(PRODUCT_ID) .build(); SessionConfiguration configuration = new SessionConfiguration.Builder() .setClientId("clientId") .build(); String result = RideRequestView.buildUrlFromRideParameters(context, rideParameters, configuration); assertEquals(expectedUri, result); } @Test public void onBuildUrl_withUserAgentNonNull_shouldNotOverride() throws IOException { String widgetUserAgent = "rides-android-v0.6.1-ride_request_widget"; String path = "src/test/resources/riderequestviewuris/default_uri"; String expectedUri = readUriResourceWithUserAgentParam(path, widgetUserAgent); RideParameters rideParameters = new RideParameters.Builder().build(); rideParameters.setUserAgent(widgetUserAgent); SessionConfiguration configuration = new SessionConfiguration.Builder() .setClientId("clientId") .build(); String result = RideRequestView.buildUrlFromRideParameters(context, rideParameters, configuration); assertEquals(expectedUri, result); } @Test public void onGetHeaders_withAccessToken_shouldReturnCorrectHeader() { String token = "accessToken123"; AccessToken accessToken = new AccessToken(2592000, ImmutableList.of(Scope.HISTORY), token, "refreshToken", "tokenType"); Map<String, String> headers = RideRequestView.getHeaders(accessToken); assertEquals(headers.size(), 1); assertEquals(headers.get("Authorization"), "Bearer " + token); } @Test public void onRideRequestViewInit_withCustomSession_viewShouldAuthorize() { AccessTokenSession session = mock(AccessTokenSession.class); rideRequestView.setSession(session); assertNotNull(rideRequestView.getSession()); assertEquals(session, rideRequestView.getSession()); } @Test public void onRideRequestViewLoad_withoutSession_viewShouldHaveAuthorizationError() { rideRequestView.setRideParameters(new RideParameters.Builder().setPickupLocation(37.2342, -122.4232, null, null).build()); RideRequestViewCallback callback = mock(RideRequestViewCallback.class); rideRequestView.setRideRequestViewCallback(callback); rideRequestView.load(); verify(callback, times(1)).onErrorReceived(RideRequestViewError.NO_ACCESS_TOKEN); } @Test public void whileRideRequestViewRunning_whenAccessTokenExpires_shouldReceiveUnauthorizedError() { boolean shouldOverrideUrlLoading = client.shouldOverrideUrlLoading(mock(WebView.class), "uberconnect://oauth#error=unauthorized"); verify(callback, times(1)).onErrorParsed(RideRequestViewError.UNAUTHORIZED); assertTrue(shouldOverrideUrlLoading); } @Test public void whileRideRequestViewRunning_whenWebResourceErrorOccurs_shouldReceiveWebError() { client.onReceivedError(mock(WebView.class), mock(WebResourceRequest.class), mock(WebResourceError.class)); verify(callback, times(1)).onErrorParsed(RideRequestViewError.CONNECTIVITY_ISSUE); } @Test public void whileRideRequestViewRunning_whenWebHTTPErrorOccurs_shouldDoNothing() { client.onReceivedHttpError(mock(WebView.class), mock(WebResourceRequest.class), mock(WebResourceResponse.class)); verify(callback, never()).onErrorParsed(any(RideRequestViewError.class)); } @Test public void whileRideRequestViewRunning_whenUnknownErrorOccurs_shouldReceiveUnknownError() { boolean shouldOverrideUrlLoading = client.shouldOverrideUrlLoading(mock(WebView.class), "uberconnect://oauth#error=on_fire"); verify(callback, times(1)).onErrorParsed(RideRequestViewError.UNKNOWN); assertTrue(shouldOverrideUrlLoading); } @Test public void whileRideRequestViewRunning_whenRegionErrorOccurs_shouldReceiveRegionError() { boolean shouldOverrideUrlLoading = client.shouldOverrideUrlLoading(mock(WebView.class), "uberconnect://oauth#error=wrong_region"); verify(callback, times(1)).onErrorParsed(RideRequestViewError.WRONG_REGION); assertTrue(shouldOverrideUrlLoading); } @Test public void shouldOverrideUrlLoading_whenHttpUrl_shouldNotOverride() { assertFalse(client.shouldOverrideUrlLoading(mock(WebView.class), "http://uber.com")); verifyZeroInteractions(callback); } @Test public void shouldOverrideUrlLoading_whenHttpsUrl_shouldNotOverride() { assertFalse(client.shouldOverrideUrlLoading(mock(WebView.class), "https://uber.com")); verifyZeroInteractions(callback); } @Test public void shouldOverrideUrlLoading_whenNonHttpOrRedirect_shouldOverrideAndLaunchActivity() { Activity activity = Robolectric.setupActivity(Activity.class); ShadowActivity shadowActivity = shadowOf(activity); RideRequestView rideRequestView = new RideRequestView(activity); client = rideRequestView.new RideRequestWebViewClient(callback); assertTrue(client.shouldOverrideUrlLoading(mock(WebView.class), "tel:+91555555555")); verifyZeroInteractions(callback); Intent startedIntent = shadowActivity.getNextStartedActivity(); assertEquals(Intent.ACTION_VIEW, startedIntent.getAction()); assertEquals("tel:+91555555555#Intent;action=android.intent.action.VIEW;end", startedIntent.toUri(0)); } }