For #25381 - Add a setting allowing to toggle Pocket sponsored stories
This commit is contained in:
parent
13c34f16dd
commit
df5786f1e3
|
@ -150,9 +150,15 @@ internal object AppStoreReducer {
|
|||
pocketStories = emptyList(),
|
||||
pocketSponsoredStories = emptyList()
|
||||
)
|
||||
is AppAction.PocketSponsoredStoriesChange -> state.copy(
|
||||
pocketSponsoredStories = action.sponsoredStories
|
||||
)
|
||||
is AppAction.PocketSponsoredStoriesChange -> {
|
||||
val updatedStoriesState = state.copy(
|
||||
pocketSponsoredStories = action.sponsoredStories,
|
||||
)
|
||||
|
||||
updatedStoriesState.copy(
|
||||
pocketStories = updatedStoriesState.getFilteredStories()
|
||||
)
|
||||
}
|
||||
is AppAction.PocketStoriesShown -> {
|
||||
var updatedCategories = state.pocketStoriesCategories
|
||||
action.storiesShown.filterIsInstance<PocketRecommendedStory>().forEach { shownStory ->
|
||||
|
|
|
@ -13,6 +13,8 @@ import androidx.preference.SwitchPreference
|
|||
import org.mozilla.fenix.FeatureFlags
|
||||
import org.mozilla.fenix.GleanMetrics.CustomizeHome
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.appstate.AppAction
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.ext.showToolbar
|
||||
import org.mozilla.fenix.utils.view.addToRadioGroup
|
||||
|
@ -116,6 +118,28 @@ class HomeSettingsFragment : PreferenceFragmentCompat() {
|
|||
}
|
||||
}
|
||||
|
||||
requirePreference<CheckBoxPreference>(R.string.pref_key_pocket_sponsored_stories).apply {
|
||||
isVisible = FeatureFlags.isPocketSponsoredStoriesFeatureEnabled(context)
|
||||
isChecked = context.settings().showPocketSponsoredStories
|
||||
onPreferenceChangeListener = object : SharedPreferenceUpdater() {
|
||||
override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
|
||||
when (newValue) {
|
||||
true -> {
|
||||
context.components.core.pocketStoriesService.startPeriodicSponsoredStoriesRefresh()
|
||||
}
|
||||
false -> {
|
||||
context.components.core.pocketStoriesService.deleteProfile()
|
||||
context.components.appStore.dispatch(
|
||||
AppAction.PocketSponsoredStoriesChange(emptyList())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return super.onPreferenceChange(preference, newValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
requirePreference<SwitchPreference>(R.string.pref_key_history_metadata_feature).apply {
|
||||
isVisible = FeatureFlags.historyMetadataUIFeature
|
||||
isChecked = context.settings().historyMetadataUIFeature
|
||||
|
|
|
@ -1269,6 +1269,9 @@ class Settings(private val appContext: Context) : PreferencesHolder {
|
|||
default = true
|
||||
)
|
||||
|
||||
/**
|
||||
* Indicates if the Pocket recommended stories homescreen section should be shown.
|
||||
*/
|
||||
var showPocketRecommendationsFeature by lazyFeatureFlagPreference(
|
||||
appContext.getPreferenceKey(R.string.pref_key_pocket_homescreen_recommendations),
|
||||
featureFlag = FeatureFlags.isPocketRecommendationsFeatureEnabled(appContext),
|
||||
|
|
|
@ -409,6 +409,8 @@
|
|||
<string name="customize_toggle_recently_visited">Recently visited</string>
|
||||
<!-- Title for the customize home screen section with Pocket. -->
|
||||
<string name="customize_toggle_pocket">Pocket</string>
|
||||
<!-- Title for the customize home screen section with sponsored Pocket stories. -->
|
||||
<string name="customize_toggle_pocket_sponsored">Sponsored stories</string>
|
||||
<!-- Title for the opening wallpaper settings screen -->
|
||||
<string name="customize_wallpapers">Wallpapers</string>
|
||||
<!-- Title for the customize home screen section with sponsored shortcuts. -->
|
||||
|
|
|
@ -35,6 +35,12 @@
|
|||
android:title="@string/customize_toggle_pocket"
|
||||
app:isPreferenceVisible="false" />
|
||||
|
||||
<androidx.preference.CheckBoxPreference
|
||||
android:dependency="@string/pref_key_pocket_homescreen_recommendations"
|
||||
android:layout="@layout/checkbox_left_sub_preference"
|
||||
android:key="@string/pref_key_pocket_sponsored_stories"
|
||||
android:title="@string/customize_toggle_pocket_sponsored" />
|
||||
|
||||
<androidx.preference.Preference
|
||||
android:key="@string/pref_key_wallpapers"
|
||||
android:title="@string/customize_wallpapers" />
|
||||
|
|
|
@ -15,6 +15,7 @@ import mozilla.components.feature.tab.collections.TabCollection
|
|||
import mozilla.components.feature.top.sites.TopSite
|
||||
import mozilla.components.service.fxa.manager.FxaAccountManager
|
||||
import mozilla.components.service.pocket.PocketStory
|
||||
import mozilla.components.service.pocket.PocketStory.PocketRecommendedStory
|
||||
import mozilla.components.service.pocket.PocketStory.PocketSponsoredStory
|
||||
import mozilla.components.service.pocket.PocketStory.PocketSponsoredStoryCaps
|
||||
import org.junit.Assert.assertEquals
|
||||
|
@ -364,7 +365,7 @@ class AppStoreTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `Test updating the list of Pocket sponsored stories`() = runTest {
|
||||
fun `Test updating the list of Pocket sponsored stories also updates the list of stories to show`() = runTest {
|
||||
val story1 = PocketSponsoredStory(
|
||||
id = 3,
|
||||
title = "title",
|
||||
|
@ -379,13 +380,20 @@ class AppStoreTest {
|
|||
|
||||
appStore = AppStore(AppState())
|
||||
|
||||
appStore.dispatch(AppAction.PocketSponsoredStoriesChange(listOf(story1, story2)))
|
||||
.join()
|
||||
assertTrue(appStore.state.pocketSponsoredStories.containsAll(listOf(story1, story2)))
|
||||
mockkStatic("org.mozilla.fenix.ext.AppStateKt") {
|
||||
val firstFilteredStories = listOf(mockk<PocketSponsoredStory>())
|
||||
every { any<AppState>().getFilteredStories() } returns firstFilteredStories
|
||||
appStore.dispatch(AppAction.PocketSponsoredStoriesChange(listOf(story1, story2))).join()
|
||||
assertTrue(appStore.state.pocketSponsoredStories.containsAll(listOf(story1, story2)))
|
||||
assertEquals(firstFilteredStories, appStore.state.pocketStories)
|
||||
|
||||
val updatedStories = listOf(story2.copy(title = "title3"))
|
||||
appStore.dispatch(AppAction.PocketSponsoredStoriesChange(updatedStories)).join()
|
||||
assertTrue(updatedStories.containsAll(appStore.state.pocketSponsoredStories))
|
||||
val secondFilteredStories = firstFilteredStories + mockk<PocketRecommendedStory>()
|
||||
every { any<AppState>().getFilteredStories() } returns secondFilteredStories
|
||||
val updatedStories = listOf(story2.copy(title = "title3"))
|
||||
appStore.dispatch(AppAction.PocketSponsoredStoriesChange(updatedStories)).join()
|
||||
assertTrue(updatedStories.containsAll(appStore.state.pocketSponsoredStories))
|
||||
assertEquals(secondFilteredStories, appStore.state.pocketStories)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
/* 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.settings
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.preference.CheckBoxPreference
|
||||
import io.mockk.Runs
|
||||
import io.mockk.every
|
||||
import io.mockk.just
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkObject
|
||||
import io.mockk.mockkStatic
|
||||
import io.mockk.unmockkStatic
|
||||
import io.mockk.verify
|
||||
import mozilla.components.service.pocket.PocketStoriesService
|
||||
import mozilla.components.support.test.robolectric.testContext
|
||||
import org.junit.After
|
||||
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.FeatureFlags
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.AppStore
|
||||
import org.mozilla.fenix.components.appstate.AppAction
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.getPreferenceKey
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.ext.showToolbar
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
import org.robolectric.Robolectric
|
||||
|
||||
@RunWith(FenixRobolectricTestRunner::class)
|
||||
internal class HomeSettingsFragmentTest {
|
||||
private lateinit var homeSettingsFragment: HomeSettingsFragment
|
||||
private lateinit var sponsoredStoriesSetting: CheckBoxPreference
|
||||
private lateinit var appSettings: Settings
|
||||
private lateinit var appPrefs: SharedPreferences
|
||||
private lateinit var appPrefsEditor: SharedPreferences.Editor
|
||||
private lateinit var pocketService: PocketStoriesService
|
||||
private lateinit var store: AppStore
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
mockkStatic("org.mozilla.fenix.ext.FragmentKt")
|
||||
every { any<Fragment>().showToolbar(any()) } just Runs
|
||||
mockkStatic("org.mozilla.fenix.ext.ContextKt")
|
||||
appPrefsEditor = mockk(relaxed = true)
|
||||
appPrefs = mockk(relaxed = true) {
|
||||
every { edit() } returns appPrefsEditor
|
||||
}
|
||||
appSettings = mockk(relaxed = true) {
|
||||
every { preferences } returns appPrefs
|
||||
}
|
||||
every { any<Context>().settings() } returns appSettings
|
||||
store = mockk(relaxed = true)
|
||||
pocketService = mockk(relaxed = true)
|
||||
every { any<Context>().components } returns mockk {
|
||||
every { appStore } returns store
|
||||
every { core.pocketStoriesService } returns pocketService
|
||||
}
|
||||
|
||||
homeSettingsFragment = HomeSettingsFragment()
|
||||
|
||||
val activity = Robolectric.buildActivity(FragmentActivity::class.java).create().get()
|
||||
activity.supportFragmentManager.beginTransaction()
|
||||
.add(homeSettingsFragment, "HomeSettingFragmentTest")
|
||||
.commitNow()
|
||||
|
||||
sponsoredStoriesSetting = homeSettingsFragment.findPreference(
|
||||
homeSettingsFragment.getPreferenceKey(R.string.pref_key_pocket_sponsored_stories)
|
||||
)!!
|
||||
}
|
||||
|
||||
@After
|
||||
fun teardown() {
|
||||
unmockkStatic("org.mozilla.fenix.ext.ContextKt")
|
||||
unmockkStatic("org.mozilla.fenix.ext.FragmentKt")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN the Pocket sponsored stories feature is disabled for the app WHEN accessing settings THEN the settings for it are not visible`() {
|
||||
every { any<Context>().settings() } returns mockk(relaxed = true)
|
||||
|
||||
mockkObject(FeatureFlags) {
|
||||
every { FeatureFlags.isPocketSponsoredStoriesFeatureEnabled(any()) } returns false
|
||||
|
||||
homeSettingsFragment.onResume()
|
||||
|
||||
assertFalse(sponsoredStoriesSetting.isVisible)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN the Pocket sponsored stories feature is enabled for the app WHEN accessing settings THEN the settings for it are visible`() {
|
||||
every { any<Context>().settings() } returns mockk(relaxed = true)
|
||||
|
||||
mockkObject(FeatureFlags) {
|
||||
every { FeatureFlags.isPocketSponsoredStoriesFeatureEnabled(any()) } returns true
|
||||
|
||||
homeSettingsFragment.onResume()
|
||||
|
||||
assertTrue(sponsoredStoriesSetting.isVisible)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN the Pocket sponsored stories preference is false WHEN accessing settings THEN the setting for it is unchecked`() {
|
||||
every { appSettings.showPocketSponsoredStories } returns false
|
||||
|
||||
homeSettingsFragment.onResume()
|
||||
|
||||
assertFalse(sponsoredStoriesSetting.isChecked)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN the Pocket sponsored stories preference is true WHEN accessing settings THEN the setting for it is checked`() {
|
||||
every { appSettings.showPocketSponsoredStories } returns true
|
||||
|
||||
homeSettingsFragment.onResume()
|
||||
|
||||
assertTrue(sponsoredStoriesSetting.isChecked)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN the setting for Pocket sponsored stories is unchecked WHEN tapping it THEN toggle it and start downloading stories`() {
|
||||
homeSettingsFragment.onResume()
|
||||
|
||||
val result = sponsoredStoriesSetting.callChangeListener(true)
|
||||
|
||||
assertTrue(result)
|
||||
verify { appPrefsEditor.putBoolean(testContext.getString(R.string.pref_key_pocket_sponsored_stories), true) }
|
||||
verify { pocketService.startPeriodicSponsoredStoriesRefresh() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN the setting for Pocket sponsored stories is checked WHEN tapping it THEN toggle it, delete Pocket profile and remove sponsored stories from showing`() {
|
||||
homeSettingsFragment.onResume()
|
||||
|
||||
val result = sponsoredStoriesSetting.callChangeListener(false)
|
||||
|
||||
assertTrue(result)
|
||||
verify { appPrefsEditor.putBoolean(testContext.getString(R.string.pref_key_pocket_sponsored_stories), false) }
|
||||
verify { pocketService.deleteProfile() }
|
||||
verify { store.dispatch(AppAction.PocketSponsoredStoriesChange(emptyList())) }
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user