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

Commit a74a1fb9 authored by Andreas Miko's avatar Andreas Miko
Browse files

Hydrate and test previewIcons

Hydrate previewIcons through Activatable.

Make sure that appIcons are fetched lazily (test added).

Bug: b/416131251 b/416132260 b/416277572
Test: New test added
Flag: com.android.systemui.notification_bundle_ui
Change-Id: I490411b50edc7931e74fb236d22b181117af8496
parent 1958f94b
Loading
Loading
Loading
Loading
+2 −5
Original line number Diff line number Diff line
@@ -60,7 +60,6 @@ import androidx.compose.ui.util.fastMap
import androidx.compose.ui.util.fastMaxOfOrDefault
import androidx.compose.ui.util.fastSumBy
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.compose.animation.scene.ContentScope
import com.android.compose.animation.scene.ElementKey
@@ -195,11 +194,9 @@ private fun ContentScope.BundleHeaderContent(
        )

        if (collapsed) {
            val currentPreviewIcons: List<Drawable> by
                viewModel.previewIcons.collectAsStateWithLifecycle(initialValue = emptyList())
            if (currentPreviewIcons.isNotEmpty()) {
            if (viewModel.previewIcons.isNotEmpty()) {
                BundlePreviewIcons(
                    previewDrawables = currentPreviewIcons,
                    previewDrawables = viewModel.previewIcons,
                    modifier = Modifier.padding(start = 8.dp),
                )
            }
+8 −6
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.testing.TestableLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.kosmos.currentValue
import com.android.systemui.statusbar.notification.collection.BundleEntry
import com.android.systemui.statusbar.notification.collection.GroupEntry
import com.android.systemui.statusbar.notification.collection.InternalNotificationsApi
@@ -37,6 +38,7 @@ import com.android.systemui.statusbar.notification.row.data.model.AppData
import com.android.systemui.statusbar.notification.row.data.repository.TEST_BUNDLE_SPEC
import com.google.common.truth.Truth.assertThat
import kotlin.test.assertEquals
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -116,18 +118,18 @@ class BundleCoordinatorTest : SysuiTestCase() {
    }

    @Test
    fun testUpdateAppData_emptyChildren_setsEmptyAppList() {
    fun testUpdateAppData_emptyChildren_setsEmptyAppList() = runTest {
        val bundle = BundleEntry(TEST_BUNDLE_SPEC)
        assertThat(bundle.children).isEmpty()

        coordinator.bundleAppDataUpdater.onBeforeRenderList(listOf(bundle))

        assertThat(bundle.bundleRepository.appDataList).isEmpty()
        assertThat(currentValue(bundle.bundleRepository.appDataList)).isEmpty()
    }

    @OptIn(InternalNotificationsApi::class)
    @Test
    fun testUpdateAppData_twoNotifs() {
    fun testUpdateAppData_twoNotifs() = runTest {
        val bundle = BundleEntry(TEST_BUNDLE_SPEC)

        val notif1 = NotificationEntryBuilder().setPkg(pkg1).setUser(user1).build()
@@ -138,13 +140,13 @@ class BundleCoordinatorTest : SysuiTestCase() {

        coordinator.bundleAppDataUpdater.onBeforeRenderList(listOf(bundle))

        assertThat(bundle.bundleRepository.appDataList)
        assertThat(currentValue(bundle.bundleRepository.appDataList))
            .containsExactly(AppData(pkg1, user1), AppData(pkg2, user2))
    }

    @OptIn(InternalNotificationsApi::class)
    @Test
    fun testUpdateAppData_notifAndGroup() {
    fun testUpdateAppData_notifAndGroup() = runTest {
        val bundle = BundleEntry(TEST_BUNDLE_SPEC)

        val notif1 = NotificationEntryBuilder().setPkg(pkg1).setUser(user1).build()
@@ -164,7 +166,7 @@ class BundleCoordinatorTest : SysuiTestCase() {

        coordinator.bundleAppDataUpdater.onBeforeRenderList(listOf(bundle))

        assertThat(bundle.bundleRepository.appDataList)
        assertThat(currentValue(bundle.bundleRepository.appDataList))
            .containsExactly(AppData(pkg1, user1), AppData(pkg2, user2))
    }

+64 −0
Original line number Diff line number Diff line
@@ -18,6 +18,9 @@

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

import android.content.Context
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
import android.platform.test.annotations.EnableFlags
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.MotionScheme
@@ -25,7 +28,13 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.MutableSceneTransitionLayoutState
import com.android.systemui.SysuiTestCase
import com.android.systemui.controls.dagger.ControlsComponentTest.Companion.eq
import com.android.systemui.controls.ui.ControlActionCoordinatorImplTest.Companion.any
import com.android.systemui.kosmos.testScope
import com.android.systemui.notifications.ui.composable.row.BundleHeader
import com.android.systemui.statusbar.notification.row.data.model.AppData
import com.android.systemui.statusbar.notification.row.data.repository.BundleRepository
import com.android.systemui.statusbar.notification.row.data.repository.testBundleRepository
import com.android.systemui.statusbar.notification.row.domain.bundleInteractor
import com.android.systemui.statusbar.notification.row.icon.appIconProvider
import com.android.systemui.statusbar.notification.row.icon.mockAppIconProvider
@@ -33,13 +42,22 @@ import com.android.systemui.statusbar.notification.shared.NotificationBundleUi
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlin.test.Test
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Rule
import org.junit.runner.RunWith
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever
import platform.test.motion.compose.runMonotonicClockTest

@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidJUnit4::class)
@EnableFlags(NotificationBundleUi.FLAG_NAME)
@@ -48,6 +66,9 @@ class BundleInteractorTest : SysuiTestCase() {
    @get:Rule val rule: MockitoRule = MockitoJUnit.rule()

    private val kosmos = testKosmos()
    private val testScope = kosmos.testScope

    private val testBundleRepository: BundleRepository = kosmos.testBundleRepository

    private lateinit var underTest: BundleInteractor

@@ -57,6 +78,49 @@ class BundleInteractorTest : SysuiTestCase() {
        underTest = kosmos.bundleInteractor
    }

    @Test
    fun previewIcons_callsFetchEnoughTimesForThreeNonNullResults() =
        testScope.runTest {
            // Arrange
            val appDataList =
                List(5) { index ->
                    mock<AppData> {
                        on { it.packageName }.thenReturn("com.example.app${index + 1}")
                    }
                }

            val drawable1: Drawable = ColorDrawable(android.graphics.Color.RED)
            val drawable2: Drawable = ColorDrawable(android.graphics.Color.GREEN)
            val drawable3: Drawable = ColorDrawable(android.graphics.Color.BLUE)
            val unusedDrawable: Drawable = ColorDrawable(android.graphics.Color.YELLOW)

            whenever(
                    kosmos.mockAppIconProvider.getOrFetchAppIcon(
                        any<String>(),
                        any<Context>(),
                        eq(false),
                        eq(false),
                    )
                )
                .thenReturn(drawable1)
                .thenReturn(null)
                .thenReturn(drawable2)
                .thenReturn(drawable3)
                .thenReturn(unusedDrawable)

            // Act
            testBundleRepository.appDataList.value = appDataList
            runCurrent()
            val result = underTest.previewIcons.first()

            // Assert
            verify(kosmos.mockAppIconProvider, times(4))
                .getOrFetchAppIcon(any<String>(), any<Context>(), eq(false), eq(false))

            assertThat(result).hasSize(3)
            assertThat(result).containsExactly(drawable1, drawable2, drawable3).inOrder()
        }

    @Test
    fun setExpansionState_sets_state_to_expanded() = runMonotonicClockTest {
        // Arrange
+0 −3
Original line number Diff line number Diff line
@@ -29,7 +29,6 @@ import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule

@@ -52,8 +51,6 @@ class BundleHeaderGutsViewModelTest : SysuiTestCase() {

    @Before
    fun setUp() {
        MockitoAnnotations.openMocks(this)

        underTest =
            BundleHeaderGutsViewModel(
                titleText = TEST_BUNDLE_SPEC.titleText,
+1 −1
Original line number Diff line number Diff line
@@ -224,7 +224,7 @@ constructor(
                        else -> error("Unexpected ListEntry type: ${listEntry::class.simpleName}")
                    }
                }
            bundleEntry.bundleRepository.appDataList = newAppDataList
            bundleEntry.bundleRepository.appDataList.value = newAppDataList
        }
    }

Loading