blob: 5866d66cf90d187f894cc57b5d7e055113113eec [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.android_webview.robolectric;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.view.DisplayCutout;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
import androidx.test.filters.SmallTest;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowLog;
import org.chromium.android_webview.AwDisplayCutoutController;
import org.chromium.android_webview.AwDisplayCutoutController.Insets;
import org.chromium.base.Log;
import org.chromium.base.test.util.Feature;
import org.chromium.testing.local.LocalRobolectricTestRunner;
/**
* JUnit tests for AwDisplayCutoutController.
*/
@RunWith(LocalRobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class AwDisplayCutoutControllerTest {
private static final String TAG = "DisplayCutoutTest";
private static final boolean DEBUG = false;
private InOrder mInOrder;
private Context mContext;
@Mock
private AwDisplayCutoutController.Delegate mDelegate;
@Mock
private WindowInsets mWindowInsets;
@Mock
private DisplayCutout mDisplayCutout;
@Mock
private View mView;
@Mock
private View mAnotherView;
@Mock
private ViewGroup mParentView;
@Mock
private ViewGroup mRootView;
private View.OnApplyWindowInsetsListener mListener;
private int[] mLocationOnScreen = {0, 0};
private int mViewWidth;
private int mViewHeight;
private Matrix mGlobalTransformMatrix;
private float mDipScale;
private int mDisplayWidth;
private int mDisplayHeight;
private AwDisplayCutoutController mController;
public AwDisplayCutoutControllerTest() {
if (DEBUG) ShadowLog.stream = System.out; // allows logging
}
@Before
public void setUp() {
if (DEBUG) Log.i(TAG, "setUp");
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
// Set up default values.
setWindowInsets(new Rect(20, 40, 60, 80));
mDipScale = 2.0f;
// Set up the view.
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
mListener = (View.OnApplyWindowInsetsListener) (invocation.getArguments()[0]);
return null;
}
})
.when(mView)
.setOnApplyWindowInsetsListener(any(View.OnApplyWindowInsetsListener.class));
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
mListener.onApplyWindowInsets(mView, mWindowInsets);
return null;
}
})
.when(mView)
.requestApplyInsets();
// Set up the delegate.
when(mDelegate.getDipScale()).thenReturn(mDipScale);
mInOrder = inOrder(mDelegate, mView, mAnotherView);
mController = new AwDisplayCutoutController(mDelegate, mView);
mInOrder.verify(mView).setOnApplyWindowInsetsListener(
any(View.OnApplyWindowInsetsListener.class));
mInOrder.verifyNoMoreInteractions();
}
private void setWindowInsets(Rect insets) {
when(mDisplayCutout.getSafeInsetLeft()).thenReturn(insets.left);
when(mDisplayCutout.getSafeInsetTop()).thenReturn(insets.top);
when(mDisplayCutout.getSafeInsetRight()).thenReturn(insets.right);
when(mDisplayCutout.getSafeInsetBottom()).thenReturn(insets.bottom);
// Note that prior to Android Q, there is no way to build WindowInsets.
when(mWindowInsets.getDisplayCutout()).thenReturn(mDisplayCutout);
}
@After
public void tearDown() {
if (DEBUG) Log.i(TAG, "tearDown");
mInOrder.verifyNoMoreInteractions();
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
public void testOnApplyWindowInsets() {
mController.onApplyWindowInsets(mWindowInsets);
mInOrder.verify(mDelegate).getDipScale();
// Note that DIP of 2.0 is applied, so the values are halved.
mInOrder.verify(mDelegate).setDisplayCutoutSafeArea(eq(new Insets(10, 20, 30, 40)));
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
public void testOnSizeChanged() {
mController.onSizeChanged();
mInOrder.verify(mView).requestApplyInsets();
mInOrder.verify(mDelegate).getDipScale();
// Note that DIP of 2.0 is applied, so the values are halved.
mInOrder.verify(mDelegate).setDisplayCutoutSafeArea(eq(new Insets(10, 20, 30, 40)));
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
public void testOnAttachedToWindow() {
mController.onAttachedToWindow();
mInOrder.verify(mView).requestApplyInsets();
mInOrder.verify(mDelegate).getDipScale();
// Note that DIP of 2.0 is applied, so the values are halved.
mInOrder.verify(mDelegate).setDisplayCutoutSafeArea(eq(new Insets(10, 20, 30, 40)));
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
public void testChangeContainerView_doesNotTriggerOriginalView() {
mController.registerContainerView(mAnotherView);
mInOrder.verify(mAnotherView)
.setOnApplyWindowInsetsListener(any(View.OnApplyWindowInsetsListener.class));
// Switching to another container view.
mController.setCurrentContainerView(mAnotherView);
mInOrder.verify(mAnotherView).requestApplyInsets();
mController.onAttachedToWindow();
// Note that mView methods are not triggered.
mInOrder.verify(mAnotherView).requestApplyInsets();
}
}