1 /*
2  * Copyright 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.window.testing.layout
18 
19 import androidx.window.layout.WindowInfoTracker
20 import androidx.window.layout.WindowLayoutInfo
21 import kotlinx.coroutines.channels.BufferOverflow.DROP_OLDEST
22 import kotlinx.coroutines.flow.MutableSharedFlow
23 import org.junit.rules.TestRule
24 import org.junit.runner.Description
25 import org.junit.runners.model.Statement
26 
27 /**
28  * A [TestRule] to help test consuming a stream of [WindowLayoutInfo] values.
29  * [WindowLayoutInfoPublisherRule] allows you to push through different [WindowLayoutInfo] values on
30  * demand.
31  *
32  * Here are some recommended testing scenarios.
33  *
34  * To test the scenario where no [WindowLayoutInfo] is ever emitted. Just set the rule as a standard
35  * rule.
36  *
37  * To test sending a generic feature build your own [WindowLayoutInfo] and publish it through the
38  * method [WindowLayoutInfoPublisherRule.overrideWindowLayoutInfo].
39  *
40  * Some helper methods are provided to test the following scenarios.
41  * <ul>
42  * <li>A fold in the middle and the dimension matches the shortest window dimension.</li>
43  * <li>A fold in the middle and the dimension matches the longest window dimension.</li>
44  * <li>A fold in the middle and has vertical orientation.</li>
45  * <li>A fold in the middle and has horizontal orientation.</li>
46  * </ul>
47  */
48 class WindowLayoutInfoPublisherRule : TestRule {
49 
50     private val flow =
51         MutableSharedFlow<WindowLayoutInfo>(extraBufferCapacity = 1, onBufferOverflow = DROP_OLDEST)
52     private val overrideServices = PublishWindowInfoTrackerDecorator(flow)
53 
applynull54     override fun apply(base: Statement, description: Description): Statement {
55         return object : Statement() {
56             override fun evaluate() {
57                 WindowInfoTracker.overrideDecorator(overrideServices)
58                 try {
59                     base.evaluate()
60                 } finally {
61                     WindowInfoTracker.reset()
62                 }
63             }
64         }
65     }
66 
67     /**
68      * Send an arbitrary [WindowLayoutInfo] through
69      * [androidx.window.layout.WindowInfoTracker.windowLayoutInfo]. Each event is sent only once.
70      */
overrideWindowLayoutInfonull71     fun overrideWindowLayoutInfo(info: WindowLayoutInfo) {
72         flow.tryEmit(info)
73     }
74 }
75