1/* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.support.v17.leanback.widget; 18 19import static org.hamcrest.CoreMatchers.is; 20import static org.hamcrest.MatcherAssert.assertThat; 21 22import android.content.Context; 23import android.content.Intent; 24import android.support.test.InstrumentationRegistry; 25import android.support.test.filters.MediumTest; 26import android.support.test.rule.ActivityTestRule; 27import android.support.test.runner.AndroidJUnit4; 28import android.support.v17.leanback.test.R; 29import android.support.v17.leanback.widget.picker.TimePicker; 30import android.view.KeyEvent; 31import android.view.View; 32import android.view.ViewGroup; 33 34import org.junit.Rule; 35import org.junit.Test; 36import org.junit.runner.RunWith; 37 38@MediumTest 39@RunWith(AndroidJUnit4.class) 40public class TimePickerTest { 41 42 private static final String TAG = "TimePickerTest"; 43 private static final long TRANSITION_LENGTH = 1000; 44 private static final long UPDATE_LENGTH = 1000; 45 46 47 Context mContext; 48 View mViewAbove; 49 TimePicker mTimePicker12HourView; 50 TimePicker mTimePicker24HourView; 51 View mViewBelow; 52 53 @Rule 54 public ActivityTestRule<TimePickerActivity> mActivityTestRule = 55 new ActivityTestRule<>(TimePickerActivity.class, false, false); 56 private TimePickerActivity mActivity; 57 58 public void initActivity(Intent intent) throws Throwable { 59 mActivity = mActivityTestRule.launchActivity(intent); 60 mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 61 mTimePicker12HourView = (TimePicker) mActivity.findViewById(R.id.time_picker12); 62 mTimePicker12HourView.setActivatedVisibleItemCount(3); 63 mTimePicker12HourView.setOnClickListener(new View.OnClickListener() { 64 @Override 65 public void onClick(View v) { 66 mTimePicker12HourView.setActivated(!mTimePicker12HourView.isActivated()); 67 } 68 }); 69 70 if (intent.getIntExtra(DatePickerActivity.EXTRA_LAYOUT_RESOURCE_ID, 71 R.layout.timepicker_with_other_widgets) == R.layout.timepicker_with_other_widgets) { 72 mViewAbove = mActivity.findViewById(R.id.above_picker); 73 mViewBelow = mActivity.findViewById(R.id.below_picker); 74 mTimePicker24HourView = (TimePicker) mActivity.findViewById(R.id.time_picker24); 75 mTimePicker24HourView.setActivatedVisibleItemCount(3); 76 mTimePicker24HourView.setOnClickListener(new View.OnClickListener() { 77 @Override 78 public void onClick(View v) { 79 mTimePicker24HourView.setActivated(!mTimePicker24HourView.isActivated()); 80 } 81 }); 82 } else if (intent.getIntExtra(DatePickerActivity.EXTRA_LAYOUT_RESOURCE_ID, 83 R.layout.timepicker_with_other_widgets) == R.layout.timepicker_alone) { 84 // A layout with only a TimePicker widget that is initially activated. 85 mActivityTestRule.runOnUiThread(new Runnable() { 86 @Override 87 public void run() { 88 mTimePicker12HourView.setActivated(true); 89 } 90 }); 91 Thread.sleep(500); 92 } 93 } 94 95 @Test 96 public void testSetHourIn24hFormat() throws Throwable { 97 Intent intent = new Intent(); 98 intent.putExtra(DatePickerActivity.EXTRA_LAYOUT_RESOURCE_ID, 99 R.layout.timepicker_with_other_widgets); 100 initActivity(intent); 101 mActivityTestRule.runOnUiThread(new Runnable() { 102 @Override 103 public void run() { 104 mTimePicker24HourView.setHour(0); 105 } 106 }); 107 Thread.sleep(UPDATE_LENGTH); 108 assertThat("TimePicker in 24-hour mode returns a different hour in getHour()", 109 mTimePicker24HourView.getHour(), is(0)); 110 111 mActivityTestRule.runOnUiThread(new Runnable() { 112 @Override 113 public void run() { 114 mTimePicker24HourView.setHour(11); 115 } 116 }); 117 Thread.sleep(UPDATE_LENGTH); 118 assertThat("TimePicker in 24-hour mode returns a different hour in getHour()", 119 mTimePicker24HourView.getHour(), is(11)); 120 121 mActivityTestRule.runOnUiThread(new Runnable() { 122 @Override 123 public void run() { 124 mTimePicker24HourView.setHour(12); 125 } 126 }); 127 Thread.sleep(UPDATE_LENGTH); 128 assertThat("TimePicker in 24-hour mode returns a different hour in getHour()", 129 mTimePicker24HourView.getHour(), is(12)); 130 131 mActivityTestRule.runOnUiThread(new Runnable() { 132 @Override 133 public void run() { 134 mTimePicker24HourView.setHour(13); 135 } 136 }); 137 Thread.sleep(UPDATE_LENGTH); 138 assertThat("TimePicker in 24-hour mode returns a different hour in getHour()", 139 mTimePicker24HourView.getHour(), is(13)); 140 141 mActivityTestRule.runOnUiThread(new Runnable() { 142 @Override 143 public void run() { 144 mTimePicker24HourView.setHour(23); 145 } 146 }); 147 Thread.sleep(UPDATE_LENGTH); 148 assertThat("TimePicker in 24-hour mode returns a different hour in getHour()", 149 mTimePicker24HourView.getHour(), is(23)); 150 } 151 152 @Test 153 public void testSetHourIn12hFormat() throws Throwable { 154 Intent intent = new Intent(); 155 intent.putExtra(DatePickerActivity.EXTRA_LAYOUT_RESOURCE_ID, 156 R.layout.timepicker_with_other_widgets); 157 initActivity(intent); 158 mActivityTestRule.runOnUiThread(new Runnable() { 159 @Override 160 public void run() { 161 mTimePicker12HourView.setHour(0); 162 } 163 }); 164 Thread.sleep(UPDATE_LENGTH); 165 assertThat("TimePicker in 24-hour mode returns a different hour in getHour()", 166 mTimePicker12HourView.getHour(), is(0)); 167 168 mActivityTestRule.runOnUiThread(new Runnable() { 169 @Override 170 public void run() { 171 mTimePicker12HourView.setHour(11); 172 } 173 }); 174 Thread.sleep(UPDATE_LENGTH); 175 assertThat("TimePicker in 24-hour mode returns a different hour in getHour()", 176 mTimePicker12HourView.getHour(), is(11)); 177 178 mActivityTestRule.runOnUiThread(new Runnable() { 179 @Override 180 public void run() { 181 mTimePicker12HourView.setHour(12); 182 } 183 }); 184 Thread.sleep(UPDATE_LENGTH); 185 assertThat("TimePicker in 24-hour mode returns a different hour in getHour()", 186 mTimePicker12HourView.getHour(), is(12)); 187 188 mActivityTestRule.runOnUiThread(new Runnable() { 189 @Override 190 public void run() { 191 mTimePicker12HourView.setHour(13); 192 } 193 }); 194 Thread.sleep(UPDATE_LENGTH); 195 assertThat("TimePicker in 24-hour mode returns a different hour in getHour()", 196 mTimePicker12HourView.getHour(), is(13)); 197 198 mActivityTestRule.runOnUiThread(new Runnable() { 199 @Override 200 public void run() { 201 mTimePicker12HourView.setHour(23); 202 } 203 }); 204 Thread.sleep(UPDATE_LENGTH); 205 assertThat("TimePicker in 24-hour mode returns a different hour in getHour()", 206 mTimePicker12HourView.getHour(), is(23)); 207 } 208 209 @Test 210 public void testSetMinuteIn24hFormat() throws Throwable { 211 Intent intent = new Intent(); 212 intent.putExtra(DatePickerActivity.EXTRA_LAYOUT_RESOURCE_ID, 213 R.layout.timepicker_with_other_widgets); 214 initActivity(intent); 215 mActivityTestRule.runOnUiThread(new Runnable() { 216 @Override 217 public void run() { 218 mTimePicker24HourView.setMinute(0); 219 } 220 }); 221 Thread.sleep(UPDATE_LENGTH); 222 assertThat("TimePicker in 24-hour mode returns a different hour in getHour()", 223 mTimePicker24HourView.getMinute(), is(0)); 224 225 mActivityTestRule.runOnUiThread(new Runnable() { 226 @Override 227 public void run() { 228 mTimePicker24HourView.setMinute(11); 229 } 230 }); 231 Thread.sleep(UPDATE_LENGTH); 232 assertThat("TimePicker in 24-hour mode returns a different hour in getHour()", 233 mTimePicker24HourView.getMinute(), is(11)); 234 235 mActivityTestRule.runOnUiThread(new Runnable() { 236 @Override 237 public void run() { 238 mTimePicker24HourView.setMinute(59); 239 } 240 }); 241 Thread.sleep(UPDATE_LENGTH); 242 assertThat("TimePicker in 24-hour mode returns a different hour in getHour()", 243 mTimePicker24HourView.getMinute(), is(59)); 244 } 245 246 @Test 247 public void testSetMinuteIn12hFormat() throws Throwable { 248 Intent intent = new Intent(); 249 intent.putExtra(DatePickerActivity.EXTRA_LAYOUT_RESOURCE_ID, 250 R.layout.timepicker_with_other_widgets); 251 initActivity(intent); 252 mActivityTestRule.runOnUiThread(new Runnable() { 253 @Override 254 public void run() { 255 mTimePicker12HourView.setMinute(0); 256 } 257 }); 258 Thread.sleep(UPDATE_LENGTH); 259 assertThat("TimePicker in 24-hour mode returns a different hour in getHour()", 260 mTimePicker12HourView.getMinute(), is(0)); 261 262 mActivityTestRule.runOnUiThread(new Runnable() { 263 @Override 264 public void run() { 265 mTimePicker12HourView.setMinute(11); 266 } 267 }); 268 Thread.sleep(UPDATE_LENGTH); 269 assertThat("TimePicker in 24-hour mode returns a different hour in getHour()", 270 mTimePicker12HourView.getMinute(), is(11)); 271 272 mActivityTestRule.runOnUiThread(new Runnable() { 273 @Override 274 public void run() { 275 mTimePicker12HourView.setMinute(59); 276 } 277 }); 278 Thread.sleep(UPDATE_LENGTH); 279 assertThat("TimePicker in 24-hour mode returns a different hour in getHour()", 280 mTimePicker12HourView.getMinute(), is(59)); 281 282 } 283 284 @Test 285 public void testAmToPmTransition() throws Throwable { 286 Intent intent = new Intent(); 287 intent.putExtra(DatePickerActivity.EXTRA_LAYOUT_RESOURCE_ID, 288 R.layout.timepicker_with_other_widgets); 289 initActivity(intent); 290 mActivityTestRule.runOnUiThread(new Runnable() { 291 @Override 292 public void run() { 293 mTimePicker12HourView.setHour(0); 294 mTimePicker12HourView.setMinute(47); 295 } 296 }); 297 Thread.sleep(UPDATE_LENGTH); 298 assertThat("TimePicker in 12-hour mode returns a different hour in getHour()", 299 mTimePicker12HourView.getHour(), is(0)); 300 assertThat("TimePicker in 12-hour mode returns a different hour in getMinute()", 301 mTimePicker12HourView.getMinute(), is(47)); 302 303 // traverse to the AM/PM column of 12 hour TimePicker widget 304 sendKeys(KeyEvent.KEYCODE_DPAD_DOWN); 305 Thread.sleep(TRANSITION_LENGTH); 306 // Click once to activate 307 sendKeys(KeyEvent.KEYCODE_DPAD_CENTER); 308 Thread.sleep(TRANSITION_LENGTH); 309 sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT); 310 Thread.sleep(TRANSITION_LENGTH); 311 sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT); 312 Thread.sleep(TRANSITION_LENGTH); 313 // scroll down to PM value 314 sendKeys(KeyEvent.KEYCODE_DPAD_DOWN); 315 Thread.sleep(TRANSITION_LENGTH); 316 // Click now to deactivate 317 sendKeys(KeyEvent.KEYCODE_DPAD_CENTER); 318 Thread.sleep(TRANSITION_LENGTH); 319 320 assertThat("TimePicker in 24-hour mode returns a different hour in getHour() returns", 321 mTimePicker12HourView.getHour(), is(12)); 322 assertThat("TimePicker in 24-hour mode returns a different hour in getHour() returns", 323 mTimePicker12HourView.getMinute(), is(47)); 324 } 325 326 @Test 327 public void testPmToAmTransition() throws Throwable { 328 Intent intent = new Intent(); 329 intent.putExtra(DatePickerActivity.EXTRA_LAYOUT_RESOURCE_ID, 330 R.layout.timepicker_with_other_widgets); 331 initActivity(intent); 332 mActivityTestRule.runOnUiThread(new Runnable() { 333 @Override 334 public void run() { 335 mTimePicker12HourView.setHour(12); 336 mTimePicker12HourView.setMinute(47); 337 } 338 }); 339 Thread.sleep(UPDATE_LENGTH); 340 assertThat("TimePicker in 12-hour mode returns a different hour in getHour()", 341 mTimePicker12HourView.getHour(), is(12)); 342 assertThat("TimePicker in 12-hour mode returns a different hour in getMinute()", 343 mTimePicker12HourView.getMinute(), is(47)); 344 345 // traverse to the AM/PM column of 12 hour TimePicker widget 346 sendKeys(KeyEvent.KEYCODE_DPAD_DOWN); 347 Thread.sleep(TRANSITION_LENGTH); 348 // Click once to activate 349 sendKeys(KeyEvent.KEYCODE_DPAD_CENTER); 350 Thread.sleep(TRANSITION_LENGTH); 351 sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT); 352 Thread.sleep(TRANSITION_LENGTH); 353 sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT); 354 Thread.sleep(TRANSITION_LENGTH); 355 // scroll down to PM value 356 sendKeys(KeyEvent.KEYCODE_DPAD_UP); 357 Thread.sleep(TRANSITION_LENGTH); 358 // Click now to deactivate 359 sendKeys(KeyEvent.KEYCODE_DPAD_CENTER); 360 Thread.sleep(TRANSITION_LENGTH); 361 362 assertThat("TimePicker in 24-hour mode returns a different hour in getHour() returns", 363 mTimePicker12HourView.getHour(), is(0)); 364 assertThat("TimePicker in 24-hour mode returns a different hour in getHour() returns", 365 mTimePicker12HourView.getMinute(), is(47)); 366 } 367 368 @Test 369 public void test12To24HourFormatTransition() throws Throwable { 370 Intent intent = new Intent(); 371 intent.putExtra(DatePickerActivity.EXTRA_LAYOUT_RESOURCE_ID, 372 R.layout.timepicker_with_other_widgets); 373 initActivity(intent); 374 mActivityTestRule.runOnUiThread(new Runnable() { 375 @Override 376 public void run() { 377 mTimePicker12HourView.setHour(14); 378 mTimePicker12HourView.setMinute(47); 379 } 380 }); 381 Thread.sleep(UPDATE_LENGTH); 382 assertThat("TimePicker should be in 12-hour format.", mTimePicker12HourView.is24Hour(), 383 is(false)); 384 mActivityTestRule.runOnUiThread(new Runnable() { 385 @Override 386 public void run() { 387 mTimePicker12HourView.setIs24Hour(true); 388 } 389 }); 390 Thread.sleep(UPDATE_LENGTH); 391 assertThat("TimePicker should now be in 24-hour format.", mTimePicker12HourView.is24Hour(), 392 is(true)); 393 // The hour and minute should not be changed. 394 assertThat("TimePicker in 24-hour mode returns a different hour in getHour() returns", 395 mTimePicker12HourView.getHour(), is(14)); 396 assertThat("TimePicker in 24-hour mode returns a different hour in getHour() returns", 397 mTimePicker12HourView.getMinute(), is(47)); 398 } 399 400 @Test 401 public void test24To12HourFormatTransition() throws Throwable { 402 Intent intent = new Intent(); 403 intent.putExtra(DatePickerActivity.EXTRA_LAYOUT_RESOURCE_ID, 404 R.layout.timepicker_with_other_widgets); 405 initActivity(intent); 406 mActivityTestRule.runOnUiThread(new Runnable() { 407 @Override 408 public void run() { 409 mTimePicker24HourView.setHour(14); 410 mTimePicker24HourView.setMinute(47); 411 } 412 }); 413 Thread.sleep(UPDATE_LENGTH); 414 assertThat("TimePicker should be in 12-hour format.", mTimePicker24HourView.is24Hour(), 415 is(true)); 416 mActivityTestRule.runOnUiThread(new Runnable() { 417 @Override 418 public void run() { 419 mTimePicker24HourView.setIs24Hour(false); 420 } 421 }); 422 Thread.sleep(UPDATE_LENGTH); 423 assertThat("TimePicker should now be in 24-hour format.", mTimePicker24HourView.is24Hour(), 424 is(false)); 425 // The hour and minute should not be changed. 426 assertThat("TimePicker in 24-hour mode returns a different hour in getHour() returns", 427 mTimePicker24HourView.getHour(), is(14)); 428 assertThat("TimePicker in 24-hour mode returns a different hour in getHour() returns", 429 mTimePicker24HourView.getMinute(), is(47)); 430 } 431 432 @Test 433 public void testInitiallyActiveTimePicker() 434 throws Throwable { 435 Intent intent = new Intent(); 436 intent.putExtra(DatePickerActivity.EXTRA_LAYOUT_RESOURCE_ID, 437 R.layout.timepicker_alone); 438 initActivity(intent); 439 440 mActivityTestRule.runOnUiThread(new Runnable() { 441 @Override 442 public void run() { 443 mTimePicker12HourView.setHour(14); 444 mTimePicker12HourView.setMinute(47); 445 } 446 }); 447 Thread.sleep(UPDATE_LENGTH); 448 449 ViewGroup mTimePickerInnerView = (ViewGroup) mTimePicker12HourView.findViewById( 450 R.id.picker); 451 452 assertThat("The first column of TimePicker should initially hold focus", 453 mTimePickerInnerView.getChildAt(0).hasFocus(), is(true)); 454 455 // focus on first column 456 sendKeys(KeyEvent.KEYCODE_DPAD_DOWN); 457 Thread.sleep(TRANSITION_LENGTH); 458 assertThat("The first column of TimePicker should still hold focus after scrolling down", 459 mTimePickerInnerView.getChildAt(0).hasFocus(), is(true)); 460 461 // focus on second column 462 sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT); 463 Thread.sleep(TRANSITION_LENGTH); 464 assertThat("The second column of TimePicker should hold focus after scrolling right", 465 mTimePickerInnerView.getChildAt(2).hasFocus(), is(true)); 466 467 sendKeys(KeyEvent.KEYCODE_DPAD_DOWN); 468 Thread.sleep(TRANSITION_LENGTH); 469 assertThat("The second column of TimePicker should still hold focus after scrolling down", 470 mTimePickerInnerView.getChildAt(2).hasFocus(), is(true)); 471 472 // focus on third column 473 sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT); 474 Thread.sleep(TRANSITION_LENGTH); 475 assertThat("The third column of TimePicker should hold focus after scrolling right", 476 mTimePickerInnerView.getChildAt(4).hasFocus(), is(true)); 477 478 sendKeys(KeyEvent.KEYCODE_DPAD_UP); 479 Thread.sleep(TRANSITION_LENGTH); 480 assertThat("The third column of TimePicker should still hold focus after scrolling down", 481 mTimePickerInnerView.getChildAt(4).hasFocus(), is(true)); 482 } 483 484 private void sendKeys(int ...keys) { 485 for (int i = 0; i < keys.length; i++) { 486 InstrumentationRegistry.getInstrumentation().sendKeyDownUpSync(keys[i]); 487 } 488 } 489} 490