fix(deps): update dependency androidx.compose:compose-bom to v2025.04.01 (#4631)
* fix(deps): update dependency androidx.compose:compose-bom to v2025.04.01 * Fix autofill deprecations * Adapt our custom BottomSheetState and scaffold to the new APIs * Get rid of all the custom bottom sheet implementation It doesn't seem to be needed anymore 🎉 * Replace `semantics { invisibleToUser() }` with `hideFromAccessibility()` * Update screenshots * Add commit and cancel callbacks for autofill on the login view * Fix broken tests caused mainly by https://issuetracker.google.com/issues/366255137 Add `LocalUiTestMode` composition local and helper functions. * Remove dependency that caused a new license to need to be approved * Let setSafeContent handle setting the value for LocalUiTestMode * Fix broken test * Apply fix to RoomMemberModerationViewTest and RoomListDeclineInviteMenuTest --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jorge Martín <jorgem@element.io> Co-authored-by: ElementBot <android@element.io> Co-authored-by: Benoit Marty <benoit@matrix.org>
This commit is contained in:
parent
b59ddeb652
commit
7bb1e24ff5
37 changed files with 189 additions and 1012 deletions
|
|
@ -17,6 +17,7 @@ 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 io.element.android.tests.testutils.setSafeContent
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.TestRule
|
||||
|
|
@ -56,7 +57,7 @@ class JoinBaseRoomByAddressViewTest {
|
|||
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setJoinRoomByAddressView(
|
||||
state: JoinRoomByAddressState,
|
||||
) {
|
||||
setContent {
|
||||
setSafeContent {
|
||||
JoinRoomByAddressView(state = state)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,10 +34,12 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.autofill.AutofillType
|
||||
import androidx.compose.ui.autofill.ContentType
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.contentType
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||
|
|
@ -54,7 +56,6 @@ import io.element.android.libraries.designsystem.atomic.organisms.InfoListOrgani
|
|||
import io.element.android.libraries.designsystem.components.button.BackButton
|
||||
import io.element.android.libraries.designsystem.components.form.textFieldState
|
||||
import io.element.android.libraries.designsystem.components.list.SwitchListItem
|
||||
import io.element.android.libraries.designsystem.modifiers.autofill
|
||||
import io.element.android.libraries.designsystem.modifiers.onTabOrEnterKeyFocusNext
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
|
|
@ -276,14 +277,9 @@ private fun Content(
|
|||
.fillMaxWidth()
|
||||
.onTabOrEnterKeyFocusNext(focusManager)
|
||||
.testTag(TestTags.loginPassword)
|
||||
.autofill(
|
||||
autofillTypes = listOf(AutofillType.Password),
|
||||
onFill = {
|
||||
val sanitized = it.sanitize()
|
||||
passwordFieldState = sanitized
|
||||
eventSink(AccountDeactivationEvents.SetPassword(sanitized))
|
||||
}
|
||||
),
|
||||
.semantics {
|
||||
contentType = ContentType.Password
|
||||
},
|
||||
onValueChange = {
|
||||
val sanitized = it.sanitize()
|
||||
passwordFieldState = sanitized
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ import androidx.compose.foundation.layout.padding
|
|||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.ListItem
|
||||
import androidx.compose.material3.SheetValue
|
||||
import androidx.compose.material3.rememberBottomSheetScaffoldState
|
||||
import androidx.compose.material3.rememberStandardBottomSheetState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.ui.Alignment
|
||||
|
|
@ -46,8 +48,6 @@ import io.element.android.libraries.designsystem.theme.components.FloatingAction
|
|||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
||||
import io.element.android.libraries.designsystem.theme.components.bottomsheet.rememberBottomSheetScaffoldState
|
||||
import io.element.android.libraries.designsystem.theme.components.bottomsheet.rememberStandardBottomSheetState
|
||||
import io.element.android.libraries.designsystem.utils.CommonDrawables
|
||||
import io.element.android.libraries.maplibre.compose.CameraMode
|
||||
import io.element.android.libraries.maplibre.compose.CameraMoveStartedReason
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
package io.element.android.features.login.impl.screens.loginpassword
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
|
|
@ -30,10 +31,13 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.autofill.AutofillType
|
||||
import androidx.compose.ui.autofill.ContentType
|
||||
import androidx.compose.ui.focus.FocusDirection
|
||||
import androidx.compose.ui.platform.LocalAutofillManager
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.contentType
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||
|
|
@ -51,7 +55,6 @@ import io.element.android.libraries.designsystem.components.BigIcon
|
|||
import io.element.android.libraries.designsystem.components.button.BackButton
|
||||
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
|
||||
import io.element.android.libraries.designsystem.components.form.textFieldState
|
||||
import io.element.android.libraries.designsystem.modifiers.autofill
|
||||
import io.element.android.libraries.designsystem.modifiers.onTabOrEnterKeyFocusNext
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
|
|
@ -71,6 +74,13 @@ fun LoginPasswordView(
|
|||
onBackClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val autofillManager = LocalAutofillManager.current
|
||||
|
||||
BackHandler {
|
||||
autofillManager?.cancel()
|
||||
onBackClick()
|
||||
}
|
||||
|
||||
val isLoading by remember(state.loginAction) {
|
||||
derivedStateOf {
|
||||
state.loginAction is AsyncData.Loading
|
||||
|
|
@ -82,6 +92,8 @@ fun LoginPasswordView(
|
|||
// Clear focus to prevent keyboard issues with textfields
|
||||
focusManager.clearFocus(force = true)
|
||||
|
||||
autofillManager?.commit()
|
||||
|
||||
state.eventSink(LoginPasswordEvents.Submit)
|
||||
}
|
||||
|
||||
|
|
@ -90,7 +102,12 @@ fun LoginPasswordView(
|
|||
topBar = {
|
||||
TopAppBar(
|
||||
title = {},
|
||||
navigationIcon = { BackButton(onClick = onBackClick) },
|
||||
navigationIcon = {
|
||||
BackButton(onClick = {
|
||||
autofillManager?.cancel()
|
||||
onBackClick()
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
) { padding ->
|
||||
|
|
@ -175,14 +192,9 @@ private fun LoginForm(
|
|||
.fillMaxWidth()
|
||||
.onTabOrEnterKeyFocusNext(focusManager)
|
||||
.testTag(TestTags.loginEmailUsername)
|
||||
.autofill(
|
||||
autofillTypes = listOf(AutofillType.Username),
|
||||
onFill = {
|
||||
val sanitized = it.sanitize()
|
||||
loginFieldState = sanitized
|
||||
eventSink(LoginPasswordEvents.SetLogin(sanitized))
|
||||
}
|
||||
),
|
||||
.semantics {
|
||||
contentType = ContentType.Username
|
||||
},
|
||||
placeholder = stringResource(CommonStrings.common_username),
|
||||
onValueChange = {
|
||||
val sanitized = it.sanitize()
|
||||
|
|
@ -227,14 +239,9 @@ private fun LoginForm(
|
|||
.fillMaxWidth()
|
||||
.onTabOrEnterKeyFocusNext(focusManager)
|
||||
.testTag(TestTags.loginPassword)
|
||||
.autofill(
|
||||
autofillTypes = listOf(AutofillType.Password),
|
||||
onFill = {
|
||||
val sanitized = it.sanitize()
|
||||
passwordFieldState = sanitized
|
||||
eventSink(LoginPasswordEvents.SetPassword(sanitized))
|
||||
}
|
||||
),
|
||||
.semantics {
|
||||
contentType = ContentType.Password
|
||||
},
|
||||
onValueChange = {
|
||||
val sanitized = it.sanitize()
|
||||
passwordFieldState = sanitized
|
||||
|
|
|
|||
|
|
@ -8,17 +8,21 @@
|
|||
package io.element.android.features.login.impl.screens.loginpassword
|
||||
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.compose.ui.test.assert
|
||||
import androidx.compose.ui.test.assertIsEnabled
|
||||
import androidx.compose.ui.test.assertIsNotEnabled
|
||||
import androidx.compose.ui.test.hasText
|
||||
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.onNodeWithText
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performTextInput
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import io.element.android.libraries.matrix.test.A_PASSWORD
|
||||
import io.element.android.libraries.matrix.test.A_USER_NAME
|
||||
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
|
||||
|
|
@ -120,15 +124,15 @@ class LoginPasswordViewTest {
|
|||
eventSink = eventsRecorder,
|
||||
),
|
||||
)
|
||||
rule.onNodeWithText(A_PASSWORD).assertDoesNotExist()
|
||||
rule.onNodeWithTag(TestTags.loginPassword.value).assert(hasText("••••••••"))
|
||||
// Show password
|
||||
val a11yShowPassword = rule.activity.getString(CommonStrings.a11y_show_password)
|
||||
rule.onNodeWithContentDescription(a11yShowPassword).performClick()
|
||||
rule.onNodeWithText(A_PASSWORD).assertExists()
|
||||
rule.onNodeWithTag(TestTags.loginPassword.value).assert(hasText(A_PASSWORD))
|
||||
// Hide password
|
||||
val a11yHidePassword = rule.activity.getString(CommonStrings.a11y_hide_password)
|
||||
rule.onNodeWithContentDescription(a11yHidePassword).performClick()
|
||||
rule.onNodeWithText(A_PASSWORD).assertDoesNotExist()
|
||||
rule.onNodeWithTag(TestTags.loginPassword.value).assert(hasText("••••••••"))
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ import androidx.compose.foundation.layout.PaddingValues
|
|||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.SheetValue
|
||||
import androidx.compose.material3.rememberBottomSheetScaffoldState
|
||||
import androidx.compose.material3.rememberStandardBottomSheetState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
|
|
@ -29,10 +31,8 @@ import androidx.compose.ui.unit.Constraints
|
|||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.min
|
||||
import io.element.android.libraries.core.data.tryOrNull
|
||||
import io.element.android.libraries.designsystem.theme.components.BottomSheetScaffold
|
||||
import io.element.android.libraries.designsystem.theme.components.bottomsheet.CustomSheetState
|
||||
import io.element.android.libraries.designsystem.theme.components.bottomsheet.rememberBottomSheetScaffoldState
|
||||
import io.element.android.libraries.designsystem.theme.components.bottomsheet.rememberStandardBottomSheetState
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/**
|
||||
|
|
@ -139,8 +139,8 @@ internal fun ExpandableBottomSheetScaffold(
|
|||
modifier = Modifier.fillMaxHeight(),
|
||||
measurePolicy = { measurables, constraints ->
|
||||
val constraintHeight = constraints.maxHeight
|
||||
val offset = scaffoldState.bottomSheetState.getIntOffset() ?: 0
|
||||
val height = Integer.max(0, constraintHeight - offset)
|
||||
val offset = tryOrNull { scaffoldState.bottomSheetState.requireOffset() } ?: 0f
|
||||
val height = Integer.max(0, constraintHeight - offset.roundToInt())
|
||||
val top = measurables[0].measure(
|
||||
constraints.copy(
|
||||
minHeight = height,
|
||||
|
|
@ -165,12 +165,6 @@ internal fun ExpandableBottomSheetScaffold(
|
|||
)
|
||||
}
|
||||
|
||||
private fun CustomSheetState.getIntOffset(): Int? = try {
|
||||
requireOffset().roundToInt()
|
||||
} catch (e: IllegalStateException) {
|
||||
null
|
||||
}
|
||||
|
||||
private sealed interface Slot {
|
||||
data class SheetContent(val key: Int?) : Slot
|
||||
data object DragHandle : Slot
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ import io.element.android.libraries.designsystem.theme.components.Surface
|
|||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.messageFromMeBackground
|
||||
import io.element.android.libraries.designsystem.theme.messageFromOtherBackground
|
||||
import io.element.android.libraries.designsystem.utils.LocalUiTestMode
|
||||
import io.element.android.libraries.testtags.TestTags
|
||||
import io.element.android.libraries.testtags.testTag
|
||||
import io.element.android.libraries.ui.utils.time.isTalkbackActive
|
||||
|
|
@ -112,7 +113,9 @@ fun MessageEventBubble(
|
|||
state.isMine -> ElementTheme.colors.messageFromMeBackground
|
||||
else -> ElementTheme.colors.messageFromOtherBackground
|
||||
}
|
||||
val bubbleShape = bubbleShape()
|
||||
// If we're running in UI test mode, we want to use a different shape to avoid
|
||||
// this issue: https://issuetracker.google.com/issues/366255137
|
||||
val bubbleShape = if (LocalUiTestMode.current) RoundedCornerShape(12.dp) else bubbleShape()
|
||||
val radiusPx = (avatarRadius + SENDER_AVATAR_BORDER_WIDTH).toPx()
|
||||
val yOffsetPx = -(NEGATIVE_MARGIN_FOR_BUBBLE + avatarRadius).toPx()
|
||||
val isRtl = LocalLayoutDirection.current == LayoutDirection.Rtl
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.invisibleToUser
|
||||
import androidx.compose.ui.semantics.hideFromAccessibility
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
|
@ -80,7 +80,7 @@ fun TimelineEventTimestampView(
|
|||
.clickable(isVerifiedUserSendFailure) {
|
||||
eventSink(TimelineEvents.ComputeVerifiedUserSendFailure(event))
|
||||
}
|
||||
.semantics { invisibleToUser() }
|
||||
.semantics { hideFromAccessibility() }
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -95,7 +95,7 @@ fun TimelineEventTimestampView(
|
|||
.clickable {
|
||||
eventSink(TimelineEvents.ShowShieldDialog(shield))
|
||||
}
|
||||
.semantics { invisibleToUser() },
|
||||
.semantics { hideFromAccessibility() },
|
||||
tint = shield.toIconColor(),
|
||||
)
|
||||
Spacer(modifier = Modifier.width(4.dp))
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ import androidx.compose.ui.platform.LocalViewConfiguration
|
|||
import androidx.compose.ui.platform.ViewConfiguration
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.clearAndSetSemantics
|
||||
import androidx.compose.ui.semantics.invisibleToUser
|
||||
import androidx.compose.ui.semantics.hideFromAccessibility
|
||||
import androidx.compose.ui.semantics.isTraversalGroup
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.semantics.traversalIndex
|
||||
|
|
@ -439,7 +439,7 @@ private fun MessageSenderInformation(
|
|||
// Add external clickable modifier with no indicator so the touch target is larger than just the display name
|
||||
.clickable(onClick = onClick, enabled = true, interactionSource = remember { MutableInteractionSource() }, indication = null)
|
||||
.clearAndSetSemantics {
|
||||
invisibleToUser()
|
||||
hideFromAccessibility()
|
||||
}
|
||||
) {
|
||||
Avatar(
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import androidx.compose.runtime.setValue
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.invisibleToUser
|
||||
import androidx.compose.ui.semantics.hideFromAccessibility
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.unit.LayoutDirection
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
|
@ -43,7 +43,7 @@ fun TimelineItemReactionsView(
|
|||
var expanded: Boolean by rememberSaveable { mutableStateOf(false) }
|
||||
TimelineItemReactionsView(
|
||||
modifier = modifier.semantics {
|
||||
invisibleToUser()
|
||||
hideFromAccessibility()
|
||||
},
|
||||
reactions = reactionsState.reactions,
|
||||
userCanSendReaction = userCanSendReaction,
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ import androidx.compose.ui.graphics.ColorFilter
|
|||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalInspectionMode
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.invisibleToUser
|
||||
import androidx.compose.ui.semantics.hideFromAccessibility
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
|
@ -136,7 +136,7 @@ fun TimelineItemVideoView(
|
|||
imageVector = CompoundIcons.PlaySolid(),
|
||||
contentDescription = stringResource(id = CommonStrings.a11y_play),
|
||||
colorFilter = ColorFilter.tint(Color.White),
|
||||
modifier = Modifier.semantics { invisibleToUser() }
|
||||
modifier = Modifier.semantics { hideFromAccessibility() }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import androidx.compose.ui.res.pluralStringResource
|
|||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.clearAndSetSemantics
|
||||
import androidx.compose.ui.semantics.contentDescription
|
||||
import androidx.compose.ui.semantics.invisibleToUser
|
||||
import androidx.compose.ui.semantics.hideFromAccessibility
|
||||
import androidx.compose.ui.semantics.testTag
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
|
@ -59,7 +59,7 @@ fun TimelineItemReadReceiptView(
|
|||
if (renderReadReceipts) {
|
||||
ReadReceiptsRow(
|
||||
modifier = modifier.clearAndSetSemantics {
|
||||
invisibleToUser()
|
||||
hideFromAccessibility()
|
||||
}
|
||||
) {
|
||||
ReadReceiptsAvatars(
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ 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 io.element.android.tests.testutils.setSafeContent
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
|
@ -567,11 +568,9 @@ private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setMessa
|
|||
onJoinCallClick: () -> Unit = EnsureNeverCalled(),
|
||||
onViewAllPinnedMessagesClick: () -> Unit = EnsureNeverCalled(),
|
||||
) {
|
||||
setContent {
|
||||
setSafeContent {
|
||||
// Cannot use the RichTextEditor, so simulate a LocalInspectionMode
|
||||
CompositionLocalProvider(
|
||||
LocalInspectionMode provides true
|
||||
) {
|
||||
CompositionLocalProvider(LocalInspectionMode provides true) {
|
||||
MessagesView(
|
||||
state = state,
|
||||
onBackClick = onBackClick,
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
|||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
import io.element.android.tests.testutils.EventsRecorder
|
||||
import io.element.android.tests.testutils.clickOn
|
||||
import io.element.android.tests.testutils.setSafeContent
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.TestRule
|
||||
|
|
@ -54,7 +55,7 @@ class ResolveVerifiedUserSendFailureViewTest {
|
|||
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setResolveVerifiedUserSendFailureView(
|
||||
state: ResolveVerifiedUserSendFailureState,
|
||||
) {
|
||||
setContent {
|
||||
setSafeContent {
|
||||
ResolveVerifiedUserSendFailureView(state = state)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setPinne
|
|||
onLinkClick: (Link) -> Unit = EnsureNeverCalledWithParam(),
|
||||
onLinkLongClick: (Link) -> Unit = EnsureNeverCalledWithParam(),
|
||||
) {
|
||||
setSafeContent {
|
||||
setSafeContent(clearAndroidUiDispatcher = true) {
|
||||
PinnedMessagesListView(
|
||||
state = state,
|
||||
onBackClick = onBackClick,
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setTimel
|
|||
onJoinCallClick: () -> Unit = EnsureNeverCalled(),
|
||||
forceJumpToBottomVisibility: Boolean = false,
|
||||
) {
|
||||
setSafeContent {
|
||||
setSafeContent(clearAndroidUiDispatcher = true) {
|
||||
TimelineView(
|
||||
state = state,
|
||||
timelineProtectionState = timelineProtectionState,
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import io.element.android.tests.testutils.clickOn
|
|||
import io.element.android.tests.testutils.ensureCalledOnce
|
||||
import io.element.android.tests.testutils.ensureCalledTimes
|
||||
import io.element.android.tests.testutils.pressBack
|
||||
import io.element.android.tests.testutils.setSafeContent
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
|
@ -159,14 +160,14 @@ class RolesAndPermissionsViewTest {
|
|||
|
||||
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setRolesAndPermissionsView(
|
||||
state: RolesAndPermissionsState = aRolesAndPermissionsState(
|
||||
eventSink = EventsRecorder(expectEvents = false),
|
||||
eventSink = EventsRecorder(expectEvents = false),
|
||||
),
|
||||
goBack: () -> Unit = EnsureNeverCalled(),
|
||||
openAdminList: () -> Unit = EnsureNeverCalled(),
|
||||
openModeratorList: () -> Unit = EnsureNeverCalled(),
|
||||
openPermissionScreens: () -> Unit = EnsureNeverCalled(),
|
||||
) {
|
||||
setContent {
|
||||
setSafeContent {
|
||||
RolesAndPermissionsView(
|
||||
state = state,
|
||||
rolesAndPermissionsNavigator = object : RolesAndPermissionsNavigator {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
package io.element.android.features.roomlist.impl
|
||||
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
|
||||
import androidx.compose.ui.test.junit4.createAndroidComposeRule
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
|
|
@ -16,6 +17,7 @@ import io.element.android.tests.testutils.EnsureCalledOnceWithParam
|
|||
import io.element.android.tests.testutils.EnsureNeverCalledWithParam
|
||||
import io.element.android.tests.testutils.EventsRecorder
|
||||
import io.element.android.tests.testutils.clickOn
|
||||
import io.element.android.tests.testutils.setSafeContent
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
|
@ -28,15 +30,10 @@ class RoomListContextMenuTest {
|
|||
fun `clicking on Mark as read generates expected Events`() {
|
||||
val eventsRecorder = EventsRecorder<RoomListEvents>()
|
||||
val contextMenu = aContextMenuShown(hasNewContent = true)
|
||||
rule.setContent {
|
||||
RoomListContextMenu(
|
||||
contextMenu = contextMenu,
|
||||
canReportRoom = false,
|
||||
eventSink = eventsRecorder,
|
||||
onRoomSettingsClick = EnsureNeverCalledWithParam(),
|
||||
onReportRoomClick = EnsureNeverCalledWithParam(),
|
||||
)
|
||||
}
|
||||
rule.setRoomListContextMenu(
|
||||
contextMenu = contextMenu,
|
||||
eventSink = eventsRecorder,
|
||||
)
|
||||
rule.clickOn(R.string.screen_roomlist_mark_as_read)
|
||||
eventsRecorder.assertList(
|
||||
listOf(
|
||||
|
|
@ -50,15 +47,10 @@ class RoomListContextMenuTest {
|
|||
fun `clicking on Mark as unread generates expected Events`() {
|
||||
val eventsRecorder = EventsRecorder<RoomListEvents>()
|
||||
val contextMenu = aContextMenuShown(hasNewContent = false)
|
||||
rule.setContent {
|
||||
RoomListContextMenu(
|
||||
contextMenu = contextMenu,
|
||||
canReportRoom = false,
|
||||
eventSink = eventsRecorder,
|
||||
onRoomSettingsClick = EnsureNeverCalledWithParam(),
|
||||
onReportRoomClick = EnsureNeverCalledWithParam(),
|
||||
)
|
||||
}
|
||||
rule.setRoomListContextMenu(
|
||||
contextMenu = contextMenu,
|
||||
eventSink = eventsRecorder,
|
||||
)
|
||||
rule.clickOn(R.string.screen_roomlist_mark_as_unread)
|
||||
eventsRecorder.assertList(
|
||||
listOf(
|
||||
|
|
@ -72,15 +64,10 @@ class RoomListContextMenuTest {
|
|||
fun `clicking on Leave room generates expected Events`() {
|
||||
val eventsRecorder = EventsRecorder<RoomListEvents>()
|
||||
val contextMenu = aContextMenuShown(isDm = false)
|
||||
rule.setContent {
|
||||
RoomListContextMenu(
|
||||
contextMenu = contextMenu,
|
||||
canReportRoom = false,
|
||||
eventSink = eventsRecorder,
|
||||
onRoomSettingsClick = EnsureNeverCalledWithParam(),
|
||||
onReportRoomClick = EnsureNeverCalledWithParam(),
|
||||
)
|
||||
}
|
||||
rule.setRoomListContextMenu(
|
||||
contextMenu = contextMenu,
|
||||
eventSink = eventsRecorder,
|
||||
)
|
||||
rule.clickOn(CommonStrings.action_leave_room)
|
||||
eventsRecorder.assertList(
|
||||
listOf(
|
||||
|
|
@ -95,15 +82,13 @@ class RoomListContextMenuTest {
|
|||
val eventsRecorder = EventsRecorder<RoomListEvents>()
|
||||
val contextMenu = aContextMenuShown()
|
||||
val callback = EnsureCalledOnceWithParam(contextMenu.roomId, Unit)
|
||||
rule.setContent {
|
||||
RoomListContextMenu(
|
||||
contextMenu = contextMenu,
|
||||
canReportRoom = true,
|
||||
eventSink = eventsRecorder,
|
||||
onRoomSettingsClick = EnsureNeverCalledWithParam(),
|
||||
onReportRoomClick = callback,
|
||||
)
|
||||
}
|
||||
rule.setRoomListContextMenu(
|
||||
contextMenu = contextMenu,
|
||||
canReportRoom = true,
|
||||
eventSink = eventsRecorder,
|
||||
onRoomSettingsClick = EnsureNeverCalledWithParam(),
|
||||
onReportRoomClick = callback,
|
||||
)
|
||||
rule.clickOn(CommonStrings.action_report_room)
|
||||
eventsRecorder.assertSingle(RoomListEvents.HideContextMenu)
|
||||
callback.assertSuccess()
|
||||
|
|
@ -114,15 +99,11 @@ class RoomListContextMenuTest {
|
|||
val eventsRecorder = EventsRecorder<RoomListEvents>()
|
||||
val contextMenu = aContextMenuShown()
|
||||
val callback = EnsureCalledOnceWithParam(contextMenu.roomId, Unit)
|
||||
rule.setContent {
|
||||
RoomListContextMenu(
|
||||
contextMenu = contextMenu,
|
||||
canReportRoom = false,
|
||||
eventSink = eventsRecorder,
|
||||
onRoomSettingsClick = callback,
|
||||
onReportRoomClick = EnsureNeverCalledWithParam(),
|
||||
)
|
||||
}
|
||||
rule.setRoomListContextMenu(
|
||||
contextMenu = contextMenu,
|
||||
eventSink = eventsRecorder,
|
||||
onRoomSettingsClick = callback,
|
||||
)
|
||||
rule.clickOn(CommonStrings.common_settings)
|
||||
eventsRecorder.assertSingle(RoomListEvents.HideContextMenu)
|
||||
callback.assertSuccess()
|
||||
|
|
@ -133,15 +114,11 @@ class RoomListContextMenuTest {
|
|||
val eventsRecorder = EventsRecorder<RoomListEvents>()
|
||||
val contextMenu = aContextMenuShown(isDm = false, isFavorite = false)
|
||||
val callback = EnsureNeverCalledWithParam<RoomId>()
|
||||
rule.setContent {
|
||||
RoomListContextMenu(
|
||||
contextMenu = contextMenu,
|
||||
canReportRoom = false,
|
||||
eventSink = eventsRecorder,
|
||||
onRoomSettingsClick = callback,
|
||||
onReportRoomClick = EnsureNeverCalledWithParam(),
|
||||
)
|
||||
}
|
||||
rule.setRoomListContextMenu(
|
||||
contextMenu = contextMenu,
|
||||
eventSink = eventsRecorder,
|
||||
onRoomSettingsClick = callback,
|
||||
)
|
||||
rule.clickOn(CommonStrings.common_favourite)
|
||||
eventsRecorder.assertList(
|
||||
listOf(
|
||||
|
|
@ -149,4 +126,22 @@ class RoomListContextMenuTest {
|
|||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun AndroidComposeTestRule<*, *>.setRoomListContextMenu(
|
||||
contextMenu: RoomListState.ContextMenu.Shown,
|
||||
canReportRoom: Boolean = false,
|
||||
eventSink: (RoomListEvents) -> Unit,
|
||||
onRoomSettingsClick: (RoomId) -> Unit = EnsureNeverCalledWithParam(),
|
||||
onReportRoomClick: (RoomId) -> Unit = EnsureNeverCalledWithParam(),
|
||||
) {
|
||||
setSafeContent {
|
||||
RoomListContextMenu(
|
||||
contextMenu = contextMenu,
|
||||
canReportRoom = canReportRoom,
|
||||
onRoomSettingsClick = onRoomSettingsClick,
|
||||
onReportRoomClick = onReportRoomClick,
|
||||
eventSink = eventSink,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import io.element.android.tests.testutils.EnsureCalledOnceWithParam
|
|||
import io.element.android.tests.testutils.EnsureNeverCalledWithParam
|
||||
import io.element.android.tests.testutils.EventsRecorder
|
||||
import io.element.android.tests.testutils.clickOn
|
||||
import io.element.android.tests.testutils.setSafeContent
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
|
@ -28,7 +29,7 @@ class RoomListDeclineInviteMenuTest {
|
|||
fun `clicking on decline emits the expected Events`() {
|
||||
val eventsRecorder = EventsRecorder<RoomListEvents>()
|
||||
val menu = RoomListState.DeclineInviteMenu.Shown(roomSummary = aRoomListRoomSummary())
|
||||
rule.setContent {
|
||||
rule.setSafeContent {
|
||||
RoomListDeclineInviteMenu(
|
||||
menu = menu,
|
||||
canReportRoom = false,
|
||||
|
|
@ -49,7 +50,7 @@ class RoomListDeclineInviteMenuTest {
|
|||
fun `clicking on decline and block when canReportRoom=true, it emits the expected Events and callback`() {
|
||||
val eventsRecorder = EventsRecorder<RoomListEvents>()
|
||||
val menu = RoomListState.DeclineInviteMenu.Shown(roomSummary = aRoomListRoomSummary())
|
||||
rule.setContent {
|
||||
rule.setSafeContent {
|
||||
RoomListDeclineInviteMenu(
|
||||
menu = menu,
|
||||
canReportRoom = true,
|
||||
|
|
@ -66,7 +67,7 @@ class RoomListDeclineInviteMenuTest {
|
|||
fun `clicking on decline and block when canReportRoom=false, it emits the expected Events`() {
|
||||
val eventsRecorder = EventsRecorder<RoomListEvents>()
|
||||
val menu = RoomListState.DeclineInviteMenu.Shown(roomSummary = aRoomListRoomSummary())
|
||||
rule.setContent {
|
||||
rule.setSafeContent {
|
||||
RoomListDeclineInviteMenu(
|
||||
menu = menu,
|
||||
canReportRoom = false,
|
||||
|
|
@ -86,7 +87,7 @@ class RoomListDeclineInviteMenuTest {
|
|||
fun `clicking on cancel emits the expected Event`() {
|
||||
val eventsRecorder = EventsRecorder<RoomListEvents>()
|
||||
val menu = RoomListState.DeclineInviteMenu.Shown(roomSummary = aRoomListRoomSummary())
|
||||
rule.setContent {
|
||||
rule.setSafeContent {
|
||||
RoomListDeclineInviteMenu(
|
||||
menu = menu,
|
||||
canReportRoom = false,
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ 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.ensureCalledOnceWithParam
|
||||
import io.element.android.tests.testutils.setSafeContent
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
|
@ -52,7 +53,7 @@ class RoomListViewTest {
|
|||
eventsRecorder.assertList(
|
||||
listOf(
|
||||
RoomListEvents.UpdateVisibleRange(IntRange.EMPTY),
|
||||
RoomListEvents.UpdateVisibleRange(0 until 2),
|
||||
RoomListEvents.UpdateVisibleRange(0..2),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
@ -273,7 +274,7 @@ private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setRoomL
|
|||
onReportRoomClick: (RoomId) -> Unit = EnsureNeverCalledWithParam(),
|
||||
onDeclineInviteAndBlockUser: (RoomListRoomSummary) -> Unit = EnsureNeverCalledWithParam(),
|
||||
) {
|
||||
setContent {
|
||||
setSafeContent {
|
||||
RoomListView(
|
||||
state = state,
|
||||
onRoomClick = onRoomClick,
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import io.element.android.tests.testutils.EventsRecorder
|
|||
import io.element.android.tests.testutils.clickOn
|
||||
import io.element.android.tests.testutils.ensureCalledOnceWithTwoParams
|
||||
import io.element.android.tests.testutils.pressTag
|
||||
import io.element.android.tests.testutils.setSafeContent
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.TestRule
|
||||
|
|
@ -217,7 +218,7 @@ private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setRoomM
|
|||
state: InternalRoomMemberModerationState,
|
||||
onSelectAction: (ModerationAction, MatrixUser) -> Unit = EnsureNeverCalledWithTwoParams(),
|
||||
) {
|
||||
setContent {
|
||||
setSafeContent {
|
||||
RoomMemberModerationView(
|
||||
state = state,
|
||||
onSelectAction = onSelectAction,
|
||||
|
|
|
|||
|
|
@ -24,10 +24,12 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.autofill.AutofillType
|
||||
import androidx.compose.ui.autofill.ContentType
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.contentType
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
|
|
@ -39,7 +41,6 @@ import io.element.android.compound.theme.ElementTheme
|
|||
import io.element.android.compound.tokens.generated.CompoundIcons
|
||||
import io.element.android.features.securebackup.impl.R
|
||||
import io.element.android.features.securebackup.impl.tools.RecoveryKeyVisualTransformation
|
||||
import io.element.android.libraries.designsystem.modifiers.autofill
|
||||
import io.element.android.libraries.designsystem.modifiers.clickableIfNotNull
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
|
|
@ -186,10 +187,9 @@ private fun RecoveryKeyFormContent(
|
|||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag(TestTags.recoveryKey)
|
||||
.autofill(
|
||||
autofillTypes = listOf(AutofillType.Password),
|
||||
onFill = { onChange(it) },
|
||||
),
|
||||
.semantics {
|
||||
contentType = ContentType.Password
|
||||
},
|
||||
minLines = 2,
|
||||
value = state.formattedRecoveryKey.orEmpty(),
|
||||
onValueChange = onChange,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue