• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 platform.test.motion.compose
18 
19 import androidx.compose.ui.semantics.SemanticsNode
20 import androidx.compose.ui.test.SemanticsMatcher
21 import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
22 import androidx.compose.ui.unit.DpOffset
23 import androidx.compose.ui.unit.DpSize
24 import androidx.compose.ui.unit.IntSize
25 import androidx.compose.ui.unit.toSize
26 import platform.test.motion.compose.values.MotionTestValues
27 import platform.test.motion.golden.FeatureCapture
28 import platform.test.motion.golden.TimeSeriesCaptureScope
29 import platform.test.motion.golden.asDataPoint
30 
31 /** Common, generic [FeatureCapture] implementations for Compose. */
32 object ComposeFeatureCaptures {
33     /** Size of a node in pixels. */
<lambda>null34     val size = FeatureCapture<SemanticsNode, IntSize>("size") { it.size.asDataPoint() }
35     /** Size of a node in DPs. */
36     val dpSize =
<lambda>null37         FeatureCapture<SemanticsNode, DpSize>("size") {
38             with(it.layoutInfo.density) { it.size.toSize().toDpSize().asDataPoint() }
39         }
40     /**
41      * The position of this node relative to the root of this Compose hierarchy, with no clipping
42      * applied.
43      */
44     val positionInRoot =
<lambda>null45         FeatureCapture<SemanticsNode, DpOffset>("position") {
46             with(it.layoutInfo.density) {
47                 DpOffset(it.positionInRoot.x.toDp(), it.positionInRoot.y.toDp()).asDataPoint()
48             }
49         }
50 
51     /**
52      * Captures the `alpha` value of a node.
53      *
54      * IMPORTANT: the alpha-value can only be captured if it has been exported in the production
55      * code, see [MotionTestValues.alpha]
56      */
57     val alpha =
<lambda>null58         FeatureCapture<SemanticsNode, Float>("alpha") {
59             it.config[MotionTestValues.alpha.semanticsPropertyKey].asDataPoint()
60         }
61 }
62 
63 /**
64  * Captures the feature using [capture] from a node found via [matcher].
65  *
66  * If zero or more than one matching node is found, `DataPoint.notFound()` is recorded.
67  */
TimeSeriesCaptureScopenull68 fun TimeSeriesCaptureScope<SemanticsNodeInteractionsProvider>.feature(
69     matcher: SemanticsMatcher,
70     capture: FeatureCapture<SemanticsNode, *>,
71     name: String = capture.name,
72 ) {
73     on({
74         try {
75             it.onNode(matcher).fetchSemanticsNode()
76         } catch (e: AssertionError) {
77             null
78         }
79     }) {
80         feature(capture, name)
81     }
82 }
83