1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package android.preference2.cts; 18 19 import static android.preference.PreferenceActivity.EXTRA_NO_HEADERS; 20 import static android.preference.PreferenceActivity.EXTRA_SHOW_FRAGMENT; 21 import static android.preference.PreferenceActivity.EXTRA_SHOW_FRAGMENT_TITLE; 22 23 import static org.junit.Assert.assertEquals; 24 import static org.junit.Assert.assertFalse; 25 import static org.junit.Assert.assertTrue; 26 27 import android.content.Intent; 28 import android.graphics.Bitmap; 29 import android.os.SystemClock; 30 import android.preference2.cts.R; 31 import android.util.Log; 32 33 import com.android.compatibility.common.util.BitmapUtils; 34 35 /** 36 * This test suite covers {@link android.preference.PreferenceActivity} to ensure its correct 37 * behavior in orientation and multi-window changes together with navigation between different 38 * screens and going back in the history. It should also cover any possible transition between 39 * single and multi pane modes. Some tests are designed to run only on large or small screen devices 40 * and some can run both. These tests are run from {@link PreferenceActivityFlowLandscapeTest} and 41 * {@link PreferenceActivityFlowPortraitTest} to ensure that both display configurations are 42 * checked. 43 */ 44 public abstract class PreferenceActivityFlowTest { 45 46 private static final String TAG = "PreferenceFlowTest"; 47 48 // Helper strings to ensure that some parts of preferences are visible or not. 49 private static final String PREFS1_HEADER_TITLE = "Prefs 1"; 50 private static final String PREFS2_HEADER_TITLE = "Prefs 2"; 51 private static final String PREFS1_PANEL_TITLE = "Preferences panel 1"; 52 private static final String PREFS2_PANEL_TITLE = "Preferences panel 2"; 53 private static final String INNER_FRAGMENT_PREF_BUTTON = "Fragment preference"; 54 private static final String INNER_FRAGMENT_PREF_TITLE = "Inner fragment"; 55 private static final String LIST_PREF_TITLE = "List preference"; 56 private static final String LIST_PREF_OPTION = "alpha"; 57 58 private static final int INITIAL_TITLE_RES_ID = R.string.test_title; 59 private static final int EXPECTED_HEADERS_COUNT = 3; 60 61 TestUtils mTestUtils; 62 protected PreferenceWithHeaders mActivity; 63 private boolean mIsMultiPane; 64 65 void switchHeadersInner() { 66 launchActivity(); 67 if (shouldRunLargeDeviceTest()) { 68 largeScreenSwitchHeadersInner(); 69 } else { 70 smallScreenSwitchHeadersInner(); 71 } 72 } 73 74 /** 75 * For: Large screen (multi-pane). 76 * Scenario: Tests that tapping on header changes to its proper preference panel and that the 77 * headers are still visible. 78 */ 79 private void largeScreenSwitchHeadersInner() { 80 assertTrue(shouldRunLargeDeviceTest()); 81 assertInitialState(); 82 83 tapOnPrefs2Header(); 84 85 // Headers and panel Prefs2 must be shown. 86 assertHeadersShown(); 87 assertPanelPrefs1Hidden(); 88 assertPanelPrefs2Shown(); 89 90 tapOnPrefs1Header(); 91 92 // Headers and panel Prefs1 must be shown. 93 assertHeadersShown(); 94 assertPanelPrefs1Shown(); 95 assertPanelPrefs2Hidden(); 96 } 97 98 /** 99 * For: Small screen (single-pane). 100 * Scenario: Tests that tapping on header changes to its proper preference panel and that the 101 * headers are hidden and pressing back button after that shows them again. 102 */ 103 private void smallScreenSwitchHeadersInner() { 104 assertTrue(shouldRunSmallDeviceTest()); 105 assertInitialState(); 106 107 tapOnPrefs2Header(); 108 109 // Only Prefs2 must be shown. 110 assertHeadersHidden(); 111 assertPanelPrefs1Hidden(); 112 assertPanelPrefs2Shown(); 113 114 pressBack(); 115 116 tapOnPrefs1Header(); 117 118 // Only Prefs1 must be shown. 119 assertHeadersHidden(); 120 assertPanelPrefs1Shown(); 121 assertPanelPrefs2Hidden(); 122 } 123 124 /** 125 * For: Small screen (single-pane). 126 * Scenario: Tests that after navigating back to the headers list there will be no header 127 * highlighted and that the title was properly restored.. 128 */ 129 void smallScreenNoHighlightInHeadersListInner() { 130 launchActivity(); 131 if (!shouldRunSmallDeviceTest()) { 132 return; 133 } 134 135 assertInitialState(); 136 137 CharSequence title = mActivity.getTitle(); 138 139 tapOnPrefs2Header(); 140 assertHeadersHidden(); 141 142 pressBack(); 143 assertHeadersShown(); 144 145 // Verify that no headers are focused. 146 assertHeadersNotFocused(); 147 148 // Verify that the title was properly restored. 149 assertEquals(title, mActivity.getTitle()); 150 151 // Verify that everthing restores back to initial state again. 152 assertInitialState(); 153 } 154 155 void backPressToExitInner() { 156 launchActivity(); 157 if (shouldRunLargeDeviceTest()) { 158 largeScreenBackPressToExitInner(); 159 } else { 160 smallScreenBackPressToExitInner(); 161 } 162 } 163 164 /** 165 * For: Small screen (single-pane). 166 * Scenario: Tests that pressing back button twice after having preference panel opened will 167 * exit the app when running single-pane. 168 */ 169 private void smallScreenBackPressToExitInner() { 170 assertTrue(shouldRunSmallDeviceTest()); 171 assertInitialState(); 172 173 tapOnPrefs2Header(); 174 175 // Only Prefs2 must be shown - covered by smallScreenSwitchHeadersTest 176 177 pressBack(); 178 pressBack(); 179 180 // Now we should be out of the activity 181 assertHeadersHidden(); 182 assertPanelPrefs1Hidden(); 183 assertPanelPrefs2Hidden(); 184 } 185 186 /** 187 * For: Large screen (multi-pane). 188 * Scenario: Selects a header and then leaves the activity by pressing back button. Tests that 189 * we don't transition to the previous header or list of header like in single-pane. 190 */ 191 private void largeScreenBackPressToExitInner() { 192 assertTrue(shouldRunLargeDeviceTest()); 193 assertInitialState(); 194 195 tapOnPrefs2Header(); 196 197 // Headers and panel Prefs2 must be shown - covered by largeScreenSwitchHeadersInner. 198 199 pressBack(); 200 201 assertHeadersHidden(); 202 } 203 204 void goToFragmentInner() { 205 launchActivity(); 206 if (shouldRunLargeDeviceTest()) { 207 largeScreenGoToFragmentInner(); 208 } else { 209 smallScreenGoToFragmentInner(); 210 } 211 } 212 213 /** 214 * For: Large screen (multi-pane). 215 * Scenario: Navigates to inner fragment. Test that the fragment was opened correctly and 216 * headers are still visible. Also tests that back press doesn't close the app but navigates 217 * back from the fragment. 218 */ 219 private void largeScreenGoToFragmentInner() { 220 assertTrue(shouldRunLargeDeviceTest()); 221 assertInitialState(); 222 223 tapOnPrefs1Header(); 224 225 // Go to preferences inner fragment. 226 mTestUtils.tapOnViewWithText(INNER_FRAGMENT_PREF_BUTTON); 227 228 // Headers and inner fragment must be shown. 229 assertHeadersShown(); 230 assertPanelPrefs1Hidden(); 231 assertInnerFragmentShown(); 232 233 pressBack(); 234 235 // Headers and panel Prefs1 must be shown. 236 assertHeadersShown(); 237 assertPanelPrefs1Shown(); 238 assertPanelPrefs2Hidden(); 239 assertInnerFragmentHidden(); 240 } 241 242 /** 243 * For: Small screen (single-pane). 244 * Scenario: Navigates to inner fragment. Tests that the fragment was opened correctly and 245 * headers are hidden. Also tests that back press doesn't close the app but navigates back from 246 * the fragment. 247 */ 248 private void smallScreenGoToFragmentInner() { 249 assertTrue(shouldRunSmallDeviceTest()); 250 assertInitialState(); 251 252 tapOnPrefs1Header(); 253 254 // Go to preferences inner fragment. 255 mTestUtils.tapOnViewWithText(INNER_FRAGMENT_PREF_BUTTON); 256 257 // Only inner fragment must be shown. 258 assertHeadersHidden(); 259 assertPanelPrefs1Hidden(); 260 assertInnerFragmentShown(); 261 262 pressBack(); 263 264 // Prefs1 must be shown. 265 assertHeadersHidden(); 266 assertPanelPrefs1Shown(); 267 assertPanelPrefs2Hidden(); 268 assertInnerFragmentHidden(); 269 } 270 271 /** 272 * For: Any screen (single or multi-pane). 273 * Scenario: Tests that opening specific preference fragment directly via intent works properly. 274 */ 275 void startWithFragmentInner() { 276 launchActivityWithExtras(PreferenceWithHeaders.PrefsTwoFragment.class, 277 false /* noHeaders */, -1 /* initialTitle */); 278 279 assertInitialStateForFragment(); 280 } 281 282 /** 283 * For: Any screen (single or multi-pane). 284 * Scenario: Tests that preference fragment opened directly survives recreation (via screenshot 285 * tests). 286 */ 287 void startWithFragmentAndRecreateInner() { 288 launchActivityWithExtras(PreferenceWithHeaders.PrefsTwoFragment.class, 289 false /* noHeaders */, -1 /* initialTitle */); 290 291 assertInitialStateForFragment(); 292 293 // Take screenshot 294 Bitmap before = mTestUtils.takeScreenshot(); 295 296 // Force recreate 297 recreate(); 298 299 assertInitialStateForFragment(); 300 301 // Compare screenshots 302 Bitmap after = mTestUtils.takeScreenshot(); 303 assertScreenshotsAreEqual(before, after); 304 } 305 306 /** 307 * For: Any screen (single or multi-pane). 308 * Scenario: Starts preference fragment directly with the given initial title and tests that 309 * multi-pane does not show it and single-pane does. 310 */ 311 void startWithFragmentAndInitTitleInner() { 312 launchActivityWithExtras(PreferenceWithHeaders.PrefsTwoFragment.class, 313 false /* noHeaders */, INITIAL_TITLE_RES_ID); 314 315 assertInitialStateForFragment(); 316 317 if (mIsMultiPane) { 318 String testTitle = mActivity.getResources().getString(INITIAL_TITLE_RES_ID); 319 // Title should not be shown. 320 assertTextHidden(testTitle); 321 } else { 322 // Title should be shown. 323 assertTitleShown(); 324 } 325 } 326 327 /** 328 * For: Large screen (multi-pane). 329 * Scenario: Tests that initial title is displayed or hidden properly when transitioning in and 330 * out of the multi-window mode. 331 */ 332 void startWithFragmentAndInitTitleMultiWindowInner() { 333 launchActivityWithExtras(PreferenceWithHeaders.PrefsTwoFragment.class, 334 false /* noHeaders */, INITIAL_TITLE_RES_ID); 335 if (!shouldRunLargeDeviceTest()) { 336 return; 337 } 338 339 assertInitialStateForFragment(); 340 String testTitle = mActivity.getResources().getString(INITIAL_TITLE_RES_ID); 341 342 // Title should not be shown (we are in multi-pane). 343 assertFalse(mTestUtils.isTextShown(testTitle)); 344 345 mTestUtils.enterMultiWindow(mActivity); 346 mTestUtils.getMultiWindowFocus(mActivity); 347 348 // Title should be shown (we are in single-pane). 349 assertTextShown(testTitle); 350 351 mTestUtils.leaveMultiWindow(mActivity); 352 353 // Title should not be shown (we are back in multi-pane). 354 assertTextHidden(testTitle); 355 } 356 357 /** 358 * For: Any screen (single or multi-pane). 359 * Scenario: Tests that EXTRA_NO_HEADERS intent arg that prevents showing headers in multi-pane 360 * is applied correctly. 361 */ 362 void startWithFragmentNoHeadersInner() { 363 launchActivityWithExtras(PreferenceWithHeaders.PrefsTwoFragment.class, 364 true /* noHeaders */, -1 /* initialTitle */); 365 366 assertInitialStateForFragment(); 367 // Only Prefs2 should be shown. 368 assertHeadersHidden(); 369 assertPanelPrefs1Hidden(); 370 assertPanelPrefs2Shown(); 371 } 372 373 /** 374 * For: Any screen (single or multi-pane). 375 * Scenario: Tests that EXTRA_NO_HEADERS intent arg that prevents showing headers in multi-pane 376 * is applied correctly plus initial title is displayed. 377 */ 378 void startWithFragmentNoHeadersButInitTitleInner() { 379 launchActivityWithExtras(PreferenceWithHeaders.PrefsTwoFragment.class, 380 true /* noHeaders */, INITIAL_TITLE_RES_ID); 381 382 assertInitialStateForFragment(); 383 // Only Prefs2 should be shown. 384 assertHeadersHidden(); 385 assertPanelPrefs1Hidden(); 386 assertPanelPrefs2Shown(); 387 388 assertTitleShown(); 389 } 390 391 /** 392 * For: Any screen (single or multi-pane). 393 * Scenario: Tests that EXTRA_NO_HEADERS intent arg that prevents showing headers survives 394 * correctly multi-window changes. Tested via screenshots. 395 */ 396 void startWithFragmentNoHeadersMultiWindowTest() { 397 launchActivityWithExtras(PreferenceWithHeaders.PrefsTwoFragment.class, 398 true /* noHeaders */, -1 /* initialTitle */); 399 400 assertInitialStateForFragment(); 401 402 // Workaround for some focus bug in the framework 403 mTestUtils.tapOnViewWithText(PREFS2_PANEL_TITLE); 404 405 // Take screenshot 406 Bitmap before = mTestUtils.takeScreenshot(); 407 408 // Enter and leave multi-window. 409 mTestUtils.enterMultiWindow(mActivity); 410 mTestUtils.leaveMultiWindow(mActivity); 411 412 assertInitialStateForFragment(); 413 414 // Compare screenshots 415 Bitmap after = mTestUtils.takeScreenshot(); 416 assertScreenshotsAreEqual(before, after); 417 } 418 419 /** 420 * For: Any screen (single or multi-pane). 421 * Scenario: Tests that list preference opens correctly and that back press correctly closes it. 422 */ 423 void listDialogTest() { 424 launchActivity(); 425 426 assertInitialState(); 427 if (!mIsMultiPane) { 428 tapOnPrefs1Header(); 429 } 430 431 mTestUtils.tapOnViewWithText(LIST_PREF_TITLE); 432 433 mTestUtils.isTextShown(LIST_PREF_OPTION); 434 435 pressBack(); 436 437 if (mIsMultiPane) { 438 // Headers and Prefs1 should be shown. 439 assertHeadersShown(); 440 assertPanelPrefs1Shown(); 441 } else { 442 // Only Prefs1 should be shown. 443 assertHeadersHidden(); 444 assertPanelPrefs1Shown(); 445 } 446 } 447 448 /** 449 * For: Any screen (single or multi-pane). 450 * Scenario: Tests that the PreferenceActivity properly restores its state after recreation. 451 * Test done via screenshots. 452 */ 453 void recreateTest() { 454 launchActivity(); 455 456 assertInitialState(); 457 tapOnPrefs2Header(); 458 459 assertPanelPrefs2Shown(); 460 461 // Take screenshot 462 Bitmap before = mTestUtils.takeScreenshot(); 463 464 recreate(); 465 466 assertPanelPrefs2Shown(); 467 468 // Compare screenshots 469 Bitmap after = mTestUtils.takeScreenshot(); 470 assertScreenshotsAreEqual(before, after); 471 } 472 473 /** 474 * For: Any screen (single or multi-pane). 475 * Scenario: Tests that the PreferenceActivity properly restores its state after recreation 476 * while an inner fragment is shown. Test done via screenshots. 477 */ 478 void recreateInnerFragmentTest() { 479 launchActivity(); 480 481 assertInitialState(); 482 483 if (!mIsMultiPane) { 484 tapOnPrefs1Header(); 485 } 486 487 // Go to preferences inner fragment. 488 mTestUtils.tapOnViewWithText(INNER_FRAGMENT_PREF_BUTTON); 489 490 // Only inner fragment must be shown. 491 if (shouldRunLargeDeviceTest()) { 492 assertHeadersShown(); 493 } else { 494 assertHeadersHidden(); 495 } 496 assertPanelPrefs1Hidden(); 497 assertInnerFragmentShown(); 498 499 // Take screenshot 500 Bitmap before = mTestUtils.takeScreenshot(); 501 502 recreate(); 503 504 // Only inner fragment must be shown. 505 if (shouldRunLargeDeviceTest()) { 506 assertHeadersShown(); 507 } else { 508 assertHeadersHidden(); 509 } 510 assertPanelPrefs1Hidden(); 511 assertInnerFragmentShown(); 512 513 // Compare screenshots 514 Bitmap after = mTestUtils.takeScreenshot(); 515 assertScreenshotsAreEqual(before, after); 516 } 517 518 /** 519 * For: Any screen (single or multi-pane). 520 * Scenario: Tests that the PreferenceActivity properly restores its state after going to 521 * multi-window and back. Test done via screenshots. 522 */ 523 void multiWindowInOutTest() { 524 launchActivity(); 525 526 assertInitialState(); 527 // Tap on Prefs2 header. 528 tapOnPrefs2Header(); 529 530 assertPanelPrefs2Shown(); 531 532 // Take screenshot 533 Bitmap before = mTestUtils.takeScreenshot(); 534 535 // Enter and leave multi-window. 536 mTestUtils.enterMultiWindow(mActivity); 537 mTestUtils.leaveMultiWindow(mActivity); 538 539 assertPanelPrefs2Shown(); 540 541 // Compare screenshots 542 Bitmap after = mTestUtils.takeScreenshot(); 543 assertScreenshotsAreEqual(before, after); 544 } 545 546 /** 547 * For: Any screen (single or multi-pane). 548 * Scenario: Tests that the PreferenceActivity properly restores its state after going to 549 * multi-window and back while an inner fragment is shown. Test done via screenshots. 550 */ 551 void multiWindowInnerFragmentInOutTest() { 552 launchActivity(); 553 554 assertInitialState(); 555 if (!mIsMultiPane) { 556 tapOnPrefs1Header(); 557 } 558 559 // Go to preferences inner fragment. 560 mTestUtils.tapOnViewWithText(INNER_FRAGMENT_PREF_BUTTON); 561 562 // We don't need to check that correct panel is displayed that is already covered by 563 // smallScreenGoToFragmentInner and largeScreenGoToFragmentInner 564 565 // Take screenshot 566 Bitmap before = mTestUtils.takeScreenshot(); 567 568 // Enter and leave multi-window. 569 mTestUtils.enterMultiWindow(mActivity); 570 mTestUtils.leaveMultiWindow(mActivity); 571 572 // Compare screenshots 573 Bitmap after = mTestUtils.takeScreenshot(); 574 assertScreenshotsAreEqual(before, after); 575 } 576 577 /** 578 * For: Large screen (single or multi-pane). 579 * Scenario: Goes to single-pane by entering multi-window and tests that back press ends up with 580 * a list of headers and nothing else. Then leaves multi-window back to single-pane and tests if 581 * the proper default header was opened (screenshot test). 582 */ 583 void multiWindowInitialHeaderOnBackTest() { 584 launchActivity(); 585 if (!shouldRunLargeDeviceTest()) { 586 return; 587 } 588 589 assertInitialState(); 590 591 Bitmap before = mTestUtils.takeScreenshot(); 592 593 // Enter multi-window. 594 mTestUtils.enterMultiWindow(mActivity); 595 596 // Get window focus (otherwise back press would close multi-window instead of firing to the 597 // Activity. 598 mTestUtils.getMultiWindowFocus(mActivity); 599 600 pressBack(); 601 602 // Only headers should be shown (also checks that we have correct focus). 603 assertHeadersShown(); 604 assertPanelPrefs1Hidden(); 605 assertPanelPrefs2Hidden(); 606 607 // Leave multi-window 608 mTestUtils.leaveMultiWindow(mActivity); 609 610 // Headers and Prefs1 should be shown. 611 assertHeadersShown(); 612 assertPanelPrefs1Shown(); 613 assertPanelPrefs2Hidden(); 614 615 // Compare screenshots 616 Bitmap after = mTestUtils.takeScreenshot(); 617 assertScreenshotsAreEqual(before, after); 618 } 619 620 /** 621 * For: Large screen (multi-pane). 622 * Scenario: Tests that history is preserved correctly while transitioning to multi-window. 623 * Navigates to Prefs2 pane and then goes to single-pane mode via multi-window. Test that back 624 * press navigates to the headers list. Then tests that restoring multi-pane by leaving 625 * multi-window opens the same screen with which was the activity started before (screenshot 626 * test). 627 */ 628 void multiWindowHistoryPreserveTest() { 629 launchActivity(); 630 if (!shouldRunLargeDeviceTest()) { 631 return; 632 } 633 634 assertInitialState(); 635 Bitmap before = mTestUtils.takeScreenshot(); 636 637 tapOnPrefs2Header(); 638 639 // Enter multi-window. 640 mTestUtils.enterMultiWindow(mActivity); 641 mTestUtils.getMultiWindowFocus(mActivity); 642 643 // Only Prefs2 should be shown (also checks that we have correct focus). 644 assertHeadersHidden(); 645 assertPanelPrefs1Hidden(); 646 assertPanelPrefs2Shown(); 647 648 pressBack(); 649 650 // Only headers should be shown. 651 assertHeadersShown(); 652 assertPanelPrefs1Hidden(); 653 assertPanelPrefs2Hidden(); 654 655 tapOnPrefs1Header(); 656 657 // Only Prefs1 should be shown. 658 assertHeadersHidden(); 659 assertPanelPrefs1Shown(); 660 assertPanelPrefs2Hidden(); 661 662 // Leave multi-window 663 mTestUtils.leaveMultiWindow(mActivity); 664 665 // Headers and Prefs1 should be shown. 666 assertHeadersShown(); 667 assertPanelPrefs1Shown(); 668 assertPanelPrefs2Hidden(); 669 670 // Compare screenshots 671 Bitmap after = mTestUtils.takeScreenshot(); 672 assertScreenshotsAreEqual(before, after); 673 } 674 675 private void assertScreenshotsAreEqual(Bitmap before, Bitmap after) { 676 assertTrue("Screenshots do not match!", BitmapUtils.compareBitmaps(before, after)); 677 } 678 679 private void assertInitialState() { 680 if (mIsMultiPane) { 681 // Headers and panel Prefs1 must be shown. 682 assertHeadersShown(); 683 runOnUiThread(() -> assertTrue(mActivity.hasHeaders())); 684 assertPanelPrefs1Shown(); 685 assertPanelPrefs2Hidden(); 686 } else { 687 // Headers must be shown and nothing else. 688 assertHeadersShown(); 689 runOnUiThread(() -> assertTrue(mActivity.hasHeaders())); 690 assertPanelPrefs1Hidden(); 691 assertPanelPrefs2Hidden(); 692 } 693 694 assertHeadersAreLoaded(); 695 } 696 697 private void assertInitialStateForFragment() { 698 if (mIsMultiPane) { 699 // Headers and Prefs2 should be shown. 700 assertHeadersShown(); 701 runOnUiThread(() -> assertTrue(mActivity.hasHeaders())); 702 assertPanelPrefs1Hidden(); 703 assertPanelPrefs2Shown(); 704 } else { 705 // Only Prefs2 should be shown. 706 assertHeadersHidden(); 707 runOnUiThread(() -> assertFalse(mActivity.hasHeaders())); 708 assertPanelPrefs1Hidden(); 709 assertPanelPrefs2Shown(); 710 } 711 712 713 } 714 715 public boolean shouldRunLargeDeviceTest() { 716 if (mActivity.onIsMultiPane()) { 717 return true; 718 } 719 720 Log.d(TAG, "Skipping a large device test."); 721 return false; 722 } 723 724 public boolean shouldRunSmallDeviceTest() { 725 if (!mActivity.onIsMultiPane()) { 726 return true; 727 } 728 729 Log.d(TAG, "Skipping a small device test."); 730 return false; 731 } 732 733 private void tapOnPrefs1Header() { 734 mTestUtils.tapOnViewWithText(PREFS1_HEADER_TITLE); 735 } 736 737 private void tapOnPrefs2Header() { 738 mTestUtils.tapOnViewWithText(PREFS2_HEADER_TITLE); 739 } 740 741 private void assertHeadersAreLoaded() { 742 runOnUiThread(() -> { 743 assertEquals(EXPECTED_HEADERS_COUNT, 744 mActivity.loadedHeaders == null 745 ? 0 746 : mActivity.loadedHeaders.size()); 747 }); 748 } 749 750 private void assertHeadersShown() { 751 assertTextShown(PREFS1_HEADER_TITLE); 752 assertTextShown(PREFS2_HEADER_TITLE); 753 } 754 755 private void assertHeadersNotFocused() { 756 assertFalse(mTestUtils.isTextFocused(PREFS1_HEADER_TITLE)); 757 assertFalse(mTestUtils.isTextFocused(PREFS2_HEADER_TITLE)); 758 } 759 760 private void assertHeadersHidden() { 761 // We check '&' instead of each individual separately because these headers are also part 762 // of individual preference panels breadcrumbs so it would fail for one. 763 assertFalse(mTestUtils.isTextShown(PREFS1_HEADER_TITLE) 764 && mTestUtils.isTextShown(PREFS2_HEADER_TITLE)); 765 } 766 767 private void assertPanelPrefs1Shown() { 768 assertTextShown(PREFS1_PANEL_TITLE); 769 } 770 771 private void assertPanelPrefs1Hidden() { 772 assertTextHidden(PREFS1_PANEL_TITLE); 773 } 774 775 private void assertPanelPrefs2Shown() { 776 assertTextShown(PREFS2_PANEL_TITLE); 777 } 778 779 private void assertPanelPrefs2Hidden() { 780 assertTextHidden(PREFS2_PANEL_TITLE); 781 } 782 783 private void assertInnerFragmentShown() { 784 assertTextShown(INNER_FRAGMENT_PREF_TITLE); 785 } 786 787 private void assertInnerFragmentHidden() { 788 assertTextHidden(INNER_FRAGMENT_PREF_TITLE); 789 } 790 791 private void assertTextShown(String text) { 792 assertTrue(mTestUtils.isTextShown(text)); 793 } 794 795 private void assertTextHidden(String text) { 796 assertTrue(mTestUtils.isTextHidden(text)); 797 } 798 799 private void assertTitleShown() { 800 if (!mTestUtils.isOnWatchUiMode()) { 801 // On watch, activity title is not shown by default. 802 String testTitle = mActivity.getResources().getString(INITIAL_TITLE_RES_ID); 803 assertTextShown(testTitle); 804 } 805 } 806 807 private void recreate() { 808 runOnUiThread(() -> mActivity.recreate()); 809 SystemClock.sleep(1000); 810 waitForIdle(); 811 } 812 813 private void waitForIdle() { 814 mTestUtils.device.waitForIdle(); 815 } 816 817 private void pressBack() { 818 mTestUtils.device.pressBack(); 819 waitForIdle(); 820 } 821 822 private void launchActivity() { 823 mActivity = launchActivity(null); 824 mTestUtils.device.waitForIdle(); 825 runOnUiThread(() -> { 826 mIsMultiPane = mActivity.isMultiPane(); 827 }); 828 } 829 830 private void launchActivityWithExtras(Class extraFragment, boolean noHeaders, 831 int initialTitle) { 832 Intent intent = new Intent(Intent.ACTION_MAIN); 833 834 if (extraFragment != null) { 835 intent.putExtra(EXTRA_SHOW_FRAGMENT, extraFragment.getName()); 836 } 837 if (noHeaders) { 838 intent.putExtra(EXTRA_NO_HEADERS, true); 839 } 840 if (initialTitle != -1) { 841 intent.putExtra(EXTRA_SHOW_FRAGMENT_TITLE, initialTitle); 842 } 843 844 mActivity = launchActivity(intent); 845 mTestUtils.device.waitForIdle(); 846 runOnUiThread(() -> { 847 mIsMultiPane = mActivity.isMultiPane(); 848 }); 849 } 850 851 protected abstract PreferenceWithHeaders launchActivity(Intent intent); 852 853 protected abstract void runOnUiThread(final Runnable runnable); 854 } 855