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

Commit f7d71b07 authored by Anton Potapov's avatar Anton Potapov
Browse files

Add Volume Panel tests

Bug: 318080198
Flag: aconfig new_volume_panel DISABLED
Test: atest BottombarViewModelTest
Test: atest ComponentsInteractorImplTest
Test: atest ComponentsFactoryTest
Test: atest VolumePanelViewModelTest
Test: atest DefaultComponentsLayoutManagerTest
Change-Id: I7929a8e8923bd9e1ae7bdc1d6b131a69b4a69c26
parent 684e0da6
Loading
Loading
Loading
Loading
+90 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.volume.panel.component.bottombar.ui.viewmodel

import android.content.Intent
import android.provider.Settings
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.testScope
import com.android.systemui.plugins.activityStarter
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
import com.android.systemui.volume.panel.volumePanelViewModel
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.Captor
import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnit

@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidJUnit4::class)
class BottomBarViewModelTest : SysuiTestCase() {

    @JvmField @Rule var mockitoRule = MockitoJUnit.rule()

    @Captor private lateinit var intentCaptor: ArgumentCaptor<Intent>

    private val kosmos = testKosmos()

    private lateinit var underTest: BottomBarViewModel

    private fun initUnderTest() {
        underTest = with(kosmos) { BottomBarViewModel(activityStarter, volumePanelViewModel) }
    }

    @Test
    fun onDoneClicked_hidesPanel() {
        with(kosmos) {
            testScope.runTest {
                initUnderTest()
                underTest.onDoneClicked()
                runCurrent()

                val volumePanelState by collectLastValue(volumePanelViewModel.volumePanelState)
                assertThat(volumePanelState!!.isVisible).isFalse()
            }
        }
    }

    @Test
    fun onSettingsClicked_dismissesPanelAndNavigatesToSettings() {
        with(kosmos) {
            testScope.runTest {
                initUnderTest()
                underTest.onSettingsClicked()

                runCurrent()

                val volumePanelState by collectLastValue(volumePanelViewModel.volumePanelState)
                assertThat(volumePanelState!!.isVisible).isFalse()
                verify(activityStarter).startActivity(capture(intentCaptor), eq(true))
                assertThat(intentCaptor.value.action).isEqualTo(Settings.ACTION_SOUND_SETTINGS)
            }
        }
    }
}
+122 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.volume.panel.domain.interactor

import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testScope
import com.android.systemui.volume.panel.availableCriteria
import com.android.systemui.volume.panel.criteriaByKey
import com.android.systemui.volume.panel.defaultCriteria
import com.android.systemui.volume.panel.domain.model.ComponentModel
import com.android.systemui.volume.panel.enabledComponents
import com.android.systemui.volume.panel.shared.model.VolumePanelComponentKey
import com.android.systemui.volume.panel.unavailableCriteria
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith

@SmallTest
@RunWith(AndroidJUnit4::class)
class ComponentsInteractorImplTest : SysuiTestCase() {

    private val kosmos = Kosmos()

    private lateinit var underTest: ComponentsInteractor

    private fun initUnderTest() {
        underTest =
            with(kosmos) {
                ComponentsInteractorImpl(
                    enabledComponents,
                    defaultCriteria,
                    testScope.backgroundScope,
                    criteriaByKey,
                )
            }
    }

    @Test
    fun componentsAvailability_checked() {
        with(kosmos) {
            testScope.runTest {
                enabledComponents =
                    setOf(
                        BOTTOM_BAR,
                        COMPONENT_1,
                        COMPONENT_2,
                    )
                criteriaByKey =
                    mapOf(
                        BOTTOM_BAR to availableCriteria,
                        COMPONENT_1 to unavailableCriteria,
                        COMPONENT_2 to availableCriteria,
                    )
                initUnderTest()

                val components by collectLastValue(underTest.components)

                assertThat(components)
                    .containsExactly(
                        ComponentModel(BOTTOM_BAR, true),
                        ComponentModel(COMPONENT_1, false),
                        ComponentModel(COMPONENT_2, true),
                    )
            }
        }
    }

    @Test
    fun noCriteria_fallbackToDefaultCriteria() {
        with(kosmos) {
            testScope.runTest {
                enabledComponents =
                    setOf(
                        BOTTOM_BAR,
                        COMPONENT_1,
                        COMPONENT_2,
                    )
                criteriaByKey =
                    mapOf(
                        BOTTOM_BAR to availableCriteria,
                        COMPONENT_2 to availableCriteria,
                    )
                defaultCriteria = unavailableCriteria
                initUnderTest()

                val components by collectLastValue(underTest.components)

                assertThat(components)
                    .containsExactly(
                        ComponentModel(BOTTOM_BAR, true),
                        ComponentModel(COMPONENT_1, false),
                        ComponentModel(COMPONENT_2, true),
                    )
            }
        }
    }

