Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add scoring algorithm for history suggestions (extracted from BSK) #4341

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ fladle {
}

dependencies {
implementation project(":history-impl")
implementation project(":history-api")
implementation project(":verified-installation-impl")
implementation project(":verified-installation-api")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import com.duckduckgo.app.accessibility.data.AccessibilitySettingsDataStore
import com.duckduckgo.app.accessibility.data.AccessibilitySettingsSharedPreferences
import com.duckduckgo.app.autocomplete.api.AutoComplete.AutoCompleteResult
import com.duckduckgo.app.autocomplete.api.AutoComplete.AutoCompleteSuggestion.AutoCompleteBookmarkSuggestion
import com.duckduckgo.app.autocomplete.api.AutoComplete.AutoCompleteSuggestion.AutoCompleteHistoryRelatedSuggestion.AutoCompleteHistorySearchSuggestion
import com.duckduckgo.app.autocomplete.api.AutoComplete.AutoCompleteSuggestion.AutoCompleteSearchSuggestion
import com.duckduckgo.app.autocomplete.api.AutoCompleteApi
import com.duckduckgo.app.autocomplete.api.AutoCompleteService
Expand Down Expand Up @@ -132,6 +133,7 @@ import com.duckduckgo.app.privacy.model.TestEntity
import com.duckduckgo.app.settings.db.SettingsDataStore
import com.duckduckgo.app.statistics.api.StatisticsUpdater
import com.duckduckgo.app.statistics.pixels.Pixel
import com.duckduckgo.app.statistics.pixels.Pixel.PixelParameter
import com.duckduckgo.app.statistics.pixels.Pixel.PixelType.COUNT
import com.duckduckgo.app.surrogates.SurrogateResponse
import com.duckduckgo.app.survey.api.SurveyRepository
Expand Down Expand Up @@ -160,6 +162,7 @@ import com.duckduckgo.downloads.api.FileDownloader
import com.duckduckgo.downloads.api.FileDownloader.PendingFileDownload
import com.duckduckgo.feature.toggles.api.FeatureToggle
import com.duckduckgo.feature.toggles.api.Toggle
import com.duckduckgo.history.api.NavigationHistory
import com.duckduckgo.privacy.config.api.*
import com.duckduckgo.privacy.config.impl.features.gpc.RealGpc
import com.duckduckgo.privacy.config.impl.features.gpc.RealGpc.Companion.GPC_HEADER
Expand Down Expand Up @@ -259,6 +262,9 @@ class BrowserTabViewModelTest {
@Mock
private lateinit var mockSavedSitesRepository: SavedSitesRepository

@Mock
private lateinit var mockNavigationHistory: NavigationHistory

@Mock
private lateinit var mockLongPressHandler: LongPressHandler

Expand Down Expand Up @@ -463,7 +469,7 @@ class BrowserTabViewModelTest {
fireproofWebsiteDao = db.fireproofWebsiteDao()
locationPermissionsDao = db.locationPermissionsDao()

mockAutoCompleteApi = AutoCompleteApi(mockAutoCompleteService, mockSavedSitesRepository)
mockAutoCompleteApi = AutoCompleteApi(mockAutoCompleteService, mockSavedSitesRepository, mockNavigationHistory)
val fireproofWebsiteRepositoryImpl = FireproofWebsiteRepositoryImpl(
fireproofWebsiteDao,
coroutineRule.testDispatcherProvider,
Expand Down Expand Up @@ -2160,7 +2166,43 @@ class BrowserTabViewModelTest {
val suggestion = AutoCompleteBookmarkSuggestion("example", "Example", "https://example.com")
testee.autoCompleteViewState.value = autoCompleteViewState().copy(searchResults = AutoCompleteResult("", listOf(suggestion)))
testee.fireAutocompletePixel(suggestion)
verify(mockPixel).fire(AppPixelName.AUTOCOMPLETE_BOOKMARK_SELECTION, pixelParams(showedBookmarks = true, bookmarkCapable = true))
val argumentCaptor = argumentCaptor<Map<String, String>>()
verify(mockPixel).fire(eq(AppPixelName.AUTOCOMPLETE_BOOKMARK_SELECTION), argumentCaptor.capture(), any(), any())

assertEquals("true", argumentCaptor.firstValue[PixelParameter.SHOWED_BOOKMARKS])
assertEquals("true", argumentCaptor.firstValue[PixelParameter.BOOKMARK_CAPABLE])
}

@Test
fun whenBookmarkFavoriteSubmittedThenAutoCompleteFavoriteSelectionPixelSent() = runTest {
whenever(mockSavedSitesRepository.hasBookmarks()).thenReturn(true)
whenever(mockSavedSitesRepository.hasFavorites()).thenReturn(true)
val suggestion = AutoCompleteBookmarkSuggestion("example", "Example", "https://example.com", isFavorite = true)
testee.autoCompleteViewState.value = autoCompleteViewState().copy(searchResults = AutoCompleteResult("", listOf(suggestion)))
testee.fireAutocompletePixel(suggestion)

val argumentCaptor = argumentCaptor<Map<String, String>>()
verify(mockPixel).fire(eq(AppPixelName.AUTOCOMPLETE_FAVORITE_SELECTION), argumentCaptor.capture(), any(), any())

assertEquals("false", argumentCaptor.firstValue[PixelParameter.SHOWED_BOOKMARKS])
assertEquals("true", argumentCaptor.firstValue[PixelParameter.SHOWED_FAVORITES])
assertEquals("true", argumentCaptor.firstValue[PixelParameter.BOOKMARK_CAPABLE])
assertEquals("true", argumentCaptor.firstValue[PixelParameter.FAVORITE_CAPABLE])
}

@Test
fun whenHistorySubmittedThenAutoCompleteHistorySelectionPixelSent() = runTest {
whenever(mockSavedSitesRepository.hasBookmarks()).thenReturn(true)
val suggestion = AutoCompleteHistorySearchSuggestion("example")
testee.autoCompleteViewState.value = autoCompleteViewState().copy(searchResults = AutoCompleteResult("", listOf(suggestion)))
testee.fireAutocompletePixel(suggestion)

val argumentCaptor = argumentCaptor<Map<String, String>>()
verify(mockPixel).fire(eq(AppPixelName.AUTOCOMPLETE_HISTORY_SELECTION), argumentCaptor.capture(), any(), any())

assertEquals("false", argumentCaptor.firstValue[PixelParameter.SHOWED_BOOKMARKS])
assertEquals("true", argumentCaptor.firstValue[PixelParameter.BOOKMARK_CAPABLE])
assertEquals("true", argumentCaptor.firstValue[PixelParameter.SHOWED_HISTORY])
}

@Test
Expand All @@ -2170,7 +2212,11 @@ class BrowserTabViewModelTest {
testee.autoCompleteViewState.value = autoCompleteViewState().copy(searchResults = AutoCompleteResult("", suggestions))
testee.fireAutocompletePixel(AutoCompleteSearchSuggestion("example", false))

verify(mockPixel).fire(AppPixelName.AUTOCOMPLETE_SEARCH_SELECTION, pixelParams(showedBookmarks = true, bookmarkCapable = true))
val argumentCaptor = argumentCaptor<Map<String, String>>()
verify(mockPixel).fire(eq(AppPixelName.AUTOCOMPLETE_SEARCH_SELECTION), argumentCaptor.capture(), any(), any())

assertEquals("true", argumentCaptor.firstValue[PixelParameter.SHOWED_BOOKMARKS])
assertEquals("true", argumentCaptor.firstValue[PixelParameter.BOOKMARK_CAPABLE])
}

@Test
Expand All @@ -2179,7 +2225,11 @@ class BrowserTabViewModelTest {
testee.autoCompleteViewState.value = autoCompleteViewState().copy(searchResults = AutoCompleteResult("", emptyList()))
testee.fireAutocompletePixel(AutoCompleteSearchSuggestion("example", false))

verify(mockPixel).fire(AppPixelName.AUTOCOMPLETE_SEARCH_SELECTION, pixelParams(showedBookmarks = false, bookmarkCapable = false))
val argumentCaptor = argumentCaptor<Map<String, String>>()
verify(mockPixel).fire(eq(AppPixelName.AUTOCOMPLETE_SEARCH_SELECTION), argumentCaptor.capture(), any(), any())

assertEquals("false", argumentCaptor.firstValue[PixelParameter.SHOWED_BOOKMARKS])
assertEquals("false", argumentCaptor.firstValue[PixelParameter.BOOKMARK_CAPABLE])
}

@Test
Expand Down Expand Up @@ -5330,9 +5380,11 @@ class BrowserTabViewModelTest {
private fun pixelParams(
showedBookmarks: Boolean,
bookmarkCapable: Boolean,
showedHistory: Boolean = false,
) = mapOf(
Pixel.PixelParameter.SHOWED_BOOKMARKS to showedBookmarks.toString(),
Pixel.PixelParameter.BOOKMARK_CAPABLE to bookmarkCapable.toString(),
Pixel.PixelParameter.SHOWED_HISTORY to showedHistory.toString(),
)

private fun givenExpectedCtaAddWidgetInstructions() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ import org.junit.Test
import org.mockito.ArgumentMatchers.anyString
import org.mockito.kotlin.any
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
import org.mockito.kotlin.never
import org.mockito.kotlin.times
Expand Down Expand Up @@ -162,7 +163,7 @@ class BrowserWebViewClientTest {
testee.webViewClientListener = listener
whenever(webResourceRequest.url).thenReturn(Uri.EMPTY)
whenever(cookieManagerProvider.get()).thenReturn(cookieManager)
whenever(currentTimeProvider.getTimeInMillis()).thenReturn(0)
whenever(currentTimeProvider.elapsedRealtime()).thenReturn(0)
whenever(webViewVersionProvider.getMajorVersion()).thenReturn("1")
whenever(deviceInfo.appVersion).thenReturn("1")
}
Expand Down Expand Up @@ -715,7 +716,7 @@ class BrowserWebViewClientTest {
fun whenPageFinishesBeforeStartingThenPixelIsNotFired() {
val mockWebView = getImmediatelyInvokedMockWebView()
testee.onPageFinished(mockWebView, EXAMPLE_URL)
verify(pageLoadedHandler, never()).invoke(any(), any(), any())
verify(pageLoadedHandler, never()).onPageLoaded(any(), any(), any(), any())
}

@Test
Expand All @@ -725,11 +726,11 @@ class BrowserWebViewClientTest {
whenever(mockWebView.safeCopyBackForwardList()).thenReturn(TestBackForwardList())
whenever(mockWebView.settings).thenReturn(mock())
testee.onPageStarted(mockWebView, EXAMPLE_URL, null)
whenever(currentTimeProvider.getTimeInMillis()).thenReturn(10)
whenever(currentTimeProvider.elapsedRealtime()).thenReturn(10)
testee.onPageFinished(mockWebView, EXAMPLE_URL)
val startArgumentCaptor = argumentCaptor<Long>()
val endArgumentCaptor = argumentCaptor<Long>()
verify(pageLoadedHandler).invoke(any(), startArgumentCaptor.capture(), endArgumentCaptor.capture())
verify(pageLoadedHandler).onPageLoaded(any(), eq(null), startArgumentCaptor.capture(), endArgumentCaptor.capture())
assertEquals(0L, startArgumentCaptor.firstValue)
assertEquals(10L, endArgumentCaptor.firstValue)
}
Expand All @@ -742,7 +743,7 @@ class BrowserWebViewClientTest {
whenever(mockWebView.settings).thenReturn(mock())
testee.onPageStarted(mockWebView, "about:blank", null)
testee.onPageFinished(mockWebView, "about:blank")
verify(pageLoadedHandler, never()).invoke(any(), any(), any())
verify(pageLoadedHandler, never()).onPageLoaded(any(), any(), any(), any())
}

@Test
Expand All @@ -751,7 +752,7 @@ class BrowserWebViewClientTest {
whenever(mockWebView.settings).thenReturn(mock())
testee.onPageStarted(mockWebView, EXAMPLE_URL, null)
testee.onPageFinished(mockWebView, EXAMPLE_URL)
verify(pageLoadedHandler, never()).invoke(any(), any(), any())
verify(pageLoadedHandler, never()).onPageLoaded(any(), any(), any(), any())
}

@Test
Expand All @@ -761,14 +762,14 @@ class BrowserWebViewClientTest {
whenever(mockWebView.safeCopyBackForwardList()).thenReturn(TestBackForwardList())
whenever(mockWebView.settings).thenReturn(mock())
testee.onPageStarted(mockWebView, EXAMPLE_URL, null)
whenever(currentTimeProvider.getTimeInMillis()).thenReturn(5)
whenever(currentTimeProvider.elapsedRealtime()).thenReturn(5)
testee.onPageStarted(mockWebView, EXAMPLE_URL, null)
whenever(currentTimeProvider.getTimeInMillis()).thenReturn(10)
whenever(currentTimeProvider.elapsedRealtime()).thenReturn(10)
testee.onPageFinished(mockWebView, EXAMPLE_URL)

val startArgumentCaptor = argumentCaptor<Long>()
val endArgumentCaptor = argumentCaptor<Long>()
verify(pageLoadedHandler).invoke(any(), startArgumentCaptor.capture(), endArgumentCaptor.capture())
verify(pageLoadedHandler).onPageLoaded(any(), eq(null), startArgumentCaptor.capture(), endArgumentCaptor.capture())
assertEquals(0L, startArgumentCaptor.firstValue)
assertEquals(10L, endArgumentCaptor.firstValue)
}
Expand All @@ -784,13 +785,13 @@ class BrowserWebViewClientTest {
whenever(webResourceError.errorCode).thenReturn(ERROR_HOST_LOOKUP)
whenever(webResourceRequest.isForMainFrame).thenReturn(true)
testee.onReceivedError(mockWebView, webResourceRequest, webResourceError)
whenever(currentTimeProvider.getTimeInMillis()).thenReturn(5)
whenever(currentTimeProvider.elapsedRealtime()).thenReturn(5)
testee.onPageStarted(mockWebView, EXAMPLE_URL, null)
whenever(currentTimeProvider.getTimeInMillis()).thenReturn(10)
whenever(currentTimeProvider.elapsedRealtime()).thenReturn(10)
testee.onPageFinished(mockWebView, EXAMPLE_URL)
val startArgumentCaptor = argumentCaptor<Long>()
val endArgumentCaptor = argumentCaptor<Long>()
verify(pageLoadedHandler).invoke(any(), startArgumentCaptor.capture(), endArgumentCaptor.capture())
verify(pageLoadedHandler).onPageLoaded(any(), eq(null), startArgumentCaptor.capture(), endArgumentCaptor.capture())
assertEquals(5L, startArgumentCaptor.firstValue)
assertEquals(10L, endArgumentCaptor.firstValue)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.duckduckgo.autoconsent.api.Autoconsent
import com.duckduckgo.browser.api.WebViewVersionProvider
import com.duckduckgo.common.test.CoroutineTestRule
import com.duckduckgo.common.utils.device.DeviceInfo
import com.duckduckgo.history.api.NavigationHistory
import kotlinx.coroutines.test.TestScope
import org.junit.Assert
import org.junit.Before
Expand All @@ -28,6 +29,7 @@ class PageLoadedHandlerTest {
private val webViewVersionProvider: WebViewVersionProvider = mock()
private val pageLoadedPixelDao: PageLoadedPixelDao = mock()
private val autoconsent: Autoconsent = mock()
private val navigationHistory: NavigationHistory = mock()

private val testee = RealPageLoadedHandler(
deviceInfo,
Expand All @@ -40,6 +42,7 @@ class PageLoadedHandlerTest {
override val enabled: Boolean
get() = true
},
navigationHistory,
)

@Before
Expand All @@ -51,15 +54,15 @@ class PageLoadedHandlerTest {

@Test
fun whenInvokingWithValidUrlThenPixelIsAdded() {
testee.invoke(VALID_URL, 0L, 10L)
testee.onPageLoaded(VALID_URL, "title", 0L, 10L)
val argumentCaptor = argumentCaptor<PageLoadedPixelEntity>()
verify(pageLoadedPixelDao).add(argumentCaptor.capture())
Assert.assertEquals(10L, argumentCaptor.firstValue.elapsedTime)
}

@Test
fun whenInvokingWithInvalidUrlThenPixelIsAdded() {
testee.invoke(INVALID_URL, 0L, 10L)
testee.onPageLoaded(INVALID_URL, "title", 0L, 10L)
verify(pageLoadedPixelDao, never()).add(any())
}
}