feat(join by alias) : add tests

This commit is contained in:
ganfra
2025-02-25 15:31:05 +01:00
parent e5ad0f6e5d
commit 13c49f184e
5 changed files with 259 additions and 1 deletions

View File

@@ -29,8 +29,9 @@ open class JoinRoomByAddressStateProvider : PreviewParameterProvider<JoinRoomByA
fun aJoinRoomByAddressState(
address: String = "",
addressState: RoomAddressState = RoomAddressState.Unknown,
eventSink: (JoinRoomByAddressEvents) -> Unit = {},
) = JoinRoomByAddressState(
address = address,
addressState = addressState,
eventSink = {}
eventSink = eventSink
)

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.createroom.impl
import io.element.android.features.createroom.CreateRoomNavigator
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
class FakeCreateRoomNavigator(
private val openRoomLambda: (roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>) -> Unit = { _, _ -> },
private val createNewRoomLambda: () -> Unit = {},
private val showJoinRoomByAddressLambda: () -> Unit = {},
private val dismissJoinRoomByAddressLambda: () -> Unit = {},
) : CreateRoomNavigator {
override fun onOpenRoom(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>) {
openRoomLambda(roomIdOrAlias, serverNames)
}
override fun onCreateNewRoom() {
createNewRoomLambda()
}
override fun onShowJoinRoomByAddress() {
showJoinRoomByAddressLambda()
}
override fun onDismissJoinRoomByAddress() {
dismissJoinRoomByAddressLambda()
}
}

View File

