[PM-24347] Tracking UserClientExportedVault event when user exports the vault (#5710)

This commit is contained in:
aj-rosado 2025-08-18 16:10:52 +01:00 committed by GitHub
parent 3164c29184
commit ff6b7b675d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 55 additions and 19 deletions

View File

@ -105,4 +105,13 @@ sealed class OrganizationEvent {
override val type: OrganizationEventType
get() = OrganizationEventType.CIPHER_CLIENT_VIEWED
}
/**
* Tracks when user's individual vault is exported.
*/
data object UserClientExportedVault : OrganizationEvent() {
override val cipherId: String? = null
override val type: OrganizationEventType
get() = OrganizationEventType.USER_CLIENT_EXPORTED_VAULT
}
}

View File

@ -21,6 +21,8 @@ import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult
import com.x8bit.bitwarden.data.auth.repository.model.VerifyOtpResult
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
import com.x8bit.bitwarden.data.platform.manager.event.OrganizationEventManager
import com.x8bit.bitwarden.data.platform.manager.model.OrganizationEvent
import com.x8bit.bitwarden.data.vault.manager.FileManager
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
import com.x8bit.bitwarden.data.vault.repository.model.ExportVaultDataResult
@ -54,6 +56,7 @@ class ExportVaultViewModel @Inject constructor(
private val fileManager: FileManager,
private val clock: Clock,
private val featureFlagManager: FeatureFlagManager,
private val organizationEventManager: OrganizationEventManager,
) : BaseViewModel<ExportVaultState, ExportVaultEvent, ExportVaultAction>(
initialState = savedStateHandle[KEY_STATE]
?: ExportVaultState(
@ -402,6 +405,9 @@ class ExportVaultViewModel @Inject constructor(
return
}
organizationEventManager.trackEvent(
event = OrganizationEvent.UserClientExportedVault,
)
sendEvent(ExportVaultEvent.ShowSnackbar(BitwardenString.export_vault_success.asText()))
}

View File

@ -22,7 +22,9 @@ import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult
import com.x8bit.bitwarden.data.auth.repository.model.VerifyOtpResult
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
import com.x8bit.bitwarden.data.platform.manager.event.OrganizationEventManager
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.platform.manager.model.OrganizationEvent
import com.x8bit.bitwarden.data.vault.manager.FileManager
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
import com.x8bit.bitwarden.data.vault.repository.model.ExportVaultDataResult
@ -31,7 +33,9 @@ import com.x8bit.bitwarden.ui.platform.feature.settings.exportvault.model.Export
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.every
import io.mockk.just
import io.mockk.mockk
import io.mockk.runs
import io.mockk.verify
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.runTest
@ -84,6 +88,10 @@ class ExportVaultViewModelTest : BaseViewModelTest() {
} returns false
}
private val organizationEventManager = mockk<OrganizationEventManager> {
every { trackEvent(event = any()) } just runs
}
@Test
fun `initial state should be correct`() = runTest {
every {
@ -792,27 +800,39 @@ class ExportVaultViewModelTest : BaseViewModelTest() {
}
@Test
fun `ExportLocationReceive should emit ShowSnackbar on success`() = runTest {
val exportData = "TestExportVaultData"
val viewModel = createViewModel(
DEFAULT_STATE.copy(
exportData = exportData,
),
)
val uri = mockk<Uri>()
coEvery { fileManager.stringToUri(fileUri = any(), dataString = exportData) } returns true
viewModel.eventFlow.test {
viewModel.trySendAction(ExportVaultAction.ExportLocationReceive(uri))
coVerify { fileManager.stringToUri(fileUri = any(), dataString = exportData) }
assertEquals(
ExportVaultEvent.ShowSnackbar(BitwardenString.export_vault_success.asText()),
awaitItem(),
fun `ExportLocationReceive should emit ShowSnackbar and UserClientExportedVault on success`() =
runTest {
val exportData = "TestExportVaultData"
val viewModel = createViewModel(
DEFAULT_STATE.copy(
exportData = exportData,
),
)
val uri = mockk<Uri>()
coEvery {
fileManager.stringToUri(
fileUri = any(),
dataString = exportData,
)
} returns true
viewModel.eventFlow.test {
viewModel.trySendAction(ExportVaultAction.ExportLocationReceive(uri))
coVerify { fileManager.stringToUri(fileUri = any(), dataString = exportData) }
verify(exactly = 1) {
organizationEventManager.trackEvent(
event = OrganizationEvent.UserClientExportedVault,
)
}
assertEquals(
ExportVaultEvent.ShowSnackbar(BitwardenString.export_vault_success.asText()),
awaitItem(),
)
}
}
}
private fun createViewModel(
initialState: ExportVaultState? = null,
@ -826,6 +846,7 @@ class ExportVaultViewModelTest : BaseViewModelTest() {
vaultRepository = vaultRepository,
clock = clock,
featureFlagManager = featureFlagManager,
organizationEventManager = organizationEventManager,
)
}