GuidedDatePickerTest.java revision fad2335f169d36b7b6f2c0ec8ddfe6c0094c2072
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.app.Instrumentation; 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.view.View; 32import android.view.ViewGroup; 33import android.widget.LinearLayout; 34 35import java.text.SimpleDateFormat; 36import java.util.ArrayList; 37import java.util.Calendar; 38import java.util.Date; 39import java.util.List; 40 41@MediumTest 42public class GuidedDatePickerTest extends 43 ActivityInstrumentationTestCase2<GuidedStepAttributesTestActivity> { 44 45 static final long TRANSITION_LENGTH = 1000; 46 static long VERTICAL_SCROLL_WAIT = 500; 47 static long HORIZONTAL_SCROLL_WAIT = 500; 48 static final long FINAL_WAIT = 3000; 49 50 static final String TAG = "GuidedDatePickerTest"; 51 52 private static final int DAY_INDEX = 0; 53 private static final int MONTH_INDEX = 1; 54 private static final int YEAR_INDEX = 2; 55 Instrumentation mInstrumentation; 56 GuidedStepAttributesTestActivity mActivity; 57 58 public GuidedDatePickerTest() { 59 super(GuidedStepAttributesTestActivity.class); 60 } 61 62 private void initActivity(Intent intent) { 63 64 setActivityIntent(intent); 65 mActivity = getActivity(); 66 try { 67 Thread.sleep(2000); 68 } catch(InterruptedException e) { 69 e.printStackTrace(); 70 } 71 } 72 73 private void scrollOnField(int field, int[] columnIndices, DatePicker mPickerView, 74 int SCROLL_DIR) throws Throwable { 75 76 final GuidedStepFragment mFragment = (GuidedStepFragment) 77 mActivity.getGuidedStepTestFragment(); 78 79 int mColDayIndex = columnIndices[0]; 80 int mColMonthIndex = columnIndices[1]; 81 int mColYearIndex = columnIndices[2]; 82 int columnIndex = -1; 83 switch (field) { 84 case Calendar.DAY_OF_MONTH: 85 columnIndex = mColDayIndex; 86 break; 87 case Calendar.MONTH: 88 columnIndex = mColMonthIndex; 89 break; 90 case Calendar.YEAR: 91 columnIndex = mColYearIndex; 92 } 93 94 95 LinearLayout columnsLayout = (LinearLayout) mPickerView.getChildAt(0); 96 97 int focusedFieldPos = columnsLayout.indexOfChild(columnsLayout.getFocusedChild()); 98 if (focusedFieldPos == -1) { 99 sendKeys(KeyEvent.KEYCODE_DPAD_CENTER); 100 Thread.sleep(TRANSITION_LENGTH); 101 } 102 focusedFieldPos = columnsLayout.indexOfChild(columnsLayout.getFocusedChild()); 103 assertTrue("Date field could not be focused!", (focusedFieldPos != -1)); 104 105 // following is to skip the separator fields "/" which are unfocusable but counted as 106 // children of columnsLayout 107 switch (focusedFieldPos) { 108 case 0: 109 focusedFieldPos = 0; 110 break; 111 case 2: 112 focusedFieldPos = 1; 113 break; 114 case 4: 115 focusedFieldPos = 2; 116 } 117 118 // now scroll right or left to the corresponding date field as indicated by the input field 119 int horizontalScrollOffset = columnIndex - focusedFieldPos; 120 121 int horizontalScrollDir = KeyEvent.KEYCODE_DPAD_RIGHT; 122 if (horizontalScrollOffset < 0) { 123 horizontalScrollOffset = -horizontalScrollOffset; 124 horizontalScrollDir = KeyEvent.KEYCODE_DPAD_LEFT; 125 } 126 for(int i = 0; i < horizontalScrollOffset; i++) { 127 sendKeys(horizontalScrollDir); 128 Thread.sleep(HORIZONTAL_SCROLL_WAIT); 129 } 130 131 132 Calendar currentActionCal = Calendar.getInstance(); 133 currentActionCal.setTimeInMillis(mPickerView.getDate()); 134 135 Calendar minCal = Calendar.getInstance(); 136 minCal.setTimeInMillis(mPickerView.getMinDate()); 137 138 Calendar maxCal = Calendar.getInstance(); 139 maxCal.setTimeInMillis(mPickerView.getMaxDate()); 140 141 142 int prevColumnVal = -1; 143 int currentColumnVal = mPickerView.getColumnAt(columnIndex).getCurrentValue(); 144 while( currentColumnVal != prevColumnVal ){ 145 assertTrue(getActivity().getString(R.string.datepicker_test_wrong_day_value), 146 mPickerView.getColumnAt(mColDayIndex).getCurrentValue() == 147 currentActionCal.get(Calendar.DAY_OF_MONTH) 148 ); 149 assertTrue(getActivity().getString(R.string.datepicker_test_wrong_month_value), 150 mPickerView.getColumnAt(mColMonthIndex).getCurrentValue() == 151 currentActionCal.get(Calendar.MONTH) 152 ); 153 assertTrue(getActivity().getString(R.string.datepicker_test_wrong_year_value), 154 mPickerView.getColumnAt(mColYearIndex).getCurrentValue() == 155 currentActionCal.get(Calendar.YEAR) 156 ); 157 158 int offset = SCROLL_DIR == KeyEvent.KEYCODE_DPAD_DOWN ? 1 : -1; 159 addDate(currentActionCal, field, offset, minCal, maxCal); 160 161 sendKeys(SCROLL_DIR); 162 Thread.sleep(VERTICAL_SCROLL_WAIT); 163 164 prevColumnVal = currentColumnVal; 165 currentColumnVal = mPickerView.getColumnAt(columnIndex).getCurrentValue(); 166 } 167 } 168 169 private void addDate(Calendar mCurrentDate, int field, int offset, 170 Calendar mMinDate, Calendar mMaxDate) { 171 int maxOffset = -1; 172 int actualMinFieldValue, actualMaxFieldValue; 173 174 if ( field == Calendar.YEAR ) { 175 actualMinFieldValue = mMinDate.get(Calendar.YEAR); 176 actualMaxFieldValue = mMaxDate.get(Calendar.YEAR); 177 } else { 178 actualMinFieldValue = mCurrentDate.getActualMinimum(field); 179 actualMaxFieldValue = mCurrentDate.getActualMaximum(field); 180 } 181 182 if ( offset > 0 ) { 183 maxOffset = Math.min( 184 actualMaxFieldValue - mCurrentDate.get(field), offset); 185 mCurrentDate.add(field, maxOffset); 186 if (mCurrentDate.after(mMaxDate)) { 187 mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis()); 188 } 189 } else { 190 maxOffset = Math.max( 191 actualMinFieldValue - mCurrentDate.get(field), offset); 192 mCurrentDate.add(field, Math.max(offset, maxOffset)); 193 if (mCurrentDate.before(mMinDate)) { 194 mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis()); 195 } 196 } 197 } 198 199 public void testDifferentMonthLengths() throws Throwable { 200 201 mInstrumentation = getInstrumentation(); 202 Intent intent = new Intent(mInstrumentation.getContext(), 203 GuidedStepAttributesTestActivity.class); 204 Resources res = mInstrumentation.getContext().getResources(); 205 206 final int NUM_DATE_ACTIONS = 1; 207 208 String title = "Date Picker Transition Test"; 209 String breadcrumb = "Month Transition Test Demo"; 210 String description = "Testing the transition between longer to shorter months"; 211 GuidanceStylist.Guidance guidance = new GuidanceStylist.Guidance(title, description, 212 breadcrumb, null); 213 214 List<GuidedAction> actionList = new ArrayList<>(); 215 216 Calendar cal = Calendar.getInstance(); 217 218 cal.set(Calendar.YEAR, 2016); 219 cal.set(Calendar.MONTH, Calendar.JANUARY); 220 cal.set(Calendar.DAY_OF_MONTH, 30); 221 Date initialDate = cal.getTime(); 222 223 GuidedDatePickerAction action = new GuidedDatePickerAction.Builder( 224 mInstrumentation.getContext()) 225 .id(0) 226 .title("Date") 227 .date(initialDate.getTime()) 228 .datePickerFormat("DMY") 229 .build(); 230 231 actionList.add(action); 232 233 GuidedStepAttributesTestFragment.clear(); 234 GuidedStepAttributesTestFragment.GUIDANCE = guidance; 235 GuidedStepAttributesTestFragment.ACTION_LIST = actionList; 236 237 initActivity(intent); 238 239 DatePicker mPickerView = (DatePicker) mActivity.findViewById( 240 R.id.guidedactions_activator_item); 241 242 final GuidedStepFragment mFragment = (GuidedStepFragment) mActivity. 243 getGuidedStepTestFragment(); 244 traverseMonths(mPickerView, (GuidedDatePickerAction) actionList.get(0)); 245 Thread.sleep(FINAL_WAIT); 246 } 247 248 private void traverseMonths(DatePicker mPickerView, GuidedDatePickerAction dateAction) 249 throws Throwable{ 250 251 final GuidedStepFragment mFragment = (GuidedStepFragment) 252 mActivity.getGuidedStepTestFragment(); 253 254 Calendar currentActionCal = Calendar.getInstance(); 255 currentActionCal.setTimeInMillis(dateAction.getDate()); 256 257 sendKeys(KeyEvent.KEYCODE_DPAD_CENTER); 258 Thread.sleep(TRANSITION_LENGTH); 259 260 int prevMonth = -1; 261 int currentMonth = mPickerView.getColumnAt(MONTH_INDEX).getCurrentValue(); 262 while (currentMonth != prevMonth) { 263 int prevDayOfMonth = -1; 264 int currentDayOfMonth = mPickerView.getColumnAt(DAY_INDEX).getCurrentValue(); 265 // scroll down the days till reaching the last day of month 266 while (currentDayOfMonth != prevDayOfMonth) { 267 sendKeys(KeyEvent.KEYCODE_DPAD_DOWN); 268 Thread.sleep(VERTICAL_SCROLL_WAIT); 269 prevDayOfMonth = currentDayOfMonth; 270 currentDayOfMonth = mPickerView.getColumnAt(DAY_INDEX).getCurrentValue(); 271 } 272 int oldDayValue = mPickerView.getColumnAt(DAY_INDEX).getCurrentValue(); 273 int oldMonthValue = mPickerView.getColumnAt(MONTH_INDEX).getCurrentValue(); 274 // increment the month 275 sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT); 276 Thread.sleep(VERTICAL_SCROLL_WAIT); 277 278 sendKeys(KeyEvent.KEYCODE_DPAD_DOWN); 279 Thread.sleep(TRANSITION_LENGTH); 280 281 int newDayValue = mPickerView.getColumnAt(DAY_INDEX).getCurrentValue(); 282 int newMonthValue = mPickerView.getColumnAt(MONTH_INDEX).getCurrentValue(); 283 verifyMonthTransition(currentActionCal, 284 oldDayValue, oldMonthValue, newDayValue, newMonthValue); 285 286 sendKeys(KeyEvent.KEYCODE_DPAD_LEFT); 287 Thread.sleep(TRANSITION_LENGTH); 288 prevMonth = currentMonth; 289 currentMonth = newMonthValue; 290 } 291 292 } 293 294 private void verifyMonthTransition(Calendar currentCal, int oldDayValue, int oldMonthValue, 295 int newDayValue, int newMonthValue) { 296 297 if (oldMonthValue == newMonthValue) 298 return; 299 300 currentCal.set(Calendar.DAY_OF_MONTH, 1); 301 currentCal.set(Calendar.MONTH, oldMonthValue); 302 int expectedOldDayValue = currentCal.getActualMaximum(Calendar.DAY_OF_MONTH); 303 currentCal.set(Calendar.MONTH, newMonthValue); 304 int numDaysInNewMonth = currentCal.getActualMaximum(Calendar.DAY_OF_MONTH); 305 int expectedNewDayValue = (expectedOldDayValue <= numDaysInNewMonth) ? 306 expectedOldDayValue : numDaysInNewMonth; 307 308 assertTrue(getActivity().getString( 309 R.string.datepicker_test_transition_error1, oldMonthValue), 310 oldDayValue == expectedOldDayValue 311 ); 312 assertTrue(getActivity().getString( 313 R.string.datepicker_test_transition_error2, newDayValue, newMonthValue), 314 newDayValue == expectedNewDayValue 315 ); 316 } 317 318 public void testDateRanges() throws Throwable { 319 320 mInstrumentation = getInstrumentation(); 321 Intent intent = new Intent(mInstrumentation.getContext(), 322 GuidedStepAttributesTestActivity.class); 323 Resources res = mInstrumentation.getContext().getResources(); 324 325 SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy"); 326 327 Calendar currCal = Calendar.getInstance(); 328 currCal.set(Calendar.YEAR, 2016); 329 currCal.set(Calendar.MONTH, Calendar.JULY); 330 currCal.set(Calendar.DAY_OF_MONTH, 15); 331 332 Calendar minCal = Calendar.getInstance(); 333 minCal.set(Calendar.YEAR, 2014); 334 minCal.set(Calendar.MONTH, Calendar.OCTOBER); 335 minCal.set(Calendar.DAY_OF_MONTH, 20); 336 337 Calendar maxCal = Calendar.getInstance(); 338 maxCal.set(Calendar.YEAR, 2018); 339 maxCal.set(Calendar.MONTH, Calendar.FEBRUARY); 340 maxCal.set(Calendar.DAY_OF_MONTH, 10); 341 342 String title = "Date Picker Range Test"; 343 String breadcrumb = "Date Picker Range Test Demo"; 344 String description = ""; 345 GuidanceStylist.Guidance guidance = new GuidanceStylist.Guidance(title, description, 346 breadcrumb, null); 347 348 List<GuidedAction> actionList = new ArrayList<>(); 349 350 // testing different date formats and the correctness of range changes as we scroll 351 GuidedDatePickerAction dateAction1 = new GuidedDatePickerAction.Builder( 352 mInstrumentation.getContext()) 353 .id(0) 354 .title(res.getString(R.string.datepicker_with_range_title, 355 dateFormat.format(minCal.getTime()), 356 dateFormat.format(maxCal.getTime()))) 357 .multilineDescription(true) 358 .date(currCal.getTimeInMillis()) 359 .datePickerFormat("MDY") 360 .minDate(minCal.getTimeInMillis()) 361 .maxDate(maxCal.getTimeInMillis()) 362 .build(); 363 364 GuidedDatePickerAction dateAction2 = new GuidedDatePickerAction.Builder( 365 mInstrumentation.getContext()) 366 .id(1) 367 .title(res.getString(R.string.datepicker_with_range_title, 368 dateFormat.format(minCal.getTimeInMillis()), 369 dateFormat.format(maxCal.getTimeInMillis()))) 370 .multilineDescription(true) 371 .date(currCal.getTimeInMillis()) 372 .datePickerFormat("DMY") 373 .minDate(minCal.getTimeInMillis()) 374 .maxDate(maxCal.getTimeInMillis()) 375 .build(); 376 377 // testing date ranges when Year is equal 378 minCal.set(Calendar.YEAR, maxCal.get(Calendar.YEAR)); 379 int minMonth = Math.min(minCal.get(Calendar.MONTH), maxCal.get(Calendar.MONTH)); 380 int maxMonth = Math.max(minCal.get(Calendar.MONTH), maxCal.get(Calendar.MONTH)); 381 minCal.set(Calendar.MONTH, minMonth); 382 maxCal.set(Calendar.MONTH, maxMonth); 383 384 GuidedDatePickerAction dateAction3 = new GuidedDatePickerAction.Builder( 385 mInstrumentation.getContext()) 386 .id(2) 387 .title(res.getString(R.string.datepicker_with_range_title, 388 dateFormat.format(minCal.getTimeInMillis()), 389 dateFormat.format(maxCal.getTimeInMillis()))) 390 .multilineDescription(true) 391 .date(currCal.getTimeInMillis()) 392 .datePickerFormat("DMY") 393 .minDate(minCal.getTimeInMillis()) 394 .maxDate(maxCal.getTimeInMillis()) 395 .build(); 396 397 398 // testing date ranges when both Month and Year are equal 399 minCal.set(Calendar.MONTH, maxCal.get(Calendar.MONTH)); 400 int minDay = Math.min(minCal.get(Calendar.DAY_OF_MONTH), maxCal.get(Calendar.DAY_OF_MONTH)); 401 int maxDay = Math.max(minCal.get(Calendar.DAY_OF_MONTH), maxCal.get(Calendar.DAY_OF_MONTH)); 402 minCal.set(Calendar.DAY_OF_MONTH, minDay); 403 maxCal.set(Calendar.DAY_OF_MONTH, maxDay); 404 405 GuidedDatePickerAction dateAction4 = new GuidedDatePickerAction.Builder( 406 mInstrumentation.getContext()) 407 .id(3) 408 .title(res.getString(R.string.datepicker_with_range_title, 409 dateFormat.format(minCal.getTimeInMillis()), 410 dateFormat.format(maxCal.getTimeInMillis()))) 411 .multilineDescription(true) 412 .date(currCal.getTimeInMillis()) 413 .datePickerFormat("DMY") 414 .minDate(minCal.getTimeInMillis()) 415 .maxDate(maxCal.getTimeInMillis()) 416 .build(); 417 418 419 // testing date ranges when all fields are equal 420 minCal.set(Calendar.DAY_OF_MONTH, maxCal.get(Calendar.DAY_OF_MONTH)); 421 422 GuidedDatePickerAction dateAction5 = new GuidedDatePickerAction.Builder( 423 mInstrumentation.getContext()) 424 .id(4) 425 .title(res.getString(R.string.datepicker_with_range_title, 426 dateFormat.format(minCal.getTimeInMillis()), 427 dateFormat.format(maxCal.getTimeInMillis()))) 428 .multilineDescription(true) 429 .date(currCal.getTimeInMillis()) 430 .datePickerFormat("DMY") 431 .minDate(minCal.getTimeInMillis()) 432 .maxDate(maxCal.getTimeInMillis()) 433 .build(); 434 435 actionList.add(dateAction1); 436 actionList.add(dateAction2); 437 actionList.add(dateAction3); 438 actionList.add(dateAction4); 439 actionList.add(dateAction5); 440 441 GuidedStepAttributesTestFragment.clear(); 442 GuidedStepAttributesTestFragment.GUIDANCE = guidance; 443 GuidedStepAttributesTestFragment.ACTION_LIST = actionList; 444 445 initActivity(intent); 446 447 final GuidedStepFragment mFragment = (GuidedStepFragment) mActivity. 448 getGuidedStepTestFragment(); 449 450 scrollToMinAndMaxDates(new int[] {1, 0, 2}, dateAction1); 451 scrollToMinAndMaxDates(new int[] {0, 1, 2}, dateAction2); 452 scrollToMinAndMaxDates(new int[] {0, 1, 2}, dateAction3); 453 scrollToMinAndMaxDates(new int[] {0, 1, 2}, dateAction4); 454 scrollToMinAndMaxDates(new int[] {0, 1, 2}, dateAction5); 455 456 Thread.sleep(FINAL_WAIT); 457 } 458 459 private void scrollToMinAndMaxDates(int[] columnIndices, GuidedDatePickerAction dateAction) 460 throws Throwable{ 461 462 final GuidedStepFragment mFragment = (GuidedStepFragment) 463 mActivity.getGuidedStepTestFragment(); 464 465 VerticalGridView guidedActionsList = (VerticalGridView) 466 mActivity.findViewById(R.id.guidedactions_list); 467 468 int currSelectedAction = mFragment.getSelectedActionPosition(); 469 // scroll up/down to the requested action 470 long verticalScrollOffset = dateAction.getId() - currSelectedAction; 471 472 int verticalScrollDir = KeyEvent.KEYCODE_DPAD_DOWN; 473 if (verticalScrollOffset < 0) { 474 verticalScrollOffset= -verticalScrollOffset; 475 verticalScrollDir = KeyEvent.KEYCODE_DPAD_UP; 476 } 477 for(int i = 0; i < verticalScrollOffset; i++) { 478 sendKeys(verticalScrollDir); 479 Thread.sleep(TRANSITION_LENGTH); 480 } 481 482 assertTrue("The wrong action was selected!", mFragment.getSelectedActionPosition() == 483 dateAction.getId()); 484 DatePicker mPickerView = (DatePicker) mFragment.getActionItemView((int) dateAction.getId()) 485 .findViewById(R.id.guidedactions_activator_item); 486 487 Calendar currentActionCal = Calendar.getInstance(); 488 currentActionCal.setTimeInMillis(dateAction.getDate()); 489 490 491 // scrolling to the minimum date 492 493 scrollOnField(Calendar.YEAR, columnIndices, mPickerView, KeyEvent.KEYCODE_DPAD_UP); 494 dateAction.setDate(mPickerView.getDate()); 495 496 scrollOnField(Calendar.MONTH, columnIndices, mPickerView, KeyEvent.KEYCODE_DPAD_UP); 497 dateAction.setDate(mPickerView.getDate()); 498 499 scrollOnField(Calendar.DAY_OF_MONTH, columnIndices, mPickerView, KeyEvent.KEYCODE_DPAD_UP); 500 dateAction.setDate(mPickerView.getDate()); 501 502 Thread.sleep(VERTICAL_SCROLL_WAIT); 503 504 // now scrolling to the maximum date 505 506 scrollOnField(Calendar.YEAR, columnIndices, mPickerView, KeyEvent.KEYCODE_DPAD_DOWN); 507 dateAction.setDate(mPickerView.getDate()); 508 509 scrollOnField(Calendar.MONTH, columnIndices, mPickerView, KeyEvent.KEYCODE_DPAD_DOWN); 510 dateAction.setDate(mPickerView.getDate()); 511 512 scrollOnField(Calendar.DAY_OF_MONTH, columnIndices, mPickerView, KeyEvent.KEYCODE_DPAD_DOWN); 513 dateAction.setDate(mPickerView.getDate()); 514 515 sendKeys(KeyEvent.KEYCODE_DPAD_CENTER); 516 Thread.sleep(TRANSITION_LENGTH); 517 } 518 519} 520