BIT-448: Create collections database table (#408)

This commit is contained in:
David Perez
2023-12-18 09:55:04 -06:00
committed by GitHub
parent ba46983444
commit 9a27aaa5ad
8 changed files with 246 additions and 1 deletions

View File

@@ -4,11 +4,14 @@ import app.cash.turbine.test
import com.x8bit.bitwarden.data.platform.datasource.network.di.PlatformNetworkModule
import com.x8bit.bitwarden.data.util.assertJsonEquals
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.FakeCiphersDao
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.FakeCollectionsDao
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.FakeFoldersDao
import com.x8bit.bitwarden.data.vault.datasource.disk.entity.CipherEntity
import com.x8bit.bitwarden.data.vault.datasource.disk.entity.CollectionEntity
import com.x8bit.bitwarden.data.vault.datasource.disk.entity.FolderEntity
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
import com.x8bit.bitwarden.data.vault.datasource.network.model.createMockCipher
import com.x8bit.bitwarden.data.vault.datasource.network.model.createMockCollection
import com.x8bit.bitwarden.data.vault.datasource.network.model.createMockFolder
import io.mockk.every
import io.mockk.mockk
@@ -24,6 +27,7 @@ class VaultDiskSourceTest {
private val json = PlatformNetworkModule.providesJson()
private lateinit var ciphersDao: FakeCiphersDao
private lateinit var collectionsDao: FakeCollectionsDao
private lateinit var foldersDao: FakeFoldersDao
private lateinit var vaultDiskSource: VaultDiskSource
@@ -31,9 +35,11 @@ class VaultDiskSourceTest {
@BeforeEach
fun setup() {
ciphersDao = FakeCiphersDao()
collectionsDao = FakeCollectionsDao()
foldersDao = FakeFoldersDao()
vaultDiskSource = VaultDiskSourceImpl(
ciphersDao = ciphersDao,
collectionsDao = collectionsDao,
foldersDao = foldersDao,
json = json,
)
@@ -53,6 +59,20 @@ class VaultDiskSourceTest {
}
}
@Test
fun `getCollections should emit all CollectionsDao updates`() = runTest {
val collectionEntities = listOf(COLLECTION_ENTITY)
val collection = listOf(COLLECTION_1)
vaultDiskSource
.getCollections(USER_ID)
.test {
assertEquals(emptyList<SyncResponseJson.Collection>(), awaitItem())
collectionsDao.insertCollections(collectionEntities)
assertEquals(collection, awaitItem())
}
}
@Test
fun `getFolders should emit all FoldersDao updates`() = runTest {
val folderEntities = listOf(FOLDER_ENTITY)
@@ -70,6 +90,7 @@ class VaultDiskSourceTest {
@Test
fun `replaceVaultData should clear the daos and insert the new vault data`() = runTest {
assertEquals(ciphersDao.storedCiphers, emptyList<CipherEntity>())
assertEquals(collectionsDao.storedCollections, emptyList<CollectionEntity>())
assertEquals(foldersDao.storedFolders, emptyList<FolderEntity>())
vaultDiskSource.replaceVaultData(USER_ID, VAULT_DATA)
@@ -84,6 +105,9 @@ class VaultDiskSourceTest {
assertEquals(CIPHER_ENTITY.copy(cipherJson = ""), storedCipherEntity.copy(cipherJson = ""))
assertJsonEquals(CIPHER_ENTITY.cipherJson, storedCipherEntity.cipherJson)
// Verify the collections dao is updated
assertEquals(listOf(COLLECTION_ENTITY), collectionsDao.storedCollections)
// Verify the folders dao is updated
assertEquals(listOf(FOLDER_ENTITY), foldersDao.storedFolders)
}
@@ -91,9 +115,11 @@ class VaultDiskSourceTest {
@Test
fun `deleteVaultData should remove all vault data matching the user ID`() = runTest {
assertFalse(ciphersDao.deleteCiphersCalled)
assertFalse(collectionsDao.deleteCollectionsCalled)
assertFalse(foldersDao.deleteFoldersCalled)
vaultDiskSource.deleteVaultData(USER_ID)
assertTrue(ciphersDao.deleteCiphersCalled)
assertTrue(collectionsDao.deleteCollectionsCalled)
assertTrue(foldersDao.deleteFoldersCalled)
}
}
@@ -101,11 +127,12 @@ class VaultDiskSourceTest {
private const val USER_ID: String = "test_user_id"
private val CIPHER_1: SyncResponseJson.Cipher = createMockCipher(1)
private val COLLECTION_1: SyncResponseJson.Collection = createMockCollection(3)
private val FOLDER_1: SyncResponseJson.Folder = createMockFolder(2)
private val VAULT_DATA: SyncResponseJson = SyncResponseJson(
folders = listOf(FOLDER_1),
collections = null,
collections = listOf(COLLECTION_1),
profile = mockk<SyncResponseJson.Profile> {
every { id } returns USER_ID
},
@@ -217,6 +244,16 @@ private val CIPHER_ENTITY = CipherEntity(
cipherJson = CIPHER_JSON,
)
private val COLLECTION_ENTITY = CollectionEntity(
id = "mockId-3",
userId = USER_ID,
organizationId = "mockOrganizationId-3",
shouldHidePasswords = false,
name = "mockName-3",
externalId = "mockExternalId-3",
isReadOnly = false,
)
private val FOLDER_ENTITY = FolderEntity(
id = "mockId-2",
userId = USER_ID,

View File

@@ -0,0 +1,57 @@
package com.x8bit.bitwarden.data.vault.datasource.disk.dao
import com.x8bit.bitwarden.data.vault.datasource.disk.entity.CollectionEntity
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.map
class FakeCollectionsDao : CollectionsDao {
val storedCollections = mutableListOf<CollectionEntity>()
var deleteCollectionCalled: Boolean = false
var deleteCollectionsCalled: Boolean = false
private val collectionsFlow = MutableSharedFlow<List<CollectionEntity>>(
replay = 1,
extraBufferCapacity = Int.MAX_VALUE,
)
init {
collectionsFlow.tryEmit(emptyList())
}
override suspend fun deleteAllCollections(userId: String) {
deleteCollectionsCalled = true
storedCollections.removeAll { it.userId == userId }
collectionsFlow.tryEmit(storedCollections.toList())
}
override suspend fun deleteCollection(userId: String, collectionId: String) {
deleteCollectionCalled = true
storedCollections.removeAll { it.userId == userId && it.id == collectionId }
collectionsFlow.tryEmit(storedCollections.toList())
}
override fun getAllCollections(userId: String): Flow<List<CollectionEntity>> =
collectionsFlow.map { ciphers -> ciphers.filter { it.userId == userId } }
override suspend fun insertCollections(collections: List<CollectionEntity>) {
storedCollections.addAll(collections)
collectionsFlow.tryEmit(storedCollections.toList())
}
override suspend fun insertCollection(collection: CollectionEntity) {
storedCollections.add(collection)
collectionsFlow.tryEmit(storedCollections.toList())
}
override suspend fun replaceAllCollections(
userId: String,
collections: List<CollectionEntity>,
) {
storedCollections.removeAll { it.userId == userId }
storedCollections.addAll(collections)
collectionsFlow.tryEmit(storedCollections.toList())
}
}