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

Issue:
[Bloganuary] Add Bloganuary tags to prompt answers
Use `bloganuaryId` field from `BloggingPromptModel` to get one of the bloganuary tags for the post, the other tag should be `bloganuary` and should be added if the `bloganuaryId` field is present.


Discussion hints:
nan

Pull request: [Bloganuary] Add bloganuary tags to Bloganuary prompt answers
Fixes #19588 

If the prompt returned by the API has the `bloganuary_id`, and therefore the `BloggingPromptModel` from FluxC has the `bloganuaryId` field, then we should also add the `bloganuary` and `bloganuary-YYYY-DD` tags (this second one IS the content of the `bloganuaryId` field).

## To test
Since this relies on the response from the backend and Bloganuary prompts will only be available in January, we need to mock the response for testing it, for that you will need to setup Charles and use the `Map Local` feature.

### Setup
- Download and setup [Charles proxy](https://www.charlesproxy.com/)
- With Charles running, set up the test device WiFi connection to use Charles (don't forget to setup the certificates so it can intercept HTTPS requests)
- Setup the `SSL Proxying` settings to include the `public-api.wordpress.com` host location
- Setup a `Map Local` entry as following:

The fields for the new `Map Local` entry should be:

**Map From**
Protocol: `https`
Host: `public-api.wordpress.com`
Path: `wpcom/v3/sites/*/blogging-prompts/`
Query: `per_page=20&after=*&force_year=2023&order=desc&locale=en_US`

**Map To**
Local path: [mocked_bloganuary_response.json](https://github.com/wordpress-mobile/WordPress-Android/files/13312455/mocked_bloganuary_response.json) (download and put this file somewhere and choose it for this field)

![image](https://github.com/wordpress-mobile/WordPress-Android/assets/5091503/1fde758d-564b-45e0-a0e6-37de6e558cf5)

#### Notes
1. This file should be OK for testing up to November 28, it makes all entries there have the `bloganuary_id` field as if it was January. 
2. I redacted user-sensitive information (avatar URLs) so it is expected that the Prompt card will only show placeholders for the respondent avatars.

### Test steps
1. Download, install, and log in the Jetpack version from this PR
3. **Disable** the `Map Local` setting in Charles (so we hit the actual endpoint)
4. Refresh the app dashboard
5. Tap `Answer Prompt` in the prompts card
6. Go to the Post Settings
7. **Verify** the tags section only show the regular `dailyprompt`-related tags
8. Go back to the Dashboard
9. **Enable** the `Map Local` setting in Charles (so we hit our mocked json response)
10. Refresh the app dashboard
11. Tap `Answer Prompt` in the prompts card
12. Go to the Post Settings
13. **Verify** the tags section now show the `dailyprompt` AND `bloganuary` tags (4 in total)

You can also test the prompt answer from the "View more prompts" list by doing this:
1. Keep the `Map Local` setting on in Charles
2. Go back to the Dashboard
3. Tap the overflow menu in the Prompts card
4. Tap "View more prompts"
5. Tap Today's prompt
6. Go to Post Settings
7. **Verify** the tags section show the `dailyprompt` AND `bloganuary` tags (4 in total)
8. Do steps 2-4 again
9. Tap a prompt **before November 9**
10. Go to Post Settings
11. **Verify** the tags section only show the regular `dailyprompt`-related tags

## Regression Notes
1. Potential unintended areas of impact
Adding tags when `bloganuaryId` not present

17. What I did to test those areas of impact (or what existing automated tests I relied on)
Manual testing + Unit tests

18. What automated tests I added (or what prevented me from doing so)
Unit tests to assert tags are only added in the correct scenario.

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.

UI Changes testing checklist:
No UI changes

Test command: ./gradlew :WordPress:testWordpressVanillaDebugUnitTest --tests "org.wordpress.android.ui.bloggingprompts.editor.EditorBloggingPromptsViewModelTest"

Fix patch:
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/bloggingprompts/BloggingPromptsPostTagProvider.kt b/WordPress/src/main/java/org/wordpress/android/ui/bloggingprompts/BloggingPromptsPostTagProvider.kt
index 14319a5319ba..0600bbcff449 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/bloggingprompts/BloggingPromptsPostTagProvider.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/bloggingprompts/BloggingPromptsPostTagProvider.kt
@@ -23,5 +23,6 @@ class BloggingPromptsPostTagProvider @Inject constructor(
 
     companion object {
         const val BLOGGING_PROMPT_TAG = "dailyprompt"
+        const val BLOGANUARY_TAG = "bloganuary"
     }
 }
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditorBloggingPromptsViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditorBloggingPromptsViewModel.kt
index 8c8380d783cb..d3c2edfceeb5 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditorBloggingPromptsViewModel.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditorBloggingPromptsViewModel.kt
@@ -5,6 +5,7 @@ import androidx.lifecycle.MutableLiveData
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.flow.first
 import org.wordpress.android.fluxc.model.SiteModel
+import org.wordpress.android.fluxc.model.bloggingprompts.BloggingPromptModel
 import org.wordpress.android.fluxc.store.bloggingprompts.BloggingPromptsStore
 import org.wordpress.android.modules.BG_THREAD
 import org.wordpress.android.ui.bloggingprompts.BloggingPromptsPostTagProvider
@@ -45,16 +46,20 @@ class EditorBloggingPromptsViewModel
                     EditorLoadedPrompt(
                         promptId,
                         content,
-                        createPromptTags(prompt.answeredLink)
+                        createPromptTags(prompt)
                     )
                 )
             )
         }
     }
 
