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 Original line Diff line number Diff line
@@ -1374,13 +1374,8 @@ public class NotificationContentView extends FrameLayout implements Notification
        if (bubbleButton == null || actionContainer == null) {
        if (bubbleButton == null || actionContainer == null) {
            return;
            return;
        }
        }
        boolean isPersonWithShortcut =

                mPeopleIdentifier.getPeopleNotificationType(entry)
        if (shouldShowBubbleButton(entry)) {
                        >= PeopleNotificationIdentifier.TYPE_FULL_PERSON;
        boolean showButton = BubblesManager.areBubblesEnabled(mContext, entry.getSbn().getUser())
                && isPersonWithShortcut
                && entry.getBubbleMetadata() != null;
        if (showButton) {
            // explicitly resolve drawable resource using SystemUI's theme
            // explicitly resolve drawable resource using SystemUI's theme
            Drawable d = mContext.getDrawable(entry.isBubble()
            Drawable d = mContext.getDrawable(entry.isBubble()
                    ? R.drawable.bubble_ic_stop_bubble
                    ? 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) {
    private void applySnoozeAction(View layout) {
        if (layout == null || mContainingNotification == null) {
        if (layout == null || mContainingNotification == null) {
            return;
            return;
+167 −3
Original line number Original line Diff line number Diff line
@@ -16,9 +16,15 @@


package com.android.systemui.statusbar.notification.row
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.testing.AndroidTestingRunner
import android.view.NotificationHeaderView
import android.view.NotificationHeaderView
import android.view.View
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
import androidx.test.filters.SmallTest
import androidx.test.filters.SmallTest
import com.android.internal.R
import com.android.internal.R
import com.android.internal.widget.NotificationActionListLayout
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.SysuiTestCase
import com.android.systemui.media.dialog.MediaOutputDialogFactory
import com.android.systemui.media.dialog.MediaOutputDialogFactory
import com.android.systemui.statusbar.notification.FeedbackIcon
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.mock
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.mockito.whenever
import junit.framework.Assert.assertEquals
import org.junit.Before
import org.junit.Before
import org.junit.Test
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runner.RunWith
import org.mockito.Mockito
import org.mockito.Mock
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.never
import org.mockito.Mockito.never
import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations.initMocks


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


    @Mock private lateinit var mPeopleNotificationIdentifier: PeopleNotificationIdentifier

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

    @Before
    @Before
    fun setup() {
    fun setup() {
        initMocks(this)

        mDependency.injectMockDependency(MediaOutputDialogFactory::class.java)
        mDependency.injectMockDependency(MediaOutputDialogFactory::class.java)


        view = NotificationContentView(mContext, /* attrs= */ null)
        view = spy(NotificationContentView(mContext, /* attrs= */ null))
        val row = ExpandableNotificationRow(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
        doReturn(10).whenever(spyRow).intrinsicHeight


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