Skip to content

Commit

Permalink
Fix UI tests with DirectionsRoute test fixture
Browse files Browse the repository at this point in the history
  • Loading branch information
danesfeder committed Nov 21, 2018
1 parent 4ab858b commit 4956fcb
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 98 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
import android.content.res.Configuration;
import android.support.test.espresso.ViewAction;

import com.mapbox.api.directions.v5.models.DirectionsRoute;
import com.mapbox.services.android.navigation.testapp.R;
import com.mapbox.services.android.navigation.testapp.test.TestNavigationActivity;
import com.mapbox.services.android.navigation.ui.v5.NavigationViewOptions;
import com.mapbox.services.android.navigation.ui.v5.map.NavigationMapboxMap;

import org.junit.Test;
Expand All @@ -19,6 +21,7 @@
import static android.support.test.espresso.matcher.ViewMatchers.isRoot;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static junit.framework.Assert.assertFalse;
import static testapp.action.NavigationViewAction.invoke;
import static testapp.action.OrientationChangeAction.orientationLandscape;
import static testapp.action.OrientationChangeAction.orientationPortrait;

Expand All @@ -36,6 +39,15 @@ public void onOrientationLandscape_navigationContinuesRunning() {
}
validateTestSetup();

invoke(getNavigationView(), (uiController, navigationView) -> {
DirectionsRoute testRoute = DirectionsRoute.fromJson(loadJsonFromAsset("lancaster-1.json"));
NavigationViewOptions options = NavigationViewOptions.builder()
.directionsRoute(testRoute)
.build();

navigationView.startNavigation(options);
});

changeOrientation(orientationLandscape());
}

Expand All @@ -46,6 +58,15 @@ public void onOrientationPortrait_navigationContinuesRunning() {
}
validateTestSetup();

invoke(getNavigationView(), (uiController, navigationView) -> {
DirectionsRoute testRoute = DirectionsRoute.fromJson(loadJsonFromAsset("lancaster-1.json"));
NavigationViewOptions options = NavigationViewOptions.builder()
.directionsRoute(testRoute)
.build();

navigationView.startNavigation(options);
});

changeOrientation(orientationPortrait());
}

Expand All @@ -56,6 +77,15 @@ public void onOrientationChange_recenterBtnStateIsRestore() {
}
validateTestSetup();

invoke(getNavigationView(), (uiController, navigationView) -> {
DirectionsRoute testRoute = DirectionsRoute.fromJson(loadJsonFromAsset("lancaster-1.json"));
NavigationViewOptions options = NavigationViewOptions.builder()
.directionsRoute(testRoute)
.build();

navigationView.startNavigation(options);
});

onView(withId(R.id.routeOverviewBtn)).perform(click());
changeOrientation(orientationLandscape());
onView(withId(R.id.recenterBtn)).check(matches(isDisplayed()));
Expand All @@ -68,6 +98,15 @@ public void onOrientationChange_cameraTrackingIsRestore() {
}
validateTestSetup();

invoke(getNavigationView(), (uiController, navigationView) -> {
DirectionsRoute testRoute = DirectionsRoute.fromJson(loadJsonFromAsset("lancaster-1.json"));
NavigationViewOptions options = NavigationViewOptions.builder()
.directionsRoute(testRoute)
.build();

navigationView.startNavigation(options);
});

onView(withId(R.id.navigationMapView)).perform(swipeUp());
changeOrientation(orientationLandscape());

Expand All @@ -83,6 +122,15 @@ public void onOrientationChange_waynameVisibilityIsRestored() {
}
validateTestSetup();

invoke(getNavigationView(), (uiController, navigationView) -> {
DirectionsRoute testRoute = DirectionsRoute.fromJson(loadJsonFromAsset("lancaster-1.json"));
NavigationViewOptions options = NavigationViewOptions.builder()
.directionsRoute(testRoute)
.build();

navigationView.startNavigation(options);
});

onView(withId(R.id.navigationMapView)).perform(swipeUp());
changeOrientation(orientationLandscape());

Expand Down
19 changes: 19 additions & 0 deletions app/src/androidTest/java/testapp/NavigationViewTest.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package testapp;

import com.mapbox.api.directions.v5.models.DirectionsRoute;
import com.mapbox.services.android.navigation.testapp.test.TestNavigationActivity;
import com.mapbox.services.android.navigation.ui.v5.NavigationViewOptions;
import com.mapbox.services.android.navigation.ui.v5.map.NavigationMapboxMap;
import com.mapbox.services.android.navigation.v5.navigation.MapboxNavigation;

Expand All @@ -9,6 +11,7 @@
import testapp.activity.BaseNavigationActivityTest;

