[go: nahoru, domu]

blob: 4e3fc36eb381c35fbf25bd3b0788b0dff3b6f820 [file] [log] [blame]
Cătălin Tudor37adfc72019-09-04 17:58:58 +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.test
18
Jelle Fresen891799c2020-05-12 10:30:34 +010019import android.view.View
20import android.view.ViewGroup
21import android.widget.FrameLayout
22import androidx.activity.ComponentActivity
Cătălin Tudor37adfc72019-09-04 17:58:58 +010023import androidx.compose.Composable
Jelle Fresen891799c2020-05-12 10:30:34 +010024import androidx.compose.Recomposer
Jelle Fresenb4c281a2020-05-11 15:15:43 +010025import androidx.compose.getValue
26import androidx.compose.mutableStateOf
27import androidx.compose.setValue
Jelle Fresen891799c2020-05-12 10:30:34 +010028import androidx.test.espresso.Espresso.onView
29import androidx.test.espresso.ViewInteraction
30import androidx.test.espresso.assertion.ViewAssertions.matches
31import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
32import androidx.test.espresso.matcher.ViewMatchers.withId
33import androidx.test.espresso.matcher.ViewMatchers.withParent
Filip Pavlis607cc412020-06-11 21:56:49 +010034import androidx.test.ext.junit.rules.ActivityScenarioRule
Cătălin Tudor37adfc72019-09-04 17:58:58 +010035import androidx.test.filters.MediumTest
36import androidx.ui.core.Layout
Adam Powell999a89b2020-03-11 09:08:07 -070037import androidx.ui.core.Modifier
Jelle Fresen891799c2020-05-12 10:30:34 +010038import androidx.ui.core.setContent
Louis Pullen-Freilichddda7be2020-07-17 18:28:12 +010039import androidx.compose.foundation.Box
40import androidx.compose.foundation.ScrollableColumn
Jelle Fresenb4c281a2020-05-11 15:15:43 +010041import androidx.ui.graphics.Color
Louis Pullen-Freilich623e4052020-07-19 20:24:03 +010042import androidx.compose.foundation.layout.Row
43import androidx.compose.foundation.layout.Stack
44import androidx.compose.foundation.layout.fillMaxHeight
45import androidx.compose.foundation.layout.fillMaxWidth
46import androidx.compose.foundation.layout.height
47import androidx.compose.foundation.layout.size
48import androidx.compose.foundation.layout.width
Jelle Fresen891799c2020-05-12 10:30:34 +010049import androidx.ui.test.android.AndroidComposeTestRule
Jelle Fresenb4c281a2020-05-11 15:15:43 +010050import androidx.ui.test.util.BoundaryNode
51import androidx.ui.unit.Dp
George Mount842c8c12020-01-08 16:03:42 -080052import androidx.ui.unit.dp
Jelle Fresen891799c2020-05-12 10:30:34 +010053import org.hamcrest.CoreMatchers.allOf
54import org.hamcrest.CoreMatchers.not
George Mount842c8c12020-01-08 16:03:42 -080055import org.junit.Rule
56import org.junit.Test
57import org.junit.runner.RunWith
Filip Pavlised382ac2020-06-04 17:10:14 +010058import org.junit.runners.Parameterized
Cătălin Tudor37adfc72019-09-04 17:58:58 +010059
60@MediumTest
Filip Pavlised382ac2020-06-04 17:10:14 +010061@RunWith(Parameterized::class)
62class IsDisplayedTest(val config: BitmapCapturingTest.TestConfig) {
63 data class TestConfig(
64 val activityClass: Class<out ComponentActivity>
65 )
Cătălin Tudor37adfc72019-09-04 17:58:58 +010066
Filip Pavlised382ac2020-06-04 17:10:14 +010067 companion object {
68 @JvmStatic
69 @Parameterized.Parameters(name = "{0}")
70 fun createTestSet(): List<BitmapCapturingTest.TestConfig> = listOf(
71 BitmapCapturingTest.TestConfig(ComponentActivity::class.java),
72 BitmapCapturingTest.TestConfig(ActivityWithActionBar::class.java)
73 )
74 }
75
Cătălin Tudor37adfc72019-09-04 17:58:58 +010076 @get:Rule
Filip Pavlised382ac2020-06-04 17:10:14 +010077 val composeTestRule = AndroidComposeTestRule(
Filip Pavlis607cc412020-06-11 21:56:49 +010078 ActivityScenarioRule(config.activityClass)
79 )
Cătălin Tudor37adfc72019-09-04 17:58:58 +010080
Jelle Fresenb4c281a2020-05-11 15:15:43 +010081 private val colors = listOf(Color.Red, Color.Green, Color.Blue)
82
83 @Composable
84 private fun Item(i: Int, width: Dp? = null, height: Dp? = null) {
85 BoundaryNode("item$i") {
86 Box(
87 modifier = with(Modifier) { width?.let { width(it) } ?: fillMaxWidth() } +
88 with(Modifier) { height?.let { height(it) } ?: fillMaxHeight() },
89 backgroundColor = colors[i % colors.size]
90 )
91 }
92 }
93
Jelle Fresend4bca952020-05-11 15:51:02 +010094 @Composable
95 fun PlaceConditionally(place: Boolean, child: @Composable () -> Unit) {
Anastasia Soboleva5e382dd2020-06-17 21:51:38 +010096 Layout(children = child) { measurables, constraints ->
Jelle Fresend4bca952020-05-11 15:51:02 +010097 if (place) {
98 val placeable = measurables[0].measure(constraints)
99 layout(placeable.width, placeable.height) {
George Mount8f237572020-04-30 12:08:30 -0700100 placeable.place(0, 0)
Jelle Fresend4bca952020-05-11 15:51:02 +0100101 }
102 } else {
George Mount8f237572020-04-30 12:08:30 -0700103 layout(0, 0) {}
Jelle Fresend4bca952020-05-11 15:51:02 +0100104 }
105 }
106 }
107
Cătălin Tudor37adfc72019-09-04 17:58:58 +0100108 @Test
109 fun componentInScrollable_isDisplayed() {
Jelle Fresenb4c281a2020-05-11 15:15:43 +0100110 composeTestRule.setContent {
Matvei Malkov235b4fa2020-07-07 21:14:49 +0100111 ScrollableColumn(modifier = Modifier.size(100.dp)) {
Matvei Malkov9fb69242020-05-19 14:07:14 +0100112 repeat(10) { Item(it, height = 30.dp) }
Jelle Fresenb4c281a2020-05-11 15:15:43 +0100113 }
114 }
Cătălin Tudor37adfc72019-09-04 17:58:58 +0100115
Filip Pavlis659ea722020-07-13 14:14:32 +0100116 onNodeWithTag("item0")
Cătălin Tudor37adfc72019-09-04 17:58:58 +0100117 .assertIsDisplayed()
118 }
119
120 @Test
121 fun componentInScrollable_isNotDisplayed() {
Cătălin Tudor37adfc72019-09-04 17:58:58 +0100122 composeTestRule.setContent {
Matvei Malkov235b4fa2020-07-07 21:14:49 +0100123 ScrollableColumn(modifier = Modifier.size(100.dp)) {
Matvei Malkov9fb69242020-05-19 14:07:14 +0100124 repeat(10) { Item(it, height = 30.dp) }
Cătălin Tudor37adfc72019-09-04 17:58:58 +0100125 }
126 }
Jelle Fresenb4c281a2020-05-11 15:15:43 +0100127
Filip Pavlis659ea722020-07-13 14:14:32 +0100128 onNodeWithTag("item4")
Jelle Fresenb4c281a2020-05-11 15:15:43 +0100129 .assertIsNotDisplayed()
Cătălin Tudor37adfc72019-09-04 17:58:58 +0100130 }
131
132 @Test
Jelle Fresend4bca952020-05-11 15:51:02 +0100133 fun togglePlacement() {
Jelle Fresenb4c281a2020-05-11 15:15:43 +0100134 var place by mutableStateOf(true)
Cătălin Tudor37adfc72019-09-04 17:58:58 +0100135
Cătălin Tudor37adfc72019-09-04 17:58:58 +0100136 composeTestRule.setContent {
Jelle Fresend4bca952020-05-11 15:51:02 +0100137 PlaceConditionally(place) {
138 // Item instead of BoundaryNode because we need non-zero size
139 Item(0)
140 }
141 }
142
Filip Pavlis659ea722020-07-13 14:14:32 +0100143 onNodeWithTag("item0")
Jelle Fresend4bca952020-05-11 15:51:02 +0100144 .assertIsDisplayed()
145
Filip Pavlisa4d73a52020-07-14 11:30:00 +0100146 runOnIdle {
Jelle Fresend4bca952020-05-11 15:51:02 +0100147 place = false
148 }
149
Filip Pavlis659ea722020-07-13 14:14:32 +0100150 onNodeWithTag("item0")
Jelle Fresend4bca952020-05-11 15:51:02 +0100151 .assertIsNotDisplayed()
152 }
153
154 @Test
155 fun toggleParentPlacement() {
156 var place by mutableStateOf(true)
157
158 composeTestRule.setContent {
159 PlaceConditionally(place) {
Anastasia Soboleva22015a62020-03-12 12:48:37 +0000160 Stack {
Jelle Fresenb4c281a2020-05-11 15:15:43 +0100161 // Item instead of BoundaryNode because we need non-zero size
162 Item(0)
163 }
Cătălin Tudor37adfc72019-09-04 17:58:58 +0100164 }
Cătălin Tudor37adfc72019-09-04 17:58:58 +0100165 }
166
Filip Pavlis659ea722020-07-13 14:14:32 +0100167 onNodeWithTag("item0")
Cătălin Tudor37adfc72019-09-04 17:58:58 +0100168 .assertIsDisplayed()
169
Filip Pavlisa4d73a52020-07-14 11:30:00 +0100170 runOnIdle {
Jelle Fresenb4c281a2020-05-11 15:15:43 +0100171 place = false
Cătălin Tudor37adfc72019-09-04 17:58:58 +0100172 }
173
Filip Pavlis659ea722020-07-13 14:14:32 +0100174 onNodeWithTag("item0")
Cătălin Tudor37adfc72019-09-04 17:58:58 +0100175 .assertIsNotDisplayed()
176 }
177
178 @Test
179 fun rowTooSmall() {
180 composeTestRule.setContent {
Jelle Fresenb4c281a2020-05-11 15:15:43 +0100181 Row(modifier = Modifier.size(100.dp)) {
182 repeat(10) { Item(it, width = 30.dp) }
Cătălin Tudor37adfc72019-09-04 17:58:58 +0100183 }
184 }
185
Filip Pavlis659ea722020-07-13 14:14:32 +0100186 onNodeWithTag("item9")
Cătălin Tudor37adfc72019-09-04 17:58:58 +0100187 .assertIsNotDisplayed()
188 }
Jelle Fresen891799c2020-05-12 10:30:34 +0100189
190 @Test
191 fun viewVisibility_androidComposeView() {
Filip Pavlis607cc412020-06-11 21:56:49 +0100192 lateinit var androidComposeView: View
193 composeTestRule.activityRule.scenario.onActivity { activity ->
Jelle Fresen891799c2020-05-12 10:30:34 +0100194 // FrameLayout(id=100, w=100, h=100)
195 // '- AndroidComposeView
Filip Pavlis607cc412020-06-11 21:56:49 +0100196 androidComposeView = FrameLayout(activity).apply {
Jelle Fresen891799c2020-05-12 10:30:34 +0100197 id = 100
198 layoutParams = ViewGroup.MarginLayoutParams(100, 100)
199 activity.setContentView(this)
200 setContent(Recomposer.current()) {
201 Item(0)
202 }
203 }.getChildAt(0)
204 }
205
206 fun onComposeView(): ViewInteraction {
207 return onView(allOf(withParent(withId(100))))
208 }
209
210 onComposeView().check(matches(isDisplayed()))
Filip Pavlis659ea722020-07-13 14:14:32 +0100211 onNodeWithTag("item0").assertIsDisplayed()
Jelle Fresen891799c2020-05-12 10:30:34 +0100212
Filip Pavlisa4d73a52020-07-14 11:30:00 +0100213 runOnIdle {
Jelle Fresen891799c2020-05-12 10:30:34 +0100214 androidComposeView.visibility = View.GONE
215 }
216
217 onComposeView().check(matches(not(isDisplayed())))
Filip Pavlis659ea722020-07-13 14:14:32 +0100218 onNodeWithTag("item0").assertIsNotDisplayed()
Jelle Fresen891799c2020-05-12 10:30:34 +0100219 }
220
221 @Test
222 fun viewVisibility_parentView() {
Filip Pavlis607cc412020-06-11 21:56:49 +0100223 lateinit var composeContainer: View
224 composeTestRule.activityRule.scenario.onActivity { activity ->
Jelle Fresen891799c2020-05-12 10:30:34 +0100225 // FrameLayout
226 // '- FrameLayout(id=100, w=100, h=100) -> composeContainer
227 // '- AndroidComposeView
Filip Pavlis607cc412020-06-11 21:56:49 +0100228 composeContainer = FrameLayout(activity).apply {
Jelle Fresen891799c2020-05-12 10:30:34 +0100229 id = 100
230 layoutParams = ViewGroup.MarginLayoutParams(100, 100)
231 activity.setContentView(FrameLayout(activity).also { it.addView(this) })
232 setContent(Recomposer.current()) {
233 Item(0)
234 }
235 }
236 }
237
238 fun onComposeView(): ViewInteraction {
239 return onView(allOf(withParent(withId(100))))
240 }
241
242 onComposeView().check(matches(isDisplayed()))
Filip Pavlis659ea722020-07-13 14:14:32 +0100243 onNodeWithTag("item0").assertIsDisplayed()
Jelle Fresen891799c2020-05-12 10:30:34 +0100244
Filip Pavlisa4d73a52020-07-14 11:30:00 +0100245 runOnIdle {
Jelle Fresen891799c2020-05-12 10:30:34 +0100246 composeContainer.visibility = View.GONE
247 }
248
249 onComposeView().check(matches(not(isDisplayed())))
Filip Pavlis659ea722020-07-13 14:14:32 +0100250 onNodeWithTag("item0").assertIsNotDisplayed()
Jelle Fresen891799c2020-05-12 10:30:34 +0100251 }
Cătălin Tudor37adfc72019-09-04 17:58:58 +0100252}