commit 8db860e6f9494a2ecb967bf7d86a05828f8ba1ff parent 17320010deeb901ffc90b291964077c73f982e53 Author: mcarare <48995920+mcarare@users.noreply.github.com> Date: Thu, 2 Oct 2025 17:19:36 +0000 Bug 1991559 - Migrate browser state tests to use BrowserStateReducer directly. r=android-reviewers,jonalmeida This patch migrates the existing browser state action tests to use the `BrowserStateReducer` directly instead of the `BrowserStore`. This refactoring simplifies the tests by removing the need for `joinBlocking()` and allows for more direct state verification. Differential Revision: https://phabricator.services.mozilla.com/D266991 Diffstat:
20 files changed, 2263 insertions(+), 1844 deletions(-)
diff --git a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/AwesomeBarActionTest.kt b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/AwesomeBarActionTest.kt @@ -4,57 +4,61 @@ package mozilla.components.browser.state.action +import mozilla.components.browser.state.reducer.BrowserStateReducer import mozilla.components.browser.state.state.AwesomeBarState import mozilla.components.browser.state.state.BrowserState -import mozilla.components.browser.state.store.BrowserStore import mozilla.components.concept.awesomebar.AwesomeBar -import mozilla.components.support.test.ext.joinBlocking import mozilla.components.support.test.mock import org.junit.Assert.assertEquals import org.junit.Assert.assertNotNull import org.junit.Assert.assertNull import org.junit.Assert.assertTrue +import org.junit.Before import org.junit.Test class AwesomeBarActionTest { + private lateinit var state: BrowserState + + @Before + fun setUp() { + state = BrowserState() + } + @Test fun `VisibilityStateUpdated - Stores updated visibility state`() { - val store = BrowserStore() - - assertTrue(store.state.awesomeBarState.visibilityState.visibleProviderGroups.isEmpty()) - assertNull(store.state.awesomeBarState.clickedSuggestion) + assertTrue(state.awesomeBarState.visibilityState.visibleProviderGroups.isEmpty()) + assertNull(state.awesomeBarState.clickedSuggestion) val provider: AwesomeBar.SuggestionProvider = mock() val providerGroup = AwesomeBar.SuggestionProviderGroup(listOf(provider)) val providerGroupSuggestions = listOf(AwesomeBar.Suggestion(provider)) - store.dispatch( + state = BrowserStateReducer.reduce( + state, AwesomeBarAction.VisibilityStateUpdated( AwesomeBar.VisibilityState( visibleProviderGroups = mapOf(providerGroup to providerGroupSuggestions), ), ), - ).joinBlocking() + ) - assertEquals(1, store.state.awesomeBarState.visibilityState.visibleProviderGroups.size) - assertEquals(providerGroupSuggestions, store.state.awesomeBarState.visibilityState.visibleProviderGroups[providerGroup]) - assertNull(store.state.awesomeBarState.clickedSuggestion) + assertEquals(1, state.awesomeBarState.visibilityState.visibleProviderGroups.size) + assertEquals(providerGroupSuggestions, state.awesomeBarState.visibilityState.visibleProviderGroups[providerGroup]) + assertNull(state.awesomeBarState.clickedSuggestion) } @Test fun `SuggestionClicked - Stores clicked suggestion`() { - val store = BrowserStore() - - assertTrue(store.state.awesomeBarState.visibilityState.visibleProviderGroups.isEmpty()) - assertNull(store.state.awesomeBarState.clickedSuggestion) + assertTrue(state.awesomeBarState.visibilityState.visibleProviderGroups.isEmpty()) + assertNull(state.awesomeBarState.clickedSuggestion) val provider: AwesomeBar.SuggestionProvider = mock() val suggestion = AwesomeBar.Suggestion(provider) - store.dispatch(AwesomeBarAction.SuggestionClicked(suggestion)).joinBlocking() + state = BrowserStateReducer.reduce(state, AwesomeBarAction.SuggestionClicked(suggestion)) - assertTrue(store.state.awesomeBarState.visibilityState.visibleProviderGroups.isEmpty()) - assertEquals(suggestion, store.state.awesomeBarState.clickedSuggestion) + assertTrue(state.awesomeBarState.visibilityState.visibleProviderGroups.isEmpty()) + assertEquals(suggestion, state.awesomeBarState.clickedSuggestion) } @Test @@ -63,24 +67,22 @@ class AwesomeBarActionTest { val suggestion = AwesomeBar.Suggestion(provider) val providerGroup = AwesomeBar.SuggestionProviderGroup(listOf(provider)) val providerGroupSuggestions = listOf(suggestion) - val store = BrowserStore( - initialState = BrowserState( - awesomeBarState = AwesomeBarState( - visibilityState = AwesomeBar.VisibilityState( - visibleProviderGroups = mapOf(providerGroup to providerGroupSuggestions), - ), - clickedSuggestion = suggestion, + state = BrowserState( + awesomeBarState = AwesomeBarState( + visibilityState = AwesomeBar.VisibilityState( + visibleProviderGroups = mapOf(providerGroup to providerGroupSuggestions), ), + clickedSuggestion = suggestion, ), ) - assertTrue(store.state.awesomeBarState.visibilityState.visibleProviderGroups.isNotEmpty()) - assertNotNull(store.state.awesomeBarState.clickedSuggestion) + assertTrue(state.awesomeBarState.visibilityState.visibleProviderGroups.isNotEmpty()) + assertNotNull(state.awesomeBarState.clickedSuggestion) - store.dispatch(AwesomeBarAction.EngagementFinished(abandoned = false)).joinBlocking() + state = BrowserStateReducer.reduce(state, AwesomeBarAction.EngagementFinished(abandoned = false)) - assertTrue(store.state.awesomeBarState.visibilityState.visibleProviderGroups.isEmpty()) - assertNull(store.state.awesomeBarState.clickedSuggestion) + assertTrue(state.awesomeBarState.visibilityState.visibleProviderGroups.isEmpty()) + assertNull(state.awesomeBarState.clickedSuggestion) } @Test @@ -89,23 +91,21 @@ class AwesomeBarActionTest { val suggestion = AwesomeBar.Suggestion(provider) val providerGroup = AwesomeBar.SuggestionProviderGroup(listOf(provider)) val providerGroupSuggestions = listOf(suggestion) - val store = BrowserStore( - initialState = BrowserState( - awesomeBarState = AwesomeBarState( - visibilityState = AwesomeBar.VisibilityState( - visibleProviderGroups = mapOf(providerGroup to providerGroupSuggestions), - ), - clickedSuggestion = suggestion, + state = BrowserState( + awesomeBarState = AwesomeBarState( + visibilityState = AwesomeBar.VisibilityState( + visibleProviderGroups = mapOf(providerGroup to providerGroupSuggestions), ), + clickedSuggestion = suggestion, ), ) - assertTrue(store.state.awesomeBarState.visibilityState.visibleProviderGroups.isNotEmpty()) - assertNotNull(store.state.awesomeBarState.clickedSuggestion) + assertTrue(state.awesomeBarState.visibilityState.visibleProviderGroups.isNotEmpty()) + assertNotNull(state.awesomeBarState.clickedSuggestion) - store.dispatch(AwesomeBarAction.EngagementFinished(abandoned = true)).joinBlocking() + state = BrowserStateReducer.reduce(state, AwesomeBarAction.EngagementFinished(abandoned = true)) - assertTrue(store.state.awesomeBarState.visibilityState.visibleProviderGroups.isEmpty()) - assertNull(store.state.awesomeBarState.clickedSuggestion) + assertTrue(state.awesomeBarState.visibilityState.visibleProviderGroups.isEmpty()) + assertNull(state.awesomeBarState.clickedSuggestion) } } diff --git a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/ContainerActionTest.kt b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/ContainerActionTest.kt @@ -4,22 +4,27 @@ package mozilla.components.browser.state.action +import mozilla.components.browser.state.reducer.BrowserStateReducer +import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.state.ContainerState -import mozilla.components.browser.state.store.BrowserStore -import mozilla.components.support.test.ext.joinBlocking import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertSame import org.junit.Assert.assertTrue +import org.junit.Before import org.junit.Test class ContainerActionTest { + private lateinit var state: BrowserState + + @Before + fun setUp() { + state = BrowserState() + } @Test fun `AddContainerAction - Adds a container to the BrowserState containers`() { - val store = BrowserStore() - - assertTrue(store.state.containers.isEmpty()) + assertTrue(state.containers.isEmpty()) val container = ContainerState( contextId = "contextId", @@ -27,21 +32,18 @@ class ContainerActionTest { color = ContainerState.Color.GREEN, icon = ContainerState.Icon.CART, ) - store.dispatch(ContainerAction.AddContainerAction(container)).joinBlocking() + val stateAfterAdd = BrowserStateReducer.reduce(state, ContainerAction.AddContainerAction(container)) - assertFalse(store.state.containers.isEmpty()) - assertEquals(container, store.state.containers.values.first()) + assertFalse(stateAfterAdd.containers.isEmpty()) + assertEquals(container, stateAfterAdd.containers.values.first()) - val state = store.state - store.dispatch(ContainerAction.AddContainerAction(container)).joinBlocking() - assertSame(state, store.state) + state = BrowserStateReducer.reduce(stateAfterAdd, ContainerAction.AddContainerAction(container)) + assertSame(stateAfterAdd, state) } @Test fun `AddContainersAction - Adds a list of containers to the BrowserState containers`() { - val store = BrowserStore() - - assertTrue(store.state.containers.isEmpty()) + assertTrue(state.containers.isEmpty()) val container1 = ContainerState( contextId = "1", @@ -61,30 +63,28 @@ class ContainerActionTest { color = ContainerState.Color.BLUE, icon = ContainerState.Icon.BRIEFCASE, ) - store.dispatch(ContainerAction.AddContainersAction(listOf(container1, container2))).joinBlocking() + state = BrowserStateReducer.reduce(state, ContainerAction.AddContainersAction(listOf(container1, container2))) - assertFalse(store.state.containers.isEmpty()) - assertEquals(container1, store.state.containers.values.first()) - assertEquals(container2, store.state.containers.values.last()) + assertFalse(state.containers.isEmpty()) + assertEquals(container1, state.containers.values.first()) + assertEquals(container2, state.containers.values.last()) // Assert that the state remains the same if the existing containers are re-added. - val state = store.state - store.dispatch(ContainerAction.AddContainersAction(listOf(container1, container2))).joinBlocking() - assertSame(state, store.state) + val stateBeforeReAdd = state + state = BrowserStateReducer.reduce(state, ContainerAction.AddContainersAction(listOf(container1, container2))) + assertEquals(stateBeforeReAdd, state) // Assert that only non-existing containers are added. - store.dispatch(ContainerAction.AddContainersAction(listOf(container1, container2, container3))).joinBlocking() - assertEquals(3, store.state.containers.size) - assertEquals(container1, store.state.containers.values.first()) - assertEquals(container2, store.state.containers.values.elementAt(1)) - assertEquals(container3, store.state.containers.values.last()) + state = BrowserStateReducer.reduce(state, ContainerAction.AddContainersAction(listOf(container1, container2, container3))) + assertEquals(3, state.containers.size) + assertEquals(container1, state.containers.values.first()) + assertEquals(container2, state.containers.values.elementAt(1)) + assertEquals(container3, state.containers.values.last()) } @Test fun `RemoveContainerAction - Removes a container from the BrowserState containers`() { - val store = BrowserStore() - - assertTrue(store.state.containers.isEmpty()) + assertTrue(state.containers.isEmpty()) val container1 = ContainerState( contextId = "1", @@ -98,16 +98,16 @@ class ContainerActionTest { color = ContainerState.Color.GREEN, icon = ContainerState.Icon.CIRCLE, ) - store.dispatch(ContainerAction.AddContainerAction(container1)).joinBlocking() - store.dispatch(ContainerAction.AddContainerAction(container2)).joinBlocking() + state = BrowserStateReducer.reduce(state, ContainerAction.AddContainerAction(container1)) + state = BrowserStateReducer.reduce(state, ContainerAction.AddContainerAction(container2)) - assertFalse(store.state.containers.isEmpty()) - assertEquals(container1, store.state.containers.values.first()) - assertEquals(container2, store.state.containers.values.last()) + assertFalse(state.containers.isEmpty()) + assertEquals(container1, state.containers.values.first()) + assertEquals(container2, state.containers.values.last()) - store.dispatch(ContainerAction.RemoveContainerAction(container1.contextId)).joinBlocking() + state = BrowserStateReducer.reduce(state, ContainerAction.RemoveContainerAction(container1.contextId)) - assertEquals(1, store.state.containers.size) - assertEquals(container2, store.state.containers.values.first()) + assertEquals(1, state.containers.size) + assertEquals(container2, state.containers.values.first()) } } diff --git a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/ContentActionTest.kt b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/ContentActionTest.kt @@ -19,6 +19,7 @@ import mozilla.components.browser.state.action.ContentAction.UpdatePermissionHig import mozilla.components.browser.state.action.ContentAction.UpdatePermissionHighlightsStateAction.NotificationChangedAction import mozilla.components.browser.state.action.ContentAction.UpdatePermissionHighlightsStateAction.PersistentStorageChangedAction import mozilla.components.browser.state.action.ContentAction.UpdatePermissionHighlightsStateAction.Reset +import mozilla.components.browser.state.reducer.BrowserStateReducer import mozilla.components.browser.state.selector.findCustomTab import mozilla.components.browser.state.state.AppIntentState import mozilla.components.browser.state.state.BrowserState @@ -31,7 +32,6 @@ import mozilla.components.browser.state.state.content.HistoryState import mozilla.components.browser.state.state.content.PermissionHighlightsState import mozilla.components.browser.state.state.createCustomTab import mozilla.components.browser.state.state.createTab -import mozilla.components.browser.state.store.BrowserStore import mozilla.components.concept.engine.HitResult import mozilla.components.concept.engine.history.HistoryItem import mozilla.components.concept.engine.manifest.WebAppManifest @@ -40,8 +40,6 @@ import mozilla.components.concept.engine.permission.Permission.ContentGeoLocatio import mozilla.components.concept.engine.permission.PermissionRequest import mozilla.components.concept.engine.prompt.PromptRequest import mozilla.components.concept.engine.window.WindowRequest -import mozilla.components.support.test.ext.joinBlocking -import mozilla.components.support.test.libstate.ext.waitUntilIdle import mozilla.components.support.test.mock import mozilla.components.support.test.whenever import org.junit.Assert.assertEquals @@ -58,19 +56,20 @@ import org.mockito.Mockito.verify @RunWith(AndroidJUnit4::class) class ContentActionTest { - private lateinit var store: BrowserStore + private lateinit var state: BrowserState + private lateinit var tabId: String private lateinit var otherTabId: String private val tab: TabSessionState - get() = store.state.tabs.find { it.id == tabId }!! + get() = state.tabs.find { it.id == tabId }!! private val otherTab: TabSessionState - get() = store.state.tabs.find { it.id == otherTabId }!! + get() = state.tabs.find { it.id == otherTabId }!! @Before fun setUp() { - val state = BrowserState( + state = BrowserState( tabs = listOf( createTab(url = "https://www.mozilla.org").also { tabId = it.id @@ -80,8 +79,6 @@ class ContentActionTest { }, ), ) - - store = BrowserStore(state) } @Test @@ -91,9 +88,7 @@ class ContentActionTest { assertNotEquals(newUrl, tab.content.url) assertNotEquals(newUrl, otherTab.content.url) - store.dispatch( - ContentAction.UpdateUrlAction(tab.id, newUrl), - ).joinBlocking() + state = BrowserStateReducer.reduce(state, ContentAction.UpdateUrlAction(tab.id, newUrl)) assertEquals(newUrl, tab.content.url) assertNotEquals(newUrl, otherTab.content.url) @@ -106,15 +101,17 @@ class ContentActionTest { assertNotEquals(icon, tab.content.icon) assertNotEquals(icon, otherTab.content.icon) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateIconAction(tab.id, tab.content.url, icon), - ).joinBlocking() + ) assertEquals(icon, tab.content.icon) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateUrlAction(tab.id, "https://www.example.org"), - ).joinBlocking() + ) assertNull(tab.content.icon) } @@ -126,15 +123,17 @@ class ContentActionTest { assertNotEquals(icon, tab.content.icon) assertNotEquals(icon, otherTab.content.icon) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateIconAction(tab.id, tab.content.url, icon), - ).joinBlocking() + ) assertEquals(icon, tab.content.icon) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateUrlAction(tab.id, "https://www.mozilla.org/firefox"), - ).joinBlocking() + ) assertEquals(icon, tab.content.icon) } @@ -142,21 +141,24 @@ class ContentActionTest { @Test fun `WHEN UpdateUrlAction is dispatched by user gesture THEN the search terms are cleared`() { val searchTerms = "Firefox" - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateSearchTermsAction(tab.id, searchTerms), - ).joinBlocking() + ) assertEquals(searchTerms, tab.content.searchTerms) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateUrlAction(tab.id, "https://www.mozilla.org", false), - ).joinBlocking() + ) assertEquals(searchTerms, tab.content.searchTerms) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateUrlAction(tab.id, "https://www.mozilla.org/firefox", true), - ).joinBlocking() + ) assertEquals("", tab.content.searchTerms) } @@ -166,27 +168,31 @@ class ContentActionTest { assertFalse(tab.content.loading) assertFalse(otherTab.content.loading) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateLoadingStateAction(tab.id, true), - ).joinBlocking() + ) assertTrue(tab.content.loading) assertFalse(otherTab.content.loading) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateLoadingStateAction(tab.id, false), - ).joinBlocking() + ) assertFalse(tab.content.loading) assertFalse(otherTab.content.loading) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateLoadingStateAction(tab.id, true), - ).joinBlocking() + ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateLoadingStateAction(otherTab.id, true), - ).joinBlocking() + ) assertTrue(tab.content.loading) assertTrue(otherTab.content.loading) @@ -197,18 +203,30 @@ class ContentActionTest { assertFalse(tab.content.refreshCanceled) assertFalse(otherTab.content.refreshCanceled) - store.dispatch(ContentAction.UpdateRefreshCanceledStateAction(tab.id, true)).joinBlocking() + state = BrowserStateReducer.reduce( + state, + ContentAction.UpdateRefreshCanceledStateAction(tab.id, true), + ) assertTrue(tab.content.refreshCanceled) assertFalse(otherTab.content.refreshCanceled) - store.dispatch(ContentAction.UpdateRefreshCanceledStateAction(tab.id, false)).joinBlocking() + state = BrowserStateReducer.reduce( + state, + ContentAction.UpdateRefreshCanceledStateAction(tab.id, false), + ) assertFalse(tab.content.refreshCanceled) assertFalse(otherTab.content.refreshCanceled) - store.dispatch(ContentAction.UpdateRefreshCanceledStateAction(tab.id, true)).joinBlocking() - store.dispatch(ContentAction.UpdateRefreshCanceledStateAction(otherTab.id, true)).joinBlocking() + state = BrowserStateReducer.reduce( + state, + ContentAction.UpdateRefreshCanceledStateAction(tab.id, true), + ) + state = BrowserStateReducer.reduce( + state, + ContentAction.UpdateRefreshCanceledStateAction(otherTab.id, true), + ) assertTrue(tab.content.refreshCanceled) assertTrue(otherTab.content.refreshCanceled) @@ -221,9 +239,10 @@ class ContentActionTest { assertNotEquals(newTitle, tab.content.title) assertNotEquals(newTitle, otherTab.content.title) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateTitleAction(tab.id, newTitle), - ).joinBlocking() + ) assertEquals(newTitle, tab.content.title) assertNotEquals(newTitle, otherTab.content.title) @@ -236,9 +255,10 @@ class ContentActionTest { assertNotEquals(newPreviewImageUrl, tab.content.previewImageUrl) assertNotEquals(newPreviewImageUrl, otherTab.content.previewImageUrl) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdatePreviewImageAction(tab.id, newPreviewImageUrl), - ).joinBlocking() + ) assertEquals(newPreviewImageUrl, tab.content.previewImageUrl) assertNotEquals(newPreviewImageUrl, otherTab.content.previewImageUrl) @@ -249,13 +269,14 @@ class ContentActionTest { assertEquals(0, tab.content.progress) assertEquals(0, otherTab.content.progress) - store.dispatch(ContentAction.UpdateProgressAction(tab.id, 75)).joinBlocking() + state = BrowserStateReducer.reduce(state, ContentAction.UpdateProgressAction(tab.id, 75)) assertEquals(75, tab.content.progress) assertEquals(0, otherTab.content.progress) - store.dispatch(ContentAction.UpdateProgressAction(otherTab.id, 25)).joinBlocking() - store.dispatch(ContentAction.UpdateProgressAction(tab.id, 85)).joinBlocking() + state = + BrowserStateReducer.reduce(state, ContentAction.UpdateProgressAction(otherTab.id, 25)) + state = BrowserStateReducer.reduce(state, ContentAction.UpdateProgressAction(tab.id, 85)) assertEquals(85, tab.content.progress) assertEquals(25, otherTab.content.progress) @@ -268,9 +289,10 @@ class ContentActionTest { assertNotEquals(searchTerms, tab.content.searchTerms) assertNotEquals(searchTerms, otherTab.content.searchTerms) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateSearchTermsAction(tab.id, searchTerms), - ).joinBlocking() + ) assertEquals(searchTerms, tab.content.searchTerms) assertNotEquals(searchTerms, otherTab.content.searchTerms) @@ -283,9 +305,10 @@ class ContentActionTest { assertNotEquals(newSecurityInfo, tab.content.securityInfo) assertNotEquals(newSecurityInfo, otherTab.content.securityInfo) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateSecurityInfoAction(tab.id, newSecurityInfo), - ).joinBlocking() + ) assertEquals(newSecurityInfo, tab.content.securityInfo) assertNotEquals(newSecurityInfo, otherTab.content.securityInfo) @@ -302,9 +325,10 @@ class ContentActionTest { assertNotEquals(icon, tab.content.icon) assertNotEquals(icon, otherTab.content.icon) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateIconAction(tab.id, tab.content.url, icon), - ).joinBlocking() + ) assertEquals(icon, tab.content.icon) assertNotEquals(icon, otherTab.content.icon) @@ -317,9 +341,10 @@ class ContentActionTest { assertNotEquals(icon, tab.content.icon) assertNotEquals(icon, otherTab.content.icon) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateIconAction(tab.id, "https://different.example.org", icon), - ).joinBlocking() + ) assertNull(tab.content.icon) } @@ -330,15 +355,17 @@ class ContentActionTest { assertNotEquals(icon, tab.content.icon) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateIconAction(tab.id, tab.content.url, icon), - ).joinBlocking() + ) assertEquals(icon, tab.content.icon) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.RemoveIconAction(tab.id), - ).joinBlocking() + ) assertNull(tab.content.icon) } @@ -348,14 +375,24 @@ class ContentActionTest { val customTab = createCustomTab("https://getpocket.com") val otherCustomTab = createCustomTab("https://www.google.com") - store.dispatch(CustomTabListAction.AddCustomTabAction(customTab)).joinBlocking() - store.dispatch(CustomTabListAction.AddCustomTabAction(otherCustomTab)).joinBlocking() + state = + BrowserStateReducer.reduce(state, CustomTabListAction.AddCustomTabAction(customTab)) + state = BrowserStateReducer.reduce( + state, + CustomTabListAction.AddCustomTabAction(otherCustomTab), + ) - store.dispatch(ContentAction.UpdateUrlAction(customTab.id, "https://www.example.org")).joinBlocking() - store.dispatch(ContentAction.UpdateTitleAction(customTab.id, "I am a custom tab")).joinBlocking() + state = BrowserStateReducer.reduce( + state, + ContentAction.UpdateUrlAction(customTab.id, "https://www.example.org"), + ) + state = BrowserStateReducer.reduce( + state, + ContentAction.UpdateTitleAction(customTab.id, "I am a custom tab"), + ) - val updatedCustomTab = store.state.findCustomTab(customTab.id)!! - val updatedOtherCustomTab = store.state.findCustomTab(otherCustomTab.id)!! + val updatedCustomTab = state.findCustomTab(customTab.id)!! + val updatedOtherCustomTab = state.findCustomTab(otherCustomTab.id)!! assertEquals("https://www.example.org", updatedCustomTab.content.url) assertNotEquals("https://www.example.org", updatedOtherCustomTab.content.url) @@ -377,9 +414,10 @@ class ContentActionTest { sessionId = tab.id, ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateDownloadAction(tab.id, download1), - ).joinBlocking() + ) assertEquals(download1.url, tab.content.download?.url) assertEquals(download1.sessionId, tab.content.download?.sessionId) @@ -389,9 +427,10 @@ class ContentActionTest { sessionId = tab.id, ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateDownloadAction(tab.id, download2), - ).joinBlocking() + ) assertEquals(download2.url, tab.content.download?.url) assertEquals(download2.sessionId, tab.content.download?.sessionId) @@ -405,15 +444,17 @@ class ContentActionTest { sessionId = tab.id, ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateDownloadAction(tab.id, download), - ).joinBlocking() + ) assertEquals(download, tab.content.download) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.ConsumeDownloadAction(tab.id, downloadId = "1337"), - ).joinBlocking() + ) assertNull(tab.content.download) } @@ -426,15 +467,17 @@ class ContentActionTest { sessionId = tab.id, ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateDownloadAction(tab.id, download), - ).joinBlocking() + ) assertEquals(download, tab.content.download) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.CancelDownloadAction(tab.id, downloadId = "1337"), - ).joinBlocking() + ) assertNull(tab.content.download) } @@ -447,15 +490,17 @@ class ContentActionTest { sessionId = tab.id, ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateDownloadAction(tab.id, download), - ).joinBlocking() + ) assertEquals(download, tab.content.download) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.ConsumeDownloadAction(tab.id, downloadId = "4223"), - ).joinBlocking() + ) assertNotNull(tab.content.download) } @@ -466,17 +511,19 @@ class ContentActionTest { val hitResult1: HitResult = HitResult.UNKNOWN("file://foo") - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateHitResultAction(tab.id, hitResult1), - ).joinBlocking() + ) assertEquals(hitResult1, tab.content.hitResult) val hitResult2: HitResult = HitResult.UNKNOWN("file://bar") - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateHitResultAction(tab.id, hitResult2), - ).joinBlocking() + ) assertEquals(hitResult2, tab.content.hitResult) } @@ -485,15 +532,17 @@ class ContentActionTest { fun `ConsumeHitResultAction removes hit result`() { val hitResult: HitResult = HitResult.UNKNOWN("file://foo") - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateHitResultAction(tab.id, hitResult), - ).joinBlocking() + ) assertEquals(hitResult, tab.content.hitResult) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.ConsumeHitResultAction(tab.id), - ).joinBlocking() + ) assertNull(tab.content.hitResult) } @@ -504,18 +553,20 @@ class ContentActionTest { val promptRequest1: PromptRequest = mock<PromptRequest.SingleChoice>() - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdatePromptRequestAction(tab.id, promptRequest1), - ).joinBlocking() + ) assertEquals(1, tab.content.promptRequests.size) assertEquals(promptRequest1, tab.content.promptRequests[0]) val promptRequest2: PromptRequest = mock<PromptRequest.MultipleChoice>() - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdatePromptRequestAction(tab.id, promptRequest2), - ).joinBlocking() + ) assertEquals(2, tab.content.promptRequests.size) assertEquals(promptRequest1, tab.content.promptRequests[0]) @@ -526,16 +577,18 @@ class ContentActionTest { fun `ConsumePromptRequestAction removes request`() { val promptRequest: PromptRequest = mock<PromptRequest.SingleChoice>() - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdatePromptRequestAction(tab.id, promptRequest), - ).joinBlocking() + ) assertEquals(1, tab.content.promptRequests.size) assertEquals(promptRequest, tab.content.promptRequests[0]) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.ConsumePromptRequestAction(tab.id, promptRequest), - ).joinBlocking() + ) assertTrue(tab.content.promptRequests.isEmpty()) } @@ -545,17 +598,19 @@ class ContentActionTest { assertTrue(tab.content.findResults.isEmpty()) val result: FindResultState = mock() - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.AddFindResultAction(tab.id, result), - ).joinBlocking() + ) assertEquals(1, tab.content.findResults.size) assertEquals(result, tab.content.findResults.last()) val result2: FindResultState = mock() - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.AddFindResultAction(tab.id, result2), - ).joinBlocking() + ) assertEquals(2, tab.content.findResults.size) assertEquals(result2, tab.content.findResults.last()) @@ -563,19 +618,22 @@ class ContentActionTest { @Test fun `ClearFindResultsAction removes all results`() { - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.AddFindResultAction(tab.id, mock()), - ).joinBlocking() + ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.AddFindResultAction(tab.id, mock()), - ).joinBlocking() + ) assertEquals(2, tab.content.findResults.size) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.ClearFindResultsAction(tab.id), - ).joinBlocking() + ) assertTrue(tab.content.findResults.isEmpty()) } @@ -586,17 +644,19 @@ class ContentActionTest { val windowRequest1: WindowRequest = mock() - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateWindowRequestAction(tab.id, windowRequest1), - ).joinBlocking() + ) assertEquals(windowRequest1, tab.content.windowRequest) val windowRequest2: WindowRequest = mock() - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateWindowRequestAction(tab.id, windowRequest2), - ).joinBlocking() + ) assertEquals(windowRequest2, tab.content.windowRequest) } @@ -605,15 +665,17 @@ class ContentActionTest { fun `ConsumeWindowRequestAction removes request`() { val windowRequest: WindowRequest = mock() - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateWindowRequestAction(tab.id, windowRequest), - ).joinBlocking() + ) assertEquals(windowRequest, tab.content.windowRequest) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.ConsumeWindowRequestAction(tab.id), - ).joinBlocking() + ) assertNull(tab.content.windowRequest) } @@ -623,12 +685,18 @@ class ContentActionTest { assertFalse(tab.content.canGoBack) assertFalse(otherTab.content.canGoBack) - store.dispatch(ContentAction.UpdateBackNavigationStateAction(tab.id, true)).joinBlocking() + state = BrowserStateReducer.reduce( + state, + ContentAction.UpdateBackNavigationStateAction(tab.id, true), + ) assertTrue(tab.content.canGoBack) assertFalse(otherTab.content.canGoBack) - store.dispatch(ContentAction.UpdateBackNavigationStateAction(tab.id, false)).joinBlocking() + state = BrowserStateReducer.reduce( + state, + ContentAction.UpdateBackNavigationStateAction(tab.id, false), + ) assertFalse(tab.content.canGoBack) assertFalse(otherTab.content.canGoBack) @@ -639,12 +707,18 @@ class ContentActionTest { assertFalse(tab.content.canGoForward) assertFalse(otherTab.content.canGoForward) - store.dispatch(ContentAction.UpdateForwardNavigationStateAction(tab.id, true)).joinBlocking() + state = BrowserStateReducer.reduce( + state, + ContentAction.UpdateForwardNavigationStateAction(tab.id, true), + ) assertTrue(tab.content.canGoForward) assertFalse(otherTab.content.canGoForward) - store.dispatch(ContentAction.UpdateForwardNavigationStateAction(tab.id, false)).joinBlocking() + state = BrowserStateReducer.reduce( + state, + ContentAction.UpdateForwardNavigationStateAction(tab.id, false), + ) assertFalse(tab.content.canGoForward) assertFalse(otherTab.content.canGoForward) @@ -660,9 +734,10 @@ class ContentActionTest { assertNotEquals(manifest, tab.content.webAppManifest) assertNotEquals(manifest, otherTab.content.webAppManifest) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateWebAppManifestAction(tab.id, manifest), - ).joinBlocking() + ) assertEquals(manifest, tab.content.webAppManifest) assertNotEquals(manifest, otherTab.content.webAppManifest) @@ -677,15 +752,17 @@ class ContentActionTest { assertNotEquals(manifest, tab.content.webAppManifest) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateWebAppManifestAction(tab.id, manifest), - ).joinBlocking() + ) assertEquals(manifest, tab.content.webAppManifest) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.RemoveWebAppManifestAction(tab.id), - ).joinBlocking() + ) assertNull(tab.content.webAppManifest) } @@ -703,9 +780,14 @@ class ContentActionTest { assertNotEquals(historyState, tab.content.history) assertNotEquals(historyState, otherTab.content.history) - store.dispatch( - ContentAction.UpdateHistoryStateAction(tab.id, historyState.items, historyState.currentIndex), - ).joinBlocking() + state = BrowserStateReducer.reduce( + state, + ContentAction.UpdateHistoryStateAction( + tab.id, + historyState.items, + historyState.currentIndex, + ), + ) assertEquals(historyState, tab.content.history) assertNotEquals(historyState, otherTab.content.history) @@ -715,9 +797,13 @@ class ContentActionTest { fun `UpdateLoadRequestAction updates load request state`() { val loadRequestUrl = "https://mozilla.org" - store.dispatch( - ContentAction.UpdateLoadRequestAction(tab.id, LoadRequestState(loadRequestUrl, true, false)), - ).joinBlocking() + state = BrowserStateReducer.reduce( + state, + ContentAction.UpdateLoadRequestAction( + tab.id, + LoadRequestState(loadRequestUrl, true, false), + ), + ) assertNotNull(tab.content.loadRequest) assertEquals(loadRequestUrl, tab.content.loadRequest!!.url) @@ -730,12 +816,13 @@ class ContentActionTest { assertFalse(tab.content.desktopMode) assertFalse(otherTab.content.desktopMode) - store.dispatch(ContentAction.UpdateTabDesktopMode(tab.id, true)).joinBlocking() + state = BrowserStateReducer.reduce(state, ContentAction.UpdateTabDesktopMode(tab.id, true)) assertTrue(tab.content.desktopMode) assertFalse(otherTab.content.desktopMode) - store.dispatch(ContentAction.UpdateTabDesktopMode(tab.id, false)).joinBlocking() + state = + BrowserStateReducer.reduce(state, ContentAction.UpdateTabDesktopMode(tab.id, false)) assertFalse(tab.content.desktopMode) assertFalse(otherTab.content.desktopMode) @@ -745,7 +832,7 @@ class ContentActionTest { fun `WHEN dispatching NotificationChangedAction THEN notificationChanged state will be updated`() { assertFalse(tab.content.permissionHighlights.notificationChanged) - store.dispatch(NotificationChangedAction(tab.id, true)).joinBlocking() + state = BrowserStateReducer.reduce(state, NotificationChangedAction(tab.id, true)) assertTrue(tab.content.permissionHighlights.notificationChanged) } @@ -754,7 +841,7 @@ class ContentActionTest { fun `WHEN dispatching CameraChangedAction THEN cameraChanged state will be updated`() { assertFalse(tab.content.permissionHighlights.cameraChanged) - store.dispatch(CameraChangedAction(tab.id, true)).joinBlocking() + state = BrowserStateReducer.reduce(state, CameraChangedAction(tab.id, true)) assertTrue(tab.content.permissionHighlights.cameraChanged) } @@ -763,7 +850,7 @@ class ContentActionTest { fun `WHEN dispatching LocationChangedAction THEN locationChanged state will be updated`() { assertFalse(tab.content.permissionHighlights.locationChanged) - store.dispatch(LocationChangedAction(tab.id, true)).joinBlocking() + state = BrowserStateReducer.reduce(state, LocationChangedAction(tab.id, true)) assertTrue(tab.content.permissionHighlights.locationChanged) } @@ -772,7 +859,7 @@ class ContentActionTest { fun `WHEN dispatching MicrophoneChangedAction THEN locationChanged state will be updated`() { assertFalse(tab.content.permissionHighlights.microphoneChanged) - store.dispatch(MicrophoneChangedAction(tab.id, true)).joinBlocking() + state = BrowserStateReducer.reduce(state, MicrophoneChangedAction(tab.id, true)) assertTrue(tab.content.permissionHighlights.microphoneChanged) } @@ -781,7 +868,7 @@ class ContentActionTest { fun `WHEN dispatching PersistentStorageChangedAction THEN persistentStorageChanged state will be updated`() { assertFalse(tab.content.permissionHighlights.persistentStorageChanged) - store.dispatch(PersistentStorageChangedAction(tab.id, true)).joinBlocking() + state = BrowserStateReducer.reduce(state, PersistentStorageChangedAction(tab.id, true)) assertTrue(tab.content.permissionHighlights.persistentStorageChanged) } @@ -790,7 +877,7 @@ class ContentActionTest { fun `WHEN dispatching MediaKeySystemAccesChangedAction THEN mediaKeySystemAccessChanged state will be updated`() { assertFalse(tab.content.permissionHighlights.mediaKeySystemAccessChanged) - store.dispatch(MediaKeySystemAccesChangedAction(tab.id, true)).joinBlocking() + state = BrowserStateReducer.reduce(state, MediaKeySystemAccesChangedAction(tab.id, true)) assertTrue(tab.content.permissionHighlights.mediaKeySystemAccessChanged) } @@ -799,7 +886,7 @@ class ContentActionTest { fun `WHEN dispatching LocalDeviceAccessChangedAction THEN localDeviceAccessChanged state will be updated`() { assertFalse(tab.content.permissionHighlights.localDeviceAccessChanged) - store.dispatch(LocalDeviceAccessChangedAction(tab.id, true)).joinBlocking() + state = BrowserStateReducer.reduce(state, LocalDeviceAccessChangedAction(tab.id, true)) assertTrue(tab.content.permissionHighlights.localDeviceAccessChanged) } @@ -808,7 +895,7 @@ class ContentActionTest { fun `WHEN dispatching LocalNetworkAccessChangedAction THEN localNetworkAccessChanged state will be updated`() { assertFalse(tab.content.permissionHighlights.localNetworkAccessChanged) - store.dispatch(LocalNetworkAccessChangedAction(tab.id, true)).joinBlocking() + state = BrowserStateReducer.reduce(state, LocalNetworkAccessChangedAction(tab.id, true)) assertTrue(tab.content.permissionHighlights.localNetworkAccessChanged) } @@ -817,7 +904,7 @@ class ContentActionTest { fun `WHEN dispatching AutoPlayAudibleChangedAction THEN autoPlayAudibleChanged state will be updated`() { assertFalse(tab.content.permissionHighlights.autoPlayAudibleChanged) - store.dispatch(AutoPlayAudibleChangedAction(tab.id, true)).joinBlocking() + state = BrowserStateReducer.reduce(state, AutoPlayAudibleChangedAction(tab.id, true)) assertTrue(tab.content.permissionHighlights.autoPlayAudibleChanged) } @@ -826,7 +913,7 @@ class ContentActionTest { fun `WHEN dispatching AutoPlayInAudibleChangedAction THEN autoPlayAudibleChanged state will be updated`() { assertFalse(tab.content.permissionHighlights.autoPlayInaudibleChanged) - store.dispatch(AutoPlayInAudibleChangedAction(tab.id, true)).joinBlocking() + state = BrowserStateReducer.reduce(state, AutoPlayInAudibleChangedAction(tab.id, true)) assertTrue(tab.content.permissionHighlights.autoPlayInaudibleChanged) } @@ -835,7 +922,7 @@ class ContentActionTest { fun `WHEN dispatching AutoPlayAudibleBlockingAction THEN autoPlayAudibleBlocking state will be updated`() { assertFalse(tab.content.permissionHighlights.autoPlayAudibleBlocking) - store.dispatch(AutoPlayAudibleBlockingAction(tab.id, true)).joinBlocking() + state = BrowserStateReducer.reduce(state, AutoPlayAudibleBlockingAction(tab.id, true)) assertTrue(tab.content.permissionHighlights.autoPlayAudibleBlocking) } @@ -844,21 +931,21 @@ class ContentActionTest { fun `WHEN dispatching AutoPlayInAudibleBlockingAction THEN autoPlayInaudibleBlocking state will be updated`() { assertFalse(tab.content.permissionHighlights.autoPlayInaudibleBlocking) - store.dispatch(AutoPlayInAudibleBlockingAction(tab.id, true)).joinBlocking() + state = BrowserStateReducer.reduce(state, AutoPlayInAudibleBlockingAction(tab.id, true)) assertTrue(tab.content.permissionHighlights.autoPlayInaudibleBlocking) } @Test fun `WHEN dispatching Reset THEN permissionHighlights state will be update to its default value`() { - store.dispatch(AutoPlayInAudibleBlockingAction(tab.id, true)).joinBlocking() + state = BrowserStateReducer.reduce(state, AutoPlayInAudibleBlockingAction(tab.id, true)) assertEquals( PermissionHighlightsState(autoPlayInaudibleBlocking = true), tab.content.permissionHighlights, ) - with(store) { dispatch(Reset(tab.id)).joinBlocking() } + state = BrowserStateReducer.reduce(state, Reset(tab.id)) assertEquals(PermissionHighlightsState(), tab.content.permissionHighlights) } @@ -869,17 +956,19 @@ class ContentActionTest { val appIntent1: AppIntentState = mock() - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateAppIntentAction(tab.id, appIntent1), - ).joinBlocking() + ) assertEquals(appIntent1, tab.content.appIntent) val appIntent2: AppIntentState = mock() - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateAppIntentAction(tab.id, appIntent2), - ).joinBlocking() + ) assertEquals(appIntent2, tab.content.appIntent) } @@ -888,15 +977,17 @@ class ContentActionTest { fun `ConsumeAppIntentAction removes request`() { val appIntent: AppIntentState = mock() - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateAppIntentAction(tab.id, appIntent), - ).joinBlocking() + ) assertEquals(appIntent, tab.content.appIntent) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.ConsumeAppIntentAction(tab.id), - ).joinBlocking() + ) assertNull(tab.content.appIntent) } @@ -905,15 +996,17 @@ class ContentActionTest { fun `CheckForFormDataAction updates hasFormData`() { assertFalse(tab.content.hasFormData) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateHasFormDataAction(tab.id, true), - ).joinBlocking() + ) assertTrue(tab.content.hasFormData) - store.dispatch( + state = BrowserStateReducer.reduce( + state, ContentAction.UpdateHasFormDataAction(tab.id, false), - ).joinBlocking() + ) assertFalse(tab.content.hasFormData) } @@ -931,9 +1024,14 @@ class ContentActionTest { whenever(uri).thenReturn(url) } - store.dispatch(ContentAction.UpdatePermissionsRequest(tab.id, request1)) - store.dispatch(ContentAction.UpdatePermissionsRequest(tab.id, request2)) - store.waitUntilIdle() + state = BrowserStateReducer.reduce( + state, + ContentAction.UpdatePermissionsRequest(tab.id, request1), + ) + state = BrowserStateReducer.reduce( + state, + ContentAction.UpdatePermissionsRequest(tab.id, request2), + ) verify(request1).merge(request2) } @@ -947,9 +1045,14 @@ class ContentActionTest { whenever(permissions).thenReturn(listOf(AppLocationCoarse(id = "permission"))) } - store.dispatch(ContentAction.UpdateAppPermissionsRequest(tab.id, request1)) - store.dispatch(ContentAction.UpdateAppPermissionsRequest(tab.id, request2)) - store.waitUntilIdle() + state = BrowserStateReducer.reduce( + state, + ContentAction.UpdateAppPermissionsRequest(tab.id, request1), + ) + state = BrowserStateReducer.reduce( + state, + ContentAction.UpdateAppPermissionsRequest(tab.id, request2), + ) verify(request1).merge(request2) } diff --git a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/CookieBannerActionTest.kt b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/CookieBannerActionTest.kt @@ -4,46 +4,43 @@ package mozilla.components.browser.state.action +import mozilla.components.browser.state.reducer.BrowserStateReducer import mozilla.components.browser.state.selector.findTab import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.state.TabSessionState import mozilla.components.browser.state.state.createTab -import mozilla.components.browser.state.store.BrowserStore import mozilla.components.concept.engine.EngineSession.CookieBannerHandlingStatus.DETECTED import mozilla.components.concept.engine.EngineSession.CookieBannerHandlingStatus.HANDLED import mozilla.components.concept.engine.EngineSession.CookieBannerHandlingStatus.NO_DETECTED -import mozilla.components.support.test.ext.joinBlocking import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Test class CookieBannerActionTest { private lateinit var tab: TabSessionState - private lateinit var store: BrowserStore + private lateinit var state: BrowserState @Before fun setUp() { tab = createTab("https://www.mozilla.org") - store = BrowserStore( - initialState = BrowserState( - tabs = listOf(tab), - ), + state = BrowserState( + tabs = listOf(tab), ) } - private fun tabState(): TabSessionState = store.state.findTab(tab.id)!! + private fun tabState(): TabSessionState = state.findTab(tab.id)!! @Test fun `WHEN an UpdateStatusAction is dispatched THEN update cookieBanner on the given session`() { assertEquals(NO_DETECTED, tabState().cookieBanner) - store.dispatch(CookieBannerAction.UpdateStatusAction(tabId = tab.id, status = HANDLED)) - .joinBlocking() + state = BrowserStateReducer.reduce(state, CookieBannerAction.UpdateStatusAction(tabId = tab.id, status = HANDLED)) assertEquals(HANDLED, tabState().cookieBanner) - store.dispatch(CookieBannerAction.UpdateStatusAction(tabId = tab.id, status = DETECTED)) - .joinBlocking() + state = BrowserStateReducer.reduce(state, CookieBannerAction.UpdateStatusAction(tabId = tab.id, status = DETECTED)) + + assertEquals(DETECTED, tabState().cookieBanner) } } diff --git a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/CustomTabListActionTest.kt b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/CustomTabListActionTest.kt @@ -4,13 +4,12 @@ package mozilla.components.browser.state.action +import mozilla.components.browser.state.reducer.BrowserStateReducer import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.state.CustomTabConfig import mozilla.components.browser.state.state.SessionState import mozilla.components.browser.state.state.createCustomTab import mozilla.components.browser.state.state.createTab -import mozilla.components.browser.state.store.BrowserStore -import mozilla.components.support.test.ext.joinBlocking import org.junit.Assert.assertEquals import org.junit.Assert.assertSame import org.junit.Test @@ -19,10 +18,10 @@ class CustomTabListActionTest { @Test fun `AddCustomTabAction - Adds provided tab`() { - val store = BrowserStore() + var state = BrowserState() - assertEquals(0, store.state.tabs.size) - assertEquals(0, store.state.customTabs.size) + assertEquals(0, state.tabs.size) + assertEquals(0, state.customTabs.size) val config = CustomTabConfig() val customTab = createCustomTab( @@ -31,13 +30,13 @@ class CustomTabListActionTest { source = SessionState.Source.Internal.CustomTab, ) - store.dispatch(CustomTabListAction.AddCustomTabAction(customTab)).joinBlocking() + state = BrowserStateReducer.reduce(state, CustomTabListAction.AddCustomTabAction(customTab)) - assertEquals(0, store.state.tabs.size) - assertEquals(1, store.state.customTabs.size) - assertEquals(SessionState.Source.Internal.CustomTab, store.state.customTabs[0].source) - assertEquals(customTab, store.state.customTabs[0]) - assertSame(config, store.state.customTabs[0].config) + assertEquals(0, state.tabs.size) + assertEquals(1, state.customTabs.size) + assertEquals(SessionState.Source.Internal.CustomTab, state.customTabs[0].source) + assertEquals(customTab, state.customTabs[0]) + assertSame(config, state.customTabs[0].config) } @Test @@ -45,15 +44,14 @@ class CustomTabListActionTest { val customTab1 = createCustomTab("https://www.mozilla.org") val customTab2 = createCustomTab("https://www.firefox.com") - val state = BrowserState(customTabs = listOf(customTab1, customTab2)) - val store = BrowserStore(state) + var state = BrowserState(customTabs = listOf(customTab1, customTab2)) - assertEquals(2, store.state.customTabs.size) + assertEquals(2, state.customTabs.size) - store.dispatch(CustomTabListAction.RemoveCustomTabAction(customTab2.id)).joinBlocking() + state = BrowserStateReducer.reduce(state, CustomTabListAction.RemoveCustomTabAction(customTab2.id)) - assertEquals(1, store.state.customTabs.size) - assertEquals(customTab1, store.state.customTabs[0]) + assertEquals(1, state.customTabs.size) + assertEquals(customTab1, state.customTabs[0]) } @Test @@ -61,16 +59,15 @@ class CustomTabListActionTest { val customTab1 = createCustomTab("https://www.mozilla.org") val customTab2 = createCustomTab("https://www.firefox.com") - val state = BrowserState(customTabs = listOf(customTab1, customTab2)) - val store = BrowserStore(state) + var state = BrowserState(customTabs = listOf(customTab1, customTab2)) - assertEquals(2, store.state.customTabs.size) + assertEquals(2, state.customTabs.size) - store.dispatch(CustomTabListAction.RemoveCustomTabAction("unknown id")).joinBlocking() + state = BrowserStateReducer.reduce(state, CustomTabListAction.RemoveCustomTabAction("unknown id")) - assertEquals(2, store.state.customTabs.size) - assertEquals(customTab1, store.state.customTabs[0]) - assertEquals(customTab2, store.state.customTabs[1]) + assertEquals(2, state.customTabs.size) + assertEquals(customTab1, state.customTabs[0]) + assertEquals(customTab2, state.customTabs[1]) } @Test @@ -79,14 +76,13 @@ class CustomTabListActionTest { val customTab2 = createCustomTab("https://www.firefox.com") val regularTab = createTab(url = "https://www.mozilla.org") - val state = BrowserState(customTabs = listOf(customTab1, customTab2), tabs = listOf(regularTab)) - val store = BrowserStore(state) + var state = BrowserState(customTabs = listOf(customTab1, customTab2), tabs = listOf(regularTab)) - assertEquals(2, store.state.customTabs.size) - assertEquals(1, store.state.tabs.size) + assertEquals(2, state.customTabs.size) + assertEquals(1, state.tabs.size) - store.dispatch(CustomTabListAction.RemoveAllCustomTabsAction).joinBlocking() - assertEquals(0, store.state.customTabs.size) - assertEquals(1, store.state.tabs.size) + state = BrowserStateReducer.reduce(state, CustomTabListAction.RemoveAllCustomTabsAction) + assertEquals(0, state.customTabs.size) + assertEquals(1, state.tabs.size) } } diff --git a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/DebugActionTest.kt b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/DebugActionTest.kt @@ -4,31 +4,34 @@ package mozilla.components.browser.state.action +import mozilla.components.browser.state.reducer.BrowserStateReducer import mozilla.components.browser.state.selector.selectedTab import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.state.createTab -import mozilla.components.browser.state.store.BrowserStore import mozilla.components.lib.state.DelicateAction -import mozilla.components.support.test.ext.joinBlocking import org.junit.Assert.assertEquals +import org.junit.Before import org.junit.Test @DelicateAction class DebugActionTest { - @Test - fun `UpdateCreatedAtAction - updates createdAt when the tab was first created`() { - val existingTab = createTab("https://www.mozilla.org") + private lateinit var state: BrowserState - val state = BrowserState( + @Before + fun setUp() { + val existingTab = createTab("https://www.mozilla.org") + state = BrowserState( tabs = listOf(existingTab), selectedTabId = existingTab.id, ) + } - val store = BrowserStore(state) + @Test + fun `UpdateCreatedAtAction - updates createdAt when the tab was first created`() { val timestamp = System.currentTimeMillis() - store.dispatch(DebugAction.UpdateCreatedAtAction(existingTab.id, timestamp)).joinBlocking() + state = BrowserStateReducer.reduce(state, DebugAction.UpdateCreatedAtAction(state.selectedTab!!.id, timestamp)) - assertEquals(timestamp, store.state.selectedTab?.createdAt) + assertEquals(timestamp, state.selectedTab?.createdAt) } } diff --git a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/DownloadActionTest.kt b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/DownloadActionTest.kt @@ -4,10 +4,9 @@ package mozilla.components.browser.state.action +import mozilla.components.browser.state.reducer.BrowserStateReducer import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.state.content.DownloadState -import mozilla.components.browser.state.store.BrowserStore -import mozilla.components.support.test.ext.joinBlocking import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertNotNull @@ -20,30 +19,34 @@ class DownloadActionTest { @Test fun `AddDownloadAction adds download`() { - val store = BrowserStore(BrowserState()) + var state = BrowserState() val download1 = DownloadState( "https://mozilla.org/download1", destinationDirectory = "", directoryPath = "", ) - store.dispatch(DownloadAction.AddDownloadAction(download1)).joinBlocking() - assertEquals(download1, store.state.downloads[download1.id]) - assertEquals(1, store.state.downloads.size) + + state = BrowserStateReducer.reduce(state, DownloadAction.AddDownloadAction(download1)) + + assertEquals(download1, state.downloads[download1.id]) + assertEquals(1, state.downloads.size) val download2 = DownloadState( "https://mozilla.org/download2", destinationDirectory = "", directoryPath = "", ) - store.dispatch(DownloadAction.AddDownloadAction(download2)).joinBlocking() - assertEquals(download2, store.state.downloads[download2.id]) - assertEquals(2, store.state.downloads.size) + + state = BrowserStateReducer.reduce(state, DownloadAction.AddDownloadAction(download2)) + + assertEquals(download2, state.downloads[download2.id]) + assertEquals(2, state.downloads.size) } @Test fun `WHEN DismissDownloadNotificationAction is dispatched THEN notificationId is set to null`() { - val store = BrowserStore(BrowserState()) + var state = BrowserState() val download = DownloadState( "https://mozilla.org/download1", @@ -51,16 +54,16 @@ class DownloadActionTest { directoryPath = "", notificationId = 100, ) - store.dispatch(DownloadAction.AddDownloadAction(download)).joinBlocking() - assertNotNull(store.state.downloads[download.id]!!.notificationId) + state = BrowserStateReducer.reduce(state, DownloadAction.AddDownloadAction(download)) + assertNotNull(state.downloads[download.id]!!.notificationId) - store.dispatch(DownloadAction.DismissDownloadNotificationAction(download.id)).joinBlocking() - assertNull(store.state.downloads[download.id]!!.notificationId) + state = BrowserStateReducer.reduce(state, DownloadAction.DismissDownloadNotificationAction(download.id)) + assertNull(state.downloads[download.id]!!.notificationId) } @Test fun `WHEN DismissDownloadNotificationAction is dispatched with an invalid downloadId THEN the state must not change`() { - val store = BrowserStore(BrowserState()) + var state = BrowserState() val download = DownloadState( "https://mozilla.org/download1", @@ -68,83 +71,83 @@ class DownloadActionTest { directoryPath = "", notificationId = 100, ) - store.dispatch(DownloadAction.AddDownloadAction(download)).joinBlocking() - assertNotNull(store.state.downloads[download.id]!!.notificationId) - assertEquals(1, store.state.downloads.size) + state = BrowserStateReducer.reduce(state, DownloadAction.AddDownloadAction(download)) + assertNotNull(state.downloads[download.id]!!.notificationId) + assertEquals(1, state.downloads.size) - store.dispatch(DownloadAction.DismissDownloadNotificationAction("-1")).joinBlocking() - assertNotNull(store.state.downloads[download.id]!!.notificationId) - assertEquals(download, store.state.downloads[download.id]) + state = BrowserStateReducer.reduce(state, DownloadAction.DismissDownloadNotificationAction("-1")) + assertNotNull(state.downloads[download.id]!!.notificationId) + assertEquals(download, state.downloads[download.id]) } @Test fun `RestoreDownloadStateAction adds download`() { - val store = BrowserStore(BrowserState()) + var state = BrowserState() val download1 = DownloadState("https://mozilla.org/download1", destinationDirectory = "", directoryPath = "") - store.dispatch(DownloadAction.RestoreDownloadStateAction(download1)).joinBlocking() - assertEquals(download1, store.state.downloads[download1.id]) - assertEquals(1, store.state.downloads.size) + state = BrowserStateReducer.reduce(state, DownloadAction.RestoreDownloadStateAction(download1)) + assertEquals(download1, state.downloads[download1.id]) + assertEquals(1, state.downloads.size) val download2 = DownloadState("https://mozilla.org/download2", destinationDirectory = "", directoryPath = "") - store.dispatch(DownloadAction.RestoreDownloadStateAction(download2)).joinBlocking() - assertEquals(download2, store.state.downloads[download2.id]) - assertEquals(2, store.state.downloads.size) + state = BrowserStateReducer.reduce(state, DownloadAction.RestoreDownloadStateAction(download2)) + assertEquals(download2, state.downloads[download2.id]) + assertEquals(2, state.downloads.size) } @Test fun `RestoreDownloadsStateAction does nothing`() { - val store = BrowserStore(BrowserState()) + var state = BrowserState() - val state = store.state - store.dispatch(DownloadAction.RestoreDownloadsStateAction).joinBlocking() - assertSame(store.state, state) + val oldState = state + state = BrowserStateReducer.reduce(state, DownloadAction.RestoreDownloadsStateAction) + assertSame(oldState, state) } @Test fun `RemoveDownloadAction removes download`() { - val store = BrowserStore(BrowserState()) + var state = BrowserState() val download = DownloadState("https://mozilla.org/download1", destinationDirectory = "", directoryPath = "") - store.dispatch(DownloadAction.AddDownloadAction(download)).joinBlocking() - assertEquals(download, store.state.downloads[download.id]) - assertFalse(store.state.downloads.isEmpty()) + state = BrowserStateReducer.reduce(state, DownloadAction.AddDownloadAction(download)) + assertEquals(download, state.downloads[download.id]) + assertFalse(state.downloads.isEmpty()) - store.dispatch(DownloadAction.RemoveDownloadAction(download.id)).joinBlocking() - assertTrue(store.state.downloads.isEmpty()) + state = BrowserStateReducer.reduce(state, DownloadAction.RemoveDownloadAction(download.id)) + assertTrue(state.downloads.isEmpty()) } @Test fun `RemoveAllDownloadsAction removes all downloads`() { - val store = BrowserStore(BrowserState()) + var state = BrowserState() val download = DownloadState("https://mozilla.org/download1", destinationDirectory = "", directoryPath = "") val download2 = DownloadState("https://mozilla.org/download2", destinationDirectory = "", directoryPath = "") - store.dispatch(DownloadAction.AddDownloadAction(download)).joinBlocking() - store.dispatch(DownloadAction.AddDownloadAction(download2)).joinBlocking() + state = BrowserStateReducer.reduce(state, DownloadAction.AddDownloadAction(download)) + state = BrowserStateReducer.reduce(state, DownloadAction.AddDownloadAction(download2)) - assertFalse(store.state.downloads.isEmpty()) - assertEquals(2, store.state.downloads.size) + assertFalse(state.downloads.isEmpty()) + assertEquals(2, state.downloads.size) - store.dispatch(DownloadAction.RemoveAllDownloadsAction).joinBlocking() - assertTrue(store.state.downloads.isEmpty()) + state = BrowserStateReducer.reduce(state, DownloadAction.RemoveAllDownloadsAction) + assertTrue(state.downloads.isEmpty()) } @Test fun `UpdateDownloadAction updates the provided download`() { - val store = BrowserStore(BrowserState()) + var state = BrowserState() val download = DownloadState("https://mozilla.org/download1", destinationDirectory = "", directoryPath = "") val download2 = DownloadState("https://mozilla.org/download2", destinationDirectory = "", directoryPath = "") - store.dispatch(DownloadAction.AddDownloadAction(download)).joinBlocking() - store.dispatch(DownloadAction.AddDownloadAction(download2)).joinBlocking() + state = BrowserStateReducer.reduce(state, DownloadAction.AddDownloadAction(download)) + state = BrowserStateReducer.reduce(state, DownloadAction.AddDownloadAction(download2)) val updatedDownload = download.copy(fileName = "filename.txt") - store.dispatch(DownloadAction.UpdateDownloadAction(updatedDownload)).joinBlocking() + state = BrowserStateReducer.reduce(state, DownloadAction.UpdateDownloadAction(updatedDownload)) - assertFalse(store.state.downloads.isEmpty()) - assertEquals(2, store.state.downloads.size) - assertEquals(updatedDownload, store.state.downloads[updatedDownload.id]) + assertFalse(state.downloads.isEmpty()) + assertEquals(2, state.downloads.size) + assertEquals(updatedDownload, state.downloads[updatedDownload.id]) } } diff --git a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/EngineActionTest.kt b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/EngineActionTest.kt @@ -4,6 +4,7 @@ package mozilla.components.browser.state.action +import mozilla.components.browser.state.reducer.BrowserStateReducer import mozilla.components.browser.state.selector.findCustomTab import mozilla.components.browser.state.selector.findTab import mozilla.components.browser.state.state.BrowserState @@ -11,10 +12,8 @@ import mozilla.components.browser.state.state.EngineState import mozilla.components.browser.state.state.TabSessionState import mozilla.components.browser.state.state.createCustomTab import mozilla.components.browser.state.state.createTab -import mozilla.components.browser.state.store.BrowserStore import mozilla.components.concept.engine.EngineSession import mozilla.components.concept.engine.EngineSessionState -import mozilla.components.support.test.ext.joinBlocking import mozilla.components.support.test.mock import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse @@ -27,27 +26,25 @@ import org.junit.Test class EngineActionTest { private lateinit var tab: TabSessionState - private lateinit var store: BrowserStore + private lateinit var state: BrowserState @Before fun setUp() { tab = createTab("https://www.mozilla.org") - store = BrowserStore( - initialState = BrowserState( - tabs = listOf(tab), - ), + state = BrowserState( + tabs = listOf(tab), ) } - private fun engineState() = store.state.findTab(tab.id)!!.engineState + private fun engineState() = state.findTab(tab.id)!!.engineState @Test fun `LinkEngineSessionAction - Attaches engine session`() { assertNull(engineState().engineSession) val engineSession: EngineSession = mock() - store.dispatch(EngineAction.LinkEngineSessionAction(tab.id, engineSession, timestamp = 1234)).joinBlocking() + state = BrowserStateReducer.reduce(state, EngineAction.LinkEngineSessionAction(tab.id, engineSession, timestamp = 1234)) assertNotNull(engineState().engineSession) assertEquals(engineSession, engineState().engineSession) @@ -56,14 +53,14 @@ class EngineActionTest { @Test fun `UnlinkEngineSessionAction - Detaches engine session`() { - store.dispatch(EngineAction.LinkEngineSessionAction(tab.id, mock())).joinBlocking() - store.dispatch(EngineAction.UpdateEngineSessionStateAction(tab.id, mock())).joinBlocking() - store.dispatch(EngineAction.UpdateEngineSessionObserverAction(tab.id, mock())).joinBlocking() + state = BrowserStateReducer.reduce(state, EngineAction.LinkEngineSessionAction(tab.id, mock())) + state = BrowserStateReducer.reduce(state, EngineAction.UpdateEngineSessionStateAction(tab.id, mock())) + state = BrowserStateReducer.reduce(state, EngineAction.UpdateEngineSessionObserverAction(tab.id, mock())) assertNotNull(engineState().engineSession) assertNotNull(engineState().engineSessionState) assertNotNull(engineState().engineObserver) - store.dispatch(EngineAction.UnlinkEngineSessionAction(tab.id)).joinBlocking() + state = BrowserStateReducer.reduce(state, EngineAction.UnlinkEngineSessionAction(tab.id)) assertNull(engineState().engineSession) assertNotNull(engineState().engineSessionState) assertNull(engineState().engineObserver) @@ -74,7 +71,7 @@ class EngineActionTest { assertNull(engineState().engineSessionState) val engineSessionState: EngineSessionState = mock() - store.dispatch(EngineAction.UpdateEngineSessionStateAction(tab.id, engineSessionState)).joinBlocking() + state = BrowserStateReducer.reduce(state, EngineAction.UpdateEngineSessionStateAction(tab.id, engineSessionState)) assertNotNull(engineState().engineSessionState) assertEquals(engineSessionState, engineState().engineSessionState) } @@ -84,7 +81,7 @@ class EngineActionTest { assertNull(engineState().engineObserver) val engineObserver: EngineSession.Observer = mock() - store.dispatch(EngineAction.UpdateEngineSessionObserverAction(tab.id, engineObserver)).joinBlocking() + state = BrowserStateReducer.reduce(state, EngineAction.UpdateEngineSessionObserverAction(tab.id, engineObserver)) assertNotNull(engineState().engineObserver) assertEquals(engineObserver, engineState().engineObserver) } @@ -107,34 +104,32 @@ class EngineActionTest { engineState = EngineState(engineSession = mock(), engineSessionState = mock()), ) - val store = BrowserStore( - BrowserState( - tabs = listOf(tab1, tab2), - customTabs = listOf(customTab1, customTab2), - ), + var state = BrowserState( + tabs = listOf(tab1, tab2), + customTabs = listOf(customTab1, customTab2), ) - store.dispatch(EngineAction.PurgeHistoryAction).joinBlocking() + state = BrowserStateReducer.reduce(state, EngineAction.PurgeHistoryAction) - assertNull(store.state.findTab(tab1.id)!!.engineState.engineSessionState) - assertNotNull(store.state.findTab(tab2.id)!!.engineState.engineSessionState) + assertNull(state.findTab(tab1.id)!!.engineState.engineSessionState) + assertNotNull(state.findTab(tab2.id)!!.engineState.engineSessionState) - assertNull(store.state.findCustomTab(customTab1.id)!!.engineState.engineSessionState) - assertNotNull(store.state.findCustomTab(customTab2.id)!!.engineState.engineSessionState) + assertNull(state.findCustomTab(customTab1.id)!!.engineState.engineSessionState) + assertNotNull(state.findCustomTab(customTab2.id)!!.engineState.engineSessionState) } @Test fun `UpdateEngineSessionInitializingAction - Updates initializing flag`() { assertFalse(engineState().initializing) - store.dispatch(EngineAction.UpdateEngineSessionInitializingAction(tab.id, true)).joinBlocking() + state = BrowserStateReducer.reduce(state, EngineAction.UpdateEngineSessionInitializingAction(tab.id, true)) assertTrue(engineState().initializing) } @Test fun `OptimizedLoadUrlTriggeredAction - State is not changed`() { - val state = store.state - store.dispatch(EngineAction.OptimizedLoadUrlTriggeredAction(tab.id, "https://mozilla.org")).joinBlocking() - assertSame(store.state, state) + val oldState = state + state = BrowserStateReducer.reduce(state, EngineAction.OptimizedLoadUrlTriggeredAction(tab.id, "https://mozilla.org")) + assertSame(state, oldState) } } diff --git a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/HistoryMetadataActionTest.kt b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/HistoryMetadataActionTest.kt @@ -4,12 +4,11 @@ package mozilla.components.browser.state.action +import mozilla.components.browser.state.reducer.BrowserStateReducer import mozilla.components.browser.state.selector.findTab import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.state.createTab -import mozilla.components.browser.state.store.BrowserStore import mozilla.components.concept.storage.HistoryMetadataKey -import mozilla.components.support.test.ext.joinBlocking import org.junit.Assert.assertEquals import org.junit.Assert.assertNull import org.junit.Test @@ -19,23 +18,23 @@ class HistoryMetadataActionTest { @Test fun `SetHistoryMetadataKeyAction - Associates tab with history metadata`() { val tab = createTab("https://www.mozilla.org") - val store = BrowserStore(BrowserState(tabs = listOf(tab))) - assertNull(store.state.findTab(tab.id)?.historyMetadata) + var state = BrowserState(tabs = listOf(tab)) + assertNull(state.findTab(tab.id)?.historyMetadata) val historyMetadata = HistoryMetadataKey( url = tab.content.url, referrerUrl = "https://firefox.com", ) - store.dispatch(HistoryMetadataAction.SetHistoryMetadataKeyAction(tab.id, historyMetadata)).joinBlocking() - assertEquals(historyMetadata, store.state.findTab(tab.id)?.historyMetadata) + state = BrowserStateReducer.reduce(state, HistoryMetadataAction.SetHistoryMetadataKeyAction(tab.id, historyMetadata)) + assertEquals(historyMetadata, state.findTab(tab.id)?.historyMetadata) } @Test fun `DisbandSearchGroupAction - clears specific search terms from any existing tab history metadata`() { val tab1 = createTab("https://www.mozilla.org") val tab2 = createTab("https://www.mozilla.org/downloads") - val store = BrowserStore(BrowserState(tabs = listOf(tab1, tab2))) + var state = BrowserState(tabs = listOf(tab1, tab2)) val historyMetadata1 = HistoryMetadataKey( url = tab1.content.url, referrerUrl = "https://firefox.com", @@ -47,21 +46,21 @@ class HistoryMetadataActionTest { ) // Okay to do this without any metadata associated with tabs. - store.dispatch(HistoryMetadataAction.DisbandSearchGroupAction("Download firefox")).joinBlocking() + state = BrowserStateReducer.reduce(state, HistoryMetadataAction.DisbandSearchGroupAction("Download firefox")) // Okay to do this with an empty search term string. - store.dispatch(HistoryMetadataAction.DisbandSearchGroupAction("")).joinBlocking() + state = BrowserStateReducer.reduce(state, HistoryMetadataAction.DisbandSearchGroupAction("")) - store.dispatch(HistoryMetadataAction.SetHistoryMetadataKeyAction(tab1.id, historyMetadata1)).joinBlocking() - store.dispatch(HistoryMetadataAction.SetHistoryMetadataKeyAction(tab2.id, historyMetadata2)).joinBlocking() + state = BrowserStateReducer.reduce(state, HistoryMetadataAction.SetHistoryMetadataKeyAction(tab1.id, historyMetadata1)) + state = BrowserStateReducer.reduce(state, HistoryMetadataAction.SetHistoryMetadataKeyAction(tab2.id, historyMetadata2)) // Search term matching is case-insensitive. - store.dispatch(HistoryMetadataAction.DisbandSearchGroupAction("Download firefox")).joinBlocking() + state = BrowserStateReducer.reduce(state, HistoryMetadataAction.DisbandSearchGroupAction("Download firefox")) // tab1 is unchanged. - assertEquals(historyMetadata1, store.state.findTab(tab1.id)?.historyMetadata) + assertEquals(historyMetadata1, state.findTab(tab1.id)?.historyMetadata) // tab2 has its search term and referrer cleared. - assertEquals(HistoryMetadataKey(url = tab2.content.url), store.state.findTab(tab2.id)?.historyMetadata) + assertEquals(HistoryMetadataKey(url = tab2.content.url), state.findTab(tab2.id)?.historyMetadata) } } diff --git a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/LastAccessActionTest.kt b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/LastAccessActionTest.kt @@ -4,29 +4,32 @@ package mozilla.components.browser.state.action +import mozilla.components.browser.state.reducer.BrowserStateReducer import mozilla.components.browser.state.selector.selectedTab import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.state.createTab -import mozilla.components.browser.state.store.BrowserStore -import mozilla.components.support.test.ext.joinBlocking import org.junit.Assert.assertEquals +import org.junit.Before import org.junit.Test class LastAccessActionTest { - @Test - fun `UpdateLastAccessAction - updates the timestamp when the tab was last accessed`() { - val existingTab = createTab("https://www.mozilla.org") + private lateinit var state: BrowserState - val state = BrowserState( + @Before + fun setUp() { + val existingTab = createTab("https://www.mozilla.org") + state = BrowserState( tabs = listOf(existingTab), selectedTabId = existingTab.id, ) + } - val store = BrowserStore(state) + @Test + fun `UpdateLastAccessAction - updates the timestamp when the tab was last accessed`() { val timestamp = System.currentTimeMillis() - store.dispatch(LastAccessAction.UpdateLastAccessAction(existingTab.id, timestamp)).joinBlocking() + state = BrowserStateReducer.reduce(state, LastAccessAction.UpdateLastAccessAction(state.selectedTab!!.id, timestamp)) - assertEquals(timestamp, store.state.selectedTab?.lastAccess) + assertEquals(timestamp, state.selectedTab?.lastAccess) } } diff --git a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/LocaleActionTest.kt b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/LocaleActionTest.kt @@ -4,9 +4,8 @@ package mozilla.components.browser.state.action +import mozilla.components.browser.state.reducer.BrowserStateReducer import mozilla.components.browser.state.state.BrowserState -import mozilla.components.browser.state.store.BrowserStore -import mozilla.components.support.test.ext.joinBlocking import org.junit.Assert.assertEquals import org.junit.Assert.assertSame import org.junit.Test @@ -15,18 +14,18 @@ import java.util.Locale class LocaleActionTest { @Test fun `WHEN a new locale is selected THEN it is updated in the store`() { - val store = BrowserStore(BrowserState()) + var state = BrowserState() val locale1 = Locale.forLanguageTag("es") - store.dispatch(LocaleAction.UpdateLocaleAction(locale1)).joinBlocking() - assertEquals(locale1, store.state.locale) + state = BrowserStateReducer.reduce(state, LocaleAction.UpdateLocaleAction(locale1)) + assertEquals(locale1, state.locale) } @Test fun `WHEN the state is restored from disk THEN the store receives the state`() { - val store = BrowserStore(BrowserState()) + var state = BrowserState() - val state = store.state - store.dispatch(LocaleAction.RestoreLocaleStateAction).joinBlocking() - assertSame(state, store.state) + val oldState = state + state = BrowserStateReducer.reduce(state, LocaleAction.RestoreLocaleStateAction) + assertSame(oldState, state) } } diff --git a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/MediaSessionActionTest.kt b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/MediaSessionActionTest.kt @@ -4,13 +4,12 @@ package mozilla.components.browser.state.action +import mozilla.components.browser.state.reducer.BrowserStateReducer import mozilla.components.browser.state.selector.findTab import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.state.MediaSessionState import mozilla.components.browser.state.state.createTab -import mozilla.components.browser.state.store.BrowserStore import mozilla.components.concept.engine.mediasession.MediaSession -import mozilla.components.support.test.ext.joinBlocking import mozilla.components.support.test.mock import org.junit.Assert.assertEquals import org.junit.Assert.assertNotNull @@ -20,85 +19,84 @@ import org.junit.Test class MediaSessionActionTest { @Test fun `ActivatedMediaSessionAction updates media session state`() { - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab("https://www.mozilla.org", id = "test-tab"), - ), + var state = BrowserState( + tabs = listOf( + createTab("https://www.mozilla.org", id = "test-tab"), ), ) val mediaSessionController: MediaSession.Controller = mock() - store.dispatch( + state = BrowserStateReducer.reduce( + state, MediaSessionAction.ActivatedMediaSessionAction( "test-tab", mediaSessionController, ), - ).joinBlocking() + ) - val mediaSessionState: MediaSessionState? = store.state.findTab("test-tab")?.mediaSessionState + val mediaSessionState: MediaSessionState? = state.findTab("test-tab")?.mediaSessionState assertNotNull(mediaSessionState) assertEquals(mediaSessionController, mediaSessionState?.controller) } @Test fun `DeactivatedMediaSessionAction updates media session state`() { - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab("https://www.mozilla.org", id = "test-tab"), - ), + var state = BrowserState( + tabs = listOf( + createTab("https://www.mozilla.org", id = "test-tab"), ), ) val mediaSessionController: MediaSession.Controller = mock() - store.dispatch( + state = BrowserStateReducer.reduce( + state, MediaSessionAction.ActivatedMediaSessionAction( "test-tab", mediaSessionController, ), - ).joinBlocking() + ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, MediaSessionAction.DeactivatedMediaSessionAction( "test-tab", ), - ).joinBlocking() + ) - val mediaSessionState: MediaSessionState? = store.state.findTab("test-tab")?.mediaSessionState + val mediaSessionState: MediaSessionState? = state.findTab("test-tab")?.mediaSessionState assertNull(mediaSessionState) } @Test fun `UpdateMediaMetadataAction updates media session state`() { - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab("https://www.mozilla.org", id = "test-tab"), - ), + var state = BrowserState( + tabs = listOf( + createTab("https://www.mozilla.org", id = "test-tab"), ), ) val mediaSessionController: MediaSession.Controller = mock() val metadata: MediaSession.Metadata = mock() - store.dispatch( + state = BrowserStateReducer.reduce( + state, MediaSessionAction.ActivatedMediaSessionAction( "test-tab", mediaSessionController, ), - ).joinBlocking() + ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, MediaSessionAction.UpdateMediaMetadataAction( "test-tab", metadata, ), - ).joinBlocking() + ) - val mediaSessionState: MediaSessionState? = store.state.findTab("test-tab")?.mediaSessionState + val mediaSessionState: MediaSessionState? = state.findTab("test-tab")?.mediaSessionState assertNotNull(mediaSessionState) assertEquals(mediaSessionController, mediaSessionState?.controller) assertEquals(metadata, mediaSessionState?.metadata) @@ -106,32 +104,32 @@ class MediaSessionActionTest { @Test fun `UpdateMediaPlaybackStateAction updates media session state`() { - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab("https://www.mozilla.org", id = "test-tab"), - ), + var state = BrowserState( + tabs = listOf( + createTab("https://www.mozilla.org", id = "test-tab"), ), ) val mediaSessionController: MediaSession.Controller = mock() val playbackState: MediaSession.PlaybackState = mock() - store.dispatch( + state = BrowserStateReducer.reduce( + state, MediaSessionAction.ActivatedMediaSessionAction( "test-tab", mediaSessionController, ), - ).joinBlocking() + ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, MediaSessionAction.UpdateMediaPlaybackStateAction( "test-tab", playbackState, ), - ).joinBlocking() + ) - val mediaSessionState: MediaSessionState? = store.state.findTab("test-tab")?.mediaSessionState + val mediaSessionState: MediaSessionState? = state.findTab("test-tab")?.mediaSessionState assertNotNull(mediaSessionState) assertEquals(mediaSessionController, mediaSessionState?.controller) assertEquals(playbackState, mediaSessionState?.playbackState) @@ -139,32 +137,32 @@ class MediaSessionActionTest { @Test fun `UpdateMediaFeatureAction updates media session state`() { - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab("https://www.mozilla.org", id = "test-tab"), - ), + var state = BrowserState( + tabs = listOf( + createTab("https://www.mozilla.org", id = "test-tab"), ), ) val mediaSessionController: MediaSession.Controller = mock() val features: MediaSession.Feature = mock() - store.dispatch( + state = BrowserStateReducer.reduce( + state, MediaSessionAction.ActivatedMediaSessionAction( "test-tab", mediaSessionController, ), - ).joinBlocking() + ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, MediaSessionAction.UpdateMediaFeatureAction( "test-tab", features, ), - ).joinBlocking() + ) - val mediaSessionState: MediaSessionState? = store.state.findTab("test-tab")?.mediaSessionState + val mediaSessionState: MediaSessionState? = state.findTab("test-tab")?.mediaSessionState assertNotNull(mediaSessionState) assertEquals(mediaSessionController, mediaSessionState?.controller) assertEquals(features, mediaSessionState?.features) @@ -172,32 +170,32 @@ class MediaSessionActionTest { @Test fun `UpdateMediaPositionStateAction updates media session state`() { - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab("https://www.mozilla.org", id = "test-tab"), - ), + var state = BrowserState( + tabs = listOf( + createTab("https://www.mozilla.org", id = "test-tab"), ), ) val mediaSessionController: MediaSession.Controller = mock() val positionState: MediaSession.PositionState = mock() - store.dispatch( + state = BrowserStateReducer.reduce( + state, MediaSessionAction.ActivatedMediaSessionAction( "test-tab", mediaSessionController, ), - ).joinBlocking() + ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, MediaSessionAction.UpdateMediaPositionStateAction( "test-tab", positionState, ), - ).joinBlocking() + ) - val mediaSessionState: MediaSessionState? = store.state.findTab("test-tab")?.mediaSessionState + val mediaSessionState: MediaSessionState? = state.findTab("test-tab")?.mediaSessionState assertNotNull(mediaSessionState) assertEquals(mediaSessionController, mediaSessionState?.controller) assertEquals(positionState, mediaSessionState?.positionState) @@ -205,31 +203,31 @@ class MediaSessionActionTest { @Test fun `UpdateMediaMutedAction updates media session state`() { - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab("https://www.mozilla.org", id = "test-tab"), - ), + var state = BrowserState( + tabs = listOf( + createTab("https://www.mozilla.org", id = "test-tab"), ), ) val mediaSessionController: MediaSession.Controller = mock() - store.dispatch( + state = BrowserStateReducer.reduce( + state, MediaSessionAction.ActivatedMediaSessionAction( "test-tab", mediaSessionController, ), - ).joinBlocking() + ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, MediaSessionAction.UpdateMediaMutedAction( "test-tab", true, ), - ).joinBlocking() + ) - val mediaSessionState: MediaSessionState? = store.state.findTab("test-tab")?.mediaSessionState + val mediaSessionState: MediaSessionState? = state.findTab("test-tab")?.mediaSessionState assertNotNull(mediaSessionState) assertEquals(mediaSessionController, mediaSessionState?.controller) assertEquals(true, mediaSessionState?.muted) @@ -237,33 +235,33 @@ class MediaSessionActionTest { @Test fun `UpdateMediaFullscreenAction updates media session state`() { - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab("https://www.mozilla.org", id = "test-tab"), - ), + var state = BrowserState( + tabs = listOf( + createTab("https://www.mozilla.org", id = "test-tab"), ), ) val mediaSessionController: MediaSession.Controller = mock() val elementMetadata: MediaSession.ElementMetadata = mock() - store.dispatch( + state = BrowserStateReducer.reduce( + state, MediaSessionAction.ActivatedMediaSessionAction( "test-tab", mediaSessionController, ), - ).joinBlocking() + ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, MediaSessionAction.UpdateMediaFullscreenAction( "test-tab", true, elementMetadata, ), - ).joinBlocking() + ) - val mediaSessionState: MediaSessionState? = store.state.findTab("test-tab")?.mediaSessionState + val mediaSessionState: MediaSessionState? = state.findTab("test-tab")?.mediaSessionState assertNotNull(mediaSessionState) assertEquals(mediaSessionController, mediaSessionState?.controller) assertEquals(true, mediaSessionState?.fullscreen) @@ -272,33 +270,33 @@ class MediaSessionActionTest { @Test fun `updates are ignore if media session is not activated`() { - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab("https://www.mozilla.org", id = "test-tab"), - ), + var state = BrowserState( + tabs = listOf( + createTab("https://www.mozilla.org", id = "test-tab"), ), ) val elementMetadata: MediaSession.ElementMetadata = mock() - store.dispatch( + state = BrowserStateReducer.reduce( + state, MediaSessionAction.UpdateMediaFullscreenAction( "test-tab", true, elementMetadata, ), - ).joinBlocking() + ) - val mediaSessionState: MediaSessionState? = store.state.findTab("test-tab")?.mediaSessionState + val mediaSessionState: MediaSessionState? = state.findTab("test-tab")?.mediaSessionState assertNull(mediaSessionState) - store.dispatch( + state = BrowserStateReducer.reduce( + state, MediaSessionAction.UpdateMediaMutedAction( "test-tab", true, ), - ).joinBlocking() + ) assertNull(mediaSessionState) } } diff --git a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/ReaderActionTest.kt b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/ReaderActionTest.kt @@ -4,12 +4,11 @@ package mozilla.components.browser.state.action +import mozilla.components.browser.state.reducer.BrowserStateReducer import mozilla.components.browser.state.selector.findTab import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.state.TabSessionState import mozilla.components.browser.state.state.createTab -import mozilla.components.browser.state.store.BrowserStore -import mozilla.components.support.test.ext.joinBlocking import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertNull @@ -19,33 +18,29 @@ import org.junit.Test class ReaderActionTest { private lateinit var tab: TabSessionState - private lateinit var store: BrowserStore + private lateinit var state: BrowserState @Before fun setUp() { tab = createTab("https://www.mozilla.org") - store = BrowserStore( - initialState = BrowserState( - tabs = listOf(tab), - ), + state = BrowserState( + tabs = listOf(tab), ) } - private fun tabState(): TabSessionState = store.state.findTab(tab.id)!! + private fun tabState(): TabSessionState = state.findTab(tab.id)!! private fun readerState() = tabState().readerState @Test fun `UpdateReaderableAction - Updates readerable flag of ReaderState`() { assertFalse(readerState().readerable) - store.dispatch(ReaderAction.UpdateReaderableAction(tabId = tab.id, readerable = true)) - .joinBlocking() + state = BrowserStateReducer.reduce(state, ReaderAction.UpdateReaderableAction(tabId = tab.id, readerable = true)) assertTrue(readerState().readerable) - store.dispatch(ReaderAction.UpdateReaderableAction(tabId = tab.id, readerable = false)) - .joinBlocking() + state = BrowserStateReducer.reduce(state, ReaderAction.UpdateReaderableAction(tabId = tab.id, readerable = false)) assertFalse(readerState().readerable) } @@ -54,13 +49,11 @@ class ReaderActionTest { fun `UpdateReaderActiveAction - Updates active flag of ReaderState`() { assertFalse(readerState().active) - store.dispatch(ReaderAction.UpdateReaderActiveAction(tabId = tab.id, active = true)) - .joinBlocking() + state = BrowserStateReducer.reduce(state, ReaderAction.UpdateReaderActiveAction(tabId = tab.id, active = true)) assertTrue(readerState().active) - store.dispatch(ReaderAction.UpdateReaderActiveAction(tabId = tab.id, active = false)) - .joinBlocking() + state = BrowserStateReducer.reduce(state, ReaderAction.UpdateReaderActiveAction(tabId = tab.id, active = false)) assertFalse(readerState().active) } @@ -69,13 +62,11 @@ class ReaderActionTest { fun `UpdateReaderableCheckRequiredAction - Updates check required flag of ReaderState`() { assertFalse(readerState().active) - store.dispatch(ReaderAction.UpdateReaderableCheckRequiredAction(tabId = tab.id, checkRequired = true)) - .joinBlocking() + state = BrowserStateReducer.reduce(state, ReaderAction.UpdateReaderableCheckRequiredAction(tabId = tab.id, checkRequired = true)) assertTrue(readerState().checkRequired) - store.dispatch(ReaderAction.UpdateReaderableCheckRequiredAction(tabId = tab.id, checkRequired = false)) - .joinBlocking() + state = BrowserStateReducer.reduce(state, ReaderAction.UpdateReaderableCheckRequiredAction(tabId = tab.id, checkRequired = false)) assertFalse(readerState().checkRequired) } @@ -84,13 +75,11 @@ class ReaderActionTest { fun `UpdateReaderConnectRequiredAction - Updates connect required flag of ReaderState`() { assertFalse(readerState().active) - store.dispatch(ReaderAction.UpdateReaderConnectRequiredAction(tabId = tab.id, connectRequired = true)) - .joinBlocking() + state = BrowserStateReducer.reduce(state, ReaderAction.UpdateReaderConnectRequiredAction(tabId = tab.id, connectRequired = true)) assertTrue(readerState().connectRequired) - store.dispatch(ReaderAction.UpdateReaderConnectRequiredAction(tabId = tab.id, connectRequired = false)) - .joinBlocking() + state = BrowserStateReducer.reduce(state, ReaderAction.UpdateReaderConnectRequiredAction(tabId = tab.id, connectRequired = false)) assertFalse(readerState().connectRequired) } @@ -99,8 +88,7 @@ class ReaderActionTest { fun `UpdateReaderBaseUrlAction - Updates base url of ReaderState`() { assertNull(readerState().baseUrl) - store.dispatch(ReaderAction.UpdateReaderBaseUrlAction(tabId = tab.id, baseUrl = "moz-extension://test")) - .joinBlocking() + state = BrowserStateReducer.reduce(state, ReaderAction.UpdateReaderBaseUrlAction(tabId = tab.id, baseUrl = "moz-extension://test")) assertEquals("moz-extension://test", readerState().baseUrl) } @@ -109,8 +97,7 @@ class ReaderActionTest { fun `UpdateReaderActiveUrlAction - Updates active url of ReaderState`() { assertNull(readerState().activeUrl) - store.dispatch(ReaderAction.UpdateReaderActiveUrlAction(tabId = tab.id, activeUrl = "https://mozilla.org")) - .joinBlocking() + state = BrowserStateReducer.reduce(state, ReaderAction.UpdateReaderActiveUrlAction(tabId = tab.id, activeUrl = "https://mozilla.org")) assertEquals("https://mozilla.org", readerState().activeUrl) } @@ -119,13 +106,11 @@ class ReaderActionTest { fun `UpdateReaderScrollYAction - Updates scrollY of ReaderState when active`() { assertFalse(readerState().active) - store.dispatch(ReaderAction.UpdateReaderActiveAction(tabId = tab.id, active = true)) - .joinBlocking() + state = BrowserStateReducer.reduce(state, ReaderAction.UpdateReaderActiveAction(tabId = tab.id, active = true)) assertTrue(readerState().active) - store.dispatch(ReaderAction.UpdateReaderScrollYAction(tabId = tab.id, scrollY = 1234)) - .joinBlocking() + state = BrowserStateReducer.reduce(state, ReaderAction.UpdateReaderScrollYAction(tabId = tab.id, scrollY = 1234)) assertEquals(1234, readerState().scrollY) } @@ -134,8 +119,7 @@ class ReaderActionTest { fun `UpdateReaderScrollYAction - Does not update scrollY of ReaderState when not active`() { assertFalse(readerState().active) - store.dispatch(ReaderAction.UpdateReaderScrollYAction(tabId = tab.id, scrollY = 1234)) - .joinBlocking() + state = BrowserStateReducer.reduce(state, ReaderAction.UpdateReaderScrollYAction(tabId = tab.id, scrollY = 1234)) assertNull(readerState().scrollY) } @@ -144,11 +128,10 @@ class ReaderActionTest { fun `ClearReaderActiveUrlAction - Clears active url of ReaderState`() { assertNull(readerState().activeUrl) - store.dispatch(ReaderAction.UpdateReaderActiveUrlAction(tabId = tab.id, activeUrl = "https://mozilla.org")) - .joinBlocking() + state = BrowserStateReducer.reduce(state, ReaderAction.UpdateReaderActiveUrlAction(tabId = tab.id, activeUrl = "https://mozilla.org")) assertEquals("https://mozilla.org", readerState().activeUrl) - store.dispatch(ReaderAction.ClearReaderActiveUrlAction(tabId = tab.id)).joinBlocking() + state = BrowserStateReducer.reduce(state, ReaderAction.ClearReaderActiveUrlAction(tabId = tab.id)) assertNull(readerState().activeUrl) } } diff --git a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/SearchActionTest.kt b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/SearchActionTest.kt @@ -4,12 +4,11 @@ package mozilla.components.browser.state.action +import mozilla.components.browser.state.reducer.BrowserStateReducer import mozilla.components.browser.state.search.RegionState import mozilla.components.browser.state.search.SearchEngine import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.state.SearchState -import mozilla.components.browser.state.store.BrowserStore -import mozilla.components.support.test.ext.joinBlocking import mozilla.components.support.test.mock import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse @@ -34,11 +33,12 @@ class SearchActionTest { type = SearchEngine.Type.BUNDLED, ) - val store = BrowserStore(BrowserState()) + var state = BrowserState() val searchEngineList = listOf(engine1, engine2) - assertTrue(store.state.search.regionSearchEngines.isEmpty()) + assertTrue(state.search.regionSearchEngines.isEmpty()) - store.dispatch( + state = BrowserStateReducer.reduce( + state, SearchAction.SetSearchEnginesAction( regionSearchEngines = searchEngineList, regionDefaultSearchEngineId = "id2", @@ -51,9 +51,9 @@ class SearchActionTest { additionalAvailableSearchEngines = emptyList(), regionSearchEnginesOrder = listOf("id1", "id2"), ), - ).joinBlocking() + ) - val searchEngines = store.state.search.regionSearchEngines + val searchEngines = state.search.regionSearchEngines assertFalse(searchEngines.isEmpty()) assertEquals(2, searchEngines.size) assertEquals(engine1, searchEngines[0]) @@ -75,15 +75,17 @@ class SearchActionTest { type = SearchEngine.Type.APPLICATION, ) - val store = BrowserStore(BrowserState()) + var state = BrowserState() + val searchEngineList = listOf(engine1, engine2) - assertTrue(store.state.search.applicationSearchEngines.isEmpty()) + assertTrue(state.search.applicationSearchEngines.isEmpty()) - store.dispatch( + state = BrowserStateReducer.reduce( + state, SearchAction.ApplicationSearchEnginesLoaded(searchEngineList), - ).joinBlocking() + ) - val searchEngines = store.state.search.applicationSearchEngines + val searchEngines = state.search.applicationSearchEngines assertEquals(2, searchEngines.size) } @@ -102,11 +104,13 @@ class SearchActionTest { type = SearchEngine.Type.CUSTOM, ) - val store = BrowserStore(BrowserState()) + var state = BrowserState() + val searchEngineList = listOf(engine1, engine2) - assertTrue(store.state.search.customSearchEngines.isEmpty()) + assertTrue(state.search.customSearchEngines.isEmpty()) - store.dispatch( + state = BrowserStateReducer.reduce( + state, SearchAction.SetSearchEnginesAction( customSearchEngines = searchEngineList, regionSearchEngines = emptyList(), @@ -119,9 +123,9 @@ class SearchActionTest { additionalAvailableSearchEngines = emptyList(), regionSearchEnginesOrder = emptyList(), ), - ).joinBlocking() + ) - val searchEngines = store.state.search.customSearchEngines + val searchEngines = state.search.customSearchEngines assertFalse(searchEngines.isEmpty()) assertEquals(2, searchEngines.size) assertEquals(engine1, searchEngines[0]) @@ -130,9 +134,9 @@ class SearchActionTest { @Test fun `UpdateCustomSearchEngineAction sets a new custom search engine`() { - val store = BrowserStore(BrowserState()) + var state = BrowserState() - assertTrue(store.state.search.customSearchEngines.isEmpty()) + assertTrue(state.search.customSearchEngines.isEmpty()) val customSearchEngine = SearchEngine( id = "customId1", @@ -142,9 +146,11 @@ class SearchActionTest { ) // Add a custom search engine - store.dispatch(SearchAction.UpdateCustomSearchEngineAction(customSearchEngine)).joinBlocking() + state = BrowserStateReducer.reduce( + state, SearchAction.UpdateCustomSearchEngineAction(customSearchEngine), + ) - store.state.search.customSearchEngines.let { searchEngines -> + state.search.customSearchEngines.let { searchEngines -> assertTrue(searchEngines.isNotEmpty()) assertEquals(1, searchEngines.size) assertEquals(customSearchEngine, searchEngines[0]) @@ -158,9 +164,11 @@ class SearchActionTest { ) // Add another search engine - store.dispatch(SearchAction.UpdateCustomSearchEngineAction(customSearchEngine2)).joinBlocking() + state = BrowserStateReducer.reduce( + state, SearchAction.UpdateCustomSearchEngineAction(customSearchEngine2), + ) - store.state.search.customSearchEngines.let { searchEngines -> + state.search.customSearchEngines.let { searchEngines -> assertTrue(searchEngines.isNotEmpty()) assertEquals(2, searchEngines.size) assertEquals(customSearchEngine, searchEngines[0]) @@ -171,9 +179,11 @@ class SearchActionTest { val updated = customSearchEngine.copy( name = "My awesome search engine", ) - store.dispatch(SearchAction.UpdateCustomSearchEngineAction(updated)).joinBlocking() + state = BrowserStateReducer.reduce( + state, SearchAction.UpdateCustomSearchEngineAction(updated), + ) - store.state.search.customSearchEngines.let { searchEngines -> + state.search.customSearchEngines.let { searchEngines -> assertTrue(searchEngines.isNotEmpty()) assertEquals(2, searchEngines.size) assertEquals(updated, searchEngines[0]) @@ -190,21 +200,26 @@ class SearchActionTest { type = SearchEngine.Type.CUSTOM, ) - val store = BrowserStore( + var state = BrowserState( search = SearchState( customSearchEngines = listOf(customSearchEngine), ), - ), + ) + + assertEquals(1, state.search.customSearchEngines.size) + + state = BrowserStateReducer.reduce( + state, SearchAction.RemoveCustomSearchEngineAction("unrecognized_id"), ) - assertEquals(1, store.state.search.customSearchEngines.size) + assertEquals(1, state.search.customSearchEngines.size) - store.dispatch(SearchAction.RemoveCustomSearchEngineAction("unrecognized_id")).joinBlocking() - assertEquals(1, store.state.search.customSearchEngines.size) + state = BrowserStateReducer.reduce( + state, SearchAction.RemoveCustomSearchEngineAction(customSearchEngine.id), + ) - store.dispatch(SearchAction.RemoveCustomSearchEngineAction(customSearchEngine.id)).joinBlocking() - assertTrue(store.state.search.customSearchEngines.isEmpty()) + assertTrue(state.search.customSearchEngines.isEmpty()) } @Test @@ -216,221 +231,304 @@ class SearchActionTest { type = SearchEngine.Type.BUNDLED, ) - val store = BrowserStore( - BrowserState( - search = SearchState( - regionSearchEngines = listOf(searchEngine), - ), + var state = BrowserState( + search = SearchState( + regionSearchEngines = listOf(searchEngine), ), ) - assertNull(store.state.search.userSelectedSearchEngineId) + assertNull(state.search.userSelectedSearchEngineId) - store.dispatch(SearchAction.SelectSearchEngineAction(searchEngine.id, null)).joinBlocking() - assertEquals(searchEngine.id, store.state.search.userSelectedSearchEngineId) + state = BrowserStateReducer.reduce( + state, SearchAction.SelectSearchEngineAction(searchEngine.id, null), + ) + assertEquals(searchEngine.id, state.search.userSelectedSearchEngineId) + + assertEquals(searchEngine.id, state.search.userSelectedSearchEngineId) - assertEquals(searchEngine.id, store.state.search.userSelectedSearchEngineId) + state = BrowserStateReducer.reduce( + state, SearchAction.SelectSearchEngineAction("unrecognized_id", null), + ) - store.dispatch(SearchAction.SelectSearchEngineAction("unrecognized_id", null)).joinBlocking() // We allow setting an ID of a search engine that is not in the state since loading happens // asynchronously and the search engine may not be loaded yet. - assertEquals("unrecognized_id", store.state.search.userSelectedSearchEngineId) + assertEquals("unrecognized_id", state.search.userSelectedSearchEngineId) } @Test fun `Setting region of user`() { - val store = BrowserStore() - assertNull(store.state.search.region) + var state = BrowserState() + assertNull(state.search.region) - store.dispatch(SearchAction.SetRegionAction(RegionState("DE", "FR"))).joinBlocking() + state = BrowserStateReducer.reduce( + state, SearchAction.SetRegionAction(RegionState("DE", "FR")), + ) - assertNotNull(store.state.search.region) - assertEquals("DE", store.state.search.region!!.home) - assertEquals("FR", store.state.search.region!!.current) + assertNotNull(state.search.region) + assertEquals("DE", state.search.region!!.home) + assertEquals("FR", state.search.region!!.current) } @Test fun `WHEN restore hidden search engines action GIVEN there are hidden engines THEN hidden engines are added back to the bundled engine list`() { - val store = BrowserStore( - BrowserState( - search = SearchState( - regionSearchEngines = listOf( - SearchEngine(id = "google", name = "Google", icon = mock(), type = SearchEngine.Type.BUNDLED), - SearchEngine(id = "bing", name = "Bing", icon = mock(), type = SearchEngine.Type.BUNDLED), + var state = BrowserState( + search = SearchState( + regionSearchEngines = listOf( + SearchEngine( + id = "google", + name = "Google", + icon = mock(), + type = SearchEngine.Type.BUNDLED, ), - hiddenSearchEngines = listOf( - SearchEngine(id = "duckduckgo", name = "DuckDuckGo", icon = mock(), type = SearchEngine.Type.BUNDLED), + SearchEngine( + id = "bing", + name = "Bing", + icon = mock(), + type = SearchEngine.Type.BUNDLED, + ), + ), + hiddenSearchEngines = listOf( + SearchEngine( + id = "duckduckgo", + name = "DuckDuckGo", + icon = mock(), + type = SearchEngine.Type.BUNDLED, ), ), ), ) - assertEquals(2, store.state.search.regionSearchEngines.size) - assertEquals(1, store.state.search.hiddenSearchEngines.size) + assertEquals(2, state.search.regionSearchEngines.size) + assertEquals(1, state.search.hiddenSearchEngines.size) - assertEquals("google", store.state.search.regionSearchEngines[0].id) - assertEquals("bing", store.state.search.regionSearchEngines[1].id) - assertEquals("duckduckgo", store.state.search.hiddenSearchEngines[0].id) + assertEquals("google", state.search.regionSearchEngines[0].id) + assertEquals("bing", state.search.regionSearchEngines[1].id) + assertEquals("duckduckgo", state.search.hiddenSearchEngines[0].id) - store.dispatch( + state = BrowserStateReducer.reduce( + state, SearchAction.RestoreHiddenSearchEnginesAction, - ).joinBlocking() + ) - assertEquals(3, store.state.search.regionSearchEngines.size) - assertEquals(0, store.state.search.hiddenSearchEngines.size) + assertEquals(3, state.search.regionSearchEngines.size) + assertEquals(0, state.search.hiddenSearchEngines.size) - assertEquals("google", store.state.search.regionSearchEngines[0].id) - assertEquals("bing", store.state.search.regionSearchEngines[1].id) - assertEquals("duckduckgo", store.state.search.regionSearchEngines[2].id) + assertEquals("google", state.search.regionSearchEngines[0].id) + assertEquals("bing", state.search.regionSearchEngines[1].id) + assertEquals("duckduckgo", state.search.regionSearchEngines[2].id) } @Test fun `WHEN restore hidden search engines action GIVEN there are no hidden engines THEN there are no changes`() { - val store = BrowserStore( - BrowserState( - search = SearchState( - regionSearchEngines = listOf( - SearchEngine(id = "google", name = "Google", icon = mock(), type = SearchEngine.Type.BUNDLED), - SearchEngine(id = "bing", name = "Bing", icon = mock(), type = SearchEngine.Type.BUNDLED), - SearchEngine(id = "duckduckgo", name = "DuckDuckGo", icon = mock(), type = SearchEngine.Type.BUNDLED), + var state = BrowserState( + search = SearchState( + regionSearchEngines = listOf( + SearchEngine( + id = "google", + name = "Google", + icon = mock(), + type = SearchEngine.Type.BUNDLED, + ), + SearchEngine( + id = "bing", + name = "Bing", + icon = mock(), + type = SearchEngine.Type.BUNDLED, + ), + SearchEngine( + id = "duckduckgo", + name = "DuckDuckGo", + icon = mock(), + type = SearchEngine.Type.BUNDLED, ), - hiddenSearchEngines = listOf(), ), + hiddenSearchEngines = listOf(), ), ) - assertEquals(3, store.state.search.regionSearchEngines.size) - assertEquals(0, store.state.search.hiddenSearchEngines.size) + assertEquals(3, state.search.regionSearchEngines.size) + assertEquals(0, state.search.hiddenSearchEngines.size) - assertEquals("google", store.state.search.regionSearchEngines[0].id) - assertEquals("bing", store.state.search.regionSearchEngines[1].id) - assertEquals("duckduckgo", store.state.search.regionSearchEngines[2].id) + assertEquals("google", state.search.regionSearchEngines[0].id) + assertEquals("bing", state.search.regionSearchEngines[1].id) + assertEquals("duckduckgo", state.search.regionSearchEngines[2].id) - store.dispatch( + state = BrowserStateReducer.reduce( + state, SearchAction.RestoreHiddenSearchEnginesAction, - ).joinBlocking() + ) - assertEquals(3, store.state.search.regionSearchEngines.size) - assertEquals(0, store.state.search.hiddenSearchEngines.size) + assertEquals(3, state.search.regionSearchEngines.size) + assertEquals(0, state.search.hiddenSearchEngines.size) - assertEquals("google", store.state.search.regionSearchEngines[0].id) - assertEquals("bing", store.state.search.regionSearchEngines[1].id) - assertEquals("duckduckgo", store.state.search.regionSearchEngines[2].id) + assertEquals("google", state.search.regionSearchEngines[0].id) + assertEquals("bing", state.search.regionSearchEngines[1].id) + assertEquals("duckduckgo", state.search.regionSearchEngines[2].id) } @Test fun `ShowSearchEngineAction - Adds hidden search engines back to region search engines`() { - val store = BrowserStore( - BrowserState( - search = SearchState( - regionSearchEngines = listOf( - SearchEngine(id = "google", name = "Google", icon = mock(), type = SearchEngine.Type.BUNDLED), - SearchEngine(id = "bing", name = "Bing", icon = mock(), type = SearchEngine.Type.BUNDLED), + var state = BrowserState( + search = SearchState( + regionSearchEngines = listOf( + SearchEngine( + id = "google", + name = "Google", + icon = mock(), + type = SearchEngine.Type.BUNDLED, + ), + SearchEngine( + id = "bing", + name = "Bing", + icon = mock(), + type = SearchEngine.Type.BUNDLED, ), - hiddenSearchEngines = listOf( - SearchEngine(id = "duckduckgo", name = "DuckDuckGo", icon = mock(), type = SearchEngine.Type.BUNDLED), + ), + hiddenSearchEngines = listOf( + SearchEngine( + id = "duckduckgo", + name = "DuckDuckGo", + icon = mock(), + type = SearchEngine.Type.BUNDLED, ), ), ), ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, SearchAction.ShowSearchEngineAction("duckduckgo"), - ).joinBlocking() + ) - assertEquals(0, store.state.search.hiddenSearchEngines.size) - assertEquals(3, store.state.search.regionSearchEngines.size) + assertEquals(0, state.search.hiddenSearchEngines.size) + assertEquals(3, state.search.regionSearchEngines.size) - assertEquals("google", store.state.search.regionSearchEngines[0].id) - assertEquals("bing", store.state.search.regionSearchEngines[1].id) - assertEquals("duckduckgo", store.state.search.regionSearchEngines[2].id) + assertEquals("google", state.search.regionSearchEngines[0].id) + assertEquals("bing", state.search.regionSearchEngines[1].id) + assertEquals("duckduckgo", state.search.regionSearchEngines[2].id) } @Test fun `HideSearchEngineAction - Adds region search engine to hidden search engines`() { - val store = BrowserStore( - BrowserState( - search = SearchState( - regionSearchEngines = listOf( - SearchEngine(id = "google", name = "Google", icon = mock(), type = SearchEngine.Type.BUNDLED), - SearchEngine(id = "bing", name = "Bing", icon = mock(), type = SearchEngine.Type.BUNDLED), + var state = BrowserState( + search = SearchState( + regionSearchEngines = listOf( + SearchEngine( + id = "google", + name = "Google", + icon = mock(), + type = SearchEngine.Type.BUNDLED, ), - hiddenSearchEngines = listOf( - SearchEngine(id = "duckduckgo", name = "DuckDuckGo", icon = mock(), type = SearchEngine.Type.BUNDLED), + SearchEngine( + id = "bing", + name = "Bing", + icon = mock(), + type = SearchEngine.Type.BUNDLED, + ), + ), + hiddenSearchEngines = listOf( + SearchEngine( + id = "duckduckgo", + name = "DuckDuckGo", + icon = mock(), + type = SearchEngine.Type.BUNDLED, ), ), ), ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, SearchAction.HideSearchEngineAction("google"), - ).joinBlocking() + ) - assertEquals(2, store.state.search.hiddenSearchEngines.size) - assertEquals(1, store.state.search.regionSearchEngines.size) + assertEquals(2, state.search.hiddenSearchEngines.size) + assertEquals(1, state.search.regionSearchEngines.size) - assertEquals("bing", store.state.search.regionSearchEngines[0].id) + assertEquals("bing", state.search.regionSearchEngines[0].id) - assertEquals("duckduckgo", store.state.search.hiddenSearchEngines[0].id) - assertEquals("google", store.state.search.hiddenSearchEngines[1].id) + assertEquals("duckduckgo", state.search.hiddenSearchEngines[0].id) + assertEquals("google", state.search.hiddenSearchEngines[1].id) } @Test fun `ShowSearchEngineAction, HideSearchEngineAction - Does nothing for unknown or custom search engines`() { - val store = BrowserStore( - BrowserState( - search = SearchState( - regionSearchEngines = listOf( - SearchEngine(id = "google", name = "Google", icon = mock(), type = SearchEngine.Type.BUNDLED), - SearchEngine(id = "bing", name = "Bing", icon = mock(), type = SearchEngine.Type.BUNDLED), + var state = BrowserState( + search = SearchState( + regionSearchEngines = listOf( + SearchEngine( + id = "google", + name = "Google", + icon = mock(), + type = SearchEngine.Type.BUNDLED, + ), + SearchEngine( + id = "bing", + name = "Bing", + icon = mock(), + type = SearchEngine.Type.BUNDLED, ), - hiddenSearchEngines = listOf( - SearchEngine(id = "duckduckgo", name = "DuckDuckGo", icon = mock(), type = SearchEngine.Type.BUNDLED), + ), + hiddenSearchEngines = listOf( + SearchEngine( + id = "duckduckgo", + name = "DuckDuckGo", + icon = mock(), + type = SearchEngine.Type.BUNDLED, ), - customSearchEngines = listOf( - SearchEngine(id = "banana", name = "Banana Search", icon = mock(), type = SearchEngine.Type.CUSTOM), + ), + customSearchEngines = listOf( + SearchEngine( + id = "banana", + name = "Banana Search", + icon = mock(), + type = SearchEngine.Type.CUSTOM, ), ), ), ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, SearchAction.ShowSearchEngineAction("banana"), - ).joinBlocking() + ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, SearchAction.HideSearchEngineAction("banana"), - ).joinBlocking() + ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, SearchAction.HideSearchEngineAction("unknown-search"), - ).joinBlocking() + ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, SearchAction.ShowSearchEngineAction("also-unknown-search"), - ).joinBlocking() + ) - assertEquals(2, store.state.search.regionSearchEngines.size) - assertEquals(1, store.state.search.hiddenSearchEngines.size) - assertEquals(1, store.state.search.customSearchEngines.size) + assertEquals(2, state.search.regionSearchEngines.size) + assertEquals(1, state.search.hiddenSearchEngines.size) + assertEquals(1, state.search.customSearchEngines.size) - assertEquals("google", store.state.search.regionSearchEngines[0].id) - assertEquals("bing", store.state.search.regionSearchEngines[1].id) + assertEquals("google", state.search.regionSearchEngines[0].id) + assertEquals("bing", state.search.regionSearchEngines[1].id) - assertEquals("duckduckgo", store.state.search.hiddenSearchEngines[0].id) + assertEquals("duckduckgo", state.search.hiddenSearchEngines[0].id) - assertEquals("banana", store.state.search.customSearchEngines[0].id) + assertEquals("banana", state.search.customSearchEngines[0].id) } @Test fun `GIVEN the search state of the browser WHEN refreshing the list of search engines THEN do not modify the state`() { - val state = BrowserState( + val initialState = BrowserState( search = mock(), ) - val store = BrowserStore(state) - store.dispatch(SearchAction.RefreshSearchEnginesAction).joinBlocking() + val state = + BrowserStateReducer.reduce(initialState, SearchAction.RefreshSearchEnginesAction) - assertEquals(state.search, store.state.search) + assertEquals(initialState.search, state.search) } } diff --git a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/TabGroupActionTest.kt b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/TabGroupActionTest.kt @@ -4,14 +4,13 @@ package mozilla.components.browser.state.action +import mozilla.components.browser.state.reducer.BrowserStateReducer import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.state.TabGroup import mozilla.components.browser.state.state.TabPartition import mozilla.components.browser.state.state.createTab import mozilla.components.browser.state.state.getGroupById import mozilla.components.browser.state.state.getGroupByName -import mozilla.components.browser.state.store.BrowserStore -import mozilla.components.support.test.ext.joinBlocking import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertNotNull @@ -24,13 +23,13 @@ class TabGroupActionTest { @Test fun `AddTabGroupAction - Adds provided group and creates partition if needed`() { - val store = BrowserStore() + var state = BrowserState() val partition = "testFeaturePartition" val testGroup = TabGroup("test", "testGroup") - store.dispatch(TabGroupAction.AddTabGroupAction(partition = partition, group = testGroup)).joinBlocking() + state = BrowserStateReducer.reduce(state, TabGroupAction.AddTabGroupAction(partition = partition, group = testGroup)) - val expectedPartition = store.state.tabPartitions[partition] + val expectedPartition = state.tabPartitions[partition] assertNotNull(expectedPartition) assertSame(testGroup, expectedPartition?.getGroupById(testGroup.id)) assertSame(testGroup, expectedPartition?.getGroupByName(testGroup.name)) @@ -38,20 +37,18 @@ class TabGroupActionTest { @Test fun `AddTabGroupAction - Adds provided group with tabs`() { - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab(id = "tab1", url = "https://firefox.com"), - createTab(id = "tab2", url = "https://mozilla.org"), - ), + var state = BrowserState( + tabs = listOf( + createTab(id = "tab1", url = "https://firefox.com"), + createTab(id = "tab2", url = "https://mozilla.org"), ), ) val partition = "testFeaturePartition" val testGroup = TabGroup("test", tabIds = listOf("tab1", "tab2")) - store.dispatch(TabGroupAction.AddTabGroupAction(partition = partition, group = testGroup)).joinBlocking() + state = BrowserStateReducer.reduce(state, TabGroupAction.AddTabGroupAction(partition = partition, group = testGroup)) - val expectedPartition = store.state.tabPartitions[partition] + val expectedPartition = state.tabPartitions[partition] assertNotNull(expectedPartition) assertSame(testGroup, expectedPartition?.getGroupById(testGroup.id)) assertEquals(listOf("tab1", "tab2"), expectedPartition?.getGroupById(testGroup.id)?.tabIds) @@ -63,21 +60,19 @@ class TabGroupActionTest { val tabGroup2 = TabGroup("test2", tabIds = listOf("tab1", "tab2")) val tabPartition = TabPartition("testFeaturePartition", tabGroups = listOf(tabGroup1, tabGroup2)) - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab(id = "tab1", url = "https://firefox.com"), - createTab(id = "tab2", url = "https://mozilla.org"), - ), - tabPartitions = mapOf("testFeaturePartition" to tabPartition), + var state = BrowserState( + tabs = listOf( + createTab(id = "tab1", url = "https://firefox.com"), + createTab(id = "tab2", url = "https://mozilla.org"), ), + tabPartitions = mapOf("testFeaturePartition" to tabPartition), ) - assertNotNull(store.state.tabPartitions[tabPartition.id]?.getGroupById(tabGroup1.id)) - assertNotNull(store.state.tabPartitions[tabPartition.id]?.getGroupById(tabGroup2.id)) - store.dispatch(TabGroupAction.RemoveTabGroupAction(tabPartition.id, tabGroup1.id)).joinBlocking() - assertNull(store.state.tabPartitions[tabPartition.id]?.getGroupById(tabGroup1.id)) - assertNotNull(store.state.tabPartitions[tabPartition.id]?.getGroupById(tabGroup2.id)) + assertNotNull(state.tabPartitions[tabPartition.id]?.getGroupById(tabGroup1.id)) + assertNotNull(state.tabPartitions[tabPartition.id]?.getGroupById(tabGroup2.id)) + state = BrowserStateReducer.reduce(state, TabGroupAction.RemoveTabGroupAction(tabPartition.id, tabGroup1.id)) + assertNull(state.tabPartitions[tabPartition.id]?.getGroupById(tabGroup1.id)) + assertNotNull(state.tabPartitions[tabPartition.id]?.getGroupById(tabGroup2.id)) } @Test @@ -85,19 +80,17 @@ class TabGroupActionTest { val tabGroup = TabGroup("test1", tabIds = listOf("tab1", "tab2")) val tabPartition = TabPartition("testFeaturePartition", tabGroups = listOf(tabGroup)) - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab(id = "tab1", url = "https://firefox.com"), - createTab(id = "tab2", url = "https://mozilla.org"), - ), - tabPartitions = mapOf("testFeaturePartition" to tabPartition), + var state = BrowserState( + tabs = listOf( + createTab(id = "tab1", url = "https://firefox.com"), + createTab(id = "tab2", url = "https://mozilla.org"), ), + tabPartitions = mapOf("testFeaturePartition" to tabPartition), ) - assertNotNull(store.state.tabPartitions[tabPartition.id]?.getGroupById(tabGroup.id)) - store.dispatch(TabGroupAction.RemoveTabGroupAction(tabPartition.id, tabGroup.id)).joinBlocking() - assertNull(store.state.tabPartitions[tabPartition.id]) + assertNotNull(state.tabPartitions[tabPartition.id]?.getGroupById(tabGroup.id)) + state = BrowserStateReducer.reduce(state, TabGroupAction.RemoveTabGroupAction(tabPartition.id, tabGroup.id)) + assertNull(state.tabPartitions[tabPartition.id]) } @Test @@ -106,16 +99,14 @@ class TabGroupActionTest { val tabPartition = TabPartition("testFeaturePartition", tabGroups = listOf(tabGroup)) val tab = createTab(id = "tab1", url = "https://firefox.com") - val store = BrowserStore( - BrowserState( - tabs = listOf(tab), - tabPartitions = mapOf("testFeaturePartition" to tabPartition), - ), + var state = BrowserState( + tabs = listOf(tab), + tabPartitions = mapOf("testFeaturePartition" to tabPartition), ) - store.dispatch(TabGroupAction.AddTabAction(tabPartition.id, tabGroup.id, tab.id)).joinBlocking() + state = BrowserStateReducer.reduce(state, TabGroupAction.AddTabAction(tabPartition.id, tabGroup.id, tab.id)) - val expectedPartition = store.state.tabPartitions[tabPartition.id] + val expectedPartition = state.tabPartitions[tabPartition.id] assertNotNull(expectedPartition) val expectedGroup = expectedPartition!!.getGroupById(tabGroup.id) assertNotNull(expectedGroup) @@ -128,15 +119,13 @@ class TabGroupActionTest { val tabPartition = TabPartition("testFeaturePartition") val tab = createTab(id = "tab1", url = "https://firefox.com") - val store = BrowserStore( - BrowserState( - tabs = listOf(tab), - ), + var state = BrowserState( + tabs = listOf(tab), ) - store.dispatch(TabGroupAction.AddTabAction(tabPartition.id, tabGroup.id, tab.id)).joinBlocking() + state = BrowserStateReducer.reduce(state, TabGroupAction.AddTabAction(tabPartition.id, tabGroup.id, tab.id)) - val expectedPartition = store.state.tabPartitions[tabPartition.id] + val expectedPartition = state.tabPartitions[tabPartition.id] assertNotNull(expectedPartition) val expectedGroup = expectedPartition!!.getGroupById(tabGroup.id) assertNotNull(expectedGroup) @@ -149,16 +138,14 @@ class TabGroupActionTest { val tabPartition = TabPartition("testFeaturePartition", tabGroups = listOf(tabGroup)) val tab = createTab(id = "tab1", url = "https://firefox.com") - val store = BrowserStore( - BrowserState( - tabs = listOf(tab), - tabPartitions = mapOf("testFeaturePartition" to tabPartition), - ), + var state = BrowserState( + tabs = listOf(tab), + tabPartitions = mapOf("testFeaturePartition" to tabPartition), ) - store.dispatch(TabGroupAction.AddTabAction(tabPartition.id, tabGroup.id, tab.id)).joinBlocking() + state = BrowserStateReducer.reduce(state, TabGroupAction.AddTabAction(tabPartition.id, tabGroup.id, tab.id)) - val expectedPartition = store.state.tabPartitions[tabPartition.id] + val expectedPartition = state.tabPartitions[tabPartition.id] assertNotNull(expectedPartition) val expectedGroup = expectedPartition!!.getGroupById(tabGroup.id) assertNotNull(expectedGroup) @@ -173,18 +160,17 @@ class TabGroupActionTest { val tab1 = createTab(id = "tab1", url = "https://firefox.com") val tab2 = createTab(id = "tab2", url = "https://mozilla.org") - val store = BrowserStore( - BrowserState( - tabs = listOf(tab1, tab2), - tabPartitions = mapOf("testFeaturePartition" to tabPartition), - ), + var state = BrowserState( + tabs = listOf(tab1, tab2), + tabPartitions = mapOf("testFeaturePartition" to tabPartition), ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TabGroupAction.AddTabsAction(tabPartition.id, tabGroup.id, listOf(tab1.id, tab2.id)), - ).joinBlocking() + ) - val expectedPartition = store.state.tabPartitions[tabPartition.id] + val expectedPartition = state.tabPartitions[tabPartition.id] assertNotNull(expectedPartition) val expectedGroup = expectedPartition!!.getGroupById(tabGroup.id) assertNotNull(expectedGroup) @@ -199,17 +185,16 @@ class TabGroupActionTest { val tab1 = createTab(id = "tab1", url = "https://firefox.com") val tab2 = createTab(id = "tab2", url = "https://mozilla.org") - val store = BrowserStore( - BrowserState( - tabs = listOf(tab1, tab2), - ), + var state = BrowserState( + tabs = listOf(tab1, tab2), ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TabGroupAction.AddTabsAction(tabPartition.id, tabGroup.id, listOf(tab1.id, tab2.id)), - ).joinBlocking() + ) - val expectedPartition = store.state.tabPartitions[tabPartition.id] + val expectedPartition = state.tabPartitions[tabPartition.id] assertNotNull(expectedPartition) val expectedGroup = expectedPartition!!.getGroupById(tabGroup.id) assertNotNull(expectedGroup) @@ -224,18 +209,17 @@ class TabGroupActionTest { val tab1 = createTab(id = "tab1", url = "https://firefox.com") val tab2 = createTab(id = "tab2", url = "https://mozilla.org") - val store = BrowserStore( - BrowserState( - tabs = listOf(tab1, tab2), - tabPartitions = mapOf("testFeaturePartition" to tabPartition), - ), + var state = BrowserState( + tabs = listOf(tab1, tab2), + tabPartitions = mapOf("testFeaturePartition" to tabPartition), ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TabGroupAction.AddTabsAction(tabPartition.id, tabGroup.id, listOf(tab1.id, tab2.id)), - ).joinBlocking() + ) - val expectedPartition = store.state.tabPartitions[tabPartition.id] + val expectedPartition = state.tabPartitions[tabPartition.id] assertNotNull(expectedPartition) val expectedGroup = expectedPartition!!.getGroupById(tabGroup.id) assertNotNull(expectedGroup) @@ -250,17 +234,16 @@ class TabGroupActionTest { val tabPartition = TabPartition("testFeaturePartition") val tab1 = createTab(id = "tab1", url = "https://firefox.com") - val store = BrowserStore( - BrowserState( - tabs = listOf(tab1), - ), + var state = BrowserState( + tabs = listOf(tab1), ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TabGroupAction.AddTabsAction(tabPartition.id, tabGroup.id, listOf(tab1.id, tab1.id)), - ).joinBlocking() + ) - val expectedPartition = store.state.tabPartitions[tabPartition.id] + val expectedPartition = state.tabPartitions[tabPartition.id] assertNotNull(expectedPartition) val expectedGroup = expectedPartition!!.getGroupById(tabGroup.id) assertNotNull(expectedGroup) @@ -275,16 +258,14 @@ class TabGroupActionTest { val tabGroup = TabGroup("test1", tabIds = listOf(tab1.id, tab2.id)) val tabPartition = TabPartition("testFeaturePartition", tabGroups = listOf(tabGroup)) - val store = BrowserStore( - BrowserState( - tabs = listOf(tab1, tab2), - tabPartitions = mapOf("testFeaturePartition" to tabPartition), - ), + var state = BrowserState( + tabs = listOf(tab1, tab2), + tabPartitions = mapOf("testFeaturePartition" to tabPartition), ) - store.dispatch(TabGroupAction.RemoveTabAction(tabPartition.id, tabGroup.id, tab1.id)).joinBlocking() + state = BrowserStateReducer.reduce(state, TabGroupAction.RemoveTabAction(tabPartition.id, tabGroup.id, tab1.id)) - val expectedPartition = store.state.tabPartitions[tabPartition.id] + val expectedPartition = state.tabPartitions[tabPartition.id] assertNotNull(expectedPartition) val expectedGroup = expectedPartition!!.getGroupById(tabGroup.id) assertNotNull(expectedGroup) @@ -299,18 +280,17 @@ class TabGroupActionTest { val tabGroup = TabGroup("test1", tabIds = listOf(tab1.id, tab2.id)) val tabPartition = TabPartition("testFeaturePartition", tabGroups = listOf(tabGroup)) - val store = BrowserStore( - BrowserState( - tabs = listOf(tab1, tab2), - tabPartitions = mapOf("testFeaturePartition" to tabPartition), - ), + var state = BrowserState( + tabs = listOf(tab1, tab2), + tabPartitions = mapOf("testFeaturePartition" to tabPartition), ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TabGroupAction.RemoveTabsAction(tabPartition.id, tabGroup.id, listOf(tab1.id, tab2.id)), - ).joinBlocking() + ) - val expectedPartition = store.state.tabPartitions[tabPartition.id] + val expectedPartition = state.tabPartitions[tabPartition.id] assertNotNull(expectedPartition) val expectedGroup = expectedPartition!!.getGroupById(tabGroup.id) assertNotNull(expectedGroup) diff --git a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/TabListActionTest.kt b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/TabListActionTest.kt @@ -4,6 +4,7 @@ package mozilla.components.browser.state.action +import mozilla.components.browser.state.reducer.BrowserStateReducer import mozilla.components.browser.state.selector.normalTabs import mozilla.components.browser.state.selector.privateTabs import mozilla.components.browser.state.selector.selectedTab @@ -17,8 +18,6 @@ import mozilla.components.browser.state.state.createTab import mozilla.components.browser.state.state.getGroupById import mozilla.components.browser.state.state.recover.RecoverableTab import mozilla.components.browser.state.state.recover.TabState -import mozilla.components.browser.state.store.BrowserStore -import mozilla.components.support.test.ext.joinBlocking import mozilla.components.support.test.mock import org.junit.Assert.assertEquals import org.junit.Assert.assertNotNull @@ -30,155 +29,151 @@ class TabListActionTest { @Test fun `AddTabAction - Adds provided SessionState`() { - val store = BrowserStore() + var state = BrowserState() - assertEquals(0, store.state.tabs.size) - assertNull(store.state.selectedTabId) + assertEquals(0, state.tabs.size) + assertNull(state.selectedTabId) val tab = createTab(url = "https://www.mozilla.org") - store.dispatch(TabListAction.AddTabAction(tab)).joinBlocking() + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(tab)) - assertEquals(1, store.state.tabs.size) - assertEquals(tab.id, store.state.selectedTabId) + assertEquals(1, state.tabs.size) + assertEquals(tab.id, state.selectedTabId) } @Test fun `AddTabAction - Add tab and update selection`() { val existingTab = createTab("https://www.mozilla.org") - val state = BrowserState( + var state = BrowserState( tabs = listOf(existingTab), selectedTabId = existingTab.id, ) - val store = BrowserStore(state) - - assertEquals(1, store.state.tabs.size) - assertEquals(existingTab.id, store.state.selectedTabId) + assertEquals(1, state.tabs.size) + assertEquals(existingTab.id, state.selectedTabId) val newTab = createTab("https://firefox.com") - store.dispatch(TabListAction.AddTabAction(newTab, select = true)).joinBlocking() + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(newTab, select = true)) - assertEquals(2, store.state.tabs.size) - assertEquals(newTab.id, store.state.selectedTabId) + assertEquals(2, state.tabs.size) + assertEquals(newTab.id, state.selectedTabId) } @Test fun `AddTabAction - Select first tab automatically`() { val existingTab = createTab("https://www.mozilla.org") - val store = BrowserStore() + var state = BrowserState() - assertEquals(0, store.state.tabs.size) - assertNull(existingTab.id, store.state.selectedTabId) + assertEquals(0, state.tabs.size) + assertNull(existingTab.id, state.selectedTabId) val newTab = createTab("https://firefox.com") - store.dispatch(TabListAction.AddTabAction(newTab, select = false)).joinBlocking() + state = + BrowserStateReducer.reduce(state, TabListAction.AddTabAction(newTab, select = false)) - assertEquals(1, store.state.tabs.size) - assertEquals(newTab.id, store.state.selectedTabId) + assertEquals(1, state.tabs.size) + assertEquals(newTab.id, state.selectedTabId) } @Test fun `AddTabAction - Specify parent tab`() { - val store = BrowserStore() + var state = BrowserState() val tab1 = createTab("https://www.mozilla.org") val tab2 = createTab("https://www.firefox.com") val tab3 = createTab("https://wiki.mozilla.org", parent = tab1) val tab4 = createTab("https://github.com/mozilla-mobile/android-components", parent = tab2) - store.dispatch(TabListAction.AddTabAction(tab1)).joinBlocking() - store.dispatch(TabListAction.AddTabAction(tab2)).joinBlocking() - store.dispatch(TabListAction.AddTabAction(tab3)).joinBlocking() - store.dispatch(TabListAction.AddTabAction(tab4)).joinBlocking() + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(tab1)) + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(tab2)) + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(tab3)) + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(tab4)) - assertEquals(4, store.state.tabs.size) - assertNull(store.state.tabs[0].parentId) - assertNull(store.state.tabs[2].parentId) - assertEquals(tab1.id, store.state.tabs[1].parentId) - assertEquals(tab2.id, store.state.tabs[3].parentId) + assertEquals(4, state.tabs.size) + assertNull(state.tabs[0].parentId) + assertNull(state.tabs[2].parentId) + assertEquals(tab1.id, state.tabs[1].parentId) + assertEquals(tab2.id, state.tabs[3].parentId) } @Test fun `AddTabAction - Specify source`() { - val store = BrowserStore() + var state = BrowserState() val tab1 = createTab("https://www.mozilla.org") val tab2 = createTab("https://www.firefox.com", source = SessionState.Source.Internal.Menu) - store.dispatch(TabListAction.AddTabAction(tab1)).joinBlocking() - store.dispatch(TabListAction.AddTabAction(tab2)).joinBlocking() + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(tab1)) + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(tab2)) - assertEquals(2, store.state.tabs.size) - assertEquals(SessionState.Source.Internal.None, store.state.tabs[0].source) - assertEquals(SessionState.Source.Internal.Menu, store.state.tabs[1].source) + assertEquals(2, state.tabs.size) + assertEquals(SessionState.Source.Internal.None, state.tabs[0].source) + assertEquals(SessionState.Source.Internal.Menu, state.tabs[1].source) } @Test fun `AddTabAction - Tabs with parent are added after (next to) parent`() { - val store = BrowserStore() + var state = BrowserState() val parent01 = createTab("https://www.mozilla.org") val parent02 = createTab("https://getpocket.com") val tab1 = createTab("https://www.firefox.com") val tab2 = createTab("https://developer.mozilla.org/en-US/") - val child001 = createTab("https://www.mozilla.org/en-US/internet-health/", parent = parent01) + val child001 = + createTab("https://www.mozilla.org/en-US/internet-health/", parent = parent01) val child002 = createTab("https://www.mozilla.org/en-US/technology/", parent = parent01) val child003 = createTab("https://getpocket.com/add/", parent = parent02) - store.dispatch(TabListAction.AddTabAction(parent01)).joinBlocking() - store.dispatch(TabListAction.AddTabAction(tab1)).joinBlocking() - store.dispatch(TabListAction.AddTabAction(child001)).joinBlocking() - store.dispatch(TabListAction.AddTabAction(tab2)).joinBlocking() - store.dispatch(TabListAction.AddTabAction(parent02)).joinBlocking() - store.dispatch(TabListAction.AddTabAction(child002)).joinBlocking() - store.dispatch(TabListAction.AddTabAction(child003)).joinBlocking() - - assertEquals(parent01.id, store.state.tabs[0].id) // ├── parent 1 - assertEquals(child002.id, store.state.tabs[1].id) // │ ├── child 2 - assertEquals(child001.id, store.state.tabs[2].id) // │ └── child 1 - assertEquals(tab1.id, store.state.tabs[3].id) // ├──tab 1 - assertEquals(tab2.id, store.state.tabs[4].id) // ├──tab 2 - assertEquals(parent02.id, store.state.tabs[5].id) // └── parent 2 - assertEquals(child003.id, store.state.tabs[6].id) // └── child 3 + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(parent01)) + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(tab1)) + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(child001)) + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(tab2)) + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(parent02)) + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(child002)) + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(child003)) + + assertEquals(parent01.id, state.tabs[0].id) // ├── parent 1 + assertEquals(child002.id, state.tabs[1].id) // │ ├── child 2 + assertEquals(child001.id, state.tabs[2].id) // │ └── child 1 + assertEquals(tab1.id, state.tabs[3].id) // ├──tab 1 + assertEquals(tab2.id, state.tabs[4].id) // ├──tab 2 + assertEquals(parent02.id, state.tabs[5].id) // └── parent 2 + assertEquals(child003.id, state.tabs[6].id) // └── child 3 } @Test fun `SelectTabAction - Selects SessionState by id`() { - val state = BrowserState( + var state = BrowserState( tabs = listOf( createTab(id = "a", url = "https://www.mozilla.org"), createTab(id = "b", url = "https://www.firefox.com"), ), ) - val store = BrowserStore(state) - assertNull(store.state.selectedTabId) + assertNull(state.selectedTabId) - store.dispatch(TabListAction.SelectTabAction("a")) - .joinBlocking() + state = BrowserStateReducer.reduce(state, TabListAction.SelectTabAction("a")) - assertEquals("a", store.state.selectedTabId) + assertEquals("a", state.selectedTabId) } @Test fun `RemoveTabAction - Removes SessionState`() { - val state = BrowserState( + var state = BrowserState( tabs = listOf( createTab(id = "a", url = "https://www.mozilla.org"), createTab(id = "b", url = "https://www.firefox.com"), ), ) - val store = BrowserStore(state) - store.dispatch(TabListAction.RemoveTabAction("a")) - .joinBlocking() + state = BrowserStateReducer.reduce(state, TabListAction.RemoveTabAction("a")) - assertEquals(1, store.state.tabs.size) - assertEquals("https://www.firefox.com", store.state.tabs[0].content.url) + assertEquals(1, state.tabs.size) + assertEquals("https://www.firefox.com", state.tabs[0].content.url) } @Test @@ -186,37 +181,37 @@ class TabListActionTest { val tabGroup = TabGroup("test1", tabIds = listOf("a", "b")) val tabPartition = TabPartition("testPartition", tabGroups = listOf(tabGroup)) - val state = BrowserState( + var state = BrowserState( tabs = listOf( createTab(id = "a", url = "https://www.mozilla.org"), createTab(id = "b", url = "https://www.firefox.com"), ), tabPartitions = mapOf(tabPartition.id to tabPartition), ) - val store = BrowserStore(state) - store.dispatch(TabListAction.RemoveTabAction("a")).joinBlocking() - assertEquals(1, store.state.tabs.size) - assertEquals("https://www.firefox.com", store.state.tabs[0].content.url) - assertEquals(listOf("b"), store.state.tabPartitions[tabPartition.id]?.getGroupById(tabGroup.id)?.tabIds) + state = BrowserStateReducer.reduce(state, TabListAction.RemoveTabAction("a")) + assertEquals(1, state.tabs.size) + assertEquals("https://www.firefox.com", state.tabs[0].content.url) + assertEquals( + listOf("b"), + state.tabPartitions[tabPartition.id]?.getGroupById(tabGroup.id)?.tabIds, + ) } @Test fun `RemoveTabsAction - Removes SessionState`() { - val state = BrowserState( + var state = BrowserState( tabs = listOf( createTab(id = "a", url = "https://www.mozilla.org"), createTab(id = "b", url = "https://www.firefox.com"), createTab(id = "c", url = "https://www.getpocket.com"), ), ) - val store = BrowserStore(state) - store.dispatch(TabListAction.RemoveTabsAction(listOf("a", "b"))) - .joinBlocking() + state = BrowserStateReducer.reduce(state, TabListAction.RemoveTabsAction(listOf("a", "b"))) - assertEquals(1, store.state.tabs.size) - assertEquals("https://www.getpocket.com", store.state.tabs[0].content.url) + assertEquals(1, state.tabs.size) + assertEquals("https://www.getpocket.com", state.tabs[0].content.url) } @Test @@ -224,81 +219,81 @@ class TabListActionTest { val tabGroup = TabGroup("test1", tabIds = listOf("a", "b")) val tabPartition = TabPartition("testPartition", tabGroups = listOf(tabGroup)) - val state = BrowserState( + var state = BrowserState( tabs = listOf( createTab(id = "a", url = "https://www.mozilla.org"), createTab(id = "b", url = "https://www.firefox.com"), ), tabPartitions = mapOf(tabPartition.id to tabPartition), ) - val store = BrowserStore(state) - store.dispatch(TabListAction.RemoveTabsAction(listOf("a", "b"))).joinBlocking() - assertEquals(0, store.state.tabs.size) - assertEquals(0, store.state.tabPartitions[tabPartition.id]?.getGroupById(tabGroup.id)?.tabIds?.size) + state = BrowserStateReducer.reduce(state, TabListAction.RemoveTabsAction(listOf("a", "b"))) + assertEquals(0, state.tabs.size) + assertEquals( + 0, + state.tabPartitions[tabPartition.id]?.getGroupById(tabGroup.id)?.tabIds?.size, + ) } @Test fun `RemoveTabAction - Noop for unknown id`() { - val state = BrowserState( + var state = BrowserState( tabs = listOf( createTab(id = "a", url = "https://www.mozilla.org"), createTab(id = "b", url = "https://www.firefox.com"), ), ) - val store = BrowserStore(state) - store.dispatch(TabListAction.RemoveTabAction("c")) - .joinBlocking() + state = BrowserStateReducer.reduce(state, TabListAction.RemoveTabAction("c")) - assertEquals(2, store.state.tabs.size) - assertEquals("https://www.mozilla.org", store.state.tabs[0].content.url) - assertEquals("https://www.firefox.com", store.state.tabs[1].content.url) + assertEquals(2, state.tabs.size) + assertEquals("https://www.mozilla.org", state.tabs[0].content.url) + assertEquals("https://www.firefox.com", state.tabs[1].content.url) } @Test fun `RemoveTabAction - Selected tab id is set to null if selected and last tab is removed`() { - val state = BrowserState( + var state = BrowserState( tabs = listOf( createTab(id = "a", url = "https://www.mozilla.org"), ), selectedTabId = "a", ) - val store = BrowserStore(state) - - assertEquals("a", store.state.selectedTabId) + assertEquals("a", state.selectedTabId) - store.dispatch(TabListAction.RemoveTabAction("a")).joinBlocking() + state = BrowserStateReducer.reduce(state, TabListAction.RemoveTabAction("a")) - assertNull(store.state.selectedTabId) + assertNull(state.selectedTabId) } @Test fun `RemoveTabAction - Does not select custom tab`() { - val state = BrowserState( + var state = BrowserState( tabs = listOf( createTab(id = "a", url = "https://www.mozilla.org"), ), customTabs = listOf( createCustomTab(id = "b", url = "https://www.firefox.com"), - createCustomTab(id = "c", url = "https://www.firefox.com/hello", source = SessionState.Source.External.CustomTab(mock())), + createCustomTab( + id = "c", + url = "https://www.firefox.com/hello", + source = SessionState.Source.External.CustomTab(mock()), + ), ), selectedTabId = "a", ) - val store = BrowserStore(state) - - assertEquals("a", store.state.selectedTabId) + assertEquals("a", state.selectedTabId) - store.dispatch(TabListAction.RemoveTabAction("a")).joinBlocking() + state = BrowserStateReducer.reduce(state, TabListAction.RemoveTabAction("a")) - assertNull(store.state.selectedTabId) + assertNull(state.selectedTabId) } @Test fun `RemoveTabAction - Will select next nearby tab after removing selected tab`() { - val state = BrowserState( + var state = BrowserState( tabs = listOf( createTab(id = "a", url = "https://www.mozilla.org"), createTab(id = "b", url = "https://www.firefox.com"), @@ -311,26 +306,24 @@ class TabListActionTest { selectedTabId = "c", ) - val store = BrowserStore(state) - - assertEquals("c", store.state.selectedTabId) + assertEquals("c", state.selectedTabId) - store.dispatch(TabListAction.RemoveTabAction("c")).joinBlocking() - assertEquals("d", store.state.selectedTabId) + state = BrowserStateReducer.reduce(state, TabListAction.RemoveTabAction("c")) + assertEquals("d", state.selectedTabId) - store.dispatch(TabListAction.RemoveTabAction("a")).joinBlocking() - assertEquals("d", store.state.selectedTabId) + state = BrowserStateReducer.reduce(state, TabListAction.RemoveTabAction("a")) + assertEquals("d", state.selectedTabId) - store.dispatch(TabListAction.RemoveTabAction("d")).joinBlocking() - assertEquals("b", store.state.selectedTabId) + state = BrowserStateReducer.reduce(state, TabListAction.RemoveTabAction("d")) + assertEquals("b", state.selectedTabId) - store.dispatch(TabListAction.RemoveTabAction("b")).joinBlocking() - assertNull(store.state.selectedTabId) + state = BrowserStateReducer.reduce(state, TabListAction.RemoveTabAction("b")) + assertNull(state.selectedTabId) } @Test fun `RemoveTabAction - Selects private tab after private tab was removed`() { - val state = BrowserState( + var state = BrowserState( tabs = listOf( createTab(id = "a", url = "https://www.mozilla.org", private = true), createTab(id = "b", url = "https://www.firefox.com", private = false), @@ -340,25 +333,27 @@ class TabListActionTest { ), customTabs = listOf( createCustomTab(id = "a1", url = "https://www.firefox.com"), - createCustomTab(id = "b1", url = "https://hubs.mozilla.com", source = SessionState.Source.External.CustomTab(mock())), + createCustomTab( + id = "b1", + url = "https://hubs.mozilla.com", + source = SessionState.Source.External.CustomTab(mock()), + ), ), selectedTabId = "d", ) - val store = BrowserStore(state) - // [a*, b, c, (d*), e*] -> [a*, b, c, (e*)] - store.dispatch(TabListAction.RemoveTabAction("d")).joinBlocking() - assertEquals("e", store.state.selectedTabId) + state = BrowserStateReducer.reduce(state, TabListAction.RemoveTabAction("d")) + assertEquals("e", state.selectedTabId) // [a*, b, c, (e*)] -> [(a*), b, c] - store.dispatch(TabListAction.RemoveTabAction("e")).joinBlocking() - assertEquals("a", store.state.selectedTabId) + state = BrowserStateReducer.reduce(state, TabListAction.RemoveTabAction("e")) + assertEquals("a", state.selectedTabId) } @Test fun `RemoveTabAction - Selects normal tab after normal tab was removed`() { - val state = BrowserState( + var state = BrowserState( tabs = listOf( createTab(id = "a", url = "https://www.mozilla.org", private = false), createTab(id = "b", url = "https://www.firefox.com", private = true), @@ -368,101 +363,110 @@ class TabListActionTest { ), customTabs = listOf( createCustomTab(id = "a1", url = "https://www.firefox.com"), - createCustomTab(id = "b1", url = "https://hubs.mozilla.com", source = SessionState.Source.External.CustomTab(mock())), + createCustomTab( + id = "b1", + url = "https://hubs.mozilla.com", + source = SessionState.Source.External.CustomTab(mock()), + ), ), selectedTabId = "d", ) - val store = BrowserStore(state) - // [a, b*, c*, (d), e] -> [a, b*, c* (e)] - store.dispatch(TabListAction.RemoveTabAction("d")).joinBlocking() - assertEquals("e", store.state.selectedTabId) + state = BrowserStateReducer.reduce(state, TabListAction.RemoveTabAction("d")) + assertEquals("e", state.selectedTabId) // [a, b*, c*, (e)] -> [(a), b*, c*] - store.dispatch(TabListAction.RemoveTabAction("e")).joinBlocking() - assertEquals("a", store.state.selectedTabId) + state = BrowserStateReducer.reduce(state, TabListAction.RemoveTabAction("e")) + assertEquals("a", state.selectedTabId) // After removing the last normal tab NO private tab should get selected // [(a), b*, c*] -> [b*, c*] - store.dispatch(TabListAction.RemoveTabAction("a")).joinBlocking() - assertNull(store.state.selectedTabId) + state = BrowserStateReducer.reduce(state, TabListAction.RemoveTabAction("a")) + assertNull(state.selectedTabId) } @Test fun `GIVEN last normal tab WHEN removed THEN no new tab is selected`() { val normalTab = createTab("normal", private = false) val privateTab = createTab("private", private = true) - val initialState = BrowserState(tabs = listOf(normalTab, privateTab), selectedTabId = normalTab.id) - val store = BrowserStore(initialState) + val initialState = + BrowserState(tabs = listOf(normalTab, privateTab), selectedTabId = normalTab.id) - store.dispatch(TabListAction.RemoveTabAction(normalTab.id)).joinBlocking() + val state = + BrowserStateReducer.reduce(initialState, TabListAction.RemoveTabAction(normalTab.id)) - assertNull(store.state.selectedTabId) - assertEquals(1, store.state.tabs.size) + assertNull(state.selectedTabId) + assertEquals(1, state.tabs.size) } @Test fun `GIVEN last private tab WHEN removed THEN no new tab is selected`() { val normalTab = createTab("normal", private = false) val privateTab = createTab("private", private = true) - val initialState = BrowserState(tabs = listOf(normalTab, privateTab), selectedTabId = privateTab.id) - val store = BrowserStore(initialState) + val initialState = + BrowserState(tabs = listOf(normalTab, privateTab), selectedTabId = privateTab.id) - store.dispatch(TabListAction.RemoveTabAction(privateTab.id)).joinBlocking() + val state = + BrowserStateReducer.reduce(initialState, TabListAction.RemoveTabAction(privateTab.id)) - assertNull(store.state.selectedTabId) - assertEquals(1, store.state.tabs.size) + assertNull(state.selectedTabId) + assertEquals(1, state.tabs.size) } @Test fun `GIVEN normal tabs and one private tab WHEN all normal tabs are removed THEN no new tab is selected`() { - val tabs = List(5) { createTab("$it", private = false) } + createTab("private", private = true) + val tabs = + List(5) { createTab("$it", private = false) } + createTab("private", private = true) val initialState = BrowserState(tabs = tabs, selectedTabId = tabs.first().id) - val store = BrowserStore(initialState) - store.dispatch(TabListAction.RemoveAllNormalTabsAction).joinBlocking() + val state = + BrowserStateReducer.reduce(initialState, TabListAction.RemoveAllNormalTabsAction) - assertNull(store.state.selectedTabId) - assertEquals(1, store.state.tabs.size) + assertNull(state.selectedTabId) + assertEquals(1, state.tabs.size) } @Test fun `GIVEN one normal tab and private tabs WHEN all private tabs are removed THEN no new tab is selected`() { - val tabs = List(5) { createTab("$it", private = true) } + createTab("normal", private = false) + val tabs = + List(5) { createTab("$it", private = true) } + createTab("normal", private = false) val initialState = BrowserState(tabs = tabs, selectedTabId = tabs.first().id) - val store = BrowserStore(initialState) - store.dispatch(TabListAction.RemoveAllPrivateTabsAction).joinBlocking() + val state = + BrowserStateReducer.reduce(initialState, TabListAction.RemoveAllPrivateTabsAction) - assertNull(store.state.selectedTabId) - assertEquals(1, store.state.tabs.size) + assertNull(state.selectedTabId) + assertEquals(1, state.tabs.size) } @Test fun `RemoveTabAction - Parent will be selected if child is removed and flag is set to true (default)`() { - val store = BrowserStore() + var state = BrowserState() val parent = createTab("https://www.mozilla.org") val tab1 = createTab("https://www.firefox.com") val tab2 = createTab("https://getpocket.com") val child = createTab("https://www.mozilla.org/en-US/internet-health/", parent = parent) - store.dispatch(TabListAction.AddTabAction(parent)).joinBlocking() - store.dispatch(TabListAction.AddTabAction(tab1)).joinBlocking() - store.dispatch(TabListAction.AddTabAction(tab2)).joinBlocking() - store.dispatch(TabListAction.AddTabAction(child)).joinBlocking() + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(parent)) + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(tab1)) + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(tab2)) + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(child)) - store.dispatch(TabListAction.SelectTabAction(child.id)).joinBlocking() - store.dispatch(TabListAction.RemoveTabAction(child.id, selectParentIfExists = true)).joinBlocking() + state = BrowserStateReducer.reduce(state, TabListAction.SelectTabAction(child.id)) + state = BrowserStateReducer.reduce( + state, + TabListAction.RemoveTabAction(child.id, selectParentIfExists = true), + ) - assertEquals(parent.id, store.state.selectedTabId) - assertEquals("https://www.mozilla.org", store.state.selectedTab?.content?.url) + assertEquals(parent.id, state.selectedTabId) + assertEquals("https://www.mozilla.org", state.selectedTab?.content?.url) } @Test fun `RemoveTabAction - Parent will not be selected if child is removed and flag is set to false`() { - val store = BrowserStore() + var state = BrowserState() val parent = createTab("https://www.mozilla.org") @@ -471,96 +475,107 @@ class TabListActionTest { val child1 = createTab("https://www.mozilla.org/en-US/internet-health/", parent = parent) val child2 = createTab("https://www.mozilla.org/en-US/technology/", parent = parent) - store.dispatch(TabListAction.AddTabAction(parent)).joinBlocking() - store.dispatch(TabListAction.AddTabAction(tab1)).joinBlocking() - store.dispatch(TabListAction.AddTabAction(tab2)).joinBlocking() - store.dispatch(TabListAction.AddTabAction(child1)).joinBlocking() - store.dispatch(TabListAction.AddTabAction(child2)).joinBlocking() + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(parent)) + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(tab1)) + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(tab2)) + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(child1)) + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(child2)) - store.dispatch(TabListAction.SelectTabAction(child1.id)).joinBlocking() - store.dispatch(TabListAction.RemoveTabAction(child1.id, selectParentIfExists = false)).joinBlocking() + state = BrowserStateReducer.reduce(state, TabListAction.SelectTabAction(child1.id)) + state = BrowserStateReducer.reduce( + state, + TabListAction.RemoveTabAction(child1.id, selectParentIfExists = false), + ) - assertEquals(tab1.id, store.state.selectedTabId) - assertEquals("https://www.firefox.com", store.state.selectedTab?.content?.url) + assertEquals(tab1.id, state.selectedTabId) + assertEquals("https://www.firefox.com", state.selectedTab?.content?.url) } @Test fun `RemoveTabAction - Providing selectParentIfExists when removing tab without parent has no effect`() { - val store = BrowserStore() + var state = BrowserState() val tab1 = createTab("https://www.firefox.com") val tab2 = createTab("https://getpocket.com") val tab3 = createTab("https://www.mozilla.org/en-US/internet-health/") - store.dispatch(TabListAction.AddTabAction(tab1)).joinBlocking() - store.dispatch(TabListAction.AddTabAction(tab2)).joinBlocking() - store.dispatch(TabListAction.AddTabAction(tab3)).joinBlocking() + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(tab1)) + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(tab2)) + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(tab3)) - store.dispatch(TabListAction.SelectTabAction(tab3.id)).joinBlocking() - store.dispatch(TabListAction.RemoveTabAction(tab3.id, selectParentIfExists = true)).joinBlocking() + state = BrowserStateReducer.reduce(state, TabListAction.SelectTabAction(tab3.id)) + state = BrowserStateReducer.reduce( + state, + TabListAction.RemoveTabAction(tab3.id, selectParentIfExists = true), + ) - assertEquals(tab2.id, store.state.selectedTabId) - assertEquals("https://getpocket.com", store.state.selectedTab?.content?.url) + assertEquals(tab2.id, state.selectedTabId) + assertEquals("https://getpocket.com", state.selectedTab?.content?.url) } @Test fun `RemoveTabAction - Children are updated when parent is removed`() { - val store = BrowserStore() + var state = BrowserState() val tab0 = createTab("https://www.firefox.com") val tab1 = createTab("https://developer.mozilla.org/en-US/", parent = tab0) val tab2 = createTab("https://www.mozilla.org/en-US/internet-health/", parent = tab1) val tab3 = createTab("https://www.mozilla.org/en-US/technology/", parent = tab2) - store.dispatch(TabListAction.AddTabAction(tab0)).joinBlocking() - store.dispatch(TabListAction.AddTabAction(tab1)).joinBlocking() - store.dispatch(TabListAction.AddTabAction(tab2)).joinBlocking() - store.dispatch(TabListAction.AddTabAction(tab3)).joinBlocking() + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(tab0)) + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(tab1)) + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(tab2)) + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(tab3)) // tab0 <- tab1 <- tab2 <- tab3 - assertEquals(tab0.id, store.state.tabs[0].id) - assertEquals(tab1.id, store.state.tabs[1].id) - assertEquals(tab2.id, store.state.tabs[2].id) - assertEquals(tab3.id, store.state.tabs[3].id) + assertEquals(tab0.id, state.tabs[0].id) + assertEquals(tab1.id, state.tabs[1].id) + assertEquals(tab2.id, state.tabs[2].id) + assertEquals(tab3.id, state.tabs[3].id) - assertNull(store.state.tabs[0].parentId) - assertEquals(tab0.id, store.state.tabs[1].parentId) - assertEquals(tab1.id, store.state.tabs[2].parentId) - assertEquals(tab2.id, store.state.tabs[3].parentId) + assertNull(state.tabs[0].parentId) + assertEquals(tab0.id, state.tabs[1].parentId) + assertEquals(tab1.id, state.tabs[2].parentId) + assertEquals(tab2.id, state.tabs[3].parentId) - store.dispatch(TabListAction.RemoveTabAction(tab2.id)).joinBlocking() + state = BrowserStateReducer.reduce(state, TabListAction.RemoveTabAction(tab2.id)) // tab0 <- tab1 <- tab3 - assertEquals(tab0.id, store.state.tabs[0].id) - assertEquals(tab1.id, store.state.tabs[1].id) - assertEquals(tab3.id, store.state.tabs[2].id) + assertEquals(tab0.id, state.tabs[0].id) + assertEquals(tab1.id, state.tabs[1].id) + assertEquals(tab3.id, state.tabs[2].id) - assertNull(store.state.tabs[0].parentId) - assertEquals(tab0.id, store.state.tabs[1].parentId) - assertEquals(tab1.id, store.state.tabs[2].parentId) + assertNull(state.tabs[0].parentId) + assertEquals(tab0.id, state.tabs[1].parentId) + assertEquals(tab1.id, state.tabs[2].parentId) - store.dispatch(TabListAction.RemoveTabAction(tab0.id)).joinBlocking() + state = BrowserStateReducer.reduce(state, TabListAction.RemoveTabAction(tab0.id)) // tab1 <- tab3 - assertEquals(tab1.id, store.state.tabs[0].id) - assertEquals(tab3.id, store.state.tabs[1].id) + assertEquals(tab1.id, state.tabs[0].id) + assertEquals(tab3.id, state.tabs[1].id) - assertNull(store.state.tabs[0].parentId) - assertEquals(tab1.id, store.state.tabs[1].parentId) + assertNull(state.tabs[0].parentId) + assertEquals(tab1.id, state.tabs[1].parentId) } @Test fun `RestoreAction - Adds restored tabs and updates selected tab`() { - val store = BrowserStore() + var state = BrowserState() - assertEquals(0, store.state.tabs.size) + assertEquals(0, state.tabs.size) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TabListAction.RestoreAction( tabs = listOf( RecoverableTab( engineSessionState = null, - state = TabState(id = "a", url = "https://www.mozilla.org", private = false), + state = TabState( + id = "a", + url = "https://www.mozilla.org", + private = false, + ), ), RecoverableTab( engineSessionState = null, @@ -578,31 +593,30 @@ class TabListActionTest { selectedTabId = "d", restoreLocation = TabListAction.RestoreAction.RestoreLocation.BEGINNING, ), - ).joinBlocking() - - assertEquals(4, store.state.tabs.size) - assertEquals("a", store.state.tabs[0].id) - assertEquals("b", store.state.tabs[1].id) - assertEquals("c", store.state.tabs[2].id) - assertEquals("d", store.state.tabs[3].id) - assertEquals("d", store.state.selectedTabId) + ) + + assertEquals(4, state.tabs.size) + assertEquals("a", state.tabs[0].id) + assertEquals("b", state.tabs[1].id) + assertEquals("c", state.tabs[2].id) + assertEquals("d", state.tabs[3].id) + assertEquals("d", state.selectedTabId) } @Test fun `RestoreAction - Adds restored tabs to the beginning of existing tabs without updating selection`() { - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab(id = "a", url = "https://www.mozilla.org", private = false), - createTab(id = "b", url = "https://www.firefox.com", private = true), - ), - selectedTabId = "a", + val initialState = BrowserState( + tabs = listOf( + createTab(id = "a", url = "https://www.mozilla.org", private = false), + createTab(id = "b", url = "https://www.firefox.com", private = true), ), + selectedTabId = "a", ) - assertEquals(2, store.state.tabs.size) + assertEquals(2, initialState.tabs.size) - store.dispatch( + val state = BrowserStateReducer.reduce( + initialState, TabListAction.RestoreAction( tabs = listOf( RecoverableTab( @@ -617,31 +631,30 @@ class TabListActionTest { selectedTabId = "d", restoreLocation = TabListAction.RestoreAction.RestoreLocation.BEGINNING, ), - ).joinBlocking() - - assertEquals(4, store.state.tabs.size) - assertEquals("c", store.state.tabs[0].id) - assertEquals("d", store.state.tabs[1].id) - assertEquals("a", store.state.tabs[2].id) - assertEquals("b", store.state.tabs[3].id) - assertEquals("a", store.state.selectedTabId) + ) + + assertEquals(4, state.tabs.size) + assertEquals("c", state.tabs[0].id) + assertEquals("d", state.tabs[1].id) + assertEquals("a", state.tabs[2].id) + assertEquals("b", state.tabs[3].id) + assertEquals("a", state.selectedTabId) } @Test fun `RestoreAction - Adds restored tabs to the end of existing tabs without updating selection`() { - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab(id = "a", url = "https://www.mozilla.org", private = false), - createTab(id = "b", url = "https://www.firefox.com", private = true), - ), - selectedTabId = "a", + val initialState = BrowserState( + tabs = listOf( + createTab(id = "a", url = "https://www.mozilla.org", private = false), + createTab(id = "b", url = "https://www.firefox.com", private = true), ), + selectedTabId = "a", ) - assertEquals(2, store.state.tabs.size) + assertEquals(2, initialState.tabs.size) - store.dispatch( + val state = BrowserStateReducer.reduce( + initialState, TabListAction.RestoreAction( tabs = listOf( RecoverableTab( @@ -656,30 +669,29 @@ class TabListActionTest { selectedTabId = "d", restoreLocation = TabListAction.RestoreAction.RestoreLocation.END, ), - ).joinBlocking() - - assertEquals(4, store.state.tabs.size) - assertEquals("a", store.state.tabs[0].id) - assertEquals("b", store.state.tabs[1].id) - assertEquals("c", store.state.tabs[2].id) - assertEquals("d", store.state.tabs[3].id) - assertEquals("a", store.state.selectedTabId) + ) + + assertEquals(4, state.tabs.size) + assertEquals("a", state.tabs[0].id) + assertEquals("b", state.tabs[1].id) + assertEquals("c", state.tabs[2].id) + assertEquals("d", state.tabs[3].id) + assertEquals("a", state.selectedTabId) } @Test fun `RestoreAction - Adds restored tabs to beginning of existing tabs with updating selection`() { - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab(id = "a", url = "https://www.mozilla.org", private = false), - createTab(id = "b", url = "https://www.firefox.com", private = true), - ), + val initialState = BrowserState( + tabs = listOf( + createTab(id = "a", url = "https://www.mozilla.org", private = false), + createTab(id = "b", url = "https://www.firefox.com", private = true), ), ) - assertEquals(2, store.state.tabs.size) + assertEquals(2, initialState.tabs.size) - store.dispatch( + val state = BrowserStateReducer.reduce( + initialState, TabListAction.RestoreAction( tabs = listOf( RecoverableTab( @@ -694,30 +706,29 @@ class TabListActionTest { selectedTabId = "d", restoreLocation = TabListAction.RestoreAction.RestoreLocation.BEGINNING, ), - ).joinBlocking() - - assertEquals(4, store.state.tabs.size) - assertEquals("c", store.state.tabs[0].id) - assertEquals("d", store.state.tabs[1].id) - assertEquals("a", store.state.tabs[2].id) - assertEquals("b", store.state.tabs[3].id) - assertEquals("d", store.state.selectedTabId) + ) + + assertEquals(4, state.tabs.size) + assertEquals("c", state.tabs[0].id) + assertEquals("d", state.tabs[1].id) + assertEquals("a", state.tabs[2].id) + assertEquals("b", state.tabs[3].id) + assertEquals("d", state.selectedTabId) } @Test fun `RestoreAction - Adds restored tabs to end of existing tabs with updating selection`() { - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab(id = "a", url = "https://www.mozilla.org", private = false), - createTab(id = "b", url = "https://www.firefox.com", private = true), - ), + val initialState = BrowserState( + tabs = listOf( + createTab(id = "a", url = "https://www.mozilla.org", private = false), + createTab(id = "b", url = "https://www.firefox.com", private = true), ), ) - assertEquals(2, store.state.tabs.size) + assertEquals(2, initialState.tabs.size) - store.dispatch( + val state = BrowserStateReducer.reduce( + initialState, TabListAction.RestoreAction( tabs = listOf( RecoverableTab( @@ -732,278 +743,309 @@ class TabListActionTest { selectedTabId = "d", restoreLocation = TabListAction.RestoreAction.RestoreLocation.END, ), - ).joinBlocking() - - assertEquals(4, store.state.tabs.size) - assertEquals("a", store.state.tabs[0].id) - assertEquals("b", store.state.tabs[1].id) - assertEquals("c", store.state.tabs[2].id) - assertEquals("d", store.state.tabs[3].id) - assertEquals("d", store.state.selectedTabId) + ) + + assertEquals(4, state.tabs.size) + assertEquals("a", state.tabs[0].id) + assertEquals("b", state.tabs[1].id) + assertEquals("c", state.tabs[2].id) + assertEquals("d", state.tabs[3].id) + assertEquals("d", state.selectedTabId) } @Test fun `RestoreAction - Does not update selection if none was provided`() { - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab(id = "a", url = "https://www.mozilla.org", private = false), - createTab(id = "b", url = "https://www.firefox.com", private = true), - ), + val initialState = BrowserState( + tabs = listOf( + createTab(id = "a", url = "https://www.mozilla.org", private = false), + createTab(id = "b", url = "https://www.firefox.com", private = true), ), ) - assertEquals(2, store.state.tabs.size) + assertEquals(2, initialState.tabs.size) - store.dispatch( + val state = BrowserStateReducer.reduce( + initialState, TabListAction.RestoreAction( tabs = listOf( - RecoverableTab(engineSessionState = null, state = TabState(id = "c", url = "https://www.example.org", private = true)), - RecoverableTab(engineSessionState = null, state = TabState(id = "d", url = "https://getpocket.com", private = false)), + RecoverableTab( + engineSessionState = null, + state = TabState(id = "c", url = "https://www.example.org", private = true), + ), + RecoverableTab( + engineSessionState = null, + state = TabState(id = "d", url = "https://getpocket.com", private = false), + ), ), selectedTabId = null, restoreLocation = TabListAction.RestoreAction.RestoreLocation.BEGINNING, ), - ).joinBlocking() - - assertEquals(4, store.state.tabs.size) - assertEquals("c", store.state.tabs[0].id) - assertEquals("d", store.state.tabs[1].id) - assertEquals("a", store.state.tabs[2].id) - assertEquals("b", store.state.tabs[3].id) - assertNull(store.state.selectedTabId) + ) + + assertEquals(4, state.tabs.size) + assertEquals("c", state.tabs[0].id) + assertEquals("d", state.tabs[1].id) + assertEquals("a", state.tabs[2].id) + assertEquals("b", state.tabs[3].id) + assertNull(state.selectedTabId) } @Test fun `RestoreAction - Add tab back to correct location (beginning)`() { - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab(id = "a", url = "https://www.mozilla.org"), - createTab(id = "b", url = "https://www.firefox.com"), - ), + val initialState = BrowserState( + tabs = listOf( + createTab(id = "a", url = "https://www.mozilla.org"), + createTab(id = "b", url = "https://www.firefox.com"), ), ) - assertEquals(2, store.state.tabs.size) + assertEquals(2, initialState.tabs.size) - store.dispatch( + val state = BrowserStateReducer.reduce( + initialState, TabListAction.RestoreAction( tabs = listOf( - RecoverableTab(engineSessionState = null, state = TabState(id = "c", url = "https://www.example.org", index = 0)), + RecoverableTab( + engineSessionState = null, + state = TabState(id = "c", url = "https://www.example.org", index = 0), + ), ), selectedTabId = null, restoreLocation = TabListAction.RestoreAction.RestoreLocation.AT_INDEX, ), - ).joinBlocking() + ) - assertEquals(3, store.state.tabs.size) - assertEquals("c", store.state.tabs[0].id) - assertEquals("a", store.state.tabs[1].id) - assertEquals("b", store.state.tabs[2].id) + assertEquals(3, state.tabs.size) + assertEquals("c", state.tabs[0].id) + assertEquals("a", state.tabs[1].id) + assertEquals("b", state.tabs[2].id) } @Test fun `RestoreAction - Add tab back to correct location (middle)`() { - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab(id = "a", url = "https://www.mozilla.org"), - createTab(id = "b", url = "https://www.firefox.com"), - ), + val initialState = BrowserState( + tabs = listOf( + createTab(id = "a", url = "https://www.mozilla.org"), + createTab(id = "b", url = "https://www.firefox.com"), ), ) - assertEquals(2, store.state.tabs.size) + assertEquals(2, initialState.tabs.size) - store.dispatch( + val state = BrowserStateReducer.reduce( + initialState, TabListAction.RestoreAction( tabs = listOf( - RecoverableTab(engineSessionState = null, state = TabState(id = "c", url = "https://www.example.org", index = 1)), + RecoverableTab( + engineSessionState = null, + state = TabState(id = "c", url = "https://www.example.org", index = 1), + ), ), selectedTabId = null, restoreLocation = TabListAction.RestoreAction.RestoreLocation.AT_INDEX, ), - ).joinBlocking() + ) - assertEquals(3, store.state.tabs.size) - assertEquals("a", store.state.tabs[0].id) - assertEquals("c", store.state.tabs[1].id) - assertEquals("b", store.state.tabs[2].id) + assertEquals(3, state.tabs.size) + assertEquals("a", state.tabs[0].id) + assertEquals("c", state.tabs[1].id) + assertEquals("b", state.tabs[2].id) } @Test fun `RestoreAction - Add tab back to correct location (end)`() { - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab(id = "a", url = "https://www.mozilla.org"), - createTab(id = "b", url = "https://www.firefox.com"), - ), + val initialState = BrowserState( + tabs = listOf( + createTab(id = "a", url = "https://www.mozilla.org"), + createTab(id = "b", url = "https://www.firefox.com"), ), ) - assertEquals(2, store.state.tabs.size) + assertEquals(2, initialState.tabs.size) - store.dispatch( + val state = BrowserStateReducer.reduce( + initialState, TabListAction.RestoreAction( tabs = listOf( - RecoverableTab(engineSessionState = null, state = TabState(id = "c", url = "https://www.example.org", index = 2)), + RecoverableTab( + engineSessionState = null, + state = TabState(id = "c", url = "https://www.example.org", index = 2), + ), ), selectedTabId = null, restoreLocation = TabListAction.RestoreAction.RestoreLocation.AT_INDEX, ), - ).joinBlocking() + ) - assertEquals(3, store.state.tabs.size) - assertEquals("a", store.state.tabs[0].id) - assertEquals("b", store.state.tabs[1].id) - assertEquals("c", store.state.tabs[2].id) + assertEquals(3, state.tabs.size) + assertEquals("a", state.tabs[0].id) + assertEquals("b", state.tabs[1].id) + assertEquals("c", state.tabs[2].id) } @Test fun `RestoreAction - Add tab back to correct location with index beyond size of total tabs`() { - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab(id = "a", url = "https://www.mozilla.org"), - createTab(id = "b", url = "https://www.firefox.com"), - ), + val initialState = BrowserState( + tabs = listOf( + createTab(id = "a", url = "https://www.mozilla.org"), + createTab(id = "b", url = "https://www.firefox.com"), ), ) - assertEquals(2, store.state.tabs.size) + assertEquals(2, initialState.tabs.size) - store.dispatch( + val state = BrowserStateReducer.reduce( + initialState, TabListAction.RestoreAction( tabs = listOf( - RecoverableTab(engineSessionState = null, state = TabState(id = "c", url = "https://www.example.org", index = 4)), + RecoverableTab( + engineSessionState = null, + state = TabState(id = "c", url = "https://www.example.org", index = 4), + ), ), selectedTabId = null, restoreLocation = TabListAction.RestoreAction.RestoreLocation.AT_INDEX, ), - ).joinBlocking() + ) - assertEquals(3, store.state.tabs.size) - assertEquals("a", store.state.tabs[0].id) - assertEquals("b", store.state.tabs[1].id) - assertEquals("c", store.state.tabs[2].id) + assertEquals(3, state.tabs.size) + assertEquals("a", state.tabs[0].id) + assertEquals("b", state.tabs[1].id) + assertEquals("c", state.tabs[2].id) } @Test fun `RestoreAction - Add tabs back to correct locations`() { - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab(id = "a", url = "https://www.mozilla.org"), - createTab(id = "b", url = "https://www.firefox.com"), - ), + val initialState = BrowserState( + tabs = listOf( + createTab(id = "a", url = "https://www.mozilla.org"), + createTab(id = "b", url = "https://www.firefox.com"), ), ) - assertEquals(2, store.state.tabs.size) + assertEquals(2, initialState.tabs.size) - store.dispatch( + val state = BrowserStateReducer.reduce( + initialState, TabListAction.RestoreAction( tabs = listOf( - RecoverableTab(engineSessionState = null, state = TabState(id = "c", url = "https://www.example.org", index = 3)), - RecoverableTab(engineSessionState = null, state = TabState(id = "d", url = "https://www.example.org", index = 0)), + RecoverableTab( + engineSessionState = null, + state = TabState(id = "c", url = "https://www.example.org", index = 3), + ), + RecoverableTab( + engineSessionState = null, + state = TabState(id = "d", url = "https://www.example.org", index = 0), + ), ), selectedTabId = null, restoreLocation = TabListAction.RestoreAction.RestoreLocation.AT_INDEX, ), - ).joinBlocking() + ) - assertEquals(4, store.state.tabs.size) - assertEquals("d", store.state.tabs[0].id) - assertEquals("a", store.state.tabs[1].id) - assertEquals("b", store.state.tabs[2].id) - assertEquals("c", store.state.tabs[3].id) + assertEquals(4, state.tabs.size) + assertEquals("d", state.tabs[0].id) + assertEquals("a", state.tabs[1].id) + assertEquals("b", state.tabs[2].id) + assertEquals("c", state.tabs[3].id) } @Test fun `RestoreAction - Add tabs with matching indices back to correct locations`() { - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab(id = "a", url = "https://www.mozilla.org"), - createTab(id = "b", url = "https://www.firefox.com"), - ), + val initialState = BrowserState( + tabs = listOf( + createTab(id = "a", url = "https://www.mozilla.org"), + createTab(id = "b", url = "https://www.firefox.com"), ), ) - assertEquals(2, store.state.tabs.size) + assertEquals(2, initialState.tabs.size) - store.dispatch( + val state = BrowserStateReducer.reduce( + initialState, TabListAction.RestoreAction( tabs = listOf( - RecoverableTab(engineSessionState = null, state = TabState(id = "c", url = "https://www.example.org", index = 0)), - RecoverableTab(engineSessionState = null, state = TabState(id = "d", url = "https://www.example.org", index = 0)), + RecoverableTab( + engineSessionState = null, + state = TabState(id = "c", url = "https://www.example.org", index = 0), + ), + RecoverableTab( + engineSessionState = null, + state = TabState(id = "d", url = "https://www.example.org", index = 0), + ), ), selectedTabId = null, restoreLocation = TabListAction.RestoreAction.RestoreLocation.AT_INDEX, ), - ).joinBlocking() + ) - assertEquals(4, store.state.tabs.size) - assertEquals("d", store.state.tabs[0].id) - assertEquals("c", store.state.tabs[1].id) - assertEquals("a", store.state.tabs[2].id) - assertEquals("b", store.state.tabs[3].id) + assertEquals(4, state.tabs.size) + assertEquals("d", state.tabs[0].id) + assertEquals("c", state.tabs[1].id) + assertEquals("a", state.tabs[2].id) + assertEquals("b", state.tabs[3].id) } @Test fun `RestoreAction - Add tabs with a -1 removal index`() { - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab(id = "a", url = "https://www.mozilla.org"), - createTab(id = "b", url = "https://www.firefox.com"), - ), + val initialState = BrowserState( + tabs = listOf( + createTab(id = "a", url = "https://www.mozilla.org"), + createTab(id = "b", url = "https://www.firefox.com"), ), ) - assertEquals(2, store.state.tabs.size) + assertEquals(2, initialState.tabs.size) - store.dispatch( + val state = BrowserStateReducer.reduce( + initialState, TabListAction.RestoreAction( tabs = listOf( - RecoverableTab(engineSessionState = null, state = TabState(id = "c", url = "https://www.example.org", index = -1)), - RecoverableTab(engineSessionState = null, state = TabState(id = "d", url = "https://www.example.org")), + RecoverableTab( + engineSessionState = null, + state = TabState(id = "c", url = "https://www.example.org", index = -1), + ), + RecoverableTab( + engineSessionState = null, + state = TabState(id = "d", url = "https://www.example.org"), + ), ), selectedTabId = null, restoreLocation = TabListAction.RestoreAction.RestoreLocation.AT_INDEX, ), - ).joinBlocking() + ) - assertEquals(4, store.state.tabs.size) - assertEquals("a", store.state.tabs[0].id) - assertEquals("b", store.state.tabs[1].id) - assertEquals("c", store.state.tabs[2].id) - assertEquals("d", store.state.tabs[3].id) + assertEquals(4, state.tabs.size) + assertEquals("a", state.tabs[0].id) + assertEquals("b", state.tabs[1].id) + assertEquals("c", state.tabs[2].id) + assertEquals("d", state.tabs[3].id) } @Test fun `RemoveAllTabsAction - Removes both private and non-private tabs (but not custom tabs)`() { - val state = BrowserState( + var state = BrowserState( tabs = listOf( createTab(id = "a", url = "https://www.mozilla.org", private = false), createTab(id = "b", url = "https://www.firefox.com", private = true), ), customTabs = listOf( createCustomTab(id = "a1", url = "https://www.firefox.com"), - createCustomTab(id = "a2", url = "https://www.firefox.com/hello", source = SessionState.Source.External.CustomTab(mock())), + createCustomTab( + id = "a2", + url = "https://www.firefox.com/hello", + source = SessionState.Source.External.CustomTab(mock()), + ), ), selectedTabId = "a", ) - val store = BrowserStore(state) - store.dispatch(TabListAction.RemoveAllTabsAction()).joinBlocking() + state = BrowserStateReducer.reduce(state, TabListAction.RemoveAllTabsAction()) - assertTrue(store.state.tabs.isEmpty()) - assertNull(store.state.selectedTabId) - assertEquals(2, store.state.customTabs.size) - assertEquals("a2", store.state.customTabs.last().id) + assertTrue(state.tabs.isEmpty()) + assertNull(state.selectedTabId) + assertEquals(2, state.customTabs.size) + assertEquals("a2", state.customTabs.last().id) } @Test @@ -1011,23 +1053,25 @@ class TabListActionTest { val tabGroup = TabGroup("test1", tabIds = listOf("a", "b")) val tabPartition = TabPartition("testPartition", tabGroups = listOf(tabGroup)) - val state = BrowserState( + var state = BrowserState( tabs = listOf( createTab(id = "a", url = "https://www.mozilla.org"), createTab(id = "b", url = "https://www.firefox.com", private = true), ), tabPartitions = mapOf(tabPartition.id to tabPartition), ) - val store = BrowserStore(state) - store.dispatch(TabListAction.RemoveAllTabsAction()).joinBlocking() - assertEquals(0, store.state.tabs.size) - assertEquals(0, store.state.tabPartitions[tabPartition.id]?.getGroupById(tabGroup.id)?.tabIds?.size) + state = BrowserStateReducer.reduce(state, TabListAction.RemoveAllTabsAction()) + assertEquals(0, state.tabs.size) + assertEquals( + 0, + state.tabPartitions[tabPartition.id]?.getGroupById(tabGroup.id)?.tabIds?.size, + ) } @Test fun `RemoveAllPrivateTabsAction - Removes only private tabs`() { - val state = BrowserState( + var state = BrowserState( tabs = listOf( createTab(id = "a", url = "https://www.mozilla.org", private = false), createTab(id = "b", url = "https://www.firefox.com", private = true), @@ -1038,20 +1082,19 @@ class TabListActionTest { selectedTabId = "a", ) - val store = BrowserStore(state) - store.dispatch(TabListAction.RemoveAllPrivateTabsAction).joinBlocking() + state = BrowserStateReducer.reduce(state, TabListAction.RemoveAllPrivateTabsAction) - assertEquals(1, store.state.tabs.size) - assertEquals("a", store.state.tabs[0].id) - assertEquals("a", store.state.selectedTabId) + assertEquals(1, state.tabs.size) + assertEquals("a", state.tabs[0].id) + assertEquals("a", state.selectedTabId) - assertEquals(1, store.state.customTabs.size) - assertEquals("a1", store.state.customTabs.last().id) + assertEquals(1, state.customTabs.size) + assertEquals("a1", state.customTabs.last().id) } @Test fun `RemoveAllPrivateTabsAction - Updates selection if affected`() { - val state = BrowserState( + var state = BrowserState( tabs = listOf( createTab(id = "a", url = "https://www.mozilla.org", private = false), createTab(id = "b", url = "https://www.firefox.com", private = true), @@ -1062,41 +1105,46 @@ class TabListActionTest { selectedTabId = "b", ) - val store = BrowserStore(state) - store.dispatch(TabListAction.RemoveAllPrivateTabsAction).joinBlocking() + state = BrowserStateReducer.reduce(state, TabListAction.RemoveAllPrivateTabsAction) - assertEquals(1, store.state.tabs.size) - assertEquals("a", store.state.tabs[0].id) - assertEquals(null, store.state.selectedTabId) + assertEquals(1, state.tabs.size) + assertEquals("a", state.tabs[0].id) + assertEquals(null, state.selectedTabId) - assertEquals(1, store.state.customTabs.size) - assertEquals("a1", store.state.customTabs.last().id) + assertEquals(1, state.customTabs.size) + assertEquals("a1", state.customTabs.last().id) } @Test fun `RemoveAllPrivateTabsAction - Removes tabs from partition`() { val normalTabGroup = TabGroup("test1", tabIds = listOf("a")) val privateTabGroup = TabGroup("test2", tabIds = listOf("b")) - val tabPartition = TabPartition("testPartition", tabGroups = listOf(normalTabGroup, privateTabGroup)) + val tabPartition = + TabPartition("testPartition", tabGroups = listOf(normalTabGroup, privateTabGroup)) - val state = BrowserState( + var state = BrowserState( tabs = listOf( createTab(id = "a", url = "https://www.mozilla.org"), createTab(id = "b", url = "https://www.firefox.com", private = true), ), tabPartitions = mapOf(tabPartition.id to tabPartition), ) - val store = BrowserStore(state) - store.dispatch(TabListAction.RemoveAllPrivateTabsAction).joinBlocking() - assertEquals(1, store.state.tabs.size) - assertEquals(1, store.state.tabPartitions[tabPartition.id]?.getGroupById(normalTabGroup.id)?.tabIds?.size) - assertEquals(0, store.state.tabPartitions[tabPartition.id]?.getGroupById(privateTabGroup.id)?.tabIds?.size) + state = BrowserStateReducer.reduce(state, TabListAction.RemoveAllPrivateTabsAction) + assertEquals(1, state.tabs.size) + assertEquals( + 1, + state.tabPartitions[tabPartition.id]?.getGroupById(normalTabGroup.id)?.tabIds?.size, + ) + assertEquals( + 0, + state.tabPartitions[tabPartition.id]?.getGroupById(privateTabGroup.id)?.tabIds?.size, + ) } @Test fun `RemoveAllNormalTabsAction - Removes only normal (non-private) tabs`() { - val state = BrowserState( + var state = BrowserState( tabs = listOf( createTab(id = "a", url = "https://www.mozilla.org", private = false), createTab(id = "b", url = "https://www.firefox.com", private = true), @@ -1107,20 +1155,19 @@ class TabListActionTest { selectedTabId = "b", ) - val store = BrowserStore(state) - store.dispatch(TabListAction.RemoveAllNormalTabsAction).joinBlocking() + state = BrowserStateReducer.reduce(state, TabListAction.RemoveAllNormalTabsAction) - assertEquals(1, store.state.tabs.size) - assertEquals("b", store.state.tabs[0].id) - assertEquals("b", store.state.selectedTabId) + assertEquals(1, state.tabs.size) + assertEquals("b", state.tabs[0].id) + assertEquals("b", state.selectedTabId) - assertEquals(1, store.state.customTabs.size) - assertEquals("a1", store.state.customTabs.last().id) + assertEquals(1, state.customTabs.size) + assertEquals("a1", state.customTabs.last().id) } @Test fun `RemoveAllNormalTabsAction - Updates selection if affected`() { - val state = BrowserState( + var state = BrowserState( tabs = listOf( createTab(id = "a", url = "https://www.mozilla.org", private = false), createTab(id = "b", url = "https://www.firefox.com", private = true), @@ -1131,98 +1178,104 @@ class TabListActionTest { selectedTabId = "a", ) - val store = BrowserStore(state) - store.dispatch(TabListAction.RemoveAllNormalTabsAction).joinBlocking() + state = BrowserStateReducer.reduce(state, TabListAction.RemoveAllNormalTabsAction) - assertEquals(1, store.state.tabs.size) - assertEquals("b", store.state.tabs[0].id) + assertEquals(1, state.tabs.size) + assertEquals("b", state.tabs[0].id) // After removing the last normal tab NO private tab should get selected - assertNull(store.state.selectedTabId) + assertNull(state.selectedTabId) - assertEquals(1, store.state.customTabs.size) - assertEquals("a1", store.state.customTabs.last().id) + assertEquals(1, state.customTabs.size) + assertEquals("a1", state.customTabs.last().id) } @Test fun `RemoveAllNormalTabsAction - Removes tabs from partition`() { val normalTabGroup = TabGroup("test1", tabIds = listOf("a")) val privateTabGroup = TabGroup("test2", tabIds = listOf("b")) - val tabPartition = TabPartition("testPartition", tabGroups = listOf(normalTabGroup, privateTabGroup)) + val tabPartition = + TabPartition("testPartition", tabGroups = listOf(normalTabGroup, privateTabGroup)) - val state = BrowserState( + var state = BrowserState( tabs = listOf( createTab(id = "a", url = "https://www.mozilla.org"), createTab(id = "b", url = "https://www.firefox.com", private = true), ), tabPartitions = mapOf(tabPartition.id to tabPartition), ) - val store = BrowserStore(state) - store.dispatch(TabListAction.RemoveAllNormalTabsAction).joinBlocking() - assertEquals(1, store.state.tabs.size) - assertEquals(0, store.state.tabPartitions[tabPartition.id]?.getGroupById(normalTabGroup.id)?.tabIds?.size) - assertEquals(1, store.state.tabPartitions[tabPartition.id]?.getGroupById(privateTabGroup.id)?.tabIds?.size) + state = BrowserStateReducer.reduce(state, TabListAction.RemoveAllNormalTabsAction) + assertEquals(1, state.tabs.size) + assertEquals( + 0, + state.tabPartitions[tabPartition.id]?.getGroupById(normalTabGroup.id)?.tabIds?.size, + ) + assertEquals( + 1, + state.tabPartitions[tabPartition.id]?.getGroupById(privateTabGroup.id)?.tabIds?.size, + ) } @Test fun `AddMultipleTabsAction - Adds multiple tabs and updates selection`() { - val store = BrowserStore() + var state = BrowserState() - assertEquals(0, store.state.tabs.size) - assertNull(store.state.selectedTabId) + assertEquals(0, state.tabs.size) + assertNull(state.selectedTabId) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TabListAction.AddMultipleTabsAction( tabs = listOf( createTab(id = "a", url = "https://www.mozilla.org", private = false), createTab(id = "b", url = "https://www.firefox.com", private = true), ), ), - ).joinBlocking() + ) - assertEquals(2, store.state.tabs.size) - assertEquals("https://www.mozilla.org", store.state.tabs[0].content.url) - assertEquals("https://www.firefox.com", store.state.tabs[1].content.url) - assertNotNull(store.state.selectedTabId) - assertEquals("a", store.state.selectedTabId) + assertEquals(2, state.tabs.size) + assertEquals("https://www.mozilla.org", state.tabs[0].content.url) + assertEquals("https://www.firefox.com", state.tabs[1].content.url) + assertNotNull(state.selectedTabId) + assertEquals("a", state.selectedTabId) } @Test fun `AddMultipleTabsAction - Adds multiple tabs and does not update selection if one exists already`() { - val store = BrowserStore( - BrowserState( - tabs = listOf(createTab(id = "z", url = "https://getpocket.com")), - selectedTabId = "z", - ), + val initialState = BrowserState( + tabs = listOf(createTab(id = "z", url = "https://getpocket.com")), + selectedTabId = "z", ) - assertEquals(1, store.state.tabs.size) - assertEquals("z", store.state.selectedTabId) + assertEquals(1, initialState.tabs.size) + assertEquals("z", initialState.selectedTabId) - store.dispatch( + val state = BrowserStateReducer.reduce( + initialState, TabListAction.AddMultipleTabsAction( tabs = listOf( createTab(id = "a", url = "https://www.mozilla.org", private = false), createTab(id = "b", url = "https://www.firefox.com", private = true), ), ), - ).joinBlocking() + ) - assertEquals(3, store.state.tabs.size) - assertEquals("https://getpocket.com", store.state.tabs[0].content.url) - assertEquals("https://www.mozilla.org", store.state.tabs[1].content.url) - assertEquals("https://www.firefox.com", store.state.tabs[2].content.url) - assertEquals("z", store.state.selectedTabId) + assertEquals(3, state.tabs.size) + assertEquals("https://getpocket.com", state.tabs[0].content.url) + assertEquals("https://www.mozilla.org", state.tabs[1].content.url) + assertEquals("https://www.firefox.com", state.tabs[2].content.url) + assertEquals("z", state.selectedTabId) } @Test fun `AddMultipleTabsAction - Non private tab will be selected`() { - val store = BrowserStore() + var state = BrowserState() - assertEquals(0, store.state.tabs.size) - assertNull(store.state.selectedTabId) + assertEquals(0, state.tabs.size) + assertNull(state.selectedTabId) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TabListAction.AddMultipleTabsAction( tabs = listOf( createTab(id = "a", url = "https://www.mozilla.org", private = true), @@ -1231,25 +1284,26 @@ class TabListActionTest { createTab(id = "d", url = "https://getpocket.com", private = true), ), ), - ).joinBlocking() - - assertEquals(4, store.state.tabs.size) - assertEquals("https://www.mozilla.org", store.state.tabs[0].content.url) - assertEquals("https://www.example.org", store.state.tabs[1].content.url) - assertEquals("https://www.firefox.com", store.state.tabs[2].content.url) - assertEquals("https://getpocket.com", store.state.tabs[3].content.url) - assertNotNull(store.state.selectedTabId) - assertEquals("c", store.state.selectedTabId) + ) + + assertEquals(4, state.tabs.size) + assertEquals("https://www.mozilla.org", state.tabs[0].content.url) + assertEquals("https://www.example.org", state.tabs[1].content.url) + assertEquals("https://www.firefox.com", state.tabs[2].content.url) + assertEquals("https://getpocket.com", state.tabs[3].content.url) + assertNotNull(state.selectedTabId) + assertEquals("c", state.selectedTabId) } @Test fun `AddMultipleTabsAction - No tab will be selected if only private tabs are added`() { - val store = BrowserStore() + var state = BrowserState() - assertEquals(0, store.state.tabs.size) - assertNull(store.state.selectedTabId) + assertEquals(0, state.tabs.size) + assertNull(state.selectedTabId) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TabListAction.AddMultipleTabsAction( tabs = listOf( createTab(id = "a", url = "https://www.mozilla.org", private = true), @@ -1257,131 +1311,133 @@ class TabListActionTest { createTab(id = "c", url = "https://getpocket.com", private = true), ), ), - ).joinBlocking() + ) - assertEquals(3, store.state.tabs.size) - assertEquals("https://www.mozilla.org", store.state.tabs[0].content.url) - assertEquals("https://www.example.org", store.state.tabs[1].content.url) - assertEquals("https://getpocket.com", store.state.tabs[2].content.url) - assertNull(store.state.selectedTabId) + assertEquals(3, state.tabs.size) + assertEquals("https://www.mozilla.org", state.tabs[0].content.url) + assertEquals("https://www.example.org", state.tabs[1].content.url) + assertEquals("https://getpocket.com", state.tabs[2].content.url) + assertNull(state.selectedTabId) } @Test fun `RemoveAllNormalTabsAction with private tab selected`() { - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab(id = "a", url = "https://www.mozilla.org", private = true), - createTab(id = "b", url = "https://www.example.org", private = false), - createTab(id = "c", url = "https://www.firefox.com", private = false), - createTab(id = "d", url = "https://getpocket.com", private = true), - ), - selectedTabId = "d", + val initialState = BrowserState( + tabs = listOf( + createTab(id = "a", url = "https://www.mozilla.org", private = true), + createTab(id = "b", url = "https://www.example.org", private = false), + createTab(id = "c", url = "https://www.firefox.com", private = false), + createTab(id = "d", url = "https://getpocket.com", private = true), ), + selectedTabId = "d", ) - store.dispatch(TabListAction.RemoveAllNormalTabsAction).joinBlocking() + val state = + BrowserStateReducer.reduce(initialState, TabListAction.RemoveAllNormalTabsAction) - assertEquals(0, store.state.normalTabs.size) - assertEquals(2, store.state.privateTabs.size) - assertEquals("d", store.state.selectedTabId) + assertEquals(0, state.normalTabs.size) + assertEquals(2, state.privateTabs.size) + assertEquals("d", state.selectedTabId) } @Test fun `RemoveAllNormalTabsAction with normal tab selected`() { - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab(id = "a", url = "https://www.mozilla.org", private = true), - createTab(id = "b", url = "https://www.example.org", private = false), - createTab(id = "c", url = "https://www.firefox.com", private = false), - createTab(id = "d", url = "https://getpocket.com", private = true), - ), - selectedTabId = "b", + val initialState = BrowserState( + tabs = listOf( + createTab(id = "a", url = "https://www.mozilla.org", private = true), + createTab(id = "b", url = "https://www.example.org", private = false), + createTab(id = "c", url = "https://www.firefox.com", private = false), + createTab(id = "d", url = "https://getpocket.com", private = true), ), + selectedTabId = "b", ) - store.dispatch(TabListAction.RemoveAllNormalTabsAction).joinBlocking() + val state = + BrowserStateReducer.reduce(initialState, TabListAction.RemoveAllNormalTabsAction) - assertEquals(0, store.state.normalTabs.size) - assertEquals(2, store.state.privateTabs.size) - assertNull(store.state.selectedTabId) + assertEquals(0, state.normalTabs.size) + assertEquals(2, state.privateTabs.size) + assertNull(state.selectedTabId) } @Test fun `RemoveAllPrivateTabsAction with private tab selected`() { - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab(id = "a", url = "https://www.mozilla.org", private = true), - createTab(id = "b", url = "https://www.example.org", private = false), - createTab(id = "c", url = "https://www.firefox.com", private = false), - createTab(id = "d", url = "https://getpocket.com", private = true), - ), - selectedTabId = "d", + val initialState = BrowserState( + tabs = listOf( + createTab(id = "a", url = "https://www.mozilla.org", private = true), + createTab(id = "b", url = "https://www.example.org", private = false), + createTab(id = "c", url = "https://www.firefox.com", private = false), + createTab(id = "d", url = "https://getpocket.com", private = true), ), + selectedTabId = "d", ) - store.dispatch(TabListAction.RemoveAllPrivateTabsAction).joinBlocking() + val state = + BrowserStateReducer.reduce(initialState, TabListAction.RemoveAllPrivateTabsAction) - assertEquals(2, store.state.normalTabs.size) - assertEquals(0, store.state.privateTabs.size) - assertEquals(null, store.state.selectedTabId) + assertEquals(2, state.normalTabs.size) + assertEquals(0, state.privateTabs.size) + assertEquals(null, state.selectedTabId) } @Test fun `RemoveAllPrivateTabsAction with private tab selected and no normal tabs`() { - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab(id = "a", url = "https://www.mozilla.org", private = true), - createTab(id = "b", url = "https://getpocket.com", private = true), - ), - selectedTabId = "b", + val initialState = BrowserState( + tabs = listOf( + createTab(id = "a", url = "https://www.mozilla.org", private = true), + createTab(id = "b", url = "https://getpocket.com", private = true), ), + selectedTabId = "b", ) - store.dispatch(TabListAction.RemoveAllPrivateTabsAction).joinBlocking() + val state = + BrowserStateReducer.reduce(initialState, TabListAction.RemoveAllPrivateTabsAction) - assertEquals(0, store.state.normalTabs.size) - assertEquals(0, store.state.privateTabs.size) - assertNull(store.state.selectedTabId) + assertEquals(0, state.normalTabs.size) + assertEquals(0, state.privateTabs.size) + assertNull(state.selectedTabId) } @Test fun `RemoveAllPrivateTabsAction with normal tab selected`() { - val store = BrowserStore( - BrowserState( - tabs = listOf( - createTab(id = "a", url = "https://www.mozilla.org", private = true), - createTab(id = "b", url = "https://www.example.org", private = false), - createTab(id = "c", url = "https://www.firefox.com", private = false), - createTab(id = "d", url = "https://getpocket.com", private = true), - ), - selectedTabId = "b", + val initialState = BrowserState( + tabs = listOf( + createTab(id = "a", url = "https://www.mozilla.org", private = true), + createTab(id = "b", url = "https://www.example.org", private = false), + createTab(id = "c", url = "https://www.firefox.com", private = false), + createTab(id = "d", url = "https://getpocket.com", private = true), ), + selectedTabId = "b", ) - store.dispatch(TabListAction.RemoveAllPrivateTabsAction).joinBlocking() + val state = + BrowserStateReducer.reduce(initialState, TabListAction.RemoveAllPrivateTabsAction) - assertEquals(2, store.state.normalTabs.size) - assertEquals(0, store.state.privateTabs.size) - assertEquals("b", store.state.selectedTabId) + assertEquals(2, state.normalTabs.size) + assertEquals(0, state.privateTabs.size) + assertEquals("b", state.selectedTabId) } - private fun assertSameTabs(a: BrowserStore, b: List<TabSessionState>, str: String? = null) { - val aMap = a.state.tabs.map { "<" + it.id + "," + it.content.url + ">\n" } + private fun assertSameTabs(a: BrowserState, b: List<TabSessionState>, str: String? = null) { + val aMap = a.tabs.map { "<" + it.id + "," + it.content.url + ">\n" } val bMap = b.map { "<" + it.id + "," + it.content.url + ">\n" } assertEquals(str, aMap.toString(), bMap.toString()) } - private fun dispatchJoinMoveAction(store: BrowserStore, tabIds: List<String>, targetTabId: String, placeAfter: Boolean) { - store.dispatch( + + private fun moveTabsAction( + state: BrowserState, + tabIds: List<String>, + targetTabId: String, + placeAfter: Boolean, + ): BrowserState { + return BrowserStateReducer.reduce( + state, TabListAction.MoveTabsAction( tabIds, targetTabId, placeAfter, ), - ).joinBlocking() + ) } @Test @@ -1392,35 +1448,33 @@ class TabListActionTest { createTab(id = "c", url = "https://getpocket.com"), createTab(id = "d", url = "https://www.example.org"), ) - val store = BrowserStore( - BrowserState( - tabs = tabList, - selectedTabId = "a", - ), + val initialState = BrowserState( + tabs = tabList, + selectedTabId = "a", ) - dispatchJoinMoveAction(store, listOf("a"), "a", false) - assertSameTabs(store, tabList, "a to a-") - dispatchJoinMoveAction(store, listOf("a"), "a", true) - assertSameTabs(store, tabList, "a to a+") - dispatchJoinMoveAction(store, listOf("a"), "b", false) - assertSameTabs(store, tabList, "a to b-") - - dispatchJoinMoveAction(store, listOf("a", "b"), "a", false) - assertSameTabs(store, tabList, "a,b to a-") - dispatchJoinMoveAction(store, listOf("a", "b"), "a", true) - assertSameTabs(store, tabList, "a,b to a+") - dispatchJoinMoveAction(store, listOf("a", "b"), "b", false) - assertSameTabs(store, tabList, "a,b to b-") - dispatchJoinMoveAction(store, listOf("a", "b"), "b", true) - assertSameTabs(store, tabList, "a,b to b+") - dispatchJoinMoveAction(store, listOf("a", "b"), "c", false) - assertSameTabs(store, tabList, "a,b to c-") - - dispatchJoinMoveAction(store, listOf("c", "d"), "c", false) - assertSameTabs(store, tabList, "c,d to c-") - dispatchJoinMoveAction(store, listOf("c", "d"), "d", true) - assertSameTabs(store, tabList, "c,d to d+") + var state: BrowserState = moveTabsAction(initialState, listOf("a"), "a", false) + assertSameTabs(state, tabList, "a to a-") + state = moveTabsAction(initialState, listOf("a"), "a", true) + assertSameTabs(state, tabList, "a to a+") + state = moveTabsAction(initialState, listOf("a"), "b", false) + assertSameTabs(state, tabList, "a to b-") + + state = moveTabsAction(initialState, listOf("a", "b"), "a", false) + assertSameTabs(state, tabList, "a,b to a-") + state = moveTabsAction(initialState, listOf("a", "b"), "a", true) + assertSameTabs(state, tabList, "a,b to a+") + state = moveTabsAction(initialState, listOf("a", "b"), "b", false) + assertSameTabs(state, tabList, "a,b to b-") + state = moveTabsAction(initialState, listOf("a", "b"), "b", true) + assertSameTabs(state, tabList, "a,b to b+") + state = moveTabsAction(initialState, listOf("a", "b"), "c", false) + assertSameTabs(state, tabList, "a,b to c-") + + state = moveTabsAction(initialState, listOf("c", "d"), "c", false) + assertSameTabs(state, tabList, "c,d to c-") + state = moveTabsAction(initialState, listOf("c", "d"), "d", true) + assertSameTabs(state, tabList, "c,d to d+") val movedTabList = listOf( createTab(id = "b", url = "https://www.firefox.com"), @@ -1428,17 +1482,17 @@ class TabListActionTest { createTab(id = "a", url = "https://www.mozilla.org"), createTab(id = "d", url = "https://www.example.org"), ) - dispatchJoinMoveAction(store, listOf("a"), "d", false) - assertSameTabs(store, movedTabList, "a to d-") - dispatchJoinMoveAction(store, listOf("b", "c"), "a", true) - assertSameTabs(store, tabList, "b,c to a+") + state = moveTabsAction(initialState, listOf("a"), "d", false) + assertSameTabs(state, movedTabList, "a to d-") + state = moveTabsAction(initialState, listOf("b", "c"), "a", true) + assertSameTabs(state, tabList, "b,c to a+") - dispatchJoinMoveAction(store, listOf("a", "d"), "c", true) - assertSameTabs(store, movedTabList, "a,d to c+") + state = moveTabsAction(initialState, listOf("a", "d"), "c", true) + assertSameTabs(state, movedTabList, "a,d to c+") - dispatchJoinMoveAction(store, listOf("b", "c"), "d", false) - assertSameTabs(store, tabList, "b,c to d-") - assertEquals("a", store.state.selectedTabId) + state = moveTabsAction(initialState, listOf("b", "c"), "d", false) + assertSameTabs(state, tabList, "b,c to d-") + assertEquals("a", state.selectedTabId) } @Test @@ -1451,14 +1505,14 @@ class TabListActionTest { createTab(id = "e", url = "https://www.mozilla.org/en-US/firefox/features/"), createTab(id = "f", url = "https://www.mozilla.org/en-US/firefox/products/"), ) - val store = BrowserStore( - BrowserState( - tabs = tabList, - selectedTabId = "a", - ), + val initialState = BrowserState( + tabs = tabList, + selectedTabId = "a", ) - dispatchJoinMoveAction(store, listOf("a", "b", "c", "d", "e", "f"), "a", false) - assertSameTabs(store, tabList, "all to a-") + + var state = + moveTabsAction(initialState, listOf("a", "b", "c", "d", "e", "f"), "a", false) + assertSameTabs(state, tabList, "all to a-") val movedTabList = listOf( createTab(id = "a", url = "https://www.mozilla.org"), @@ -1468,29 +1522,32 @@ class TabListActionTest { createTab(id = "d", url = "https://www.example.org"), createTab(id = "f", url = "https://www.mozilla.org/en-US/firefox/products/"), ) - dispatchJoinMoveAction(store, listOf("b", "e"), "d", false) - assertSameTabs(store, movedTabList, "b,e to d-") + state = moveTabsAction(initialState, listOf("b", "e"), "d", false) + assertSameTabs(state, movedTabList, "b,e to d-") - dispatchJoinMoveAction(store, listOf("c", "d"), "b", true) - assertSameTabs(store, tabList, "c,d to b+") + state = moveTabsAction(initialState, listOf("c", "d"), "b", true) + assertSameTabs(state, tabList, "c,d to b+") } @Test fun `WHEN an unselected child tab is closed THEN the tab that is selected remains selected`() { - val store = BrowserStore() + var state = BrowserState() val parent = createTab("https://www.mozilla.org") val child = createTab("https://www.mozilla.org/en-US/internet-health/", parent = parent) val nonChildTab = createTab("https://www.firefox.com") - store.dispatch(TabListAction.AddTabAction(parent)).joinBlocking() - store.dispatch(TabListAction.AddTabAction(nonChildTab)).joinBlocking() - store.dispatch(TabListAction.AddTabAction(child)).joinBlocking() + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(parent)) + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(nonChildTab)) + state = BrowserStateReducer.reduce(state, TabListAction.AddTabAction(child)) - store.dispatch(TabListAction.SelectTabAction(nonChildTab.id)).joinBlocking() - store.dispatch(TabListAction.RemoveTabAction(child.id, selectParentIfExists = true)).joinBlocking() + state = BrowserStateReducer.reduce(state, TabListAction.SelectTabAction(nonChildTab.id)) + state = BrowserStateReducer.reduce( + state, + TabListAction.RemoveTabAction(child.id, selectParentIfExists = true), + ) - assertEquals(nonChildTab.id, store.state.selectedTabId) - assertEquals(nonChildTab.content.url, store.state.selectedTab?.content?.url) + assertEquals(nonChildTab.id, state.selectedTabId) + assertEquals(nonChildTab.content.url, state.selectedTab?.content?.url) } } diff --git a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/TrackingProtectionActionTest.kt b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/TrackingProtectionActionTest.kt @@ -4,12 +4,11 @@ package mozilla.components.browser.state.action +import mozilla.components.browser.state.reducer.BrowserStateReducer import mozilla.components.browser.state.selector.findTab import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.state.TabSessionState import mozilla.components.browser.state.state.createTab -import mozilla.components.browser.state.store.BrowserStore -import mozilla.components.support.test.ext.joinBlocking import mozilla.components.support.test.mock import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse @@ -19,43 +18,49 @@ import org.junit.Test class TrackingProtectionActionTest { private lateinit var tab: TabSessionState - private lateinit var store: BrowserStore + private lateinit var state: BrowserState @Before fun setUp() { tab = createTab("https://www.mozilla.org") - store = BrowserStore( - initialState = BrowserState( - tabs = listOf(tab), - ), + state = BrowserState( + tabs = listOf(tab), ) } - private fun tabState(): TabSessionState = store.state.findTab(tab.id)!! + private fun tabState(): TabSessionState = state.findTab(tab.id)!! private fun trackingProtectionState() = tabState().trackingProtection @Test fun `ToggleAction - Updates enabled flag of TrackingProtectionState`() { assertFalse(trackingProtectionState().enabled) - store.dispatch(TrackingProtectionAction.ToggleAction(tabId = tab.id, enabled = true)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TrackingProtectionAction.ToggleAction(tabId = tab.id, enabled = true), + ) assertTrue(trackingProtectionState().enabled) - store.dispatch(TrackingProtectionAction.ToggleAction(tabId = tab.id, enabled = true)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TrackingProtectionAction.ToggleAction(tabId = tab.id, enabled = true), + ) assertTrue(trackingProtectionState().enabled) - store.dispatch(TrackingProtectionAction.ToggleAction(tabId = tab.id, enabled = false)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TrackingProtectionAction.ToggleAction(tabId = tab.id, enabled = false), + ) assertFalse(trackingProtectionState().enabled) - store.dispatch(TrackingProtectionAction.ToggleAction(tabId = tab.id, enabled = true)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TrackingProtectionAction.ToggleAction(tabId = tab.id, enabled = true), + ) assertTrue(trackingProtectionState().enabled) } @@ -64,39 +69,43 @@ class TrackingProtectionActionTest { fun `ToggleExclusionListAction - Updates enabled flag of TrackingProtectionState`() { assertFalse(trackingProtectionState().ignoredOnTrackingProtection) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TrackingProtectionAction.ToggleExclusionListAction( tabId = tab.id, excluded = true, ), - ).joinBlocking() + ) assertTrue(trackingProtectionState().ignoredOnTrackingProtection) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TrackingProtectionAction.ToggleExclusionListAction( tabId = tab.id, excluded = true, ), - ).joinBlocking() + ) assertTrue(trackingProtectionState().ignoredOnTrackingProtection) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TrackingProtectionAction.ToggleExclusionListAction( tabId = tab.id, excluded = false, ), - ).joinBlocking() + ) assertFalse(trackingProtectionState().ignoredOnTrackingProtection) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TrackingProtectionAction.ToggleExclusionListAction( tabId = tab.id, excluded = true, ), - ).joinBlocking() + ) assertTrue(trackingProtectionState().ignoredOnTrackingProtection) } @@ -106,17 +115,23 @@ class TrackingProtectionActionTest { assertTrue(trackingProtectionState().blockedTrackers.isEmpty()) assertTrue(trackingProtectionState().loadedTrackers.isEmpty()) - store.dispatch(TrackingProtectionAction.TrackerBlockedAction(tabId = tab.id, tracker = mock())) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TrackingProtectionAction.TrackerBlockedAction(tabId = tab.id, tracker = mock()), + ) assertEquals(1, trackingProtectionState().blockedTrackers.size) assertEquals(0, trackingProtectionState().loadedTrackers.size) - store.dispatch(TrackingProtectionAction.TrackerBlockedAction(tabId = tab.id, tracker = mock())) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TrackingProtectionAction.TrackerBlockedAction(tabId = tab.id, tracker = mock()), + ) - store.dispatch(TrackingProtectionAction.TrackerBlockedAction(tabId = tab.id, tracker = mock())) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TrackingProtectionAction.TrackerBlockedAction(tabId = tab.id, tracker = mock()), + ) assertEquals(3, trackingProtectionState().blockedTrackers.size) assertEquals(0, trackingProtectionState().loadedTrackers.size) @@ -127,17 +142,23 @@ class TrackingProtectionActionTest { assertTrue(trackingProtectionState().blockedTrackers.isEmpty()) assertTrue(trackingProtectionState().loadedTrackers.isEmpty()) - store.dispatch(TrackingProtectionAction.TrackerLoadedAction(tabId = tab.id, tracker = mock())) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TrackingProtectionAction.TrackerLoadedAction(tabId = tab.id, tracker = mock()), + ) assertEquals(0, trackingProtectionState().blockedTrackers.size) assertEquals(1, trackingProtectionState().loadedTrackers.size) - store.dispatch(TrackingProtectionAction.TrackerLoadedAction(tabId = tab.id, tracker = mock())) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TrackingProtectionAction.TrackerLoadedAction(tabId = tab.id, tracker = mock()), + ) - store.dispatch(TrackingProtectionAction.TrackerLoadedAction(tabId = tab.id, tracker = mock())) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TrackingProtectionAction.TrackerLoadedAction(tabId = tab.id, tracker = mock()), + ) assertEquals(0, trackingProtectionState().blockedTrackers.size) assertEquals(3, trackingProtectionState().loadedTrackers.size) @@ -145,25 +166,37 @@ class TrackingProtectionActionTest { @Test fun `ClearTrackers - Removes trackers from TrackingProtectionState`() { - store.dispatch(TrackingProtectionAction.TrackerBlockedAction(tabId = tab.id, tracker = mock())) - .joinBlocking() - - store.dispatch(TrackingProtectionAction.TrackerBlockedAction(tabId = tab.id, tracker = mock())) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TrackingProtectionAction.TrackerBlockedAction(tabId = tab.id, tracker = mock()), + ) + state = BrowserStateReducer.reduce( + state, + TrackingProtectionAction.TrackerBlockedAction(tabId = tab.id, tracker = mock()), + ) - store.dispatch(TrackingProtectionAction.TrackerLoadedAction(tabId = tab.id, tracker = mock())) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TrackingProtectionAction.TrackerLoadedAction(tabId = tab.id, tracker = mock()), + ) - store.dispatch(TrackingProtectionAction.TrackerLoadedAction(tabId = tab.id, tracker = mock())) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TrackingProtectionAction.TrackerLoadedAction(tabId = tab.id, tracker = mock()), + ) - store.dispatch(TrackingProtectionAction.TrackerLoadedAction(tabId = tab.id, tracker = mock())) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TrackingProtectionAction.TrackerLoadedAction(tabId = tab.id, tracker = mock()), + ) assertEquals(2, trackingProtectionState().blockedTrackers.size) assertEquals(3, trackingProtectionState().loadedTrackers.size) - store.dispatch(TrackingProtectionAction.ClearTrackersAction(tab.id)).joinBlocking() + state = BrowserStateReducer.reduce( + state, + TrackingProtectionAction.ClearTrackersAction(tab.id), + ) assertEquals(0, trackingProtectionState().blockedTrackers.size) assertEquals(0, trackingProtectionState().loadedTrackers.size) diff --git a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/TranslationsActionTest.kt b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/TranslationsActionTest.kt @@ -4,11 +4,11 @@ package mozilla.components.browser.state.action +import mozilla.components.browser.state.reducer.BrowserStateReducer import mozilla.components.browser.state.selector.findTab import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.state.TabSessionState import mozilla.components.browser.state.state.createTab -import mozilla.components.browser.state.store.BrowserStore import mozilla.components.concept.engine.translate.DetectedLanguages import mozilla.components.concept.engine.translate.Language import mozilla.components.concept.engine.translate.LanguageModel @@ -25,7 +25,6 @@ import mozilla.components.concept.engine.translate.TranslationPageSettingOperati import mozilla.components.concept.engine.translate.TranslationPageSettings import mozilla.components.concept.engine.translate.TranslationPair import mozilla.components.concept.engine.translate.TranslationSupport -import mozilla.components.support.test.ext.joinBlocking import mozilla.components.support.test.mock import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse @@ -34,31 +33,30 @@ import org.junit.Assert.assertNull import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test -import java.lang.Exception class TranslationsActionTest { private lateinit var tab: TabSessionState - private lateinit var store: BrowserStore + private lateinit var state: BrowserState @Before fun setUp() { tab = createTab("https://www.mozilla.org") - store = BrowserStore( - initialState = BrowserState( - tabs = listOf(tab), - ), + state = BrowserState( + tabs = listOf(tab), ) } - private fun tabState(): TabSessionState = store.state.findTab(tab.id)!! + private fun tabState(): TabSessionState = state.findTab(tab.id)!! @Test fun `WHEN a TranslateExpectedAction is dispatched THEN update translation expected status`() { assertEquals(false, tabState().translationsState.isExpectedTranslate) - store.dispatch(TranslationsAction.TranslateExpectedAction(tabId = tab.id)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TranslationsAction.TranslateExpectedAction(tabId = tab.id), + ) assertEquals(true, tabState().translationsState.isExpectedTranslate) } @@ -67,13 +65,17 @@ class TranslationsActionTest { fun `WHEN a TranslateOfferAction is dispatched THEN update translation expected status`() { assertEquals(false, tabState().translationsState.isOfferTranslate) - store.dispatch(TranslationsAction.TranslateOfferAction(tabId = tab.id, isOfferTranslate = true)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TranslationsAction.TranslateOfferAction(tabId = tab.id, isOfferTranslate = true), + ) assertEquals(true, tabState().translationsState.isOfferTranslate) - store.dispatch(TranslationsAction.TranslateOfferAction(tabId = tab.id, isOfferTranslate = false)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TranslationsAction.TranslateOfferAction(tabId = tab.id, isOfferTranslate = false), + ) assertFalse(tabState().translationsState.isOfferTranslate) } @@ -82,8 +84,10 @@ class TranslationsActionTest { fun `WHEN a TranslateStateChangeAction is dispatched THEN update translation expected status`() { assertEquals(null, tabState().translationsState.translationEngineState) - store.dispatch(TranslationsAction.TranslateStateChangeAction(tabId = tab.id, mock())) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TranslationsAction.TranslateStateChangeAction(tabId = tab.id, mock()), + ) assertEquals(true, tabState().translationsState.translationEngineState != null) } @@ -96,20 +100,32 @@ class TranslationsActionTest { assertFalse(tabState().translationsState.isTranslateProcessing) // Set an initial state for is translate processing via a translation request: - store.dispatch(TranslationsAction.TranslateAction(tabId = tab.id, "en", "es", null)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TranslationsAction.TranslateAction(tabId = tab.id, "en", "es", null), + ) + assertTrue(tabState().translationsState.isTranslateProcessing) val translatedEngineState = TranslationEngineState( - detectedLanguages = DetectedLanguages(documentLangTag = "es", supportedDocumentLang = true, userPreferredLangTag = "en"), + detectedLanguages = DetectedLanguages( + documentLangTag = "es", + supportedDocumentLang = true, + userPreferredLangTag = "en", + ), error = null, isEngineReady = true, requestedTranslationPair = TranslationPair(fromLanguage = "es", toLanguage = "en"), hasVisibleChange = true, ) - store.dispatch(TranslationsAction.TranslateStateChangeAction(tabId = tab.id, translationEngineState = translatedEngineState)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TranslationsAction.TranslateStateChangeAction( + tabId = tab.id, + translationEngineState = translatedEngineState, + ), + ) // Translated state assertEquals(translatedEngineState, tabState().translationsState.translationEngineState) @@ -118,15 +134,21 @@ class TranslationsActionTest { assertFalse(tabState().translationsState.isTranslateProcessing) val nonTranslatedEngineState = TranslationEngineState( - detectedLanguages = DetectedLanguages(documentLangTag = "es", supportedDocumentLang = true, userPreferredLangTag = "en"), + detectedLanguages = DetectedLanguages( + documentLangTag = "es", + supportedDocumentLang = true, + userPreferredLangTag = "en", + ), error = null, isEngineReady = true, requestedTranslationPair = TranslationPair(fromLanguage = null, toLanguage = null), hasVisibleChange = false, ) - store.dispatch(TranslationsAction.TranslateStateChangeAction(tabId = tab.id, nonTranslatedEngineState)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TranslationsAction.TranslateStateChangeAction(tabId = tab.id, nonTranslatedEngineState), + ) // Non-translated state assertEquals(nonTranslatedEngineState, tabState().translationsState.translationEngineState) @@ -140,11 +162,22 @@ class TranslationsActionTest { assertFalse(tabState().translationsState.isOfferTranslate) // Initial Offer State - store.dispatch(TranslationsAction.TranslateOfferAction(tabId = tab.id, true)).joinBlocking() + state = BrowserStateReducer.reduce( + state, + TranslationsAction.TranslateOfferAction(tabId = tab.id, true), + ) assertTrue(tabState().translationsState.isOfferTranslate) // Action - store.dispatch(TranslationsAction.TranslateAction(tabId = tab.id, fromLanguage = "en", toLanguage = "en", options = null)).joinBlocking() + state = BrowserStateReducer.reduce( + state, + TranslationsAction.TranslateAction( + tabId = tab.id, + fromLanguage = "en", + toLanguage = "en", + options = null, + ), + ) // Should revert to false assertFalse(tabState().translationsState.isOfferTranslate) @@ -158,34 +191,62 @@ class TranslationsActionTest { // Sending an initial request to set state; however, the engine hasn't decided if it is an // expected state var translatedEngineState = TranslationEngineState( - detectedLanguages = DetectedLanguages(documentLangTag = "es", supportedDocumentLang = true, userPreferredLangTag = "en"), + detectedLanguages = DetectedLanguages( + documentLangTag = "es", + supportedDocumentLang = true, + userPreferredLangTag = "en", + ), error = null, isEngineReady = true, requestedTranslationPair = TranslationPair(fromLanguage = "es", toLanguage = "en"), ) - store.dispatch(TranslationsAction.TranslateStateChangeAction(tabId = tab.id, translationEngineState = translatedEngineState)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TranslationsAction.TranslateStateChangeAction( + tabId = tab.id, + translationEngineState = translatedEngineState, + ), + ) + assertFalse(tabState().translationsState.isExpectedTranslate) // Engine is sending a translation expected action - store.dispatch(TranslationsAction.TranslateExpectedAction(tabId = tab.id)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TranslationsAction.TranslateExpectedAction(tabId = tab.id), + ) // Initial expected translation state - store.dispatch(TranslationsAction.TranslateStateChangeAction(tabId = tab.id, translationEngineState = translatedEngineState)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TranslationsAction.TranslateStateChangeAction( + tabId = tab.id, + translationEngineState = translatedEngineState, + ), + ) + assertTrue(tabState().translationsState.isExpectedTranslate) // Not expected translation state, because it is no longer supported translatedEngineState = TranslationEngineState( - detectedLanguages = DetectedLanguages(documentLangTag = "es", supportedDocumentLang = false, userPreferredLangTag = "en"), + detectedLanguages = DetectedLanguages( + documentLangTag = "es", + supportedDocumentLang = false, + userPreferredLangTag = "en", + ), error = null, isEngineReady = true, requestedTranslationPair = TranslationPair(fromLanguage = "es", toLanguage = "en"), ) - store.dispatch(TranslationsAction.TranslateStateChangeAction(tabId = tab.id, translationEngineState = translatedEngineState)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TranslationsAction.TranslateStateChangeAction( + tabId = tab.id, + translationEngineState = translatedEngineState, + ), + ) + assertFalse(tabState().translationsState.isExpectedTranslate) } @@ -197,34 +258,62 @@ class TranslationsActionTest { // Sending an initial request to set state; however, the engine hasn't decided if it is an // offered state var translatedEngineState = TranslationEngineState( - detectedLanguages = DetectedLanguages(documentLangTag = "es", supportedDocumentLang = true, userPreferredLangTag = "en"), + detectedLanguages = DetectedLanguages( + documentLangTag = "es", + supportedDocumentLang = true, + userPreferredLangTag = "en", + ), error = null, isEngineReady = true, requestedTranslationPair = TranslationPair(fromLanguage = "es", toLanguage = "en"), ) - store.dispatch(TranslationsAction.TranslateStateChangeAction(tabId = tab.id, translationEngineState = translatedEngineState)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TranslationsAction.TranslateStateChangeAction( + tabId = tab.id, + translationEngineState = translatedEngineState, + ), + ) + assertFalse(tabState().translationsState.isOfferTranslate) // Engine is sending a translation offer action - store.dispatch(TranslationsAction.TranslateOfferAction(tabId = tab.id, isOfferTranslate = true)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TranslationsAction.TranslateOfferAction(tabId = tab.id, isOfferTranslate = true), + ) // Initial expected translation state - store.dispatch(TranslationsAction.TranslateStateChangeAction(tabId = tab.id, translationEngineState = translatedEngineState)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TranslationsAction.TranslateStateChangeAction( + tabId = tab.id, + translationEngineState = translatedEngineState, + ), + ) + assertTrue(tabState().translationsState.isOfferTranslate) // Not in an offer translation state, because it is no longer supported translatedEngineState = TranslationEngineState( - detectedLanguages = DetectedLanguages(documentLangTag = "es", supportedDocumentLang = false, userPreferredLangTag = "en"), + detectedLanguages = DetectedLanguages( + documentLangTag = "es", + supportedDocumentLang = false, + userPreferredLangTag = "en", + ), error = null, isEngineReady = true, requestedTranslationPair = TranslationPair(fromLanguage = "es", toLanguage = "en"), ) - store.dispatch(TranslationsAction.TranslateStateChangeAction(tabId = tab.id, translationEngineState = translatedEngineState)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TranslationsAction.TranslateStateChangeAction( + tabId = tab.id, + translationEngineState = translatedEngineState, + ), + ) + assertFalse(tabState().translationsState.isOfferTranslate) } @@ -236,13 +325,22 @@ class TranslationsActionTest { // Sending an initial request to set state, notice the supportedDocumentLang isn't supported val noSupportedState = TranslationEngineState( - detectedLanguages = DetectedLanguages(documentLangTag = "unknown", supportedDocumentLang = false, userPreferredLangTag = "en"), + detectedLanguages = DetectedLanguages( + documentLangTag = "unknown", + supportedDocumentLang = false, + userPreferredLangTag = "en", + ), error = null, isEngineReady = true, requestedTranslationPair = null, ) - store.dispatch(TranslationsAction.TranslateStateChangeAction(tabId = tab.id, translationEngineState = noSupportedState)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TranslationsAction.TranslateStateChangeAction( + tabId = tab.id, + translationEngineState = noSupportedState, + ), + ) // Response state assertEquals(noSupportedState, tabState().translationsState.translationEngineState) @@ -250,13 +348,22 @@ class TranslationsActionTest { // Sending a request to show state change, notice the supportedDocumentLang is now supported val supportedState = TranslationEngineState( - detectedLanguages = DetectedLanguages(documentLangTag = "es", supportedDocumentLang = true, userPreferredLangTag = "en"), + detectedLanguages = DetectedLanguages( + documentLangTag = "es", + supportedDocumentLang = true, + userPreferredLangTag = "en", + ), error = null, isEngineReady = true, requestedTranslationPair = null, ) - store.dispatch(TranslationsAction.TranslateStateChangeAction(tabId = tab.id, translationEngineState = supportedState)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TranslationsAction.TranslateStateChangeAction( + tabId = tab.id, + translationEngineState = supportedState, + ), + ) // Response state assertEquals(supportedState, tabState().translationsState.translationEngineState) @@ -269,13 +376,22 @@ class TranslationsActionTest { assertEquals(false, tabState().translationsState.isTranslateProcessing) // Action started - store.dispatch(TranslationsAction.TranslateAction(tabId = tab.id, "en", "es", null)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TranslationsAction.TranslateAction(tabId = tab.id, "en", "es", null), + ) + assertEquals(true, tabState().translationsState.isTranslateProcessing) // Action success - store.dispatch(TranslationsAction.TranslateSuccessAction(tabId = tab.id, operation = TranslationOperation.TRANSLATE)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TranslationsAction.TranslateSuccessAction( + tabId = tab.id, + operation = TranslationOperation.TRANSLATE, + ), + ) + assertEquals(null, tabState().translationsState.translationError) } @@ -285,14 +401,24 @@ class TranslationsActionTest { assertEquals(false, tabState().translationsState.isTranslateProcessing) // Action started - store.dispatch(TranslationsAction.TranslateAction(tabId = tab.id, "en", "es", null)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TranslationsAction.TranslateAction(tabId = tab.id, "en", "es", null), + ) + assertEquals(true, tabState().translationsState.isTranslateProcessing) // Action failure val error = TranslationError.UnknownError(Exception()) - store.dispatch(TranslationsAction.TranslateExceptionAction(tabId = tab.id, operation = TranslationOperation.TRANSLATE, error)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TranslationsAction.TranslateExceptionAction( + tabId = tab.id, + operation = TranslationOperation.TRANSLATE, + error, + ), + ) + assertEquals(false, tabState().translationsState.isTranslateProcessing) assertEquals(false, tabState().translationsState.isTranslated) assertEquals(error, tabState().translationsState.translationError) @@ -304,13 +430,22 @@ class TranslationsActionTest { assertEquals(false, tabState().translationsState.isRestoreProcessing) // Action started - store.dispatch(TranslationsAction.TranslateRestoreAction(tabId = tab.id)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TranslationsAction.TranslateRestoreAction(tabId = tab.id), + ) + assertEquals(true, tabState().translationsState.isRestoreProcessing) // Action success - store.dispatch(TranslationsAction.TranslateSuccessAction(tabId = tab.id, operation = TranslationOperation.RESTORE)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TranslationsAction.TranslateSuccessAction( + tabId = tab.id, + operation = TranslationOperation.RESTORE, + ), + ) + assertEquals(false, tabState().translationsState.isRestoreProcessing) assertEquals(false, tabState().translationsState.isTranslated) assertEquals(null, tabState().translationsState.translationError) @@ -322,14 +457,24 @@ class TranslationsActionTest { assertEquals(false, tabState().translationsState.isRestoreProcessing) // Action started - store.dispatch(TranslationsAction.TranslateRestoreAction(tabId = tab.id)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TranslationsAction.TranslateRestoreAction(tabId = tab.id), + ) + assertEquals(true, tabState().translationsState.isRestoreProcessing) // Action failure val error = TranslationError.UnknownError(Exception()) - store.dispatch(TranslationsAction.TranslateExceptionAction(tabId = tab.id, operation = TranslationOperation.RESTORE, error)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TranslationsAction.TranslateExceptionAction( + tabId = tab.id, + operation = TranslationOperation.RESTORE, + error, + ), + ) + assertEquals(false, tabState().translationsState.isRestoreProcessing) assertEquals(false, tabState().translationsState.isTranslated) assertEquals(error, tabState().translationsState.translationError) @@ -338,61 +483,64 @@ class TranslationsActionTest { @Test fun `WHEN a SetSupportedLanguagesAction is dispatched AND successful THEN update supportedLanguages`() { // Initial - assertNull(store.state.translationEngine.supportedLanguages) + assertNull(state.translationEngine.supportedLanguages) // Action started val toLanguage = Language("de", "German") val fromLanguage = Language("es", "Spanish") val supportedLanguages = TranslationSupport(listOf(fromLanguage), listOf(toLanguage)) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.SetSupportedLanguagesAction( supportedLanguages = supportedLanguages, ), ) - .joinBlocking() // Action success - assertEquals(supportedLanguages, store.state.translationEngine.supportedLanguages) + assertEquals(supportedLanguages, state.translationEngine.supportedLanguages) } @Test fun `WHEN a SetNeverTranslateSitesAction is dispatched AND successful THEN update neverTranslateSites`() { // Initial - assertNull(store.state.translationEngine.neverTranslateSites) + assertNull(state.translationEngine.neverTranslateSites) // Action started val neverTranslateSites = listOf("google.com") - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.SetNeverTranslateSitesAction( neverTranslateSites = neverTranslateSites, ), - ).joinBlocking() + ) // Action success - assertEquals(neverTranslateSites, store.state.translationEngine.neverTranslateSites) + assertEquals(neverTranslateSites, state.translationEngine.neverTranslateSites) } @Test fun `WHEN a RemoveNeverTranslateSiteAction is dispatched AND successful THEN update neverTranslateSites`() { // Initial add to neverTranslateSites - assertNull(store.state.translationEngine.neverTranslateSites) + assertNull(state.translationEngine.neverTranslateSites) val neverTranslateSites = listOf("google.com") - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.SetNeverTranslateSitesAction( neverTranslateSites = neverTranslateSites, ), - ).joinBlocking() - assertEquals(neverTranslateSites, store.state.translationEngine.neverTranslateSites) + ) + assertEquals(neverTranslateSites, state.translationEngine.neverTranslateSites) // Action started - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.RemoveNeverTranslateSiteAction( origin = "google.com", ), - ).joinBlocking() + ) // Action success - assertEquals(listOf<String>(), store.state.translationEngine.neverTranslateSites) + assertEquals(listOf<String>(), state.translationEngine.neverTranslateSites) } @Test @@ -402,54 +550,61 @@ class TranslationsActionTest { assertFalse(tabState().translationsState.isTranslateProcessing) // Set an initial state for is translate processing via a translation request: - store.dispatch(TranslationsAction.TranslateAction(tabId = tab.id, "en", "es", null)) - .joinBlocking() + state = BrowserStateReducer.reduce( + state, + TranslationsAction.TranslateAction(tabId = tab.id, "en", "es", null), + ) + assertTrue(tabState().translationsState.isTranslateProcessing) // TRANSLATE usage val translateError = TranslationError.CouldNotLoadLanguagesError(null) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.TranslateExceptionAction( tabId = tab.id, operation = TranslationOperation.TRANSLATE, translationError = translateError, ), - ).joinBlocking() + ) assertEquals(translateError, tabState().translationsState.translationError) // A translate error should clear this state assertFalse(tabState().translationsState.isTranslateProcessing) // RESTORE usage val restoreError = TranslationError.CouldNotRestoreError(null) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.TranslateExceptionAction( tabId = tab.id, operation = TranslationOperation.RESTORE, translationError = restoreError, ), - ).joinBlocking() + ) assertEquals(restoreError, tabState().translationsState.translationError) // FETCH_LANGUAGES usage val fetchLanguagesError = TranslationError.CouldNotLoadLanguagesError(null) // Testing setting tab level error - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.TranslateExceptionAction( tabId = tab.id, operation = TranslationOperation.FETCH_SUPPORTED_LANGUAGES, translationError = fetchLanguagesError, ), - ).joinBlocking() + ) assertEquals(fetchLanguagesError, tabState().translationsState.translationError) // Testing setting browser level error - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.EngineExceptionAction( error = fetchLanguagesError, ), - ).joinBlocking() - assertEquals(fetchLanguagesError, store.state.translationEngine.engineError) + ) + assertEquals(fetchLanguagesError, state.translationEngine.engineError) } @Test @@ -460,33 +615,36 @@ class TranslationsActionTest { assertEquals(false, tabState().translationsState.isTranslateProcessing) // TRANSLATE usage - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.TranslateSuccessAction( tabId = tab.id, operation = TranslationOperation.TRANSLATE, ), - ).joinBlocking() + ) assertEquals(null, tabState().translationsState.translationError) assertEquals(false, tabState().translationsState.isTranslateProcessing) // RESTORE usage - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.TranslateSuccessAction( tabId = tab.id, operation = TranslationOperation.RESTORE, ), - ).joinBlocking() + ) assertEquals(null, tabState().translationsState.translationError) assertEquals(false, tabState().translationsState.isTranslated) assertEquals(false, tabState().translationsState.isRestoreProcessing) // FETCH_LANGUAGES usage - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.TranslateSuccessAction( tabId = tab.id, operation = TranslationOperation.FETCH_SUPPORTED_LANGUAGES, ), - ).joinBlocking() + ) assertEquals(null, tabState().translationsState.translationError) assertEquals(false, tabState().translationsState.isTranslated) } @@ -503,12 +661,13 @@ class TranslationsActionTest { neverTranslateLanguage = true, neverTranslateSite = true, ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.SetPageSettingsAction( tabId = tab.id, pageSettings = pageSettings, ), - ).joinBlocking() + ) // Action success assertEquals(pageSettings, tabState().translationsState.pageSettings) @@ -521,12 +680,13 @@ class TranslationsActionTest { // Action started val isProcessing = true - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.SetTranslateProcessingAction( tabId = tab.id, isProcessing = isProcessing, ), - ).joinBlocking() + ) // Action success assertEquals(isProcessing, tabState().translationsState.isTranslateProcessing) @@ -544,12 +704,13 @@ class TranslationsActionTest { size = 10000L, error = null, ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.SetTranslationDownloadSizeAction( tabId = tab.id, translationSize = translationSize, ), - ).joinBlocking() + ) // Action success assertEquals(translationSize, tabState().translationsState.translationDownloadSize) @@ -564,23 +725,25 @@ class TranslationsActionTest { size = 10000L, error = null, ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.SetTranslationDownloadSizeAction( tabId = tab.id, translationSize = translationSize, ), - ).joinBlocking() + ) assertEquals(translationSize, tabState().translationsState.translationDownloadSize) // Action started - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.FetchTranslationDownloadSizeAction( tabId = tab.id, fromLanguage = Language("en", "English"), toLanguage = Language("fr", "French"), ), - ).joinBlocking() + ) // Action success assertNull(tabState().translationsState.translationDownloadSize) @@ -598,23 +761,25 @@ class TranslationsActionTest { neverTranslateSite = true, ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.SetPageSettingsAction( tabId = tab.id, pageSettings = pageSettings, ), - ).joinBlocking() + ) assertEquals(pageSettings, tabState().translationsState.pageSettings) assertNull(tabState().translationsState.settingsError) // Action started - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.OperationRequestedAction( tabId = tab.id, operation = TranslationOperation.FETCH_PAGE_SETTINGS, ), - ).joinBlocking() + ) // Action success assertNull(tabState().translationsState.pageSettings) @@ -623,31 +788,33 @@ class TranslationsActionTest { @Test fun `WHEN a OperationRequestedAction is dispatched for FETCH_SUPPORTED_LANGUAGES THEN clear supportLanguages`() { // Setting first to have a more robust initial state - assertNull(store.state.translationEngine.supportedLanguages) + assertNull(state.translationEngine.supportedLanguages) val supportLanguages = TranslationSupport( fromLanguages = listOf(Language("en", "English")), toLanguages = listOf(Language("en", "English")), ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.SetSupportedLanguagesAction( supportedLanguages = supportLanguages, ), - ).joinBlocking() + ) - assertEquals(supportLanguages, store.state.translationEngine.supportedLanguages) + assertEquals(supportLanguages, state.translationEngine.supportedLanguages) // Action started - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.OperationRequestedAction( tabId = tab.id, operation = TranslationOperation.FETCH_SUPPORTED_LANGUAGES, ), - ).joinBlocking() + ) // Action success - assertNull(store.state.translationEngine.supportedLanguages) + assertNull(state.translationEngine.supportedLanguages) } @Test @@ -656,13 +823,14 @@ class TranslationsActionTest { assertNull(tabState().translationsState.pageSettings?.alwaysOfferPopup) // Action started - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.UpdatePageSettingAction( tabId = tab.id, operation = TranslationPageSettingOperation.UPDATE_ALWAYS_OFFER_POPUP, setting = true, ), - ).joinBlocking() + ) // Action success assertTrue(tabState().translationsState.pageSettings?.alwaysOfferPopup!!) @@ -675,13 +843,14 @@ class TranslationsActionTest { assertNull(tabState().translationsState.pageSettings?.neverTranslateLanguage) // Action started - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.UpdatePageSettingAction( tabId = tab.id, operation = TranslationPageSettingOperation.UPDATE_ALWAYS_TRANSLATE_LANGUAGE, setting = true, ), - ).joinBlocking() + ) // Action success assertTrue(tabState().translationsState.pageSettings?.alwaysTranslateLanguage!!) @@ -695,13 +864,14 @@ class TranslationsActionTest { assertNull(tabState().translationsState.pageSettings?.alwaysTranslateLanguage) // Action started - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.UpdatePageSettingAction( tabId = tab.id, operation = TranslationPageSettingOperation.UPDATE_NEVER_TRANSLATE_LANGUAGE, setting = true, ), - ).joinBlocking() + ) // Action success assertTrue(tabState().translationsState.pageSettings?.neverTranslateLanguage!!) @@ -714,13 +884,14 @@ class TranslationsActionTest { assertNull(tabState().translationsState.pageSettings?.neverTranslateLanguage) // Action started - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.UpdatePageSettingAction( tabId = tab.id, operation = TranslationPageSettingOperation.UPDATE_NEVER_TRANSLATE_SITE, setting = true, ), - ).joinBlocking() + ) // Action success assertTrue(tabState().translationsState.pageSettings?.neverTranslateSite!!) @@ -733,39 +904,42 @@ class TranslationsActionTest { assertNull(tabState().translationsState.pageSettings?.neverTranslateLanguage) // Action started to update the always offer setting to true - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.UpdatePageSettingAction( tabId = tab.id, operation = TranslationPageSettingOperation.UPDATE_ALWAYS_TRANSLATE_LANGUAGE, setting = true, ), - ).joinBlocking() + ) // When always is true, never should be false assertTrue(tabState().translationsState.pageSettings?.alwaysTranslateLanguage!!) assertFalse(tabState().translationsState.pageSettings?.neverTranslateLanguage!!) // Action started to update the never offer setting to true - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.UpdatePageSettingAction( tabId = tab.id, operation = TranslationPageSettingOperation.UPDATE_NEVER_TRANSLATE_LANGUAGE, setting = true, ), - ).joinBlocking() + ) // When never is true, always should be false assertFalse(tabState().translationsState.pageSettings?.alwaysTranslateLanguage!!) assertTrue(tabState().translationsState.pageSettings?.neverTranslateLanguage!!) // Action started to update the never language setting to false - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.UpdatePageSettingAction( tabId = tab.id, operation = TranslationPageSettingOperation.UPDATE_NEVER_TRANSLATE_LANGUAGE, setting = false, ), - ).joinBlocking() + ) // When never is false, always may also be false assertFalse(tabState().translationsState.pageSettings?.alwaysTranslateLanguage!!) @@ -781,37 +955,41 @@ class TranslationsActionTest { assertNull(tabState().translationsState.pageSettings?.neverTranslateSite) // Action started - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.UpdatePageSettingAction( tabId = tab.id, operation = TranslationPageSettingOperation.UPDATE_ALWAYS_OFFER_POPUP, setting = true, ), - ).joinBlocking() + ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.UpdatePageSettingAction( tabId = tab.id, operation = TranslationPageSettingOperation.UPDATE_ALWAYS_TRANSLATE_LANGUAGE, setting = true, ), - ).joinBlocking() + ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.UpdatePageSettingAction( tabId = tab.id, operation = TranslationPageSettingOperation.UPDATE_NEVER_TRANSLATE_LANGUAGE, setting = true, ), - ).joinBlocking() + ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.UpdatePageSettingAction( tabId = tab.id, operation = TranslationPageSettingOperation.UPDATE_NEVER_TRANSLATE_SITE, setting = true, ), - ).joinBlocking() + ) // Action success assertTrue(tabState().translationsState.pageSettings?.alwaysOfferPopup!!) @@ -824,54 +1002,58 @@ class TranslationsActionTest { @Test fun `WHEN a SetLanguageSettingsAction is dispatched THEN the browser store is updated to match`() { // Initial state - assertNull(store.state.translationEngine.languageSettings) + assertNull(state.translationEngine.languageSettings) // Dispatch val languageSetting = mapOf("es" to LanguageSetting.OFFER) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.SetLanguageSettingsAction( languageSettings = languageSetting, ), - ).joinBlocking() + ) // Final state - assertEquals(store.state.translationEngine.languageSettings!!, languageSetting) + assertEquals(state.translationEngine.languageSettings!!, languageSetting) } @Test fun `WHEN a OperationRequestedAction is dispatched for FETCH_AUTOMATIC_LANGUAGE_SETTINGS THEN clear languageSettings`() { // Setting first to have a more robust initial state val languageSetting = mapOf("es" to LanguageSetting.OFFER) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.SetLanguageSettingsAction( languageSettings = languageSetting, ), - ).joinBlocking() - assertEquals(store.state.translationEngine.languageSettings, languageSetting) + ) + assertEquals(state.translationEngine.languageSettings, languageSetting) // Action started - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.OperationRequestedAction( tabId = tab.id, operation = TranslationOperation.FETCH_AUTOMATIC_LANGUAGE_SETTINGS, ), - ).joinBlocking() + ) // Action success - assertNull(store.state.translationEngine.languageSettings) + assertNull(state.translationEngine.languageSettings) } @Test fun `WHEN a TranslateExceptionAction is dispatched for FETCH_AUTOMATIC_LANGUAGE_SETTINGS THEN set the error`() { // Action started val error = TranslationError.UnknownError(IllegalStateException()) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.TranslateExceptionAction( tabId = tab.id, operation = TranslationOperation.FETCH_AUTOMATIC_LANGUAGE_SETTINGS, translationError = error, ), - ).joinBlocking() + ) // Action success assertEquals(error, tabState().translationsState.translationError) @@ -880,40 +1062,42 @@ class TranslationsActionTest { @Test fun `WHEN a SetEngineSupportAction is dispatched THEN the browser store is updated to match`() { // Initial state - assertNull(store.state.translationEngine.isEngineSupported) + assertNull(state.translationEngine.isEngineSupported) // Dispatch - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.SetEngineSupportedAction( isEngineSupported = true, ), - ).joinBlocking() + ) // Final state - assertTrue(store.state.translationEngine.isEngineSupported!!) + assertTrue(state.translationEngine.isEngineSupported!!) } @Test fun `WHEN an EngineExceptionAction is dispatched THEN the browser store is updated to match`() { // Initial state - assertNull(store.state.translationEngine.engineError) + assertNull(state.translationEngine.engineError) // Dispatch val error = TranslationError.UnknownError(Throwable()) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.EngineExceptionAction( error = error, ), - ).joinBlocking() + ) // Final state - assertEquals(store.state.translationEngine.engineError!!, error) + assertEquals(state.translationEngine.engineError!!, error) } @Test fun `WHEN a SetLanguageModelsAction is dispatched and successful THEN the browser store is updated to match`() { // Initial state - assertNull(store.state.translationEngine.languageModels) + assertNull(state.translationEngine.languageModels) val code = "es" val localizedDisplayName = "Spanish" @@ -924,20 +1108,21 @@ class TranslationsActionTest { val languageModels = mutableListOf(languageModel) // Dispatch - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.SetLanguageModelsAction( languageModels = languageModels, ), - ).joinBlocking() + ) // Final state - assertEquals(languageModels, store.state.translationEngine.languageModels) + assertEquals(languageModels, state.translationEngine.languageModels) } @Test fun `WHEN a ManageLanguageModelsAction is dispatched and successful THEN the browser store is updated to match`() { // Initial state - assertNull(store.state.translationEngine.languageModels) + assertNull(state.translationEngine.languageModels) // Test Operation val options = ModelManagementOptions( @@ -947,14 +1132,15 @@ class TranslationsActionTest { ) // Dispatch a request when state is not setup - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.ManageLanguageModelsAction( options = options, ), - ).joinBlocking() + ) // We don't have an initial state, so nothing should change. - assertNull(store.state.translationEngine.languageModels) + assertNull(state.translationEngine.languageModels) // Setting up an initial test state. val code = "es" @@ -964,26 +1150,29 @@ class TranslationsActionTest { val language = Language(code, localizedDisplayName) val languageModel = LanguageModel(language, processState, size) val languageModels = mutableListOf(languageModel) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.SetLanguageModelsAction( languageModels = languageModels, ), - ).joinBlocking() + ) // Dispatch a valid request - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.ManageLanguageModelsAction( options = options, ), - ).joinBlocking() + ) // Expectations based on operation val expectedLanguageModel = LanguageModel(language, ModelState.DOWNLOAD_IN_PROGRESS, size) val expectedLanguageModels = mutableListOf(expectedLanguageModel) - assertEquals(expectedLanguageModels, store.state.translationEngine.languageModels) + assertEquals(expectedLanguageModels, state.translationEngine.languageModels) // Dispatch a language not listed - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.ManageLanguageModelsAction( options = ModelManagementOptions( languageToManage = "de", @@ -991,58 +1180,61 @@ class TranslationsActionTest { operationLevel = OperationLevel.LANGUAGE, ), ), - ).joinBlocking() + ) // Nothing should change, since it isn't a known option - assertEquals(expectedLanguageModels, store.state.translationEngine.languageModels) + assertEquals(expectedLanguageModels, state.translationEngine.languageModels) } @Test fun `WHEN SetOfferTranslateSettingAction is called then set offerToTranslate`() { // Initial State - assertNull(store.state.translationEngine.offerTranslation) + assertNull(state.translationEngine.offerTranslation) // Action started - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.SetGlobalOfferTranslateSettingAction( offerTranslation = false, ), - ).joinBlocking() + ) // Action success - assertFalse(store.state.translationEngine.offerTranslation!!) + assertFalse(state.translationEngine.offerTranslation!!) } @Test fun `WHEN UpdateOfferTranslateSettingAction is called then set offerToTranslate`() { // Initial State - assertNull(store.state.translationEngine.offerTranslation) + assertNull(state.translationEngine.offerTranslation) // Action started - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.UpdateGlobalOfferTranslateSettingAction( offerTranslation = false, ), - ).joinBlocking() + ) // Action success - assertFalse(store.state.translationEngine.offerTranslation!!) + assertFalse(state.translationEngine.offerTranslation!!) } @Test fun `WHEN UpdateGlobalLanguageSettingAction is called then update languageSettings`() { // Initial State - assertNull(store.state.translationEngine.languageSettings) + assertNull(state.translationEngine.languageSettings) // No-op null test - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.UpdateLanguageSettingsAction( languageCode = "fr", setting = LanguageSetting.ALWAYS, ), - ).joinBlocking() + ) - assertNull(store.state.translationEngine.languageSettings) + assertNull(state.translationEngine.languageSettings) // Setting Initial State val languageSettings = mapOf<String, LanguageSetting>( @@ -1051,33 +1243,36 @@ class TranslationsActionTest { "de" to LanguageSetting.ALWAYS, ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.SetLanguageSettingsAction( languageSettings = languageSettings, ), - ).joinBlocking() + ) - assertEquals(languageSettings, store.state.translationEngine.languageSettings) + assertEquals(languageSettings, state.translationEngine.languageSettings) // No-op update test - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.UpdateLanguageSettingsAction( languageCode = "fr", setting = LanguageSetting.ALWAYS, ), - ).joinBlocking() + ) - assertEquals(languageSettings, store.state.translationEngine.languageSettings) + assertEquals(languageSettings, state.translationEngine.languageSettings) // Main action started - store.dispatch( + state = BrowserStateReducer.reduce( + state, TranslationsAction.UpdateLanguageSettingsAction( languageCode = "es", setting = LanguageSetting.ALWAYS, ), - ).joinBlocking() + ) // Action success - assertEquals(LanguageSetting.ALWAYS, store.state.translationEngine.languageSettings!!["es"]) + assertEquals(LanguageSetting.ALWAYS, state.translationEngine.languageSettings!!["es"]) } } diff --git a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/WebExtensionActionTest.kt b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/WebExtensionActionTest.kt @@ -4,15 +4,14 @@ package mozilla.components.browser.state.action +import mozilla.components.browser.state.reducer.BrowserStateReducer import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.state.WebExtensionState import mozilla.components.browser.state.state.createTab import mozilla.components.browser.state.state.extension.WebExtensionPromptRequest -import mozilla.components.browser.state.store.BrowserStore import mozilla.components.concept.engine.EngineSession import mozilla.components.concept.engine.webextension.WebExtensionBrowserAction import mozilla.components.concept.engine.webextension.WebExtensionPageAction -import mozilla.components.support.test.ext.joinBlocking import mozilla.components.support.test.mock import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse @@ -26,41 +25,41 @@ class WebExtensionActionTest { @Test fun `InstallWebExtension - Adds an extension to the BrowserState extensions`() { - val store = BrowserStore() + var state = BrowserState() - assertTrue(store.state.extensions.isEmpty()) + assertTrue(state.extensions.isEmpty()) val extension = WebExtensionState("id", "url") - store.dispatch(WebExtensionAction.InstallWebExtensionAction(extension)).joinBlocking() + state = BrowserStateReducer.reduce(state, WebExtensionAction.InstallWebExtensionAction(extension)) - assertFalse(store.state.extensions.isEmpty()) - assertEquals(extension, store.state.extensions.values.first()) + assertFalse(state.extensions.isEmpty()) + assertEquals(extension, state.extensions.values.first()) // Installing the same extension twice should have no effect - val state = store.state - store.dispatch(WebExtensionAction.InstallWebExtensionAction(extension)).joinBlocking() - assertSame(state, store.state) + val oldState = state + state = BrowserStateReducer.reduce(state, WebExtensionAction.InstallWebExtensionAction(extension)) + assertEquals(oldState, state) } @Test fun `InstallWebExtension - Keeps existing browser and page actions`() { - val store = BrowserStore() - assertTrue(store.state.extensions.isEmpty()) + var state = BrowserState() + assertTrue(state.extensions.isEmpty()) val extension = WebExtensionState("id", "url", "name") val mockedBrowserAction = mock<WebExtensionBrowserAction>() val mockedPageAction = mock<WebExtensionPageAction>() - store.dispatch(WebExtensionAction.UpdateBrowserAction(extension.id, mockedBrowserAction)).joinBlocking() - store.dispatch(WebExtensionAction.UpdatePageAction(extension.id, mockedPageAction)).joinBlocking() - store.dispatch(WebExtensionAction.InstallWebExtensionAction(extension)).joinBlocking() + state = BrowserStateReducer.reduce(state, WebExtensionAction.UpdateBrowserAction(extension.id, mockedBrowserAction)) + state = BrowserStateReducer.reduce(state, WebExtensionAction.UpdatePageAction(extension.id, mockedPageAction)) + state = BrowserStateReducer.reduce(state, WebExtensionAction.InstallWebExtensionAction(extension)) - assertFalse(store.state.extensions.isEmpty()) + assertFalse(state.extensions.isEmpty()) assertEquals( extension.copy( browserAction = mockedBrowserAction, pageAction = mockedPageAction, ), - store.state.extensions.values.first(), + state.extensions.values.first(), ) } @@ -68,97 +67,87 @@ class WebExtensionActionTest { fun `UninstallWebExtension - Removes all state of the uninstalled extension`() { val tab1 = createTab("url") val tab2 = createTab("url") - val store = BrowserStore( - initialState = BrowserState( - tabs = listOf(tab1, tab2), - ), + var state = BrowserState( + tabs = listOf(tab1, tab2), ) - assertTrue(store.state.extensions.isEmpty()) + assertTrue(state.extensions.isEmpty()) val extension1 = WebExtensionState("id1", "url") val extension2 = WebExtensionState("i2", "url") - store.dispatch(WebExtensionAction.InstallWebExtensionAction(extension1)).joinBlocking() + state = BrowserStateReducer.reduce(state, WebExtensionAction.InstallWebExtensionAction(extension1)) - assertFalse(store.state.extensions.isEmpty()) - assertEquals(extension1, store.state.extensions.values.first()) + assertFalse(state.extensions.isEmpty()) + assertEquals(extension1, state.extensions.values.first()) val mockedBrowserAction = mock<WebExtensionBrowserAction>() - store.dispatch(WebExtensionAction.UpdateBrowserAction(extension1.id, mockedBrowserAction)).joinBlocking() - assertEquals(mockedBrowserAction, store.state.extensions.values.first().browserAction) + state = BrowserStateReducer.reduce(state, WebExtensionAction.UpdateBrowserAction(extension1.id, mockedBrowserAction)) + assertEquals(mockedBrowserAction, state.extensions.values.first().browserAction) - store.dispatch(WebExtensionAction.UpdateTabBrowserAction(tab1.id, extension1.id, mockedBrowserAction)) - .joinBlocking() - val extensionsTab1 = store.state.tabs.first().extensionState + state = BrowserStateReducer.reduce(state, WebExtensionAction.UpdateTabBrowserAction(tab1.id, extension1.id, mockedBrowserAction)) + val extensionsTab1 = state.tabs.first().extensionState assertEquals(mockedBrowserAction, extensionsTab1.values.first().browserAction) - store.dispatch(WebExtensionAction.UpdateTabBrowserAction(tab2.id, extension2.id, mockedBrowserAction)) - .joinBlocking() - val extensionsTab2 = store.state.tabs.last().extensionState - assertEquals(mockedBrowserAction, extensionsTab2.values.last().browserAction) + state = BrowserStateReducer.reduce(state, WebExtensionAction.UpdateTabBrowserAction(tab2.id, extension2.id, mockedBrowserAction)) - store.dispatch(WebExtensionAction.UninstallWebExtensionAction(extension1.id)).joinBlocking() - assertTrue(store.state.extensions.isEmpty()) - assertTrue(store.state.tabs.first().extensionState.isEmpty()) - assertFalse(store.state.tabs.last().extensionState.isEmpty()) - assertEquals(mockedBrowserAction, extensionsTab2.values.last().browserAction) + state = BrowserStateReducer.reduce(state, WebExtensionAction.UninstallWebExtensionAction(extension1.id)) + assertTrue(state.extensions.isEmpty()) + assertTrue(state.tabs.first().extensionState.isEmpty()) + assertFalse(state.tabs.last().extensionState.isEmpty()) + assertEquals(mockedBrowserAction, state.tabs.last().extensionState.values.last().browserAction) } @Test fun `UninstallAllWebExtensions - Removes all state of all extensions`() { val tab1 = createTab("url") val tab2 = createTab("url") - val store = BrowserStore( - initialState = BrowserState( - tabs = listOf(tab1, tab2), - ), + var state = BrowserState( + tabs = listOf(tab1, tab2), ) - assertTrue(store.state.extensions.isEmpty()) + assertTrue(state.extensions.isEmpty()) val extension1 = WebExtensionState("id1", "url") val extension2 = WebExtensionState("i2", "url") - store.dispatch(WebExtensionAction.InstallWebExtensionAction(extension1)).joinBlocking() - store.dispatch(WebExtensionAction.InstallWebExtensionAction(extension2)).joinBlocking() - assertEquals(2, store.state.extensions.size) + state = BrowserStateReducer.reduce(state, WebExtensionAction.InstallWebExtensionAction(extension1)) + state = BrowserStateReducer.reduce(state, WebExtensionAction.InstallWebExtensionAction(extension2)) + assertEquals(2, state.extensions.size) val mockedBrowserAction = mock<WebExtensionBrowserAction>() - store.dispatch(WebExtensionAction.UpdateBrowserAction(extension1.id, mockedBrowserAction)).joinBlocking() - assertEquals(mockedBrowserAction, store.state.extensions["id1"]?.browserAction) - store.dispatch(WebExtensionAction.UpdateTabBrowserAction(tab1.id, extension1.id, mockedBrowserAction)).joinBlocking() - store.dispatch(WebExtensionAction.UpdateTabBrowserAction(tab2.id, extension2.id, mockedBrowserAction)).joinBlocking() - - store.dispatch(WebExtensionAction.UninstallAllWebExtensionsAction).joinBlocking() - assertTrue(store.state.extensions.isEmpty()) - assertTrue(store.state.tabs.first().extensionState.isEmpty()) - assertTrue(store.state.tabs.last().extensionState.isEmpty()) + state = BrowserStateReducer.reduce(state, WebExtensionAction.UpdateBrowserAction(extension1.id, mockedBrowserAction)) + assertEquals(mockedBrowserAction, state.extensions["id1"]?.browserAction) + state = BrowserStateReducer.reduce(state, WebExtensionAction.UpdateTabBrowserAction(tab1.id, extension1.id, mockedBrowserAction)) + state = BrowserStateReducer.reduce(state, WebExtensionAction.UpdateTabBrowserAction(tab2.id, extension2.id, mockedBrowserAction)) + + state = BrowserStateReducer.reduce(state, WebExtensionAction.UninstallAllWebExtensionsAction) + assertTrue(state.extensions.isEmpty()) + assertTrue(state.tabs.first().extensionState.isEmpty()) + assertTrue(state.tabs.last().extensionState.isEmpty()) } @Test fun `UpdateBrowserAction - Updates a global browser action of an existing WebExtensionState on the BrowserState`() { - val store = BrowserStore() + var state = BrowserState() val mockedBrowserAction = mock<WebExtensionBrowserAction>() val mockedBrowserAction2 = mock<WebExtensionBrowserAction>() - assertTrue(store.state.extensions.isEmpty()) - store.dispatch(WebExtensionAction.UpdateBrowserAction("id", mockedBrowserAction)).joinBlocking() - assertEquals(mockedBrowserAction, store.state.extensions.values.first().browserAction) + assertTrue(state.extensions.isEmpty()) + state = BrowserStateReducer.reduce(state, WebExtensionAction.UpdateBrowserAction("id", mockedBrowserAction)) + assertEquals(mockedBrowserAction, state.extensions.values.first().browserAction) val extension = WebExtensionState("id", "url") - store.dispatch(WebExtensionAction.InstallWebExtensionAction(extension)).joinBlocking() - assertFalse(store.state.extensions.isEmpty()) - assertEquals(mockedBrowserAction, store.state.extensions.values.first().browserAction) + state = BrowserStateReducer.reduce(state, WebExtensionAction.InstallWebExtensionAction(extension)) + assertFalse(state.extensions.isEmpty()) + assertEquals(mockedBrowserAction, state.extensions.values.first().browserAction) - store.dispatch(WebExtensionAction.UpdateBrowserAction("id", mockedBrowserAction2)).joinBlocking() - assertEquals(mockedBrowserAction2, store.state.extensions.values.first().browserAction) + state = BrowserStateReducer.reduce(state, WebExtensionAction.UpdateBrowserAction("id", mockedBrowserAction2)) + assertEquals(mockedBrowserAction2, state.extensions.values.first().browserAction) } @Test fun `UpdateTabBrowserAction - Updates the browser action of an existing WebExtensionState on a given tab`() { val tab = createTab("url") - val store = BrowserStore( - initialState = BrowserState( - tabs = listOf(tab), - ), + var state = BrowserState( + tabs = listOf(tab), ) val mockedBrowserAction = mock<WebExtensionBrowserAction>() @@ -166,15 +155,16 @@ class WebExtensionActionTest { val extension = WebExtensionState("id", "url") - store.dispatch( + state = BrowserStateReducer.reduce( + state, WebExtensionAction.UpdateTabBrowserAction( tab.id, extension.id, mockedBrowserAction, ), - ).joinBlocking() + ) - val extensions = store.state.tabs.first().extensionState + val extensions = state.tabs.first().extensionState assertEquals(mockedBrowserAction, extensions.values.first().browserAction) } @@ -196,51 +186,48 @@ class WebExtensionActionTest { ), ), ) - val store = BrowserStore( - initialState = BrowserState( - tabs = listOf(tab), - ), + var state = BrowserState( + tabs = listOf(tab), ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, WebExtensionAction.UpdateTabBrowserAction( tab.id, "extensionId", mockedBrowserAction2, ), - ).joinBlocking() + ) - val extensions = store.state.tabs.first().extensionState + val extensions = state.tabs.first().extensionState assertEquals(mockedBrowserAction2, extensions.values.first().browserAction) } @Test fun `UpdatePageAction - Updates a global page action of an existing WebExtensionState on the BrowserState`() { - val store = BrowserStore() + var state = BrowserState() val mockedPageAction = mock<WebExtensionPageAction>() val mockedPageAction2 = mock<WebExtensionPageAction>() - assertTrue(store.state.extensions.isEmpty()) - store.dispatch(WebExtensionAction.UpdatePageAction("id", mockedPageAction)).joinBlocking() - assertEquals(mockedPageAction, store.state.extensions.values.first().pageAction) + assertTrue(state.extensions.isEmpty()) + state = BrowserStateReducer.reduce(state, WebExtensionAction.UpdatePageAction("id", mockedPageAction)) + assertEquals(mockedPageAction, state.extensions.values.first().pageAction) val extension = WebExtensionState("id", "url") - store.dispatch(WebExtensionAction.InstallWebExtensionAction(extension)).joinBlocking() - assertFalse(store.state.extensions.isEmpty()) - assertEquals(mockedPageAction, store.state.extensions.values.first().pageAction) + state = BrowserStateReducer.reduce(state, WebExtensionAction.InstallWebExtensionAction(extension)) + assertFalse(state.extensions.isEmpty()) + assertEquals(mockedPageAction, state.extensions.values.first().pageAction) - store.dispatch(WebExtensionAction.UpdatePageAction("id", mockedPageAction2)).joinBlocking() - assertEquals(mockedPageAction2, store.state.extensions.values.first().pageAction) + state = BrowserStateReducer.reduce(state, WebExtensionAction.UpdatePageAction("id", mockedPageAction2)) + assertEquals(mockedPageAction2, state.extensions.values.first().pageAction) } @Test fun `UpdateTabPageAction - Updates the page action of an existing WebExtensionState on a given tab`() { val tab = createTab("url") - val store = BrowserStore( - initialState = BrowserState( - tabs = listOf(tab), - ), + var state = BrowserState( + tabs = listOf(tab), ) val mockedPageAction = mock<WebExtensionPageAction>() @@ -248,15 +235,16 @@ class WebExtensionActionTest { val extension = WebExtensionState("id", "url") - store.dispatch( + state = BrowserStateReducer.reduce( + state, WebExtensionAction.UpdateTabPageAction( tab.id, extension.id, mockedPageAction, ), - ).joinBlocking() + ) - val extensions = store.state.tabs.first().extensionState + val extensions = state.tabs.first().extensionState assertEquals(mockedPageAction, extensions.values.first().pageAction) } @@ -278,63 +266,62 @@ class WebExtensionActionTest { ), ), ) - val store = BrowserStore( - initialState = BrowserState( - tabs = listOf(tab), - ), + var state = BrowserState( + tabs = listOf(tab), ) - store.dispatch( + state = BrowserStateReducer.reduce( + state, WebExtensionAction.UpdateTabPageAction( tab.id, "extensionId", mockedPageAction2, ), - ).joinBlocking() + ) - val extensions = store.state.tabs.first().extensionState + val extensions = state.tabs.first().extensionState assertEquals(mockedPageAction2, extensions.values.first().pageAction) } @Test fun `UpdatePopupSessionAction - Adds popup session to the web extension state`() { - val store = BrowserStore() + var state = BrowserState() val extension = WebExtensionState("id", "url") - store.dispatch(WebExtensionAction.InstallWebExtensionAction(extension)).joinBlocking() + state = BrowserStateReducer.reduce(state, WebExtensionAction.InstallWebExtensionAction(extension)) - assertEquals(extension, store.state.extensions[extension.id]) - assertNull(store.state.extensions[extension.id]?.popupSessionId) - assertNull(store.state.extensions[extension.id]?.popupSession) + assertEquals(extension, state.extensions[extension.id]) + assertNull(state.extensions[extension.id]?.popupSessionId) + assertNull(state.extensions[extension.id]?.popupSession) val engineSession: EngineSession = mock() - store.dispatch(WebExtensionAction.UpdatePopupSessionAction(extension.id, popupSession = engineSession)).joinBlocking() - assertEquals(engineSession, store.state.extensions[extension.id]?.popupSession) + state = BrowserStateReducer.reduce(state, WebExtensionAction.UpdatePopupSessionAction(extension.id, popupSession = engineSession)) + assertEquals(engineSession, state.extensions[extension.id]?.popupSession) - store.dispatch(WebExtensionAction.UpdatePopupSessionAction(extension.id, popupSession = null)).joinBlocking() - assertNull(store.state.extensions[extension.id]?.popupSession) + state = BrowserStateReducer.reduce(state, WebExtensionAction.UpdatePopupSessionAction(extension.id, popupSession = null)) + assertNull(state.extensions[extension.id]?.popupSession) - store.dispatch(WebExtensionAction.UpdatePopupSessionAction(extension.id, "popupId")).joinBlocking() - assertEquals("popupId", store.state.extensions[extension.id]?.popupSessionId) + state = BrowserStateReducer.reduce(state, WebExtensionAction.UpdatePopupSessionAction(extension.id, "popupId")) + assertEquals("popupId", state.extensions[extension.id]?.popupSessionId) - store.dispatch(WebExtensionAction.UpdatePopupSessionAction(extension.id, null)).joinBlocking() - assertNull(store.state.extensions[extension.id]?.popupSessionId) + state = BrowserStateReducer.reduce(state, WebExtensionAction.UpdatePopupSessionAction(extension.id, null)) + assertNull(state.extensions[extension.id]?.popupSessionId) } @Test fun `UpdateWebExtensionEnabledAction - Updates enabled state of an existing web extension`() { - val store = BrowserStore() + var state = BrowserState() val extension = WebExtensionState("id", "url") - store.dispatch(WebExtensionAction.InstallWebExtensionAction(extension)).joinBlocking() - assertTrue(store.state.extensions[extension.id]?.enabled!!) + state = BrowserStateReducer.reduce(state, WebExtensionAction.InstallWebExtensionAction(extension)) + assertTrue(state.extensions[extension.id]?.enabled!!) - store.dispatch(WebExtensionAction.UpdateWebExtensionEnabledAction(extension.id, false)).joinBlocking() - assertFalse(store.state.extensions[extension.id]?.enabled!!) + state = BrowserStateReducer.reduce(state, WebExtensionAction.UpdateWebExtensionEnabledAction(extension.id, false)) + assertFalse(state.extensions[extension.id]?.enabled!!) - store.dispatch(WebExtensionAction.UpdateWebExtensionEnabledAction(extension.id, true)).joinBlocking() - assertTrue(store.state.extensions[extension.id]?.enabled!!) + state = BrowserStateReducer.reduce(state, WebExtensionAction.UpdateWebExtensionEnabledAction(extension.id, true)) + assertTrue(state.extensions[extension.id]?.enabled!!) } @Test @@ -342,80 +329,72 @@ class WebExtensionActionTest { val existingExtension = WebExtensionState("id", "url") val updatedExtension = WebExtensionState("id", "url2") - val store = BrowserStore( - initialState = BrowserState( - extensions = mapOf("id" to existingExtension), - ), + var state = BrowserState( + extensions = mapOf("id" to existingExtension), ) - store.dispatch(WebExtensionAction.UpdateWebExtensionAction(updatedExtension)).joinBlocking() - assertEquals(updatedExtension, store.state.extensions.values.first()) - assertSame(updatedExtension, store.state.extensions.values.first()) + state = BrowserStateReducer.reduce(state, WebExtensionAction.UpdateWebExtensionAction(updatedExtension)) + assertEquals(updatedExtension, state.extensions.values.first()) + assertSame(updatedExtension, state.extensions.values.first()) } @Test fun `UpdateWebExtensionAllowedInPrivateBrowsingAction - Updates allowedInPrivateBrowsing state of an existing web extension`() { - val store = BrowserStore() + var state = BrowserState() val extension = WebExtensionState("id", "url", allowedInPrivateBrowsing = false) - store.dispatch(WebExtensionAction.InstallWebExtensionAction(extension)).joinBlocking() - assertFalse(store.state.extensions[extension.id]?.allowedInPrivateBrowsing!!) + state = BrowserStateReducer.reduce(state, WebExtensionAction.InstallWebExtensionAction(extension)) + assertFalse(state.extensions[extension.id]?.allowedInPrivateBrowsing!!) - store.dispatch(WebExtensionAction.UpdateWebExtensionAllowedInPrivateBrowsingAction(extension.id, true)).joinBlocking() - assertTrue(store.state.extensions[extension.id]?.allowedInPrivateBrowsing!!) + state = BrowserStateReducer.reduce(state, WebExtensionAction.UpdateWebExtensionAllowedInPrivateBrowsingAction(extension.id, true)) + assertTrue(state.extensions[extension.id]?.allowedInPrivateBrowsing!!) - store.dispatch(WebExtensionAction.UpdateWebExtensionAllowedInPrivateBrowsingAction(extension.id, false)).joinBlocking() - assertFalse(store.state.extensions[extension.id]?.allowedInPrivateBrowsing!!) + state = BrowserStateReducer.reduce(state, WebExtensionAction.UpdateWebExtensionAllowedInPrivateBrowsingAction(extension.id, false)) + assertFalse(state.extensions[extension.id]?.allowedInPrivateBrowsing!!) } @Test fun `UpdateWebExtensionTabAction - Marks tab active for web extensions`() { val tab = createTab(url = "https://mozilla.org") - val store = BrowserStore( - initialState = BrowserState( - tabs = listOf(tab), - ), + var state = BrowserState( + tabs = listOf(tab), ) - assertNull(store.state.activeWebExtensionTabId) + assertNull(state.activeWebExtensionTabId) - store.dispatch(WebExtensionAction.UpdateActiveWebExtensionTabAction(tab.id)).joinBlocking() - assertEquals(tab.id, store.state.activeWebExtensionTabId) + state = BrowserStateReducer.reduce(state, WebExtensionAction.UpdateActiveWebExtensionTabAction(tab.id)) + assertEquals(tab.id, state.activeWebExtensionTabId) - store.dispatch(WebExtensionAction.UpdateActiveWebExtensionTabAction(null)).joinBlocking() - assertNull(store.state.activeWebExtensionTabId) + state = BrowserStateReducer.reduce(state, WebExtensionAction.UpdateActiveWebExtensionTabAction(null)) + assertNull(state.activeWebExtensionTabId) } @Test fun `WHEN UpdatePromptRequestWebExtensionAction is dispatched THEN a WebExtensionPromptRequest is added to the store`() { - val store = BrowserStore() + var state = BrowserState() - assertNull(store.state.webExtensionPromptRequest) + assertNull(state.webExtensionPromptRequest) val promptRequest = WebExtensionPromptRequest.AfterInstallation.Permissions.Required(mock(), mock(), mock(), mock(), mock()) - store.dispatch(WebExtensionAction.UpdatePromptRequestWebExtensionAction(promptRequest)) - .joinBlocking() + state = BrowserStateReducer.reduce(state, WebExtensionAction.UpdatePromptRequestWebExtensionAction(promptRequest)) - assertEquals(promptRequest, store.state.webExtensionPromptRequest) + assertNotNull(state.webExtensionPromptRequest) + assertEquals(promptRequest, state.webExtensionPromptRequest) } @Test - fun `WHEN ConsumePromptRequestWebExtensionAction is dispatched THEN the actual WebExtensionPromptRequest is removed from the store`() { - val promptRequest = WebExtensionPromptRequest.AfterInstallation.Permissions.Required(mock(), mock(), mock(), mock(), mock()) + fun `WHEN ConsumePromptRequestWebExtensionAction is dispatched THEN the WebExtensionPromptRequest is removed from the store`() { + val promptRequest = + WebExtensionPromptRequest.AfterInstallation.Permissions.Required(mock(), mock(), mock(), mock(), mock()) - val store = BrowserStore( - initialState = BrowserState( - webExtensionPromptRequest = promptRequest, - ), + var state = BrowserState( + webExtensionPromptRequest = promptRequest, ) + assertNotNull(state.webExtensionPromptRequest) - assertNotNull(store.state.webExtensionPromptRequest) - - store.dispatch(WebExtensionAction.ConsumePromptRequestWebExtensionAction) - .joinBlocking() - - assertNull(store.state.webExtensionPromptRequest) + state = BrowserStateReducer.reduce(state, WebExtensionAction.ConsumePromptRequestWebExtensionAction) + assertNull(state.webExtensionPromptRequest) } } diff --git a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/store/BrowserStoreTest.kt b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/store/BrowserStoreTest.kt @@ -4,15 +4,14 @@ package mozilla.components.browser.state.store -import kotlinx.coroutines.test.runTest import mozilla.components.browser.state.action.BrowserAction import mozilla.components.browser.state.action.InitAction import mozilla.components.browser.state.action.RestoreCompleteAction import mozilla.components.browser.state.action.TabListAction +import mozilla.components.browser.state.reducer.BrowserStateReducer import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.state.createTab import mozilla.components.lib.state.Middleware -import mozilla.components.support.test.ext.joinBlocking import mozilla.components.support.test.libstate.ext.waitUntilIdle import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse @@ -50,19 +49,18 @@ class BrowserStoreTest { } @Test - fun `Adding a tab`() = runTest { - val store = BrowserStore() + fun `Adding a tab`() { + val initialState = BrowserState() - assertEquals(0, store.state.tabs.size) - assertNull(store.state.selectedTabId) + assertEquals(0, initialState.tabs.size) + assertNull(initialState.selectedTabId) val tab = createTab(url = "https://www.mozilla.org") - store.dispatch(TabListAction.AddTabAction(tab)) - .join() + val finalState = BrowserStateReducer.reduce(initialState, TabListAction.AddTabAction(tab)) - assertEquals(1, store.state.tabs.size) - assertEquals(tab.id, store.state.selectedTabId) + assertEquals(1, finalState.tabs.size) + assertEquals(tab.id, finalState.selectedTabId) } @Test @@ -83,13 +81,13 @@ class BrowserStoreTest { @Test fun `RestoreCompleteAction updates state`() { - val store = BrowserStore() - assertFalse(store.state.restoreComplete) + val initialState = BrowserState() + assertFalse(initialState.restoreComplete) - store.dispatch(RestoreCompleteAction).joinBlocking() - assertTrue(store.state.restoreComplete) + val finalState = BrowserStateReducer.reduce(initialState, RestoreCompleteAction) + assertTrue(finalState.restoreComplete) - store.dispatch(RestoreCompleteAction).joinBlocking() - assertTrue(store.state.restoreComplete) + val finalState2 = BrowserStateReducer.reduce(finalState, RestoreCompleteAction) + assertTrue(finalState2.restoreComplete) } }