• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.healthconnect.cts.ui
18 
19 import android.health.connect.datatypes.Record
20 import android.healthconnect.cts.lib.ActivityLauncher.launchMainActivity
21 import android.healthconnect.cts.lib.ActivityLauncher.launchRequestPermissionActivity
22 import android.healthconnect.cts.lib.UiTestUtils.findDesc
23 import android.healthconnect.cts.lib.UiTestUtils.findDescAndClick
24 import android.healthconnect.cts.lib.UiTestUtils.findObject
25 import android.healthconnect.cts.lib.UiTestUtils.findText
26 import android.healthconnect.cts.lib.UiTestUtils.findTextAndClick
27 import android.healthconnect.cts.lib.UiTestUtils.grantPermissionViaPackageManager
28 import android.healthconnect.cts.lib.UiTestUtils.navigateToNewPage
29 import android.healthconnect.cts.lib.UiTestUtils.revokePermissionViaPackageManager
30 import android.healthconnect.cts.lib.UiTestUtils.scrollDownTo
31 import android.healthconnect.cts.lib.UiTestUtils.scrollDownToAndClick
32 import android.healthconnect.cts.lib.UiTestUtils.scrollDownToAndFindText
33 import android.healthconnect.cts.lib.UiTestUtils.scrollToEnd
34 import android.healthconnect.cts.lib.UiTestUtils.verifyTextNotFound
35 import android.healthconnect.cts.lib.UiTestUtils.waitForObjectNotFound
36 import android.healthconnect.cts.utils.PermissionHelper.getGrantedHealthPermissions
37 import android.healthconnect.cts.utils.TestUtils
38 import android.healthconnect.cts.utils.TestUtils.readAllRecords
39 import android.platform.test.annotations.RequiresFlagsDisabled
40 import android.platform.test.annotations.RequiresFlagsEnabled
41 import android.platform.test.flag.junit.CheckFlagsRule
42 import android.platform.test.flag.junit.DeviceFlagsValueProvider
43 import androidx.test.uiautomator.By
44 import com.android.healthfitness.flags.AconfigFlagHelper
45 import com.android.settingslib.widget.theme.flags.Flags.FLAG_IS_EXPRESSIVE_DESIGN_ENABLED
46 import com.google.common.truth.Truth.assertThat
47 import java.time.Duration.ofSeconds
48 import org.junit.After
49 import org.junit.Before
50 import org.junit.Rule
51 import org.junit.Test
52 
53 abstract class BaseDataTypeTest<T : Record> : HealthConnectBaseTest() {
54     abstract val dataTypeString: String
55     abstract val dataCategoryString: String
56     abstract val permissionString: String
57     abstract val permissions: List<String>
58     abstract val sameCategoryDataTypeString: String?
59     abstract val anotherCategoryString: String
60 
createRecordnull61     abstract fun createRecord(): T
62 
63     abstract val expectedRecordHeader: String
64     abstract val expectedRecordTitle: String
65     abstract val expectedRecordSubtitle: String?
66 
67     abstract fun createRecordToBeDeleted(): Record
68 
69     abstract val expectedRecordToBeDeletedHeader: String
70     abstract val expectedRecordToBeDeletedTitle: String
71 
72     abstract fun createSameCategoryRecord(): Record?
73 
74     abstract fun createAnotherCategoryRecord(): Record
75 
76     @get:Rule val mCheckFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
77 
78     companion object {
79         const val APP_WITH_READ_WRITE_PERMISSIONS =
80             "android.healthconnect.cts.testapp.readWritePerms.A"
81         const val APP_WITH_READ_WRITE_PERMISSIONS_LABEL =
82             "CtsHealthConnectTestAppAWithNormalReadWritePermission"
83     }
84 
85     private lateinit var record: Record
86 
87     @Before
setupnull88     fun setup() {
89         assertThat(getGrantedHealthPermissions(context.packageName))
90             .containsAtLeastElementsIn(permissions)
91         assertThat(getGrantedHealthPermissions(APP_WITH_READ_WRITE_PERMISSIONS))
92             .containsAtLeastElementsIn(permissions)
93 
94         TestUtils.deleteAllStagedRemoteData()
95 
96         val record = createRecord()
97 
98         val recordToBeDeleted = createRecordToBeDeleted()
99 
100         val insertedRecords = TestUtils.insertRecords(record, recordToBeDeleted)
101         this.record = insertedRecords[0]
102     }
103 
104     @After
tearDownnull105     fun tearDown() {
106         TestUtils.deleteAllStagedRemoteData()
107         permissions.forEach {
108             grantPermissionViaPackageManager(context, APP_WITH_READ_WRITE_PERMISSIONS, it)
109             assertPermissionGranted(it, APP_WITH_READ_WRITE_PERMISSIONS)
110         }
111     }
112 
113     @Test
dataAndAccess_showsEntries_deletesEntrynull114     fun dataAndAccess_showsEntries_deletesEntry() {
115         context.launchMainActivity {
116             navigateToNewPage("Data and access")
117 
118             scrollDownToAndFindText(dataCategoryString)
119             navigateToNewPage(dataTypeString)
120 
121             findText("No data")
122             findDescAndClick("Previous day")
123             waitForObjectNotFound(By.text("No data"), timeout = ofSeconds(1))
124             scrollToEnd()
125 
126             findText(expectedRecordHeader)
127             findText(expectedRecordTitle)
128             expectedRecordSubtitle?.let { findText(it) }
129 
130             findText(expectedRecordToBeDeletedHeader)
131             // Check that clicking on the entry does not open the details screen.
132             findTextAndClick(expectedRecordToBeDeletedTitle)
133             findText(expectedRecordTitle)
134             findDesc("Previous day")
135 
136             findDescAndClick("Enter deletion")
137             findTextAndClick(expectedRecordToBeDeletedTitle)
138             findDescAndClick("Delete data")
139             findTextAndClick("Delete")
140             findObject(By.text("Done"), timeout = ofSeconds(3))
141             findTextAndClick("Done")
142             verifyTextNotFound(expectedRecordToBeDeletedTitle)
143             findText(expectedRecordTitle)
144 
145             assertThat(readAllRecords(record::class.java)).containsExactly(record)
146         }
147     }
148 
149     @Test
dataAndAccess_deleteData_deletesDataType_doesNotDeleteOtherDataTypesnull150     fun dataAndAccess_deleteData_deletesDataType_doesNotDeleteOtherDataTypes() {
151         val sameCategoryRecord = createSameCategoryRecord()
152         val anotherCategoryRecord = createAnotherCategoryRecord()
153         TestUtils.insertRecords(listOfNotNull(sameCategoryRecord, anotherCategoryRecord))
154 
155         context.launchMainActivity {
156             navigateToNewPage("Data and access")
157 
158             findDescAndClick("Enter deletion")
159             scrollDownToAndClick(By.text(dataTypeString))
160             findDescAndClick("Delete data")
161             findTextAndClick("Delete")
162             findObject(By.text("Done"), timeout = ofSeconds(3))
163             findTextAndClick("Done")
164 
165             assertThat(readAllRecords(record::class.java)).isEmpty()
166             assertThat(readAllRecords(anotherCategoryRecord::class.java)).hasSize(1)
167 
168             verifyTextNotFound(dataTypeString)
169             findText(anotherCategoryString)
170 
171             sameCategoryRecord?.let {
172                 assertThat(readAllRecords(it::class.java)).hasSize(1)
173                 findText(dataCategoryString)
174                 findText(sameCategoryDataTypeString!!)
175             }
176 
177             if (sameCategoryRecord == null) {
178                 verifyTextNotFound(dataCategoryString)
179             }
180         }
181     }
182 
183     @Test
184     @RequiresFlagsDisabled(FLAG_IS_EXPRESSIVE_DESIGN_ENABLED)
legacySeeAllRecentAccess_showsDataCategorynull185     fun legacySeeAllRecentAccess_showsDataCategory() {
186         context.launchMainActivity {
187             navigateToNewPage("See all recent access")
188             scrollDownToAndFindText("Write: ${dataCategoryString}")
189         }
190     }
191 
192     @Test
193     @RequiresFlagsEnabled(FLAG_IS_EXPRESSIVE_DESIGN_ENABLED)
expressiveSeeAllRecentAccess_showsDataCategorynull194     fun expressiveSeeAllRecentAccess_showsDataCategory() {
195         context.launchMainActivity {
196             navigateToNewPage("View all")
197             scrollDownToAndFindText("Write: ${dataCategoryString}")
198         }
199     }
200 
201     @Test
appPermissions_allowAll_grantsPermissionsnull202     fun appPermissions_allowAll_grantsPermissions() {
203         permissions.forEach {
204             revokePermissionViaPackageManager(context, APP_WITH_READ_WRITE_PERMISSIONS, it)
205             assertPermissionDenied(it, APP_WITH_READ_WRITE_PERMISSIONS)
206         }
207 
208         context.launchMainActivity {
209             navigateToNewPage("App permissions")
210             navigateToNewPage(APP_WITH_READ_WRITE_PERMISSIONS_LABEL)
211             if (AconfigFlagHelper.isPersonalHealthRecordEnabled()) {
212                 navigateToNewPage("Fitness and wellness")
213             }
214             findTextAndClick("Allow all")
215         }
216 
217         permissions.forEach { assertPermissionGranted(it, APP_WITH_READ_WRITE_PERMISSIONS) }
218     }
219 
220     @Test
requestPermission_showsPermissionnull221     fun requestPermission_showsPermission() {
222         permissions.forEach {
223             revokePermissionViaPackageManager(context, APP_WITH_READ_WRITE_PERMISSIONS, it)
224             assertPermissionDenied(it, APP_WITH_READ_WRITE_PERMISSIONS)
225         }
226 
227         context.launchRequestPermissionActivity(
228             packageName = APP_WITH_READ_WRITE_PERMISSIONS,
229             permissions = permissions,
230         ) {
231             scrollDownTo(By.text(permissionString))
232             findTextAndClick("Allow all")
233             findTextAndClick("Allow")
234         }
235 
236         permissions.forEach { assertPermissionGranted(it, APP_WITH_READ_WRITE_PERMISSIONS) }
237     }
238 }
239