Introduce simulateLongTask to ensure that the Presenter State Loading is visible.

Also do some cleanup on the tests.
This commit is contained in:
Benoit Marty 2023-06-15 10:57:05 +02:00
parent 026baf9349
commit 9321a9f718
25 changed files with 169 additions and 180 deletions

View file

@ -27,7 +27,6 @@ import io.element.android.features.roomdetails.impl.RoomTopicState
import io.element.android.features.roomdetails.impl.members.aRoomMember
import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsPresenter
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
@ -48,7 +47,7 @@ class RoomDetailsPresenterTests {
private fun aRoomDetailsPresenter(room: MatrixRoom): RoomDetailsPresenter {
val roomMemberDetailsPresenterFactory = object : RoomMemberDetailsPresenter.Factory {
override fun create(roomMemberId: UserId): RoomMemberDetailsPresenter {
return RoomMemberDetailsPresenter(aMatrixClient(), room, roomMemberId)
return RoomMemberDetailsPresenter(FakeMatrixClient(), room, roomMemberId)
}
}
return RoomDetailsPresenter(room, roomMemberDetailsPresenterFactory, LeaveRoomPresenterFake())
@ -250,10 +249,6 @@ class RoomDetailsPresenterTests {
}
}
fun aMatrixClient(
sessionId: SessionId = A_SESSION_ID,
) = FakeMatrixClient(sessionId = sessionId)
fun aMatrixRoom(
roomId: RoomId = A_ROOM_ID,
name: String? = A_ROOM_NAME,

View file

@ -105,7 +105,8 @@ class RoomDetailsEditPresenterTest {
val room = aMatrixRoom(avatarUrl = AN_AVATAR_URL).apply {
givenCanSendStateResult(StateEventType.ROOM_NAME, Result.success(true))
givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.success(false))
givenCanSendStateResult(StateEventType.ROOM_TOPIC, Result.failure(Throwable("Oops"))) }
givenCanSendStateResult(StateEventType.ROOM_TOPIC, Result.failure(Throwable("Oops")))
}
val presenter = aRoomDetailsEditPresenter(room)
moleculeFlow(RecompositionClock.Immediate) {
@ -381,7 +382,7 @@ class RoomDetailsEditPresenterTest {
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomTopic("New topic"))
initialState.eventSink(RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.Remove))
initialState.eventSink(RoomDetailsEditEvents.Save)
skipItems(5)
assertThat(room.newName).isEqualTo("New name")
assertThat(room.newTopic).isEqualTo("New topic")
assertThat(room.newAvatarData).isNull()
@ -476,7 +477,7 @@ class RoomDetailsEditPresenterTest {
initialState.eventSink(RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.ChoosePhoto))
initialState.eventSink(RoomDetailsEditEvents.Save)
skipItems(2)
skipItems(3)
assertThat(room.newName).isNull()
assertThat(room.newTopic).isNull()
@ -501,7 +502,7 @@ class RoomDetailsEditPresenterTest {
initialState.eventSink(RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.ChoosePhoto))
initialState.eventSink(RoomDetailsEditEvents.Save)
skipItems(1)
skipItems(2)
assertThat(room.newName).isNull()
assertThat(room.newTopic).isNull()
@ -567,7 +568,7 @@ class RoomDetailsEditPresenterTest {
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomTopic("foo"))
initialState.eventSink(RoomDetailsEditEvents.Save)
skipItems(1)
skipItems(2)
assertThat(awaitItem().saveAction).isInstanceOf(Async.Failure::class.java)
@ -588,6 +589,7 @@ class RoomDetailsEditPresenterTest {
initialState.eventSink(RoomDetailsEditEvents.Save)
skipItems(1)
assertThat(awaitItem().saveAction).isInstanceOf(Async.Loading::class.java)
assertThat(awaitItem().saveAction).isInstanceOf(Async.Failure::class.java)
}
}
@ -599,14 +601,17 @@ class RoomDetailsEditPresenterTest {
}
fakePickerProvider.givenResult(anotherAvatarUri)
fakeMediaPreProcessor.givenResult(Result.success(MediaUploadInfo.AnyFile(
file = processedFile,
info = mockk(),
)))
fakeMediaPreProcessor.givenResult(
Result.success(
MediaUploadInfo.AnyFile(
file = processedFile,
info = mockk(),
)
)
)
}
companion object {
private const val ANOTHER_AVATAR_URL = "example://camera/foo.jpg"
}
}

View file

