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

Commit 632d1d99 authored by Jordan Demeulenaere's avatar Jordan Demeulenaere
Browse files

Add test for STL contents zIndex

This CL adds a test for the zIndex logic in STLImpl. This would have
caught the regression at b/435361598, caused by ag/34879256.

Bug: 435361598
Test: atest SceneTransitionLayoutTest
Flag: TEST_ONLY
Change-Id: Ib9b702f27efd37012aa063b3828e51760e846f7d
parent 3233ae9e
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import androidx.compose.ui.layout.Measurable
import androidx.compose.ui.layout.MeasureResult
import androidx.compose.ui.node.LayoutAwareModifierNode
import androidx.compose.ui.node.ModifierNodeElement
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.IntSize
@@ -57,6 +58,7 @@ import com.android.compose.animation.scene.content.Content
import com.android.compose.animation.scene.content.Overlay
import com.android.compose.animation.scene.content.Scene
import com.android.compose.animation.scene.content.state.TransitionState
import com.android.compose.modifiers.thenIf
import com.android.compose.ui.util.lerp
import kotlinx.coroutines.CoroutineScope

@@ -481,6 +483,7 @@ internal class SceneTransitionLayoutImpl(
                .then(
                    LayoutElement(layoutImpl = this, transitionState = this.state.transitionState)
                )
                .thenIf(implicitTestTags) { Modifier.testTag(SceneTransitionLayoutRootContentTag) }
        ) {
            LookaheadScope {
                if (_lookaheadScope == null) {
@@ -708,3 +711,5 @@ private class LayoutNode(
        return layout(width, height) { placeable.place(0, 0) }
    }
}

internal const val SceneTransitionLayoutRootContentTag = "SceneTransitionLayoutRootContent"
+42 −0
Original line number Diff line number Diff line
@@ -42,12 +42,15 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalViewConfiguration
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.semantics.SemanticsProperties
import androidx.compose.ui.semantics.getOrNull
import androidx.compose.ui.test.SemanticsNodeInteraction
import androidx.compose.ui.test.assertHeightIsEqualTo
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsNotDisplayed
import androidx.compose.ui.test.assertPositionInRootIsEqualTo
import androidx.compose.ui.test.assertWidthIsEqualTo
import androidx.compose.ui.test.hasTestTag
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onChild
import androidx.compose.ui.test.onNodeWithTag
@@ -61,6 +64,7 @@ import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.compose.animation.scene.TestOverlays.OverlayA
import com.android.compose.animation.scene.TestOverlays.OverlayB
import com.android.compose.animation.scene.TestScenes.SceneA
import com.android.compose.animation.scene.TestScenes.SceneB
import com.android.compose.animation.scene.TestScenes.SceneC
@@ -652,4 +656,42 @@ class SceneTransitionLayoutTest {
        rule.onNode(isElement(TestElements.Foo)).assertIsDisplayed().assertSizeIsEqualTo(40.dp)
        rule.onNode(isElement(TestElements.Bar)).assertExists().assertIsNotDisplayed()
    }

    @Test
    fun zIndex() {
        val state =
            rule.runOnUiThread {
                MutableSceneTransitionLayoutStateForTests(
                    SceneA,
                    initialOverlays = setOf(OverlayA, OverlayB),
                )
            }
        val scope =
            rule.setContentAndCreateMainScope {
                SceneTransitionLayoutForTesting(state) {
                    scene(SceneA) { Box(Modifier.fillMaxSize()) }
                    scene(SceneB) { Box(Modifier.fillMaxSize()) }
                    overlay(OverlayA) { Box(Modifier.fillMaxSize()) }
                    overlay(OverlayB) { Box(Modifier.fillMaxSize()) }
                }
            }

        // Start transition. We go from A => B because STLImpl always composes the scene we are
        // going *to* first (B in this case), so that we can check that B's zIndex is still higher
        // than A's even if it is composed first.
        val aToB = transition(SceneA, SceneB)
        scope.launch { state.startTransition(aToB) }
        rule.waitForIdle()

        val childrenByZIndex =
            rule
                .onNode(hasTestTag(SceneTransitionLayoutRootContentTag))
                .fetchSemanticsNode()
                .children
                .mapNotNull { it.config.getOrNull(SemanticsProperties.TestTag) }

        assertThat(childrenByZIndex)
            .containsExactly("scene:SceneA", "scene:SceneB", "overlay:OverlayA", "overlay:OverlayB")
            .inOrder()
    }
}