diff --git a/db/build.gradle b/db/build.gradle index aea3506b..0ea696f2 100644 --- a/db/build.gradle +++ b/db/build.gradle @@ -91,4 +91,5 @@ dependencies { testImplementation(libs.bundles.kointest) implementation(libs.bundles.coroutines) + androidTestImplementation(libs.coroutines.test) } diff --git a/db/src/androidTest/java/com/readrops/db/dao/NewFolderDaoTest.kt b/db/src/androidTest/java/com/readrops/db/dao/NewFolderDaoTest.kt new file mode 100644 index 00000000..9836708c --- /dev/null +++ b/db/src/androidTest/java/com/readrops/db/dao/NewFolderDaoTest.kt @@ -0,0 +1,72 @@ +package com.readrops.db.dao + +import android.content.Context +import androidx.room.Room +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.readrops.db.Database +import com.readrops.db.entities.Folder +import com.readrops.db.entities.account.Account +import com.readrops.db.entities.account.AccountType +import junit.framework.TestCase.assertFalse +import junit.framework.TestCase.assertTrue +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.test.runTest +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class NewFolderDaoTest { + + private lateinit var database: Database + private lateinit var account: Account + + @Before + fun before() = runTest { + val context = ApplicationProvider.getApplicationContext() + database = Room.inMemoryDatabaseBuilder(context, Database::class.java).build() + + account = Account(accountType = AccountType.LOCAL).apply { + id = database.newAccountDao().insert(this).toInt() + } + + repeat(2) { time -> + database.newFolderDao().insert( + Folder( + name = "Folder $time", + remoteId = "folder_$time", + accountId = account.id + ) + ) + } + } + + @After + fun after() { + database.close() + } + + @Test + fun upsertFoldersTest() = runTest { + val remoteFolders = listOf( + // updated folder + Folder(name = "New Folder 0", remoteId = "folder_0", accountId = account.id), + + // removed folder + //Folder(name = "Folder 1", remoteId = "folder_1"), + + // new inserted Folder + Folder(name = "Folder 2", remoteId = "folder_2", accountId = account.id) + ) + + database.newFolderDao().upsertFolders(remoteFolders, account) + val allFolders = database.newFolderDao().selectFolders(account.id).first() + + assertTrue(allFolders.any { it.name == "New Folder 0" }) + + assertFalse(allFolders.any { it.remoteId == "folder_1" }) + assertTrue(allFolders.any { it.remoteId == "folder_2" }) + } +} \ No newline at end of file diff --git a/db/src/main/java/com/readrops/db/dao/newdao/NewFolderDao.kt b/db/src/main/java/com/readrops/db/dao/newdao/NewFolderDao.kt index e7cfa4cd..f21122c7 100644 --- a/db/src/main/java/com/readrops/db/dao/newdao/NewFolderDao.kt +++ b/db/src/main/java/com/readrops/db/dao/newdao/NewFolderDao.kt @@ -2,7 +2,9 @@ package com.readrops.db.dao.newdao import androidx.room.Dao import androidx.room.Query +import androidx.room.Transaction import com.readrops.db.entities.Folder +import com.readrops.db.entities.account.Account import com.readrops.db.pojo.FolderWithFeed import kotlinx.coroutines.flow.Flow @@ -29,4 +31,38 @@ interface NewFolderDao : NewBaseDao { @Query("Select * From Folder Where name = :name And account_id = :accountId") suspend fun selectFolderByName(name: String, accountId: Int): Folder? + + @Query("Select remoteId From Folder Where account_id = :accountId") + suspend fun selectFolderRemoteIds(accountId: Int): List + + @Query("Update Folder set name = :name Where remoteId = :remoteId And account_id = :accountId") + suspend fun updateFolderName(name: String, remoteId: String, accountId: Int) + + @Query("Delete From Folder Where remoteId in (:ids) And account_id = :accountId") + suspend fun deleteByIds(ids: List, accountId: Int) + + /** + * Insert, update and delete folders + * + * @param folders folders to insert or update + * @param account owner of the feeds + * @return the list of the inserted folders ids + */ + @Transaction + suspend fun upsertFolders(folders: List, account: Account): List { + val localFolderIds = selectFolderRemoteIds(account.id) + + val foldersToInsert = folders.filter { folder -> localFolderIds.none { localFolderId -> folder.remoteId == localFolderId } } + val foldersToDelete = localFolderIds.filter { localFolderId -> folders.none { folder -> localFolderId == folder.remoteId } } + + // folders to update + folders.filter { folder -> localFolderIds.any { localFolderId -> folder.remoteId == localFolderId} } + .forEach { updateFolderName(it.name!!, it.remoteId!!, account.id) } + + if (foldersToDelete.isNotEmpty()) { + deleteByIds(foldersToDelete, account.id) + } + + return insert(foldersToInsert) + } } \ No newline at end of file