1 /* 2 * Copyright (C) 2008 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 17 package android.widget; 18 19 import android.app.Activity; 20 import android.app.Instrumentation; 21 import android.os.SystemClock; 22 import android.support.test.filters.LargeTest; 23 import android.test.ActivityInstrumentationTestCase2; 24 import android.view.KeyEvent; 25 import android.view.View; 26 27 import com.android.frameworks.coretests.R; 28 29 /** 30 * Test {@link DatePicker} focus changes. 31 */ 32 @LargeTest 33 public class DatePickerFocusTest extends ActivityInstrumentationTestCase2<DatePickerActivity> { 34 35 private Activity mActivity; 36 private Instrumentation mInstrumentation; 37 private DatePicker mDatePicker; 38 39 public DatePickerFocusTest() { 40 super(DatePickerActivity.class); 41 } 42 43 @Override 44 protected void setUp() throws Exception { 45 super.setUp(); 46 47 mActivity = getActivity(); 48 mInstrumentation = getInstrumentation(); 49 50 mDatePicker = (DatePicker) mActivity.findViewById(R.id.datePicker); 51 } 52 53 /** 54 * Tabs (forward and backward) through the DatePicker to ensure the correct 55 * Views gain focus. 56 */ 57 public void testFocusTravel() throws Throwable { 58 runTestOnUiThread(new Runnable() { 59 @Override 60 public void run() { 61 assertTrue(mDatePicker.requestFocus()); 62 } 63 }); 64 assertViewHasFocus(com.android.internal.R.id.date_picker_header_year); 65 sendKey(KeyEvent.KEYCODE_TAB); 66 assertViewHasFocus(com.android.internal.R.id.prev); 67 sendKey(KeyEvent.KEYCODE_TAB); 68 assertViewHasFocus(com.android.internal.R.id.next); 69 sendKey(KeyEvent.KEYCODE_TAB); 70 assertViewHasFocus(com.android.internal.R.id.day_picker_view_pager); 71 sendKey(KeyEvent.KEYCODE_TAB); 72 assertViewHasFocus(R.id.belowPicker); 73 sendShiftKey(KeyEvent.KEYCODE_TAB); 74 assertViewHasFocus(com.android.internal.R.id.day_picker_view_pager); 75 sendShiftKey(KeyEvent.KEYCODE_TAB); 76 assertViewHasFocus(com.android.internal.R.id.next); 77 sendShiftKey(KeyEvent.KEYCODE_TAB); 78 assertViewHasFocus(com.android.internal.R.id.prev); 79 sendShiftKey(KeyEvent.KEYCODE_TAB); 80 assertViewHasFocus(com.android.internal.R.id.date_picker_header_year); 81 } 82 83 private void sendKey(int keycode) { 84 mInstrumentation.sendKeyDownUpSync(keycode); 85 mInstrumentation.waitForIdleSync(); 86 } 87 88 private void assertViewHasFocus(final int id) throws Throwable { 89 runTestOnUiThread(new Runnable() { 90 @Override 91 public void run() { 92 View view = mActivity.findViewById(id); 93 assertTrue(view.hasFocus()); 94 } 95 }); 96 } 97 98 private void sendShiftKey(int keycode) { 99 final KeyEvent shiftDown = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_SHIFT_LEFT); 100 mInstrumentation.sendKeySync(shiftDown); 101 102 final KeyEvent keyDown = new KeyEvent(SystemClock.uptimeMillis(), 103 SystemClock.uptimeMillis(), KeyEvent.ACTION_DOWN, keycode, 0, 104 KeyEvent.META_SHIFT_ON); 105 mInstrumentation.sendKeySync(keyDown); 106 107 final KeyEvent keyUp = new KeyEvent(SystemClock.uptimeMillis(), 108 SystemClock.uptimeMillis(), KeyEvent.ACTION_UP, keycode, 0, 109 KeyEvent.META_SHIFT_ON); 110 mInstrumentation.sendKeySync(keyUp); 111 112 final KeyEvent shiftUp = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_SHIFT_LEFT); 113 mInstrumentation.sendKeySync(shiftUp); 114 115 mInstrumentation.waitForIdleSync(); 116 } 117 118 /** 119 * Tests to ensure the keyboard can select the current year. 120 */ 121 public void testYearChoice() throws Throwable { 122 setKnownDate(); 123 runTestOnUiThread(new Runnable() { 124 @Override 125 public void run() { 126 View year = mDatePicker. 127 findViewById(com.android.internal.R.id.date_picker_header_year); 128 assertTrue(year.requestFocus()); 129 } 130 }); 131 sendKey(KeyEvent.KEYCODE_ENTER); 132 runTestOnUiThread(new Runnable() { 133 @Override 134 public void run() { 135 View yearSelect = mDatePicker. 136 findViewById(com.android.internal.R.id.date_picker_year_picker); 137 assertEquals(yearSelect, mDatePicker.findFocus()); 138 } 139 }); 140 sendKey(KeyEvent.KEYCODE_DPAD_UP); 141 sendKey(KeyEvent.KEYCODE_ENTER); 142 runTestOnUiThread(new Runnable() { 143 @Override 144 public void run() { 145 View yearSelect = mDatePicker. 146 findViewById(com.android.internal.R.id.date_picker_year_picker); 147 assertNotSame(View.VISIBLE, yearSelect.getVisibility()); 148 View year = mDatePicker. 149 findViewById(com.android.internal.R.id.date_picker_header_year); 150 assertTrue(year.hasFocus()); 151 assertEquals(2014, mDatePicker.getYear()); 152 } 153 }); 154 } 155 156 public void testArrowThroughDays() throws Throwable { 157 setKnownDate(); 158 runTestOnUiThread(new Runnable() { 159 @Override 160 public void run() { 161 View prev = mDatePicker.findViewById(com.android.internal.R.id.next); 162 prev.requestFocus(); 163 } 164 }); 165 sendKey(KeyEvent.KEYCODE_TAB); 166 // Should select the current date and the date shouldn't change 167 sendKey(KeyEvent.KEYCODE_ENTER); 168 assertDateIs(12, 31, 2015); 169 // Move right to January 24, 2016 170 sendKey(KeyEvent.KEYCODE_DPAD_RIGHT); 171 sendKey(KeyEvent.KEYCODE_ENTER); 172 assertDateIs(1, 24, 2016); 173 // Move down to January 31, 2016 174 sendKey(KeyEvent.KEYCODE_DPAD_DOWN); 175 sendKey(KeyEvent.KEYCODE_ENTER); 176 assertDateIs(1, 31, 2016); 177 // Move up to January 5, 2016 178 sendKey(KeyEvent.KEYCODE_DPAD_UP); 179 sendKey(KeyEvent.KEYCODE_DPAD_UP); 180 sendKey(KeyEvent.KEYCODE_DPAD_UP); 181 sendKey(KeyEvent.KEYCODE_DPAD_UP); 182 sendKey(KeyEvent.KEYCODE_DPAD_RIGHT); 183 sendKey(KeyEvent.KEYCODE_DPAD_RIGHT); 184 sendKey(KeyEvent.KEYCODE_ENTER); 185 assertDateIs(1, 5, 2016); 186 // Move up to prev arrow key 187 sendKey(KeyEvent.KEYCODE_DPAD_UP); 188 assertViewHasFocus(com.android.internal.R.id.prev); 189 // tab back into the day-selection pager 190 sendKey(KeyEvent.KEYCODE_TAB); 191 sendKey(KeyEvent.KEYCODE_TAB); 192 sendKey(KeyEvent.KEYCODE_ENTER); 193 assertViewHasFocus(com.android.internal.R.id.day_picker_view_pager); 194 assertDateIs(1, 5, 2016); 195 196 // Move up out again, then down back into the day-selection pager. 197 // It should land right below the prev button (1/3/2016) 198 sendKey(KeyEvent.KEYCODE_DPAD_UP); 199 sendKey(KeyEvent.KEYCODE_DPAD_DOWN); 200 sendKey(KeyEvent.KEYCODE_ENTER); 201 assertViewHasFocus(com.android.internal.R.id.day_picker_view_pager); 202 assertDateIs(1, 3, 2016); 203 204 // Move left to previous month (12/12/2015) 205 sendKey(KeyEvent.KEYCODE_DPAD_LEFT); 206 sendKey(KeyEvent.KEYCODE_ENTER); 207 assertDateIs(12, 12, 2015); 208 // Now make sure the start of the month works 209 // Move up to 12/5/2015 and right to 1/1/2016 210 sendKey(KeyEvent.KEYCODE_DPAD_UP); 211 sendKey(KeyEvent.KEYCODE_DPAD_RIGHT); 212 sendKey(KeyEvent.KEYCODE_ENTER); 213 assertDateIs(1, 1, 2016); 214 // Now make sure the left key goes back to previous month (12/5/2015) 215 sendKey(KeyEvent.KEYCODE_DPAD_LEFT); 216 sendKey(KeyEvent.KEYCODE_ENTER); 217 assertDateIs(12, 5, 2015); 218 // Now go to a mismatched row (no such row on previous month) 219 // This moves over to 1/31/2016 and then left to 12/31/2015 220 sendKey(KeyEvent.KEYCODE_DPAD_DOWN); 221 sendKey(KeyEvent.KEYCODE_DPAD_DOWN); 222 sendKey(KeyEvent.KEYCODE_DPAD_DOWN); 223 sendKey(KeyEvent.KEYCODE_DPAD_RIGHT); 224 sendKey(KeyEvent.KEYCODE_DPAD_DOWN); 225 sendKey(KeyEvent.KEYCODE_DPAD_DOWN); 226 sendKey(KeyEvent.KEYCODE_DPAD_LEFT); 227 sendKey(KeyEvent.KEYCODE_ENTER); 228 assertDateIs(12, 31, 2015); 229 } 230 231 private void assertDateIs(int month, final int day, final int year) throws Throwable { 232 final int monthInt = month - 1; // months are 0-based 233 runTestOnUiThread(new Runnable() { 234 @Override 235 public void run() { 236 assertEquals(day, mDatePicker.getDayOfMonth()); 237 assertEquals(year, mDatePicker.getYear()); 238 assertEquals(monthInt, mDatePicker.getMonth()); 239 } 240 }); 241 } 242 243 private void setKnownDate() throws Throwable { 244 runTestOnUiThread(new Runnable() { 245 @Override 246 public void run() { 247 mDatePicker.updateDate(2015, 11, 31); // December 31, 2015 248 } 249 }); 250 mInstrumentation.waitForIdleSync(); 251 } 252 } 253