From e66c362fad21ddad9d8a6c4f11f86fbc8d5827be Mon Sep 17 00:00:00 2001 From: Marco Romano Date: Wed, 26 Jul 2023 06:13:22 +0200 Subject: [PATCH] Add missing tests --- .../impl/show/ShowLocationPresenterTest.kt | 163 ++++++++++++++++++ 1 file changed, 163 insertions(+) diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt index e0a59e0998..12ccdc16a5 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt @@ -22,6 +22,7 @@ import app.cash.turbine.test import com.google.common.truth.Truth import io.element.android.features.location.api.Location import io.element.android.features.location.impl.common.actions.FakeLocationActions +import io.element.android.features.location.impl.common.permissions.PermissionsEvents import io.element.android.features.location.impl.common.permissions.PermissionsPresenter import io.element.android.features.location.impl.common.permissions.PermissionsPresenterFake import io.element.android.features.location.impl.common.permissions.PermissionsState @@ -48,6 +49,33 @@ class ShowLocationPresenterTest { @Test fun `emits initial state with no location permission`() = runTest { + permissionsPresenterFake.givenState( + PermissionsState( + permissions = PermissionsState.Permissions.NoneGranted, + shouldShowRationale = false, + ) + ) + + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + Truth.assertThat(initialState.location).isEqualTo(location) + Truth.assertThat(initialState.description).isEqualTo(A_DESCRIPTION) + Truth.assertThat(initialState.hasLocationPermission).isEqualTo(false) + Truth.assertThat(initialState.isTrackMyLocation).isEqualTo(false) + } + } + + @Test + fun `emits initial state location permission denied once`() = runTest { + permissionsPresenterFake.givenState( + PermissionsState( + permissions = PermissionsState.Permissions.NoneGranted, + shouldShowRationale = true, + ) + ) + moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -120,9 +148,144 @@ class ShowLocationPresenterTest { Truth.assertThat(trackMyLocationState.hasLocationPermission).isEqualTo(true) Truth.assertThat(trackMyLocationState.isTrackMyLocation).isEqualTo(true) + + // Swipe the map to switch mode + initialState.eventSink(ShowLocationEvents.TrackMyLocation(false)) + val trackLocationDisabledState = awaitItem() + Truth.assertThat(trackLocationDisabledState.permissionDialog).isEqualTo(ShowLocationState.Dialog.None) + Truth.assertThat(trackLocationDisabledState.isTrackMyLocation).isEqualTo(false) + Truth.assertThat(trackLocationDisabledState.hasLocationPermission).isEqualTo(true) } } + @Test + fun `rationale dialog dismiss`() = runTest { + permissionsPresenterFake.givenState( + PermissionsState( + permissions = PermissionsState.Permissions.NoneGranted, + shouldShowRationale = true, + ) + ) + + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + // Skip initial state + val initialState = awaitItem() + + // Click on the button to switch mode + initialState.eventSink(ShowLocationEvents.TrackMyLocation(true)) + val trackLocationState = awaitItem() + Truth.assertThat(trackLocationState.permissionDialog).isEqualTo(ShowLocationState.Dialog.PermissionRationale) + Truth.assertThat(trackLocationState.isTrackMyLocation).isEqualTo(false) + Truth.assertThat(trackLocationState.hasLocationPermission).isEqualTo(false) + + // Dismiss the dialog + initialState.eventSink(ShowLocationEvents.DismissDialog) + val dialogDismissedState = awaitItem() + Truth.assertThat(dialogDismissedState.permissionDialog).isEqualTo(ShowLocationState.Dialog.None) + Truth.assertThat(dialogDismissedState.isTrackMyLocation).isEqualTo(false) + Truth.assertThat(dialogDismissedState.hasLocationPermission).isEqualTo(false) + } + } + + @Test + fun `rationale dialog continue`() = runTest { + permissionsPresenterFake.givenState( + PermissionsState( + permissions = PermissionsState.Permissions.NoneGranted, + shouldShowRationale = true, + ) + ) + + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + // Skip initial state + val initialState = awaitItem() + + // Click on the button to switch mode + initialState.eventSink(ShowLocationEvents.TrackMyLocation(true)) + val trackLocationState = awaitItem() + Truth.assertThat(trackLocationState.permissionDialog).isEqualTo(ShowLocationState.Dialog.PermissionRationale) + Truth.assertThat(trackLocationState.isTrackMyLocation).isEqualTo(false) + Truth.assertThat(trackLocationState.hasLocationPermission).isEqualTo(false) + + // Continue the dialog sends permission request to the permissions presenter + trackLocationState.eventSink(ShowLocationEvents.RequestPermissions) + Truth.assertThat(permissionsPresenterFake.events.last()).isEqualTo(PermissionsEvents.RequestPermissions) + } + } + + @Test + fun `permission denied dialog dismiss`() = runTest { + permissionsPresenterFake.givenState( + PermissionsState( + permissions = PermissionsState.Permissions.NoneGranted, + shouldShowRationale = false, + ) + ) + + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + // Skip initial state + val initialState = awaitItem() + + // Click on the button to switch mode + initialState.eventSink(ShowLocationEvents.TrackMyLocation(true)) + val trackLocationState = awaitItem() + Truth.assertThat(trackLocationState.permissionDialog).isEqualTo(ShowLocationState.Dialog.PermissionDenied) + Truth.assertThat(trackLocationState.isTrackMyLocation).isEqualTo(false) + Truth.assertThat(trackLocationState.hasLocationPermission).isEqualTo(false) + + // Dismiss the dialog + initialState.eventSink(ShowLocationEvents.DismissDialog) + val dialogDismissedState = awaitItem() + Truth.assertThat(dialogDismissedState.permissionDialog).isEqualTo(ShowLocationState.Dialog.None) + Truth.assertThat(dialogDismissedState.isTrackMyLocation).isEqualTo(false) + Truth.assertThat(dialogDismissedState.hasLocationPermission).isEqualTo(false) + } + } + + @Test + fun `open settings activity`() = runTest { + permissionsPresenterFake.givenState( + PermissionsState( + permissions = PermissionsState.Permissions.NoneGranted, + shouldShowRationale = false, + ) + ) + + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + // Skip initial state + val initialState = awaitItem() + + initialState.eventSink(ShowLocationEvents.TrackMyLocation(true)) + val dialogShownState = awaitItem() + + // Open settings + dialogShownState.eventSink(ShowLocationEvents.OpenAppSettings) + val settingsOpenedState = awaitItem() + + Truth.assertThat(settingsOpenedState.permissionDialog).isEqualTo(ShowLocationState.Dialog.None) + Truth.assertThat(fakeLocationActions.openSettingsInvocationsCount).isEqualTo(1) + } + } + + @Test + fun `application name is in state`() = runTest { + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + Truth.assertThat(initialState.appName).isEqualTo("app name") + } + } + + companion object { private const val A_DESCRIPTION = "My happy place" }