diff options
author | 2025-02-06 16:11:38 +0100 | |
---|---|---|
committer | 2025-02-06 16:13:21 +0100 | |
commit | a32356a1baa3236a4584d45cce1d9ffcdca7656b (patch) | |
tree | 42d1360910030666c59486687e873a80695db447 | |
parent | 3a0fb660834c95cbd3ea314466e9775b337bb09d (diff) |
Move STL specific FeatureCapture / DataPointTypes to testing utilities
Going to reuse them in upcoming `ContentRevealTest.kt`
Flag: TEST_ONLY
Bug: 392534646
Test: BouncerPredictiveBackTest
Change-Id: Idde8e02d68fba5711e3005501b5072c0ea7119a8
4 files changed, 153 insertions, 82 deletions
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/testing/ElementStateAccess.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/testing/ElementStateAccess.kt index cade9bff5abb..ad2ddfe2b2a4 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/testing/ElementStateAccess.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/testing/ElementStateAccess.kt @@ -16,9 +16,12 @@ package com.android.compose.animation.scene.testing +import androidx.compose.ui.geometry.Offset import androidx.compose.ui.semantics.SemanticsNode +import androidx.compose.ui.unit.IntSize import com.android.compose.animation.scene.Element import com.android.compose.animation.scene.Element.Companion.AlphaUnspecified +import com.android.compose.animation.scene.Element.Companion.SizeUnspecified import com.android.compose.animation.scene.ElementModifier import com.android.compose.animation.scene.Scale @@ -28,6 +31,12 @@ val SemanticsNode.lastAlphaForTesting: Float? val SemanticsNode.lastScaleForTesting: Scale? get() = elementState.lastScale.takeIf { it != Scale.Unspecified } +val SemanticsNode.lastOffsetForTesting: Offset? + get() = elementState.lastOffset.takeIf { it != Offset.Unspecified } + +val SemanticsNode.lastSizeForTesting: IntSize? + get() = elementState.lastSize.takeIf { it != SizeUnspecified } + private val SemanticsNode.elementState: Element.State get() { val elementModifier = diff --git a/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/DataPointTypes.kt b/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/DataPointTypes.kt new file mode 100644 index 000000000000..7be7fa17eeea --- /dev/null +++ b/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/DataPointTypes.kt @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2025 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.compose.ui.geometry.Offset +import androidx.compose.ui.geometry.isFinite +import androidx.compose.ui.geometry.isUnspecified +import org.json.JSONObject +import platform.test.motion.golden.DataPointType +import platform.test.motion.golden.UnknownTypeException + +fun Scale.asDataPoint() = DataPointTypes.scale.makeDataPoint(this) + +object DataPointTypes { + val scale: DataPointType<Scale> = + DataPointType( + "scale", + jsonToValue = { + when (it) { + "unspecified" -> Scale.Unspecified + "default" -> Scale.Default + "zero" -> Scale.Zero + is JSONObject -> { + val pivot = it.get("pivot") + Scale( + scaleX = it.getDouble("x").toFloat(), + scaleY = it.getDouble("y").toFloat(), + pivot = + when (pivot) { + "unspecified" -> Offset.Unspecified + "infinite" -> Offset.Infinite + is JSONObject -> + Offset( + pivot.getDouble("x").toFloat(), + pivot.getDouble("y").toFloat(), + ) + else -> throw UnknownTypeException() + }, + ) + } + else -> throw UnknownTypeException() + } + }, + valueToJson = { + when (it) { + Scale.Unspecified -> "unspecified" + Scale.Default -> "default" + Scale.Zero -> "zero" + else -> { + JSONObject().apply { + put("x", it.scaleX) + put("y", it.scaleY) + put( + "pivot", + when { + it.pivot.isUnspecified -> "unspecified" + !it.pivot.isFinite -> "infinite" + else -> + JSONObject().apply { + put("x", it.pivot.x) + put("y", it.pivot.y) + } + }, + ) + } + } + } + }, + ) +} diff --git a/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/FeatureCaptures.kt b/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/FeatureCaptures.kt new file mode 100644 index 000000000000..8658bbf1da56 --- /dev/null +++ b/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/FeatureCaptures.kt @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2025 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.compose.ui.geometry.Offset +import androidx.compose.ui.semantics.SemanticsNode +import androidx.compose.ui.unit.IntSize +import com.android.compose.animation.scene.DataPointTypes.scale +import com.android.compose.animation.scene.testing.lastAlphaForTesting +import com.android.compose.animation.scene.testing.lastOffsetForTesting +import com.android.compose.animation.scene.testing.lastScaleForTesting +import com.android.compose.animation.scene.testing.lastSizeForTesting +import platform.test.motion.compose.DataPointTypes.intSize +import platform.test.motion.compose.DataPointTypes.offset +import platform.test.motion.golden.DataPoint +import platform.test.motion.golden.DataPointTypes +import platform.test.motion.golden.FeatureCapture + +/** + * [FeatureCapture] implementations to record animated state of [SceneTransitionLayout] [Element]. + */ +object FeatureCaptures { + + val elementAlpha = + FeatureCapture<SemanticsNode, Float>("alpha") { + DataPoint.of(it.lastAlphaForTesting, DataPointTypes.float) + } + + val elementScale = + FeatureCapture<SemanticsNode, Scale>("scale") { + DataPoint.of(it.lastScaleForTesting, scale) + } + + val elementOffset = + FeatureCapture<SemanticsNode, Offset>("offset") { + DataPoint.of(it.lastOffsetForTesting, offset) + } + + val elementSize = + FeatureCapture<SemanticsNode, IntSize>("size") { + DataPoint.of(it.lastSizeForTesting, intSize) + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/composable/BouncerPredictiveBackTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/composable/BouncerPredictiveBackTest.kt index d8a9719d2058..dda460a6198f 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/composable/BouncerPredictiveBackTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/composable/BouncerPredictiveBackTest.kt @@ -30,22 +30,17 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.geometry.isFinite -import androidx.compose.ui.geometry.isUnspecified -import androidx.compose.ui.semantics.SemanticsNode import androidx.compose.ui.test.junit4.AndroidComposeTestRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest import com.android.compose.animation.scene.ContentScope +import com.android.compose.animation.scene.FeatureCaptures.elementAlpha +import com.android.compose.animation.scene.FeatureCaptures.elementScale import com.android.compose.animation.scene.ObservableTransitionState -import com.android.compose.animation.scene.Scale import com.android.compose.animation.scene.SceneKey import com.android.compose.animation.scene.UserAction import com.android.compose.animation.scene.UserActionResult import com.android.compose.animation.scene.isElement -import com.android.compose.animation.scene.testing.lastAlphaForTesting -import com.android.compose.animation.scene.testing.lastScaleForTesting import com.android.compose.theme.PlatformTheme import com.android.systemui.SysuiTestCase import com.android.systemui.bouncer.domain.interactor.bouncerInteractor @@ -71,12 +66,12 @@ import com.android.systemui.scene.ui.composable.Scene import com.android.systemui.scene.ui.composable.SceneContainer import com.android.systemui.scene.ui.view.sceneJankMonitorFactory import com.android.systemui.testKosmos +import kotlin.test.Ignore import kotlin.time.Duration.Companion.seconds import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.flowOf -import org.json.JSONObject import org.junit.Before import org.junit.Rule import org.junit.Test @@ -89,14 +84,8 @@ import platform.test.motion.compose.MotionControl import platform.test.motion.compose.feature import platform.test.motion.compose.recordMotion import platform.test.motion.compose.runTest -import platform.test.motion.golden.DataPoint -import platform.test.motion.golden.DataPointType -import platform.test.motion.golden.DataPointTypes -import platform.test.motion.golden.FeatureCapture -import platform.test.motion.golden.UnknownTypeException import platform.test.screenshot.DeviceEmulationSpec import platform.test.screenshot.Displays.Phone -import kotlin.test.Ignore /** MotionTest for the Bouncer Predictive Back animation */ @LargeTest @@ -280,72 +269,4 @@ class BouncerPredictiveBackTest : SysuiTestCase() { override suspend fun onActivated() = awaitCancellation() } - - companion object { - private val elementAlpha = - FeatureCapture<SemanticsNode, Float>("alpha") { - DataPoint.of(it.lastAlphaForTesting, DataPointTypes.float) - } - - private val elementScale = - FeatureCapture<SemanticsNode, Scale>("scale") { - DataPoint.of(it.lastScaleForTesting, scale) - } - - private val scale: DataPointType<Scale> = - DataPointType( - "scale", - jsonToValue = { - when (it) { - "unspecified" -> Scale.Unspecified - "default" -> Scale.Default - "zero" -> Scale.Zero - is JSONObject -> { - val pivot = it.get("pivot") - Scale( - scaleX = it.getDouble("x").toFloat(), - scaleY = it.getDouble("y").toFloat(), - pivot = - when (pivot) { - "unspecified" -> Offset.Unspecified - "infinite" -> Offset.Infinite - is JSONObject -> - Offset( - pivot.getDouble("x").toFloat(), - pivot.getDouble("y").toFloat(), - ) - else -> throw UnknownTypeException() - }, - ) - } - else -> throw UnknownTypeException() - } - }, - valueToJson = { - when (it) { - Scale.Unspecified -> "unspecified" - Scale.Default -> "default" - Scale.Zero -> "zero" - else -> { - JSONObject().apply { - put("x", it.scaleX) - put("y", it.scaleY) - put( - "pivot", - when { - it.pivot.isUnspecified -> "unspecified" - !it.pivot.isFinite -> "infinite" - else -> - JSONObject().apply { - put("x", it.pivot.x) - put("y", it.pivot.y) - } - }, - ) - } - } - } - }, - ) - } } |