1 /* <lambda>null2 * Copyright (C) 2021 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 androidx.constraintlayout.compose 18 19 import android.content.Context 20 import androidx.compose.foundation.layout.Box 21 import androidx.compose.foundation.layout.size 22 import androidx.compose.ui.Modifier 23 import androidx.compose.ui.layout.layoutId 24 import androidx.compose.ui.platform.isDebugInspectorInfoEnabled 25 import androidx.compose.ui.test.junit4.createComposeRule 26 import androidx.compose.ui.unit.IntSize 27 import androidx.compose.ui.unit.dp 28 import androidx.constraintlayout.core.parser.CLParser 29 import androidx.constraintlayout.core.parser.CLParsingException 30 import androidx.constraintlayout.core.state.TransitionParser 31 import androidx.test.core.app.ApplicationProvider 32 import androidx.test.ext.junit.runners.AndroidJUnit4 33 import androidx.test.filters.MediumTest 34 import kotlin.test.assertFailsWith 35 import org.junit.After 36 import org.junit.Before 37 import org.junit.Rule 38 import org.junit.Test 39 import org.junit.runner.RunWith 40 41 @MediumTest 42 @RunWith(AndroidJUnit4::class) 43 internal class MotionParserTest { 44 @get:Rule val rule = createComposeRule() 45 46 var displaySize: IntSize = IntSize.Zero 47 48 // region sizing tests 49 50 @Before 51 fun before() { 52 isDebugInspectorInfoEnabled = true 53 displaySize = 54 ApplicationProvider.getApplicationContext<Context>().resources.displayMetrics.let { 55 IntSize(it.widthPixels, it.heightPixels) 56 } 57 } 58 59 @After 60 fun after() { 61 isDebugInspectorInfoEnabled = false 62 } 63 64 @OptIn(ExperimentalMotionApi::class) 65 @Test 66 fun testTransitionParseFailsSilently() { 67 // We don't want applications to hard-crash when the parser sees an error 68 var coreTransition = androidx.constraintlayout.core.state.Transition { dp -> dp } 69 val transitionContent = 70 """ 71 { 72 from: "start", 73 to: "end", 74 KeyFrames: { 75 KeyAttributes: [{ 76 target: ['id1'], 77 frames: [10, 20], 78 alpha: [0.5,], 79 }], 80 } 81 } 82 """ 83 .trimIndent() 84 // Parsing transition throws an exception but the Composable should not crash the app 85 assertFailsWith<CLParsingException> { 86 TransitionParser.parse(CLParser.parse(transitionContent), coreTransition) 87 } 88 coreTransition = androidx.constraintlayout.core.state.Transition { dp -> dp } 89 rule.setContent { 90 val transition = Transition(content = transitionContent) 91 MotionLayout( 92 modifier = Modifier.size(100.dp), 93 start = 94 ConstraintSet( 95 """ 96 { 97 id1: { 98 width: 10, height: 10, 99 centerVertically: 'parent', start: ['parent', 'start', 0] 100 } 101 } 102 """ 103 .trimIndent() 104 ), 105 end = 106 ConstraintSet( 107 """ 108 { 109 id1: { 110 width: 10, height: 10, 111 centerVertically: 'parent', end: ['parent', 'end', 0] 112 } 113 } 114 """ 115 .trimIndent() 116 ), 117 transition = transition, 118 progress = 0f 119 ) { 120 Box(modifier = Modifier.layoutId("id1")) 121 } 122 } 123 // Test should finish without exceptions 124 rule.waitForIdle() 125 } 126 } 127