1 /*
2  * Copyright 2019 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.compose.testutils
18 
19 import androidx.compose.runtime.Composable
20 import androidx.compose.ui.UiComposable
21 
22 /**
23  * To be implemented to provide a test case that is then executed by [ComposeTestRule] or can be
24  * used in benchmarks.
25  */
26 interface ComposeTestCase {
27     /**
28      * This method is guaranteed to be called only once per class lifetime. In case a benchmark
29      * needs to measure initial composition / measure / layout / draw it re-creates this class every
30      * time it needs to call Content again. This ensures that any setup you do in this class is not
31      * shared between multiple calls of this method. So the init method is a good place to setup /
32      * clean your caches.
33      */
Contentnull34     @Composable fun Content()
35 }
36 
37 /** To be implemented to provide a test case that is then executed in benchmarks. */
38 // TODO(b/185389423): Make this to be an interface once the compiler gets fixed.
39 abstract class LayeredComposeTestCase : ComposeTestCase {
40     /**
41      * This method is guaranteed to be called only once per class lifetime. In case a benchmark
42      * needs to measure initial composition / measure / layout / draw it re-creates this class every
43      * time it needs to call emitContent again. This ensures that any setup you do in this class is
44      * not shared between multiple calls of this method. So the init method is a good place to setup
45      * / clean your caches.
46      */
47     @Composable
48     override fun Content() {
49         ContentWrappers { MeasuredContent() }
50     }
51 
52     /**
53      * This method should emit content that is supposed to be measured. Any other helper containers,
54      * CompositionLocals and themes should be set in [ContentWrappers].
55      *
56      * The lifecycle rules for this method are same as for [Content]
57      */
58     @Composable abstract fun MeasuredContent()
59 
60     /**
61      * Receives the result of [MeasuredContent].
62      *
63      * In "first" benchmarks this method's content is set up before the content from
64      * [MeasuredContent] gets introduced to be measured. This helps to avoid measuring helper
65      * containers or CompositionLocal setups.
66      *
67      * The lifecycle rules for this method are same as for [Content]
68      */
69     @Composable
70     @UiComposable
71     open fun ContentWrappers(content: @Composable () -> Unit) {
72         content()
73     }
74 }
75