/* * Copyright (C) 2015 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.android.switchaccess.test; import android.annotation.TargetApi; import android.content.Context; import android.graphics.Paint; import android.graphics.Rect; import android.os.Build; import android.view.View; import android.view.WindowManager; import android.widget.ImageView; import android.widget.RelativeLayout; import com.android.switchaccess.OverlayController; import com.android.talkback.BuildConfig; import com.android.utils.widget.SimpleOverlay; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.robolectric.Robolectric; import org.robolectric.RobolectricGradleTestRunner; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import java.util.Arrays; import java.util.List; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.*; import static org.mockito.Mockito.when; /** * Tests for OverlayController */ /** * Tests for ContextMenuController */ @Config( constants = BuildConfig.class, sdk = 21) @RunWith(RobolectricGradleTestRunner.class) @TargetApi(Build.VERSION_CODES.LOLLIPOP) public class OverlayControllerTest { private static final Rect BOUNDS0 = new Rect(130, 140, 200, 250); // 70x110 private static final Rect BOUNDS1 = new Rect(130, 260, 200, 300); // 70x40 /* * Choose offsets large enough that getting them wrong or transposing them would move * the highlight enough to include the wrong rectangles */ private static final int RELATIVE_LAYOUT_X_OFFSET = 50; private static final int RELATIVE_LAYOUT_Y_OFFSET = 100; private final Context mContext = RuntimeEnvironment.application.getApplicationContext(); private SimpleOverlay mMockSimpleOverlay = mock(SimpleOverlay.class); private RelativeLayout mMockRelativeLayout = mock(RelativeLayout.class); private OverlayController mOverlayController; @Before public void setUp() { WindowManager.LayoutParams overlayLayoutParams = new WindowManager.LayoutParams(); when(mMockSimpleOverlay.findViewById(anyInt())).thenReturn(mMockRelativeLayout); when(mMockSimpleOverlay.getParams()).thenReturn(overlayLayoutParams); when(mMockSimpleOverlay.getContext()).thenReturn(mContext); mOverlayController = new OverlayController(mMockSimpleOverlay); doAnswer(new Answer<Void>() { @Override public Void answer(InvocationOnMock invocation) throws Throwable { int[] locationOnScreen = (int[]) invocation.getArguments()[0]; locationOnScreen[0] = RELATIVE_LAYOUT_X_OFFSET; locationOnScreen[1] = RELATIVE_LAYOUT_Y_OFFSET; return null; } }).when(mMockRelativeLayout).getLocationOnScreen((int[]) anyObject()); } @Test public void testAtStartup_overlayNotShown() { verify(mMockSimpleOverlay, times(0)).show(); } @Test public void testConfigure_systemOverlayIsNotTouchable() { mOverlayController.configureOverlay(); ArgumentCaptor<WindowManager.LayoutParams> layoutParamsArgumentCaptor = ArgumentCaptor.forClass(WindowManager.LayoutParams.class); verify(mMockSimpleOverlay, atLeastOnce()).setParams(layoutParamsArgumentCaptor.capture()); WindowManager.LayoutParams layoutParams = layoutParamsArgumentCaptor.getValue(); assertEquals(WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, layoutParams.type); assertTrue((layoutParams.flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0); } @Test public void testHighlightPerimeterOfRects_singleRectHighlighted() { mOverlayController.highlightPerimeterOfRects(Arrays.asList(BOUNDS0), new Paint()); ArgumentCaptor<ImageView> highlightViewCaptor = ArgumentCaptor.forClass(ImageView.class); verify(mMockRelativeLayout, times(1)).addView(highlightViewCaptor.capture()); ImageView highlightView = highlightViewCaptor.getValue(); RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) highlightView.getLayoutParams(); assertTrue(paramsBoundsRect(layoutParams, BOUNDS0)); } @Test public void testHighlightPerimeterOfRects_twoRectHighlighted() { mOverlayController.highlightPerimeterOfRects(Arrays.asList(BOUNDS0, BOUNDS1), new Paint()); ArgumentCaptor<ImageView> highlightViewCaptor = ArgumentCaptor.forClass(ImageView.class); verify(mMockRelativeLayout, times(2)).addView(highlightViewCaptor.capture()); List<ImageView> highlightViews = highlightViewCaptor.getAllValues(); ImageView highlightView0 = highlightViews.get(0); ImageView highlightView1 = highlightViews.get(1); RelativeLayout.LayoutParams layoutParams0 = (RelativeLayout.LayoutParams) highlightView0.getLayoutParams(); RelativeLayout.LayoutParams layoutParams1 = (RelativeLayout.LayoutParams) highlightView1.getLayoutParams(); if (paramsBoundsRect(layoutParams0, BOUNDS0)) { assertTrue(paramsBoundsRect(layoutParams1, BOUNDS1)); } else { assertTrue(paramsBoundsRect(layoutParams0, BOUNDS1)); assertTrue(paramsBoundsRect(layoutParams1, BOUNDS0)); } } @Test public void testAddViewAndShow_doesAddViewAndShow() { View view = new View(mContext); mOverlayController.addViewAndShow(view); verify(mMockRelativeLayout, times(1)).addView(view); verify(mMockSimpleOverlay, times(1)).show(); } @Test public void testClearOverlay_removesAllViewsAndHides() { mOverlayController.clearOverlay(); verify(mMockRelativeLayout, times(1)).removeAllViews(); verify(mMockSimpleOverlay, times(1)).hide(); } @Test public void testShutdown_hides() { mOverlayController.shutdown(); verify(mMockSimpleOverlay, times(1)).hide(); } private boolean paramsBoundsRect(RelativeLayout.LayoutParams layoutParams, Rect rect) { boolean result = (layoutParams.leftMargin <= rect.left - RELATIVE_LAYOUT_X_OFFSET); result = result && (layoutParams.topMargin <= rect.top - RELATIVE_LAYOUT_Y_OFFSET); result = result && (layoutParams.leftMargin + layoutParams.width >= rect.right - RELATIVE_LAYOUT_X_OFFSET); result = result && (layoutParams.topMargin + layoutParams.height >= rect.bottom - RELATIVE_LAYOUT_Y_OFFSET); return result; } }