@@ -3520,6 +3520,236 @@ class VaultItemScreenTest : BitwardenComposeTest() {
35203520 }
35213521
35223522 // endregion bank account
3523+
3524+ // region drivers license
3525+
3526+ @Test
3527+ fun `in drivers license state, all fields should be displayed when populated` () {
3528+ mutableStateFlow.update { it.copy(viewState = DEFAULT_DRIVERS_LICENSE_VIEW_STATE ) }
3529+
3530+ composeTestRule.onNodeWithTextAfterScroll(" the first name" ).assertIsDisplayed()
3531+ composeTestRule.onNodeWithTextAfterScroll(" the middle name" ).assertIsDisplayed()
3532+ composeTestRule.onNodeWithTextAfterScroll(" the last name" ).assertIsDisplayed()
3533+ composeTestRule.onNodeWithTextAfterScroll(" the date of birth" ).assertIsDisplayed()
3534+ composeTestRule.onNodeWithTextAfterScroll(" the issuing country" ).assertIsDisplayed()
3535+ composeTestRule.onNodeWithTextAfterScroll(" the issuing state" ).assertIsDisplayed()
3536+ composeTestRule.onNodeWithTextAfterScroll(" the issuing authority" ).assertIsDisplayed()
3537+ composeTestRule.onNodeWithTextAfterScroll(" the issue date" ).assertIsDisplayed()
3538+ composeTestRule.onNodeWithTextAfterScroll(" the expiration date" ).assertIsDisplayed()
3539+ composeTestRule.onNodeWithTextAfterScroll(" the license class" ).assertIsDisplayed()
3540+ }
3541+
3542+ @Test
3543+ fun `in drivers license state, on copy first name click should send CopyFirstNameClick` () {
3544+ mutableStateFlow.update { it.copy(viewState = DEFAULT_DRIVERS_LICENSE_VIEW_STATE ) }
3545+ composeTestRule
3546+ .onNodeWithContentDescriptionAfterScroll(" Copy first name" )
3547+ .performClick()
3548+
3549+ verify(exactly = 1 ) {
3550+ viewModel.trySendAction(
3551+ VaultItemAction .ItemType .DriversLicense .CopyFirstNameClick ,
3552+ )
3553+ }
3554+ }
3555+
3556+ @Test
3557+ fun `in drivers license state, on copy middle name click should send CopyMiddleNameClick` () {
3558+ mutableStateFlow.update { it.copy(viewState = DEFAULT_DRIVERS_LICENSE_VIEW_STATE ) }
3559+ composeTestRule
3560+ .onNode(hasScrollToNodeAction())
3561+ .performScrollToNode(hasTestTag(" DriversLicenseCopyMiddleNameButton" ))
3562+ composeTestRule
3563+ .onNodeWithTag(" DriversLicenseCopyMiddleNameButton" )
3564+ .performSemanticsAction(SemanticsActions .OnClick )
3565+
3566+ verify(exactly = 1 ) {
3567+ viewModel.trySendAction(
3568+ VaultItemAction .ItemType .DriversLicense .CopyMiddleNameClick ,
3569+ )
3570+ }
3571+ }
3572+
3573+ @Test
3574+ fun `in drivers license state, on copy last name click should send CopyLastNameClick` () {
3575+ mutableStateFlow.update { it.copy(viewState = DEFAULT_DRIVERS_LICENSE_VIEW_STATE ) }
3576+ composeTestRule
3577+ .onNodeWithContentDescriptionAfterScroll(" Copy last name" )
3578+ .performClick()
3579+
3580+ verify(exactly = 1 ) {
3581+ viewModel.trySendAction(
3582+ VaultItemAction .ItemType .DriversLicense .CopyLastNameClick ,
3583+ )
3584+ }
3585+ }
3586+
3587+ @Suppress(" MaxLineLength" )
3588+ @Test
3589+ fun `in drivers license state, on copy license number click should send CopyLicenseNumberClick` () {
3590+ mutableStateFlow.update { it.copy(viewState = DEFAULT_DRIVERS_LICENSE_VIEW_STATE ) }
3591+ composeTestRule
3592+ .onNodeWithContentDescriptionAfterScroll(" Copy license number" )
3593+ .performClick()
3594+
3595+ verify(exactly = 1 ) {
3596+ viewModel.trySendAction(
3597+ VaultItemAction .ItemType .DriversLicense .CopyLicenseNumberClick ,
3598+ )
3599+ }
3600+ }
3601+
3602+ @Test
3603+ fun `in drivers license state, firstName should be displayed according to state` () {
3604+ val firstName = " the first name"
3605+ mutableStateFlow.update { it.copy(viewState = DEFAULT_DRIVERS_LICENSE_VIEW_STATE ) }
3606+ composeTestRule.onNodeWithTextAfterScroll(firstName).assertIsDisplayed()
3607+
3608+ mutableStateFlow.update { currentState ->
3609+ updateDriversLicenseType(currentState) { copy(firstName = null ) }
3610+ }
3611+
3612+ composeTestRule.assertScrollableNodeDoesNotExist(firstName)
3613+ }
3614+
3615+ @Test
3616+ fun `in drivers license state, middleName should be displayed according to state` () {
3617+ val middleName = " the middle name"
3618+ mutableStateFlow.update { it.copy(viewState = DEFAULT_DRIVERS_LICENSE_VIEW_STATE ) }
3619+ composeTestRule.onNodeWithTextAfterScroll(middleName).assertIsDisplayed()
3620+
3621+ mutableStateFlow.update { currentState ->
3622+ updateDriversLicenseType(currentState) { copy(middleName = null ) }
3623+ }
3624+
3625+ composeTestRule.assertScrollableNodeDoesNotExist(middleName)
3626+ }
3627+
3628+ @Test
3629+ fun `in drivers license state, lastName should be displayed according to state` () {
3630+ val lastName = " the last name"
3631+ mutableStateFlow.update { it.copy(viewState = DEFAULT_DRIVERS_LICENSE_VIEW_STATE ) }
3632+ composeTestRule.onNodeWithTextAfterScroll(lastName).assertIsDisplayed()
3633+
3634+ mutableStateFlow.update { currentState ->
3635+ updateDriversLicenseType(currentState) { copy(lastName = null ) }
3636+ }
3637+
3638+ composeTestRule.assertScrollableNodeDoesNotExist(lastName)
3639+ }
3640+
3641+ @Test
3642+ fun `in drivers license state, licenseNumber should be displayed according to state` () {
3643+ val licenseNumberLabel = " License number"
3644+ mutableStateFlow.update { it.copy(viewState = DEFAULT_DRIVERS_LICENSE_VIEW_STATE ) }
3645+ composeTestRule.onNodeWithTextAfterScroll(licenseNumberLabel).assertIsDisplayed()
3646+
3647+ mutableStateFlow.update { currentState ->
3648+ updateDriversLicenseType(currentState) { copy(licenseNumber = null ) }
3649+ }
3650+
3651+ composeTestRule.assertScrollableNodeDoesNotExist(licenseNumberLabel)
3652+ }
3653+
3654+ @Test
3655+ fun `in drivers license state, dateOfBirth should be displayed according to state` () {
3656+ val dateOfBirth = " the date of birth"
3657+ mutableStateFlow.update { it.copy(viewState = DEFAULT_DRIVERS_LICENSE_VIEW_STATE ) }
3658+ composeTestRule.onNodeWithTextAfterScroll(dateOfBirth).assertIsDisplayed()
3659+
3660+ mutableStateFlow.update { currentState ->
3661+ updateDriversLicenseType(currentState) { copy(dateOfBirth = null ) }
3662+ }
3663+
3664+ composeTestRule.assertScrollableNodeDoesNotExist(dateOfBirth)
3665+ }
3666+
3667+ @Test
3668+ fun `in drivers license state, issuingCountry should be displayed according to state` () {
3669+ val issuingCountry = " the issuing country"
3670+ mutableStateFlow.update { it.copy(viewState = DEFAULT_DRIVERS_LICENSE_VIEW_STATE ) }
3671+ composeTestRule.onNodeWithTextAfterScroll(issuingCountry).assertIsDisplayed()
3672+
3673+ mutableStateFlow.update { currentState ->
3674+ updateDriversLicenseType(currentState) { copy(issuingCountry = null ) }
3675+ }
3676+
3677+ composeTestRule.assertScrollableNodeDoesNotExist(issuingCountry)
3678+ }
3679+
3680+ @Test
3681+ fun `in drivers license state, issuingState should be displayed according to state` () {
3682+ val issuingState = " the issuing state"
3683+ mutableStateFlow.update { it.copy(viewState = DEFAULT_DRIVERS_LICENSE_VIEW_STATE ) }
3684+ composeTestRule.onNodeWithTextAfterScroll(issuingState).assertIsDisplayed()
3685+
3686+ mutableStateFlow.update { currentState ->
3687+ updateDriversLicenseType(currentState) { copy(issuingState = null ) }
3688+ }
3689+
3690+ composeTestRule.assertScrollableNodeDoesNotExist(issuingState)
3691+ }
3692+
3693+ @Test
3694+ fun `in drivers license state, issuingAuthority should be displayed according to state` () {
3695+ val issuingAuthority = " the issuing authority"
3696+ mutableStateFlow.update { it.copy(viewState = DEFAULT_DRIVERS_LICENSE_VIEW_STATE ) }
3697+ composeTestRule.onNodeWithTextAfterScroll(issuingAuthority).assertIsDisplayed()
3698+
3699+ mutableStateFlow.update { currentState ->
3700+ updateDriversLicenseType(currentState) { copy(issuingAuthority = null ) }
3701+ }
3702+
3703+ composeTestRule.assertScrollableNodeDoesNotExist(issuingAuthority)
3704+ }
3705+
3706+ @Test
3707+ fun `in drivers license state, issueDate should be displayed according to state` () {
3708+ val issueDate = " the issue date"
3709+ mutableStateFlow.update { it.copy(viewState = DEFAULT_DRIVERS_LICENSE_VIEW_STATE ) }
3710+ composeTestRule.onNodeWithTextAfterScroll(issueDate).assertIsDisplayed()
3711+
3712+ mutableStateFlow.update { currentState ->
3713+ updateDriversLicenseType(currentState) { copy(issueDate = null ) }
3714+ }
3715+
3716+ composeTestRule.assertScrollableNodeDoesNotExist(issueDate)
3717+ }
3718+
3719+ @Test
3720+ fun `in drivers license state, expirationDate should be displayed according to state` () {
3721+ val expirationDate = " the expiration date"
3722+ mutableStateFlow.update { it.copy(viewState = DEFAULT_DRIVERS_LICENSE_VIEW_STATE ) }
3723+ composeTestRule.onNodeWithTextAfterScroll(expirationDate).assertIsDisplayed()
3724+
3725+ mutableStateFlow.update { currentState ->
3726+ updateDriversLicenseType(currentState) { copy(expirationDate = null ) }
3727+ }
3728+
3729+ composeTestRule.assertScrollableNodeDoesNotExist(expirationDate)
3730+ }
3731+
3732+ @Test
3733+ fun `in drivers license state, licenseClass should be displayed according to state` () {
3734+ val licenseClass = " the license class"
3735+ mutableStateFlow.update { it.copy(viewState = DEFAULT_DRIVERS_LICENSE_VIEW_STATE ) }
3736+ composeTestRule.onNodeWithTextAfterScroll(licenseClass).assertIsDisplayed()
3737+
3738+ mutableStateFlow.update { currentState ->
3739+ updateDriversLicenseType(currentState) { copy(licenseClass = null ) }
3740+ }
3741+
3742+ composeTestRule.assertScrollableNodeDoesNotExist(licenseClass)
3743+ }
3744+
3745+ @Test
3746+ fun `in drivers license state, edit fab should be displayed` () {
3747+ mutableStateFlow.update { it.copy(viewState = DEFAULT_DRIVERS_LICENSE_VIEW_STATE ) }
3748+
3749+ composeTestRule.onNodeWithContentDescription(" Edit item" ).assertIsDisplayed()
3750+ }
3751+
3752+ // endregion drivers license
35233753}
35243754
35253755// region Helper functions
@@ -3616,6 +3846,29 @@ private fun updateBankAccountType(
36163846 return currentState.copy(viewState = updatedType)
36173847}
36183848
3849+ private fun updateDriversLicenseType (
3850+ currentState : VaultItemState ,
3851+ transform : VaultItemState .ViewState .Content .ItemType .DriversLicense .() ->
3852+ VaultItemState .ViewState .Content .ItemType .DriversLicense ,
3853+ ): VaultItemState {
3854+ val updatedType = when (val viewState = currentState.viewState) {
3855+ is VaultItemState .ViewState .Content -> {
3856+ when (val type = viewState.type) {
3857+ is VaultItemState .ViewState .Content .ItemType .DriversLicense -> {
3858+ viewState.copy(
3859+ type = type.transform(),
3860+ )
3861+ }
3862+
3863+ else -> viewState
3864+ }
3865+ }
3866+
3867+ else -> viewState
3868+ }
3869+ return currentState.copy(viewState = updatedType)
3870+ }
3871+
36193872private fun updateCommonContent (
36203873 currentState : VaultItemState ,
36213874 transform : VaultItemState .ViewState .Content .Common .()
@@ -3910,6 +4163,27 @@ private val DEFAULT_BANK_ACCOUNT_VIEW_STATE: VaultItemState.ViewState.Content =
39104163 type = DEFAULT_BANK_ACCOUNT ,
39114164 )
39124165
4166+ private val DEFAULT_DRIVERS_LICENSE : VaultItemState .ViewState .Content .ItemType .DriversLicense =
4167+ VaultItemState .ViewState .Content .ItemType .DriversLicense (
4168+ firstName = " the first name" ,
4169+ middleName = " the middle name" ,
4170+ lastName = " the last name" ,
4171+ licenseNumber = " the license number" ,
4172+ dateOfBirth = " the date of birth" ,
4173+ issuingCountry = " the issuing country" ,
4174+ issuingState = " the issuing state" ,
4175+ issuingAuthority = " the issuing authority" ,
4176+ issueDate = " the issue date" ,
4177+ expirationDate = " the expiration date" ,
4178+ licenseClass = " the license class" ,
4179+ )
4180+
4181+ private val DEFAULT_DRIVERS_LICENSE_VIEW_STATE : VaultItemState .ViewState .Content =
4182+ VaultItemState .ViewState .Content (
4183+ common = DEFAULT_COMMON .copy(iconData = IconData .Local (BitwardenDrawable .ic_globe)),
4184+ type = DEFAULT_DRIVERS_LICENSE ,
4185+ )
4186+
39134187private val EMPTY_VIEW_STATES = listOf (
39144188 EMPTY_LOGIN_VIEW_STATE ,
39154189 EMPTY_IDENTITY_VIEW_STATE ,
0 commit comments