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