• 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 package com.google.jetpackcamera
17 
18 import androidx.compose.ui.test.isDisplayed
19 import androidx.compose.ui.test.isNotDisplayed
20 import androidx.compose.ui.test.junit4.createEmptyComposeRule
21 import androidx.compose.ui.test.onNodeWithTag
22 import androidx.compose.ui.test.performClick
23 import androidx.test.ext.junit.runners.AndroidJUnit4
24 import androidx.test.filters.SdkSuppress
25 import androidx.test.platform.app.InstrumentationRegistry
26 import androidx.test.uiautomator.UiDevice
27 import com.google.jetpackcamera.feature.preview.ui.CAPTURE_BUTTON
28 import com.google.jetpackcamera.permissions.ui.CAMERA_PERMISSION_BUTTON
29 import com.google.jetpackcamera.permissions.ui.RECORD_AUDIO_PERMISSION_BUTTON
30 import com.google.jetpackcamera.permissions.ui.REQUEST_PERMISSION_BUTTON
31 import com.google.jetpackcamera.utils.APP_REQUIRED_PERMISSIONS
32 import com.google.jetpackcamera.utils.APP_START_TIMEOUT_MILLIS
33 import com.google.jetpackcamera.utils.IndividualTestGrantPermissionRule
34 import com.google.jetpackcamera.utils.askEveryTimeDialog
35 import com.google.jetpackcamera.utils.denyPermissionDialog
36 import com.google.jetpackcamera.utils.grantPermissionDialog
37 import com.google.jetpackcamera.utils.onNodeWithText
38 import com.google.jetpackcamera.utils.runScenarioTest
39 import org.junit.Rule
40 import org.junit.Test
41 import org.junit.runner.RunWith
42 
43 const val CAMERA_PERMISSION = "android.permission.CAMERA"
44 
45 @RunWith(AndroidJUnit4::class)
46 class PermissionsTest {
47     @get:Rule
48     val composeTestRule = createEmptyComposeRule()
49 
50     @get:Rule
51     val allPermissionsRule = IndividualTestGrantPermissionRule(
52         permissions = APP_REQUIRED_PERMISSIONS.toTypedArray(),
53         targetTestNames = arrayOf(
54             "allPermissions_alreadyGranted_screenNotShown"
55         )
56     )
57 
58     @get:Rule
59     val cameraPermissionRule = IndividualTestGrantPermissionRule(
60         permissions = arrayOf(CAMERA_PERMISSION),
61         targetTestNames = arrayOf(
62             "recordAudioPermission_granted_closesPage",
63             "recordAudioPermission_denied_closesPage"
64         )
65     )
66 
67     private val instrumentation = InstrumentationRegistry.getInstrumentation()
68     private val uiDevice = UiDevice.getInstance(instrumentation)
69 
70     @Test
allPermissions_alreadyGranted_screenNotShownnull71     fun allPermissions_alreadyGranted_screenNotShown() {
72         runScenarioTest<MainActivity> {
73             composeTestRule.waitUntil(timeoutMillis = APP_START_TIMEOUT_MILLIS) {
74                 composeTestRule.onNodeWithTag(CAPTURE_BUTTON).isDisplayed()
75             }
76         }
77     }
78 
79     @Test
<lambda>null80     fun cameraPermission_granted_closesPage() = runScenarioTest<MainActivity> {
81         // Wait for the camera permission screen to be displayed
82         composeTestRule.waitUntil(timeoutMillis = APP_START_TIMEOUT_MILLIS) {
83             composeTestRule.onNodeWithTag(CAMERA_PERMISSION_BUTTON).isDisplayed()
84         }
85 
86         // Click button to request permission
87         composeTestRule.onNodeWithTag(REQUEST_PERMISSION_BUTTON)
88             .assertExists()
89             .performClick()
90 
91         uiDevice.waitForIdle()
92         // grant permission
93         uiDevice.grantPermissionDialog()
94 
95         // Assert we're no longer on camera permission screen
96         composeTestRule.onNodeWithTag(CAMERA_PERMISSION_BUTTON).assertDoesNotExist()
97     }
98 
99     @SdkSuppress(minSdkVersion = 30)
100     @Test
cameraPermission_askEveryTime_closesPagenull101     fun cameraPermission_askEveryTime_closesPage() {
102         uiDevice.waitForIdle()
103         runScenarioTest<MainActivity> {
104             // Wait for the camera permission screen to be displayed
105             composeTestRule.waitUntil(timeoutMillis = APP_START_TIMEOUT_MILLIS) {
106                 composeTestRule.onNodeWithTag(CAMERA_PERMISSION_BUTTON).isDisplayed()
107             }
108 
109             // Click button to request permission
110             composeTestRule.onNodeWithTag(REQUEST_PERMISSION_BUTTON)
111                 .assertExists()
112                 .performClick()
113 
114             // set permission to ask every time
115             uiDevice.askEveryTimeDialog()
116 
117             // Assert we're no longer on camera permission screen
118             composeTestRule.onNodeWithTag(CAMERA_PERMISSION_BUTTON).assertDoesNotExist()
119         }
120     }
121 
122     @Test
cameraPermission_declined_staysOnScreennull123     fun cameraPermission_declined_staysOnScreen() {
124         // required permissions should persist on screen
125         // Wait for the permission screen to be displayed
126         runScenarioTest<MainActivity> {
127             composeTestRule.waitUntil(timeoutMillis = APP_START_TIMEOUT_MILLIS) {
128                 composeTestRule.onNodeWithTag(CAMERA_PERMISSION_BUTTON).isDisplayed()
129             }
130 
131             // Click button to request permission
132             composeTestRule.onNodeWithTag(REQUEST_PERMISSION_BUTTON)
133                 .assertExists()
134                 .performClick()
135 
136             // deny permission
137             uiDevice.denyPermissionDialog()
138 
139             uiDevice.waitForIdle()
140 
141             // Assert we're still on camera permission screen
142             composeTestRule.onNodeWithTag(CAMERA_PERMISSION_BUTTON).isDisplayed()
143 
144             // text changed after permission denied
145             composeTestRule.waitUntil(timeoutMillis = APP_START_TIMEOUT_MILLIS) {
146                 composeTestRule.onNodeWithText(
147                     com.google.jetpackcamera.permissions.R.string
148                         .camera_permission_declined_rationale
149                 )
150                     .isDisplayed()
151             }
152             // request permissions button should now say to navigate to settings
153             composeTestRule.onNodeWithText(
154                 com.google.jetpackcamera.permissions
155                     .R.string.navigate_to_settings
156             ).assertExists()
157         }
158     }
159 
160     @Test
recordAudioPermission_granted_closesPagenull161     fun recordAudioPermission_granted_closesPage() {
162         // optional permissions should close the screen after declining
163         runScenarioTest<MainActivity> {
164             composeTestRule.waitUntil(timeoutMillis = APP_START_TIMEOUT_MILLIS) {
165                 composeTestRule.onNodeWithTag(RECORD_AUDIO_PERMISSION_BUTTON).isDisplayed()
166             }
167 
168             // Click button to request permission
169             composeTestRule.onNodeWithTag(REQUEST_PERMISSION_BUTTON)
170                 .assertExists()
171                 .performClick()
172 
173             // grant permission
174             uiDevice.grantPermissionDialog()
175             uiDevice.waitForIdle()
176 
177             // Assert we're on a different page
178             composeTestRule.waitUntil(timeoutMillis = APP_START_TIMEOUT_MILLIS) {
179                 composeTestRule.onNodeWithTag(RECORD_AUDIO_PERMISSION_BUTTON).isNotDisplayed()
180             }
181         }
182     }
183 
184     @Test
recordAudioPermission_denied_closesPagenull185     fun recordAudioPermission_denied_closesPage() {
186         // optional permissions should close the screen after declining
187         runScenarioTest<MainActivity> {
188             composeTestRule.waitUntil(timeoutMillis = APP_START_TIMEOUT_MILLIS) {
189                 composeTestRule.onNodeWithTag(RECORD_AUDIO_PERMISSION_BUTTON).isDisplayed()
190             }
191 
192             // Click button to request permission
193             composeTestRule.onNodeWithTag(REQUEST_PERMISSION_BUTTON)
194                 .assertExists()
195                 .performClick()
196 
197             // deny permission
198             uiDevice.denyPermissionDialog()
199             uiDevice.waitForIdle()
200 
201             // Assert we're on a different page
202             composeTestRule.waitUntil(timeoutMillis = APP_START_TIMEOUT_MILLIS) {
203                 composeTestRule.onNodeWithTag(RECORD_AUDIO_PERMISSION_BUTTON).isNotDisplayed()
204             }
205         }
206     }
207 }
208