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

Issue:
🤖 [Dynamic Cards] Make the whole card actionable
The whole card should be actionable when there is a valid action url

Slack conversation: p1703156111412259/1702977446.551109-slack-C067H36F011


Discussion hints:
nan

Pull request: 🤖 [Dynamic Cards] Makes the whole card actionable
Fixes #19833

## Description
Makes the whole card actionable when there is a valid action url.

-----

## To Test:
### Domains management card
* **Verify** that the button is actionable and the `dynamic_dashboard_card_cta_tapped` event is emmitted.
* **Verify** that the whole card is actionable and the `dynamic_dashboard_card_tapped` event is emmitted.
### Mocked data
* Apply the patch [cardsactions.patch](https://github.com/wordpress-mobile/WordPress-Android/files/13742797/cardsactions.patch)
* **Verify** that both the card and the button is actionable on the first card
* **Verify** that the card is actionable on the second card
* **Verify** that the third card is not actionable

-----

## Regression Notes

1. Potential unintended areas of impact

    Dynamic dashboard cards action

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)

    Updated the existing tests

-----

## 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:

- [ ] 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.mysite.cards.dynamiccard.DynamicCardsBuilderTest"

Fix patch:
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteCardAndItem.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteCardAndItem.kt
index 981eb1d64c54..81026f4db9a4 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteCardAndItem.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteCardAndItem.kt
@@ -400,16 +400,17 @@ sealed class MySiteCardAndItem(open val type: Type, open val activeQuickStartIte
 
             sealed class ActionSource {
                 abstract val url: String
-                abstract val onClick: ListItemInteraction
+                abstract val onCardClick: ListItemInteraction
 
                 data class Card(
                     override val url: String,
-                    override val onClick: ListItemInteraction
+                    override val onCardClick: ListItemInteraction
                 ) : ActionSource()
 
-                data class Button(
+                data class CardOrButton(
                     override val url: String,
-                    override val onClick: ListItemInteraction,
+                    override val onCardClick: ListItemInteraction,
+                    val onButtonClick: ListItemInteraction,
                     val title: String
                 ) : ActionSource()
             }
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardComposable.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardComposable.kt
index 58449c70ca24..caa92fd07216 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardComposable.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardComposable.kt
@@ -22,13 +22,13 @@ fun DynamicDashboardCard(
     UnelevatedCard(
         modifier = modifier
             .run {
-                if (card.action is ActionSource.Card) clickable { card.action.onClick.click() } else this
+                if (card.action != null) clickable { card.action.onCardClick.click() } else this
             },
         content = {
             Column(
                 Modifier.padding(bottom = 8.dp)
             ) {
-                val isCtaInvisible = card.action !is ActionSource.Button
+                val isCtaInvisible = card.action !is ActionSource.CardOrButton
                 DynamicCardHeader(
                     title = card.title,
                     onHideMenuClicked = { card.onHideMenuItemClick.click() }
@@ -47,8 +47,8 @@ fun DynamicDashboardCard(
                         modifier = Modifier.run { if (isCtaInvisible) padding(bottom = 8.dp) else this }
                     )
                 }
-                (card.action as? ActionSource.Button)?.title?.let { title ->
-                    DynamicCardCallToActionButton(text = title, onClicked = { card.action.onClick.click() })
+                (card.action as? ActionSource.CardOrButton)?.title?.let { title ->
+                    DynamicCardCallToActionButton(text = title, onClicked = { card.action.onButtonClick.click() })
                 }
             }
         }
@@ -65,9 +65,10 @@ fun DynamicDashboardCardPreview() {
                 id = "id",
                 title = "Card Title",
                 image = "https://picsum.photos/200/300",
-                action = ActionSource.Button(
+                action = ActionSource.CardOrButton(
                     title = "Call to Action", url = "",
-                    onClick = ListItemInteraction.create {},
+                    onCardClick = ListItemInteraction.create {},
+                    onButtonClick = ListItemInteraction.create {},
                 ),
                 rows = listOf(
                     MySiteCardAndItem.Card.Dynamic.Row(
@@ -96,10 +97,11 @@ fun DynamicDashboardCardWithFeatureAndDescriptionPreview() {
                 id = "id",
                 title = null,
                 image = "https://picsum.photos/200/300",
-                action = ActionSource.Button(
+                action = ActionSource.CardOrButton(
                     title = "See yours now",
                     url = "",
-                    onClick = ListItemInteraction.create {},
+                    onCardClick = ListItemInteraction.create {},
+                    onButtonClick = ListItemInteraction.create {},
                 ),
                 rows = listOf(
                     MySiteCardAndItem.Card.Dynamic.Row(
@@ -124,10 +126,11 @@ fun DynamicDashboardCardWithFeatureAndSubtitleAndDescriptionPreview() {
                 id = "id",
                 title = null,
                 image = "https://picsum.photos/200/300",
-                action = ActionSource.Button(
+                action = ActionSource.CardOrButton(
                     title = "Find out more",
                     url = "",
-                    onClick = ListItemInteraction.create {},
+                    onCardClick = ListItemInteraction.create {},
+                    onButtonClick = ListItemInteraction.create {},
                 ),
                 rows = listOf(
                     MySiteCardAndItem.Card.Dynamic.Row(
@@ -154,7 +157,7 @@ fun DynamicDashboardCardWithNoCta() {
                 image = "https://picsum.photos/200/300",
                 action = ActionSource.Card(
                     url = "",
-                    onClick = ListItemInteraction.create {},
+                    onCardClick = ListItemInteraction.create {},
                 ),
                 rows = listOf(
                     MySiteCardAndItem.Card.Dynamic.Row(
@@ -181,7 +184,7 @@ fun DynamicDashboardWithFeatureImageOnly() {
                 image = "https://picsum.photos/200/300",
                 action = ActionSource.Card(
                     url = "",
-                    onClick = ListItemInteraction.create {},
+                    onCardClick = ListItemInteraction.create {},
                 ),
                 rows = listOf(),
                 onHideMenuItemClick = ListItemInteraction.create {},
@@ -199,9 +202,10 @@ fun DynamicDashboardCardWithTitleAndCompleteRowsPreview() {
                 id = "id",
                 title = "What's New in Jetpack",
                 image = null,
-                action = ActionSource.Button(
+                action = ActionSource.CardOrButton(
                     title = "Find out more", url = "",
-                    onClick = ListItemInteraction.create {},
+                    onCardClick = ListItemInteraction.create {},
+                    onButtonClick = ListItemInteraction.create {},
                 ),
                 rows = listOf(
                     MySiteCardAndItem.Card.Dynamic.Row(
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardsBuilder.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardsBuilder.kt
index a99ad5d9c057..646052113207 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardsBuilder.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardsBuilder.kt
@@ -60,17 +60,21 @@ class DynamicCardsBuilder @Inject constructor(
         params: DynamicCardsBuilderParams,
         card: DynamicCardModel
     ): Dynamic.ActionSource? = when {
-        isValidUrlOrDeeplink(card.url) && isValidActionTitle(card.action) -> Dynamic.ActionSource.Button(
+        isValidUrlOrDeeplink(card.url) && isValidActionTitle(card.action) -> Dynamic.ActionSource.CardOrButton(
             url = requireNotNull(card.url),
             title = requireNotNull(card.action),
-            onClick = ListItemInteraction.create(
+            onCardClick = ListItemInteraction.create(
+                data = DynamicCardsBuilderParams.ClickParams(id = card.id, actionUrl = requireNotNull(card.url)),
+                action = params.onCardClick
+            ),
+            onButtonClick = ListItemInteraction.create(
                 data = DynamicCardsBuilderParams.ClickParams(id = card.id, actionUrl = requireNotNull(card.url)),
                 action = params.onCtaClick
             )
         )
         isValidUrlOrDeeplink(card.url) -> Dynamic.ActionSource.Card(
             url = requireNotNull(card.url),
-            onClick = ListItemInteraction.create(
+            onCardClick = ListItemInteraction.create(
                 data = DynamicCardsBuilderParams.ClickParams(id = card.id, actionUrl = requireNotNull(card.url)),
                 action = params.onCardClick
             )


Test patch:
diff --git a/WordPress/src/test/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardsBuilderTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardsBuilderTest.kt
index a4284372ad73..23f7dc822998 100644
--- a/WordPress/src/test/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardsBuilderTest.kt
+++ b/WordPress/src/test/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardsBuilderTest.kt
@@ -158,9 +158,10 @@ class DynamicCardsBuilderTest : BaseUnitTest() {
                 ),
                 title = DYNAMIC_CARD_TITLE,
                 image = DYNAMIC_CARD_FEATURED_IMAGE,
-                action = MySiteCardAndItem.Card.Dynamic.ActionSource.Button(
+                action = MySiteCardAndItem.Card.Dynamic.ActionSource.CardOrButton(
                     url = DYNAMIC_CARD_URL,
-                    onClick = mock(),
+                    onCardClick = mock(),
+                    onButtonClick = mock(),
                     title = DYNAMIC_CARD_ACTION
                 ),
                 onHideMenuItemClick = mock(),
@@ -181,9 +182,10 @@ class DynamicCardsBuilderTest : BaseUnitTest() {
         assertEquals(expectedCards[0].image, dynamicCards[0].image)
         assertEquals(expectedCards[0].rows.size, 1)
         assertEquals(expectedCards[0].rows, dynamicCards[0].rows)
-        assertThat(dynamicCards[0].action).isInstanceOf(MySiteCardAndItem.Card.Dynamic.ActionSource.Button::class.java)
-        val expected = expectedCards[0].action as? MySiteCardAndItem.Card.Dynamic.ActionSource.Button
-        val actual = dynamicCards[0].action as? MySiteCardAndItem.Card.Dynamic.ActionSource.Button
+        assertThat(dynamicCards[0].action)
+            .isInstanceOf(MySiteCardAndItem.Card.Dynamic.ActionSource.CardOrButton::class.java)
+        val expected = expectedCards[0].action as? MySiteCardAndItem.Card.Dynamic.ActionSource.CardOrButton
+        val actual = dynamicCards[0].action as? MySiteCardAndItem.Card.Dynamic.ActionSource.CardOrButton
         assertEquals(expected?.title, actual?.title)
         assertEquals(expected?.url, actual?.url)
     }