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.isEnabled 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.UiDevice 27 import com.google.jetpackcamera.feature.preview.quicksettings.ui.QUICK_SETTINGS_DROP_DOWN 28 import com.google.jetpackcamera.feature.preview.quicksettings.ui.QUICK_SETTINGS_RATIO_1_1_BUTTON 29 import com.google.jetpackcamera.feature.preview.quicksettings.ui.QUICK_SETTINGS_RATIO_BUTTON 30 import com.google.jetpackcamera.feature.preview.ui.CAPTURE_BUTTON 31 import com.google.jetpackcamera.feature.preview.ui.FLIP_CAMERA_BUTTON 32 import com.google.jetpackcamera.feature.preview.ui.SETTINGS_BUTTON 33 import com.google.jetpackcamera.settings.ui.BACK_BUTTON 34 import org.junit.Rule 35 import org.junit.Test 36 import org.junit.runner.RunWith 37 38 @RunWith(AndroidJUnit4::class) 39 class NavigationTest { 40 @get:Rule 41 val permissionsRule: GrantPermissionRule = 42 GrantPermissionRule.grant(*(APP_REQUIRED_PERMISSIONS).toTypedArray()) 43 44 @get:Rule 45 val composeTestRule = createEmptyComposeRule() 46 47 private val instrumentation = InstrumentationRegistry.getInstrumentation() 48 private val uiDevice = UiDevice.getInstance(instrumentation) 49 50 @Test <lambda>null51 fun backAfterReturnFromSettings_doesNotReturnToSettings() = runScenarioTest<MainActivity> { 52 // Wait for the capture button to be displayed 53 composeTestRule.waitUntil(timeoutMillis = APP_START_TIMEOUT_MILLIS) { 54 composeTestRule.onNodeWithTag(CAPTURE_BUTTON).isDisplayed() 55 } 56 57 // Navigate to the settings screen 58 composeTestRule.onNodeWithTag(SETTINGS_BUTTON) 59 .assertExists() 60 .performClick() 61 62 // Navigate back using the button 63 composeTestRule.onNodeWithTag(BACK_BUTTON) 64 .assertExists() 65 .performClick() 66 67 // Assert we're on PreviewScreen by finding the capture button 68 composeTestRule.onNodeWithTag(CAPTURE_BUTTON).assertExists() 69 70 // Press the device's back button 71 uiDevice.pressBack() 72 73 // Assert we do not see the settings screen based on the title 74 composeTestRule.onNodeWithText( 75 com.google.jetpackcamera.settings.R.string.settings_title 76 ).assertDoesNotExist() 77 } 78 79 // Test to ensure we haven't regressed to the cause of 80 // https://github.com/google/jetpack-camera-app/pull/28 81 @Test <lambda>null82 fun returnFromSettings_afterFlipCamera_returnsToPreview() = runScenarioTest<MainActivity> { 83 // Wait for the capture button to be displayed 84 composeTestRule.waitUntil(timeoutMillis = APP_START_TIMEOUT_MILLIS) { 85 composeTestRule.onNodeWithTag(CAPTURE_BUTTON).isDisplayed() 86 } 87 88 // If flipping the camera is available, flip it. Otherwise skip test. 89 composeTestRule.onNodeWithTag(FLIP_CAMERA_BUTTON) 90 .assume(isEnabled()) { 91 "Device does not have multiple cameras to flip between." 92 }.performClick() 93 94 // Navigate to the settings screen 95 composeTestRule.onNodeWithTag(SETTINGS_BUTTON) 96 .assertExists() 97 .performClick() 98 99 // Navigate back using the button 100 composeTestRule.onNodeWithTag(BACK_BUTTON) 101 .assertExists() 102 .performClick() 103 104 // Assert we're on PreviewScreen by finding the capture button 105 composeTestRule.onNodeWithTag(CAPTURE_BUTTON).assertExists() 106 } 107 108 @Test <lambda>null109 fun backFromQuickSettings_returnToPreview() = runScenarioTest<MainActivity> { 110 // Wait for the capture button to be displayed 111 composeTestRule.waitUntil(timeoutMillis = APP_START_TIMEOUT_MILLIS) { 112 composeTestRule.onNodeWithTag(CAPTURE_BUTTON).isDisplayed() 113 } 114 115 // Navigate to the quick settings screen 116 composeTestRule.onNodeWithTag(QUICK_SETTINGS_DROP_DOWN) 117 .assertExists() 118 .performClick() 119 120 // Wait for the quick settings to be displayed 121 composeTestRule.waitUntil { 122 composeTestRule.onNodeWithTag(QUICK_SETTINGS_RATIO_BUTTON).isDisplayed() 123 } 124 125 // Press the device's back button 126 uiDevice.pressBack() 127 128 // Assert we're on PreviewScreen by finding the flip camera button 129 composeTestRule.onNodeWithTag(FLIP_CAMERA_BUTTON).assertExists() 130 } 131 132 @Test <lambda>null133 fun backFromQuickSettingsExpended_returnToQuickSettings() = runScenarioTest<MainActivity> { 134 // Wait for the capture button to be displayed 135 composeTestRule.waitUntil(timeoutMillis = APP_START_TIMEOUT_MILLIS) { 136 composeTestRule.onNodeWithTag(CAPTURE_BUTTON).isDisplayed() 137 } 138 139 // Navigate to the quick settings screen 140 composeTestRule.onNodeWithTag(QUICK_SETTINGS_DROP_DOWN) 141 .assertExists() 142 .performClick() 143 144 // Navigate to the expanded quick settings ratio screen 145 composeTestRule.onNodeWithTag(QUICK_SETTINGS_RATIO_BUTTON) 146 .assertExists() 147 .performClick() 148 149 // Wait for the 1:1 ratio button to be displayed 150 composeTestRule.waitUntil { 151 composeTestRule.onNodeWithTag(QUICK_SETTINGS_RATIO_1_1_BUTTON).isDisplayed() 152 } 153 154 // Press the device's back button 155 uiDevice.pressBack() 156 157 // Assert we're on quick settings by finding the ratio button 158 composeTestRule.onNodeWithTag(QUICK_SETTINGS_RATIO_BUTTON).assertExists() 159 } 160 } 161