1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.components.browser_ui.widget;
6 
7 import static org.mockito.Mockito.any;
8 import static org.mockito.Mockito.never;
9 import static org.mockito.Mockito.reset;
10 import static org.mockito.Mockito.verify;
11 
12 import android.app.Activity;
13 import android.content.Context;
14 import android.graphics.Rect;
15 import android.support.test.filters.SmallTest;
16 import android.view.WindowInsets;
17 import android.widget.LinearLayout;
18 
19 import org.junit.Before;
20 import org.junit.Test;
21 import org.junit.runner.RunWith;
22 import org.mockito.Mock;
23 import org.mockito.MockitoAnnotations;
24 import org.robolectric.Robolectric;
25 import org.robolectric.annotation.Config;
26 
27 import org.chromium.testing.local.LocalRobolectricTestRunner;
28 
29 /**
30  * Tests for {@link InsetObserverView} class.
31  */
32 @RunWith(LocalRobolectricTestRunner.class)
33 @Config(manifest = Config.NONE)
34 public class InsetObserverViewTest {
35     /** The rect values if the display cutout is present. */
36     private static final Rect DISPLAY_CUTOUT_RECT = new Rect(1, 1, 1, 1);
37 
38     /** The rect values if there is no cutout. */
39     private static final Rect NO_CUTOUT_RECT = new Rect(0, 0, 0, 0);
40 
41     /** Mock Android P+ Display Cutout class. */
42     private static class DisplayCutout {
getSafeInsetLeft()43         public int getSafeInsetLeft() {
44             return 1;
45         }
46 
getSafeInsetTop()47         public int getSafeInsetTop() {
48             return 1;
49         }
50 
getSafeInsetRight()51         public int getSafeInsetRight() {
52             return 1;
53         }
54 
getSafeInsetBottom()55         public int getSafeInsetBottom() {
56             return 1;
57         }
58     }
59 
60     /** This is a {@InsetObserverView} that will use a fake display cutout. */
61     private static class TestInsetObserverView extends InsetObserverView.InsetObserverViewApi28 {
62         private Object mDisplayCutout;
63 
TestInsetObserverView(Context context, Object displayCutout)64         TestInsetObserverView(Context context, Object displayCutout) {
65             super(context);
66             mDisplayCutout = displayCutout;
67         }
68 
69         @Override
extractDisplayCutout(WindowInsets insets)70         protected Object extractDisplayCutout(WindowInsets insets) {
71             return mDisplayCutout;
72         }
73 
setDisplayCutout(DisplayCutout displayCutout)74         public void setDisplayCutout(DisplayCutout displayCutout) {
75             mDisplayCutout = displayCutout;
76         }
77     }
78 
79     @Mock
80     private InsetObserverView.WindowInsetObserver mObserver;
81 
82     @Mock
83     private WindowInsets mInsets;
84 
85     private Activity mActivity;
86 
87     private TestInsetObserverView mView;
88 
89     private LinearLayout mContentView;
90 
91     @Before
setUp()92     public void setUp() {
93         MockitoAnnotations.initMocks(this);
94 
95         mActivity = Robolectric.buildActivity(Activity.class).setup().get();
96         mContentView = new LinearLayout(mActivity);
97         mActivity.setContentView(mContentView);
98     }
99 
100     /** Test that applying new insets does not notify the observer.. */
101     @Test
102     @SmallTest
applyInsets()103     public void applyInsets() {
104         mView = new TestInsetObserverView(mActivity, null);
105         mView.addObserver(mObserver);
106 
107         mView.onApplyWindowInsets(mInsets);
108         verify(mObserver, never()).onSafeAreaChanged(any());
109     }
110 
111     /** Test that applying new insets with a cutout notifies the observer. */
112     @Test
113     @SmallTest
applyInsets_WithCutout()114     public void applyInsets_WithCutout() {
115         mView = new TestInsetObserverView(mActivity, new DisplayCutout());
116         mView.addObserver(mObserver);
117 
118         mView.onApplyWindowInsets(mInsets);
119         verify(mObserver).onSafeAreaChanged(DISPLAY_CUTOUT_RECT);
120     }
121 
122     /** Test applying new insets with a cutout and then remove the cutout. */
123     @Test
124     @SmallTest
applyInsets_WithCutout_WithoutCutout()125     public void applyInsets_WithCutout_WithoutCutout() {
126         mView = new TestInsetObserverView(mActivity, new DisplayCutout());
127         mView.addObserver(mObserver);
128 
129         mView.onApplyWindowInsets(mInsets);
130         verify(mObserver).onSafeAreaChanged(DISPLAY_CUTOUT_RECT);
131 
132         reset(mObserver);
133         mView.setDisplayCutout(null);
134         mView.onApplyWindowInsets(mInsets);
135         verify(mObserver).onSafeAreaChanged(NO_CUTOUT_RECT);
136     }
137 
138     /** Test that applying new insets with a cutout but no observer is a no-op. */
139     @Test
140     @SmallTest
applyInsets_WithCutout_NoListener()141     public void applyInsets_WithCutout_NoListener() {
142         mView = new TestInsetObserverView(mActivity, new DisplayCutout());
143         mView.onApplyWindowInsets(mInsets);
144     }
145 
146     /** Test that applying new insets with no observer is a no-op. */
147     @Test
148     @SmallTest
applyInsets_NoListener()149     public void applyInsets_NoListener() {
150         mView = new TestInsetObserverView(mActivity, null);
151         mView.onApplyWindowInsets(mInsets);
152     }
153 }
154