summaryrefslogtreecommitdiff
path: root/tests/functional/safetycenter/subpages/src/android/safetycenter/functional/ui/SafetyCenterSubpagesTest.kt
diff options
context:
space:
mode:
Diffstat (limited to 'tests/functional/safetycenter/subpages/src/android/safetycenter/functional/ui/SafetyCenterSubpagesTest.kt')
-rw-r--r--tests/functional/safetycenter/subpages/src/android/safetycenter/functional/ui/SafetyCenterSubpagesTest.kt1002
1 files changed, 1002 insertions, 0 deletions
diff --git a/tests/functional/safetycenter/subpages/src/android/safetycenter/functional/ui/SafetyCenterSubpagesTest.kt b/tests/functional/safetycenter/subpages/src/android/safetycenter/functional/ui/SafetyCenterSubpagesTest.kt
new file mode 100644
index 000000000..236beb34e
--- /dev/null
+++ b/tests/functional/safetycenter/subpages/src/android/safetycenter/functional/ui/SafetyCenterSubpagesTest.kt
@@ -0,0 +1,1002 @@
+/*
+ * 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 android.safetycenter.functional.ui
+
+import android.content.Context
+import android.os.Bundle
+import android.safetycenter.SafetyCenterManager.EXTRA_SAFETY_SOURCES_GROUP_ID
+import android.safetycenter.SafetySourceData
+import android.safetycenter.SafetySourceIssue
+import android.safetycenter.config.SafetySource
+import android.safetycenter.config.SafetySourcesGroup
+import androidx.test.core.app.ApplicationProvider.getApplicationContext
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.uiautomator.By
+import com.android.compatibility.common.util.DisableAnimationRule
+import com.android.compatibility.common.util.FreezeRotationRule
+import com.android.compatibility.common.util.UiAutomatorUtils2
+import com.android.safetycenter.resources.SafetyCenterResourcesApk
+import com.android.safetycenter.testing.Coroutines.TIMEOUT_LONG
+import com.android.safetycenter.testing.Coroutines.TIMEOUT_SHORT
+import com.android.safetycenter.testing.SafetyCenterActivityLauncher.launchSafetyCenterActivity
+import com.android.safetycenter.testing.SafetyCenterActivityLauncher.openPageAndExit
+import com.android.safetycenter.testing.SafetyCenterFlags
+import com.android.safetycenter.testing.SafetyCenterTestConfigs
+import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.MULTIPLE_SOURCES_GROUP_ID_1
+import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SINGLE_SOURCE_ID
+import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SOURCE_ID_1
+import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SOURCE_ID_2
+import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SOURCE_ID_3
+import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SOURCE_ID_4
+import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SOURCE_ID_5
+import com.android.safetycenter.testing.SafetyCenterTestData
+import com.android.safetycenter.testing.SafetyCenterTestHelper
+import com.android.safetycenter.testing.SafetyCenterTestRule
+import com.android.safetycenter.testing.SafetySourceIntentHandler.Request
+import com.android.safetycenter.testing.SafetySourceIntentHandler.Response
+import com.android.safetycenter.testing.SafetySourceReceiver
+import com.android.safetycenter.testing.SafetySourceTestData
+import com.android.safetycenter.testing.SupportsSafetyCenterRule
+import com.android.safetycenter.testing.UiTestHelper.MORE_ISSUES_LABEL
+import com.android.safetycenter.testing.UiTestHelper.clickConfirmDismissal
+import com.android.safetycenter.testing.UiTestHelper.clickDismissIssueCard
+import com.android.safetycenter.testing.UiTestHelper.clickMoreIssuesCard
+import com.android.safetycenter.testing.UiTestHelper.clickOpenSubpage
+import com.android.safetycenter.testing.UiTestHelper.clickSubpageBrandChip
+import com.android.safetycenter.testing.UiTestHelper.resetRotation
+import com.android.safetycenter.testing.UiTestHelper.rotate
+import com.android.safetycenter.testing.UiTestHelper.setAnimationsEnabled
+import com.android.safetycenter.testing.UiTestHelper.waitAllTextDisplayed
+import com.android.safetycenter.testing.UiTestHelper.waitAllTextNotDisplayed
+import com.android.safetycenter.testing.UiTestHelper.waitButtonDisplayed
+import com.android.safetycenter.testing.UiTestHelper.waitCollapsedIssuesDisplayed
+import com.android.safetycenter.testing.UiTestHelper.waitDisplayed
+import com.android.safetycenter.testing.UiTestHelper.waitExpandedIssuesDisplayed
+import com.android.safetycenter.testing.UiTestHelper.waitGroupShownOnHomepage
+import com.android.safetycenter.testing.UiTestHelper.waitPageTitleDisplayed
+import com.android.safetycenter.testing.UiTestHelper.waitPageTitleNotDisplayed
+import com.android.safetycenter.testing.UiTestHelper.waitSourceIssueDisplayed
+import com.android.safetycenter.testing.UiTestHelper.waitSourceIssueNotDisplayed
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/** Functional tests for generic subpages in Safety Center. */
+@RunWith(AndroidJUnit4::class)
+class SafetyCenterSubpagesTest {
+
+ private val context: Context = getApplicationContext()
+ private val safetyCenterTestHelper = SafetyCenterTestHelper(context)
+ private val safetySourceTestData = SafetySourceTestData(context)
+ private val safetyCenterTestConfigs = SafetyCenterTestConfigs(context)
+ private val safetyCenterResourcesApk = SafetyCenterResourcesApk.forTests(context)
+
+ @get:Rule(order = 1) val supportsSafetyCenterRule = SupportsSafetyCenterRule(context)
+ @get:Rule(order = 2) val safetyCenterTestRule = SafetyCenterTestRule(safetyCenterTestHelper)
+ @get:Rule(order = 3) val disableAnimationRule = DisableAnimationRule()
+ @get:Rule(order = 4) val freezeRotationRule = FreezeRotationRule()
+
+ @Before
+ fun enableSubpagesBeforeTest() {
+ SafetyCenterFlags.showSubpages = true
+ }
+
+ @After
+ fun resetRotationAfterTest() {
+ UiAutomatorUtils2.getUiDevice().resetRotation()
+ }
+
+ @Test
+ fun launchSafetyCenter_withSubpagesIntentExtra_showsSubpageTitle() {
+ val config = safetyCenterTestConfigs.multipleSourceGroupsConfig
+ val sourceGroup = config.safetySourcesGroups.first()!!
+ safetyCenterTestHelper.setConfig(config)
+ val extras = Bundle()
+ extras.putString(EXTRA_SAFETY_SOURCES_GROUP_ID, MULTIPLE_SOURCES_GROUP_ID_1)
+
+ context.launchSafetyCenterActivity(extras) {
+ waitPageTitleDisplayed(context.getString(sourceGroup.titleResId))
+ }
+ }
+
+ @Test
+ fun launchSafetyCenter_withSubpagesIntentExtraButFlagDisabled_showsHomepageTitle() {
+ SafetyCenterFlags.showSubpages = false
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.multipleSourceGroupsConfig)
+ val extras = Bundle()
+ extras.putString(EXTRA_SAFETY_SOURCES_GROUP_ID, MULTIPLE_SOURCES_GROUP_ID_1)
+
+ context.launchSafetyCenterActivity(extras) { waitPageTitleDisplayed("Security & privacy") }
+ }
+
+ @Test
+ fun launchSafetyCenter_withNonExistingGroupID_opensHomepageAsFallback() {
+ val config = safetyCenterTestConfigs.multipleSourceGroupsConfig
+ val sourceGroup = config.safetySourcesGroups.first()!!
+ safetyCenterTestHelper.setConfig(config)
+ val extras = Bundle()
+ extras.putString(EXTRA_SAFETY_SOURCES_GROUP_ID, "non_existing_group_id")
+
+ context.launchSafetyCenterActivity(extras) {
+ waitPageTitleNotDisplayed(context.getString(sourceGroup.titleResId))
+ waitPageTitleDisplayed("Security & privacy")
+ }
+ }
+
+ @Test
+ fun launchSafetyCenter_withMultipleGroups_showsHomepageEntries() {
+ val sourceTestData = safetySourceTestData.information
+ with(safetyCenterTestHelper) {
+ setConfig(safetyCenterTestConfigs.multipleSourceGroupsConfig)
+ setData(SOURCE_ID_1, sourceTestData)
+ setData(SOURCE_ID_2, sourceTestData)
+ setData(SOURCE_ID_3, sourceTestData)
+ setData(SOURCE_ID_4, sourceTestData)
+ setData(SOURCE_ID_5, sourceTestData)
+ }
+ val firstGroup =
+ safetyCenterTestConfigs.multipleSourceGroupsConfig.safetySourcesGroups.first()
+ val lastGroup =
+ safetyCenterTestConfigs.multipleSourceGroupsConfig.safetySourcesGroups.last()
+
+ context.launchSafetyCenterActivity {
+ waitAllTextDisplayed(
+ context.getString(firstGroup.titleResId),
+ context.getString(firstGroup.summaryResId),
+ context.getString(lastGroup.titleResId),
+ context.getString(lastGroup.summaryResId)
+ )
+
+ openPageAndExit(context.getString(lastGroup.titleResId)) {
+ waitPageTitleDisplayed(context.getString(lastGroup.titleResId))
+ waitAllTextNotDisplayed(context.getString(lastGroup.summaryResId))
+ }
+ }
+ }
+
+ @Test
+ fun launchSafetyCenter_withMultipleGroupsButFlagDisabled_showsExpandAndCollapseEntries() {
+ SafetyCenterFlags.showSubpages = false
+ val sourceTestData = safetySourceTestData.information
+ with(safetyCenterTestHelper) {
+ setConfig(safetyCenterTestConfigs.multipleSourceGroupsConfig)
+ setData(SOURCE_ID_1, sourceTestData)
+ setData(SOURCE_ID_2, sourceTestData)
+ setData(SOURCE_ID_3, sourceTestData)
+ setData(SOURCE_ID_4, sourceTestData)
+ setData(SOURCE_ID_5, sourceTestData)
+ }
+ val firstGroup =
+ safetyCenterTestConfigs.multipleSourceGroupsConfig.safetySourcesGroups.first()
+ val lastGroup =
+ safetyCenterTestConfigs.multipleSourceGroupsConfig.safetySourcesGroups.last()
+
+ context.launchSafetyCenterActivity {
+ waitAllTextDisplayed(
+ context.getString(firstGroup.titleResId),
+ context.getString(firstGroup.summaryResId),
+ context.getString(lastGroup.titleResId)
+ )
+ waitDisplayed(By.text(context.getString(lastGroup.summaryResId))) { it.click() }
+
+ // Verifying that the group is expanded and sources are displayed
+ waitAllTextDisplayed(sourceTestData.status!!.title, sourceTestData.status!!.summary)
+ waitAllTextNotDisplayed(context.getString(lastGroup.summaryResId))
+ }
+ }
+
+ @Test
+ fun launchSafetyCenter_redirectBackFromSubpage_showsHomepageEntries() {
+ with(safetyCenterTestHelper) {
+ setConfig(safetyCenterTestConfigs.multipleSourceGroupsConfig)
+ setData(SOURCE_ID_1, safetySourceTestData.information)
+ setData(SOURCE_ID_2, safetySourceTestData.information)
+ }
+ val firstGroup =
+ safetyCenterTestConfigs.multipleSourceGroupsConfig.safetySourcesGroups.first()
+
+ context.launchSafetyCenterActivity {
+ waitGroupShownOnHomepage(context, firstGroup)
+
+ openPageAndExit(context.getString(firstGroup.titleResId)) {
+ waitPageTitleDisplayed(context.getString(firstGroup.titleResId))
+ waitAllTextNotDisplayed(context.getString(firstGroup.summaryResId))
+ }
+
+ waitGroupShownOnHomepage(context, firstGroup)
+ }
+ }
+
+ @Test
+ fun entryListWithMultipleSources_clickingOnHomepageEntry_showsSubpageEntries() {
+ with(safetyCenterTestHelper) {
+ setConfig(safetyCenterTestConfigs.multipleSourcesConfig)
+ setData(
+ SOURCE_ID_1,
+ safetySourceTestData.buildSafetySourceDataWithSummary(
+ severityLevel = SafetySourceData.SEVERITY_LEVEL_INFORMATION,
+ entryTitle = SAFETY_SOURCE_1_TITLE,
+ entrySummary = SAFETY_SOURCE_1_SUMMARY
+ )
+ )
+ setData(
+ SOURCE_ID_2,
+ safetySourceTestData.buildSafetySourceDataWithSummary(
+ severityLevel = SafetySourceData.SEVERITY_LEVEL_INFORMATION,
+ entryTitle = SAFETY_SOURCE_2_TITLE,
+ entrySummary = SAFETY_SOURCE_2_SUMMARY
+ )
+ )
+ setData(
+ SOURCE_ID_3,
+ safetySourceTestData.buildSafetySourceDataWithSummary(
+ severityLevel = SafetySourceData.SEVERITY_LEVEL_INFORMATION,
+ entryTitle = SAFETY_SOURCE_3_TITLE,
+ entrySummary = SAFETY_SOURCE_3_SUMMARY
+ )
+ )
+ }
+ val firstGroup = safetyCenterTestConfigs.multipleSourcesConfig.safetySourcesGroups[0]
+ val secondGroup = safetyCenterTestConfigs.multipleSourcesConfig.safetySourcesGroups[1]
+
+ context.launchSafetyCenterActivity {
+ // Verifying that subpage entries of the first group are displayed
+ openPageAndExit(context.getString(firstGroup.titleResId)) {
+ waitAllTextNotDisplayed(context.getString(firstGroup.summaryResId))
+ waitAllTextDisplayed(
+ SAFETY_SOURCE_1_TITLE,
+ SAFETY_SOURCE_1_SUMMARY,
+ SAFETY_SOURCE_2_TITLE,
+ SAFETY_SOURCE_2_SUMMARY
+ )
+ }
+
+ // Verifying that subpage entries of the second group are displayed
+ openPageAndExit(context.getString(secondGroup.titleResId)) {
+ waitAllTextNotDisplayed(context.getString(secondGroup.summaryResId))
+ waitAllTextDisplayed(SAFETY_SOURCE_3_TITLE, SAFETY_SOURCE_3_SUMMARY)
+ }
+ }
+ }
+
+ @Test
+ fun entryListWithSingleSource_clickingOnSubpageEntry_redirectsToDifferentScreen() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+ val sourcesGroup = safetyCenterTestConfigs.singleSourceConfig.safetySourcesGroups.first()
+ val source: SafetySource = sourcesGroup.safetySources.first()
+
+ context.launchSafetyCenterActivity {
+ openPageAndExit(context.getString(sourcesGroup.titleResId)) {
+ waitDisplayed(By.text(context.getString(source.titleResId))) { it.click() }
+ waitButtonDisplayed("Exit test activity") { it.click() }
+ waitAllTextDisplayed(
+ context.getString(source.titleResId),
+ context.getString(source.summaryResId)
+ )
+ }
+ }
+ }
+
+ @Test
+ fun entryListWithSingleSource_clickingTheInfoIcon_redirectsToDifferentScreen() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+ val sourceTestData = safetySourceTestData.informationWithIconAction
+ safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, sourceTestData)
+ val sourcesGroup = safetyCenterTestConfigs.singleSourceConfig.safetySourcesGroups.first()
+
+ context.launchSafetyCenterActivity {
+ openPageAndExit(context.getString(sourcesGroup.titleResId)) {
+ waitDisplayed(By.desc("Information")) { it.click() }
+ waitButtonDisplayed("Exit test activity") { it.click() }
+ waitAllTextDisplayed(sourceTestData.status!!.title, sourceTestData.status!!.summary)
+ }
+ }
+ }
+
+ @Test
+ fun entryListWithSingleSource_clickingTheGearIcon_redirectsToDifferentScreen() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+ val sourceTestData = safetySourceTestData.informationWithGearIconAction
+ safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, sourceTestData)
+ val sourcesGroup = safetyCenterTestConfigs.singleSourceConfig.safetySourcesGroups.first()
+
+ context.launchSafetyCenterActivity {
+ openPageAndExit(context.getString(sourcesGroup.titleResId)) {
+ waitDisplayed(By.desc("Settings")) { it.click() }
+ waitButtonDisplayed("Exit test activity") { it.click() }
+ waitAllTextDisplayed(sourceTestData.status!!.title, sourceTestData.status!!.summary)
+ }
+ }
+ }
+
+ @Test
+ fun entryListWithSingleSource_clickingAnUnclickableDisabledEntry_doesNothing() {
+ val config = safetyCenterTestConfigs.singleSourceInvalidIntentConfig
+ safetyCenterTestHelper.setConfig(config)
+ val sourceTestData = safetySourceTestData.informationWithNullIntent
+ safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, sourceTestData)
+ val sourcesGroup = config.safetySourcesGroups.first()
+
+ context.launchSafetyCenterActivity {
+ openPageAndExit(context.getString(sourcesGroup.titleResId)) {
+ waitDisplayed(By.text(sourceTestData.status!!.title.toString())) { it.click() }
+
+ // Verifying that clicking on the entry doesn't redirect to any other screen
+ waitAllTextDisplayed(sourceTestData.status!!.title, sourceTestData.status!!.summary)
+ }
+ }
+ }
+
+ @Test
+ fun entryListWithSingleSource_clickingAClickableDisabledEntry_redirectsToDifferentScreen() {
+ val config = safetyCenterTestConfigs.singleSourceConfig
+ safetyCenterTestHelper.setConfig(config)
+ val sourceTestData = safetySourceTestData.unspecifiedDisabledWithTestActivityRedirect
+ safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, sourceTestData)
+ val sourcesGroup = config.safetySourcesGroups.first()
+
+ context.launchSafetyCenterActivity {
+ openPageAndExit(context.getString(sourcesGroup.titleResId)) {
+ waitDisplayed(By.text(sourceTestData.status!!.title.toString())) { it.click() }
+
+ waitButtonDisplayed("Exit test activity") { it.click() }
+ }
+ }
+ }
+
+ @Test
+ fun entryListWithSingleSource_updateSafetySourceData_displayedDataIsUpdated() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+ val sourcesGroup = safetyCenterTestConfigs.singleSourceConfig.safetySourcesGroups.first()
+ val source: SafetySource = sourcesGroup.safetySources.first()
+
+ context.launchSafetyCenterActivity(withReceiverPermission = true) {
+ openPageAndExit(context.getString(sourcesGroup.titleResId)) {
+ waitAllTextDisplayed(
+ context.getString(source.titleResId),
+ context.getString(source.summaryResId)
+ )
+ }
+
+ SafetySourceReceiver.setResponse(
+ Request.Refresh(SINGLE_SOURCE_ID),
+ Response.SetData(
+ safetySourceTestData.buildSafetySourceDataWithSummary(
+ severityLevel = SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION,
+ entryTitle = "Updated title",
+ entrySummary = "Updated summary"
+ )
+ )
+ )
+
+ openPageAndExit(context.getString(sourcesGroup.titleResId)) {
+ waitAllTextNotDisplayed(
+ context.getString(source.titleResId),
+ context.getString(source.summaryResId)
+ )
+ waitAllTextDisplayed("Updated title", "Updated summary")
+ }
+ }
+ }
+
+ @Test
+ fun entryListWithSingleSource_updateSafetySourceDataAndRotate_displayedDataIsNotUpdated() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+ val sourcesGroup = safetyCenterTestConfigs.singleSourceConfig.safetySourcesGroups.first()
+ val source: SafetySource = sourcesGroup.safetySources.first()
+
+ context.launchSafetyCenterActivity(withReceiverPermission = true) {
+ openPageAndExit(context.getString(sourcesGroup.titleResId)) {
+ waitAllTextDisplayed(
+ context.getString(source.titleResId),
+ context.getString(source.summaryResId)
+ )
+
+ SafetySourceReceiver.setResponse(
+ Request.Refresh(SINGLE_SOURCE_ID),
+ Response.SetData(
+ safetySourceTestData.buildSafetySourceDataWithSummary(
+ severityLevel = SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION,
+ entryTitle = "Updated title",
+ entrySummary = "Updated summary"
+ )
+ )
+ )
+ UiAutomatorUtils2.getUiDevice().rotate()
+
+ waitAllTextDisplayed(
+ context.getString(source.titleResId),
+ context.getString(source.summaryResId)
+ )
+ waitAllTextNotDisplayed("Updated title", "Updated summary")
+ }
+ }
+ }
+
+ @Test
+ fun issueCard_withMultipleGroups_onlyRelevantSubpageHasIssueCard() {
+ /* The default attribution title for an issue card is same as the entry group title on the
+ * homepage. This causes test flakiness as UiAutomator is unable to choose from duplicate
+ * strings. To address that, an issue with a different attribution title is used here. */
+ val sourceData = safetySourceTestData.informationWithIssueWithAttributionTitle
+ val issue = sourceData.issues[0]
+
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.multipleSourcesConfig)
+ val firstGroup = safetyCenterTestConfigs.multipleSourcesConfig.safetySourcesGroups[0]
+ val secondGroup = safetyCenterTestConfigs.multipleSourcesConfig.safetySourcesGroups[1]
+ safetyCenterTestHelper.setData(SOURCE_ID_3, sourceData)
+
+ context.launchSafetyCenterActivity {
+ // Verify that homepage has the issue card
+ waitSourceIssueDisplayed(issue)
+
+ // Verify that irrelevant subpage doesn't have the issue card
+ openPageAndExit(context.getString(firstGroup.titleResId)) {
+ waitSourceIssueNotDisplayed(issue)
+ }
+ // Verify that relevant subpage has the issue card
+ openPageAndExit(context.getString(secondGroup.titleResId)) {
+ waitSourceIssueDisplayed(issue)
+ }
+ }
+ }
+
+ @Test
+ fun issueCard_updateSafetySourceData_subpageDisplaysUpdatedIssue() {
+ val initialDataToDisplay = safetySourceTestData.informationWithIssueWithAttributionTitle
+ val updatedDataToDisplay = safetySourceTestData.criticalWithIssueWithAttributionTitle
+
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+ val sourcesGroup = safetyCenterTestConfigs.singleSourceConfig.safetySourcesGroups.first()
+ safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, initialDataToDisplay)
+
+ context.launchSafetyCenterActivity {
+ openPageAndExit(context.getString(sourcesGroup.titleResId)) {
+ waitSourceIssueDisplayed(initialDataToDisplay.issues[0])
+
+ safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, updatedDataToDisplay)
+
+ waitSourceIssueDisplayed(updatedDataToDisplay.issues[0])
+ }
+ }
+ }
+
+ @Test
+ fun issueCard_resolveIssueOnSubpage_issueDismisses() {
+ val sourceData = safetySourceTestData.criticalWithIssueWithAttributionTitle
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+ safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, sourceData)
+ val sourcesGroup = safetyCenterTestConfigs.singleSourceConfig.safetySourcesGroups.first()
+ val issue = sourceData.issues[0]
+ val action = issue.actions[0]
+
+ // Clear the data when action is triggered to simulate resolution.
+ SafetySourceReceiver.setResponse(
+ Request.ResolveAction(SINGLE_SOURCE_ID),
+ Response.ClearData
+ )
+
+ context.launchSafetyCenterActivity(withReceiverPermission = true) {
+ openPageAndExit(context.getString(sourcesGroup.titleResId)) {
+ waitSourceIssueDisplayed(issue)
+ waitButtonDisplayed(action.label) { it.click() }
+
+ // Wait for success message to go away, verify issue no longer displayed
+ waitAllTextNotDisplayed(action.successMessage)
+ waitSourceIssueNotDisplayed(issue)
+ }
+ }
+ }
+
+ @Test
+ fun issueCard_confirmDismissalOnSubpage_dismissesIssue() {
+ val sourceData = safetySourceTestData.criticalWithIssueWithAttributionTitle
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+ safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, sourceData)
+ val sourcesGroup = safetyCenterTestConfigs.singleSourceConfig.safetySourcesGroups.first()
+ val issue = sourceData.issues[0]
+
+ context.launchSafetyCenterActivity {
+ openPageAndExit(context.getString(sourcesGroup.titleResId)) {
+ waitSourceIssueDisplayed(issue)
+ clickDismissIssueCard()
+
+ waitAllTextDisplayed("Dismiss this alert?")
+ clickConfirmDismissal()
+
+ waitSourceIssueNotDisplayed(issue)
+ }
+ }
+ }
+
+ @Test
+ fun issueCard_dismissOnSubpageWithRotation_cancellationPersistsIssue() {
+ val sourceData = safetySourceTestData.criticalWithIssueWithAttributionTitle
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+ safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, sourceData)
+ val sourcesGroup = safetyCenterTestConfigs.singleSourceConfig.safetySourcesGroups.first()
+ val issue = sourceData.issues[0]
+
+ context.launchSafetyCenterActivity {
+ openPageAndExit(context.getString(sourcesGroup.titleResId)) {
+ waitSourceIssueDisplayed(issue)
+ clickDismissIssueCard()
+ waitAllTextDisplayed("Dismiss this alert?")
+
+ UiAutomatorUtils2.getUiDevice().rotate()
+
+ waitAllTextDisplayed("Dismiss this alert?")
+ waitButtonDisplayed("Cancel") { it.click() }
+ waitSourceIssueDisplayed(issue)
+ }
+ }
+ }
+
+ @Test
+ fun moreIssuesCard_expandOnSubpage_showsAdditionalCard() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.multipleSourcesConfig)
+ val sourcesGroup = safetyCenterTestConfigs.multipleSourcesConfig.safetySourcesGroups.first()
+ val firstSourceData = safetySourceTestData.criticalWithIssueWithAttributionTitle
+ val secondSourceData = safetySourceTestData.informationWithIssueWithAttributionTitle
+ safetyCenterTestHelper.setData(SOURCE_ID_1, firstSourceData)
+ safetyCenterTestHelper.setData(SOURCE_ID_2, secondSourceData)
+
+ context.launchSafetyCenterActivity {
+ openPageAndExit(context.getString(sourcesGroup.titleResId)) {
+ waitCollapsedIssuesDisplayed(firstSourceData.issues[0], secondSourceData.issues[0])
+
+ clickMoreIssuesCard()
+
+ waitExpandedIssuesDisplayed(firstSourceData.issues[0], secondSourceData.issues[0])
+ }
+ }
+ }
+
+ @Test
+ fun dismissedIssuesCard_expandWithOnlyDismissedIssues_showsAdditionalCard() {
+ val sourceData = safetySourceTestData.criticalWithIssueWithAttributionTitle
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+ safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, sourceData)
+ val sourcesGroup = safetyCenterTestConfigs.singleSourceConfig.safetySourcesGroups.first()
+ val issue = sourceData.issues[0]
+
+ context.launchSafetyCenterActivity {
+ openPageAndExit(context.getString(sourcesGroup.titleResId)) {
+ waitSourceIssueDisplayed(issue)
+ clickDismissIssueCard()
+ waitAllTextDisplayed("Dismiss this alert?")
+ clickConfirmDismissal()
+ waitSourceIssueNotDisplayed(issue)
+
+ waitDisplayed(By.text("Dismissed alerts")) { it.click() }
+
+ waitAllTextDisplayed("Dismissed alerts")
+ waitSourceIssueDisplayed(issue)
+ }
+ }
+ }
+
+ @Test
+ fun dismissedIssuesCard_collapseWithOnlyDismissedIssues_hidesAdditionalCard() {
+ val sourceData = safetySourceTestData.criticalWithIssueWithAttributionTitle
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+ safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, sourceData)
+ val sourcesGroup = safetyCenterTestConfigs.singleSourceConfig.safetySourcesGroups.first()
+ val issue = sourceData.issues[0]
+
+ context.launchSafetyCenterActivity {
+ openPageAndExit(context.getString(sourcesGroup.titleResId)) {
+ waitSourceIssueDisplayed(issue)
+ clickDismissIssueCard()
+ waitAllTextDisplayed("Dismiss this alert?")
+ clickConfirmDismissal()
+ waitSourceIssueNotDisplayed(issue)
+
+ waitDisplayed(By.text("Dismissed alerts")) { it.click() }
+ waitSourceIssueDisplayed(issue)
+
+ waitDisplayed(By.text("Dismissed alerts")) { it.click() }
+ waitSourceIssueNotDisplayed(issue)
+ }
+ }
+ }
+
+ @Test
+ fun dismissedIssuesCard_resolveIssue_successConfirmationShown() {
+ SafetyCenterFlags.hideResolvedIssueUiTransitionDelay = TIMEOUT_LONG
+ val (sourcesGroup, issue) =
+ prepareSingleSourceGroupWithIssue(
+ safetySourceTestData.criticalWithIssueWithAttributionTitle
+ )
+ prepareActionResponse(Response.ClearData)
+
+ checkOnDismissedIssue(sourcesGroup, issue) {
+ val action = issue.actions[0]
+ waitButtonDisplayed(action.label) {
+ // Re-enable animations for this test as this is needed to show the success message.
+ setAnimationsEnabled(true)
+ it.click()
+ }
+
+ // Success message should show up if issue marked as resolved
+ val successMessage = action.successMessage
+ waitAllTextDisplayed(successMessage)
+ }
+ }
+
+ @Test
+ fun dismissedIssuesCard_resolveIssue_issueDismisses() {
+ val (sourcesGroup, issue) =
+ prepareSingleSourceGroupWithIssue(
+ safetySourceTestData.criticalWithIssueWithAttributionTitle
+ )
+ prepareActionResponse(Response.ClearData)
+
+ checkOnDismissedIssue(sourcesGroup, issue) {
+ val action = issue.actions[0]
+ waitButtonDisplayed(action.label) { it.click() }
+
+ // Wait for success message to go away, verify issue no longer displayed
+ val successMessage = action.successMessage
+ waitAllTextNotDisplayed(successMessage)
+ waitSourceIssueNotDisplayed(issue)
+ }
+ }
+
+ @Test
+ fun dismissedIssuesCard_resolveIssue_withDialogClickYes_resolves() {
+ val (sourcesGroup, issue) =
+ prepareSingleSourceGroupWithIssue(
+ safetySourceTestData.criticalWithIssueWithConfirmationWithAttributionTitle
+ )
+ prepareActionResponse(Response.ClearData)
+
+ checkOnDismissedIssue(sourcesGroup, issue) {
+ val action = issue.actions[0]
+ waitButtonDisplayed(action.label) { it.click() }
+
+ waitAllTextDisplayed(SafetySourceTestData.CONFIRMATION_TITLE)
+ waitButtonDisplayed(SafetySourceTestData.CONFIRMATION_YES) { it.click() }
+
+ waitSourceIssueNotDisplayed(issue)
+ }
+ }
+
+ @Test
+ fun dismissedIssuesCard_resolveIssue_withDialog_rotates_clickYes_resolves() {
+ val (sourcesGroup, issue) =
+ prepareSingleSourceGroupWithIssue(
+ safetySourceTestData.criticalWithIssueWithConfirmationWithAttributionTitle
+ )
+ prepareActionResponse(Response.ClearData)
+
+ checkOnDismissedIssue(sourcesGroup, issue) {
+ val action = issue.actions[0]
+ waitButtonDisplayed(action.label) { it.click() }
+
+ waitAllTextDisplayed(SafetySourceTestData.CONFIRMATION_TITLE)
+
+ UiAutomatorUtils2.getUiDevice().rotate()
+
+ waitAllTextDisplayed(SafetySourceTestData.CONFIRMATION_TITLE)
+ waitButtonDisplayed(SafetySourceTestData.CONFIRMATION_YES) { it.click() }
+
+ waitSourceIssueNotDisplayed(issue)
+ }
+ }
+
+ @Test
+ fun dismissedIssuesCard_resolveIssue_withDialogClicksNo_cancels() {
+ val (sourcesGroup, issue) =
+ prepareSingleSourceGroupWithIssue(
+ safetySourceTestData.criticalWithIssueWithConfirmationWithAttributionTitle
+ )
+
+ checkOnDismissedIssue(sourcesGroup, issue) {
+ val action = issue.actions[0]
+ waitButtonDisplayed(action.label) { it.click() }
+
+ waitAllTextDisplayed(SafetySourceTestData.CONFIRMATION_TITLE)
+ waitButtonDisplayed(SafetySourceTestData.CONFIRMATION_NO) { it.click() }
+
+ waitSourceIssueDisplayed(issue)
+ }
+ }
+
+ @Test
+ fun dismissedIssuesCard_resolveIssue_noSuccessMessage_noResolutionUiShown_issueDismisses() {
+ SafetyCenterFlags.hideResolvedIssueUiTransitionDelay = TIMEOUT_LONG
+ val (sourcesGroup, issue) =
+ prepareSingleSourceGroupWithIssue(
+ safetySourceTestData.criticalWithIssueWithAttributionTitle
+ )
+ prepareActionResponse(Response.ClearData)
+
+ checkOnDismissedIssue(sourcesGroup, issue) {
+ val action = issue.actions[0]
+ waitButtonDisplayed(action.label) {
+ // Re-enable animations for this test as this is needed to show the success message.
+ setAnimationsEnabled(true)
+ it.click()
+ }
+
+ waitSourceIssueNotDisplayed(issue)
+ }
+ }
+
+ @Test
+ fun dismissedIssuesCard_resolvingInflightIssueFailed_issueRemains() {
+ val (sourcesGroup, issue) =
+ prepareSingleSourceGroupWithIssue(
+ safetySourceTestData.criticalWithIssueWithAttributionTitle
+ )
+ prepareActionResponse(Response.Error)
+
+ checkOnDismissedIssue(sourcesGroup, issue) {
+ val action = issue.actions[0]
+ waitButtonDisplayed(action.label) { it.click() }
+
+ waitSourceIssueDisplayed(issue)
+ }
+ }
+
+ @Test
+ fun dismissedIssuesCard_resolvingInFlightIssueTimesOut_issueRemains() {
+ SafetyCenterFlags.resolveActionTimeout = TIMEOUT_SHORT
+ val (sourcesGroup, issue) =
+ prepareSingleSourceGroupWithIssue(
+ safetySourceTestData.criticalWithIssueWithAttributionTitle
+ )
+
+ checkOnDismissedIssue(sourcesGroup, issue) {
+ val action = issue.actions[0]
+ waitButtonDisplayed(action.label) { it.click() }
+
+ waitSourceIssueDisplayed(issue)
+ }
+ }
+
+ @Test
+ fun dismissedIssuesCard_clickingNonResolvingActionButton_redirectsToDifferentScreen() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+ val (sourcesGroup, issue) =
+ prepareSingleSourceGroupWithIssue(
+ safetySourceTestData.criticalWithTestActivityRedirectWithAttributionTitle
+ )
+
+ checkOnDismissedIssue(sourcesGroup, issue) {
+ val action = issue.actions[0]
+ waitButtonDisplayed(action.label) { it.click() }
+ waitButtonDisplayed("Exit test activity") { it.click() }
+ }
+ }
+
+ @Test
+ fun dismissedIssuesCard_doesntShowGreenCards() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+ val (sourcesGroup, issue) =
+ prepareSingleSourceGroupWithIssue(
+ safetySourceTestData.informationWithIssueWithAttributionTitle
+ )
+ val safetyCenterIssueId = SafetyCenterTestData.issueId(SINGLE_SOURCE_ID, issue.id)
+ safetyCenterTestHelper.dismissSafetyCenterIssue(safetyCenterIssueId)
+
+ context.launchSafetyCenterActivity {
+ openPageAndExit(context.getString(sourcesGroup.titleResId)) {
+ waitAllTextNotDisplayed("Dismissed alerts")
+ waitSourceIssueNotDisplayed(issue)
+ }
+ }
+ }
+
+ @Test
+ fun moreIssuesCard_expandWithDismissedIssues_showsAdditionalCards() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.multipleSourcesInSingleGroupConfig)
+
+ val firstSourceData = safetySourceTestData.criticalWithIssueWithAttributionTitle
+ val secondSourceData = safetySourceTestData.informationWithIssueWithAttributionTitle
+ val thirdSourceData = safetySourceTestData.informationWithIssueWithAttributionTitle
+
+ safetyCenterTestHelper.setData(SOURCE_ID_1, firstSourceData)
+ safetyCenterTestHelper.setData(SOURCE_ID_2, secondSourceData)
+ safetyCenterTestHelper.setData(SOURCE_ID_3, thirdSourceData)
+
+ val sourcesGroup =
+ safetyCenterTestConfigs.multipleSourcesInSingleGroupConfig.safetySourcesGroups.first()
+ val issue = firstSourceData.issues[0]
+
+ context.launchSafetyCenterActivity {
+ openPageAndExit(context.getString(sourcesGroup.titleResId)) {
+ waitSourceIssueDisplayed(issue)
+ clickDismissIssueCard()
+ waitAllTextDisplayed("Dismiss this alert?")
+ clickConfirmDismissal()
+ waitSourceIssueNotDisplayed(issue)
+
+ clickMoreIssuesCard()
+
+ waitAllTextDisplayed(MORE_ISSUES_LABEL)
+ waitAllTextDisplayed("Dismissed alerts")
+ waitSourceIssueDisplayed(issue)
+ }
+ }
+ }
+
+ @Test
+ fun moreIssuesCard_collapseWithDismissedIssues_hidesAdditionalCards() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.multipleSourcesInSingleGroupConfig)
+
+ val firstSourceData = safetySourceTestData.criticalWithIssueWithAttributionTitle
+ val secondSourceData = safetySourceTestData.informationWithIssueWithAttributionTitle
+ val thirdSourceData = safetySourceTestData.informationWithIssueWithAttributionTitle
+
+ safetyCenterTestHelper.setData(SOURCE_ID_1, firstSourceData)
+ safetyCenterTestHelper.setData(SOURCE_ID_2, secondSourceData)
+ safetyCenterTestHelper.setData(SOURCE_ID_3, thirdSourceData)
+
+ val sourcesGroup =
+ safetyCenterTestConfigs.multipleSourcesInSingleGroupConfig.safetySourcesGroups.first()
+ val issue = firstSourceData.issues[0]
+
+ context.launchSafetyCenterActivity {
+ openPageAndExit(context.getString(sourcesGroup.titleResId)) {
+ waitSourceIssueDisplayed(issue)
+ clickDismissIssueCard()
+ clickConfirmDismissal()
+ waitSourceIssueNotDisplayed(issue)
+
+ clickMoreIssuesCard()
+ waitSourceIssueDisplayed(issue)
+
+ clickMoreIssuesCard()
+ waitAllTextDisplayed(MORE_ISSUES_LABEL)
+ waitAllTextNotDisplayed("Dismissed alerts")
+ waitSourceIssueNotDisplayed(issue)
+ }
+ }
+ }
+
+ @Test
+ fun brandChip_openSubpageFromHomepage_homepageReopensOnClick() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+ safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, safetySourceTestData.information)
+ val sourcesGroup = safetyCenterTestConfigs.singleSourceConfig.safetySourcesGroups.first()
+
+ context.launchSafetyCenterActivity {
+ waitGroupShownOnHomepage(context, sourcesGroup)
+
+ clickOpenSubpage(context, sourcesGroup)
+ waitPageTitleDisplayed(context.getString(sourcesGroup.titleResId))
+ waitAllTextNotDisplayed(context.getString(sourcesGroup.summaryResId))
+
+ clickSubpageBrandChip()
+ waitGroupShownOnHomepage(context, sourcesGroup)
+ }
+ }
+
+ @Test
+ fun brandChip_openSubpageFromIntent_homepageOpensOnClick() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+ safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, safetySourceTestData.information)
+ val sourcesGroup = safetyCenterTestConfigs.singleSourceConfig.safetySourcesGroups.first()
+ val extras = Bundle()
+ extras.putString(EXTRA_SAFETY_SOURCES_GROUP_ID, sourcesGroup.id)
+
+ context.launchSafetyCenterActivity(extras) {
+ waitPageTitleDisplayed(context.getString(sourcesGroup.titleResId))
+ waitAllTextNotDisplayed(context.getString(sourcesGroup.summaryResId))
+
+ clickSubpageBrandChip()
+ waitGroupShownOnHomepage(context, sourcesGroup)
+ }
+ }
+
+ @Test
+ fun settingsSearch_openWithGenericIntentExtra_showsGenericSubpage() {
+ val config = safetyCenterTestConfigs.multipleSourcesConfig
+ safetyCenterTestHelper.setConfig(config)
+ val sourcesGroup = config.safetySourcesGroups.first()
+ val source = sourcesGroup.safetySources.first()
+ val preferenceKey = "${source.id}_personal"
+ val extras = Bundle()
+ extras.putString(EXTRA_SETTINGS_FRAGMENT_ARGS_KEY, preferenceKey)
+
+ context.launchSafetyCenterActivity(extras) {
+ waitPageTitleDisplayed(context.getString(sourcesGroup.titleResId))
+ waitAllTextDisplayed(
+ context.getString(source.titleResId),
+ context.getString(source.summaryResId)
+ )
+ }
+ }
+
+ @Test
+ fun settingsSearch_openWithInvalidKey_showsHomepage() {
+ val config = safetyCenterTestConfigs.singleSourceConfig
+ val sourcesGroup = config.safetySourcesGroups.first()
+ safetyCenterTestHelper.setConfig(config)
+ val extras = Bundle()
+ extras.putString(EXTRA_SETTINGS_FRAGMENT_ARGS_KEY, "invalid_preference_key")
+
+ context.launchSafetyCenterActivity(extras) {
+ waitPageTitleDisplayed("Security & privacy")
+ waitGroupShownOnHomepage(context, sourcesGroup)
+ }
+ }
+
+ @Test
+ fun footerSummary_openGenericSubpageHavingFooter_showsExpectedText() {
+ val config = safetyCenterTestConfigs.singleSourceConfig
+ val sourcesGroup = config.safetySourcesGroups.first()
+ val source: SafetySource = sourcesGroup.safetySources.first()
+ safetyCenterTestHelper.setConfig(config)
+
+ context.launchSafetyCenterActivity {
+ openPageAndExit(context.getString(sourcesGroup.titleResId)) {
+ waitAllTextDisplayed(
+ context.getString(source.titleResId),
+ context.getString(source.summaryResId),
+ safetyCenterResourcesApk.getStringByName("test_single_source_group_id_footer")
+ )
+ }
+ }
+ }
+
+ private fun prepareSingleSourceGroupWithIssue(
+ sourceData: SafetySourceData
+ ): Pair<SafetySourcesGroup, SafetySourceIssue> {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+ safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, sourceData)
+ val sourcesGroup = safetyCenterTestConfigs.singleSourceConfig.safetySourcesGroups.first()
+ val issue = sourceData.issues[0]
+ return sourcesGroup to issue
+ }
+
+ private fun prepareActionResponse(actionResponse: Response) {
+ SafetySourceReceiver.setResponse(Request.ResolveAction(SINGLE_SOURCE_ID), actionResponse)
+ }
+
+ private fun checkOnDismissedIssue(
+ sourcesGroup: SafetySourcesGroup,
+ issue: SafetySourceIssue,
+ block: () -> Unit
+ ) {
+ val safetyCenterIssueId = SafetyCenterTestData.issueId(SINGLE_SOURCE_ID, issue.id)
+ safetyCenterTestHelper.dismissSafetyCenterIssue(safetyCenterIssueId)
+
+ context.launchSafetyCenterActivity(withReceiverPermission = true) {
+ openPageAndExit(context.getString(sourcesGroup.titleResId)) {
+ waitDisplayed(By.text("Dismissed alerts")) { it.click() }
+ waitSourceIssueDisplayed(issue)
+
+ block()
+ }
+ }
+ }
+
+ companion object {
+ private const val SAFETY_SOURCE_1_TITLE = "Safety Source 1 Title"
+ private const val SAFETY_SOURCE_1_SUMMARY = "Safety Source 1 Summary"
+ private const val SAFETY_SOURCE_2_TITLE = "Safety Source 2 Title"
+ private const val SAFETY_SOURCE_2_SUMMARY = "Safety Source 2 Summary"
+ private const val SAFETY_SOURCE_3_TITLE = "Safety Source 3 Title"
+ private const val SAFETY_SOURCE_3_SUMMARY = "Safety Source 3 Summary"
+ private const val EXTRA_SETTINGS_FRAGMENT_ARGS_KEY = ":settings:fragment_args_key"
+ }
+}