Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.mapbox.mapboxsdk.plugins.locationlayer

import android.Manifest
import android.R
import android.content.Context
import android.location.Location
import android.support.test.espresso.Espresso.onView
Expand All @@ -20,6 +21,8 @@ import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.*
import com.mapbox.mapboxsdk.plugins.locationlayer.modes.RenderMode
import com.mapbox.mapboxsdk.plugins.testapp.activity.SingleActivity
import com.mapbox.mapboxsdk.plugins.utils.*
import com.mapbox.mapboxsdk.plugins.utils.MapboxTestingUtils.Companion.MAPBOX_HEAVY_STYLE
import com.mapbox.mapboxsdk.plugins.utils.MapboxTestingUtils.Companion.pushSourceUpdates
import com.mapbox.mapboxsdk.plugins.utils.PluginGenerationUtil.Companion.MAP_CONNECTION_DELAY
import com.mapbox.mapboxsdk.plugins.utils.PluginGenerationUtil.Companion.MAP_RENDER_DELAY
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource
Expand Down Expand Up @@ -47,6 +50,7 @@ class LocationLayerTest {
val permissionRule: GrantPermissionRule = grant(Manifest.permission.ACCESS_FINE_LOCATION)

private lateinit var idlingResource: OnMapReadyIdlingResource
private lateinit var styleChangeIdlingResource: StyleChangeIdlingResource
private lateinit var mapboxMap: MapboxMap
private val location: Location by lazy {
val initLocation = Location("test")
Expand All @@ -60,7 +64,9 @@ class LocationLayerTest {
Timber.e("@Before: register idle resource")
// If idlingResource is null, throw Kotlin exception
idlingResource = OnMapReadyIdlingResource(rule.activity)
styleChangeIdlingResource = StyleChangeIdlingResource()
IdlingRegistry.getInstance().register(idlingResource)
IdlingRegistry.getInstance().register(styleChangeIdlingResource)
onView(withId(android.R.id.content)).check(matches(isDisplayed()))
mapboxMap = idlingResource.mapboxMap
}
Expand Down Expand Up @@ -94,11 +100,11 @@ class LocationLayerTest {
plugin.renderMode = RenderMode.NORMAL
plugin.forceLocationUpdate(location)
uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY)
assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(equalTo(true)))
assertThat(mapboxMap.isLayerVisible(BACKGROUND_LAYER), `is`(equalTo(true)))
assertThat(mapboxMap.isLayerVisible(SHADOW_LAYER), `is`(equalTo(true)))
assertThat(mapboxMap.isLayerVisible(ACCURACY_LAYER), `is`(equalTo(true)))
assertThat(mapboxMap.isLayerVisible(BEARING_LAYER), `is`(equalTo(false)))
assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(true))
assertThat(mapboxMap.isLayerVisible(BACKGROUND_LAYER), `is`(true))
assertThat(mapboxMap.isLayerVisible(SHADOW_LAYER), `is`(true))
assertThat(mapboxMap.isLayerVisible(ACCURACY_LAYER), `is`(true))
assertThat(mapboxMap.isLayerVisible(BEARING_LAYER), `is`(false))
}
}
executePluginTest(pluginAction)
Expand All @@ -112,11 +118,11 @@ class LocationLayerTest {
plugin.renderMode = RenderMode.COMPASS
plugin.forceLocationUpdate(location)
uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY)
assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(equalTo(true)))
assertThat(mapboxMap.isLayerVisible(BACKGROUND_LAYER), `is`(equalTo(true)))
assertThat(mapboxMap.isLayerVisible(SHADOW_LAYER), `is`(equalTo(true)))
assertThat(mapboxMap.isLayerVisible(ACCURACY_LAYER), `is`(equalTo(true)))
assertThat(mapboxMap.isLayerVisible(BEARING_LAYER), `is`(equalTo(true)))
assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(true))
assertThat(mapboxMap.isLayerVisible(BACKGROUND_LAYER), `is`(true))
assertThat(mapboxMap.isLayerVisible(SHADOW_LAYER), `is`(true))
assertThat(mapboxMap.isLayerVisible(ACCURACY_LAYER), `is`(true))
assertThat(mapboxMap.isLayerVisible(BEARING_LAYER), `is`(true))
}
}
executePluginTest(pluginAction)
Expand All @@ -130,11 +136,11 @@ class LocationLayerTest {
plugin.renderMode = RenderMode.GPS
plugin.forceLocationUpdate(location)
uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY)
assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(equalTo(true)))
assertThat(mapboxMap.isLayerVisible(BACKGROUND_LAYER), `is`(equalTo(true)))
assertThat(mapboxMap.isLayerVisible(SHADOW_LAYER), `is`(equalTo(false)))
assertThat(mapboxMap.isLayerVisible(ACCURACY_LAYER), `is`(equalTo(false)))
assertThat(mapboxMap.isLayerVisible(BEARING_LAYER), `is`(equalTo(false)))
assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(true))
assertThat(mapboxMap.isLayerVisible(BACKGROUND_LAYER), `is`(true))
assertThat(mapboxMap.isLayerVisible(SHADOW_LAYER), `is`(false))
assertThat(mapboxMap.isLayerVisible(ACCURACY_LAYER), `is`(false))
assertThat(mapboxMap.isLayerVisible(BEARING_LAYER), `is`(false))
}
}
executePluginTest(pluginAction)
Expand All @@ -151,11 +157,11 @@ class LocationLayerTest {
uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY)

