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