-    private fun createPromptTags(tagUrl: String): List<String> = mutableListOf<String>().apply {
+    private fun createPromptTags(prompt: BloggingPromptModel): List<String> = mutableListOf<String>().apply {
         add(BloggingPromptsPostTagProvider.BLOGGING_PROMPT_TAG)
-        add(bloggingPromptsPostTagProvider.promptIdTag(tagUrl))
+        add(bloggingPromptsPostTagProvider.promptIdTag(prompt.answeredLink))
+        prompt.bloganuaryId?.let { bloganuaryIdTag ->
+            add(BloggingPromptsPostTagProvider.BLOGANUARY_TAG)
+            add(bloganuaryIdTag)
+        }
     }
 
     data class EditorLoadedPrompt(val promptId: Int, val content: String, val tags: List<String>)


Test patch:
diff --git a/WordPress/src/test/java/org/wordpress/android/ui/bloggingprompts/editor/EditorBloggingPromptsViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/bloggingprompts/editor/EditorBloggingPromptsViewModelTest.kt
index f79de2779589..4c8c5ee0cfe8 100644
--- a/WordPress/src/test/java/org/wordpress/android/ui/bloggingprompts/editor/EditorBloggingPromptsViewModelTest.kt
+++ b/WordPress/src/test/java/org/wordpress/android/ui/bloggingprompts/editor/EditorBloggingPromptsViewModelTest.kt
@@ -7,6 +7,7 @@ import org.junit.Before
 import org.junit.Test
 import org.mockito.Mock
 import org.mockito.kotlin.any
+import org.mockito.kotlin.doAnswer
 import org.mockito.kotlin.doReturn
 import org.mockito.kotlin.mock
 import org.mockito.kotlin.times
@@ -31,20 +32,37 @@ class EditorBloggingPromptsViewModelTest : BaseUnitTest() {
     private lateinit var viewModel: EditorBloggingPromptsViewModel
     private var loadedPrompt: EditorLoadedPrompt? = null
 
-    private val bloggingPrompt = BloggingPromptsResult(
-        model = BloggingPromptModel(
-            id = 123,
-            text = "title",
-            date = Date(),
-            isAnswered = false,
-            attribution = "",
-            respondentsCount = 5,
-            respondentsAvatarUrls = listOf(),
-            answeredLink = "https://wordpress.com/tag/dailyprompt-123",
+    private val bloggingPrompt = listOf(
+        BloggingPromptsResult(
+            model = BloggingPromptModel(
+                id = 123,
+                text = "title",
+                date = Date(),
+                isAnswered = false,
+                attribution = "",
+                respondentsCount = 5,
+                respondentsAvatarUrls = listOf(),
+                answeredLink = "https://wordpress.com/tag/dailyprompt-123",
+            )
+        ),
+        BloggingPromptsResult(
+            model = BloggingPromptModel(
+                id = 321,
+                text = "title",
+                date = Date(),
+                isAnswered = false,
+                attribution = "",
+                respondentsCount = 10,
+                respondentsAvatarUrls = listOf(),
+                answeredLink = "https://wordpress.com/tag/dailyprompt-321",
+                bloganuaryId = "bloganuaryTag"
+            )
         )
     )
     private val bloggingPromptsStore: BloggingPromptsStore = mock {
-        onBlocking { getPromptById(any(), any()) } doReturn flowOf(bloggingPrompt)
+        onBlocking { getPromptById(any(), any()) } doAnswer { mock ->
+            flowOf(bloggingPrompt.first { it.model?.id == mock.arguments[1] })
+        }
     }
     private val bloggingPromptsBlock = "blogging_prompts_block"
     private val bloggingPromptsEditorBlockMapper: BloggingPromptsEditorBlockMapper = mock {
@@ -72,7 +90,7 @@ class EditorBloggingPromptsViewModelTest : BaseUnitTest() {
     fun `starting VM fetches a prompt and posts it to onBloggingPromptLoaded`() = test {
         viewModel.start(siteModel, 123)
 
-        assertThat(loadedPrompt?.promptId).isEqualTo(bloggingPrompt.model?.id)
+        assertThat(loadedPrompt?.promptId).isEqualTo(123)
 
         verify(bloggingPromptsStore, times(1)).getPromptById(any(), any())
     }
@@ -98,4 +116,16 @@ class EditorBloggingPromptsViewModelTest : BaseUnitTest() {
             "promptIdTag"
         )
     }
+
+    @Test
+    fun `should add bloganuary tags`() {
+        whenever(bloggingPromptsPostTagProvider.promptIdTag(any())).thenReturn("promptIdTag")
+        viewModel.start(siteModel, 321)
+        assertThat(loadedPrompt?.tags).containsOnly(
+            BloggingPromptsPostTagProvider.BLOGGING_PROMPT_TAG,
+            "promptIdTag",
+            BloggingPromptsPostTagProvider.BLOGANUARY_TAG,
+            "bloganuaryTag"
+        )
+    }
 }