mirror of
https://github.com/bitwarden/android.git
synced 2024-10-31 15:15:34 +03:00
BIT-752: Update the dropdown accessibility callout (#1100)
This commit is contained in:
parent
a8f76488da
commit
51a8ab87eb
5 changed files with 140 additions and 141 deletions
|
@ -2,7 +2,6 @@ package com.x8bit.bitwarden.ui.platform.components.dropdown
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
@ -23,11 +22,12 @@ import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.semantics.CustomAccessibilityAction
|
||||||
import androidx.compose.ui.semantics.Role
|
import androidx.compose.ui.semantics.Role
|
||||||
import androidx.compose.ui.semantics.clearAndSetSemantics
|
import androidx.compose.ui.semantics.clearAndSetSemantics
|
||||||
import androidx.compose.ui.semantics.contentDescription
|
import androidx.compose.ui.semantics.contentDescription
|
||||||
|
import androidx.compose.ui.semantics.customActions
|
||||||
import androidx.compose.ui.semantics.role
|
import androidx.compose.ui.semantics.role
|
||||||
import androidx.compose.ui.semantics.semantics
|
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
@ -71,95 +71,102 @@ fun BitwardenMultiSelectButton(
|
||||||
) {
|
) {
|
||||||
var shouldShowDialog by rememberSaveable { mutableStateOf(false) }
|
var shouldShowDialog by rememberSaveable { mutableStateOf(false) }
|
||||||
|
|
||||||
Box(
|
OutlinedTextField(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.semantics(mergeDescendants = true) {},
|
.clearAndSetSemantics {
|
||||||
) {
|
role = Role.DropdownList
|
||||||
OutlinedTextField(
|
contentDescription = supportingText
|
||||||
// TODO: Update with final accessibility reading (BIT-752)
|
?.let { "$selectedOption. $label. $it" }
|
||||||
modifier = Modifier
|
?: "$selectedOption. $label"
|
||||||
.clearAndSetSemantics {
|
customActions = listOfNotNull(
|
||||||
this.role = Role.DropdownList
|
|
||||||
contentDescription = "$label, $selectedOption"
|
|
||||||
}
|
|
||||||
.fillMaxWidth()
|
|
||||||
.clickable(
|
|
||||||
indication = null,
|
|
||||||
enabled = isEnabled,
|
|
||||||
interactionSource = remember { MutableInteractionSource() },
|
|
||||||
) {
|
|
||||||
shouldShowDialog = !shouldShowDialog
|
|
||||||
},
|
|
||||||
textStyle = MaterialTheme.typography.bodyLarge,
|
|
||||||
readOnly = true,
|
|
||||||
label = {
|
|
||||||
Row {
|
|
||||||
Text(
|
|
||||||
text = label,
|
|
||||||
maxLines = 1,
|
|
||||||
overflow = TextOverflow.Ellipsis,
|
|
||||||
)
|
|
||||||
tooltip?.let {
|
tooltip?.let {
|
||||||
Spacer(modifier = Modifier.width(3.dp))
|
CustomAccessibilityAction(
|
||||||
IconButton(
|
label = it.contentDescription,
|
||||||
onClick = it.onClick,
|
action = {
|
||||||
enabled = isEnabled,
|
it.onClick()
|
||||||
colors = IconButtonDefaults.iconButtonColors(
|
true
|
||||||
contentColor = MaterialTheme.colorScheme.primary,
|
},
|
||||||
),
|
)
|
||||||
modifier = Modifier.size(16.dp),
|
},
|
||||||
) {
|
)
|
||||||
Icon(
|
}
|
||||||
painter = painterResource(id = R.drawable.ic_tooltip_small),
|
.fillMaxWidth()
|
||||||
contentDescription = it.contentDescription,
|
.clickable(
|
||||||
)
|
indication = null,
|
||||||
}
|
enabled = isEnabled,
|
||||||
|
interactionSource = remember { MutableInteractionSource() },
|
||||||
|
) {
|
||||||
|
shouldShowDialog = !shouldShowDialog
|
||||||
|
},
|
||||||
|
textStyle = MaterialTheme.typography.bodyLarge,
|
||||||
|
readOnly = true,
|
||||||
|
label = {
|
||||||
|
Row {
|
||||||
|
Text(
|
||||||
|
text = label,
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
)
|
||||||
|
tooltip?.let {
|
||||||
|
Spacer(modifier = Modifier.width(3.dp))
|
||||||
|
IconButton(
|
||||||
|
onClick = it.onClick,
|
||||||
|
enabled = isEnabled,
|
||||||
|
colors = IconButtonDefaults.iconButtonColors(
|
||||||
|
contentColor = MaterialTheme.colorScheme.primary,
|
||||||
|
),
|
||||||
|
modifier = Modifier.size(16.dp),
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(id = R.drawable.ic_tooltip_small),
|
||||||
|
contentDescription = it.contentDescription,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
value = selectedOption ?: "",
|
},
|
||||||
onValueChange = onOptionSelected,
|
value = selectedOption.orEmpty(),
|
||||||
enabled = shouldShowDialog,
|
onValueChange = onOptionSelected,
|
||||||
trailingIcon = {
|
enabled = shouldShowDialog,
|
||||||
Icon(
|
trailingIcon = {
|
||||||
painter = painterResource(id = R.drawable.ic_region_select_dropdown),
|
Icon(
|
||||||
contentDescription = null,
|
painter = painterResource(id = R.drawable.ic_region_select_dropdown),
|
||||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
contentDescription = null,
|
||||||
|
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
colors = OutlinedTextFieldDefaults.colors(
|
||||||
|
disabledTextColor = MaterialTheme.colorScheme.onSurface,
|
||||||
|
disabledBorderColor = MaterialTheme.colorScheme.outline,
|
||||||
|
disabledLeadingIconColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
|
disabledTrailingIconColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
|
disabledLabelColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
|
disabledPlaceholderColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
|
disabledSupportingTextColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
supportingText = supportingText?.let {
|
||||||
|
{
|
||||||
|
Text(
|
||||||
|
text = supportingText,
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if (shouldShowDialog) {
|
||||||
|
BitwardenSelectionDialog(
|
||||||
|
title = label,
|
||||||
|
onDismissRequest = { shouldShowDialog = false },
|
||||||
|
) {
|
||||||
|
options.forEach { optionString ->
|
||||||
|
BitwardenSelectionRow(
|
||||||
|
text = optionString.asText(),
|
||||||
|
isSelected = optionString == selectedOption,
|
||||||
|
onClick = {
|
||||||
|
shouldShowDialog = false
|
||||||
|
onOptionSelected(optionString)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
},
|
|
||||||
colors = OutlinedTextFieldDefaults.colors(
|
|
||||||
disabledTextColor = MaterialTheme.colorScheme.onSurface,
|
|
||||||
disabledBorderColor = MaterialTheme.colorScheme.outline,
|
|
||||||
disabledLeadingIconColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
|
||||||
disabledTrailingIconColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
|
||||||
disabledLabelColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
|
||||||
disabledPlaceholderColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
|
||||||
disabledSupportingTextColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
|
||||||
),
|
|
||||||
supportingText = supportingText?.let {
|
|
||||||
{
|
|
||||||
Text(
|
|
||||||
text = supportingText,
|
|
||||||
style = MaterialTheme.typography.bodySmall,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
if (shouldShowDialog) {
|
|
||||||
BitwardenSelectionDialog(
|
|
||||||
title = label,
|
|
||||||
onDismissRequest = { shouldShowDialog = false },
|
|
||||||
) {
|
|
||||||
options.forEach { optionString ->
|
|
||||||
BitwardenSelectionRow(
|
|
||||||
text = optionString.asText(),
|
|
||||||
isSelected = optionString == selectedOption,
|
|
||||||
onClick = {
|
|
||||||
shouldShowDialog = false
|
|
||||||
onOptionSelected(optionString)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,7 +163,7 @@ class ExportVaultScreenTest : BaseComposeTest() {
|
||||||
fun `file format selection button should send ExportFormatOptionSelect action`() {
|
fun `file format selection button should send ExportFormatOptionSelect action`() {
|
||||||
// Open the menu.
|
// Open the menu.
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescription(label = "File format, .json")
|
.onNodeWithContentDescription(label = ".json. File format")
|
||||||
.performClick()
|
.performClick()
|
||||||
|
|
||||||
// Choose the option from the menu.
|
// Choose the option from the menu.
|
||||||
|
@ -182,7 +182,7 @@ class ExportVaultScreenTest : BaseComposeTest() {
|
||||||
@Test
|
@Test
|
||||||
fun `file format selection button should update according to state`() {
|
fun `file format selection button should update according to state`() {
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescription(label = "File format, .json")
|
.onNodeWithContentDescription(label = ".json. File format")
|
||||||
.assertIsDisplayed()
|
.assertIsDisplayed()
|
||||||
|
|
||||||
mutableStateFlow.update {
|
mutableStateFlow.update {
|
||||||
|
@ -190,7 +190,7 @@ class ExportVaultScreenTest : BaseComposeTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescription(label = "File format, .csv")
|
.onNodeWithContentDescription(label = ".csv. File format")
|
||||||
.assertIsDisplayed()
|
.assertIsDisplayed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -189,7 +189,7 @@ class GeneratorScreenTest : BaseComposeTest() {
|
||||||
fun `clicking a MainStateOption should send MainTypeOptionSelect action`() {
|
fun `clicking a MainStateOption should send MainTypeOptionSelect action`() {
|
||||||
// Opens the menu
|
// Opens the menu
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescription(label = "What would you like to generate?, Password")
|
.onNodeWithContentDescription(label = "Password. What would you like to generate?")
|
||||||
.performClick()
|
.performClick()
|
||||||
|
|
||||||
// Choose the option from the menu
|
// Choose the option from the menu
|
||||||
|
@ -216,7 +216,7 @@ class GeneratorScreenTest : BaseComposeTest() {
|
||||||
fun `clicking a PasscodeOption should send PasscodeTypeOption action`() {
|
fun `clicking a PasscodeOption should send PasscodeTypeOption action`() {
|
||||||
// Opens the menu
|
// Opens the menu
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescription(label = "Password type, Password")
|
.onNodeWithContentDescription(label = "Password. Password type")
|
||||||
.performClick()
|
.performClick()
|
||||||
|
|
||||||
// Choose the option from the menu
|
// Choose the option from the menu
|
||||||
|
@ -240,6 +240,7 @@ class GeneratorScreenTest : BaseComposeTest() {
|
||||||
.assertDoesNotExist()
|
.assertDoesNotExist()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("MaxLineLength")
|
||||||
@Test
|
@Test
|
||||||
fun `clicking a UsernameOption should send UsernameTypeOption action`() {
|
fun `clicking a UsernameOption should send UsernameTypeOption action`() {
|
||||||
updateState(
|
updateState(
|
||||||
|
@ -256,7 +257,9 @@ class GeneratorScreenTest : BaseComposeTest() {
|
||||||
|
|
||||||
// Opens the menu
|
// Opens the menu
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescription(label = "Username type, Plus addressed email")
|
.onNodeWithContentDescription(
|
||||||
|
label = "Plus addressed email. Username type. Use your email provider's subaddress capabilities",
|
||||||
|
)
|
||||||
.performClick()
|
.performClick()
|
||||||
|
|
||||||
// Choose the option from the menu
|
// Choose the option from the menu
|
||||||
|
@ -285,11 +288,11 @@ class GeneratorScreenTest : BaseComposeTest() {
|
||||||
@Test
|
@Test
|
||||||
fun `in Passcode_Password state, the ViewModel state should update the UI correctly`() {
|
fun `in Passcode_Password state, the ViewModel state should update the UI correctly`() {
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescription(label = "What would you like to generate?, Password")
|
.onNodeWithContentDescription(label = "Password. What would you like to generate?")
|
||||||
.assertIsDisplayed()
|
.assertIsDisplayed()
|
||||||
|
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescription(label = "Password type, Password")
|
.onNodeWithContentDescription(label = "Password. Password type")
|
||||||
.assertIsDisplayed()
|
.assertIsDisplayed()
|
||||||
|
|
||||||
composeTestRule
|
composeTestRule
|
||||||
|
@ -1154,7 +1157,7 @@ class GeneratorScreenTest : BaseComposeTest() {
|
||||||
|
|
||||||
// Opens the menu
|
// Opens the menu
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescription(label = "Service, null")
|
.onNodeWithContentDescription(label = "null. Service")
|
||||||
.performScrollTo()
|
.performScrollTo()
|
||||||
.performClick()
|
.performClick()
|
||||||
|
|
||||||
|
@ -1517,13 +1520,14 @@ class GeneratorScreenTest : BaseComposeTest() {
|
||||||
|
|
||||||
//region Username Type Tests
|
//region Username Type Tests
|
||||||
|
|
||||||
|
@Suppress("MaxLineLength")
|
||||||
@Test
|
@Test
|
||||||
fun `in Username state, clicking the toolitp icon should send the TooltipClick action`() {
|
fun `in Username state, clicking the tooltip icon should send the TooltipClick action`() {
|
||||||
updateState(DEFAULT_STATE.copy(selectedType = GeneratorState.MainType.Username()))
|
updateState(DEFAULT_STATE.copy(selectedType = GeneratorState.MainType.Username()))
|
||||||
|
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescription(
|
.onNodeWithContentDescription(
|
||||||
label = "Username type, Plus addressed email",
|
label = "Plus addressed email. Username type. Use your email provider's subaddress capabilities",
|
||||||
useUnmergedTree = true,
|
useUnmergedTree = true,
|
||||||
)
|
)
|
||||||
// Find the button
|
// Find the button
|
||||||
|
|
|
@ -134,14 +134,12 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("MaxLineLength")
|
|
||||||
@Test
|
@Test
|
||||||
fun `on NavigateToQrCodeScan event should invoke NavigateToQrCodeScan`() {
|
fun `on NavigateToQrCodeScan event should invoke NavigateToQrCodeScan`() {
|
||||||
mutableEventFlow.tryEmit(VaultAddEditEvent.NavigateToQrCodeScan)
|
mutableEventFlow.tryEmit(VaultAddEditEvent.NavigateToQrCodeScan)
|
||||||
assertTrue(onNavigateQrCodeScanScreenCalled)
|
assertTrue(onNavigateQrCodeScanScreenCalled)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("MaxLineLength")
|
|
||||||
@Test
|
@Test
|
||||||
fun `on NavigateToManualCodeEntry event should invoke NavigateToManualCodeEntry`() {
|
fun `on NavigateToManualCodeEntry event should invoke NavigateToManualCodeEntry`() {
|
||||||
mutableEventFlow.tryEmit(VaultAddEditEvent.NavigateToManualCodeEntry)
|
mutableEventFlow.tryEmit(VaultAddEditEvent.NavigateToManualCodeEntry)
|
||||||
|
@ -347,7 +345,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
fun `clicking a Type Option should send TypeOptionSelect action`() {
|
fun `clicking a Type Option should send TypeOptionSelect action`() {
|
||||||
// Opens the menu
|
// Opens the menu
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescriptionAfterScroll(label = "Type, Login")
|
.onNodeWithContentDescriptionAfterScroll(label = "Login. Type")
|
||||||
.performClick()
|
.performClick()
|
||||||
|
|
||||||
// Choose the option from the menu
|
// Choose the option from the menu
|
||||||
|
@ -367,7 +365,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
@Test
|
@Test
|
||||||
fun `the Type Option field should display the text of the selected item type`() {
|
fun `the Type Option field should display the text of the selected item type`() {
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescriptionAfterScroll(label = "Type, Login")
|
.onNodeWithContentDescriptionAfterScroll(label = "Login. Type")
|
||||||
.assertIsDisplayed()
|
.assertIsDisplayed()
|
||||||
|
|
||||||
mutableStateFlow.update {
|
mutableStateFlow.update {
|
||||||
|
@ -381,7 +379,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescriptionAfterScroll(label = "Type, Card")
|
.onNodeWithContentDescriptionAfterScroll(label = "Card. Type")
|
||||||
.assertIsDisplayed()
|
.assertIsDisplayed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -642,7 +640,6 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
.assertTextContains("•••••••••••")
|
.assertTextContains("•••••••••••")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("MaxLineLength")
|
|
||||||
@Test
|
@Test
|
||||||
fun `in ItemType_Login state the totp text field should be present based on state`() {
|
fun `in ItemType_Login state the totp text field should be present based on state`() {
|
||||||
mutableStateFlow.update { currentState ->
|
mutableStateFlow.update { currentState ->
|
||||||
|
@ -844,7 +841,6 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
.assertTextContains("NewURI")
|
.assertTextContains("NewURI")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("MaxLineLength")
|
|
||||||
@Test
|
@Test
|
||||||
fun `in ItemType_Login Uri settings dialog should be dismissed on cancel click`() {
|
fun `in ItemType_Login Uri settings dialog should be dismissed on cancel click`() {
|
||||||
composeTestRule
|
composeTestRule
|
||||||
|
@ -1042,7 +1038,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
mutableStateFlow.value = DEFAULT_STATE_IDENTITY
|
mutableStateFlow.value = DEFAULT_STATE_IDENTITY
|
||||||
// Opens the menu
|
// Opens the menu
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescriptionAfterScroll(label = "Title, -- Select --")
|
.onNodeWithContentDescriptionAfterScroll(label = "-- Select --. Title")
|
||||||
.performClick()
|
.performClick()
|
||||||
|
|
||||||
// Choose the option from the menu
|
// Choose the option from the menu
|
||||||
|
@ -1065,7 +1061,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
fun `in ItemType_Identity the Title should display the selected title from the state`() {
|
fun `in ItemType_Identity the Title should display the selected title from the state`() {
|
||||||
mutableStateFlow.value = DEFAULT_STATE_IDENTITY
|
mutableStateFlow.value = DEFAULT_STATE_IDENTITY
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescriptionAfterScroll(label = "Title, -- Select --")
|
.onNodeWithContentDescriptionAfterScroll(label = "-- Select --. Title")
|
||||||
.assertIsDisplayed()
|
.assertIsDisplayed()
|
||||||
|
|
||||||
mutableStateFlow.update { currentState ->
|
mutableStateFlow.update { currentState ->
|
||||||
|
@ -1077,7 +1073,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescriptionAfterScroll(label = "Title, Mx")
|
.onNodeWithContentDescriptionAfterScroll(label = "Mx. Title")
|
||||||
.assertIsDisplayed()
|
.assertIsDisplayed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1497,7 +1493,6 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("MaxLineLength")
|
|
||||||
@Test
|
@Test
|
||||||
fun `in ItemType_Identity the city text field should display the text provided by the state`() {
|
fun `in ItemType_Identity the city text field should display the text provided by the state`() {
|
||||||
mutableStateFlow.value = DEFAULT_STATE_IDENTITY
|
mutableStateFlow.value = DEFAULT_STATE_IDENTITY
|
||||||
|
@ -1530,7 +1525,6 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("MaxLineLength")
|
|
||||||
@Test
|
@Test
|
||||||
fun `in ItemType_Identity the zip text field should display the text provided by the state`() {
|
fun `in ItemType_Identity the zip text field should display the text provided by the state`() {
|
||||||
mutableStateFlow.value = DEFAULT_STATE_IDENTITY
|
mutableStateFlow.value = DEFAULT_STATE_IDENTITY
|
||||||
|
@ -1688,7 +1682,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
mutableStateFlow.value = DEFAULT_STATE_CARD
|
mutableStateFlow.value = DEFAULT_STATE_CARD
|
||||||
// Opens the menu
|
// Opens the menu
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescriptionAfterScroll(label = "Brand, -- Select --")
|
.onNodeWithContentDescriptionAfterScroll(label = "-- Select --. Brand")
|
||||||
.performClick()
|
.performClick()
|
||||||
|
|
||||||
// Choose the option from the menu
|
// Choose the option from the menu
|
||||||
|
@ -1707,12 +1701,11 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("MaxLineLength")
|
|
||||||
@Test
|
@Test
|
||||||
fun `in ItemType_Card the Brand should display the selected brand from the state`() {
|
fun `in ItemType_Card the Brand should display the selected brand from the state`() {
|
||||||
mutableStateFlow.value = DEFAULT_STATE_CARD
|
mutableStateFlow.value = DEFAULT_STATE_CARD
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescriptionAfterScroll(label = "Brand, -- Select --")
|
.onNodeWithContentDescriptionAfterScroll(label = "-- Select --. Brand")
|
||||||
.assertIsDisplayed()
|
.assertIsDisplayed()
|
||||||
|
|
||||||
mutableStateFlow.update { currentState ->
|
mutableStateFlow.update { currentState ->
|
||||||
|
@ -1724,17 +1717,16 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescriptionAfterScroll(label = "Brand, American Express")
|
.onNodeWithContentDescriptionAfterScroll(label = "American Express. Brand")
|
||||||
.assertIsDisplayed()
|
.assertIsDisplayed()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("MaxLineLength")
|
|
||||||
@Test
|
@Test
|
||||||
fun `in ItemType_Card selecting an expiration month should trigger ExpirationMonthSelected`() {
|
fun `in ItemType_Card selecting an expiration month should trigger ExpirationMonthSelected`() {
|
||||||
mutableStateFlow.value = DEFAULT_STATE_CARD
|
mutableStateFlow.value = DEFAULT_STATE_CARD
|
||||||
// Opens the menu
|
// Opens the menu
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescriptionAfterScroll(label = "Expiration month, -- Select --")
|
.onNodeWithContentDescriptionAfterScroll(label = "-- Select --. Expiration month")
|
||||||
.performClick()
|
.performClick()
|
||||||
|
|
||||||
// Choose the option from the menu
|
// Choose the option from the menu
|
||||||
|
@ -1758,7 +1750,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
fun `in ItemType_Card the Expiration month should display the selected expiration month from the state`() {
|
fun `in ItemType_Card the Expiration month should display the selected expiration month from the state`() {
|
||||||
mutableStateFlow.value = DEFAULT_STATE_CARD
|
mutableStateFlow.value = DEFAULT_STATE_CARD
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescriptionAfterScroll(label = "Expiration month, -- Select --")
|
.onNodeWithContentDescriptionAfterScroll(label = "-- Select --. Expiration month")
|
||||||
.assertIsDisplayed()
|
.assertIsDisplayed()
|
||||||
|
|
||||||
mutableStateFlow.update { currentState ->
|
mutableStateFlow.update { currentState ->
|
||||||
|
@ -1770,7 +1762,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescriptionAfterScroll(label = "Expiration month, 03 - March")
|
.onNodeWithContentDescriptionAfterScroll(label = "03 - March. Expiration month")
|
||||||
.assertIsDisplayed()
|
.assertIsDisplayed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1890,7 +1882,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
// Opens the menu
|
// Opens the menu
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescriptionAfterScroll(
|
.onNodeWithContentDescriptionAfterScroll(
|
||||||
label = "Who owns this item?, placeholder@email.com",
|
label = "placeholder@email.com. Who owns this item?",
|
||||||
)
|
)
|
||||||
.performClick()
|
.performClick()
|
||||||
|
|
||||||
|
@ -1919,7 +1911,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
updateStateWithOwners()
|
updateStateWithOwners()
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescriptionAfterScroll(
|
.onNodeWithContentDescriptionAfterScroll(
|
||||||
label = "Who owns this item?, placeholder@email.com",
|
label = "placeholder@email.com. Who owns this item?",
|
||||||
)
|
)
|
||||||
.assertIsDisplayed()
|
.assertIsDisplayed()
|
||||||
|
|
||||||
|
@ -1928,7 +1920,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescriptionAfterScroll(label = "Who owns this item?, mockOwnerName-2")
|
.onNodeWithContentDescriptionAfterScroll(label = "mockOwnerName-2. Who owns this item?")
|
||||||
.assertIsDisplayed()
|
.assertIsDisplayed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2009,7 +2001,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
|
|
||||||
// Opens the menu
|
// Opens the menu
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescriptionAfterScroll(label = "Folder, No Folder")
|
.onNodeWithContentDescriptionAfterScroll(label = "No Folder. Folder")
|
||||||
.performClick()
|
.performClick()
|
||||||
|
|
||||||
// Choose the option from the menu
|
// Choose the option from the menu
|
||||||
|
@ -2031,13 +2023,12 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("MaxLineLength")
|
|
||||||
@Test
|
@Test
|
||||||
fun `the folder control should display the text provided by the state`() {
|
fun `the folder control should display the text provided by the state`() {
|
||||||
updateStateWithFolders()
|
updateStateWithFolders()
|
||||||
|
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescriptionAfterScroll(label = "Folder, No Folder")
|
.onNodeWithContentDescriptionAfterScroll(label = "No Folder. Folder")
|
||||||
.assertIsDisplayed()
|
.assertIsDisplayed()
|
||||||
|
|
||||||
mutableStateFlow.update { currentState ->
|
mutableStateFlow.update { currentState ->
|
||||||
|
@ -2045,11 +2036,10 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescriptionAfterScroll(label = "Folder, mockFolderName-1")
|
.onNodeWithContentDescriptionAfterScroll(label = "mockFolderName-1. Folder")
|
||||||
.assertIsDisplayed()
|
.assertIsDisplayed()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("MaxLineLength")
|
|
||||||
@Test
|
@Test
|
||||||
fun `toggling the favorite toggle should send ToggleFavorite action`() {
|
fun `toggling the favorite toggle should send ToggleFavorite action`() {
|
||||||
mutableStateFlow.value = DEFAULT_STATE_SECURE_NOTES
|
mutableStateFlow.value = DEFAULT_STATE_SECURE_NOTES
|
||||||
|
@ -2104,7 +2094,6 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("MaxLineLength")
|
|
||||||
@Test
|
@Test
|
||||||
fun `the master password re-prompt toggle should be enabled or disabled according to state`() {
|
fun `the master password re-prompt toggle should be enabled or disabled according to state`() {
|
||||||
mutableStateFlow.value = DEFAULT_STATE_SECURE_NOTES
|
mutableStateFlow.value = DEFAULT_STATE_SECURE_NOTES
|
||||||
|
@ -2172,7 +2161,6 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
.assertTextContains("NewNote")
|
.assertTextContains("NewNote")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("MaxLineLength")
|
|
||||||
@Test
|
@Test
|
||||||
fun `Ownership option should send OwnershipChange action`() {
|
fun `Ownership option should send OwnershipChange action`() {
|
||||||
mutableStateFlow.value = DEFAULT_STATE_SECURE_NOTES
|
mutableStateFlow.value = DEFAULT_STATE_SECURE_NOTES
|
||||||
|
@ -2181,7 +2169,9 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
|
|
||||||
// Opens the menu
|
// Opens the menu
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescriptionAfterScroll(label = "Who owns this item?, placeholder@email.com")
|
.onNodeWithContentDescriptionAfterScroll(
|
||||||
|
label = "placeholder@email.com. Who owns this item?",
|
||||||
|
)
|
||||||
.performClick()
|
.performClick()
|
||||||
|
|
||||||
// Choose the option from the menu
|
// Choose the option from the menu
|
||||||
|
@ -2210,7 +2200,9 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
updateStateWithOwners()
|
updateStateWithOwners()
|
||||||
|
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescriptionAfterScroll(label = "Who owns this item?, placeholder@email.com")
|
.onNodeWithContentDescriptionAfterScroll(
|
||||||
|
label = "placeholder@email.com. Who owns this item?",
|
||||||
|
)
|
||||||
.assertIsDisplayed()
|
.assertIsDisplayed()
|
||||||
|
|
||||||
mutableStateFlow.update { currentState ->
|
mutableStateFlow.update { currentState ->
|
||||||
|
@ -2218,11 +2210,12 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescriptionAfterScroll(label = "Who owns this item?, mockOwnerName-2")
|
.onNodeWithContentDescriptionAfterScroll(
|
||||||
|
label = "mockOwnerName-2. Who owns this item?",
|
||||||
|
)
|
||||||
.assertIsDisplayed()
|
.assertIsDisplayed()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("MaxLineLength")
|
|
||||||
@Test
|
@Test
|
||||||
fun `clicking New Custom Field button should allow creation of Text type`() {
|
fun `clicking New Custom Field button should allow creation of Text type`() {
|
||||||
mutableStateFlow.value = DEFAULT_STATE_SECURE_NOTES
|
mutableStateFlow.value = DEFAULT_STATE_SECURE_NOTES
|
||||||
|
@ -2259,7 +2252,6 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("MaxLineLength")
|
|
||||||
@Test
|
@Test
|
||||||
fun `clicking New Custom Field button should not display linked type`() {
|
fun `clicking New Custom Field button should not display linked type`() {
|
||||||
mutableStateFlow.value = DEFAULT_STATE_SECURE_NOTES
|
mutableStateFlow.value = DEFAULT_STATE_SECURE_NOTES
|
||||||
|
@ -2278,7 +2270,6 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
.assertIsNotDisplayed()
|
.assertIsNotDisplayed()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("MaxLineLength")
|
|
||||||
@Test
|
@Test
|
||||||
fun `clicking New Custom Field button should allow creation of Boolean type`() {
|
fun `clicking New Custom Field button should allow creation of Boolean type`() {
|
||||||
mutableStateFlow.value = DEFAULT_STATE_SECURE_NOTES
|
mutableStateFlow.value = DEFAULT_STATE_SECURE_NOTES
|
||||||
|
@ -2352,7 +2343,6 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("MaxLineLength")
|
|
||||||
@Test
|
@Test
|
||||||
fun `clicking and changing the custom text field will send a CustomFieldValueChange event`() {
|
fun `clicking and changing the custom text field will send a CustomFieldValueChange event`() {
|
||||||
mutableStateFlow.value = DEFAULT_STATE_SECURE_NOTES_CUSTOM_FIELDS
|
mutableStateFlow.value = DEFAULT_STATE_SECURE_NOTES_CUSTOM_FIELDS
|
||||||
|
@ -2370,7 +2360,6 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("MaxLineLength")
|
|
||||||
@Test
|
@Test
|
||||||
fun `clicking and changing the custom hidden field will send a CustomFieldValueChange event`() {
|
fun `clicking and changing the custom hidden field will send a CustomFieldValueChange event`() {
|
||||||
mutableStateFlow.value = DEFAULT_STATE_SECURE_NOTES_CUSTOM_FIELDS
|
mutableStateFlow.value = DEFAULT_STATE_SECURE_NOTES_CUSTOM_FIELDS
|
||||||
|
@ -2406,7 +2395,6 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("MaxLineLength")
|
|
||||||
@Test
|
@Test
|
||||||
fun `clicking custom field edit icon and Edit option sends a CustomFieldValueChange action`() {
|
fun `clicking custom field edit icon and Edit option sends a CustomFieldValueChange action`() {
|
||||||
mutableStateFlow.value = DEFAULT_STATE_SECURE_NOTES_CUSTOM_FIELDS
|
mutableStateFlow.value = DEFAULT_STATE_SECURE_NOTES_CUSTOM_FIELDS
|
||||||
|
|
|
@ -103,7 +103,7 @@ class VaultMoveToOrganizationScreenTest : BaseComposeTest() {
|
||||||
@Test
|
@Test
|
||||||
fun `the organization option field should update according to state`() {
|
fun `the organization option field should update according to state`() {
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescription(label = "Organization, mockOrganizationName-1")
|
.onNodeWithContentDescription(label = "mockOrganizationName-1. Organization")
|
||||||
.assertIsDisplayed()
|
.assertIsDisplayed()
|
||||||
|
|
||||||
mutableStateFlow.update { currentState ->
|
mutableStateFlow.update { currentState ->
|
||||||
|
@ -111,7 +111,7 @@ class VaultMoveToOrganizationScreenTest : BaseComposeTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescription(label = "Organization, mockOrganizationName-1")
|
.onNodeWithContentDescription(label = "mockOrganizationName-1. Organization")
|
||||||
.assertIsNotDisplayed()
|
.assertIsNotDisplayed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ class VaultMoveToOrganizationScreenTest : BaseComposeTest() {
|
||||||
@Test
|
@Test
|
||||||
fun `selecting an organization should send OrganizationSelect action`() {
|
fun `selecting an organization should send OrganizationSelect action`() {
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescriptionAfterScroll(label = "Organization, mockOrganizationName-1")
|
.onNodeWithContentDescriptionAfterScroll(label = "mockOrganizationName-1. Organization")
|
||||||
.performClick()
|
.performClick()
|
||||||
// Choose the option from the menu
|
// Choose the option from the menu
|
||||||
composeTestRule
|
composeTestRule
|
||||||
|
@ -197,7 +197,7 @@ class VaultMoveToOrganizationScreenTest : BaseComposeTest() {
|
||||||
@Test
|
@Test
|
||||||
fun `the organization option field should display according to state`() {
|
fun `the organization option field should display according to state`() {
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescriptionAfterScroll(label = "Organization, mockOrganizationName-1")
|
.onNodeWithContentDescriptionAfterScroll(label = "mockOrganizationName-1. Organization")
|
||||||
.assertIsDisplayed()
|
.assertIsDisplayed()
|
||||||
|
|
||||||
mutableStateFlow.update { currentState ->
|
mutableStateFlow.update { currentState ->
|
||||||
|
@ -210,7 +210,7 @@ class VaultMoveToOrganizationScreenTest : BaseComposeTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithContentDescriptionAfterScroll(label = "Organization, mockOrganizationName-2")
|
.onNodeWithContentDescriptionAfterScroll(label = "mockOrganizationName-2. Organization")
|
||||||
.assertIsDisplayed()
|
.assertIsDisplayed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue