Migrate from Session.toTab to BrowserStore (#12221)
parent
9af167ba0a
commit
652af79e95
|
@ -17,14 +17,16 @@ import kotlinx.android.synthetic.main.fragment_create_collection.view.*
|
|||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.plus
|
||||
import mozilla.components.browser.session.SessionManager
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.browser.state.selector.findTab
|
||||
import mozilla.components.browser.state.state.BrowserState
|
||||
import mozilla.components.browser.state.state.TabSessionState
|
||||
import mozilla.components.lib.publicsuffixlist.PublicSuffixList
|
||||
import mozilla.components.lib.state.ext.consumeFrom
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.StoreProvider
|
||||
import org.mozilla.fenix.ext.getMediaStateForSession
|
||||
import org.mozilla.fenix.ext.requireComponents
|
||||
import org.mozilla.fenix.ext.toTab
|
||||
import org.mozilla.fenix.ext.toShortUrl
|
||||
import org.mozilla.fenix.home.Tab
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
|
@ -47,12 +49,11 @@ class CollectionCreationFragment : DialogFragment() {
|
|||
val view = inflater.inflate(R.layout.fragment_create_collection, container, false)
|
||||
val args: CollectionCreationFragmentArgs by navArgs()
|
||||
|
||||
val sessionManager = requireComponents.core.sessionManager
|
||||
val store = requireComponents.core.store
|
||||
val publicSuffixList = requireComponents.publicSuffixList
|
||||
val tabs = sessionManager.getTabs(args.tabIds, store, publicSuffixList)
|
||||
val tabs = store.state.getTabs(args.tabIds, publicSuffixList)
|
||||
val selectedTabs = if (args.selectedTabIds != null) {
|
||||
sessionManager.getTabs(args.selectedTabIds, store, publicSuffixList).toSet()
|
||||
store.state.getTabs(args.selectedTabIds, publicSuffixList).toSet()
|
||||
} else {
|
||||
if (tabs.size == 1) setOf(tabs.first()) else emptySet()
|
||||
}
|
||||
|
@ -112,14 +113,30 @@ class CollectionCreationFragment : DialogFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
|
||||
fun SessionManager.getTabs(
|
||||
@VisibleForTesting
|
||||
internal fun BrowserState.getTabs(
|
||||
tabIds: Array<String>?,
|
||||
store: BrowserStore,
|
||||
publicSuffixList: PublicSuffixList
|
||||
): List<Tab> {
|
||||
return tabIds
|
||||
?.mapNotNull { this.findSessionById(it) }
|
||||
?.map { it.toTab(store, publicSuffixList) }
|
||||
?: emptyList()
|
||||
?.mapNotNull { id -> findTab(id) }
|
||||
?.map { it.toTab(this, publicSuffixList) }
|
||||
.orEmpty()
|
||||
}
|
||||
|
||||
private fun TabSessionState.toTab(
|
||||
state: BrowserState,
|
||||
publicSuffixList: PublicSuffixList,
|
||||
selected: Boolean? = null
|
||||
): Tab {
|
||||
val url = readerState.activeUrl ?: content.url
|
||||
return Tab(
|
||||
sessionId = this.id,
|
||||
url = url,
|
||||
hostname = url.toShortUrl(publicSuffixList),
|
||||
title = content.title,
|
||||
selected = selected,
|
||||
icon = content.icon,
|
||||
mediaState = state.getMediaStateForSession(this.id)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.fenix.ext
|
||||
|
||||
import mozilla.components.browser.state.state.BrowserState
|
||||
import mozilla.components.browser.state.state.MediaState
|
||||
|
||||
fun BrowserState.getMediaStateForSession(sessionId: String): MediaState.State {
|
||||
return if (media.aggregate.activeTabId == sessionId) {
|
||||
media.aggregate.state
|
||||
} else {
|
||||
MediaState.State.NONE
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.fenix.ext
|
||||
|
||||
import android.content.Context
|
||||
import mozilla.components.browser.session.Session
|
||||
import mozilla.components.browser.state.selector.findTab
|
||||
import mozilla.components.browser.state.state.MediaState
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.lib.publicsuffixlist.PublicSuffixList
|
||||
import org.mozilla.fenix.home.Tab
|
||||
|
||||
fun Session.toTab(context: Context, selected: Boolean? = null): Tab =
|
||||
this.toTab(
|
||||
context.components.core.store,
|
||||
context.components.publicSuffixList,
|
||||
selected
|
||||
)
|
||||
|
||||
fun Session.toTab(store: BrowserStore, publicSuffixList: PublicSuffixList, selected: Boolean? = null): Tab {
|
||||
val url = store.state.findTab(this.id)?.readerState?.activeUrl ?: this.url
|
||||
return Tab(
|
||||
sessionId = this.id,
|
||||
url = url,
|
||||
hostname = url.toShortUrl(publicSuffixList),
|
||||
title = this.title,
|
||||
selected = selected,
|
||||
icon = this.icon,
|
||||
mediaState = getMediaStateForSession(store, this)
|
||||
)
|
||||
}
|
||||
|
||||
private fun getMediaStateForSession(store: BrowserStore, session: Session): MediaState.State {
|
||||
// For now we are looking up the media state for this session in the BrowserStore. Eventually
|
||||
// we will migrate away from Session(Manager) and can use BrowserStore and BrowserState directly.
|
||||
return if (store.state.media.aggregate.activeTabId == session.id) {
|
||||
store.state.media.aggregate.state
|
||||
} else {
|
||||
MediaState.State.NONE
|
||||
}
|
||||
}
|
|
@ -60,9 +60,11 @@ import mozilla.components.browser.menu.item.BrowserMenuImageText
|
|||
import mozilla.components.browser.menu.view.MenuButton
|
||||
import mozilla.components.browser.session.Session
|
||||
import mozilla.components.browser.session.SessionManager
|
||||
import mozilla.components.browser.state.selector.getNormalOrPrivateTabs
|
||||
import mozilla.components.browser.state.selector.normalTabs
|
||||
import mozilla.components.browser.state.selector.privateTabs
|
||||
import mozilla.components.browser.state.state.BrowserState
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.concept.sync.AccountObserver
|
||||
import mozilla.components.concept.sync.AuthType
|
||||
import mozilla.components.concept.sync.OAuthAccount
|
||||
|
@ -90,9 +92,7 @@ import org.mozilla.fenix.ext.metrics
|
|||
import org.mozilla.fenix.ext.nav
|
||||
import org.mozilla.fenix.ext.requireComponents
|
||||
import org.mozilla.fenix.ext.resetPoliciesAfter
|
||||
import org.mozilla.fenix.ext.sessionsOfType
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.ext.toTab
|
||||
import org.mozilla.fenix.home.sessioncontrol.DefaultSessionControlController
|
||||
import org.mozilla.fenix.home.sessioncontrol.SessionControlInteractor
|
||||
import org.mozilla.fenix.home.sessioncontrol.SessionControlView
|
||||
|
@ -145,6 +145,8 @@ class HomeFragment : Fragment() {
|
|||
|
||||
private val sessionManager: SessionManager
|
||||
get() = requireComponents.core.sessionManager
|
||||
private val store: BrowserStore
|
||||
get() = requireComponents.core.store
|
||||
|
||||
private lateinit var homeAppBarOffSetListener: AppBarLayout.OnOffsetChangedListener
|
||||
private val onboarding by lazy { FenixOnboarding(requireContext()) }
|
||||
|
@ -774,10 +776,6 @@ class HomeFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun getNumberOfSessions(private: Boolean = browsingModeManager.mode.isPrivate): Int {
|
||||
return sessionManager.sessionsOfType(private = private).count()
|
||||
}
|
||||
|
||||
private fun registerCollectionStorageObserver() {
|
||||
requireComponents.core.tabCollectionStorage.register(collectionStorageObserver, this)
|
||||
}
|
||||
|
@ -789,7 +787,9 @@ class HomeFragment : Fragment() {
|
|||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
val recyclerView = sessionControlView!!.view
|
||||
delay(ANIM_SCROLL_DELAY)
|
||||
val tabsSize = getNumberOfSessions()
|
||||
val tabsSize = store.state
|
||||
.getNormalOrPrivateTabs(browsingModeManager.mode.isPrivate)
|
||||
.size
|
||||
|
||||
var indexOfCollection = tabsSize + NON_TAB_ITEM_NUM
|
||||
changedCollection?.let { changedCollection ->
|
||||
|
@ -888,14 +888,6 @@ class HomeFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun List<Session>.toTabs(): List<Tab> {
|
||||
val selected = sessionManager.selectedSession
|
||||
|
||||
return map {
|
||||
it.toTab(requireContext(), it == selected)
|
||||
}
|
||||
}
|
||||
|
||||
private fun calculateNewOffset() {
|
||||
homeAppBarOffset = ((homeAppBar.layoutParams as CoordinatorLayout.LayoutParams)
|
||||
.behavior as AppBarLayout.Behavior).topAndBottomOffset
|
||||
|
|
|
@ -10,9 +10,11 @@ import android.widget.ImageButton
|
|||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.appcompat.widget.AppCompatImageButton
|
||||
import androidx.core.content.ContextCompat
|
||||
import mozilla.components.browser.state.state.MediaState
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.browser.tabstray.TabViewHolder
|
||||
import mozilla.components.browser.tabstray.thumbnail.TabThumbnailView
|
||||
import mozilla.components.browser.toolbar.MAX_URI_LENGTH
|
||||
|
@ -26,12 +28,14 @@ import mozilla.components.support.images.loader.ImageLoader
|
|||
import mozilla.components.support.ktx.kotlin.tryGetHostFromUrl
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.metrics.Event
|
||||
import org.mozilla.fenix.components.metrics.MetricController
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.getMediaStateForSession
|
||||
import org.mozilla.fenix.ext.increaseTapArea
|
||||
import org.mozilla.fenix.ext.removeAndDisable
|
||||
import org.mozilla.fenix.ext.removeTouchDelegate
|
||||
import org.mozilla.fenix.ext.showAndEnable
|
||||
import org.mozilla.fenix.ext.toTab
|
||||
import org.mozilla.fenix.utils.Do
|
||||
import kotlin.math.max
|
||||
|
||||
/**
|
||||
|
@ -40,8 +44,11 @@ import kotlin.math.max
|
|||
class TabTrayViewHolder(
|
||||
itemView: View,
|
||||
private val imageLoader: ImageLoader,
|
||||
val getSelectedTabId: () -> String? = { itemView.context.components.core.store.state.selectedTabId }
|
||||
private val store: BrowserStore = itemView.context.components.core.store,
|
||||
private val metrics: MetricController = itemView.context.components.analytics.metrics,
|
||||
val getSelectedTabId: () -> String? = { store.state.selectedTabId }
|
||||
) : TabViewHolder(itemView) {
|
||||
|
||||
private val titleView: TextView = itemView.findViewById(R.id.mozac_browser_tabstray_title)
|
||||
private val closeView: AppCompatImageButton =
|
||||
itemView.findViewById(R.id.mozac_browser_tabstray_close)
|
||||
|
@ -79,16 +86,15 @@ class TabTrayViewHolder(
|
|||
|
||||
// Media state
|
||||
playPauseButtonView.increaseTapArea(PLAY_PAUSE_BUTTON_EXTRA_DPS)
|
||||
val session = itemView.context?.components?.core?.sessionManager?.findSessionById(tab.id)
|
||||
with(playPauseButtonView) {
|
||||
invalidate()
|
||||
when (session?.toTab(itemView.context)?.mediaState) {
|
||||
Do exhaustive when (store.state.getMediaStateForSession(tab.id)) {
|
||||
MediaState.State.PAUSED -> {
|
||||
showAndEnable()
|
||||
contentDescription =
|
||||
context.getString(R.string.mozac_feature_media_notification_action_play)
|
||||
setImageDrawable(
|
||||
androidx.appcompat.content.res.AppCompatResources.getDrawable(
|
||||
AppCompatResources.getDrawable(
|
||||
context,
|
||||
R.drawable.tab_tray_play_with_background
|
||||
)
|
||||
|
@ -100,7 +106,7 @@ class TabTrayViewHolder(
|
|||
contentDescription =
|
||||
context.getString(R.string.mozac_feature_media_notification_action_pause)
|
||||
setImageDrawable(
|
||||
androidx.appcompat.content.res.AppCompatResources.getDrawable(
|
||||
AppCompatResources.getDrawable(
|
||||
context,
|
||||
R.drawable.tab_tray_pause_with_background
|
||||
)
|
||||
|
@ -115,16 +121,15 @@ class TabTrayViewHolder(
|
|||
}
|
||||
|
||||
playPauseButtonView.setOnClickListener {
|
||||
val mState = session?.toTab(itemView.context)?.mediaState
|
||||
when (mState) {
|
||||
Do exhaustive when (store.state.getMediaStateForSession(tab.id)) {
|
||||
MediaState.State.PLAYING -> {
|
||||
itemView.context.components.analytics.metrics.track(Event.TabMediaPause)
|
||||
itemView.context.components.core.store.state.media.pauseIfPlaying()
|
||||
metrics.track(Event.TabMediaPause)
|
||||
store.state.media.pauseIfPlaying()
|
||||
}
|
||||
|
||||
MediaState.State.PAUSED -> {
|
||||
itemView.context.components.analytics.metrics.track(Event.TabMediaPlay)
|
||||
itemView.context.components.core.store.state.media.playIfPaused()
|
||||
metrics.track(Event.TabMediaPlay)
|
||||
store.state.media.playIfPaused()
|
||||
}
|
||||
|
||||
MediaState.State.NONE -> throw AssertionError(
|
||||
|
@ -189,7 +194,7 @@ class TabTrayViewHolder(
|
|||
}
|
||||
|
||||
internal fun updateAccessibilityRowIndex(item: View, newIndex: Int) {
|
||||
item.setAccessibilityDelegate(object : View.AccessibilityDelegate() {
|
||||
item.accessibilityDelegate = object : View.AccessibilityDelegate() {
|
||||
override fun onInitializeAccessibilityNodeInfo(
|
||||
host: View?,
|
||||
info: AccessibilityNodeInfo?
|
||||
|
@ -208,7 +213,7 @@ class TabTrayViewHolder(
|
|||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -7,17 +7,15 @@ package org.mozilla.fenix.collections
|
|||
import io.mockk.MockKAnnotations
|
||||
import io.mockk.every
|
||||
import io.mockk.impl.annotations.MockK
|
||||
import kotlinx.coroutines.CompletableDeferred
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.ObsoleteCoroutinesApi
|
||||
import kotlinx.coroutines.async
|
||||
import mozilla.components.browser.session.Session
|
||||
import mozilla.components.browser.session.SessionManager
|
||||
import mozilla.components.browser.state.state.BrowserState
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.browser.state.state.ReaderState
|
||||
import mozilla.components.browser.state.state.createTab
|
||||
import mozilla.components.feature.tab.collections.Tab
|
||||
import mozilla.components.lib.publicsuffixlist.PublicSuffixList
|
||||
import mozilla.components.support.test.robolectric.createAddedTestFragment
|
||||
import mozilla.components.support.test.robolectric.testContext
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNotNull
|
||||
import org.junit.Assert.assertNull
|
||||
|
@ -25,6 +23,7 @@ import org.junit.Assert.assertTrue
|
|||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
|
||||
private const val URL_MOZILLA = "www.mozilla.org"
|
||||
|
@ -36,31 +35,29 @@ private const val SESSION_ID_BAD_1 = "not a real session id"
|
|||
private const val SESSION_ID_BAD_2 = "definitely not a real session id"
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
@ObsoleteCoroutinesApi
|
||||
@RunWith(FenixRobolectricTestRunner::class)
|
||||
class CollectionCreationFragmentTest {
|
||||
|
||||
@MockK private lateinit var sessionManager: SessionManager
|
||||
@MockK private lateinit var publicSuffixList: PublicSuffixList
|
||||
@MockK private lateinit var store: BrowserStore
|
||||
@MockK(relaxed = true) private lateinit var publicSuffixList: PublicSuffixList
|
||||
|
||||
private val sessionMozilla = Session(initialUrl = URL_MOZILLA, id = SESSION_ID_MOZILLA)
|
||||
private val sessionBcc = Session(initialUrl = URL_BCC, id = SESSION_ID_BCC)
|
||||
private val sessionMozilla = createTab(URL_MOZILLA, id = SESSION_ID_MOZILLA)
|
||||
private val sessionBcc = createTab(URL_BCC, id = SESSION_ID_BCC)
|
||||
private val state = BrowserState(
|
||||
tabs = listOf(sessionMozilla, sessionBcc)
|
||||
)
|
||||
|
||||
@Before
|
||||
fun before() {
|
||||
MockKAnnotations.init(this)
|
||||
every { sessionManager.findSessionById(SESSION_ID_MOZILLA) } answers { sessionMozilla }
|
||||
every { sessionManager.findSessionById(SESSION_ID_BCC) } answers { sessionBcc }
|
||||
every { sessionManager.findSessionById(SESSION_ID_BAD_1) } answers { null }
|
||||
every { sessionManager.findSessionById(SESSION_ID_BAD_2) } answers { null }
|
||||
every { publicSuffixList.stripPublicSuffix(URL_MOZILLA) } answers { GlobalScope.async { URL_MOZILLA } }
|
||||
every { publicSuffixList.stripPublicSuffix(URL_BCC) } answers { GlobalScope.async { URL_BCC } }
|
||||
every { store.state } answers { BrowserState() }
|
||||
every { publicSuffixList.stripPublicSuffix(URL_MOZILLA) } returns CompletableDeferred(URL_MOZILLA)
|
||||
every { publicSuffixList.stripPublicSuffix(URL_BCC) } returns CompletableDeferred(URL_BCC)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `creation dialog shows and can be dismissed`() {
|
||||
val store = testContext.components.core.store
|
||||
every { store.state } returns state
|
||||
|
||||
val fragment = createAddedTestFragment {
|
||||
CollectionCreationFragment().apply {
|
||||
arguments = CollectionCreationFragmentArgs(
|
||||
|
@ -76,9 +73,8 @@ class CollectionCreationFragmentTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN tabs are present in session manager WHEN getTabs is called THEN tabs will be returned`() {
|
||||
val tabs = sessionManager
|
||||
.getTabs(arrayOf(SESSION_ID_MOZILLA, SESSION_ID_BCC), store, publicSuffixList)
|
||||
fun `GIVEN tabs are present in state WHEN getTabs is called THEN tabs will be returned`() {
|
||||
val tabs = state.getTabs(arrayOf(SESSION_ID_MOZILLA, SESSION_ID_BCC), publicSuffixList)
|
||||
|
||||
val hosts = tabs.map { it.hostname }
|
||||
|
||||
|
@ -87,9 +83,8 @@ class CollectionCreationFragmentTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN some tabs are present in session manager WHEN getTabs is called THEN only valid tabs will be returned`() {
|
||||
val tabs = sessionManager
|
||||
.getTabs(arrayOf(SESSION_ID_MOZILLA, SESSION_ID_BAD_1), store, publicSuffixList)
|
||||
fun `GIVEN some tabs are present in state WHEN getTabs is called THEN only valid tabs will be returned`() {
|
||||
val tabs = state.getTabs(arrayOf(SESSION_ID_MOZILLA, SESSION_ID_BAD_1), publicSuffixList)
|
||||
|
||||
val hosts = tabs.map { it.hostname }
|
||||
|
||||
|
@ -98,18 +93,41 @@ class CollectionCreationFragmentTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN tabs are not present in session manager WHEN getTabs is called THEN an empty list will be returned`() {
|
||||
val tabs = sessionManager
|
||||
.getTabs(arrayOf(SESSION_ID_BAD_1, SESSION_ID_BAD_2), store, publicSuffixList)
|
||||
fun `GIVEN tabs are not present in state WHEN getTabs is called THEN an empty list will be returned`() {
|
||||
val tabs = state.getTabs(arrayOf(SESSION_ID_BAD_1, SESSION_ID_BAD_2), publicSuffixList)
|
||||
|
||||
assertEquals(emptyList<Tab>(), tabs)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WHEN getTabs is called will null tabIds THEN an empty list will be returned`() {
|
||||
val tabs = sessionManager
|
||||
.getTabs(null, store, publicSuffixList)
|
||||
val tabs = state.getTabs(null, publicSuffixList)
|
||||
|
||||
assertEquals(emptyList<Tab>(), tabs)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `toTab uses active reader URL`() {
|
||||
val tabWithoutReaderState = createTab(url = "https://example.com", id = "1")
|
||||
|
||||
val tabWithInactiveReaderState = createTab(url = "https://blog.mozilla.org", id = "2",
|
||||
readerState = ReaderState(active = false, activeUrl = null)
|
||||
)
|
||||
|
||||
val tabWithActiveReaderState = createTab(url = "moz-extension://123", id = "3",
|
||||
readerState = ReaderState(active = true, activeUrl = "https://blog.mozilla.org/123")
|
||||
)
|
||||
|
||||
val state = BrowserState(
|
||||
tabs = listOf(tabWithoutReaderState, tabWithInactiveReaderState, tabWithActiveReaderState)
|
||||
)
|
||||
val tabs = state.getTabs(
|
||||
arrayOf(tabWithoutReaderState.id, tabWithInactiveReaderState.id, tabWithActiveReaderState.id),
|
||||
publicSuffixList
|
||||
)
|
||||
|
||||
assertEquals(tabWithoutReaderState.content.url, tabs[0].url)
|
||||
assertEquals(tabWithInactiveReaderState.content.url, tabs[1].url)
|
||||
assertEquals("https://blog.mozilla.org/123", tabs[2].url)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,7 +64,6 @@ import org.mozilla.fenix.components.metrics.MetricController
|
|||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.directionsEq
|
||||
import org.mozilla.fenix.ext.nav
|
||||
import org.mozilla.fenix.ext.toTab
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
import org.mozilla.fenix.home.Tab
|
||||
import org.mozilla.fenix.settings.deletebrowsingdata.deleteAndQuit
|
||||
|
@ -110,11 +109,6 @@ class DefaultBrowserToolbarControllerTest {
|
|||
fun setUp() {
|
||||
MockKAnnotations.init(this)
|
||||
|
||||
mockkStatic(
|
||||
"org.mozilla.fenix.ext.SessionKt"
|
||||
)
|
||||
every { any<Session>().toTab(any()) } returns currentSessionAsTab
|
||||
|
||||
mockkStatic(
|
||||
"org.mozilla.fenix.settings.deletebrowsingdata.DeleteAndQuitKt"
|
||||
)
|
||||
|
@ -138,7 +132,6 @@ class DefaultBrowserToolbarControllerTest {
|
|||
|
||||
@After
|
||||
fun tearDown() {
|
||||
unmockkStatic("org.mozilla.fenix.ext.SessionKt")
|
||||
unmockkStatic("org.mozilla.fenix.settings.deletebrowsingdata.DeleteAndQuitKt")
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.fenix.ext
|
||||
|
||||
import mozilla.components.browser.state.state.BrowserState
|
||||
import mozilla.components.browser.state.state.MediaState
|
||||
import mozilla.components.browser.state.state.createTab
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
|
||||
private const val SESSION_ID_MOZILLA = "0"
|
||||
private const val SESSION_ID_BCC = "1"
|
||||
private const val SESSION_ID_BAD = "not a real session id"
|
||||
|
||||
class BrowserStateTest {
|
||||
|
||||
private val sessionMozilla = createTab(url = "www.mozilla.org", id = SESSION_ID_MOZILLA)
|
||||
private val sessionBcc = createTab(url = "www.bcc.co.uk", id = SESSION_ID_BCC)
|
||||
|
||||
@Test
|
||||
fun `return media state if it matches tab id`() {
|
||||
val state = BrowserState(
|
||||
tabs = listOf(sessionBcc, sessionMozilla),
|
||||
media = MediaState(
|
||||
MediaState.Aggregate(
|
||||
state = MediaState.State.PLAYING,
|
||||
activeTabId = SESSION_ID_MOZILLA
|
||||
))
|
||||
)
|
||||
|
||||
assertEquals(MediaState.State.PLAYING, state.getMediaStateForSession(SESSION_ID_MOZILLA))
|
||||
assertEquals(MediaState.State.NONE, state.getMediaStateForSession(SESSION_ID_BCC))
|
||||
assertEquals(MediaState.State.NONE, state.getMediaStateForSession(SESSION_ID_BAD))
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.fenix.ext
|
||||
|
||||
import io.mockk.mockk
|
||||
import mozilla.components.browser.session.Session
|
||||
import mozilla.components.browser.state.state.BrowserState
|
||||
import mozilla.components.browser.state.state.ReaderState
|
||||
import mozilla.components.browser.state.state.createTab
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.lib.publicsuffixlist.PublicSuffixList
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
|
||||
@RunWith(FenixRobolectricTestRunner::class)
|
||||
class SessionTest {
|
||||
|
||||
@Test
|
||||
fun `toTab uses active reader URL`() {
|
||||
val sessionWithoutReaderState = Session(id = "1", initialUrl = "https://example.com")
|
||||
val tabWithoutReaderState = createTab(url = sessionWithoutReaderState.url, id = sessionWithoutReaderState.id)
|
||||
|
||||
val sessionWithInactiveReaderState = Session(id = "2", initialUrl = "https://blog.mozilla.org")
|
||||
val tabWithInactiveReaderState = createTab(url = sessionWithInactiveReaderState.url, id = sessionWithInactiveReaderState.id,
|
||||
readerState = ReaderState(active = false, activeUrl = null)
|
||||
)
|
||||
|
||||
val sessionWithActiveReaderState = Session(id = "3", initialUrl = "moz-extension://123")
|
||||
val tabWithActiveReaderState = createTab(url = sessionWithActiveReaderState.url, id = sessionWithActiveReaderState.id,
|
||||
readerState = ReaderState(active = true, activeUrl = "https://blog.mozilla.org/123")
|
||||
)
|
||||
|
||||
val tabs = listOf(tabWithoutReaderState, tabWithInactiveReaderState, tabWithActiveReaderState)
|
||||
val store = BrowserStore(BrowserState(tabs))
|
||||
|
||||
val suffixList = mockk<PublicSuffixList>(relaxed = true)
|
||||
assertEquals(sessionWithoutReaderState.url, sessionWithoutReaderState.toTab(store, suffixList).url)
|
||||
assertEquals(sessionWithInactiveReaderState.url, sessionWithInactiveReaderState.toTab(store, suffixList).url)
|
||||
assertEquals("https://blog.mozilla.org/123", sessionWithActiveReaderState.toTab(store, suffixList).url)
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|||
import kotlinx.coroutines.test.TestCoroutineDispatcher
|
||||
import kotlinx.coroutines.test.TestCoroutineScope
|
||||
import mozilla.components.browser.session.SessionManager
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.concept.engine.Engine
|
||||
import mozilla.components.feature.tab.collections.TabCollection
|
||||
import mozilla.components.feature.tabs.TabsUseCases
|
||||
|
@ -43,6 +44,7 @@ class DefaultSessionControlControllerTest {
|
|||
private val navController: NavController = mockk(relaxed = true)
|
||||
private val metrics: MetricController = mockk(relaxed = true)
|
||||
private val sessionManager: SessionManager = mockk(relaxed = true)
|
||||
private val store: BrowserStore = mockk(relaxed = true)
|
||||
private val engine: Engine = mockk(relaxed = true)
|
||||
private val tabCollectionStorage: TabCollectionStorage = mockk(relaxed = true)
|
||||
private val topSiteStorage: TopSiteStorage = mockk(relaxed = true)
|
||||
|
|
|
@ -5,33 +5,54 @@
|
|||
package org.mozilla.fenix.tabtray
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import android.view.View
|
||||
import android.widget.ImageButton
|
||||
import io.mockk.MockKAnnotations
|
||||
import io.mockk.Runs
|
||||
import io.mockk.every
|
||||
import io.mockk.impl.annotations.MockK
|
||||
import io.mockk.just
|
||||
import io.mockk.mockk
|
||||
import io.mockk.spyk
|
||||
import io.mockk.verify
|
||||
import mozilla.components.browser.state.state.BrowserState
|
||||
import mozilla.components.browser.state.state.MediaState
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.browser.toolbar.MAX_URI_LENGTH
|
||||
import mozilla.components.concept.tabstray.Tab
|
||||
import mozilla.components.support.images.ImageLoadRequest
|
||||
import mozilla.components.support.images.loader.ImageLoader
|
||||
import mozilla.components.support.test.robolectric.testContext
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.metrics.MetricController
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
|
||||
@RunWith(FenixRobolectricTestRunner::class)
|
||||
class TabTrayViewHolderTest {
|
||||
|
||||
private lateinit var view: View
|
||||
@MockK private lateinit var imageLoader: ImageLoader
|
||||
@MockK private lateinit var store: BrowserStore
|
||||
@MockK private lateinit var metrics: MetricController
|
||||
private var state = BrowserState()
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
MockKAnnotations.init(this)
|
||||
view = LayoutInflater.from(testContext)
|
||||
.inflate(R.layout.tab_tray_item, null, false)
|
||||
state = BrowserState()
|
||||
|
||||
every { imageLoader.loadIntoView(any(), any(), any(), any()) } just Runs
|
||||
every { store.state } answers { state }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `extremely long URLs are truncated to prevent slowing down the UI`() {
|
||||
val view = LayoutInflater.from(ApplicationProvider.getApplicationContext()).inflate(
|
||||
R.layout.tab_tray_item, null, false
|
||||
)
|
||||
val imageLoader: ImageLoader = mockk()
|
||||
every { imageLoader.loadIntoView(any(), any(), any(), any()) } just Runs
|
||||
val tabViewHolder = spyk(TabTrayViewHolder(view, imageLoader) { null })
|
||||
every { tabViewHolder.updateBackgroundColor(false) } just Runs
|
||||
val tabViewHolder = createViewHolder()
|
||||
|
||||
val extremelyLongUrl = "m".repeat(MAX_URI_LENGTH + 1)
|
||||
val tab = Tab(
|
||||
|
@ -41,5 +62,58 @@ class TabTrayViewHolderTest {
|
|||
tabViewHolder.bind(tab, false, mockk())
|
||||
|
||||
assertEquals("m".repeat(MAX_URI_LENGTH), tabViewHolder.urlView?.text)
|
||||
verify { imageLoader.loadIntoView(any(), ImageLoadRequest("123", 92)) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `show play button if media is paused in tab`() {
|
||||
val playPauseButtonView: ImageButton = view.findViewById(R.id.play_pause_button)
|
||||
val tabViewHolder = createViewHolder()
|
||||
|
||||
val tab = Tab(
|
||||
id = "123",
|
||||
url = "https://example.com"
|
||||
)
|
||||
state = state.copy(
|
||||
media = MediaState(
|
||||
aggregate = MediaState.Aggregate(
|
||||
activeTabId = "123",
|
||||
state = MediaState.State.PAUSED
|
||||
)
|
||||
)
|
||||
)
|
||||
tabViewHolder.bind(tab, false, mockk())
|
||||
|
||||
assertEquals("Play", playPauseButtonView.contentDescription)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `show pause button if media is playing in tab`() {
|
||||
val playPauseButtonView: ImageButton = view.findViewById(R.id.play_pause_button)
|
||||
val tabViewHolder = createViewHolder()
|
||||
|
||||
val tab = Tab(
|
||||
id = "123",
|
||||
url = "https://example.com"
|
||||
)
|
||||
state = state.copy(
|
||||
media = MediaState(
|
||||
aggregate = MediaState.Aggregate(
|
||||
activeTabId = "123",
|
||||
state = MediaState.State.PLAYING
|
||||
)
|
||||
)
|
||||
)
|
||||
tabViewHolder.bind(tab, false, mockk())
|
||||
|
||||
assertEquals("Pause", playPauseButtonView.contentDescription)
|
||||
}
|
||||
|
||||
private fun createViewHolder(getSelectedTabId: () -> String? = { null }) = TabTrayViewHolder(
|
||||
view,
|
||||
imageLoader = imageLoader,
|
||||
store = store,
|
||||
metrics = metrics,
|
||||
getSelectedTabId = getSelectedTabId
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue