GuidedDatePickerTest.java revision 483c63f22a5e6de67350b20045d05930f5006daf
1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 * in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the License
10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 * or implied. See the License for the specific language governing permissions and limitations under
12 * the License.
13 */
14
15package android.support.v17.leanback.app.wizard;
16
17import android.content.Context;
18import android.content.Intent;
19import android.content.res.Resources;
20import android.support.v17.leanback.app.GuidedStepFragment;
21import android.support.v17.leanback.test.R;
22import android.support.v17.leanback.widget.GuidanceStylist;
23import android.support.v17.leanback.widget.GuidedAction;
24import android.support.v17.leanback.widget.GuidedDatePickerAction;
25import android.support.v17.leanback.widget.VerticalGridView;
26import android.support.v17.leanback.widget.picker.DatePicker;
27import android.test.ActivityInstrumentationTestCase2;
28import android.test.suitebuilder.annotation.MediumTest;
29import android.util.Log;
30import android.view.KeyEvent;
31import android.widget.LinearLayout;
32import org.junit.Before;
33import org.junit.Rule;
34import org.junit.Test;
35import org.junit.runner.RunWith;
36
37import java.text.SimpleDateFormat;
38import java.util.ArrayList;
39import java.util.Calendar;
40import java.util.Date;
41import java.util.List;
42
43import android.support.test.runner.AndroidJUnit4;
44import android.support.test.rule.ActivityTestRule;
45import org.mockito.Mockito;
46
47import android.support.test.InstrumentationRegistry;
48import static org.junit.Assert.assertEquals;
49import static org.junit.Assert.assertNotNull;
50import static org.junit.Assert.assertTrue;
51import static org.mockito.Matchers.any;
52import static org.mockito.Mockito.timeout;
53import static org.mockito.Mockito.verify;
54
55@MediumTest
56@RunWith(AndroidJUnit4.class)
57public class GuidedDatePickerTest {
58
59    static final long TRANSITION_LENGTH = 1000;
60    static long VERTICAL_SCROLL_WAIT = 500;
61    static long HORIZONTAL_SCROLL_WAIT = 500;
62    static final long FINAL_WAIT = 1000;
63
64    static final String TAG = "GuidedDatePickerTest";
65
66    private static final int DAY_INDEX = 0;
67    private static final int MONTH_INDEX = 1;
68    private static final int YEAR_INDEX = 2;
69
70    @Rule
71    public ActivityTestRule<GuidedStepAttributesTestActivity> activityTestRule
72            = new ActivityTestRule<>(GuidedStepAttributesTestActivity.class, false, false);
73
74    GuidedStepAttributesTestActivity mActivity;
75
76
77    private void initActivity(Intent intent) {
78        mActivity = activityTestRule.launchActivity(intent);
79        try {
80            Thread.sleep(2000);
81        } catch(InterruptedException e) {
82            e.printStackTrace();
83        }
84
85    }
86
87    Context mContext;
88    @Before
89    public void setUp() {
90        mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();;
91    }
92
93    public static void sendKey(int keyCode) {
94        InstrumentationRegistry.getInstrumentation().sendKeyDownUpSync(keyCode);
95    }
96
97    private int getColumnIndexForDateField(int field, int[] columnIndices) {
98        int mColDayIndex = columnIndices[0];
99        int mColMonthIndex = columnIndices[1];
100        int mColYearIndex = columnIndices[2];
101        int columnIndex = -1;
102        switch (field) {
103            case Calendar.DAY_OF_MONTH:
104                columnIndex = mColDayIndex;
105                break;
106            case Calendar.MONTH:
107                columnIndex = mColMonthIndex;
108                break;
109            case Calendar.YEAR:
110                columnIndex = mColYearIndex;
111        }
112        return columnIndex;
113    }
114
115    private void horizontalScrollToDateField(int field, int[] columnIndices,
116                                             DatePicker pickerView) throws Throwable{
117        int columnIndex = getColumnIndexForDateField(field, columnIndices);
118
119        LinearLayout columnsLayout = (LinearLayout) pickerView.getChildAt(0);
120
121        int focusedFieldPos = columnsLayout.indexOfChild(columnsLayout.getFocusedChild());
122        if (focusedFieldPos == -1) {
123            sendKey(KeyEvent.KEYCODE_DPAD_CENTER);
124            Thread.sleep(TRANSITION_LENGTH);
125        }
126        focusedFieldPos = columnsLayout.indexOfChild(columnsLayout.getFocusedChild());
127        assertTrue("Date field could not be focused!", (focusedFieldPos != -1));
128
129        // following is to skip the separator fields "/" which are unfocusable but counted as
130        // children of columnsLayout
131        switch (focusedFieldPos) {
132            case 0:
133                focusedFieldPos = 0;
134                break;
135            case 2:
136                focusedFieldPos = 1;
137                break;
138            case 4:
139                focusedFieldPos = 2;
140        }
141
142        // now scroll right or left to the corresponding date field as indicated by the input field
143        int horizontalScrollOffset = columnIndex - focusedFieldPos;
144
145        int horizontalScrollDir = KeyEvent.KEYCODE_DPAD_RIGHT;
146        if (horizontalScrollOffset < 0) {
147            horizontalScrollOffset = -horizontalScrollOffset;
148            horizontalScrollDir = KeyEvent.KEYCODE_DPAD_LEFT;
149        }
150        for(int i = 0; i < horizontalScrollOffset; i++) {
151            sendKey(horizontalScrollDir);
152            Thread.sleep(HORIZONTAL_SCROLL_WAIT);
153        }
154
155    }
156
157    /**
158     * Scrolls vertically all the way up or down (depending on the provided scrollDir parameter)
159     * to fieldValue if it's not equal to -1; otherwise, the scrolling goes all the way to the end.
160     * @param field The date field over which the scrolling is performed
161     * @param fieldValue The field value to scroll to or -1 if the scrolling should go all the way.
162     * @param columnIndices The date field indices corresponding to day, month, and the year
163     * @param pickerView The DatePicker view.
164     * @param scrollDir The direction of scrolling to reach the desired field value.
165     * @throws Throwable
166     */
167    private void verticalScrollToFieldValue(int field, int fieldValue, int[] columnIndices,
168                                                 DatePicker pickerView, int scrollDir)
169            throws Throwable {
170
171        int columnIndex = getColumnIndexForDateField(field, columnIndices);
172        int colDayIndex = columnIndices[0];
173        int colMonthIndex = columnIndices[1];
174        int colYearIndex = columnIndices[2];
175
176        horizontalScrollToDateField(field, columnIndices, pickerView);
177
178        Calendar currentActionCal = Calendar.getInstance();
179        currentActionCal.setTimeInMillis(pickerView.getDate());
180
181        Calendar minCal = Calendar.getInstance();
182        minCal.setTimeInMillis(pickerView.getMinDate());
183
184        Calendar maxCal = Calendar.getInstance();
185        maxCal.setTimeInMillis(pickerView.getMaxDate());
186
187
188        int prevColumnVal = -1;
189        int currentColumnVal = pickerView.getColumnAt(columnIndex).getCurrentValue();
190        while( currentColumnVal != prevColumnVal && currentColumnVal != fieldValue){
191            assertTrue(mContext.getString(R.string.datepicker_test_wrong_day_value),
192                    pickerView.getColumnAt(colDayIndex).getCurrentValue() ==
193                            currentActionCal.get(Calendar.DAY_OF_MONTH)
194            );
195            assertTrue(mContext.getString(R.string.datepicker_test_wrong_month_value),
196                    pickerView.getColumnAt(colMonthIndex).getCurrentValue() ==
197                            currentActionCal.get(Calendar.MONTH)
198            );
199            assertTrue(mContext.getString(R.string.datepicker_test_wrong_year_value),
200                    pickerView.getColumnAt(colYearIndex).getCurrentValue() ==
201                            currentActionCal.get(Calendar.YEAR)
202            );
203
204            int offset = scrollDir == KeyEvent.KEYCODE_DPAD_DOWN ? 1 : -1;
205            addDate(currentActionCal, field, offset, minCal, maxCal);
206
207            sendKey(scrollDir);
208            Thread.sleep(VERTICAL_SCROLL_WAIT);
209
210            prevColumnVal = currentColumnVal;
211            currentColumnVal = pickerView.getColumnAt(columnIndex).getCurrentValue();
212        }
213    }
214
215    private void addDate(Calendar mCurrentDate, int field, int offset,
216                         Calendar mMinDate, Calendar mMaxDate) {
217        int maxOffset = -1;
218        int actualMinFieldValue, actualMaxFieldValue;
219
220        if ( field == Calendar.YEAR ) {
221            actualMinFieldValue = mMinDate.get(Calendar.YEAR);
222            actualMaxFieldValue = mMaxDate.get(Calendar.YEAR);
223        } else {
224            actualMinFieldValue = mCurrentDate.getActualMinimum(field);
225            actualMaxFieldValue = mCurrentDate.getActualMaximum(field);
226        }
227
228        if ( offset > 0 ) {
229            maxOffset = Math.min(
230                    actualMaxFieldValue - mCurrentDate.get(field), offset);
231            mCurrentDate.add(field, maxOffset);
232            if (mCurrentDate.after(mMaxDate)) {
233                mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis());
234            }
235        } else {
236            maxOffset = Math.max(
237                    actualMinFieldValue - mCurrentDate.get(field), offset);
238            mCurrentDate.add(field, Math.max(offset, maxOffset));
239            if (mCurrentDate.before(mMinDate)) {
240                mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis());
241            }
242        }
243    }
244
245    @Test
246    public void testJanuaryToFebruaryTransitionForLeapYear() throws Throwable {
247        long startTime = System.currentTimeMillis();
248        Intent intent = new Intent();
249
250        String title = "Date Picker Transition Test";
251        String breadcrumb = "Month Transition Test Demo";
252        String description = "Testing the transition from Jan to Feb (leap year)";
253        GuidanceStylist.Guidance guidance = new GuidanceStylist.Guidance(title, description,
254                breadcrumb, null);
255
256        List<GuidedAction> actionList = new ArrayList<>();
257
258        Calendar cal = Calendar.getInstance();
259
260        cal.set(Calendar.YEAR, 2016);   // 2016 is a leap year
261        cal.set(Calendar.MONTH, Calendar.JANUARY);
262        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
263        Date initialDate = cal.getTime();
264
265        GuidedDatePickerAction action = new GuidedDatePickerAction.Builder(
266                mContext)
267                .id(0)
268                .title("Date")
269                .date(initialDate.getTime())
270                .datePickerFormat("DMY")
271                .build();
272
273        actionList.add(action);
274
275        GuidedStepAttributesTestFragment.clear();
276        GuidedStepAttributesTestFragment.GUIDANCE = guidance;
277        GuidedStepAttributesTestFragment.ACTION_LIST = actionList;
278
279        initActivity(intent);
280
281        DatePicker mPickerView = (DatePicker) mActivity.findViewById(
282                R.id.guidedactions_activator_item);
283
284        verticalScrollToFieldValue(Calendar.MONTH, Calendar.FEBRUARY, new int[] {0, 1, 2},
285                mPickerView, KeyEvent.KEYCODE_DPAD_DOWN);
286        long executionTime = System.currentTimeMillis() - startTime;
287        Log.d(TAG, "testJanuaryToFebruaryTransitionForLeapYear() Execution time: " + executionTime);
288        Thread.sleep(FINAL_WAIT);
289    }
290
291    @Test
292    public void testFebruaryToMarchTransitionForLeapYear() throws Throwable {
293        long startTime = System.currentTimeMillis();
294        Intent intent = new Intent();
295
296        String title = "Date Picker Transition Test";
297        String breadcrumb = "Month Transition Test Demo";
298        String description = "Testing the transition from Feb to Mar (leap year)";
299        GuidanceStylist.Guidance guidance = new GuidanceStylist.Guidance(title, description,
300                breadcrumb, null);
301
302        List<GuidedAction> actionList = new ArrayList<>();
303
304        Calendar cal = Calendar.getInstance();
305
306        cal.set(Calendar.YEAR, 2016);
307        cal.set(Calendar.MONTH, Calendar.FEBRUARY);
308        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
309        Date initialDate = cal.getTime();
310
311        GuidedDatePickerAction action = new GuidedDatePickerAction.Builder(
312                mContext)
313                .id(0)
314                .title("Date")
315                .date(initialDate.getTime())
316                .datePickerFormat("DMY")
317                .build();
318
319        actionList.add(action);
320
321        GuidedStepAttributesTestFragment.clear();
322        GuidedStepAttributesTestFragment.GUIDANCE = guidance;
323        GuidedStepAttributesTestFragment.ACTION_LIST = actionList;
324
325        initActivity(intent);
326
327        DatePicker mPickerView = (DatePicker) mActivity.findViewById(
328                R.id.guidedactions_activator_item);
329
330        verticalScrollToFieldValue(Calendar.MONTH, Calendar.MARCH, new int[] {0, 1, 2},
331                mPickerView, KeyEvent.KEYCODE_DPAD_DOWN);
332        long executionTime = System.currentTimeMillis() - startTime;
333        Log.d(TAG, "testFebruaryToMarchTransition() Execution time: " + executionTime);
334        Thread.sleep(FINAL_WAIT);
335    }
336
337    @Test
338    public void testJanuaryToFebruaryTransitionForNonLeapYear() throws Throwable {
339        long startTime = System.currentTimeMillis();
340        Intent intent = new Intent();
341
342        String title = "Date Picker Transition Test";
343        String breadcrumb = "Month Transition Test Demo";
344        String description = "Testing the transition from Jan to Feb (nonleap year)";
345        GuidanceStylist.Guidance guidance = new GuidanceStylist.Guidance(title, description,
346                breadcrumb, null);
347
348        List<GuidedAction> actionList = new ArrayList<>();
349
350        Calendar cal = Calendar.getInstance();
351
352        cal.set(Calendar.YEAR, 2017);   // 2017 is a leap year
353        cal.set(Calendar.MONTH, Calendar.JANUARY);
354        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
355        Date initialDate = cal.getTime();
356
357        GuidedDatePickerAction action = new GuidedDatePickerAction.Builder(
358                mContext)
359                .id(0)
360                .title("Date")
361                .date(initialDate.getTime())
362                .datePickerFormat("DMY")
363                .build();
364
365        actionList.add(action);
366
367        GuidedStepAttributesTestFragment.clear();
368        GuidedStepAttributesTestFragment.GUIDANCE = guidance;
369        GuidedStepAttributesTestFragment.ACTION_LIST = actionList;
370
371        initActivity(intent);
372
373        DatePicker mPickerView = (DatePicker) mActivity.findViewById(
374                R.id.guidedactions_activator_item);
375
376        verticalScrollToFieldValue(Calendar.MONTH, Calendar.FEBRUARY, new int[] {0, 1, 2},
377                mPickerView, KeyEvent.KEYCODE_DPAD_DOWN);
378        long executionTime = System.currentTimeMillis() - startTime;
379        Log.d(TAG, "testJanuaryToFebruaryTransition() Execution time: " + executionTime);
380        Thread.sleep(FINAL_WAIT);
381    }
382
383    @Test
384    public void testFebruaryToMarchTransitionForNonLeapYear() throws Throwable {
385        long startTime = System.currentTimeMillis();
386        Intent intent = new Intent();
387
388        String title = "Date Picker Transition Test";
389        String breadcrumb = "Month Transition Test Demo";
390        String description = "Testing the transition from Feb to Mar (nonleap year)";
391        GuidanceStylist.Guidance guidance = new GuidanceStylist.Guidance(title, description,
392                breadcrumb, null);
393
394        List<GuidedAction> actionList = new ArrayList<>();
395
396        Calendar cal = Calendar.getInstance();
397
398        cal.set(Calendar.YEAR, 2017);
399        cal.set(Calendar.MONTH, Calendar.FEBRUARY);
400        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
401        Date initialDate = cal.getTime();
402
403        GuidedDatePickerAction action = new GuidedDatePickerAction.Builder(
404                mContext)
405                .id(0)
406                .title("Date")
407                .date(initialDate.getTime())
408                .datePickerFormat("DMY")
409                .build();
410
411        actionList.add(action);
412
413        GuidedStepAttributesTestFragment.clear();
414        GuidedStepAttributesTestFragment.GUIDANCE = guidance;
415        GuidedStepAttributesTestFragment.ACTION_LIST = actionList;
416
417        initActivity(intent);
418
419        DatePicker mPickerView = (DatePicker) mActivity.findViewById(
420                R.id.guidedactions_activator_item);
421
422        verticalScrollToFieldValue(Calendar.MONTH, Calendar.MARCH, new int[] {0, 1, 2},
423                mPickerView, KeyEvent.KEYCODE_DPAD_DOWN);
424        long executionTime = System.currentTimeMillis() - startTime;
425        Log.d(TAG, "testFebruaryToMarchTransition() Execution time: " + executionTime);
426        Thread.sleep(FINAL_WAIT);
427    }
428
429    @Test
430    public void testDecemberToNovemberTransition() throws Throwable {
431        long startTime = System.currentTimeMillis();
432        Intent intent = new Intent();
433
434        String title = "Date Picker Transition Test";
435        String breadcrumb = "Month Transition Test Demo";
436        String description = "Testing the transition from Dec to Nov";
437        GuidanceStylist.Guidance guidance = new GuidanceStylist.Guidance(title, description,
438                breadcrumb, null);
439
440        List<GuidedAction> actionList = new ArrayList<>();
441
442        Calendar cal = Calendar.getInstance();
443
444        cal.set(Calendar.YEAR, 2016);
445        cal.set(Calendar.MONTH, Calendar.DECEMBER);
446        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
447        Date initialDate = cal.getTime();
448
449        GuidedDatePickerAction action = new GuidedDatePickerAction.Builder(
450                mContext)
451                .id(0)
452                .title("Date")
453                .date(initialDate.getTime())
454                .datePickerFormat("DMY")
455                .build();
456
457        actionList.add(action);
458
459        GuidedStepAttributesTestFragment.clear();
460        GuidedStepAttributesTestFragment.GUIDANCE = guidance;
461        GuidedStepAttributesTestFragment.ACTION_LIST = actionList;
462
463        initActivity(intent);
464
465        DatePicker mPickerView = (DatePicker) mActivity.findViewById(
466                R.id.guidedactions_activator_item);
467
468        verticalScrollToFieldValue(Calendar.MONTH, Calendar.NOVEMBER, new int[] {0, 1, 2},
469                mPickerView, KeyEvent.KEYCODE_DPAD_UP);
470        long executionTime = System.currentTimeMillis() - startTime;
471        Log.d(TAG, "testDecemberToNovember() Execution time: " + executionTime);
472        Thread.sleep(FINAL_WAIT);
473    }
474
475    @Test
476    public void testNovemberToOctoberTransition() throws Throwable {
477        long startTime = System.currentTimeMillis();
478        Intent intent = new Intent();
479
480        String title = "Date Picker Transition Test";
481        String breadcrumb = "Month Transition Test Demo";
482        String description = "Testing the transition from Nov to Oct";
483        GuidanceStylist.Guidance guidance = new GuidanceStylist.Guidance(title, description,
484                breadcrumb, null);
485
486        List<GuidedAction> actionList = new ArrayList<>();
487
488        Calendar cal = Calendar.getInstance();
489
490        cal.set(Calendar.YEAR, 2016);
491        cal.set(Calendar.MONTH, Calendar.NOVEMBER);
492        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
493        Date initialDate = cal.getTime();
494
495        GuidedDatePickerAction action = new GuidedDatePickerAction.Builder(
496                mContext)
497                .id(0)
498                .title("Date")
499                .date(initialDate.getTime())
500                .datePickerFormat("DMY")
501                .build();
502
503        actionList.add(action);
504
505        GuidedStepAttributesTestFragment.clear();
506        GuidedStepAttributesTestFragment.GUIDANCE = guidance;
507        GuidedStepAttributesTestFragment.ACTION_LIST = actionList;
508
509        initActivity(intent);
510
511        DatePicker mPickerView = (DatePicker) mActivity.findViewById(
512                R.id.guidedactions_activator_item);
513
514        verticalScrollToFieldValue(Calendar.MONTH, Calendar.OCTOBER, new int[] {0, 1, 2},
515                mPickerView, KeyEvent.KEYCODE_DPAD_UP);
516        long executionTime = System.currentTimeMillis() - startTime;
517        Log.d(TAG, "testNovemberToOctober() Execution time: " + executionTime);
518        Thread.sleep(FINAL_WAIT);
519    }
520
521    @Test
522    public void testLeapToNonLeapYearTransition() throws Throwable {
523        long startTime = System.currentTimeMillis();
524        Intent intent = new Intent();
525
526        String title = "Date Picker Transition Test";
527        String breadcrumb = "Leap Year Transition Test Demo";
528        String description = "Testing Feb transition from leap to nonlneap year";
529        GuidanceStylist.Guidance guidance = new GuidanceStylist.Guidance(title, description,
530                breadcrumb, null);
531
532        List<GuidedAction> actionList = new ArrayList<>();
533
534        Calendar cal = Calendar.getInstance();
535
536        cal.set(Calendar.YEAR, 2016);   // 2016 is a leap year
537        cal.set(Calendar.MONTH, Calendar.FEBRUARY);
538        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
539        Date initialDate = cal.getTime();
540
541        GuidedDatePickerAction action = new GuidedDatePickerAction.Builder(
542                mContext)
543                .id(0)
544                .title("Date")
545                .date(initialDate.getTime())
546                .datePickerFormat("DMY")
547                .build();
548
549        actionList.add(action);
550
551        GuidedStepAttributesTestFragment.clear();
552        GuidedStepAttributesTestFragment.GUIDANCE = guidance;
553        GuidedStepAttributesTestFragment.ACTION_LIST = actionList;
554
555        initActivity(intent);
556
557        DatePicker mPickerView = (DatePicker) mActivity.findViewById(
558                R.id.guidedactions_activator_item);
559
560        verticalScrollToFieldValue(Calendar.YEAR, 2017, new int[] {0, 1, 2},
561                mPickerView, KeyEvent.KEYCODE_DPAD_DOWN);
562        long executionTime = System.currentTimeMillis() - startTime;
563        Log.d(TAG, "testLeapToNonLeapYearTransition() Execution time: " + executionTime);
564        Thread.sleep(FINAL_WAIT);
565    }
566
567    @Test
568    public void testNonLeapToLeapYearTransition() throws Throwable {
569        long startTime = System.currentTimeMillis();
570        Intent intent = new Intent();
571
572        String title = "Date Picker Transition Test";
573        String breadcrumb = "Leap Year Transition Test Demo";
574        String description = "Testing Feb transition from nonleap to leap year";
575        GuidanceStylist.Guidance guidance = new GuidanceStylist.Guidance(title, description,
576                breadcrumb, null);
577
578        List<GuidedAction> actionList = new ArrayList<>();
579
580        Calendar cal = Calendar.getInstance();
581
582        cal.set(Calendar.YEAR, 2017);   // 2017 is a non-leap year
583        cal.set(Calendar.MONTH, Calendar.FEBRUARY);
584        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
585        Date initialDate = cal.getTime();
586
587        GuidedDatePickerAction action = new GuidedDatePickerAction.Builder(
588                mContext)
589                .id(0)
590                .title("Date")
591                .date(initialDate.getTime())
592                .datePickerFormat("DMY")
593                .build();
594
595        actionList.add(action);
596
597        GuidedStepAttributesTestFragment.clear();
598        GuidedStepAttributesTestFragment.GUIDANCE = guidance;
599        GuidedStepAttributesTestFragment.ACTION_LIST = actionList;
600
601        initActivity(intent);
602
603        DatePicker mPickerView = (DatePicker) mActivity.findViewById(
604                R.id.guidedactions_activator_item);
605
606        verticalScrollToFieldValue(Calendar.YEAR, 2016, new int[] {0, 1, 2},
607                mPickerView, KeyEvent.KEYCODE_DPAD_UP);
608        long executionTime = System.currentTimeMillis() - startTime;
609        Log.d(TAG, "testNonLeapToLeapYearTransition() Execution time: " + executionTime);
610        Thread.sleep(FINAL_WAIT);
611    }
612
613    private void traverseMonths(DatePicker mPickerView, GuidedDatePickerAction dateAction)
614            throws Throwable {
615
616        final GuidedStepFragment mFragment = (GuidedStepFragment)
617                mActivity.getGuidedStepTestFragment();
618
619        Calendar currentActionCal = Calendar.getInstance();
620        currentActionCal.setTimeInMillis(dateAction.getDate());
621
622        sendKey(KeyEvent.KEYCODE_DPAD_CENTER);
623        Thread.sleep(TRANSITION_LENGTH);
624
625        int prevMonth = -1;
626        int currentMonth = mPickerView.getColumnAt(MONTH_INDEX).getCurrentValue();
627        while (currentMonth != prevMonth) {
628            int prevDayOfMonth = -1;
629            int currentDayOfMonth = mPickerView.getColumnAt(DAY_INDEX).getCurrentValue();
630            // scroll down the days till reaching the last day of month
631            while (currentDayOfMonth != prevDayOfMonth) {
632                sendKey(KeyEvent.KEYCODE_DPAD_DOWN);
633                Thread.sleep(VERTICAL_SCROLL_WAIT);
634                prevDayOfMonth = currentDayOfMonth;
635                currentDayOfMonth = mPickerView.getColumnAt(DAY_INDEX).getCurrentValue();
636            }
637            int oldDayValue = mPickerView.getColumnAt(DAY_INDEX).getCurrentValue();
638            int oldMonthValue = mPickerView.getColumnAt(MONTH_INDEX).getCurrentValue();
639            // increment the month
640            sendKey(KeyEvent.KEYCODE_DPAD_RIGHT);
641            Thread.sleep(VERTICAL_SCROLL_WAIT);
642
643            sendKey(KeyEvent.KEYCODE_DPAD_DOWN);
644            Thread.sleep(TRANSITION_LENGTH);
645
646            int newDayValue = mPickerView.getColumnAt(DAY_INDEX).getCurrentValue();
647            int newMonthValue = mPickerView.getColumnAt(MONTH_INDEX).getCurrentValue();
648            verifyMonthTransition(currentActionCal,
649                    oldDayValue, oldMonthValue, newDayValue, newMonthValue);
650
651            sendKey(KeyEvent.KEYCODE_DPAD_LEFT);
652            Thread.sleep(TRANSITION_LENGTH);
653            prevMonth = currentMonth;
654            currentMonth = newMonthValue;
655        }
656
657    }
658
659
660    private void verifyMonthTransition(Calendar currentCal, int oldDayValue, int oldMonthValue,
661                                       int newDayValue, int newMonthValue) {
662
663        if (oldMonthValue == newMonthValue)
664            return;
665
666        currentCal.set(Calendar.DAY_OF_MONTH, 1);
667        currentCal.set(Calendar.MONTH, oldMonthValue);
668        int expectedOldDayValue = currentCal.getActualMaximum(Calendar.DAY_OF_MONTH);
669        currentCal.set(Calendar.MONTH, newMonthValue);
670        int numDaysInNewMonth = currentCal.getActualMaximum(Calendar.DAY_OF_MONTH);
671        int expectedNewDayValue = (expectedOldDayValue <= numDaysInNewMonth) ?
672                expectedOldDayValue : numDaysInNewMonth;
673
674        assertTrue(mContext.getString(
675                R.string.datepicker_test_transition_error1, oldMonthValue),
676                oldDayValue == expectedOldDayValue
677        );
678        assertTrue(mContext.getString(
679                R.string.datepicker_test_transition_error2, newDayValue, newMonthValue),
680                newDayValue == expectedNewDayValue
681        );
682    }
683
684    @Test
685    public void testDateRangesMDYFormat() throws Throwable {
686
687        long startTime = System.currentTimeMillis();
688
689        GuidedDatePickerAction[] datePickerActions = setupDateActionsForMinAndMaxRangeTests();
690
691        scrollToMinAndMaxDates(new int[] {1, 0, 2}, datePickerActions[0]);
692        long executionTime = System.currentTimeMillis() - startTime;
693        Log.d(TAG, "testDateRangesMDYFormat() Execution time: " + executionTime);
694        Thread.sleep(FINAL_WAIT);
695    }
696
697    public void testDateRangesDMYFormat() throws Throwable {
698
699        long startTime = System.currentTimeMillis();
700
701        GuidedDatePickerAction[] datePickerActions = setupDateActionsForMinAndMaxRangeTests();
702        Log.d(TAG, "setup dateactions complete!");
703        scrollToMinAndMaxDates(new int[] {0, 1, 2}, datePickerActions[1]);
704        long executionTime = System.currentTimeMillis() - startTime;
705        Log.d(TAG, "testDateRangesDMYFormat() Execution time: " + executionTime);
706        Thread.sleep(FINAL_WAIT);
707    }
708
709    @Test
710    public void testDateRangesWithYearEqual() throws Throwable {
711
712        long startTime = System.currentTimeMillis();
713
714        GuidedDatePickerAction[] datePickerActions = setupDateActionsForMinAndMaxRangeTests();
715
716        scrollToMinAndMaxDates(new int[] {0, 1, 2}, datePickerActions[2]);
717        long executionTime = System.currentTimeMillis() - startTime;
718        Log.d(TAG, "testDateRangesWithYearEqual() Execution time: " + executionTime);
719        Thread.sleep(FINAL_WAIT);
720    }
721
722    @Test
723    public void testDateRangesWithMonthAndYearEqual() throws Throwable {
724
725        long startTime = System.currentTimeMillis();
726
727        GuidedDatePickerAction[] datePickerActions = setupDateActionsForMinAndMaxRangeTests();
728
729        scrollToMinAndMaxDates(new int[] {0, 1, 2}, datePickerActions[3]);
730        long executionTime = System.currentTimeMillis() - startTime;
731        Log.d(TAG, "testDateRangesWithMonthAndYearEqual() Execution time: " + executionTime);
732        Thread.sleep(FINAL_WAIT);
733    }
734
735    @Test
736    public void testDateRangesWithAllFieldsEqual() throws Throwable {
737
738        long startTime = System.currentTimeMillis();
739
740        GuidedDatePickerAction[] datePickerActions = setupDateActionsForMinAndMaxRangeTests();
741
742        scrollToMinAndMaxDates(new int[] {0, 1, 2}, datePickerActions[4]);
743        long executionTime = System.currentTimeMillis() - startTime;
744        Log.d(TAG, "testDateRangesWithAllFieldsEqual() Execution time: " + executionTime);
745        Thread.sleep(FINAL_WAIT);
746    }
747
748    private GuidedDatePickerAction[] setupDateActionsForMinAndMaxRangeTests() {
749        Intent intent = new Intent();
750        Resources res = mContext.getResources();
751
752        SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
753
754        Calendar currCal = Calendar.getInstance();
755        currCal.set(Calendar.YEAR, 2016);
756        currCal.set(Calendar.MONTH, Calendar.JULY);
757        currCal.set(Calendar.DAY_OF_MONTH, 15);
758
759        Calendar minCal = Calendar.getInstance();
760        minCal.set(Calendar.YEAR, 2014);
761        minCal.set(Calendar.MONTH, Calendar.OCTOBER);
762        minCal.set(Calendar.DAY_OF_MONTH, 20);
763
764        Calendar maxCal = Calendar.getInstance();
765        maxCal.set(Calendar.YEAR, 2018);
766        maxCal.set(Calendar.MONTH, Calendar.FEBRUARY);
767        maxCal.set(Calendar.DAY_OF_MONTH, 10);
768
769        String title = "Date Picker Range Test";
770        String breadcrumb = "Date Picker Range Test Demo";
771        String description = "";
772        GuidanceStylist.Guidance guidance = new GuidanceStylist.Guidance(title, description,
773                breadcrumb, null);
774
775        List<GuidedAction> actionList = new ArrayList<>();
776
777        // testing different date formats and the correctness of range changes as we scroll
778        GuidedDatePickerAction dateAction1 = new GuidedDatePickerAction.Builder(
779                mContext)
780                .id(0)
781                .title(res.getString(R.string.datepicker_with_range_title,
782                        dateFormat.format(minCal.getTime()),
783                        dateFormat.format(maxCal.getTime())))
784                .multilineDescription(true)
785                .date(currCal.getTimeInMillis())
786                .datePickerFormat("MDY")
787                .minDate(minCal.getTimeInMillis())
788                .maxDate(maxCal.getTimeInMillis())
789                .build();
790
791        GuidedDatePickerAction dateAction2 = new GuidedDatePickerAction.Builder(
792                mContext)
793                .id(1)
794                .title(res.getString(R.string.datepicker_with_range_title,
795                        dateFormat.format(minCal.getTimeInMillis()),
796                        dateFormat.format(maxCal.getTimeInMillis())))
797                .multilineDescription(true)
798                .date(currCal.getTimeInMillis())
799                .datePickerFormat("DMY")
800                .minDate(minCal.getTimeInMillis())
801                .maxDate(maxCal.getTimeInMillis())
802                .build();
803
804        // testing date ranges when Year is equal
805        minCal.set(Calendar.YEAR, maxCal.get(Calendar.YEAR));
806        int minMonth = Math.min(minCal.get(Calendar.MONTH), maxCal.get(Calendar.MONTH));
807        int maxMonth = Math.max(minCal.get(Calendar.MONTH), maxCal.get(Calendar.MONTH));
808        minCal.set(Calendar.MONTH, minMonth);
809        maxCal.set(Calendar.MONTH, maxMonth);
810
811        GuidedDatePickerAction dateAction3 = new GuidedDatePickerAction.Builder(
812                mContext)
813                .id(2)
814                .title(res.getString(R.string.datepicker_with_range_title,
815                        dateFormat.format(minCal.getTimeInMillis()),
816                        dateFormat.format(maxCal.getTimeInMillis())))
817                .multilineDescription(true)
818                .date(currCal.getTimeInMillis())
819                .datePickerFormat("DMY")
820                .minDate(minCal.getTimeInMillis())
821                .maxDate(maxCal.getTimeInMillis())
822                .build();
823
824
825        // testing date ranges when both Month and Year are equal
826        minCal.set(Calendar.MONTH, maxCal.get(Calendar.MONTH));
827        int minDay = Math.min(minCal.get(Calendar.DAY_OF_MONTH), maxCal.get(Calendar.DAY_OF_MONTH));
828        int maxDay = Math.max(minCal.get(Calendar.DAY_OF_MONTH), maxCal.get(Calendar.DAY_OF_MONTH));
829        minCal.set(Calendar.DAY_OF_MONTH, minDay);
830        maxCal.set(Calendar.DAY_OF_MONTH, maxDay);
831
832        GuidedDatePickerAction dateAction4 = new GuidedDatePickerAction.Builder(
833                mContext)
834                .id(3)
835                .title(res.getString(R.string.datepicker_with_range_title,
836                        dateFormat.format(minCal.getTimeInMillis()),
837                        dateFormat.format(maxCal.getTimeInMillis())))
838                .multilineDescription(true)
839                .date(currCal.getTimeInMillis())
840                .datePickerFormat("DMY")
841                .minDate(minCal.getTimeInMillis())
842                .maxDate(maxCal.getTimeInMillis())
843                .build();
844
845
846        // testing date ranges when all fields are equal
847        minCal.set(Calendar.DAY_OF_MONTH, maxCal.get(Calendar.DAY_OF_MONTH));
848
849        GuidedDatePickerAction dateAction5 = new GuidedDatePickerAction.Builder(
850                mContext)
851                .id(4)
852                .title(res.getString(R.string.datepicker_with_range_title,
853                        dateFormat.format(minCal.getTimeInMillis()),
854                        dateFormat.format(maxCal.getTimeInMillis())))
855                .multilineDescription(true)
856                .date(currCal.getTimeInMillis())
857                .datePickerFormat("DMY")
858                .minDate(minCal.getTimeInMillis())
859                .maxDate(maxCal.getTimeInMillis())
860                .build();
861
862        actionList.add(dateAction1);
863        actionList.add(dateAction2);
864        actionList.add(dateAction3);
865        actionList.add(dateAction4);
866        actionList.add(dateAction5);
867
868        GuidedStepAttributesTestFragment.clear();
869        GuidedStepAttributesTestFragment.GUIDANCE = guidance;
870        GuidedStepAttributesTestFragment.ACTION_LIST = actionList;
871
872        initActivity(intent);
873        return new GuidedDatePickerAction[] {dateAction1, dateAction2, dateAction3, dateAction4,
874                dateAction5};
875    }
876
877    private void scrollToMinAndMaxDates(int[] columnIndices, GuidedDatePickerAction dateAction)
878            throws Throwable{
879
880        final GuidedStepFragment mFragment = (GuidedStepFragment)
881                mActivity.getGuidedStepTestFragment();
882
883        VerticalGridView guidedActionsList = (VerticalGridView)
884                mActivity.findViewById(R.id.guidedactions_list);
885
886        int currSelectedAction = mFragment.getSelectedActionPosition();
887        // scroll up/down to the requested action
888        long verticalScrollOffset = dateAction.getId() - currSelectedAction;
889
890        int verticalScrollDir = KeyEvent.KEYCODE_DPAD_DOWN;
891        if (verticalScrollOffset < 0) {
892            verticalScrollOffset= -verticalScrollOffset;
893            verticalScrollDir = KeyEvent.KEYCODE_DPAD_UP;
894        }
895        for(int i = 0; i < verticalScrollOffset; i++) {
896            sendKey(verticalScrollDir);
897            Thread.sleep(TRANSITION_LENGTH);
898        }
899
900        assertTrue("The wrong action was selected!", mFragment.getSelectedActionPosition() ==
901                dateAction.getId());
902        DatePicker mPickerView = (DatePicker) mFragment.getActionItemView((int) dateAction.getId())
903                .findViewById(R.id.guidedactions_activator_item);
904
905        Calendar currentActionCal = Calendar.getInstance();
906        currentActionCal.setTimeInMillis(dateAction.getDate());
907
908
909        // scrolling to the minimum date
910
911        verticalScrollToFieldValue(Calendar.YEAR, -1, columnIndices, mPickerView,
912                KeyEvent.KEYCODE_DPAD_UP);
913        dateAction.setDate(mPickerView.getDate());
914
915        verticalScrollToFieldValue(Calendar.MONTH, -1, columnIndices, mPickerView,
916                KeyEvent.KEYCODE_DPAD_UP);
917        dateAction.setDate(mPickerView.getDate());
918
919        verticalScrollToFieldValue(Calendar.DAY_OF_MONTH, -1, columnIndices, mPickerView,
920                KeyEvent.KEYCODE_DPAD_UP);
921        dateAction.setDate(mPickerView.getDate());
922
923        Thread.sleep(VERTICAL_SCROLL_WAIT);
924
925        // now scrolling to the maximum date
926
927        verticalScrollToFieldValue(Calendar.YEAR, -1, columnIndices, mPickerView,
928                KeyEvent.KEYCODE_DPAD_DOWN);
929        dateAction.setDate(mPickerView.getDate());
930
931        verticalScrollToFieldValue(Calendar.MONTH, -1, columnIndices, mPickerView,
932                KeyEvent.KEYCODE_DPAD_DOWN);
933        dateAction.setDate(mPickerView.getDate());
934
935        verticalScrollToFieldValue(Calendar.DAY_OF_MONTH, -1, columnIndices, mPickerView,
936                KeyEvent.KEYCODE_DPAD_DOWN);
937        dateAction.setDate(mPickerView.getDate());
938
939        sendKey(KeyEvent.KEYCODE_DPAD_CENTER);
940        Thread.sleep(TRANSITION_LENGTH);
941    }
942
943}
944