feat(security&privacy) : add all tests for EditRoomAddress classes
This commit is contained in:
@@ -30,6 +30,7 @@ import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import io.element.android.libraries.matrix.test.room.alias.FakeRoomAliasHelper
|
||||
import io.element.android.libraries.matrix.ui.components.aMatrixUser
|
||||
import io.element.android.libraries.matrix.ui.media.AvatarAction
|
||||
import io.element.android.libraries.matrix.ui.room.address.RoomAddressValidity
|
||||
import io.element.android.libraries.mediapickers.api.PickerProvider
|
||||
import io.element.android.libraries.mediapickers.test.FakePickerProvider
|
||||
import io.element.android.libraries.mediaupload.api.MediaPreProcessor
|
||||
|
||||
@@ -14,7 +14,7 @@ import com.bumble.appyx.navmodel.backstack.operation.push
|
||||
|
||||
interface SecurityAndPrivacyNavigator : Plugin {
|
||||
fun openEditRoomAddress()
|
||||
fun closeEditorRoomAddress()
|
||||
fun closeEditRoomAddress()
|
||||
}
|
||||
|
||||
class BackstackSecurityAndPrivacyNavigator(
|
||||
@@ -24,7 +24,7 @@ class BackstackSecurityAndPrivacyNavigator(
|
||||
backStack.push(SecurityAndPrivacyFlowNode.NavTarget.EditRoomAddress)
|
||||
}
|
||||
|
||||
override fun closeEditorRoomAddress() {
|
||||
override fun closeEditRoomAddress() {
|
||||
backStack.pop()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ class EditRoomAddressPresenter @AssistedInject constructor(
|
||||
room.updateCanonicalAlias(savedCanonicalAlias, newAlternativeAliases).getOrThrow()
|
||||
}
|
||||
}
|
||||
navigator.closeEditorRoomAddress()
|
||||
navigator.closeEditRoomAddress()
|
||||
}.runCatchingUpdatingState(saveAction)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,15 +14,15 @@ import io.element.android.libraries.matrix.ui.room.address.RoomAddressValidity
|
||||
open class EditRoomAddressStateProvider : PreviewParameterProvider<EditRoomAddressState> {
|
||||
override val values: Sequence<EditRoomAddressState>
|
||||
get() = sequenceOf(
|
||||
aEditRoomAddressState(),
|
||||
aEditRoomAddressState(roomAddressValidity = RoomAddressValidity.NotAvailable),
|
||||
aEditRoomAddressState(roomAddressValidity = RoomAddressValidity.InvalidSymbols),
|
||||
aEditRoomAddressState(roomAddressValidity = RoomAddressValidity.Valid),
|
||||
aEditRoomAddressState(roomAddressValidity = RoomAddressValidity.Valid, saveAction = AsyncAction.Loading),
|
||||
anEditRoomAddressState(),
|
||||
anEditRoomAddressState(roomAddressValidity = RoomAddressValidity.NotAvailable),
|
||||
anEditRoomAddressState(roomAddressValidity = RoomAddressValidity.InvalidSymbols),
|
||||
anEditRoomAddressState(roomAddressValidity = RoomAddressValidity.Valid),
|
||||
anEditRoomAddressState(roomAddressValidity = RoomAddressValidity.Valid, saveAction = AsyncAction.Loading),
|
||||
)
|
||||
}
|
||||
|
||||
fun aEditRoomAddressState(
|
||||
fun anEditRoomAddressState(
|
||||
roomAddress: String = "therapy",
|
||||
roomAddressValidity: RoomAddressValidity = RoomAddressValidity.Unknown,
|
||||
homeserverName: String = ":myserver.org",
|
||||
|
||||
@@ -12,13 +12,13 @@ import io.element.android.tests.testutils.lambda.lambdaError
|
||||
|
||||
class FakeSecurityAndPrivacyNavigator(
|
||||
private val openEditRoomAddressLambda: () -> Unit = { lambdaError() },
|
||||
private val closeEditorRoomAddressLambda: () -> Unit = { lambdaError() },
|
||||
private val closeEditRoomAddressLambda: () -> Unit = { lambdaError() },
|
||||
) : SecurityAndPrivacyNavigator {
|
||||
override fun openEditRoomAddress() {
|
||||
openEditRoomAddressLambda()
|
||||
}
|
||||
|
||||
override fun closeEditorRoomAddress() {
|
||||
closeEditorRoomAddressLambda()
|
||||
override fun closeEditRoomAddress() {
|
||||
closeEditRoomAddressLambda()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,6 +192,20 @@ class SecurityAndPrivacyPresenterTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - edit room address`() = runTest {
|
||||
val openEditRoomAddressLambda = lambdaRecorder<Unit> { }
|
||||
val navigator = FakeSecurityAndPrivacyNavigator(openEditRoomAddressLambda)
|
||||
val presenter = createSecurityAndPrivacyPresenter(navigator = navigator)
|
||||
presenter.test {
|
||||
skipItems(1)
|
||||
with(awaitItem()) {
|
||||
eventSink(SecurityAndPrivacyEvents.EditRoomAddress)
|
||||
}
|
||||
assert(openEditRoomAddressLambda).isCalledOnce()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - save success`() = runTest {
|
||||
val enableEncryptionLambda = lambdaRecorder<Result<Unit>> { Result.success(Unit) }
|
||||
|
||||
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
* 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.roomdetails.securityandprivacy.editroomaddress
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.features.roomdetails.impl.securityandprivacy.SecurityAndPrivacyNavigator
|
||||
import io.element.android.features.roomdetails.impl.securityandprivacy.editroomaddress.EditRoomAddressEvents
|
||||
import io.element.android.features.roomdetails.impl.securityandprivacy.editroomaddress.EditRoomAddressPresenter
|
||||
import io.element.android.features.roomdetails.securityandprivacy.FakeSecurityAndPrivacyNavigator
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.matrix.api.core.RoomAlias
|
||||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||
import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias
|
||||
import io.element.android.libraries.matrix.api.room.alias.RoomAliasHelper
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
|
||||
import io.element.android.libraries.matrix.test.room.alias.FakeRoomAliasHelper
|
||||
import io.element.android.libraries.matrix.ui.room.address.RoomAddressValidity
|
||||
import io.element.android.tests.testutils.lambda.assert
|
||||
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||
import io.element.android.tests.testutils.lambda.value
|
||||
import io.element.android.tests.testutils.test
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
import java.util.Optional
|
||||
|
||||
class EditRoomAddressPresenterTest {
|
||||
|
||||
@Test
|
||||
fun `present - initial state no address`() = runTest {
|
||||
val presenter = createEditRoomAddressPresenter()
|
||||
presenter.test {
|
||||
with(awaitItem()) {
|
||||
assertThat(homeserverName).isEqualTo("matrix.org")
|
||||
assertThat(canBeSaved).isFalse()
|
||||
assertThat(saveAction).isEqualTo(AsyncAction.Uninitialized)
|
||||
assertThat(roomAddressValidity).isEqualTo(RoomAddressValidity.Unknown)
|
||||
assertThat(roomAddress).isEmpty()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - initial state address matching own homeserver`() = runTest {
|
||||
val room = FakeMatrixRoom(
|
||||
canonicalAlias = RoomAlias("#canonical:matrix.org"),
|
||||
)
|
||||
val presenter = createEditRoomAddressPresenter(room = room)
|
||||
presenter.test {
|
||||
with(awaitItem()) {
|
||||
assertThat(homeserverName).isEqualTo("matrix.org")
|
||||
assertThat(canBeSaved).isFalse()
|
||||
assertThat(saveAction).isEqualTo(AsyncAction.Uninitialized)
|
||||
assertThat(roomAddressValidity).isEqualTo(RoomAddressValidity.Unknown)
|
||||
assertThat(roomAddress).isEqualTo("canonical")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - initial state address not matching own homeserver`() = runTest {
|
||||
val room = FakeMatrixRoom(
|
||||
canonicalAlias = RoomAlias("#canonical:notmatrix.org"),
|
||||
)
|
||||
val presenter = createEditRoomAddressPresenter(room = room)
|
||||
presenter.test {
|
||||
with(awaitItem()) {
|
||||
assertThat(homeserverName).isEqualTo("matrix.org")
|
||||
assertThat(canBeSaved).isFalse()
|
||||
assertThat(saveAction).isEqualTo(AsyncAction.Uninitialized)
|
||||
assertThat(roomAddressValidity).isEqualTo(RoomAddressValidity.Unknown)
|
||||
assertThat(roomAddress).isEmpty()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - room address change invalid state`() = runTest {
|
||||
val roomAliasHelper = FakeRoomAliasHelper(
|
||||
isRoomAliasValidLambda = { false }
|
||||
)
|
||||
val presenter = createEditRoomAddressPresenter(roomAliasHelper = roomAliasHelper)
|
||||
presenter.test {
|
||||
with(awaitItem()) {
|
||||
eventSink(EditRoomAddressEvents.RoomAddressChanged("invalid"))
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(roomAddress).isEqualTo("invalid")
|
||||
assertThat(roomAddressValidity).isEqualTo(RoomAddressValidity.Unknown)
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(roomAddressValidity).isEqualTo(RoomAddressValidity.InvalidSymbols)
|
||||
assertThat(canBeSaved).isFalse()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - room address change valid state`() = runTest {
|
||||
val presenter = createEditRoomAddressPresenter()
|
||||
presenter.test {
|
||||
with(awaitItem()) {
|
||||
eventSink(EditRoomAddressEvents.RoomAddressChanged("valid"))
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(roomAddress).isEqualTo("valid")
|
||||
assertThat(roomAddressValidity).isEqualTo(RoomAddressValidity.Unknown)
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(roomAddressValidity).isEqualTo(RoomAddressValidity.Valid)
|
||||
assertThat(canBeSaved).isTrue()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - room address change alias unavailable`() = runTest {
|
||||
val client = createMatrixClient(isAliasAvailable = false)
|
||||
val presenter = createEditRoomAddressPresenter(client = client)
|
||||
presenter.test {
|
||||
with(awaitItem()) {
|
||||
eventSink(EditRoomAddressEvents.RoomAddressChanged("valid"))
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(roomAddress).isEqualTo("valid")
|
||||
assertThat(roomAddressValidity).isEqualTo(RoomAddressValidity.Unknown)
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(roomAddressValidity).isEqualTo(RoomAddressValidity.NotAvailable)
|
||||
assertThat(canBeSaved).isFalse()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - save success no current alias`() = runTest {
|
||||
val publishAliasInRoomDirectoryResult = lambdaRecorder<RoomAlias, Result<Boolean>> { _ -> Result.success(true) }
|
||||
val updateCanonicalAliasResult = lambdaRecorder<RoomAlias?, List<RoomAlias>, Result<Unit>> { _, _ -> Result.success(Unit) }
|
||||
val removeAliasFromRoomDirectoryResult = lambdaRecorder<RoomAlias, Result<Boolean>> { _ -> Result.success(true) }
|
||||
val closeEditAddressLambda = lambdaRecorder<Unit> { }
|
||||
val navigator = FakeSecurityAndPrivacyNavigator(
|
||||
closeEditRoomAddressLambda = closeEditAddressLambda
|
||||
)
|
||||
val room = FakeMatrixRoom(
|
||||
updateCanonicalAliasResult = updateCanonicalAliasResult,
|
||||
publishRoomAliasInRoomDirectoryResult = publishAliasInRoomDirectoryResult
|
||||
)
|
||||
val presenter = createEditRoomAddressPresenter(room = room, navigator = navigator)
|
||||
presenter.test {
|
||||
with(awaitItem()) {
|
||||
eventSink(EditRoomAddressEvents.RoomAddressChanged("valid"))
|
||||
}
|
||||
skipItems(1)
|
||||
with(awaitItem()) {
|
||||
assertThat(roomAddressValidity).isEqualTo(RoomAddressValidity.Valid)
|
||||
assertThat(canBeSaved).isTrue()
|
||||
eventSink(EditRoomAddressEvents.Save)
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(saveAction).isEqualTo(AsyncAction.Loading)
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(saveAction).isEqualTo(AsyncAction.Success(Unit))
|
||||
}
|
||||
|
||||
val createdAlias = RoomAlias("#valid:matrix.org")
|
||||
assert(updateCanonicalAliasResult)
|
||||
.isCalledOnce()
|
||||
.with(value(createdAlias), value(emptyList<RoomAlias>()))
|
||||
|
||||
assert(publishAliasInRoomDirectoryResult)
|
||||
.isCalledOnce()
|
||||
.with(value(createdAlias))
|
||||
|
||||
assert(removeAliasFromRoomDirectoryResult).isNeverCalled()
|
||||
|
||||
assert(closeEditAddressLambda).isCalledOnce()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - save success current canonical alias from own homeserver`() = runTest {
|
||||
val publishAliasInRoomDirectoryResult = lambdaRecorder<RoomAlias, Result<Boolean>> { _ -> Result.success(true) }
|
||||
val removeAliasFromRoomDirectoryResult = lambdaRecorder<RoomAlias, Result<Boolean>> { _ -> Result.success(true) }
|
||||
val updateCanonicalAliasResult = lambdaRecorder<RoomAlias?, List<RoomAlias>, Result<Unit>> { _, _ -> Result.success(Unit) }
|
||||
val closeEditAddressLambda = lambdaRecorder<Unit> { }
|
||||
|
||||
val navigator = FakeSecurityAndPrivacyNavigator(closeEditRoomAddressLambda = closeEditAddressLambda)
|
||||
val canonicalAlias = RoomAlias("#canonical:matrix.org")
|
||||
val room = FakeMatrixRoom(
|
||||
canonicalAlias = canonicalAlias,
|
||||
updateCanonicalAliasResult = updateCanonicalAliasResult,
|
||||
publishRoomAliasInRoomDirectoryResult = publishAliasInRoomDirectoryResult,
|
||||
removeRoomAliasFromRoomDirectoryResult = removeAliasFromRoomDirectoryResult
|
||||
)
|
||||
val presenter = createEditRoomAddressPresenter(room = room, navigator = navigator)
|
||||
presenter.test {
|
||||
with(awaitItem()) {
|
||||
eventSink(EditRoomAddressEvents.RoomAddressChanged("valid"))
|
||||
}
|
||||
skipItems(1)
|
||||
with(awaitItem()) {
|
||||
assertThat(roomAddressValidity).isEqualTo(RoomAddressValidity.Valid)
|
||||
assertThat(canBeSaved).isTrue()
|
||||
eventSink(EditRoomAddressEvents.Save)
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(saveAction).isEqualTo(AsyncAction.Loading)
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(saveAction).isEqualTo(AsyncAction.Success(Unit))
|
||||
}
|
||||
|
||||
val createdAlias = RoomAlias("#valid:matrix.org")
|
||||
assert(updateCanonicalAliasResult)
|
||||
.isCalledOnce()
|
||||
.with(value(createdAlias), value(emptyList<RoomAlias>()))
|
||||
|
||||
assert(publishAliasInRoomDirectoryResult)
|
||||
.isCalledOnce()
|
||||
.with(value(createdAlias))
|
||||
|
||||
assert(removeAliasFromRoomDirectoryResult)
|
||||
.isCalledOnce()
|
||||
.with(value(canonicalAlias))
|
||||
|
||||
assert(closeEditAddressLambda).isCalledOnce()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - save success current canonical alias from other homeserver`() = runTest {
|
||||
val publishAliasInRoomDirectoryResult = lambdaRecorder<RoomAlias, Result<Boolean>> { _ -> Result.success(true) }
|
||||
val removeAliasFromRoomDirectoryResult = lambdaRecorder<RoomAlias, Result<Boolean>> { _ -> Result.success(true) }
|
||||
val updateCanonicalAliasResult = lambdaRecorder<RoomAlias?, List<RoomAlias>, Result<Unit>> { _, _ -> Result.success(Unit) }
|
||||
val closeEditAddressLambda = lambdaRecorder<Unit> { }
|
||||
|
||||
val navigator = FakeSecurityAndPrivacyNavigator(closeEditRoomAddressLambda = closeEditAddressLambda)
|
||||
val canonicalAlias = RoomAlias("#canonical:notmatrix.org")
|
||||
val room = FakeMatrixRoom(
|
||||
canonicalAlias = canonicalAlias,
|
||||
updateCanonicalAliasResult = updateCanonicalAliasResult,
|
||||
publishRoomAliasInRoomDirectoryResult = publishAliasInRoomDirectoryResult,
|
||||
removeRoomAliasFromRoomDirectoryResult = removeAliasFromRoomDirectoryResult
|
||||
)
|
||||
val presenter = createEditRoomAddressPresenter(room = room, navigator = navigator)
|
||||
presenter.test {
|
||||
with(awaitItem()) {
|
||||
eventSink(EditRoomAddressEvents.RoomAddressChanged("valid"))
|
||||
}
|
||||
skipItems(1)
|
||||
with(awaitItem()) {
|
||||
assertThat(roomAddressValidity).isEqualTo(RoomAddressValidity.Valid)
|
||||
assertThat(canBeSaved).isTrue()
|
||||
eventSink(EditRoomAddressEvents.Save)
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(saveAction).isEqualTo(AsyncAction.Loading)
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(saveAction).isEqualTo(AsyncAction.Success(Unit))
|
||||
}
|
||||
|
||||
val createdAlias = RoomAlias("#valid:matrix.org")
|
||||
assert(updateCanonicalAliasResult)
|
||||
.isCalledOnce()
|
||||
.with(value(canonicalAlias), value(listOf(createdAlias)))
|
||||
|
||||
assert(publishAliasInRoomDirectoryResult)
|
||||
.isCalledOnce()
|
||||
.with(value(createdAlias))
|
||||
|
||||
assert(removeAliasFromRoomDirectoryResult).isNeverCalled()
|
||||
|
||||
assert(closeEditAddressLambda).isCalledOnce()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - save failure`() = runTest {
|
||||
val closeEditAddressLambda = lambdaRecorder<Unit> { }
|
||||
val navigator = FakeSecurityAndPrivacyNavigator(
|
||||
closeEditRoomAddressLambda = closeEditAddressLambda
|
||||
)
|
||||
val presenter = createEditRoomAddressPresenter(navigator = navigator)
|
||||
presenter.test {
|
||||
with(awaitItem()) {
|
||||
eventSink(EditRoomAddressEvents.RoomAddressChanged("valid"))
|
||||
}
|
||||
skipItems(1)
|
||||
with(awaitItem()) {
|
||||
assertThat(roomAddressValidity).isEqualTo(RoomAddressValidity.Valid)
|
||||
assertThat(canBeSaved).isTrue()
|
||||
eventSink(EditRoomAddressEvents.Save)
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(saveAction).isEqualTo(AsyncAction.Loading)
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(saveAction).isInstanceOf(AsyncAction.Failure::class.java)
|
||||
}
|
||||
|
||||
assert(closeEditAddressLambda).isNeverCalled()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - dismiss error`() = runTest {
|
||||
val presenter = createEditRoomAddressPresenter()
|
||||
presenter.test {
|
||||
with(awaitItem()) {
|
||||
eventSink(EditRoomAddressEvents.Save)
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(saveAction).isInstanceOf(AsyncAction.Failure::class.java)
|
||||
eventSink(EditRoomAddressEvents.DismissError)
|
||||
}
|
||||
with(awaitItem()) {
|
||||
assertThat(saveAction).isEqualTo(AsyncAction.Uninitialized)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createMatrixClient(isAliasAvailable: Boolean = true) = FakeMatrixClient(
|
||||
userIdServerNameLambda = { "matrix.org" },
|
||||
resolveRoomAliasResult = {
|
||||
val resolvedRoomAlias = if (isAliasAvailable) {
|
||||
Optional.empty()
|
||||
} else {
|
||||
Optional.of(ResolvedRoomAlias(A_ROOM_ID, emptyList()))
|
||||
}
|
||||
Result.success(resolvedRoomAlias)
|
||||
}
|
||||
)
|
||||
|
||||
private fun createEditRoomAddressPresenter(
|
||||
client: FakeMatrixClient = createMatrixClient(),
|
||||
room: MatrixRoom = FakeMatrixRoom(),
|
||||
navigator: SecurityAndPrivacyNavigator = FakeSecurityAndPrivacyNavigator(),
|
||||
roomAliasHelper: RoomAliasHelper = FakeRoomAliasHelper()
|
||||
): EditRoomAddressPresenter {
|
||||
return EditRoomAddressPresenter(
|
||||
room = room,
|
||||
client = client,
|
||||
roomAliasHelper = roomAliasHelper,
|
||||
navigator = navigator
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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.roomdetails.securityandprivacy.editroomaddress
|
||||
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
|
||||
import androidx.compose.ui.test.junit4.createAndroidComposeRule
|
||||
import androidx.compose.ui.test.onNodeWithContentDescription
|
||||
import androidx.compose.ui.test.onNodeWithTag
|
||||
import androidx.compose.ui.test.performTextInput
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import io.element.android.features.roomdetails.impl.securityandprivacy.editroomaddress.EditRoomAddressEvents
|
||||
import io.element.android.features.roomdetails.impl.securityandprivacy.editroomaddress.EditRoomAddressState
|
||||
import io.element.android.features.roomdetails.impl.securityandprivacy.editroomaddress.EditRoomAddressView
|
||||
import io.element.android.features.roomdetails.impl.securityandprivacy.editroomaddress.anEditRoomAddressState
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.matrix.ui.room.address.RoomAddressValidity
|
||||
import io.element.android.libraries.testtags.TestTags
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
import io.element.android.tests.testutils.EnsureNeverCalled
|
||||
import io.element.android.tests.testutils.EventsRecorder
|
||||
import io.element.android.tests.testutils.clickOn
|
||||
import io.element.android.tests.testutils.ensureCalledOnce
|
||||
import io.element.android.tests.testutils.pressBack
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.TestRule
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class EditRoomAddressViewTest {
|
||||
@get:Rule val rule = createAndroidComposeRule<ComponentActivity>()
|
||||
|
||||
@Test
|
||||
fun `click on back invokes expected callback`() {
|
||||
ensureCalledOnce { callback ->
|
||||
rule.setEditRoomAddressView(onBackClick = callback)
|
||||
rule.pressBack()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `click on disabled save doesn't emit event`() {
|
||||
val recorder = EventsRecorder<EditRoomAddressEvents>(expectEvents = false)
|
||||
val state = anEditRoomAddressState(eventSink = recorder)
|
||||
rule.setEditRoomAddressView(state)
|
||||
rule.clickOn(CommonStrings.action_save)
|
||||
recorder.assertEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `click on enabled save emits the expected event`() {
|
||||
val recorder = EventsRecorder<EditRoomAddressEvents>()
|
||||
val state = anEditRoomAddressState(
|
||||
roomAddress = "room",
|
||||
roomAddressValidity = RoomAddressValidity.Valid,
|
||||
eventSink = recorder
|
||||
)
|
||||
rule.setEditRoomAddressView(state)
|
||||
rule.clickOn(CommonStrings.action_save)
|
||||
recorder.assertSingle(EditRoomAddressEvents.Save)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `text changes on text field emits the expected event`() {
|
||||
val recorder = EventsRecorder<EditRoomAddressEvents>()
|
||||
val state = anEditRoomAddressState(
|
||||
roomAddress = "",
|
||||
eventSink = recorder
|
||||
)
|
||||
rule.setEditRoomAddressView(state)
|
||||
|
||||
rule.onNodeWithTag(TestTags.roomAddressField.value).performTextInput("alias")
|
||||
recorder.assertSingle(EditRoomAddressEvents.RoomAddressChanged("alias"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `click on dismiss error emits the expected event`() {
|
||||
val recorder = EventsRecorder<EditRoomAddressEvents>()
|
||||
val state = anEditRoomAddressState(
|
||||
roomAddress = "",
|
||||
saveAction = AsyncAction.Failure(IllegalStateException()),
|
||||
eventSink = recorder
|
||||
)
|
||||
rule.setEditRoomAddressView(state)
|
||||
rule.clickOn(CommonStrings.action_cancel)
|
||||
recorder.assertSingle(EditRoomAddressEvents.DismissError)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `click on retry error emits the expected event`() {
|
||||
val recorder = EventsRecorder<EditRoomAddressEvents>()
|
||||
val state = anEditRoomAddressState(
|
||||
roomAddress = "",
|
||||
saveAction = AsyncAction.Failure(IllegalStateException()),
|
||||
eventSink = recorder
|
||||
)
|
||||
rule.setEditRoomAddressView(state)
|
||||
rule.clickOn(CommonStrings.action_retry)
|
||||
recorder.assertSingle(EditRoomAddressEvents.Save)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setEditRoomAddressView(
|
||||
state: EditRoomAddressState = anEditRoomAddressState(
|
||||
eventSink = EventsRecorder(expectEvents = false),
|
||||
),
|
||||
onBackClick: () -> Unit = EnsureNeverCalled(),
|
||||
) {
|
||||
setContent {
|
||||
EditRoomAddressView(
|
||||
state = state,
|
||||
onBackClick = onBackClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,8 @@ import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.components.TextField
|
||||
import io.element.android.libraries.testtags.TestTags
|
||||
import io.element.android.libraries.testtags.testTag
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
||||
@Composable
|
||||
@@ -28,7 +30,7 @@ fun RoomAddressField(
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
TextField(
|
||||
modifier = modifier,
|
||||
modifier = modifier.testTag(TestTags.roomAddressField),
|
||||
value = address,
|
||||
label = label,
|
||||
leadingIcon = {
|
||||
|
||||
@@ -111,4 +111,11 @@ object TestTags {
|
||||
* Generic call to action.
|
||||
*/
|
||||
val callToAction = TestTag("call_to_action")
|
||||
|
||||
/**
|
||||
* Room address field.
|
||||
*
|
||||
*/
|
||||
val roomAddressField = TestTag("room_address_field")
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user