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