<lambda>null1 package android.platform.helpers.foldable
2 
3 import android.graphics.Point
4 import android.platform.uiautomator_helpers.DeviceHelpers.uiDevice
5 import android.platform.uiautomator_helpers.WaitUtils.waitFor
6 import com.google.common.truth.Expect
7 import com.google.common.truth.Truth.assertWithMessage
8 import java.time.Duration
9 
10 /**
11  * Utilities to write tests for moving icons towards the center, as happens during the fold
12  * animation.
13  */
14 object UnfoldAnimationTestingUtils {
15 
16     /**
17      * Returns icon positions after any one of them is moved.
18      *
19      * [currentProvider] returned icons are compared with [initialIcons]. As soon as any moved, the
20      * new set is returned.
21      */
22     fun getIconPositionsAfterAnyIconMove(
23         initialIcons: Set<Icon>,
24         currentProvider: () -> Set<Icon>
25     ): Set<Icon> {
26         return waitFor("Icons moving", Duration.ofSeconds(20)) {
27             val newIcons = currentProvider()
28             val moved =
29                 commonIcons(initialIcons, newIcons).any { (initial, new) ->
30                     initial.position != new.position
31                 }
32             return@waitFor if (moved) newIcons else null
33         }
34     }
35 
36     /**
37      * Waits until the positions returned by [currentProvider] match [expected].
38      *
39      * Only common icons between the 2 sets are considered. Thows if there is no intersection.
40      */
41     fun waitForPositionsToMatch(expected: Set<Icon>, currentProvider: () -> Set<Icon>) {
42         waitFor("Icons matching expected positions") {
43             val allMoved =
44                 commonIcons(expected, currentProvider()).all { (expected, current) ->
45                     expected.position == current.position
46                 }
47             return@waitFor if (allMoved) true else null
48         }
49     }
50 
51     /** Returns icons in both [setA] and [setB], comparing only icon name. */
52     fun commonIcons(setA: Set<Icon>, setB: Set<Icon>): Set<Pair<Icon, Icon>> {
53         return commonNames(setA, setB)
54             .also {
55                 assertWithMessage("Empty intersection between $setA and $setB")
56                     .that(it)
57                     .isNotEmpty()
58             }
59             .map { name ->
60                 val aIcon = setA.findWithName(name)
61                 val bIcon = setB.findWithName(name)
62                 aIcon to bIcon
63             }
64             .toSet()
65     }
66 
67     private fun commonNames(setA: Set<Icon>, setB: Set<Icon>): Set<String> {
68         return setA.map { it.name }.intersect(setB.map { it.name }.toSet())
69     }
70 
71     private fun Set<Icon>.findWithName(iconName: String): Icon {
72         return find { it.name == iconName } ?: error("Icon with name $iconName not found in $this")
73     }
74 
75     /**
76      * Asserts [coordinate] (x or y)coordinate of [new] icon has moved towards the center compared
77      * to [old].
78      */
79     fun assertIconMovedTowardsTheCenter(old: Icon, new: Icon, expect: Expect, axis: Axis) {
80         assertWithMessage("Comparing icons with different names").that(old.name).isEqualTo(new.name)
81         val oldPosition = if (axis == Axis.X) old.position.x else old.position.y
82         val newPosition = if (axis == Axis.X) new.position.x else new.position.y
83         val expectThatOld =
84             expect.withMessage("Icon: ${old.name} didn't move towards the center").that(oldPosition)
85         if (oldPosition < uiDevice.displayWidth / 2) {
86             expectThatOld.isLessThan(newPosition)
87         } else {
88             expectThatOld.isGreaterThan(newPosition)
89         }
90     }
91 
92     /** Describes axis (x or y) of a View */
93     enum class Axis {
94         X,
95         Y
96     }
97 
98     /**
99      * Represent a UI element with a position, used in [UnfoldAnimationTestingUtils] for foldable
100      * animation testing.
101      */
102     data class Icon(val name: String, val position: Point)
103 }
104