Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 900fa741 authored by Yining Liu's avatar Yining Liu
Browse files

Add test code for `Fix the height of NotificationContentView when there's no...

Add test code for `Fix the height of NotificationContentView when there's no actions but bubble button`

Added function `NotificationContentView.shouldShowBubbleButton(NotificationEntry entry)` to make unit test possible. Added tests in the converted Kotlin version of NotificationContentViewTest.

Bug: 244522899
Test: `atest NotificationContentViewTest`
Change-Id: I8c34db53386dac95d52874ed250d8420ab9a1676
parent 3650a601
Loading
Loading
Loading
Loading
+12 −7
Original line number Diff line number Diff line
@@ -1374,13 +1374,8 @@ public class NotificationContentView extends FrameLayout implements Notification
        if (bubbleButton == null || actionContainer == null) {
            return;
        }
        boolean isPersonWithShortcut =
                mPeopleIdentifier.getPeopleNotificationType(entry)
                        >= PeopleNotificationIdentifier.TYPE_FULL_PERSON;
        boolean showButton = BubblesManager.areBubblesEnabled(mContext, entry.getSbn().getUser())
                && isPersonWithShortcut
                && entry.getBubbleMetadata() != null;
        if (showButton) {

        if (shouldShowBubbleButton(entry)) {
            // explicitly resolve drawable resource using SystemUI's theme
            Drawable d = mContext.getDrawable(entry.isBubble()
                    ? R.drawable.bubble_ic_stop_bubble
@@ -1410,6 +1405,16 @@ public class NotificationContentView extends FrameLayout implements Notification
        }
    }

    @VisibleForTesting
    boolean shouldShowBubbleButton(NotificationEntry entry) {
        boolean isPersonWithShortcut =
                mPeopleIdentifier.getPeopleNotificationType(entry)
                        >= PeopleNotificationIdentifier.TYPE_FULL_PERSON;
        return BubblesManager.areBubblesEnabled(mContext, entry.getSbn().getUser())
                && isPersonWithShortcut
                && entry.getBubbleMetadata() != null;
    }

    private void applySnoozeAction(View layout) {
        if (layout == null || mContainingNotification == null) {
            return;
+167 −3
Original line number Diff line number Diff line
@@ -16,9 +16,15 @@

package com.android.systemui.statusbar.notification.row

import android.content.res.Resources
import android.os.UserHandle
import android.service.notification.StatusBarNotification
import android.testing.AndroidTestingRunner
import android.view.NotificationHeaderView
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
import androidx.test.filters.SmallTest
import com.android.internal.R
import com.android.internal.widget.NotificationActionListLayout
@@ -26,31 +32,45 @@ import com.android.internal.widget.NotificationExpandButton
import com.android.systemui.SysuiTestCase
import com.android.systemui.media.dialog.MediaOutputDialogFactory
import com.android.systemui.statusbar.notification.FeedbackIcon
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import junit.framework.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito
import org.mockito.Mock
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.never
import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations.initMocks

@SmallTest
@RunWith(AndroidTestingRunner::class)
class NotificationContentViewTest : SysuiTestCase() {
    private lateinit var view: NotificationContentView

    @Mock private lateinit var mPeopleNotificationIdentifier: PeopleNotificationIdentifier

    private val notificationContentMargin =
        mContext.resources.getDimensionPixelSize(R.dimen.notification_content_margin)

    @Before
    fun setup() {
        initMocks(this)

        mDependency.injectMockDependency(MediaOutputDialogFactory::class.java)

        view = NotificationContentView(mContext, /* attrs= */ null)
        view = spy(NotificationContentView(mContext, /* attrs= */ null))
        val row = ExpandableNotificationRow(mContext, /* attrs= */ null)
        val spyRow = Mockito.spy(row)
        row.entry = createMockNotificationEntry(false)
        val spyRow = spy(row)
        doReturn(10).whenever(spyRow).intrinsicHeight

        with(view) {
            initialize(mPeopleNotificationIdentifier, mock(), mock(), mock())
            setContainingNotification(spyRow)
            setHeights(/* smallHeight= */ 10, /* headsUpMaxHeight= */ 20, /* maxHeight= */ 30)
            contractedChild = createViewWithHeight(10)
@@ -183,4 +203,148 @@ class NotificationContentViewTest : SysuiTestCase() {
            View.IMPORTANT_FOR_ACCESSIBILITY_AUTO
        verify(mockHeadsUpActions).importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_AUTO
    }

    @Test
    fun setExpandedChild_notShowBubbleButton_marginTargetBottomMarginShouldNotChange() {
        // Given: bottom margin of actionListMarginTarget is notificationContentMargin
        // Bubble button should not be shown for the given NotificationEntry
        val mockNotificationEntry = createMockNotificationEntry(/* showButton= */ false)
        val mockContainingNotification = createMockContainingNotification(mockNotificationEntry)
        val actionListMarginTarget =
            spy(createLinearLayoutWithBottomMargin(notificationContentMargin))
        val mockExpandedChild = createMockExpandedChild(mockNotificationEntry)
        whenever(
                mockExpandedChild.findViewById<LinearLayout>(
                    R.id.notification_action_list_margin_target
                )
            )
            .thenReturn(actionListMarginTarget)
        view.setContainingNotification(mockContainingNotification)

        // When: call NotificationContentView.setExpandedChild() to set the expandedChild
        view.expandedChild = mockExpandedChild

        // Then: bottom margin of actionListMarginTarget should not change,
        // still be notificationContentMargin
        assertEquals(notificationContentMargin, getMarginBottom(actionListMarginTarget))
    }

    @Test
    fun setExpandedChild_showBubbleButton_marginTargetBottomMarginShouldChangeToZero() {
        // Given: bottom margin of actionListMarginTarget is notificationContentMargin
        // Bubble button should be shown for the given NotificationEntry
        val mockNotificationEntry = createMockNotificationEntry(/* showButton= */ true)
        val mockContainingNotification = createMockContainingNotification(mockNotificationEntry)
        val actionListMarginTarget =
            spy(createLinearLayoutWithBottomMargin(notificationContentMargin))
        val mockExpandedChild = createMockExpandedChild(mockNotificationEntry)
        whenever(
                mockExpandedChild.findViewById<LinearLayout>(
                    R.id.notification_action_list_margin_target
                )
            )
            .thenReturn(actionListMarginTarget)
        view.setContainingNotification(mockContainingNotification)

        // When: call NotificationContentView.setExpandedChild() to set the expandedChild
        view.expandedChild = mockExpandedChild

        // Then: bottom margin of actionListMarginTarget should be set to 0
        assertEquals(0, getMarginBottom(actionListMarginTarget))
    }

    @Test
    fun onNotificationUpdated_notShowBubbleButton_marginTargetBottomMarginShouldNotChange() {
        // Given: bottom margin of actionListMarginTarget is notificationContentMargin
        val mockNotificationEntry = createMockNotificationEntry(/* showButton= */ false)
        val mockContainingNotification = createMockContainingNotification(mockNotificationEntry)
        val actionListMarginTarget =
            spy(createLinearLayoutWithBottomMargin(notificationContentMargin))
        val mockExpandedChild = createMockExpandedChild(mockNotificationEntry)
        whenever(
                mockExpandedChild.findViewById<LinearLayout>(
                    R.id.notification_action_list_margin_target
                )
            )
            .thenReturn(actionListMarginTarget)
        view.setContainingNotification(mockContainingNotification)
        view.expandedChild = mockExpandedChild
        assertEquals(notificationContentMargin, getMarginBottom(actionListMarginTarget))

        // When: call NotificationContentView.onNotificationUpdated() to update the
        // NotificationEntry, which should not show bubble button
        view.onNotificationUpdated(createMockNotificationEntry(/* showButton= */ false))

        // Then: bottom margin of actionListMarginTarget should not change, still be 20
        assertEquals(notificationContentMargin, getMarginBottom(actionListMarginTarget))
    }

    @Test
    fun onNotificationUpdated_showBubbleButton_marginTargetBottomMarginShouldChangeToZero() {
        // Given: bottom margin of actionListMarginTarget is notificationContentMargin
        val mockNotificationEntry = createMockNotificationEntry(/* showButton= */ false)
        val mockContainingNotification = createMockContainingNotification(mockNotificationEntry)
        val actionListMarginTarget =
            spy(createLinearLayoutWithBottomMargin(notificationContentMargin))
        val mockExpandedChild = createMockExpandedChild(mockNotificationEntry)
        whenever(
                mockExpandedChild.findViewById<LinearLayout>(
                    R.id.notification_action_list_margin_target
                )
            )
            .thenReturn(actionListMarginTarget)
        view.setContainingNotification(mockContainingNotification)
        view.expandedChild = mockExpandedChild
        assertEquals(notificationContentMargin, getMarginBottom(actionListMarginTarget))

        // When: call NotificationContentView.onNotificationUpdated() to update the
        // NotificationEntry, which should show bubble button
        view.onNotificationUpdated(createMockNotificationEntry(true))

        // Then: bottom margin of actionListMarginTarget should not change, still be 20
        assertEquals(0, getMarginBottom(actionListMarginTarget))
    }

    private fun createMockContainingNotification(notificationEntry: NotificationEntry) =
        mock<ExpandableNotificationRow>().apply {
            whenever(this.entry).thenReturn(notificationEntry)
            whenever(this.context).thenReturn(mContext)
            whenever(this.bubbleClickListener).thenReturn(View.OnClickListener {})
        }

    private fun createMockNotificationEntry(showButton: Boolean) =
        mock<NotificationEntry>().apply {
            whenever(mPeopleNotificationIdentifier.getPeopleNotificationType(this))
                .thenReturn(PeopleNotificationIdentifier.TYPE_FULL_PERSON)
            whenever(this.bubbleMetadata).thenReturn(mock())
            val sbnMock: StatusBarNotification = mock()
            val userMock: UserHandle = mock()
            whenever(this.sbn).thenReturn(sbnMock)
            whenever(sbnMock.user).thenReturn(userMock)
            doReturn(showButton).whenever(view).shouldShowBubbleButton(this)
        }

    private fun createLinearLayoutWithBottomMargin(bottomMargin: Int): LinearLayout {
        val outerLayout = LinearLayout(mContext)
        val innerLayout = LinearLayout(mContext)
        outerLayout.addView(innerLayout)
        val mlp = innerLayout.layoutParams as ViewGroup.MarginLayoutParams
        mlp.setMargins(0, 0, 0, bottomMargin)
        return innerLayout
    }

    private fun createMockExpandedChild(notificationEntry: NotificationEntry) =
        mock<ExpandableNotificationRow>().apply {
            whenever(this.findViewById<ImageView>(R.id.bubble_button)).thenReturn(mock())
            whenever(this.findViewById<View>(R.id.actions_container)).thenReturn(mock())
            whenever(this.entry).thenReturn(notificationEntry)
            whenever(this.context).thenReturn(mContext)

            val resourcesMock: Resources = mock()
            whenever(resourcesMock.configuration).thenReturn(mock())
            whenever(this.resources).thenReturn(resourcesMock)
        }

    private fun getMarginBottom(layout: LinearLayout): Int =
        (layout.layoutParams as ViewGroup.MarginLayoutParams).bottomMargin
}