summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jordan Demeulenaere <jdemeulenaere@google.com> 2024-10-17 09:07:02 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-10-17 09:07:02 +0000
commit0144760b3c8ce65ac36fca2fdcc878c04d6134a7 (patch)
tree722efb05d656b861addc266461e88320f9155024
parent3b08060bda0d3641230d851c0089d7e7fd0a46d6 (diff)
parent4dfd56f81043c6eec75a821f104a240244e9e4f9 (diff)
Merge "Introduce more complex ways to match elements" into main
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ElementMatcher.kt47
-rw-r--r--packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementMatcherTest.kt56
-rw-r--r--packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt4
-rw-r--r--packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/OverlayTest.kt6
-rw-r--r--packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/SharedElementTest.kt6
-rw-r--r--packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/TestMatchers.kt4
6 files changed, 107 insertions, 16 deletions
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ElementMatcher.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ElementMatcher.kt
index ca68c256fd73..772872719ebe 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ElementMatcher.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ElementMatcher.kt
@@ -22,19 +22,52 @@ interface ElementMatcher {
fun matches(key: ElementKey, content: ContentKey): Boolean
}
+/** Returns an [ElementMatcher] that matches any element in [content]. */
+fun inContent(content: ContentKey): ElementMatcher {
+ val matcherContent = content
+ return object : ElementMatcher {
+ override fun matches(key: ElementKey, content: ContentKey): Boolean {
+ return content == matcherContent
+ }
+ }
+}
+
+/** Returns an [ElementMatcher] that matches all elements not matching [this] matcher. */
+operator fun ElementMatcher.not(): ElementMatcher {
+ val delegate = this
+ return object : ElementMatcher {
+ override fun matches(key: ElementKey, content: ContentKey): Boolean {
+ return !delegate.matches(key, content)
+ }
+ }
+}
+
+/**
+ * Returns an [ElementMatcher] that matches all elements matching both [this] matcher and [other].
+ */
+infix fun ElementMatcher.and(other: ElementMatcher): ElementMatcher {
+ val delegate = this
+ return object : ElementMatcher {
+ override fun matches(key: ElementKey, content: ContentKey): Boolean {
+ return delegate.matches(key, content) && other.matches(key, content)
+ }
+ }
+}
+
/**
- * Returns an [ElementMatcher] that matches elements in [content] also matching [this]
- * [ElementMatcher].
+ * Returns an [ElementMatcher] that matches all elements either [this] matcher, or [other], or both.
*/
-fun ElementMatcher.inContent(content: ContentKey): ElementMatcher {
+infix fun ElementMatcher.or(other: ElementMatcher): ElementMatcher {
val delegate = this
- val matcherScene = content
return object : ElementMatcher {
override fun matches(key: ElementKey, content: ContentKey): Boolean {
- return content == matcherScene && delegate.matches(key, content)
+ return delegate.matches(key, content) || other.matches(key, content)
}
}
}
-@Deprecated("Use inContent() instead", replaceWith = ReplaceWith("inContent(scene)"))
-fun ElementMatcher.inScene(scene: SceneKey) = inContent(scene)
+@Deprecated(
+ "Use `this and inContent()` instead",
+ replaceWith = ReplaceWith("this and inContent(scene)"),
+)
+fun ElementMatcher.inScene(scene: SceneKey) = this and inContent(scene)
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementMatcherTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementMatcherTest.kt
new file mode 100644
index 000000000000..af0962361fb2
--- /dev/null
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementMatcherTest.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compose.animation.scene
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.compose.animation.scene.TestElements.Bar
+import com.android.compose.animation.scene.TestElements.Foo
+import com.android.compose.animation.scene.TestScenes.SceneA
+import com.android.compose.animation.scene.TestScenes.SceneB
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ElementMatcherTest {
+ @Test
+ fun and() {
+ val matcher = Foo and inContent(SceneA)
+ assertThat(matcher.matches(Foo, SceneA)).isTrue()
+ assertThat(matcher.matches(Foo, SceneB)).isFalse()
+ assertThat(matcher.matches(Bar, SceneA)).isFalse()
+ assertThat(matcher.matches(Bar, SceneB)).isFalse()
+ }
+
+ @Test
+ fun or() {
+ val matcher = Foo or inContent(SceneA)
+ assertThat(matcher.matches(Foo, SceneA)).isTrue()
+ assertThat(matcher.matches(Foo, SceneB)).isTrue()
+ assertThat(matcher.matches(Bar, SceneA)).isTrue()
+ assertThat(matcher.matches(Bar, SceneB)).isFalse()
+ }
+
+ @Test
+ fun not() {
+ val matcher = !Foo
+ assertThat(matcher.matches(Foo, SceneA)).isFalse()
+ assertThat(matcher.matches(Foo, SceneB)).isFalse()
+ assertThat(matcher.matches(Bar, SceneA)).isTrue()
+ assertThat(matcher.matches(Bar, SceneB)).isTrue()
+ }
+}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
index 39d46990dc4b..ee807e6a7ede 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
@@ -2221,8 +2221,8 @@ class ElementTest {
// In A => B, Foo is not shared and first fades out from A then fades in
// B.
sharedElement(TestElements.Foo, enabled = false)
- fractionRange(end = 0.5f) { fade(TestElements.Foo.inContent(SceneA)) }
- fractionRange(start = 0.5f) { fade(TestElements.Foo.inContent(SceneB)) }
+ fractionRange(end = 0.5f) { fade(TestElements.Foo.inScene(SceneA)) }
+ fractionRange(start = 0.5f) { fade(TestElements.Foo.inScene(SceneB)) }
}
from(SceneB, to = SceneA) {
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/OverlayTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/OverlayTest.kt
index cae6617cb11b..7ea414d6b8cd 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/OverlayTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/OverlayTest.kt
@@ -35,6 +35,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.SemanticsMatcher
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsNotDisplayed
import androidx.compose.ui.test.assertPositionInRootIsEqualTo
@@ -205,7 +206,8 @@ class OverlayTest {
val key = MovableElementKey("MovableBar", contents = setOf(SceneA, OverlayA, OverlayB))
val elementChildTag = "elementChildTag"
- fun elementChild(content: ContentKey) = hasTestTag(elementChildTag) and inContent(content)
+ fun elementChild(content: ContentKey) =
+ hasTestTag(elementChildTag) and SemanticsMatcher.inContent(content)
@Composable
fun ContentScope.MovableBar() {
@@ -773,7 +775,7 @@ class OverlayTest {
// Overscroll on Overlay A.
scope.launch { state.startTransition(transition(SceneA, OverlayA, progress = { 1.5f })) }
rule
- .onNode(hasTestTag(movableElementChildTag) and inContent(SceneA))
+ .onNode(hasTestTag(movableElementChildTag) and SemanticsMatcher.inContent(SceneA))
.assertPositionInRootIsEqualTo(0.dp, 0.dp)
.assertSizeIsEqualTo(100.dp)
.assertIsDisplayed()
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/SharedElementTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/SharedElementTest.kt
index 4877cd610875..2e3a934c2701 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/SharedElementTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/SharedElementTest.kt
@@ -31,7 +31,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.compose.animation.scene.Edge
import com.android.compose.animation.scene.TestElements
import com.android.compose.animation.scene.TestScenes
-import com.android.compose.animation.scene.inContent
+import com.android.compose.animation.scene.inScene
import com.android.compose.animation.scene.testTransition
import com.android.compose.test.assertSizeIsEqualTo
import org.junit.Rule
@@ -125,10 +125,10 @@ class SharedElementTest {
sharedElement(TestElements.Foo, enabled = false)
// In SceneA, Foo leaves to the left edge.
- translate(TestElements.Foo.inContent(TestScenes.SceneA), Edge.Left)
+ translate(TestElements.Foo.inScene(TestScenes.SceneA), Edge.Left)
// In SceneB, Foo comes from the bottom edge.
- translate(TestElements.Foo.inContent(TestScenes.SceneB), Edge.Bottom)
+ translate(TestElements.Foo.inScene(TestScenes.SceneB), Edge.Bottom)
},
) {
before { onElement(TestElements.Foo).assertPositionInRootIsEqualTo(10.dp, 50.dp) }
diff --git a/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/TestMatchers.kt b/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/TestMatchers.kt
index 22450d32ea62..b3201d0daffe 100644
--- a/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/TestMatchers.kt
+++ b/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/TestMatchers.kt
@@ -25,11 +25,11 @@ fun isElement(element: ElementKey, content: ContentKey? = null): SemanticsMatche
return if (content == null) {
hasTestTag(element.testTag)
} else {
- hasTestTag(element.testTag) and inContent(content)
+ hasTestTag(element.testTag) and SemanticsMatcher.inContent(content)
}
}
/** A [SemanticsMatcher] that matches anything inside [content]. */
-fun inContent(content: ContentKey): SemanticsMatcher {
+fun SemanticsMatcher.Companion.inContent(content: ContentKey): SemanticsMatcher {
return hasAnyAncestor(hasTestTag(content.testTag))
}