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