Split up VaultDataExtensions(Test) files (#458)

This commit is contained in:
Brian Yencho 2023-12-29 14:33:12 -06:00 committed by Álison Fernandes
parent ab03c83cb3
commit 3142a640ce
4 changed files with 832 additions and 822 deletions

View file

@ -0,0 +1,176 @@
package com.x8bit.bitwarden.ui.vault.feature.vault.util
import com.bitwarden.core.CardView
import com.bitwarden.core.CipherRepromptType
import com.bitwarden.core.CipherType
import com.bitwarden.core.CipherView
import com.bitwarden.core.FieldType
import com.bitwarden.core.FieldView
import com.bitwarden.core.IdentityView
import com.bitwarden.core.LoginUriView
import com.bitwarden.core.LoginView
import com.bitwarden.core.SecureNoteType
import com.bitwarden.core.SecureNoteView
import com.bitwarden.core.UriMatchType
import com.x8bit.bitwarden.ui.platform.base.util.orNullIfBlank
import com.x8bit.bitwarden.ui.vault.feature.additem.VaultAddItemState
import java.time.Instant
/**
* Transforms a [VaultAddItemState.ViewState.ItemType] into [CipherView].
*/
fun VaultAddItemState.ViewState.Content.toCipherView(): CipherView =
CipherView(
// Pulled from original cipher when editing, otherwise uses defaults
id = common.originalCipher?.id,
collectionIds = common.originalCipher?.collectionIds.orEmpty(),
key = common.originalCipher?.key,
edit = common.originalCipher?.edit ?: true,
viewPassword = common.originalCipher?.viewPassword ?: true,
localData = common.originalCipher?.localData,
attachments = common.originalCipher?.attachments,
organizationUseTotp = common.originalCipher?.organizationUseTotp ?: false,
passwordHistory = common.originalCipher?.passwordHistory,
creationDate = common.originalCipher?.creationDate ?: Instant.now(),
deletedDate = common.originalCipher?.deletedDate,
revisionDate = common.originalCipher?.revisionDate ?: Instant.now(),
// Type specific section
type = type.toCipherType(),
identity = type.toIdentityView(),
secureNote = type.toSecureNotesView(),
login = type.toLoginView(common = common),
card = type.toCardView(),
// Fields we always grab from the UI
name = common.name,
notes = common.notes,
favorite = common.favorite,
// TODO Use real folder ID (BIT-528)
folderId = common.originalCipher?.folderId,
// TODO Use real organization ID (BIT-780)
organizationId = common.originalCipher?.organizationId,
reprompt = common.toCipherRepromptType(),
fields = common.customFieldData.map { it.toFieldView() },
)
private fun VaultAddItemState.ViewState.Content.ItemType.toCipherType(): CipherType =
when (this) {
is VaultAddItemState.ViewState.Content.ItemType.Card -> CipherType.CARD
is VaultAddItemState.ViewState.Content.ItemType.Identity -> CipherType.IDENTITY
is VaultAddItemState.ViewState.Content.ItemType.Login -> CipherType.LOGIN
is VaultAddItemState.ViewState.Content.ItemType.SecureNotes -> CipherType.SECURE_NOTE
}
private fun VaultAddItemState.ViewState.Content.ItemType.toCardView(): CardView? =
(this as? VaultAddItemState.ViewState.Content.ItemType.Card)?.let {
// TODO Create real CardView from Content (BIT-668)
CardView(
cardholderName = null,
expMonth = null,
expYear = null,
code = null,
brand = null,
number = null,
)
}
private fun VaultAddItemState.ViewState.Content.ItemType.toIdentityView(): IdentityView? =
(this as? VaultAddItemState.ViewState.Content.ItemType.Identity)?.let {
IdentityView(
title = it.selectedTitle.name,
firstName = it.firstName.orNullIfBlank(),
lastName = it.lastName.orNullIfBlank(),
middleName = it.middleName.orNullIfBlank(),
address1 = it.address1.orNullIfBlank(),
address2 = it.address2.orNullIfBlank(),
address3 = it.address3.orNullIfBlank(),
city = it.city.orNullIfBlank(),
state = it.state.orNullIfBlank(),
postalCode = it.zip.orNullIfBlank(),
country = it.country.orNullIfBlank(),
company = it.company.orNullIfBlank(),
email = it.email.orNullIfBlank(),
phone = it.phone.orNullIfBlank(),
ssn = it.ssn.orNullIfBlank(),
username = it.username.orNullIfBlank(),
passportNumber = it.passportNumber.orNullIfBlank(),
licenseNumber = it.licenseNumber.orNullIfBlank(),
)
}
private fun VaultAddItemState.ViewState.Content.ItemType.toLoginView(
common: VaultAddItemState.ViewState.Content.Common,
): LoginView? =
(this as? VaultAddItemState.ViewState.Content.ItemType.Login)?.let {
LoginView(
username = it.username,
password = it.password,
passwordRevisionDate = common.originalCipher?.login?.passwordRevisionDate,
uris = listOf(
// TODO Implement URI list (BIT-1094)
LoginUriView(
uri = it.uri,
// TODO Implement URI settings in (BIT-1094)
match = UriMatchType.DOMAIN,
),
),
// TODO Implement TOTP (BIT-1066)
totp = common.originalCipher?.login?.totp,
autofillOnPageLoad = common.originalCipher?.login?.autofillOnPageLoad,
)
}
private fun VaultAddItemState.ViewState.Content.ItemType.toSecureNotesView(): SecureNoteView? =
(this as? VaultAddItemState.ViewState.Content.ItemType.SecureNotes)?.let {
SecureNoteView(type = SecureNoteType.GENERIC)
}
private fun VaultAddItemState.ViewState.Content.Common.toCipherRepromptType(): CipherRepromptType =
if (masterPasswordReprompt) {
CipherRepromptType.PASSWORD
} else {
CipherRepromptType.NONE
}
/**
* Transforms [VaultAddItemState.Custom into [FieldView].
*/
private fun VaultAddItemState.Custom.toFieldView(): FieldView =
when (val item = this) {
is VaultAddItemState.Custom.BooleanField -> {
FieldView(
name = item.name,
value = item.value.toString(),
type = FieldType.BOOLEAN,
linkedId = null,
)
}
is VaultAddItemState.Custom.HiddenField -> {
FieldView(
name = item.name,
value = item.value,
type = FieldType.HIDDEN,
linkedId = null,
)
}
is VaultAddItemState.Custom.LinkedField -> {
FieldView(
name = item.name,
value = null,
type = FieldType.LINKED,
linkedId = item.vaultLinkedFieldType.id,
)
}
is VaultAddItemState.Custom.TextField -> {
FieldView(
name = item.name,
value = item.value,
type = FieldType.TEXT,
linkedId = null,
)
}
}

View file

@ -1,63 +1,13 @@
@file:Suppress("TooManyFunctions")
package com.x8bit.bitwarden.ui.vault.feature.vault.util
import com.bitwarden.core.CardView
import com.bitwarden.core.CipherRepromptType
import com.bitwarden.core.CipherType
import com.bitwarden.core.CipherView
import com.bitwarden.core.CollectionView
import com.bitwarden.core.FieldType
import com.bitwarden.core.FieldView
import com.bitwarden.core.FolderView
import com.bitwarden.core.IdentityView
import com.bitwarden.core.LoginUriView
import com.bitwarden.core.LoginView
import com.bitwarden.core.SecureNoteType
import com.bitwarden.core.SecureNoteView
import com.bitwarden.core.UriMatchType
import com.x8bit.bitwarden.data.vault.repository.model.VaultData
import com.x8bit.bitwarden.ui.platform.base.util.asText
import com.x8bit.bitwarden.ui.platform.base.util.orNullIfBlank
import com.x8bit.bitwarden.ui.vault.feature.additem.VaultAddItemState
import com.x8bit.bitwarden.ui.vault.feature.vault.VaultState
import com.x8bit.bitwarden.ui.vault.feature.vault.model.VaultFilterType
import java.time.Instant
/**
* Transforms a [CipherView] into a [VaultState.ViewState.VaultItem].
*/
@Suppress("MagicNumber")
private fun CipherView.toVaultItemOrNull(): VaultState.ViewState.VaultItem? {
val id = this.id ?: return null
return when (type) {
CipherType.LOGIN -> VaultState.ViewState.VaultItem.Login(
id = id,
name = name.asText(),
username = login?.username?.asText(),
)
CipherType.SECURE_NOTE -> VaultState.ViewState.VaultItem.SecureNote(
id = id,
name = name.asText(),
)
CipherType.CARD -> VaultState.ViewState.VaultItem.Card(
id = id,
name = name.asText(),
brand = card?.brand?.asText(),
lastFourDigits = card?.number
?.takeLast(4)
?.asText(),
)
CipherType.IDENTITY -> VaultState.ViewState.VaultItem.Identity(
id = id,
name = name.asText(),
firstName = identity?.firstName?.asText(),
)
}
}
/**
* Transforms [VaultData] into [VaultState.ViewState] using the given [vaultFilterType].
@ -111,6 +61,41 @@ fun VaultData.toViewState(
}
}
/**
* Transforms a [CipherView] into a [VaultState.ViewState.VaultItem].
*/
@Suppress("MagicNumber")
private fun CipherView.toVaultItemOrNull(): VaultState.ViewState.VaultItem? {
val id = this.id ?: return null
return when (type) {
CipherType.LOGIN -> VaultState.ViewState.VaultItem.Login(
id = id,
name = name.asText(),
username = login?.username?.asText(),
)
CipherType.SECURE_NOTE -> VaultState.ViewState.VaultItem.SecureNote(
id = id,
name = name.asText(),
)
CipherType.CARD -> VaultState.ViewState.VaultItem.Card(
id = id,
name = name.asText(),
brand = card?.brand?.asText(),
lastFourDigits = card?.number
?.takeLast(4)
?.asText(),
)
CipherType.IDENTITY -> VaultState.ViewState.VaultItem.Identity(
id = id,
name = name.asText(),
firstName = identity?.firstName?.asText(),
)
}
}
@JvmName("toFilteredCipherList")
private fun List<CipherView>.toFilteredList(
vaultFilterType: VaultFilterType,
@ -158,162 +143,3 @@ private fun List<CollectionView>.toFilteredList(
}
}
}
/**
* Transforms a [VaultAddItemState.ViewState.ItemType] into [CipherView].
*/
fun VaultAddItemState.ViewState.Content.toCipherView(): CipherView =
CipherView(
// Pulled from original cipher when editing, otherwise uses defaults
id = common.originalCipher?.id,
collectionIds = common.originalCipher?.collectionIds.orEmpty(),
key = common.originalCipher?.key,
edit = common.originalCipher?.edit ?: true,
viewPassword = common.originalCipher?.viewPassword ?: true,
localData = common.originalCipher?.localData,
attachments = common.originalCipher?.attachments,
organizationUseTotp = common.originalCipher?.organizationUseTotp ?: false,
passwordHistory = common.originalCipher?.passwordHistory,
creationDate = common.originalCipher?.creationDate ?: Instant.now(),
deletedDate = common.originalCipher?.deletedDate,
revisionDate = common.originalCipher?.revisionDate ?: Instant.now(),
// Type specific section
type = type.toCipherType(),
identity = type.toIdentityView(),
secureNote = type.toSecureNotesView(),
login = type.toLoginView(common = common),
card = type.toCardView(),
// Fields we always grab from the UI
name = common.name,
notes = common.notes,
favorite = common.favorite,
// TODO Use real folder ID (BIT-528)
folderId = common.originalCipher?.folderId,
// TODO Use real organization ID (BIT-780)
organizationId = common.originalCipher?.organizationId,
reprompt = common.toCipherRepromptType(),
fields = common.customFieldData.map { it.toFieldView() },
)
private fun VaultAddItemState.ViewState.Content.ItemType.toCipherType(): CipherType =
when (this) {
is VaultAddItemState.ViewState.Content.ItemType.Card -> CipherType.CARD
is VaultAddItemState.ViewState.Content.ItemType.Identity -> CipherType.IDENTITY
is VaultAddItemState.ViewState.Content.ItemType.Login -> CipherType.LOGIN
is VaultAddItemState.ViewState.Content.ItemType.SecureNotes -> CipherType.SECURE_NOTE
}
private fun VaultAddItemState.ViewState.Content.ItemType.toCardView(): CardView? =
(this as? VaultAddItemState.ViewState.Content.ItemType.Card)?.let {
// TODO Create real CardView from Content (BIT-668)
CardView(
cardholderName = null,
expMonth = null,
expYear = null,
code = null,
brand = null,
number = null,
)
}
private fun VaultAddItemState.ViewState.Content.ItemType.toIdentityView(): IdentityView? =
(this as? VaultAddItemState.ViewState.Content.ItemType.Identity)?.let {
IdentityView(
title = it.selectedTitle.name,
firstName = it.firstName.orNullIfBlank(),
lastName = it.lastName.orNullIfBlank(),
middleName = it.middleName.orNullIfBlank(),
address1 = it.address1.orNullIfBlank(),
address2 = it.address2.orNullIfBlank(),
address3 = it.address3.orNullIfBlank(),
city = it.city.orNullIfBlank(),
state = it.state.orNullIfBlank(),
postalCode = it.zip.orNullIfBlank(),
country = it.country.orNullIfBlank(),
company = it.company.orNullIfBlank(),
email = it.email.orNullIfBlank(),
phone = it.phone.orNullIfBlank(),
ssn = it.ssn.orNullIfBlank(),
username = it.username.orNullIfBlank(),
passportNumber = it.passportNumber.orNullIfBlank(),
licenseNumber = it.licenseNumber.orNullIfBlank(),
)
}
private fun VaultAddItemState.ViewState.Content.ItemType.toLoginView(
common: VaultAddItemState.ViewState.Content.Common,
): LoginView? =
(this as? VaultAddItemState.ViewState.Content.ItemType.Login)?.let {
LoginView(
username = it.username,
password = it.password,
passwordRevisionDate = common.originalCipher?.login?.passwordRevisionDate,
uris = listOf(
// TODO Implement URI list (BIT-1094)
LoginUriView(
uri = it.uri,
// TODO Implement URI settings in (BIT-1094)
match = UriMatchType.DOMAIN,
),
),
// TODO Implement TOTP (BIT-1066)
totp = common.originalCipher?.login?.totp,
autofillOnPageLoad = common.originalCipher?.login?.autofillOnPageLoad,
)
}
private fun VaultAddItemState.ViewState.Content.ItemType.toSecureNotesView(): SecureNoteView? =
(this as? VaultAddItemState.ViewState.Content.ItemType.SecureNotes)?.let {
SecureNoteView(type = SecureNoteType.GENERIC)
}
private fun VaultAddItemState.ViewState.Content.Common.toCipherRepromptType(): CipherRepromptType =
if (masterPasswordReprompt) {
CipherRepromptType.PASSWORD
} else {
CipherRepromptType.NONE
}
/**
* Transforms [VaultAddItemState.Custom into [FieldView].
*/
private fun VaultAddItemState.Custom.toFieldView(): FieldView =
when (val item = this) {
is VaultAddItemState.Custom.BooleanField -> {
FieldView(
name = item.name,
value = item.value.toString(),
type = FieldType.BOOLEAN,
linkedId = null,
)
}
is VaultAddItemState.Custom.HiddenField -> {
FieldView(
name = item.name,
value = item.value,
type = FieldType.HIDDEN,
linkedId = null,
)
}
is VaultAddItemState.Custom.LinkedField -> {
FieldView(
name = item.name,
value = null,
type = FieldType.LINKED,
linkedId = item.vaultLinkedFieldType.id,
)
}
is VaultAddItemState.Custom.TextField -> {
FieldView(
name = item.name,
value = item.value,
type = FieldType.TEXT,
linkedId = null,
)
}
}

