From d2fa53ff1df7ac9af5a052c8c9c8c39506d32a62 Mon Sep 17 00:00:00 2001 From: sarah541 Date: Tue, 5 Apr 2022 14:25:32 -0400 Subject: [PATCH] [fenix] For https://github.com/mozilla-mobile/fenix/pull/24455 - Migrate NoCollectionsMessageViewHolder to Compose --- .../fenix/ui/robots/HomeScreenRobot.kt | 66 +++++++--- .../fenix/compose/CollectionsPlaceholder.kt | 117 ++++++++++++++++++ .../org/mozilla/fenix/home/HomeFragment.kt | 5 - .../sessioncontrol/SessionControlAdapter.kt | 22 ++-- .../NoCollectionsMessageViewHolder.kt | 84 +++++++------ .../empty_session_control_background.xml | 9 -- .../res/layout/no_collections_message.xml | 69 ----------- app/src/main/res/values/dimens.xml | 1 - .../NoCollectionsMessageViewHolderTest.kt | 78 ------------ 9 files changed, 221 insertions(+), 230 deletions(-) create mode 100644 app/src/main/java/org/mozilla/fenix/compose/CollectionsPlaceholder.kt delete mode 100644 app/src/main/res/drawable/empty_session_control_background.xml delete mode 100644 app/src/main/res/layout/no_collections_message.xml delete mode 100644 app/src/test/java/org/mozilla/fenix/home/sessioncontrol/viewholders/NoCollectionsMessageViewHolderTest.kt diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HomeScreenRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HomeScreenRobot.kt index c1ceb0c807..9c3b6fc5f2 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HomeScreenRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HomeScreenRobot.kt @@ -33,7 +33,6 @@ import androidx.test.uiautomator.Until import androidx.test.uiautomator.Until.findObject import mozilla.components.browser.state.state.searchEngines import org.hamcrest.CoreMatchers.allOf -import org.hamcrest.CoreMatchers.containsString import org.hamcrest.CoreMatchers.instanceOf import org.hamcrest.CoreMatchers.not import org.hamcrest.Matchers @@ -141,7 +140,11 @@ class HomeScreenRobot { fun verifyRecentBookmarksSectionIsDisplayed() = assertRecentBookmarksSectionIsDisplayed() fun verifyRecentBookmarksSectionIsNotDisplayed() = assertRecentBookmarksSectionIsNotDisplayed() - fun verifyRecentlyVisitedSearchGroupDisplayed(shouldBeDisplayed: Boolean, searchTerm: String, groupSize: Int) { + fun verifyRecentlyVisitedSearchGroupDisplayed( + shouldBeDisplayed: Boolean, + searchTerm: String, + groupSize: Int + ) { // checks if the search group exists in the Recently visited section if (shouldBeDisplayed) { recentlyVisitedList.waitForExists(waitingTime) @@ -162,7 +165,11 @@ class HomeScreenRobot { } } - fun verifyCurrentSearchGroupIsDisplayed(shouldBeDisplayed: Boolean, searchTerm: String, groupSize: Int = 0) { + fun verifyCurrentSearchGroupIsDisplayed( + shouldBeDisplayed: Boolean, + searchTerm: String, + groupSize: Int = 0 + ) { // checks search group in the Jump back in section if (shouldBeDisplayed) { assertTrue( @@ -392,7 +399,10 @@ class HomeScreenRobot { return TabDrawerRobot.Transition() } - fun expandCollection(title: String, interact: CollectionRobot.() -> Unit): CollectionRobot.Transition { + fun expandCollection( + title: String, + interact: CollectionRobot.() -> Unit + ): CollectionRobot.Transition { // Depending on the screen dimensions collections might report as visible on screen // but actually have the bottom toolbar above so interactions with collections might fail. // As a quick solution we'll try scrolling to the element below collection on the homescreen @@ -405,8 +415,12 @@ class HomeScreenRobot { return CollectionRobot.Transition() } - fun openRecentlyVisitedSearchGroupHistoryList(title: String, interact: HistoryRobot.() -> Unit): HistoryRobot.Transition { - val searchGroup = recentlyVisitedList.getChildByText(UiSelector().text(title), title, true) + fun openRecentlyVisitedSearchGroupHistoryList( + title: String, + interact: HistoryRobot.() -> Unit + ): HistoryRobot.Transition { + val searchGroup = + recentlyVisitedList.getChildByText(UiSelector().text(title), title, true) searchGroup.waitForExists(waitingTimeShort) searchGroup.click() @@ -438,7 +452,8 @@ private fun assertKeyboardVisibility(isExpectedToBeVisible: Boolean) = .contains("mInputShown=true") ) -private fun navigationToolbar() = mDevice.findObject(UiSelector().resourceId("$packageName:id/toolbar")) +private fun navigationToolbar() = + mDevice.findObject(UiSelector().resourceId("$packageName:id/toolbar")) private fun assertNavigationToolbar() = assertTrue(navigationToolbar().waitForExists(waitingTime)) @@ -447,7 +462,8 @@ private fun assertFocusedNavigationToolbar() = .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) private fun assertHomeScreen() { - mDevice.findObject(UiSelector().resourceId("$packageName:id/homeLayout")).waitForExists(waitingTime) + mDevice.findObject(UiSelector().resourceId("$packageName:id/homeLayout")) + .waitForExists(waitingTime) onView(ViewMatchers.withResourceName("homeLayout")) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) } @@ -471,18 +487,23 @@ private fun assertTabButton() = .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) private fun assertCollectionsHeader() = - onView(allOf(withText("Collections"))) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + assertTrue( + mDevice.findObject( + UiSelector().textContains( + "Collections" + ) + ).waitForExists(waitingTime) + ) private fun assertNoCollectionsText() = - onView( - withText( - containsString( + assertTrue( + mDevice.findObject( + UiSelector().textContains( "Collect the things that matter to you.\n" + "Group together similar searches, sites, and tabs for quick access later." ) - ) - ).check(matches(isDisplayed())) + ).waitForExists(waitingTime) + ) private fun assertHomeComponent() = onView(ViewMatchers.withResourceName("sessionControlRecyclerView")) @@ -521,6 +542,7 @@ private fun assertStartSyncHeader() { onView(allOf(withText(R.string.onboarding_account_sign_in_header_1))) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) } + private fun assertAccountsSignInButton() = onView(ViewMatchers.withResourceName("fxa_sign_in_button")) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) @@ -530,6 +552,7 @@ private fun assertChooseThemeHeader() { onView(withText("Choose your theme")) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) } + private fun assertChooseThemeText() { scrollToElementByText("Choose your theme") onView(allOf(withText("Save some battery and your eyesight with dark mode."))) @@ -559,6 +582,7 @@ private fun assertDarkThemeDescription() { onView(allOf(withText("Dark theme"))) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) } + private fun assertAutomaticThemeToggle() { scrollToElementByText("Choose your theme") onView(withId(R.id.theme_automatic_radio_button)) @@ -686,9 +710,11 @@ private fun assertTopSiteContextMenuItems() { ) } -private fun assertJumpBackInSectionIsDisplayed() = assertTrue(jumpBackInSection().waitForExists(waitingTime)) +private fun assertJumpBackInSectionIsDisplayed() = + assertTrue(jumpBackInSection().waitForExists(waitingTime)) -private fun assertJumpBackInSectionIsNotDisplayed() = assertFalse(jumpBackInSection().waitForExists(waitingTimeShort)) +private fun assertJumpBackInSectionIsNotDisplayed() = + assertFalse(jumpBackInSection().waitForExists(waitingTimeShort)) private fun assertRecentBookmarksSectionIsDisplayed() = assertTrue(recentBookmarksSection().waitForExists(waitingTime)) @@ -698,7 +724,8 @@ private fun assertRecentBookmarksSectionIsNotDisplayed() = private fun privateBrowsingButton() = onView(withId(R.id.privateBrowsingButton)) -private fun saveTabsToCollectionButton() = onView(withId(R.id.add_tabs_to_collections_button)) +private fun saveTabsToCollectionButton() = + mDevice.findObject(UiSelector().textContains(getStringResource(R.string.tabs_menu_save_to_collection1))) private fun tabsCounter() = onView(withId(R.id.tab_button)) @@ -709,7 +736,8 @@ private fun recentBookmarksSection() = mDevice.findObject(UiSelector().textContains(getStringResource(R.string.recent_bookmarks_title))) private fun startBrowsingButton(): UiObject { - val startBrowsingButton = mDevice.findObject(UiSelector().resourceId("$packageName:id/finish_button")) + val startBrowsingButton = + mDevice.findObject(UiSelector().resourceId("$packageName:id/finish_button")) homeScreenList() .scrollIntoView(startBrowsingButton) homeScreenList() diff --git a/app/src/main/java/org/mozilla/fenix/compose/CollectionsPlaceholder.kt b/app/src/main/java/org/mozilla/fenix/compose/CollectionsPlaceholder.kt new file mode 100644 index 0000000000..00fc885c59 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/compose/CollectionsPlaceholder.kt @@ -0,0 +1,117 @@ +/* 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.compose + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.Spacer +import androidx.compose.material.Icon +import androidx.compose.material.IconButton +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import org.mozilla.fenix.R +import org.mozilla.fenix.compose.button.PrimaryButton +import org.mozilla.fenix.compose.ext.dashedBorder +import org.mozilla.fenix.theme.FirefoxTheme +import org.mozilla.fenix.theme.Theme + +/** + * [CollectionsPlaceholder] for displaying a message detailing the collections feature and + * allowing users to easily start creating their collection. + * + * @param showAddToCollectionButton Whether or not the "Add to Collection" button should be shown. + * @param onAddTabsToCollectionButtonClick Invoked when the user clicks on the "Add Tabs to Collection" button. + * @param onRemovePlaceholderClick Invoked when the user clicks on the close button to remove the Collections + * placeholder. + */ +@Composable +fun CollectionsPlaceholder( + showAddToCollectionButton: Boolean, + onAddTabsToCollectionButtonClick: () -> Unit, + onRemovePlaceholderClick: () -> Unit, +) { + Box( + modifier = Modifier + .semantics(mergeDescendants = true) {} + .dashedBorder( + color = FirefoxTheme.colors.borderPrimary, + cornerRadius = 8.dp, + dashHeight = 2.dp, + dashWidth = 4.dp + ) + ) { + Column( + Modifier + .padding(16.dp) + .fillMaxWidth() + ) { + Row( + modifier = Modifier.fillMaxWidth(), + ) { + SectionHeader( + text = stringResource(R.string.collections_header), + modifier = Modifier.weight(1f) + ) + + IconButton( + onClick = onRemovePlaceholderClick, + modifier = Modifier.size(20.dp), + ) { + Icon( + painter = painterResource(R.drawable.ic_close), + contentDescription = stringResource( + R.string.remove_home_collection_placeholder_content_description + ), + tint = FirefoxTheme.colors.iconPrimary + ) + } + } + + Spacer(modifier = Modifier.height(4.dp)) + + SecondaryText( + text = stringResource(R.string.no_collections_description2), + modifier = Modifier.fillMaxWidth(), + fontSize = 14.sp + ) + + if (showAddToCollectionButton) { + Spacer(modifier = Modifier.height(12.dp)) + + PrimaryButton( + text = stringResource(R.string.tabs_menu_save_to_collection1), + icon = painterResource(R.drawable.ic_tab_collection), + onClick = onAddTabsToCollectionButtonClick + ) + } + } + } +} + +@Composable +@Preview +private fun CollectionsPlaceholderPreview() { + FirefoxTheme(theme = Theme.getTheme(isPrivate = false)) { + Box(Modifier.background(FirefoxTheme.colors.layer1)) { + CollectionsPlaceholder( + showAddToCollectionButton = true, + onAddTabsToCollectionButtonClick = {}, + onRemovePlaceholderClick = {} + ) + } + } +} diff --git a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt index 026cc09e09..b84addc36f 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt @@ -28,7 +28,6 @@ import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID import androidx.constraintlayout.widget.ConstraintSet.TOP import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.core.content.ContextCompat -import androidx.core.view.isVisible import androidx.core.view.updateLayoutParams import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels @@ -37,7 +36,6 @@ import androidx.lifecycle.lifecycleScope import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs import com.google.android.material.appbar.AppBarLayout -import com.google.android.material.button.MaterialButton import com.google.android.material.snackbar.Snackbar import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.Main @@ -1069,9 +1067,6 @@ class HomeFragment : Fragment() { } binding.tabButton.setCountWithAnimation(tabCount) - // The add_tabs_to_collections_button is added at runtime. We need to search for it in the same way. - sessionControlView?.view?.findViewById(R.id.add_tabs_to_collections_button) - ?.isVisible = tabCount > 0 } private fun displayWallpaperIfEnabled() { diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapter.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapter.kt index 5e4f6cd7d5..26b45facd1 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapter.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapter.kt @@ -171,7 +171,8 @@ sealed class AdapterItem(@LayoutRes val viewType: Int) { object PocketStoriesItem : AdapterItem(PocketStoriesViewHolder.LAYOUT_ID) object PocketCategoriesItem : AdapterItem(PocketCategoriesViewHolder.LAYOUT_ID) - object PocketRecommendationsFooterItem : AdapterItem(PocketRecommendationsHeaderViewHolder.LAYOUT_ID) + object PocketRecommendationsFooterItem : + AdapterItem(PocketRecommendationsHeaderViewHolder.LAYOUT_ID) object BottomSpacer : AdapterItem(BottomSpacerViewHolder.LAYOUT_ID) @@ -272,19 +273,21 @@ class SessionControlAdapter( composeView = ComposeView(parent.context), viewLifecycleOwner = viewLifecycleOwner ) + NoCollectionsMessageViewHolder.LAYOUT_ID -> return NoCollectionsMessageViewHolder( + composeView = ComposeView(parent.context), + viewLifecycleOwner = viewLifecycleOwner, + interactor = interactor + ) } val view = LayoutInflater.from(parent.context).inflate(viewType, parent, false) return when (viewType) { TopPlaceholderViewHolder.LAYOUT_ID -> TopPlaceholderViewHolder(view) - TopSitePagerViewHolder.LAYOUT_ID -> TopSitePagerViewHolder(view, viewLifecycleOwner, interactor) - NoCollectionsMessageViewHolder.LAYOUT_ID -> - NoCollectionsMessageViewHolder( - view, - viewLifecycleOwner, - components.core.store, - interactor - ) + TopSitePagerViewHolder.LAYOUT_ID -> TopSitePagerViewHolder( + view = view, + viewLifecycleOwner = viewLifecycleOwner, + interactor = interactor + ) CollectionViewHolder.LAYOUT_ID -> CollectionViewHolder(view, interactor) TabInCollectionViewHolder.LAYOUT_ID -> TabInCollectionViewHolder( view as WidgetSiteItemView, @@ -315,6 +318,7 @@ class SessionControlAdapter( when (holder) { is CollectionHeaderViewHolder, is CustomizeHomeButtonViewHolder, + is NoCollectionsMessageViewHolder, is RecentlyVisitedViewHolder, is RecentVisitsHeaderViewHolder, is RecentBookmarksViewHolder, diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/NoCollectionsMessageViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/NoCollectionsMessageViewHolder.kt index 8311a8949e..9846ea58ec 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/NoCollectionsMessageViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/NoCollectionsMessageViewHolder.kt @@ -5,59 +5,63 @@ package org.mozilla.fenix.home.sessioncontrol.viewholders import android.view.View -import androidx.core.view.isVisible +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.ComposeView +import androidx.compose.ui.unit.dp import androidx.lifecycle.LifecycleOwner -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.collect -import kotlinx.coroutines.flow.map import mozilla.components.browser.state.selector.normalTabs -import mozilla.components.browser.state.store.BrowserStore -import mozilla.components.lib.state.ext.flowScoped -import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifChanged +import mozilla.components.lib.state.ext.observeAsComposableState import org.mozilla.fenix.R -import org.mozilla.fenix.databinding.NoCollectionsMessageBinding -import org.mozilla.fenix.ext.increaseTapArea +import org.mozilla.fenix.components.components +import org.mozilla.fenix.compose.CollectionsPlaceholder +import org.mozilla.fenix.compose.ComposeViewHolder import org.mozilla.fenix.home.sessioncontrol.CollectionInteractor -import org.mozilla.fenix.utils.view.ViewHolder -@OptIn(ExperimentalCoroutinesApi::class) -open class NoCollectionsMessageViewHolder( - view: View, +/** + * [RecyclerView.ComposeViewHolder] for displaying a message detailing the collections feature and + * allowing users to easily start creating their first. + * + * @param composeView [ComposeView] which will be populated with Jetpack Compose UI content. + * @param viewLifecycleOwner [LifecycleOwner] to which this Composable will be tied to. + * @param interactor [CollectionInteractor] callback for user interaction. + */ +class NoCollectionsMessageViewHolder( + composeView: ComposeView, viewLifecycleOwner: LifecycleOwner, - store: BrowserStore, - interactor: CollectionInteractor -) : ViewHolder(view) { + private val interactor: CollectionInteractor +) : ComposeViewHolder(composeView, viewLifecycleOwner) { init { - val binding = NoCollectionsMessageBinding.bind(view) + val horizontalPadding = + composeView.resources.getDimensionPixelSize(R.dimen.home_item_horizontal_margin) + composeView.setPadding(horizontalPadding, 0, horizontalPadding, 0) + } - binding.addTabsToCollectionsButton.apply { + companion object { + val LAYOUT_ID = View.generateViewId() + } - setOnClickListener { - interactor.onAddTabsToCollectionTapped() - } - isVisible = store.state.normalTabs.isNotEmpty() - } + @Composable + override fun Content() { + val normalTabsState = components.core.store.observeAsComposableState { + state -> + state.normalTabs + }.value ?: emptyList() + + Column { + Spacer(modifier = Modifier.height(40.dp)) - binding.removeCollectionPlaceholder.apply { - increaseTapArea( - view.resources.getDimensionPixelSize(R.dimen.tap_increase_16) + CollectionsPlaceholder( + showAddToCollectionButton = normalTabsState.isNotEmpty(), + onAddTabsToCollectionButtonClick = interactor::onAddTabsToCollectionTapped, + onRemovePlaceholderClick = interactor::onRemoveCollectionsPlaceholder ) - setOnClickListener { - interactor.onRemoveCollectionsPlaceholder() - } - } - store.flowScoped(viewLifecycleOwner) { flow -> - flow.map { state -> state.normalTabs.size } - .ifChanged() - .collect { tabs -> - binding.addTabsToCollectionsButton.isVisible = tabs > 0 - } + Spacer(modifier = Modifier.height(12.dp)) } } - - companion object { - const val LAYOUT_ID = R.layout.no_collections_message - } } diff --git a/app/src/main/res/drawable/empty_session_control_background.xml b/app/src/main/res/drawable/empty_session_control_background.xml deleted file mode 100644 index 8c45e84f37..0000000000 --- a/app/src/main/res/drawable/empty_session_control_background.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - diff --git a/app/src/main/res/layout/no_collections_message.xml b/app/src/main/res/layout/no_collections_message.xml deleted file mode 100644 index 377d9848f0..0000000000 --- a/app/src/main/res/layout/no_collections_message.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 6c263a1305..bccdff53b6 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -187,5 +187,4 @@ 48dp - 16dp diff --git a/app/src/test/java/org/mozilla/fenix/home/sessioncontrol/viewholders/NoCollectionsMessageViewHolderTest.kt b/app/src/test/java/org/mozilla/fenix/home/sessioncontrol/viewholders/NoCollectionsMessageViewHolderTest.kt deleted file mode 100644 index 95aac9aea1..0000000000 --- a/app/src/test/java/org/mozilla/fenix/home/sessioncontrol/viewholders/NoCollectionsMessageViewHolderTest.kt +++ /dev/null @@ -1,78 +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.home.sessioncontrol.viewholders - -import android.view.LayoutInflater -import androidx.core.view.isVisible -import androidx.lifecycle.LifecycleOwner -import io.mockk.mockk -import io.mockk.verify -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.robolectric.testContext -import org.junit.Assert.assertFalse -import org.junit.Assert.assertTrue -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.mozilla.fenix.databinding.NoCollectionsMessageBinding -import org.mozilla.fenix.helpers.FenixRobolectricTestRunner -import org.mozilla.fenix.home.sessioncontrol.CollectionInteractor - -@RunWith(FenixRobolectricTestRunner::class) -class NoCollectionsMessageViewHolderTest { - - private lateinit var binding: NoCollectionsMessageBinding - private val store: BrowserStore = BrowserStore( - initialState = BrowserState( - listOf( - createTab("https://www.mozilla.org", id = "reader-inactive-tab") - ) - ) - ) - private lateinit var lifecycleOwner: LifecycleOwner - private lateinit var interactor: CollectionInteractor - - @Before - fun setup() { - binding = NoCollectionsMessageBinding.inflate(LayoutInflater.from(testContext)) - lifecycleOwner = mockk(relaxed = true) - interactor = mockk(relaxed = true) - } - - @Test - fun `hide add to collection button when there are no tabs open`() { - val noTabsStore = BrowserStore() - NoCollectionsMessageViewHolder(binding.root, lifecycleOwner, noTabsStore, interactor) - - assertFalse(binding.addTabsToCollectionsButton.isVisible) - } - - @Test - fun `show add to collection button when there are tabs`() { - NoCollectionsMessageViewHolder(binding.root, lifecycleOwner, store, interactor) - - assertTrue(binding.addTabsToCollectionsButton.isVisible) - } - - @Test - fun `call interactor on click`() { - NoCollectionsMessageViewHolder(binding.root, lifecycleOwner, store, interactor) - - binding.addTabsToCollectionsButton.performClick() - verify { interactor.onAddTabsToCollectionTapped() } - } - - @Test - fun `hide view and change setting on remove placeholder click`() { - NoCollectionsMessageViewHolder(binding.root, lifecycleOwner, store, interactor) - - binding.removeCollectionPlaceholder.performClick() - verify { - interactor.onRemoveCollectionsPlaceholder() - } - } -}