1 /* 2 * Copyright (C) 2016 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 package androidx.appcompat.widget; 17 18 import static android.support.test.espresso.Espresso.onView; 19 import static android.support.test.espresso.assertion.ViewAssertions.matches; 20 import static android.support.test.espresso.matcher.ViewMatchers.withId; 21 22 import static androidx.appcompat.testutils.TestUtilsActions.setEnabled; 23 import static androidx.appcompat.testutils.TestUtilsActions.setTextAppearance; 24 import static androidx.appcompat.testutils.TestUtilsMatchers.isBackground; 25 26 import static org.junit.Assert.assertEquals; 27 import static org.junit.Assert.assertNotEquals; 28 import static org.junit.Assert.assertNotNull; 29 import static org.junit.Assert.assertTrue; 30 31 import android.content.pm.PackageManager; 32 import android.content.res.ColorStateList; 33 import android.graphics.Color; 34 import android.graphics.Typeface; 35 import android.os.Build; 36 import android.support.test.annotation.UiThreadTest; 37 import android.support.test.filters.MediumTest; 38 import android.support.test.filters.SdkSuppress; 39 import android.support.test.filters.SmallTest; 40 import android.view.View; 41 import android.widget.TextView; 42 43 import androidx.annotation.ColorInt; 44 import androidx.appcompat.test.R; 45 import androidx.core.content.ContextCompat; 46 import androidx.core.content.res.ResourcesCompat; 47 import androidx.core.view.ViewCompat; 48 import androidx.core.widget.TextViewCompat; 49 50 import org.junit.Test; 51 52 import java.util.concurrent.CountDownLatch; 53 import java.util.concurrent.TimeUnit; 54 55 /** 56 * In addition to all tinting-related tests done by the base class, this class provides 57 * tests specific to {@link AppCompatTextView} class. 58 */ 59 @SmallTest 60 public class AppCompatTextViewTest 61 extends AppCompatBaseViewTest<AppCompatTextViewActivity, AppCompatTextView> { 62 63 public AppCompatTextViewTest() { 64 super(AppCompatTextViewActivity.class); 65 } 66 67 /** 68 * This method tests that background tinting is applied when the call to 69 * {@link androidx.core.view.ViewCompat#setBackgroundTintList(View, ColorStateList)} 70 * is done as a deferred event. 71 */ 72 @Test 73 @MediumTest 74 public void testDeferredBackgroundTinting() throws Throwable { 75 onView(withId(R.id.view_untinted_deferred)) 76 .check(matches(isBackground(0xff000000, true))); 77 78 final @ColorInt int oceanDefault = ResourcesCompat.getColor( 79 mResources, R.color.ocean_default, null); 80 81 final ColorStateList oceanColor = ResourcesCompat.getColorStateList( 82 mResources, R.color.color_state_list_ocean, null); 83 84 // Emulate delay in kicking off the call to ViewCompat.setBackgroundTintList 85 Thread.sleep(200); 86 final CountDownLatch latch = new CountDownLatch(1); 87 mActivityTestRule.runOnUiThread(new Runnable() { 88 @Override 89 public void run() { 90 TextView view = mActivity.findViewById(R.id.view_untinted_deferred); 91 ViewCompat.setBackgroundTintList(view, oceanColor); 92 latch.countDown(); 93 } 94 }); 95 96 assertTrue(latch.await(2, TimeUnit.SECONDS)); 97 98 // Check that the background has switched to the matching entry in the newly set 99 // color state list. 100 onView(withId(R.id.view_untinted_deferred)) 101 .check(matches(isBackground(oceanDefault, true))); 102 } 103 104 @Test 105 public void testAllCaps() { 106 final String text1 = mResources.getString(R.string.sample_text1); 107 final String text2 = mResources.getString(R.string.sample_text2); 108 109 final AppCompatTextView textView1 = mContainer.findViewById(R.id.text_view_caps1); 110 final AppCompatTextView textView2 = mContainer.findViewById(R.id.text_view_caps2); 111 112 // Note that TextView.getText() returns the original text. We are interested in 113 // the transformed text that is set on the Layout object used to draw the final 114 // (transformed) content. 115 assertEquals("Text view starts in all caps on", 116 text1.toUpperCase(), textView1.getLayout().getText().toString()); 117 assertEquals("Text view starts in all caps off", 118 text2, textView2.getLayout().getText().toString()); 119 120 // Toggle all-caps mode on the two text views 121 onView(withId(R.id.text_view_caps1)).perform( 122 setTextAppearance(R.style.TextStyleAllCapsOff)); 123 assertEquals("Text view is now in all caps off", 124 text1, textView1.getLayout().getText().toString()); 125 126 onView(withId(R.id.text_view_caps2)).perform( 127 setTextAppearance(R.style.TextStyleAllCapsOn)); 128 assertEquals("Text view is now in all caps on", 129 text2.toUpperCase(), textView2.getLayout().getText().toString()); 130 } 131 132 @Test 133 public void testAppCompatAllCapsFalseOnButton() { 134 final String text = mResources.getString(R.string.sample_text2); 135 final AppCompatTextView textView = 136 mContainer.findViewById(R.id.text_view_app_allcaps_false); 137 138 assertEquals("Text view is not in all caps", text, textView.getLayout().getText()); 139 } 140 141 @Test 142 public void testTextColorSetHex() { 143 final TextView textView = mContainer.findViewById(R.id.view_text_color_hex); 144 assertEquals(Color.RED, textView.getCurrentTextColor()); 145 } 146 147 @Test 148 public void testTextColorSetColorStateList() { 149 final TextView textView = mContainer.findViewById(R.id.view_text_color_csl); 150 151 onView(withId(R.id.view_text_color_csl)).perform(setEnabled(true)); 152 assertEquals(ContextCompat.getColor(textView.getContext(), R.color.ocean_default), 153 textView.getCurrentTextColor()); 154 155 onView(withId(R.id.view_text_color_csl)).perform(setEnabled(false)); 156 assertEquals(ContextCompat.getColor(textView.getContext(), R.color.ocean_disabled), 157 textView.getCurrentTextColor()); 158 } 159 160 @Test 161 public void testTextColorSetThemeAttrHex() { 162 final TextView textView = mContainer.findViewById(R.id.view_text_color_primary); 163 assertEquals(Color.BLUE, textView.getCurrentTextColor()); 164 } 165 166 @Test 167 public void testTextColorSetThemeAttrColorStateList() { 168 final TextView textView = mContainer.findViewById(R.id.view_text_color_secondary); 169 170 onView(withId(R.id.view_text_color_secondary)).perform(setEnabled(true)); 171 assertEquals(ContextCompat.getColor(textView.getContext(), R.color.sand_default), 172 textView.getCurrentTextColor()); 173 174 onView(withId(R.id.view_text_color_secondary)).perform(setEnabled(false)); 175 assertEquals(ContextCompat.getColor(textView.getContext(), R.color.sand_disabled), 176 textView.getCurrentTextColor()); 177 } 178 179 private void verifyTextLinkColor(TextView textView) { 180 ColorStateList linkColorStateList = textView.getLinkTextColors(); 181 assertEquals(ContextCompat.getColor(textView.getContext(), R.color.lilac_default), 182 linkColorStateList.getColorForState(new int[] { android.R.attr.state_enabled}, 0)); 183 assertEquals(ContextCompat.getColor(textView.getContext(), R.color.lilac_disabled), 184 linkColorStateList.getColorForState(new int[] { -android.R.attr.state_enabled}, 0)); 185 } 186 187 @Test 188 public void testTextLinkColor() { 189 verifyTextLinkColor((TextView) mContainer.findViewById(R.id.view_text_link_enabled)); 190 verifyTextLinkColor((TextView) mContainer.findViewById(R.id.view_text_link_disabled)); 191 } 192 193 @Test 194 public void testFontResources_setInStringFamilyName() { 195 TextView textView = 196 mContainer.findViewById(R.id.textview_fontresource_fontfamily_string_resource); 197 assertNotNull(textView.getTypeface()); 198 // Pre-L, Typeface always resorts to native for a Typeface object, hence giving you a 199 // different one each call. 200 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 201 assertEquals(Typeface.SANS_SERIF, textView.getTypeface()); 202 } 203 textView = mContainer.findViewById(R.id.textview_fontresource_fontfamily_string_direct); 204 assertNotNull(textView.getTypeface()); 205 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 206 assertEquals(Typeface.SANS_SERIF, textView.getTypeface()); 207 } 208 } 209 210 @Test 211 public void testFontResources_setInXmlFamilyName() { 212 TextView textView = mContainer.findViewById(R.id.textview_fontresource_fontfamily); 213 Typeface expected = ResourcesCompat.getFont(mActivity, R.font.samplefont); 214 215 assertEquals(expected, textView.getTypeface()); 216 } 217 218 @Test 219 public void testFontResourcesXml_setInXmlFamilyName() { 220 TextView textView = mContainer.findViewById(R.id.textview_fontxmlresource_fontfamily); 221 Typeface expected = ResourcesCompat.getFont(mActivity, R.font.samplexmlfont); 222 223 assertEquals(expected, textView.getTypeface()); 224 } 225 226 @Test 227 public void testFontResourcesXml_setInXmlFamilyNameWithTextStyle() { 228 TextView textView = 229 mContainer.findViewById(R.id.textview_fontxmlresource_fontfamily_textstyle); 230 231 assertNotEquals(Typeface.DEFAULT, textView.getTypeface()); 232 } 233 234 @Test 235 public void testFontResourcesXml_setInXmlFamilyNameWithTextStyle2() { 236 TextView textView = 237 mContainer.findViewById(R.id.textview_fontxmlresource_fontfamily_textstyle2); 238 239 assertNotEquals(Typeface.DEFAULT, textView.getTypeface()); 240 } 241 242 @Test 243 public void testFontResources_setInXmlStyle() { 244 TextView textView = mContainer.findViewById(R.id.textview_fontresource_style); 245 Typeface expected = ResourcesCompat.getFont(mActivity, R.font.samplefont); 246 247 assertEquals(expected, textView.getTypeface()); 248 } 249 250 @Test 251 public void testFontResourcesXml_setInXmlStyle() { 252 TextView textView = mContainer.findViewById(R.id.textview_fontxmlresource_style); 253 Typeface expected = ResourcesCompat.getFont(mActivity, R.font.samplexmlfont); 254 255 assertEquals(expected, textView.getTypeface()); 256 } 257 258 @Test 259 public void testFontResources_setInXmlTextAppearance() { 260 TextView textView = mContainer.findViewById(R.id.textview_fontresource_textAppearance); 261 Typeface expected = ResourcesCompat.getFont(mActivity, R.font.samplefont); 262 263 assertEquals(expected, textView.getTypeface()); 264 } 265 266 @Test 267 public void testFontResourcesXml_setInXmlTextAppearance() { 268 TextView textView = mContainer.findViewById(R.id.textview_fontxmlresource_textAppearance); 269 Typeface expected = ResourcesCompat.getFont(mActivity, R.font.samplexmlfont); 270 271 assertEquals(expected, textView.getTypeface()); 272 } 273 274 @Test 275 public void testTextStyle_setTextStyleInStyle() { 276 // TextView has a TextAppearance by default, but the textStyle can be overriden in style. 277 TextView textView = mContainer.findViewById(R.id.textview_textStyleOverride); 278 279 assertEquals(Typeface.ITALIC, textView.getTypeface().getStyle()); 280 } 281 282 @Test 283 public void testTextStyle_setTextStyleDirectly() { 284 TextView textView = mContainer.findViewById(R.id.textview_textStyleDirect); 285 286 assertEquals(Typeface.ITALIC, textView.getTypeface().getStyle()); 287 } 288 289 @Test 290 @UiThreadTest 291 public void testFontResources_setTextAppearance() { 292 TextView textView = mContainer.findViewById(R.id.textview_simple); 293 294 TextViewCompat.setTextAppearance(textView, R.style.TextView_FontResourceWithStyle); 295 296 assertNotEquals(Typeface.DEFAULT, textView.getTypeface()); 297 } 298 299 @Test 300 @UiThreadTest 301 public void testSetTextAppearance_resetTypeface() throws PackageManager.NameNotFoundException { 302 TextView textView = mContainer.findViewById(R.id.textview_simple); 303 304 TextViewCompat.setTextAppearance(textView, R.style.TextView_SansSerif); 305 Typeface firstTypeface = textView.getTypeface(); 306 307 TextViewCompat.setTextAppearance(textView, R.style.TextView_Serif); 308 Typeface secondTypeface = textView.getTypeface(); 309 assertNotNull(firstTypeface); 310 assertNotNull(secondTypeface); 311 assertNotEquals(firstTypeface, secondTypeface); 312 } 313 314 @Test 315 @UiThreadTest 316 public void testTypefaceAttribute_serif() { 317 TextView textView = mContainer.findViewById(R.id.textview_simple); 318 319 TextViewCompat.setTextAppearance(textView, R.style.TextView_Typeface_Serif); 320 321 assertEquals(Typeface.SERIF, textView.getTypeface()); 322 } 323 324 @Test 325 @UiThreadTest 326 public void testTypefaceAttribute_monospace() { 327 TextView textView = mContainer.findViewById(R.id.textview_simple); 328 329 TextViewCompat.setTextAppearance(textView, R.style.TextView_Typeface_Monospace); 330 331 assertEquals(Typeface.MONOSPACE, textView.getTypeface()); 332 } 333 334 @Test 335 @UiThreadTest 336 public void testTypefaceAttribute_serifFromXml() { 337 TextView textView = mContainer.findViewById(R.id.textview_typeface_serif); 338 339 assertEquals(Typeface.SERIF, textView.getTypeface()); 340 } 341 342 @Test 343 @UiThreadTest 344 public void testTypefaceAttribute_monospaceFromXml() { 345 TextView textView = mContainer.findViewById(R.id.textview_typeface_monospace); 346 347 assertEquals(Typeface.MONOSPACE, textView.getTypeface()); 348 } 349 350 @Test 351 @UiThreadTest 352 public void testTypefaceAttribute_fontFamilyHierarchy() { 353 // This view has typeface=serif set on the view directly and a fontFamily on the appearance 354 TextView textView = mContainer.findViewById(R.id.textview_typeface_and_fontfamily); 355 356 assertEquals(Typeface.SERIF, textView.getTypeface()); 357 } 358 359 @SdkSuppress(minSdkVersion = 16) 360 @Test 361 @UiThreadTest 362 public void testfontFamilyNamespaceHierarchy() { 363 // This view has fontFamily set in both the app and android namespace. App should be used. 364 TextView textView = mContainer.findViewById(R.id.textview_app_and_android_fontfamily); 365 366 assertEquals(Typeface.MONOSPACE, textView.getTypeface()); 367 } 368 369 @Test 370 @UiThreadTest 371 public void testBaselineAttributes() { 372 TextView textView = mContainer.findViewById(R.id.textview_baseline); 373 374 final int firstBaselineToTopHeight = textView.getResources() 375 .getDimensionPixelSize(R.dimen.textview_firstBaselineToTopHeight); 376 final int lastBaselineToBottomHeight = textView.getResources() 377 .getDimensionPixelSize(R.dimen.textview_lastBaselineToBottomHeight); 378 final int lineHeight = textView.getResources() 379 .getDimensionPixelSize(R.dimen.textview_lineHeight); 380 381 assertEquals(firstBaselineToTopHeight, 382 TextViewCompat.getFirstBaselineToTopHeight(textView)); 383 assertEquals(lastBaselineToBottomHeight, 384 TextViewCompat.getLastBaselineToBottomHeight(textView)); 385 assertEquals(lineHeight, textView.getLineHeight()); 386 } 387 } 388