10ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam/* 20ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam * Copyright (C) 2017 The Android Open Source Project 30ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam * 40ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam * Licensed under the Apache License, Version 2.0 (the "License"); 50ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam * you may not use this file except in compliance with the License. 60ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam * You may obtain a copy of the License at 70ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam * 80ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam * http://www.apache.org/licenses/LICENSE-2.0 90ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam * 100ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam * Unless required by applicable law or agreed to in writing, software 110ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam * distributed under the License is distributed on an "AS IS" BASIS, 120ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam * See the License for the specific language governing permissions and 140ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam * limitations under the License. 150ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam */ 160ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 170ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lampackage com.android.setupwizardlib.template; 180ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 190ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport static org.junit.Assert.assertEquals; 200ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport static org.junit.Assert.assertFalse; 210ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport static org.junit.Assert.assertSame; 220ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport static org.junit.Assert.assertTrue; 230ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport static org.mockito.Matchers.any; 240ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport static org.mockito.Matchers.eq; 250ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport static org.mockito.Mockito.doReturn; 260ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport static org.mockito.Mockito.mock; 270ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport static org.mockito.Mockito.never; 280ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport static org.mockito.Mockito.verify; 290ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport static org.mockito.Mockito.verifyNoMoreInteractions; 300ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport static org.robolectric.RuntimeEnvironment.application; 310ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 320ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport android.annotation.SuppressLint; 330ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport android.view.View; 340ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport android.view.View.OnClickListener; 350ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport android.widget.Button; 360ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 370ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport com.android.setupwizardlib.TemplateLayout; 380ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport com.android.setupwizardlib.robolectric.SuwLibRobolectricTestRunner; 390ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport com.android.setupwizardlib.template.RequireScrollMixin.OnRequireScrollStateChangedListener; 400ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport com.android.setupwizardlib.template.RequireScrollMixin.ScrollHandlingDelegate; 410ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport com.android.setupwizardlib.view.NavigationBar; 420ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 430ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport org.junit.Before; 440ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport org.junit.Test; 450ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport org.junit.runner.RunWith; 460ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport org.mockito.Mock; 470ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport org.mockito.MockitoAnnotations; 480ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport org.robolectric.annotation.Config; 490ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 5066815fe66392bcbb12e2fc93bbf326a5c2d8782fMaurice Lam@Config(sdk = { Config.OLDEST_SDK, Config.NEWEST_SDK }) 510ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam@RunWith(SuwLibRobolectricTestRunner.class) 520ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lampublic class RequireScrollMixinTest { 530ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 540ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam @Mock 550ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam private TemplateLayout mTemplateLayout; 560ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 570ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam @Mock 580ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam private ScrollHandlingDelegate mDelegate; 590ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 600ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam private RequireScrollMixin mRequireScrollMixin; 610ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 620ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam @Before 630ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam public void setUp() { 640ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam MockitoAnnotations.initMocks(this); 650ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 660ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam doReturn(application).when(mTemplateLayout).getContext(); 670ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam mRequireScrollMixin = new RequireScrollMixin(mTemplateLayout); 680ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam mRequireScrollMixin.setScrollHandlingDelegate(mDelegate); 690ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam } 700ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 710ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam @Test 720ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam public void testRequireScroll() { 730ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam mRequireScrollMixin.requireScroll(); 740ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 750ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam verify(mDelegate).startListening(); 760ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam } 770ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 780ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam @Test 790ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam public void testScrollStateChangedListener() { 800ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam OnRequireScrollStateChangedListener listener = 810ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam mock(OnRequireScrollStateChangedListener.class); 820ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam mRequireScrollMixin.setOnRequireScrollStateChangedListener(listener); 830ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam assertFalse("Scrolling should not be required initially", 840ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam mRequireScrollMixin.isScrollingRequired()); 850ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 860ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam mRequireScrollMixin.notifyScrollabilityChange(true); 870ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam verify(listener).onRequireScrollStateChanged(true); 880ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam assertTrue("Scrolling should be required when there is more content below the fold", 890ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam mRequireScrollMixin.isScrollingRequired()); 900ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 910ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam mRequireScrollMixin.notifyScrollabilityChange(false); 920ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam verify(listener).onRequireScrollStateChanged(false); 930ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam assertFalse("Scrolling should not be required after scrolling to bottom", 940ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam mRequireScrollMixin.isScrollingRequired()); 950ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 960ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam // Once the user has scrolled to the bottom, they should not be forced to scroll down again 970ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam mRequireScrollMixin.notifyScrollabilityChange(true); 980ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam verifyNoMoreInteractions(listener); 990ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 1000ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam assertFalse("Scrolling should not be required after scrolling to bottom once", 1010ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam mRequireScrollMixin.isScrollingRequired()); 1020ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 1030ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam assertSame(listener, mRequireScrollMixin.getOnRequireScrollStateChangedListener()); 1040ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam } 1050ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 1060ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam @Test 1070ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam public void testCreateOnClickListener() { 1080ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam OnClickListener wrappedListener = mock(OnClickListener.class); 1090ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam final OnClickListener onClickListener = 1100ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam mRequireScrollMixin.createOnClickListener(wrappedListener); 1110ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 1120ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam mRequireScrollMixin.notifyScrollabilityChange(true); 1130ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam onClickListener.onClick(null); 1140ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 1150ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam verify(wrappedListener, never()).onClick(any(View.class)); 1160ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam verify(mDelegate).pageScrollDown(); 1170ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 1180ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam mRequireScrollMixin.notifyScrollabilityChange(false); 1190ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam onClickListener.onClick(null); 1200ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 1210ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam verify(wrappedListener).onClick(any(View.class)); 1220ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam } 1230ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 1240ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam @Test 1250ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam public void testRequireScrollWithNavigationBar() { 1260ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam final NavigationBar navigationBar = new NavigationBar(application); 1270ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam mRequireScrollMixin.requireScrollWithNavigationBar(navigationBar); 1280ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 1290ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam mRequireScrollMixin.notifyScrollabilityChange(true); 1300ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam assertEquals("More button should be visible", 1310ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam View.VISIBLE, navigationBar.getMoreButton().getVisibility()); 1320ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam assertEquals("Next button should be hidden", 1330ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam View.GONE, navigationBar.getNextButton().getVisibility()); 1340ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 1350ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam navigationBar.getMoreButton().performClick(); 1360ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam verify(mDelegate).pageScrollDown(); 1370ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 1380ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam mRequireScrollMixin.notifyScrollabilityChange(false); 1390ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam assertEquals("More button should be hidden", 1400ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam View.GONE, navigationBar.getMoreButton().getVisibility()); 1410ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam assertEquals("Next button should be visible", 1420ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam View.VISIBLE, navigationBar.getNextButton().getVisibility()); 1430ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam } 1440ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 1450ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam @SuppressLint("SetTextI18n") // It's OK for testing 1460ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam @Test 1470ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam public void testRequireScrollWithButton() { 1480ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam final Button button = new Button(application); 1490ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam button.setText("OriginalLabel"); 1500ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam OnClickListener wrappedListener = mock(OnClickListener.class); 1510ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam mRequireScrollMixin.requireScrollWithButton( 1520ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam button, "TestMoreLabel", wrappedListener); 1530ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 1540ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam assertEquals("Button label should be kept initially", "OriginalLabel", button.getText()); 1550ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 1560ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam mRequireScrollMixin.notifyScrollabilityChange(true); 1570ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam assertEquals("TestMoreLabel", button.getText()); 1580ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam button.performClick(); 1590ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam verify(wrappedListener, never()).onClick(eq(button)); 1600ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam verify(mDelegate).pageScrollDown(); 1610ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 1620ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam mRequireScrollMixin.notifyScrollabilityChange(false); 1630ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam assertEquals("OriginalLabel", button.getText()); 1640ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam button.performClick(); 1650ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam verify(wrappedListener).onClick(eq(button)); 1660ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam } 1670ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam} 168