TextListItemTest.java revision 5dd6cdb91b24bb42fce840b3398b13f416a8c9d0
1/* 2 * Copyright 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 androidx.car.widget; 18 19import static android.support.test.espresso.Espresso.onView; 20import static android.support.test.espresso.action.ViewActions.click; 21import static android.support.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition; 22import static android.support.test.espresso.contrib.RecyclerViewActions.scrollToPosition; 23import static android.support.test.espresso.matcher.ViewMatchers.withId; 24 25import static org.hamcrest.Matchers.greaterThanOrEqualTo; 26import static org.hamcrest.core.Is.is; 27import static org.hamcrest.core.IsEqual.equalTo; 28import static org.hamcrest.number.IsCloseTo.closeTo; 29import static org.junit.Assert.assertFalse; 30import static org.junit.Assert.assertThat; 31import static org.junit.Assert.assertTrue; 32 33import android.graphics.drawable.Drawable; 34import android.support.test.InstrumentationRegistry; 35import android.support.test.espresso.UiController; 36import android.support.test.espresso.ViewAction; 37import android.support.test.filters.SmallTest; 38import android.support.test.rule.ActivityTestRule; 39import android.support.test.runner.AndroidJUnit4; 40import android.support.v7.widget.LinearLayoutManager; 41import android.view.View; 42import android.view.ViewGroup; 43import android.widget.RelativeLayout; 44 45import org.hamcrest.Matcher; 46import org.junit.Before; 47import org.junit.Rule; 48import org.junit.Test; 49import org.junit.runner.RunWith; 50 51import java.util.ArrayList; 52import java.util.Arrays; 53import java.util.List; 54 55import androidx.car.test.R; 56 57/** 58* Tests the layout configuration in {@link TextListItem}. 59 */ 60@RunWith(AndroidJUnit4.class) 61@SmallTest 62public class TextListItemTest { 63 64 @Rule 65 public ActivityTestRule<PagedListViewTestActivity> mActivityRule = 66 new ActivityTestRule<>(PagedListViewTestActivity.class); 67 68 private PagedListViewTestActivity mActivity; 69 private PagedListView mPagedListView; 70 71 @Before 72 public void setUp() { 73 mActivity = mActivityRule.getActivity(); 74 mPagedListView = mActivity.findViewById(R.id.paged_list_view); 75 } 76 77 private void setupPagedListView(List<TextListItem> items) { 78 ListItemProvider provider = new ListItemProvider.ListProvider( 79 new ArrayList<>(items)); 80 try { 81 mActivityRule.runOnUiThread(() -> { 82 mPagedListView.setAdapter(new ListItemAdapter(mActivity, provider)); 83 }); 84 } catch (Throwable throwable) { 85 throwable.printStackTrace(); 86 throw new RuntimeException(throwable); 87 } 88 // Wait for paged list view to layout by using espresso to scroll to a position. 89 onView(withId(R.id.recycler_view)).perform(scrollToPosition(0)); 90 } 91 92 private static void verifyViewIsHidden(View view) { 93 if (view instanceof ViewGroup) { 94 ViewGroup viewGroup = (ViewGroup) view; 95 final int childCount = viewGroup.getChildCount(); 96 for (int i = 0; i < childCount; i++) { 97 verifyViewIsHidden(viewGroup.getChildAt(i)); 98 } 99 } else { 100 assertThat(view.getVisibility(), is(equalTo(View.GONE))); 101 } 102 } 103 104 private TextListItem.ViewHolder getViewHolderAtPosition(int position) { 105 return (TextListItem.ViewHolder) mPagedListView.getRecyclerView() 106 .findViewHolderForAdapterPosition( 107 position); 108 } 109 110 @Test 111 public void testEmptyItemHidesAllViews() { 112 TextListItem item = new TextListItem(mActivity); 113 setupPagedListView(Arrays.asList(item)); 114 verifyViewIsHidden(mPagedListView.getRecyclerView().getLayoutManager().getChildAt(0)); 115 } 116 117 @Test 118 public void testPrimaryActionVisible() { 119 TextListItem item0 = new TextListItem(mActivity); 120 item0.setPrimaryActionIcon(android.R.drawable.sym_def_app_icon, true); 121 122 TextListItem item1 = new TextListItem(mActivity); 123 item1.setPrimaryActionIcon(android.R.drawable.sym_def_app_icon, false); 124 125 List<TextListItem> items = Arrays.asList(item0, item1); 126 setupPagedListView(items); 127 128 assertThat(getViewHolderAtPosition(0).getPrimaryIcon().getVisibility(), 129 is(equalTo(View.VISIBLE))); 130 assertThat(getViewHolderAtPosition(1).getPrimaryIcon().getVisibility(), 131 is(equalTo(View.VISIBLE))); 132 } 133 134 @Test 135 public void testTextVisible() { 136 TextListItem item0 = new TextListItem(mActivity); 137 item0.setTitle("title"); 138 139 TextListItem item1 = new TextListItem(mActivity); 140 item1.setBody("body"); 141 142 List<TextListItem> items = Arrays.asList(item0, item1); 143 setupPagedListView(items); 144 145 assertThat(getViewHolderAtPosition(0).getTitle().getVisibility(), 146 is(equalTo(View.VISIBLE))); 147 assertThat(getViewHolderAtPosition(1).getBody().getVisibility(), 148 is(equalTo(View.VISIBLE))); 149 } 150 151 @Test 152 public void testSupplementalActionVisible() { 153 TextListItem item0 = new TextListItem(mActivity); 154 item0.setSupplementalIcon(android.R.drawable.sym_def_app_icon, true); 155 156 TextListItem item1 = new TextListItem(mActivity); 157 item1.setAction("text", true, v -> { /* Do nothing. */ }); 158 159 160 TextListItem item2 = new TextListItem(mActivity); 161 item2.setActions("text", true, v -> { /* Do nothing. */ }, 162 "text", true, v -> { /* Do nothing. */ }); 163 164 List<TextListItem> items = Arrays.asList(item0, item1, item2); 165 setupPagedListView(items); 166 167 TextListItem.ViewHolder viewHolder = getViewHolderAtPosition(0); 168 assertThat(viewHolder.getSupplementalIcon().getVisibility(), is(equalTo(View.VISIBLE))); 169 assertThat(viewHolder.getSupplementalIconDivider().getVisibility(), 170 is(equalTo(View.VISIBLE))); 171 172 viewHolder = getViewHolderAtPosition(1); 173 assertThat(viewHolder.getAction1().getVisibility(), is(equalTo(View.VISIBLE))); 174 assertThat(viewHolder.getAction1Divider().getVisibility(), is(equalTo(View.VISIBLE))); 175 176 viewHolder = getViewHolderAtPosition(2); 177 assertThat(viewHolder.getAction1().getVisibility(), is(equalTo(View.VISIBLE))); 178 assertThat(viewHolder.getAction1Divider().getVisibility(), is(equalTo(View.VISIBLE))); 179 assertThat(viewHolder.getAction2().getVisibility(), is(equalTo(View.VISIBLE))); 180 assertThat(viewHolder.getAction2Divider().getVisibility(), is(equalTo(View.VISIBLE))); 181 } 182 183 @Test 184 public void testSwitchVisibleAndCheckedState() { 185 TextListItem item0 = new TextListItem(mActivity); 186 item0.setSwitch(true, true, null); 187 188 TextListItem item1 = new TextListItem(mActivity); 189 item1.setSwitch(false, true, null); 190 191 List<TextListItem> items = Arrays.asList(item0, item1); 192 setupPagedListView(items); 193 194 TextListItem.ViewHolder viewHolder = getViewHolderAtPosition(0); 195 assertThat(viewHolder.getSwitch().getVisibility(), is(equalTo(View.VISIBLE))); 196 assertThat(viewHolder.getSwitch().isChecked(), is(equalTo(true))); 197 assertThat(viewHolder.getSwitchDivider().getVisibility(), is(equalTo(View.VISIBLE))); 198 199 viewHolder = getViewHolderAtPosition(1); 200 assertThat(viewHolder.getSwitch().getVisibility(), is(equalTo(View.VISIBLE))); 201 assertThat(viewHolder.getSwitch().isChecked(), is(equalTo(false))); 202 assertThat(viewHolder.getSwitchDivider().getVisibility(), is(equalTo(View.VISIBLE))); 203 } 204 205 @Test 206 public void testDividersAreOptional() { 207 TextListItem item0 = new TextListItem(mActivity); 208 item0.setSupplementalIcon(android.R.drawable.sym_def_app_icon, false); 209 210 TextListItem item1 = new TextListItem(mActivity); 211 item1.setAction("text", false, v -> { /* Do nothing. */ }); 212 213 TextListItem item2 = new TextListItem(mActivity); 214 item2.setActions("text", false, v -> { /* Do nothing. */ }, 215 "text", false, v -> { /* Do nothing. */ }); 216 217 TextListItem item3 = new TextListItem(mActivity); 218 item3.setSwitch(true, false, null); 219 220 List<TextListItem> items = Arrays.asList(item0, item1, item2, item3); 221 setupPagedListView(items); 222 223 TextListItem.ViewHolder viewHolder = getViewHolderAtPosition(0); 224 assertThat(viewHolder.getSupplementalIcon().getVisibility(), is(equalTo(View.VISIBLE))); 225 assertThat(viewHolder.getSupplementalIconDivider().getVisibility(), 226 is(equalTo(View.GONE))); 227 228 viewHolder = getViewHolderAtPosition(1); 229 assertThat(viewHolder.getAction1().getVisibility(), is(equalTo(View.VISIBLE))); 230 assertThat(viewHolder.getAction1Divider().getVisibility(), is(equalTo(View.GONE))); 231 232 viewHolder = getViewHolderAtPosition(2); 233 assertThat(viewHolder.getAction1().getVisibility(), is(equalTo(View.VISIBLE))); 234 assertThat(viewHolder.getAction1Divider().getVisibility(), is(equalTo(View.GONE))); 235 assertThat(viewHolder.getAction2().getVisibility(), is(equalTo(View.VISIBLE))); 236 assertThat(viewHolder.getAction2Divider().getVisibility(), is(equalTo(View.GONE))); 237 238 viewHolder = getViewHolderAtPosition(3); 239 assertThat(viewHolder.getSwitch().getVisibility(), is(equalTo(View.VISIBLE))); 240 assertThat(viewHolder.getSwitchDivider().getVisibility(), is(equalTo(View.GONE))); 241 } 242 243 @Test 244 public void testTextStartMarginMatchesPrimaryActionType() { 245 TextListItem item0 = new TextListItem(mActivity); 246 item0.setPrimaryActionIcon(android.R.drawable.sym_def_app_icon, true); 247 248 TextListItem item1 = new TextListItem(mActivity); 249 item1.setPrimaryActionIcon(android.R.drawable.sym_def_app_icon, false); 250 251 TextListItem item2 = new TextListItem(mActivity); 252 item2.setPrimaryActionEmptyIcon(); 253 254 TextListItem item3 = new TextListItem(mActivity); 255 item3.setPrimaryActionNoIcon(); 256 257 List<TextListItem> items = Arrays.asList(item0, item1, item2, item3); 258 List<Integer> expectedStartMargin = Arrays.asList(R.dimen.car_keyline_4, 259 R.dimen.car_keyline_3, R.dimen.car_keyline_3, R.dimen.car_keyline_1); 260 setupPagedListView(items); 261 262 for (int i = 0; i < items.size(); i++) { 263 TextListItem.ViewHolder viewHolder = getViewHolderAtPosition(i); 264 265 int expected = InstrumentationRegistry.getContext().getResources() 266 .getDimensionPixelSize(expectedStartMargin.get(i)); 267 assertThat(((ViewGroup.MarginLayoutParams) viewHolder.getTitle().getLayoutParams()) 268 .getMarginStart(), is(equalTo(expected))); 269 assertThat(((ViewGroup.MarginLayoutParams) viewHolder.getBody().getLayoutParams()) 270 .getMarginStart(), is(equalTo(expected))); 271 } 272 } 273 274 @Test 275 public void testItemWithOnlyTitleIsSingleLine() { 276 // Only space. 277 TextListItem item0 = new TextListItem(mActivity); 278 item0.setTitle(" "); 279 280 // Underscore. 281 TextListItem item1 = new TextListItem(mActivity); 282 item1.setTitle("______"); 283 284 TextListItem item2 = new TextListItem(mActivity); 285 item2.setTitle("ALL UPPER CASE"); 286 287 // String wouldn't fit in one line. 288 TextListItem item3 = new TextListItem(mActivity); 289 item3.setTitle(InstrumentationRegistry.getContext().getResources().getString( 290 R.string.over_120_chars)); 291 292 List<TextListItem> items = Arrays.asList(item0, item1, item2, item3); 293 setupPagedListView(items); 294 295 double singleLineHeight = InstrumentationRegistry.getContext().getResources().getDimension( 296 R.dimen.car_single_line_list_item_height); 297 298 LinearLayoutManager layoutManager = 299 (LinearLayoutManager) mPagedListView.getRecyclerView().getLayoutManager(); 300 for (int i = 0; i < items.size(); i++) { 301 assertThat((double) layoutManager.findViewByPosition(i).getHeight(), 302 is(closeTo(singleLineHeight, 1.0d))); 303 } 304 } 305 306 @Test 307 public void testItemWithBodyTextIsAtLeastDoubleLine() { 308 // Only space. 309 TextListItem item0 = new TextListItem(mActivity); 310 item0.setBody(" "); 311 312 // Underscore. 313 TextListItem item1 = new TextListItem(mActivity); 314 item1.setBody("____"); 315 316 // String wouldn't fit in one line. 317 TextListItem item2 = new TextListItem(mActivity); 318 item2.setBody(InstrumentationRegistry.getContext().getResources().getString( 319 R.string.over_120_chars)); 320 321 List<TextListItem> items = Arrays.asList(item0, item1, item2); 322 setupPagedListView(items); 323 324 final int doubleLineHeight = 325 (int) InstrumentationRegistry.getContext().getResources().getDimension( 326 R.dimen.car_double_line_list_item_height); 327 328 LinearLayoutManager layoutManager = 329 (LinearLayoutManager) mPagedListView.getRecyclerView().getLayoutManager(); 330 for (int i = 0; i < items.size(); i++) { 331 assertThat(layoutManager.findViewByPosition(i).getHeight(), 332 is(greaterThanOrEqualTo(doubleLineHeight))); 333 } 334 } 335 336 @Test 337 public void testBodyTextLengthLimit() { 338 final String longText = InstrumentationRegistry.getContext().getResources().getString( 339 R.string.over_120_chars); 340 final int limit = InstrumentationRegistry.getContext().getResources().getInteger( 341 R.integer.car_list_item_text_length_limit); 342 343 TextListItem item0 = new TextListItem(mActivity); 344 item0.setBody(longText); 345 346 List<TextListItem> items = Arrays.asList(item0); 347 setupPagedListView(items); 348 349 // + 1 for appended ellipsis. 350 assertThat(getViewHolderAtPosition(0).getBody().getText().length(), 351 is(equalTo(limit + 1))); 352 } 353 354 @Test 355 public void testPrimaryIconDrawable() { 356 Drawable drawable = InstrumentationRegistry.getContext().getResources().getDrawable( 357 android.R.drawable.sym_def_app_icon, null); 358 359 TextListItem item0 = new TextListItem(mActivity); 360 item0.setPrimaryActionIcon(drawable, true); 361 362 List<TextListItem> items = Arrays.asList(item0); 363 setupPagedListView(items); 364 365 assertTrue(getViewHolderAtPosition(0).getPrimaryIcon().getDrawable().getConstantState() 366 .equals(drawable.getConstantState())); 367 } 368 369 @Test 370 public void testLargePrimaryIconHasNoStartMargin() { 371 TextListItem item0 = new TextListItem(mActivity); 372 item0.setPrimaryActionIcon(android.R.drawable.sym_def_app_icon, true); 373 374 List<TextListItem> items = Arrays.asList(item0); 375 setupPagedListView(items); 376 377 TextListItem.ViewHolder viewHolder = getViewHolderAtPosition(0); 378 assertThat(((ViewGroup.MarginLayoutParams) viewHolder.getPrimaryIcon().getLayoutParams()) 379 .getMarginStart(), is(equalTo(0))); 380 } 381 382 @Test 383 public void testSmallPrimaryIconStartMargin() { 384 TextListItem item0 = new TextListItem(mActivity); 385 item0.setPrimaryActionIcon(android.R.drawable.sym_def_app_icon, false); 386 387 List<TextListItem> items = Arrays.asList(item0); 388 setupPagedListView(items); 389 390 int expected = InstrumentationRegistry.getContext().getResources().getDimensionPixelSize( 391 R.dimen.car_keyline_1); 392 393 TextListItem.ViewHolder viewHolder = getViewHolderAtPosition(0); 394 assertThat(((ViewGroup.MarginLayoutParams) viewHolder.getPrimaryIcon().getLayoutParams()) 395 .getMarginStart(), is(equalTo(expected))); 396 } 397 398 @Test 399 public void testSmallPrimaryIconTopMarginRemainsTheSameRegardlessOfTextLength() { 400 final String longText = InstrumentationRegistry.getContext().getResources().getString( 401 R.string.over_120_chars); 402 403 // Single line item. 404 TextListItem item0 = new TextListItem(mActivity); 405 item0.setPrimaryActionIcon(android.R.drawable.sym_def_app_icon, false); 406 item0.setTitle("one line text"); 407 408 // Double line item with one line text. 409 TextListItem item1 = new TextListItem(mActivity); 410 item1.setPrimaryActionIcon(android.R.drawable.sym_def_app_icon, false); 411 item1.setTitle("one line text"); 412 item1.setBody("one line text"); 413 414 // Double line item with long text. 415 TextListItem item2 = new TextListItem(mActivity); 416 item2.setPrimaryActionIcon(android.R.drawable.sym_def_app_icon, false); 417 item2.setTitle("one line text"); 418 item2.setBody(longText); 419 420 // Body text only - long text. 421 TextListItem item3 = new TextListItem(mActivity); 422 item3.setPrimaryActionIcon(android.R.drawable.sym_def_app_icon, false); 423 item3.setBody(longText); 424 425 // Body text only - one line text. 426 TextListItem item4 = new TextListItem(mActivity); 427 item4.setPrimaryActionIcon(android.R.drawable.sym_def_app_icon, false); 428 item4.setBody("one line text"); 429 430 List<TextListItem> items = Arrays.asList(item0, item1, item2, item3, item4); 431 setupPagedListView(items); 432 433 for (int i = 1; i < items.size(); i++) { 434 onView(withId(R.id.recycler_view)).perform(scrollToPosition(i)); 435 // Implementation uses integer division so it may be off by 1 vs centered vertically. 436 assertThat((double) getViewHolderAtPosition(i - 1).getPrimaryIcon().getTop(), 437 is(closeTo( 438 (double) getViewHolderAtPosition(i).getPrimaryIcon().getTop(), 1.0d))); 439 } 440 } 441 442 @Test 443 public void testClickingPrimaryActionIsSeparateFromSupplementalAction() { 444 final boolean[] clicked = {false, false}; 445 446 TextListItem item0 = new TextListItem(mActivity); 447 item0.setOnClickListener(v -> clicked[0] = true); 448 item0.setSupplementalIcon(android.R.drawable.sym_def_app_icon, true, 449 v -> clicked[1] = true); 450 451 List<TextListItem> items = Arrays.asList(item0); 452 setupPagedListView(items); 453 454 onView(withId(R.id.recycler_view)).perform(actionOnItemAtPosition(0, click())); 455 assertTrue(clicked[0]); 456 assertFalse(clicked[1]); 457 458 onView(withId(R.id.recycler_view)).perform( 459 actionOnItemAtPosition(0, clickChildViewWithId(R.id.supplemental_icon))); 460 assertTrue(clicked[1]); 461 } 462 463 @Test 464 public void testClickingSupplementalIcon() { 465 final boolean[] clicked = {false}; 466 467 TextListItem item0 = new TextListItem(mActivity); 468 item0.setSupplementalIcon(android.R.drawable.sym_def_app_icon, true, 469 v -> clicked[0] = true); 470 471 List<TextListItem> items = Arrays.asList(item0); 472 setupPagedListView(items); 473 474 onView(withId(R.id.recycler_view)).perform( 475 actionOnItemAtPosition(0, clickChildViewWithId(R.id.supplemental_icon))); 476 assertTrue(clicked[0]); 477 } 478 479 @Test 480 public void testSupplementalIconWithoutClickListenerIsNotClickable() { 481 TextListItem item0 = new TextListItem(mActivity); 482 item0.setSupplementalIcon(android.R.drawable.sym_def_app_icon, true); 483 484 List<TextListItem> items = Arrays.asList(item0); 485 setupPagedListView(items); 486 487 TextListItem.ViewHolder viewHolder = getViewHolderAtPosition(0); 488 assertFalse(viewHolder.getSupplementalIcon().isClickable()); 489 } 490 491 @Test 492 public void testCheckingSwitch() { 493 final boolean[] clicked = {false, false}; 494 495 TextListItem item0 = new TextListItem(mActivity); 496 item0.setSwitch(false, false, (button, isChecked) -> { 497 // Initial value is false. 498 assertTrue(isChecked); 499 clicked[0] = true; 500 }); 501 502 TextListItem item1 = new TextListItem(mActivity); 503 item1.setSwitch(true, false, (button, isChecked) -> { 504 // Initial value is true. 505 assertFalse(isChecked); 506 clicked[1] = true; 507 }); 508 509 List<TextListItem> items = Arrays.asList(item0, item1); 510 setupPagedListView(items); 511 512 onView(withId(R.id.recycler_view)).perform( 513 actionOnItemAtPosition(0, clickChildViewWithId(R.id.switch_widget))); 514 assertTrue(clicked[0]); 515 516 onView(withId(R.id.recycler_view)).perform( 517 actionOnItemAtPosition(1, clickChildViewWithId(R.id.switch_widget))); 518 assertTrue(clicked[1]); 519 } 520 521 @Test 522 public void testClickingSupplementalAction() { 523 final boolean[] clicked = {false}; 524 525 TextListItem item0 = new TextListItem(mActivity); 526 item0.setAction("action", true, v -> clicked[0] = true); 527 528 List<TextListItem> items = Arrays.asList(item0); 529 setupPagedListView(items); 530 531 onView(withId(R.id.recycler_view)).perform( 532 actionOnItemAtPosition(0, clickChildViewWithId(R.id.action1))); 533 assertTrue(clicked[0]); 534 } 535 536 @Test 537 public void testClickingBothSupplementalActions() { 538 final boolean[] clicked = {false, false}; 539 540 TextListItem item0 = new TextListItem(mActivity); 541 item0.setActions("action 1", true, v -> clicked[0] = true, 542 "action 2", true, v -> clicked[1] = true); 543 544 List<TextListItem> items = Arrays.asList(item0); 545 setupPagedListView(items); 546 547 onView(withId(R.id.recycler_view)).perform( 548 actionOnItemAtPosition(0, clickChildViewWithId(R.id.action1))); 549 assertTrue(clicked[0]); 550 assertFalse(clicked[1]); 551 552 onView(withId(R.id.recycler_view)).perform( 553 actionOnItemAtPosition(0, clickChildViewWithId(R.id.action2))); 554 assertTrue(clicked[1]); 555 } 556 557 @Test 558 public void testCustomViewBinderBindsLast() { 559 final String updatedTitle = "updated title"; 560 561 TextListItem item0 = new TextListItem(mActivity); 562 item0.setTitle("original title"); 563 item0.addViewBinder((viewHolder) -> viewHolder.getTitle().setText(updatedTitle)); 564 565 List<TextListItem> items = Arrays.asList(item0); 566 setupPagedListView(items); 567 568 TextListItem.ViewHolder viewHolder = getViewHolderAtPosition(0); 569 assertThat(viewHolder.getTitle().getText(), is(equalTo(updatedTitle))); 570 } 571 572 @Test 573 public void testCustomViewBinderOnUnusedViewsHasNoEffect() { 574 TextListItem item0 = new TextListItem(mActivity); 575 item0.addViewBinder((viewHolder) -> viewHolder.getBody().setText("text")); 576 577 List<TextListItem> items = Arrays.asList(item0); 578 setupPagedListView(items); 579 580 TextListItem.ViewHolder viewHolder = getViewHolderAtPosition(0); 581 assertThat(viewHolder.getBody().getVisibility(), is(equalTo(View.GONE))); 582 // Custom binder interacts with body but has no effect. 583 // Expect card height to remain single line. 584 assertThat((double) viewHolder.itemView.getHeight(), is(closeTo( 585 InstrumentationRegistry.getContext().getResources().getDimension( 586 R.dimen.car_single_line_list_item_height), 1.0d))); 587 } 588 589 @Test 590 public void testSettingTitleOrBodyAsPrimaryText() { 591 // Create 2 items, one with Title as primary (default) and one with Body. 592 // The primary text, regardless of view, should have consistent look (as primary). 593 TextListItem item0 = new TextListItem(mActivity); 594 item0.setTitle("title"); 595 item0.setBody("body"); 596 597 TextListItem item1 = new TextListItem(mActivity); 598 item1.setTitle("title"); 599 item1.setBody("body", true); 600 601 List<TextListItem> items = Arrays.asList(item0, item1); 602 setupPagedListView(items); 603 604 TextListItem.ViewHolder titlePrimary = getViewHolderAtPosition(0); 605 TextListItem.ViewHolder bodyPrimary = getViewHolderAtPosition(1); 606 assertThat(titlePrimary.getTitle().getTextSize(), 607 is(equalTo(bodyPrimary.getBody().getTextSize()))); 608 assertThat(titlePrimary.getTitle().getTextColors(), 609 is(equalTo(bodyPrimary.getBody().getTextColors()))); 610 } 611 612 @Test 613 public void testNoCarriedOverLayoutParamsForTextView() throws Throwable { 614 TextListItem singleLine = new TextListItem(mActivity); 615 singleLine.setTitle("title"); 616 617 setupPagedListView(Arrays.asList(singleLine)); 618 619 // Manually rebind the view holder of a single line item to a double line item. 620 TextListItem doubleLine = new TextListItem(mActivity); 621 doubleLine.setTitle("title"); 622 doubleLine.setBody("body"); 623 TextListItem.ViewHolder viewHolder = getViewHolderAtPosition(0); 624 mActivityRule.runOnUiThread(() -> doubleLine.bind(viewHolder)); 625 626 RelativeLayout.LayoutParams titleLayoutParams = 627 (RelativeLayout.LayoutParams) viewHolder.getTitle().getLayoutParams(); 628 RelativeLayout.LayoutParams bodyLayoutParams = 629 (RelativeLayout.LayoutParams) viewHolder.getTitle().getLayoutParams(); 630 assertThat(titleLayoutParams.getRule(RelativeLayout.CENTER_VERTICAL), is(equalTo(0))); 631 assertThat(bodyLayoutParams.getRule(RelativeLayout.CENTER_VERTICAL), is(equalTo(0))); 632 } 633 634 @Test 635 public void testNoCarriedOverLayoutParamsForPrimaryIcon() throws Throwable { 636 TextListItem smallIcon = new TextListItem(mActivity); 637 smallIcon.setPrimaryActionIcon(android.R.drawable.sym_def_app_icon, false); 638 smallIcon.setBody("body"); // Small icon of items with body text should use top margin. 639 setupPagedListView(Arrays.asList(smallIcon)); 640 641 // Manually rebind the view holder. 642 TextListItem largeIcon = new TextListItem(mActivity); 643 largeIcon.setPrimaryActionIcon(android.R.drawable.sym_def_app_icon, true); 644 TextListItem.ViewHolder viewHolder = getViewHolderAtPosition(0); 645 mActivityRule.runOnUiThread(() -> largeIcon.bind(viewHolder)); 646 647 RelativeLayout.LayoutParams iconLayoutParams = 648 (RelativeLayout.LayoutParams) viewHolder.getPrimaryIcon().getLayoutParams(); 649 assertThat(iconLayoutParams.getRule(RelativeLayout.CENTER_VERTICAL), 650 is(equalTo(RelativeLayout.TRUE))); 651 assertThat(iconLayoutParams.topMargin, is(equalTo(0))); 652 } 653 654 @Test 655 public void testUpdateItem() throws Throwable { 656 TextListItem item = new TextListItem(mActivity); 657 setupPagedListView(Arrays.asList(item)); 658 659 String title = "updated title"; 660 item.setTitle(title); 661 mActivityRule.runOnUiThread(() -> mPagedListView.getAdapter().notifyItemChanged(0)); 662 663 // Wait for paged list view to layout by using espresso to scroll to a position. 664 onView(withId(R.id.recycler_view)).perform(scrollToPosition(0)); 665 666 TextListItem.ViewHolder viewHolder = getViewHolderAtPosition(0); 667 assertThat(viewHolder.getTitle().getText(), is(equalTo(title))); 668 } 669 670 private static ViewAction clickChildViewWithId(final int id) { 671 return new ViewAction() { 672 @Override 673 public Matcher<View> getConstraints() { 674 return null; 675 } 676 677 @Override 678 public String getDescription() { 679 return "Click on a child view with specific id."; 680 } 681 682 @Override 683 public void perform(UiController uiController, View view) { 684 View v = view.findViewById(id); 685 v.performClick(); 686 } 687 }; 688 } 689} 690