[go: nahoru, domu]

blob: 76b3d5cca7395aa2c3fbf44efd69291117ff8a60 [file] [log] [blame]
Mihai Popa746e2302019-09-30 17:31:56 +01001/*
2 * Copyright 2019 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
17package androidx.ui.material
18
Mihai Popa746e2302019-09-30 17:31:56 +010019import androidx.test.filters.SmallTest
Louis Pullen-Freilichca6eca22020-07-20 00:31:45 +010020import androidx.compose.foundation.text.FirstBaseline
Adam Powell999a89b2020-03-11 09:08:07 -070021import androidx.ui.core.LayoutCoordinates
George Mountbfa1fb22020-03-11 09:35:05 -070022import androidx.ui.core.Modifier
Mihai Popa746e2302019-09-30 17:31:56 +010023import androidx.ui.core.Ref
George Mountbfa1fb22020-03-11 09:35:05 -070024import androidx.ui.core.onPositioned
Louis Pullen-Freilichddda7be2020-07-17 18:28:12 +010025import androidx.compose.foundation.Box
26import androidx.compose.foundation.Image
27import androidx.compose.foundation.Text
Louis Pullen-Freilichf434a13e2020-07-22 14:19:24 +010028import androidx.compose.ui.geometry.Offset
Louis Pullen-Freilich4dc4dac2020-07-22 14:39:14 +010029import androidx.compose.ui.graphics.ImageAsset
Filip Pavlis028c0d52020-06-29 15:07:53 +010030import androidx.ui.test.assertHeightIsEqualTo
Mihai Popa746e2302019-09-30 17:31:56 +010031import androidx.ui.test.createComposeRule
Louis Pullen-Freilicha7eeb102020-07-22 17:54:24 +010032import androidx.compose.ui.unit.Dp
33import androidx.compose.ui.unit.IntSize
34import androidx.compose.ui.unit.dp
Filip Pavlis2b161e42019-11-22 17:40:08 +000035import com.google.common.truth.Truth.assertThat
Mihai Popa746e2302019-09-30 17:31:56 +010036import org.junit.Rule
37import org.junit.Test
38import org.junit.runner.RunWith
39import org.junit.runners.JUnit4
40import kotlin.math.roundToInt
41
42@SmallTest
43@RunWith(JUnit4::class)
44class ListItemTest {
45
46 @get:Rule
47 val composeTestRule = createComposeRule()
48
Nader Jawad6ec796a2020-02-28 13:40:11 -080049 val icon24x24 by lazy { ImageAsset(width = 24.dp.toIntPx(), height = 24.dp.toIntPx()) }
50 val icon40x40 by lazy { ImageAsset(width = 40.dp.toIntPx(), height = 40.dp.toIntPx()) }
51 val icon56x56 by lazy { ImageAsset(width = 56.dp.toIntPx(), height = 56.dp.toIntPx()) }
Mihai Popa746e2302019-09-30 17:31:56 +010052
53 @Test
54 fun listItem_oneLine_size() {
Mihai Popa746e2302019-09-30 17:31:56 +010055 val expectedHeightNoIcon = 48.dp
Mihai Popa746e2302019-09-30 17:31:56 +010056 composeTestRule
Filip Pavlis028c0d52020-06-29 15:07:53 +010057 .setMaterialContentForSizeAssertions {
Mihai Popa746e2302019-09-30 17:31:56 +010058 ListItem(text = "Primary text")
59 }
Filip Pavlis028c0d52020-06-29 15:07:53 +010060 .assertHeightIsEqualTo(expectedHeightNoIcon)
61 .assertWidthFillsRoot()
Filip Pavlis2b161e42019-11-22 17:40:08 +000062 }
63
64 @Test
65 fun listItem_oneLine_withIcon24_size() {
Filip Pavlis2b161e42019-11-22 17:40:08 +000066 val expectedHeightSmallIcon = 56.dp
Mihai Popa746e2302019-09-30 17:31:56 +010067 composeTestRule
Filip Pavlis028c0d52020-06-29 15:07:53 +010068 .setMaterialContentForSizeAssertions {
Mihai Popa746e2302019-09-30 17:31:56 +010069 ListItem(text = "Primary text", icon = icon24x24)
70 }
Filip Pavlis028c0d52020-06-29 15:07:53 +010071 .assertHeightIsEqualTo(expectedHeightSmallIcon)
72 .assertWidthFillsRoot()
Filip Pavlis2b161e42019-11-22 17:40:08 +000073 }
74
75 @Test
76 fun listItem_oneLine_withIcon56_size() {
Filip Pavlis2b161e42019-11-22 17:40:08 +000077 val expectedHeightLargeIcon = 72.dp
Mihai Popa746e2302019-09-30 17:31:56 +010078 composeTestRule
Filip Pavlis028c0d52020-06-29 15:07:53 +010079 .setMaterialContentForSizeAssertions {
Mihai Popa746e2302019-09-30 17:31:56 +010080 ListItem(text = "Primary text", icon = icon56x56)
81 }
Filip Pavlis028c0d52020-06-29 15:07:53 +010082 .assertHeightIsEqualTo(expectedHeightLargeIcon)
83 .assertWidthFillsRoot()
Mihai Popa746e2302019-09-30 17:31:56 +010084 }
85
86 @Test
87 fun listItem_twoLine_size() {
Mihai Popa746e2302019-09-30 17:31:56 +010088 val expectedHeightNoIcon = 64.dp
Mihai Popa746e2302019-09-30 17:31:56 +010089 composeTestRule
Filip Pavlis028c0d52020-06-29 15:07:53 +010090 .setMaterialContentForSizeAssertions {
Mihai Popa746e2302019-09-30 17:31:56 +010091 ListItem(text = "Primary text", secondaryText = "Secondary text")
92 }
Filip Pavlis028c0d52020-06-29 15:07:53 +010093 .assertHeightIsEqualTo(expectedHeightNoIcon)
94 .assertWidthFillsRoot()
Filip Pavlis2b161e42019-11-22 17:40:08 +000095 }
96
97 @Test
98 fun listItem_twoLine_withIcon_size() {
Filip Pavlis2b161e42019-11-22 17:40:08 +000099 val expectedHeightWithIcon = 72.dp
100
Mihai Popa746e2302019-09-30 17:31:56 +0100101 composeTestRule
Filip Pavlis028c0d52020-06-29 15:07:53 +0100102 .setMaterialContentForSizeAssertions {
Mihai Popa746e2302019-09-30 17:31:56 +0100103 ListItem(
104 text = "Primary text",
105 secondaryText = "Secondary text",
106 icon = icon24x24
107 )
108 }
Filip Pavlis028c0d52020-06-29 15:07:53 +0100109 .assertHeightIsEqualTo(expectedHeightWithIcon)
110 .assertWidthFillsRoot()
Mihai Popa746e2302019-09-30 17:31:56 +0100111 }
112
113 @Test
114 fun listItem_threeLine_size() {
Mihai Popa746e2302019-09-30 17:31:56 +0100115 val expectedHeight = 88.dp
116 composeTestRule
Filip Pavlis028c0d52020-06-29 15:07:53 +0100117 .setMaterialContentForSizeAssertions {
Mihai Popa746e2302019-09-30 17:31:56 +0100118 ListItem(
119 overlineText = "OVERLINE",
120 text = "Primary text",
121 secondaryText = "Secondary text"
122 )
123 }
Filip Pavlis028c0d52020-06-29 15:07:53 +0100124 .assertHeightIsEqualTo(expectedHeight)
125 .assertWidthFillsRoot()
Filip Pavlis2b161e42019-11-22 17:40:08 +0000126 }
127
128 @Test
129 fun listItem_threeLine_noSingleLine_size() {
Filip Pavlis2b161e42019-11-22 17:40:08 +0000130 val expectedHeight = 88.dp
Mihai Popa746e2302019-09-30 17:31:56 +0100131 composeTestRule
Filip Pavlis028c0d52020-06-29 15:07:53 +0100132 .setMaterialContentForSizeAssertions {
Mihai Popa746e2302019-09-30 17:31:56 +0100133 ListItem(
134 text = "Primary text",
135 secondaryText = "Secondary text with long text",
136 singleLineSecondaryText = false
137 )
138 }
Filip Pavlis028c0d52020-06-29 15:07:53 +0100139 .assertHeightIsEqualTo(expectedHeight)
140 .assertWidthFillsRoot()
Filip Pavlis2b161e42019-11-22 17:40:08 +0000141 }
142
143 @Test
144 fun listItem_threeLine_metaText_size() {
Filip Pavlis2b161e42019-11-22 17:40:08 +0000145 val expectedHeight = 88.dp
Mihai Popa746e2302019-09-30 17:31:56 +0100146 composeTestRule
Filip Pavlis028c0d52020-06-29 15:07:53 +0100147 .setMaterialContentForSizeAssertions {
Mihai Popa746e2302019-09-30 17:31:56 +0100148 ListItem(
149 overlineText = "OVERLINE",
150 text = "Primary text",
151 secondaryText = "Secondary text",
152 metaText = "meta"
153 )
154 }
Filip Pavlis028c0d52020-06-29 15:07:53 +0100155 .assertHeightIsEqualTo(expectedHeight)
156 .assertWidthFillsRoot()
Filip Pavlis2b161e42019-11-22 17:40:08 +0000157 }
158
159 @Test
160 fun listItem_threeLine_noSingleLine_metaText_size() {
Filip Pavlis2b161e42019-11-22 17:40:08 +0000161 val expectedHeight = 88.dp
Mihai Popa746e2302019-09-30 17:31:56 +0100162 composeTestRule
Filip Pavlis028c0d52020-06-29 15:07:53 +0100163 .setMaterialContentForSizeAssertions {
Mihai Popa746e2302019-09-30 17:31:56 +0100164 ListItem(
165 text = "Primary text",
166 secondaryText = "Secondary text with long text",
167 singleLineSecondaryText = false,
168 metaText = "meta"
169 )
170 }
Filip Pavlis028c0d52020-06-29 15:07:53 +0100171 .assertHeightIsEqualTo(expectedHeight)
172 .assertWidthFillsRoot()
Mihai Popa746e2302019-09-30 17:31:56 +0100173 }
174
175 @Test
176 fun listItem_oneLine_positioning_noIcon() {
177 val listItemHeight = 48.dp
178 val expectedLeftPadding = 16.dp
179 val expectedRightPadding = 16.dp
180
Nader Jawad6df06122020-06-03 15:27:08 -0700181 val textPosition = Ref<Offset>()
George Mount8f237572020-04-30 12:08:30 -0700182 val textSize = Ref<IntSize>()
Nader Jawad6df06122020-06-03 15:27:08 -0700183 val trailingPosition = Ref<Offset>()
George Mount8f237572020-04-30 12:08:30 -0700184 val trailingSize = Ref<IntSize>()
Mihai Popa746e2302019-09-30 17:31:56 +0100185 composeTestRule.setMaterialContent {
Matvei Malkov201726d2020-03-13 14:03:54 +0000186 Box {
Mihai Popa746e2302019-09-30 17:31:56 +0100187 ListItem(
George Mountbfa1fb22020-03-11 09:35:05 -0700188 text = { Text("Primary text", saveLayout(textPosition, textSize)) },
Mihai Popa746e2302019-09-30 17:31:56 +0100189 trailing = {
George Mountbfa1fb22020-03-11 09:35:05 -0700190 Image(icon24x24, saveLayout(trailingPosition, trailingSize))
Mihai Popa746e2302019-09-30 17:31:56 +0100191 }
192 )
193 }
194 }
Filip Pavlisa4d73a52020-07-14 11:30:00 +0100195 composeTestRule.runOnIdleWithDensity {
Nader Jawad63153c12020-05-21 14:17:08 -0700196 assertThat(textPosition.value!!.x).isEqualTo(expectedLeftPadding.toIntPx()
George Mount8f237572020-04-30 12:08:30 -0700197 .toFloat())
Filip Pavlis2b161e42019-11-22 17:40:08 +0000198 assertThat(textPosition.value!!.y).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700199 ((listItemHeight.toIntPx() - textSize.value!!.height) / 2f).roundToInt().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100200 )
201 val dm = composeTestRule.displayMetrics
Filip Pavlis2b161e42019-11-22 17:40:08 +0000202 assertThat(trailingPosition.value!!.x).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700203 dm.widthPixels - trailingSize.value!!.width -
204 expectedRightPadding.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100205 )
Filip Pavlis2b161e42019-11-22 17:40:08 +0000206 assertThat(trailingPosition.value!!.y).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700207 ((listItemHeight.toIntPx() - trailingSize.value!!.height) / 2f).roundToInt()
208 .toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100209 )
210 }
211 }
212
213 @Test
214 fun listItem_oneLine_positioning_withIcon() {
215 val listItemHeight = 56.dp
216 val expectedLeftPadding = 16.dp
217 val expectedTextLeftPadding = 32.dp
218
Nader Jawad6df06122020-06-03 15:27:08 -0700219 val textPosition = Ref<Offset>()
George Mount8f237572020-04-30 12:08:30 -0700220 val textSize = Ref<IntSize>()
Nader Jawad6df06122020-06-03 15:27:08 -0700221 val iconPosition = Ref<Offset>()
George Mount8f237572020-04-30 12:08:30 -0700222 val iconSize = Ref<IntSize>()
Mihai Popa746e2302019-09-30 17:31:56 +0100223 composeTestRule.setMaterialContent {
Matvei Malkov201726d2020-03-13 14:03:54 +0000224 Box {
Mihai Popa746e2302019-09-30 17:31:56 +0100225 ListItem(
George Mountbfa1fb22020-03-11 09:35:05 -0700226 text = { Text("Primary text", saveLayout(textPosition, textSize)) },
227 icon = { Image(icon24x24, saveLayout(iconPosition, iconSize)) }
Mihai Popa746e2302019-09-30 17:31:56 +0100228 )
229 }
230 }
Filip Pavlisa4d73a52020-07-14 11:30:00 +0100231 composeTestRule.runOnIdleWithDensity {
Nader Jawad63153c12020-05-21 14:17:08 -0700232 assertThat(iconPosition.value!!.x).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700233 expectedLeftPadding.toIntPx().toFloat()
Nader Jawad63153c12020-05-21 14:17:08 -0700234 )
Filip Pavlis2b161e42019-11-22 17:40:08 +0000235 assertThat(iconPosition.value!!.y).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700236 ((listItemHeight.toIntPx() - iconSize.value!!.height) / 2f).roundToInt().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100237 )
Filip Pavlis2b161e42019-11-22 17:40:08 +0000238 assertThat(textPosition.value!!.x).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700239 expectedLeftPadding.toIntPx().toFloat() +
240 iconSize.value!!.width +
241 expectedTextLeftPadding.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100242 )
Filip Pavlis2b161e42019-11-22 17:40:08 +0000243 assertThat(textPosition.value!!.y).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700244 ((listItemHeight.toIntPx() - textSize.value!!.height) / 2f).roundToInt().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100245 )
246 }
247 }
248
249 @Test
250 fun listItem_twoLine_positioning_noIcon() {
251 val expectedLeftPadding = 16.dp
252 val expectedRightPadding = 16.dp
253 val expectedTextBaseline = 28.dp
254 val expectedSecondaryTextBaselineOffset = 20.dp
255
Nader Jawad6df06122020-06-03 15:27:08 -0700256 val textPosition = Ref<Offset>()
Nader Jawade6a9b332020-05-21 13:49:20 -0700257 val textBaseline = Ref<Float>()
George Mount8f237572020-04-30 12:08:30 -0700258 val textSize = Ref<IntSize>()
Nader Jawad6df06122020-06-03 15:27:08 -0700259 val secondaryTextPosition = Ref<Offset>()
Nader Jawade6a9b332020-05-21 13:49:20 -0700260 val secondaryTextBaseline = Ref<Float>()
George Mount8f237572020-04-30 12:08:30 -0700261 val secondaryTextSize = Ref<IntSize>()
Nader Jawad6df06122020-06-03 15:27:08 -0700262 val trailingPosition = Ref<Offset>()
Nader Jawade6a9b332020-05-21 13:49:20 -0700263 val trailingBaseline = Ref<Float>()
George Mount8f237572020-04-30 12:08:30 -0700264 val trailingSize = Ref<IntSize>()
Mihai Popa746e2302019-09-30 17:31:56 +0100265 composeTestRule.setMaterialContent {
Matvei Malkov201726d2020-03-13 14:03:54 +0000266 Box {
Mihai Popa746e2302019-09-30 17:31:56 +0100267 ListItem(
268 text = {
George Mountbfa1fb22020-03-11 09:35:05 -0700269 Text("Primary text", saveLayout(textPosition, textSize, textBaseline))
Mihai Popa746e2302019-09-30 17:31:56 +0100270 },
271 secondaryText = {
George Mountbfa1fb22020-03-11 09:35:05 -0700272 Text(
273 "Secondary text",
274 saveLayout(
275 secondaryTextPosition,
276 secondaryTextSize,
277 secondaryTextBaseline
278 )
279 )
Mihai Popa746e2302019-09-30 17:31:56 +0100280 },
281 trailing = {
George Mountbfa1fb22020-03-11 09:35:05 -0700282 Text("meta", saveLayout(trailingPosition, trailingSize, trailingBaseline))
Mihai Popa746e2302019-09-30 17:31:56 +0100283 }
284 )
285 }
286 }
Filip Pavlisa4d73a52020-07-14 11:30:00 +0100287 composeTestRule.runOnIdleWithDensity {
Nader Jawad63153c12020-05-21 14:17:08 -0700288 assertThat(textPosition.value!!.x).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700289 expectedLeftPadding.toIntPx().toFloat()
Nader Jawad63153c12020-05-21 14:17:08 -0700290 )
291 assertThat(textBaseline.value!!).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700292 expectedTextBaseline.toIntPx().toFloat()
Nader Jawad63153c12020-05-21 14:17:08 -0700293 )
Filip Pavlis2b161e42019-11-22 17:40:08 +0000294 assertThat(secondaryTextPosition.value!!.x).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700295 expectedLeftPadding.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100296 )
Filip Pavlis2b161e42019-11-22 17:40:08 +0000297 assertThat(secondaryTextBaseline.value!!).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700298 expectedTextBaseline.toIntPx().toFloat() +
299 expectedSecondaryTextBaselineOffset.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100300 )
301 val dm = composeTestRule.displayMetrics
Filip Pavlis2b161e42019-11-22 17:40:08 +0000302 assertThat(trailingPosition.value!!.x).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700303 dm.widthPixels - trailingSize.value!!.width -
304 expectedRightPadding.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100305 )
Filip Pavlis2b161e42019-11-22 17:40:08 +0000306 assertThat(trailingBaseline.value!!).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700307 expectedTextBaseline.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100308 )
309 }
310 }
311
312 @Test
313 fun listItem_twoLine_positioning_withSmallIcon() {
314 val expectedLeftPadding = 16.dp
315 val expectedIconTopPadding = 16.dp
316 val expectedContentLeftPadding = 32.dp
317 val expectedTextBaseline = 32.dp
318 val expectedSecondaryTextBaselineOffset = 20.dp
319
Nader Jawad6df06122020-06-03 15:27:08 -0700320 val textPosition = Ref<Offset>()
Nader Jawade6a9b332020-05-21 13:49:20 -0700321 val textBaseline = Ref<Float>()
George Mount8f237572020-04-30 12:08:30 -0700322 val textSize = Ref<IntSize>()
Nader Jawad6df06122020-06-03 15:27:08 -0700323 val secondaryTextPosition = Ref<Offset>()
Nader Jawade6a9b332020-05-21 13:49:20 -0700324 val secondaryTextBaseline = Ref<Float>()
George Mount8f237572020-04-30 12:08:30 -0700325 val secondaryTextSize = Ref<IntSize>()
Nader Jawad6df06122020-06-03 15:27:08 -0700326 val iconPosition = Ref<Offset>()
George Mount8f237572020-04-30 12:08:30 -0700327 val iconSize = Ref<IntSize>()
Mihai Popa746e2302019-09-30 17:31:56 +0100328 composeTestRule.setMaterialContent {
Matvei Malkov201726d2020-03-13 14:03:54 +0000329 Box {
Mihai Popa746e2302019-09-30 17:31:56 +0100330 ListItem(
331 text = {
George Mountbfa1fb22020-03-11 09:35:05 -0700332 Text("Primary text", saveLayout(textPosition, textSize, textBaseline))
Mihai Popa746e2302019-09-30 17:31:56 +0100333 },
334 secondaryText = {
George Mountbfa1fb22020-03-11 09:35:05 -0700335 Text(
336 "Secondary text",
337 saveLayout(
338 secondaryTextPosition,
339 secondaryTextSize,
340 secondaryTextBaseline
341 )
342 )
Mihai Popa746e2302019-09-30 17:31:56 +0100343 },
344 icon = {
George Mountbfa1fb22020-03-11 09:35:05 -0700345 Image(icon24x24, saveLayout(iconPosition, iconSize))
Mihai Popa746e2302019-09-30 17:31:56 +0100346 }
347 )
348 }
349 }
Filip Pavlisa4d73a52020-07-14 11:30:00 +0100350 composeTestRule.runOnIdleWithDensity {
Filip Pavlis2b161e42019-11-22 17:40:08 +0000351 assertThat(textPosition.value!!.x).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700352 expectedLeftPadding.toIntPx().toFloat() + iconSize.value!!.width +
353 expectedContentLeftPadding.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100354 )
Nader Jawad63153c12020-05-21 14:17:08 -0700355 assertThat(textBaseline.value!!).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700356 expectedTextBaseline.toIntPx().toFloat()
Nader Jawad63153c12020-05-21 14:17:08 -0700357 )
Filip Pavlis2b161e42019-11-22 17:40:08 +0000358 assertThat(secondaryTextPosition.value!!.x).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700359 expectedLeftPadding.toIntPx().toFloat() +
360 iconSize.value!!.width +
361 expectedContentLeftPadding.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100362 )
Filip Pavlis2b161e42019-11-22 17:40:08 +0000363 assertThat(secondaryTextBaseline.value!!).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700364 expectedTextBaseline.toIntPx().toFloat() +
365 expectedSecondaryTextBaselineOffset.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100366 )
Nader Jawade6a9b332020-05-21 13:49:20 -0700367 assertThat(iconPosition.value!!.x).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700368 expectedLeftPadding.toIntPx().toFloat()
Nader Jawade6a9b332020-05-21 13:49:20 -0700369 )
Filip Pavlis2b161e42019-11-22 17:40:08 +0000370 assertThat(iconPosition.value!!.y).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700371 expectedIconTopPadding.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100372 )
373 }
374 }
375
376 @Test
377 fun listItem_twoLine_positioning_withLargeIcon() {
378 val listItemHeight = 72.dp
379 val expectedLeftPadding = 16.dp
380 val expectedIconTopPadding = 16.dp
381 val expectedContentLeftPadding = 16.dp
382 val expectedTextBaseline = 32.dp
383 val expectedSecondaryTextBaselineOffset = 20.dp
384 val expectedRightPadding = 16.dp
385
Nader Jawad6df06122020-06-03 15:27:08 -0700386 val textPosition = Ref<Offset>()
Nader Jawade6a9b332020-05-21 13:49:20 -0700387 val textBaseline = Ref<Float>()
George Mount8f237572020-04-30 12:08:30 -0700388 val textSize = Ref<IntSize>()
Nader Jawad6df06122020-06-03 15:27:08 -0700389 val secondaryTextPosition = Ref<Offset>()
Nader Jawade6a9b332020-05-21 13:49:20 -0700390 val secondaryTextBaseline = Ref<Float>()
George Mount8f237572020-04-30 12:08:30 -0700391 val secondaryTextSize = Ref<IntSize>()
Nader Jawad6df06122020-06-03 15:27:08 -0700392 val iconPosition = Ref<Offset>()
George Mount8f237572020-04-30 12:08:30 -0700393 val iconSize = Ref<IntSize>()
Nader Jawad6df06122020-06-03 15:27:08 -0700394 val trailingPosition = Ref<Offset>()
George Mount8f237572020-04-30 12:08:30 -0700395 val trailingSize = Ref<IntSize>()
Mihai Popa746e2302019-09-30 17:31:56 +0100396 composeTestRule.setMaterialContent {
Matvei Malkov201726d2020-03-13 14:03:54 +0000397 Box {
Mihai Popa746e2302019-09-30 17:31:56 +0100398 ListItem(
399 text = {
George Mountbfa1fb22020-03-11 09:35:05 -0700400 Text("Primary text", saveLayout(textPosition, textSize, textBaseline))
Mihai Popa746e2302019-09-30 17:31:56 +0100401 },
402 secondaryText = {
George Mountbfa1fb22020-03-11 09:35:05 -0700403 Text(
404 "Secondary text",
405 saveLayout(
406 secondaryTextPosition,
407 secondaryTextSize,
408 secondaryTextBaseline
409 )
410 )
Mihai Popa746e2302019-09-30 17:31:56 +0100411 },
412 icon = {
George Mountbfa1fb22020-03-11 09:35:05 -0700413 Image(icon40x40, saveLayout(iconPosition, iconSize))
Mihai Popa746e2302019-09-30 17:31:56 +0100414 },
415 trailing = {
George Mountbfa1fb22020-03-11 09:35:05 -0700416 Image(icon24x24, saveLayout(trailingPosition, trailingSize))
Mihai Popa746e2302019-09-30 17:31:56 +0100417 }
418 )
419 }
420 }
Filip Pavlisa4d73a52020-07-14 11:30:00 +0100421 composeTestRule.runOnIdleWithDensity {
Filip Pavlis2b161e42019-11-22 17:40:08 +0000422 assertThat(textPosition.value!!.x).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700423 expectedLeftPadding.toIntPx().toFloat() + iconSize.value!!.width +
424 expectedContentLeftPadding.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100425 )
Nader Jawad63153c12020-05-21 14:17:08 -0700426 assertThat(textBaseline.value!!).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700427 expectedTextBaseline.toIntPx().toFloat()
Nader Jawad63153c12020-05-21 14:17:08 -0700428 )
Filip Pavlis2b161e42019-11-22 17:40:08 +0000429 assertThat(secondaryTextPosition.value!!.x).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700430 expectedLeftPadding.toIntPx().toFloat() +
431 iconSize.value!!.width +
432 expectedContentLeftPadding.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100433 )
Filip Pavlis2b161e42019-11-22 17:40:08 +0000434 assertThat(secondaryTextBaseline.value!!).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700435 expectedTextBaseline.toIntPx().toFloat() +
436 expectedSecondaryTextBaselineOffset.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100437 )
Nader Jawad63153c12020-05-21 14:17:08 -0700438 assertThat(iconPosition.value!!.x).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700439 expectedLeftPadding.toIntPx().toFloat()
Nader Jawad63153c12020-05-21 14:17:08 -0700440 )
Filip Pavlis2b161e42019-11-22 17:40:08 +0000441 assertThat(iconPosition.value!!.y).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700442 expectedIconTopPadding.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100443 )
444 val dm = composeTestRule.displayMetrics
Filip Pavlis2b161e42019-11-22 17:40:08 +0000445 assertThat(trailingPosition.value!!.x).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700446 dm.widthPixels - trailingSize.value!!.width -
447 expectedRightPadding.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100448 )
Filip Pavlis2b161e42019-11-22 17:40:08 +0000449 assertThat(trailingPosition.value!!.y).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700450 ((listItemHeight.toIntPx() - trailingSize.value!!.height) / 2).toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100451 )
452 }
453 }
454
455 @Test
456 fun listItem_threeLine_positioning_noOverline_metaText() {
457 val expectedLeftPadding = 16.dp
458 val expectedIconTopPadding = 16.dp
459 val expectedContentLeftPadding = 32.dp
460 val expectedTextBaseline = 28.dp
461 val expectedSecondaryTextBaselineOffset = 20.dp
462 val expectedRightPadding = 16.dp
463
Nader Jawad6df06122020-06-03 15:27:08 -0700464 val textPosition = Ref<Offset>()
Nader Jawade6a9b332020-05-21 13:49:20 -0700465 val textBaseline = Ref<Float>()
George Mount8f237572020-04-30 12:08:30 -0700466 val textSize = Ref<IntSize>()
Nader Jawad6df06122020-06-03 15:27:08 -0700467 val secondaryTextPosition = Ref<Offset>()
Nader Jawade6a9b332020-05-21 13:49:20 -0700468 val secondaryTextBaseline = Ref<Float>()
George Mount8f237572020-04-30 12:08:30 -0700469 val secondaryTextSize = Ref<IntSize>()
Nader Jawad6df06122020-06-03 15:27:08 -0700470 val iconPosition = Ref<Offset>()
George Mount8f237572020-04-30 12:08:30 -0700471 val iconSize = Ref<IntSize>()
Nader Jawad6df06122020-06-03 15:27:08 -0700472 val trailingPosition = Ref<Offset>()
George Mount8f237572020-04-30 12:08:30 -0700473 val trailingSize = Ref<IntSize>()
Mihai Popa746e2302019-09-30 17:31:56 +0100474 composeTestRule.setMaterialContent {
Matvei Malkov201726d2020-03-13 14:03:54 +0000475 Box {
Mihai Popa746e2302019-09-30 17:31:56 +0100476 ListItem(
477 text = {
George Mountbfa1fb22020-03-11 09:35:05 -0700478 Text("Primary text", saveLayout(textPosition, textSize, textBaseline))
Mihai Popa746e2302019-09-30 17:31:56 +0100479 },
480 secondaryText = {
George Mountbfa1fb22020-03-11 09:35:05 -0700481 Text(
482 "Secondary text",
483 saveLayout(
484 secondaryTextPosition,
485 secondaryTextSize,
486 secondaryTextBaseline
487 )
488 )
Mihai Popa746e2302019-09-30 17:31:56 +0100489 },
490 singleLineSecondaryText = false,
491 icon = {
George Mountbfa1fb22020-03-11 09:35:05 -0700492 Image(icon24x24, saveLayout(iconPosition, iconSize))
Mihai Popa746e2302019-09-30 17:31:56 +0100493 },
494 trailing = {
George Mountbfa1fb22020-03-11 09:35:05 -0700495 Image(icon24x24, saveLayout(trailingPosition, trailingSize))
Mihai Popa746e2302019-09-30 17:31:56 +0100496 }
497 )
498 }
499 }
Filip Pavlisa4d73a52020-07-14 11:30:00 +0100500 composeTestRule.runOnIdleWithDensity {
Filip Pavlis2b161e42019-11-22 17:40:08 +0000501 assertThat(textPosition.value!!.x).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700502 expectedLeftPadding.toIntPx().toFloat() + iconSize.value!!.width +
503 expectedContentLeftPadding.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100504 )
Nader Jawad63153c12020-05-21 14:17:08 -0700505 assertThat(textBaseline.value!!).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700506 expectedTextBaseline.toIntPx().toFloat()
Nader Jawad63153c12020-05-21 14:17:08 -0700507 )
Filip Pavlis2b161e42019-11-22 17:40:08 +0000508 assertThat(secondaryTextPosition.value!!.x).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700509 expectedLeftPadding.toIntPx().toFloat() + iconSize.value!!.width +
510 expectedContentLeftPadding.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100511 )
Filip Pavlis2b161e42019-11-22 17:40:08 +0000512 assertThat(secondaryTextBaseline.value!!).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700513 expectedTextBaseline.toIntPx().toFloat() +
514 expectedSecondaryTextBaselineOffset.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100515 )
George Mount8f237572020-04-30 12:08:30 -0700516 assertThat(iconPosition.value!!.x).isEqualTo(expectedLeftPadding.toIntPx().toFloat())
Filip Pavlis2b161e42019-11-22 17:40:08 +0000517 assertThat(iconPosition.value!!.y).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700518 expectedIconTopPadding.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100519 )
520 val dm = composeTestRule.displayMetrics
Filip Pavlis2b161e42019-11-22 17:40:08 +0000521 assertThat(trailingPosition.value!!.x).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700522 dm.widthPixels - trailingSize.value!!.width.toFloat() -
523 expectedRightPadding.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100524 )
Filip Pavlis2b161e42019-11-22 17:40:08 +0000525 assertThat(trailingPosition.value!!.y).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700526 expectedIconTopPadding.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100527 )
528 }
529 }
530
531 @Test
532 fun listItem_threeLine_positioning_overline_trailingIcon() {
533 val expectedLeftPadding = 16.dp
534 val expectedIconTopPadding = 16.dp
535 val expectedContentLeftPadding = 16.dp
536 val expectedOverlineBaseline = 28.dp
537 val expectedTextBaselineOffset = 20.dp
538 val expectedSecondaryTextBaselineOffset = 20.dp
539 val expectedRightPadding = 16.dp
540
Nader Jawad6df06122020-06-03 15:27:08 -0700541 val textPosition = Ref<Offset>()
Nader Jawade6a9b332020-05-21 13:49:20 -0700542 val textBaseline = Ref<Float>()
George Mount8f237572020-04-30 12:08:30 -0700543 val textSize = Ref<IntSize>()
Nader Jawad6df06122020-06-03 15:27:08 -0700544 val overlineTextPosition = Ref<Offset>()
Nader Jawade6a9b332020-05-21 13:49:20 -0700545 val overlineTextBaseline = Ref<Float>()
George Mount8f237572020-04-30 12:08:30 -0700546 val overlineTextSize = Ref<IntSize>()
Nader Jawad6df06122020-06-03 15:27:08 -0700547 val secondaryTextPosition = Ref<Offset>()
Nader Jawade6a9b332020-05-21 13:49:20 -0700548 val secondaryTextBaseline = Ref<Float>()
George Mount8f237572020-04-30 12:08:30 -0700549 val secondaryTextSize = Ref<IntSize>()
Nader Jawad6df06122020-06-03 15:27:08 -0700550 val iconPosition = Ref<Offset>()
George Mount8f237572020-04-30 12:08:30 -0700551 val iconSize = Ref<IntSize>()
Nader Jawad6df06122020-06-03 15:27:08 -0700552 val trailingPosition = Ref<Offset>()
George Mount8f237572020-04-30 12:08:30 -0700553 val trailingSize = Ref<IntSize>()
Nader Jawade6a9b332020-05-21 13:49:20 -0700554 val trailingBaseline = Ref<Float>()
Mihai Popa746e2302019-09-30 17:31:56 +0100555 composeTestRule.setMaterialContent {
Matvei Malkov201726d2020-03-13 14:03:54 +0000556 Box {
Mihai Popa746e2302019-09-30 17:31:56 +0100557 ListItem(
558 overlineText = {
George Mountbfa1fb22020-03-11 09:35:05 -0700559 Text(
560 "OVERLINE",
561 saveLayout(
562 overlineTextPosition,
563 overlineTextSize,
564 overlineTextBaseline
565 )
566 )
Mihai Popa746e2302019-09-30 17:31:56 +0100567 },
568 text = {
George Mountbfa1fb22020-03-11 09:35:05 -0700569 Text("Primary text", saveLayout(textPosition, textSize, textBaseline))
Mihai Popa746e2302019-09-30 17:31:56 +0100570 },
571 secondaryText = {
George Mountbfa1fb22020-03-11 09:35:05 -0700572 Text(
573 "Secondary text",
574 saveLayout(
575 secondaryTextPosition,
576 secondaryTextSize,
577 secondaryTextBaseline
578 )
579 )
Mihai Popa746e2302019-09-30 17:31:56 +0100580 },
581 icon = {
George Mountbfa1fb22020-03-11 09:35:05 -0700582 Image(
583 icon40x40,
584 saveLayout(iconPosition, iconSize)
585 )
Mihai Popa746e2302019-09-30 17:31:56 +0100586 },
587 trailing = {
George Mountbfa1fb22020-03-11 09:35:05 -0700588 Text(
589 "meta",
590 saveLayout(
591 trailingPosition,
592 trailingSize,
593 trailingBaseline
594 )
595 )
Mihai Popa746e2302019-09-30 17:31:56 +0100596 }
597 )
598 }
599 }
Filip Pavlisa4d73a52020-07-14 11:30:00 +0100600 composeTestRule.runOnIdleWithDensity {
Filip Pavlis2b161e42019-11-22 17:40:08 +0000601 assertThat(textPosition.value!!.x).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700602 expectedLeftPadding.toIntPx().toFloat() +
603 iconSize.value!!.width +
604 expectedContentLeftPadding.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100605 )
Filip Pavlis2b161e42019-11-22 17:40:08 +0000606 assertThat(textBaseline.value!!).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700607 expectedOverlineBaseline.toIntPx().toFloat() +
608 expectedTextBaselineOffset.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100609 )
Filip Pavlis2b161e42019-11-22 17:40:08 +0000610 assertThat(overlineTextPosition.value!!.x).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700611 expectedLeftPadding.toIntPx().toFloat() +
612 iconSize.value!!.width +
613 expectedContentLeftPadding.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100614 )
Filip Pavlis2b161e42019-11-22 17:40:08 +0000615 assertThat(overlineTextBaseline.value!!).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700616 expectedOverlineBaseline.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100617 )
Filip Pavlis2b161e42019-11-22 17:40:08 +0000618 assertThat(secondaryTextPosition.value!!.x).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700619 expectedLeftPadding.toIntPx().toFloat() +
620 iconSize.value!!.width +
621 expectedContentLeftPadding.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100622 )
Filip Pavlis2b161e42019-11-22 17:40:08 +0000623 assertThat(secondaryTextBaseline.value!!).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700624 expectedOverlineBaseline.toIntPx().toFloat() +
625 expectedTextBaselineOffset.toIntPx().toFloat() +
626 expectedSecondaryTextBaselineOffset.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100627 )
Nader Jawad63153c12020-05-21 14:17:08 -0700628 assertThat(iconPosition.value!!.x).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700629 expectedLeftPadding.toIntPx().toFloat()
Nader Jawad63153c12020-05-21 14:17:08 -0700630 )
Filip Pavlis2b161e42019-11-22 17:40:08 +0000631 assertThat(iconPosition.value!!.y).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700632 expectedIconTopPadding.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100633 )
634 val dm = composeTestRule.displayMetrics
Filip Pavlis2b161e42019-11-22 17:40:08 +0000635 assertThat(trailingPosition.value!!.x).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700636 dm.widthPixels - trailingSize.value!!.width -
637 expectedRightPadding.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100638 )
Filip Pavlis2b161e42019-11-22 17:40:08 +0000639 assertThat(trailingBaseline.value!!).isEqualTo(
George Mount8f237572020-04-30 12:08:30 -0700640 expectedOverlineBaseline.toIntPx().toFloat()
Mihai Popa746e2302019-09-30 17:31:56 +0100641 )
642 }
643 }
644
645 private fun Dp.toIntPx() = (this.value * composeTestRule.density.density).roundToInt()
646
George Mountbfa1fb22020-03-11 09:35:05 -0700647 private fun saveLayout(
Nader Jawad6df06122020-06-03 15:27:08 -0700648 coords: Ref<Offset>,
George Mount8f237572020-04-30 12:08:30 -0700649 size: Ref<IntSize>,
Nader Jawade6a9b332020-05-21 13:49:20 -0700650 baseline: Ref<Float> = Ref()
Adam Powell999a89b2020-03-11 09:08:07 -0700651 ): Modifier = Modifier.onPositioned { coordinates: LayoutCoordinates ->
Filip Pavlis028c0d52020-06-29 15:07:53 +0100652 coords.value = coordinates.localToRoot(Offset.Zero)
Mihai Popa08c47952020-06-04 20:01:27 +0100653 baseline.value = coordinates[FirstBaseline].toFloat() + coords.value!!.y
George Mountbfa1fb22020-03-11 09:35:05 -0700654 size.value = coordinates.size
Mihai Popa746e2302019-09-30 17:31:56 +0100655 }
656}