@@ -0,0 +1,141 @@
/*
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.createroom.impl.joinbyaddress
import com.google.common.truth.Truth.assertThat
import io.element.android.features.createroom.CreateRoomNavigator
import io.element.android.features.createroom.impl.FakeCreateRoomNavigator
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
import io.element.android.libraries.matrix.api.room.alias.RoomAliasHelper
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.test.room.alias.FakeRoomAliasHelper
import io.element.android.tests.testutils.lambda.assert
import io.element.android.tests.testutils.lambda.lambdaRecorder
import io.element.android.tests.testutils.test
import kotlinx.coroutines.test.runTest
import org.junit.Test
class JoinRoomByAddressPresenterTest {
@Test
fun `present - initial state`() = runTest {
val presenter = createJoinRoomByAddressPresenter()
presenter.test {
with(awaitItem()) {
assertThat(address).isEmpty()
assertThat(addressState).isEqualTo(RoomAddressState.Unknown)
}
}
}
@Test
fun `present - invalid address`() = runTest {
val presenter = createJoinRoomByAddressPresenter(
roomAliasHelper = FakeRoomAliasHelper(
isRoomAliasValidLambda = { false }
)
)
presenter.test {
with(awaitItem()) {
eventSink(JoinRoomByAddressEvents.UpdateAddress("invalid_address"))
}
with(awaitItem()) {
assertThat(address).isEqualTo("invalid_address")
assertThat(addressState).isEqualTo(RoomAddressState.Unknown)
eventSink(JoinRoomByAddressEvents.Continue)
}
// The address should be marked as invalid only after the user tries to continue
with(awaitItem()) {
assertThat(address).isEqualTo("invalid_address")
assertThat(addressState).isEqualTo(RoomAddressState.Invalid)
}
}
}
@Test
fun `present - room found`() = runTest {
val openRoomLambda = lambdaRecorder<RoomIdOrAlias, List<String>, Unit> { _, _ -> }
val dismissJoinRoomByAddressLambda = lambdaRecorder<Unit> { }
val navigator = FakeCreateRoomNavigator(
openRoomLambda = openRoomLambda,
dismissJoinRoomByAddressLambda = dismissJoinRoomByAddressLambda
)
val presenter = createJoinRoomByAddressPresenter(navigator = navigator)
presenter.test {
with(awaitItem()) {
eventSink(JoinRoomByAddressEvents.UpdateAddress("#room_found:matrix.org"))
}
with(awaitItem()) {
assertThat(address).isEqualTo("#room_found:matrix.org")
assertThat(addressState).isEqualTo(RoomAddressState.Unknown)
}
with(awaitItem()) {
assertThat(address).isEqualTo("#room_found:matrix.org")
assertThat(addressState).isInstanceOf(RoomAddressState.RoomFound::class.java)
eventSink(JoinRoomByAddressEvents.Continue)
}
assert(openRoomLambda).isCalledOnce()
assert(dismissJoinRoomByAddressLambda).isCalledOnce()
}
}
@Test
fun `present - room not found`() = runTest {
val presenter = createJoinRoomByAddressPresenter(
matrixClient = FakeMatrixClient(
resolveRoomAliasResult = { Result.failure(RuntimeException()) }
)
)
presenter.test {
with(awaitItem()) {
eventSink(JoinRoomByAddressEvents.UpdateAddress("#room_not_found:matrix.org"))
}
with(awaitItem()) {
assertThat(address).isEqualTo("#room_not_found:matrix.org")
assertThat(addressState).isEqualTo(RoomAddressState.Unknown)
eventSink(JoinRoomByAddressEvents.Continue)
}
with(awaitItem()) {
assertThat(address).isEqualTo("#room_not_found:matrix.org")
assertThat(addressState).isEqualTo(RoomAddressState.Resolving)
}
with(awaitItem()) {
assertThat(address).isEqualTo("#room_not_found:matrix.org")
assertThat(addressState).isEqualTo(RoomAddressState.RoomNotFound)
}
}
}
@Test
fun `present - dismiss`() = runTest {
val dismissJoinRoomByAddressLambda = lambdaRecorder<Unit> { }
val navigator = FakeCreateRoomNavigator(
dismissJoinRoomByAddressLambda = dismissJoinRoomByAddressLambda
)
val presenter = createJoinRoomByAddressPresenter(navigator = navigator)
presenter.test {
with(awaitItem()) {
eventSink(JoinRoomByAddressEvents.Dismiss)
}
assert(dismissJoinRoomByAddressLambda).isCalledOnce()
}
}
private fun createJoinRoomByAddressPresenter(
navigator: CreateRoomNavigator = FakeCreateRoomNavigator(),
matrixClient: MatrixClient = FakeMatrixClient(),
roomAliasHelper: RoomAliasHelper = FakeRoomAliasHelper(),
): JoinRoomByAddressPresenter {
return JoinRoomByAddressPresenter(
navigator = navigator,
client = matrixClient,
roomAliasHelper = roomAliasHelper,
)
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.createroom.impl.joinbyaddress
import androidx.activity.ComponentActivity
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performTextInput
import androidx.test.ext.junit.runners.AndroidJUnit4
import io.element.android.features.createroom.impl.R
import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.tests.testutils.EventsRecorder
import io.element.android.tests.testutils.clickOn
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TestRule
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class JoinRoomByAddressViewTest {
@get:Rule
val rule = createAndroidComposeRule<ComponentActivity>()
@Test
fun `entering text emits the expected event`() {
val eventsRecorder = EventsRecorder<JoinRoomByAddressEvents>()
rule.setJoinRoomByAddressView(
aJoinRoomByAddressState(
eventSink = eventsRecorder,
)
)
val text = rule.activity.getString(R.string.screen_start_chat_join_room_by_address_action)
rule.onNodeWithText(text).performTextInput("#address:matrix.org")
eventsRecorder.assertSingle(JoinRoomByAddressEvents.UpdateAddress("#address:matrix.org"))
}
@Test
fun `clicking on continue emits the expected event`() {
val eventsRecorder = EventsRecorder<JoinRoomByAddressEvents>()
rule.setJoinRoomByAddressView(
aJoinRoomByAddressState(
eventSink = eventsRecorder,
)
)
rule.clickOn(CommonStrings.action_continue)
eventsRecorder.assertSingle(JoinRoomByAddressEvents.Continue)
}
}
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setJoinRoomByAddressView(
state: JoinRoomByAddressState,
) {
setContent {
JoinRoomByAddressView(state = state)
}
}

View File

@@ -101,6 +101,21 @@ class CreateRoomRootViewTest {
rule.onNodeWithText(firstRoom.matrixUser.getBestName()).performClick()
}
}
@Config(qualifiers = "h1024dp")
@Test
fun `clicking on Join room by address invokes the expected callback`() {
val eventsRecorder = EventsRecorder<CreateRoomRootEvents>(expectEvents = false)
ensureCalledOnce {
rule.setCreateRoomRootView(
aCreateRoomRootState(
eventSink = eventsRecorder,
),
onJoinRoomByAddressClick = it
)
rule.clickOn(R.string.screen_start_chat_join_room_by_address_action)
}
}
}
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setCreateRoomRootView(
@@ -109,6 +124,7 @@ private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setCreat
onNewRoomClick: () -> Unit = EnsureNeverCalled(),
onOpenDM: (RoomId) -> Unit = EnsureNeverCalledWithParam(),
onInviteFriendsClick: () -> Unit = EnsureNeverCalled(),
onJoinRoomByAddressClick: () -> Unit = EnsureNeverCalled(),
) {
setContent {
CreateRoomRootView(
@@ -117,6 +133,7 @@ private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setCreat
onNewRoomClick = onNewRoomClick,
onOpenDM = onOpenDM,
onInviteFriendsClick = onInviteFriendsClick,
onJoinByAddressClick = onJoinRoomByAddressClick
)
}
}