diff --git a/app/src/test/java/org/mozilla/fenix/home/PocketUpdatesMiddlewareTest.kt b/app/src/test/java/org/mozilla/fenix/home/PocketUpdatesMiddlewareTest.kt index 1314e28ca7..b91bfa14d1 100644 --- a/app/src/test/java/org/mozilla/fenix/home/PocketUpdatesMiddlewareTest.kt +++ b/app/src/test/java/org/mozilla/fenix/home/PocketUpdatesMiddlewareTest.kt @@ -11,6 +11,8 @@ import io.mockk.mockk import io.mockk.spyk import io.mockk.verify import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.TestCoroutineScope import mozilla.components.service.pocket.PocketRecommendedStory @@ -59,6 +61,7 @@ class PocketUpdatesMiddlewareTest { } @Test + @Suppress("UNCHECKED_CAST") fun `WHEN PocketStoriesCategoriesChange is dispatched THEN intercept and dispatch PocketStoriesCategoriesSelectionsChange`() { val persistedSelectedCategory: SelectedPocketStoriesCategory = mockk { every { name } returns "testCategory" @@ -67,9 +70,10 @@ class PocketUpdatesMiddlewareTest { val persistedSelectedCategories: SelectedPocketStoriesCategories = mockk { every { valuesList } returns mutableListOf(persistedSelectedCategory) } - val dataStore: DataStore = mockk { - every { data } returns flowOf(persistedSelectedCategories) - } + val dataStore: DataStore = + mockk>(relaxed = true) { + every { data } returns flowOf(persistedSelectedCategories) + } as DataStore val currentCategories = listOf(mockk()) val pocketMiddleware = PocketUpdatesMiddleware(TestCoroutineScope(), mockk(), dataStore) val homeStore = spyk( @@ -96,10 +100,13 @@ class PocketUpdatesMiddlewareTest { } @Test + @Suppress("UNCHECKED_CAST") fun `WHEN SelectPocketStoriesCategory is dispatched THEN persist details in DataStore`() { val categ1 = PocketRecommendedStoriesCategory("categ1") val categ2 = PocketRecommendedStoriesCategory("categ2") - val dataStore: DataStore = mockk(relaxed = true) + val dataStore: DataStore = + mockk>(relaxed = true) as + DataStore val pocketMiddleware = PocketUpdatesMiddleware(TestCoroutineScope(), mockk(), dataStore) val homeStore = spyk( HomeFragmentStore( @@ -117,10 +124,13 @@ class PocketUpdatesMiddlewareTest { } @Test + @Suppress("UNCHECKED_CAST") fun `WHEN DeselectPocketStoriesCategory is dispatched THEN persist details in DataStore`() { val categ1 = PocketRecommendedStoriesCategory("categ1") val categ2 = PocketRecommendedStoriesCategory("categ2") - val dataStore: DataStore = mockk(relaxed = true) + val dataStore: DataStore = + mockk>(relaxed = true) as + DataStore val pocketMiddleware = PocketUpdatesMiddleware(TestCoroutineScope(), mockk(), dataStore) val homeStore = spyk( HomeFragmentStore( @@ -138,8 +148,11 @@ class PocketUpdatesMiddlewareTest { } @Test + @Suppress("UNCHECKED_CAST") fun `WHEN persistCategories is called THEN update dataStore`() { - val dataStore: DataStore = mockk(relaxed = true) + val dataStore: DataStore = + mockk>(relaxed = true) as + DataStore persistSelectedCategories(TestCoroutineScope(), listOf(mockk(relaxed = true)), dataStore) @@ -148,6 +161,7 @@ class PocketUpdatesMiddlewareTest { } @Test + @Suppress("UNCHECKED_CAST") fun `WHEN restoreSelectedCategories is called THEN dispatch PocketStoriesCategoriesSelectionsChange with data read from the persistence layer`() { val persistedSelectedCategory: SelectedPocketStoriesCategory = mockk { every { name } returns "testCategory" @@ -156,9 +170,10 @@ class PocketUpdatesMiddlewareTest { val persistedSelectedCategories: SelectedPocketStoriesCategories = mockk { every { valuesList } returns mutableListOf(persistedSelectedCategory) } - val dataStore: DataStore = mockk { - every { data } returns flowOf(persistedSelectedCategories) - } + val dataStore: DataStore = + mockk>(relaxed = true) { + every { data } returns flowOf(persistedSelectedCategories) + } as DataStore val currentCategories = listOf(mockk()) val homeStore = spyk( HomeFragmentStore(HomeFragmentState()) @@ -183,3 +198,18 @@ class PocketUpdatesMiddlewareTest { } } } + +/** + * Incomplete fake of a [DataStore]. + * Respects the [DataStore] contract with basic method implementations but needs to have mocked behavior + * for more complex interactions. + * Can be used as a replacement for mocks of the [DataStore] interface which might fail intermittently. + */ +private class FakeDataStore : DataStore { + override val data: Flow + get() = flow { } + + override suspend fun updateData(transform: suspend (t: T?) -> T?): T? { + return transform(null) + } +} diff --git a/app/src/test/java/org/mozilla/fenix/home/sessioncontrol/viewholders/pocket/DefaultPocketStoriesControllerTest.kt b/app/src/test/java/org/mozilla/fenix/home/sessioncontrol/viewholders/pocket/DefaultPocketStoriesControllerTest.kt index 9185ac21d0..5981796801 100644 --- a/app/src/test/java/org/mozilla/fenix/home/sessioncontrol/viewholders/pocket/DefaultPocketStoriesControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/home/sessioncontrol/viewholders/pocket/DefaultPocketStoriesControllerTest.kt @@ -39,15 +39,10 @@ class DefaultPocketStoriesControllerTest { ) val controller = DefaultPocketStoriesController(mockk(), store, mockk(), metrics) - controller.handleCategoryClick(category1) - verify(exactly = 0) { store.dispatch(HomeFragmentAction.DeselectPocketStoriesCategory(category1.name)) } - verify { store.dispatch(HomeFragmentAction.SelectPocketStoriesCategory(category1.name)) } - verify { metrics.track(Event.PocketHomeRecsCategoryClicked(category1.name, 1, true)) } - controller.handleCategoryClick(category2) verify(exactly = 0) { store.dispatch(HomeFragmentAction.SelectPocketStoriesCategory(category2.name)) } verify { store.dispatch(HomeFragmentAction.DeselectPocketStoriesCategory(category2.name)) } - verify { metrics.track(Event.PocketHomeRecsCategoryClicked(category2.name, 2, false)) } + verify { metrics.track(Event.PocketHomeRecsCategoryClicked(category2.name, 1, false)) } } @Test