BaseKeyEventsTestCase.java revision 261ba392bba9ff4018ff7dd53091f71549bf56ad
1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.support.v7.app; 18 19import static android.support.test.espresso.Espresso.onView; 20import static android.support.test.espresso.action.ViewActions.click; 21import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist; 22import static android.support.test.espresso.assertion.ViewAssertions.matches; 23import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; 24import static android.support.test.espresso.matcher.ViewMatchers.withContentDescription; 25import static android.support.test.espresso.matcher.ViewMatchers.withId; 26 27import static org.junit.Assert.assertEquals; 28import static org.junit.Assert.assertFalse; 29import static org.junit.Assert.assertNotNull; 30import static org.junit.Assert.assertTrue; 31 32import android.support.v7.appcompat.test.R; 33import android.support.v7.testutils.BaseTestActivity; 34import android.support.v7.view.ActionMode; 35import android.test.suitebuilder.annotation.SmallTest; 36import android.view.KeyEvent; 37import android.view.Menu; 38import android.view.MenuItem; 39 40import org.junit.Test; 41 42import java.util.concurrent.atomic.AtomicBoolean; 43 44public abstract class BaseKeyEventsTestCase<A extends BaseTestActivity> 45 extends BaseInstrumentationTestCase<A> { 46 47 protected BaseKeyEventsTestCase(Class<A> activityClass) { 48 super(activityClass); 49 } 50 51 @Test 52 @SmallTest 53 public void testBackDismissesActionMode() { 54 final AtomicBoolean destroyed = new AtomicBoolean(); 55 56 getActivity().runOnUiThread(new Runnable() { 57 @Override 58 public void run() { 59 getActivity().startSupportActionMode(new ActionMode.Callback() { 60 @Override 61 public boolean onCreateActionMode(ActionMode mode, Menu menu) { 62 mode.getMenuInflater().inflate(R.menu.sample_actions, menu); 63 return true; 64 } 65 66 @Override 67 public boolean onPrepareActionMode(ActionMode mode, Menu menu) { 68 return false; 69 } 70 71 @Override 72 public boolean onActionItemClicked(ActionMode mode, MenuItem item) { 73 return false; 74 } 75 76 @Override 77 public void onDestroyActionMode(ActionMode mode) { 78 destroyed.set(true); 79 } 80 }); 81 } 82 }); 83 84 getInstrumentation().waitForIdleSync(); 85 getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_BACK); 86 getInstrumentation().waitForIdleSync(); 87 88 assertFalse("Activity was not finished", getActivity().isFinishing()); 89 assertTrue("ActionMode was destroyed", destroyed.get()); 90 } 91 92 @Test 93 @SmallTest 94 public void testBackCollapsesSearchView() throws InterruptedException { 95 final String itemTitle = getActivity().getString(R.string.search_menu_title); 96 97 // Click on the Search menu item 98 onView(withContentDescription(itemTitle)).perform(click()); 99 // Check that the SearchView is displayed 100 onView(withId(R.id.search_bar)).check(matches(isDisplayed())); 101 102 // Wait for the IME to show 103 getInstrumentation().waitForIdleSync(); 104 // Now send a back event to dismiss the IME 105 getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_BACK); 106 // ...and another to collapse the SearchView 107 getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_BACK); 108 109 // Check that the Activity is still running 110 assertFalse(getActivity().isFinishing()); 111 assertFalse(getActivity().isDestroyed()); 112 // ...and that the SearchView is not attached 113 onView(withId(R.id.search_bar)).check(doesNotExist()); 114 } 115 116 @Test 117 @SmallTest 118 public void testMenuPressInvokesPanelCallbacks() throws InterruptedException { 119 getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_MENU); 120 getInstrumentation().waitForIdleSync(); 121 assertTrue("onMenuOpened called", getActivity().wasOnMenuOpenedCalled()); 122 123 getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_MENU); 124 getInstrumentation().waitForIdleSync(); 125 assertTrue("onPanelClosed called", getActivity().wasOnPanelClosedCalled()); 126 } 127 128 @Test 129 @SmallTest 130 public void testBackPressWithMenuInvokesOnPanelClosed() throws InterruptedException { 131 getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_MENU); 132 getInstrumentation().waitForIdleSync(); 133 134 getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_BACK); 135 getInstrumentation().waitForIdleSync(); 136 assertTrue("onPanelClosed called", getActivity().wasOnPanelClosedCalled()); 137 } 138 139 @Test 140 @SmallTest 141 public void testBackPressWithEmptyMenuFinishesActivity() throws InterruptedException { 142 repopulateWithEmptyMenu(); 143 144 getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_MENU); 145 getInstrumentation().waitForIdleSync(); 146 147 getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_BACK); 148 assertTrue(getActivity().isFinishing()); 149 } 150 151 @Test 152 @SmallTest 153 public void testDelKeyEventReachesActivity() { 154 // First send the event 155 getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_DEL); 156 getInstrumentation().waitForIdleSync(); 157 158 KeyEvent downEvent = getActivity().getInvokedKeyDownEvent(); 159 assertNotNull("onKeyDown called", downEvent); 160 assertEquals("onKeyDown event matches", KeyEvent.KEYCODE_DEL, downEvent.getKeyCode()); 161 162 KeyEvent upEvent = getActivity().getInvokedKeyUpEvent(); 163 assertNotNull("onKeyUp called", upEvent); 164 assertEquals("onKeyUp event matches", KeyEvent.KEYCODE_DEL, upEvent.getKeyCode()); 165 } 166 167 @Test 168 @SmallTest 169 public void testMenuKeyEventReachesActivity() throws InterruptedException { 170 getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_MENU); 171 getInstrumentation().waitForIdleSync(); 172 173 KeyEvent downEvent = getActivity().getInvokedKeyDownEvent(); 174 assertNotNull("onKeyDown called", downEvent); 175 assertEquals("onKeyDown event matches", KeyEvent.KEYCODE_MENU, downEvent.getKeyCode()); 176 177 KeyEvent upEvent = getActivity().getInvokedKeyUpEvent(); 178 assertNotNull("onKeyUp called", upEvent); 179 assertEquals("onKeyDown event matches", KeyEvent.KEYCODE_MENU, upEvent.getKeyCode()); 180 } 181 182 private void repopulateWithEmptyMenu() throws InterruptedException { 183 int count = 0; 184 getActivity().setShouldPopulateOptionsMenu(false); 185 while (count++ < 10) { 186 Menu menu = getActivity().getMenu(); 187 if (menu == null || menu.size() != 0) { 188 Thread.sleep(100); 189 } else { 190 return; 191 } 192 } 193 } 194} 195