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 17 package android.databinding.testapp; 18 19 import static org.mockito.Matchers.eq; 20 import static org.mockito.Mockito.any; 21 import static org.mockito.Mockito.mock; 22 import static org.mockito.Mockito.never; 23 import static org.mockito.Mockito.times; 24 import static org.mockito.Mockito.verify; 25 import static org.mockito.Mockito.verifyZeroInteractions; 26 import static org.mockito.Mockito.when; 27 28 import android.annotation.TargetApi; 29 import android.databinding.testapp.databinding.CallbacksBinding; 30 import android.databinding.testapp.vo.CallbackBindingObject; 31 import android.databinding.testapp.vo.NotBindableVo; 32 import android.os.Build; 33 import android.support.test.runner.AndroidJUnit4; 34 import android.view.View; 35 import android.widget.ArrayAdapter; 36 37 import org.hamcrest.CoreMatchers; 38 import org.hamcrest.MatcherAssert; 39 import org.junit.Before; 40 import org.junit.Rule; 41 import org.junit.Test; 42 import org.junit.runner.RunWith; 43 44 import java.util.Arrays; 45 import java.util.concurrent.atomic.AtomicInteger; 46 47 @RunWith(AndroidJUnit4.class) 48 public class CallbackTest { 49 @Rule 50 public DataBindingTestRule<CallbacksBinding> mBindingRule = new DataBindingTestRule<>( 51 R.layout.callbacks 52 ); 53 54 CallbackBindingObject mObj; 55 NotBindableVo mOther; 56 CallbacksBinding mBinding; 57 58 @Before 59 public void setup() throws Throwable { 60 mBinding = mBindingRule.getBinding(); 61 mObj = mock(CallbackBindingObject.class); 62 mOther = new NotBindableVo(); 63 mBinding.setObj(mObj); 64 mBinding.setOtherObj(mOther); 65 mBindingRule.executePending(); 66 mBindingRule.runOnUiThread(new Runnable() { 67 @Override 68 public void run() { 69 verifyZeroInteractions(mObj); 70 } 71 }); 72 73 } 74 75 @Test 76 public void testRegularClick() throws Throwable { 77 mBindingRule.runOnUiThread(new Runnable() { 78 @Override 79 public void run() { 80 mBinding.view1.performClick(); 81 verify(mObj, times(1)).onClick(); 82 verify(mObj, never()).onClick(any(View.class)); 83 verify(mObj, never()).onClickWithParam(any(NotBindableVo.class)); 84 verify(mObj, never()).onClickWithParam(any(View.class), any(NotBindableVo.class)); 85 } 86 }); 87 } 88 89 @Test 90 public void testClickWithCallbackArg() throws Throwable { 91 mBindingRule.runOnUiThread(new Runnable() { 92 @Override 93 public void run() { 94 mBinding.view2.performClick(); 95 verify(mObj, never()).onClick(); 96 verify(mObj, times(1)).onClick(mBinding.view2); 97 verify(mObj, never()).onClickWithParam(any(NotBindableVo.class)); 98 verify(mObj, never()).onClickWithParam(any(View.class), any(NotBindableVo.class)); 99 } 100 }); 101 } 102 103 @Test 104 public void testClickWithAnotherVariableAsArg() throws Throwable { 105 mBindingRule.runOnUiThread(new Runnable() { 106 @Override 107 public void run() { 108 mBinding.view3.performClick(); 109 verify(mObj, never()).onClick(); 110 verify(mObj, never()).onClick(any(View.class)); 111 verify(mObj, times(1)).onClickWithParam(eq(mOther)); 112 verify(mObj, never()).onClickWithParam(any(View.class), any(NotBindableVo.class)); 113 } 114 }); 115 } 116 117 @Test 118 public void testClickWithViewAndAnotherVariableAsArgs() throws Throwable { 119 mBindingRule.runOnUiThread(new Runnable() { 120 @Override 121 public void run() { 122 mBinding.view4.performClick(); 123 verify(mObj, never()).onClick(); 124 verify(mObj, never()).onClick(any(View.class)); 125 verify(mObj, never()).onClickWithParam(any(NotBindableVo.class)); 126 verify(mObj, times(1)).onClickWithParam(mBinding.view4, mOther); 127 } 128 }); 129 } 130 131 @Test 132 public void nullObjectInCallback() throws Throwable { 133 mBinding.setObj(null); 134 mBindingRule.executePending(); 135 mBindingRule.runOnUiThread(new Runnable() { 136 @Override 137 public void run() { 138 mBinding.view1.performClick(); 139 mBinding.view2.performClick(); 140 mBinding.view3.performClick(); 141 mBinding.view4.performClick(); 142 143 MatcherAssert.assertThat(mBinding.view1.performLongClick(), CoreMatchers.is(false)); 144 MatcherAssert.assertThat(mBinding.view2.performLongClick(), CoreMatchers.is(false)); 145 MatcherAssert.assertThat(mBinding.view3.performLongClick(), CoreMatchers.is(false)); 146 MatcherAssert.assertThat(mBinding.view4.performLongClick(), CoreMatchers.is(false)); 147 148 } 149 }); 150 verifyZeroInteractions(mObj); 151 } 152 153 // long click 154 @Test 155 public void testRegularLongClick() throws Throwable { 156 mBindingRule.runOnUiThread(new Runnable() { 157 @Override 158 public void run() { 159 when(mObj.onLongClick()).thenReturn(true); 160 MatcherAssert.assertThat(mBinding.view1.performLongClick(), CoreMatchers.is(true)); 161 verify(mObj, times(1)).onLongClick(); 162 verify(mObj, never()).onLongClick(any(View.class)); 163 verify(mObj, never()).onLongClickWithParam(any(NotBindableVo.class)); 164 verify(mObj, never()).onLongClickWithParam(any(View.class), any(NotBindableVo 165 .class)); 166 } 167 }); 168 } 169 170 @Test 171 public void testLongClickWithCallbackArg() throws Throwable { 172 mBindingRule.runOnUiThread(new Runnable() { 173 @Override 174 public void run() { 175 when(mObj.onLongClick(mBinding.view2)).thenReturn(true); 176 MatcherAssert.assertThat(mBinding.view2.performLongClick(), CoreMatchers.is(true)); 177 verify(mObj, never()).onLongClick(); 178 verify(mObj, times(1)).onLongClick(mBinding.view2); 179 verify(mObj, never()).onLongClickWithParam(any(NotBindableVo.class)); 180 verify(mObj, never()).onLongClickWithParam(any(View.class), any(NotBindableVo 181 .class)); 182 } 183 }); 184 } 185 186 @Test 187 public void testLongClickWithAnotherVariableAsArg() throws Throwable { 188 mBindingRule.runOnUiThread(new Runnable() { 189 @Override 190 public void run() { 191 when(mObj.onLongClickWithParam(mOther)).thenReturn(true); 192 MatcherAssert.assertThat(mBinding.view3.performLongClick(), CoreMatchers.is(true)); 193 verify(mObj, never()).onLongClick(); 194 verify(mObj, never()).onLongClick(any(View.class)); 195 verify(mObj, times(1)).onLongClickWithParam(mOther); 196 verify(mObj, never()).onLongClickWithParam(any(View.class), any(NotBindableVo 197 .class)); 198 } 199 }); 200 } 201 202 @Test 203 public void testLongClickWithViewAndAnotherVariableAsArgs() throws Throwable { 204 mBindingRule.runOnUiThread(new Runnable() { 205 @Override 206 public void run() { 207 when(mObj.onLongClickWithParam(mBinding.view4, mOther)).thenReturn(true); 208 MatcherAssert.assertThat(mBinding.view4.performLongClick(), CoreMatchers.is(true)); 209 verify(mObj, never()).onLongClick(); 210 verify(mObj, never()).onLongClick(any(View.class)); 211 verify(mObj, never()).onLongClickWithParam(any(NotBindableVo.class)); 212 verify(mObj, times(1)).onLongClickWithParam(mBinding.view4, mOther); 213 } 214 }); 215 } 216 217 @Test 218 public void testListViewOnScroll() throws Throwable { 219 final CallbackBindingObject obj2 = mock(CallbackBindingObject.class); 220 mBinding.setObj2(obj2); 221 mBindingRule.executePending(); 222 mBindingRule.runOnUiThread(new Runnable() { 223 @Override 224 public void run() { 225 // this is going to trigger scroll 226 mBinding.listView.setAdapter(new ArrayAdapter<>(mBinding.listView.getContext(), 227 android.R.layout.simple_list_item_1, Arrays.asList("a", "b"))); 228 } 229 }); 230 mBindingRule.runOnUiThread(new Runnable() { 231 @TargetApi(Build.VERSION_CODES.KITKAT) 232 @Override 233 public void run() { 234 // setting listener also calls the callback 235 verify(obj2).onScrolled(); 236 } 237 }); 238 } 239 240 @Test 241 public void testProgressChange() throws Throwable { 242 mBindingRule.runOnUiThread(new Runnable() { 243 @Override 244 public void run() { 245 mBinding.seekBar.setProgress(20); 246 verify(mObj, times(1)).onProgressChanged(mBinding.seekBar, 20, false); 247 } 248 }); 249 } 250 251 @Test 252 public void testStaticCallViaClass() throws Throwable { 253 staticCall(mBinding.view5); 254 } 255 256 @Test 257 public void testStaticCallViaInstance() throws Throwable { 258 staticCall(mBinding.view6); 259 } 260 261 @Test 262 public void testVariableOverride() throws Throwable { 263 mBindingRule.runOnUiThread(new Runnable() { 264 @Override 265 public void run() { 266 mBinding.view8.performClick(); 267 verify(mObj).onClick(mBinding.view8); 268 } 269 }); 270 } 271 272 @Test 273 public void testArrayAccess() throws Throwable { 274 final CallbackBindingObject[] objects = new CallbackBindingObject[] { 275 mock(CallbackBindingObject.class), 276 mock(CallbackBindingObject.class), 277 mock(CallbackBindingObject.class), 278 }; 279 mBinding.setObjArr(objects); 280 mBindingRule.executePending(); 281 mBindingRule.runOnUiThread(new Runnable() { 282 @Override 283 public void run() { 284 verifyZeroInteractions(objects); 285 mBinding.view7.performClick(); 286 verify(objects[1]).onClick(mBinding.view7); 287 mBinding.view7.performLongClick(); 288 verify(objects[2]).onLongClick(mBinding.view7); 289 verifyZeroInteractions(objects[0]); 290 } 291 }); 292 } 293 294 @Test 295 public void testStaticVariableFullPackage() throws Throwable { 296 mBindingRule.runOnUiThread(new Runnable() { 297 @Override 298 public void run() { 299 mBinding.view9.performClick(); 300 verify(mObj).setVisible(View.VISIBLE); 301 } 302 }); 303 } 304 305 @Test 306 public void testStaticVariableImported() throws Throwable { 307 mBindingRule.runOnUiThread(new Runnable() { 308 @Override 309 public void run() { 310 mBinding.view10.performClick(); 311 verify(mObj).setVisible(NotBindableVo.STATIC_VAL); 312 } 313 }); 314 } 315 316 @Test 317 public void testTernary1() throws Throwable { 318 mBindingRule.runOnUiThread(new Runnable() { 319 @Override 320 public void run() { 321 mBinding.view11.setFocusable(false); 322 mBinding.view11.performClick(); 323 verify(mObj).onNotFocusable(); 324 verify(mObj, never()).onFocusable(); 325 } 326 }); 327 } 328 329 @Test 330 public void testTernary2() throws Throwable { 331 mBindingRule.runOnUiThread(new Runnable() { 332 @Override 333 public void run() { 334 mBinding.view11.setFocusable(true); 335 mBinding.view11.performClick(); 336 verify(mObj).onFocusable(); 337 verify(mObj, never()).onNotFocusable(); 338 } 339 }); 340 } 341 342 @Test 343 public void testTernary3() throws Throwable { 344 mBindingRule.runOnUiThread(new Runnable() { 345 @Override 346 public void run() { 347 mBinding.view11.setFocusable(false); 348 when(mObj.onFocusable()).thenReturn(true, false); 349 when(mObj.onNotFocusable()).thenReturn(false, true); 350 MatcherAssert.assertThat(mBinding.view11.performLongClick(), CoreMatchers.is(false)); 351 MatcherAssert.assertThat(mBinding.view11.performLongClick(), CoreMatchers.is(true)); 352 mBinding.view11.setFocusable(true); 353 MatcherAssert.assertThat(mBinding.view11.performLongClick(), CoreMatchers.is(true)); 354 MatcherAssert.assertThat(mBinding.view11.performLongClick(), CoreMatchers.is(false)); 355 } 356 }); 357 } 358 359 @Test 360 public void testTernary4() throws Throwable { 361 mBindingRule.runOnUiThread(new Runnable() { 362 @Override 363 public void run() { 364 mBinding.view11.setFocusable(true); 365 mBinding.view11.performClick(); 366 verify(mObj).onFocusable(); 367 verify(mObj, never()).onNotFocusable(); 368 } 369 }); 370 } 371 372 private void staticCall(final View view) throws Throwable { 373 final AtomicInteger counter = NotBindableVo.sStaticCounter; 374 final int start = counter.get(); 375 mBindingRule.runOnUiThread(new Runnable() { 376 @Override 377 public void run() { 378 view.performClick(); 379 MatcherAssert.assertThat(counter.get(), CoreMatchers.is(start + 1)); 380 MatcherAssert.assertThat(view.performLongClick(), CoreMatchers.is(true)); 381 MatcherAssert.assertThat(counter.get(), CoreMatchers.is(start + 2)); 382 } 383 }); 384 } 385 } 386