[go: nahoru, domu]

Cleanup of event injection tests

- Added default values to ClickableTestBox parameters
- Used ClickableTestBox in most (if not all) places
- Replaced runOnUiThread with runOnIdleCompose where appropriate
- Inlined `fun Ui(..)` where appropriate
- Simplified TestConfig data classes
- Removed lateinit where possible
- Removed redundant variables
- Removed @Before and @After where possible
- Extracted PointerInputFilter for recording touches

Fixes: 155400301
Test: ./gradlew ui:ui-test:cC
Change-Id: I312973f1c1ce418b4bf3c710b24a25be3e4e6e47
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendClickTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendClickTest.kt
index 98b3c66..ab9d3c3 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendClickTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendClickTest.kt
@@ -24,26 +24,20 @@
 import androidx.compose.Recomposer
 import androidx.test.filters.MediumTest
 import androidx.test.rule.ActivityTestRule
-import androidx.ui.core.DensityAmbient
-import androidx.ui.core.PointerEventPass
-import androidx.ui.core.PointerInputChange
-import androidx.ui.core.TestTag
 import androidx.ui.core.changedToUp
 import androidx.ui.core.pointerinput.PointerInputFilter
 import androidx.ui.core.pointerinput.PointerInputModifier
 import androidx.ui.core.setContent
-import androidx.ui.foundation.Box
 import androidx.ui.graphics.Color
 import androidx.ui.layout.Column
-import androidx.ui.layout.preferredSize
-import androidx.ui.semantics.Semantics
 import androidx.ui.test.android.AndroidComposeTestRule
 import androidx.ui.test.doGesture
 import androidx.ui.test.findByTag
 import androidx.ui.test.runOnIdleCompose
 import androidx.ui.test.runOnUiThread
 import androidx.ui.test.sendClick
-import androidx.ui.unit.IntPxSize
+import androidx.ui.test.util.ClickableTestBox
+import androidx.ui.test.util.RecordingFilter
 import androidx.ui.unit.PxPosition
 import androidx.ui.unit.px
 import com.google.common.truth.Truth.assertThat
@@ -65,6 +59,17 @@
     val position: PxPosition
 )
 
+private class ClickRecorder(
+    private val componentIndex: Int,
+    private val recordedClicks: MutableList<ClickData>
+) : PointerInputModifier {
+    override val pointerInputFilter: PointerInputFilter = RecordingFilter {
+        if (it.changedToUp()) {
+            recordedClicks.add(ClickData(componentIndex, it.current.position!!))
+        }
+    }
+}
+
 // The presence of an ActionBar follows from the theme set in AndroidManifest.xml
 class ActivityWithActionBar : ComponentActivity() {
     private lateinit var composeHolder: FrameLayout
@@ -88,58 +93,28 @@
     }
 }
 
