mirror of
https://github.com/bitwarden/android.git
synced 2026-05-20 11:01:36 -05:00
[PM-32806] feat: Add Add/Edit support for Passport item type (#6923)
This commit is contained in:
@@ -38,6 +38,7 @@ import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditCommonH
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditIdentityTypeHandlers
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditLicenseTypeHandlers
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditLoginTypeHandlers
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditPassportTypeHandlers
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditSshKeyTypeHandlers
|
||||
|
||||
/**
|
||||
@@ -56,6 +57,7 @@ fun CoachMarkScope<AddEditItemCoachMark>.VaultAddEditContent(
|
||||
sshKeyItemTypeHandlers: VaultAddEditSshKeyTypeHandlers,
|
||||
bankAccountItemTypeHandlers: VaultAddEditBankAccountTypeHandlers,
|
||||
licenseItemTypeHandlers: VaultAddEditLicenseTypeHandlers,
|
||||
passportItemTypeHandlers: VaultAddEditPassportTypeHandlers,
|
||||
isCardScannerEnabled: Boolean,
|
||||
cardHolderNameFocusRequester: FocusRequester,
|
||||
modifier: Modifier = Modifier,
|
||||
@@ -296,7 +298,13 @@ fun CoachMarkScope<AddEditItemCoachMark>.VaultAddEditContent(
|
||||
licenseHandlers = licenseItemTypeHandlers,
|
||||
)
|
||||
}
|
||||
is VaultAddEditState.ViewState.Content.ItemType.Passport -> Unit
|
||||
|
||||
is VaultAddEditState.ViewState.Content.ItemType.Passport -> {
|
||||
vaultAddEditPassportItems(
|
||||
passportState = state.type,
|
||||
passportHandlers = passportItemTypeHandlers,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
vaultAddEditAdditionalOptions(
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
package com.x8bit.bitwarden.ui.vault.feature.addedit
|
||||
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.bitwarden.ui.platform.base.util.standardHorizontalMargin
|
||||
import com.bitwarden.ui.platform.components.button.BitwardenTextSelectionButton
|
||||
import com.bitwarden.ui.platform.components.field.BitwardenPasswordField
|
||||
import com.bitwarden.ui.platform.components.field.BitwardenTextField
|
||||
import com.bitwarden.ui.platform.components.header.BitwardenListHeaderText
|
||||
import com.bitwarden.ui.platform.components.model.CardStyle
|
||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditPassportTypeHandlers
|
||||
|
||||
/**
|
||||
* The UI for adding and editing a passport cipher.
|
||||
*/
|
||||
@Suppress("LongMethod")
|
||||
fun LazyListScope.vaultAddEditPassportItems(
|
||||
passportState: VaultAddEditState.ViewState.Content.ItemType.Passport,
|
||||
passportHandlers: VaultAddEditPassportTypeHandlers,
|
||||
) {
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
BitwardenListHeaderText(
|
||||
label = stringResource(id = BitwardenString.passport_details),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin()
|
||||
.padding(horizontal = 16.dp),
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
BitwardenTextField(
|
||||
label = stringResource(id = BitwardenString.first_name),
|
||||
value = passportState.givenName,
|
||||
onValueChange = passportHandlers.onGivenNameTextChange,
|
||||
textFieldTestTag = "PassportGivenNameEntry",
|
||||
cardStyle = CardStyle.Top(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
BitwardenTextField(
|
||||
label = stringResource(id = BitwardenString.last_name),
|
||||
value = passportState.surname,
|
||||
onValueChange = passportHandlers.onSurnameTextChange,
|
||||
textFieldTestTag = "PassportSurnameEntry",
|
||||
cardStyle = CardStyle.Middle(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
BitwardenTextSelectionButton(
|
||||
label = stringResource(id = BitwardenString.date_of_birth),
|
||||
selectedOption = passportState.dateOfBirth,
|
||||
// TODO: Open a native Material date picker (separate ticket TBD).
|
||||
onClick = {},
|
||||
textFieldTestTag = "PassportDateOfBirthEntry",
|
||||
cardStyle = CardStyle.Middle(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
BitwardenTextField(
|
||||
label = stringResource(id = BitwardenString.sex),
|
||||
value = passportState.sex,
|
||||
onValueChange = passportHandlers.onSexTextChange,
|
||||
textFieldTestTag = "PassportSexEntry",
|
||||
cardStyle = CardStyle.Middle(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
BitwardenTextField(
|
||||
label = stringResource(id = BitwardenString.birth_place),
|
||||
value = passportState.birthPlace,
|
||||
onValueChange = passportHandlers.onBirthPlaceTextChange,
|
||||
textFieldTestTag = "PassportBirthPlaceEntry",
|
||||
cardStyle = CardStyle.Middle(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
BitwardenTextField(
|
||||
label = stringResource(id = BitwardenString.nationality),
|
||||
value = passportState.nationality,
|
||||
onValueChange = passportHandlers.onNationalityTextChange,
|
||||
textFieldTestTag = "PassportNationalityEntry",
|
||||
cardStyle = CardStyle.Middle(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
BitwardenPasswordField(
|
||||
label = stringResource(id = BitwardenString.passport_number),
|
||||
value = passportState.passportNumber,
|
||||
onValueChange = passportHandlers.onPassportNumberTextChange,
|
||||
passwordFieldTestTag = "PassportPassportNumberEntry",
|
||||
showPasswordTestTag = "PassportShowPassportNumberButton",
|
||||
cardStyle = CardStyle.Middle(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
BitwardenTextField(
|
||||
label = stringResource(id = BitwardenString.passport_type),
|
||||
value = passportState.passportType,
|
||||
onValueChange = passportHandlers.onPassportTypeTextChange,
|
||||
textFieldTestTag = "PassportPassportTypeEntry",
|
||||
cardStyle = CardStyle.Middle(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
BitwardenPasswordField(
|
||||
label = stringResource(id = BitwardenString.national_identification_number),
|
||||
value = passportState.nationalIdentificationNumber,
|
||||
onValueChange = passportHandlers.onNationalIdentificationNumberTextChange,
|
||||
passwordFieldTestTag = "PassportNationalIdentificationNumberEntry",
|
||||
showPasswordTestTag = "PassportShowNationalIdentificationNumberButton",
|
||||
cardStyle = CardStyle.Middle(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
BitwardenTextField(
|
||||
label = stringResource(id = BitwardenString.issuing_country),
|
||||
value = passportState.issuingCountry,
|
||||
onValueChange = passportHandlers.onIssuingCountryTextChange,
|
||||
textFieldTestTag = "PassportIssuingCountryEntry",
|
||||
cardStyle = CardStyle.Middle(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
BitwardenTextField(
|
||||
label = stringResource(id = BitwardenString.issuing_authority),
|
||||
value = passportState.issuingAuthority,
|
||||
onValueChange = passportHandlers.onIssuingAuthorityTextChange,
|
||||
textFieldTestTag = "PassportIssuingAuthorityEntry",
|
||||
cardStyle = CardStyle.Middle(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
BitwardenTextSelectionButton(
|
||||
label = stringResource(id = BitwardenString.issue_date),
|
||||
selectedOption = passportState.issueDate,
|
||||
// TODO: Open a native Material date picker (separate ticket TBD).
|
||||
onClick = {},
|
||||
textFieldTestTag = "PassportIssueDateEntry",
|
||||
cardStyle = CardStyle.Middle(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
BitwardenTextSelectionButton(
|
||||
label = stringResource(id = BitwardenString.expiration_date),
|
||||
selectedOption = passportState.expirationDate,
|
||||
// TODO: Open a native Material date picker (separate ticket TBD).
|
||||
onClick = {},
|
||||
textFieldTestTag = "PassportExpirationDateEntry",
|
||||
cardStyle = CardStyle.Bottom,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -87,6 +87,7 @@ import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditCardTyp
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditCommonHandlers
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditIdentityTypeHandlers
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditLicenseTypeHandlers
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.rememberVaultAddEditPassportTypeHandlers
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditLoginTypeHandlers
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditSshKeyTypeHandlers
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditUserVerificationHandlers
|
||||
@@ -246,6 +247,8 @@ fun VaultAddEditScreen(
|
||||
VaultAddEditLicenseTypeHandlers.create(viewModel = viewModel)
|
||||
}
|
||||
|
||||
val passportItemTypeHandlers = rememberVaultAddEditPassportTypeHandlers(viewModel = viewModel)
|
||||
|
||||
val archiveClickAction = { viewModel.trySendAction(VaultAddEditAction.Common.ArchiveClick) }
|
||||
|
||||
val unarchiveClickAction = { viewModel.trySendAction(VaultAddEditAction.Common.UnarchiveClick) }
|
||||
@@ -429,6 +432,7 @@ fun VaultAddEditScreen(
|
||||
sshKeyItemTypeHandlers = sshKeyItemTypeHandlers,
|
||||
bankAccountItemTypeHandlers = bankAccountItemTypeHandlers,
|
||||
licenseItemTypeHandlers = licenseItemTypeHandlers,
|
||||
passportItemTypeHandlers = passportItemTypeHandlers,
|
||||
isCardScannerEnabled = state.isCardScannerEnabled,
|
||||
cardHolderNameFocusRequester = cardHolderNameFocusRequester,
|
||||
lazyListState = lazyListState,
|
||||
|
||||
@@ -318,6 +318,10 @@ class VaultAddEditViewModel @Inject constructor(
|
||||
handleLicenseTypeActions(action)
|
||||
}
|
||||
|
||||
is VaultAddEditAction.ItemType.PassportType -> {
|
||||
handlePassportTypeActions(action)
|
||||
}
|
||||
|
||||
is VaultAddEditAction.Internal -> handleInternalActions(action)
|
||||
}
|
||||
}
|
||||
@@ -1793,6 +1797,59 @@ class VaultAddEditViewModel @Inject constructor(
|
||||
|
||||
//endregion License Type Handlers
|
||||
|
||||
//region Passport Type Handlers
|
||||
|
||||
@Suppress("LongMethod")
|
||||
private fun handlePassportTypeActions(
|
||||
action: VaultAddEditAction.ItemType.PassportType,
|
||||
) {
|
||||
when (action) {
|
||||
is VaultAddEditAction.ItemType.PassportType.GivenNameTextChange -> {
|
||||
updatePassportContent { it.copy(givenName = action.givenName) }
|
||||
}
|
||||
|
||||
is VaultAddEditAction.ItemType.PassportType.SurnameTextChange -> {
|
||||
updatePassportContent { it.copy(surname = action.surname) }
|
||||
}
|
||||
|
||||
is VaultAddEditAction.ItemType.PassportType.SexTextChange -> {
|
||||
updatePassportContent { it.copy(sex = action.sex) }
|
||||
}
|
||||
|
||||
is VaultAddEditAction.ItemType.PassportType.BirthPlaceTextChange -> {
|
||||
updatePassportContent { it.copy(birthPlace = action.birthPlace) }
|
||||
}
|
||||
|
||||
is VaultAddEditAction.ItemType.PassportType.NationalityTextChange -> {
|
||||
updatePassportContent { it.copy(nationality = action.nationality) }
|
||||
}
|
||||
|
||||
is VaultAddEditAction.ItemType.PassportType.PassportNumberTextChange -> {
|
||||
updatePassportContent { it.copy(passportNumber = action.passportNumber) }
|
||||
}
|
||||
|
||||
is VaultAddEditAction.ItemType.PassportType.PassportTypeTextChange -> {
|
||||
updatePassportContent { it.copy(passportType = action.passportType) }
|
||||
}
|
||||
|
||||
is VaultAddEditAction.ItemType.PassportType.NationalIdentificationNumberTextChange -> {
|
||||
updatePassportContent {
|
||||
it.copy(nationalIdentificationNumber = action.nationalIdentificationNumber)
|
||||
}
|
||||
}
|
||||
|
||||
is VaultAddEditAction.ItemType.PassportType.IssuingCountryTextChange -> {
|
||||
updatePassportContent { it.copy(issuingCountry = action.country) }
|
||||
}
|
||||
|
||||
is VaultAddEditAction.ItemType.PassportType.IssuingAuthorityTextChange -> {
|
||||
updatePassportContent { it.copy(issuingAuthority = action.authority) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//endregion Passport Type Handlers
|
||||
|
||||
//region Internal Type Handlers
|
||||
|
||||
private fun handleInternalActions(action: VaultAddEditAction.Internal) {
|
||||
@@ -2570,6 +2627,16 @@ class VaultAddEditViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun updatePassportContent(
|
||||
crossinline block: (VaultAddEditState.ViewState.Content.ItemType.Passport) ->
|
||||
VaultAddEditState.ViewState.Content.ItemType.Passport,
|
||||
) {
|
||||
updateContent { currentContent ->
|
||||
(currentContent.type as? VaultAddEditState.ViewState.Content.ItemType.Passport)
|
||||
?.let { currentContent.copy(type = block(it)) }
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
private suspend fun VaultAddEditState.ViewState.Content.createCipherForAddAndCloneItemStates(): CreateCipherResult {
|
||||
return common.selectedOwner?.collections
|
||||
@@ -3154,8 +3221,6 @@ data class VaultAddEditState(
|
||||
override val itemTypeOption: ItemTypeOption
|
||||
get() = ItemTypeOption.PASSPORT
|
||||
|
||||
override val isSdkSupported: Boolean get() = false
|
||||
|
||||
override val vaultLinkedFieldTypes: ImmutableList<VaultLinkedFieldType>
|
||||
get() = persistentListOf()
|
||||
}
|
||||
@@ -4140,6 +4205,64 @@ sealed class VaultAddEditAction {
|
||||
data class BankContactPhoneTextChange(val phone: String) : BankAccountType()
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents actions specific to the Passport type.
|
||||
*/
|
||||
sealed class PassportType : ItemType() {
|
||||
|
||||
/**
|
||||
* Fired when the given name text input is changed.
|
||||
*/
|
||||
data class GivenNameTextChange(val givenName: String) : PassportType()
|
||||
|
||||
/**
|
||||
* Fired when the surname text input is changed.
|
||||
*/
|
||||
data class SurnameTextChange(val surname: String) : PassportType()
|
||||
|
||||
/**
|
||||
* Fired when the sex text input is changed.
|
||||
*/
|
||||
data class SexTextChange(val sex: String) : PassportType()
|
||||
|
||||
/**
|
||||
* Fired when the birth place text input is changed.
|
||||
*/
|
||||
data class BirthPlaceTextChange(val birthPlace: String) : PassportType()
|
||||
|
||||
/**
|
||||
* Fired when the nationality text input is changed.
|
||||
*/
|
||||
data class NationalityTextChange(val nationality: String) : PassportType()
|
||||
|
||||
/**
|
||||
* Fired when the passport number text input is changed.
|
||||
*/
|
||||
data class PassportNumberTextChange(val passportNumber: String) : PassportType()
|
||||
|
||||
/**
|
||||
* Fired when the passport type text input is changed.
|
||||
*/
|
||||
data class PassportTypeTextChange(val passportType: String) : PassportType()
|
||||
|
||||
/**
|
||||
* Fired when the national identification number text input is changed.
|
||||
*/
|
||||
data class NationalIdentificationNumberTextChange(
|
||||
val nationalIdentificationNumber: String,
|
||||
) : PassportType()
|
||||
|
||||
/**
|
||||
* Fired when the issuing country text input is changed.
|
||||
*/
|
||||
data class IssuingCountryTextChange(val country: String) : PassportType()
|
||||
|
||||
/**
|
||||
* Fired when the issuing authority text input is changed.
|
||||
*/
|
||||
data class IssuingAuthorityTextChange(val authority: String) : PassportType()
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents actions specific to the License type.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
package com.x8bit.bitwarden.ui.vault.feature.addedit.handlers
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.VaultAddEditAction
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.VaultAddEditViewModel
|
||||
|
||||
/**
|
||||
* A collection of handler functions for managing user interactions on the Passport portion of the
|
||||
* Add/Edit cipher screen.
|
||||
*
|
||||
* @property onGivenNameTextChange Handles changes to the given name (first name) text input.
|
||||
* @property onSurnameTextChange Handles changes to the surname (last name) text input.
|
||||
* @property onSexTextChange Handles changes to the sex text input.
|
||||
* @property onBirthPlaceTextChange Handles changes to the birth place text input.
|
||||
* @property onNationalityTextChange Handles changes to the nationality text input.
|
||||
* @property onPassportNumberTextChange Handles changes to the passport number text input.
|
||||
* @property onPassportTypeTextChange Handles changes to the passport type text input.
|
||||
* @property onNationalIdentificationNumberTextChange Handles changes to the national identification
|
||||
* number text input.
|
||||
* @property onIssuingCountryTextChange Handles changes to the issuing country text input.
|
||||
* @property onIssuingAuthorityTextChange Handles changes to the issuing authority text input.
|
||||
*/
|
||||
@Suppress("LongParameterList")
|
||||
data class VaultAddEditPassportTypeHandlers(
|
||||
val onGivenNameTextChange: (String) -> Unit,
|
||||
val onSurnameTextChange: (String) -> Unit,
|
||||
val onSexTextChange: (String) -> Unit,
|
||||
val onBirthPlaceTextChange: (String) -> Unit,
|
||||
val onNationalityTextChange: (String) -> Unit,
|
||||
val onPassportNumberTextChange: (String) -> Unit,
|
||||
val onPassportTypeTextChange: (String) -> Unit,
|
||||
val onNationalIdentificationNumberTextChange: (String) -> Unit,
|
||||
val onIssuingCountryTextChange: (String) -> Unit,
|
||||
val onIssuingAuthorityTextChange: (String) -> Unit,
|
||||
) {
|
||||
@Suppress("UndocumentedPublicClass")
|
||||
companion object {
|
||||
|
||||
/**
|
||||
* Creates an instance of [VaultAddEditPassportTypeHandlers] by binding actions to
|
||||
* the provided [VaultAddEditViewModel].
|
||||
*/
|
||||
@Suppress("LongMethod")
|
||||
fun create(
|
||||
viewModel: VaultAddEditViewModel,
|
||||
): VaultAddEditPassportTypeHandlers =
|
||||
VaultAddEditPassportTypeHandlers(
|
||||
onGivenNameTextChange = {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.PassportType.GivenNameTextChange(
|
||||
givenName = it,
|
||||
),
|
||||
)
|
||||
},
|
||||
onSurnameTextChange = {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.PassportType.SurnameTextChange(
|
||||
surname = it,
|
||||
),
|
||||
)
|
||||
},
|
||||
onSexTextChange = {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.PassportType.SexTextChange(sex = it),
|
||||
)
|
||||
},
|
||||
onBirthPlaceTextChange = {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.PassportType.BirthPlaceTextChange(
|
||||
birthPlace = it,
|
||||
),
|
||||
)
|
||||
},
|
||||
onNationalityTextChange = {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.PassportType.NationalityTextChange(
|
||||
nationality = it,
|
||||
),
|
||||
)
|
||||
},
|
||||
onPassportNumberTextChange = {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.PassportType.PassportNumberTextChange(
|
||||
passportNumber = it,
|
||||
),
|
||||
)
|
||||
},
|
||||
onPassportTypeTextChange = {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.PassportType.PassportTypeTextChange(
|
||||
passportType = it,
|
||||
),
|
||||
)
|
||||
},
|
||||
onNationalIdentificationNumberTextChange = {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction
|
||||
.ItemType
|
||||
.PassportType
|
||||
.NationalIdentificationNumberTextChange(
|
||||
nationalIdentificationNumber = it,
|
||||
),
|
||||
)
|
||||
},
|
||||
onIssuingCountryTextChange = {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.PassportType.IssuingCountryTextChange(
|
||||
country = it,
|
||||
),
|
||||
)
|
||||
},
|
||||
onIssuingAuthorityTextChange = {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.PassportType.IssuingAuthorityTextChange(
|
||||
authority = it,
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to remember a [VaultAddEditPassportTypeHandlers] instance in a [Composable]
|
||||
* scope.
|
||||
*/
|
||||
@Composable
|
||||
fun rememberVaultAddEditPassportTypeHandlers(
|
||||
viewModel: VaultAddEditViewModel,
|
||||
): VaultAddEditPassportTypeHandlers =
|
||||
remember(viewModel) {
|
||||
VaultAddEditPassportTypeHandlers.create(viewModel = viewModel)
|
||||
}
|
||||
@@ -88,9 +88,10 @@ private fun VaultAddEditState.ViewState.Content.ItemType.toCipherType(): CipherT
|
||||
is VaultAddEditState.ViewState.Content.ItemType.SecureNotes -> CipherType.SECURE_NOTE
|
||||
is VaultAddEditState.ViewState.Content.ItemType.SshKey -> CipherType.SSH_KEY
|
||||
is VaultAddEditState.ViewState.Content.ItemType.BankAccount -> CipherType.BANK_ACCOUNT
|
||||
is VaultAddEditState.ViewState.Content.ItemType.License,
|
||||
is VaultAddEditState.ViewState.Content.ItemType.Passport,
|
||||
-> throw IllegalArgumentException("SDK mapping not yet available for $this")
|
||||
is VaultAddEditState.ViewState.Content.ItemType.Passport -> CipherType.PASSPORT
|
||||
is VaultAddEditState.ViewState.Content.ItemType.License -> {
|
||||
throw IllegalArgumentException("SDK mapping not yet available for $this")
|
||||
}
|
||||
}
|
||||
|
||||
private fun VaultAddEditState.ViewState.Content.ItemType.toSshKeyView(): SshKeyView? =
|
||||
|
||||
@@ -2911,6 +2911,171 @@ class VaultAddEditScreenTest : BitwardenComposeTest() {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `in ItemType_Passport changing first name should trigger GivenNameTextChange`() {
|
||||
mutableStateFlow.value = DEFAULT_STATE_PASSPORT
|
||||
composeTestRule
|
||||
.onNodeWithTextAfterScroll(text = "First name")
|
||||
.performTextInput(text = "Bruce")
|
||||
|
||||
verify {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.PassportType.GivenNameTextChange(
|
||||
givenName = "Bruce",
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `in ItemType_Passport changing last name should trigger SurnameTextChange`() {
|
||||
mutableStateFlow.value = DEFAULT_STATE_PASSPORT
|
||||
composeTestRule
|
||||
.onNodeWithTextAfterScroll(text = "Last name")
|
||||
.performTextInput(text = "Wayne")
|
||||
|
||||
verify {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.PassportType.SurnameTextChange(
|
||||
surname = "Wayne",
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `in ItemType_Passport changing sex should trigger SexTextChange`() {
|
||||
mutableStateFlow.value = DEFAULT_STATE_PASSPORT
|
||||
composeTestRule
|
||||
.onNodeWithTextAfterScroll(text = "Sex")
|
||||
.performTextInput(text = "M")
|
||||
|
||||
verify {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.PassportType.SexTextChange(sex = "M"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `in ItemType_Passport changing birth place should trigger BirthPlaceTextChange`() {
|
||||
mutableStateFlow.value = DEFAULT_STATE_PASSPORT
|
||||
composeTestRule
|
||||
.onNodeWithTextAfterScroll(text = "Birth place")
|
||||
.performTextInput(text = "Gotham City")
|
||||
|
||||
verify {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.PassportType.BirthPlaceTextChange(
|
||||
birthPlace = "Gotham City",
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `in ItemType_Passport changing nationality should trigger NationalityTextChange`() {
|
||||
mutableStateFlow.value = DEFAULT_STATE_PASSPORT
|
||||
composeTestRule
|
||||
.onNodeWithTextAfterScroll(text = "Nationality")
|
||||
.performTextInput(text = "American")
|
||||
|
||||
verify {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.PassportType.NationalityTextChange(
|
||||
nationality = "American",
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `in ItemType_Passport changing the passport number text field should trigger PassportNumberTextChange`() {
|
||||
mutableStateFlow.value = DEFAULT_STATE_PASSPORT
|
||||
composeTestRule
|
||||
.onNodeWithTextAfterScroll(text = "Passport number")
|
||||
.performTextInput(text = "X12345678")
|
||||
|
||||
verify {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.PassportType.PassportNumberTextChange(
|
||||
passportNumber = "X12345678",
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `in ItemType_Passport changing passport type should trigger PassportTypeTextChange`() {
|
||||
mutableStateFlow.value = DEFAULT_STATE_PASSPORT
|
||||
composeTestRule
|
||||
.onNodeWithTextAfterScroll(text = "Passport type")
|
||||
.performTextInput(text = "Regular")
|
||||
|
||||
verify {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.PassportType.PassportTypeTextChange(
|
||||
passportType = "Regular",
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `in ItemType_Passport changing the national identification number text field should trigger NationalIdentificationNumberTextChange`() {
|
||||
mutableStateFlow.value = DEFAULT_STATE_PASSPORT
|
||||
composeTestRule
|
||||
.onNodeWithTextAfterScroll(text = "National identification number")
|
||||
.performTextInput(text = "987-65-4321")
|
||||
|
||||
verify {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction
|
||||
.ItemType
|
||||
.PassportType
|
||||
.NationalIdentificationNumberTextChange(
|
||||
nationalIdentificationNumber = "987-65-4321",
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `in ItemType_Passport changing the issuing country text field should trigger IssuingCountryTextChange`() {
|
||||
mutableStateFlow.value = DEFAULT_STATE_PASSPORT
|
||||
composeTestRule
|
||||
.onNodeWithTextAfterScroll(text = "Issuing country")
|
||||
.performTextInput(text = "USA")
|
||||
|
||||
verify {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.PassportType.IssuingCountryTextChange(
|
||||
country = "USA",
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `in ItemType_Passport changing the issuing authority text field should trigger IssuingAuthorityTextChange`() {
|
||||
mutableStateFlow.value = DEFAULT_STATE_PASSPORT
|
||||
composeTestRule
|
||||
.onNodeWithTextAfterScroll(text = "Issuing authority")
|
||||
.performTextInput(text = "U.S. Department of State")
|
||||
|
||||
verify {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.PassportType.IssuingAuthorityTextChange(
|
||||
authority = "U.S. Department of State",
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `clicking Add field button should allow creation of Linked type`() {
|
||||
mutableStateFlow.value = DEFAULT_STATE_LOGIN
|
||||
@@ -5037,6 +5202,22 @@ class VaultAddEditScreenTest : BitwardenComposeTest() {
|
||||
isCardScannerEnabled = false,
|
||||
)
|
||||
|
||||
private val DEFAULT_STATE_PASSPORT = VaultAddEditState(
|
||||
vaultAddEditType = VaultAddEditType.AddItem,
|
||||
cipherType = VaultItemCipherType.PASSPORT,
|
||||
viewState = VaultAddEditState.ViewState.Content(
|
||||
common = VaultAddEditState.ViewState.Content.Common(),
|
||||
type = VaultAddEditState.ViewState.Content.ItemType.Passport(),
|
||||
isIndividualVaultDisabled = false,
|
||||
),
|
||||
dialog = null,
|
||||
bottomSheetState = null,
|
||||
shouldShowCoachMarkTour = false,
|
||||
defaultUriMatchType = UriMatchTypeModel.EXACT,
|
||||
hasPremium = false,
|
||||
isCardScannerEnabled = false,
|
||||
)
|
||||
|
||||
private val DEFAULT_STATE_SECURE_NOTES_CUSTOM_FIELDS = VaultAddEditState(
|
||||
viewState = VaultAddEditState.ViewState.Content(
|
||||
common = VaultAddEditState.ViewState.Content.Common(
|
||||
|
||||
@@ -2444,14 +2444,21 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `in add mode, SaveClick with a Passport item should emit ShowSnackbar without saving`() =
|
||||
fun `in add mode, SaveClick with a Passport item should not short-circuit and should run validation`() =
|
||||
runTest {
|
||||
mutableVaultDataFlow.value = DataState.Loaded(createVaultData())
|
||||
val passportState = createVaultAddItemState(
|
||||
vaultItemCipherType = VaultItemCipherType.PASSPORT,
|
||||
commonContentViewState = createCommonContentViewState(name = "mockName-1"),
|
||||
commonContentViewState = createCommonContentViewState(name = ""),
|
||||
typeContentViewState = VaultAddEditState.ViewState.Content.ItemType.Passport(),
|
||||
)
|
||||
val expectedValidationDialogState = passportState.copy(
|
||||
dialog = VaultAddEditState.DialogState.Generic(
|
||||
title = BitwardenString.an_error_has_occurred.asText(),
|
||||
message = BitwardenString.validation_field_required
|
||||
.asText(BitwardenString.name.asText()),
|
||||
),
|
||||
)
|
||||
val viewModel = createAddVaultItemViewModel(
|
||||
createSavedStateHandleWithState(
|
||||
state = passportState,
|
||||
@@ -2460,19 +2467,11 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
||||
),
|
||||
)
|
||||
|
||||
viewModel.eventFlow.test {
|
||||
viewModel.stateEventFlow(backgroundScope) { stateFlow, eventFlow ->
|
||||
viewModel.trySendAction(VaultAddEditAction.Common.SaveClick)
|
||||
assertEquals(
|
||||
VaultAddEditEvent.ShowSnackbar(
|
||||
message = BitwardenString.an_error_has_occurred.asText(),
|
||||
),
|
||||
awaitItem(),
|
||||
)
|
||||
}
|
||||
assertEquals(passportState, viewModel.stateFlow.value)
|
||||
coVerify(exactly = 0) {
|
||||
vaultRepository.createCipher(any())
|
||||
vaultRepository.createCipherInOrganization(any(), any())
|
||||
assertEquals(passportState, stateFlow.awaitItem())
|
||||
assertEquals(expectedValidationDialogState, stateFlow.awaitItem())
|
||||
eventFlow.expectNoEvents()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2533,13 +2532,13 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ItemType Passport should expose PASSPORT itemTypeOption and not be SDK supported`() {
|
||||
fun `ItemType Passport should expose PASSPORT itemTypeOption and be SDK supported`() {
|
||||
val itemType = VaultAddEditState.ViewState.Content.ItemType.Passport()
|
||||
assertEquals(
|
||||
VaultAddEditState.ItemTypeOption.PASSPORT,
|
||||
itemType.itemTypeOption,
|
||||
)
|
||||
assertFalse(itemType.isSdkSupported)
|
||||
assertTrue(itemType.isSdkSupported)
|
||||
assertTrue(itemType.vaultLinkedFieldTypes.isEmpty())
|
||||
}
|
||||
|
||||
@@ -4340,6 +4339,188 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class VaultAddEditPassportTypeItemActions {
|
||||
private lateinit var viewModel: VaultAddEditViewModel
|
||||
private lateinit var vaultAddItemInitialState: VaultAddEditState
|
||||
private lateinit var passportInitialSavedStateHandle: SavedStateHandle
|
||||
|
||||
@BeforeEach
|
||||
fun setup() {
|
||||
mutableVaultDataFlow.value = DataState.Loaded(
|
||||
createVaultData(cipherListView = createMockCipherListView(1)),
|
||||
)
|
||||
vaultAddItemInitialState = createVaultAddItemState(
|
||||
vaultItemCipherType = VaultItemCipherType.PASSPORT,
|
||||
typeContentViewState =
|
||||
VaultAddEditState.ViewState.Content.ItemType.Passport(),
|
||||
)
|
||||
passportInitialSavedStateHandle = createSavedStateHandleWithState(
|
||||
state = vaultAddItemInitialState,
|
||||
vaultAddEditType = VaultAddEditType.AddItem,
|
||||
vaultItemCipherType = VaultItemCipherType.PASSPORT,
|
||||
)
|
||||
viewModel = createAddVaultItemViewModel(
|
||||
savedStateHandle = passportInitialSavedStateHandle,
|
||||
)
|
||||
}
|
||||
|
||||
private fun expectedPassport(
|
||||
block: VaultAddEditState.ViewState.Content.ItemType.Passport.() ->
|
||||
VaultAddEditState.ViewState.Content.ItemType.Passport,
|
||||
): VaultAddEditState =
|
||||
createVaultAddItemState(
|
||||
vaultItemCipherType = VaultItemCipherType.PASSPORT,
|
||||
typeContentViewState = VaultAddEditState
|
||||
.ViewState
|
||||
.Content
|
||||
.ItemType
|
||||
.Passport()
|
||||
.block(),
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `GivenNameTextChange should update given name`() = runTest {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.PassportType.GivenNameTextChange(
|
||||
givenName = "Bruce",
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
expectedPassport { copy(givenName = "Bruce") },
|
||||
viewModel.stateFlow.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `SurnameTextChange should update surname`() = runTest {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.PassportType.SurnameTextChange(
|
||||
surname = "Wayne",
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
expectedPassport { copy(surname = "Wayne") },
|
||||
viewModel.stateFlow.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `SexTextChange should update sex`() = runTest {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.PassportType.SexTextChange(sex = "M"),
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
expectedPassport { copy(sex = "M") },
|
||||
viewModel.stateFlow.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `BirthPlaceTextChange should update birth place`() = runTest {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.PassportType.BirthPlaceTextChange(
|
||||
birthPlace = "Gotham City",
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
expectedPassport { copy(birthPlace = "Gotham City") },
|
||||
viewModel.stateFlow.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `NationalityTextChange should update nationality`() = runTest {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.PassportType.NationalityTextChange(
|
||||
nationality = "American",
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
expectedPassport { copy(nationality = "American") },
|
||||
viewModel.stateFlow.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `PassportNumberTextChange should update passport number`() = runTest {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.PassportType.PassportNumberTextChange(
|
||||
passportNumber = "X12345678",
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
expectedPassport { copy(passportNumber = "X12345678") },
|
||||
viewModel.stateFlow.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `PassportTypeTextChange should update passport type`() = runTest {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.PassportType.PassportTypeTextChange(
|
||||
passportType = "Regular",
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
expectedPassport { copy(passportType = "Regular") },
|
||||
viewModel.stateFlow.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `NationalIdentificationNumberTextChange should update national id number`() = runTest {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction
|
||||
.ItemType
|
||||
.PassportType
|
||||
.NationalIdentificationNumberTextChange(
|
||||
nationalIdentificationNumber = "987-65-4321",
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
expectedPassport { copy(nationalIdentificationNumber = "987-65-4321") },
|
||||
viewModel.stateFlow.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `IssuingCountryTextChange should update issuing country`() = runTest {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.PassportType.IssuingCountryTextChange(
|
||||
country = "USA",
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
expectedPassport { copy(issuingCountry = "USA") },
|
||||
viewModel.stateFlow.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `IssuingAuthorityTextChange should update issuing authority`() = runTest {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.PassportType.IssuingAuthorityTextChange(
|
||||
authority = "U.S. Department of State",
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
expectedPassport { copy(issuingAuthority = "U.S. Department of State") },
|
||||
viewModel.stateFlow.value,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `NumberVisibilityChange should log an event when in edit mode and password is visible`() =
|
||||
runTest {
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.bitwarden.vault.FieldView
|
||||
import com.bitwarden.vault.IdentityView
|
||||
import com.bitwarden.vault.LoginUriView
|
||||
import com.bitwarden.vault.LoginView
|
||||
import com.bitwarden.vault.PassportView
|
||||
import com.bitwarden.vault.PasswordHistoryView
|
||||
import com.bitwarden.vault.SecureNoteType
|
||||
import com.bitwarden.vault.SecureNoteView
|
||||
@@ -554,6 +555,89 @@ class VaultAddItemStateExtensionsTest {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `toCipherView should transform Passport ItemType to CipherView`() {
|
||||
val viewState = VaultAddEditState.ViewState.Content(
|
||||
common = VaultAddEditState.ViewState.Content.Common(
|
||||
name = "mockName-1",
|
||||
selectedFolderId = "mockId-1",
|
||||
favorite = false,
|
||||
masterPasswordReprompt = false,
|
||||
notes = "mockNotes-1",
|
||||
selectedOwnerId = "mockOwnerId-1",
|
||||
),
|
||||
isIndividualVaultDisabled = false,
|
||||
type = VaultAddEditState.ViewState.Content.ItemType.Passport(
|
||||
givenName = "Bruce",
|
||||
surname = "Wayne",
|
||||
dateOfBirth = "1939-05-27",
|
||||
sex = "M",
|
||||
birthPlace = "Gotham City",
|
||||
nationality = "American",
|
||||
passportNumber = "X12345678",
|
||||
passportType = "Regular",
|
||||
nationalIdentificationNumber = "987-65-4321",
|
||||
issuingCountry = "USA",
|
||||
issuingAuthority = "U.S. Department of State",
|
||||
issueDate = "2020-01-15",
|
||||
expirationDate = "2030-01-15",
|
||||
),
|
||||
)
|
||||
|
||||
val result = viewState.toCipherView(clock = FIXED_CLOCK, isPremiumUser = true)
|
||||
|
||||
assertEquals(
|
||||
CipherView(
|
||||
id = null,
|
||||
organizationId = "mockOwnerId-1",
|
||||
folderId = "mockId-1",
|
||||
collectionIds = emptyList(),
|
||||
key = null,
|
||||
name = "mockName-1",
|
||||
notes = "mockNotes-1",
|
||||
type = CipherType.PASSPORT,
|
||||
login = null,
|
||||
identity = null,
|
||||
card = null,
|
||||
secureNote = null,
|
||||
bankAccount = null,
|
||||
driversLicense = null,
|
||||
passport = PassportView(
|
||||
surname = "Wayne",
|
||||
givenName = "Bruce",
|
||||
dateOfBirth = "1939-05-27",
|
||||
birthPlace = "Gotham City",
|
||||
sex = "M",
|
||||
nationality = "American",
|
||||
passportNumber = "X12345678",
|
||||
passportType = "Regular",
|
||||
issuingCountry = "USA",
|
||||
issuingAuthority = "U.S. Department of State",
|
||||
issueDate = "2020-01-15",
|
||||
expirationDate = "2030-01-15",
|
||||
nationalIdentificationNumber = "987-65-4321",
|
||||
),
|
||||
favorite = false,
|
||||
reprompt = CipherRepromptType.NONE,
|
||||
organizationUseTotp = false,
|
||||
edit = true,
|
||||
viewPassword = true,
|
||||
localData = null,
|
||||
attachments = null,
|
||||
fields = emptyList(),
|
||||
passwordHistory = null,
|
||||
permissions = null,
|
||||
creationDate = FIXED_CLOCK.instant(),
|
||||
deletedDate = null,
|
||||
revisionDate = FIXED_CLOCK.instant(),
|
||||
archivedDate = null,
|
||||
sshKey = null,
|
||||
attachmentDecryptionFailures = null,
|
||||
),
|
||||
result,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `toCipherView should transform Card ItemType to CipherView`() {
|
||||
val viewState = VaultAddEditState.ViewState.Content(
|
||||
|
||||
Reference in New Issue
Block a user