fix: 首次提交

This commit is contained in:
2024-12-09 11:25:23 +08:00
parent d0c01071e9
commit 2c2109a5f3
4741 changed files with 290641 additions and 0 deletions

View File

@@ -0,0 +1,155 @@
/*
* 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.spaprivileged.template.app
import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settingslib.spa.testutils.waitUntilExists
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class AppInfoTest {
@get:Rule
val composeTestRule = createComposeRule()
private val context: Context = ApplicationProvider.getApplicationContext()
@Test
fun appInfoLabel_isDisplayed() {
val packageInfo = PackageInfo().apply {
applicationInfo = APP
}
val appInfoProvider = AppInfoProvider(packageInfo)
composeTestRule.setContent {
CompositionLocalProvider(LocalContext provides context) {
appInfoProvider.AppInfo()
}
}
composeTestRule.waitUntilExists(hasText(LABEL))
}
@Test
fun appInfoVersion_whenDisplayVersionIsFalse() {
val packageInfo = PackageInfo().apply {
applicationInfo = APP
versionName = VERSION_NAME
}
val appInfoProvider = AppInfoProvider(packageInfo)
composeTestRule.setContent {
CompositionLocalProvider(LocalContext provides context) {
appInfoProvider.AppInfo(displayVersion = false)
}
}
composeTestRule.onNodeWithText(VERSION_NAME).assertDoesNotExist()
}
@Test
fun appInfoVersion_whenDisplayVersionIsTrue() {
val packageInfo = PackageInfo().apply {
applicationInfo = APP
versionName = VERSION_NAME
}
val appInfoProvider = AppInfoProvider(packageInfo)
composeTestRule.setContent {
CompositionLocalProvider(LocalContext provides context) {
appInfoProvider.AppInfo(displayVersion = true)
}
}
composeTestRule.onNodeWithText(VERSION_NAME).assertIsDisplayed()
}
@Test
fun footerAppVersion_versionIsDisplayed() {
val packageInfo = PackageInfo().apply {
applicationInfo = APP
versionName = VERSION_NAME
packageName = PACKAGE_NAME
}
val appInfoProvider = AppInfoProvider(packageInfo)
composeTestRule.setContent {
CompositionLocalProvider(LocalContext provides context) {
appInfoProvider.FooterAppVersion()
}
}
composeTestRule.onNodeWithText(text = "version $VERSION_NAME", substring = true)
.assertIsDisplayed()
}
@Test
fun footerAppVersion_developmentEnabled_packageNameIsDisplayed() {
val packageInfo = PackageInfo().apply {
applicationInfo = APP
versionName = VERSION_NAME
packageName = PACKAGE_NAME
}
val appInfoProvider = AppInfoProvider(packageInfo)
composeTestRule.setContent {
CompositionLocalProvider(LocalContext provides context) {
appInfoProvider.FooterAppVersion(showPackageName = true)
}
}
composeTestRule.onNodeWithText(text = PACKAGE_NAME, substring = true).assertIsDisplayed()
}
@Test
fun footerAppVersion_developmentDisabled_packageNameDoesNotExist() {
val packageInfo = PackageInfo().apply {
applicationInfo = APP
versionName = VERSION_NAME
packageName = PACKAGE_NAME
}
val appInfoProvider = AppInfoProvider(packageInfo)
composeTestRule.setContent {
CompositionLocalProvider(LocalContext provides context) {
appInfoProvider.FooterAppVersion(showPackageName = false)
}
}
composeTestRule.onNodeWithText(text = PACKAGE_NAME, substring = true).assertDoesNotExist()
}
private companion object {
const val LABEL = "Label"
const val VERSION_NAME = "VersionName"
const val PACKAGE_NAME = "package.name"
val APP = object : ApplicationInfo() {
override fun loadLabel(pm: PackageManager) = LABEL
}
}
}

View File

@@ -0,0 +1,125 @@
/*
* 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.spaprivileged.template.app
import android.content.Context
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithContentDescription
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.spaprivileged.R
import com.android.settingslib.spaprivileged.tests.testutils.TestAppListModel
import com.android.settingslib.spaprivileged.tests.testutils.TestAppRecord
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class AppListPageTest {
@get:Rule
val composeTestRule = createComposeRule()
private val context: Context = ApplicationProvider.getApplicationContext()
@Test
fun title_isDisplayed() {
setContent()
composeTestRule.onNodeWithText(TITLE).assertIsDisplayed()
}
@Test
fun appListState_hasCorrectInitialState() {
val inputState by setContent()
val state = inputState!!.state
assertThat(state.showSystem()).isFalse()
assertThat(state.searchQuery()).isEqualTo("")
}
@Test
fun canShowSystem() {
val inputState by setContent()
onMoreOptions().performClick()
composeTestRule.onNodeWithText(context.getString(R.string.menu_show_system)).performClick()
val state = inputState!!.state
assertThat(state.showSystem()).isTrue()
}
@Test
fun afterShowSystem_displayHideSystem() {
setContent()
onMoreOptions().performClick()
composeTestRule.onNodeWithText(context.getString(R.string.menu_show_system)).performClick()
onMoreOptions().performClick()
composeTestRule.onNodeWithText(context.getString(R.string.menu_hide_system))
.assertIsDisplayed()
}
@Test
fun noMoreOptions_notDisplayMoreOptions() {
setContent(noMoreOptions = true)
onMoreOptions().assertDoesNotExist()
}
@Test
fun noMoreOptions_showSystemIsFalse() {
val inputState by setContent(noMoreOptions = true)
val state = inputState!!.state
assertThat(state.showSystem()).isFalse()
}
private fun setContent(
noMoreOptions: Boolean = false,
header: @Composable () -> Unit = {},
): State<AppListInput<TestAppRecord>?> {
val appListState = mutableStateOf<AppListInput<TestAppRecord>?>(null)
composeTestRule.setContent {
AppListPage(
title = TITLE,
listModel = TestAppListModel(),
noMoreOptions = noMoreOptions,
header = header,
appList = { appListState.value = this },
)
}
return appListState
}
private fun onMoreOptions() =
composeTestRule.onNodeWithContentDescription(
context.getString(androidx.appcompat.R.string.abc_action_menu_overflow_description)
)
private companion object {
const val TITLE = "Title"
}
}

View File

@@ -0,0 +1,163 @@
/*
* 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.settingslib.spaprivileged.template.app
import android.content.pm.ApplicationInfo
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsEnabled
import androidx.compose.ui.test.assertIsNotEnabled
import androidx.compose.ui.test.assertIsOff
import androidx.compose.ui.test.assertIsOn
import androidx.compose.ui.test.isToggleable
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settingslib.spaprivileged.model.app.AppRecord
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class AppListSwitchItemTest {
@get:Rule
val composeTestRule = createComposeRule()
@Test
fun appLabel_displayed() {
composeTestRule.setContent {
ITEM_MODEL.AppListSwitchItem(
checked = { null },
changeable = { false },
onCheckedChange = {},
)
}
composeTestRule.onNodeWithText(LABEL).assertIsDisplayed()
}
@Test
fun summary_displayed() {
composeTestRule.setContent {
ITEM_MODEL.AppListSwitchItem(
checked = { null },
changeable = { false },
onCheckedChange = {},
)
}
composeTestRule.onNodeWithText(SUMMARY).assertIsDisplayed()
}
@Test
fun switch_checkIsNull() {
composeTestRule.setContent {
ITEM_MODEL.AppListSwitchItem(
checked = { null },
changeable = { false },
onCheckedChange = {},
)
}
composeTestRule.onNode(isToggleable()).assertDoesNotExist()
}
@Test
fun switch_checked() {
composeTestRule.setContent {
ITEM_MODEL.AppListSwitchItem(
checked = { true },
changeable = { false },
onCheckedChange = {},
)
}
composeTestRule.onNode(isToggleable()).assertIsOn()
}
@Test
fun switch_notChecked() {
composeTestRule.setContent {
ITEM_MODEL.AppListSwitchItem(
checked = { false },
changeable = { false },
onCheckedChange = {},
)
}
composeTestRule.onNode(isToggleable()).assertIsOff()
}
@Test
fun switch_changeable() {
composeTestRule.setContent {
ITEM_MODEL.AppListSwitchItem(
checked = { false },
changeable = { true },
onCheckedChange = {},
)
}
composeTestRule.onNode(isToggleable()).assertIsEnabled()
}
@Test
fun switch_notChangeable() {
composeTestRule.setContent {
ITEM_MODEL.AppListSwitchItem(
checked = { false },
changeable = { false },
onCheckedChange = {},
)
}
composeTestRule.onNode(isToggleable()).assertIsNotEnabled()
}
@Test
fun switch_onClick() {
var switchClicked = false
composeTestRule.setContent {
ITEM_MODEL.AppListSwitchItem(
checked = { false },
changeable = { true },
onCheckedChange = { switchClicked = true },
)
}
composeTestRule.onNode(isToggleable()).performClick()
assertThat(switchClicked).isTrue()
}
private companion object {
const val PACKAGE_NAME = "package.name"
const val LABEL = "Label"
const val SUMMARY = "Summary"
val APP = ApplicationInfo().apply {
packageName = PACKAGE_NAME
}
val ITEM_MODEL = AppListItemModel(
record = object : AppRecord {
override val app = APP
},
label = LABEL,
summary = { SUMMARY },
)
}
}

View File

@@ -0,0 +1,186 @@
/*
* 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.spaprivileged.template.app
import android.content.Context
import android.content.pm.ApplicationInfo
import android.icu.text.CollationKey
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.unit.dp
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settingslib.spa.widget.ui.SpinnerOption
import com.android.settingslib.spaprivileged.R
import com.android.settingslib.spaprivileged.model.app.AppEntry
import com.android.settingslib.spaprivileged.model.app.AppListData
import com.android.settingslib.spaprivileged.model.app.IAppListViewModel
import com.android.settingslib.spaprivileged.tests.testutils.TestAppListModel
import com.android.settingslib.spaprivileged.tests.testutils.TestAppRecord
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flowOf
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@OptIn(ExperimentalTestApi::class)
@RunWith(AndroidJUnit4::class)
class AppListTest {
@get:Rule
val composeTestRule = createComposeRule()
private val context: Context = ApplicationProvider.getApplicationContext()
@Test
fun whenHasOptions_firstOptionDisplayed() {
setContent(options = listOf(OPTION_0, OPTION_1))
composeTestRule.waitUntilExactlyOneExists(
matcher = hasText(OPTION_0),
timeoutMillis = 5_000,
)
composeTestRule.onNodeWithText(OPTION_1).assertDoesNotExist()
}
@Test
fun whenHasOptions_couldSwitchOption() {
setContent(options = listOf(OPTION_0, OPTION_1))
composeTestRule.waitUntilExactlyOneExists(
matcher = hasText(OPTION_0),
timeoutMillis = 5_000,
)
composeTestRule.onNodeWithText(OPTION_0).performClick()
composeTestRule.onNodeWithText(OPTION_1).performClick()
composeTestRule.onNodeWithText(OPTION_1).assertIsDisplayed()
composeTestRule.onNodeWithText(OPTION_0).assertDoesNotExist()
}
@Test
fun whenNoApps() {
setContent(appEntries = emptyList())
composeTestRule.waitUntilExactlyOneExists(
matcher = hasText(context.getString(R.string.no_applications)),
timeoutMillis = 5_000,
)
}
@Test
fun couldShowAppItem() {
setContent(appEntries = listOf(APP_ENTRY_A))
composeTestRule.waitUntilExactlyOneExists(
matcher = hasText(APP_ENTRY_A.label),
timeoutMillis = 5_000,
)
}
@Test
fun couldShowHeader() {
setContent(appEntries = listOf(APP_ENTRY_A), header = { Text(HEADER) })
composeTestRule.waitUntilExactlyOneExists(
matcher = hasText(HEADER),
timeoutMillis = 5_000,
)
}
@Test
fun whenNotGrouped_groupTitleDoesNotExist() {
setContent(appEntries = listOf(APP_ENTRY_A, APP_ENTRY_B), enableGrouping = false)
composeTestRule.onNodeWithText(GROUP_A).assertDoesNotExist()
composeTestRule.onNodeWithText(GROUP_B).assertDoesNotExist()
}
@Test
fun whenGrouped_groupTitleDisplayed() {
setContent(appEntries = listOf(APP_ENTRY_A, APP_ENTRY_B), enableGrouping = true)
composeTestRule.waitUntilExactlyOneExists(
matcher = hasText(GROUP_A),
timeoutMillis = 5_000,
)
composeTestRule.onNodeWithText(GROUP_B).assertIsDisplayed()
}
private fun setContent(
options: List<String> = emptyList(),
appEntries: List<AppEntry<TestAppRecord>> = emptyList(),
header: @Composable () -> Unit = {},
enableGrouping: Boolean = false,
) {
val appListInput = AppListInput(
config = AppListConfig(
userIds = listOf(USER_ID),
showInstantApps = false,
matchAnyUserForAdmin = false,
),
listModel = TestAppListModel(enableGrouping = enableGrouping),
state = AppListState(showSystem = { false }, searchQuery = { "" }),
header = header,
bottomPadding = 0.dp,
)
val listViewModel = object : IAppListViewModel<TestAppRecord> {
override val optionFlow = MutableStateFlow<Int?>(null)
override val spinnerOptionsFlow = flowOf(options.mapIndexed { index, option ->
SpinnerOption(id = index, text = option)
})
override val appListDataFlow = flowOf(AppListData(appEntries, option = 0))
}
composeTestRule.setContent {
appListInput.AppListImpl { listViewModel }
}
}
private companion object {
const val USER_ID = 0
const val OPTION_0 = "Option 1"
const val OPTION_1 = "Option 2"
const val HEADER = "Header"
const val GROUP_A = "Group A"
const val GROUP_B = "Group B"
val APP_ENTRY_A = AppEntry(
record = TestAppRecord(
app = ApplicationInfo().apply {
packageName = "package.name.a"
},
group = GROUP_A,
),
label = "Label A",
labelCollationKey = CollationKey("", byteArrayOf()),
)
val APP_ENTRY_B = AppEntry(
record = TestAppRecord(
app = ApplicationInfo().apply {
packageName = "package.name.b"
},
group = GROUP_B,
),
label = "Label B",
labelCollationKey = CollationKey("", byteArrayOf()),
)
}
}

View File

@@ -0,0 +1,188 @@
/*
* 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.settingslib.spaprivileged.template.app
import android.content.pm.ApplicationInfo
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsEnabled
import androidx.compose.ui.test.assertIsNotEnabled
import androidx.compose.ui.test.assertIsOff
import androidx.compose.ui.test.assertIsOn
import androidx.compose.ui.test.isToggleable
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settingslib.spaprivileged.model.app.AppRecord
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class AppListTwoTargetSwitchItemTest {
@get:Rule
val composeTestRule = createComposeRule()
@Test
fun appLabel_displayed() {
composeTestRule.setContent {
ITEM_MODEL.AppListTwoTargetSwitchItem(
onClick = {},
checked = { null },
changeable = { false },
onCheckedChange = {},
)
}
composeTestRule.onNodeWithText(LABEL).assertIsDisplayed()
}
@Test
fun summary_displayed() {
composeTestRule.setContent {
ITEM_MODEL.AppListTwoTargetSwitchItem(
onClick = {},
checked = { null },
changeable = { false },
onCheckedChange = {},
)
}
composeTestRule.onNodeWithText(SUMMARY).assertIsDisplayed()
}
@Test
fun title_onClick() {
var titleClicked = false
composeTestRule.setContent {
ITEM_MODEL.AppListTwoTargetSwitchItem(
onClick = { titleClicked = true },
checked = { false },
changeable = { false },
onCheckedChange = {},
)
}
composeTestRule.onNodeWithText(LABEL).performClick()
assertThat(titleClicked).isTrue()
}
@Test
fun switch_checkIsNull() {
composeTestRule.setContent {
ITEM_MODEL.AppListTwoTargetSwitchItem(
onClick = {},
checked = { null },
changeable = { false },
onCheckedChange = {},
)
}
composeTestRule.onNode(isToggleable()).assertDoesNotExist()
}
@Test
fun switch_checked() {
composeTestRule.setContent {
ITEM_MODEL.AppListTwoTargetSwitchItem(
onClick = {},
checked = { true },
changeable = { false },
onCheckedChange = {},
)
}
composeTestRule.onNode(isToggleable()).assertIsOn()
}
@Test
fun switch_notChecked() {
composeTestRule.setContent {
ITEM_MODEL.AppListTwoTargetSwitchItem(
onClick = {},
checked = { false },
changeable = { false },
onCheckedChange = {},
)
}
composeTestRule.onNode(isToggleable()).assertIsOff()
}
@Test
fun switch_changeable() {
composeTestRule.setContent {
ITEM_MODEL.AppListTwoTargetSwitchItem(
onClick = {},
checked = { false },
changeable = { true },
onCheckedChange = {},
)
}
composeTestRule.onNode(isToggleable()).assertIsEnabled()
}
@Test
fun switch_notChangeable() {
composeTestRule.setContent {
ITEM_MODEL.AppListTwoTargetSwitchItem(
onClick = {},
checked = { false },
changeable = { false },
onCheckedChange = {},
)
}
composeTestRule.onNode(isToggleable()).assertIsNotEnabled()
}
@Test
fun switch_onClick() {
var switchClicked = false
composeTestRule.setContent {
ITEM_MODEL.AppListTwoTargetSwitchItem(
onClick = {},
checked = { false },
changeable = { true },
onCheckedChange = { switchClicked = true },
)
}
composeTestRule.onNode(isToggleable()).performClick()
assertThat(switchClicked).isTrue()
}
private companion object {
const val PACKAGE_NAME = "package.name"
const val LABEL = "Label"
const val SUMMARY = "Summary"
val APP = ApplicationInfo().apply {
packageName = PACKAGE_NAME
}
val ITEM_MODEL = AppListItemModel(
record = object : AppRecord {
override val app = APP
},
label = LABEL,
summary = { SUMMARY },
)
}
}

View File

@@ -0,0 +1,339 @@
/*
* 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.spaprivileged.template.app
import android.app.AppOpsManager
import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settingslib.spa.testutils.firstWithTimeoutOrNull
import com.android.settingslib.spaprivileged.framework.common.appOpsManager
import com.android.settingslib.spaprivileged.model.app.IAppOpsController
import com.android.settingslib.spaprivileged.model.app.IPackageManagers
import com.android.settingslib.spaprivileged.test.R
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.any
import org.mockito.kotlin.doNothing
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.spy
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
@RunWith(AndroidJUnit4::class)
class AppOpPermissionAppListTest {
@get:Rule
val composeTestRule = createComposeRule()
private val packageManagers = mock<IPackageManagers>()
private val appOpsManager = mock<AppOpsManager>()
private val packageManager = mock<PackageManager> {
doNothing().whenever(mock).updatePermissionFlags(any(), any(), any(), any(), any())
}
private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
on { appOpsManager } doReturn appOpsManager
on { packageManager } doReturn packageManager
}
private val listModel = TestAppOpPermissionAppListModel()
@Test
fun transformItem_recordHasCorrectApp() {
val record = listModel.transformItem(APP)
assertThat(record.app).isSameInstanceAs(APP)
}
@Test
fun transformItem_hasRequestPermission() = runTest {
with(packageManagers) { whenever(APP.hasRequestPermission(PERMISSION)).thenReturn(true) }
val record = listModel.transformItem(APP)
assertThat(record.hasRequestPermission).isTrue()
}
@Test
fun transformItem_notRequestPermission() = runTest {
with(packageManagers) { whenever(APP.hasRequestPermission(PERMISSION)).thenReturn(false) }
val record = listModel.transformItem(APP)
assertThat(record.hasRequestPermission).isFalse()
}
@Test
fun transformItem_hasRequestBroaderPermission() = runTest {
listModel.broaderPermission = BROADER_PERMISSION
with(packageManagers) {
whenever(APP.hasRequestPermission(BROADER_PERMISSION)).thenReturn(true)
}
val record = listModel.transformItem(APP)
assertThat(record.hasRequestBroaderPermission).isTrue()
}
@Test
fun transformItem_notRequestBroaderPermission() = runTest {
listModel.broaderPermission = BROADER_PERMISSION
with(packageManagers) {
whenever(APP.hasRequestPermission(BROADER_PERMISSION)).thenReturn(false)
}
val record = listModel.transformItem(APP)
assertThat(record.hasRequestPermission).isFalse()
}
@Test
fun filter() = runTest {
with(packageManagers) { whenever(APP.hasRequestPermission(PERMISSION)).thenReturn(false) }
val record =
AppOpPermissionRecord(
app = APP,
hasRequestBroaderPermission = false,
hasRequestPermission = false,
appOpsController = FakeAppOpsController(fakeMode = AppOpsManager.MODE_DEFAULT),
)
val recordListFlow = listModel.filter(flowOf(USER_ID), flowOf(listOf(record)))
val recordList = recordListFlow.firstWithTimeoutOrNull()!!
assertThat(recordList).isEmpty()
}
@Test
fun isAllowed_allowed() {
val record =
AppOpPermissionRecord(
app = APP,
hasRequestBroaderPermission = false,
hasRequestPermission = true,
appOpsController = FakeAppOpsController(fakeMode = AppOpsManager.MODE_ALLOWED),
)
val isAllowed = getIsAllowed(record)
assertThat(isAllowed).isTrue()
}
@Test
fun isAllowed_defaultAndHasGrantPermission() {
with(packageManagers) { whenever(APP.hasGrantPermission(PERMISSION)).thenReturn(true) }
val record =
AppOpPermissionRecord(
app = APP,
hasRequestBroaderPermission = false,
hasRequestPermission = true,
appOpsController = FakeAppOpsController(fakeMode = AppOpsManager.MODE_DEFAULT),
)
val isAllowed = getIsAllowed(record)
assertThat(isAllowed).isTrue()
}
@Test
fun isAllowed_defaultAndNotGrantPermission() {
with(packageManagers) { whenever(APP.hasGrantPermission(PERMISSION)).thenReturn(false) }
val record =
AppOpPermissionRecord(
app = APP,
hasRequestBroaderPermission = false,
hasRequestPermission = true,
appOpsController = FakeAppOpsController(fakeMode = AppOpsManager.MODE_DEFAULT),
)
val isAllowed = getIsAllowed(record)
assertThat(isAllowed).isFalse()
}
@Test
fun isAllowed_broaderPermissionTrumps() {
listModel.broaderPermission = BROADER_PERMISSION
with(packageManagers) {
whenever(APP.hasGrantPermission(PERMISSION)).thenReturn(false)
whenever(APP.hasGrantPermission(BROADER_PERMISSION)).thenReturn(true)
}
val record =
AppOpPermissionRecord(
app = APP,
hasRequestBroaderPermission = true,
hasRequestPermission = false,
appOpsController = FakeAppOpsController(fakeMode = AppOpsManager.MODE_ERRORED),
)
val isAllowed = getIsAllowed(record)
assertThat(isAllowed).isTrue()
}
@Test
fun isAllowed_notAllowed() {
val record =
AppOpPermissionRecord(
app = APP,
hasRequestBroaderPermission = false,
hasRequestPermission = true,
appOpsController = FakeAppOpsController(fakeMode = AppOpsManager.MODE_ERRORED),
)
val isAllowed = getIsAllowed(record)
assertThat(isAllowed).isFalse()
}
@Test
fun isChangeable_notRequestPermission() {
val record =
AppOpPermissionRecord(
app = APP,
hasRequestBroaderPermission = false,
hasRequestPermission = false,
appOpsController = FakeAppOpsController(fakeMode = AppOpsManager.MODE_DEFAULT),
)
val isChangeable = listModel.isChangeable(record)
assertThat(isChangeable).isFalse()
}
@Test
fun isChangeable_notChangeablePackages() {
val record =
AppOpPermissionRecord(
app = NOT_CHANGEABLE_APP,
hasRequestBroaderPermission = false,
hasRequestPermission = true,
appOpsController = FakeAppOpsController(fakeMode = AppOpsManager.MODE_DEFAULT),
)
val isChangeable = listModel.isChangeable(record)
assertThat(isChangeable).isFalse()
}
@Test
fun isChangeable_hasRequestPermissionAndChangeable() {
val record =
AppOpPermissionRecord(
app = APP,
hasRequestBroaderPermission = false,
hasRequestPermission = true,
appOpsController = FakeAppOpsController(fakeMode = AppOpsManager.MODE_DEFAULT),
)
val isChangeable = listModel.isChangeable(record)
assertThat(isChangeable).isTrue()
}
@Test
fun isChangeable_broaderPermissionTrumps() {
listModel.broaderPermission = BROADER_PERMISSION
val record =
AppOpPermissionRecord(
app = APP,
hasRequestBroaderPermission = true,
hasRequestPermission = true,
appOpsController = FakeAppOpsController(fakeMode = AppOpsManager.MODE_DEFAULT),
)
val isChangeable = listModel.isChangeable(record)
assertThat(isChangeable).isFalse()
}
@Test
fun setAllowed() {
val appOpsController = FakeAppOpsController(fakeMode = AppOpsManager.MODE_DEFAULT)
val record =
AppOpPermissionRecord(
app = APP,
hasRequestBroaderPermission = false,
hasRequestPermission = true,
appOpsController = appOpsController,
)
listModel.setAllowed(record = record, newAllowed = true)
assertThat(appOpsController.setAllowedCalledWith).isTrue()
}
@Test
fun setAllowed_setModeByUid() {
listModel.setModeByUid = true
val record = listModel.transformItem(APP)
listModel.setAllowed(record = record, newAllowed = true)
verify(appOpsManager).setUidMode(listModel.appOp, APP.uid, AppOpsManager.MODE_ALLOWED)
}
private fun getIsAllowed(record: AppOpPermissionRecord): Boolean? {
lateinit var isAllowedState: () -> Boolean?
composeTestRule.setContent { isAllowedState = listModel.isAllowed(record) }
return isAllowedState()
}
private inner class TestAppOpPermissionAppListModel :
AppOpPermissionListModel(context, packageManagers) {
override val pageTitleResId = R.string.test_app_op_permission_title
override val switchTitleResId = R.string.test_app_op_permission_switch_title
override val footerResId = R.string.test_app_op_permission_footer
override val appOp = AppOpsManager.OP_MANAGE_MEDIA
override val permission = PERMISSION
override var broaderPermission: String? = null
override var setModeByUid = false
}
private companion object {
const val USER_ID = 0
const val PACKAGE_NAME = "package.name"
const val PERMISSION = "PERMISSION"
const val BROADER_PERMISSION = "BROADER_PERMISSION"
val APP = ApplicationInfo().apply { packageName = PACKAGE_NAME }
val NOT_CHANGEABLE_APP = ApplicationInfo().apply { packageName = "android" }
}
}
private class FakeAppOpsController(private val fakeMode: Int) : IAppOpsController {
var setAllowedCalledWith: Boolean? = null
override val mode = flowOf(fakeMode)
override fun setAllowed(allowed: Boolean) {
setAllowedCalledWith = allowed
}
override fun getMode() = fakeMode
}

View File

@@ -0,0 +1,113 @@
/*
* 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.spaprivileged.template.app
import android.app.usage.StorageStats
import android.app.usage.StorageStatsManager
import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager.NameNotFoundException
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settingslib.spa.framework.compose.stateOf
import com.android.settingslib.spaprivileged.framework.common.storageStatsManager
import com.android.settingslib.spaprivileged.model.app.userHandle
import java.util.UUID
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Spy
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule
import org.mockito.kotlin.whenever
@RunWith(AndroidJUnit4::class)
class AppStorageSizeTest {
@get:Rule
val mockito: MockitoRule = MockitoJUnit.rule()
@get:Rule
val composeTestRule = createComposeRule()
@Spy
private val context: Context = ApplicationProvider.getApplicationContext()
@Mock
private lateinit var storageStatsManager: StorageStatsManager
private val app = ApplicationInfo().apply {
storageUuid = UUID.randomUUID()
}
@Before
fun setUp() {
whenever(context.storageStatsManager).thenReturn(storageStatsManager)
whenever(
storageStatsManager.queryStatsForPackage(
app.storageUuid,
app.packageName,
app.userHandle,
)
).thenReturn(STATS)
}
@Test
fun getStorageSize() {
var storageSize = stateOf("")
composeTestRule.setContent {
CompositionLocalProvider(LocalContext provides context) {
storageSize = app.getStorageSize()
}
}
composeTestRule.waitUntil { storageSize.value == "120 B" }
}
@Test
fun getStorageSize_throwException() {
var storageSize = stateOf("Computing")
whenever(
storageStatsManager.queryStatsForPackage(
app.storageUuid,
app.packageName,
app.userHandle,
)
).thenThrow(NameNotFoundException())
composeTestRule.setContent {
CompositionLocalProvider(LocalContext provides context) {
storageSize = app.getStorageSize()
}
}
composeTestRule.waitUntil { storageSize.value == "" }
}
companion object {
private val STATS = StorageStats().apply {
codeBytes = 100
dataBytes = 20
cacheBytes = 3
}
}
}

View File

@@ -0,0 +1,237 @@
/*
* 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.spaprivileged.template.app
import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsNotDisplayed
import androidx.compose.ui.test.assertIsNotEnabled
import androidx.compose.ui.test.assertIsOff
import androidx.compose.ui.test.assertIsOn
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.onRoot
import androidx.compose.ui.test.performClick
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settingslib.spa.testutils.FakeNavControllerWrapper
import com.android.settingslib.spaprivileged.R
import com.android.settingslib.spaprivileged.model.app.IPackageManagers
import com.android.settingslib.spaprivileged.model.enterprise.NoRestricted
import com.android.settingslib.spaprivileged.tests.testutils.FakeRestrictionsProvider
import com.android.settingslib.spaprivileged.tests.testutils.TestTogglePermissionAppListModel
import com.android.settingslib.spaprivileged.tests.testutils.TestTogglePermissionAppListProvider
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
@RunWith(AndroidJUnit4::class)
class TogglePermissionAppInfoPageTest {
@get:Rule
val composeTestRule = createComposeRule()
private val context: Context = ApplicationProvider.getApplicationContext()
private val packageManagers = mock<IPackageManagers> {
on { getPackageInfoAsUser(PACKAGE_NAME, USER_ID) } doReturn PACKAGE_INFO
}
private val fakeNavControllerWrapper = FakeNavControllerWrapper()
private val fakeRestrictionsProvider = FakeRestrictionsProvider().apply {
restrictedMode = NoRestricted
}
private val appListTemplate =
TogglePermissionAppListTemplate(listOf(TestTogglePermissionAppListProvider))
private val appInfoPageProvider = TogglePermissionAppInfoPageProvider(appListTemplate)
@Test
fun buildEntry() {
val entryList = appInfoPageProvider.buildEntry(null)
assertThat(entryList).hasSize(1)
assertThat(entryList[0].label).isEqualTo("AllowControl")
}
@Test
fun entryItem_whenNotChangeable_notDisplayed() {
val listModel = TestTogglePermissionAppListModel(isChangeable = false)
setEntryItem(listModel)
composeTestRule.onRoot().assertIsNotDisplayed()
}
@Test
fun entryItem_whenChangeable_titleDisplayed() {
val listModel = TestTogglePermissionAppListModel(isChangeable = true)
setEntryItem(listModel)
composeTestRule.onNodeWithText(context.getString(listModel.pageTitleResId))
.assertIsDisplayed()
}
@Test
fun entryItem_whenAllowed_summaryIsAllowed() {
val listModel = TestTogglePermissionAppListModel(isAllowed = true, isChangeable = true)
setEntryItem(listModel)
composeTestRule.onNodeWithText(context.getString(R.string.app_permission_summary_allowed))
.assertIsDisplayed()
}
@Test
fun entryItem_whenNotAllowed_summaryIsNotAllowed() {
val listModel = TestTogglePermissionAppListModel(isAllowed = false, isChangeable = true)
setEntryItem(listModel)
composeTestRule.onNodeWithText(
context.getString(R.string.app_permission_summary_not_allowed)
).assertIsDisplayed()
}
@Test
fun entryItem_onClick() {
val listModel = TestTogglePermissionAppListModel(isChangeable = true)
setEntryItem(listModel)
composeTestRule.onRoot().performClick()
assertThat(fakeNavControllerWrapper.navigateCalledWith)
.isEqualTo("TogglePermissionAppInfoPage/test.PERMISSION/package.name/0")
}
@Test
fun infoPage_title_isDisplayed() {
val listModel = TestTogglePermissionAppListModel()
setTogglePermissionAppInfoPage(listModel)
composeTestRule.onNodeWithText(context.getString(listModel.pageTitleResId))
.assertIsDisplayed()
}
@Test
fun infoPage_whenAllowed_switchIsOn() {
val listModel = TestTogglePermissionAppListModel(isAllowed = true)
setTogglePermissionAppInfoPage(listModel)
composeTestRule.onNodeWithText(context.getString(listModel.switchTitleResId))
.assertIsOn()
}
@Test
fun infoPage_whenNotAllowed_switchIsOff() {
val listModel = TestTogglePermissionAppListModel(isAllowed = false)
setTogglePermissionAppInfoPage(listModel)
composeTestRule.onNodeWithText(context.getString(listModel.switchTitleResId))
.assertIsOff()
}
@Test
fun infoPage_whenChangeableAndClick() {
val listModel = TestTogglePermissionAppListModel(isAllowed = false, isChangeable = true)
setTogglePermissionAppInfoPage(listModel)
composeTestRule.onNodeWithText(context.getString(listModel.switchTitleResId))
.performClick()
composeTestRule.onNodeWithText(context.getString(listModel.switchTitleResId))
.assertIsOn()
}
@Test
fun infoPage_whenNotChangeableAndClick() {
val listModel = TestTogglePermissionAppListModel(isAllowed = false, isChangeable = false)
setTogglePermissionAppInfoPage(listModel)
composeTestRule.onNodeWithText(context.getString(listModel.switchTitleResId))
.performClick()
composeTestRule.onNodeWithText(context.getString(listModel.switchTitleResId))
.assertIsOff()
}
@Test
fun infoPage_whenNotChangeable_switchNotEnabled() {
val listModel = TestTogglePermissionAppListModel(isAllowed = false, isChangeable = false)
setTogglePermissionAppInfoPage(listModel)
composeTestRule.onNodeWithText(context.getString(listModel.switchTitleResId))
.assertIsDisplayed()
.assertIsNotEnabled()
}
@Test
fun infoPage_footer_isDisplayed() {
val listModel = TestTogglePermissionAppListModel()
setTogglePermissionAppInfoPage(listModel)
composeTestRule.onNodeWithText(context.getString(listModel.footerResId))
.assertIsDisplayed()
}
private fun setEntryItem(listModel: TestTogglePermissionAppListModel) {
composeTestRule.setContent {
fakeNavControllerWrapper.Wrapper {
listModel.TogglePermissionAppInfoPageEntryItem(
permissionType = PERMISSION_TYPE,
app = APP,
)
}
}
}
private fun setTogglePermissionAppInfoPage(listModel: TestTogglePermissionAppListModel) {
composeTestRule.setContent {
listModel.TogglePermissionAppInfoPage(
packageName = PACKAGE_NAME,
userId = USER_ID,
packageManagers = packageManagers,
restrictionsProviderFactory = { _, _ -> fakeRestrictionsProvider },
)
}
}
private companion object {
const val PERMISSION_TYPE = "test.PERMISSION"
const val USER_ID = 0
const val PACKAGE_NAME = "package.name"
val APP = ApplicationInfo().apply {
packageName = PACKAGE_NAME
}
val PACKAGE_INFO = PackageInfo().apply {
packageName = PACKAGE_NAME
applicationInfo = APP
}
}
}

View File

@@ -0,0 +1,169 @@
/*
* 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.spaprivileged.template.app
import android.content.Context
import android.content.pm.ApplicationInfo
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createComposeRule
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.testutils.FakeNavControllerWrapper
import com.android.settingslib.spaprivileged.R
import com.android.settingslib.spaprivileged.framework.compose.getPlaceholder
import com.android.settingslib.spaprivileged.model.enterprise.NoRestricted
import com.android.settingslib.spaprivileged.tests.testutils.FakeRestrictionsProvider
import com.android.settingslib.spaprivileged.tests.testutils.TestAppRecord
import com.android.settingslib.spaprivileged.tests.testutils.TestTogglePermissionAppListModel
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class TogglePermissionAppListPageTest {
@get:Rule
val composeTestRule = createComposeRule()
private val context: Context = ApplicationProvider.getApplicationContext()
private val fakeNavControllerWrapper = FakeNavControllerWrapper()
private val fakeRestrictionsProvider = FakeRestrictionsProvider()
@Test
fun pageTitle() {
val listModel = TestTogglePermissionAppListModel()
composeTestRule.setContent {
listModel.TogglePermissionAppList(
permissionType = PERMISSION_TYPE,
restrictionsProviderFactory = { _, _ -> fakeRestrictionsProvider },
appList = {},
)
}
composeTestRule.onNodeWithText(context.getString(listModel.pageTitleResId))
.assertIsDisplayed()
}
@Test
fun summary_whenAllowed() {
fakeRestrictionsProvider.restrictedMode = NoRestricted
val listModel = TestTogglePermissionAppListModel(isAllowed = true)
val summary = getSummary(listModel)
assertThat(summary).isEqualTo(context.getString(R.string.app_permission_summary_allowed))
}
@Test
fun summary_whenNotAllowed() {
fakeRestrictionsProvider.restrictedMode = NoRestricted
val listModel = TestTogglePermissionAppListModel(isAllowed = false)
val summary = getSummary(listModel)
assertThat(summary)
.isEqualTo(context.getString(R.string.app_permission_summary_not_allowed))
}
@Test
fun summary_whenComputingAllowed() {
fakeRestrictionsProvider.restrictedMode = NoRestricted
val listModel = TestTogglePermissionAppListModel(isAllowed = null)
val summary = getSummary(listModel)
assertThat(summary).isEqualTo(context.getPlaceholder())
}
@Test
fun appListItem_onClick_navigate() {
val listModel = TestTogglePermissionAppListModel()
composeTestRule.setContent {
fakeNavControllerWrapper.Wrapper {
with(createInternalAppListModel(listModel)) {
AppListItemModel(
record = listModel.transformItem(APP),
label = LABEL,
summary = { SUMMARY },
).AppItem()
}
}
}
composeTestRule.onNodeWithText(LABEL).performClick()
assertThat(fakeNavControllerWrapper.navigateCalledWith)
.isEqualTo("TogglePermissionAppInfoPage/test.PERMISSION/package.name/0")
}
@Test
fun getRoute() {
val route = TogglePermissionAppListPageProvider.getRoute(PERMISSION_TYPE)
assertThat(route).isEqualTo("TogglePermissionAppList/test.PERMISSION")
}
@Test
fun buildInjectEntry_titleDisplayed() {
val listModel = TestTogglePermissionAppListModel()
val entry = TogglePermissionAppListPageProvider.buildInjectEntry(PERMISSION_TYPE) {
listModel
}.build()
composeTestRule.setContent {
CompositionLocalProvider(LocalContext provides context) {
entry.UiLayout()
}
}
composeTestRule.onNodeWithText(context.getString(listModel.pageTitleResId))
.assertIsDisplayed()
}
private fun createInternalAppListModel(listModel: TestTogglePermissionAppListModel) =
TogglePermissionInternalAppListModel(
context = context,
permissionType = PERMISSION_TYPE,
listModel = listModel,
restrictionsProviderFactory = { _, _ -> fakeRestrictionsProvider },
)
private fun getSummary(listModel: TestTogglePermissionAppListModel): String {
lateinit var summary: () -> String
composeTestRule.setContent {
summary = createInternalAppListModel(listModel).getSummary(record = TestAppRecord(APP))
}
return summary()
}
private companion object {
const val PERMISSION_TYPE = "test.PERMISSION"
const val PACKAGE_NAME = "package.name"
const val LABEL = "Label"
const val SUMMARY = "Summary"
val APP = ApplicationInfo().apply {
packageName = PACKAGE_NAME
}
}
}

View File

@@ -0,0 +1,72 @@
/*
* 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.spaprivileged.template.app
import android.content.Context
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settingslib.spaprivileged.test.R
import com.android.settingslib.spaprivileged.tests.testutils.TestTogglePermissionAppListProvider
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class TogglePermissionAppListTest {
@get:Rule
val composeTestRule = createComposeRule()
private val context: Context = ApplicationProvider.getApplicationContext()
@Test
fun appListInjectEntry_titleDisplayed() {
val entry = TestTogglePermissionAppListProvider.buildAppListInjectEntry().build()
composeTestRule.setContent {
CompositionLocalProvider(LocalContext provides context) {
entry.UiLayout()
}
}
composeTestRule.onNodeWithText(context.getString(R.string.test_permission_title))
.assertIsDisplayed()
}
@Test
fun appListRoute() {
val route = TestTogglePermissionAppListProvider.getAppListRoute()
assertThat(route).isEqualTo("TogglePermissionAppList/test.PERMISSION")
}
@Test
fun togglePermissionAppListTemplate_createPageProviders() {
val togglePermissionAppListTemplate =
TogglePermissionAppListTemplate(listOf(TestTogglePermissionAppListProvider))
val createPageProviders = togglePermissionAppListTemplate.createPageProviders()
assertThat(createPageProviders).hasSize(2)
assertThat(createPageProviders.any { it is TogglePermissionAppListPageProvider }).isTrue()
assertThat(createPageProviders.any { it is TogglePermissionAppInfoPageProvider }).isTrue()
}
}

View File

@@ -0,0 +1,73 @@
/*
* 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.settingslib.spaprivileged.template.common
import android.content.Context
import android.content.pm.UserInfo
import android.content.pm.UserProperties
import android.os.UserManager
import androidx.compose.material3.Text
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settingslib.spaprivileged.framework.common.userManager
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.any
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.spy
@RunWith(AndroidJUnit4::class)
class UserProfilePagerTest {
@get:Rule
val composeTestRule = createComposeRule()
private val mockUserManager = mock<UserManager> {
on { getProfiles(any()) } doReturn listOf(USER_0)
on { getUserProperties(USER_0.userHandle) } doReturn
UserProperties.Builder()
.setShowInSettings(UserProperties.SHOW_IN_LAUNCHER_WITH_PARENT)
.build()
}
private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
on { userManager } doReturn mockUserManager
}
@Test
fun userProfilePager() {
composeTestRule.setContent {
CompositionLocalProvider(LocalContext provides context) {
UserProfilePager { userGroup ->
Text(text = userGroup.userInfos.joinToString { it.id.toString() })
}
}
}
composeTestRule.onNodeWithText(USER_0.id.toString()).assertIsDisplayed()
}
private companion object {
val USER_0 = UserInfo(0, "", 0)
}
}

View File

@@ -0,0 +1,157 @@
/*
* 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.settingslib.spaprivileged.template.preference
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsEnabled
import androidx.compose.ui.test.assertIsNotEnabled
import androidx.compose.ui.test.isOff
import androidx.compose.ui.test.isOn
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.onRoot
import androidx.compose.ui.test.performClick
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
import com.android.settingslib.spaprivileged.model.enterprise.BaseUserRestricted
import com.android.settingslib.spaprivileged.model.enterprise.NoRestricted
import com.android.settingslib.spaprivileged.model.enterprise.Restrictions
import com.android.settingslib.spaprivileged.tests.testutils.FakeBlockedByAdmin
import com.android.settingslib.spaprivileged.tests.testutils.FakeRestrictionsProvider
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class RestrictedMainSwitchPreferenceTest {
@get:Rule
val composeTestRule = createComposeRule()
private val fakeBlockedByAdmin = FakeBlockedByAdmin()
private val fakeRestrictionsProvider = FakeRestrictionsProvider()
private val switchPreferenceModel = object : SwitchPreferenceModel {
override val title = TITLE
private val checkedState = mutableStateOf(true)
override val checked = { checkedState.value }
override val onCheckedChange: (Boolean) -> Unit = { checkedState.value = it }
}
@Test
fun whenRestrictionsKeysIsEmpty_enabled() {
val restrictions = Restrictions(userId = USER_ID, keys = emptyList())
setContent(restrictions)
composeTestRule.onNodeWithText(TITLE).assertIsDisplayed().assertIsEnabled()
composeTestRule.onNode(isOn()).assertIsDisplayed()
}
@Test
fun whenRestrictionsKeysIsEmpty_toggleable() {
val restrictions = Restrictions(userId = USER_ID, keys = emptyList())
setContent(restrictions)
composeTestRule.onRoot().performClick()
composeTestRule.onNode(isOff()).assertIsDisplayed()
}
@Test
fun whenNoRestricted_enabled() {
val restrictions = Restrictions(userId = USER_ID, keys = listOf(RESTRICTION_KEY))
fakeRestrictionsProvider.restrictedMode = NoRestricted
setContent(restrictions)
composeTestRule.onNodeWithText(TITLE).assertIsDisplayed().assertIsEnabled()
composeTestRule.onNode(isOn()).assertIsDisplayed()
}
@Test
fun whenNoRestricted_toggleable() {
val restrictions = Restrictions(userId = USER_ID, keys = listOf(RESTRICTION_KEY))
fakeRestrictionsProvider.restrictedMode = NoRestricted
setContent(restrictions)
composeTestRule.onRoot().performClick()
composeTestRule.onNode(isOff()).assertIsDisplayed()
}
@Test
fun whenBaseUserRestricted_disabled() {
val restrictions = Restrictions(userId = USER_ID, keys = listOf(RESTRICTION_KEY))
fakeRestrictionsProvider.restrictedMode = BaseUserRestricted
setContent(restrictions)
composeTestRule.onNodeWithText(TITLE).assertIsDisplayed().assertIsNotEnabled()
composeTestRule.onNode(isOff()).assertIsDisplayed()
}
@Test
fun whenBaseUserRestricted_notToggleable() {
val restrictions = Restrictions(userId = USER_ID, keys = listOf(RESTRICTION_KEY))
fakeRestrictionsProvider.restrictedMode = BaseUserRestricted
setContent(restrictions)
composeTestRule.onRoot().performClick()
composeTestRule.onNode(isOff()).assertIsDisplayed()
}
@Test
fun whenBlockedByAdmin_disabled() {
val restrictions = Restrictions(userId = USER_ID, keys = listOf(RESTRICTION_KEY))
fakeRestrictionsProvider.restrictedMode = fakeBlockedByAdmin
setContent(restrictions)
composeTestRule.onNodeWithText(TITLE).assertIsDisplayed().assertIsEnabled()
composeTestRule.onNodeWithText(FakeBlockedByAdmin.SUMMARY).assertDoesNotExist()
composeTestRule.onNode(isOn()).assertIsDisplayed()
}
@Test
fun whenBlockedByAdmin_click() {
val restrictions = Restrictions(userId = USER_ID, keys = listOf(RESTRICTION_KEY))
fakeRestrictionsProvider.restrictedMode = fakeBlockedByAdmin
setContent(restrictions)
composeTestRule.onRoot().performClick()
assertThat(fakeBlockedByAdmin.sendShowAdminSupportDetailsIntentIsCalled).isTrue()
}
private fun setContent(restrictions: Restrictions) {
composeTestRule.setContent {
RestrictedMainSwitchPreference(switchPreferenceModel, restrictions) { _, _ ->
fakeRestrictionsProvider
}
}
}
private companion object {
const val TITLE = "Title"
const val USER_ID = 0
const val RESTRICTION_KEY = "restriction_key"
}
}

View File

@@ -0,0 +1,149 @@
/*
* 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.settingslib.spaprivileged.template.preference
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsEnabled
import androidx.compose.ui.test.assertIsNotEnabled
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.onRoot
import androidx.compose.ui.test.performClick
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settingslib.spa.widget.preference.PreferenceModel
import com.android.settingslib.spaprivileged.model.enterprise.BaseUserRestricted
import com.android.settingslib.spaprivileged.model.enterprise.NoRestricted
import com.android.settingslib.spaprivileged.model.enterprise.Restrictions
import com.android.settingslib.spaprivileged.tests.testutils.FakeBlockedByAdmin
import com.android.settingslib.spaprivileged.tests.testutils.FakeRestrictionsProvider
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class RestrictedPreferenceTest {
@get:Rule
val composeTestRule = createComposeRule()
private val fakeBlockedByAdmin = FakeBlockedByAdmin()
private val fakeRestrictionsProvider = FakeRestrictionsProvider()
private var clicked = false
private val preferenceModel = object : PreferenceModel {
override val title = TITLE
override val onClick = { clicked = true }
}
@Test
fun whenRestrictionsKeysIsEmpty_enabled() {
val restrictions = Restrictions(userId = USER_ID, keys = emptyList())
setContent(restrictions)
composeTestRule.onNodeWithText(TITLE).assertIsDisplayed().assertIsEnabled()
}
@Test
fun whenRestrictionsKeysIsEmpty_clickable() {
val restrictions = Restrictions(userId = USER_ID, keys = emptyList())
setContent(restrictions)
composeTestRule.onRoot().performClick()
assertThat(clicked).isTrue()
}
@Test
fun whenNoRestricted_enabled() {
val restrictions = Restrictions(userId = USER_ID, keys = listOf(RESTRICTION_KEY))
fakeRestrictionsProvider.restrictedMode = NoRestricted
setContent(restrictions)
composeTestRule.onNodeWithText(TITLE).assertIsDisplayed().assertIsEnabled()
}
@Test
fun whenNoRestricted_clickable() {
val restrictions = Restrictions(userId = USER_ID, keys = listOf(RESTRICTION_KEY))
fakeRestrictionsProvider.restrictedMode = NoRestricted
setContent(restrictions)
composeTestRule.onRoot().performClick()
assertThat(clicked).isTrue()
}
@Test
fun whenBaseUserRestricted_disabled() {
val restrictions = Restrictions(userId = USER_ID, keys = listOf(RESTRICTION_KEY))
fakeRestrictionsProvider.restrictedMode = BaseUserRestricted
setContent(restrictions)
composeTestRule.onNodeWithText(TITLE).assertIsDisplayed().assertIsNotEnabled()
}
@Test
fun whenBaseUserRestricted_notClickable() {
val restrictions = Restrictions(userId = USER_ID, keys = listOf(RESTRICTION_KEY))
fakeRestrictionsProvider.restrictedMode = BaseUserRestricted
setContent(restrictions)
composeTestRule.onRoot().performClick()
assertThat(clicked).isFalse()
}
@Test
fun whenBlockedByAdmin_widgetInEnableStateToAllowClick() {
val restrictions = Restrictions(userId = USER_ID, keys = listOf(RESTRICTION_KEY))
fakeRestrictionsProvider.restrictedMode = fakeBlockedByAdmin
setContent(restrictions)
composeTestRule.onNodeWithText(TITLE).assertIsDisplayed().assertIsEnabled()
}
@Test
fun whenBlockedByAdmin_click() {
val restrictions = Restrictions(userId = USER_ID, keys = listOf(RESTRICTION_KEY))
fakeRestrictionsProvider.restrictedMode = fakeBlockedByAdmin
setContent(restrictions)
composeTestRule.onRoot().performClick()
assertThat(fakeBlockedByAdmin.sendShowAdminSupportDetailsIntentIsCalled).isTrue()
}
private fun setContent(restrictions: Restrictions) {
composeTestRule.setContent {
RestrictedPreference(preferenceModel, restrictions) { _, _ ->
fakeRestrictionsProvider
}
}
}
private companion object {
const val TITLE = "Title"
const val USER_ID = 0
const val RESTRICTION_KEY = "restriction_key"
}
}

View File

@@ -0,0 +1,182 @@
/*
* 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.spaprivileged.template.preference
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsEnabled
import androidx.compose.ui.test.assertIsNotEnabled
import androidx.compose.ui.test.isOff
import androidx.compose.ui.test.isOn
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.onRoot
import androidx.compose.ui.test.performClick
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
import com.android.settingslib.spaprivileged.model.enterprise.BaseUserRestricted
import com.android.settingslib.spaprivileged.model.enterprise.NoRestricted
import com.android.settingslib.spaprivileged.model.enterprise.Restrictions
import com.android.settingslib.spaprivileged.tests.testutils.FakeBlockedByAdmin
import com.android.settingslib.spaprivileged.tests.testutils.FakeBlockedByEcm
import com.android.settingslib.spaprivileged.tests.testutils.FakeRestrictionsProvider
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class RestrictedSwitchPreferenceTest {
@get:Rule
val composeTestRule = createComposeRule()
private val fakeBlockedByAdmin = FakeBlockedByAdmin()
private val fakeBlockedByEcm = FakeBlockedByEcm()
private val fakeRestrictionsProvider = FakeRestrictionsProvider()
private val switchPreferenceModel = object : SwitchPreferenceModel {
override val title = TITLE
private val checkedState = mutableStateOf(true)
override val checked = { checkedState.value }
override val onCheckedChange: (Boolean) -> Unit = { checkedState.value = it }
}
@Test
fun whenRestrictionsKeysIsEmpty_enabled() {
val restrictions = Restrictions(userId = USER_ID, keys = emptyList())
setContent(restrictions)
composeTestRule.onNodeWithText(TITLE).assertIsDisplayed().assertIsEnabled()
composeTestRule.onNode(isOn()).assertIsDisplayed()
}
@Test
fun whenRestrictionsKeysIsEmpty_toggleable() {
val restrictions = Restrictions(userId = USER_ID, keys = emptyList())
setContent(restrictions)
composeTestRule.onRoot().performClick()
composeTestRule.onNode(isOff()).assertIsDisplayed()
}
@Test
fun whenNoRestricted_enabled() {
val restrictions = Restrictions(userId = USER_ID, keys = listOf(RESTRICTION_KEY))
fakeRestrictionsProvider.restrictedMode = NoRestricted
setContent(restrictions)
composeTestRule.onNodeWithText(TITLE).assertIsDisplayed().assertIsEnabled()
composeTestRule.onNode(isOn()).assertIsDisplayed()
}
@Test
fun whenNoRestricted_toggleable() {
val restrictions = Restrictions(userId = USER_ID, keys = listOf(RESTRICTION_KEY))
fakeRestrictionsProvider.restrictedMode = NoRestricted
setContent(restrictions)
composeTestRule.onRoot().performClick()
composeTestRule.onNode(isOff()).assertIsDisplayed()
}
@Test
fun whenBaseUserRestricted_disabled() {
val restrictions = Restrictions(userId = USER_ID, keys = listOf(RESTRICTION_KEY))
fakeRestrictionsProvider.restrictedMode = BaseUserRestricted
setContent(restrictions)
composeTestRule.onNodeWithText(TITLE).assertIsDisplayed().assertIsNotEnabled()
composeTestRule.onNode(isOff()).assertIsDisplayed()
}
@Test
fun whenBaseUserRestricted_notToggleable() {
val restrictions = Restrictions(userId = USER_ID, keys = listOf(RESTRICTION_KEY))
fakeRestrictionsProvider.restrictedMode = BaseUserRestricted
setContent(restrictions)
composeTestRule.onRoot().performClick()
composeTestRule.onNode(isOff()).assertIsDisplayed()
}
@Test
fun whenBlockedByAdmin_disabled() {
val restrictions = Restrictions(userId = USER_ID, keys = listOf(RESTRICTION_KEY))
fakeRestrictionsProvider.restrictedMode = fakeBlockedByAdmin
setContent(restrictions)
composeTestRule.onNodeWithText(TITLE).assertIsDisplayed().assertIsEnabled()
composeTestRule.onNodeWithText(FakeBlockedByAdmin.SUMMARY).assertIsDisplayed()
composeTestRule.onNode(isOn()).assertIsDisplayed()
}
@Test
fun whenBlockedByAdmin_click() {
val restrictions = Restrictions(userId = USER_ID, keys = listOf(RESTRICTION_KEY))
fakeRestrictionsProvider.restrictedMode = fakeBlockedByAdmin
setContent(restrictions)
composeTestRule.onRoot().performClick()
assertThat(fakeBlockedByAdmin.sendShowAdminSupportDetailsIntentIsCalled).isTrue()
}
@Test
fun whenBlockedByEcm_disabled() {
val restrictions = Restrictions(userId = USER_ID, keys = listOf(RESTRICTION_KEY))
fakeRestrictionsProvider.restrictedMode = fakeBlockedByEcm
setContent(restrictions)
composeTestRule.onNodeWithText(TITLE).assertIsDisplayed().assertIsEnabled()
composeTestRule.onNodeWithText(FakeBlockedByEcm.SUMMARY).assertIsDisplayed()
composeTestRule.onNode(isOn()).assertIsDisplayed()
}
@Test
fun whenBlockedByEcm_click() {
val restrictions = Restrictions(userId = USER_ID, keys = listOf(RESTRICTION_KEY))
fakeRestrictionsProvider.restrictedMode = fakeBlockedByEcm
setContent(restrictions)
composeTestRule.onRoot().performClick()
assertThat(fakeBlockedByEcm.showRestrictedSettingsDetailsIsCalled).isTrue()
}
private fun setContent(restrictions: Restrictions) {
composeTestRule.setContent {
RestrictedSwitchPreference(switchPreferenceModel, restrictions) { _, _ ->
fakeRestrictionsProvider
}
}
}
private companion object {
const val TITLE = "Title"
const val USER_ID = 0
const val RESTRICTION_KEY = "restriction_key"
}
}

View File

@@ -0,0 +1,175 @@
/*
* 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.spaprivileged.template.scaffold
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsEnabled
import androidx.compose.ui.test.assertIsNotEnabled
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.onRoot
import androidx.compose.ui.test.performClick
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settingslib.spa.widget.scaffold.MoreOptionsScope
import com.android.settingslib.spaprivileged.model.enterprise.BaseUserRestricted
import com.android.settingslib.spaprivileged.model.enterprise.NoRestricted
import com.android.settingslib.spaprivileged.model.enterprise.Restrictions
import com.android.settingslib.spaprivileged.tests.testutils.FakeBlockedByAdmin
import com.android.settingslib.spaprivileged.tests.testutils.FakeBlockedByEcm
import com.android.settingslib.spaprivileged.tests.testutils.FakeRestrictionsProvider
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class RestrictedMenuItemTest {
@get:Rule
val composeTestRule = createComposeRule()
private val fakeBlockedByAdmin = FakeBlockedByAdmin()
private val fakeBlockedByEcm = FakeBlockedByEcm()
private val fakeRestrictionsProvider = FakeRestrictionsProvider()
private var menuItemOnClickIsCalled = false
@Test
fun whenRestrictionsKeysIsEmpty_enabled() {
val restrictions = Restrictions(userId = USER_ID, keys = emptyList())
setContent(restrictions)
composeTestRule.onNodeWithText(TEXT).assertIsDisplayed().assertIsEnabled()
}
@Test
fun whenRestrictionsKeysIsEmpty_clickable() {
val restrictions = Restrictions(userId = USER_ID, keys = emptyList())
setContent(restrictions)
composeTestRule.onRoot().performClick()
assertThat(menuItemOnClickIsCalled).isTrue()
}
@Test
fun whenNoRestricted_enabled() {
val restrictions = Restrictions(userId = USER_ID, keys = listOf(RESTRICTION_KEY))
fakeRestrictionsProvider.restrictedMode = NoRestricted
setContent(restrictions)
composeTestRule.onNodeWithText(TEXT).assertIsDisplayed().assertIsEnabled()
}
@Test
fun whenNoRestricted_clickable() {
val restrictions = Restrictions(userId = USER_ID, keys = listOf(RESTRICTION_KEY))
fakeRestrictionsProvider.restrictedMode = NoRestricted
setContent(restrictions)
composeTestRule.onRoot().performClick()
assertThat(menuItemOnClickIsCalled).isTrue()
}
@Test
fun whenBaseUserRestricted_disabled() {
val restrictions = Restrictions(userId = USER_ID, keys = listOf(RESTRICTION_KEY))
fakeRestrictionsProvider.restrictedMode = BaseUserRestricted
setContent(restrictions)
composeTestRule.onNodeWithText(TEXT).assertIsDisplayed().assertIsNotEnabled()
}
@Test
fun whenBaseUserRestricted_notClickable() {
val restrictions = Restrictions(userId = USER_ID, keys = listOf(RESTRICTION_KEY))
fakeRestrictionsProvider.restrictedMode = BaseUserRestricted
setContent(restrictions)
composeTestRule.onRoot().performClick()
assertThat(menuItemOnClickIsCalled).isFalse()
}
@Test
fun whenBlockedByAdmin_disabled() {
val restrictions = Restrictions(userId = USER_ID, keys = listOf(RESTRICTION_KEY))
fakeRestrictionsProvider.restrictedMode = fakeBlockedByAdmin
setContent(restrictions)
composeTestRule.onNodeWithText(TEXT).assertIsDisplayed().assertIsEnabled()
}
@Test
fun whenBlockedByAdmin_onClick_showAdminSupportDetails() {
val restrictions = Restrictions(userId = USER_ID, keys = listOf(RESTRICTION_KEY))
fakeRestrictionsProvider.restrictedMode = fakeBlockedByAdmin
setContent(restrictions)
composeTestRule.onRoot().performClick()
assertThat(fakeBlockedByAdmin.sendShowAdminSupportDetailsIntentIsCalled).isTrue()
assertThat(menuItemOnClickIsCalled).isFalse()
}
@Test
fun whenBlockedByEcm_disabled() {
val restrictions = Restrictions(userId = USER_ID, keys = listOf(RESTRICTION_KEY))
fakeRestrictionsProvider.restrictedMode = fakeBlockedByEcm
setContent(restrictions)
composeTestRule.onNodeWithText(TEXT).assertIsDisplayed().assertIsEnabled()
}
@Test
fun whenBlockedByEcm_onClick_showEcmDetails() {
val restrictions = Restrictions(userId = USER_ID, keys = listOf(RESTRICTION_KEY))
fakeRestrictionsProvider.restrictedMode = fakeBlockedByEcm
setContent(restrictions)
composeTestRule.onRoot().performClick()
assertThat(fakeBlockedByEcm.showRestrictedSettingsDetailsIsCalled).isTrue()
assertThat(menuItemOnClickIsCalled).isFalse()
}
private fun setContent(restrictions: Restrictions) {
val fakeMoreOptionsScope = object : MoreOptionsScope() {
override fun dismiss() {}
}
composeTestRule.setContent {
fakeMoreOptionsScope.RestrictedMenuItemImpl(
text = TEXT,
restrictions = restrictions,
onClick = { menuItemOnClickIsCalled = true },
restrictionsProviderFactory = { _, _ -> fakeRestrictionsProvider },
)
}
}
private companion object {
const val TEXT = "Text"
const val USER_ID = 0
const val RESTRICTION_KEY = "restriction_key"
}
}