I've two Box
es and one Button
. Clicking on the Button
would toggle a flag and it triggers an AnimatedVisibility
animation on these Boxes.
Code
@Composable
fun TestBox() {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
var flag by remember { mutableStateOf(false) }
AnimatedVisibility(
visible = !flag,
enter = slideInHorizontally(animationSpec = tween(3000)) { it },
exit = slideOutHorizontally(animationSpec = tween(3000)) { -it }
) {
// Red box
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.Red)
.testTag("red_box"),
) {}
}
AnimatedVisibility(
visible = flag,
enter = slideInHorizontally(animationSpec = tween(3000)) { it },
exit = slideOutHorizontally(animationSpec = tween(3000)) { -it }
) {
// Red box
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.Green)
.testTag("green_box"),
) {}
}
Button(onClick = { flag = !flag }) {
Text(text = "TOGGLE")
}
}
}
Output
Now I want to write a test to check if two boxes are visible in the middle of the transition. So I wrote a test like this
class BoxAnimationTest {
@get:Rule
val composeRule = createComposeRule()
@Before
fun beforeAll() {
composeRule.setContent {
TestBox()
}
}
@Test
fun firstTest() {
with(composeRule) {
mainClock.autoAdvance = false
onNodeWithTag("red_box").assertExists() // red box visible
onNodeWithTag("green_box").assertDoesNotExist() // green box shouldn't be visible
onNodeWithText("TOGGLE").performClick() // clicking toggle button
mainClock.advanceTimeBy(1500) // and advance time to half of total duration (3000ms)
onNodeWithTag("green_box").assertExists() // now both green and
onNodeWithTag("red_box").assertExists() // [FAILED] red should be visible
mainClock.advanceTimeBy(1500) // finishing the animation
onNodeWithTag("green_box") // now green should be visible
onNodeWithTag("red_box").assertDoesNotExist() // but red shouldn't be
}
}
}
But it fails at onNodeWithTag("red_box").assertExists()
(2nd).
java.lang.AssertionError: Failed: assertExists.
Reason: Expected exactly '1' node but could not find any node that satisfies: (TestTag = 'red_box')
Any idea why?
Some initial investigation showed that the animations from
AnimatedVisibility
were never added to theTransition
, becausemeasure()
was not called and slide animation is initialized during measure. As a result, we ended up having an emptyTransition
that finished right away. That's why the test failed. Note that addingadvanceTimeByFrame()
beforeadvanceTimeBy(1500)
seems to allow the test to pass. This might be useful for narrowing down the cause.
Source - KotlingLang Slack: https://kotlinlang.slack.com/archives/CJLTWPH7S/p1644036648038349?thread_ts=1643956469.612919&cid=CJLTWPH7S
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.