1/* 2 * Copyright (C) 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 com.android.setupwizardlib.template; 18 19import static org.junit.Assert.assertEquals; 20import static org.junit.Assert.assertFalse; 21import static org.junit.Assert.assertSame; 22import static org.junit.Assert.assertTrue; 23import static org.mockito.Matchers.any; 24import static org.mockito.Matchers.eq; 25import static org.mockito.Mockito.doReturn; 26import static org.mockito.Mockito.mock; 27import static org.mockito.Mockito.never; 28import static org.mockito.Mockito.verify; 29import static org.mockito.Mockito.verifyNoMoreInteractions; 30import static org.robolectric.RuntimeEnvironment.application; 31 32import android.annotation.SuppressLint; 33import android.view.View; 34import android.view.View.OnClickListener; 35import android.widget.Button; 36 37import com.android.setupwizardlib.BuildConfig; 38import com.android.setupwizardlib.TemplateLayout; 39import com.android.setupwizardlib.robolectric.SuwLibRobolectricTestRunner; 40import com.android.setupwizardlib.template.RequireScrollMixin.OnRequireScrollStateChangedListener; 41import com.android.setupwizardlib.template.RequireScrollMixin.ScrollHandlingDelegate; 42import com.android.setupwizardlib.view.NavigationBar; 43 44import org.junit.Before; 45import org.junit.Test; 46import org.junit.runner.RunWith; 47import org.mockito.Mock; 48import org.mockito.MockitoAnnotations; 49import org.robolectric.annotation.Config; 50 51@Config(constants = BuildConfig.class, sdk = { Config.OLDEST_SDK, Config.NEWEST_SDK }) 52@RunWith(SuwLibRobolectricTestRunner.class) 53public class RequireScrollMixinTest { 54 55 @Mock 56 private TemplateLayout mTemplateLayout; 57 58 @Mock 59 private ScrollHandlingDelegate mDelegate; 60 61 private RequireScrollMixin mRequireScrollMixin; 62 63 @Before 64 public void setUp() { 65 MockitoAnnotations.initMocks(this); 66 67 doReturn(application).when(mTemplateLayout).getContext(); 68 mRequireScrollMixin = new RequireScrollMixin(mTemplateLayout); 69 mRequireScrollMixin.setScrollHandlingDelegate(mDelegate); 70 } 71 72 @Test 73 public void testRequireScroll() { 74 mRequireScrollMixin.requireScroll(); 75 76 verify(mDelegate).startListening(); 77 } 78 79 @Test 80 public void testScrollStateChangedListener() { 81 OnRequireScrollStateChangedListener listener = 82 mock(OnRequireScrollStateChangedListener.class); 83 mRequireScrollMixin.setOnRequireScrollStateChangedListener(listener); 84 assertFalse("Scrolling should not be required initially", 85 mRequireScrollMixin.isScrollingRequired()); 86 87 mRequireScrollMixin.notifyScrollabilityChange(true); 88 verify(listener).onRequireScrollStateChanged(true); 89 assertTrue("Scrolling should be required when there is more content below the fold", 90 mRequireScrollMixin.isScrollingRequired()); 91 92 mRequireScrollMixin.notifyScrollabilityChange(false); 93 verify(listener).onRequireScrollStateChanged(false); 94 assertFalse("Scrolling should not be required after scrolling to bottom", 95 mRequireScrollMixin.isScrollingRequired()); 96 97 // Once the user has scrolled to the bottom, they should not be forced to scroll down again 98 mRequireScrollMixin.notifyScrollabilityChange(true); 99 verifyNoMoreInteractions(listener); 100 101 assertFalse("Scrolling should not be required after scrolling to bottom once", 102 mRequireScrollMixin.isScrollingRequired()); 103 104 assertSame(listener, mRequireScrollMixin.getOnRequireScrollStateChangedListener()); 105 } 106 107 @Test 108 public void testCreateOnClickListener() { 109 OnClickListener wrappedListener = mock(OnClickListener.class); 110 final OnClickListener onClickListener = 111 mRequireScrollMixin.createOnClickListener(wrappedListener); 112 113 mRequireScrollMixin.notifyScrollabilityChange(true); 114 onClickListener.onClick(null); 115 116 verify(wrappedListener, never()).onClick(any(View.class)); 117 verify(mDelegate).pageScrollDown(); 118 119 mRequireScrollMixin.notifyScrollabilityChange(false); 120 onClickListener.onClick(null); 121 122 verify(wrappedListener).onClick(any(View.class)); 123 } 124 125 @Test 126 public void testRequireScrollWithNavigationBar() { 127 final NavigationBar navigationBar = new NavigationBar(application); 128 mRequireScrollMixin.requireScrollWithNavigationBar(navigationBar); 129 130 mRequireScrollMixin.notifyScrollabilityChange(true); 131 assertEquals("More button should be visible", 132 View.VISIBLE, navigationBar.getMoreButton().getVisibility()); 133 assertEquals("Next button should be hidden", 134 View.GONE, navigationBar.getNextButton().getVisibility()); 135 136 navigationBar.getMoreButton().performClick(); 137 verify(mDelegate).pageScrollDown(); 138 139 mRequireScrollMixin.notifyScrollabilityChange(false); 140 assertEquals("More button should be hidden", 141 View.GONE, navigationBar.getMoreButton().getVisibility()); 142 assertEquals("Next button should be visible", 143 View.VISIBLE, navigationBar.getNextButton().getVisibility()); 144 } 145 146 @SuppressLint("SetTextI18n") // It's OK for testing 147 @Test 148 public void testRequireScrollWithButton() { 149 final Button button = new Button(application); 150 button.setText("OriginalLabel"); 151 OnClickListener wrappedListener = mock(OnClickListener.class); 152 mRequireScrollMixin.requireScrollWithButton( 153 button, "TestMoreLabel", wrappedListener); 154 155 assertEquals("Button label should be kept initially", "OriginalLabel", button.getText()); 156 157 mRequireScrollMixin.notifyScrollabilityChange(true); 158 assertEquals("TestMoreLabel", button.getText()); 159 button.performClick(); 160 verify(wrappedListener, never()).onClick(eq(button)); 161 verify(mDelegate).pageScrollDown(); 162 163 mRequireScrollMixin.notifyScrollabilityChange(false); 164 assertEquals("OriginalLabel", button.getText()); 165 button.performClick(); 166 verify(wrappedListener).onClick(eq(button)); 167 } 168} 169