1/*
2 * Copyright (C) 2007 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 android.widget.scroll;
18
19import android.widget.scroll.ScrollViewButtonsAndLabels;
20
21import android.test.ActivityInstrumentationTestCase;
22import android.test.suitebuilder.annotation.LargeTest;
23import android.test.suitebuilder.annotation.MediumTest;
24import android.widget.Button;
25import android.widget.LinearLayout;
26import android.widget.ScrollView;
27import android.view.KeyEvent;
28
29
30public class ScrollViewButtonsAndLabelsTest
31        extends ActivityInstrumentationTestCase<ScrollViewButtonsAndLabels> {
32
33    private ScrollView mScrollView;
34    private LinearLayout mLinearLayout;
35    private int mScreenBottom;
36    private int mScreenTop;
37
38    public ScrollViewButtonsAndLabelsTest() {
39        super("com.android.frameworks.coretests",
40              ScrollViewButtonsAndLabels.class);
41    }
42
43    @Override
44    public void setUp() throws Exception {
45        super.setUp();
46        mScrollView = getActivity().getScrollView();
47        mLinearLayout = getActivity().getLinearLayout();
48
49        int origin[] = {0, 0};
50        mScrollView.getLocationOnScreen(origin);
51        mScreenTop = origin[1];
52        mScreenBottom = origin[1] + mScrollView.getHeight();
53    }
54
55    @MediumTest
56    public void testPreconditions() {
57        assertTrue("vertical fading edge width needs to be non-zero for this "
58                + "test to be worth anything",
59                mScrollView.getVerticalFadingEdgeLength() > 0);
60    }
61
62    // moving down to something off screen should move the element
63    // onto the screen just above the vertical fading edge
64    @LargeTest
65    public void testArrowScrollDownOffScreenVerticalFadingEdge() {
66
67        int offScreenIndex = findFirstButtonOffScreenTop2Bottom();
68        Button firstButtonOffScreen = getActivity().getButton(offScreenIndex);
69
70        for (int i = 0; i < offScreenIndex; i++) {
71            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
72        }
73        getInstrumentation().waitForIdleSync();
74        assertTrue(firstButtonOffScreen.hasFocus());
75
76        assertTrue("the button we've moved to off screen must not be the last "
77                + "button in the scroll view for this test to work (since we "
78                + "are expecting the fading edge to be there).",
79                offScreenIndex < getActivity().getNumButtons());
80
81        // now we are at the first button off screen
82        int buttonLoc[] = {0, 0};
83        firstButtonOffScreen.getLocationOnScreen(buttonLoc);
84        int buttonBottom = buttonLoc[1] + firstButtonOffScreen.getHeight();
85
86        int verticalFadingEdgeLength = mScrollView
87                .getVerticalFadingEdgeLength();
88        assertEquals("bottom of button should be verticalFadingEdgeLength "
89                + "above the bottom of the screen",
90                buttonBottom, mScreenBottom - verticalFadingEdgeLength);
91    }
92
93    // there should be no offset for vertical fading edge
94    // if the item is the last one on screen
95    @LargeTest
96    public void testArrowScrollDownToBottomElementOnScreen() {
97
98        int numGroups = getActivity().getNumButtons();
99        Button lastButton = getActivity().getButton(numGroups - 1);
100
101        assertEquals("button needs to be at the very bottom of the layout for "
102                + "this test to work",
103                mLinearLayout.getHeight(), lastButton.getBottom());
104
105        // move down to last button
106        for (int i = 0; i < numGroups; i++) {
107            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
108        }
109        getInstrumentation().waitForIdleSync();
110        assertTrue("last button should have focus", lastButton.hasFocus());
111
112        int buttonLoc[] = {0, 0};
113        lastButton.getLocationOnScreen(buttonLoc);
114        int buttonBottom = buttonLoc[1] + lastButton.getHeight();
115        assertEquals("button should be at very bottom of screen",
116                mScreenBottom, buttonBottom);
117    }
118
119    @LargeTest
120    public void testArrowScrollUpOffScreenVerticalFadingEdge() {
121        // get to bottom button
122        int numGroups = goToBottomButton();
123
124        // go up to first off screen button
125        int offScreenIndex = findFirstButtonOffScreenBottom2Top();
126        Button offScreenButton = getActivity().getButton(offScreenIndex);
127        int clicksToOffScreenIndex = numGroups - offScreenIndex - 1;
128        for (int i = 0; i < clicksToOffScreenIndex; i++) {
129            sendKeys(KeyEvent.KEYCODE_DPAD_UP);
130        }
131        getInstrumentation().waitForIdleSync();
132        assertTrue("we want to be at offScreenButton", offScreenButton.hasFocus());
133
134        // top should take into account fading edge
135        int buttonLoc[] = {0, 0};
136        offScreenButton.getLocationOnScreen(buttonLoc);
137        assertEquals("top should take into account fading edge",
138            mScreenTop + mScrollView.getVerticalFadingEdgeLength(), buttonLoc[1]);
139    }
140
141
142    @LargeTest
143    public void testArrowScrollUpToTopElementOnScreen() {
144        // get to bottom button
145        int numButtons = goToBottomButton();
146
147        // go back to the top
148        for (int i = 0; i < numButtons; i++) {
149            sendKeys(KeyEvent.KEYCODE_DPAD_UP);
150        }
151        getInstrumentation().waitForIdleSync();
152
153        Button topButton = getActivity().getButton(0);
154        assertTrue("should be back at top button", topButton.hasFocus());
155
156
157        int buttonLoc[] = {0, 0};
158        topButton.getLocationOnScreen(buttonLoc);
159        assertEquals("top of top button should be at top of screen; no need to take"
160                + " into account vertical fading edge.",
161                mScreenTop, buttonLoc[1]);
162    }
163
164    private int goToBottomButton() {
165        int numButtons = getActivity().getNumButtons();
166        Button lastButton = getActivity().getButton(numButtons - 1);
167
168        for (int i = 0; i < numButtons; i++) {
169          sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
170        }
171        getInstrumentation().waitForIdleSync();
172        assertTrue("we want to be at the last button", lastButton.hasFocus());
173        return numButtons;
174    }
175
176    // search from top to bottom for the first button off screen
177    private int findFirstButtonOffScreenTop2Bottom() {
178        int origin[] = {0, 0};
179        mScrollView.getLocationOnScreen(origin);
180        int screenHeight = mScrollView.getHeight();
181
182        for (int i = 0; i < getActivity().getNumButtons(); i++) {
183
184            int buttonLoc[] = {0, 0};
185            Button button = getActivity().getButton(i);
186            button.getLocationOnScreen(buttonLoc);
187
188            if (buttonLoc[1] - origin[1] > screenHeight) {
189                return i;
190            }
191        }
192        fail("couldn't find first button off screen");
193        return -1; // this won't execute, but the compiler needs it
194    }
195
196    private int findFirstButtonOffScreenBottom2Top() {
197        int origin[] = {0, 0};
198        mScrollView.getLocationOnScreen(origin);
199
200        for (int i = getActivity().getNumButtons() - 1; i >= 0; i--) {
201
202            int buttonLoc[] = {0, 0};
203            Button button = getActivity().getButton(i);
204            button.getLocationOnScreen(buttonLoc);
205
206            if (buttonLoc[1] < 0) {
207                return i;
208            }
209        }
210        fail("couldn't find first button off screen");
211        return -1; // this won't execute, but the compiler needs it
212    }
213
214}
215