mirror of
https://github.com/bitwarden/android.git
synced 2026-06-01 18:26:31 -05:00
BIT-1128: Expose vault data (#227)
This commit is contained in:
@@ -3,6 +3,7 @@ package com.x8bit.bitwarden.data.platform.datasource.network.util
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assertions.assertNull
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.net.UnknownHostException
|
||||
|
||||
class NetworkUtilsTest {
|
||||
@Test
|
||||
@@ -40,4 +41,20 @@ class NetworkUtilsTest {
|
||||
"*.*".base64UrlDecodeOrNull(),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `isNoConnectionError should return return true for UnknownHostException`() {
|
||||
assertEquals(
|
||||
true,
|
||||
UnknownHostException().isNoConnectionError(),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `isNoConnectionError should return return false for not UnknownHostException`() {
|
||||
assertEquals(
|
||||
false,
|
||||
IllegalStateException().isNoConnectionError(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.x8bit.bitwarden.data.vault.datasource.sdk.model
|
||||
|
||||
import com.bitwarden.core.CipherListView
|
||||
import com.bitwarden.core.CipherRepromptType
|
||||
import com.bitwarden.core.CipherType
|
||||
import java.time.LocalDateTime
|
||||
import java.time.ZoneOffset
|
||||
|
||||
/**
|
||||
* Create a mock [CipherListView] with a given [number].
|
||||
*/
|
||||
fun createMockCipherListView(number: Int): CipherListView =
|
||||
CipherListView(
|
||||
id = "mockId-$number",
|
||||
organizationId = "mockOrganizationId-$number",
|
||||
folderId = "mockFolderId-$number",
|
||||
collectionIds = listOf("mockCollectionId-$number"),
|
||||
name = "mockName-$number",
|
||||
type = CipherType.LOGIN,
|
||||
creationDate = LocalDateTime
|
||||
.parse("2023-10-27T12:00:00")
|
||||
.toInstant(ZoneOffset.UTC),
|
||||
deletedDate = LocalDateTime
|
||||
.parse("2023-10-27T12:00:00")
|
||||
.toInstant(ZoneOffset.UTC),
|
||||
revisionDate = LocalDateTime
|
||||
.parse("2023-10-27T12:00:00")
|
||||
.toInstant(ZoneOffset.UTC),
|
||||
attachments = 1U,
|
||||
favorite = false,
|
||||
reprompt = CipherRepromptType.NONE,
|
||||
edit = false,
|
||||
viewPassword = false,
|
||||
subTitle = "",
|
||||
)
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.x8bit.bitwarden.data.vault.datasource.sdk.model
|
||||
|
||||
import com.bitwarden.core.FolderView
|
||||
import java.time.LocalDateTime
|
||||
import java.time.ZoneOffset
|
||||
|
||||
/**
|
||||
* Create a mock [FolderView] with a given [number].
|
||||
*/
|
||||
fun createMockFolderView(number: Int): FolderView =
|
||||
FolderView(
|
||||
id = "mockId-$number",
|
||||
name = "mockName-$number",
|
||||
revisionDate = LocalDateTime
|
||||
.parse("2023-10-27T12:00:00")
|
||||
.toInstant(ZoneOffset.UTC),
|
||||
)
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.x8bit.bitwarden.data.vault.datasource.sdk
|
||||
package com.x8bit.bitwarden.data.vault.datasource.sdk.model
|
||||
|
||||
import com.bitwarden.core.Attachment
|
||||
import com.bitwarden.core.Card
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.x8bit.bitwarden.data.vault.datasource.sdk
|
||||
package com.x8bit.bitwarden.data.vault.datasource.sdk.model
|
||||
|
||||
import com.bitwarden.core.Folder
|
||||
import java.time.LocalDateTime
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.x8bit.bitwarden.data.vault.repository
|
||||
|
||||
import app.cash.turbine.test
|
||||
import com.bitwarden.core.InitCryptoRequest
|
||||
import com.bitwarden.core.Kdf
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.AccountJson
|
||||
@@ -8,12 +9,18 @@ import com.x8bit.bitwarden.data.auth.datasource.disk.util.FakeAuthDiskSource
|
||||
import com.x8bit.bitwarden.data.auth.util.KdfParamsConstants.DEFAULT_PBKDF2_ITERATIONS
|
||||
import com.x8bit.bitwarden.data.platform.base.FakeDispatcherManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager
|
||||
import com.x8bit.bitwarden.data.platform.repository.model.DataState
|
||||
import com.x8bit.bitwarden.data.platform.util.asFailure
|
||||
import com.x8bit.bitwarden.data.platform.util.asSuccess
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.createMockSyncResponse
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.service.SyncService
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.InitializeCryptoResult
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.VaultSdkSource
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.createMockSdkCipher
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.createMockSdkFolder
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockSdkCipher
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockSdkFolder
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockCipherListView
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockFolderView
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.VaultData
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.VaultUnlockResult
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.coVerify
|
||||
@@ -21,6 +28,7 @@ import io.mockk.mockk
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.net.UnknownHostException
|
||||
|
||||
class VaultRepositoryTest {
|
||||
|
||||
@@ -36,27 +44,228 @@ class VaultRepositoryTest {
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `sync when syncService Success should update AuthDiskSource with keys`() = runTest {
|
||||
coEvery { syncService.sync() } returns Result.success(createMockSyncResponse(number = 1))
|
||||
coEvery {
|
||||
vaultSdkSource.decryptCipherList(listOf(createMockSdkCipher(1)))
|
||||
} returns mockk()
|
||||
coEvery {
|
||||
vaultSdkSource.decryptFolderList(listOf(createMockSdkFolder(1)))
|
||||
} returns mockk()
|
||||
fakeAuthDiskSource.userState = MOCK_USER_STATE
|
||||
fun `sync with syncService Success should update AuthDiskSource and vaultDataStateFlow`() =
|
||||
runTest {
|
||||
coEvery {
|
||||
syncService.sync()
|
||||
} returns Result.success(createMockSyncResponse(number = 1))
|
||||
coEvery {
|
||||
vaultSdkSource.decryptCipherList(listOf(createMockSdkCipher(1)))
|
||||
} returns listOf(createMockCipherListView(number = 1)).asSuccess()
|
||||
coEvery {
|
||||
vaultSdkSource.decryptFolderList(listOf(createMockSdkFolder(1)))
|
||||
} returns listOf(createMockFolderView(number = 1)).asSuccess()
|
||||
fakeAuthDiskSource.userState = MOCK_USER_STATE
|
||||
|
||||
vaultRepository.sync()
|
||||
vaultRepository.sync()
|
||||
|
||||
fakeAuthDiskSource.assertUserKey(
|
||||
userId = "mockUserId",
|
||||
userKey = "mockKey-1",
|
||||
)
|
||||
fakeAuthDiskSource.assertPrivateKey(
|
||||
userId = "mockUserId",
|
||||
privateKey = "mockPrivateKey-1",
|
||||
)
|
||||
}
|
||||
fakeAuthDiskSource.assertUserKey(
|
||||
userId = "mockUserId",
|
||||
userKey = "mockKey-1",
|
||||
)
|
||||
fakeAuthDiskSource.assertPrivateKey(
|
||||
userId = "mockUserId",
|
||||
privateKey = "mockPrivateKey-1",
|
||||
)
|
||||
assertEquals(
|
||||
DataState.Loaded(
|
||||
data = VaultData(
|
||||
cipherListViewList = listOf(createMockCipherListView(number = 1)),
|
||||
folderViewList = listOf(createMockFolderView(number = 1)),
|
||||
),
|
||||
),
|
||||
vaultRepository.vaultDataStateFlow.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `sync with data should update vaultDataStateFlow to Pending before service sync`() =
|
||||
runTest {
|
||||
coEvery {
|
||||
syncService.sync()
|
||||
} returns Result.success(createMockSyncResponse(number = 1))
|
||||
coEvery {
|
||||
vaultSdkSource.decryptCipherList(listOf(createMockSdkCipher(1)))
|
||||
} returns listOf(createMockCipherListView(number = 1)).asSuccess()
|
||||
coEvery {
|
||||
vaultSdkSource.decryptFolderList(listOf(createMockSdkFolder(1)))
|
||||
} returns listOf(createMockFolderView(number = 1)).asSuccess()
|
||||
fakeAuthDiskSource.userState = MOCK_USER_STATE
|
||||
|
||||
vaultRepository.vaultDataStateFlow.test {
|
||||
assertEquals(
|
||||
DataState.Loading,
|
||||
awaitItem(),
|
||||
)
|
||||
vaultRepository.sync()
|
||||
assertEquals(
|
||||
DataState.Loaded(
|
||||
data = VaultData(
|
||||
cipherListViewList = listOf(createMockCipherListView(number = 1)),
|
||||
folderViewList = listOf(createMockFolderView(number = 1)),
|
||||
),
|
||||
),
|
||||
awaitItem(),
|
||||
)
|
||||
vaultRepository.sync()
|
||||
assertEquals(
|
||||
DataState.Pending(
|
||||
data = VaultData(
|
||||
cipherListViewList = listOf(createMockCipherListView(number = 1)),
|
||||
folderViewList = listOf(createMockFolderView(number = 1)),
|
||||
),
|
||||
),
|
||||
awaitItem(),
|
||||
)
|
||||
assertEquals(
|
||||
DataState.Loaded(
|
||||
data = VaultData(
|
||||
cipherListViewList = listOf(createMockCipherListView(number = 1)),
|
||||
folderViewList = listOf(createMockFolderView(number = 1)),
|
||||
),
|
||||
),
|
||||
awaitItem(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `sync with decryptCipherList Failure should update vaultDataStateFlow with Error`() =
|
||||
runTest {
|
||||
val mockException = IllegalStateException()
|
||||
coEvery {
|
||||
syncService.sync()
|
||||
} returns Result.success(createMockSyncResponse(number = 1))
|
||||
coEvery {
|
||||
vaultSdkSource.decryptCipherList(listOf(createMockSdkCipher(1)))
|
||||
} returns mockException.asFailure()
|
||||
coEvery {
|
||||
vaultSdkSource.decryptFolderList(listOf(createMockSdkFolder(1)))
|
||||
} returns listOf(createMockFolderView(number = 1)).asSuccess()
|
||||
fakeAuthDiskSource.userState = MOCK_USER_STATE
|
||||
|
||||
vaultRepository.sync()
|
||||
|
||||
assertEquals(
|
||||
DataState.Error<VaultData>(error = mockException),
|
||||
vaultRepository.vaultDataStateFlow.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `sync with decryptFolderList Failure should update vaultDataStateFlow with Error`() =
|
||||
runTest {
|
||||
val mockException = IllegalStateException()
|
||||
coEvery {
|
||||
syncService.sync()
|
||||
} returns Result.success(createMockSyncResponse(number = 1))
|
||||
coEvery {
|
||||
vaultSdkSource.decryptCipherList(listOf(createMockSdkCipher(1)))
|
||||
} returns listOf(createMockCipherListView(number = 1)).asSuccess()
|
||||
coEvery {
|
||||
vaultSdkSource.decryptFolderList(listOf(createMockSdkFolder(1)))
|
||||
} returns mockException.asFailure()
|
||||
fakeAuthDiskSource.userState = MOCK_USER_STATE
|
||||
|
||||
vaultRepository.sync()
|
||||
|
||||
assertEquals(
|
||||
DataState.Error<VaultData>(error = mockException),
|
||||
vaultRepository.vaultDataStateFlow.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `sync with syncService Failure should update vaultDataStateFlow with an Error`() =
|
||||
runTest {
|
||||
val mockException = IllegalStateException(
|
||||
"sad",
|
||||
)
|
||||
coEvery {
|
||||
syncService.sync()
|
||||
} returns mockException.asFailure()
|
||||
|
||||
vaultRepository.sync()
|
||||
|
||||
assertEquals(
|
||||
DataState.Error(
|
||||
error = mockException,
|
||||
data = null,
|
||||
),
|
||||
vaultRepository.vaultDataStateFlow.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `sync with NoNetwork should update vaultDataStateFlow to NoNetwork`() =
|
||||
runTest {
|
||||
coEvery {
|
||||
syncService.sync()
|
||||
} returns UnknownHostException().asFailure()
|
||||
|
||||
vaultRepository.sync()
|
||||
|
||||
assertEquals(
|
||||
DataState.NoNetwork(
|
||||
data = null,
|
||||
),
|
||||
vaultRepository.vaultDataStateFlow.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `sync with NoNetwork data should update vaultDataStateFlow to NoNetwork with data`() =
|
||||
runTest {
|
||||
coEvery {
|
||||
syncService.sync()
|
||||
} returns Result.success(createMockSyncResponse(number = 1))
|
||||
coEvery {
|
||||
vaultSdkSource.decryptCipherList(listOf(createMockSdkCipher(1)))
|
||||
} returns listOf(createMockCipherListView(number = 1)).asSuccess()
|
||||
coEvery {
|
||||
vaultSdkSource.decryptFolderList(listOf(createMockSdkFolder(1)))
|
||||
} returns listOf(createMockFolderView(number = 1)).asSuccess()
|
||||
fakeAuthDiskSource.userState = MOCK_USER_STATE
|
||||
|
||||
vaultRepository.vaultDataStateFlow.test {
|
||||
assertEquals(
|
||||
DataState.Loading,
|
||||
awaitItem(),
|
||||
)
|
||||
vaultRepository.sync()
|
||||
assertEquals(
|
||||
DataState.Loaded(
|
||||
data = VaultData(
|
||||
cipherListViewList = listOf(createMockCipherListView(number = 1)),
|
||||
folderViewList = listOf(createMockFolderView(number = 1)),
|
||||
),
|
||||
),
|
||||
awaitItem(),
|
||||
)
|
||||
coEvery {
|
||||
syncService.sync()
|
||||
} returns UnknownHostException().asFailure()
|
||||
vaultRepository.sync()
|
||||
assertEquals(
|
||||
DataState.Pending(
|
||||
data = VaultData(
|
||||
cipherListViewList = listOf(createMockCipherListView(number = 1)),
|
||||
folderViewList = listOf(createMockFolderView(number = 1)),
|
||||
),
|
||||
),
|
||||
awaitItem(),
|
||||
)
|
||||
assertEquals(
|
||||
DataState.NoNetwork(
|
||||
data = VaultData(
|
||||
cipherListViewList = listOf(createMockCipherListView(number = 1)),
|
||||
folderViewList = listOf(createMockFolderView(number = 1)),
|
||||
),
|
||||
),
|
||||
awaitItem(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `unlockVaultAndSync with initializeCrypto Success should sync and return Success`() =
|
||||
@@ -66,10 +275,10 @@ class VaultRepositoryTest {
|
||||
} returns Result.success(createMockSyncResponse(number = 1))
|
||||
coEvery {
|
||||
vaultSdkSource.decryptCipherList(listOf(createMockSdkCipher(1)))
|
||||
} returns mockk()
|
||||
} returns listOf(createMockCipherListView(number = 1)).asSuccess()
|
||||
coEvery {
|
||||
vaultSdkSource.decryptFolderList(listOf(createMockSdkFolder(1)))
|
||||
} returns mockk()
|
||||
} returns listOf(createMockFolderView(number = 1)).asSuccess()
|
||||
fakeAuthDiskSource.storePrivateKey(
|
||||
userId = "mockUserId",
|
||||
privateKey = "mockPrivateKey-1",
|
||||
@@ -233,6 +442,45 @@ class VaultRepositoryTest {
|
||||
result,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `clearVaultData should update the vaultDataStateFlow to Loading`() =
|
||||
runTest {
|
||||
coEvery {
|
||||
syncService.sync()
|
||||
} returns Result.success(createMockSyncResponse(number = 1))
|
||||
coEvery {
|
||||
vaultSdkSource.decryptCipherList(listOf(createMockSdkCipher(1)))
|
||||
} returns listOf(createMockCipherListView(number = 1)).asSuccess()
|
||||
coEvery {
|
||||
vaultSdkSource.decryptFolderList(listOf(createMockSdkFolder(1)))
|
||||
} returns listOf(createMockFolderView(number = 1)).asSuccess()
|
||||
fakeAuthDiskSource.userState = MOCK_USER_STATE
|
||||
|
||||
vaultRepository.vaultDataStateFlow.test {
|
||||
assertEquals(
|
||||
DataState.Loading,
|
||||
awaitItem(),
|
||||
)
|
||||
vaultRepository.sync()
|
||||
assertEquals(
|
||||
DataState.Loaded(
|
||||
data = VaultData(
|
||||
cipherListViewList = listOf(createMockCipherListView(number = 1)),
|
||||
folderViewList = listOf(createMockFolderView(number = 1)),
|
||||
),
|
||||
),
|
||||
awaitItem(),
|
||||
)
|
||||
|
||||
vaultRepository.clearVaultData()
|
||||
|
||||
assertEquals(
|
||||
DataState.Loading,
|
||||
awaitItem(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val MOCK_USER_STATE = UserStateJson(
|
||||
|
||||
@@ -17,15 +17,15 @@ import com.x8bit.bitwarden.data.vault.datasource.network.model.createMockLogin
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.createMockPasswordHistory
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.createMockSecureNote
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.createMockUri
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.createMockSdkAttachment
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.createMockSdkCard
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.createMockSdkCipher
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.createMockSdkField
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.createMockSdkIdentity
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.createMockSdkLogin
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.createMockSdkPasswordHistory
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.createMockSdkSecureNote
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.createMockSdkUri
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockSdkAttachment
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockSdkCard
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockSdkCipher
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockSdkField
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockSdkIdentity
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockSdkLogin
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockSdkPasswordHistory
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockSdkSecureNote
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockSdkUri
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.x8bit.bitwarden.data.vault.repository.util
|
||||
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.createMockFolder
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.createMockSdkFolder
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockSdkFolder
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
|
||||
|
||||
Reference in New Issue
Block a user