@Test public void testMoveToParent_nowhereToGoWithWrap_shouldClearFocus() { mOptionManager.clearFocusIfNewTree(mSelectionNode); mOptionManager.selectOption(0); mOptionManager.moveToParent(true); /* Confirm that we're on null selection by moving to a child */ mOptionManager.selectOption(0); assertEquals(0, mShadowInfo1.getPerformedActions().size()); mOptionManager.selectOption(0); assertEquals(1, mShadowInfo1.getPerformedActions().size()); }
@Test public void testScrollWithParent_shouldScrollAndClearFocus() { AccessibilityNodeInfoCompat parent = AccessibilityNodeInfoCompat.obtain(); ((ShadowAccessibilityNodeInfoCompat) ShadowExtractor.extract(parent)).addChild(mCompat1); ShadowAccessibilityNodeInfo shadowParent = (ShadowAccessibilityNodeInfo) ShadowExtractor.extract(parent.getInfo()); parent.setScrollable(true); mActionNode1.recycle(); mActionNode1 = new AccessibilityNodeActionNode( mCompat1, new AccessibilityNodeInfoCompat.AccessibilityActionCompat( AccessibilityNodeInfoCompat.ACTION_CLICK, "label1")); mSelectionNode = new OptionScanSelectionNode(mActionNode1, mActionNode2); mOptionManager.clearFocusIfNewTree(mSelectionNode); mOptionManager.selectOption(0); mOptionManager.performScrollAction(AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD); assertEquals(0, mShadowInfo1.getPerformedActions().size()); List<Integer> parentActions = shadowParent.getPerformedActions(); assertEquals(1, parentActions.size()); assertEquals( new Integer(AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD), parentActions.get(0)); verify(mOverlayController, times(3)).clearOverlay(); parent.recycle(); }
@Test public void testOptionScanningEnabled_highlightsMenuButton() { mSharedPreferences .edit() .putString( mContext.getString(R.string.pref_scanning_methods_key), mContext.getString(R.string.option_scanning_key)) .commit(); mOptionManager.onSharedPreferenceChanged(mSharedPreferences, null); when(mOverlayController.getMenuButtonLocation()).thenReturn(MENU_BUTTON_BOUNDS); /* add a context menu with two items to the tree */ CharSequence globalActionLabel0 = "global action label 0"; CharSequence globalActionLabel1 = "global action label 1"; GlobalActionNode globalNode0 = new GlobalActionNode(0, null, globalActionLabel0); GlobalActionNode globalNode1 = new GlobalActionNode(1, null, globalActionLabel1); ContextMenuNode contextMenu = new ContextMenuNode(globalNode0, globalNode1); mSelectionNode = new OptionScanSelectionNode(mSelectionNode, contextMenu); mOptionManager.clearFocusIfNewTree(mSelectionNode); mOptionManager.selectOption(0); verify(mOverlayController, times(1)).drawMenuButton(); ShadowHandler.runMainLooperToEndOfTasks(); verify(mOverlayController, times(2)) .highlightPerimeterOfRects(mHighlightCaptor.capture(), mPaintCaptor.capture()); List<Collection<Rect>> capturedHighlights = mHighlightCaptor.getAllValues(); assertTrue(capturedHighlights.get(0).contains(NODE_BOUNDS_1)); assertTrue(capturedHighlights.get(0).contains(NODE_BOUNDS_2)); assertTrue(capturedHighlights.get(1).contains(MENU_BUTTON_BOUNDS)); }
@Test public void testSelectionNodeWithSettingsCleared_shouldHighlightWithDefault() { mSharedPreferences.edit().clear().commit(); mOptionManager = new OptionManager(mOverlayController); mOptionManager.clearFocusIfNewTree(mSelectionNode); mOptionManager.selectOption(0); verify(mOverlayController, times(2)) .highlightPerimeterOfRects(mHighlightCaptor.capture(), mPaintCaptor.capture()); /* One paint should be transparent; the other should be the default green */ List<Collection<Rect>> capturedHighlights = mHighlightCaptor.getAllValues(); List<Paint> capturedPaints = mPaintCaptor.getAllValues(); int defaultIndex = 0; int transparentIndex = 1; if (capturedPaints.get(0).getColor() == Color.TRANSPARENT) { transparentIndex = 0; defaultIndex = 1; } assertEquals(Color.TRANSPARENT, capturedPaints.get(transparentIndex).getColor()); assertEquals(DEFAULT_HIGHLIGHT_COLOR, capturedPaints.get(defaultIndex).getColor()); assertEquals(0xff, capturedPaints.get(defaultIndex).getAlpha()); DisplayMetrics dm = mContext.getResources().getDisplayMetrics(); float expectedStrokeWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, dm); assertEquals(expectedStrokeWidth, capturedPaints.get(defaultIndex).getStrokeWidth(), 0.01); assertTrue(capturedHighlights.get(defaultIndex).contains(NODE_BOUNDS_1)); assertTrue(capturedHighlights.get(transparentIndex).contains(NODE_BOUNDS_2)); }
@Test public void testOnlyOneActionNode_shouldClearFocusAndOverlayWhenActionPerformed() { mOptionManager.addFocusClearedListener(mMockListener); mOptionManager.clearFocusIfNewTree(mActionNode1); mOptionManager.selectOption(0); verify(mMockListener, times(2)).onOptionManagerClearedFocus(); verify(mOverlayController, times(2)).clearOverlay(); }
@Test public void testMoveToParent_hasParent_shouldRefocusOnParent() { OptionScanSelectionNode mockSelectionNode = mock(OptionScanSelectionNode.class); mSelectionNode.setParent(mockSelectionNode); mOptionManager.clearFocusIfNewTree(mSelectionNode); mOptionManager.selectOption(0); mOptionManager.moveToParent(false); verify(mockSelectionNode, times(1)).performAction(); }
@Test public void testStartScanningWithListener_shouldCallScanStart() { OptionManager.ScanListener mockListener = mock(OptionManager.ScanListener.class); mOptionManager.setScanListener(mockListener); mOptionManager.clearFocusIfNewTree(mSelectionNode); mOptionManager.selectOption(0); verify(mockListener, times(1)).onScanStart(); verify(mockListener, times(1)).onScanFocusChanged(); verifyNoMoreInteractions(mockListener); }
@Test public void testLongClickWithTwoOptions_shouldDoNothing() { OptionScanSelectionNode superParentNode = new OptionScanSelectionNode(mSelectionNode, mSelectionNode); mOptionManager.clearFocusIfNewTree(superParentNode); mOptionManager.selectOption(0); mOptionManager.performLongClick(); assertEquals(0, mShadowInfo1.getPerformedActions().size()); assertEquals(0, mShadowInfo2.getPerformedActions().size()); }
@Test public void testMoveToParent_fromNull_shouldWrap() { OptionScanSelectionNode topSelectionNode = new OptionScanSelectionNode(mActionNode1, mSelectionNode); mOptionManager.clearFocusIfNewTree(topSelectionNode); mOptionManager.moveToParent(true); /* Confirm that we're on mSelectionNode by moving to a child */ mOptionManager.selectOption(0); assertEquals(1, mShadowInfo1.getPerformedActions().size()); }
@Test public void testLongClickWithOneOptionThatSucceeds_shouldLongClickAndClearFocus() { mOptionManager.clearFocusIfNewTree(mSelectionNode); mOptionManager.selectOption(0); mOptionManager.performLongClick(); List<Integer> info1Actions = mShadowInfo1.getPerformedActions(); assertEquals(1, info1Actions.size()); assertEquals(new Integer(AccessibilityNodeInfoCompat.ACTION_LONG_CLICK), info1Actions.get(0)); verify(mOverlayController, times(3)).clearOverlay(); }
@Test public void testHighlightStylesForOptionScanning_defaultsAreDifferent() { mOptionManager.onSharedPreferenceChanged(mSharedPreferences, null); mOptionManager.clearFocusIfNewTree(mSelectionNode); mOptionManager.selectOption(0); verify(mOverlayController, times(2)) .highlightPerimeterOfRects(mHighlightCaptor.capture(), mPaintCaptor.capture()); /* The two paint colors should be different */ List<Paint> capturedPaints = mPaintCaptor.getAllValues(); assertFalse(capturedPaints.get(0).getColor() == capturedPaints.get(1).getColor()); }
@Test public void userAbortsScanWithExtraSwitch_shouldCallNoSelection() { OptionManager.ScanListener mockListener = mock(OptionManager.ScanListener.class); mOptionManager.setScanListener(mockListener); mOptionManager.clearFocusIfNewTree(mSelectionNode); mOptionManager.selectOption(0); mOptionManager.selectOption(2); verify(mockListener, times(1)).onScanStart(); verify(mockListener, times(1)).onScanFocusChanged(); verify(mockListener, times(1)).onScanCompletedWithNoSelection(); verifyNoMoreInteractions(mockListener); }
@Test public void testOptionScanningDisabled_NoMenuButtonDrawn() { /* add a context menu with two items to the tree */ CharSequence globalActionLabel0 = "global action label 0"; CharSequence globalActionLabel1 = "global action label 1"; GlobalActionNode globalNode0 = new GlobalActionNode(0, null, globalActionLabel0); GlobalActionNode globalNode1 = new GlobalActionNode(1, null, globalActionLabel1); ContextMenuNode contextMenu = new ContextMenuNode(globalNode0, globalNode1); mSelectionNode = new OptionScanSelectionNode(mSelectionNode, contextMenu); mOptionManager.clearFocusIfNewTree(mSelectionNode); mOptionManager.selectOption(0); verify(mOverlayController, times(0)).drawMenuButton(); }
@Test public void scanningReachesClearFocusNode_shouldCallNoSelection() { OptionManager.ScanListener mockListener = mock(OptionManager.ScanListener.class); mOptionManager.setScanListener(mockListener); mActionNode2.recycle(); mSelectionNode = new OptionScanSelectionNode(mActionNode1, new ClearFocusNode()); mOptionManager.clearFocusIfNewTree(mSelectionNode); mOptionManager.selectOption(0); mOptionManager.selectOption(1); verify(mockListener, times(1)).onScanStart(); verify(mockListener, times(1)).onScanFocusChanged(); verify(mockListener, times(1)).onScanCompletedWithNoSelection(); verifyNoMoreInteractions(mockListener); }
/** Called when auto scan key is pressed */ public void autoScanActivated(boolean reverseScan) { if (!mIsScanInProgress) { startScan(reverseScan); return; } if (mReverseScan != reverseScan) { mReverseScan = reverseScan; return; } /* The user made a selection. Stop moving focus. */ mHandler.removeCallbacks(mAutoScanRunnable); mOptionManager.selectOption(OptionManager.OPTION_INDEX_CLICK); /* Re-start scanning on the updated tree if focus wasn't cleared */ if (mIsScanInProgress) { mHandler.postDelayed(mAutoScanRunnable, getAutoScanDelay()); } }
@Test public void testSelectionNodeWithOptionScanning_shouldHighlightTwoOptions() { mSharedPreferences .edit() .putString( mContext.getString(R.string.pref_highlight_0_color_key), mContext.getString(R.string.material_orange_500)) .putString( mContext.getString(R.string.pref_highlight_0_weight_key), mContext.getString(R.string.thickness_4_dp)) .putString( mContext.getString(R.string.pref_highlight_1_color_key), mContext.getString(R.string.material_blue_500)) .putString( mContext.getString(R.string.pref_highlight_1_weight_key), mContext.getString(R.string.thickness_4_dp)) .putString( mContext.getString(R.string.pref_scanning_methods_key), mContext.getString(R.string.option_scanning_key)) .commit(); mOptionManager.onSharedPreferenceChanged(mSharedPreferences, null); mOptionManager.clearFocusIfNewTree(mSelectionNode); mOptionManager.selectOption(0); verify(mOverlayController, times(2)) .highlightPerimeterOfRects(mHighlightCaptor.capture(), mPaintCaptor.capture()); /* One paint should be blue; the other should be orange */ List<Collection<Rect>> capturedHighlights = mHighlightCaptor.getAllValues(); List<Paint> capturedPaints = mPaintCaptor.getAllValues(); int orangeIndex = 0; int blueIndex = 1; if (capturedPaints.get(0).getColor() == BLUE_500_COLOR) { blueIndex = 0; orangeIndex = 1; } assertEquals(BLUE_500_COLOR, capturedPaints.get(blueIndex).getColor()); assertEquals(ORANGE_500_COLOR, capturedPaints.get(orangeIndex).getColor()); assertEquals(0xff, capturedPaints.get(orangeIndex).getAlpha()); DisplayMetrics dm = mContext.getResources().getDisplayMetrics(); float expectedStrokeWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, dm); assertEquals(expectedStrokeWidth, capturedPaints.get(orangeIndex).getStrokeWidth(), 0.01); assertTrue(capturedHighlights.get(orangeIndex).contains(NODE_BOUNDS_1)); assertTrue(capturedHighlights.get(blueIndex).contains(NODE_BOUNDS_2)); }
@Test public void testScrollWithOneOptionThatSucceeds_shouldScrollAndClearFocus() { mCompat1.setScrollable(true); mActionNode1.recycle(); mActionNode1 = new AccessibilityNodeActionNode( mCompat1, new AccessibilityNodeInfoCompat.AccessibilityActionCompat( AccessibilityNodeInfoCompat.ACTION_CLICK, "label1")); mSelectionNode = new OptionScanSelectionNode(mActionNode1, mActionNode2); mOptionManager.clearFocusIfNewTree(mSelectionNode); mOptionManager.selectOption(0); mOptionManager.performScrollAction(AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD); List<Integer> info1Actions = mShadowInfo1.getPerformedActions(); assertEquals(1, info1Actions.size()); assertEquals( new Integer(AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD), info1Actions.get(0)); verify(mOverlayController, times(3)).clearOverlay(); }
/** * Advances the focus to the next node in the view. If there are no more nodes that can be * clicked or if Auto Scan was disabled, then the scan is stopped */ @Override public void run() { if (!SwitchAccessPreferenceActivity.isAutoScanEnabled(mContext)) { stopScan(); return; } /* * TODO(PW): Option selection should be configurable. This choice mimics * linear scanning */ if (mIsScanInProgress) { if (mReverseScan) { mOptionManager.moveToParent(true); } else { mOptionManager.selectOption(OptionManager.OPTION_INDEX_NEXT); } if (mIsScanInProgress) { mHandler.postDelayed(mAutoScanRunnable, getAutoScanDelay()); } } }
@Test public void testOnlyOneActionNode_shouldPerformActionOnFirstSelect() { mOptionManager.clearFocusIfNewTree(mActionNode1); mOptionManager.selectOption(0); assertEquals(1, mShadowInfo1.getPerformedActions().size()); }
@Test public void testNegativeSelection_shouldBeIgnored() { mOptionManager.clearFocusIfNewTree(mActionNode1); mOptionManager.selectOption(-1); assertEquals(0, mShadowInfo1.getPerformedActions().size()); }