From 27e567e6f4b63d11ec659a9c1920343e4d60673e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 15 Sep 2023 19:24:43 +0200 Subject: [PATCH] Fix the test. --- .../editprofile/EditUserProfilePresenter.kt | 9 +++- .../EditUserProfilePresenterTest.kt | 42 ++++++++++--------- .../libraries/matrix/test/FakeMatrixClient.kt | 7 ++-- 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenter.kt index 5d3821931e..793c4840d7 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenter.kt @@ -26,6 +26,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue +import androidx.core.net.toUri import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject @@ -111,8 +112,12 @@ class EditUserProfilePresenter @AssistedInject constructor( ) } - private fun hasDisplayNameChanged(name: String?, currentUser: MatrixUser?) = name?.trim() != currentUser?.displayName?.trim() - private fun hasAvatarUrlChanged(avatarUri: Uri?, currentUser: MatrixUser?) = avatarUri?.toString()?.trim() != currentUser?.avatarUrl?.trim() + private fun hasDisplayNameChanged(name: String?, currentUser: MatrixUser) = + name?.trim() != currentUser.displayName?.trim() + + private fun hasAvatarUrlChanged(avatarUri: Uri?, currentUser: MatrixUser) = + // Need to call `toUri()?.toString()` to make the test pass (we mockk Uri) + avatarUri?.toString()?.trim() != currentUser.avatarUrl?.toUri()?.toString()?.trim() private fun CoroutineScope.saveChanges(name: String?, avatarUri: Uri?, currentUser: MatrixUser, action: MutableState>) = launch { val results = mutableListOf>() diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenterTest.kt index d3580a82b1..beece60c9a 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenterTest.kt @@ -33,6 +33,7 @@ import io.element.android.libraries.mediapickers.test.FakePickerProvider import io.element.android.libraries.mediaupload.api.MediaUploadInfo import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.consumeItemsUntilPredicate import io.mockk.every import io.mockk.mockk import io.mockk.mockkStatic @@ -87,14 +88,14 @@ class EditUserProfilePresenterTest { } @Test - fun `present - initial state is created from room info`() = runTest { + fun `present - initial state is created from user info`() = runTest { val user = aMatrixUser(avatarUrl = AN_AVATAR_URL) val presenter = createEditUserProfilePresenter(matrixUser = user) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { val initialState = awaitItem() - assertThat(initialState.userId).isEqualTo(user.userId.value) + assertThat(initialState.userId).isEqualTo(user.userId) assertThat(initialState.displayName).isEqualTo(user.displayName) assertThat(initialState.userAvatarUrl).isEqualTo(userAvatarUri) assertThat(initialState.avatarActions).containsExactly( @@ -102,7 +103,7 @@ class EditUserProfilePresenterTest { AvatarAction.TakePhoto, AvatarAction.Remove ) - assertThat(initialState.saveButtonEnabled).isEqualTo(false) + assertThat(initialState.saveButtonEnabled).isFalse() assertThat(initialState.saveAction).isInstanceOf(Async.Uninitialized::class.java) } } @@ -178,26 +179,26 @@ class EditUserProfilePresenterTest { presenter.present() }.test { val initialState = awaitItem() - assertThat(initialState.saveButtonEnabled).isEqualTo(false) + assertThat(initialState.saveButtonEnabled).isFalse() // Once a change is made, the save button is enabled initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("Name II")) awaitItem().apply { - assertThat(saveButtonEnabled).isEqualTo(true) + assertThat(saveButtonEnabled).isTrue() } // If it's reverted then the save disables again initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("Name")) awaitItem().apply { - assertThat(saveButtonEnabled).isEqualTo(false) + assertThat(saveButtonEnabled).isFalse() } // Make a change... initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.Remove)) awaitItem().apply { - assertThat(saveButtonEnabled).isEqualTo(true) + assertThat(saveButtonEnabled).isTrue() } // Revert it... initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.ChoosePhoto)) awaitItem().apply { - assertThat(saveButtonEnabled).isEqualTo(false) + assertThat(saveButtonEnabled).isFalse() } } } @@ -211,26 +212,26 @@ class EditUserProfilePresenterTest { presenter.present() }.test { val initialState = awaitItem() - assertThat(initialState.saveButtonEnabled).isEqualTo(false) + assertThat(initialState.saveButtonEnabled).isFalse() // Once a change is made, the save button is enabled initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("Name II")) awaitItem().apply { - assertThat(saveButtonEnabled).isEqualTo(true) + assertThat(saveButtonEnabled).isTrue() } // If it's reverted then the save disables again - initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("fallback")) + initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("Name")) awaitItem().apply { - assertThat(saveButtonEnabled).isEqualTo(false) + assertThat(saveButtonEnabled).isFalse() } // Make a change... initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.ChoosePhoto)) awaitItem().apply { - assertThat(saveButtonEnabled).isEqualTo(true) + assertThat(saveButtonEnabled).isTrue() } // Revert it... initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.Remove)) awaitItem().apply { - assertThat(saveButtonEnabled).isEqualTo(false) + assertThat(saveButtonEnabled).isFalse() } } } @@ -250,7 +251,7 @@ class EditUserProfilePresenterTest { initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("New name")) initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.Remove)) initialState.eventSink(EditUserProfileEvents.Save) - skipItems(5) + consumeItemsUntilPredicate { matrixClient.setDisplayNameCalled && matrixClient.removeAvatarCalled && !matrixClient.uploadAvatarCalled } assertThat(matrixClient.setDisplayNameCalled).isTrue() assertThat(matrixClient.removeAvatarCalled).isTrue() assertThat(matrixClient.uploadAvatarCalled).isFalse() @@ -259,7 +260,7 @@ class EditUserProfilePresenterTest { } @Test - fun `present - save doesn't change room details if they're the same trimmed`() = runTest { + fun `present - save does not change room details if they're the same trimmed`() = runTest { val matrixClient = FakeMatrixClient() val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL) val presenter = createEditUserProfilePresenter( @@ -272,7 +273,8 @@ class EditUserProfilePresenterTest { val initialState = awaitItem() initialState.eventSink(EditUserProfileEvents.UpdateDisplayName(" Name ")) initialState.eventSink(EditUserProfileEvents.Save) - assertThat(matrixClient.setDisplayNameCalled).isTrue() + consumeItemsUntilPredicate { matrixClient.setDisplayNameCalled && !matrixClient.removeAvatarCalled && !matrixClient.uploadAvatarCalled } + assertThat(matrixClient.setDisplayNameCalled).isFalse() assertThat(matrixClient.uploadAvatarCalled).isFalse() assertThat(matrixClient.removeAvatarCalled).isFalse() cancelAndIgnoreRemainingEvents() @@ -280,7 +282,7 @@ class EditUserProfilePresenterTest { } @Test - fun `present - save doesn't change name if it's now empty`() = runTest { + fun `present - save does not change name if it's now empty`() = runTest { val matrixClient = FakeMatrixClient() val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL) val presenter = createEditUserProfilePresenter( @@ -315,7 +317,7 @@ class EditUserProfilePresenterTest { val initialState = awaitItem() initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.ChoosePhoto)) initialState.eventSink(EditUserProfileEvents.Save) - skipItems(2) + consumeItemsUntilPredicate { matrixClient.uploadAvatarCalled } assertThat(matrixClient.uploadAvatarCalled).isTrue() } } @@ -377,7 +379,7 @@ class EditUserProfilePresenterTest { val matrixClient = FakeMatrixClient().apply { givenSetDisplayNameResult(Result.failure(Throwable("!"))) } - val presenter = createEditUserProfilePresenter(matrixUser = user) + val presenter = createEditUserProfilePresenter(matrixUser = user, matrixClient = matrixClient) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt index ce518730c4..67a36f0db7 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt @@ -143,6 +143,7 @@ class FakeMatrixClient( override suspend fun getAccountManagementUrl(action: AccountManagementAction?): Result { return accountManagementUrlString } + override suspend fun uploadMedia( mimeType: String, data: ByteArray, @@ -151,17 +152,17 @@ class FakeMatrixClient( return uploadMediaResult } - override suspend fun setDisplayName(displayName: String): Result { + override suspend fun setDisplayName(displayName: String): Result = simulateLongTask { setDisplayNameCalled = true return setDisplayNameResult } - override suspend fun uploadAvatar(mimeType: String, data: ByteArray): Result { + override suspend fun uploadAvatar(mimeType: String, data: ByteArray): Result = simulateLongTask { uploadAvatarCalled = true return uploadAvatarResult } - override suspend fun removeAvatar(): Result { + override suspend fun removeAvatar(): Result = simulateLongTask { removeAvatarCalled = true return removeAvatarResult }