// Check that all layers visibilities are set to none
assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(equalTo(false)))
assertThat(mapboxMap.isLayerVisible(BACKGROUND_LAYER), `is`(equalTo(false)))
assertThat(mapboxMap.isLayerVisible(SHADOW_LAYER), `is`(equalTo(false)))
assertThat(mapboxMap.isLayerVisible(ACCURACY_LAYER), `is`(equalTo(false)))
assertThat(mapboxMap.isLayerVisible(BEARING_LAYER), `is`(equalTo(false)))
assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(false))
assertThat(mapboxMap.isLayerVisible(BACKGROUND_LAYER), `is`(false))
assertThat(mapboxMap.isLayerVisible(SHADOW_LAYER), `is`(false))
assertThat(mapboxMap.isLayerVisible(ACCURACY_LAYER), `is`(false))
assertThat(mapboxMap.isLayerVisible(BEARING_LAYER), `is`(false))
}
}
executePluginTest(pluginAction)
Expand All @@ -168,7 +174,8 @@ class LocationLayerTest {
uiController: UiController, context: Context) {
plugin.renderMode = RenderMode.NORMAL
plugin.forceLocationUpdate(location)
mapboxMap.setStyleUrl(Style.SATELLITE)
mapboxMap.setStyleUrl(Style.LIGHT)
plugin.forceLocationUpdate(location)
uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY)