@ -93,9 +93,8 @@ internal class RoomInviteMembersPresenterTest {
val presenter = RoomInviteMembersPresenter(
userRepository = repository,
roomMemberListDataSource = createDataSource(FakeMatrixRoom()),
coroutineDispatchers = testCoroutineDispatchers()
coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true)
)
moleculeFlow(RecompositionClock.Immediate) {
presenter.present()
}.test {
@ -120,9 +119,8 @@ internal class RoomInviteMembersPresenterTest {
val presenter = RoomInviteMembersPresenter(
userRepository = repository,
roomMemberListDataSource = createDataSource(FakeMatrixRoom()),
coroutineDispatchers = testCoroutineDispatchers()
coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true)
)
moleculeFlow(RecompositionClock.Immediate) {
presenter.present()
}.test {
@ -157,17 +155,24 @@ internal class RoomInviteMembersPresenterTest {
val invitedUser = userList[1]
val repository = FakeUserRepository()
val coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true)
val presenter = RoomInviteMembersPresenter(
userRepository = repository,
roomMemberListDataSource = createDataSource(FakeMatrixRoom().apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(listOf(
aRoomMember(userId = joinedUser.userId, membership = RoomMembershipState.JOIN),
aRoomMember(userId = invitedUser.userId, membership = RoomMembershipState.INVITE),
)))
}),
coroutineDispatchers = testCoroutineDispatchers()
roomMemberListDataSource = createDataSource(
matrixRoom = FakeMatrixRoom().apply {
givenRoomMembersState(
MatrixRoomMembersState.Ready(
listOf(
aRoomMember(userId = joinedUser.userId, membership = RoomMembershipState.JOIN),
aRoomMember(userId = invitedUser.userId, membership = RoomMembershipState.INVITE),
)
)
)
},
coroutineDispatchers = coroutineDispatchers,
),
coroutineDispatchers = coroutineDispatchers
)
moleculeFlow(RecompositionClock.Immediate) {
presenter.present()
}.test {
@ -215,12 +220,16 @@ internal class RoomInviteMembersPresenterTest {
val presenter = RoomInviteMembersPresenter(
userRepository = repository,
roomMemberListDataSource = createDataSource(FakeMatrixRoom().apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(listOf(
aRoomMember(userId = joinedUser.userId, membership = RoomMembershipState.JOIN),
aRoomMember(userId = invitedUser.userId, membership = RoomMembershipState.INVITE),
)))
givenRoomMembersState(
MatrixRoomMembersState.Ready(
listOf(
aRoomMember(userId = joinedUser.userId, membership = RoomMembershipState.JOIN),
aRoomMember(userId = invitedUser.userId, membership = RoomMembershipState.INVITE),
)
)
)
}),
coroutineDispatchers = testCoroutineDispatchers()
coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true)
)
moleculeFlow(RecompositionClock.Immediate) {
@ -287,9 +296,8 @@ internal class RoomInviteMembersPresenterTest {
val presenter = RoomInviteMembersPresenter(
userRepository = repository,
roomMemberListDataSource = createDataSource(FakeMatrixRoom()),
coroutineDispatchers = testCoroutineDispatchers()
coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true)
)
moleculeFlow(RecompositionClock.Immediate) {
presenter.present()
}.test {
@ -323,16 +331,14 @@ internal class RoomInviteMembersPresenterTest {
}
}
@Test
fun `present - toggling a user updates existing search results`() = runTest {
val repository = FakeUserRepository()
val presenter = RoomInviteMembersPresenter(
userRepository = repository,
roomMemberListDataSource = createDataSource(FakeMatrixRoom()),
coroutineDispatchers = testCoroutineDispatchers()
coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true)
)
moleculeFlow(RecompositionClock.Immediate) {
presenter.present()
}.test {

View file

@ -20,7 +20,6 @@ import app.cash.molecule.RecompositionClock
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
import com.google.common.truth.Truth
import io.element.android.features.roomdetails.aMatrixRoom
import io.element.android.features.roomdetails.impl.members.RoomMemberListDataSource
import io.element.android.features.roomdetails.impl.members.RoomMemberListEvents
import io.element.android.features.roomdetails.impl.members.RoomMemberListPresenter
@ -167,7 +166,7 @@ class RoomMemberListPresenterTests {
@ExperimentalCoroutinesApi
private fun TestScope.createDataSource(
matrixRoom: MatrixRoom = aMatrixRoom().apply {
matrixRoom: MatrixRoom = FakeMatrixRoom().apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(aRoomMemberList()))
},
coroutineDispatchers: CoroutineDispatchers = testCoroutineDispatchers()
@ -175,7 +174,7 @@ private fun TestScope.createDataSource(
@ExperimentalCoroutinesApi
private fun TestScope.createPresenter(
coroutineDispatchers: CoroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true),
matrixRoom: MatrixRoom = FakeMatrixRoom(),
roomMemberListDataSource: RoomMemberListDataSource = createDataSource(),
coroutineDispatchers: CoroutineDispatchers = testCoroutineDispatchers()
roomMemberListDataSource: RoomMemberListDataSource = createDataSource(coroutineDispatchers = coroutineDispatchers),
) = RoomMemberListPresenter(matrixRoom, roomMemberListDataSource, coroutineDispatchers)

View file

@ -20,13 +20,13 @@ import app.cash.molecule.RecompositionClock
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
import com.google.common.truth.Truth
import io.element.android.features.roomdetails.aMatrixClient
import io.element.android.features.roomdetails.aMatrixRoom
import io.element.android.features.roomdetails.impl.members.aRoomMember
import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsEvents
import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsPresenter
import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsState
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.test.FakeMatrixClient
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Test
@ -34,8 +34,6 @@ import org.junit.Test
@ExperimentalCoroutinesApi
class RoomMemberDetailsPresenterTests {
private val matrixClient = aMatrixClient()
@Test
fun `present - returns the room member's data, then updates it if needed`() = runTest {
val roomMember = aRoomMember(displayName = "Alice")
@ -44,7 +42,7 @@ class RoomMemberDetailsPresenterTests {
givenUserAvatarUrlResult(Result.success("A custom avatar"))
givenRoomMembersState(MatrixRoomMembersState.Ready(listOf(roomMember)))
}
val presenter = RoomMemberDetailsPresenter(matrixClient, room, roomMember.userId)
val presenter = RoomMemberDetailsPresenter(FakeMatrixClient(), room, roomMember.userId)
moleculeFlow(RecompositionClock.Immediate) {
presenter.present()
}.test {
@ -53,7 +51,7 @@ class RoomMemberDetailsPresenterTests {
Truth.assertThat(initialState.userName).isEqualTo(roomMember.displayName)
Truth.assertThat(initialState.avatarUrl).isEqualTo(roomMember.avatarUrl)
Truth.assertThat(initialState.isBlocked).isEqualTo(roomMember.isIgnored)
skipItems(1)
val loadedState = awaitItem()
Truth.assertThat(loadedState.userName).isEqualTo("A custom name")
Truth.assertThat(loadedState.avatarUrl).isEqualTo("A custom avatar")
@ -68,7 +66,7 @@ class RoomMemberDetailsPresenterTests {
givenUserAvatarUrlResult(Result.failure(Throwable()))
givenRoomMembersState(MatrixRoomMembersState.Ready(listOf(roomMember)))
}
val presenter = RoomMemberDetailsPresenter(matrixClient, room, roomMember.userId)
val presenter = RoomMemberDetailsPresenter(FakeMatrixClient(), room, roomMember.userId)
moleculeFlow(RecompositionClock.Immediate) {
presenter.present()
}.test {
@ -88,7 +86,7 @@ class RoomMemberDetailsPresenterTests {
givenUserAvatarUrlResult(Result.success(null))
givenRoomMembersState(MatrixRoomMembersState.Ready(listOf(roomMember)))
}
val presenter =RoomMemberDetailsPresenter(matrixClient, room, roomMember.userId)
val presenter = RoomMemberDetailsPresenter(FakeMatrixClient(), room, roomMember.userId)
moleculeFlow(RecompositionClock.Immediate) {
presenter.present()
}.test {
@ -104,7 +102,7 @@ class RoomMemberDetailsPresenterTests {
fun `present - BlockUser needing confirmation displays confirmation dialog`() = runTest {
val room = aMatrixRoom()
val roomMember = aRoomMember()
val presenter =RoomMemberDetailsPresenter(matrixClient, room, roomMember.userId)
val presenter = RoomMemberDetailsPresenter(FakeMatrixClient(), room, roomMember.userId)
moleculeFlow(RecompositionClock.Immediate) {
presenter.present()
}.test {
@ -125,7 +123,7 @@ class RoomMemberDetailsPresenterTests {
fun `present - BlockUser and UnblockUser without confirmation change the 'blocked' state`() = runTest {
val room = aMatrixRoom()
val roomMember = aRoomMember()
val presenter =RoomMemberDetailsPresenter(matrixClient, room, roomMember.userId)
val presenter = RoomMemberDetailsPresenter(FakeMatrixClient(), room, roomMember.userId)
moleculeFlow(RecompositionClock.Immediate) {
presenter.present()
}.test {
@ -142,7 +140,7 @@ class RoomMemberDetailsPresenterTests {
fun `present - UnblockUser needing confirmation displays confirmation dialog`() = runTest {
val room = aMatrixRoom()
val roomMember = aRoomMember()
val presenter =RoomMemberDetailsPresenter(matrixClient, room, roomMember.userId)
val presenter = RoomMemberDetailsPresenter(FakeMatrixClient(), room, roomMember.userId)
moleculeFlow(RecompositionClock.Immediate) {
presenter.present()
}.test {