diff options
author | 2022-11-28 23:32:22 +0000 | |
---|---|---|
committer | 2022-11-28 23:32:22 +0000 | |
commit | b769860c31cec33df924204c62d555aa1bf26e88 (patch) | |
tree | 3649b35119ab4af8cb679d000c6c133836efca98 | |
parent | 3d9d4e5f180b644f3d890cbb4c28823acbace4ed (diff) | |
parent | 5387ee15f5a100c51f331f1a155abe11de48b450 (diff) |
Merge "Add tests of BrowseActivity"
5 files changed, 182 insertions, 73 deletions
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/BrowseActivity.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/BrowseActivity.kt index c3c90ab4fdb8..6ed7481b2400 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/BrowseActivity.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/BrowseActivity.kt @@ -19,6 +19,7 @@ package com.android.settingslib.spa.framework import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent +import androidx.annotation.VisibleForTesting import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.DisposableEffect @@ -37,6 +38,7 @@ import androidx.navigation.compose.rememberNavController import com.android.settingslib.spa.R import com.android.settingslib.spa.framework.common.LogCategory import com.android.settingslib.spa.framework.common.SettingsPage +import com.android.settingslib.spa.framework.common.SettingsPageProvider import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory import com.android.settingslib.spa.framework.common.createSettingsPage import com.android.settingslib.spa.framework.compose.LocalNavController @@ -74,86 +76,97 @@ open class BrowseActivity : ComponentActivity() { setContent { SettingsTheme { - MainContent() + val sppRepository by spaEnvironment.pageProviderRepository + BrowseContent( + allProviders = sppRepository.getAllProviders(), + initialDestination = intent?.getStringExtra(KEY_DESTINATION) + ?: sppRepository.getDefaultStartPage(), + initialEntryId = intent?.getStringExtra(KEY_HIGHLIGHT_ENTRY) + ) } } } - @Composable - private fun MainContent() { - val sppRepository by spaEnvironment.pageProviderRepository - val navController = rememberNavController() - val nullPage = SettingsPage.createNull() - CompositionLocalProvider(navController.localNavController()) { - NavHost( - navController = navController, - startDestination = nullPage.sppName, - ) { - composable(nullPage.sppName) {} - for (spp in sppRepository.getAllProviders()) { - composable( - route = spp.name + spp.parameter.navRoute(), - arguments = spp.parameter, - ) { navBackStackEntry -> - PageLogger(remember(navBackStackEntry.arguments) { - spp.createSettingsPage(arguments = navBackStackEntry.arguments) - }) + companion object { + const val KEY_DESTINATION = "spaActivityDestination" + const val KEY_HIGHLIGHT_ENTRY = "highlightEntry" + } +} - spp.Page(navBackStackEntry.arguments) - } - } - } - InitialDestinationNavigator() - } +@VisibleForTesting +@Composable +fun BrowseContent( + allProviders: Collection<SettingsPageProvider>, + initialDestination: String, + initialEntryId: String? +) { + val navController = rememberNavController() + CompositionLocalProvider(navController.localNavController()) { + val controller = LocalNavController.current as NavControllerWrapperImpl + controller.NavContent(allProviders) + controller.InitialDestination(initialDestination, initialEntryId) } +} - @Composable - private fun PageLogger(settingsPage: SettingsPage) { - val lifecycleOwner = LocalLifecycleOwner.current - DisposableEffect(lifecycleOwner) { - val observer = LifecycleEventObserver { _, event -> - if (event == Lifecycle.Event.ON_START) { - settingsPage.enterPage() - } else if (event == Lifecycle.Event.ON_STOP) { - settingsPage.leavePage() - } +@Composable +private fun SettingsPageProvider.PageEvents(arguments: Bundle? = null) { + val page = remember(arguments) { createSettingsPage(arguments) } + val lifecycleOwner = LocalLifecycleOwner.current + DisposableEffect(lifecycleOwner) { + val observer = LifecycleEventObserver { _, event -> + if (event == Lifecycle.Event.ON_START) { + page.enterPage() + } else if (event == Lifecycle.Event.ON_STOP) { + page.leavePage() } + } - // Add the observer to the lifecycle - lifecycleOwner.lifecycle.addObserver(observer) + // Add the observer to the lifecycle + lifecycleOwner.lifecycle.addObserver(observer) - // When the effect leaves the Composition, remove the observer - onDispose { - lifecycleOwner.lifecycle.removeObserver(observer) - } + // When the effect leaves the Composition, remove the observer + onDispose { + lifecycleOwner.lifecycle.removeObserver(observer) } } +} - @Composable - private fun InitialDestinationNavigator() { - val sppRepository by spaEnvironment.pageProviderRepository - val destinationNavigated = rememberSaveable { mutableStateOf(false) } - if (destinationNavigated.value) return - destinationNavigated.value = true - val controller = LocalNavController.current as NavControllerWrapperImpl - LaunchedEffect(Unit) { - val destination = - intent?.getStringExtra(KEY_DESTINATION) ?: sppRepository.getDefaultStartPage() - val highlightEntryId = intent?.getStringExtra(KEY_HIGHLIGHT_ENTRY) - if (destination.isNotEmpty()) { - controller.highlightId = highlightEntryId - val navController = controller.navController - navController.navigate(destination) { - popUpTo(navController.graph.findStartDestination().id) { - inclusive = true - } - } +@Composable +private fun NavControllerWrapperImpl.NavContent(allProvider: Collection<SettingsPageProvider>) { + val nullPage = SettingsPage.createNull() + NavHost( + navController = navController, + startDestination = nullPage.sppName, + ) { + composable(nullPage.sppName) {} + for (spp in allProvider) { + composable( + route = spp.name + spp.parameter.navRoute(), + arguments = spp.parameter, + ) { navBackStackEntry -> + spp.PageEvents(navBackStackEntry.arguments) + spp.Page(navBackStackEntry.arguments) } } } +} - companion object { - const val KEY_DESTINATION = "spaActivityDestination" - const val KEY_HIGHLIGHT_ENTRY = "highlightEntry" +@Composable +private fun NavControllerWrapperImpl.InitialDestination( + destination: String, + highlightEntryId: String? +) { + val destinationNavigated = rememberSaveable { mutableStateOf(false) } + if (destinationNavigated.value) return + destinationNavigated.value = true + + if (destination.isEmpty()) return + LaunchedEffect(Unit) { + highlightId = highlightEntryId + navController.navigate(destination) { + popUpTo(navController.graph.findStartDestination().id) { + inclusive = true + } + } } } diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPage.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPage.kt index a372bbd3721b..82e05a55a64b 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPage.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPage.kt @@ -156,6 +156,15 @@ data class SettingsPage( } } +fun SettingsPageProvider.createSettingsPage(arguments: Bundle? = null): SettingsPage { + return SettingsPage.create( + name = name, + displayName = displayName, + parameter = parameter, + arguments = arguments + ) +} + fun String.toHashId(): String { return this.hashCode().toUInt().toString(36) } diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPageProvider.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPageProvider.kt index 60599d49968f..940005d0c514 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPageProvider.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPageProvider.kt @@ -51,12 +51,3 @@ interface SettingsPageProvider { } } } - -fun SettingsPageProvider.createSettingsPage(arguments: Bundle? = null): SettingsPage { - return SettingsPage.create( - name = name, - displayName = displayName, - parameter = parameter, - arguments = arguments - ) -} diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/BrowseActivityTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/BrowseActivityTest.kt new file mode 100644 index 000000000000..bde3bba149a3 --- /dev/null +++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/BrowseActivityTest.kt @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2022 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.settingslib.spa.framework + +import android.content.Context +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onAllNodesWithText +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.settingslib.spa.framework.common.LogCategory +import com.android.settingslib.spa.framework.common.LogEvent +import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory +import com.android.settingslib.spa.framework.common.createSettingsPage +import com.android.settingslib.spa.tests.testutils.SpaEnvironmentForTest +import com.android.settingslib.spa.tests.testutils.SpaLoggerForTest +import com.android.settingslib.spa.testutils.waitUntil +import com.google.common.truth.Truth +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +const val WAIT_UNTIL_TIMEOUT = 1000L + +@RunWith(AndroidJUnit4::class) +class BrowseActivityTest { + @get:Rule + val composeTestRule = createComposeRule() + + private val context: Context = ApplicationProvider.getApplicationContext() + private val spaLogger = SpaLoggerForTest() + private val spaEnvironment = SpaEnvironmentForTest(context, logger = spaLogger) + + @Test + fun testBrowsePage() { + spaLogger.reset() + SpaEnvironmentFactory.reset(spaEnvironment) + + val sppRepository by spaEnvironment.pageProviderRepository + val sppHome = sppRepository.getProviderOrNull("SppHome")!! + val pageHome = sppHome.createSettingsPage() + val sppLayer1 = sppRepository.getProviderOrNull("SppLayer1")!! + val pageLayer1 = sppLayer1.createSettingsPage() + + composeTestRule.setContent { + BrowseContent( + allProviders = listOf(sppHome, sppLayer1), + initialDestination = pageHome.buildRoute(), + initialEntryId = null + ) + } + + composeTestRule.onNodeWithText(sppHome.getTitle(null)).assertIsDisplayed() + spaLogger.verifyPageEvent(pageHome.id, 1, 0) + spaLogger.verifyPageEvent(pageLayer1.id, 0, 0) + + // click to layer1 page + composeTestRule.onNodeWithText("SppHome to Layer1").assertIsDisplayed().performClick() + waitUntil(WAIT_UNTIL_TIMEOUT) { + composeTestRule.onAllNodesWithText(sppLayer1.getTitle(null)) + .fetchSemanticsNodes().size == 1 + } + spaLogger.verifyPageEvent(pageHome.id, 1, 1) + spaLogger.verifyPageEvent(pageLayer1.id, 1, 0) + } +} + +private fun SpaLoggerForTest.verifyPageEvent(id: String, entryCount: Int, leaveCount: Int) { + Truth.assertThat(getEventCount(id, LogEvent.PAGE_ENTER, LogCategory.FRAMEWORK)) + .isEqualTo(entryCount) + Truth.assertThat(getEventCount(id, LogEvent.PAGE_LEAVE, LogCategory.FRAMEWORK)) + .isEqualTo(leaveCount) +} diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/tests/testutils/SpaEnvironmentForTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/tests/testutils/SpaEnvironmentForTest.kt index a404dd3df709..ab269f2f024a 100644 --- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/tests/testutils/SpaEnvironmentForTest.kt +++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/tests/testutils/SpaEnvironmentForTest.kt @@ -35,6 +35,7 @@ import com.android.settingslib.spa.framework.common.SettingsPageProviderReposito import com.android.settingslib.spa.framework.common.SpaEnvironment import com.android.settingslib.spa.framework.common.SpaLogger import com.android.settingslib.spa.framework.common.createSettingsPage +import com.android.settingslib.spa.widget.preference.SimplePreferenceMacro class SpaLoggerForTest : SpaLogger { data class MsgCountKey(val msg: String, val category: LogCategory) @@ -98,6 +99,12 @@ object SppLayer1 : SettingsPageProvider { fun buildInject(): SettingsEntryBuilder { return SettingsEntryBuilder.createInject(this.createSettingsPage()) + .setMacro { + SimplePreferenceMacro( + title = "SppHome to Layer1", + clickRoute = name + ) + } } override fun buildEntry(arguments: Bundle?): List<SettingsEntry> { |