assertThat(plugin.renderMode, `is`(equalTo(RenderMode.NORMAL)))
Expand All @@ -178,11 +185,11 @@ class LocationLayerTest {
assertThat(source, notNullValue())

// Check that all layers visibilities are set to visible
assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(equalTo(true)))
assertThat(mapboxMap.isLayerVisible(BACKGROUND_LAYER), `is`(equalTo(true)))
assertThat(mapboxMap.isLayerVisible(SHADOW_LAYER), `is`(equalTo(true)))
assertThat(mapboxMap.isLayerVisible(ACCURACY_LAYER), `is`(equalTo(true)))
assertThat(mapboxMap.isLayerVisible(BEARING_LAYER), `is`(equalTo(false)))
assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(true))
assertThat(mapboxMap.isLayerVisible(BACKGROUND_LAYER), `is`(true))
assertThat(mapboxMap.isLayerVisible(SHADOW_LAYER), `is`(true))
assertThat(mapboxMap.isLayerVisible(ACCURACY_LAYER), `is`(true))
assertThat(mapboxMap.isLayerVisible(BEARING_LAYER), `is`(false))
}
}
executePluginTest(pluginAction)
Expand All @@ -193,7 +200,7 @@ class LocationLayerTest {
//

@Test
fun whenDrawableChanged_continuesUsingStaleIcons() {
fun whenStyleChanged_continuesUsingStaleIcons() {
val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction<LocationLayerPlugin> {
override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap,
uiController: UiController, context: Context) {
Expand All @@ -202,21 +209,61 @@ class LocationLayerTest {
uiController.loopMainThreadForAtLeast(200)
uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY)

assertThat(mapboxMap.queryLocationSourceFeatures(LOCATION_SOURCE)[0].getBooleanProperty(PROPERTY_LOCATION_STALE), `is`(true))
assertThat(mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getBooleanProperty(PROPERTY_LOCATION_STALE), `is`(true))

mapboxMap.setStyleUrl(Style.SATELLITE)
mapboxMap.setStyleUrl(Style.LIGHT)
uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY)

assertThat(mapboxMap.queryLocationSourceFeatures(LOCATION_SOURCE)[0].getBooleanProperty(PROPERTY_LOCATION_STALE), `is`(true))
assertThat(mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getBooleanProperty(PROPERTY_LOCATION_STALE), `is`(true))
}
}
executePluginTest(pluginAction)
}

@Test
fun whenStyleChanged_staleStateChanges() {
val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction<LocationLayerPlugin> {
override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap,
uiController: UiController, context: Context) {
plugin.applyStyle(LocationLayerOptions.builder(context).staleStateTimeout(1).build())
styleChangeIdlingResource.waitForStyle(idlingResource.mapView, mapboxMap, MAPBOX_HEAVY_STYLE)
pushSourceUpdates(styleChangeIdlingResource) {
plugin.forceLocationUpdate(location)
}
}
}
executePluginTest(pluginAction)

// Waiting for style to finish loading while pushing updates
onView(withId(R.id.content)).check(matches(isDisplayed()))
}

@Test
fun whenStyleChanged_layerVisibilityUpdates() {
val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction<LocationLayerPlugin> {
override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap,
uiController: UiController, context: Context) {
styleChangeIdlingResource.waitForStyle(idlingResource.mapView, mapboxMap, MAPBOX_HEAVY_STYLE)
var show = true
pushSourceUpdates(styleChangeIdlingResource) {
plugin.isLocationLayerEnabled = show
show = !show
}

uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY)
}
}
executePluginTest(pluginAction)

// Waiting for style to finish loading while pushing updates
onView(withId(R.id.content)).check(matches(isDisplayed()))
}

@After
fun afterTest() {
Timber.e("@After: unregister idle resource")
IdlingRegistry.getInstance().unregister(idlingResource)
IdlingRegistry.getInstance().unregister(styleChangeIdlingResource)
}

private fun executePluginTest(listener: GenericPluginAction.OnPerformGenericPluginAction<LocationLayerPlugin>) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,52 @@
package com.mapbox.mapboxsdk.plugins.utils

import android.os.Handler
import android.os.Looper
import com.mapbox.geojson.Feature
import com.mapbox.mapboxsdk.maps.MapboxMap
import com.mapbox.mapboxsdk.style.layers.Property
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource

