1 /* 2 * Copyright (C) 2009 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.view.cts; 18 19 import static com.android.compatibility.common.util.CtsMockitoUtils.within; 20 21 import static org.junit.Assert.assertArrayEquals; 22 import static org.junit.Assert.assertEquals; 23 import static org.junit.Assert.assertFalse; 24 import static org.junit.Assert.assertNotNull; 25 import static org.junit.Assert.assertSame; 26 import static org.junit.Assert.assertTrue; 27 import static org.mockito.ArgumentMatchers.any; 28 import static org.mockito.Mockito.doAnswer; 29 import static org.mockito.Mockito.mock; 30 import static org.mockito.Mockito.reset; 31 import static org.mockito.Mockito.spy; 32 import static org.mockito.Mockito.times; 33 import static org.mockito.Mockito.verify; 34 import static org.mockito.Mockito.verifyNoMoreInteractions; 35 36 import android.Manifest; 37 import android.app.Activity; 38 import android.app.Instrumentation; 39 import android.graphics.Bitmap; 40 import android.graphics.Color; 41 import android.platform.test.annotations.AppModeSdkSandbox; 42 import android.view.View; 43 import android.view.View.OnClickListener; 44 import android.widget.Button; 45 import android.widget.EditText; 46 import android.widget.RelativeLayout; 47 import android.widget.TextView; 48 49 import androidx.test.InstrumentationRegistry; 50 import androidx.test.annotation.UiThreadTest; 51 import androidx.test.filters.MediumTest; 52 import androidx.test.rule.ActivityTestRule; 53 import androidx.test.runner.AndroidJUnit4; 54 import androidx.test.uiautomator.UiDevice; 55 56 import com.android.compatibility.common.util.AdoptShellPermissionsRule; 57 import com.android.compatibility.common.util.CtsTouchUtils; 58 59 import org.junit.Before; 60 import org.junit.Rule; 61 import org.junit.Test; 62 import org.junit.runner.RunWith; 63 import org.mockito.invocation.InvocationOnMock; 64 65 @MediumTest 66 @RunWith(AndroidJUnit4.class) 67 @AppModeSdkSandbox(reason = "Allow test in the SDK sandbox (does not prevent other modes).") 68 public class View_UsingViewsTest { 69 /** 70 * country of Argentina 71 */ 72 private static final String ARGENTINA = "Argentina"; 73 74 /** 75 * country of America 76 */ 77 private static final String AMERICA = "America"; 78 79 /** 80 * country of China 81 */ 82 private static final String CHINA = "China"; 83 84 /** 85 * the symbol of Argentina is football 86 */ 87 private static final String ARGENTINA_SYMBOL = "football"; 88 89 /** 90 * the symbol of America is basketball 91 */ 92 private static final String AMERICA_SYMBOL = "basketball"; 93 94 /** 95 * the symbol of China is table tennis 96 */ 97 private static final String CHINA_SYMBOL = "table tennis"; 98 99 private Instrumentation mInstrumentation; 100 private CtsTouchUtils mCtsTouchUtils; 101 102 private Activity mActivity; 103 104 private EditText mEditText; 105 private Button mButtonOk; 106 private Button mButtonCancel; 107 private TextView mSymbolTextView; 108 private TextView mWarningTextView; 109 110 @Rule(order = 0) 111 public AdoptShellPermissionsRule mAdoptShellPermissionsRule = new AdoptShellPermissionsRule( 112 androidx.test.platform.app.InstrumentationRegistry 113 .getInstrumentation().getUiAutomation(), 114 Manifest.permission.START_ACTIVITIES_FROM_SDK_SANDBOX); 115 116 @Rule(order = 1) 117 public ActivityTestRule<UsingViewsCtsActivity> mActivityRule = 118 new ActivityTestRule<>(UsingViewsCtsActivity.class, /* initialTouchMode= */ true); 119 120 @Before setup()121 public void setup() { 122 mInstrumentation = InstrumentationRegistry.getInstrumentation(); 123 mCtsTouchUtils = new CtsTouchUtils(mInstrumentation.getTargetContext()); 124 mActivity = mActivityRule.getActivity(); 125 126 mEditText = (EditText) mActivity.findViewById(R.id.entry); 127 mButtonOk = (Button) mActivity.findViewById(R.id.ok); 128 mButtonCancel = (Button) mActivity.findViewById(R.id.cancel); 129 mSymbolTextView = (TextView) mActivity.findViewById(R.id.symbolball); 130 mWarningTextView = (TextView) mActivity.findViewById(R.id.warning); 131 } 132 133 @UiThreadTest 134 @Test testSetProperties()135 public void testSetProperties() { 136 // setClickable, setOnClickListener 137 mButtonOk.setClickable(true); 138 assertTrue(mButtonOk.isClickable()); 139 140 View.OnClickListener okButtonListener = spy(new MockOnClickOkListener()); 141 mButtonOk.setOnClickListener(okButtonListener); 142 143 mButtonOk.performClick(); 144 verify(okButtonListener, times(1)).onClick(mButtonOk); 145 146 mButtonCancel.setClickable(false); 147 assertFalse(mButtonCancel.isClickable()); 148 149 View.OnClickListener cancelButtonListener = mock(View.OnClickListener.class); 150 doAnswer((InvocationOnMock invocation) -> { 151 mEditText.setText(null); 152 return null; 153 }).when(cancelButtonListener).onClick(any(View.class)); 154 mButtonCancel.setOnClickListener(cancelButtonListener); 155 assertTrue(mButtonCancel.isClickable()); 156 157 mButtonCancel.performClick(); 158 verify(cancelButtonListener, times(1)).onClick(mButtonCancel); 159 160 // setDrawingCacheEnabled, setDrawingCacheQuality, setDrawingCacheBackgroundColor, 161 mEditText.setDrawingCacheEnabled(true); 162 assertTrue(mEditText.isDrawingCacheEnabled()); 163 164 // the default quality is auto 165 assertEquals(View.DRAWING_CACHE_QUALITY_AUTO, mEditText.getDrawingCacheQuality()); 166 mEditText.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_LOW); 167 assertEquals(View.DRAWING_CACHE_QUALITY_LOW, mEditText.getDrawingCacheQuality()); 168 mEditText.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH); 169 assertEquals(View.DRAWING_CACHE_QUALITY_HIGH, mEditText.getDrawingCacheQuality()); 170 171 mEditText.setDrawingCacheBackgroundColor(Color.GREEN); 172 assertEquals(Color.GREEN, mEditText.getDrawingCacheBackgroundColor()); 173 174 // create the cache 175 Bitmap b = mEditText.getDrawingCache(); 176 assertNotNull(b); 177 assertEquals(mEditText.getHeight(), b.getHeight()); 178 assertEquals(mEditText.getWidth(), b.getWidth()); 179 assertEquals(Color.GREEN, b.getPixel(0, 0)); 180 181 // setDrawingCacheEnabled to false 182 mEditText.setDrawingCacheEnabled(false); 183 assertFalse(mEditText.isDrawingCacheEnabled()); 184 185 mEditText.setDrawingCacheBackgroundColor(Color.YELLOW); 186 assertEquals(Color.YELLOW, mEditText.getDrawingCacheBackgroundColor()); 187 188 // build drawable cache 189 mEditText.buildDrawingCache(); 190 b = mEditText.getDrawingCache(); 191 assertNotNull(b); 192 assertEquals(mEditText.getHeight(), b.getHeight()); 193 assertEquals(mEditText.getWidth(), b.getWidth()); 194 assertEquals(Color.YELLOW, b.getPixel(0, 0)); 195 mEditText.destroyDrawingCache(); 196 197 // setDuplicateParentStateEnabled 198 TextView v = new TextView(mActivity); 199 v.setSingleLine(); // otherwise the multiline state interferes with theses tests 200 v.setEnabled(false); 201 v.setText("Test setDuplicateParentStateEnabled"); 202 203 v.setDuplicateParentStateEnabled(false); 204 assertFalse(v.isDuplicateParentStateEnabled()); 205 206 RelativeLayout parent = (RelativeLayout) mEditText.getParent(); 207 parent.addView(v); 208 209 assertFalse(parent.getDrawableState().length == v.getDrawableState().length); 210 parent.removeView(v); 211 212 v.setDuplicateParentStateEnabled(true); 213 assertTrue(v.isDuplicateParentStateEnabled()); 214 215 parent.addView(v); 216 v.refreshDrawableState(); 217 218 assertArrayEquals(parent.getDrawableState(), v.getDrawableState()); 219 parent.removeView(v); 220 221 // setEnabled 222 mWarningTextView.setEnabled(false); 223 assertFalse(mWarningTextView.isEnabled()); 224 225 mWarningTextView.setEnabled(true); 226 assertTrue(mWarningTextView.isEnabled()); 227 228 // setFadingEdgeLength, setVerticalFadingEdgeEnabled and 229 // setHorizontalFadingEdgeEnabled(boolean) 230 mWarningTextView.setVerticalFadingEdgeEnabled(true); 231 assertTrue(mWarningTextView.isVerticalFadingEdgeEnabled()); 232 mWarningTextView.setFadingEdgeLength(10); 233 234 mSymbolTextView.setHorizontalFadingEdgeEnabled(true); 235 assertTrue(mSymbolTextView.isHorizontalFadingEdgeEnabled()); 236 mSymbolTextView.setFadingEdgeLength(100); 237 238 // setFocusable and setFocusableInTouchMode 239 mButtonCancel.setFocusable(false); 240 assertFalse(mButtonCancel.isFocusable()); 241 assertFalse(mButtonCancel.isFocusableInTouchMode()); 242 243 mButtonCancel.setFocusable(true); 244 assertTrue(mButtonCancel.isFocusable()); 245 assertFalse(mButtonCancel.isFocusableInTouchMode()); 246 247 mButtonCancel.setFocusableInTouchMode(true); 248 assertTrue(mButtonCancel.isFocusable()); 249 assertTrue(mButtonCancel.isFocusableInTouchMode()); 250 251 mButtonOk.setFocusable(false); 252 assertFalse(mButtonOk.isFocusable()); 253 assertFalse(mButtonOk.isFocusableInTouchMode()); 254 255 mButtonOk.setFocusableInTouchMode(true); 256 assertTrue(mButtonOk.isFocusable()); 257 assertTrue(mButtonOk.isFocusableInTouchMode()); 258 259 // setHorizontalScrollBarEnabled and setVerticalScrollBarEnabled 260 // both two bar is not drawn by default 261 assertFalse(parent.isHorizontalScrollBarEnabled()); 262 assertFalse(parent.isVerticalScrollBarEnabled()); 263 264 parent.setHorizontalScrollBarEnabled(true); 265 assertTrue(parent.isHorizontalScrollBarEnabled()); 266 267 parent.setVerticalScrollBarEnabled(true); 268 assertTrue(parent.isVerticalScrollBarEnabled()); 269 270 // setId 271 assertEquals(View.NO_ID, parent.getId()); 272 assertEquals(R.id.entry, mEditText.getId()); 273 assertEquals(R.id.symbolball, mSymbolTextView.getId()); 274 275 mSymbolTextView.setId(0x5555); 276 assertEquals(0x5555, mSymbolTextView.getId()); 277 TextView t = (TextView) parent.findViewById(0x5555); 278 assertSame(mSymbolTextView, t); 279 280 mSymbolTextView.setId(R.id.symbolball); 281 assertEquals(R.id.symbolball, mSymbolTextView.getId()); 282 } 283 284 @UiThreadTest 285 @Test testSetFocus()286 public void testSetFocus() { 287 boolean focusWasOnEditText = mEditText.hasFocus(); 288 289 View.OnFocusChangeListener editListener = mock(View.OnFocusChangeListener.class); 290 View.OnFocusChangeListener okListener = mock(View.OnFocusChangeListener.class); 291 View.OnFocusChangeListener cancelListener = mock(View.OnFocusChangeListener.class); 292 View.OnFocusChangeListener symbolListener = mock(View.OnFocusChangeListener.class); 293 View.OnFocusChangeListener warningListener = mock(View.OnFocusChangeListener.class); 294 295 mEditText.setOnFocusChangeListener(editListener); 296 mButtonOk.setOnFocusChangeListener(okListener); 297 mButtonCancel.setOnFocusChangeListener(cancelListener); 298 mSymbolTextView.setOnFocusChangeListener(symbolListener); 299 mWarningTextView.setOnFocusChangeListener(warningListener); 300 301 mSymbolTextView.setText(ARGENTINA_SYMBOL); 302 mWarningTextView.setVisibility(View.VISIBLE); 303 304 assertTrue(mEditText.requestFocus()); 305 assertTrue(mEditText.hasFocus()); 306 assertFalse(mButtonOk.hasFocus()); 307 assertFalse(mButtonCancel.hasFocus()); 308 assertFalse(mSymbolTextView.hasFocus()); 309 assertFalse(mWarningTextView.hasFocus()); 310 311 if (!focusWasOnEditText) { 312 verify(editListener, times(1)).onFocusChange(mEditText, true); 313 } 314 verifyNoMoreInteractions(okListener); 315 verifyNoMoreInteractions(cancelListener); 316 verifyNoMoreInteractions(symbolListener); 317 verifyNoMoreInteractions(warningListener); 318 319 // exit touch mode and set ok button to focus 320 reset(editListener); 321 assertTrue(mButtonOk.requestFocusFromTouch()); 322 assertTrue(mButtonOk.hasFocus()); 323 verify(okListener, times(1)).onFocusChange(mButtonOk, true); 324 assertFalse(mEditText.hasFocus()); 325 verify(editListener, times(1)).onFocusChange(mEditText, false); 326 verifyNoMoreInteractions(cancelListener); 327 verifyNoMoreInteractions(symbolListener); 328 verifyNoMoreInteractions(warningListener); 329 330 // set cancel button to focus 331 reset(okListener); 332 reset(editListener); 333 assertTrue(mButtonCancel.requestFocus()); 334 assertTrue(mButtonCancel.hasFocus()); 335 verify(cancelListener, times(1)).onFocusChange(mButtonCancel, true); 336 assertFalse(mButtonOk.hasFocus()); 337 verify(okListener, times(1)).onFocusChange(mButtonOk, false); 338 verifyNoMoreInteractions(editListener); 339 verifyNoMoreInteractions(symbolListener); 340 verifyNoMoreInteractions(warningListener); 341 342 // set symbol text to focus 343 mSymbolTextView.setFocusable(true); 344 assertTrue(mSymbolTextView.requestFocus()); 345 assertTrue(mSymbolTextView.hasFocus()); 346 verify(symbolListener, times(1)).onFocusChange(mSymbolTextView, true); 347 assertFalse(mButtonCancel.hasFocus()); 348 verify(cancelListener, times(1)).onFocusChange(mButtonCancel, false); 349 verifyNoMoreInteractions(okListener); 350 verifyNoMoreInteractions(editListener); 351 verifyNoMoreInteractions(warningListener); 352 353 // set warning text to focus 354 mWarningTextView.setFocusable(true); 355 assertTrue(mWarningTextView.requestFocus()); 356 assertTrue(mWarningTextView.hasFocus()); 357 verify(warningListener, times(1)).onFocusChange(mWarningTextView, true); 358 assertFalse(mSymbolTextView.hasFocus()); 359 verify(symbolListener, times(1)).onFocusChange(mSymbolTextView, false); 360 verifyNoMoreInteractions(editListener); 361 verifyNoMoreInteractions(okListener); 362 verifyNoMoreInteractions(cancelListener); 363 364 // set edit text to focus 365 assertTrue(mEditText.requestFocus()); 366 assertTrue(mEditText.hasFocus()); 367 verify(editListener, times(1)).onFocusChange(mEditText, true); 368 assertFalse(mWarningTextView.hasFocus()); 369 verify(warningListener, times(1)).onFocusChange(mWarningTextView, false); 370 verifyNoMoreInteractions(cancelListener); 371 verifyNoMoreInteractions(symbolListener); 372 verifyNoMoreInteractions(okListener); 373 } 374 375 @Test testSetupListeners()376 public void testSetupListeners() throws Throwable { 377 // set ok button OnClick listener 378 mButtonOk.setClickable(true); 379 assertTrue(mButtonOk.isClickable()); 380 381 View.OnClickListener okButtonListener = spy(new MockOnClickOkListener()); 382 mButtonOk.setOnClickListener(okButtonListener); 383 384 // set cancel button OnClick listener 385 mButtonCancel.setClickable(true); 386 assertTrue(mButtonCancel.isClickable()); 387 388 View.OnClickListener cancelButtonListener = mock(View.OnClickListener.class); 389 doAnswer((InvocationOnMock invocation) -> { 390 mEditText.setText(null); 391 return null; 392 }).when(cancelButtonListener).onClick(any(View.class)); 393 mButtonCancel.setOnClickListener(cancelButtonListener); 394 395 // set edit text OnLongClick listener 396 mEditText.setLongClickable(true); 397 assertTrue(mEditText.isLongClickable()); 398 399 final View.OnLongClickListener onLongClickListener = 400 mock(View.OnLongClickListener.class); 401 mEditText.setOnLongClickListener(onLongClickListener); 402 403 // long click the edit text 404 mInstrumentation.waitForIdleSync(); 405 mCtsTouchUtils.emulateLongPressOnViewCenter(mInstrumentation, mActivityRule, mEditText); 406 verify(onLongClickListener, within(1000)).onLongClick(mEditText); 407 408 // Wait for the UI Thread to become idle. 409 final UiDevice device = UiDevice.getInstance(mInstrumentation); 410 411 // click the Cancel button 412 mActivityRule.runOnUiThread(() -> mEditText.setText("Germany")); 413 mInstrumentation.waitForIdleSync(); 414 device.waitForIdle(); 415 416 mCtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mButtonCancel); 417 assertEquals("", mEditText.getText().toString()); 418 419 mInstrumentation.waitForIdleSync(); 420 device.waitForIdle(); 421 422 // click the OK button 423 mActivityRule.runOnUiThread(() -> mEditText.setText(ARGENTINA)); 424 mInstrumentation.waitForIdleSync(); 425 426 mCtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mButtonOk); 427 assertEquals(ARGENTINA_SYMBOL, mSymbolTextView.getText().toString()); 428 429 mActivityRule.runOnUiThread(() -> mEditText.setText(AMERICA)); 430 mInstrumentation.waitForIdleSync(); 431 432 mCtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mButtonOk); 433 assertEquals(AMERICA_SYMBOL, mSymbolTextView.getText().toString()); 434 435 mActivityRule.runOnUiThread(() -> mEditText.setText(CHINA)); 436 mInstrumentation.waitForIdleSync(); 437 438 mCtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mButtonOk); 439 assertEquals(CHINA_SYMBOL, mSymbolTextView.getText().toString()); 440 441 mActivityRule.runOnUiThread(() -> mEditText.setText("Unknown")); 442 mInstrumentation.waitForIdleSync(); 443 444 mCtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mButtonOk); 445 assertEquals(View.VISIBLE, mWarningTextView.getVisibility()); 446 } 447 448 @UiThreadTest 449 @Test testSetVisibility()450 public void testSetVisibility() { 451 mActivity.setContentView(R.layout.view_visibility_layout); 452 453 View v1 = mActivity.findViewById(R.id.textview1); 454 View v2 = mActivity.findViewById(R.id.textview2); 455 View v3 = mActivity.findViewById(R.id.textview3); 456 457 assertNotNull(v1); 458 assertNotNull(v2); 459 assertNotNull(v3); 460 461 assertEquals(View.VISIBLE, v1.getVisibility()); 462 assertEquals(View.INVISIBLE, v2.getVisibility()); 463 assertEquals(View.GONE, v3.getVisibility()); 464 465 v1.setVisibility(View.GONE); 466 assertEquals(View.GONE, v1.getVisibility()); 467 468 v2.setVisibility(View.VISIBLE); 469 assertEquals(View.VISIBLE, v2.getVisibility()); 470 471 v3.setVisibility(View.INVISIBLE); 472 assertEquals(View.INVISIBLE, v3.getVisibility()); 473 } 474 475 protected class MockOnClickOkListener implements OnClickListener { showPicture(String country)476 private boolean showPicture(String country) { 477 if (ARGENTINA.equals(country)) { 478 mSymbolTextView.setText(ARGENTINA_SYMBOL); 479 return true; 480 } else if (AMERICA.equals(country)) { 481 mSymbolTextView.setText(AMERICA_SYMBOL); 482 return true; 483 } else if (CHINA.equals(country)) { 484 mSymbolTextView.setText(CHINA_SYMBOL); 485 return true; 486 } 487 488 return false; 489 } 490 onClick(View v)491 public void onClick(View v) { 492 String country = mEditText.getText().toString(); 493 if (!showPicture(country)) { 494 mWarningTextView.setVisibility(View.VISIBLE); 495 } else if (View.VISIBLE == mWarningTextView.getVisibility()) { 496 mWarningTextView.setVisibility(View.INVISIBLE); 497 } 498 } 499 } 500 } 501