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.doubleClick
19 import androidx.compose.ui.test.isDisplayed
20 import androidx.compose.ui.test.isEnabled
21 import androidx.compose.ui.test.junit4.ComposeTestRule
22 import androidx.compose.ui.test.junit4.createEmptyComposeRule
23 import androidx.compose.ui.test.onNodeWithTag
24 import androidx.compose.ui.test.performClick
25 import androidx.compose.ui.test.performTouchInput
26 import androidx.test.core.app.ActivityScenario
27 import androidx.test.ext.junit.runners.AndroidJUnit4
28 import androidx.test.rule.GrantPermissionRule
29 import com.google.common.truth.Truth.assertThat
30 import com.google.jetpackcamera.feature.preview.quicksettings.ui.QUICK_SETTINGS_DROP_DOWN
31 import com.google.jetpackcamera.feature.preview.quicksettings.ui.QUICK_SETTINGS_FLIP_CAMERA_BUTTON
32 import com.google.jetpackcamera.feature.preview.ui.FLIP_CAMERA_BUTTON
33 import com.google.jetpackcamera.feature.preview.ui.PREVIEW_DISPLAY
34 import com.google.jetpackcamera.settings.model.LensFacing
35 import org.junit.Rule
36 import org.junit.Test
37 import org.junit.runner.RunWith
38
39 @RunWith(AndroidJUnit4::class)
40 class SwitchCameraTest {
41 @get:Rule
42 val permissionsRule: GrantPermissionRule =
43 GrantPermissionRule.grant(*(APP_REQUIRED_PERMISSIONS).toTypedArray())
44
45 @get:Rule
46 val composeTestRule = createEmptyComposeRule()
47
48 @Test
<lambda>null49 fun canFlipCamera_fromPreviewScreenButton() = runFlipCameraTest(composeTestRule) {
50 val lensFacingStates = mutableListOf<LensFacing>()
51 // Get initial lens facing
52 val initialLensFacing = composeTestRule.getCurrentLensFacing()
53 lensFacingStates.add(initialLensFacing)
54
55 // Press the flip camera button
56 composeTestRule.onNodeWithTag(FLIP_CAMERA_BUTTON).performClick()
57
58 // Get lens facing after first flip
59 lensFacingStates.add(composeTestRule.getCurrentLensFacing())
60
61 // Press the flip camera button again
62 composeTestRule.onNodeWithTag(FLIP_CAMERA_BUTTON).performClick()
63
64 // Get lens facing after second flip
65 lensFacingStates.add(composeTestRule.getCurrentLensFacing())
66
67 assertThat(lensFacingStates).containsExactly(
68 initialLensFacing,
69 initialLensFacing.flip(),
70 initialLensFacing.flip().flip()
71 ).inOrder()
72 }
73
74 @Test
<lambda>null75 fun canFlipCamera_fromPreviewScreenDoubleTap() = runFlipCameraTest(composeTestRule) {
76 val lensFacingStates = mutableListOf<LensFacing>()
77 // Get initial lens facing
78 val initialLensFacing = composeTestRule.getCurrentLensFacing()
79 lensFacingStates.add(initialLensFacing)
80
81 // Double click display to flip camera
82 composeTestRule.onNodeWithTag(PREVIEW_DISPLAY)
83 .performTouchInput { doubleClick() }
84
85 // Get lens facing after first flip
86 lensFacingStates.add(composeTestRule.getCurrentLensFacing())
87
88 // Double click display to flip camera again
89 composeTestRule.onNodeWithTag(PREVIEW_DISPLAY)
90 .performTouchInput { doubleClick() }
91
92 // Get lens facing after second flip
93 lensFacingStates.add(composeTestRule.getCurrentLensFacing())
94
95 assertThat(lensFacingStates).containsExactly(
96 initialLensFacing,
97 initialLensFacing.flip(),
98 initialLensFacing.flip().flip()
99 ).inOrder()
100 }
101
102 @Test
<lambda>null103 fun canFlipCamera_fromQuickSettings() = runFlipCameraTest(composeTestRule) {
104 // Navigate to quick settings
105 composeTestRule.onNodeWithTag(QUICK_SETTINGS_DROP_DOWN)
106 .assertExists()
107 .performClick()
108
109 val lensFacingStates = mutableListOf<LensFacing>()
110 // Get initial lens facing
111 val initialLensFacing = composeTestRule.getCurrentLensFacing()
112 lensFacingStates.add(initialLensFacing)
113
114 // Double click quick settings button to flip camera
115 composeTestRule.onNodeWithTag(QUICK_SETTINGS_FLIP_CAMERA_BUTTON).performClick()
116
117 // Get lens facing after first flip
118 lensFacingStates.add(composeTestRule.getCurrentLensFacing())
119
120 // Double click quick settings button to flip camera again
121 composeTestRule.onNodeWithTag(QUICK_SETTINGS_FLIP_CAMERA_BUTTON).performClick()
122
123 // Get lens facing after second flip
124 lensFacingStates.add(composeTestRule.getCurrentLensFacing())
125
126 assertThat(lensFacingStates).containsExactly(
127 initialLensFacing,
128 initialLensFacing.flip(),
129 initialLensFacing.flip().flip()
130 ).inOrder()
131 }
132 }
133
runFlipCameraTestnull134 inline fun runFlipCameraTest(
135 composeTestRule: ComposeTestRule,
136 crossinline block: ActivityScenario<MainActivity>.() -> Unit
137 ) = runScenarioTest {
138 // Wait for the preview display to be visible
139 composeTestRule.waitUntil {
140 composeTestRule.onNodeWithTag(PREVIEW_DISPLAY).isDisplayed()
141 }
142
143 // If flipping the camera is available, flip it. Otherwise skip test.
144 composeTestRule.onNodeWithTag(FLIP_CAMERA_BUTTON).assume(isEnabled()) {
145 "Device does not have multiple cameras to flip between."
146 }
147
148 block()
149 }
150