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.RequestRectangleVisible;
21import com.android.frameworks.coretests.R;
22
23import android.test.ActivityInstrumentationTestCase;
24import android.test.suitebuilder.annotation.LargeTest;
25import android.test.suitebuilder.annotation.MediumTest;
26import android.test.ViewAsserts;
27import android.widget.Button;
28import android.widget.ScrollView;
29import android.widget.TextView;
30import android.view.View;
31import android.view.KeyEvent;
32
33/**
34 * {@link RequestRectangleVisible} is set up to exercise the cases of moving a
35 * rectangle that is either off screen or not entirely on the screen onto the screen.
36 */
37@Suppress // Flaky.
38public class RequestRectangleVisibleTest extends ActivityInstrumentationTestCase<RequestRectangleVisible> {
39
40    private ScrollView mScrollView;
41
42    private Button mClickToScrollFromAbove;
43    private Button mClickToScrollToUpperBlob;
44    private TextView mTopBlob;
45
46    private View mChildToScrollTo;
47
48    private TextView mBottomBlob;
49    private Button mClickToScrollToBlobLowerBlob;
50    private Button mClickToScrollFromBelow;
51
52    public RequestRectangleVisibleTest() {
53        super("com.android.frameworks.coretests", RequestRectangleVisible.class);
54    }
55
56    @Override
57    protected void setUp() throws Exception {
58        super.setUp();
59
60        RequestRectangleVisible a = getActivity();
61
62        mScrollView = (ScrollView) a.findViewById(R.id.scrollView);
63        mClickToScrollFromAbove = (Button) a.findViewById(R.id.scrollToRectFromTop);
64        mClickToScrollToUpperBlob = (Button) a.findViewById(R.id.scrollToRectFromTop2);
65        mTopBlob = (TextView) a.findViewById(R.id.topBlob);
66        mChildToScrollTo = a.findViewById(R.id.childToMakeVisible);
67        mBottomBlob = (TextView) a.findViewById(R.id.bottomBlob);
68        mClickToScrollToBlobLowerBlob = (Button) a.findViewById(R.id.scrollToRectFromBottom2);
69        mClickToScrollFromBelow = (Button) a.findViewById(R.id.scrollToRectFromBottom);
70
71
72    }
73
74
75    @MediumTest
76    public void testPreconditions() {
77        assertNotNull(mScrollView);
78        assertNotNull(mClickToScrollFromAbove);
79        assertNotNull(mClickToScrollToUpperBlob);
80        assertNotNull(mTopBlob);
81        assertNotNull(mChildToScrollTo);
82        assertNotNull(mBottomBlob);
83        assertNotNull(mClickToScrollToBlobLowerBlob);
84        assertNotNull(mClickToScrollFromBelow);
85
86        assertTrue("top blob needs to be taller than the screen for many of the "
87                + "tests below to work.",
88                mTopBlob.getHeight() > mScrollView.getHeight());
89
90        assertTrue("bottom blob needs to be taller than the screen for many of the "
91                + "tests below to work.",
92                mBottomBlob.getHeight() > mScrollView.getHeight());
93
94        assertTrue("top blob needs to be lower than the fading edge region",
95                mTopBlob.getTop() > mScrollView.getVerticalFadingEdgeLength());
96    }
97
98    @MediumTest
99    public void testScrollToOffScreenRectangleFromTop() {
100        // view is off screen
101        assertTrue(mClickToScrollFromAbove.hasFocus());
102        ViewAsserts.assertOffScreenBelow(mScrollView, mChildToScrollTo);
103
104        // click
105        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
106        getInstrumentation().waitForIdleSync();  // wait for scrolling to finish
107
108        // should be on screen, positioned at the bottom (with room for
109        // fading edge)
110        ViewAsserts.assertOnScreen(mScrollView, mChildToScrollTo);
111        ViewAsserts.assertHasScreenCoordinates(
112                mScrollView, mChildToScrollTo,
113                0,
114                mScrollView.getHeight()
115                        - mChildToScrollTo.getHeight()
116                        - mScrollView.getVerticalFadingEdgeLength());
117    }
118
119    @MediumTest
120    public void testScrollToPartiallyOffScreenRectFromTop() {
121        pressDownUntilViewInFocus(mClickToScrollToUpperBlob, 4);
122
123        // make sure the blob is indeed partially on screen below
124        assertOnBottomEdgeOfScreen(mScrollView, mTopBlob);
125
126        // click
127        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
128        getInstrumentation().waitForIdleSync();  // wait for scrolling to finish
129
130        // blob should have moved so top of it is at top of screen (with
131        // room for the vertical fading edge
132        ViewAsserts.assertHasScreenCoordinates(
133                mScrollView, mTopBlob, 0, mScrollView.getVerticalFadingEdgeLength());
134    }
135
136    @LargeTest
137    public void testScrollToOffScreenRectangleFromBottom() {
138        // go to bottom button
139        pressDownUntilViewInFocus(mClickToScrollFromBelow, 10);
140
141        // view is off screen above
142        assertTrue(mClickToScrollFromBelow.hasFocus());
143        ViewAsserts.assertOffScreenAbove(mScrollView, mChildToScrollTo);
144
145        // click
146        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
147        getInstrumentation().waitForIdleSync();  // wait for scrolling to finish
148
149        // on screen, positioned at top (with room for fading edge)
150        ViewAsserts.assertOnScreen(mScrollView, mChildToScrollTo);
151        ViewAsserts.assertHasScreenCoordinates(
152                mScrollView, mChildToScrollTo, 0, mScrollView.getVerticalFadingEdgeLength());
153    }
154
155
156    @LargeTest
157    public void testScrollToPartiallyOffScreenRectFromBottom() {
158        pressDownUntilViewInFocus(mClickToScrollToBlobLowerBlob, 10);
159
160        // make sure the blob is indeed partially on screen above
161        assertOnTopEdgeOfScreen(mScrollView, mBottomBlob);
162
163        // click
164        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
165        getInstrumentation().waitForIdleSync();  // wait for scrolling to finish
166
167        // blob should have moved so bottom of it is at bottom of screen
168        // with room for vertical fading edge
169        ViewAsserts.assertHasScreenCoordinates(
170                mScrollView, mBottomBlob,
171                0,
172                mScrollView.getHeight() - mBottomBlob.getHeight()
173                    - mScrollView.getVerticalFadingEdgeLength());
174    }
175
176
177    /**
178     * Press the down key until a particular view is in focus
179     * @param view The view to get in focus.
180     * @param maxKeyPress The maximum times to press down before failing.
181     */
182    private void pressDownUntilViewInFocus(View view, int maxKeyPress) {
183        int count = 0;
184        while(!view.hasFocus()) {
185            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
186            getInstrumentation().waitForIdleSync();
187
188            // just in case...
189            if (++count > maxKeyPress) {
190                fail("couldn't move down to bottom button within "
191                        + maxKeyPress + " key presses.");
192            }
193        }
194    }
195
196    /**
197     * Assert that view overlaps the bottom edge of the screen
198     * @param origin The root view of the screen.
199     * @param view The view
200     */
201    static public void assertOnBottomEdgeOfScreen(View origin, View view) {
202        int[] xy = new int[2];
203        view.getLocationOnScreen(xy);
204
205        int[] xyRoot = new int[2];
206        origin.getLocationOnScreen(xyRoot);
207
208        int bottom = xy[1] + view.getHeight();
209        int bottomOfRoot = xyRoot[1] + origin.getHeight();
210
211        assertTrue(bottom > bottomOfRoot);
212
213        assertTrue(xy[1] < bottomOfRoot);
214        assertTrue(bottom > bottomOfRoot);
215    }
216
217    /**
218     * Assert that view overlaps the bottom edge of the screen
219     * @param origin The root view of the screen.
220     * @param view The view
221     */
222    static public void assertOnTopEdgeOfScreen(View origin, View view) {
223        int[] xy = new int[2];
224        view.getLocationOnScreen(xy);
225
226        int[] xyRoot = new int[2];
227        origin.getLocationOnScreen(xyRoot);
228
229        int bottom = xy[1] + view.getHeight();
230        int bottomOfRoot = xyRoot[1] + origin.getHeight();
231
232        assertTrue(bottom < bottomOfRoot);
233        assertTrue(bottom > xyRoot[1]);
234
235        assertTrue(xy[1] < xyRoot[1]);
236    }
237
238
239}
240