diff --git a/features/createroom/impl/build.gradle.kts b/features/createroom/impl/build.gradle.kts index 4d3e8f191d..2026ac5214 100644 --- a/features/createroom/impl/build.gradle.kts +++ b/features/createroom/impl/build.gradle.kts @@ -52,6 +52,7 @@ dependencies { api(projects.features.createroom.api) testImplementation(libs.test.junit) + testImplementation(libs.test.mockk) testImplementation(libs.coroutines.test) testImplementation(libs.molecule.runtime) testImplementation(libs.test.truth) diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt index c0a43784f7..7659226bd9 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt @@ -119,8 +119,8 @@ class ConfigureRoomPresenter @Inject constructor( config: CreateRoomConfig, createRoomAction: MutableState> ) = launch { - val mxc = config.avatarUri?.let { uploadAvatar(it) } suspend { + val mxc = config.avatarUri?.let { uploadAvatar(it) } val params = CreateRoomParameters( name = config.roomName, topic = config.topic, diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenterTests.kt b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenterTests.kt index 71ea4062f1..eadad19d23 100644 --- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenterTests.kt +++ b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenterTests.kt @@ -29,21 +29,29 @@ import io.element.android.features.createroom.impl.configureroom.avatar.AvatarAc import io.element.android.features.userlist.api.UserListDataStore import io.element.android.libraries.architecture.Async import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.test.AN_AVATAR_URL import io.element.android.libraries.matrix.test.A_MESSAGE import io.element.android.libraries.matrix.test.A_ROOM_NAME import io.element.android.libraries.matrix.test.A_THROWABLE import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.ui.components.aMatrixUser 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.mockk.every +import io.mockk.mockk +import io.mockk.mockkStatic +import io.mockk.unmockkAll import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest +import org.junit.After import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner +import java.io.File private const val AN_URI_FROM_CAMERA = "content://uri_from_camera" private const val AN_URI_FROM_GALLERY = "content://uri_from_gallery" @@ -56,6 +64,7 @@ class ConfigureRoomPresenterTests { private lateinit var createRoomDataStore: CreateRoomDataStore private lateinit var fakeMatrixClient: FakeMatrixClient private lateinit var fakePickerProvider: FakePickerProvider + private lateinit var fakeMediaPreProcessor: FakeMediaPreProcessor @Before fun setup() { @@ -63,12 +72,21 @@ class ConfigureRoomPresenterTests { userListDataStore = UserListDataStore() createRoomDataStore = CreateRoomDataStore(userListDataStore) fakePickerProvider = FakePickerProvider() + fakeMediaPreProcessor = FakeMediaPreProcessor() presenter = ConfigureRoomPresenter( dataStore = createRoomDataStore, matrixClient = fakeMatrixClient, mediaPickerProvider = fakePickerProvider, - mediaPreProcessor = FakeMediaPreProcessor(), + mediaPreProcessor = fakeMediaPreProcessor, ) + + mockkStatic(File::readBytes) + every { any().readBytes() } returns byteArrayOf() + } + + @After + fun tearDown() { + unmockkAll() } @Test @@ -206,6 +224,30 @@ class ConfigureRoomPresenterTests { } } + @Test + fun `present - trigger create room with upload error and retry`() = runTest { + moleculeFlow(RecompositionClock.Immediate) { + presenter.present() + }.test { + skipItems(1) + createRoomDataStore.setAvatarUri(Uri.parse(AN_URI_FROM_GALLERY)) + fakeMediaPreProcessor.givenResult(Result.success(MediaUploadInfo.Image(mockk(), mockk(), null))) + fakeMatrixClient.givenUploadMediaResult(Result.failure(A_THROWABLE)) + + val initialState = awaitItem() + initialState.eventSink(ConfigureRoomEvents.CreateRoom(initialState.config)) + val stateAfterCreateRoom = awaitItem() + assertThat(stateAfterCreateRoom.createRoomAction).isInstanceOf(Async.Failure::class.java) + + fakeMatrixClient.givenUploadMediaResult(Result.success(AN_AVATAR_URL)) + stateAfterCreateRoom.eventSink(ConfigureRoomEvents.CreateRoom(initialState.config)) + assertThat(awaitItem().createRoomAction).isInstanceOf(Async.Uninitialized::class.java) + assertThat(awaitItem().createRoomAction).isInstanceOf(Async.Loading::class.java) + assertThat(awaitItem().createRoomAction).isInstanceOf(Async.Success::class.java) + + } + } + @Test fun `present - trigger retry and cancel actions`() = runTest { moleculeFlow(RecompositionClock.Immediate) { 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 51088115ed..bdf76c8e05 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 @@ -59,6 +59,7 @@ class FakeMatrixClient( private val getRoomResults = mutableMapOf() private val searchUserResults = mutableMapOf>() private val getProfileResults = mutableMapOf>() + private var uploadMediaResult: Result = Result.success(AN_AVATAR_URL) override fun getRoom(roomId: RoomId): MatrixRoom? { return getRoomResults[roomId] @@ -127,7 +128,7 @@ class FakeMatrixClient( } override suspend fun uploadMedia(mimeType: String, data: ByteArray): Result { - return Result.success("") + return uploadMediaResult } override fun sessionVerificationService(): SessionVerificationService = sessionVerificationService @@ -183,4 +184,8 @@ class FakeMatrixClient( fun givenGetProfileResult(userId: UserId, result: Result) { getProfileResults[userId] = result } + + fun givenUploadMediaResult(result: Result) { + uploadMediaResult = result + } }