Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 65cfa4d4 authored by Jordan Demeulenaere's avatar Jordan Demeulenaere Committed by Android (Google) Code Review
Browse files

Merge "Add Truth subjects for TransitionState" into main

parents c1a39ae2 c2e53a2f
Loading
Loading
Loading
Loading
+9 −34
Original line number Diff line number Diff line
@@ -32,12 +32,11 @@ import com.android.compose.animation.scene.NestedScrollBehavior.EdgeWithPreview
import com.android.compose.animation.scene.TestScenes.SceneA
import com.android.compose.animation.scene.TestScenes.SceneB
import com.android.compose.animation.scene.TestScenes.SceneC
import com.android.compose.animation.scene.TransitionState.Idle
import com.android.compose.animation.scene.TransitionState.Transition
import com.android.compose.animation.scene.subjects.assertThat
import com.android.compose.test.MonotonicClockTestScope
import com.android.compose.test.runMonotonicClockTest
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertWithMessage
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.launch
@@ -145,10 +144,8 @@ class DraggableHandlerTest {
        }

        fun assertIdle(currentScene: SceneKey) {
            assertThat(transitionState).isInstanceOf(Idle::class.java)
            assertWithMessage("currentScene does not match")
                .that(transitionState.currentScene)
                .isEqualTo(currentScene)
            assertThat(transitionState).isIdle()
            assertThat(transitionState).hasCurrentScene(currentScene)
        }

        fun assertTransition(
@@ -158,34 +155,12 @@ class DraggableHandlerTest {
            progress: Float? = null,
            isUserInputOngoing: Boolean? = null
        ) {
            assertThat(transitionState).isInstanceOf(Transition::class.java)
            val transition = transitionState as Transition

            if (currentScene != null)
                assertWithMessage("currentScene does not match")
                    .that(transition.currentScene)
                    .isEqualTo(currentScene)

            if (fromScene != null)
                assertWithMessage("fromScene does not match")
                    .that(transition.fromScene)
                    .isEqualTo(fromScene)

            if (toScene != null)
                assertWithMessage("toScene does not match")
                    .that(transition.toScene)
                    .isEqualTo(toScene)

            if (progress != null)
                assertWithMessage("progress does not match")
                    .that(transition.progress)
                    .isWithin(0f) // returns true when comparing 0.0f with -0.0f
                    .of(progress)

            if (isUserInputOngoing != null)
                assertWithMessage("isUserInputOngoing does not match")
                    .that(transition.isUserInputOngoing)
                    .isEqualTo(isUserInputOngoing)
            val transition = assertThat(transitionState).isTransition()
            currentScene?.let { assertThat(transition).hasCurrentScene(it) }
            fromScene?.let { assertThat(transition).hasFromScene(it) }
            toScene?.let { assertThat(transition).hasToScene(it) }
            progress?.let { assertThat(transition).hasProgress(it) }
            isUserInputOngoing?.let { assertThat(transition).hasIsUserInputOngoing(it) }
        }

        fun onDragStarted(
+31 −40
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@ import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.tween
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.rememberScrollableState
import androidx.compose.foundation.gestures.scrollable
@@ -43,7 +42,6 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.layout.approachLayout
@@ -64,6 +62,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.compose.animation.scene.TestScenes.SceneA
import com.android.compose.animation.scene.TestScenes.SceneB
import com.android.compose.animation.scene.TestScenes.SceneC
import com.android.compose.animation.scene.subjects.assertThat
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
@@ -78,7 +77,6 @@ class ElementTest {
    @get:Rule val rule = createComposeRule()

    @Composable
    @OptIn(ExperimentalComposeUiApi::class)
    private fun SceneScope.Element(
        key: ElementKey,
        size: Dp,
@@ -496,7 +494,6 @@ class ElementTest {
    }

    @Test
    @OptIn(ExperimentalFoundationApi::class)
    fun elementModifierNodeIsRecycledInLazyLayouts() = runTest {
        val nPages = 2
        val pagerState = PagerState(currentPage = 0) { nPages }
@@ -654,8 +651,7 @@ class ElementTest {
            }
        }

        assertThat(state.currentTransition).isNull()
        assertThat(state.currentTransition?.currentOverscrollSpec).isNull()
        assertThat(state.transitionState).isIdle()

        // Swipe by half of verticalSwipeDistance.
        rule.onRoot().performTouchInput {
@@ -691,9 +687,9 @@ class ElementTest {

        val fooElement = rule.onNodeWithTag(TestElements.Foo.testTag, useUnmergedTree = true)
        fooElement.assertTopPositionInRootIsEqualTo(0.dp)
        val transition = state.currentTransition
        val transition = assertThat(state.transitionState).isTransition()
        assertThat(transition).isNotNull()
        assertThat(transition!!.progress).isEqualTo(0.5f)
        assertThat(transition).hasProgress(0.5f)
        assertThat(animatedFloat).isEqualTo(50f)

        rule.onRoot().performTouchInput {
@@ -702,8 +698,8 @@ class ElementTest {
        }

        // Scroll 150% (Scene B overscroll by 50%)
        assertThat(transition.progress).isEqualTo(1.5f)
        assertThat(state.currentTransition?.currentOverscrollSpec).isNotNull()
        assertThat(transition).hasProgress(1.5f)
        assertThat(transition).hasOverscrollSpec()
        fooElement.assertTopPositionInRootIsEqualTo(overscrollTranslateY * 0.5f)
        // animatedFloat cannot overflow (canOverflow = false)
        assertThat(animatedFloat).isEqualTo(100f)
@@ -714,8 +710,8 @@ class ElementTest {
        }

        // Scroll 250% (Scene B overscroll by 150%)
        assertThat(transition.progress).isEqualTo(2.5f)
        assertThat(state.currentTransition?.currentOverscrollSpec).isNotNull()
        assertThat(transition).hasProgress(2.5f)
        assertThat(transition).hasOverscrollSpec()
        fooElement.assertTopPositionInRootIsEqualTo(overscrollTranslateY * 1.5f)
        assertThat(animatedFloat).isEqualTo(100f)
    }
@@ -766,8 +762,7 @@ class ElementTest {
            }
        }

        assertThat(state.currentTransition).isNull()
        assertThat(state.currentTransition?.currentOverscrollSpec).isNull()
        assertThat(state.transitionState).isIdle()
        val fooElement = rule.onNodeWithTag(TestElements.Foo.testTag, useUnmergedTree = true)
        fooElement.assertTopPositionInRootIsEqualTo(0.dp)

@@ -779,10 +774,9 @@ class ElementTest {
            moveBy(Offset(0f, touchSlop + layoutHeight.toPx() * 0.5f), delayMillis = 1_000)
        }

        val transition = state.currentTransition
        assertThat(state.currentTransition?.currentOverscrollSpec).isNotNull()
        assertThat(transition).isNotNull()
        assertThat(transition!!.progress).isEqualTo(-0.5f)
        val transition = assertThat(state.transitionState).isTransition()
        assertThat(transition).hasOverscrollSpec()
        assertThat(transition).hasProgress(-0.5f)
        fooElement.assertTopPositionInRootIsEqualTo(overscrollTranslateY * 0.5f)

        rule.onRoot().performTouchInput {
@@ -791,8 +785,8 @@ class ElementTest {
        }

        // Scroll 150% (Scene B overscroll by 50%)
        assertThat(transition.progress).isEqualTo(-1.5f)
        assertThat(state.currentTransition?.currentOverscrollSpec).isNotNull()
        assertThat(transition).hasProgress(-1.5f)
        assertThat(transition).hasOverscrollSpec()
        fooElement.assertTopPositionInRootIsEqualTo(overscrollTranslateY * 1.5f)
    }

@@ -825,13 +819,12 @@ class ElementTest {
            moveBy(Offset(0f, layoutHeight.toPx() * 0.5f), delayMillis = 1_000)
        }

        val transition = state.currentTransition
        assertThat(transition).isNotNull()
        val transition = assertThat(state.transitionState).isTransition()
        assertThat(animatedFloat).isEqualTo(100f)

        // Scroll 150% (100% scroll + 50% overscroll)
        assertThat(transition!!.progress).isEqualTo(1.5f)
        assertThat(state.currentTransition?.currentOverscrollSpec).isNotNull()
        assertThat(transition).hasProgress(1.5f)
        assertThat(transition).hasOverscrollSpec()
        fooElement.assertTopPositionInRootIsEqualTo(layoutHeight * 0.5f)
        assertThat(animatedFloat).isEqualTo(100f)

@@ -841,8 +834,8 @@ class ElementTest {
        }

        // Scroll 250% (100% scroll + 150% overscroll)
        assertThat(transition.progress).isEqualTo(2.5f)
        assertThat(state.currentTransition?.currentOverscrollSpec).isNotNull()
        assertThat(transition).hasProgress(2.5f)
        assertThat(transition).hasOverscrollSpec()
        fooElement.assertTopPositionInRootIsEqualTo(layoutHeight * 1.5f)
        assertThat(animatedFloat).isEqualTo(100f)
    }
@@ -882,13 +875,11 @@ class ElementTest {
            moveBy(Offset(0f, layoutHeight.toPx() * 0.5f), delayMillis = 1_000)
        }

        val transition = state.currentTransition
        assertThat(transition).isNotNull()
        transition as TransitionState.HasOverscrollProperties
        val transition = assertThat(state.transitionState).isTransition()

        // Scroll 150% (100% scroll + 50% overscroll)
        assertThat(transition.progress).isEqualTo(1.5f)
        assertThat(state.currentTransition?.currentOverscrollSpec).isNotNull()
        assertThat(transition).hasProgress(1.5f)
        assertThat(transition).hasOverscrollSpec()
        fooElement.assertTopPositionInRootIsEqualTo(layoutHeight * (transition.progress - 1f))
        assertThat(animatedFloat).isEqualTo(100f)

@@ -900,8 +891,8 @@ class ElementTest {
        rule.waitUntil(timeoutMillis = 10_000) { transition.progress < 1f }

        assertThat(transition.progress).isLessThan(1f)
        assertThat(state.currentTransition?.currentOverscrollSpec).isNotNull()
        assertThat(transition.bouncingScene).isEqualTo(transition.toScene)
        assertThat(transition).hasOverscrollSpec()
        assertThat(transition).hasBouncingScene(transition.toScene)
        assertThat(animatedFloat).isEqualTo(100f)
    }

@@ -980,13 +971,13 @@ class ElementTest {

        val transitions = state.currentTransitions
        assertThat(transitions).hasSize(2)
        assertThat(transitions[0].fromScene).isEqualTo(SceneA)
        assertThat(transitions[0].toScene).isEqualTo(SceneB)
        assertThat(transitions[0].progress).isEqualTo(0f)
        assertThat(transitions[0]).hasFromScene(SceneA)
        assertThat(transitions[0]).hasToScene(SceneB)
        assertThat(transitions[0]).hasProgress(0f)

        assertThat(transitions[1].fromScene).isEqualTo(SceneB)
        assertThat(transitions[1].toScene).isEqualTo(SceneC)
        assertThat(transitions[1].progress).isEqualTo(0f)
        assertThat(transitions[1]).hasFromScene(SceneB)
        assertThat(transitions[1]).hasToScene(SceneC)
        assertThat(transitions[1]).hasProgress(0f)

        // First frame: both are at x = 0dp. For the whole transition, Foo is at y = 0dp and Bar is
        // at y = layoutSize - elementSoze = 100dp.
@@ -1153,7 +1144,7 @@ class ElementTest {
        state.finishTransition(aToB, SceneB)
        state.finishTransition(bToC, SceneC)
        rule.waitForIdle()
        assertThat(state.currentTransition).isNull()
        assertThat(state.transitionState).isIdle()

        // The interruption values should be unspecified and deltas should be set to zero.
        val foo = layoutImpl.elements.getValue(TestElements.Foo)
+9 −8
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.compose.animation.scene.TestScenes.SceneA
import com.android.compose.animation.scene.TestScenes.SceneB
import com.android.compose.animation.scene.TestScenes.SceneC
import com.android.compose.animation.scene.subjects.assertThat
import com.android.compose.test.runMonotonicClockTest
import com.google.common.truth.Correspondence
import com.google.common.truth.Truth.assertThat
@@ -165,10 +166,10 @@ class InterruptionHandlerTest {
        // pair, and its velocity is used when animating the progress back to 0.
        val bToA = checkNotNull(state.setTargetScene(SceneA, coroutineScope = this))
        testScheduler.runCurrent()
        assertThat(bToA.fromScene).isEqualTo(SceneA)
        assertThat(bToA.toScene).isEqualTo(SceneB)
        assertThat(bToA.currentScene).isEqualTo(SceneA)
        assertThat(bToA.progressVelocity).isEqualTo(progressVelocity)
        assertThat(bToA).hasFromScene(SceneA)
        assertThat(bToA).hasToScene(SceneB)
        assertThat(bToA).hasCurrentScene(SceneA)
        assertThat(bToA).hasProgressVelocity(progressVelocity)
    }

    @Test
@@ -191,10 +192,10 @@ class InterruptionHandlerTest {
        // and its velocity is used when animating the progress to 1.
        val bToA = checkNotNull(state.setTargetScene(SceneB, coroutineScope = this))
        testScheduler.runCurrent()
        assertThat(bToA.fromScene).isEqualTo(SceneA)
        assertThat(bToA.toScene).isEqualTo(SceneB)
        assertThat(bToA.currentScene).isEqualTo(SceneB)
        assertThat(bToA.progressVelocity).isEqualTo(progressVelocity)
        assertThat(bToA).hasFromScene(SceneA)
        assertThat(bToA).hasToScene(SceneB)
        assertThat(bToA).hasCurrentScene(SceneB)
        assertThat(bToA).hasProgressVelocity(progressVelocity)
    }

    companion object {
+3 −2
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.unit.dp
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.compose.animation.scene.subjects.assertThat
import com.android.compose.test.assertSizeIsEqualTo
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
@@ -157,8 +158,8 @@ class MovableElementTest {
                            fromSceneZIndex: Float,
                            toSceneZIndex: Float
                        ): SceneKey {
                            assertThat(transition.fromScene).isEqualTo(TestScenes.SceneA)
                            assertThat(transition.toScene).isEqualTo(TestScenes.SceneB)
                            assertThat(transition).hasFromScene(TestScenes.SceneA)
                            assertThat(transition).hasToScene(TestScenes.SceneB)
                            assertThat(fromSceneZIndex).isEqualTo(0)
                            assertThat(toSceneZIndex).isEqualTo(1)

+25 −19
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import com.android.compose.animation.scene.TestScenes.SceneA
import com.android.compose.animation.scene.TestScenes.SceneB
import com.android.compose.animation.scene.TestScenes.SceneC
import com.android.compose.animation.scene.TestScenes.SceneD
import com.android.compose.animation.scene.subjects.assertThat
import com.android.compose.animation.scene.transition.link.StateLink
import com.android.compose.test.runMonotonicClockTest
import com.google.common.truth.Truth.assertThat
@@ -322,8 +323,8 @@ class SceneTransitionLayoutStateTest {
        // Go back to A.
        state.setTargetScene(SceneA, coroutineScope = this)
        testScheduler.advanceUntilIdle()
        assertThat(state.currentTransition).isNull()
        assertThat(state.transitionState.currentScene).isEqualTo(SceneA)
        assertThat(state.transitionState).isIdle()
        assertThat(state.transitionState).hasCurrentScene(SceneA)

        // Specific transition from A to B.
        assertThat(
@@ -477,23 +478,24 @@ class SceneTransitionLayoutStateTest {
                        overscroll(SceneB, Orientation.Vertical) { fade(TestElements.Foo) }
                    }
            )
        assertThat(state.currentTransition?.currentOverscrollSpec).isNull()
        val transition = assertThat(state.transitionState).isTransition()
        assertThat(transition).hasNoOverscrollSpec()

        // overscroll for SceneA is NOT defined
        progress.value = -0.1f
        assertThat(state.currentTransition?.currentOverscrollSpec).isNull()
        assertThat(transition).hasNoOverscrollSpec()

        // scroll from SceneA to SceneB
        progress.value = 0.5f
        assertThat(state.currentTransition?.currentOverscrollSpec).isNull()
        assertThat(transition).hasNoOverscrollSpec()

        progress.value = 1f
        assertThat(state.currentTransition?.currentOverscrollSpec).isNull()
        assertThat(transition).hasNoOverscrollSpec()

        // overscroll for SceneB is defined
        progress.value = 1.1f
        assertThat(state.currentTransition?.currentOverscrollSpec).isNotNull()
        assertThat(state.currentTransition?.currentOverscrollSpec?.scene).isEqualTo(SceneB)
        val overscrollSpec = assertThat(transition).hasOverscrollSpec()
        assertThat(overscrollSpec.scene).isEqualTo(SceneB)
    }

    @Test
@@ -507,23 +509,25 @@ class SceneTransitionLayoutStateTest {
                        overscroll(SceneA, Orientation.Vertical) { fade(TestElements.Foo) }
                    }
            )
        assertThat(state.currentTransition?.currentOverscrollSpec).isNull()

        val transition = assertThat(state.transitionState).isTransition()
        assertThat(transition).hasNoOverscrollSpec()

        // overscroll for SceneA is defined
        progress.value = -0.1f
        assertThat(state.currentTransition?.currentOverscrollSpec).isNotNull()
        assertThat(state.currentTransition?.currentOverscrollSpec?.scene).isEqualTo(SceneA)
        val overscrollSpec = assertThat(transition).hasOverscrollSpec()
        assertThat(overscrollSpec.scene).isEqualTo(SceneA)

        // scroll from SceneA to SceneB
        progress.value = 0.5f
        assertThat(state.currentTransition?.currentOverscrollSpec).isNull()
        assertThat(transition).hasNoOverscrollSpec()

        progress.value = 1f
        assertThat(state.currentTransition?.currentOverscrollSpec).isNull()
        assertThat(transition).hasNoOverscrollSpec()

        // overscroll for SceneB is NOT defined
        progress.value = 1.1f
        assertThat(state.currentTransition?.currentOverscrollSpec).isNull()
        assertThat(transition).hasNoOverscrollSpec()
    }

    @Test
@@ -534,22 +538,24 @@ class SceneTransitionLayoutStateTest {
                progress = { progress.value },
                sceneTransitions = transitions {}
            )
        assertThat(state.currentTransition?.currentOverscrollSpec).isNull()

        val transition = assertThat(state.transitionState).isTransition()
        assertThat(transition).hasNoOverscrollSpec()

        // overscroll for SceneA is NOT defined
        progress.value = -0.1f
        assertThat(state.currentTransition?.currentOverscrollSpec).isNull()
        assertThat(transition).hasNoOverscrollSpec()

        // scroll from SceneA to SceneB
        progress.value = 0.5f
        assertThat(state.currentTransition?.currentOverscrollSpec).isNull()
        assertThat(transition).hasNoOverscrollSpec()

        progress.value = 1f
        assertThat(state.currentTransition?.currentOverscrollSpec).isNull()
        assertThat(transition).hasNoOverscrollSpec()

        // overscroll for SceneB is NOT defined
        progress.value = 1.1f
        assertThat(state.currentTransition?.currentOverscrollSpec).isNull()
        assertThat(transition).hasNoOverscrollSpec()
    }

    @Test
Loading