diff --git a/app/metrics.yaml b/app/metrics.yaml index 0c41fa17d..69648f5e9 100644 --- a/app/metrics.yaml +++ b/app/metrics.yaml @@ -10856,14 +10856,36 @@ fx_suggest: ping_type: type: string description: > - The ping's type. Currently always "fxsuggest-click". + The ping's type. Either "fxsuggest-click" or "fxsuggest-impression". bugs: - https://bugzilla.mozilla.org/show_bug.cgi?id=1857092 data_reviews: - - https://github.com/mozilla-mobile/firefox-android/pull/3958#issuecomment-1758607927 + - https://github.com/mozilla-mobile/firefox-android/pull/3958#issuecomment-1768996728 + - https://github.com/mozilla-mobile/firefox-android/pull/4146#issuecomment-1775955811 data_sensitivity: - interaction notification_emails: + - android-probes@mozilla.com + - lina@mozilla.com + - ttran@mozilla.com + - najiang@mozilla.com + expires: never + send_in_pings: + - fx-suggest + position: + type: quantity + unit: non-negative integer + description: > + The position (1-based) of this suggestion in the full list of suggestions, relative to the + top of the awesomebar. + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1858542 + data_reviews: + - https://github.com/mozilla-mobile/firefox-android/pull/4146#issuecomment-1775955811 + data_sensitivity: + - interaction + notification_emails: + - android-probes@mozilla.com - lina@mozilla.com - ttran@mozilla.com - najiang@mozilla.com @@ -10877,10 +10899,11 @@ fx_suggest: bugs: - https://bugzilla.mozilla.org/show_bug.cgi?id=1857092 data_reviews: - - https://github.com/mozilla-mobile/firefox-android/pull/3958#issuecomment-1758607927 + - https://github.com/mozilla-mobile/firefox-android/pull/3958#issuecomment-1768996728 data_sensitivity: - interaction notification_emails: + - android-probes@mozilla.com - lina@mozilla.com - ttran@mozilla.com - najiang@mozilla.com @@ -10895,10 +10918,30 @@ fx_suggest: bugs: - https://bugzilla.mozilla.org/show_bug.cgi?id=1857092 data_reviews: - - https://github.com/mozilla-mobile/firefox-android/pull/3958#issuecomment-1758607927 + - https://github.com/mozilla-mobile/firefox-android/pull/3958#issuecomment-1768996728 + data_sensitivity: + - interaction + notification_emails: + - android-probes@mozilla.com + - lina@mozilla.com + - ttran@mozilla.com + - najiang@mozilla.com + expires: never + send_in_pings: + - fx-suggest + is_clicked: + type: boolean + description: > + If `ping_type` is "fxsuggest-impression", indicates whether this impression is for a clicked + suggestion. If `ping_type` is "fxsuggest-click", always `true`. + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1858542 + data_reviews: + - https://github.com/mozilla-mobile/firefox-android/pull/4146#issuecomment-1775955811 data_sensitivity: - interaction notification_emails: + - android-probes@mozilla.com - lina@mozilla.com - ttran@mozilla.com - najiang@mozilla.com @@ -10912,10 +10955,11 @@ fx_suggest: bugs: - https://bugzilla.mozilla.org/show_bug.cgi?id=1857092 data_reviews: - - https://github.com/mozilla-mobile/firefox-android/pull/3958#issuecomment-1758607927 + - https://github.com/mozilla-mobile/firefox-android/pull/3958#issuecomment-1768996728 data_sensitivity: - interaction notification_emails: + - android-probes@mozilla.com - lina@mozilla.com - ttran@mozilla.com - najiang@mozilla.com @@ -10929,10 +10973,11 @@ fx_suggest: bugs: - https://bugzilla.mozilla.org/show_bug.cgi?id=1857092 data_reviews: - - https://github.com/mozilla-mobile/firefox-android/pull/3958#issuecomment-1758607927 + - https://github.com/mozilla-mobile/firefox-android/pull/3958#issuecomment-1768996728 data_sensitivity: - interaction notification_emails: + - android-probes@mozilla.com - lina@mozilla.com - ttran@mozilla.com - najiang@mozilla.com @@ -10946,10 +10991,11 @@ fx_suggest: bugs: - https://bugzilla.mozilla.org/show_bug.cgi?id=1857092 data_reviews: - - https://github.com/mozilla-mobile/firefox-android/pull/3958#issuecomment-1758607927 + - https://github.com/mozilla-mobile/firefox-android/pull/3958#issuecomment-1768996728 data_sensitivity: - interaction notification_emails: + - android-probes@mozilla.com - lina@mozilla.com - ttran@mozilla.com - najiang@mozilla.com diff --git a/app/src/main/java/org/mozilla/fenix/components/Core.kt b/app/src/main/java/org/mozilla/fenix/components/Core.kt index 4a4ad1c7c..aece11e5a 100644 --- a/app/src/main/java/org/mozilla/fenix/components/Core.kt +++ b/app/src/main/java/org/mozilla/fenix/components/Core.kt @@ -40,6 +40,7 @@ import mozilla.components.concept.fetch.Client import mozilla.components.feature.awesomebar.provider.SessionAutocompleteProvider import mozilla.components.feature.customtabs.store.CustomTabsServiceStore import mozilla.components.feature.downloads.DownloadMiddleware +import mozilla.components.feature.fxsuggest.facts.FxSuggestFactsMiddleware import mozilla.components.feature.logins.exceptions.LoginExceptionStorage import mozilla.components.feature.media.MediaSessionFeature import mozilla.components.feature.media.middleware.LastMediaAccessMiddleware @@ -281,6 +282,7 @@ class Core( HistoryMetadataMiddleware(historyMetadataService), SessionPrioritizationMiddleware(), SaveToPDFMiddleware(context), + FxSuggestFactsMiddleware(), ) BrowserStore( diff --git a/app/src/main/java/org/mozilla/fenix/components/metrics/MetricController.kt b/app/src/main/java/org/mozilla/fenix/components/metrics/MetricController.kt index 7227140f4..05fd94769 100644 --- a/app/src/main/java/org/mozilla/fenix/components/metrics/MetricController.kt +++ b/app/src/main/java/org/mozilla/fenix/components/metrics/MetricController.kt @@ -281,16 +281,37 @@ internal class ReleaseMetricController( } Component.FEATURE_FXSUGGEST to FxSuggestFacts.Items.AMP_SUGGESTION_CLICKED -> { + FxSuggest.pingType.set("fxsuggest-click") + FxSuggest.isClicked.set(true) + (metadata?.get(FxSuggestFacts.MetadataKeys.POSITION) as? Long)?.let { + FxSuggest.position.set(it) + } (metadata?.get(FxSuggestFacts.MetadataKeys.INTERACTION_INFO) as? FxSuggestInteractionInfo.Amp)?.let { - FxSuggest.pingType.set("fxsuggest-click") FxSuggest.blockId.set(it.blockId) FxSuggest.advertiser.set(it.advertiser) FxSuggest.reportingUrl.set(it.reportingUrl) FxSuggest.iabCategory.set(it.iabCategory) FxSuggest.contextId.set(UUID.fromString(it.contextId)) - Pings.fxSuggest.submit() } - Unit + Pings.fxSuggest.submit() + } + + Component.FEATURE_FXSUGGEST to FxSuggestFacts.Items.AMP_SUGGESTION_IMPRESSED -> { + FxSuggest.pingType.set("fxsuggest-impression") + (metadata?.get(FxSuggestFacts.MetadataKeys.IS_CLICKED) as? Boolean)?.let { + FxSuggest.isClicked.set(it) + } + (metadata?.get(FxSuggestFacts.MetadataKeys.POSITION) as? Long)?.let { + FxSuggest.position.set(it) + } + (metadata?.get(FxSuggestFacts.MetadataKeys.INTERACTION_INFO) as? FxSuggestInteractionInfo.Amp)?.let { + FxSuggest.blockId.set(it.blockId) + FxSuggest.advertiser.set(it.advertiser) + FxSuggest.reportingUrl.set(it.reportingUrl) + FxSuggest.iabCategory.set(it.iabCategory) + FxSuggest.contextId.set(UUID.fromString(it.contextId)) + } + Pings.fxSuggest.submit() } Component.FEATURE_PWA to ProgressiveWebAppFacts.Items.HOMESCREEN_ICON_TAP -> { diff --git a/app/src/main/java/org/mozilla/fenix/search/SearchDialogController.kt b/app/src/main/java/org/mozilla/fenix/search/SearchDialogController.kt index c0443a551..a7d948e61 100644 --- a/app/src/main/java/org/mozilla/fenix/search/SearchDialogController.kt +++ b/app/src/main/java/org/mozilla/fenix/search/SearchDialogController.kt @@ -12,6 +12,7 @@ import android.text.SpannableString import androidx.annotation.VisibleForTesting import androidx.appcompat.app.AlertDialog import androidx.navigation.NavController +import mozilla.components.browser.state.action.AwesomeBarAction import mozilla.components.browser.state.search.SearchEngine import mozilla.components.browser.state.state.selectedOrDefaultSearchEngine import mozilla.components.browser.state.store.BrowserStore @@ -88,11 +89,13 @@ class SearchDialogController( // fennec users may be used to navigating to "about:crashes". So we intercept this here // and open the crash list activity instead. activity.startActivity(Intent(activity, CrashListActivity::class.java)) + store.dispatch(AwesomeBarAction.EngagementFinished(abandoned = false)) } "about:addons" -> { val directions = SearchDialogFragmentDirections.actionGlobalAddonsManagementFragment() navController.navigateSafe(R.id.searchDialogFragment, directions) + store.dispatch(AwesomeBarAction.EngagementFinished(abandoned = false)) } "moz://a" -> openSearchOrUrl( SupportUtils.getMozillaPageUrl(SupportUtils.MozillaPage.MANIFESTO), @@ -101,6 +104,8 @@ class SearchDialogController( else -> if (url.isNotBlank()) { openSearchOrUrl(url, fromHomeScreen) + } else { + store.dispatch(AwesomeBarAction.EngagementFinished(abandoned = true)) } } dismissDialog() @@ -143,6 +148,8 @@ class SearchDialogController( searchAccessPoint, ) } + + store.dispatch(AwesomeBarAction.EngagementFinished(abandoned = false)) } override fun handleEditingCancelled() { @@ -193,6 +200,8 @@ class SearchDialogController( ) Events.enteredUrl.record(Events.EnteredUrlExtra(autocomplete = false)) + + store.dispatch(AwesomeBarAction.EngagementFinished(abandoned = false)) } override fun handleSearchTermsTapped(searchTerms: String) { @@ -228,6 +237,8 @@ class SearchDialogController( searchAccessPoint, ) } + + store.dispatch(AwesomeBarAction.EngagementFinished(abandoned = false)) } override fun handleSearchShortcutEngineSelected(searchEngine: SearchEngine) { @@ -280,6 +291,7 @@ class SearchDialogController( clearToolbarFocus() val directions = SearchDialogFragmentDirections.actionGlobalSearchEngineFragment() navController.navigateSafe(R.id.searchDialogFragment, directions) + store.dispatch(AwesomeBarAction.EngagementFinished(abandoned = true)) } override fun handleExistingSessionSelected(tabId: String) { @@ -290,6 +302,8 @@ class SearchDialogController( activity.openToBrowser( from = BrowserDirection.FromSearchDialog, ) + + store.dispatch(AwesomeBarAction.EngagementFinished(abandoned = false)) } /** @@ -346,6 +360,9 @@ class SearchDialogController( dialog.cancel() activity.startActivity(intent) } + setOnDismissListener { + store.dispatch(AwesomeBarAction.EngagementFinished(abandoned = true)) + } create().withCenterAlignedButtons() } } diff --git a/app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt b/app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt index 4d4d80ac6..04a28a1b3 100644 --- a/app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt @@ -46,6 +46,7 @@ import androidx.navigation.fragment.navArgs import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch +import mozilla.components.browser.state.action.AwesomeBarAction import mozilla.components.browser.state.search.SearchEngine import mozilla.components.browser.state.state.searchEngines import mozilla.components.browser.state.state.selectedOrDefaultSearchEngine @@ -634,6 +635,9 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { override fun onDismiss(dialog: DialogInterface) { super.onDismiss(dialog) hideDeviceKeyboard() + if (!dialogHandledAction) { + requireComponents.core.store.dispatch(AwesomeBarAction.EngagementFinished(abandoned = true)) + } } override fun onBackPressed(): Boolean { diff --git a/app/src/main/java/org/mozilla/fenix/search/awesomebar/AwesomeBarWrapper.kt b/app/src/main/java/org/mozilla/fenix/search/awesomebar/AwesomeBarWrapper.kt index a70da3c97..c6702c683 100644 --- a/app/src/main/java/org/mozilla/fenix/search/awesomebar/AwesomeBarWrapper.kt +++ b/app/src/main/java/org/mozilla/fenix/search/awesomebar/AwesomeBarWrapper.kt @@ -10,6 +10,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.AbstractComposeView +import mozilla.components.browser.state.action.AwesomeBarAction import mozilla.components.compose.browser.awesomebar.AwesomeBar import mozilla.components.compose.browser.awesomebar.AwesomeBarDefaults import mozilla.components.compose.browser.awesomebar.AwesomeBarOrientation @@ -64,6 +65,7 @@ class AwesomeBarWrapper @JvmOverloads constructor( groupTitle = ThemeManager.resolveAttributeColor(R.attr.textSecondary), ), onSuggestionClicked = { suggestion -> + context.components.core.store.dispatch(AwesomeBarAction.SuggestionClicked(suggestion)) suggestion.onSuggestionClicked?.invoke() when { suggestion.flags.contains(AwesomeBar.Suggestion.Flag.HISTORY) -> { @@ -78,6 +80,9 @@ class AwesomeBarWrapper @JvmOverloads constructor( onAutoComplete = { suggestion -> onEditSuggestionListener?.invoke(suggestion.editSuggestion!!) }, + onVisibilityStateUpdated = { + context.components.core.store.dispatch(AwesomeBarAction.VisibilityStateUpdated(it)) + }, onScroll = { hideKeyboard() }, profiler = context.components.core.engine.profiler, ) diff --git a/app/src/test/java/org/mozilla/fenix/search/SearchDialogControllerTest.kt b/app/src/test/java/org/mozilla/fenix/search/SearchDialogControllerTest.kt index 504e012be..1133b6c8d 100644 --- a/app/src/test/java/org/mozilla/fenix/search/SearchDialogControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/search/SearchDialogControllerTest.kt @@ -18,6 +18,7 @@ import io.mockk.spyk import io.mockk.unmockkObject import io.mockk.verify import kotlinx.coroutines.test.runTest +import mozilla.components.browser.state.action.AwesomeBarAction import mozilla.components.browser.state.action.BrowserAction import mozilla.components.browser.state.action.TabListAction import mozilla.components.browser.state.search.SearchEngine @@ -112,6 +113,8 @@ class SearchDialogControllerTest { createController().handleUrlCommitted(url) + browserStore.waitUntilIdle() + verify { activity.openToBrowserAndLoad( searchTermOrURL = url, @@ -124,6 +127,10 @@ class SearchDialogControllerTest { ) } + middleware.assertLastAction(AwesomeBarAction.EngagementFinished::class) { action -> + assertFalse(action.abandoned) + } + assertNotNull(Events.enteredUrl.testGetValue()) val snapshot = Events.enteredUrl.testGetValue()!! assertEquals(1, snapshot.size) @@ -139,6 +146,8 @@ class SearchDialogControllerTest { createController().handleUrlCommitted(url) + browserStore.waitUntilIdle() + verify { activity.openToBrowserAndLoad( searchTermOrURL = url, @@ -151,6 +160,10 @@ class SearchDialogControllerTest { ) } + middleware.assertLastAction(AwesomeBarAction.EngagementFinished::class) { action -> + assertFalse(action.abandoned) + } + assertNotNull(Events.enteredUrl.testGetValue()) val snapshot = Events.enteredUrl.testGetValue()!! assertEquals(1, snapshot.size) @@ -168,6 +181,8 @@ class SearchDialogControllerTest { createController().handleUrlCommitted(searchTerm) + browserStore.waitUntilIdle() + verify { activity.openToBrowserAndLoad( searchTermOrURL = searchTerm, @@ -181,6 +196,10 @@ class SearchDialogControllerTest { ), ) } + + middleware.assertLastAction(AwesomeBarAction.EngagementFinished::class) { action -> + assertFalse(action.abandoned) + } } @Test @@ -194,6 +213,8 @@ class SearchDialogControllerTest { createController().handleUrlCommitted(searchTerm) + browserStore.waitUntilIdle() + verify { activity.openToBrowserAndLoad( searchTermOrURL = searchTerm, @@ -207,6 +228,10 @@ class SearchDialogControllerTest { ), ) } + + middleware.assertLastAction(AwesomeBarAction.EngagementFinished::class) { action -> + assertFalse(action.abandoned) + } } @Test @@ -220,7 +245,13 @@ class SearchDialogControllerTest { }, ).handleUrlCommitted(url) + browserStore.waitUntilIdle() + assertTrue(dismissDialogInvoked) + + middleware.assertLastAction(AwesomeBarAction.EngagementFinished::class) { action -> + assertTrue(action.abandoned) + } } @Test @@ -229,6 +260,8 @@ class SearchDialogControllerTest { createController().handleUrlCommitted(searchTerm) + browserStore.waitUntilIdle() + verify { activity.openToBrowserAndLoad( searchTermOrURL = searchTerm, @@ -240,6 +273,10 @@ class SearchDialogControllerTest { additionalHeaders = null, ) } + + middleware.assertLastAction(AwesomeBarAction.EngagementFinished::class) { action -> + assertFalse(action.abandoned) + } } @Test @@ -255,6 +292,8 @@ class SearchDialogControllerTest { }, ).handleUrlCommitted(searchTerm) + browserStore.waitUntilIdle() + verify(exactly = 0) { activity.openToBrowserAndLoad( searchTermOrURL = any(), @@ -265,6 +304,8 @@ class SearchDialogControllerTest { } assertFalse(dismissDialogInvoked) + + middleware.assertNotDispatched(AwesomeBarAction.EngagementFinished::class) } @Test @@ -274,9 +315,15 @@ class SearchDialogControllerTest { createController().handleUrlCommitted(url) + browserStore.waitUntilIdle() + verify { activity.startActivity(any()) } + + middleware.assertLastAction(AwesomeBarAction.EngagementFinished::class) { action -> + assertFalse(action.abandoned) + } } @Test @@ -286,7 +333,13 @@ class SearchDialogControllerTest { createController().handleUrlCommitted(url) + browserStore.waitUntilIdle() + verify { navController.navigate(directions) } + + middleware.assertLastAction(AwesomeBarAction.EngagementFinished::class) { action -> + assertFalse(action.abandoned) + } } @Test @@ -298,6 +351,8 @@ class SearchDialogControllerTest { createController().handleUrlCommitted(url) + browserStore.waitUntilIdle() + verify { activity.openToBrowserAndLoad( searchTermOrURL = SupportUtils.getMozillaPageUrl(SupportUtils.MozillaPage.MANIFESTO), @@ -309,6 +364,10 @@ class SearchDialogControllerTest { ) } + middleware.assertLastAction(AwesomeBarAction.EngagementFinished::class) { action -> + assertFalse(action.abandoned) + } + assertNotNull(Events.enteredUrl.testGetValue()) val snapshot = Events.enteredUrl.testGetValue()!! assertEquals(1, snapshot.size) @@ -338,7 +397,11 @@ class SearchDialogControllerTest { createController().handleTextChanged(text) + browserStore.waitUntilIdle() + verify { store.dispatch(SearchFragmentAction.UpdateQuery(text)) } + + middleware.assertNotDispatched(AwesomeBarAction.EngagementFinished::class) } @Test @@ -347,7 +410,11 @@ class SearchDialogControllerTest { createController().handleTextChanged(text) + browserStore.waitUntilIdle() + verify { store.dispatch(SearchFragmentAction.UpdateQuery(text)) } + + middleware.assertNotDispatched(AwesomeBarAction.EngagementFinished::class) } @Test @@ -357,7 +424,11 @@ class SearchDialogControllerTest { createController().handleTextChanged(text) + browserStore.waitUntilIdle() + verify { store.dispatch(SearchFragmentAction.ShowSearchShortcutEnginePicker(true)) } + + middleware.assertNotDispatched(AwesomeBarAction.EngagementFinished::class) } @Test @@ -368,7 +439,11 @@ class SearchDialogControllerTest { createController().handleTextChanged(text) + browserStore.waitUntilIdle() + verify { store.dispatch(SearchFragmentAction.ShowSearchShortcutEnginePicker(true)) } + + middleware.assertNotDispatched(AwesomeBarAction.EngagementFinished::class) } @Test @@ -379,7 +454,11 @@ class SearchDialogControllerTest { createController().handleTextChanged(text) + browserStore.waitUntilIdle() + verify { store.dispatch(SearchFragmentAction.ShowSearchShortcutEnginePicker(false)) } + + middleware.assertNotDispatched(AwesomeBarAction.EngagementFinished::class) } @Test @@ -391,7 +470,11 @@ class SearchDialogControllerTest { createController().handleTextChanged(text) + browserStore.waitUntilIdle() + verify { store.dispatch(SearchFragmentAction.ShowSearchShortcutEnginePicker(false)) } + + middleware.assertNotDispatched(AwesomeBarAction.EngagementFinished::class) } @Test @@ -400,7 +483,11 @@ class SearchDialogControllerTest { createController().handleTextChanged(text) + browserStore.waitUntilIdle() + verify { store.dispatch(SearchFragmentAction.ShowSearchShortcutEnginePicker(false)) } + + middleware.assertNotDispatched(AwesomeBarAction.EngagementFinished::class) } @Test @@ -411,7 +498,11 @@ class SearchDialogControllerTest { createController().handleTextChanged(text) + browserStore.waitUntilIdle() + verify { store.dispatch(SearchFragmentAction.ShowSearchShortcutEnginePicker(false)) } + + middleware.assertNotDispatched(AwesomeBarAction.EngagementFinished::class) } @Test @@ -422,7 +513,11 @@ class SearchDialogControllerTest { createController().handleTextChanged(text) + browserStore.waitUntilIdle() + verify { store.dispatch(SearchFragmentAction.ShowSearchShortcutEnginePicker(false)) } + + middleware.assertNotDispatched(AwesomeBarAction.EngagementFinished::class) } @Test @@ -432,9 +527,14 @@ class SearchDialogControllerTest { val text = "mozilla" createController().handleTextChanged(text) + + browserStore.waitUntilIdle() + val actionSlot = mutableListOf() verify { store.dispatch(capture(actionSlot)) } assertFalse(actionSlot.any { it is SearchFragmentAction.AllowSearchSuggestionsInPrivateModePrompt }) + + middleware.assertNotDispatched(AwesomeBarAction.EngagementFinished::class) } @Test @@ -444,9 +544,14 @@ class SearchDialogControllerTest { val text = "mozilla" createController().handleTextChanged(text) + + browserStore.waitUntilIdle() + val actionSlot = mutableListOf() verify { store.dispatch(capture(actionSlot)) } assertTrue(actionSlot.any { it is SearchFragmentAction.AllowSearchSuggestionsInPrivateModePrompt }) + + middleware.assertNotDispatched(AwesomeBarAction.EngagementFinished::class) } @Test @@ -458,6 +563,8 @@ class SearchDialogControllerTest { createController().handleUrlTapped(url, flags) createController().handleUrlTapped(url) + browserStore.waitUntilIdle() + verify { activity.openToBrowserAndLoad( searchTermOrURL = url, @@ -472,6 +579,10 @@ class SearchDialogControllerTest { assertEquals(2, snapshot.size) assertEquals("false", snapshot.first().extra?.getValue("autocomplete")) assertEquals("false", snapshot[1].extra?.getValue("autocomplete")) + + middleware.assertLastAction(AwesomeBarAction.EngagementFinished::class) { action -> + assertFalse(action.abandoned) + } } @Test @@ -480,6 +591,8 @@ class SearchDialogControllerTest { createController().handleSearchTermsTapped(searchTerms) + browserStore.waitUntilIdle() + verify { activity.openToBrowserAndLoad( searchTermOrURL = searchTerms, @@ -491,6 +604,10 @@ class SearchDialogControllerTest { additionalHeaders = null, ) } + + middleware.assertLastAction(AwesomeBarAction.EngagementFinished::class) { action -> + assertFalse(action.abandoned) + } } @Test @@ -506,9 +623,13 @@ class SearchDialogControllerTest { }, ).handleSearchShortcutEngineSelected(searchEngine) + browserStore.waitUntilIdle() + assertTrue(focusToolbarInvoked) verify { store.dispatch(SearchFragmentAction.SearchShortcutEngineSelected(searchEngine, browsingMode, settings)) } + middleware.assertNotDispatched(AwesomeBarAction.EngagementFinished::class) + assertNotNull(SearchShortcuts.selected.testGetValue()) val recordedEvents = SearchShortcuts.selected.testGetValue()!! assertEquals(1, recordedEvents.size) @@ -534,9 +655,13 @@ class SearchDialogControllerTest { }, ).handleSearchShortcutEngineSelected(searchEngine) + browserStore.waitUntilIdle() + assertTrue(focusToolbarInvoked) verify { store.dispatch(SearchFragmentAction.SearchHistoryEngineSelected(searchEngine)) } + middleware.assertNotDispatched(AwesomeBarAction.EngagementFinished::class) + assertNotNull(UnifiedSearch.engineSelected.testGetValue()) val recordedEvents = UnifiedSearch.engineSelected.testGetValue()!! assertEquals(1, recordedEvents.size) @@ -562,9 +687,13 @@ class SearchDialogControllerTest { }, ).handleSearchShortcutEngineSelected(searchEngine) + browserStore.waitUntilIdle() + assertTrue(focusToolbarInvoked) verify { store.dispatch(SearchFragmentAction.SearchBookmarksEngineSelected(searchEngine)) } + middleware.assertNotDispatched(AwesomeBarAction.EngagementFinished::class) + assertNotNull(UnifiedSearch.engineSelected.testGetValue()) val recordedEvents = UnifiedSearch.engineSelected.testGetValue()!! assertEquals(1, recordedEvents.size) @@ -590,9 +719,13 @@ class SearchDialogControllerTest { }, ).handleSearchShortcutEngineSelected(searchEngine) + browserStore.waitUntilIdle() + assertTrue(focusToolbarInvoked) verify { store.dispatch(SearchFragmentAction.SearchTabsEngineSelected(searchEngine)) } + middleware.assertNotDispatched(AwesomeBarAction.EngagementFinished::class) + assertNotNull(UnifiedSearch.engineSelected.testGetValue()) val recordedEvents = UnifiedSearch.engineSelected.testGetValue()!! assertEquals(1, recordedEvents.size) @@ -608,7 +741,13 @@ class SearchDialogControllerTest { createController().handleClickSearchEngineSettings() + browserStore.waitUntilIdle() + verify { navController.navigate(directions) } + + middleware.assertLastAction(AwesomeBarAction.EngagementFinished::class) { action -> + assertTrue(action.abandoned) + } } @Test @@ -617,7 +756,11 @@ class SearchDialogControllerTest { createController().handleSearchShortcutsButtonClicked() + browserStore.waitUntilIdle() + verify { store.dispatch(SearchFragmentAction.ShowSearchShortcutEnginePicker(false)) } + + middleware.assertNotDispatched(AwesomeBarAction.EngagementFinished::class) } @Test @@ -626,7 +769,11 @@ class SearchDialogControllerTest { createController().handleSearchShortcutsButtonClicked() + browserStore.waitUntilIdle() + verify { store.dispatch(SearchFragmentAction.ShowSearchShortcutEnginePicker(true)) } + + middleware.assertNotDispatched(AwesomeBarAction.EngagementFinished::class) } @Test @@ -640,6 +787,10 @@ class SearchDialogControllerTest { } verify { activity.openToBrowser(from = BrowserDirection.FromSearchDialog) } + + middleware.assertLastAction(AwesomeBarAction.EngagementFinished::class) { action -> + assertFalse(action.abandoned) + } } @Test @@ -652,6 +803,10 @@ class SearchDialogControllerTest { assertEquals("tab-id", action.tabId) } verify { activity.openToBrowser(from = BrowserDirection.FromSearchDialog) } + + middleware.assertLastAction(AwesomeBarAction.EngagementFinished::class) { action -> + assertFalse(action.abandoned) + } } @Test