Repository: wordpress-mobile/WordPress-Android (language: kotlin)

Issue:
[Reader] Implement feature flag for tags IA
- Only display "Tags" feed item if the FF is enabled.
- Only hide the "Tags" chip from "Subscriptions" feed if the FF is enabled.


Discussion hints:
Thanks for reporting! 👍 <!-- generated_by_dangermattic -->


Pull request: [Reader] Implement Tags IA feature flag
Fixes #20595 

-----

## To Test:

- Install JP and sign in.
- Enable remote feature `reader_tags_feed`.
- Open "Reader".
- 🔍  Open the dropdown menu: "Tags" feed should be in the list.
- Disable remote feature `reader_tags_feed`.
- Restart the app.
- 🔍 Open "Reader" and dropdown menu: "Tags" feed should **not** be in the list.

-----

## Regression Notes

1. Potential unintended areas of impact

    - None.

2. What I did to test those areas of impact (or what existing automated tests I relied on)

    - Manual testing.

3. What automated tests I added (or what prevented me from doing so)

    --

-----

## PR Submission Checklist:

- [x] I have completed the Regression Notes.
- [x] I have considered adding accessibility improvements for my changes.
- [x] I have considered if this change warrants user-facing release notes and have added them to `RELEASE-NOTES.txt` if necessary.

-----

## Testing Checklist (strike-out the not-applying and unnecessary ones):

- [ ] WordPress.com sites and self-hosted Jetpack sites.
- [ ] Portrait and landscape orientations.
- [ ] Light and dark modes.
- [ ] Fonts: Larger, smaller and bold text.
- [ ] High contrast.
- [ ] Talkback.
- [ ] Languages with large words or with letters/accents not frequently used in English.
- [ ] Right-to-left languages. (Even if translation isn’t complete, formatting should still respect the right-to-left layout)
- [ ] Large and small screen sizes. (Tablet and smaller phones)
- [ ] Multi-tasking: Split screen and Pop-up view. (Android 10 or higher)


Test command: ./gradlew :WordPress:testWordpressVanillaDebugUnitTest --tests "org.wordpress.android.ui.reader.viewmodels.ReaderViewModelTest" --tests "org.wordpress.android.ui.reader.utils.ReaderTopBarMenuHelperTest"