import static junit.framework.Assert.assertNotNull;
import static testapp.action.NavigationViewAction.invoke;

public class NavigationViewTest extends BaseNavigationActivityTest {

Expand All @@ -21,6 +24,14 @@ protected Class getActivityClass() {
public void onInitialization_navigationMapboxMapIsNotNull() {
validateTestSetup();

invoke(getNavigationView(), (uiController, navigationView) -> {
DirectionsRoute testRoute = DirectionsRoute.fromJson(loadJsonFromAsset("lancaster-1.json"));
NavigationViewOptions options = NavigationViewOptions.builder()
.directionsRoute(testRoute)
.build();

navigationView.startNavigation(options);
});
NavigationMapboxMap navigationMapboxMap = getNavigationView().retrieveNavigationMapboxMap();

assertNotNull(navigationMapboxMap);
Expand All @@ -30,6 +41,14 @@ public void onInitialization_navigationMapboxMapIsNotNull() {
public void onNavigationStart_mapboxNavigationIsNotNull() {
validateTestSetup();

invoke(getNavigationView(), (uiController, navigationView) -> {
DirectionsRoute testRoute = DirectionsRoute.fromJson(loadJsonFromAsset("lancaster-1.json"));
NavigationViewOptions options = NavigationViewOptions.builder()
.directionsRoute(testRoute)
.build();

navigationView.startNavigation(options);
});
MapboxNavigation mapboxNavigation = getNavigationView().retrieveMapboxNavigation();

assertNotNull(mapboxNavigation);
Expand Down
48 changes: 48 additions & 0 deletions app/src/androidTest/java/testapp/action/NavigationViewAction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package testapp.action;

import android.support.annotation.NonNull;
import android.support.test.espresso.UiController;
import android.support.test.espresso.ViewAction;
import android.view.View;

import com.mapbox.services.android.navigation.ui.v5.NavigationView;

import org.hamcrest.Matcher;

import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withId;

public class NavigationViewAction implements ViewAction {

private OnInvokeActionListener invokeViewAction;
private NavigationView navigationView;

private NavigationViewAction(OnInvokeActionListener invokeViewAction, NavigationView navigationView) {
this.invokeViewAction = invokeViewAction;
this.navigationView = navigationView;
}

@Override
public Matcher<View> getConstraints() {
return isDisplayed();
}

@Override
public String getDescription() {
return getClass().getSimpleName();
}

@Override
public void perform(UiController uiController, View view) {
invokeViewAction.onInvokeAction(uiController, navigationView);
}

public static void invoke(NavigationView navigationView, OnInvokeActionListener invokeViewAction) {
onView(withId(android.R.id.content)).perform(new NavigationViewAction(invokeViewAction, navigationView));
}

public interface OnInvokeActionListener {
void onInvokeAction(@NonNull UiController uiController, @NonNull NavigationView navigationView);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import android.app.Activity;
import android.content.Context;
import android.content.res.AssetManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.test.espresso.IdlingRegistry;
Expand All @@ -17,6 +18,9 @@
import org.junit.Before;
import org.junit.Rule;

import java.io.IOException;
import java.io.InputStream;

import testapp.utils.OnNavigationReadyIdlingResource;
import timber.log.Timber;

Expand All @@ -29,23 +33,32 @@ public abstract class BaseNavigationActivityTest {

@Rule
public ActivityTestRule<Activity> rule = new ActivityTestRule<>(getActivityClass());

private NavigationView navigationView;
private AssetManager assetManager;
private OnNavigationReadyIdlingResource idlingResource;

@Before
public void beforeTest() {
try {
idlingResource = new OnNavigationReadyIdlingResource(rule.getActivity());
Activity activity = rule.getActivity();
idlingResource = new OnNavigationReadyIdlingResource(activity);
IdlingRegistry.getInstance().register(idlingResource);
checkViewIsDisplayed(R.id.navigationView);
navigationView = idlingResource.getNavigationView();
assetManager = activity.getAssets();
} catch (IdlingResourceTimeoutException idlingResourceTimeoutException) {
Timber.e("Idling resource timed out. Could not validate if navigation is ready.");
throw new RuntimeException("Could not start test for " + getActivityClass().getSimpleName() + ".\n"
+ "The ViewHierarchy doesn't contain a view with resource id = R.id.navigationView");
}
}

@After
public void afterTest() {
IdlingRegistry.getInstance().unregister(idlingResource);
}

protected void validateTestSetup() {
Assert.assertTrue("Device is not connected to the Internet.", isConnected(rule.getActivity()));
checkViewIsDisplayed(R.id.navigationView);
Expand All @@ -57,6 +70,21 @@ protected NavigationView getNavigationView() {

protected abstract Class getActivityClass();

protected String loadJsonFromAsset(String filename) {
try {
InputStream is = assetManager.open(filename);
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
return new String(buffer, "UTF-8");

} catch (IOException ex) {
ex.printStackTrace();
return null;
}
}

private void checkViewIsDisplayed(int id) {
onView(withId(id)).check(matches(isDisplayed()));
}
Expand All @@ -67,9 +95,4 @@ private boolean isConnected(Context context) {
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}

@After
public void afterTest() {
IdlingRegistry.getInstance().unregister(idlingResource);
}
}
Original file line number Diff line number Diff line change
@@ -1,51 +1,26 @@
package testapp.utils;

import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.os.Handler;
import android.os.Looper;
import android.support.test.espresso.IdlingResource;

import com.google.gson.GsonBuilder;
import com.mapbox.api.directions.v5.DirectionsAdapterFactory;
import com.mapbox.api.directions.v5.models.DirectionsResponse;
import com.mapbox.api.directions.v5.models.DirectionsRoute;
import com.mapbox.geojson.Point;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.services.android.navigation.testapp.R;
import com.mapbox.services.android.navigation.ui.v5.NavigationView;
import com.mapbox.services.android.navigation.ui.v5.NavigationViewOptions;
import com.mapbox.services.android.navigation.ui.v5.OnNavigationReadyCallback;
import com.mapbox.services.android.navigation.v5.navigation.NavigationRoute;

import java.lang.reflect.Field;
public class OnNavigationReadyIdlingResource implements IdlingResource, OnNavigationReadyCallback {

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class OnNavigationReadyIdlingResource implements IdlingResource, Callback<DirectionsResponse>,
OnNavigationReadyCallback {

private static final String NAVIGATION_VIEW = "navigationView";
private static final String TEST_ROUTE_JSON = "test_route_json";
private static final int FIRST_ROUTE = 0;
private boolean isNavigationReady;
private NavigationView navigationView;
private DirectionsRoute testRoute;
private ResourceCallback resourceCallback;
private SharedPreferences preferences;
private IdlingResource.ResourceCallback resourceCallback;
private boolean isNavigationReady;
private final Handler handler = new Handler(Looper.getMainLooper());

public OnNavigationReadyIdlingResource(Activity activity) {
try {
Field field = activity.getClass().getDeclaredField(NAVIGATION_VIEW);
field.setAccessible(true);
navigationView = (NavigationView) field.get(activity);
preferences = PreferenceManager.getDefaultSharedPreferences(activity);
fetchRoute(activity);
} catch (Exception err) {
throw new RuntimeException(err);
}
handler.post(() -> {
navigationView = activity.findViewById(R.id.navigationView);
navigationView.initialize(OnNavigationReadyIdlingResource.this);
});
}

@Override
Expand All @@ -67,53 +42,15 @@ public NavigationView getNavigationView() {
return navigationView;
}

@Override
public void onResponse(@NonNull Call<DirectionsResponse> call, @NonNull Response<DirectionsResponse> response) {
testRoute = response.body().routes().get(FIRST_ROUTE);
storeRouteForRotation(testRoute);
navigationView.initialize(this);
}

@Override
public void onFailure(@NonNull Call<DirectionsResponse> call, @NonNull Throwable throwable) {
throw new RuntimeException(throwable);
}

@Override
public void onNavigationReady(boolean isRunning) {
navigationView.startNavigation(buildTestNavigationViewOptions());
transitionToIdle();
}

private void fetchRoute(Context context) {
Point origin = Point.fromLngLat(-77.033987, 38.900123);
Point destination = Point.fromLngLat(-77.044818, 38.848942);
NavigationRoute.builder(context)
.accessToken(Mapbox.getAccessToken())
.origin(origin)
.destination(destination)
.build().getRoute(this);
}

private void storeRouteForRotation(DirectionsRoute route) {
SharedPreferences.Editor editor = preferences.edit();
String testRouteJson = new GsonBuilder()
.registerTypeAdapterFactory(DirectionsAdapterFactory.create()).create().toJson(route);
editor.putString(TEST_ROUTE_JSON, testRouteJson);
editor.apply();
}

private NavigationViewOptions buildTestNavigationViewOptions() {
return NavigationViewOptions.builder()
.directionsRoute(testRoute)
.shouldSimulateRoute(true)
.build();
}

private void transitionToIdle() {
isNavigationReady = true;
if (resourceCallback != null) {
resourceCallback.onTransitionToIdle();
}
}
}
}
Loading

0 comments on commit 4956fcb

Please sign in to comment.