1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.compose.animation.scene.transformation 18 19 import android.platform.test.annotations.MotionTest 20 import androidx.compose.animation.core.LinearEasing 21 import androidx.compose.animation.core.tween 22 import androidx.compose.foundation.layout.Box 23 import androidx.compose.foundation.layout.size 24 import androidx.compose.runtime.Composable 25 import androidx.compose.ui.Modifier 26 import androidx.compose.ui.unit.dp 27 import androidx.test.ext.junit.runners.AndroidJUnit4 28 import com.android.compose.animation.scene.SceneScope 29 import com.android.compose.animation.scene.TestElements 30 import com.android.compose.animation.scene.TransitionBuilder 31 import com.android.compose.animation.scene.TransitionRecordingSpec 32 import com.android.compose.animation.scene.featureOfElement 33 import com.android.compose.animation.scene.recordTransition 34 import org.junit.Rule 35 import org.junit.Test 36 import org.junit.runner.RunWith 37 import platform.test.motion.compose.ComposeFeatureCaptures 38 import platform.test.motion.compose.createComposeMotionTestRule 39 import platform.test.motion.testing.createGoldenPathManager 40 41 @RunWith(AndroidJUnit4::class) 42 @MotionTest 43 class AnchoredSizeTest { 44 private val goldenPaths = 45 createGoldenPathManager("frameworks/base/packages/SystemUI/compose/scene/tests/goldens") 46 47 @get:Rule val motionRule = createComposeMotionTestRule(goldenPaths) 48 49 @Test testAnchoredSizeEnternull50 fun testAnchoredSizeEnter() { 51 assertBarSizeMatchesGolden( 52 fromSceneContent = { Box(Modifier.size(100.dp, 100.dp).element(TestElements.Foo)) }, 53 toSceneContent = { 54 Box(Modifier.size(50.dp, 50.dp).element(TestElements.Foo)) 55 Box(Modifier.size(200.dp, 60.dp).element(TestElements.Bar)) 56 }, 57 transition = { 58 spec = tween(16 * 4, easing = LinearEasing) 59 anchoredSize(TestElements.Bar, TestElements.Foo) 60 } 61 ) 62 } 63 64 @Test testAnchoredSizeExitnull65 fun testAnchoredSizeExit() { 66 assertBarSizeMatchesGolden( 67 fromSceneContent = { 68 Box(Modifier.size(100.dp, 100.dp).element(TestElements.Foo)) 69 Box(Modifier.size(100.dp, 100.dp).element(TestElements.Bar)) 70 }, 71 toSceneContent = { Box(Modifier.size(200.dp, 60.dp).element(TestElements.Foo)) }, 72 transition = { 73 // Scale during 4 frames. 74 spec = tween(16 * 4, easing = LinearEasing) 75 anchoredSize(TestElements.Bar, TestElements.Foo) 76 } 77 ) 78 } 79 80 @Test testAnchoredWidthOnlynull81 fun testAnchoredWidthOnly() { 82 assertBarSizeMatchesGolden( 83 fromSceneContent = { Box(Modifier.size(100.dp, 100.dp).element(TestElements.Foo)) }, 84 toSceneContent = { 85 Box(Modifier.size(50.dp, 50.dp).element(TestElements.Foo)) 86 Box(Modifier.size(200.dp, 60.dp).element(TestElements.Bar)) 87 }, 88 transition = { 89 spec = tween(16 * 4, easing = LinearEasing) 90 anchoredSize(TestElements.Bar, TestElements.Foo, anchorHeight = false) 91 }, 92 ) 93 } 94 95 @Test testAnchoredHeightOnlynull96 fun testAnchoredHeightOnly() { 97 assertBarSizeMatchesGolden( 98 fromSceneContent = { Box(Modifier.size(100.dp, 100.dp).element(TestElements.Foo)) }, 99 toSceneContent = { 100 Box(Modifier.size(50.dp, 50.dp).element(TestElements.Foo)) 101 Box(Modifier.size(200.dp, 60.dp).element(TestElements.Bar)) 102 }, 103 transition = { 104 spec = tween(16 * 4, easing = LinearEasing) 105 anchoredSize(TestElements.Bar, TestElements.Foo, anchorWidth = false) 106 } 107 ) 108 } 109 assertBarSizeMatchesGoldennull110 private fun assertBarSizeMatchesGolden( 111 fromSceneContent: @Composable SceneScope.() -> Unit, 112 toSceneContent: @Composable SceneScope.() -> Unit, 113 transition: TransitionBuilder.() -> Unit, 114 ) { 115 val recordingSpec = 116 TransitionRecordingSpec(recordAfter = true) { 117 featureOfElement(TestElements.Bar, ComposeFeatureCaptures.dpSize) 118 } 119 120 val motion = 121 motionRule.recordTransition(fromSceneContent, toSceneContent, transition, recordingSpec) 122 123 motionRule.assertThat(motion).timeSeriesMatchesGolden() 124 } 125 } 126