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