fun MapboxMap.queryLocationSourceFeatures(sourceId: String): List<Feature> {
fun MapboxMap.querySourceFeatures(sourceId: String): List<Feature> {
return this.getSourceAs<GeoJsonSource>(sourceId)?.querySourceFeatures(null) as List<Feature>
}

fun MapboxMap.isLayerVisible(layerId: String): Boolean {
return this.getLayer(layerId)?.visibility?.value?.equals(Property.VISIBLE)!!
}

class MapboxTestingUtils {
companion object {

/**
* Used to increase style load time for stress testing.
*/
const val MAPBOX_HEAVY_STYLE = "asset://heavy_style.json"

private const val DATA_PUSH_INTERVAL = 1L

/**
* Pushes data updates every [DATA_PUSH_INTERVAL] milliseconds until the style has been loaded,
* checked with [StyleChangeIdlingResource].
*/
fun pushSourceUpdates(styleChangeIdlingResource: StyleChangeIdlingResource, update: () -> Unit) {
val mainHandler = Handler(Looper.getMainLooper())
val runnable = object : Runnable {
override fun run() {
update.invoke()
if (!styleChangeIdlingResource.isIdleNow) {
mainHandler.postDelayed(this, DATA_PUSH_INTERVAL)
}
}
}

if (!styleChangeIdlingResource.isIdleNow) {
if (Looper.myLooper() == Looper.getMainLooper()) {
runnable.run()
} else {
mainHandler.post(runnable)
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.mapbox.mapboxsdk.plugins.utils

import android.os.Handler
import android.os.Looper
import android.support.test.espresso.IdlingResource

import com.mapbox.mapboxsdk.maps.MapboxMap
Expand All @@ -13,7 +15,9 @@ class OnMapFragmentReadyIdlingResource(fragment: SupportMapFragment?) : IdlingRe
private var resourceCallback: IdlingResource.ResourceCallback? = null

init {
fragment?.getMapAsync(this)
Handler(Looper.getMainLooper()).post {
fragment?.getMapAsync(this)
}
}

override fun getName(): String {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.mapbox.mapboxsdk.plugins.utils;

import android.app.Activity;
import android.os.Handler;
import android.os.Looper;
import android.support.test.espresso.IdlingResource;

import com.mapbox.mapboxsdk.maps.MapView;
Expand All @@ -16,14 +18,16 @@ public class OnMapReadyIdlingResource implements IdlingResource, OnMapReadyCallb
private IdlingResource.ResourceCallback resourceCallback;

public OnMapReadyIdlingResource(Activity activity) {
try {
Field field = activity.getClass().getDeclaredField("mapView");
field.setAccessible(true);
mapView = ((MapView) field.get(activity));
mapView.getMapAsync(this);
} catch (Exception err) {
throw new RuntimeException(err);
}
new Handler(Looper.getMainLooper()).post(() -> {
try {
Field field = activity.getClass().getDeclaredField("mapView");
field.setAccessible(true);
mapView = ((MapView) field.get(activity));
mapView.getMapAsync(this);
} catch (Exception err) {
throw new RuntimeException(err);
}
});
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.mapbox.mapboxsdk.plugins.utils

import android.support.test.espresso.IdlingResource
import com.mapbox.mapboxsdk.maps.MapView
import com.mapbox.mapboxsdk.maps.MapboxMap

/**
* Resource, that's idling until the provided style is loaded.
* Remember to add any espresso action (like view assertion) after the [waitForStyle] call
* for the test to keep running.
*/
class StyleChangeIdlingResource : IdlingResource {

private var callback: IdlingResource.ResourceCallback? = null
private var isIdle = true

override fun getName(): String {
return javaClass.simpleName
}

override fun isIdleNow(): Boolean {
return isIdle
}

override fun registerIdleTransitionCallback(callback: IdlingResource.ResourceCallback?) {
this.callback = callback
}

private fun setIdle() {
isIdle = true
callback?.onTransitionToIdle()
}

fun waitForStyle(mapView: MapView, mapboxMap: MapboxMap, styleUrl: String) {
isIdle = false
mapView.addOnMapChangedListener(object : MapView.OnMapChangedListener {
override fun onMapChanged(change: Int) {
if (change == MapView.DID_FINISH_LOADING_STYLE) {
mapView.removeOnMapChangedListener(this)
setIdle()
}
}
})
mapboxMap.setStyleUrl(styleUrl)
}
}
Loading