tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 600e0fb902f88987e06c260b01ca426cb77ef382
parent c26815f243d858c4097554f2879a8ff004f1dae8
Author: mcarare <48995920+mcarare@users.noreply.github.com>
Date:   Fri, 14 Nov 2025 11:46:10 +0000

Bug 1996628 - Remove mockkStatic from DefaultPocketStoriesControllerTest. r=android-reviewers,giorga

This patch removes the usage of `mockkStatic` in `DefaultPocketStoriesControllerTest` to simplify the test setup. The mocked static `getCurrentFlightImpressions()` extension function is replaced by providing realistic test data for the `caps` property of the story objects directly within the tests.

Differential Revision: https://phabricator.services.mozilla.com/D272618

Diffstat:
Mmobile/android/fenix/app/src/test/java/org/mozilla/fenix/home/pocket/DefaultPocketStoriesControllerTest.kt | 280+++++++++++++++++++++++++++++++++++++++++++------------------------------------
1 file changed, 151 insertions(+), 129 deletions(-)

diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/home/pocket/DefaultPocketStoriesControllerTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/home/pocket/DefaultPocketStoriesControllerTest.kt @@ -9,7 +9,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import io.mockk.coVerify import io.mockk.every import io.mockk.mockk -import io.mockk.mockkStatic import io.mockk.spyk import io.mockk.verify import io.mockk.verifyOrder @@ -17,9 +16,10 @@ import mozilla.components.service.pocket.PocketStory import mozilla.components.service.pocket.PocketStory.ContentRecommendation import mozilla.components.service.pocket.PocketStory.PocketRecommendedStory import mozilla.components.service.pocket.PocketStory.PocketSponsoredStory +import mozilla.components.service.pocket.PocketStory.PocketSponsoredStoryCaps import mozilla.components.service.pocket.PocketStory.SponsoredContent import mozilla.components.service.pocket.PocketStory.SponsoredContentCallbacks -import mozilla.components.service.pocket.ext.getCurrentFlightImpressions +import mozilla.components.service.pocket.PocketStory.SponsoredContentFrequencyCaps import mozilla.components.support.test.robolectric.testContext import mozilla.components.support.test.rule.MainCoroutineRule import org.junit.Assert.assertEquals @@ -62,6 +62,46 @@ class DefaultPocketStoriesControllerTest { private val scope = coroutinesTestRule.scope + private val nowInSeconds = System.currentTimeMillis() / 1000 + private val flightPeriod = 100 + + // Data for "shown" tests, expecting 3 previous impressions. + private val impressionsForShownTest = listOf( + nowInSeconds - flightPeriod * 2, // This one is old and will be filtered out + nowInSeconds - flightPeriod / 2, + nowInSeconds - flightPeriod / 3, + nowInSeconds - flightPeriod / 4, + ) + private val storyCapsForShownTest = PocketSponsoredStoryCaps( + currentImpressions = impressionsForShownTest, + lifetimeCount = 10, + flightCount = 5, + flightPeriod = flightPeriod, + ) + private val contentCapsForShownTest = SponsoredContentFrequencyCaps( + currentImpressions = impressionsForShownTest, + flightCount = 5, + flightPeriod = flightPeriod, + ) + + // Data for "clicked" tests, expecting 2 previous impressions. + private val impressionsForClickedTest = listOf( + nowInSeconds - flightPeriod * 2, // This one is old and will be filtered out + nowInSeconds - flightPeriod / 2, + nowInSeconds - flightPeriod / 3, + ) + private val storyCapsForClickedTest = PocketSponsoredStoryCaps( + currentImpressions = impressionsForClickedTest, + lifetimeCount = 10, + flightCount = 5, + flightPeriod = flightPeriod, + ) + private val contentCapsForClickedTest = SponsoredContentFrequencyCaps( + currentImpressions = impressionsForClickedTest, + flightCount = 5, + flightPeriod = flightPeriod, + ) + @Test fun `GIVEN a category is selected WHEN that same category is clicked THEN deselect it and record telemetry`() { val category1 = PocketRecommendedStoriesCategory("cat1", emptyList()) @@ -216,38 +256,34 @@ class DefaultPocketStoriesControllerTest { every { shim.click } returns "testClickShim" every { shim.impression } returns "testImpressionShim" every { id } returns 123 + every { caps } returns storyCapsForShownTest } var wasPingSent = false - mockkStatic("mozilla.components.service.pocket.ext.PocketStoryKt") { - // Simulate that the story was already shown 3 times. - every { storyShown.getCurrentFlightImpressions() } returns listOf(2L, 3L, 7L) - // Test that the spoc ping is immediately sent with the needed data. - val job = Pings.spoc.testBeforeNextSubmit { reason -> - assertEquals(storyShown.shim.impression, Pocket.spocShim.testGetValue()) - assertEquals(Pings.spocReasonCodes.impression.name, reason?.name) - wasPingSent = true - } - - controller.handleStoryShown(storyShown, storyPosition = Triple(1, 2, 3)) - job.join() - - verify { - store.dispatch( - ContentRecommendationsAction.PocketStoriesShown( - impressions = listOf( - PocketImpression(story = storyShown, position = 3), - ), + val job = Pings.spoc.testBeforeNextSubmit { reason -> + assertEquals(storyShown.shim.impression, Pocket.spocShim.testGetValue()) + assertEquals(Pings.spocReasonCodes.impression.name, reason?.name) + wasPingSent = true + } + + controller.handleStoryShown(storyShown, storyPosition = Triple(1, 2, 3)) + job.join() + + verify { + store.dispatch( + ContentRecommendationsAction.PocketStoriesShown( + impressions = listOf( + PocketImpression(story = storyShown, position = 3), ), - ) - } - assertNotNull(Pocket.homeRecsSpocShown.testGetValue()) - assertEquals(1, Pocket.homeRecsSpocShown.testGetValue()!!.size) - val data = Pocket.homeRecsSpocShown.testGetValue()!!.single().extra - assertEquals("123", data?.entries?.first { it.key == "spoc_id" }?.value) - assertEquals("1x2", data?.entries?.first { it.key == "position" }?.value) - assertEquals("4", data?.entries?.first { it.key == "times_shown" }?.value) - assertTrue(wasPingSent) + ), + ) } + assertNotNull(Pocket.homeRecsSpocShown.testGetValue()) + assertEquals(1, Pocket.homeRecsSpocShown.testGetValue()!!.size) + val data = Pocket.homeRecsSpocShown.testGetValue()!!.single().extra + assertEquals("123", data?.entries?.first { it.key == "spoc_id" }?.value) + assertEquals("1x2", data?.entries?.first { it.key == "position" }?.value) + assertEquals("4", data?.entries?.first { it.key == "times_shown" }?.value) + assertTrue(wasPingSent) } @Test @@ -266,31 +302,27 @@ class DefaultPocketStoriesControllerTest { excerpt = "Mozilla Firefox", sponsor = "Mozilla", blockKey = "1", - caps = mockk(relaxed = true), + caps = contentCapsForShownTest, priority = 3, ) - mockkStatic("mozilla.components.service.pocket.ext.PocketStoryKt") { - every { sponsoredContent.getCurrentFlightImpressions() } returns listOf(2L, 3L, 7L) - - controller.handleStoryShown(sponsoredContent, storyPosition = Triple(1, 2, 3)) + controller.handleStoryShown(sponsoredContent, storyPosition = Triple(1, 2, 3)) - assertEquals(1, Pocket.homeRecsSpocShown.testGetValue()!!.size) + assertEquals(1, Pocket.homeRecsSpocShown.testGetValue()!!.size) - val data = Pocket.homeRecsSpocShown.testGetValue()!!.single().extra - assertEquals(2, data?.size) - assertEquals("1x2", data?.entries?.first { it.key == "position" }?.value) - assertEquals("4", data?.entries?.first { it.key == "times_shown" }?.value) + val data = Pocket.homeRecsSpocShown.testGetValue()!!.single().extra + assertEquals(2, data?.size) + assertEquals("1x2", data?.entries?.first { it.key == "position" }?.value) + assertEquals("4", data?.entries?.first { it.key == "times_shown" }?.value) - verify { - store.dispatch( - ContentRecommendationsAction.PocketStoriesShown( - impressions = listOf( - PocketImpression(story = sponsoredContent, position = 3), - ), + verify { + store.dispatch( + ContentRecommendationsAction.PocketStoriesShown( + impressions = listOf( + PocketImpression(story = sponsoredContent, position = 3), ), - ) - } + ), + ) } } @@ -406,41 +438,38 @@ class DefaultPocketStoriesControllerTest { every { impression } returns "testImpressionShim" }, priority = 3, - caps = mockk(relaxed = true), + caps = storyCapsForClickedTest, ) val controller = createController() var wasPingSent = false assertNull(Pocket.homeRecsSpocClicked.testGetValue()) - mockkStatic("mozilla.components.service.pocket.ext.PocketStoryKt") { - // Simulate that the story was already shown 2 times. - every { storyClicked.getCurrentFlightImpressions() } returns listOf(2L, 3L) - // Test that the spoc ping is immediately sent with the needed data. - val job = Pings.spoc.testBeforeNextSubmit { reason -> - assertEquals(storyClicked.shim.click, Pocket.spocShim.testGetValue()) - assertEquals(Pings.spocReasonCodes.click.name, reason?.name) - wasPingSent = true - } - - controller.handleStoryClicked(storyClicked, storyPosition = Triple(2, 3, 4)) - job.join() - - verify { - navController.navigate(R.id.browserFragment) - fenixBrowserUseCases.loadUrlOrSearch( - searchTermOrURL = storyClicked.url, - newTab = true, - private = false, - ) - } - - assertNotNull(Pocket.homeRecsSpocClicked.testGetValue()) - assertEquals(1, Pocket.homeRecsSpocClicked.testGetValue()!!.size) - val data = Pocket.homeRecsSpocClicked.testGetValue()!!.single().extra - assertEquals("7", data?.entries?.first { it.key == "spoc_id" }?.value) - assertEquals("2x3", data?.entries?.first { it.key == "position" }?.value) - assertEquals("3", data?.entries?.first { it.key == "times_shown" }?.value) - assertTrue(wasPingSent) + + // Test that the spoc ping is immediately sent with the needed data. + val job = Pings.spoc.testBeforeNextSubmit { reason -> + assertEquals(storyClicked.shim.click, Pocket.spocShim.testGetValue()) + assertEquals(Pings.spocReasonCodes.click.name, reason?.name) + wasPingSent = true } + + controller.handleStoryClicked(storyClicked, storyPosition = Triple(2, 3, 4)) + job.join() + + verify { + navController.navigate(R.id.browserFragment) + fenixBrowserUseCases.loadUrlOrSearch( + searchTermOrURL = storyClicked.url, + newTab = true, + private = false, + ) + } + + assertNotNull(Pocket.homeRecsSpocClicked.testGetValue()) + assertEquals(1, Pocket.homeRecsSpocClicked.testGetValue()!!.size) + val data = Pocket.homeRecsSpocClicked.testGetValue()!!.single().extra + assertEquals("7", data?.entries?.first { it.key == "spoc_id" }?.value) + assertEquals("2x3", data?.entries?.first { it.key == "position" }?.value) + assertEquals("3", data?.entries?.first { it.key == "times_shown" }?.value) + assertTrue(wasPingSent) } @Test @@ -458,41 +487,38 @@ class DefaultPocketStoriesControllerTest { every { impression } returns "testImpressionShim" }, priority = 3, - caps = mockk(relaxed = true), + caps = storyCapsForClickedTest, ) val controller = createController() var wasPingSent = false assertNull(Pocket.homeRecsSpocClicked.testGetValue()) - mockkStatic("mozilla.components.service.pocket.ext.PocketStoryKt") { - // Simulate that the story was already shown 2 times. - every { storyClicked.getCurrentFlightImpressions() } returns listOf(2L, 3L) - // Test that the spoc ping is immediately sent with the needed data. - val job = Pings.spoc.testBeforeNextSubmit { reason -> - assertEquals(storyClicked.shim.click, Pocket.spocShim.testGetValue()) - assertEquals(Pings.spocReasonCodes.click.name, reason?.name) - wasPingSent = true - } - - controller.handleStoryClicked(storyClicked, storyPosition = Triple(2, 3, 4)) - job.join() - - verify { - navController.navigate(R.id.browserFragment) - fenixBrowserUseCases.loadUrlOrSearch( - searchTermOrURL = storyClicked.url, - newTab = false, - private = false, - ) - } - - assertNotNull(Pocket.homeRecsSpocClicked.testGetValue()) - assertEquals(1, Pocket.homeRecsSpocClicked.testGetValue()!!.size) - val data = Pocket.homeRecsSpocClicked.testGetValue()!!.single().extra - assertEquals("7", data?.entries?.first { it.key == "spoc_id" }?.value) - assertEquals("2x3", data?.entries?.first { it.key == "position" }?.value) - assertEquals("3", data?.entries?.first { it.key == "times_shown" }?.value) - assertTrue(wasPingSent) + + // Test that the spoc ping is immediately sent with the needed data. + val job = Pings.spoc.testBeforeNextSubmit { reason -> + assertEquals(storyClicked.shim.click, Pocket.spocShim.testGetValue()) + assertEquals(Pings.spocReasonCodes.click.name, reason?.name) + wasPingSent = true + } + + controller.handleStoryClicked(storyClicked, storyPosition = Triple(2, 3, 4)) + job.join() + + verify { + navController.navigate(R.id.browserFragment) + fenixBrowserUseCases.loadUrlOrSearch( + searchTermOrURL = storyClicked.url, + newTab = false, + private = false, + ) } + + assertNotNull(Pocket.homeRecsSpocClicked.testGetValue()) + assertEquals(1, Pocket.homeRecsSpocClicked.testGetValue()!!.size) + val data = Pocket.homeRecsSpocClicked.testGetValue()!!.single().extra + assertEquals("7", data?.entries?.first { it.key == "spoc_id" }?.value) + assertEquals("2x3", data?.entries?.first { it.key == "position" }?.value) + assertEquals("3", data?.entries?.first { it.key == "times_shown" }?.value) + assertTrue(wasPingSent) } @Test @@ -509,33 +535,29 @@ class DefaultPocketStoriesControllerTest { excerpt = "Mozilla Firefox", sponsor = "Mozilla", blockKey = "1", - caps = mockk(relaxed = true), + caps = contentCapsForClickedTest, priority = 3, ) val controller = createController() assertNull(Pocket.homeRecsSpocClicked.testGetValue()) - mockkStatic("mozilla.components.service.pocket.ext.PocketStoryKt") { - every { sponsoredContent.getCurrentFlightImpressions() } returns listOf(2L, 3L) - - controller.handleStoryClicked(sponsoredContent, storyPosition = Triple(2, 3, 4)) - - assertEquals(1, Pocket.homeRecsSpocClicked.testGetValue()!!.size) - val data = Pocket.homeRecsSpocClicked.testGetValue()!!.single().extra - assertEquals(2, data?.size) - assertEquals("2x3", data?.entries?.first { it.key == "position" }?.value) - assertEquals("3", data?.entries?.first { it.key == "times_shown" }?.value) - - coVerify { - navController.navigate(R.id.browserFragment) - fenixBrowserUseCases.loadUrlOrSearch( - searchTermOrURL = sponsoredContent.url, - newTab = true, - private = false, - ) - marsUseCases.recordInteraction(sponsoredContent.callbacks.clickUrl) - } + controller.handleStoryClicked(sponsoredContent, storyPosition = Triple(2, 3, 4)) + + assertEquals(1, Pocket.homeRecsSpocClicked.testGetValue()!!.size) + val data = Pocket.homeRecsSpocClicked.testGetValue()!!.single().extra + assertEquals(2, data?.size) + assertEquals("2x3", data?.entries?.first { it.key == "position" }?.value) + assertEquals("3", data?.entries?.first { it.key == "times_shown" }?.value) + + coVerify { + navController.navigate(R.id.browserFragment) + fenixBrowserUseCases.loadUrlOrSearch( + searchTermOrURL = sponsoredContent.url, + newTab = true, + private = false, + ) + marsUseCases.recordInteraction(sponsoredContent.callbacks.clickUrl) } }