Bug 1842304 - Remove feature flag for history interactor removal
parent
e2c03c8b77
commit
585e29def3
@ -1,209 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.fenix.library.history
|
||||
|
||||
import android.content.Context
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavOptions
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import mozilla.components.browser.state.action.EngineAction
|
||||
import mozilla.components.browser.state.action.HistoryMetadataAction
|
||||
import mozilla.components.browser.state.action.RecentlyClosedAction
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.browser.storage.sync.PlacesHistoryStorage
|
||||
import mozilla.components.service.glean.private.NoExtras
|
||||
import org.mozilla.fenix.GleanMetrics.Events
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.AppStore
|
||||
import org.mozilla.fenix.components.appstate.AppAction
|
||||
import org.mozilla.fenix.components.history.DefaultPagedHistoryProvider
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.navigateSafe
|
||||
import org.mozilla.fenix.library.history.HistoryFragment.DeleteConfirmationDialogFragment
|
||||
import org.mozilla.fenix.GleanMetrics.History as GleanHistory
|
||||
|
||||
@Suppress("TooManyFunctions")
|
||||
interface HistoryController {
|
||||
fun handleOpen(item: History)
|
||||
fun handleSelect(item: History)
|
||||
fun handleDeselect(item: History)
|
||||
fun handleBackPressed(): Boolean
|
||||
fun handleModeSwitched()
|
||||
fun handleSearch()
|
||||
|
||||
/**
|
||||
* Displays a [DeleteConfirmationDialogFragment].
|
||||
*/
|
||||
fun handleDeleteTimeRange()
|
||||
fun handleDeleteSome(items: Set<History>)
|
||||
|
||||
/**
|
||||
* Deletes history items inside the time frame.
|
||||
*
|
||||
* @param timeFrame Selected time frame by the user. If `null`, removes all history.
|
||||
*/
|
||||
fun handleDeleteTimeRangeConfirmed(timeFrame: RemoveTimeFrame?)
|
||||
fun handleRequestSync()
|
||||
fun handleEnterRecentlyClosed()
|
||||
}
|
||||
|
||||
@Suppress("TooManyFunctions", "LongParameterList")
|
||||
class DefaultHistoryController(
|
||||
private val store: HistoryFragmentStore,
|
||||
private val appStore: AppStore,
|
||||
private val browserStore: BrowserStore,
|
||||
private val historyStorage: PlacesHistoryStorage,
|
||||
private var historyProvider: DefaultPagedHistoryProvider,
|
||||
private val navController: NavController,
|
||||
private val scope: CoroutineScope,
|
||||
private val openToBrowser: (item: History.Regular) -> Unit,
|
||||
private val displayDeleteTimeRange: () -> Unit,
|
||||
private val onTimeFrameDeleted: () -> Unit,
|
||||
private val invalidateOptionsMenu: () -> Unit,
|
||||
private val deleteSnackbar: (
|
||||
items: Set<History>,
|
||||
undo: suspend (Set<History>) -> Unit,
|
||||
delete: (Set<History>) -> suspend (context: Context) -> Unit,
|
||||
) -> Unit,
|
||||
private val syncHistory: suspend () -> Unit,
|
||||
) : HistoryController {
|
||||
|
||||
override fun handleOpen(item: History) {
|
||||
when (item) {
|
||||
is History.Regular -> openToBrowser(item)
|
||||
is History.Group -> {
|
||||
GleanHistory.searchTermGroupTapped.record(NoExtras())
|
||||
navController.navigate(
|
||||
HistoryFragmentDirections.actionGlobalHistoryMetadataGroup(
|
||||
title = item.title,
|
||||
historyMetadataItems = item.items.toTypedArray(),
|
||||
),
|
||||
NavOptions.Builder().setPopUpTo(R.id.historyMetadataGroupFragment, true).build(),
|
||||
)
|
||||
}
|
||||
else -> { /* noop */ }
|
||||
}
|
||||
}
|
||||
|
||||
override fun handleSelect(item: History) {
|
||||
if (store.state.mode === HistoryFragmentState.Mode.Syncing) {
|
||||
return
|
||||
}
|
||||
|
||||
store.dispatch(HistoryFragmentAction.AddItemForRemoval(item))
|
||||
}
|
||||
|
||||
override fun handleDeselect(item: History) {
|
||||
store.dispatch(HistoryFragmentAction.RemoveItemForRemoval(item))
|
||||
}
|
||||
|
||||
override fun handleBackPressed(): Boolean {
|
||||
return if (store.state.mode is HistoryFragmentState.Mode.Editing) {
|
||||
store.dispatch(HistoryFragmentAction.ExitEditMode)
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
override fun handleModeSwitched() {
|
||||
invalidateOptionsMenu.invoke()
|
||||
}
|
||||
|
||||
override fun handleSearch() {
|
||||
navController.navigateSafe(
|
||||
R.id.historyFragment,
|
||||
HistoryFragmentDirections.actionGlobalSearchDialog(sessionId = null),
|
||||
)
|
||||
}
|
||||
|
||||
override fun handleDeleteTimeRange() {
|
||||
displayDeleteTimeRange.invoke()
|
||||
}
|
||||
|
||||
override fun handleDeleteSome(items: Set<History>) {
|
||||
val pendingDeletionItems = items.map { it.toPendingDeletionHistory() }.toSet()
|
||||
appStore.dispatch(AppAction.AddPendingDeletionSet(pendingDeletionItems))
|
||||
deleteSnackbar.invoke(items, ::undo, ::delete)
|
||||
}
|
||||
|
||||
override fun handleDeleteTimeRangeConfirmed(timeFrame: RemoveTimeFrame?) {
|
||||
scope.launch {
|
||||
store.dispatch(HistoryFragmentAction.EnterDeletionMode)
|
||||
if (timeFrame == null) {
|
||||
historyStorage.deleteEverything()
|
||||
} else {
|
||||
val longRange = timeFrame.toLongRange()
|
||||
historyStorage.deleteVisitsBetween(
|
||||
startTime = longRange.first,
|
||||
endTime = longRange.last,
|
||||
)
|
||||
}
|
||||
when (timeFrame) {
|
||||
RemoveTimeFrame.LastHour -> GleanHistory.removedLastHour.record(NoExtras())
|
||||
RemoveTimeFrame.TodayAndYesterday -> GleanHistory.removedTodayAndYesterday.record(NoExtras())
|
||||
null -> GleanHistory.removedAll.record(NoExtras())
|
||||
}
|
||||
// We introduced more deleting options, but are keeping these actions for all options.
|
||||
// The approach could be improved: https://github.com/mozilla-mobile/fenix/issues/26102
|
||||
browserStore.dispatch(RecentlyClosedAction.RemoveAllClosedTabAction)
|
||||
browserStore.dispatch(EngineAction.PurgeHistoryAction).join()
|
||||
|
||||
store.dispatch(HistoryFragmentAction.ExitDeletionMode)
|
||||
|
||||
launch(Dispatchers.Main) {
|
||||
onTimeFrameDeleted.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun undo(items: Set<History>) {
|
||||
val pendingDeletionItems = items.map { it.toPendingDeletionHistory() }.toSet()
|
||||
appStore.dispatch(AppAction.UndoPendingDeletionSet(pendingDeletionItems))
|
||||
}
|
||||
|
||||
private fun delete(items: Set<History>): suspend (context: Context) -> Unit {
|
||||
return { context ->
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
store.dispatch(HistoryFragmentAction.EnterDeletionMode)
|
||||
for (item in items) {
|
||||
GleanHistory.removed.record(NoExtras())
|
||||
|
||||
when (item) {
|
||||
is History.Regular -> context.components.core.historyStorage.deleteVisitsFor(item.url)
|
||||
is History.Group -> {
|
||||
// NB: If we have non-search groups, this logic needs to be updated.
|
||||
historyProvider.deleteMetadataSearchGroup(item)
|
||||
context.components.core.store.dispatch(
|
||||
HistoryMetadataAction.DisbandSearchGroupAction(searchTerm = item.title),
|
||||
)
|
||||
}
|
||||
// We won't encounter individual metadata entries outside of groups.
|
||||
is History.Metadata -> {}
|
||||
}
|
||||
}
|
||||
store.dispatch(HistoryFragmentAction.ExitDeletionMode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun handleRequestSync() {
|
||||
scope.launch {
|
||||
store.dispatch(HistoryFragmentAction.StartSync)
|
||||
syncHistory.invoke()
|
||||
store.dispatch(HistoryFragmentAction.FinishSync)
|
||||
}
|
||||
}
|
||||
|
||||
override fun handleEnterRecentlyClosed() {
|
||||
navController.navigate(
|
||||
HistoryFragmentDirections.actionGlobalRecentlyClosed(),
|
||||
NavOptions.Builder().setPopUpTo(R.id.recentlyClosedFragment, true).build(),
|
||||
)
|
||||
Events.recentlyClosedTabsOpened.record(NoExtras())
|
||||
}
|
||||
}
|
@ -1,114 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.fenix.library.history
|
||||
|
||||
import mozilla.components.service.glean.private.NoExtras
|
||||
import org.mozilla.fenix.selection.SelectionInteractor
|
||||
import org.mozilla.fenix.GleanMetrics.History as GleanHistory
|
||||
|
||||
/**
|
||||
* Interface for the HistoryInteractor. This interface is implemented by objects that want
|
||||
* to respond to user interaction on the HistoryView
|
||||
*/
|
||||
interface HistoryInteractor : SelectionInteractor<History> {
|
||||
|
||||
/**
|
||||
* Called on backpressed to exit edit mode
|
||||
*/
|
||||
fun onBackPressed(): Boolean
|
||||
|
||||
/**
|
||||
* Called when the mode is switched so we can invalidate the menu
|
||||
*/
|
||||
fun onModeSwitched()
|
||||
|
||||
/**
|
||||
* Called when search is tapped
|
||||
*/
|
||||
fun onSearch()
|
||||
|
||||
/**
|
||||
* Called when the delete menu button is tapped.
|
||||
*/
|
||||
fun onDeleteTimeRange()
|
||||
|
||||
/**
|
||||
* Called when multiple history items are deleted
|
||||
* @param items the history items to delete
|
||||
*/
|
||||
fun onDeleteSome(items: Set<History>)
|
||||
|
||||
/**
|
||||
* Called when the user has confirmed deletion of a time range.
|
||||
*
|
||||
* @param timeFrame The selected timeframe. `null` means no specific time frame has been
|
||||
* selected; should remove everything.
|
||||
*/
|
||||
fun onDeleteTimeRangeConfirmed(timeFrame: RemoveTimeFrame?)
|
||||
|
||||
/**
|
||||
* Called when the user requests a sync of the history
|
||||
*/
|
||||
fun onRequestSync()
|
||||
|
||||
/**
|
||||
* Called when the user clicks on recently closed tab button.
|
||||
*/
|
||||
fun onRecentlyClosedClicked()
|
||||
}
|
||||
|
||||
/**
|
||||
* Interactor for the history screen
|
||||
* Provides implementations for the HistoryInteractor
|
||||
*/
|
||||
@SuppressWarnings("TooManyFunctions")
|
||||
class DefaultHistoryInteractor(
|
||||
private val historyController: HistoryController,
|
||||
) : HistoryInteractor {
|
||||
override fun open(item: History) {
|
||||
historyController.handleOpen(item)
|
||||
}
|
||||
|
||||
override fun select(item: History) {
|
||||
historyController.handleSelect(item)
|
||||
}
|
||||
|
||||
override fun deselect(item: History) {
|
||||
historyController.handleDeselect(item)
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
return historyController.handleBackPressed()
|
||||
}
|
||||
|
||||
override fun onModeSwitched() {
|
||||
historyController.handleModeSwitched()
|
||||
}
|
||||
|
||||
override fun onSearch() {
|
||||
GleanHistory.searchIconTapped.record(NoExtras())
|
||||
historyController.handleSearch()
|
||||
}
|
||||
|
||||
override fun onDeleteTimeRange() {
|
||||
historyController.handleDeleteTimeRange()
|
||||
}
|
||||
|
||||
override fun onDeleteSome(items: Set<History>) {
|
||||
historyController.handleDeleteSome(items)
|
||||
}
|
||||
|
||||
override fun onDeleteTimeRangeConfirmed(timeFrame: RemoveTimeFrame?) {
|
||||
historyController.handleDeleteTimeRangeConfirmed(timeFrame)
|
||||
}
|
||||
|
||||
override fun onRequestSync() {
|
||||
historyController.handleRequestSync()
|
||||
}
|
||||
|
||||
override fun onRecentlyClosedClicked() {
|
||||
historyController.handleEnterRecentlyClosed()
|
||||
}
|
||||
}
|
@ -1,272 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.fenix.library.history
|
||||
|
||||
import androidx.navigation.NavController
|
||||
import io.mockk.coVerifyOrder
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
import mozilla.components.browser.state.action.EngineAction
|
||||
import mozilla.components.browser.state.action.RecentlyClosedAction
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.browser.storage.sync.PlacesHistoryStorage
|
||||
import mozilla.components.service.glean.testing.GleanTestRule
|
||||
import mozilla.components.support.test.robolectric.testContext
|
||||
import mozilla.components.support.test.rule.MainCoroutineRule
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertNotNull
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.AppStore
|
||||
import org.mozilla.fenix.components.history.DefaultPagedHistoryProvider
|
||||
import org.mozilla.fenix.ext.navigateSafe
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
|
||||
@RunWith(FenixRobolectricTestRunner::class)
|
||||
class HistoryControllerTest {
|
||||
private val historyItem = History.Regular(
|
||||
0,
|
||||
"title",
|
||||
"url",
|
||||
0.toLong(),
|
||||
HistoryItemTimeGroup.timeGroupForTimestamp(0),
|
||||
)
|
||||
|
||||
@get:Rule
|
||||
val gleanTestRule = GleanTestRule(testContext)
|
||||
|
||||
@get:Rule
|
||||
val coroutinesTestRule = MainCoroutineRule()
|
||||
private val scope = coroutinesTestRule.scope
|
||||
|
||||
private val store: HistoryFragmentStore = mockk(relaxed = true)
|
||||
private val appStore: AppStore = mockk(relaxed = true)
|
||||
private val browserStore: BrowserStore = mockk(relaxed = true)
|
||||
private val historyStorage: PlacesHistoryStorage = mockk(relaxed = true)
|
||||
private val state: HistoryFragmentState = mockk(relaxed = true)
|
||||
private val navController: NavController = mockk(relaxed = true)
|
||||
private val historyProvider: DefaultPagedHistoryProvider = mockk(relaxed = true)
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
every { store.state } returns state
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onPressHistoryItemInNormalMode() {
|
||||
var actualHistoryItem: History? = null
|
||||
val controller = createController(
|
||||
openInBrowser = {
|
||||
actualHistoryItem = it
|
||||
},
|
||||
)
|
||||
controller.handleOpen(historyItem)
|
||||
assertEquals(historyItem, actualHistoryItem)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onPressHistoryItemInEditMode() {
|
||||
every { state.mode } returns HistoryFragmentState.Mode.Editing(setOf())
|
||||
|
||||
createController().handleSelect(historyItem)
|
||||
|
||||
verify {
|
||||
store.dispatch(HistoryFragmentAction.AddItemForRemoval(historyItem))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onPressSelectedHistoryItemInEditMode() {
|
||||
every { state.mode } returns HistoryFragmentState.Mode.Editing(setOf(historyItem))
|
||||
|
||||
createController().handleDeselect(historyItem)
|
||||
|
||||
verify {
|
||||
store.dispatch(HistoryFragmentAction.RemoveItemForRemoval(historyItem))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onSelectHistoryItemDuringSync() {
|
||||
every { state.mode } returns HistoryFragmentState.Mode.Syncing
|
||||
|
||||
createController().handleSelect(historyItem)
|
||||
|
||||
verify(exactly = 0) {
|
||||
store.dispatch(HistoryFragmentAction.AddItemForRemoval(historyItem))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onBackPressedInNormalMode() {
|
||||
every { state.mode } returns HistoryFragmentState.Mode.Normal
|
||||
|
||||
assertFalse(createController().handleBackPressed())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onBackPressedInEditMode() {
|
||||
every { state.mode } returns HistoryFragmentState.Mode.Editing(setOf())
|
||||
|
||||
assertTrue(createController().handleBackPressed())
|
||||
verify {
|
||||
store.dispatch(HistoryFragmentAction.ExitEditMode)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onModeSwitched() {
|
||||
var invalidateOptionsMenuInvoked = false
|
||||
val controller = createController(
|
||||
invalidateOptionsMenu = {
|
||||
invalidateOptionsMenuInvoked = true
|
||||
},
|
||||
)
|
||||
|
||||
controller.handleModeSwitched()
|
||||
assertTrue(invalidateOptionsMenuInvoked)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onSearch() {
|
||||
val controller = createController()
|
||||
|
||||
controller.handleSearch()
|
||||
verify {
|
||||
navController.navigateSafe(
|
||||
R.id.historyFragment,
|
||||
HistoryFragmentDirections.actionGlobalSearchDialog(sessionId = null),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onDeleteTimeRange() {
|
||||
var displayDeleteTimeRangeInvoked = false
|
||||
val controller = createController(
|
||||
displayDeleteTimeRange = {
|
||||
displayDeleteTimeRangeInvoked = true
|
||||
},
|
||||
)
|
||||
|
||||
controller.handleDeleteTimeRange()
|
||||
assertTrue(displayDeleteTimeRangeInvoked)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WHEN user confirms history deletion GIVEN timeFrame is null THEN delete all history, log the event, purge history and remove recently closed items`() {
|
||||
val controller = createController()
|
||||
assertNull(org.mozilla.fenix.GleanMetrics.History.removedAll.testGetValue())
|
||||
|
||||
controller.handleDeleteTimeRangeConfirmed(null)
|
||||
coVerifyOrder {
|
||||
store.dispatch(HistoryFragmentAction.EnterDeletionMode)
|
||||
historyStorage.deleteEverything()
|
||||
browserStore.dispatch(RecentlyClosedAction.RemoveAllClosedTabAction)
|
||||
browserStore.dispatch(EngineAction.PurgeHistoryAction)
|
||||
store.dispatch(HistoryFragmentAction.ExitDeletionMode)
|
||||
}
|
||||
|
||||
assertNotNull(org.mozilla.fenix.GleanMetrics.History.removedAll.testGetValue())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WHEN user confirms history deletion GIVEN timeFrame is lastHour THEN delete visits between the time frame, log the event, purge history and remove recently closed items`() {
|
||||
val controller = createController()
|
||||
assertNull(org.mozilla.fenix.GleanMetrics.History.removedLastHour.testGetValue())
|
||||
|
||||
controller.handleDeleteTimeRangeConfirmed(RemoveTimeFrame.LastHour)
|
||||
coVerifyOrder {
|
||||
store.dispatch(HistoryFragmentAction.EnterDeletionMode)
|
||||
historyStorage.deleteVisitsBetween(any(), any())
|
||||
browserStore.dispatch(RecentlyClosedAction.RemoveAllClosedTabAction)
|
||||
browserStore.dispatch(EngineAction.PurgeHistoryAction)
|
||||
store.dispatch(HistoryFragmentAction.ExitDeletionMode)
|
||||
}
|
||||
|
||||
assertNotNull(org.mozilla.fenix.GleanMetrics.History.removedLastHour.testGetValue())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WHEN user confirms history deletion GIVEN timeFrame is todayAndYesterday THEN delete visits between the time frame, log the event, purge history and remove recently closed items`() {
|
||||
val controller = createController()
|
||||
assertNull(org.mozilla.fenix.GleanMetrics.History.removedTodayAndYesterday.testGetValue())
|
||||
|
||||
controller.handleDeleteTimeRangeConfirmed(RemoveTimeFrame.TodayAndYesterday)
|
||||
coVerifyOrder {
|
||||
store.dispatch(HistoryFragmentAction.EnterDeletionMode)
|
||||
historyStorage.deleteVisitsBetween(any(), any())
|
||||
browserStore.dispatch(RecentlyClosedAction.RemoveAllClosedTabAction)
|
||||
browserStore.dispatch(EngineAction.PurgeHistoryAction)
|
||||
store.dispatch(HistoryFragmentAction.ExitDeletionMode)
|
||||
}
|
||||
|
||||
assertNotNull(org.mozilla.fenix.GleanMetrics.History.removedTodayAndYesterday.testGetValue())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onDeleteSome() {
|
||||
val itemsToDelete = setOf(historyItem)
|
||||
var actualItems: Set<History>? = null
|
||||
val controller = createController(
|
||||
deleteHistoryItems = { items ->
|
||||
actualItems = items
|
||||
},
|
||||
)
|
||||
|
||||
controller.handleDeleteSome(itemsToDelete)
|
||||
assertEquals(itemsToDelete, actualItems)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onRequestSync() {
|
||||
var syncHistoryInvoked = false
|
||||
createController(
|
||||
syncHistory = {
|
||||
syncHistoryInvoked = true
|
||||
},
|
||||
).handleRequestSync()
|
||||
|
||||
coVerifyOrder {
|
||||
store.dispatch(HistoryFragmentAction.StartSync)
|
||||
store.dispatch(HistoryFragmentAction.FinishSync)
|
||||
}
|
||||
|
||||
assertTrue(syncHistoryInvoked)
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
private fun createController(
|
||||
openInBrowser: (History) -> Unit = { _ -> },
|
||||
displayDeleteTimeRange: () -> Unit = {},
|
||||
onTimeFrameDeleted: () -> Unit = {},
|
||||
invalidateOptionsMenu: () -> Unit = {},
|
||||
deleteHistoryItems: (Set<History>) -> Unit = { _ -> },
|
||||
syncHistory: suspend () -> Unit = {},
|
||||
): HistoryController {
|
||||
return DefaultHistoryController(
|
||||
store,
|
||||
appStore,
|
||||
browserStore,
|
||||
historyStorage,
|
||||
historyProvider,
|
||||
navController,
|
||||
scope,
|
||||
openInBrowser,
|
||||
displayDeleteTimeRange,
|
||||
onTimeFrameDeleted,
|
||||
invalidateOptionsMenu,
|
||||
{ items, _, _ -> deleteHistoryItems.invoke(items) },
|
||||
syncHistory,
|
||||
)
|
||||
}
|
||||
}
|
@ -1,128 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.fenix.library.history
|
||||
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verifyAll
|
||||
import mozilla.components.service.glean.testing.GleanTestRule
|
||||
import mozilla.components.support.test.robolectric.testContext
|
||||
import org.junit.Assert.assertNotNull
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
import org.mozilla.fenix.GleanMetrics.History as GleanHistory
|
||||
|
||||
@RunWith(FenixRobolectricTestRunner::class) // For GleanTestRule
|
||||
class HistoryInteractorTest {
|
||||
private val historyItem = History.Regular(0, "title", "url", 0.toLong(), HistoryItemTimeGroup.timeGroupForTimestamp(0))
|
||||
val controller: HistoryController = mockk(relaxed = true)
|
||||
val interactor = DefaultHistoryInteractor(controller)
|
||||
|
||||
@get:Rule
|
||||
val gleanTestRule = GleanTestRule(testContext)
|
||||
|
||||
@Test
|
||||
fun onOpen() {
|
||||
interactor.open(historyItem)
|
||||
|
||||
verifyAll {
|
||||
controller.handleOpen(historyItem)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onSelect() {
|
||||
interactor.select(historyItem)
|
||||
|
||||
verifyAll {
|
||||
controller.handleSelect(historyItem)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onDeselect() {
|
||||
interactor.deselect(historyItem)
|
||||
|
||||
verifyAll {
|
||||
controller.handleDeselect(historyItem)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onBackPressed() {
|
||||
every {
|
||||
controller.handleBackPressed()
|
||||
} returns true
|
||||
|
||||
val backpressHandled = interactor.onBackPressed()
|
||||
|
||||
verifyAll {
|
||||
controller.handleBackPressed()
|
||||
}
|
||||
assertTrue(backpressHandled)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onModeSwitched() {
|
||||
interactor.onModeSwitched()
|
||||
|
||||
verifyAll {
|
||||
controller.handleModeSwitched()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onSearch() {
|
||||
assertNull(GleanHistory.searchIconTapped.testGetValue())
|
||||
interactor.onSearch()
|
||||
|
||||
verifyAll {
|
||||
controller.handleSearch()
|
||||
}
|
||||
assertNotNull(GleanHistory.searchIconTapped.testGetValue())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onDeleteTimeRange() {
|
||||
interactor.onDeleteTimeRange()
|
||||
|
||||
verifyAll {
|
||||
controller.handleDeleteTimeRange()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onDeleteTimeRangeConfirmed() {
|
||||
interactor.onDeleteTimeRangeConfirmed(null)
|
||||
|
||||
verifyAll {
|
||||
controller.handleDeleteTimeRangeConfirmed(null)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onDeleteSome() {
|
||||
val items = setOf(historyItem)
|
||||
|
||||
interactor.onDeleteSome(items)
|
||||
|
||||
verifyAll {
|
||||
controller.handleDeleteSome(items)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onRequestSync() {
|
||||
interactor.onRequestSync()
|
||||
|
||||
verifyAll {
|
||||
controller.handleRequestSync()
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue