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