1 /* 2 * Copyright (C) 2023 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 android.os.Build 19 import androidx.compose.ui.test.isDisplayed 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.platform.app.InstrumentationRegistry 25 import androidx.test.rule.GrantPermissionRule 26 import androidx.test.uiautomator.By 27 import androidx.test.uiautomator.UiDevice 28 import androidx.test.uiautomator.Until 29 import com.google.common.truth.Truth.assertThat 30 import com.google.common.truth.TruthJUnit.assume 31 import com.google.jetpackcamera.feature.preview.quicksettings.ui.QUICK_SETTINGS_DROP_DOWN 32 import com.google.jetpackcamera.feature.preview.quicksettings.ui.QUICK_SETTINGS_FLIP_CAMERA_BUTTON 33 import com.google.jetpackcamera.feature.preview.quicksettings.ui.QUICK_SETTINGS_RATIO_1_1_BUTTON 34 import com.google.jetpackcamera.feature.preview.quicksettings.ui.QUICK_SETTINGS_RATIO_BUTTON 35 import com.google.jetpackcamera.feature.preview.quicksettings.ui.QUICK_SETTINGS_STREAM_CONFIG_BUTTON 36 import com.google.jetpackcamera.feature.preview.ui.CAPTURE_BUTTON 37 import com.google.jetpackcamera.utils.APP_START_TIMEOUT_MILLIS 38 import com.google.jetpackcamera.utils.TEST_REQUIRED_PERMISSIONS 39 import com.google.jetpackcamera.utils.runScenarioTest 40 import org.junit.Before 41 import org.junit.Rule 42 import org.junit.Test 43 import org.junit.runner.RunWith 44 45 @RunWith(AndroidJUnit4::class) 46 class BackgroundDeviceTest { 47 @get:Rule 48 val permissionsRule: GrantPermissionRule = 49 GrantPermissionRule.grant(*(TEST_REQUIRED_PERMISSIONS).toTypedArray()) 50 51 @get:Rule 52 val composeTestRule = createEmptyComposeRule() 53 54 private val instrumentation = InstrumentationRegistry.getInstrumentation() 55 private val uiDevice = UiDevice.getInstance(instrumentation) 56 backgroundThenForegroundAppnull57 private fun backgroundThenForegroundApp() { 58 uiDevice.pressHome() 59 uiDevice.pressRecentApps() 60 uiDevice.pressRecentApps() 61 62 // Wait for the app to return to the foreground 63 uiDevice.wait( 64 Until.hasObject(By.pkg("com.google.jetpackcamera")), 65 APP_START_TIMEOUT_MILLIS 66 ) 67 } 68 69 @Before setUpnull70 fun setUp() { 71 assertThat(uiDevice.isScreenOn).isTrue() 72 } 73 74 @Test <lambda>null75 fun background_foreground() = runScenarioTest<MainActivity> { 76 // Wait for the capture button to be displayed 77 composeTestRule.waitUntil(timeoutMillis = APP_START_TIMEOUT_MILLIS) { 78 composeTestRule.onNodeWithTag(CAPTURE_BUTTON).isDisplayed() 79 } 80 81 backgroundThenForegroundApp() 82 } 83 84 @Test <lambda>null85 fun flipCamera_then_background_foreground() = runScenarioTest<MainActivity> { 86 // Wait for the capture button to be displayed 87 composeTestRule.waitUntil(timeoutMillis = APP_START_TIMEOUT_MILLIS) { 88 composeTestRule.onNodeWithTag(CAPTURE_BUTTON).isDisplayed() 89 } 90 91 // Navigate to quick settings 92 composeTestRule.onNodeWithTag(QUICK_SETTINGS_DROP_DOWN) 93 .assertExists() 94 .performClick() 95 96 // Click the flip camera button 97 composeTestRule.onNodeWithTag(QUICK_SETTINGS_FLIP_CAMERA_BUTTON) 98 .assertExists() 99 .performClick() 100 101 // Exit quick settings 102 composeTestRule.onNodeWithTag(QUICK_SETTINGS_DROP_DOWN) 103 .assertExists() 104 .performClick() 105 106 backgroundThenForegroundApp() 107 } 108 109 @Test <lambda>null110 fun setAspectRatio_then_background_foreground() = runScenarioTest<MainActivity> { 111 // Wait for the capture button to be displayed 112 composeTestRule.waitUntil(timeoutMillis = APP_START_TIMEOUT_MILLIS) { 113 composeTestRule.onNodeWithTag(CAPTURE_BUTTON).isDisplayed() 114 } 115 116 // Navigate to quick settings 117 composeTestRule.onNodeWithTag(QUICK_SETTINGS_DROP_DOWN) 118 .assertExists() 119 .performClick() 120 121 // Click the ratio button 122 composeTestRule.onNodeWithTag(QUICK_SETTINGS_RATIO_BUTTON) 123 .assertExists() 124 .performClick() 125 126 // Click the 1:1 ratio button 127 composeTestRule.onNodeWithTag(QUICK_SETTINGS_RATIO_1_1_BUTTON) 128 .assertExists() 129 .performClick() 130 131 // Exit quick settings 132 composeTestRule.onNodeWithTag(QUICK_SETTINGS_DROP_DOWN) 133 .assertExists() 134 .performClick() 135 136 backgroundThenForegroundApp() 137 } 138 assumeSupportsSingleStreamnull139 private fun assumeSupportsSingleStream() { 140 // The GMD emulators with API <=28 do not support single-stream configs. 141 assume().that(Build.HARDWARE == "ranchu" && Build.VERSION.SDK_INT <= 28).isFalse() 142 } 143 144 @Test <lambda>null145 fun toggleCaptureMode_then_background_foreground() = runScenarioTest<MainActivity> { 146 // Skip this test on devices that don't support single stream 147 assumeSupportsSingleStream() 148 149 // Wait for the capture button to be displayed 150 composeTestRule.waitUntil(timeoutMillis = APP_START_TIMEOUT_MILLIS) { 151 composeTestRule.onNodeWithTag(CAPTURE_BUTTON).isDisplayed() 152 } 153 154 // Navigate to quick settings 155 composeTestRule.onNodeWithTag(QUICK_SETTINGS_DROP_DOWN) 156 .assertExists() 157 .performClick() 158 159 // Click the flip camera button 160 composeTestRule.onNodeWithTag(QUICK_SETTINGS_STREAM_CONFIG_BUTTON) 161 .assertExists() 162 .performClick() 163 164 // Exit quick settings 165 composeTestRule.onNodeWithTag(QUICK_SETTINGS_DROP_DOWN) 166 .assertExists() 167 .performClick() 168 169 backgroundThenForegroundApp() 170 } 171 } 172