-private fun <T : ComponentActivity> AndroidComposeTestRule<T>.setContent(
-    recordedClicks: MutableList<ClickData>
-) {
+private fun AndroidComposeTestRule<*>.setContent(recordedClicks: MutableList<ClickData>) {
+    val content = @Composable {
+        Column {
+            repeat(numberOfSquares) { i ->
+                ClickableTestBox(
+                    modifier = ClickRecorder(i, recordedClicks),
+                    width = squareSize,
+                    height = squareSize,
+                    color = colors[i],
+                    tag = "$tag$i"
+                )
+            }
+        }
+    }
+
     val activity = activityTestRule.activity
     if (activity is ActivityWithActionBar) {
         runOnUiThread {
-            activity.setContent { Ui(recordedClicks) }
+            activity.setContent(content)
         }
     } else {
-        setContent { Ui(recordedClicks) }
-    }
-}
-
-@Composable
-private fun Ui(recordedClicks: MutableList<ClickData>) {
-    with(DensityAmbient.current) {
-        Column {
-            for (i in first..last) {
-                TestTag(tag = "$tag$i") {
-                    Semantics(container = true) {
-                        val pointerInputModifier =
-                            object : PointerInputModifier {
-                                override val pointerInputFilter = object : PointerInputFilter() {
-                                    override fun onPointerInput(
-                                        changes: List<PointerInputChange>,
-                                        pass: PointerEventPass,
-                                        bounds: IntPxSize
-                                    ): List<PointerInputChange> {
-                                        if (pass == PointerEventPass.InitialDown) {
-                                            changes.filter { it.changedToUp() }.forEach {
-                                                recordedClicks.add(
-                                                    ClickData(i, it.current.position!!)
-                                                )
-                                            }
-                                        }
-                                        return changes
-                                    }
-
-                                    override fun onCancel() {
-                                        // Do nothing
-                                    }
-                                }
-                            }
-                        squareSize.toDp()
-                        Box(
-                            pointerInputModifier.preferredSize(squareSize.toDp()),
-                            backgroundColor = colors[i]
-                        )
-                    }
-                }
-            }
-        }
+        setContent(content)
     }
 }
 
@@ -172,8 +147,8 @@
         composeTestRule.setContent(recordedClicks)
 
         // When I click each of the components
-        findByTag("${tag}$first").doGesture { sendClick() }
-        findByTag("${tag}$last").doGesture { sendClick() }
+        findByTag("$tag$first").doGesture { sendClick() }
+        findByTag("$tag$last").doGesture { sendClick() }
 
         // Then each component has registered a click
         runOnIdleCompose {
@@ -223,8 +198,8 @@
         composeTestRule.setContent(recordedClicks)
 
         // When I click each of the components
-        findByTag("${tag}$first").doGesture { sendClick(config.position) }
-        findByTag("${tag}$last").doGesture { sendClick(config.position) }
+        findByTag("$tag$first").doGesture { sendClick(config.position) }
+        findByTag("$tag$last").doGesture { sendClick(config.position) }
 
         // Then each component has registered a click
         runOnIdleCompose {
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendDoubleClickTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendDoubleClickTest.kt
index 401abcd..049380a 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendDoubleClickTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendDoubleClickTest.kt
@@ -16,27 +16,18 @@
 
 package androidx.ui.test.gesturescope
 
-import androidx.compose.Composable
 import androidx.test.filters.MediumTest
-import androidx.ui.core.DensityAmbient
 import androidx.ui.core.Modifier
-import androidx.ui.core.TestTag
 import androidx.ui.core.gesture.doubleTapGestureFilter
-import androidx.ui.core.pointerinput.PointerInputModifier
-import androidx.ui.foundation.Box
-import androidx.ui.graphics.Color
-import androidx.ui.layout.Stack
-import androidx.ui.layout.preferredSize
-import androidx.ui.semantics.Semantics
 import androidx.ui.test.android.AndroidInputDispatcher
 import androidx.ui.test.createComposeRule
 import androidx.ui.test.doGesture
 import androidx.ui.test.findByTag
-import androidx.ui.test.runOnUiThread
+import androidx.ui.test.runOnIdleCompose
 import androidx.ui.test.sendDoubleClick
+import androidx.ui.test.util.ClickableTestBox
 import androidx.ui.test.util.PointerInputRecorder
 import androidx.ui.test.util.assertTimestampsAreIncreasing
-import androidx.ui.unit.Px
 import androidx.ui.unit.PxPosition
 import androidx.ui.unit.milliseconds
 import androidx.ui.unit.px
@@ -50,27 +41,8 @@
 private val width = 200.px
 private val height = 200.px
 private val expectedDelay = 145.milliseconds
-
 private const val tag = "widget"
 
-@Composable
-private fun Ui(onDoubleTap: (PxPosition) -> Unit, pointerInputRecorder: PointerInputModifier) {
-    Stack {
-        TestTag(tag) {
-            Semantics(container = true) {
-                with(DensityAmbient.current) {
-                    Box(
-                        Modifier.doubleTapGestureFilter(onDoubleTap)
-                            .plus(pointerInputRecorder)
-                            .preferredSize(width.toDp(), height.toDp()),
-                        backgroundColor = Color.Yellow
-                    )
-                }
-            }
-        }
-    }
-}
-
 @MediumTest
 class SendDoubleClickWithoutArgumentsTest {
 
@@ -95,13 +67,18 @@
         // Given some content
         recorder = PointerInputRecorder()
         composeTestRule.setContent {
-            Ui( pointerInputRecorder = recorder)
+            ClickableTestBox(
+                Modifier.doubleTapGestureFilter(this::recordDoubleClick).plus(recorder),
+                width = width,
+                height = height,
+                tag = tag
+            )
         }
 
         // When we inject a double click
         findByTag(tag).doGesture { sendDoubleClick() }
 
-        runOnUiThread {
+        runOnIdleCompose {
             // Then we record 1 double click
             assertThat(recordedDoubleClicks).hasSize(1)
             // at the expected position
@@ -126,12 +103,7 @@
 @MediumTest
 @RunWith(Parameterized::class)
 class SendDoubleClickWithArgumentsTest(private val config: TestConfig) {
-    data class TestConfig(
-        val x: Px,
-        val y: Px
-    ) {
-        val position get() = PxPosition(x, y)
-    }
+    data class TestConfig(val position: PxPosition)
 
     companion object {
         @JvmStatic
@@ -140,15 +112,13 @@
             return mutableListOf<TestConfig>().apply {
                 for (x in listOf(1.px, 33.px, 99.px)) {
                     for (y in listOf(1.px, 33.px, 99.px)) {
-                        add(TestConfig(x, y))
+                        add(TestConfig(PxPosition(x, y)))
                     }
                 }
             }
         }
     }
 
-    private val tag = "widget"
-
     @get:Rule
     val composeTestRule = createComposeRule(disableTransitions = true)
 
@@ -157,7 +127,7 @@
         disableDispatchInRealTime = true
     )
 
-    private lateinit var recorder: PointerInputRecorder
+    private val recorder = PointerInputRecorder()
     private val recordedDoubleClicks = mutableListOf<PxPosition>()
     private val expectedClickPosition = config.position
 
@@ -168,15 +138,19 @@
     @Test
     fun testDoubleClickOnPosition() {
         // Given some content
-        recorder = PointerInputRecorder()
         composeTestRule.setContent {
-            Ui( pointerInputRecorder = recorder)
+            ClickableTestBox(
+                Modifier.doubleTapGestureFilter(this::recordDoubleClick).plus(recorder),
+                width = width,
+                height = height,
+                tag = tag
+            )
         }
 
         // When we inject a double click
         findByTag(tag).doGesture { sendDoubleClick(config.position) }
 
-        runOnUiThread {
+        runOnIdleCompose {
             // Then we record 1 double click
             assertThat(recordedDoubleClicks).hasSize(1)
             // at the expected position
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendLongClickTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendLongClickTest.kt
index 8366cc4..87d315f7 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendLongClickTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendLongClickTest.kt
@@ -16,26 +16,20 @@
 
 package androidx.ui.test.gesturescope
 
-import androidx.compose.Composable
 import androidx.test.filters.MediumTest
 import androidx.ui.core.Alignment
-import androidx.ui.core.DensityAmbient
 import androidx.ui.core.Modifier
-import androidx.ui.core.TestTag
 import androidx.ui.core.gesture.LongPressTimeout
 import androidx.ui.core.gesture.longPressGestureFilter
-import androidx.ui.foundation.Box
-import androidx.ui.graphics.Color
 import androidx.ui.layout.Stack
 import androidx.ui.layout.fillMaxSize
-import androidx.ui.layout.preferredSize
 import androidx.ui.layout.wrapContentSize
-import androidx.ui.semantics.Semantics
 import androidx.ui.test.createComposeRule
 import androidx.ui.test.doGesture
 import androidx.ui.test.findByTag
-import androidx.ui.test.runOnUiThread
+import androidx.ui.test.runOnIdleCompose
 import androidx.ui.test.sendLongClick
+import androidx.ui.test.util.ClickableTestBox
 import androidx.ui.test.util.PointerInputRecorder
 import androidx.ui.test.util.areAlmostEqualTo
 import androidx.ui.test.util.assertOnlyLastEventIsUp
@@ -56,24 +50,6 @@
 private val height = 100.px
 private val expectedDuration = LongPressTimeout + 100.milliseconds
 
-@Composable
-private fun Ui(recorder: PointerInputRecorder, onLongPress: (PxPosition) -> Unit) {
-    Stack(Modifier.fillMaxSize().wrapContentSize(Alignment.BottomEnd)) {
-        TestTag(tag) {
-            Semantics(container = true) {
-                with(DensityAmbient.current) {
-                    Box(
-                        Modifier.longPressGestureFilter(onLongPress)
-                            .plus(recorder)
-                            .preferredSize(width.toDp(), height.toDp()),
-                        backgroundColor = Color.Yellow
-                    )
-                }
-            }
-        }
-    }
-}
-
 /**
  * Tests [sendLongClick] without arguments. Verifies that the click is in the middle
  * of the component, that the gesture has a duration of 600 milliseconds and that all input
@@ -97,7 +73,16 @@
     @Test
     fun testLongClick() {
         // Given some content
-        composeTestRule.setContent { Ui(recorder, ::recordLongPress) }
+        composeTestRule.setContent {
+            Stack(Modifier.fillMaxSize().wrapContentSize(Alignment.BottomEnd)) {
+                ClickableTestBox(
+                    modifier = Modifier.longPressGestureFilter(::recordLongPress).plus(recorder),
+                    width = width,
+                    height = height,
+                    tag = tag
+                )
+            }
+        }
 
         // When we inject a long click
         findByTag(tag).doGesture { sendLongClick() }
@@ -106,7 +91,7 @@
         assertThat(recordedLongClicks).hasSize(1)
 
         // And all events are at the click location
-        runOnUiThread {
+        runOnIdleCompose {
             recorder.run {
                 assertTimestampsAreIncreasing()
                 assertOnlyLastEventIsUp()
@@ -156,7 +141,16 @@
     @Test
     fun testLongClick() {
         // Given some content
-        composeTestRule.setContent { Ui(recorder, ::recordLongPress) }
+        composeTestRule.setContent {
+            Stack(Modifier.fillMaxSize().wrapContentSize(Alignment.BottomEnd)) {
+                ClickableTestBox(
+                    modifier = Modifier.longPressGestureFilter(::recordLongPress).plus(recorder),
+                    width = width,
+                    height = height,
+                    tag = tag
+                )
+            }
+        }
 
         // When we inject a long click
         findByTag(tag).doGesture { sendLongClick(config.position) }
@@ -165,7 +159,7 @@
         assertThat(recordedLongClicks).hasSize(1)
 
         // And all events are at the click location
-        runOnUiThread {
+        runOnIdleCompose {
             recorder.run {
                 assertTimestampsAreIncreasing()
                 assertOnlyLastEventIsUp()
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendSwipeTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendSwipeTest.kt
index f966857..c701ed9 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendSwipeTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendSwipeTest.kt
@@ -20,29 +20,23 @@
 import androidx.test.filters.MediumTest
 import androidx.ui.core.Alignment
 import androidx.ui.core.Modifier
-import androidx.ui.foundation.Box
-import androidx.ui.graphics.Color
 import androidx.ui.layout.Stack
 import androidx.ui.layout.fillMaxSize
-import androidx.ui.layout.preferredSize
 import androidx.ui.layout.wrapContentSize
-import androidx.ui.semantics.Semantics
-import androidx.ui.semantics.testTag
 import androidx.ui.test.createComposeRule
 import androidx.ui.test.doGesture
 import androidx.ui.test.findByTag
-import androidx.ui.test.runOnUiThread
+import androidx.ui.test.runOnIdleCompose
 import androidx.ui.test.sendSwipeDown
 import androidx.ui.test.sendSwipeLeft
 import androidx.ui.test.sendSwipeRight
 import androidx.ui.test.sendSwipeUp
+import androidx.ui.test.util.ClickableTestBox
 import androidx.ui.test.util.PointerInputRecorder
 import androidx.ui.test.util.assertOnlyLastEventIsUp
 import androidx.ui.test.util.assertTimestampsAreIncreasing
-import androidx.ui.unit.dp
 import com.google.common.collect.Ordering
 import com.google.common.truth.Truth.assertThat
-import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -57,30 +51,20 @@
     @get:Rule
     val composeTestRule = createComposeRule(disableTransitions = true)
 
-    private lateinit var recorder: PointerInputRecorder
-
-    @Before
-    fun setup() {
-        recorder = PointerInputRecorder()
-    }
+    private val recorder = PointerInputRecorder()
 
     @Composable
-    fun Ui(alignment: Modifier) {
-        Stack(Modifier.fillMaxSize() + alignment) {
-            Semantics(container = true, properties = { testTag = tag }) {
-                Box(
-                    recorder.preferredSize(100.dp),
-                    backgroundColor = Color.Yellow
-                )
-            }
+    fun Ui(alignment: Alignment) {
+        Stack(Modifier.fillMaxSize().wrapContentSize(alignment)) {
+            ClickableTestBox(modifier = recorder, tag = tag)
         }
     }
 
     @Test
     fun swipeUp() {
-        composeTestRule.setContent { Ui(Modifier.wrapContentSize(Alignment.TopStart)) }
+        composeTestRule.setContent { Ui(Alignment.TopStart) }
         findByTag(tag).doGesture { sendSwipeUp() }
-        runOnUiThread {
+        runOnIdleCompose {
             recorder.run {
                 assertTimestampsAreIncreasing()
                 assertOnlyLastEventIsUp()
@@ -91,9 +75,9 @@
 
     @Test
     fun swipeDown() {
-        composeTestRule.setContent { Ui(Modifier.wrapContentSize(Alignment.TopEnd)) }
+        composeTestRule.setContent { Ui(Alignment.TopEnd) }
         findByTag(tag).doGesture { sendSwipeDown() }
-        runOnUiThread {
+        runOnIdleCompose {
             recorder.run {
                 assertTimestampsAreIncreasing()
                 assertOnlyLastEventIsUp()
@@ -104,9 +88,9 @@
 
     @Test
     fun swipeLeft() {
-        composeTestRule.setContent { Ui(Modifier.wrapContentSize(Alignment.BottomEnd)) }
+        composeTestRule.setContent { Ui(Alignment.BottomEnd) }
         findByTag(tag).doGesture { sendSwipeLeft() }
-        runOnUiThread {
+        runOnIdleCompose {
             recorder.run {
                 assertTimestampsAreIncreasing()
                 assertOnlyLastEventIsUp()
@@ -117,9 +101,9 @@
 
     @Test
     fun swipeRight() {
-        composeTestRule.setContent { Ui(Modifier.wrapContentSize(Alignment.BottomStart)) }
+        composeTestRule.setContent { Ui(Alignment.BottomStart) }
         findByTag(tag).doGesture { sendSwipeRight() }
-        runOnUiThread {
+        runOnIdleCompose {
             recorder.run {
                 assertTimestampsAreIncreasing()
                 assertOnlyLastEventIsUp()
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendSwipeVelocityTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendSwipeVelocityTest.kt
index 252823d..ef42a73 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendSwipeVelocityTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendSwipeVelocityTest.kt
@@ -16,28 +16,19 @@
 
 package androidx.ui.test.gesturescope
 
-import androidx.compose.Composable
-import androidx.compose.remember
 import androidx.test.filters.MediumTest
 import androidx.ui.core.Alignment
-import androidx.ui.core.DensityAmbient
 import androidx.ui.core.Modifier
-import androidx.ui.foundation.Canvas
-import androidx.ui.geometry.Rect
-import androidx.ui.graphics.Color
-import androidx.ui.graphics.Paint
 import androidx.ui.layout.Stack
 import androidx.ui.layout.fillMaxSize
-import androidx.ui.layout.preferredSize
 import androidx.ui.layout.wrapContentSize
-import androidx.ui.semantics.Semantics
-import androidx.ui.semantics.testTag
 import androidx.ui.test.android.AndroidInputDispatcher
 import androidx.ui.test.createComposeRule
 import androidx.ui.test.doGesture
 import androidx.ui.test.findByTag
-import androidx.ui.test.runOnUiThread
+import androidx.ui.test.runOnIdleCompose
 import androidx.ui.test.sendSwipeWithVelocity
+import androidx.ui.test.util.ClickableTestBox
 import androidx.ui.test.util.PointerInputRecorder
 import androidx.ui.test.util.assertOnlyLastEventIsUp
 import androidx.ui.test.util.assertTimestampsAreIncreasing
@@ -51,7 +42,6 @@
 import androidx.ui.unit.inMilliseconds
 import androidx.ui.unit.px
 import com.google.common.truth.Truth.assertThat
-import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
 import org.junit.rules.TestRule
@@ -72,16 +62,11 @@
         val eventPeriod: Long
     )
 
-    enum class Direction(
-        val x0: (Rect) -> Float,
-        val y0: (Rect) -> Float,
-        val x1: (Rect) -> Float,
-        val y1: (Rect) -> Float
-    ) {
-        LeftToRight({ it.left + 1 }, ::hmiddle, { it.right - 1 }, ::hmiddle),
-        RightToLeft({ it.right - 1 }, ::hmiddle, { it.left + 1 }, ::hmiddle),
-        TopToBottom(::vmiddle, { it.top + 1 }, ::vmiddle, { it.bottom - 1 }),
-        BottomToTop(::vmiddle, { it.bottom - 1 }, ::vmiddle, { it.top + 1 })
+    enum class Direction(val from: PxPosition, val to: PxPosition) {
+        LeftToRight(PxPosition(boxStart, boxMiddle), PxPosition(boxEnd, boxMiddle)),
+        RightToLeft(PxPosition(boxEnd, boxMiddle), PxPosition(boxStart, boxMiddle)),
+        TopToBottom(PxPosition(boxMiddle, boxStart), PxPosition(boxMiddle, boxEnd)),
+        BottomToTop(PxPosition(boxMiddle, boxEnd), PxPosition(boxMiddle, boxStart))
     }
 
     companion object {
@@ -108,18 +93,16 @@
             }
         }
 
-        private fun hmiddle(bounds: Rect): Float = (bounds.left + bounds.right) / 2
-        private fun vmiddle(bounds: Rect): Float = (bounds.top + bounds.bottom) / 2
-
         private const val tag = "widget"
+
+        private val boxSize = 500.px
+        private val boxStart = 1.px
+        private val boxMiddle = boxSize / 2
+        private val boxEnd = boxSize - 1.px
     }
 
-    private val x0 get() = config.direction.x0(bounds)
-    private val y0 get() = config.direction.y0(bounds)
-    private val x1 get() = config.direction.x1(bounds)
-    private val y1 get() = config.direction.y1(bounds)
-    private val start get() = PxPosition(x0.px, y0.px)
-    private val end get() = PxPosition(x1.px, y1.px)
+    private val start get() = config.direction.from
+    private val end get() = config.direction.to
     private val duration get() = config.duration
     private val velocity get() = config.velocity
     private val eventPeriod get() = config.eventPeriod
@@ -145,34 +128,21 @@
         eventPeriodOverride = eventPeriod
     )
 
-    private lateinit var recorder: PointerInputRecorder
-    private lateinit var bounds: Rect
-
-    @Before
-    fun setUp() {
-        recorder = PointerInputRecorder()
-    }
-
-    @Composable
-    fun Ui() {
-        val paint = remember { Paint().apply { color = Color.Yellow } }
-        Stack(Modifier.fillMaxSize().wrapContentSize(Alignment.BottomEnd)) {
-            Semantics(container = true, properties = { testTag = tag }) {
-                with(DensityAmbient.current) {
-                    Canvas(recorder.preferredSize(500.px.toDp())) {
-                        bounds = Rect(0f, 0f, size.width.value, size.height.value)
-                        drawRect(bounds, paint)
-                    }
-                }
-            }
-        }
-    }
+    private val recorder = PointerInputRecorder()
 
     @Test
     fun swipeWithVelocity() {
-        composeTestRule.setContent { Ui() }
-        findByTag(tag).doGesture { sendSwipeWithVelocity(start, end, velocity, duration) }
-        runOnUiThread {
+        composeTestRule.setContent {
+            Stack(Modifier.fillMaxSize().wrapContentSize(Alignment.BottomEnd)) {
+                ClickableTestBox(recorder, boxSize, boxSize, tag = tag)
+            }
+        }
+
+        findByTag(tag).doGesture {
+            sendSwipeWithVelocity(start, end, velocity, duration)
+        }
+
+        runOnIdleCompose {
             recorder.run {
                 val durationMs = duration.inMilliseconds()
                 val minimumEventSize = max(2, (durationMs / eventPeriod).toInt())
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/DelayTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/DelayTest.kt
index 592dc54..c792d9b 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/DelayTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/DelayTest.kt
@@ -28,7 +28,6 @@
 import androidx.ui.unit.milliseconds
 import com.google.common.truth.Truth.assertThat
 import org.junit.After
-import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
 import org.junit.rules.TestRule
@@ -95,14 +94,8 @@
         disableDispatchInRealTime = true
     )
 
-    private lateinit var recorder: MotionEventRecorder
-    private lateinit var subject: AndroidInputDispatcher
-
-    @Before
-    fun setUp() {
-        recorder = MotionEventRecorder()
-        subject = AndroidInputDispatcher(recorder::sendEvent)
-    }
+    private val recorder = MotionEventRecorder()
+    private val subject = AndroidInputDispatcher(recorder::sendEvent)
 
     @After
     fun tearDown() {
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendCancelTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendCancelTest.kt
index 6dd3329..711ecb1 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendCancelTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendCancelTest.kt
@@ -27,7 +27,6 @@
 import androidx.ui.unit.px
 import com.google.common.truth.Truth.assertThat
 import org.junit.After
-import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
 import org.junit.rules.TestRule
@@ -67,14 +66,8 @@
 
     private val position = PxPosition(config.x.px, config.y.px)
 
-    private lateinit var recorder: MotionEventRecorder
-    private lateinit var subject: AndroidInputDispatcher
-
-    @Before
-    fun setUp() {
-        recorder = MotionEventRecorder()
-        subject = AndroidInputDispatcher(recorder::sendEvent)
-    }
+    private val recorder = MotionEventRecorder()
+    private val subject = AndroidInputDispatcher(recorder::sendEvent)
 
     @After
     fun tearDown() {
@@ -111,7 +104,7 @@
         disableDispatchInRealTime = true
     )
 
-    private val subject: AndroidInputDispatcher = AndroidInputDispatcher {}
+    private val subject = AndroidInputDispatcher {}
 
     @Test
     fun testCancelAfterUp() {
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendClickTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendClickTest.kt
index c1e19ea..d8ab709 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendClickTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendClickTest.kt
@@ -26,7 +26,6 @@
 import androidx.ui.unit.px
 import com.google.common.truth.Truth.assertThat
 import org.junit.After
-import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
 import org.junit.rules.TestRule
@@ -64,14 +63,8 @@
     private val eventPeriod = 10L
     private val position = PxPosition(config.x.px, config.y.px)
 
-    private lateinit var recorder: MotionEventRecorder
-    private lateinit var subject: AndroidInputDispatcher
-
-    @Before
-    fun setUp() {
-        recorder = MotionEventRecorder()
-        subject = AndroidInputDispatcher(recorder::sendEvent)
-    }
+    private val recorder = MotionEventRecorder()
+    private val subject = AndroidInputDispatcher(recorder::sendEvent)
 
     @After
     fun tearDown() {
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendDownTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendDownTest.kt
index f1cda6b..dd6eef6 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendDownTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendDownTest.kt
@@ -26,7 +26,6 @@
 import androidx.ui.unit.px
 import com.google.common.truth.Truth.assertThat
 import org.junit.After
-import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
 import org.junit.rules.TestRule
@@ -63,14 +62,8 @@
 
     private val position = PxPosition(config.x.px, config.y.px)
 
-    private lateinit var recorder: MotionEventRecorder
-    private lateinit var subject: AndroidInputDispatcher
-
-    @Before
-    fun setUp() {
-        recorder = MotionEventRecorder()
-        subject = AndroidInputDispatcher(recorder::sendEvent)
-    }
+    private val recorder = MotionEventRecorder()
+    private val subject = AndroidInputDispatcher(recorder::sendEvent)
 
     @After
     fun tearDown() {
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendMoveTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendMoveTest.kt
index f8ab469..6a5cc38 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendMoveTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendMoveTest.kt
@@ -27,7 +27,6 @@
 import androidx.ui.unit.px
 import com.google.common.truth.Truth.assertThat
 import org.junit.After
-import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
 import org.junit.rules.TestRule
@@ -67,14 +66,8 @@
 
     private val position = PxPosition(config.x.px, config.y.px)
 
-    private lateinit var recorder: MotionEventRecorder
-    private lateinit var subject: AndroidInputDispatcher
-
-    @Before
-    fun setUp() {
-        recorder = MotionEventRecorder()
-        subject = AndroidInputDispatcher(recorder::sendEvent)
-    }
+    private val recorder = MotionEventRecorder()
+    private val subject = AndroidInputDispatcher(recorder::sendEvent)
 
     @After
     fun tearDown() {
@@ -111,7 +104,7 @@
         disableDispatchInRealTime = true
     )
 
-    private val subject: AndroidInputDispatcher = AndroidInputDispatcher {}
+    private val subject = AndroidInputDispatcher {}
 
     @Test
     fun testMoveAfterUp() {
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendSwipeFunctionTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendSwipeFunctionTest.kt
index e73ef56..44ce4c4 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendSwipeFunctionTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendSwipeFunctionTest.kt
@@ -108,14 +108,8 @@
         disableDispatchInRealTime = true
     )
 
-    private lateinit var recorder: MotionEventRecorder
-    private lateinit var subject: AndroidInputDispatcher
-
-    @Before
-    fun setUp() {
-        recorder = MotionEventRecorder()
-        subject = AndroidInputDispatcher(recorder::sendEvent)
-    }
+    private val recorder = MotionEventRecorder()
+    private val subject = AndroidInputDispatcher(recorder::sendEvent)
 
     @After
     fun tearDown() {
@@ -194,14 +188,11 @@
         disableDispatchInRealTime = true
     )
 
-    private lateinit var recorder: MotionEventRecorder
-    private lateinit var subject: AndroidInputDispatcher
+    private val recorder = MotionEventRecorder()
+    private val subject = AndroidInputDispatcher(recorder::sendEvent)
 
     @Before
     fun setUp() {
-        recorder = MotionEventRecorder()
-        subject = AndroidInputDispatcher(recorder::sendEvent)
-
         require(config.keyTimes.distinct() == config.keyTimes.distinct().sorted()) {
             "keyTimes needs to be sorted, not ${config.keyTimes}"
         }
@@ -293,14 +284,11 @@
     private val keyTimes get() = config.keyTimes
     private val eventPeriod = config.eventPeriod
 
-    private lateinit var recorder: MotionEventRecorder
-    private lateinit var subject: AndroidInputDispatcher
+    private val recorder = MotionEventRecorder()
+    private val subject = AndroidInputDispatcher(recorder::sendEvent)
 
     @Before
     fun setUp() {
-        recorder = MotionEventRecorder()
-        subject = AndroidInputDispatcher(recorder::sendEvent)
-
         require(config.keyTimes.distinct() == config.keyTimes.distinct().sorted()) {
             "keyTimes needs to be sorted, not ${config.keyTimes}"
         }
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendSwipeLineTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendSwipeLineTest.kt
index b893eb0..a91587c 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendSwipeLineTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendSwipeLineTest.kt
@@ -31,7 +31,6 @@
 import androidx.ui.unit.px
 import com.google.common.truth.Truth.assertThat
 import org.junit.After
-import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
 import org.junit.rules.TestRule
@@ -75,14 +74,8 @@
     private val duration get() = config.duration
     private val eventPeriod = config.eventPeriod
 
-    private lateinit var recorder: MotionEventRecorder
-    private lateinit var subject: AndroidInputDispatcher
-
-    @Before
-    fun setUp() {
-        recorder = MotionEventRecorder()
-        subject = AndroidInputDispatcher(recorder::sendEvent)
-    }
+    private val recorder = MotionEventRecorder()
+    private val subject = AndroidInputDispatcher(recorder::sendEvent)
 
     @After
     fun tearDown() {
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendUpTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendUpTest.kt
index 6d584ed..d1606c2 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendUpTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendUpTest.kt
@@ -27,7 +27,6 @@
 import androidx.ui.unit.px
 import com.google.common.truth.Truth.assertThat
 import org.junit.After
-import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
 import org.junit.rules.TestRule
@@ -67,14 +66,8 @@
 
     private val position = PxPosition(config.x.px, config.y.px)
 
-    private lateinit var recorder: MotionEventRecorder
-    private lateinit var subject: AndroidInputDispatcher
-
-    @Before
-    fun setUp() {
-        recorder = MotionEventRecorder()
-        subject = AndroidInputDispatcher(recorder::sendEvent)
-    }
+    private val recorder = MotionEventRecorder()
+    private val subject = AndroidInputDispatcher(recorder::sendEvent)
 
     @After
     fun tearDown() {
@@ -111,7 +104,7 @@
         disableDispatchInRealTime = true
     )
 
-    private val subject: AndroidInputDispatcher = AndroidInputDispatcher {}
+    private val subject = AndroidInputDispatcher {}
 
     @Test
     fun testUpAfterUp() {
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendCancelTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendCancelTest.kt
index b6c4ee7..355ff67 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendCancelTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendCancelTest.kt
@@ -17,7 +17,6 @@
 package androidx.ui.test.partialgesturescope
 
 import androidx.test.filters.MediumTest
-import androidx.ui.graphics.Color
 import androidx.ui.test.GestureToken
 import androidx.ui.test.android.AndroidInputDispatcher
 import androidx.ui.test.createComposeRule
@@ -39,9 +38,6 @@
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 
-private val width = 200.px
-private val height = 200.px
-
 private const val tag = "widget"
 
 @MediumTest
@@ -81,7 +77,7 @@
         // Given some content
         recorder = PointerInputRecorder()
         composeTestRule.setContent {
-            ClickableTestBox(width, height, Color.Yellow, tag, recorder)
+            ClickableTestBox(recorder, tag = tag)
         }
 
         // When we inject a down event followed by a cancel event
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendDownTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendDownTest.kt
index c56472e..ec8d112 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendDownTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendDownTest.kt
@@ -17,7 +17,6 @@
 package androidx.ui.test.partialgesturescope
 
 import androidx.test.filters.MediumTest
-import androidx.ui.graphics.Color
 import androidx.ui.test.GestureToken
 import androidx.ui.test.android.AndroidInputDispatcher
 import androidx.ui.test.createComposeRule
@@ -38,9 +37,6 @@
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 
-private val width = 200.px
-private val height = 200.px
-
 private const val tag = "widget"
 
 @MediumTest
@@ -78,7 +74,7 @@
         // Given some content
         recorder = PointerInputRecorder()
         composeTestRule.setContent {
-            ClickableTestBox(width, height, Color.Yellow, tag, recorder)
+            ClickableTestBox(recorder, tag = tag)
         }
 
         // When we inject a down event
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendMoveByTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendMoveByTest.kt
index acc538a..1a3d87d 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendMoveByTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendMoveByTest.kt
@@ -17,7 +17,6 @@
 package androidx.ui.test.partialgesturescope
 
 import androidx.test.filters.MediumTest
-import androidx.ui.graphics.Color
 import androidx.ui.test.GestureToken
 import androidx.ui.test.android.AndroidInputDispatcher
 import androidx.ui.test.createComposeRule
@@ -40,9 +39,6 @@
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 
-private val width = 200.px
-private val height = 200.px
-
 private const val tag = "widget"
 
 @MediumTest
@@ -81,7 +77,7 @@
         // Given some content
         recorder = PointerInputRecorder()
         composeTestRule.setContent {
-            ClickableTestBox(width, height, Color.Yellow, tag, recorder)
+            ClickableTestBox(recorder, tag = tag)
         }
 
         // When we inject a down event followed by a move event
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendMoveToTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendMoveToTest.kt
index 86092f5..d0e176f 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendMoveToTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendMoveToTest.kt
@@ -17,7 +17,6 @@
 package androidx.ui.test.partialgesturescope
 
 import androidx.test.filters.MediumTest
-import androidx.ui.graphics.Color
 import androidx.ui.test.GestureToken
 import androidx.ui.test.android.AndroidInputDispatcher
 import androidx.ui.test.createComposeRule
@@ -40,9 +39,6 @@
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 
-private val width = 200.px
-private val height = 200.px
-
 private const val tag = "widget"
 
 @MediumTest
@@ -81,7 +77,7 @@
         // Given some content
         recorder = PointerInputRecorder()
         composeTestRule.setContent {
-            ClickableTestBox(width, height, Color.Yellow, tag, recorder)
+            ClickableTestBox(recorder, tag = tag)
         }
 
         // When we inject a down event followed by a move event
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendUpTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendUpTest.kt
index 6bc448b..33b8788 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendUpTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendUpTest.kt
@@ -17,7 +17,6 @@
 package androidx.ui.test.partialgesturescope
 
 import androidx.test.filters.MediumTest
-import androidx.ui.graphics.Color
 import androidx.ui.test.GestureToken
 import androidx.ui.test.android.AndroidInputDispatcher
 import androidx.ui.test.createComposeRule
@@ -40,9 +39,6 @@
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 
-private val width = 200.px
-private val height = 200.px
-
 private const val tag = "widget"
 
 @MediumTest
@@ -82,7 +78,7 @@
         // Given some content
         recorder = PointerInputRecorder()
         composeTestRule.setContent {
-            ClickableTestBox(width, height, Color.Yellow, tag, recorder)
+            ClickableTestBox(recorder, tag = tag)
         }
 
         // When we inject a down event followed by an up event
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/util/ClickableTestBox.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/util/ClickableTestBox.kt
index ec46184..e6ea4f2 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/util/ClickableTestBox.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/util/ClickableTestBox.kt
@@ -18,26 +18,36 @@
 
 import androidx.compose.Composable
 import androidx.ui.core.DensityAmbient
-import androidx.ui.core.pointerinput.PointerInputModifier
+import androidx.ui.core.Modifier
 import androidx.ui.foundation.Box
 import androidx.ui.graphics.Color
 import androidx.ui.layout.size
 import androidx.ui.semantics.Semantics
 import androidx.ui.semantics.testTag
+import androidx.ui.test.util.ClickableTestBox.defaultColor
+import androidx.ui.test.util.ClickableTestBox.defaultSize
+import androidx.ui.test.util.ClickableTestBox.defaultTag
 import androidx.ui.unit.Px
+import androidx.ui.unit.px
+
+object ClickableTestBox {
+    val defaultSize = 100.px
+    val defaultColor = Color.Yellow
+    const val defaultTag = "ClickableTestBox"
+}
 
 @Composable
 fun ClickableTestBox(
-    width: Px,
-    height: Px,
-    color: Color,
-    tag: String,
-    pointerInputModifier: PointerInputModifier
+    modifier: Modifier = Modifier,
+    width: Px = defaultSize,
+    height: Px = defaultSize,
+    color: Color = defaultColor,
+    tag: String = defaultTag
 ) {
     Semantics(container = true, properties = { testTag = tag }) {
         with(DensityAmbient.current) {
             Box(
-                modifier = pointerInputModifier.size(width.toDp(), height.toDp()),
+                modifier = modifier.size(width.toDp(), height.toDp()),
                 backgroundColor = color
             )
         }
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/util/PointerInputs.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/util/PointerInputs.kt
index 2321adc..51b360e 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/util/PointerInputs.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/util/PointerInputs.kt
@@ -46,26 +46,29 @@
     private val velocityTracker = VelocityTracker()
     val recordedVelocity get() = velocityTracker.calculateVelocity()
 
-    override val pointerInputFilter: PointerInputFilter =
-        object : PointerInputFilter() {
-            override fun onPointerInput(
-                changes: List<PointerInputChange>,
-                pass: PointerEventPass,
-                bounds: IntPxSize
-            ): List<PointerInputChange> {
-                if (pass == PointerEventPass.InitialDown) {
-                    changes.forEach {
-                        _events.add(DataPoint(it.id, it.current))
-                        velocityTracker.addPosition(it.current.uptime!!, it.current.position!!)
-                    }
-                }
-                return changes
-            }
+    override val pointerInputFilter = RecordingFilter {
+        _events.add(DataPoint(it.id, it.current))
+        velocityTracker.addPosition(it.current.uptime!!, it.current.position!!)
+    }
+}
 
-            override fun onCancel() {
-                // Do nothing
+class RecordingFilter(private val record: (PointerInputChange) -> Unit) : PointerInputFilter() {
+    override fun onPointerInput(
+        changes: List<PointerInputChange>,
+        pass: PointerEventPass,
+        bounds: IntPxSize
+    ): List<PointerInputChange> {
+        if (pass == PointerEventPass.InitialDown) {
+            changes.forEach {
+                record(it)
             }
         }
+        return changes
+    }
+
+    override fun onCancel() {
+        // Do nothing
+    }
 }
 
 fun Uptime.inMilliseconds(): Long = nanoseconds / 1_000_000