From 00fc9c29d2d2812c0e7eac27d5daa662529b1468 Mon Sep 17 00:00:00 2001 From: Simon Marquis Date: Sat, 19 Nov 2022 00:41:52 +0100 Subject: [PATCH] Sort authors stream by news count Fixes #393 --- ...GetSortedFollowableAuthorsStreamUseCase.kt | 31 ++++++--- ...ortedFollowableAuthorsStreamUseCaseTest.kt | 22 ++++++- .../feature/foryou/ForYouViewModelTest.kt | 63 ++++++++++--------- .../interests/InterestsViewModelTest.kt | 4 ++ .../feature/topic/TopicViewModelTest.kt | 1 + 5 files changed, 82 insertions(+), 39 deletions(-) diff --git a/core/domain/src/main/java/com/google/samples/apps/nowinandroid/core/domain/GetSortedFollowableAuthorsStreamUseCase.kt b/core/domain/src/main/java/com/google/samples/apps/nowinandroid/core/domain/GetSortedFollowableAuthorsStreamUseCase.kt index 498558c2f..8b4634a00 100644 --- a/core/domain/src/main/java/com/google/samples/apps/nowinandroid/core/domain/GetSortedFollowableAuthorsStreamUseCase.kt +++ b/core/domain/src/main/java/com/google/samples/apps/nowinandroid/core/domain/GetSortedFollowableAuthorsStreamUseCase.kt @@ -17,34 +17,49 @@ package com.google.samples.apps.nowinandroid.core.domain import com.google.samples.apps.nowinandroid.core.data.repository.AuthorsRepository +import com.google.samples.apps.nowinandroid.core.data.repository.NewsRepository import com.google.samples.apps.nowinandroid.core.data.repository.UserDataRepository import com.google.samples.apps.nowinandroid.core.domain.model.FollowableAuthor +import com.google.samples.apps.nowinandroid.core.model.data.Author import javax.inject.Inject import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine /** - * A use case which obtains a list of authors sorted alphabetically by name with their followed - * state. + * A use case which obtains a list of authors sorted by descending news count and then alphabetically by name with their followed state. */ class GetSortedFollowableAuthorsStreamUseCase @Inject constructor( private val authorsRepository: AuthorsRepository, - private val userDataRepository: UserDataRepository + private val newsRepository: NewsRepository, + private val userDataRepository: UserDataRepository, ) { /** - * Returns a list of authors with their associated followed state sorted alphabetically by name. + * Returns a list of authors with their associated followed state sorted by descending news count and then alphabetically by name. */ operator fun invoke(): Flow> = combine( authorsRepository.getAuthorsStream(), - userDataRepository.userDataStream - ) { authors, userData -> + newsRepository.getNewsResourcesStream(), + userDataRepository.userDataStream, + ) { authors, news, userData -> + val newsCountByAuthor: Map = buildMap { + news.forEach { news -> + news.authors.forEach { author -> + compute(author) { _, count -> count?.inc() ?: 1 } + } + } + } authors.map { author -> FollowableAuthor( author = author, isFollowed = author.id in userData.followedAuthors ) - } - .sortedBy { it.author.name } + }.sortedWith( + compareByDescending { + newsCountByAuthor[it.author] + }.thenBy { + it.author.name + } + ) } } diff --git a/core/domain/src/test/java/com/google/samples/apps/nowinandroid/core/domain/GetSortedFollowableAuthorsStreamUseCaseTest.kt b/core/domain/src/test/java/com/google/samples/apps/nowinandroid/core/domain/GetSortedFollowableAuthorsStreamUseCaseTest.kt index 24b88a88b..dd40cd461 100644 --- a/core/domain/src/test/java/com/google/samples/apps/nowinandroid/core/domain/GetSortedFollowableAuthorsStreamUseCaseTest.kt +++ b/core/domain/src/test/java/com/google/samples/apps/nowinandroid/core/domain/GetSortedFollowableAuthorsStreamUseCaseTest.kt @@ -18,12 +18,16 @@ package com.google.samples.apps.nowinandroid.core.domain import com.google.samples.apps.nowinandroid.core.domain.model.FollowableAuthor import com.google.samples.apps.nowinandroid.core.model.data.Author +import com.google.samples.apps.nowinandroid.core.model.data.NewsResource +import com.google.samples.apps.nowinandroid.core.model.data.NewsResourceType.Video import com.google.samples.apps.nowinandroid.core.testing.repository.TestAuthorsRepository +import com.google.samples.apps.nowinandroid.core.testing.repository.TestNewsRepository import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserDataRepository import com.google.samples.apps.nowinandroid.core.testing.util.MainDispatcherRule import kotlin.test.assertEquals import kotlinx.coroutines.flow.first import kotlinx.coroutines.test.runTest +import kotlinx.datetime.Instant import org.junit.Rule import org.junit.Test @@ -33,15 +37,18 @@ class GetSortedFollowableAuthorsStreamUseCaseTest { val mainDispatcherRule = MainDispatcherRule() private val authorsRepository = TestAuthorsRepository() + private val newsRepository = TestNewsRepository() private val userDataRepository = TestUserDataRepository() val useCase = GetSortedFollowableAuthorsStreamUseCase( authorsRepository = authorsRepository, - userDataRepository = userDataRepository + newsRepository = newsRepository, + userDataRepository = userDataRepository, ) @Test fun whenFollowedAuthorsSupplied_sortedFollowableAuthorsAreReturned() = runTest { + newsRepository.sendNewsResources(listOf(sampleNews1)) // Specify some authors which the user is following. userDataRepository.setFollowedAuthorIds(setOf(sampleAuthor1.id)) @@ -95,3 +102,16 @@ private val sampleAuthor3 = ) private val sampleAuthors = listOf(sampleAuthor1, sampleAuthor2, sampleAuthor3) + +private val sampleNews1 = + NewsResource( + id = "1", + title = "", + content = "", + url = "", + headerImageUrl = null, + publishDate = Instant.parse("2021-11-09T00:00:00.000Z"), + type = Video, + authors = listOf(sampleAuthor2), + topics = emptyList() + ) diff --git a/feature/foryou/src/test/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouViewModelTest.kt b/feature/foryou/src/test/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouViewModelTest.kt index daeeb46c2..9df86dee2 100644 --- a/feature/foryou/src/test/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouViewModelTest.kt +++ b/feature/foryou/src/test/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouViewModelTest.kt @@ -65,6 +65,7 @@ class ForYouViewModelTest { ) private val getSortedFollowableAuthorsStream = GetSortedFollowableAuthorsStreamUseCase( authorsRepository = authorsRepository, + newsRepository = newsRepository, userDataRepository = userDataRepository ) private val getFollowableTopicsStreamUseCase = GetFollowableTopicsStreamUseCase( @@ -190,6 +191,7 @@ class ForYouViewModelTest { userDataRepository.setFollowedTopicIds(emptySet()) authorsRepository.sendAuthors(sampleAuthors) userDataRepository.setFollowedAuthorIds(emptySet()) + newsRepository.sendNewsResources(emptyList()) assertEquals( OnboardingUiState.Shown( @@ -329,8 +331,8 @@ class ForYouViewModelTest { authors = listOf( FollowableAuthor( author = Author( - id = "0", - name = "Android Dev", + id = "1", + name = "Android Dev 2", imageUrl = "", twitter = "", mediumPage = "", @@ -340,8 +342,8 @@ class ForYouViewModelTest { ), FollowableAuthor( author = Author( - id = "1", - name = "Android Dev 2", + id = "0", + name = "Android Dev", imageUrl = "", twitter = "", mediumPage = "", @@ -386,6 +388,7 @@ class ForYouViewModelTest { userDataRepository.setFollowedAuthorIds(emptySet()) topicsRepository.sendTopics(sampleTopics) userDataRepository.setFollowedTopicIds(setOf("0", "1")) + newsRepository.sendNewsResources(emptyList()) viewModel.dismissOnboarding() assertEquals( @@ -469,8 +472,8 @@ class ForYouViewModelTest { authors = listOf( FollowableAuthor( author = Author( - id = "0", - name = "Android Dev", + id = "1", + name = "Android Dev 2", imageUrl = "", twitter = "", mediumPage = "", @@ -480,8 +483,8 @@ class ForYouViewModelTest { ), FollowableAuthor( author = Author( - id = "1", - name = "Android Dev 2", + id = "0", + name = "Android Dev", imageUrl = "", twitter = "", mediumPage = "", @@ -553,8 +556,8 @@ class ForYouViewModelTest { authors = listOf( FollowableAuthor( author = Author( - id = "0", - name = "Android Dev", + id = "1", + name = "Android Dev 2", imageUrl = "", twitter = "", mediumPage = "", @@ -564,8 +567,8 @@ class ForYouViewModelTest { ), FollowableAuthor( author = Author( - id = "1", - name = "Android Dev 2", + id = "0", + name = "Android Dev", imageUrl = "", twitter = "", mediumPage = "", @@ -660,8 +663,8 @@ class ForYouViewModelTest { authors = listOf( FollowableAuthor( author = Author( - id = "0", - name = "Android Dev", + id = "1", + name = "Android Dev 2", imageUrl = "", twitter = "", mediumPage = "", @@ -671,8 +674,8 @@ class ForYouViewModelTest { ), FollowableAuthor( author = Author( - id = "1", - name = "Android Dev 2", + id = "0", + name = "Android Dev", imageUrl = "", twitter = "", mediumPage = "", @@ -744,25 +747,25 @@ class ForYouViewModelTest { authors = listOf( FollowableAuthor( author = Author( - id = "0", - name = "Android Dev", + id = "1", + name = "Android Dev 2", imageUrl = "", twitter = "", mediumPage = "", bio = "", ), - isFollowed = false + isFollowed = true ), FollowableAuthor( author = Author( - id = "1", - name = "Android Dev 2", + id = "0", + name = "Android Dev", imageUrl = "", twitter = "", mediumPage = "", bio = "", ), - isFollowed = true + isFollowed = false ), FollowableAuthor( author = Author( @@ -854,8 +857,8 @@ class ForYouViewModelTest { authors = listOf( FollowableAuthor( author = Author( - id = "0", - name = "Android Dev", + id = "1", + name = "Android Dev 2", imageUrl = "", twitter = "", mediumPage = "", @@ -865,8 +868,8 @@ class ForYouViewModelTest { ), FollowableAuthor( author = Author( - id = "1", - name = "Android Dev 2", + id = "0", + name = "Android Dev", imageUrl = "", twitter = "", mediumPage = "", @@ -955,8 +958,8 @@ class ForYouViewModelTest { authors = listOf( FollowableAuthor( author = Author( - id = "0", - name = "Android Dev", + id = "1", + name = "Android Dev 2", imageUrl = "", twitter = "", mediumPage = "", @@ -966,8 +969,8 @@ class ForYouViewModelTest { ), FollowableAuthor( author = Author( - id = "1", - name = "Android Dev 2", + id = "0", + name = "Android Dev", imageUrl = "", twitter = "", mediumPage = "", diff --git a/feature/interests/src/test/java/com/google/samples/apps/nowinandroid/interests/InterestsViewModelTest.kt b/feature/interests/src/test/java/com/google/samples/apps/nowinandroid/interests/InterestsViewModelTest.kt index aaac504d3..c128946fd 100644 --- a/feature/interests/src/test/java/com/google/samples/apps/nowinandroid/interests/InterestsViewModelTest.kt +++ b/feature/interests/src/test/java/com/google/samples/apps/nowinandroid/interests/InterestsViewModelTest.kt @@ -23,6 +23,7 @@ import com.google.samples.apps.nowinandroid.core.domain.model.FollowableTopic import com.google.samples.apps.nowinandroid.core.model.data.Author import com.google.samples.apps.nowinandroid.core.model.data.Topic import com.google.samples.apps.nowinandroid.core.testing.repository.TestAuthorsRepository +import com.google.samples.apps.nowinandroid.core.testing.repository.TestNewsRepository import com.google.samples.apps.nowinandroid.core.testing.repository.TestTopicsRepository import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserDataRepository import com.google.samples.apps.nowinandroid.core.testing.util.MainDispatcherRule @@ -48,6 +49,7 @@ class InterestsViewModelTest { private val userDataRepository = TestUserDataRepository() private val authorsRepository = TestAuthorsRepository() + private val newsRepository = TestNewsRepository() private val topicsRepository = TestTopicsRepository() private val getFollowableTopicsStreamUseCase = GetFollowableTopicsStreamUseCase( topicsRepository = topicsRepository, @@ -56,6 +58,7 @@ class InterestsViewModelTest { private val getSortedFollowableAuthorsStream = GetSortedFollowableAuthorsStreamUseCase( authorsRepository = authorsRepository, + newsRepository = newsRepository, userDataRepository = userDataRepository ) private lateinit var viewModel: InterestsViewModel @@ -67,6 +70,7 @@ class InterestsViewModelTest { getFollowableTopicsStream = getFollowableTopicsStreamUseCase, getSortedFollowableAuthorsStream = getSortedFollowableAuthorsStream ) + newsRepository.sendNewsResources(emptyList()) } @Test diff --git a/feature/topic/src/test/java/com/google/samples/apps/nowinandroid/feature/topic/TopicViewModelTest.kt b/feature/topic/src/test/java/com/google/samples/apps/nowinandroid/feature/topic/TopicViewModelTest.kt index 17d7b45ee..c2b42e864 100644 --- a/feature/topic/src/test/java/com/google/samples/apps/nowinandroid/feature/topic/TopicViewModelTest.kt +++ b/feature/topic/src/test/java/com/google/samples/apps/nowinandroid/feature/topic/TopicViewModelTest.kt @@ -68,6 +68,7 @@ class TopicViewModelTest { topicsRepository = topicsRepository, getSaveableNewsResourcesStream = getSaveableNewsResourcesStreamUseCase ) + newsRepository.sendNewsResources(emptyList()) } @Test