Browse Source

Unit and Snapshot tests for error and loading states.

pull/1610/head
David Langley 11 months ago
parent
commit
75e95333a8
  1. 8
      features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsStateProvider.kt
  2. 11
      features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingStateProvider.kt
  3. 22
      features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/EditDefaultNotificationSettingsPresenterTests.kt
  4. 30
      features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenterTests.kt
  5. 52
      features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsStateProvider.kt
  6. 49
      features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/notificationsettings/RoomNotificationSettingsPresenterTests.kt
  7. 28
      libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt

8
features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsStateProvider.kt

@ -24,10 +24,14 @@ open class NotificationSettingsStateProvider : PreviewParameterProvider<Notifica @@ -24,10 +24,14 @@ open class NotificationSettingsStateProvider : PreviewParameterProvider<Notifica
override val values: Sequence<NotificationSettingsState>
get() = sequenceOf(
aNotificationSettingsState(),
aNotificationSettingsState(changeNotificationSettingAction = Async.Loading(Unit)),
aNotificationSettingsState(changeNotificationSettingAction = Async.Failure(Throwable("error"))),
)
}
fun aNotificationSettingsState() = NotificationSettingsState(
fun aNotificationSettingsState(
changeNotificationSettingAction: Async<Unit> = Async.Uninitialized,
) = NotificationSettingsState(
matrixSettings = NotificationSettingsState.MatrixSettings.Valid(
atRoomNotificationsEnabled = true,
callNotificationsEnabled = true,
@ -38,6 +42,6 @@ fun aNotificationSettingsState() = NotificationSettingsState( @@ -38,6 +42,6 @@ fun aNotificationSettingsState() = NotificationSettingsState(
systemNotificationsEnabled = false,
appNotificationsEnabled = true,
),
changeNotificationSettingAction = Async.Uninitialized,
changeNotificationSettingAction = changeNotificationSettingAction,
eventSink = {}
)

11
features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingStateProvider.kt

@ -27,15 +27,20 @@ open class EditDefaultNotificationSettingStateProvider: PreviewParameterProvider @@ -27,15 +27,20 @@ open class EditDefaultNotificationSettingStateProvider: PreviewParameterProvider
override val values: Sequence<EditDefaultNotificationSettingState>
get() = sequenceOf(
anEditDefaultNotificationSettingsState(),
anEditDefaultNotificationSettingsState(isOneToOne = true)
anEditDefaultNotificationSettingsState(isOneToOne = true),
anEditDefaultNotificationSettingsState(changeNotificationSettingAction = Async.Loading(Unit)),
anEditDefaultNotificationSettingsState(changeNotificationSettingAction = Async.Failure(Throwable("error"))),
)
}
fun anEditDefaultNotificationSettingsState(isOneToOne: Boolean = false) = EditDefaultNotificationSettingState(
private fun anEditDefaultNotificationSettingsState(
isOneToOne: Boolean = false,
changeNotificationSettingAction: Async<Unit> = Async.Uninitialized
) = EditDefaultNotificationSettingState(
isOneToOne = isOneToOne,
mode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY,
roomsWithUserDefinedMode = listOf(aRoomSummary()),
changeNotificationSettingAction = Async.Uninitialized,
changeNotificationSettingAction = changeNotificationSettingAction,
eventSink = {}
)

22
features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/EditDefaultNotificationSettingsPresenterTests.kt

@ -25,6 +25,7 @@ import io.element.android.features.preferences.impl.notifications.edit.EditDefau @@ -25,6 +25,7 @@ import io.element.android.features.preferences.impl.notifications.edit.EditDefau
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.libraries.matrix.test.A_THROWABLE
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
@ -90,6 +91,27 @@ class EditDefaultNotificationSettingsPresenterTests { @@ -90,6 +91,27 @@ class EditDefaultNotificationSettingsPresenterTests {
}
}
@Test
fun `present - edit default notification setting failed`() = runTest {
val notificationSettingsService = FakeNotificationSettingsService()
val presenter = createEditDefaultNotificationSettingPresenter(notificationSettingsService)
notificationSettingsService.givenSetDefaultNotificationModeError(A_THROWABLE)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
awaitItem().eventSink(EditDefaultNotificationSettingStateEvents.SetNotificationMode(RoomNotificationMode.ALL_MESSAGES))
val errorState = consumeItemsUntilPredicate {
it.changeNotificationSettingAction.isFailure()
}.last()
Truth.assertThat(errorState.changeNotificationSettingAction.isFailure()).isTrue()
errorState.eventSink(EditDefaultNotificationSettingStateEvents.ClearError)
val clearErrorState = consumeItemsUntilPredicate {
it.changeNotificationSettingAction.isUninitialized()
}.last()
Truth.assertThat(clearErrorState.changeNotificationSettingAction.isUninitialized()).isTrue()
}
}
private fun createEditDefaultNotificationSettingPresenter(
notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService(),
roomListService: FakeRoomListService = FakeRoomListService(),

30
features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenterTests.kt

@ -22,6 +22,7 @@ import app.cash.turbine.test @@ -22,6 +22,7 @@ import app.cash.turbine.test
import com.element.android.libraries.pushstore.test.userpushstore.FakeUserPushStoreFactory
import com.google.common.truth.Truth
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.test.A_THROWABLE
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService
import io.element.android.tests.testutils.consumeItemsUntilPredicate
@ -187,6 +188,35 @@ class NotificationSettingsPresenterTests { @@ -187,6 +188,35 @@ class NotificationSettingsPresenterTests {
}
}
@Test
fun `present - clear notification settings change error`() = runTest {
val notificationSettingsService = FakeNotificationSettingsService()
val presenter = createNotificationSettingsPresenter(notificationSettingsService)
notificationSettingsService.givenSetAtRoomError(A_THROWABLE)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val loadedState = consumeItemsUntilPredicate {
(it.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid)?.atRoomNotificationsEnabled == false
}.last()
val validMatrixState = loadedState.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid
Truth.assertThat(validMatrixState?.atRoomNotificationsEnabled).isFalse()
loadedState.eventSink(NotificationSettingsEvents.SetAtRoomNotificationsEnabled(true))
val errorState = consumeItemsUntilPredicate {
it.changeNotificationSettingAction.isFailure()
}.last()
Truth.assertThat(errorState.changeNotificationSettingAction.isFailure()).isTrue()
errorState.eventSink(NotificationSettingsEvents.ClearNotificationChangeError)
val clearErrorState = consumeItemsUntilPredicate {
it.changeNotificationSettingAction.isUninitialized()
}.last()
Truth.assertThat(clearErrorState.changeNotificationSettingAction.isUninitialized()).isTrue()
cancelAndIgnoreRemainingEvents()
}
}
private fun createNotificationSettingsPresenter(
notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService()
) : NotificationSettingsPresenter {

52
features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsStateProvider.kt

@ -24,31 +24,31 @@ import io.element.android.libraries.matrix.api.room.RoomNotificationSettings @@ -24,31 +24,31 @@ import io.element.android.libraries.matrix.api.room.RoomNotificationSettings
internal class RoomNotificationSettingsStateProvider : PreviewParameterProvider<RoomNotificationSettingsState> {
override val values: Sequence<RoomNotificationSettingsState>
get() = sequenceOf(
RoomNotificationSettingsState(
showUserDefinedSettingStyle = false,
roomName = "Room 1",
Async.Success(RoomNotificationSettings(
mode = RoomNotificationMode.MUTE,
isDefault = true)),
pendingRoomNotificationMode = null,
pendingSetDefault = null,
defaultRoomNotificationMode = RoomNotificationMode.ALL_MESSAGES,
setNotificationSettingAction = Async.Uninitialized,
restoreDefaultAction = Async.Uninitialized,
eventSink = { },
),
RoomNotificationSettingsState(
showUserDefinedSettingStyle = false,
roomName = "Room 1",
Async.Success(RoomNotificationSettings(
mode = RoomNotificationMode.MUTE,
isDefault = false)),
pendingRoomNotificationMode = null,
pendingSetDefault = null,
defaultRoomNotificationMode = RoomNotificationMode.ALL_MESSAGES,
setNotificationSettingAction = Async.Uninitialized,
restoreDefaultAction = Async.Uninitialized,
eventSink = { },
),
aRoomNotificationSettingsState(),
aRoomNotificationSettingsState(isDefault = false),
aRoomNotificationSettingsState(setNotificationSettingAction = Async.Loading(Unit)),
aRoomNotificationSettingsState(setNotificationSettingAction = Async.Failure(Throwable("error"))),
aRoomNotificationSettingsState(restoreDefaultAction = Async.Loading(Unit)),
aRoomNotificationSettingsState(restoreDefaultAction = Async.Failure(Throwable("error"))),
)
private fun aRoomNotificationSettingsState(
isDefault: Boolean = true,
setNotificationSettingAction: Async<Unit> = Async.Uninitialized,
restoreDefaultAction: Async<Unit> = Async.Uninitialized,
): RoomNotificationSettingsState {
return RoomNotificationSettingsState(
showUserDefinedSettingStyle = false,
roomName = "Room 1",
Async.Success(RoomNotificationSettings(
mode = RoomNotificationMode.MUTE,
isDefault = isDefault)),
pendingRoomNotificationMode = null,
pendingSetDefault = null,
defaultRoomNotificationMode = RoomNotificationMode.ALL_MESSAGES,
setNotificationSettingAction = setNotificationSettingAction,
restoreDefaultAction = restoreDefaultAction,
eventSink = { },
)
}
}

49
features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/notificationsettings/RoomNotificationSettingsPresenterTests.kt

@ -30,7 +30,6 @@ import io.element.android.libraries.matrix.test.notificationsettings.FakeNotific @@ -30,7 +30,6 @@ import io.element.android.libraries.matrix.test.notificationsettings.FakeNotific
import io.element.android.tests.testutils.consumeItemsUntilPredicate
import kotlinx.coroutines.test.runTest
import org.junit.Test
import kotlin.time.Duration.Companion.milliseconds
class RoomNotificationSettingsPresenterTests {
@Test
@ -76,7 +75,6 @@ class RoomNotificationSettingsPresenterTests { @@ -76,7 +75,6 @@ class RoomNotificationSettingsPresenterTests {
}
}
@Test
fun `present - notification settings set custom failed`() = runTest {
val notificationSettingsService = FakeNotificationSettingsService()
@ -87,13 +85,20 @@ class RoomNotificationSettingsPresenterTests { @@ -87,13 +85,20 @@ class RoomNotificationSettingsPresenterTests {
}.test {
val initialState = awaitItem()
initialState.eventSink(RoomNotificationSettingsEvents.SetNotificationMode(false))
val states = consumeItemsUntilPredicate {
it.roomNotificationSettings.dataOrNull()?.isDefault == false
}
states.forEach {
Truth.assertThat(it.roomNotificationSettings.dataOrNull()?.isDefault).isTrue()
Truth.assertThat(it.pendingSetDefault).isNull()
}
val failedState = consumeItemsUntilPredicate {
it.setNotificationSettingAction.isFailure()
}.last()
Truth.assertThat(failedState.roomNotificationSettings.dataOrNull()?.isDefault).isTrue()
Truth.assertThat(failedState.pendingSetDefault).isNull()
Truth.assertThat(failedState.setNotificationSettingAction.isFailure()).isTrue()
failedState.eventSink(RoomNotificationSettingsEvents.ClearSetNotificationError)
val errorClearedState = consumeItemsUntilPredicate {
it.setNotificationSettingAction.isUninitialized()
}.last()
Truth.assertThat(errorClearedState.setNotificationSettingAction.isUninitialized()).isTrue()
}
}
@ -122,7 +127,7 @@ class RoomNotificationSettingsPresenterTests { @@ -122,7 +127,7 @@ class RoomNotificationSettingsPresenterTests {
val initialState = awaitItem()
initialState.eventSink(RoomNotificationSettingsEvents.RoomNotificationModeChanged(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY))
initialState.eventSink(RoomNotificationSettingsEvents.SetNotificationMode(true))
val defaultState = consumeItemsUntilPredicate(timeout = 2000.milliseconds) {
val defaultState = consumeItemsUntilPredicate {
it.roomNotificationSettings.dataOrNull()?.mode == RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY
}.last()
Truth.assertThat(defaultState.roomNotificationSettings.dataOrNull()?.mode).isEqualTo(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY)
@ -130,6 +135,30 @@ class RoomNotificationSettingsPresenterTests { @@ -130,6 +135,30 @@ class RoomNotificationSettingsPresenterTests {
}
}
@Test
fun `present - notification settings restore default failed`() = runTest {
val notificationSettingsService = FakeNotificationSettingsService()
notificationSettingsService.givenRestoreDefaultNotificationModeError(A_THROWABLE)
val presenter = createRoomNotificationSettingsPresenter(notificationSettingsService)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
initialState.eventSink(RoomNotificationSettingsEvents.RoomNotificationModeChanged(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY))
initialState.eventSink(RoomNotificationSettingsEvents.SetNotificationMode(true))
val failedState = consumeItemsUntilPredicate {
it.restoreDefaultAction.isFailure()
}.last()
Truth.assertThat(failedState.restoreDefaultAction.isFailure()).isTrue()
failedState.eventSink(RoomNotificationSettingsEvents.ClearRestoreDefaultError)
val errorClearedState = consumeItemsUntilPredicate {
it.restoreDefaultAction.isUninitialized()
}.last()
Truth.assertThat(errorClearedState.restoreDefaultAction.isUninitialized()).isTrue()
cancelAndIgnoreRemainingEvents()
}
}
private fun createRoomNotificationSettingsPresenter(
notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService()
): RoomNotificationSettingsPresenter{

28
libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt

@ -43,6 +43,9 @@ class FakeNotificationSettingsService( @@ -43,6 +43,9 @@ class FakeNotificationSettingsService(
private var callNotificationsEnabled = false
private var atRoomNotificationsEnabled = false
private var setNotificationModeError: Throwable? = null
private var restoreDefaultNotificationModeError: Throwable? = null
private var setDefaultNotificationModeError: Throwable? = null
private var setAtRoomError: Throwable? = null
override val notificationSettingsChangeFlow: SharedFlow<Unit>
get() = _notificationSettingsStateFlow
@ -72,6 +75,10 @@ class FakeNotificationSettingsService( @@ -72,6 +75,10 @@ class FakeNotificationSettingsService(
}
override suspend fun setDefaultRoomNotificationMode(isEncrypted: Boolean, mode: RoomNotificationMode, isOneToOne: Boolean): Result<Unit> {
val error = setDefaultNotificationModeError
if (error != null) {
return Result.failure(error)
}
if (isOneToOne) {
if (isEncrypted) {
defaultEncryptedOneToOneRoomNotificationMode = mode
@ -102,6 +109,10 @@ class FakeNotificationSettingsService( @@ -102,6 +109,10 @@ class FakeNotificationSettingsService(
}
override suspend fun restoreDefaultRoomNotificationMode(roomId: RoomId): Result<Unit> {
val error = restoreDefaultNotificationModeError
if (error != null) {
return Result.failure(error)
}
roomNotificationModeIsDefault = true
roomNotificationMode = defaultEncryptedGroupRoomNotificationMode
_notificationSettingsStateFlow.emit(Unit)
@ -121,6 +132,10 @@ class FakeNotificationSettingsService( @@ -121,6 +132,10 @@ class FakeNotificationSettingsService(
}
override suspend fun setRoomMentionEnabled(enabled: Boolean): Result<Unit> {
val error = setAtRoomError
if (error != null) {
return Result.failure(error)
}
atRoomNotificationsEnabled = enabled
return Result.success(Unit)
}
@ -141,4 +156,17 @@ class FakeNotificationSettingsService( @@ -141,4 +156,17 @@ class FakeNotificationSettingsService(
fun givenSetNotificationModeError(throwable: Throwable?) {
setNotificationModeError = throwable
}
fun givenRestoreDefaultNotificationModeError(throwable: Throwable?) {
restoreDefaultNotificationModeError = throwable
}
fun givenSetAtRoomError(throwable: Throwable?) {
setAtRoomError = throwable
}
fun givenSetDefaultNotificationModeError(throwable: Throwable?) {
setDefaultNotificationModeError = throwable
}
}

Loading…
Cancel
Save