View file

@ -0,0 +1,621 @@
package com.x8bit.bitwarden.ui.vault.feature.vault.util
import com.bitwarden.core.CipherRepromptType
import com.bitwarden.core.CipherType
import com.bitwarden.core.CipherView
import com.bitwarden.core.FieldType
import com.bitwarden.core.FieldView
import com.bitwarden.core.IdentityView
import com.bitwarden.core.LoginUriView
import com.bitwarden.core.LoginView
import com.bitwarden.core.PasswordHistoryView
import com.bitwarden.core.SecureNoteType
import com.bitwarden.core.SecureNoteView
import com.bitwarden.core.UriMatchType
import com.x8bit.bitwarden.ui.platform.base.util.asText
import com.x8bit.bitwarden.ui.vault.feature.additem.VaultAddItemState
import com.x8bit.bitwarden.ui.vault.model.VaultLinkedFieldType
import io.mockk.every
import io.mockk.mockkStatic
import io.mockk.unmockkStatic
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
import java.time.Instant
class VaultAddItemStateExtensionsTest {
@AfterEach
fun tearDown() {
// Some individual tests call mockkStatic so we will make sure this is always undone.
unmockkStatic(Instant::class)
}
@Test
fun `toCipherView should transform Login ItemType to CipherView`() {
mockkStatic(Instant::class)
every { Instant.now() } returns Instant.MIN
val loginItemType = VaultAddItemState.ViewState.Content(
common = VaultAddItemState.ViewState.Content.Common(
name = "mockName-1",
folderName = "mockFolder-1".asText(),
favorite = false,
masterPasswordReprompt = false,
notes = "mockNotes-1",
ownership = "mockOwnership-1",
),
type = VaultAddItemState.ViewState.Content.ItemType.Login(
username = "mockUsername-1",
password = "mockPassword-1",
uri = "mockUri-1",
),
)
val result = loginItemType.toCipherView()
assertEquals(
CipherView(
id = null,
organizationId = null,
folderId = null,
collectionIds = emptyList(),
key = null,
name = "mockName-1",
notes = "mockNotes-1",
type = CipherType.LOGIN,
login = LoginView(
username = "mockUsername-1",
password = "mockPassword-1",
passwordRevisionDate = null,
uris = listOf(
LoginUriView(
uri = "mockUri-1",
match = UriMatchType.DOMAIN,
),
),
totp = null,
autofillOnPageLoad = null,
),
identity = null,
card = null,
secureNote = null,
favorite = false,
reprompt = CipherRepromptType.NONE,
organizationUseTotp = false,
edit = true,
viewPassword = true,
localData = null,
attachments = null,
fields = emptyList(),
passwordHistory = null,
creationDate = Instant.MIN,
deletedDate = null,
revisionDate = Instant.MIN,
),
result,
)
}
@Test
fun `toCipherView should transform Login ItemType to CipherView with original cipher`() {
val cipherView = DEFAULT_LOGIN_CIPHER_VIEW
val viewState = VaultAddItemState.ViewState.Content(
common = VaultAddItemState.ViewState.Content.Common(
originalCipher = cipherView,
name = "mockName-1",
folderName = "mockFolder-1".asText(),
favorite = true,
masterPasswordReprompt = false,
customFieldData = listOf(
VaultAddItemState.Custom.BooleanField("testId", "TestBoolean", false),
VaultAddItemState.Custom.TextField("testId", "TestText", "TestText"),
VaultAddItemState.Custom.HiddenField("testId", "TestHidden", "TestHidden"),
VaultAddItemState.Custom.LinkedField(
"testId",
"TestLinked",
VaultLinkedFieldType.USERNAME,
),
),
notes = "mockNotes-1",
ownership = "mockOwnership-1",
),
type = VaultAddItemState.ViewState.Content.ItemType.Login(
username = "mockUsername-1",
password = "mockPassword-1",
uri = "mockUri-1",
),
)
val result = viewState.toCipherView()
assertEquals(
@Suppress("MaxLineLength")
cipherView.copy(
name = "mockName-1",
notes = "mockNotes-1",
type = CipherType.LOGIN,
login = LoginView(
username = "mockUsername-1",
password = "mockPassword-1",
passwordRevisionDate = Instant.ofEpochSecond(1_000L),
uris = listOf(
LoginUriView(
uri = "mockUri-1",
match = UriMatchType.DOMAIN,
),
),
totp = "otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example",
autofillOnPageLoad = false,
),
favorite = true,
reprompt = CipherRepromptType.NONE,
fields = listOf(
FieldView(
name = "TestBoolean",
value = "false",
type = FieldType.BOOLEAN,
linkedId = null,
),
FieldView(
name = "TestText",
value = "TestText",
type = FieldType.TEXT,
linkedId = null,
),
FieldView(
name = "TestHidden",
value = "TestHidden",
type = FieldType.HIDDEN,
linkedId = null,
),
FieldView(
name = "TestLinked",
value = null,
type = FieldType.LINKED,
linkedId = VaultLinkedFieldType.USERNAME.id,
),
),
passwordHistory = listOf(
PasswordHistoryView(
password = "old_password",
lastUsedDate = Instant.ofEpochSecond(1_000L),
),
),
),
result,
)
}
@Test
fun `toCipherView should transform SecureNotes ItemType to CipherView`() {
mockkStatic(Instant::class)
every { Instant.now() } returns Instant.MIN
val viewState = VaultAddItemState.ViewState.Content(
common = VaultAddItemState.ViewState.Content.Common(
name = "mockName-1",
folderName = "mockFolder-1".asText(),
favorite = false,
masterPasswordReprompt = false,
notes = "mockNotes-1",
ownership = "mockOwnership-1",
customFieldData = listOf(
VaultAddItemState.Custom.BooleanField("testId", "TestBoolean", false),
VaultAddItemState.Custom.TextField("testId", "TestText", "TestText"),
VaultAddItemState.Custom.HiddenField("testId", "TestHidden", "TestHidden"),
),
),
type = VaultAddItemState.ViewState.Content.ItemType.SecureNotes,
)
val result = viewState.toCipherView()
assertEquals(
CipherView(
id = null,
organizationId = null,
folderId = null,
collectionIds = emptyList(),
key = null,
name = "mockName-1",
notes = "mockNotes-1",
type = CipherType.SECURE_NOTE,
login = null,
identity = null,
card = null,
secureNote = SecureNoteView(SecureNoteType.GENERIC),
favorite = false,
reprompt = CipherRepromptType.NONE,
organizationUseTotp = false,
edit = true,
viewPassword = true,
localData = null,
attachments = null,
fields = listOf(
FieldView(
name = "TestBoolean",
value = "false",
type = FieldType.BOOLEAN,
linkedId = null,
),
FieldView(
name = "TestText",
value = "TestText",
type = FieldType.TEXT,
linkedId = null,
),
FieldView(
name = "TestHidden",
value = "TestHidden",
type = FieldType.HIDDEN,
linkedId = null,
),
),
passwordHistory = null,
creationDate = Instant.MIN,
deletedDate = null,
revisionDate = Instant.MIN,
),
result,
)
}
@Test
fun `toCipherView should transform SecureNotes ItemType to CipherView with original cipher`() {
val cipherView = DEFAULT_SECURE_NOTES_CIPHER_VIEW
val viewState = VaultAddItemState.ViewState.Content(
common = VaultAddItemState.ViewState.Content.Common(
originalCipher = cipherView,
name = "mockName-1",
folderName = "mockFolder-1".asText(),
favorite = false,
masterPasswordReprompt = true,
notes = "mockNotes-1",
ownership = "mockOwnership-1",
customFieldData = emptyList(),
),
type = VaultAddItemState.ViewState.Content.ItemType.SecureNotes,
)
val result = viewState.toCipherView()
assertEquals(
cipherView.copy(
name = "mockName-1",
notes = "mockNotes-1",
type = CipherType.SECURE_NOTE,
secureNote = SecureNoteView(SecureNoteType.GENERIC),
reprompt = CipherRepromptType.PASSWORD,
fields = emptyList(),
),
result,
)
}
@Test
fun `toCipherView should transform Identity ItemType to CipherView`() {
mockkStatic(Instant::class)
every { Instant.now() } returns Instant.MIN
val viewState = VaultAddItemState.ViewState.Content(
common = VaultAddItemState.ViewState.Content.Common(
name = "mockName-1",
folderName = "mockFolder-1".asText(),
favorite = false,
masterPasswordReprompt = false,
notes = "mockNotes-1",
ownership = "mockOwnership-1",
),
type = VaultAddItemState.ViewState.Content.ItemType.Identity(
selectedTitle = VaultAddItemState.ViewState.Content.ItemType.Identity.Title.MR,
firstName = "mockFirstName",
lastName = "mockLastName",
middleName = "mockMiddleName",
address1 = "mockAddress1",
address2 = "mockAddress2",
address3 = "mockAddress3",
city = "mockCity",
state = "mockState",
zip = "mockPostalCode",
country = "mockCountry",
company = "mockCompany",
email = "mockEmail",
phone = "mockPhone",
ssn = "mockSsn",
username = "MockUsername",
passportNumber = "mockPassportNumber",
licenseNumber = "mockLicenseNumber",
),
)
val result = viewState.toCipherView()
assertEquals(
CipherView(
id = null,
organizationId = null,
folderId = null,
collectionIds = emptyList(),
key = null,
name = "mockName-1",
notes = "mockNotes-1",
type = CipherType.IDENTITY,
login = null,
identity = IdentityView(
title = "MR",
firstName = "mockFirstName",
lastName = "mockLastName",
middleName = "mockMiddleName",
address1 = "mockAddress1",
address2 = "mockAddress2",
address3 = "mockAddress3",
city = "mockCity",
state = "mockState",
postalCode = "mockPostalCode",
country = "mockCountry",
company = "mockCompany",
email = "mockEmail",
phone = "mockPhone",
ssn = "mockSsn",
username = "MockUsername",
passportNumber = "mockPassportNumber",
licenseNumber = "mockLicenseNumber",
),
card = null,
secureNote = null,
favorite = false,
reprompt = CipherRepromptType.NONE,
organizationUseTotp = false,
edit = true,
viewPassword = true,
localData = null,
attachments = null,
fields = emptyList(),
passwordHistory = null,
creationDate = Instant.MIN,
deletedDate = null,
revisionDate = Instant.MIN,
),
result,
)
}
@Test
fun `toCipherView should transform Identity ItemType to CipherView with original cipher`() {
val cipherView = DEFAULT_IDENTITY_CIPHER_VIEW
val viewState = VaultAddItemState.ViewState.Content(
common = VaultAddItemState.ViewState.Content.Common(
originalCipher = cipherView,
name = "mockName-1",
folderName = "mockFolder-1".asText(),
favorite = true,
masterPasswordReprompt = false,
customFieldData = listOf(
VaultAddItemState.Custom.BooleanField("testId", "TestBoolean", false),
VaultAddItemState.Custom.TextField("testId", "TestText", "TestText"),
VaultAddItemState.Custom.HiddenField("testId", "TestHidden", "TestHidden"),
VaultAddItemState.Custom.LinkedField(
"testId",
"TestLinked",
VaultLinkedFieldType.USERNAME,
),
),
notes = "mockNotes-1",
ownership = "mockOwnership-1",
),
type = VaultAddItemState.ViewState.Content.ItemType.Identity(
selectedTitle = VaultAddItemState.ViewState.Content.ItemType.Identity.Title.MR,
firstName = "mockFirstName",
lastName = "mockLastName",
middleName = "mockMiddleName",
address1 = "mockAddress1",
address2 = "mockAddress2",
address3 = "mockAddress3",
city = "mockCity",
state = "mockState",
zip = "mockPostalCode",
country = "mockCountry",
company = "mockCompany",
email = "mockEmail",
phone = "mockPhone",
ssn = "mockSsn",
username = "MockUsername",
passportNumber = "mockPassportNumber",
licenseNumber = "mockLicenseNumber",
),
)
val result = viewState.toCipherView()
assertEquals(
@Suppress("MaxLineLength")
cipherView.copy(
name = "mockName-1",
notes = "mockNotes-1",
type = CipherType.IDENTITY,
identity = IdentityView(
title = "MR",
firstName = "mockFirstName",
lastName = "mockLastName",
middleName = "mockMiddleName",
address1 = "mockAddress1",
address2 = "mockAddress2",
address3 = "mockAddress3",
city = "mockCity",
state = "mockState",
postalCode = "mockPostalCode",
country = "mockCountry",
company = "mockCompany",
email = "mockEmail",
phone = "mockPhone",
ssn = "mockSsn",
username = "MockUsername",
passportNumber = "mockPassportNumber",
licenseNumber = "mockLicenseNumber",
),
favorite = true,
reprompt = CipherRepromptType.NONE,
fields = listOf(
FieldView(
name = "TestBoolean",
value = "false",
type = FieldType.BOOLEAN,
linkedId = null,
),
FieldView(
name = "TestText",
value = "TestText",
type = FieldType.TEXT,
linkedId = null,
),
FieldView(
name = "TestHidden",
value = "TestHidden",
type = FieldType.HIDDEN,
linkedId = null,
),
FieldView(
name = "TestLinked",
value = null,
type = FieldType.LINKED,
linkedId = VaultLinkedFieldType.USERNAME.id,
),
),
passwordHistory = listOf(
PasswordHistoryView(
password = "old_password",
lastUsedDate = Instant.ofEpochSecond(1_000L),
),
),
),
result,
)
}
}
private val DEFAULT_BASE_CIPHER_VIEW: CipherView = CipherView(
id = "id1234",
organizationId = null,
folderId = null,
collectionIds = emptyList(),
key = null,
name = "cipher",
notes = "Lots of notes",
type = CipherType.LOGIN,
login = null,
identity = null,
card = null,
secureNote = null,
favorite = false,
reprompt = CipherRepromptType.PASSWORD,
organizationUseTotp = false,
edit = false,
viewPassword = false,
localData = null,
attachments = null,
fields = listOf(
FieldView(
name = "text",
value = "value",
type = FieldType.TEXT,
linkedId = null,
),
FieldView(
name = "hidden",
value = "value",
type = FieldType.HIDDEN,
linkedId = null,
),
FieldView(
name = "boolean",
value = "true",
type = FieldType.BOOLEAN,
linkedId = null,
),
FieldView(
name = "linked username",
value = null,
type = FieldType.LINKED,
linkedId = 100U,
),
FieldView(
name = "linked password",
value = null,
type = FieldType.LINKED,
linkedId = 101U,
),
),
passwordHistory = listOf(
PasswordHistoryView(
password = "old_password",
lastUsedDate = Instant.ofEpochSecond(1_000L),
),
),
creationDate = Instant.ofEpochSecond(1_000L),
deletedDate = null,
revisionDate = Instant.ofEpochSecond(1_000L),
)
private val DEFAULT_LOGIN_CIPHER_VIEW: CipherView = DEFAULT_BASE_CIPHER_VIEW.copy(
type = CipherType.LOGIN,
login = LoginView(
username = "username",
password = "password",
passwordRevisionDate = Instant.ofEpochSecond(1_000L),
uris = listOf(
LoginUriView(
uri = "www.example.com",
match = null,
),
),
totp = "otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example",
autofillOnPageLoad = false,
),
)
private val DEFAULT_SECURE_NOTES_CIPHER_VIEW: CipherView = DEFAULT_BASE_CIPHER_VIEW.copy(
type = CipherType.SECURE_NOTE,
fields = listOf(
FieldView(
name = "text",
value = "value",
type = FieldType.TEXT,
linkedId = null,
),
FieldView(
name = "hidden",
value = "value",
type = FieldType.HIDDEN,
linkedId = null,
),
FieldView(
name = "boolean",
value = "true",
type = FieldType.BOOLEAN,
linkedId = null,
),
),
secureNote = SecureNoteView(type = SecureNoteType.GENERIC),
)
private val DEFAULT_IDENTITY_CIPHER_VIEW: CipherView = DEFAULT_BASE_CIPHER_VIEW.copy(
type = CipherType.IDENTITY,
identity = IdentityView(
title = "MR",
firstName = "mockFirstName",
lastName = "mockLastName",
middleName = "mockMiddleName",
address1 = "mockAddress1",
address2 = "mockAddress2",
address3 = "mockAddress3",
city = "mockCity",
state = "mockState",
postalCode = "mockPostalCode",
country = "mockCountry",
company = "mockCompany",
email = "mockEmail",
phone = "mockPhone",
ssn = "mockSsn",
username = "MockUsername",
passportNumber = "mockPassportNumber",
licenseNumber = "mockLicenseNumber",
),
)

