BIT-2202: Add element ids for cipher icons (#1251)

This commit is contained in:
Ramsey Smith 2024-04-11 09:06:47 -06:00 committed by Álison Fernandes
parent b81b79e215
commit c171c9353f
10 changed files with 56 additions and 2 deletions

View file

@ -16,6 +16,8 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.testTag
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.x8bit.bitwarden.R
@ -33,6 +35,7 @@ import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme
* @param onClick A lambda function that is invoked when the group is clicked.
* @param modifier The [Modifier] to be applied to the [Row] composable that holds the list item.
* @param showDivider Indicates whether the divider should be shown or not.
* @param startIconTestTag The optional test tag for the [startIcon].
*/
@Composable
fun BitwardenGroupItem(
@ -42,6 +45,7 @@ fun BitwardenGroupItem(
onClick: () -> Unit,
modifier: Modifier = Modifier,
showDivider: Boolean = true,
startIconTestTag: String? = null,
) {
Row(
modifier = Modifier
@ -67,7 +71,9 @@ fun BitwardenGroupItem(
painter = startIcon,
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurface,
modifier = Modifier.size(24.dp),
modifier = Modifier
.semantics { startIconTestTag?.let { testTag = it } }
.size(24.dp),
)
Text(
@ -102,6 +108,7 @@ private fun BitwardenGroupItem_preview() {
label = "Sample Label",
supportingLabel = "5",
startIcon = painterResource(id = R.drawable.ic_send_text),
startIconTestTag = "Test Tag",
onClick = {},
)
}

View file

@ -55,6 +55,7 @@ import kotlinx.collections.immutable.persistentListOf
* @param optionsTestTag The optional test tag for the options button.
* @param supportingLabel An optional secondary text label to display beneath the label.
* @param supportingLabelTestTag The optional test tag for the [supportingLabel].
* @param startIconTestTag The optional test tag for the [startIcon].
* @param trailingLabelIcons An optional list of small icons to be displayed after the [label].
*/
@Suppress("LongMethod")
@ -69,6 +70,7 @@ fun BitwardenListItem(
optionsTestTag: String? = null,
supportingLabel: String? = null,
supportingLabelTestTag: String? = null,
startIconTestTag: String? = null,
trailingLabelIcons: ImmutableList<IconResource> = persistentListOf(),
) {
var shouldShowDialog by rememberSaveable { mutableStateOf(false) }
@ -89,7 +91,9 @@ fun BitwardenListItem(
iconData = startIcon,
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurface,
modifier = Modifier.size(24.dp),
modifier = Modifier
.semantics { startIconTestTag?.let { testTag = it } }
.size(24.dp),
)
Column(modifier = Modifier.weight(1f)) {

View file

@ -195,6 +195,7 @@ fun VaultItemListingContent(
items(state.displayItemList) {
BitwardenListItem(
startIcon = it.iconData,
startIconTestTag = it.iconTestTag,
label = it.title,
labelTestTag = it.titleTestTag,
supportingLabel = it.subtitle,

View file

@ -881,6 +881,7 @@ data class VaultItemListingState(
* @property subtitle subtitle of the item (nullable).
* @property subtitleTestTag The test tag associated with the [subtitle].
* @property iconData data for the icon to be displayed (nullable).
* @property iconTestTag The test tag for the icon (nullable).
* @property overflowOptions list of options for the item's overflow menu.
* @property optionsTestTag The test tag associated with the [overflowOptions].
* @property isAutofill whether or not this screen is part of an autofill flow.
@ -894,6 +895,7 @@ data class VaultItemListingState(
val subtitle: String?,
val subtitleTestTag: String,
val iconData: IconData,
val iconTestTag: String?,
val extraIconList: List<IconRes>,
val overflowOptions: List<ListingItemOverflowAction>,
val optionsTestTag: String,

View file

@ -1,3 +1,5 @@
@file:Suppress("TooManyFunctions")
package com.x8bit.bitwarden.ui.vault.feature.itemlisting.util
import androidx.annotation.DrawableRes
@ -281,6 +283,7 @@ private fun CipherView.toDisplayItem(
baseIconUrl = baseIconUrl,
isIconLoadingDisabled = isIconLoadingDisabled,
),
iconTestTag = toIconTestTag(),
extraIconList = toLabelIcons(),
overflowOptions = toOverflowActions(),
optionsTestTag = "CipherOptionsButton",
@ -288,6 +291,14 @@ private fun CipherView.toDisplayItem(
shouldShowMasterPasswordReprompt = reprompt == CipherRepromptType.PASSWORD,
)
private fun CipherView.toIconTestTag(): String =
when (type) {
CipherType.LOGIN -> "LoginCipherIcon"
CipherType.SECURE_NOTE -> "SecureNoteCipherIcon"
CipherType.CARD -> "CardCipherIcon"
CipherType.IDENTITY -> "IdentityCipherIcon"
}
private fun CipherView.toIconData(
baseIconUrl: String,
isIconLoadingDisabled: Boolean,
@ -322,6 +333,7 @@ private fun SendView.toDisplayItem(
SendType.FILE -> R.drawable.ic_send_file
},
),
iconTestTag = null,
extraIconList = toLabelIcons(clock = clock),
overflowOptions = toOverflowActions(baseWebSendUrl = baseWebSendUrl),
optionsTestTag = "SendOptionsButton",

View file

@ -81,6 +81,7 @@ fun VaultContent(
items(state.favoriteItems) { favoriteItem ->
VaultEntryListItem(
startIcon = favoriteItem.startIcon,
startIconTestTag = favoriteItem.startIconTestTag,
trailingLabelIcons = favoriteItem
.extraIconList
.toIconResources()
@ -138,6 +139,7 @@ fun VaultContent(
item {
BitwardenGroupItem(
startIcon = painterResource(id = R.drawable.ic_login_item),
startIconTestTag = "LoginCipherIcon",
label = stringResource(id = R.string.type_login),
supportingLabel = state.loginItemsCount.toString(),
onClick = vaultHandlers.loginGroupClick,
@ -152,6 +154,7 @@ fun VaultContent(
item {
BitwardenGroupItem(
startIcon = painterResource(id = R.drawable.ic_card_item),
startIconTestTag = "CardCipherIcon",
label = stringResource(id = R.string.type_card),
supportingLabel = state.cardItemsCount.toString(),
onClick = vaultHandlers.cardGroupClick,
@ -166,6 +169,7 @@ fun VaultContent(
item {
BitwardenGroupItem(
startIcon = painterResource(id = R.drawable.ic_identity_item),
startIconTestTag = "IdentityCipherIcon",
label = stringResource(id = R.string.type_identity),
supportingLabel = state.identityItemsCount.toString(),
onClick = vaultHandlers.identityGroupClick,
@ -180,6 +184,7 @@ fun VaultContent(
item {
BitwardenGroupItem(
startIcon = painterResource(id = R.drawable.ic_secure_note_item),
startIconTestTag = "SecureNoteCipherIcon",
label = stringResource(id = R.string.type_secure_note),
supportingLabel = state.secureNoteItemsCount.toString(),
onClick = vaultHandlers.secureNoteGroupClick,
@ -254,6 +259,7 @@ fun VaultContent(
items(state.noFolderItems) { noFolderItem ->
VaultEntryListItem(
startIcon = noFolderItem.startIcon,
startIconTestTag = noFolderItem.startIconTestTag,
trailingLabelIcons = noFolderItem
.extraIconList
.toIconResources()

View file

@ -17,6 +17,8 @@ import kotlinx.collections.immutable.toImmutableList
/**
* A Composable function that displays a row item for different types of vault entries.
*
* @param startIcon The [IconData] object used to draw the icon at the start of the item.
* @param startIconTestTag The test tag for the [startIcon].
* @param label The primary text label to display for the item.
* @param supportingLabel An optional secondary text label to display beneath the primary label.
* @param onClick The lambda to be invoked when the item is clicked.
@ -28,6 +30,7 @@ import kotlinx.collections.immutable.toImmutableList
@Composable
fun VaultEntryListItem(
startIcon: IconData,
startIconTestTag: String,
label: String,
onClick: () -> Unit,
overflowOptions: List<ListingItemOverflowAction.VaultAction>,
@ -41,6 +44,7 @@ fun VaultEntryListItem(
label = label,
supportingLabel = supportingLabel,
startIcon = startIcon,
startIconTestTag = startIconTestTag,
trailingLabelIcons = trailingLabelIcons,
onClick = onClick,
selectionDataList = overflowOptions
@ -60,6 +64,7 @@ private fun VaultEntryListItem_preview() {
BitwardenTheme {
VaultEntryListItem(
startIcon = IconData.Local(R.drawable.ic_login_item),
startIconTestTag = "Test Tag",
label = "Example Login",
supportingLabel = "Username",
onClick = {},

View file

@ -760,6 +760,11 @@ data class VaultState(
*/
abstract val startIcon: IconData
/**
* The test tag for the icon at the start of the item.
*/
abstract val startIconTestTag: String
/**
* The icons shown after the item name.
*/
@ -792,6 +797,7 @@ data class VaultState(
override val id: String,
override val name: Text,
override val startIcon: IconData = IconData.Local(R.drawable.ic_login_item),
override val startIconTestTag: String = "LoginCipherIcon",
override val extraIconList: List<IconRes> = emptyList(),
override val overflowOptions: List<ListingItemOverflowAction.VaultAction>,
override val shouldShowMasterPasswordReprompt: Boolean,
@ -811,6 +817,7 @@ data class VaultState(
override val id: String,
override val name: Text,
override val startIcon: IconData = IconData.Local(R.drawable.ic_card_item),
override val startIconTestTag: String = "CardCipherIcon",
override val extraIconList: List<IconRes> = emptyList(),
override val overflowOptions: List<ListingItemOverflowAction.VaultAction>,
override val shouldShowMasterPasswordReprompt: Boolean,
@ -840,6 +847,7 @@ data class VaultState(
override val id: String,
override val name: Text,
override val startIcon: IconData = IconData.Local(R.drawable.ic_identity_item),
override val startIconTestTag: String = "IdentityCipherIcon",
override val extraIconList: List<IconRes> = emptyList(),
override val overflowOptions: List<ListingItemOverflowAction.VaultAction>,
override val shouldShowMasterPasswordReprompt: Boolean,
@ -857,6 +865,7 @@ data class VaultState(
override val id: String,
override val name: Text,
override val startIcon: IconData = IconData.Local(R.drawable.ic_secure_note_item),
override val startIconTestTag: String = "SecureNoteCipherIcon",
override val extraIconList: List<IconRes> = emptyList(),
override val overflowOptions: List<ListingItemOverflowAction.VaultAction>,
override val shouldShowMasterPasswordReprompt: Boolean,

View file

@ -1508,6 +1508,7 @@ private fun createDisplayItem(number: Int): VaultItemListingState.DisplayItem =
optionsTestTag = "SendOptionsButton",
isAutofill = false,
shouldShowMasterPasswordReprompt = false,
iconTestTag = null,
)
private fun createCipherDisplayItem(number: Int): VaultItemListingState.DisplayItem =
@ -1525,4 +1526,5 @@ private fun createCipherDisplayItem(number: Int): VaultItemListingState.DisplayI
optionsTestTag = "CipherOptionsButton",
isAutofill = false,
shouldShowMasterPasswordReprompt = false,
iconTestTag = null,
)

View file

@ -60,6 +60,7 @@ fun createMockDisplayItemForCipher(
optionsTestTag = "CipherOptionsButton",
isAutofill = false,
shouldShowMasterPasswordReprompt = false,
iconTestTag = "LoginCipherIcon",
)
}
@ -93,6 +94,7 @@ fun createMockDisplayItemForCipher(
optionsTestTag = "CipherOptionsButton",
isAutofill = false,
shouldShowMasterPasswordReprompt = false,
iconTestTag = "SecureNoteCipherIcon",
)
}
@ -129,6 +131,7 @@ fun createMockDisplayItemForCipher(
optionsTestTag = "CipherOptionsButton",
isAutofill = false,
shouldShowMasterPasswordReprompt = false,
iconTestTag = "CardCipherIcon",
)
}
@ -159,6 +162,7 @@ fun createMockDisplayItemForCipher(
optionsTestTag = "CipherOptionsButton",
isAutofill = false,
shouldShowMasterPasswordReprompt = false,
iconTestTag = "IdentityCipherIcon",
)
}
}
@ -206,6 +210,7 @@ fun createMockDisplayItemForSend(
optionsTestTag = "SendOptionsButton",
isAutofill = false,
shouldShowMasterPasswordReprompt = false,
iconTestTag = null,
)
}
@ -243,6 +248,7 @@ fun createMockDisplayItemForSend(
optionsTestTag = "SendOptionsButton",
isAutofill = false,
shouldShowMasterPasswordReprompt = false,
iconTestTag = null,
)
}
}