    private companion object {
        const val BOTTOM_BAR: VolumePanelComponentKey = "test_bottom_bar"
        const val COMPONENT_1: VolumePanelComponentKey = "test_component:1"
        const val COMPONENT_2: VolumePanelComponentKey = "test_component:2"
    }
}
+63 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.volume.panel.ui.composable

import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.testKosmos
import com.android.systemui.volume.panel.componentByKey
import com.android.systemui.volume.panel.mockVolumePanelUiComponentProvider
import com.android.systemui.volume.panel.shared.model.VolumePanelComponentKey
import com.google.common.truth.Truth
import org.junit.Test
import org.junit.runner.RunWith

@SmallTest
@RunWith(AndroidJUnit4::class)
class ComponentsFactoryTest : SysuiTestCase() {

    private val kosmos = testKosmos()

    private lateinit var underTest: ComponentsFactory

    private fun initUnderTest() {
        underTest = ComponentsFactory(kosmos.componentByKey)
    }

    @Test
    fun existingComponent_created() {
        kosmos.componentByKey = mapOf(TEST_COMPONENT to kosmos.mockVolumePanelUiComponentProvider)
        initUnderTest()

        val component = underTest.createComponent(TEST_COMPONENT)

        Truth.assertThat(component).isNotNull()
    }

    @Test(expected = IllegalArgumentException::class)
    fun componentAbsence_throws() {
        kosmos.componentByKey = emptyMap()
        initUnderTest()

        underTest.createComponent(TEST_COMPONENT)
    }

    private companion object {
        const val TEST_COMPONENT: VolumePanelComponentKey = "test_component"
    }
}
+73 −2
Original line number Diff line number Diff line
@@ -16,7 +16,78 @@

package com.android.systemui.volume.panel.ui.viewmodel

class DefaultComponentsLayoutManagerTest {
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.testKosmos
import com.android.systemui.volume.panel.mockVolumePanelUiComponent
import com.android.systemui.volume.panel.shared.model.VolumePanelComponentKey
import com.android.systemui.volume.panel.ui.layout.ComponentsLayoutManager
import com.android.systemui.volume.panel.ui.layout.DefaultComponentsLayoutManager
import com.google.common.truth.Truth
import org.junit.Test
import org.junit.runner.RunWith

    // TODO(b/318080198) Write tests
@SmallTest
@RunWith(AndroidJUnit4::class)
class DefaultComponentsLayoutManagerTest : SysuiTestCase() {

    private val kosmos = testKosmos()
    private val underTest: ComponentsLayoutManager = DefaultComponentsLayoutManager()

    @Test
    fun bottomBar_isSet() {
        val bottomBarComponentState =
            ComponentState(BOTTOM_BAR, kosmos.mockVolumePanelUiComponent, false)
        val layout =
            underTest.layout(
                VolumePanelState(0, false),
                setOf(
                    bottomBarComponentState,
                    ComponentState(COMPONENT_1, kosmos.mockVolumePanelUiComponent, false),
                    ComponentState(COMPONENT_2, kosmos.mockVolumePanelUiComponent, false),
                )
            )

        Truth.assertThat(layout.bottomBarComponent).isEqualTo(bottomBarComponentState)
    }

    @Test
    fun componentsAreInOrder() {
        val bottomBarComponentState =
            ComponentState(BOTTOM_BAR, kosmos.mockVolumePanelUiComponent, false)
        val component1State = ComponentState(COMPONENT_1, kosmos.mockVolumePanelUiComponent, false)
        val component2State = ComponentState(COMPONENT_2, kosmos.mockVolumePanelUiComponent, false)
        val layout =
            underTest.layout(
                VolumePanelState(0, false),
                setOf(
                    bottomBarComponentState,
                    component1State,
                    component2State,
                )
            )

        Truth.assertThat(layout.contentComponents[0]).isEqualTo(component1State)
        Truth.assertThat(layout.contentComponents[1]).isEqualTo(component2State)
    }

    @Test(expected = IllegalStateException::class)
    fun bottomBarAbsence_throwsException() {
        val component1State = ComponentState(COMPONENT_1, kosmos.mockVolumePanelUiComponent, false)
        val component2State = ComponentState(COMPONENT_2, kosmos.mockVolumePanelUiComponent, false)
        underTest.layout(
            VolumePanelState(0, false),
            setOf(
                component1State,
                component2State,
            )
        )
    }