View file

@ -1,42 +1,17 @@
package com.x8bit.bitwarden.ui.vault.feature.vault.util
import com.bitwarden.core.CipherRepromptType
import com.bitwarden.core.CipherType
import com.bitwarden.core.CipherView
import com.bitwarden.core.FieldType
import com.bitwarden.core.FieldView
import com.bitwarden.core.IdentityView
import com.bitwarden.core.LoginUriView
import com.bitwarden.core.LoginView
import com.bitwarden.core.PasswordHistoryView
import com.bitwarden.core.SecureNoteType
import com.bitwarden.core.SecureNoteView
import com.bitwarden.core.UriMatchType
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockCipherView
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockCollectionView
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockFolderView
import com.x8bit.bitwarden.data.vault.repository.model.VaultData
import com.x8bit.bitwarden.ui.platform.base.util.asText
import com.x8bit.bitwarden.ui.vault.feature.additem.VaultAddItemState
import com.x8bit.bitwarden.ui.vault.feature.vault.VaultState
import com.x8bit.bitwarden.ui.vault.feature.vault.model.VaultFilterType
import com.x8bit.bitwarden.ui.vault.model.VaultLinkedFieldType
import io.mockk.every
import io.mockk.mockkStatic
import io.mockk.unmockkStatic
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
import java.time.Instant
class VaultDataExtensionsTest {
@AfterEach
fun tearDown() {
// Some individual tests call mockkStatic so we will make sure this is always undone.
unmockkStatic(Instant::class)
}
@Suppress("MaxLineLength")
@Test
fun `toViewState for AllVaults should transform full VaultData into ViewState Content without filtering`() {
@ -187,592 +162,4 @@ class VaultDataExtensionsTest {
actual,
)
}
@Test
fun `toCipherView should transform Login ItemType to CipherView`() {
mockkStatic(Instant::class)
every { Instant.now() } returns Instant.MIN
val loginItemType = VaultAddItemState.ViewState.Content(
common = VaultAddItemState.ViewState.Content.Common(
name = "mockName-1",
folderName = "mockFolder-1".asText(),
favorite = false,
masterPasswordReprompt = false,
notes = "mockNotes-1",
ownership = "mockOwnership-1",
),
type = VaultAddItemState.ViewState.Content.ItemType.Login(
username = "mockUsername-1",
password = "mockPassword-1",
uri = "mockUri-1",
),
)
val result = loginItemType.toCipherView()
assertEquals(
CipherView(
id = null,
organizationId = null,
folderId = null,
collectionIds = emptyList(),
key = null,
name = "mockName-1",
notes = "mockNotes-1",
type = CipherType.LOGIN,
login = LoginView(
username = "mockUsername-1",
password = "mockPassword-1",
passwordRevisionDate = null,
uris = listOf(
LoginUriView(
uri = "mockUri-1",
match = UriMatchType.DOMAIN,
),
),
totp = null,
autofillOnPageLoad = null,
),
identity = null,
card = null,
secureNote = null,
favorite = false,
reprompt = CipherRepromptType.NONE,
organizationUseTotp = false,
edit = true,
viewPassword = true,
localData = null,
attachments = null,
fields = emptyList(),
passwordHistory = null,
creationDate = Instant.MIN,
deletedDate = null,
revisionDate = Instant.MIN,
),
result,
)
}
@Test
fun `toCipherView should transform Login ItemType to CipherView with original cipher`() {
val cipherView = DEFAULT_LOGIN_CIPHER_VIEW
val viewState = VaultAddItemState.ViewState.Content(
common = VaultAddItemState.ViewState.Content.Common(
originalCipher = cipherView,
name = "mockName-1",
folderName = "mockFolder-1".asText(),
favorite = true,
masterPasswordReprompt = false,
customFieldData = listOf(
VaultAddItemState.Custom.BooleanField("testId", "TestBoolean", false),
VaultAddItemState.Custom.TextField("testId", "TestText", "TestText"),
VaultAddItemState.Custom.HiddenField("testId", "TestHidden", "TestHidden"),
VaultAddItemState.Custom.LinkedField(
"testId",
"TestLinked",
VaultLinkedFieldType.USERNAME,
),
),
notes = "mockNotes-1",
ownership = "mockOwnership-1",
),
type = VaultAddItemState.ViewState.Content.ItemType.Login(
username = "mockUsername-1",
password = "mockPassword-1",
uri = "mockUri-1",
),
)
val result = viewState.toCipherView()
assertEquals(
@Suppress("MaxLineLength")
cipherView.copy(
name = "mockName-1",
notes = "mockNotes-1",
type = CipherType.LOGIN,
login = LoginView(
username = "mockUsername-1",
password = "mockPassword-1",
passwordRevisionDate = Instant.ofEpochSecond(1_000L),
uris = listOf(
LoginUriView(
uri = "mockUri-1",
match = UriMatchType.DOMAIN,
),
),
totp = "otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example",
autofillOnPageLoad = false,
),
favorite = true,
reprompt = CipherRepromptType.NONE,
fields = listOf(
FieldView(
name = "TestBoolean",
value = "false",
type = FieldType.BOOLEAN,
linkedId = null,
),
FieldView(
name = "TestText",
value = "TestText",
type = FieldType.TEXT,
linkedId = null,
),
FieldView(
name = "TestHidden",
value = "TestHidden",
type = FieldType.HIDDEN,
linkedId = null,
),
FieldView(
name = "TestLinked",
value = null,
type = FieldType.LINKED,
linkedId = VaultLinkedFieldType.USERNAME.id,
),
),
passwordHistory = listOf(
PasswordHistoryView(
password = "old_password",
lastUsedDate = Instant.ofEpochSecond(1_000L),
),
),
),
result,
)
}
@Test
fun `toCipherView should transform SecureNotes ItemType to CipherView`() {
mockkStatic(Instant::class)
every { Instant.now() } returns Instant.MIN
val viewState = VaultAddItemState.ViewState.Content(
common = VaultAddItemState.ViewState.Content.Common(
name = "mockName-1",
folderName = "mockFolder-1".asText(),
favorite = false,
masterPasswordReprompt = false,
notes = "mockNotes-1",
ownership = "mockOwnership-1",
customFieldData = listOf(
VaultAddItemState.Custom.BooleanField("testId", "TestBoolean", false),
VaultAddItemState.Custom.TextField("testId", "TestText", "TestText"),
VaultAddItemState.Custom.HiddenField("testId", "TestHidden", "TestHidden"),
),
),
type = VaultAddItemState.ViewState.Content.ItemType.SecureNotes,
)
val result = viewState.toCipherView()
assertEquals(
CipherView(
id = null,
organizationId = null,
folderId = null,
collectionIds = emptyList(),
key = null,
name = "mockName-1",
notes = "mockNotes-1",
type = CipherType.SECURE_NOTE,
login = null,
identity = null,
card = null,
secureNote = SecureNoteView(SecureNoteType.GENERIC),
favorite = false,
reprompt = CipherRepromptType.NONE,
organizationUseTotp = false,
edit = true,
viewPassword = true,
localData = null,
attachments = null,
fields = listOf(
FieldView(
name = "TestBoolean",
value = "false",
type = FieldType.BOOLEAN,
linkedId = null,
),
FieldView(
name = "TestText",
value = "TestText",
type = FieldType.TEXT,
linkedId = null,
),
FieldView(
name = "TestHidden",
value = "TestHidden",
type = FieldType.HIDDEN,
linkedId = null,
),
),
passwordHistory = null,
creationDate = Instant.MIN,
deletedDate = null,
revisionDate = Instant.MIN,
),
result,
)
}
@Test
fun `toCipherView should transform SecureNotes ItemType to CipherView with original cipher`() {
val cipherView = DEFAULT_SECURE_NOTES_CIPHER_VIEW
val viewState = VaultAddItemState.ViewState.Content(
common = VaultAddItemState.ViewState.Content.Common(
originalCipher = cipherView,
name = "mockName-1",
folderName = "mockFolder-1".asText(),
favorite = false,
masterPasswordReprompt = true,
notes = "mockNotes-1",
ownership = "mockOwnership-1",
customFieldData = emptyList(),
),
type = VaultAddItemState.ViewState.Content.ItemType.SecureNotes,
)
val result = viewState.toCipherView()
assertEquals(
cipherView.copy(
name = "mockName-1",
notes = "mockNotes-1",
type = CipherType.SECURE_NOTE,
secureNote = SecureNoteView(SecureNoteType.GENERIC),
reprompt = CipherRepromptType.PASSWORD,
fields = emptyList(),
),
result,
)
}
@Test
fun `toCipherView should transform Identity ItemType to CipherView`() {
mockkStatic(Instant::class)
every { Instant.now() } returns Instant.MIN
val viewState = VaultAddItemState.ViewState.Content(
common = VaultAddItemState.ViewState.Content.Common(
name = "mockName-1",
folderName = "mockFolder-1".asText(),
favorite = false,
masterPasswordReprompt = false,
notes = "mockNotes-1",
ownership = "mockOwnership-1",
),
type = VaultAddItemState.ViewState.Content.ItemType.Identity(
selectedTitle = VaultAddItemState.ViewState.Content.ItemType.Identity.Title.MR,
firstName = "mockFirstName",
lastName = "mockLastName",
middleName = "mockMiddleName",
address1 = "mockAddress1",
address2 = "mockAddress2",
address3 = "mockAddress3",
city = "mockCity",
state = "mockState",
zip = "mockPostalCode",
country = "mockCountry",
company = "mockCompany",
email = "mockEmail",
phone = "mockPhone",
ssn = "mockSsn",
username = "MockUsername",
passportNumber = "mockPassportNumber",
licenseNumber = "mockLicenseNumber",
),
)
val result = viewState.toCipherView()
assertEquals(
CipherView(
id = null,
organizationId = null,
folderId = null,
collectionIds = emptyList(),
key = null,
name = "mockName-1",
notes = "mockNotes-1",
type = CipherType.IDENTITY,
login = null,
identity = IdentityView(
title = "MR",
firstName = "mockFirstName",
lastName = "mockLastName",
middleName = "mockMiddleName",
address1 = "mockAddress1",
address2 = "mockAddress2",
address3 = "mockAddress3",
city = "mockCity",
state = "mockState",
postalCode = "mockPostalCode",
country = "mockCountry",
company = "mockCompany",
email = "mockEmail",
phone = "mockPhone",
ssn = "mockSsn",
username = "MockUsername",
passportNumber = "mockPassportNumber",
licenseNumber = "mockLicenseNumber",
),
card = null,
secureNote = null,
favorite = false,
reprompt = CipherRepromptType.NONE,
organizationUseTotp = false,
edit = true,
viewPassword = true,
localData = null,
attachments = null,
fields = emptyList(),
passwordHistory = null,
creationDate = Instant.MIN,
deletedDate = null,
revisionDate = Instant.MIN,
),
result,
)
}
@Test
fun `toCipherView should transform Identity ItemType to CipherView with original cipher`() {
val cipherView = DEFAULT_IDENTITY_CIPHER_VIEW
val viewState = VaultAddItemState.ViewState.Content(
common = VaultAddItemState.ViewState.Content.Common(
originalCipher = cipherView,
name = "mockName-1",
folderName = "mockFolder-1".asText(),
favorite = true,
masterPasswordReprompt = false,
customFieldData = listOf(
VaultAddItemState.Custom.BooleanField("testId", "TestBoolean", false),
VaultAddItemState.Custom.TextField("testId", "TestText", "TestText"),
VaultAddItemState.Custom.HiddenField("testId", "TestHidden", "TestHidden"),
VaultAddItemState.Custom.LinkedField(
"testId",
"TestLinked",
VaultLinkedFieldType.USERNAME,
),
),
notes = "mockNotes-1",
ownership = "mockOwnership-1",
),
type = VaultAddItemState.ViewState.Content.ItemType.Identity(
selectedTitle = VaultAddItemState.ViewState.Content.ItemType.Identity.Title.MR,
firstName = "mockFirstName",
lastName = "mockLastName",
middleName = "mockMiddleName",
address1 = "mockAddress1",
address2 = "mockAddress2",
address3 = "mockAddress3",
city = "mockCity",
state = "mockState",
zip = "mockPostalCode",
country = "mockCountry",
company = "mockCompany",
email = "mockEmail",
phone = "mockPhone",
ssn = "mockSsn",
username = "MockUsername",
passportNumber = "mockPassportNumber",
licenseNumber = "mockLicenseNumber",
),
)
val result = viewState.toCipherView()
assertEquals(
@Suppress("MaxLineLength")
cipherView.copy(
name = "mockName-1",
notes = "mockNotes-1",
type = CipherType.IDENTITY,
identity = IdentityView(
title = "MR",
firstName = "mockFirstName",
lastName = "mockLastName",
middleName = "mockMiddleName",
address1 = "mockAddress1",
address2 = "mockAddress2",
address3 = "mockAddress3",
city = "mockCity",
state = "mockState",
postalCode = "mockPostalCode",
country = "mockCountry",
company = "mockCompany",
email = "mockEmail",
phone = "mockPhone",
ssn = "mockSsn",
username = "MockUsername",
passportNumber = "mockPassportNumber",
licenseNumber = "mockLicenseNumber",
),
favorite = true,
reprompt = CipherRepromptType.NONE,
fields = listOf(
FieldView(
name = "TestBoolean",
value = "false",
type = FieldType.BOOLEAN,
linkedId = null,
),
FieldView(
name = "TestText",
value = "TestText",
type = FieldType.TEXT,
linkedId = null,
),
FieldView(
name = "TestHidden",
value = "TestHidden",
type = FieldType.HIDDEN,
linkedId = null,
),
FieldView(
name = "TestLinked",
value = null,
type = FieldType.LINKED,
linkedId = VaultLinkedFieldType.USERNAME.id,
),
),
passwordHistory = listOf(
PasswordHistoryView(
password = "old_password",
lastUsedDate = Instant.ofEpochSecond(1_000L),
),
),
),
result,
)
}
}
private val DEFAULT_BASE_CIPHER_VIEW: CipherView = CipherView(
id = "id1234",
organizationId = null,
folderId = null,
collectionIds = emptyList(),
key = null,
name = "cipher",
notes = "Lots of notes",
type = CipherType.LOGIN,
login = null,
identity = null,
card = null,
secureNote = null,
favorite = false,
reprompt = CipherRepromptType.PASSWORD,
organizationUseTotp = false,
edit = false,
viewPassword = false,
localData = null,
attachments = null,
fields = listOf(
FieldView(
name = "text",
value = "value",
type = FieldType.TEXT,
linkedId = null,
),
FieldView(
name = "hidden",
value = "value",
type = FieldType.HIDDEN,
linkedId = null,
),
FieldView(
name = "boolean",
value = "true",
type = FieldType.BOOLEAN,
linkedId = null,
),
FieldView(
name = "linked username",
value = null,
type = FieldType.LINKED,
linkedId = 100U,
),
FieldView(
name = "linked password",
value = null,
type = FieldType.LINKED,
linkedId = 101U,
),
),
passwordHistory = listOf(
PasswordHistoryView(
password = "old_password",
lastUsedDate = Instant.ofEpochSecond(1_000L),
),
),
creationDate = Instant.ofEpochSecond(1_000L),
deletedDate = null,
revisionDate = Instant.ofEpochSecond(1_000L),
)
private val DEFAULT_LOGIN_CIPHER_VIEW: CipherView = DEFAULT_BASE_CIPHER_VIEW.copy(
type = CipherType.LOGIN,
login = LoginView(
username = "username",
password = "password",
passwordRevisionDate = Instant.ofEpochSecond(1_000L),
uris = listOf(
LoginUriView(
uri = "www.example.com",
match = null,
),
),
totp = "otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example",
autofillOnPageLoad = false,
),
)
private val DEFAULT_SECURE_NOTES_CIPHER_VIEW: CipherView = DEFAULT_BASE_CIPHER_VIEW.copy(
type = CipherType.SECURE_NOTE,
fields = listOf(
FieldView(
name = "text",
value = "value",
type = FieldType.TEXT,
linkedId = null,
),
FieldView(
name = "hidden",
value = "value",
type = FieldType.HIDDEN,
linkedId = null,
),
FieldView(
name = "boolean",
value = "true",
type = FieldType.BOOLEAN,
linkedId = null,
),
),
secureNote = SecureNoteView(type = SecureNoteType.GENERIC),
)
private val DEFAULT_IDENTITY_CIPHER_VIEW: CipherView = DEFAULT_BASE_CIPHER_VIEW.copy(
type = CipherType.IDENTITY,
identity = IdentityView(
title = "MR",
firstName = "mockFirstName",
lastName = "mockLastName",
middleName = "mockMiddleName",
address1 = "mockAddress1",
address2 = "mockAddress2",
address3 = "mockAddress3",
city = "mockCity",
state = "mockState",
postalCode = "mockPostalCode",
country = "mockCountry",
company = "mockCompany",
email = "mockEmail",
phone = "mockPhone",
ssn = "mockSsn",
username = "MockUsername",
passportNumber = "mockPassportNumber",
licenseNumber = "mockLicenseNumber",
),
)