1841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang/* 2841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang * Copyright (C) 2017 The Android Open Source Project 3841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang * 4841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang * Licensed under the Apache License, Version 2.0 (the "License"); 5841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang * you may not use this file except in compliance with the License. 6841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang * You may obtain a copy of the License at 7841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang * 8841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang * http://www.apache.org/licenses/LICENSE-2.0 9841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang * 10841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang * Unless required by applicable law or agreed to in writing, software 11841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang * distributed under the License is distributed on an "AS IS" BASIS, 12841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang * See the License for the specific language governing permissions and 14841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang * limitations under the License. 15841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang */ 16841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang 17841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhangpackage com.android.settings.widget; 18841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang 19841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang 20e651ddf9e6c00a62338ef8c7114b5e5e9cd307ecFan Zhangimport static com.google.common.truth.Truth.assertThat; 21e651ddf9e6c00a62338ef8c7114b5e5e9cd307ecFan Zhangimport static org.mockito.Matchers.any; 22e651ddf9e6c00a62338ef8c7114b5e5e9cd307ecFan Zhangimport static org.mockito.Mockito.times; 23e651ddf9e6c00a62338ef8c7114b5e5e9cd307ecFan Zhangimport static org.mockito.Mockito.verify; 24e651ddf9e6c00a62338ef8c7114b5e5e9cd307ecFan Zhangimport static org.mockito.Mockito.when; 25e651ddf9e6c00a62338ef8c7114b5e5e9cd307ecFan Zhang 26841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhangimport android.app.ActionBar; 27841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhangimport android.app.Activity; 28841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhangimport android.support.v7.widget.RecyclerView; 29e651ddf9e6c00a62338ef8c7114b5e5e9cd307ecFan Zhangimport android.view.View; 30841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang 31841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhangimport com.android.settings.TestConfig; 32e651ddf9e6c00a62338ef8c7114b5e5e9cd307ecFan Zhangimport com.android.settings.testutils.SettingsRobolectricTestRunner; 33841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhangimport com.android.settingslib.core.lifecycle.Lifecycle; 34841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhangimport com.android.settingslib.core.lifecycle.LifecycleObserver; 35841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang 36841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhangimport org.junit.Before; 37841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhangimport org.junit.Test; 38841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhangimport org.junit.runner.RunWith; 39841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhangimport org.mockito.Mock; 40841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhangimport org.mockito.MockitoAnnotations; 41e651ddf9e6c00a62338ef8c7114b5e5e9cd307ecFan Zhangimport org.robolectric.RuntimeEnvironment; 42841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhangimport org.robolectric.annotation.Config; 43841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhangimport org.robolectric.util.ReflectionHelpers; 44841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang 45841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhangimport java.util.List; 46841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang 47841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang@RunWith(SettingsRobolectricTestRunner.class) 48841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) 49841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhangpublic class ActionBarShadowControllerTest { 50841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang 51841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang @Mock 52841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang private RecyclerView mRecyclerView; 53841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang @Mock 54841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang private Activity mActivity; 55841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang @Mock 56841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang private ActionBar mActionBar; 57841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang private Lifecycle mLifecycle; 58e651ddf9e6c00a62338ef8c7114b5e5e9cd307ecFan Zhang private View mView; 59841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang 60841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang @Before 61841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang public void setUp() { 62841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang MockitoAnnotations.initMocks(this); 63841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang when(mActivity.getActionBar()).thenReturn(mActionBar); 64e651ddf9e6c00a62338ef8c7114b5e5e9cd307ecFan Zhang mView = new View(RuntimeEnvironment.application); 65841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang mLifecycle = new Lifecycle(); 66841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang } 67841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang 68841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang @Test 69841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang public void attachToRecyclerView_shouldAddScrollWatcherAndUpdateActionBar() { 70841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang when(mRecyclerView.canScrollVertically(-1)).thenReturn(false); 71841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang 72841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang ActionBarShadowController.attachToRecyclerView(mActivity, mLifecycle, mRecyclerView); 73841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang 74e651ddf9e6c00a62338ef8c7114b5e5e9cd307ecFan Zhang verify(mActionBar).setElevation(ActionBarShadowController.ELEVATION_LOW); 75841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang } 76841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang 77e651ddf9e6c00a62338ef8c7114b5e5e9cd307ecFan Zhang @Test 78e651ddf9e6c00a62338ef8c7114b5e5e9cd307ecFan Zhang public void attachToRecyclerView_customViewAsActionBar_shouldUpdateElevationOnScroll() { 79e651ddf9e6c00a62338ef8c7114b5e5e9cd307ecFan Zhang // Setup 80e651ddf9e6c00a62338ef8c7114b5e5e9cd307ecFan Zhang mView.setElevation(50); 81e651ddf9e6c00a62338ef8c7114b5e5e9cd307ecFan Zhang when(mRecyclerView.canScrollVertically(-1)).thenReturn(false); 82e651ddf9e6c00a62338ef8c7114b5e5e9cd307ecFan Zhang final ActionBarShadowController controller = 83e651ddf9e6c00a62338ef8c7114b5e5e9cd307ecFan Zhang ActionBarShadowController.attachToRecyclerView(mView, mLifecycle, mRecyclerView); 84e651ddf9e6c00a62338ef8c7114b5e5e9cd307ecFan Zhang assertThat(mView.getElevation()).isEqualTo(ActionBarShadowController.ELEVATION_LOW); 85e651ddf9e6c00a62338ef8c7114b5e5e9cd307ecFan Zhang 86e651ddf9e6c00a62338ef8c7114b5e5e9cd307ecFan Zhang // Scroll 87e651ddf9e6c00a62338ef8c7114b5e5e9cd307ecFan Zhang when(mRecyclerView.canScrollVertically(-1)).thenReturn(true); 88e651ddf9e6c00a62338ef8c7114b5e5e9cd307ecFan Zhang controller.mScrollChangeWatcher.onScrolled(mRecyclerView, 10 /* dx */, 10 /* dy */); 89e651ddf9e6c00a62338ef8c7114b5e5e9cd307ecFan Zhang assertThat(mView.getElevation()).isEqualTo(ActionBarShadowController.ELEVATION_HIGH); 90e651ddf9e6c00a62338ef8c7114b5e5e9cd307ecFan Zhang } 91841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang 92841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang @Test 93841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang public void attachToRecyclerView_lifecycleChange_shouldAttachDetach() { 94841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang ActionBarShadowController.attachToRecyclerView(mActivity, mLifecycle, mRecyclerView); 95841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang 96841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang List<LifecycleObserver> observers = ReflectionHelpers.getField(mLifecycle, "mObservers"); 97841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang assertThat(observers).hasSize(1); 98841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang verify(mRecyclerView).addOnScrollListener(any()); 99841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang 100841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang mLifecycle.onStop(); 101841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang verify(mRecyclerView).removeOnScrollListener(any()); 102841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang 103841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang mLifecycle.onStart(); 104841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang verify(mRecyclerView, times(2)).addOnScrollListener(any()); 105841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang } 106841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang 107d53a3128e8107569636da407d7cb75e458e22779Doris Ling @Test 108d53a3128e8107569636da407d7cb75e458e22779Doris Ling public void onScrolled_nullAnchorViewAndActivity_shouldNotCrash() { 109d53a3128e8107569636da407d7cb75e458e22779Doris Ling final Activity activity = null; 110d53a3128e8107569636da407d7cb75e458e22779Doris Ling final ActionBarShadowController controller = 111d53a3128e8107569636da407d7cb75e458e22779Doris Ling ActionBarShadowController.attachToRecyclerView(activity, mLifecycle, mRecyclerView); 112d53a3128e8107569636da407d7cb75e458e22779Doris Ling 113d53a3128e8107569636da407d7cb75e458e22779Doris Ling // Scroll 114d53a3128e8107569636da407d7cb75e458e22779Doris Ling controller.mScrollChangeWatcher.onScrolled(mRecyclerView, 10 /* dx */, 10 /* dy */); 115d53a3128e8107569636da407d7cb75e458e22779Doris Ling // no crash 116d53a3128e8107569636da407d7cb75e458e22779Doris Ling } 117d53a3128e8107569636da407d7cb75e458e22779Doris Ling 118841d1d5aabc33024b2e03276085b0d1dbdb92b23Fan Zhang} 119