Fix patch:
diff --git a/WordPress/build.gradle b/WordPress/build.gradle
index e3f33b5c6cf4..8b9c6ad61d76 100644
--- a/WordPress/build.gradle
+++ b/WordPress/build.gradle
@@ -150,6 +150,7 @@ android {
         buildConfigField "boolean", "READER_DISCOVER_NEW_ENDPOINT", "false"
         buildConfigField "boolean", "READER_READING_PREFERENCES", "false"
         buildConfigField "boolean", "READER_READING_PREFERENCES_FEEDBACK", "false"
+        buildConfigField "boolean", "READER_TAGS_FEED", "false"
 
         // Override these constants in jetpack product flavor to enable/ disable features
         buildConfigField "boolean", "ENABLE_SITE_CREATION", "true"
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/utils/ReaderTopBarMenuHelper.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/utils/ReaderTopBarMenuHelper.kt
index 466c642f271f..ba94c014f5c5 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/reader/utils/ReaderTopBarMenuHelper.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/utils/ReaderTopBarMenuHelper.kt
@@ -10,10 +10,13 @@ import org.wordpress.android.models.ReaderTagList
 import org.wordpress.android.models.ReaderTagType
 import org.wordpress.android.ui.compose.components.menu.dropdown.MenuElementData
 import org.wordpress.android.ui.utils.UiString
+import org.wordpress.android.util.config.ReaderTagsFeedFeatureConfig
 import org.wordpress.android.util.extensions.indexOrNull
 import javax.inject.Inject
 
-class ReaderTopBarMenuHelper @Inject constructor() {
+class ReaderTopBarMenuHelper @Inject constructor(
+    private val readerTagsFeedFeatureConfig: ReaderTagsFeedFeatureConfig
+) {
     fun createMenu(readerTagsList: ReaderTagList): List<MenuElementData> {
         return mutableListOf<MenuElementData>().apply {
             readerTagsList.indexOrNull { it.isDiscover }?.let { discoverIndex ->
@@ -37,8 +40,10 @@ class ReaderTopBarMenuHelper @Inject constructor() {
                     text = readerTagsList[followedP2sIndex].tagTitle,
                 ))
             }
-            readerTagsList.indexOrNull { it.isTags }?.let { tagsIndex ->
-                add(createTagsItem(getMenuItemIdFromReaderTagIndex(tagsIndex)))
+            if (readerTagsFeedFeatureConfig.isEnabled()) {
+                readerTagsList.indexOrNull { it.isTags }?.let { tagsIndex ->
+                    add(createTagsItem(getMenuItemIdFromReaderTagIndex(tagsIndex)))
+                }
             }
             readerTagsList
                 .foldIndexed(SparseArrayCompat<ReaderTag>()) { index, sparseArray, readerTag ->
diff --git a/WordPress/src/main/java/org/wordpress/android/util/config/ReaderTagsFeedFeatureConfig.kt b/WordPress/src/main/java/org/wordpress/android/util/config/ReaderTagsFeedFeatureConfig.kt
new file mode 100644
index 000000000000..a41e596b5b2f
--- /dev/null
+++ b/WordPress/src/main/java/org/wordpress/android/util/config/ReaderTagsFeedFeatureConfig.kt
@@ -0,0 +1,16 @@
+package org.wordpress.android.util.config
+
+import org.wordpress.android.BuildConfig
+import org.wordpress.android.annotation.Feature
+import javax.inject.Inject
+
+private const val READER_TAGS_FEED_REMOTE_FIELD = "reader_tags_feed"
+
+@Feature(remoteField = READER_TAGS_FEED_REMOTE_FIELD, defaultValue = false)
+class ReaderTagsFeedFeatureConfig @Inject constructor(
+    appConfig: AppConfig
+) : FeatureConfig(
+    appConfig,
+    BuildConfig.READER_TAGS_FEED,
+    READER_TAGS_FEED_REMOTE_FIELD,
+)


Test patch:
diff --git a/WordPress/src/test/java/org/wordpress/android/ui/reader/utils/ReaderTopBarMenuHelperTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/reader/utils/ReaderTopBarMenuHelperTest.kt
index 0279f25bee2d..03e57616424e 100644
--- a/WordPress/src/test/java/org/wordpress/android/ui/reader/utils/ReaderTopBarMenuHelperTest.kt
+++ b/WordPress/src/test/java/org/wordpress/android/ui/reader/utils/ReaderTopBarMenuHelperTest.kt
@@ -4,6 +4,7 @@ import org.assertj.core.api.Assertions.assertThat
 import org.junit.Test
 import org.mockito.kotlin.doReturn
 import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
 import org.wordpress.android.R
 import org.wordpress.android.models.ReaderTag
 import org.wordpress.android.models.ReaderTagList
@@ -11,12 +12,18 @@ import org.wordpress.android.models.ReaderTagType
 import org.wordpress.android.ui.compose.components.menu.dropdown.MenuElementData
 import org.wordpress.android.ui.utils.UiString.UiStringRes
 import org.wordpress.android.ui.utils.UiString.UiStringText
+import org.wordpress.android.util.config.ReaderTagsFeedFeatureConfig
 
 class ReaderTopBarMenuHelperTest {
-    val helper = ReaderTopBarMenuHelper()
+    private val readerTagsFeedFeatureConfig: ReaderTagsFeedFeatureConfig = mock()
+    val helper = ReaderTopBarMenuHelper(
+        readerTagsFeedFeatureConfig = readerTagsFeedFeatureConfig
+    )
 
     @Test
-    fun `GIVEN all tags are available WHEN createMenu THEN all items are created correctly`() {
+    fun `GIVEN all tags are available and tags FF disabled WHEN createMenu THEN all items are created correctly`() {
+        whenever(readerTagsFeedFeatureConfig.isEnabled()).thenReturn(false)
+
         val tags = ReaderTagList().apply {
             add(mockFollowingTag()) // item 0
             add(mockDiscoverTag()) // item 1
@@ -65,6 +72,62 @@ class ReaderTopBarMenuHelperTest {
         assertThat(customList3Item.text).isEqualTo(UiStringText("custom-list-3"))
     }
 
+    @Test
+    fun `GIVEN all tags are available and tags FF enabled WHEN createMenu THEN all items are created correctly`() {
+        whenever(readerTagsFeedFeatureConfig.isEnabled()).thenReturn(true)
+
+        val tags = ReaderTagList().apply {
+            add(mockFollowingTag()) // item 0
+            add(mockDiscoverTag()) // item 1
+            add(mockSavedTag()) // item 2
+            add(mockLikedTag()) // item 3
+            add(mockTagsTag()) // item 4
+            add(mockA8CTag()) // item 5
+            add(mockFollowedP2sTag()) // item 6
+            add(createCustomListTag("custom-list-1")) // item 7
+            add(createCustomListTag("custom-list-2")) // item 8
+            add(createCustomListTag("custom-list-3")) // item 9
+        }
+
+        val menu = helper.createMenu(tags)
+
+        // compare the menu items one by one to check their indices
+        val discoverItem = menu.findSingleItem { it.id == "1" }!!
+        assertThat(discoverItem.text).isEqualTo(UiStringRes(R.string.reader_dropdown_menu_discover))
+
+        val subscriptionsItem = menu.findSingleItem { it.id == "0" }!!
+        assertThat(subscriptionsItem.text).isEqualTo(UiStringRes(R.string.reader_dropdown_menu_subscriptions))
+
+        val savedItem = menu.findSingleItem { it.id == "2" }!!
+        assertThat(savedItem.text).isEqualTo(UiStringRes(R.string.reader_dropdown_menu_saved))
+
+        val likedItem = menu.findSingleItem { it.id == "3" }!!
+        assertThat(likedItem.text).isEqualTo(UiStringRes(R.string.reader_dropdown_menu_liked))
+
+        val tagsItem = menu.findSingleItem { it.id == "4" }!!
+        assertThat(tagsItem.text).isEqualTo(UiStringRes(R.string.reader_dropdown_menu_tags))
+
+        val a8cItem = menu.findSingleItem { it.id == "5" }!!
+        assertThat(a8cItem.text).isEqualTo(UiStringRes(R.string.reader_dropdown_menu_automattic))
+
+        val followedP2sItem = menu.findSingleItem { it.id == "6" }!!
+        assertThat(followedP2sItem.text).isEqualTo(UiStringText("Followed P2s"))
+
+        assertThat(menu).contains(MenuElementData.Divider)
+
+        val customListsItem = menu.findSubMenu()!!
+        assertThat(customListsItem.text).isEqualTo(UiStringRes(R.string.reader_dropdown_menu_lists))
+
+        val customList1Item = customListsItem.children.findSingleItem { it.id == "7" }!!
+        assertThat(customList1Item.text).isEqualTo(UiStringText("custom-list-1"))
+
+        val customList2Item = customListsItem.children.findSingleItem { it.id == "8" }!!
+        assertThat(customList2Item.text).isEqualTo(UiStringText("custom-list-2"))
+
+        val customList3Item = customListsItem.children.findSingleItem { it.id == "9" }!!
+        assertThat(customList3Item.text).isEqualTo(UiStringText("custom-list-3"))
+    }
+
     @Test
     fun `GIVEN discover not present WHEN createMenu THEN discover menu item not created`() {
         val tags = ReaderTagList().apply {
@@ -275,6 +338,12 @@ class ReaderTopBarMenuHelperTest {
         }
     }
 
+    private fun mockTagsTag(): ReaderTag {
+        return mock {
+            on { isTags } doReturn true
+        }
+    }
+
     private fun createCustomListTag(title: String): ReaderTag {
         return ReaderTag(
             title,
diff --git a/WordPress/src/test/java/org/wordpress/android/ui/reader/viewmodels/ReaderViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/reader/viewmodels/ReaderViewModelTest.kt
index bc6e73735645..bb9c557587bd 100644
--- a/WordPress/src/test/java/org/wordpress/android/ui/reader/viewmodels/ReaderViewModelTest.kt
+++ b/WordPress/src/test/java/org/wordpress/android/ui/reader/viewmodels/ReaderViewModelTest.kt
@@ -42,6 +42,7 @@ import org.wordpress.android.ui.reader.viewmodels.ReaderViewModel.TopBarUiState
 import org.wordpress.android.util.JetpackBrandingUtils
 import org.wordpress.android.util.SnackbarSequencer
 import org.wordpress.android.util.UrlUtilsWrapper
+import org.wordpress.android.util.config.ReaderTagsFeedFeatureConfig
 import org.wordpress.android.viewmodel.Event
 import java.util.Date
 
@@ -85,7 +86,9 @@ class ReaderViewModelTest : BaseUnitTest() {
     @Mock
     lateinit var jetpackFeatureRemovalOverlayUtil: JetpackFeatureRemovalOverlayUtil
 
-    private val readerTopBarMenuHelper: ReaderTopBarMenuHelper = ReaderTopBarMenuHelper()
+    private val readerTagsFeedFeatureConfig: ReaderTagsFeedFeatureConfig = mock()
+
+    private val readerTopBarMenuHelper: ReaderTopBarMenuHelper = ReaderTopBarMenuHelper(readerTagsFeedFeatureConfig)
 
 
     private val emptyReaderTagList = ReaderTagList()