• 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 com.android.systemui.qs.panels.ui
18 
19 import androidx.compose.foundation.layout.Box
20 import androidx.compose.foundation.layout.fillMaxWidth
21 import androidx.compose.foundation.layout.height
22 import androidx.compose.runtime.Composable
23 import androidx.compose.ui.Modifier
24 import androidx.compose.ui.platform.testTag
25 import androidx.compose.ui.test.getBoundsInRoot
26 import androidx.compose.ui.test.junit4.createComposeRule
27 import androidx.compose.ui.test.onNodeWithTag
28 import androidx.compose.ui.unit.Dp
29 import androidx.compose.ui.unit.DpRect
30 import androidx.compose.ui.unit.dp
31 import androidx.compose.ui.unit.width
32 import androidx.test.ext.junit.runners.AndroidJUnit4
33 import androidx.test.filters.SmallTest
34 import com.android.systemui.SysuiTestCase
35 import com.android.systemui.qs.composefragment.QuickQuickSettingsLayout
36 import com.android.systemui.qs.composefragment.QuickSettingsLayout
37 import com.google.common.truth.Truth.assertThat
38 import org.junit.Rule
39 import org.junit.Test
40 import org.junit.runner.RunWith
41 
42 @RunWith(AndroidJUnit4::class)
43 @SmallTest
44 class QSFragmentComposeTest : SysuiTestCase() {
45 
46     @get:Rule val composeTestRule = createComposeRule()
47 
48     @Test
portraitLayout_qqsnull49     fun portraitLayout_qqs() {
50         composeTestRule.setContent {
51             QuickQuickSettingsLayout(
52                 tiles = { Tiles(TILES_HEIGHT_PORTRAIT) },
53                 media = { Media() },
54                 mediaInRow = false,
55             )
56         }
57 
58         composeTestRule.waitForIdle()
59 
60         val tilesBounds = composeTestRule.onNodeWithTag(TILES).getBoundsInRoot()
61         val mediaBounds = composeTestRule.onNodeWithTag(MEDIA).getBoundsInRoot()
62 
63         // All nodes aligned in a column
64         assertThat(tilesBounds.left).isEqualTo(mediaBounds.left)
65         assertThat(tilesBounds.right).isEqualTo(mediaBounds.right)
66         assertThat(tilesBounds.bottom).isLessThan(mediaBounds.top)
67     }
68 
69     @Test
landscapeLayout_qqsnull70     fun landscapeLayout_qqs() {
71         composeTestRule.setContent {
72             QuickQuickSettingsLayout(
73                 tiles = { Tiles(TILES_HEIGHT_LANDSCAPE) },
74                 media = { Media() },
75                 mediaInRow = true,
76             )
77         }
78 
79         composeTestRule.waitForIdle()
80 
81         val tilesBounds = composeTestRule.onNodeWithTag(TILES).getBoundsInRoot()
82         val mediaBounds = composeTestRule.onNodeWithTag(MEDIA).getBoundsInRoot()
83 
84         // Media to the right of tiles
85         assertThat(tilesBounds.right).isLessThan(mediaBounds.left)
86         // "Same" width
87         assertThat((tilesBounds.width - mediaBounds.width).abs()).isAtMost(1.dp)
88         // Vertically centered
89         assertThat((tilesBounds.centerY - mediaBounds.centerY).abs()).isAtMost(1.dp)
90     }
91 
92     @Test
portraitLayout_qsnull93     fun portraitLayout_qs() {
94         composeTestRule.setContent {
95             QuickSettingsLayout(
96                 brightness = { Brightness() },
97                 tiles = { Tiles(TILES_HEIGHT_PORTRAIT) },
98                 media = { Media() },
99                 mediaInRow = false,
100             )
101         }
102 
103         composeTestRule.waitForIdle()
104 
105         val brightnessBounds = composeTestRule.onNodeWithTag(BRIGHTNESS).getBoundsInRoot()
106         val tilesBounds = composeTestRule.onNodeWithTag(TILES).getBoundsInRoot()
107         val mediaBounds = composeTestRule.onNodeWithTag(MEDIA).getBoundsInRoot()
108 
109         assertThat(brightnessBounds.left).isEqualTo(tilesBounds.left)
110         assertThat(tilesBounds.left).isEqualTo(mediaBounds.left)
111 
112         assertThat(brightnessBounds.right).isEqualTo(tilesBounds.right)
113         assertThat(tilesBounds.right).isEqualTo(mediaBounds.right)
114 
115         assertThat(brightnessBounds.bottom).isLessThan(tilesBounds.top)
116         assertThat(tilesBounds.bottom).isLessThan(mediaBounds.top)
117     }
118 
119     @Test
landscapeLayout_qsnull120     fun landscapeLayout_qs() {
121         composeTestRule.setContent {
122             QuickSettingsLayout(
123                 brightness = { Brightness() },
124                 tiles = { Tiles(TILES_HEIGHT_PORTRAIT) },
125                 media = { Media() },
126                 mediaInRow = true,
127             )
128         }
129 
130         composeTestRule.waitForIdle()
131 
132         val brightnessBounds = composeTestRule.onNodeWithTag(BRIGHTNESS).getBoundsInRoot()
133         val tilesBounds = composeTestRule.onNodeWithTag(TILES).getBoundsInRoot()
134         val mediaBounds = composeTestRule.onNodeWithTag(MEDIA).getBoundsInRoot()
135 
136         // Brightness takes full width, with left end aligned with tiles and right end aligned with
137         // media
138         assertThat(brightnessBounds.left).isEqualTo(tilesBounds.left)
139         assertThat(brightnessBounds.right).isEqualTo(mediaBounds.right)
140 
141         // Brightness above tiles and media
142         assertThat(brightnessBounds.bottom).isLessThan(tilesBounds.top)
143         assertThat(brightnessBounds.bottom).isLessThan(mediaBounds.top)
144 
145         // Media to the right of tiles
146         assertThat(tilesBounds.right).isLessThan(mediaBounds.left)
147         // "Same" width
148         assertThat((tilesBounds.width - mediaBounds.width).abs()).isAtMost(1.dp)
149         // Vertically centered
150         assertThat((tilesBounds.centerY - mediaBounds.centerY).abs()).isAtMost(1.dp)
151     }
152 
153     private companion object {
154         const val BRIGHTNESS = "brightness"
155         const val TILES = "tiles"
156         const val MEDIA = "media"
157         val TILES_HEIGHT_PORTRAIT = 300.dp
158         val TILES_HEIGHT_LANDSCAPE = 150.dp
159         val MEDIA_HEIGHT = 100.dp
160         val BRIGHTNESS_HEIGHT = 64.dp
161 
162         @Composable
Brightnessnull163         fun Brightness() {
164             Box(modifier = Modifier.testTag(BRIGHTNESS).height(BRIGHTNESS_HEIGHT).fillMaxWidth())
165         }
166 
167         @Composable
Tilesnull168         fun Tiles(height: Dp) {
169             Box(modifier = Modifier.testTag(TILES).height(height).fillMaxWidth())
170         }
171 
172         @Composable
Medianull173         fun Media() {
174             Box(modifier = Modifier.testTag(MEDIA).height(MEDIA_HEIGHT).fillMaxWidth())
175         }
176 
177         val DpRect.centerY: Dp
178             get() = (top + bottom) / 2
179 
absnull180         fun Dp.abs() = if (this > 0.dp) this else -this
181     }
182 }
183