    private companion object {
        const val BOTTOM_BAR: VolumePanelComponentKey = "bottom_bar"
        const val COMPONENT_1: VolumePanelComponentKey = "test_component:1"
        const val COMPONENT_2: VolumePanelComponentKey = "test_component:2"
    }
}
+115 −2
Original line number Diff line number Diff line
@@ -16,7 +16,120 @@

package com.android.systemui.volume.panel.ui.viewmodel

class VolumePanelViewModelTest {
import android.content.res.Configuration
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.testScope
import com.android.systemui.statusbar.policy.fakeConfigurationController
import com.android.systemui.testKosmos
import com.android.systemui.volume.panel.componentByKey
import com.android.systemui.volume.panel.componentsLayoutManager
import com.android.systemui.volume.panel.criteriaByKey
import com.android.systemui.volume.panel.dagger.factory.KosmosVolumePanelComponentFactory
import com.android.systemui.volume.panel.mockVolumePanelUiComponentProvider
import com.android.systemui.volume.panel.shared.model.VolumePanelComponentKey
import com.android.systemui.volume.panel.ui.layout.FakeComponentsLayoutManager
import com.android.systemui.volume.panel.unavailableCriteria
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith

    // TODO(b/318080198) Write tests
@SmallTest
@RunWith(AndroidJUnit4::class)
@OptIn(ExperimentalCoroutinesApi::class)
class VolumePanelViewModelTest : SysuiTestCase() {

    private val kosmos =
        testKosmos().apply {
            componentsLayoutManager = FakeComponentsLayoutManager { it.key == BOTTOM_BAR }
        }

    private val testableResources = context.orCreateTestableResources

    private lateinit var underTest: VolumePanelViewModel

    private fun initUnderTest() {
        underTest =
            VolumePanelViewModel(
                testableResources.resources,
                KosmosVolumePanelComponentFactory(kosmos),
                kosmos.fakeConfigurationController,
            )
    }

    @Test
    fun dismissingPanel_changesVisibility() {
        with(kosmos) {
            testScope.runTest {
                initUnderTest()
                assertThat(underTest.volumePanelState.value.isVisible).isTrue()

                underTest.dismissPanel()
                runCurrent()

                assertThat(underTest.volumePanelState.value.isVisible).isFalse()
            }
        }
    }

    @Test
    fun orientationChanges_panelOrientationChanges() {
        with(kosmos) {
            testScope.runTest {
                initUnderTest()
                val volumePanelState by collectLastValue(underTest.volumePanelState)
                testableResources.overrideConfiguration(
                    Configuration().apply { orientation = Configuration.ORIENTATION_PORTRAIT }
                )
                assertThat(volumePanelState!!.orientation)
                    .isEqualTo(Configuration.ORIENTATION_PORTRAIT)

                fakeConfigurationController.onConfigurationChanged(
                    Configuration().apply { orientation = Configuration.ORIENTATION_LANDSCAPE }
                )
                runCurrent()

                assertThat(volumePanelState!!.orientation)
                    .isEqualTo(Configuration.ORIENTATION_LANDSCAPE)
            }
        }
    }

    @Test
    fun components_areReturned() {
        with(kosmos) {
            testScope.runTest {
                componentByKey =
                    mapOf(
                        COMPONENT_1 to mockVolumePanelUiComponentProvider,
                        COMPONENT_2 to mockVolumePanelUiComponentProvider,
                        BOTTOM_BAR to mockVolumePanelUiComponentProvider,
                    )
                criteriaByKey = mapOf(COMPONENT_2 to unavailableCriteria)
                initUnderTest()

                val componentsLayout by collectLastValue(underTest.componentsLayout)
                runCurrent()

                assertThat(componentsLayout!!.contentComponents).hasSize(2)
                assertThat(componentsLayout!!.contentComponents[0].key).isEqualTo(COMPONENT_1)
                assertThat(componentsLayout!!.contentComponents[0].isVisible).isTrue()
                assertThat(componentsLayout!!.contentComponents[1].key).isEqualTo(COMPONENT_2)
                assertThat(componentsLayout!!.contentComponents[1].isVisible).isFalse()
                assertThat(componentsLayout!!.bottomBarComponent.key).isEqualTo(BOTTOM_BAR)
                assertThat(componentsLayout!!.bottomBarComponent.isVisible).isTrue()
            }
        }
    }

    private companion object {
        const val BOTTOM_BAR: VolumePanelComponentKey = "test_bottom_bar"
        const val COMPONENT_1: VolumePanelComponentKey = "test_component:1"
        const val COMPONENT_2: VolumePanelComponentKey = "test_component:2"
    }
}
Loading