diff --git a/mobile/android/fenix/app/metrics.yaml b/mobile/android/fenix/app/metrics.yaml index 871ef094943db..b5f86ece59744 100644 --- a/mobile/android/fenix/app/metrics.yaml +++ b/mobile/android/fenix/app/metrics.yaml @@ -9736,6 +9736,12 @@ pocket: type: event description: | The Pocket recommended stories are shown on the home screen. + extra_keys: + source: + type: string + description: | + Where the stories impression was recorded. + One of "homepage" or "stories_screen". bugs: - https://github.com/mozilla-mobile/fenix/issues/21593 data_reviews: @@ -9764,6 +9770,11 @@ pocket: description: | Position of the clicked story in the list shown. Uses the [row x column] matrix notation. + source: + type: string + description: | + Where the clicked story was shown. + One of "homepage" or "stories_screen". bugs: - https://github.com/mozilla-mobile/fenix/issues/21593 data_reviews: diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/fake/FakeHomepagePreview.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/fake/FakeHomepagePreview.kt index 30fded6c23606..79cd9d55bbccb 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/fake/FakeHomepagePreview.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/fake/FakeHomepagePreview.kt @@ -35,6 +35,7 @@ import org.mozilla.fenix.home.collections.CollectionsState import org.mozilla.fenix.home.interactor.HomepageInteractor import org.mozilla.fenix.home.pocket.PocketRecommendedStoriesCategory import org.mozilla.fenix.home.pocket.PocketState +import org.mozilla.fenix.home.pocket.controller.StoriesImpressionSource import org.mozilla.fenix.home.pocket.interactor.PocketStoriesInteractor import org.mozilla.fenix.home.privatebrowsing.interactor.PrivateBrowsingInteractor import org.mozilla.fenix.home.recentsyncedtabs.RecentSyncedTab @@ -140,13 +141,17 @@ internal object FakeHomepagePreview { storyPosition: Triple, ) { /* no op */ } - override fun onStoriesShown(storiesShown: List) { /* no op */ } + override fun onStoriesShown( + storiesShown: List, + source: StoriesImpressionSource, + ) { /* no op */ } override fun onCategoryClicked(categoryClicked: PocketRecommendedStoriesCategory) { /* no op */ } override fun onStoryClicked( storyClicked: PocketStory, storyPosition: Triple, + source: StoriesImpressionSource, ) { /* no op */ } override fun onDiscoverMoreClicked() { /* no op */ } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/pocket/controller/PocketStoriesController.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/pocket/controller/PocketStoriesController.kt index 2bdfedbd414de..041df856528b0 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/pocket/controller/PocketStoriesController.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/pocket/controller/PocketStoriesController.kt @@ -32,6 +32,15 @@ import java.lang.ref.WeakReference private const val POCKET_CATEGORIES_SELECTED_AT_A_TIME_COUNT = 8 +/** + * The surface where a Pocket stories impression was recorded. Used as the `source` extra on the + * `pocket.home_recs_shown` Glean event. + */ +enum class StoriesImpressionSource(val sourceName: String) { + HOMEPAGE("homepage"), + STORIES_SCREEN("stories_screen"), +} + /** * Contract for how all user interactions with the Pocket stories feature are to be handled. */ @@ -49,8 +58,9 @@ interface PocketStoriesController { * Callback to decide what should happen as an effect of a new list of stories being shown. * * @param storiesShown the new list of [PocketStory]es shown to the user. + * @param source the surface where the stories were shown. */ - fun handleStoriesShown(storiesShown: List) + fun handleStoriesShown(storiesShown: List, source: StoriesImpressionSource) /** * Callback allowing to handle a specific [PocketRecommendedStoriesCategory] being clicked by the user. @@ -65,8 +75,13 @@ interface PocketStoriesController { * @param storyClicked The just clicked [PocketStory]. * @param storyPosition `row x column x index` matrix representing the grid and index position * of the clicked story. + * @param source the surface where the clicked story was shown. */ - fun handleStoryClicked(storyClicked: PocketStory, storyPosition: Triple) + fun handleStoryClicked( + storyClicked: PocketStory, + storyPosition: Triple, + source: StoriesImpressionSource, + ) /** * Callback for when the user clicks on the "Discover more" button. @@ -138,7 +153,10 @@ internal class DefaultPocketStoriesController( } } - override fun handleStoriesShown(storiesShown: List) { + override fun handleStoriesShown( + storiesShown: List, + source: StoriesImpressionSource, + ) { // Only report here the impressions for recommended stories. // Sponsored stories use a different API for more accurate tracking. appStore.dispatch( @@ -149,7 +167,9 @@ internal class DefaultPocketStoriesController( ), ) - Pocket.homeRecsShown.record(NoExtras()) + Pocket.homeRecsShown.record( + Pocket.HomeRecsShownExtra(source = source.sourceName), + ) } override fun handleCategoryClick(categoryClicked: PocketRecommendedStoriesCategory) { @@ -196,6 +216,7 @@ internal class DefaultPocketStoriesController( override fun handleStoryClicked( storyClicked: PocketStory, storyPosition: Triple, + source: StoriesImpressionSource, ) { val storyUrl = when (navController.currentDestination?.id) { R.id.storiesFragment -> storyClicked.url.markAsOpenedFromStoriesScreen() @@ -216,6 +237,7 @@ internal class DefaultPocketStoriesController( Pocket.HomeRecsStoryClickedExtra( position = "${storyPosition.first}x${storyPosition.second}", timesShown = storyClicked.timesShown.inc().toString(), + source = source.sourceName, ), ) } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/pocket/interactor/PocketStoriesInteractor.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/pocket/interactor/PocketStoriesInteractor.kt index bd0c2980b7d37..4ef0b4d6457f8 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/pocket/interactor/PocketStoriesInteractor.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/pocket/interactor/PocketStoriesInteractor.kt @@ -8,6 +8,7 @@ import mozilla.components.service.pocket.PocketStory import mozilla.components.service.pocket.PocketStory.PocketRecommendedStory import org.mozilla.fenix.home.pocket.PocketRecommendedStoriesCategory import org.mozilla.fenix.home.pocket.controller.PocketStoriesController +import org.mozilla.fenix.home.pocket.controller.StoriesImpressionSource /** * Contract for all possible user interactions with the Pocket recommended stories feature. @@ -26,8 +27,9 @@ interface PocketStoriesInteractor { * Callback for then new stories are shown to the user. * * @param storiesShown The new list of [PocketRecommendedStory]es shown to the user. + * @param source the surface where the stories were shown. */ - fun onStoriesShown(storiesShown: List) + fun onStoriesShown(storiesShown: List, source: StoriesImpressionSource) /** * Callback for when the user clicks a specific category. @@ -42,8 +44,13 @@ interface PocketStoriesInteractor { * @param storyClicked The just clicked [PocketStory]. * @param storyPosition `row x column x index` matrix representing the grid and index position * of the clicked story. + * @param source the surface where the clicked story was shown. */ - fun onStoryClicked(storyClicked: PocketStory, storyPosition: Triple) + fun onStoryClicked( + storyClicked: PocketStory, + storyPosition: Triple, + source: StoriesImpressionSource, + ) /** * Callback when an user clicks on the "Discover more" nutton for stories on the homepage. @@ -66,16 +73,20 @@ class DefaultPocketStoriesInteractor( controller.handleStoryShown(storyShown, storyPosition) } - override fun onStoriesShown(storiesShown: List) { - controller.handleStoriesShown(storiesShown) + override fun onStoriesShown(storiesShown: List, source: StoriesImpressionSource) { + controller.handleStoriesShown(storiesShown, source) } override fun onCategoryClicked(categoryClicked: PocketRecommendedStoriesCategory) { controller.handleCategoryClick(categoryClicked) } - override fun onStoryClicked(storyClicked: PocketStory, storyPosition: Triple) { - controller.handleStoryClicked(storyClicked, storyPosition) + override fun onStoryClicked( + storyClicked: PocketStory, + storyPosition: Triple, + source: StoriesImpressionSource, + ) { + controller.handleStoryClicked(storyClicked, storyPosition, source) } override fun onDiscoverMoreClicked() { diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/pocket/ui/PocketSection.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/pocket/ui/PocketSection.kt index bef29f92f2881..0d7f3880c2ea9 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/pocket/ui/PocketSection.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/pocket/ui/PocketSection.kt @@ -22,6 +22,7 @@ import org.mozilla.fenix.R import org.mozilla.fenix.compose.home.HomeSectionHeader import org.mozilla.fenix.home.fake.FakeHomepagePreview import org.mozilla.fenix.home.pocket.PocketState +import org.mozilla.fenix.home.pocket.controller.StoriesImpressionSource import org.mozilla.fenix.home.pocket.interactor.PocketStoriesInteractor import org.mozilla.fenix.theme.FirefoxTheme import org.mozilla.fenix.wallpapers.WallpaperState @@ -45,7 +46,10 @@ fun PocketSection( // We should report back when a certain story is actually being displayed. // Cannot do it reliably so for now we'll just mass report everything as being displayed. state.stories.let { - interactor.onStoriesShown(storiesShown = it) + interactor.onStoriesShown( + storiesShown = it, + source = StoriesImpressionSource.HOMEPAGE, + ) } } @@ -65,7 +69,9 @@ fun PocketSection( contentPadding = horizontalPadding, backgroundColor = cardBackgroundColor, onStoryShown = interactor::onStoryShown, - onStoryClicked = interactor::onStoryClicked, + onStoryClicked = { story, position -> + interactor.onStoryClicked(story, position, StoriesImpressionSource.HOMEPAGE) + }, ) } } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/pocket/ui/StoriesScreen.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/pocket/ui/StoriesScreen.kt index 40d44c5de12e7..a14d1537550e6 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/pocket/ui/StoriesScreen.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/pocket/ui/StoriesScreen.kt @@ -34,6 +34,7 @@ import mozilla.components.compose.base.utils.BackInvokedHandler import org.mozilla.fenix.R import org.mozilla.fenix.components.appstate.recommendations.ContentRecommendationsState import org.mozilla.fenix.home.fake.FakeHomepagePreview +import org.mozilla.fenix.home.pocket.controller.StoriesImpressionSource import org.mozilla.fenix.home.pocket.interactor.PocketStoriesInteractor import org.mozilla.fenix.home.ui.LeftChevronPillButton import org.mozilla.fenix.theme.FirefoxTheme @@ -54,6 +55,15 @@ fun StoriesScreen( interactor.onDiscoverMoreScreenViewed() } + // We should report back when a certain story is actually being displayed. + // Cannot do it reliably so for now we'll just mass report everything as being displayed. + LaunchedEffect(state.pocketStories) { + interactor.onStoriesShown( + storiesShown = state.pocketStories, + source = StoriesImpressionSource.STORIES_SCREEN, + ) + } + BackInvokedHandler { onNavigationIconClick() } @@ -155,7 +165,13 @@ private fun Stories( itemsIndexed(state.pocketStories) { index, story -> StoryCard( story = story, - onClick = interactor::onStoryClicked, + onClick = { clickedStory, position -> + interactor.onStoryClicked( + clickedStory, + position, + StoriesImpressionSource.STORIES_SCREEN, + ) + }, ) } } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlInteractor.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlInteractor.kt index 6c6df71e4aca3..f9b14aeb91c1c 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlInteractor.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlInteractor.kt @@ -19,6 +19,7 @@ import org.mozilla.fenix.home.logo.LogoController import org.mozilla.fenix.home.logo.TrackingProtectionController import org.mozilla.fenix.home.pocket.PocketRecommendedStoriesCategory import org.mozilla.fenix.home.pocket.controller.PocketStoriesController +import org.mozilla.fenix.home.pocket.controller.StoriesImpressionSource import org.mozilla.fenix.home.privatebrowsing.controller.PrivateBrowsingController import org.mozilla.fenix.home.recentsyncedtabs.RecentSyncedTab import org.mozilla.fenix.home.recentsyncedtabs.controller.RecentSyncedTabController @@ -381,16 +382,20 @@ class SessionControlInteractor( pocketStoriesController.handleStoryShown(storyShown, storyPosition) } - override fun onStoriesShown(storiesShown: List) { - pocketStoriesController.handleStoriesShown(storiesShown) + override fun onStoriesShown(storiesShown: List, source: StoriesImpressionSource) { + pocketStoriesController.handleStoriesShown(storiesShown, source) } override fun onCategoryClicked(categoryClicked: PocketRecommendedStoriesCategory) { pocketStoriesController.handleCategoryClick(categoryClicked) } - override fun onStoryClicked(storyClicked: PocketStory, storyPosition: Triple) { - pocketStoriesController.handleStoryClicked(storyClicked, storyPosition) + override fun onStoryClicked( + storyClicked: PocketStory, + storyPosition: Triple, + source: StoriesImpressionSource, + ) { + pocketStoriesController.handleStoryClicked(storyClicked, storyPosition, source) } override fun onDiscoverMoreClicked() { diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/home/SessionControlInteractorTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/home/SessionControlInteractorTest.kt index 048e1d392ab95..db92682347f11 100644 --- a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/home/SessionControlInteractorTest.kt +++ b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/home/SessionControlInteractorTest.kt @@ -21,6 +21,7 @@ import org.mozilla.fenix.home.logo.LogoController import org.mozilla.fenix.home.logo.TrackingProtectionController import org.mozilla.fenix.home.pocket.PocketRecommendedStoriesCategory import org.mozilla.fenix.home.pocket.controller.PocketStoriesController +import org.mozilla.fenix.home.pocket.controller.StoriesImpressionSource import org.mozilla.fenix.home.privatebrowsing.controller.PrivateBrowsingController import org.mozilla.fenix.home.recentsyncedtabs.RecentSyncedTab import org.mozilla.fenix.home.recentsyncedtabs.controller.RecentSyncedTabController @@ -245,9 +246,11 @@ class SessionControlInteractorTest { fun `GIVEN a PocketStoriesInteractor WHEN stories are shown THEN handle it in a PocketStoriesController`() { val shownStories: List = emptyList() - interactor.onStoriesShown(shownStories) + interactor.onStoriesShown(shownStories, StoriesImpressionSource.HOMEPAGE) - verify { pocketStoriesController.handleStoriesShown(shownStories) } + verify { + pocketStoriesController.handleStoriesShown(shownStories, StoriesImpressionSource.HOMEPAGE) + } } @Test @@ -264,9 +267,15 @@ class SessionControlInteractorTest { val clickedStory: PocketStory = mockk() val storyPosition = Triple(1, 2, 3) - interactor.onStoryClicked(clickedStory, storyPosition) + interactor.onStoryClicked(clickedStory, storyPosition, StoriesImpressionSource.HOMEPAGE) - verify { pocketStoriesController.handleStoryClicked(clickedStory, storyPosition) } + verify { + pocketStoriesController.handleStoryClicked( + clickedStory, + storyPosition, + StoriesImpressionSource.HOMEPAGE, + ) + } } @Test 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 index bd988aac9a15c..899f092e923a1 100644 --- 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 @@ -41,6 +41,7 @@ import org.mozilla.fenix.helpers.FenixGleanTestRule import org.mozilla.fenix.home.HomeFragmentDirections import org.mozilla.fenix.home.mars.MARSUseCases import org.mozilla.fenix.home.pocket.controller.DefaultPocketStoriesController +import org.mozilla.fenix.home.pocket.controller.StoriesImpressionSource import org.mozilla.fenix.utils.Settings import org.mozilla.fenix.utils.Stories.markAsOpenedFromHomeScreen import org.mozilla.fenix.utils.Stories.markAsOpenedFromStoriesScreen @@ -282,7 +283,7 @@ class DefaultPocketStoriesControllerTest { assertNull(Pocket.homeRecsShown.testGetValue()) - controller.handleStoriesShown(storiesShown) + controller.handleStoriesShown(storiesShown, StoriesImpressionSource.HOMEPAGE) verify { store.dispatch( @@ -297,7 +298,42 @@ class DefaultPocketStoriesControllerTest { assertNotNull(Pocket.homeRecsShown.testGetValue()) assertEquals(1, Pocket.homeRecsShown.testGetValue()!!.size) - assertNull(Pocket.homeRecsShown.testGetValue()!!.single().extra) + assertEquals( + "homepage", + Pocket.homeRecsShown.testGetValue()!!.single().extra?.get("source"), + ) + } + + @Test + fun `WHEN new stories are shown on the stories screen THEN update the State and record telemetry`() = runTest { + val store = spyk(AppStore()) + val controller = createController(scope = this, appStore = store) + val recommendation = mockk() + val story = mockk() + val sponsoredStory = mockk() + val storiesShown = listOf(recommendation, story, sponsoredStory) + + assertNull(Pocket.homeRecsShown.testGetValue()) + + controller.handleStoriesShown(storiesShown, StoriesImpressionSource.STORIES_SCREEN) + + verify { + store.dispatch( + ContentRecommendationsAction.PocketStoriesShown( + impressions = listOf( + PocketImpression(story = recommendation, position = 0), + PocketImpression(story = story, position = 1), + ), + ), + ) + } + + assertNotNull(Pocket.homeRecsShown.testGetValue()) + assertEquals(1, Pocket.homeRecsShown.testGetValue()!!.size) + assertEquals( + "stories_screen", + Pocket.homeRecsShown.testGetValue()!!.single().extra?.get("source"), + ) } @Test @@ -314,7 +350,51 @@ class DefaultPocketStoriesControllerTest { val controller = createController(scope = this) assertNull(Pocket.homeRecsStoryClicked.testGetValue()) - controller.handleStoryClicked(story, storyPosition = Triple(1, 2, 3)) + controller.handleStoryClicked( + story, + storyPosition = Triple(1, 2, 3), + source = StoriesImpressionSource.HOMEPAGE, + ) + + verify { + navController.navigate(R.id.browserFragment) + fenixBrowserUseCases.loadUrlOrSearch( + searchTermOrURL = story.url, + newTab = true, + private = false, + ) + } + + assertNotNull(Pocket.homeRecsStoryClicked.testGetValue()) + val event = Pocket.homeRecsStoryClicked.testGetValue()!! + assertEquals(1, event.size) + assertTrue(event.single().extra!!.containsKey("position")) + assertEquals("1x2", event.single().extra!!["position"]) + assertTrue(event.single().extra!!.containsKey("times_shown")) + assertEquals(story.timesShown.inc().toString(), event.single().extra!!["times_shown"]) + assertTrue(event.single().extra!!.containsKey("source")) + assertEquals("homepage", event.single().extra!!["source"]) + } + + @Test + fun `WHEN a recommended story is clicked on the stories screen THEN open that story's url using HomeActivity and record telemetry`() = runTest { + val story = PocketRecommendedStory( + title = "", + url = "testLink", + imageUrl = "", + publisher = "", + category = "", + timeToRead = 0, + timesShown = 123, + ) + val controller = createController(scope = this) + assertNull(Pocket.homeRecsStoryClicked.testGetValue()) + + controller.handleStoryClicked( + story, + storyPosition = Triple(1, 2, 3), + source = StoriesImpressionSource.STORIES_SCREEN, + ) verify { navController.navigate(R.id.browserFragment) @@ -332,6 +412,8 @@ class DefaultPocketStoriesControllerTest { assertEquals("1x2", event.single().extra!!["position"]) assertTrue(event.single().extra!!.containsKey("times_shown")) assertEquals(story.timesShown.inc().toString(), event.single().extra!!["times_shown"]) + assertTrue(event.single().extra!!.containsKey("source")) + assertEquals("stories_screen", event.single().extra!!["source"]) } @Test @@ -350,7 +432,11 @@ class DefaultPocketStoriesControllerTest { val controller = createController(scope = this) assertNull(Pocket.homeRecsStoryClicked.testGetValue()) - controller.handleStoryClicked(story, storyPosition = Triple(1, 2, 3)) + controller.handleStoryClicked( + story, + storyPosition = Triple(1, 2, 3), + source = StoriesImpressionSource.HOMEPAGE, + ) verify { navController.navigate(R.id.browserFragment) @@ -368,6 +454,8 @@ class DefaultPocketStoriesControllerTest { assertEquals("1x2", event.single().extra!!["position"]) assertTrue(event.single().extra!!.containsKey("times_shown")) assertEquals(story.timesShown.inc().toString(), event.single().extra!!["times_shown"]) + assertTrue(event.single().extra!!.containsKey("source")) + assertEquals("homepage", event.single().extra!!["source"]) } @Test @@ -391,7 +479,11 @@ class DefaultPocketStoriesControllerTest { assertNull(Pocket.homeRecsSpocClicked.testGetValue()) - controller.handleStoryClicked(sponsoredContent, storyPosition = Triple(2, 3, 4)) + controller.handleStoryClicked( + sponsoredContent, + storyPosition = Triple(2, 3, 4), + source = StoriesImpressionSource.HOMEPAGE, + ) testScheduler.advanceUntilIdle() assertEquals(1, Pocket.homeRecsSpocClicked.testGetValue()!!.size) @@ -416,7 +508,11 @@ class DefaultPocketStoriesControllerTest { val story = PocketRecommendedStory("", "url", "", "", "", 0, 0) val controller = createController(scope = this) - controller.handleStoryClicked(story, storyPosition = Triple(1, 2, 3)) + controller.handleStoryClicked( + story, + storyPosition = Triple(1, 2, 3), + source = StoriesImpressionSource.HOMEPAGE, + ) verifyOrder { navController.navigate(R.id.browserFragment) @@ -435,7 +531,11 @@ class DefaultPocketStoriesControllerTest { val story = PocketRecommendedStory("", "url", "", "", "", 0, 0) val controller = createController(scope = this) - controller.handleStoryClicked(story, storyPosition = Triple(1, 2, 3)) + controller.handleStoryClicked( + story, + storyPosition = Triple(1, 2, 3), + source = StoriesImpressionSource.HOMEPAGE, + ) verifyOrder { navController.navigate(R.id.browserFragment) @@ -454,7 +554,11 @@ class DefaultPocketStoriesControllerTest { val story = PocketRecommendedStory("", originalURL, "", "", "", 0, 0) val controller = createController(scope = this) - controller.handleStoryClicked(story, storyPosition = Triple(1, 2, 3)) + controller.handleStoryClicked( + story, + storyPosition = Triple(1, 2, 3), + source = StoriesImpressionSource.HOMEPAGE, + ) verifyOrder { navController.navigate(R.id.browserFragment) @@ -473,7 +577,11 @@ class DefaultPocketStoriesControllerTest { val story = PocketRecommendedStory("", originalURL, "", "", "", 0, 0) val controller = createController(scope = this) - controller.handleStoryClicked(story, storyPosition = Triple(1, 2, 3)) + controller.handleStoryClicked( + story, + storyPosition = Triple(1, 2, 3), + source = StoriesImpressionSource.HOMEPAGE, + ) verifyOrder { navController.navigate(R.id.browserFragment)