diff --git a/libnavui-androidauto/CHANGELOG.md b/libnavui-androidauto/CHANGELOG.md index 3a5857c48ac..9c7bc6aec4b 100644 --- a/libnavui-androidauto/CHANGELOG.md +++ b/libnavui-androidauto/CHANGELOG.md @@ -8,6 +8,8 @@ Mapbox welcomes participation and contributions from everyone. - Remove experimental from `MapboxCarNavigationManager` and showcase java. [#6292](https://github.com/mapbox/mapbox-navigation-android/pull/6292) - Removed `MapboxNavigation` from `CarNavigationInfoObserver` constructor, and rename to `CarNavigationInfoProvider`. Removed dependencies from `CarActiveGuidanceCarContext` that require `MapboxNavigation`. [#6224](https://github.com/mapbox/mapbox-navigation-android/pull/6224) - Removed `MapboxNavigation` from `CarSpeedLimitRenderer` constructor. [#6325](https://github.com/mapbox/mapbox-navigation-android/pull/6325) +- Deleted `CarActiveGuidanceCarContext` because it is no longer needed after `MapboxNavigation` is removed. [#6326](https://github.com/mapbox/mapbox-navigation-android/pull/6326) +- Added `CarArrivalTrigger` and `CarActiveGuidanceMarkers` for logical components that help build the `ActiveGuidanceScreen`. [#6326](https://github.com/mapbox/mapbox-navigation-android/pull/6326) ## androidauto-v0.10.0 - Sep 9, 2022 ### Changelog diff --git a/libnavui-androidauto/api/current.txt b/libnavui-androidauto/api/current.txt index 71c8a83f607..913dde2465d 100644 --- a/libnavui-androidauto/api/current.txt +++ b/libnavui-androidauto/api/current.txt @@ -305,7 +305,7 @@ package com.mapbox.androidauto.car.map.widgets.logo { package com.mapbox.androidauto.car.navigation { public final class ActiveGuidanceScreen extends androidx.car.app.Screen { - ctor public ActiveGuidanceScreen(com.mapbox.androidauto.car.navigation.CarActiveGuidanceCarContext carActiveGuidanceContext, java.util.List actionProviders, com.mapbox.androidauto.car.placeslistonmap.PlacesListOnMapLayerUtil placesLayerUtil = com.mapbox.androidauto.car.placeslistonmap.PlacesListOnMapLayerUtil()); + ctor public ActiveGuidanceScreen(com.mapbox.androidauto.car.MainCarContext mainCarContext, java.util.List actionProviders); method public com.mapbox.androidauto.car.location.CarLocationRenderer getCarLocationRenderer(); method public com.mapbox.androidauto.car.navigation.CarNavigationCamera getCarNavigationCamera(); method public com.mapbox.androidauto.car.preview.CarRouteLine getCarRouteLine(); @@ -317,18 +317,17 @@ package com.mapbox.androidauto.car.navigation { property public final com.mapbox.androidauto.car.navigation.speedlimit.CarSpeedLimitRenderer carSpeedLimitRenderer; } - public final class CarActiveGuidanceCarContext { - ctor public CarActiveGuidanceCarContext(com.mapbox.androidauto.car.MainCarContext mainCarContext); - method public androidx.car.app.CarContext getCarContext(); - method public com.mapbox.navigation.base.formatter.DistanceFormatter getDistanceFormatter(); - method public com.mapbox.androidauto.car.MainCarContext getMainCarContext(); - method public com.mapbox.maps.extension.androidauto.MapboxCarMap getMapboxCarMap(); - method public com.mapbox.navigation.core.MapboxNavigation getMapboxNavigation(); - property public final androidx.car.app.CarContext carContext; - property public final com.mapbox.navigation.base.formatter.DistanceFormatter distanceFormatter; - property public final com.mapbox.androidauto.car.MainCarContext mainCarContext; - property public final com.mapbox.maps.extension.androidauto.MapboxCarMap mapboxCarMap; - property public final com.mapbox.navigation.core.MapboxNavigation mapboxNavigation; + public final class CarActiveGuidanceMarkers implements com.mapbox.maps.extension.androidauto.MapboxCarMapObserver { + ctor public CarActiveGuidanceMarkers(); + method public void onAttached(com.mapbox.maps.extension.androidauto.MapboxCarMapSurface mapboxCarMapSurface); + method public void onDetached(com.mapbox.maps.extension.androidauto.MapboxCarMapSurface mapboxCarMapSurface); + } + + public final class CarArrivalTrigger implements com.mapbox.navigation.core.lifecycle.MapboxNavigationObserver { + ctor public CarArrivalTrigger(); + method public void onAttached(com.mapbox.navigation.core.MapboxNavigation mapboxNavigation); + method public void onDetached(com.mapbox.navigation.core.MapboxNavigation mapboxNavigation); + method public void triggerArrival(); } public enum CarCameraMode { diff --git a/libnavui-androidauto/src/main/java/com/mapbox/androidauto/car/MainScreenManager.kt b/libnavui-androidauto/src/main/java/com/mapbox/androidauto/car/MainScreenManager.kt index 6f76a457fb9..f8157066331 100644 --- a/libnavui-androidauto/src/main/java/com/mapbox/androidauto/car/MainScreenManager.kt +++ b/libnavui-androidauto/src/main/java/com/mapbox/androidauto/car/MainScreenManager.kt @@ -12,7 +12,6 @@ import com.mapbox.androidauto.car.feedback.core.CarFeedbackSender import com.mapbox.androidauto.car.feedback.ui.CarFeedbackAction import com.mapbox.androidauto.car.feedback.ui.CarGridFeedbackScreen import com.mapbox.androidauto.car.navigation.ActiveGuidanceScreen -import com.mapbox.androidauto.car.navigation.CarActiveGuidanceCarContext import com.mapbox.androidauto.internal.logAndroidAuto import com.mapbox.androidauto.navigation.audioguidance.CarAudioGuidanceUi import kotlinx.coroutines.flow.collect @@ -28,7 +27,7 @@ class MainScreenManager(val mainCarContext: MainCarContext) { FreeDriveState, RoutePreviewState -> MainCarScreen(mainCarContext) ActiveGuidanceState -> { ActiveGuidanceScreen( - CarActiveGuidanceCarContext(mainCarContext), + mainCarContext, listOf( CarFeedbackAction( mainCarContext.mapboxCarMap, diff --git a/libnavui-androidauto/src/main/java/com/mapbox/androidauto/car/navigation/ActiveGuidanceScreen.kt b/libnavui-androidauto/src/main/java/com/mapbox/androidauto/car/navigation/ActiveGuidanceScreen.kt index c56de082377..eb9306b1a52 100644 --- a/libnavui-androidauto/src/main/java/com/mapbox/androidauto/car/navigation/ActiveGuidanceScreen.kt +++ b/libnavui-androidauto/src/main/java/com/mapbox/androidauto/car/navigation/ActiveGuidanceScreen.kt @@ -8,30 +8,17 @@ import androidx.car.app.model.Template import androidx.car.app.navigation.model.NavigationTemplate import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.LifecycleOwner -import com.mapbox.androidauto.ArrivalState -import com.mapbox.androidauto.MapboxCarApp import com.mapbox.androidauto.R +import com.mapbox.androidauto.car.MainCarContext import com.mapbox.androidauto.car.MainMapActionStrip import com.mapbox.androidauto.car.action.MapboxActionProvider import com.mapbox.androidauto.car.location.CarLocationRenderer import com.mapbox.androidauto.car.navigation.roadlabel.RoadLabelSurfaceLayer import com.mapbox.androidauto.car.navigation.speedlimit.CarSpeedLimitRenderer -import com.mapbox.androidauto.car.placeslistonmap.PlacesListOnMapLayerUtil import com.mapbox.androidauto.car.preview.CarRouteLine -import com.mapbox.androidauto.internal.car.extensions.getStyle -import com.mapbox.androidauto.internal.car.extensions.handleStyleOnAttached -import com.mapbox.androidauto.internal.car.extensions.handleStyleOnDetached import com.mapbox.androidauto.internal.logAndroidAuto -import com.mapbox.geojson.Feature -import com.mapbox.geojson.FeatureCollection import com.mapbox.maps.MapboxExperimental -import com.mapbox.maps.extension.androidauto.MapboxCarMapObserver -import com.mapbox.maps.extension.androidauto.MapboxCarMapSurface -import com.mapbox.maps.plugin.delegates.listeners.OnStyleLoadedListener -import com.mapbox.navigation.base.trip.model.RouteLegProgress -import com.mapbox.navigation.base.trip.model.RouteProgress -import com.mapbox.navigation.core.arrival.ArrivalObserver -import com.mapbox.navigation.core.directions.session.RoutesObserver +import com.mapbox.navigation.core.lifecycle.MapboxNavigationApp /** * After a route has been selected. This view gives turn-by-turn instructions @@ -39,14 +26,13 @@ import com.mapbox.navigation.core.directions.session.RoutesObserver */ @OptIn(MapboxExperimental::class) class ActiveGuidanceScreen( - private val carActiveGuidanceContext: CarActiveGuidanceCarContext, + private val mainCarContext: MainCarContext, private val actionProviders: List, - private val placesLayerUtil: PlacesListOnMapLayerUtil = PlacesListOnMapLayerUtil(), -) : Screen(carActiveGuidanceContext.carContext) { +) : Screen(mainCarContext.carContext) { - val carRouteLine = CarRouteLine(carActiveGuidanceContext.mainCarContext) - val carLocationRenderer = CarLocationRenderer(carActiveGuidanceContext.mainCarContext) - val carSpeedLimitRenderer = CarSpeedLimitRenderer(carActiveGuidanceContext.mainCarContext) + val carRouteLine = CarRouteLine(mainCarContext) + val carLocationRenderer = CarLocationRenderer(mainCarContext) + val carSpeedLimitRenderer = CarSpeedLimitRenderer(mainCarContext) val carNavigationCamera = CarNavigationCamera( initialCarCameraMode = CarCameraMode.FOLLOWING, alternativeCarCameraMode = CarCameraMode.OVERVIEW, @@ -54,98 +40,37 @@ class ActiveGuidanceScreen( private val roadLabelSurfaceLayer = RoadLabelSurfaceLayer(carContext) private val navigationInfoProvider = CarNavigationInfoProvider() .invalidateOnChange(this) + private val carActiveGuidanceMarkers = CarActiveGuidanceMarkers() private val mapActionStripBuilder = MainMapActionStrip(this, carNavigationCamera) - - private val arrivalObserver = object : ArrivalObserver { - - override fun onFinalDestinationArrival(routeProgress: RouteProgress) { - stopNavigation() - } - - override fun onNextRouteLegStart(routeLegProgress: RouteLegProgress) { - // not implemented - } - - override fun onWaypointArrival(routeProgress: RouteProgress) { - // not implemented - } - } - - private var styleLoadedListener: OnStyleLoadedListener? = null - - private val surfaceListener = object : MapboxCarMapObserver { - - override fun onAttached(mapboxCarMapSurface: MapboxCarMapSurface) { - super.onAttached(mapboxCarMapSurface) - logAndroidAuto("ActiveGuidanceScreen loaded") - styleLoadedListener = mapboxCarMapSurface.handleStyleOnAttached { - placesLayerUtil.initializePlacesListOnMapLayer(it, carContext.resources) - carActiveGuidanceContext.mapboxNavigation.registerRoutesObserver(routesObserver) - } - } - - override fun onDetached(mapboxCarMapSurface: MapboxCarMapSurface) { - super.onDetached(mapboxCarMapSurface) - logAndroidAuto("ActiveGuidanceScreen detached") - carActiveGuidanceContext.mapboxNavigation.unregisterRoutesObserver(routesObserver) - mapboxCarMapSurface.handleStyleOnDetached(styleLoadedListener)?.let { - placesLayerUtil.removePlacesListOnMapLayer(it) - } - } - } - - private val routesObserver = RoutesObserver { result -> - val route = result.navigationRoutes.firstOrNull() - ?: return@RoutesObserver - val coordinate = route.routeOptions.coordinatesList().lastOrNull() - ?: return@RoutesObserver - val mapboxCarMapSurface = carActiveGuidanceContext.mapboxCarMap.carMapSurface - ?: return@RoutesObserver - val featureCollection = FeatureCollection.fromFeature(Feature.fromGeometry(coordinate)) - mapboxCarMapSurface.getStyle()?.let { - placesLayerUtil.updatePlacesListOnMapLayer(it, featureCollection) - } - } + private val carArrivalTrigger = CarArrivalTrigger() init { logAndroidAuto("ActiveGuidanceScreen constructor") - lifecycle.addObserver(object : DefaultLifecycleObserver { - - override fun onCreate(owner: LifecycleOwner) { - logAndroidAuto("ActiveGuidanceScreen onCreate") - carActiveGuidanceContext.mapboxNavigation.registerArrivalObserver(arrivalObserver) - } - override fun onResume(owner: LifecycleOwner) { logAndroidAuto("ActiveGuidanceScreen onResume") - carActiveGuidanceContext.mapboxCarMap.registerObserver(carLocationRenderer) - carActiveGuidanceContext.mapboxCarMap.registerObserver(roadLabelSurfaceLayer) - carActiveGuidanceContext.mapboxCarMap.registerObserver(carSpeedLimitRenderer) - carActiveGuidanceContext.mapboxCarMap.registerObserver(carNavigationCamera) - carActiveGuidanceContext.mapboxCarMap.setGestureHandler( - carNavigationCamera.gestureHandler - ) - carActiveGuidanceContext.mapboxCarMap.registerObserver(carRouteLine) - carActiveGuidanceContext.mapboxCarMap.registerObserver(surfaceListener) - carActiveGuidanceContext.mapboxCarMap.registerObserver(navigationInfoProvider) + mainCarContext.mapboxCarMap.registerObserver(carLocationRenderer) + mainCarContext.mapboxCarMap.registerObserver(roadLabelSurfaceLayer) + mainCarContext.mapboxCarMap.registerObserver(carSpeedLimitRenderer) + mainCarContext.mapboxCarMap.registerObserver(carNavigationCamera) + mainCarContext.mapboxCarMap.setGestureHandler(carNavigationCamera.gestureHandler) + mainCarContext.mapboxCarMap.registerObserver(carRouteLine) + mainCarContext.mapboxCarMap.registerObserver(carActiveGuidanceMarkers) + mainCarContext.mapboxCarMap.registerObserver(navigationInfoProvider) + MapboxNavigationApp.registerObserver(carArrivalTrigger) } override fun onPause(owner: LifecycleOwner) { logAndroidAuto("ActiveGuidanceScreen onPause") - carActiveGuidanceContext.mapboxCarMap.unregisterObserver(roadLabelSurfaceLayer) - carActiveGuidanceContext.mapboxCarMap.unregisterObserver(carLocationRenderer) - carActiveGuidanceContext.mapboxCarMap.unregisterObserver(carSpeedLimitRenderer) - carActiveGuidanceContext.mapboxCarMap.unregisterObserver(carNavigationCamera) - carActiveGuidanceContext.mapboxCarMap.setGestureHandler(null) - carActiveGuidanceContext.mapboxCarMap.unregisterObserver(carRouteLine) - carActiveGuidanceContext.mapboxCarMap.unregisterObserver(surfaceListener) - carActiveGuidanceContext.mapboxCarMap.unregisterObserver(navigationInfoProvider) - } - - override fun onDestroy(owner: LifecycleOwner) { - logAndroidAuto("ActiveGuidanceScreen onDestroy") - carActiveGuidanceContext.mapboxNavigation.unregisterArrivalObserver(arrivalObserver) + mainCarContext.mapboxCarMap.unregisterObserver(roadLabelSurfaceLayer) + mainCarContext.mapboxCarMap.unregisterObserver(carLocationRenderer) + mainCarContext.mapboxCarMap.unregisterObserver(carSpeedLimitRenderer) + mainCarContext.mapboxCarMap.unregisterObserver(carNavigationCamera) + mainCarContext.mapboxCarMap.setGestureHandler(null) + mainCarContext.mapboxCarMap.unregisterObserver(carRouteLine) + mainCarContext.mapboxCarMap.unregisterObserver(carActiveGuidanceMarkers) + mainCarContext.mapboxCarMap.unregisterObserver(navigationInfoProvider) + MapboxNavigationApp.unregisterObserver(carArrivalTrigger) } }) } @@ -167,7 +92,7 @@ class ActiveGuidanceScreen( Action.Builder() .setTitle(carContext.getString(R.string.car_action_navigation_stop_button)) .setOnClickListener { - stopNavigation() + carArrivalTrigger.triggerArrival() }.build() ) }.build() @@ -179,9 +104,4 @@ class ActiveGuidanceScreen( .apply { navigationInfoProvider.setNavigationInfo(this) } .build() } - - private fun stopNavigation() { - logAndroidAuto("ActiveGuidanceScreen stopNavigation") - MapboxCarApp.updateCarAppState(ArrivalState) - } } diff --git a/libnavui-androidauto/src/main/java/com/mapbox/androidauto/car/navigation/CarActiveGuidanceCarContext.kt b/libnavui-androidauto/src/main/java/com/mapbox/androidauto/car/navigation/CarActiveGuidanceCarContext.kt deleted file mode 100644 index 4de6be4bf15..00000000000 --- a/libnavui-androidauto/src/main/java/com/mapbox/androidauto/car/navigation/CarActiveGuidanceCarContext.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.mapbox.androidauto.car.navigation - -import com.mapbox.androidauto.car.MainCarContext - -class CarActiveGuidanceCarContext( - val mainCarContext: MainCarContext -) { - /** MapCarContext **/ - val carContext = mainCarContext.carContext - val mapboxCarMap = mainCarContext.mapboxCarMap - val mapboxNavigation = mainCarContext.mapboxNavigation - val distanceFormatter = mainCarContext.distanceFormatter -} diff --git a/libnavui-androidauto/src/main/java/com/mapbox/androidauto/car/navigation/CarActiveGuidanceMarkers.kt b/libnavui-androidauto/src/main/java/com/mapbox/androidauto/car/navigation/CarActiveGuidanceMarkers.kt new file mode 100644 index 00000000000..fc8fc2b12c8 --- /dev/null +++ b/libnavui-androidauto/src/main/java/com/mapbox/androidauto/car/navigation/CarActiveGuidanceMarkers.kt @@ -0,0 +1,65 @@ +package com.mapbox.androidauto.car.navigation + +import com.mapbox.androidauto.car.placeslistonmap.PlacesListOnMapLayerUtil +import com.mapbox.androidauto.internal.car.extensions.getStyle +import com.mapbox.androidauto.internal.car.extensions.handleStyleOnAttached +import com.mapbox.androidauto.internal.car.extensions.handleStyleOnDetached +import com.mapbox.androidauto.internal.car.extensions.mapboxNavigationForward +import com.mapbox.androidauto.internal.logAndroidAuto +import com.mapbox.geojson.Feature +import com.mapbox.geojson.FeatureCollection +import com.mapbox.maps.MapboxExperimental +import com.mapbox.maps.extension.androidauto.MapboxCarMapObserver +import com.mapbox.maps.extension.androidauto.MapboxCarMapSurface +import com.mapbox.maps.plugin.delegates.listeners.OnStyleLoadedListener +import com.mapbox.navigation.core.MapboxNavigation +import com.mapbox.navigation.core.directions.session.RoutesObserver +import com.mapbox.navigation.core.lifecycle.MapboxNavigationApp + +@OptIn(MapboxExperimental::class) +class CarActiveGuidanceMarkers : MapboxCarMapObserver { + private var styleLoadedListener: OnStyleLoadedListener? = null + private var mapboxCarMapSurface: MapboxCarMapSurface? = null + private val navigationObserver = mapboxNavigationForward(this::onAttached, this::onDetached) + private val routesObserver = RoutesObserver { updateMarkers() } + private val placesLayerUtil = PlacesListOnMapLayerUtil() + + private fun updateMarkers() { + val route = MapboxNavigationApp.current()?.getNavigationRoutes()?.firstOrNull() + ?: return + val coordinate = route.routeOptions.coordinatesList().lastOrNull() + ?: return + val featureCollection = FeatureCollection.fromFeature(Feature.fromGeometry(coordinate)) + mapboxCarMapSurface?.getStyle()?.let { + placesLayerUtil.updatePlacesListOnMapLayer(it, featureCollection) + } + } + + override fun onAttached(mapboxCarMapSurface: MapboxCarMapSurface) { + logAndroidAuto("ActiveGuidanceScreen loaded") + this.mapboxCarMapSurface = mapboxCarMapSurface + val carContext = mapboxCarMapSurface.carContext + styleLoadedListener = mapboxCarMapSurface.handleStyleOnAttached { + placesLayerUtil.initializePlacesListOnMapLayer(it, carContext.resources) + updateMarkers() + } + MapboxNavigationApp.registerObserver(navigationObserver) + } + + override fun onDetached(mapboxCarMapSurface: MapboxCarMapSurface) { + super.onDetached(mapboxCarMapSurface) + logAndroidAuto("ActiveGuidanceScreen detached") + MapboxNavigationApp.unregisterObserver(navigationObserver) + mapboxCarMapSurface.handleStyleOnDetached(styleLoadedListener)?.let { + placesLayerUtil.removePlacesListOnMapLayer(it) + } + } + + private fun onAttached(mapboxNavigation: MapboxNavigation) { + mapboxNavigation.registerRoutesObserver(routesObserver) + } + + private fun onDetached(mapboxNavigation: MapboxNavigation) { + mapboxNavigation.unregisterRoutesObserver(routesObserver) + } +} diff --git a/libnavui-androidauto/src/main/java/com/mapbox/androidauto/car/navigation/CarArrivalTrigger.kt b/libnavui-androidauto/src/main/java/com/mapbox/androidauto/car/navigation/CarArrivalTrigger.kt new file mode 100644 index 00000000000..33fe3005571 --- /dev/null +++ b/libnavui-androidauto/src/main/java/com/mapbox/androidauto/car/navigation/CarArrivalTrigger.kt @@ -0,0 +1,50 @@ +package com.mapbox.androidauto.car.navigation + +import com.mapbox.androidauto.ArrivalState +import com.mapbox.androidauto.MapboxCarApp +import com.mapbox.androidauto.internal.logAndroidAuto +import com.mapbox.maps.extension.androidauto.MapboxCarMapObserver +import com.mapbox.navigation.base.trip.model.RouteLegProgress +import com.mapbox.navigation.base.trip.model.RouteProgress +import com.mapbox.navigation.core.MapboxNavigation +import com.mapbox.navigation.core.arrival.ArrivalObserver +import com.mapbox.navigation.core.lifecycle.MapboxNavigationObserver + +/** + * When attached this will observe when the final destination is reached and change the car app + * state to the [ArrivalState]. This is not a [MapboxCarMapObserver] because arrival can happen + * even when the map is not showing. + */ +class CarArrivalTrigger : MapboxNavigationObserver { + + private val arrivalObserver = object : ArrivalObserver { + + override fun onFinalDestinationArrival(routeProgress: RouteProgress) { + triggerArrival() + } + + override fun onNextRouteLegStart(routeLegProgress: RouteLegProgress) { + // not implemented + } + + override fun onWaypointArrival(routeProgress: RouteProgress) { + // not implemented + } + } + + override fun onAttached(mapboxNavigation: MapboxNavigation) { + mapboxNavigation.registerArrivalObserver(arrivalObserver) + } + + override fun onDetached(mapboxNavigation: MapboxNavigation) { + mapboxNavigation.unregisterArrivalObserver(arrivalObserver) + } + + /** + * Manually trigger the arrival. + */ + fun triggerArrival() { + logAndroidAuto("CarArrivalTrigger triggerArrival") + MapboxCarApp.updateCarAppState(ArrivalState) + } +} diff --git a/libnavui-androidauto/src/test/java/com/mapbox/androidauto/car/navigation/CarArrivalTriggerTest.kt b/libnavui-androidauto/src/test/java/com/mapbox/androidauto/car/navigation/CarArrivalTriggerTest.kt new file mode 100644 index 00000000000..57ea7606281 --- /dev/null +++ b/libnavui-androidauto/src/test/java/com/mapbox/androidauto/car/navigation/CarArrivalTriggerTest.kt @@ -0,0 +1,55 @@ +package com.mapbox.androidauto.car.navigation + +import com.mapbox.androidauto.ArrivalState +import com.mapbox.androidauto.MapboxCarApp +import com.mapbox.navigation.core.MapboxNavigation +import com.mapbox.navigation.core.arrival.ArrivalObserver +import io.mockk.every +import io.mockk.just +import io.mockk.mockk +import io.mockk.mockkObject +import io.mockk.runs +import io.mockk.slot +import io.mockk.unmockkAll +import io.mockk.verify +import org.junit.After +import org.junit.Before +import org.junit.Test + +class CarArrivalTriggerTest { + + private val sut = CarArrivalTrigger() + + @Before + fun setup() { + mockkObject(MapboxCarApp) + } + + @After + fun teardown() { + unmockkAll() + } + + @Test + fun `should go to ArrivalState when onFinalDestinationArrival is called`() { + val observerSlot = slot() + val mapboxNavigation: MapboxNavigation = mockk(relaxed = true) { + every { registerArrivalObserver(capture(observerSlot)) } just runs + } + + sut.onAttached(mapboxNavigation) + observerSlot.captured.onFinalDestinationArrival(mockk()) + + verify { MapboxCarApp.updateCarAppState(ArrivalState) } + } + + @Test + fun `should unregisterArrivalObserver when MapboxNavigation is detached`() { + val mapboxNavigation: MapboxNavigation = mockk(relaxed = true) + + sut.onAttached(mapboxNavigation) + sut.onDetached(mapboxNavigation) + + verify { mapboxNavigation.unregisterArrivalObserver(any()) } + } +}