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

Commit a7c687bb authored by omarmt's avatar omarmt
Browse files

STL improve readability of OffsetOverscrollEffect tests

Test: atest ElementTest
Test: atest OffsetOverscrollEffectTest
Bug: 378470603
Flag: com.android.systemui.scene_container
Change-Id: I17fe8a74651e36d75268a42959ff7290e8990826
parent cb488d98
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -771,7 +771,7 @@ class ElementTest {

    private fun expectedOffset(currentOffset: Dp, density: Density): Dp {
        return with(density) {
            OffsetOverscrollEffect.computeOffset(this, currentOffset.toPx()).toDp()
            OffsetOverscrollEffect.computeOffset(density, currentOffset.toPx()).toDp()
        }
    }

+64 −97
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.test.ext.junit.runners.AndroidJUnit4
import kotlin.properties.Delegates
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -44,165 +45,131 @@ import org.junit.runner.RunWith
class OffsetOverscrollEffectTest {
    @get:Rule val rule = createComposeRule()

    private fun expectedOffset(currentOffset: Dp, density: Density): Dp {
    private val BOX_TAG = "box"

    private data class LayoutInfo(val layoutSize: Dp, val touchSlop: Float, val density: Density) {
        fun expectedOffset(currentOffset: Dp): Dp {
            return with(density) {
                OffsetOverscrollEffect.computeOffset(this, currentOffset.toPx()).toDp()
            }
        }
    }

    @Test
    fun applyVerticalOffset_duringVerticalOverscroll() {
    private fun setupOverscrollableBox(
        scrollableOrientation: Orientation,
        overscrollEffectOrientation: Orientation = scrollableOrientation,
    ): LayoutInfo {
        val layoutSize: Dp = 200.dp
        var touchSlop: Float by Delegates.notNull()
        // The draggable touch slop, i.e. the min px distance a touch pointer must move before it is
        // detected as a drag event.
        var touchSlop = 0f
        lateinit var density: Density
        val layoutSize = 200.dp

        rule.setContent {
            density = LocalDensity.current
            touchSlop = LocalViewConfiguration.current.touchSlop
            val overscrollEffect = rememberOffsetOverscrollEffect(Orientation.Vertical)
            val overscrollEffect = rememberOffsetOverscrollEffect(overscrollEffectOrientation)

            Box(
                Modifier.overscroll(overscrollEffect)
                    // A scrollable that does not consume the scroll gesture.
                    .scrollable(
                        state = rememberScrollableState { 0f },
                        orientation = Orientation.Vertical,
                        orientation = scrollableOrientation,
                        overscrollEffect = overscrollEffect,
                    )
                    .size(layoutSize)
                    .testTag("box")
                    .testTag(BOX_TAG)
            )
        }
        return LayoutInfo(layoutSize, touchSlop, density)
    }

        val onBox = rule.onNodeWithTag("box")
    @Test
    fun applyVerticalOffset_duringVerticalOverscroll() {
        val info = setupOverscrollableBox(scrollableOrientation = Orientation.Vertical)

        onBox.assertTopPositionInRootIsEqualTo(0.dp)
        rule.onNodeWithTag(BOX_TAG).assertTopPositionInRootIsEqualTo(0.dp)

        rule.onRoot().performTouchInput {
            down(center)
            moveBy(Offset(0f, touchSlop + layoutSize.toPx()), delayMillis = 1_000)
            moveBy(Offset(0f, info.touchSlop + info.layoutSize.toPx()), delayMillis = 1_000)
        }

        onBox.assertTopPositionInRootIsEqualTo(expectedOffset(layoutSize, density))
        rule
            .onNodeWithTag(BOX_TAG)
            .assertTopPositionInRootIsEqualTo(info.expectedOffset(info.layoutSize))
    }

    @Test
    fun applyNoOffset_duringHorizontalOverscroll() {
        // The draggable touch slop, i.e. the min px distance a touch pointer must move before it is
        // detected as a drag event.
        var touchSlop = 0f
        val layoutSize = 200.dp

        rule.setContent {
            touchSlop = LocalViewConfiguration.current.touchSlop
            val overscrollEffect = rememberOffsetOverscrollEffect(Orientation.Vertical)

            Box(
                Modifier.overscroll(overscrollEffect)
                    // A scrollable that does not consume the scroll gesture.
                    .scrollable(
                        state = rememberScrollableState { 0f },
                        orientation = Orientation.Horizontal,
                        overscrollEffect = overscrollEffect,
        val info =
            setupOverscrollableBox(
                scrollableOrientation = Orientation.Vertical,
                overscrollEffectOrientation = Orientation.Horizontal,
            )
                    .size(layoutSize)
                    .testTag("box")
            )
        }

        val onBox = rule.onNodeWithTag("box")

        onBox.assertTopPositionInRootIsEqualTo(0.dp)
        rule.onNodeWithTag(BOX_TAG).assertTopPositionInRootIsEqualTo(0.dp)

        rule.onRoot().performTouchInput {
            down(center)
            moveBy(Offset(touchSlop + layoutSize.toPx(), 0f), delayMillis = 1_000)
            moveBy(Offset(info.touchSlop + info.layoutSize.toPx(), 0f), delayMillis = 1_000)
        }

        onBox.assertTopPositionInRootIsEqualTo(0.dp)
        rule.onNodeWithTag(BOX_TAG).assertTopPositionInRootIsEqualTo(0.dp)
    }

    @Test
    fun backToZero_afterOverscroll() {
        // The draggable touch slop, i.e. the min px distance a touch pointer must move before it is
        // detected as a drag event.
        var touchSlop = 0f
        lateinit var density: Density
        val layoutSize = 200.dp

        rule.setContent {
            density = LocalDensity.current
            touchSlop = LocalViewConfiguration.current.touchSlop
            val overscrollEffect = rememberOffsetOverscrollEffect(Orientation.Vertical)

            Box(
                Modifier.overscroll(overscrollEffect)
                    // A scrollable that does not consume the scroll gesture.
                    .scrollable(
                        state = rememberScrollableState { 0f },
                        orientation = Orientation.Vertical,
                        overscrollEffect = overscrollEffect,
                    )
                    .size(layoutSize)
                    .testTag("box")
            )
        }

        val onBox = rule.onNodeWithTag("box")
        val info = setupOverscrollableBox(scrollableOrientation = Orientation.Vertical)

        rule.onRoot().performTouchInput {
            down(center)
            moveBy(Offset(0f, touchSlop + layoutSize.toPx()), delayMillis = 1_000)
            moveBy(Offset(0f, info.touchSlop + info.layoutSize.toPx()), delayMillis = 1_000)
        }

        onBox.assertTopPositionInRootIsEqualTo(expectedOffset(layoutSize, density))
        rule
            .onNodeWithTag(BOX_TAG)
            .assertTopPositionInRootIsEqualTo(info.expectedOffset(info.layoutSize))

        rule.onRoot().performTouchInput { up() }

        onBox.assertTopPositionInRootIsEqualTo(0.dp)
        rule.onNodeWithTag(BOX_TAG).assertTopPositionInRootIsEqualTo(0.dp)
    }

    @Test
    fun offsetOverscroll_followTheTouchPointer() {
        // The draggable touch slop, i.e. the min px distance a touch pointer must move before it is
        // detected as a drag event.
        var touchSlop = 0f
        lateinit var density: Density
        val layoutSize = 200.dp

        rule.setContent {
            density = LocalDensity.current
            touchSlop = LocalViewConfiguration.current.touchSlop
            val overscrollEffect = rememberOffsetOverscrollEffect(Orientation.Vertical)

            Box(
                Modifier.overscroll(overscrollEffect)
                    // A scrollable that does not consume the scroll gesture.
                    .scrollable(
                        state = rememberScrollableState { 0f },
                        orientation = Orientation.Vertical,
                        overscrollEffect = overscrollEffect,
                    )
                    .size(layoutSize)
                    .testTag("box")
            )
        }

        val onBox = rule.onNodeWithTag("box")
        val info = setupOverscrollableBox(scrollableOrientation = Orientation.Vertical)

        // First gesture, drag down.
        rule.onRoot().performTouchInput {
            down(center)
            // A full screen scroll.
            moveBy(Offset(0f, touchSlop + layoutSize.toPx()), delayMillis = 1_000)
            moveBy(Offset(0f, info.touchSlop + info.layoutSize.toPx()), delayMillis = 1_000)
        }
        onBox.assertTopPositionInRootIsEqualTo(expectedOffset(layoutSize, density))
        rule
            .onNodeWithTag(BOX_TAG)
            .assertTopPositionInRootIsEqualTo(info.expectedOffset(info.layoutSize))

        rule.onRoot().performTouchInput {
            // Reduced by half.
            moveBy(Offset(0f, -layoutSize.toPx() / 2), delayMillis = 1_000)
            moveBy(Offset(0f, -info.layoutSize.toPx() / 2), delayMillis = 1_000)
        }
        rule
            .onNodeWithTag(BOX_TAG)
            .assertTopPositionInRootIsEqualTo(info.expectedOffset(info.layoutSize / 2))

        rule.onRoot().performTouchInput { up() }
        // Animate back to 0.
        rule.onNodeWithTag(BOX_TAG).assertTopPositionInRootIsEqualTo(0.dp)

        // Second gesture, drag up.
        rule.onRoot().performTouchInput {
            down(center)
            // A full screen scroll.
            moveBy(Offset(0f, -info.touchSlop - info.layoutSize.toPx()), delayMillis = 1_000)
        }
        onBox.assertTopPositionInRootIsEqualTo(expectedOffset(layoutSize / 2, density))
        rule
            .onNodeWithTag(BOX_TAG)
            .assertTopPositionInRootIsEqualTo(info.expectedOffset(-info.layoutSize))
    }
}