From 4317a803cd34d986923420c5199a273e78ed91c0 Mon Sep 17 00:00:00 2001 From: SkyD666 Date: Thu, 12 Dec 2024 16:42:04 +0800 Subject: [PATCH] [build|test] Update dependencies; add test code [skip_post] --- app/build.gradle.kts | 1 + .../java/com/skyd/anivu/RssModule.kt | 778 +++++++++++++++++- .../skyd/anivu/model/bean/group/GroupVo.kt | 4 + .../com/skyd/anivu/model/db/dao/GroupDao.kt | 13 +- .../model/repository/feed/FeedRepository.kt | 7 +- .../anivu/ui/screen/feed/FeedViewModel.kt | 2 +- gradle/libs.versions.toml | 4 +- 7 files changed, 796 insertions(+), 13 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 1d61ba3b..d616a723 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -243,4 +243,5 @@ dependencies { androidTestImplementation(libs.kotlinx.coroutines.test) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) + androidTestImplementation(libs.androidx.paging.test) } \ No newline at end of file diff --git a/app/src/androidTest/java/com/skyd/anivu/RssModule.kt b/app/src/androidTest/java/com/skyd/anivu/RssModule.kt index 1f738d94..10ec83e8 100644 --- a/app/src/androidTest/java/com/skyd/anivu/RssModule.kt +++ b/app/src/androidTest/java/com/skyd/anivu/RssModule.kt @@ -1,18 +1,26 @@ package com.skyd.anivu import android.content.Context +import android.net.Uri import androidx.paging.PagingConfig +import androidx.paging.testing.asSnapshot +import androidx.sqlite.db.SimpleSQLiteQuery import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory import com.skyd.anivu.base.mvi.mviViewModelNeedMainThread import com.skyd.anivu.config.Const +import com.skyd.anivu.model.bean.article.ARTICLE_TABLE_NAME +import com.skyd.anivu.model.bean.article.ArticleBean +import com.skyd.anivu.model.bean.feed.FEED_VIEW_NAME +import com.skyd.anivu.model.bean.feed.FeedBean import com.skyd.anivu.model.bean.group.GroupVo import com.skyd.anivu.model.db.AppDatabase import com.skyd.anivu.model.db.dao.ArticleDao import com.skyd.anivu.model.db.dao.FeedDao import com.skyd.anivu.model.db.dao.GroupDao import com.skyd.anivu.model.repository.ArticleRepository +import com.skyd.anivu.model.repository.ArticleSort import com.skyd.anivu.model.repository.ReadRepository import com.skyd.anivu.model.repository.RssHelper import com.skyd.anivu.model.repository.SearchRepository @@ -35,6 +43,7 @@ import org.junit.runner.RunWith import org.junit.runners.MethodSorters import retrofit2.Retrofit import java.io.IOException +import java.util.UUID /** @@ -79,25 +88,781 @@ class RssModule { private lateinit var requestHeadersRepository: RequestHeadersRepository + /** + * Pass + * feedRepository.requestGroupAnyList + */ @Test - fun test1RequestGroupAnyList() = runTest { + fun test1() = runTest { feedRepository.requestGroupAnyList().first().also { assertTrue(it[0] is GroupVo.DefaultGroup) } } + /** + * Pass + * feedRepository.setFeed + * feedDao.getFeed + */ @Test - fun test2SetFeed() = runTest { + fun test2() = runTest { feedRepository.setFeed( url = "https://blogs.nvidia.cn/feed/", groupId = null, nickname = "Nvidia", - ).first().also { - assertTrue( - it.url == "https://blogs.nvidia.cn/feed/" && - it.groupId == null && it.nickname == "Nvidia" + ).first() + feedDao.getFeed("https://blogs.nvidia.cn/feed/").apply { + assertTrue(groupId == null && nickname == "Nvidia") + } + } + + /** + * Pass + * feedRepository.setFeed + * articleRepository.requestArticleList + * feedRepository.clearFeedArticles + */ + @Test + fun test3() = runTest { + val url1 = "https://www.ximalaya.com/album/68370676.xml" + val url2 = "https://blogs.nvidia.cn/feed/" + feedRepository.setFeed(url = url1, groupId = null, nickname = null).first() + feedRepository.setFeed(url = url2, groupId = null, nickname = null).first() + articleRepository.requestArticleList( + feedUrls = listOf(url1, url2), + articleIds = emptyList(), + ).apply { + assertTrue(asSnapshot().run { + firstOrNull { it.feed.url == url1 } != null && + firstOrNull { it.feed.url == url2 } != null + }) + } + feedRepository.clearFeedArticles(url = url1).first() + articleRepository.requestArticleList( + feedUrls = listOf(url1, url2), + articleIds = emptyList(), + ).apply { + assertTrue(asSnapshot().run { + firstOrNull { it.feed.url == url1 } == null && + firstOrNull { it.feed.url == url2 } != null + }) + } + } + + /** + * Pass + * feedRepository.setFeed + * feedDao.getFeed + * feedRepository.createGroup + * feedRepository.editFeedGroup + * feedRepository.moveGroupFeedsTo + * feedRepository.renameGroup + * feedDao.getFeedsByGroupId + * groupDao.getGroupById + * feedRepository.removeFeed + * feedDao.containsByUrl + * feedRepository.deleteGroup + */ + @Test + fun test4() = runTest { + val url1 = "https://www.ximalaya.com/album/68370676.xml" + val url2 = "https://blogs.nvidia.cn/feed/" + feedRepository.setFeed(url = url1, groupId = null, nickname = null).first() + feedRepository.setFeed(url = url2, groupId = null, nickname = null).first() + + articleRepository.requestArticleList( + feedUrls = listOf(url1, url2), + articleIds = emptyList(), + ).apply { + assertTrue(asSnapshot().run { + firstOrNull { it.feed.url == url1 } != null && + firstOrNull { it.feed.url == url2 } != null + }) + } + + val groupId = UUID.randomUUID().toString() + feedRepository.createGroup( + GroupVo(groupId = groupId, name = "text", isExpanded = true) + ).first() + + feedRepository.editFeedGroup(url1, groupId).first() + assertTrue(feedDao.getFeed(url1).groupId == groupId) + + feedRepository.moveGroupFeedsTo(GroupVo.DEFAULT_GROUP_ID, groupId).first() + assertTrue(feedDao.getFeedsByGroupId(null).isEmpty()) + + feedRepository.renameGroup(groupId, "text2").first() + assertTrue(groupDao.getGroupById(groupId).name == "text2") + + feedRepository.removeFeed(url1).first() + assertTrue(feedDao.containsByUrl(url1) == 0) + + feedRepository.deleteGroup(groupId).first() + assertTrue(feedDao.containsByUrl(url2) == 0) + } + + /** + * Pass + * feedRepository.createGroup + * groupDao.getGroupById + * feedRepository.changeGroupExpanded + */ + @Test + fun test5() = runTest { + val groupId = UUID.randomUUID().toString() + feedRepository.createGroup( + GroupVo(groupId = groupId, name = "test5", isExpanded = true) + ).first() + assertTrue(groupDao.getGroupById(groupId).isExpanded) + feedRepository.changeGroupExpanded(groupId, false).first() + assertFalse(groupDao.getGroupById(groupId).isExpanded) + } + + /** + * Pass + * feedRepository.createGroup + * feedRepository.setFeed + * articleRepository.requestArticleList + * feedRepository.readAllInFeed + * articleRepository.favoriteArticle + * articleRepository.refreshArticleList + * feedRepository.clearFeedArticles + */ + @Test + fun test6() = runTest { + val url1 = "https://blogs.nvidia.cn/feed/" + val groupId = UUID.randomUUID().toString() + feedRepository.createGroup( + GroupVo(groupId = groupId, name = "test6", isExpanded = true) + ).first() + feedRepository.setFeed(url = url1, groupId = null, nickname = null).first() + articleRepository.requestArticleList( + feedUrls = listOf(url1), + articleIds = emptyList(), + ).apply { + assertTrue(asSnapshot().all { !it.articleWithEnclosure.article.isRead }) + } + feedRepository.readAllInFeed(url1).first() + articleRepository.requestArticleList( + feedUrls = listOf(url1), + articleIds = emptyList(), + ).apply { + assertTrue(asSnapshot().all { it.articleWithEnclosure.article.isRead }) + } + + feedRepository.clearFeedArticles(url1).first() + articleRepository.refreshArticleList(feedUrls = listOf(url1)).first() + val article = articleRepository.requestArticleList( + feedUrls = listOf(url1), + articleIds = emptyList(), + ).asSnapshot().first() + val articleId = article.articleWithEnclosure.article.articleId + articleRepository.favoriteArticle( + articleId = articleId, + favorite = true, + ).first() + assertTrue( + articleDao.getArticleWithFeed(articleId) + .first()?.articleWithEnclosure?.article?.isFavorite == true + ) + } + + /** + * Pass + * feedRepository.setFeed + * feedRepository.clearFeedArticles + * feedDao.getFeedsByGroupId + * articleRepository.refreshGroupArticles + */ + @Test + fun test7() = runTest { + val url1 = "https://blogs.nvidia.cn/feed/" + feedRepository.setFeed(url = url1, groupId = null, nickname = null).first() + feedRepository.clearFeedArticles(url1).first() + assertTrue(feedDao.getFeedsByGroupId(null).first().articleCount == 0) + + articleRepository.refreshGroupArticles(null).first() + assertTrue(feedDao.getFeedsByGroupId(null).first().articleCount > 0) + } + + /** + * Pass + * feedRepository.setFeed + * articleRepository.requestArticleList + * articleRepository.readArticle + * articleDao.getArticleWithFeed + */ + @Test + fun test8() = runTest { + val url1 = "https://blogs.nvidia.cn/feed/" + feedRepository.setFeed(url = url1, groupId = null, nickname = null).first() + val article = articleRepository.requestArticleList( + feedUrls = listOf(url1), + articleIds = emptyList(), + ).asSnapshot().first() + val articleId = article.articleWithEnclosure.article.articleId + assertFalse(article.articleWithEnclosure.article.isRead) + articleRepository.readArticle(articleId, true).first() + assertTrue( + articleDao.getArticleWithFeed(articleId) + .first()?.articleWithEnclosure?.article?.isRead == true + ) + } + + /** + * Pass + * feedRepository.setFeed + * searchRepository.updateQuery + * searchRepository.listenSearchFeed + * articleDao.innerUpdateArticle + * searchRepository.listenSearchArticle + */ + @Test + fun test9() = runTest { + val url1 = "https://blogs.nvidia.cn/feed/" + feedRepository.setFeed(url = url1, groupId = null, nickname = "Nvidia").first() + searchRepository.updateQuery("Nvidia") + assertTrue(searchRepository.listenSearchFeed().asSnapshot().first().feed.url == url1) + val article = articleRepository.requestArticleList( + feedUrls = listOf(url1), + articleIds = emptyList(), + ).asSnapshot().first() + val realArticle = article.articleWithEnclosure.article + articleDao.innerUpdateArticle(realArticle.copy(title = "test9")) + assertTrue( + searchRepository.listenSearchArticle(listOf(url1), emptyList()) + .asSnapshot() + .any { it.articleWithEnclosure.article.articleId == realArticle.articleId } + ) + } + + /** + * Pass + * feedRepository.setFeed + * articleRepository.requestArticleList + * readRepository.requestArticleWithFeed + */ + @Test + fun test10() = runTest { + val url1 = "https://blogs.nvidia.cn/feed/" + feedRepository.setFeed(url = url1, groupId = null, nickname = "Nvidia").first() + val article = articleRepository.requestArticleList( + feedUrls = listOf(url1), + articleIds = emptyList(), + ).asSnapshot().first() + assertEquals( + readRepository.requestArticleWithFeed(article.articleWithEnclosure.article.articleId) + .first(), article + ) + } + + /** + * Pass + * feedRepository.createGroup + * reorderGroupRepository.requestGroupList + * reorderGroupRepository.requestReorderGroup + * reorderGroupRepository.requestResetGroupOrder + */ + @Test + fun test11() = runTest { + val groupId1 = UUID.randomUUID().toString() + val groupId2 = UUID.randomUUID().toString() + val groupId3 = UUID.randomUUID().toString() + feedRepository.createGroup( + GroupVo(groupId = groupId1, name = "test11-1", isExpanded = true) + ).first() + feedRepository.createGroup( + GroupVo(groupId = groupId2, name = "test11-2", isExpanded = true) + ).first() + feedRepository.createGroup( + GroupVo(groupId = groupId3, name = "test11-3", isExpanded = true) + ).first() + assertTrue(reorderGroupRepository.requestGroupList().first().run { + get(0).groupId == groupId1 && get(1).groupId == groupId2 && get(2).groupId == groupId3 + }) + + reorderGroupRepository.requestReorderGroup( + movedGroupId = groupId3, newPreviousGroupId = groupId1, newNextGroupId = groupId2 + ).first() + assertTrue(reorderGroupRepository.requestGroupList().first().run { + get(0).groupId == groupId1 && get(1).groupId == groupId3 && get(2).groupId == groupId2 + }) + reorderGroupRepository.requestResetGroupOrder().first() + assertTrue(reorderGroupRepository.requestGroupList().first().run { + get(0).groupId == groupId1 && get(1).groupId == groupId2 && get(2).groupId == groupId3 + }) + } + + /** + * Pass + * feedRepository.setFeed + * requestHeadersRepository.getFeedHeaders + * requestHeadersRepository.updateFeedHeaders + */ + @Test + fun test12() = runTest { + val url1 = "https://blogs.nvidia.cn/feed/" + feedRepository.setFeed(url = url1, groupId = null, nickname = null).first() + assertTrue(requestHeadersRepository.getFeedHeaders(url1).first()?.headers.isNullOrEmpty()) + + requestHeadersRepository.updateFeedHeaders( + url1, FeedBean.RequestHeaders( + mapOf("Content-Type" to "text/xml; charset=utf-8") ) + ).first() + assertTrue( + requestHeadersRepository.getFeedHeaders(url1).first()!!.run { + headers.size == 1 && headers["Content-Type"] == "text/xml; charset=utf-8" + } + ) + } + + /** + * Pass + * feedRepository.setFeed + * articleRepository.requestArticleList + * readRepository.requestArticleWithFeed + */ + @Test + fun test13() = runTest { + val url1 = "https://blogs.nvidia.cn/feed/" + feedRepository.setFeed(url = url1, groupId = null, nickname = "Nvidia").first() + val article = articleRepository.requestArticleList( + feedUrls = listOf(url1), + articleIds = emptyList(), + ).asSnapshot().first() + assertEquals( + readRepository.requestArticleWithFeed(article.articleWithEnclosure.article.articleId) + .first(), article + ) + } + + /** + * Pass + * feedRepository.setFeed + * feedDao.getFeed + * feedRepository.editFeedCustomDescription + */ + @Test + fun test14() = runTest { + val url1 = "https://blogs.nvidia.cn/feed/" + feedRepository.setFeed(url = url1, groupId = null, nickname = null).first() + feedRepository.editFeedCustomDescription(url1, "test13").first() + assertEquals(feedDao.getFeed(url1).customDescription, "test13") + } + + /** + * Pass + * feedRepository.setFeed + * feedDao.getFeed + * feedRepository.editFeedNickname + */ + @Test + fun test15() = runTest { + val url1 = "https://blogs.nvidia.cn/feed/" + feedRepository.setFeed(url = url1, groupId = null, nickname = null).first() + feedRepository.editFeedNickname(url1, "nickname test13").first() + assertEquals(feedDao.getFeed(url1).nickname, "nickname test13") + } + + /** + * Pass + * feedRepository.setFeed + * feedDao.getFeed + * feedRepository.editFeedCustomIcon + */ + @Test + fun test16() = runTest { + val url1 = "https://blogs.nvidia.cn/feed/" + feedRepository.setFeed(url = url1, groupId = null, nickname = null).first() + val icon = + "https://www.gstatic.com/devrel-devsite/prod/v3239347c48d1e3c46204782fd038ba187a6753dfa7d7a0d08a574587ae2085f5/android/images/lockup.svg" + feedRepository.editFeedCustomIcon(url1, Uri.parse(icon)).first() + assertEquals(feedDao.getFeed(url1).customIcon, icon) + } + + /** + * Pass + * feedRepository.setFeed + * feedDao.getFeed + * feedRepository.editFeedSortXmlArticlesOnUpdate + */ + @Test + fun test17() = runTest { + val url1 = "https://blogs.nvidia.cn/feed/" + feedRepository.setFeed(url = url1, groupId = null, nickname = null).first() + feedRepository.editFeedSortXmlArticlesOnUpdate(url1, true).first() + assertTrue(feedDao.getFeed(url1).sortXmlArticlesOnUpdate) + feedRepository.editFeedSortXmlArticlesOnUpdate(url1, false).first() + assertFalse(feedDao.getFeed(url1).sortXmlArticlesOnUpdate) + } + + /** + * Pass + * feedRepository.setFeed + * feedRepository.clearGroupArticles + * feedDao.getFeedsByGroupId + */ + @Test + fun test18() = runTest { + val url1 = "https://blogs.nvidia.cn/feed/" + feedRepository.setFeed(url = url1, groupId = null, nickname = null).first() + feedRepository.clearGroupArticles(GroupVo.DEFAULT_GROUP_ID).first() + assertTrue(feedDao.getFeedsByGroupId(null).all { it.articleCount == 0 }) + } + + /** + * Pass + * feedRepository.setFeed + * articleRepository.requestArticleList + * articleDao.queryArticleByGuid + */ + @Test + fun test19() = runTest { + val url1 = "https://blogs.nvidia.cn/feed/" + feedRepository.setFeed(url = url1, groupId = null, nickname = "Nvidia").first() + val article = articleRepository.requestArticleList( + feedUrls = listOf(url1), + articleIds = emptyList(), + ).asSnapshot().first { it.articleWithEnclosure.article.guid != null } + assertEquals( + article.articleWithEnclosure.article.articleId, + articleDao.queryArticleByGuid( + article.articleWithEnclosure.article.guid!!, + url1 + )?.articleId + ) + } + + /** + * Pass + * feedRepository.setFeed + * articleRepository.requestArticleList + * articleDao.queryArticleByLink + */ + @Test + fun test20() = runTest { + val url1 = "https://blogs.nvidia.cn/feed/" + feedRepository.setFeed(url = url1, groupId = null, nickname = "Nvidia").first() + val article = articleRepository.requestArticleList( + feedUrls = listOf(url1), + articleIds = emptyList(), + ).asSnapshot().first { it.articleWithEnclosure.article.link != null } + assertEquals( + article.articleWithEnclosure.article.link, + articleDao.queryArticleByLink( + article.articleWithEnclosure.article.link!!, + url1 + )?.link + ) + } + + /** + * Pass + * feedRepository.setFeed + * articleRepository.requestArticleList + * articleDao.queryLatestByFeedUrl + */ + @Test + fun test21() = runTest { + val url1 = "https://blogs.nvidia.cn/feed/" + feedRepository.setFeed(url = url1, groupId = null, nickname = "Nvidia").first() + val article = articleRepository.requestArticleList( + feedUrls = listOf(url1), + articleIds = emptyList(), + ).asSnapshot().maxBy { it.articleWithEnclosure.article.date ?: 0 } + assertEquals( + article.articleWithEnclosure.article.articleId, + articleDao.queryLatestByFeedUrl(url1)?.articleId + ) + } + + /** + * Pass + * feedRepository.setFeed + * articleDao.readAllInGroup + */ + @Test + fun test22() = runTest { + val url1 = "https://blogs.nvidia.cn/feed/" + feedRepository.setFeed(url = url1, groupId = null, nickname = "Nvidia").first() + articleDao.readAllInGroup(null) + assertTrue(articleRepository.requestArticleList( + feedUrls = feedDao.getFeedsByGroupId(null).map { it.feed.url }, + articleIds = emptyList(), + ).asSnapshot().all { it.articleWithEnclosure.article.isRead }) + } + + /** + * Pass + * feedRepository.createGroup + * reorderGroupRepository.requestGroupList + * reorderGroupRepository.requestReorderGroup + * reorderGroupRepository.requestResetGroupOrder + */ + @Test + fun test23() = runTest { + val groupId1 = UUID.randomUUID().toString() + val groupId2 = UUID.randomUUID().toString() + val groupId3 = UUID.randomUUID().toString() + feedRepository.createGroup( + GroupVo(groupId = groupId1, name = "test23-1", isExpanded = true) + ).first() + feedRepository.createGroup( + GroupVo(groupId = groupId2, name = "test23-2", isExpanded = true) + ).first() + feedRepository.createGroup( + GroupVo(groupId = groupId3, name = "test23-3", isExpanded = true) + ).first() + assertTrue(reorderGroupRepository.requestGroupList().first().run { + get(0).groupId == groupId1 && get(1).groupId == groupId2 && get(2).groupId == groupId3 + }) + + assertFalse( + reorderGroupRepository.requestReorderGroup( + movedGroupId = groupId3, newPreviousGroupId = groupId3, newNextGroupId = groupId3 + ).first() + ) + assertTrue(reorderGroupRepository.requestGroupList().first().run { + get(0).groupId == groupId1 && get(1).groupId == groupId2 && get(2).groupId == groupId3 + }) + } + + /** + * Pass + * feedRepository.createGroup + * reorderGroupRepository.requestGroupList + * reorderGroupRepository.requestReorderGroup + * reorderGroupRepository.requestResetGroupOrder + */ + @Test + fun test24() = runTest { + val groupId1 = UUID.randomUUID().toString() + val groupId2 = UUID.randomUUID().toString() + val groupId3 = UUID.randomUUID().toString() + feedRepository.createGroup( + GroupVo(groupId = groupId1, name = "test24-1", isExpanded = true) + ).first() + feedRepository.createGroup( + GroupVo(groupId = groupId2, name = "test24-2", isExpanded = true) + ).first() + feedRepository.createGroup( + GroupVo(groupId = groupId3, name = "test24-3", isExpanded = true) + ).first() + assertTrue(reorderGroupRepository.requestGroupList().first().run { + get(0).groupId == groupId1 && get(1).groupId == groupId2 && get(2).groupId == groupId3 + }) + + assertFalse( + reorderGroupRepository.requestReorderGroup( + movedGroupId = "fakeId", newPreviousGroupId = "fakeId2", newNextGroupId = "fakeId3" + ).first() + ) + assertTrue(reorderGroupRepository.requestGroupList().first().run { + get(0).groupId == groupId1 && get(1).groupId == groupId2 && get(2).groupId == groupId3 + }) + } + + /** + * Pass + * feedRepository.createGroup + * reorderGroupRepository.requestGroupList + * reorderGroupRepository.requestReorderGroup + * reorderGroupRepository.requestResetGroupOrder + */ + @Test + fun test25() = runTest { + val groupId1 = UUID.randomUUID().toString() + val groupId2 = UUID.randomUUID().toString() + val groupId3 = UUID.randomUUID().toString() + feedRepository.createGroup( + GroupVo(groupId = groupId1, name = "test25-1", isExpanded = true) + ).first() + feedRepository.createGroup( + GroupVo(groupId = groupId2, name = "test25-2", isExpanded = true) + ).first() + feedRepository.createGroup( + GroupVo(groupId = groupId3, name = "test25-3", isExpanded = true) + ).first() + assertTrue(reorderGroupRepository.requestGroupList().first().run { + get(0).groupId == groupId1 && get(1).groupId == groupId2 && get(2).groupId == groupId3 + }) + + assertFalse( + reorderGroupRepository.requestReorderGroup( + movedGroupId = GroupVo.DEFAULT_GROUP_ID, + newPreviousGroupId = groupId3, + newNextGroupId = groupId2 + ).first() + ) + assertTrue(reorderGroupRepository.requestGroupList().first().run { + get(0).groupId == groupId1 && get(1).groupId == groupId2 && get(2).groupId == groupId3 + }) + } + + /** + * Pass + * feedRepository.setFeed + * searchRepository.updateQuery + * articleDao.getArticleList + * searchRepository.listenSearchArticle + */ + @Test + fun test26() = runTest { + val url1 = "https://blogs.nvidia.cn/feed/" + feedRepository.setFeed(url = url1, groupId = null, nickname = "Nvidia").first() + searchRepository.updateQuery("") + val excepted = + articleDao.getArticleList(SimpleSQLiteQuery("SELECT * FROM $ARTICLE_TABLE_NAME")) + val itemsSnapshot = + searchRepository.listenSearchArticle(feedDao.getAllFeedUrl(), emptyList()).asSnapshot { + scrollTo(excepted.size) + } + assertEquals(excepted, itemsSnapshot) + } + + /** + * Pass + * feedRepository.setFeed + * searchRepository.updateQuery + * feedDao.getFeedList + * searchRepository.listenSearchFeed + */ + @Test + fun test27() = runTest { + val url1 = "https://blogs.nvidia.cn/feed/" + val url2 = "https://www.ximalaya.com/album/68370676.xml" + feedRepository.setFeed(url = url1, groupId = null, nickname = "Nvidia").first() + feedRepository.setFeed(url = url2, groupId = null, nickname = null).first() + searchRepository.updateQuery("") + val excepted = feedDao.getFeedList(SimpleSQLiteQuery("SELECT * FROM $FEED_VIEW_NAME")) + val itemsSnapshot = searchRepository.listenSearchFeed().asSnapshot { + scrollTo(excepted.size) } + assertEquals(excepted, itemsSnapshot) + } + + /** + * Pass + * feedRepository.setFeed + * articleRepository.updateSort + * articleDao.getArticleList + * articleRepository.requestArticleList + */ + @Test + fun test28() = runTest { + val url1 = "https://blogs.nvidia.cn/feed/" + feedRepository.setFeed(url = url1, groupId = null, nickname = "Nvidia").first() + articleRepository.updateSort(ArticleSort.Date(asc = true)) + val excepted = + articleDao.getArticleList(SimpleSQLiteQuery("SELECT * FROM $ARTICLE_TABLE_NAME")) + .sortedBy { it.articleWithEnclosure.article.date } + val itemsSnapshot = + articleRepository.requestArticleList(listOf(url1), emptyList()).asSnapshot { + scrollTo(excepted.size) + } + assertEquals(excepted, itemsSnapshot) + } + + /** + * Pass + * feedRepository.setFeed + * articleRepository.updateSort + * articleDao.getArticleList + * articleRepository.requestArticleList + */ + @Test + fun test29() = runTest { + val url1 = "https://blogs.nvidia.cn/feed/" + feedRepository.setFeed(url = url1, groupId = null, nickname = "Nvidia").first() + articleRepository.updateSort(ArticleSort.Title(asc = false)) + val excepted = + articleDao.getArticleList(SimpleSQLiteQuery("SELECT * FROM $ARTICLE_TABLE_NAME")) + .sortedByDescending { it.articleWithEnclosure.article.title } + val itemsSnapshot = + articleRepository.requestArticleList(listOf(url1), emptyList()).asSnapshot { + scrollTo(excepted.size) + } + assertEquals(excepted, itemsSnapshot) + } + + /** + * Pass + * feedRepository.setFeed + * articleDao.readAllInFeed + * articleRepository.filterRead + * articleDao.getArticleList + * articleRepository.requestArticleList + */ + @Test + fun test30() = runTest { + val url1 = "https://blogs.nvidia.cn/feed/" + val url2 = "https://www.ximalaya.com/album/68370676.xml" + feedRepository.setFeed(url = url1, groupId = null, nickname = "Nvidia").first() + feedRepository.setFeed(url = url2, groupId = null, nickname = null).first() + articleDao.readAllInFeed(url1) + articleRepository.filterRead(true) + val excepted = + articleDao.getArticleList(SimpleSQLiteQuery("SELECT * FROM $ARTICLE_TABLE_NAME WHERE ${ArticleBean.FEED_URL_COLUMN} = \"$url1\"")) + val itemsSnapshot = + articleRepository.requestArticleList(listOf(url1, url2), emptyList()).asSnapshot { + scrollTo(excepted.size) + } + assertEquals(excepted, itemsSnapshot) + } + + /** + * Pass + * feedRepository.setFeed + * articleDao.favoriteArticle + * articleDao.getArticleWithFeed + * articleRepository.filterFavorite + * articleRepository.updateSort + * articleRepository.requestArticleList + */ + @Test + fun test31() = runTest { + val url1 = "https://blogs.nvidia.cn/feed/" + feedRepository.setFeed(url = url1, groupId = null, nickname = "Nvidia").first() + val (article1, article2) = articleRepository.requestArticleList( + feedUrls = listOf(url1), + articleIds = emptyList(), + ).asSnapshot { scrollTo(1) } + articleDao.favoriteArticle(article1.articleWithEnclosure.article.articleId, true) + articleDao.favoriteArticle(article2.articleWithEnclosure.article.articleId, true) + val newArticle1 = + articleDao.getArticleWithFeed(article1.articleWithEnclosure.article.articleId).first()!! + val newArticle2 = + articleDao.getArticleWithFeed(article2.articleWithEnclosure.article.articleId).first()!! + articleRepository.filterFavorite(true) + articleRepository.updateSort(ArticleSort.Date(asc = false)) + val excepted = listOf(newArticle1, newArticle2) + .sortedByDescending { it.articleWithEnclosure.article.date } + val itemsSnapshot = + articleRepository.requestArticleList(listOf(url1), emptyList()).asSnapshot { + scrollTo(excepted.size) + } + assertEquals(excepted, itemsSnapshot) + } + + /** + * Pass + * feedRepository.setFeed + * articleDao.readAllInFeed + * articleRepository.updateSort + * articleRepository.filterRead + * articleRepository.requestArticleList + */ + @Test + fun test32() = runTest { + val url1 = "https://blogs.nvidia.cn/feed/" + feedRepository.setFeed(url = url1, groupId = null, nickname = "Nvidia").first() + articleDao.readAllInFeed(url1) + articleRepository.updateSort(ArticleSort.Title(asc = false)) + articleRepository.filterRead(false) + assertTrue( + articleRepository.requestArticleList(listOf(url1), emptyList()).asSnapshot().isEmpty() + ) } @Before @@ -115,6 +880,7 @@ class RssModule { FeedRepository(groupDao, feedDao, articleDao, reorderGroupRepository, rssHelper) articleRepository = ArticleRepository(feedDao, articleDao, rssHelper, pagingConfig) searchRepository = SearchRepository(feedDao, articleDao, pagingConfig) + readRepository = ReadRepository(articleDao) requestHeadersRepository = RequestHeadersRepository(feedDao) } diff --git a/app/src/main/java/com/skyd/anivu/model/bean/group/GroupVo.kt b/app/src/main/java/com/skyd/anivu/model/bean/group/GroupVo.kt index 87610f93..bed90779 100644 --- a/app/src/main/java/com/skyd/anivu/model/bean/group/GroupVo.kt +++ b/app/src/main/java/com/skyd/anivu/model/bean/group/GroupVo.kt @@ -21,6 +21,10 @@ open class GroupVo( return GroupBean(groupId, name, null, null, isExpanded = isExpanded) } + override fun toString(): String { + return "groupId: $groupId, name: $name, isExpanded: $isExpanded" + } + object DefaultGroup : GroupVo( DEFAULT_GROUP_ID, diff --git a/app/src/main/java/com/skyd/anivu/model/db/dao/GroupDao.kt b/app/src/main/java/com/skyd/anivu/model/db/dao/GroupDao.kt index aa940b64..d7708641 100644 --- a/app/src/main/java/com/skyd/anivu/model/db/dao/GroupDao.kt +++ b/app/src/main/java/com/skyd/anivu/model/db/dao/GroupDao.kt @@ -8,6 +8,7 @@ import androidx.room.Transaction import com.skyd.anivu.appContext import com.skyd.anivu.model.bean.group.GROUP_TABLE_NAME import com.skyd.anivu.model.bean.group.GroupBean +import com.skyd.anivu.model.bean.group.GroupVo import com.skyd.anivu.model.bean.group.GroupWithFeedBean import com.skyd.anivu.model.repository.feed.tryDeleteFeedIconFile import dagger.hilt.EntryPoint @@ -142,7 +143,13 @@ interface GroupDao { newPreviousGroupId: String? = null, newNextGroupId: String? = null, ): Boolean { - if (groupId == newPreviousGroupId || + if (groupId == GroupVo.DEFAULT_GROUP_ID || + newPreviousGroupId == GroupVo.DEFAULT_GROUP_ID || + newNextGroupId == GroupVo.DEFAULT_GROUP_ID || + containsById(groupId) == 0 || + newPreviousGroupId != null && containsById(newPreviousGroupId) == 0 || + newNextGroupId != null && containsById(newNextGroupId) == 0 || + groupId == newPreviousGroupId || groupId == newNextGroupId || newPreviousGroupId != null && newPreviousGroupId == newNextGroupId ) { @@ -194,6 +201,10 @@ interface GroupDao { @Query("SELECT COUNT(*) FROM `$GROUP_TABLE_NAME` WHERE ${GroupBean.NAME_COLUMN} LIKE :name") fun containsByName(name: String): Int + @Transaction + @Query("SELECT COUNT(*) FROM `$GROUP_TABLE_NAME` WHERE ${GroupBean.GROUP_ID_COLUMN} LIKE :groupId") + fun containsById(groupId: String): Int + @Transaction @Query( "SELECT ${GroupBean.GROUP_ID_COLUMN} FROM `$GROUP_TABLE_NAME` " + diff --git a/app/src/main/java/com/skyd/anivu/model/repository/feed/FeedRepository.kt b/app/src/main/java/com/skyd/anivu/model/repository/feed/FeedRepository.kt index f75d9a23..946fe4e2 100644 --- a/app/src/main/java/com/skyd/anivu/model/repository/feed/FeedRepository.kt +++ b/app/src/main/java/com/skyd/anivu/model/repository/feed/FeedRepository.kt @@ -12,7 +12,6 @@ import com.skyd.anivu.ext.isNetwork import com.skyd.anivu.ext.put import com.skyd.anivu.model.bean.feed.FeedBean import com.skyd.anivu.model.bean.group.GroupVo -import com.skyd.anivu.model.bean.group.GroupVo.Companion.isDefaultGroup import com.skyd.anivu.model.db.dao.ArticleDao import com.skyd.anivu.model.db.dao.FeedDao import com.skyd.anivu.model.db.dao.GroupDao @@ -208,15 +207,15 @@ class FeedRepository @Inject constructor( }.flowOn(Dispatchers.IO) } - suspend fun changeGroupExpanded(group: GroupVo, expanded: Boolean): Flow { + suspend fun changeGroupExpanded(groupId: String?, expanded: Boolean): Flow { return flow { - if (group.isDefaultGroup()) { + if (groupId == null || groupId == GroupVo.DEFAULT_GROUP_ID) { appContext.dataStore.put( FeedDefaultGroupExpandPreference.key, value = expanded, ) } else { - groupDao.changeGroupExpanded(group.groupId, expanded) + groupDao.changeGroupExpanded(groupId, expanded) } emit(Unit) }.flowOn(Dispatchers.IO) diff --git a/app/src/main/java/com/skyd/anivu/ui/screen/feed/FeedViewModel.kt b/app/src/main/java/com/skyd/anivu/ui/screen/feed/FeedViewModel.kt index d65c9819..320c6d04 100644 --- a/app/src/main/java/com/skyd/anivu/ui/screen/feed/FeedViewModel.kt +++ b/app/src/main/java/com/skyd/anivu/ui/screen/feed/FeedViewModel.kt @@ -202,7 +202,7 @@ class FeedViewModel @Inject constructor( .catchMap { FeedPartialStateChange.CreateGroup.Failed(it.message.toString()) } }, filterIsInstance().flatMapConcat { intent -> - feedRepo.changeGroupExpanded(intent.group, intent.expanded).map { + feedRepo.changeGroupExpanded(intent.group.groupId, intent.expanded).map { FeedPartialStateChange.GroupExpandedChanged.Success }.catchMap { FeedPartialStateChange.GroupExpandedChanged.Failed(it.message.toString()) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c7ac8b91..8b837958 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,6 +6,7 @@ libtorrent4j = "2.1.0-35" composeMaterial = "1.7.5" composeMaterial3 = "1.4.0-alpha04" okhttp3 = "4.12.0" +paging = "3.3.5" rome = "2.1.0" room = "2.6.1" kotlin = "2.0.21" @@ -35,7 +36,7 @@ androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = androidx-work-runtime-ktx = { module = "androidx.work:work-runtime-ktx", version = "2.10.0" } androidx-datastore-preferences = { module = "androidx.datastore:datastore-preferences", version = "1.1.1" } androidx-core-splashscreen = { module = "androidx.core:core-splashscreen", version = "1.0.1" } -androidx-paging-compose = { module = "androidx.paging:paging-compose", version = "3.3.4" } +androidx-paging-compose = { module = "androidx.paging:paging-compose", version.ref = "paging" } androidx-hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version = "1.2.0" } androidx-profileinstaller = { module = "androidx.profileinstaller:profileinstaller", version = "1.4.1" } @@ -86,6 +87,7 @@ mockito-kotlin = { module = "org.mockito.kotlin:mockito-kotlin", version = "5.4. androidx-espresso-core = { module = "androidx.test.espresso:espresso-core", version = "3.6.1" } androidx-uiautomator = { group = "androidx.test.uiautomator", name = "uiautomator", version = "2.3.0" } androidx-benchmark-macro-junit4 = { group = "androidx.benchmark", name = "benchmark-macro-junit4", version = "1.3.3" } +androidx-paging-test = { module = "androidx.paging:paging-testing", version.ref = "paging" } kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version = "1.9.0" } [plugins]