No show AppButtons for system modules

To try:
1. adb shell am start -n com.android.settings/.spa.SpaActivity
2. Go to Apps -> All apps (Show system) -> Bluetooth

Bug: 236346018
Test: Unit test & Manual with Settings App
Change-Id: Ibdf5f1ec9f69beefe47fb7a046b0192a73e71b27
This commit is contained in:
Chaohui Wang
2022-10-28 15:26:02 +08:00
parent c972af0ca7
commit 56c9bfed08
5 changed files with 165 additions and 10 deletions

View File

@@ -0,0 +1,131 @@
/*
* 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.settings.spa.app.appinfo
import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.ModuleInfo
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.content.pm.PackageManager.NameNotFoundException
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsNotDisplayed
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onRoot
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.dx.mockito.inline.extended.ExtendedMockito
import com.android.settings.testutils.delay
import com.android.settingslib.applications.AppUtils
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.stateIn
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.doThrow
import org.mockito.MockitoSession
import org.mockito.Spy
import org.mockito.quality.Strictness
import org.mockito.Mockito.`when` as whenever
@RunWith(AndroidJUnit4::class)
class AppButtonsTest {
@get:Rule
val composeTestRule = createComposeRule()
private lateinit var mockSession: MockitoSession
@Spy
private val context: Context = ApplicationProvider.getApplicationContext()
@Mock
private lateinit var packageInfoPresenter: PackageInfoPresenter
@Mock
private lateinit var packageManager: PackageManager
@Before
fun setUp() {
mockSession = ExtendedMockito.mockitoSession()
.initMocks(this)
.mockStatic(AppUtils::class.java)
.strictness(Strictness.LENIENT)
.startMocking()
whenever(packageInfoPresenter.context).thenReturn(context)
whenever(packageInfoPresenter.packageName).thenReturn(PACKAGE_NAME)
whenever(packageInfoPresenter.userPackageManager).thenReturn(packageManager)
doThrow(NameNotFoundException()).`when`(packageManager).getModuleInfo(PACKAGE_NAME, 0)
whenever(packageManager.getPackageInfo(PACKAGE_NAME, 0)).thenReturn(PACKAGE_INFO)
whenever(AppUtils.isMainlineModule(packageManager, PACKAGE_NAME)).thenReturn(false)
}
@After
fun tearDown() {
mockSession.finishMocking()
}
@Test
fun isSystemModule_notDisplayed() {
doReturn(ModuleInfo()).`when`(packageManager).getModuleInfo(PACKAGE_NAME, 0)
setContent()
composeTestRule.onRoot().assertIsNotDisplayed()
}
@Test
fun isMainlineModule_notDisplayed() {
whenever(AppUtils.isMainlineModule(packageManager, PACKAGE_NAME)).thenReturn(true)
setContent()
composeTestRule.onRoot().assertIsNotDisplayed()
}
@Test
fun isNormalApp_displayed() {
setContent()
composeTestRule.onRoot().assertIsDisplayed()
}
private fun setContent() {
composeTestRule.setContent {
val scope = rememberCoroutineScope()
LaunchedEffect(Unit) {
whenever(packageInfoPresenter.flow).thenReturn(flowOf(PACKAGE_INFO).stateIn(scope))
}
AppButtons(packageInfoPresenter)
}
composeTestRule.delay()
}
private companion object {
const val PACKAGE_NAME = "package.name"
val PACKAGE_INFO = PackageInfo().apply {
applicationInfo = ApplicationInfo()
}
}
}

View File

@@ -16,6 +16,7 @@
package com.android.settings.testutils
import androidx.compose.ui.test.ComposeTimeoutException
import androidx.compose.ui.test.SemanticsMatcher
import androidx.compose.ui.test.junit4.ComposeContentTestRule
@@ -23,3 +24,10 @@ import androidx.compose.ui.test.junit4.ComposeContentTestRule
fun ComposeContentTestRule.waitUntilExists(matcher: SemanticsMatcher) = waitUntil {
onAllNodes(matcher).fetchSemanticsNodes().isNotEmpty()
}
/** Blocks until the timeout is reached. */
fun ComposeContentTestRule.delay(timeoutMillis: Long = 1_000) = try {
waitUntil(timeoutMillis) { false }
} catch (_: ComposeTimeoutException) {
// Expected
}