• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 androidx.leanback.widget.picker;
18 
19 import static org.hamcrest.CoreMatchers.is;
20 import static org.hamcrest.MatcherAssert.assertThat;
21 import static org.junit.Assert.assertEquals;
22 
23 import android.content.Context;
24 import android.content.Intent;
25 import android.support.test.InstrumentationRegistry;
26 import android.support.test.filters.LargeTest;
27 import android.support.test.rule.ActivityTestRule;
28 import android.support.test.runner.AndroidJUnit4;
29 import android.view.KeyEvent;
30 import android.view.View;
31 import android.view.ViewGroup;
32 
33 import androidx.leanback.test.R;
34 
35 import org.junit.Before;
36 import org.junit.Rule;
37 import org.junit.Test;
38 import org.junit.runner.RunWith;
39 
40 import java.util.Arrays;
41 import java.util.List;
42 
43 @LargeTest
44 @RunWith(AndroidJUnit4.class)
45 public class TimePickerTest {
46 
47     private static final String TAG = "TimePickerTest";
48     private static final long TRANSITION_LENGTH = 1000;
49     private static final long UPDATE_LENGTH = 1000;
50 
51     View mViewAbove;
52     TimePicker mTimePicker12HourView;
53     TimePicker mTimePicker24HourView;
54     View mViewBelow;
55 
56     @Rule
57     public ActivityTestRule<TimePickerActivity> mActivityTestRule =
58             new ActivityTestRule<>(TimePickerActivity.class, false, false);
59     private TimePickerActivity mActivity;
60     private Context mContext;
61 
62     @Before
setUp()63     public void setUp() throws Exception {
64         mContext = InstrumentationRegistry.getTargetContext();
65     }
66 
initActivity(Intent intent)67     public void initActivity(Intent intent) throws Throwable {
68         mActivity = mActivityTestRule.launchActivity(intent);
69         mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
70         mTimePicker12HourView = (TimePicker) mActivity.findViewById(R.id.time_picker12);
71         mTimePicker12HourView.setActivatedVisibleItemCount(3);
72         mTimePicker12HourView.setOnClickListener(new View.OnClickListener() {
73             @Override
74             public void onClick(View v) {
75                 mTimePicker12HourView.setActivated(!mTimePicker12HourView.isActivated());
76             }
77         });
78 
79         if (intent.getIntExtra(TimePickerActivity.EXTRA_LAYOUT_RESOURCE_ID,
80                 R.layout.timepicker_with_other_widgets) == R.layout.timepicker_with_other_widgets) {
81             mViewAbove = mActivity.findViewById(R.id.above_picker);
82             mViewBelow = mActivity.findViewById(R.id.below_picker);
83             mTimePicker24HourView = (TimePicker) mActivity.findViewById(R.id.time_picker24);
84             mTimePicker24HourView.setActivatedVisibleItemCount(3);
85             mTimePicker24HourView.setOnClickListener(new View.OnClickListener() {
86                 @Override
87                 public void onClick(View v) {
88                     mTimePicker24HourView.setActivated(!mTimePicker24HourView.isActivated());
89                 }
90             });
91         } else if (intent.getIntExtra(TimePickerActivity.EXTRA_LAYOUT_RESOURCE_ID,
92                 R.layout.timepicker_with_other_widgets) == R.layout.timepicker_alone) {
93             // A layout with only a TimePicker widget that is initially activated.
94             mActivityTestRule.runOnUiThread(new Runnable() {
95                 @Override
96                 public void run() {
97                     mTimePicker12HourView.setActivated(true);
98                 }
99             });
100             Thread.sleep(500);
101         }
102     }
103 
104     @Test
testSetHourIn24hFormat()105     public void testSetHourIn24hFormat() throws Throwable {
106         Intent intent = new Intent();
107         intent.putExtra(TimePickerActivity.EXTRA_LAYOUT_RESOURCE_ID,
108                 R.layout.timepicker_with_other_widgets);
109         initActivity(intent);
110 
111         mActivityTestRule.runOnUiThread(new Runnable() {
112             @Override
113             public void run() {
114                 mTimePicker24HourView.setHour(0);
115             }
116         });
117         Thread.sleep(UPDATE_LENGTH);
118         assertThat("TimePicker in 24-hour mode returns a different hour in getHour()",
119                 mTimePicker24HourView.getHour(), is(0));
120 
121         mActivityTestRule.runOnUiThread(new Runnable() {
122             @Override
123             public void run() {
124                 mTimePicker24HourView.setHour(11);
125             }
126         });
127         Thread.sleep(UPDATE_LENGTH);
128         assertThat("TimePicker in 24-hour mode returns a different hour in getHour()",
129                 mTimePicker24HourView.getHour(), is(11));
130 
131         mActivityTestRule.runOnUiThread(new Runnable() {
132             @Override
133             public void run() {
134                 mTimePicker24HourView.setHour(12);
135             }
136         });
137         Thread.sleep(UPDATE_LENGTH);
138         assertThat("TimePicker in 24-hour mode returns a different hour in getHour()",
139                 mTimePicker24HourView.getHour(), is(12));
140 
141         mActivityTestRule.runOnUiThread(new Runnable() {
142             @Override
143             public void run() {
144                 mTimePicker24HourView.setHour(13);
145             }
146         });
147         Thread.sleep(UPDATE_LENGTH);
148         assertThat("TimePicker in 24-hour mode returns a different hour in getHour()",
149                 mTimePicker24HourView.getHour(), is(13));
150 
151         mActivityTestRule.runOnUiThread(new Runnable() {
152             @Override
153             public void run() {
154                 mTimePicker24HourView.setHour(23);
155             }
156         });
157         Thread.sleep(UPDATE_LENGTH);
158         assertThat("TimePicker in 24-hour mode returns a different hour in getHour()",
159                 mTimePicker24HourView.getHour(), is(23));
160     }
161 
162     @Test
testSetHourIn12hFormat()163     public void testSetHourIn12hFormat() throws Throwable {
164         Intent intent = new Intent();
165         intent.putExtra(TimePickerActivity.EXTRA_LAYOUT_RESOURCE_ID,
166                 R.layout.timepicker_with_other_widgets);
167         initActivity(intent);
168         mActivityTestRule.runOnUiThread(new Runnable() {
169             @Override
170             public void run() {
171                 mTimePicker12HourView.setHour(0);
172             }
173         });
174         Thread.sleep(UPDATE_LENGTH);
175         assertThat("TimePicker in 24-hour mode returns a different hour in getHour()",
176                 mTimePicker12HourView.getHour(), is(0));
177 
178         mActivityTestRule.runOnUiThread(new Runnable() {
179             @Override
180             public void run() {
181                 mTimePicker12HourView.setHour(11);
182             }
183         });
184         Thread.sleep(UPDATE_LENGTH);
185         assertThat("TimePicker in 24-hour mode returns a different hour in getHour()",
186                 mTimePicker12HourView.getHour(), is(11));
187 
188         mActivityTestRule.runOnUiThread(new Runnable() {
189             @Override
190             public void run() {
191                 mTimePicker12HourView.setHour(12);
192             }
193         });
194         Thread.sleep(UPDATE_LENGTH);
195         assertThat("TimePicker in 24-hour mode returns a different hour in getHour()",
196                 mTimePicker12HourView.getHour(), is(12));
197 
198         mActivityTestRule.runOnUiThread(new Runnable() {
199             @Override
200             public void run() {
201                 mTimePicker12HourView.setHour(13);
202             }
203         });
204         Thread.sleep(UPDATE_LENGTH);
205         assertThat("TimePicker in 24-hour mode returns a different hour in getHour()",
206                 mTimePicker12HourView.getHour(), is(13));
207 
208         mActivityTestRule.runOnUiThread(new Runnable() {
209             @Override
210             public void run() {
211                 mTimePicker12HourView.setHour(23);
212             }
213         });
214         Thread.sleep(UPDATE_LENGTH);
215         assertThat("TimePicker in 24-hour mode returns a different hour in getHour()",
216                 mTimePicker12HourView.getHour(), is(23));
217     }
218 
219     @Test
testSetMinuteIn24hFormat()220     public void testSetMinuteIn24hFormat() throws Throwable {
221         Intent intent = new Intent();
222         intent.putExtra(TimePickerActivity.EXTRA_LAYOUT_RESOURCE_ID,
223                 R.layout.timepicker_with_other_widgets);
224         initActivity(intent);
225         mActivityTestRule.runOnUiThread(new Runnable() {
226             @Override
227             public void run() {
228                 mTimePicker24HourView.setMinute(0);
229             }
230         });
231         Thread.sleep(UPDATE_LENGTH);
232         assertThat("TimePicker in 24-hour mode returns a different hour in getHour()",
233                 mTimePicker24HourView.getMinute(), is(0));
234 
235         mActivityTestRule.runOnUiThread(new Runnable() {
236             @Override
237             public void run() {
238                 mTimePicker24HourView.setMinute(11);
239             }
240         });
241         Thread.sleep(UPDATE_LENGTH);
242         assertThat("TimePicker in 24-hour mode returns a different hour in getHour()",
243                 mTimePicker24HourView.getMinute(), is(11));
244 
245         mActivityTestRule.runOnUiThread(new Runnable() {
246             @Override
247             public void run() {
248                 mTimePicker24HourView.setMinute(59);
249             }
250         });
251         Thread.sleep(UPDATE_LENGTH);
252         assertThat("TimePicker in 24-hour mode returns a different hour in getHour()",
253                 mTimePicker24HourView.getMinute(), is(59));
254     }
255 
256     @Test
testSetMinuteIn12hFormat()257     public void testSetMinuteIn12hFormat() throws Throwable {
258         Intent intent = new Intent();
259         intent.putExtra(TimePickerActivity.EXTRA_LAYOUT_RESOURCE_ID,
260                 R.layout.timepicker_with_other_widgets);
261         initActivity(intent);
262         mActivityTestRule.runOnUiThread(new Runnable() {
263             @Override
264             public void run() {
265                 mTimePicker12HourView.setMinute(0);
266             }
267         });
268         Thread.sleep(UPDATE_LENGTH);
269         assertThat("TimePicker in 24-hour mode returns a different hour in getHour()",
270                 mTimePicker12HourView.getMinute(), is(0));
271 
272         mActivityTestRule.runOnUiThread(new Runnable() {
273             @Override
274             public void run() {
275                 mTimePicker12HourView.setMinute(11);
276             }
277         });
278         Thread.sleep(UPDATE_LENGTH);
279         assertThat("TimePicker in 24-hour mode returns a different hour in getHour()",
280                 mTimePicker12HourView.getMinute(), is(11));
281 
282         mActivityTestRule.runOnUiThread(new Runnable() {
283             @Override
284             public void run() {
285                 mTimePicker12HourView.setMinute(59);
286             }
287         });
288         Thread.sleep(UPDATE_LENGTH);
289         assertThat("TimePicker in 24-hour mode returns a different hour in getHour()",
290                 mTimePicker12HourView.getMinute(), is(59));
291 
292     }
293 
294     @Test
testAmToPmTransition()295     public void testAmToPmTransition() throws Throwable {
296         Intent intent = new Intent();
297         intent.putExtra(TimePickerActivity.EXTRA_LAYOUT_RESOURCE_ID,
298                 R.layout.timepicker_with_other_widgets);
299         initActivity(intent);
300         mActivityTestRule.runOnUiThread(new Runnable() {
301             @Override
302             public void run() {
303                 mTimePicker12HourView.setHour(0);
304                 mTimePicker12HourView.setMinute(47);
305             }
306         });
307         Thread.sleep(UPDATE_LENGTH);
308         assertThat("TimePicker in 12-hour mode returns a different hour in getHour()",
309                 mTimePicker12HourView.getHour(), is(0));
310         assertThat("TimePicker in 12-hour mode returns a different hour in getMinute()",
311                 mTimePicker12HourView.getMinute(), is(47));
312 
313         // traverse to the AM/PM column of 12 hour TimePicker widget
314         sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
315         Thread.sleep(TRANSITION_LENGTH);
316         // Click once to activate
317         sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
318         Thread.sleep(TRANSITION_LENGTH);
319         sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT);
320         Thread.sleep(TRANSITION_LENGTH);
321         sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT);
322         Thread.sleep(TRANSITION_LENGTH);
323         // scroll down to PM value
324         sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
325         Thread.sleep(TRANSITION_LENGTH);
326         // Click now to deactivate
327         sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
328         Thread.sleep(TRANSITION_LENGTH);
329 
330         assertThat("TimePicker in 24-hour mode returns a different hour in getHour() returns",
331                 mTimePicker12HourView.getHour(), is(12));
332         assertThat("TimePicker in 24-hour mode returns a different hour in getHour() returns",
333                 mTimePicker12HourView.getMinute(), is(47));
334     }
335 
336     @Test
testPmToAmTransition()337     public void testPmToAmTransition() throws Throwable {
338         Intent intent = new Intent();
339         intent.putExtra(TimePickerActivity.EXTRA_LAYOUT_RESOURCE_ID,
340                 R.layout.timepicker_with_other_widgets);
341         initActivity(intent);
342         mActivityTestRule.runOnUiThread(new Runnable() {
343             @Override
344             public void run() {
345                 mTimePicker12HourView.setHour(12);
346                 mTimePicker12HourView.setMinute(47);
347             }
348         });
349         Thread.sleep(UPDATE_LENGTH);
350         assertThat("TimePicker in 12-hour mode returns a different hour in getHour()",
351                 mTimePicker12HourView.getHour(), is(12));
352         assertThat("TimePicker in 12-hour mode returns a different hour in getMinute()",
353                 mTimePicker12HourView.getMinute(), is(47));
354 
355         // traverse to the AM/PM column of 12 hour TimePicker widget
356         sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
357         Thread.sleep(TRANSITION_LENGTH);
358         // Click once to activate
359         sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
360         Thread.sleep(TRANSITION_LENGTH);
361         sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT);
362         Thread.sleep(TRANSITION_LENGTH);
363         sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT);
364         Thread.sleep(TRANSITION_LENGTH);
365         // scroll down to PM value
366         sendKeys(KeyEvent.KEYCODE_DPAD_UP);
367         Thread.sleep(TRANSITION_LENGTH);
368         // Click now to deactivate
369         sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
370         Thread.sleep(TRANSITION_LENGTH);
371 
372         assertThat("TimePicker in 24-hour mode returns a different hour in getHour() returns",
373                 mTimePicker12HourView.getHour(), is(0));
374         assertThat("TimePicker in 24-hour mode returns a different hour in getHour() returns",
375                 mTimePicker12HourView.getMinute(), is(47));
376     }
377 
378     @Test
test12To24HourFormatTransition()379     public void test12To24HourFormatTransition() throws Throwable {
380         Intent intent = new Intent();
381         intent.putExtra(TimePickerActivity.EXTRA_LAYOUT_RESOURCE_ID,
382                 R.layout.timepicker_with_other_widgets);
383         initActivity(intent);
384         mActivityTestRule.runOnUiThread(new Runnable() {
385             @Override
386             public void run() {
387                 mTimePicker12HourView.setHour(14);
388                 mTimePicker12HourView.setMinute(47);
389             }
390         });
391         Thread.sleep(UPDATE_LENGTH);
392         assertThat("TimePicker should be in 12-hour format.", mTimePicker12HourView.is24Hour(),
393                 is(false));
394         mActivityTestRule.runOnUiThread(new Runnable() {
395             @Override
396             public void run() {
397                 mTimePicker12HourView.setIs24Hour(true);
398             }
399         });
400         Thread.sleep(UPDATE_LENGTH);
401         assertThat("TimePicker should now be in 24-hour format.", mTimePicker12HourView.is24Hour(),
402                 is(true));
403         // The hour and minute should not be changed.
404         assertThat("TimePicker in 24-hour mode returns a different hour in getHour() returns",
405                 mTimePicker12HourView.getHour(), is(14));
406         assertThat("TimePicker in 24-hour mode returns a different hour in getHour() returns",
407                 mTimePicker12HourView.getMinute(), is(47));
408     }
409 
410     @Test
test24To12HourFormatTransition()411     public void test24To12HourFormatTransition() throws Throwable {
412         Intent intent = new Intent();
413         intent.putExtra(TimePickerActivity.EXTRA_LAYOUT_RESOURCE_ID,
414                 R.layout.timepicker_with_other_widgets);
415         initActivity(intent);
416         mActivityTestRule.runOnUiThread(new Runnable() {
417             @Override
418             public void run() {
419                 mTimePicker24HourView.setHour(14);
420                 mTimePicker24HourView.setMinute(47);
421             }
422         });
423         Thread.sleep(UPDATE_LENGTH);
424         assertThat("TimePicker should be in 12-hour format.", mTimePicker24HourView.is24Hour(),
425                 is(true));
426         mActivityTestRule.runOnUiThread(new Runnable() {
427             @Override
428             public void run() {
429                 mTimePicker24HourView.setIs24Hour(false);
430             }
431         });
432         Thread.sleep(UPDATE_LENGTH);
433         assertThat("TimePicker should now be in 24-hour format.", mTimePicker24HourView.is24Hour(),
434                 is(false));
435         // The hour and minute should not be changed.
436         assertThat("TimePicker in 24-hour mode returns a different hour in getHour() returns",
437                 mTimePicker24HourView.getHour(), is(14));
438         assertThat("TimePicker in 24-hour mode returns a different hour in getHour() returns",
439                 mTimePicker24HourView.getMinute(), is(47));
440     }
441 
442     @Test
testInitiallyActiveTimePicker()443     public void testInitiallyActiveTimePicker()
444             throws Throwable {
445         Intent intent = new Intent();
446         intent.putExtra(TimePickerActivity.EXTRA_LAYOUT_RESOURCE_ID,
447                 R.layout.timepicker_alone);
448         initActivity(intent);
449 
450         mActivityTestRule.runOnUiThread(new Runnable() {
451             @Override
452             public void run() {
453                 mTimePicker12HourView.setHour(14);
454                 mTimePicker12HourView.setMinute(47);
455             }
456         });
457         Thread.sleep(UPDATE_LENGTH);
458 
459         ViewGroup mTimePickerInnerView = (ViewGroup) mTimePicker12HourView.findViewById(
460                 R.id.picker);
461 
462         assertThat("The first column of TimePicker should initially hold focus",
463                 mTimePickerInnerView.getChildAt(0).hasFocus(), is(true));
464 
465         // focus on first column
466         sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
467         Thread.sleep(TRANSITION_LENGTH);
468         assertThat("The first column of TimePicker should still hold focus after scrolling down",
469                 mTimePickerInnerView.getChildAt(0).hasFocus(), is(true));
470 
471         // focus on second column
472         sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT);
473         Thread.sleep(TRANSITION_LENGTH);
474         assertThat("The second column of TimePicker should hold focus after scrolling right",
475                 mTimePickerInnerView.getChildAt(2).hasFocus(), is(true));
476 
477         sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
478         Thread.sleep(TRANSITION_LENGTH);
479         assertThat("The second column of TimePicker should still hold focus after scrolling down",
480                 mTimePickerInnerView.getChildAt(2).hasFocus(), is(true));
481 
482         // focus on third column
483         sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT);
484         Thread.sleep(TRANSITION_LENGTH);
485         assertThat("The third column of TimePicker should hold focus after scrolling right",
486                 mTimePickerInnerView.getChildAt(3).hasFocus(), is(true));
487 
488         sendKeys(KeyEvent.KEYCODE_DPAD_UP);
489         Thread.sleep(TRANSITION_LENGTH);
490         assertThat("The third column of TimePicker should still hold focus after scrolling down",
491                 mTimePickerInnerView.getChildAt(3).hasFocus(), is(true));
492     }
493 
494     @Test
testExtractSeparatorsForDifferentLocales()495     public void testExtractSeparatorsForDifferentLocales() throws Throwable {
496         // A typical time pattern for different locales in 12-hour format
497         TimePicker timePicker = new TimePicker(mContext, null) {
498             @Override
499             String getBestHourMinutePattern() {
500                 return "h:mm a";
501             }
502         };
503         List<CharSequence> actualSeparators = timePicker.extractSeparators();
504         List<String> expectedSeparators = Arrays.asList(new String[] {"", ":", "", ""});
505         assertEquals(expectedSeparators, actualSeparators);
506 
507         // time pattern for ja_JP in 12 hour format
508         timePicker = new TimePicker(mContext, null) {
509             @Override
510             String getBestHourMinutePattern() {
511                 return "aK:mm";
512             }
513 
514             @Override
515             public boolean is24Hour() {
516                 return false;
517             }
518         };
519         actualSeparators = timePicker.extractSeparators();
520         expectedSeparators = Arrays.asList(new String[] {"", "", ":", ""});
521         assertEquals(expectedSeparators, actualSeparators);
522 
523         // time pattern for fr_CA in 24 hour format
524         timePicker = new TimePicker(mContext, null) {
525             @Override
526             String getBestHourMinutePattern() {
527                 return "HH 'h' mm";
528             }
529 
530             @Override
531             public boolean is24Hour() {
532                 return true;
533             }
534         };
535         actualSeparators = timePicker.extractSeparators();
536         expectedSeparators = Arrays.asList(new String[] {"", "h", ""});
537         assertEquals(expectedSeparators, actualSeparators);
538 
539         // time pattern for hsb_DE in 24 hour format
540         timePicker = new TimePicker(mContext, null) {
541             @Override
542             String getBestHourMinutePattern() {
543                 return "H:mm 'hodz'";
544             }
545 
546             @Override
547             public boolean is24Hour() {
548                 return true;
549             }
550         };
551         actualSeparators = timePicker.extractSeparators();
552         expectedSeparators = Arrays.asList(new String[] {"", ":", "hodz"});
553         assertEquals(expectedSeparators, actualSeparators);
554 
555         // time pattern for ko_KR in 12 hour format
556         timePicker = new TimePicker(mContext, null) {
557             @Override
558             String getBestHourMinutePattern() {
559                 return "a h:mm";
560             }
561 
562             @Override
563             public boolean is24Hour() {
564                 return false;
565             }
566         };
567         actualSeparators = timePicker.extractSeparators();
568         expectedSeparators = Arrays.asList(new String[] {"", "", ":", ""});
569         assertEquals(expectedSeparators, actualSeparators);
570 
571         // time pattern for fa_IR in 24 hour format
572         timePicker = new TimePicker(mContext, null) {
573             @Override
574             String getBestHourMinutePattern() {
575                 return "H:mm";
576             }
577 
578             @Override
579             public boolean is24Hour() {
580                 return true;
581             }
582         };
583         actualSeparators = timePicker.extractSeparators();
584         expectedSeparators = Arrays.asList(new String[] {"", ":", ""});
585         assertEquals(expectedSeparators, actualSeparators);
586     }
587 
sendKeys(int ...keys)588     private void sendKeys(int ...keys) {
589         for (int i = 0; i < keys.length; i++) {
590             InstrumentationRegistry.getInstrumentation().sendKeyDownUpSync(keys[i]);
591         }
592     }
593 }
594