1/*
2 * Copyright (C) 2008 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;
18
19import android.app.Instrumentation;
20import android.test.ActivityInstrumentationTestCase2;
21import android.test.FlakyTest;
22import android.test.suitebuilder.annotation.MediumTest;
23
24/**
25 * A collection of tests on aspects of the AutoCompleteTextView's popup
26 *
27 * TODO: tests fail intermittently. Add back MediumTest annotation when fixed
28 */
29public class AutoCompleteTextViewPopup
30        extends ActivityInstrumentationTestCase2<AutoCompleteTextViewSimple> {
31
32    // ms to sleep when checking for intermittent UI state
33    private static final int SLEEP_TIME = 50;
34    // number of times to poll when checking expected UI state
35    // total wait time will be LOOP_AMOUNT * SLEEP_TIME
36    private static final int LOOP_AMOUNT = 10;
37
38
39    public AutoCompleteTextViewPopup() {
40        super("com.android.frameworks.coretests", AutoCompleteTextViewSimple.class);
41    }
42
43    /** Test that we can move the selection and it responds as expected */
44    @FlakyTest(tolerance=3)
45    public void testPopupSetListSelection() throws Throwable {
46        AutoCompleteTextViewSimple theActivity = getActivity();
47        final AutoCompleteTextView textView = theActivity.getTextView();
48        final Instrumentation instrumentation = getInstrumentation();
49
50        // focus and type
51        textView.requestFocus();
52        instrumentation.waitForIdleSync();
53        sendKeys("A");
54
55        // No initial selection
56        waitAssertListSelection(textView, ListView.INVALID_POSITION);
57
58        // set and check
59        runTestOnUiThread(new Runnable() {
60            public void run() {
61                textView.setListSelection(0);
62            }
63        });
64        instrumentation.waitForIdleSync();
65        waitAssertListSelection("set selection to (0)", textView, 0);
66
67        // Use movement to cross-check the movement
68        sendKeys("DPAD_DOWN");
69        waitAssertListSelection("move selection to (1)", textView, 1);
70
71        // TODO: FlakyTest repeat runs will not currently call setUp, clear state
72        clearText(textView);
73    }
74
75    /** Test that we can look at the selection as we move around */
76    @FlakyTest(tolerance=3)
77    public void testPopupGetListSelection() throws Throwable {
78        AutoCompleteTextViewSimple theActivity = getActivity();
79        final AutoCompleteTextView textView = theActivity.getTextView();
80        final Instrumentation instrumentation = getInstrumentation();
81
82        // focus and type
83        textView.requestFocus();
84        instrumentation.waitForIdleSync();
85        sendKeys("A");
86
87        // No initial selection
88        waitAssertListSelection(textView, ListView.INVALID_POSITION);
89
90        // check for selection position as expected
91        sendKeys("DPAD_DOWN");
92        waitAssertListSelection("move selection to (0)", textView, 0);
93
94        // Repeat for one more movement
95        sendKeys("DPAD_DOWN");
96        waitAssertListSelection("move selection to (1)", textView, 1);
97
98        // TODO: FlakyTest repeat runs will not currently call setUp, clear state
99        clearText(textView);
100    }
101
102    /** Test that we can clear the selection */
103    @FlakyTest(tolerance=3)
104    public void testPopupClearListSelection() throws Throwable {
105        AutoCompleteTextViewSimple theActivity = getActivity();
106        final AutoCompleteTextView textView = theActivity.getTextView();
107        final Instrumentation instrumentation = getInstrumentation();
108
109        // focus and type
110        textView.requestFocus();
111        instrumentation.waitForIdleSync();
112        sendKeys("A");
113
114        // No initial selection
115        waitAssertListSelection(textView, ListView.INVALID_POSITION);
116
117        // check for selection position as expected
118        sendKeys("DPAD_DOWN");
119        waitAssertListSelection(textView, 0);
120
121        // clear it
122        runTestOnUiThread(new Runnable() {
123            public void run() {
124                textView.clearListSelection();
125            }
126        });
127        instrumentation.waitForIdleSync();
128        waitAssertListSelection("setListSelection(ListView.INVALID_POSITION)", textView,
129                ListView.INVALID_POSITION);
130
131        // TODO: FlakyTest repeat runs will not currently call setUp, clear state
132        clearText(textView);
133    }
134
135    /** Make sure we handle an empty adapter properly */
136    @FlakyTest(tolerance=3)
137    public void testPopupNavigateNoAdapter() throws Throwable {
138        AutoCompleteTextViewSimple theActivity = getActivity();
139        final AutoCompleteTextView textView = theActivity.getTextView();
140        final Instrumentation instrumentation = getInstrumentation();
141
142        // focus and type
143        textView.requestFocus();
144        instrumentation.waitForIdleSync();
145        sendKeys("A");
146
147        // No initial selection
148         waitAssertListSelection(textView, ListView.INVALID_POSITION);
149
150        // check for selection position as expected
151        sendKeys("DPAD_DOWN");
152        waitAssertListSelection(textView, 0);
153
154        // Now get rid of the adapter
155        runTestOnUiThread(new Runnable() {
156            public void run() {
157                textView.setAdapter((ArrayAdapter<?>) null);
158            }
159        });
160        instrumentation.waitForIdleSync();
161
162        // now try moving "down" - nothing should happen since there's no longer an adapter
163        sendKeys("DPAD_DOWN");
164
165        // TODO: FlakyTest repeat runs will not currently call setUp, clear state
166        clearText(textView);
167    }
168
169    /** Test the show/hide behavior of the drop-down. */
170    @FlakyTest(tolerance=3)
171    public void testPopupShow() throws Throwable {
172        AutoCompleteTextViewSimple theActivity = getActivity();
173        final AutoCompleteTextView textView = theActivity.getTextView();
174        final Instrumentation instrumentation = getInstrumentation();
175
176        // Drop-down should not be showing when no text has been entered
177        assertFalse("isPopupShowing() on start", textView.isPopupShowing());
178
179        // focus and type
180        textView.requestFocus();
181        instrumentation.waitForIdleSync();
182        sendKeys("A");
183
184        // Drop-down should now be visible
185        waitAssertPopupShowState("isPopupShowing() after typing", textView, true);
186
187        // Clear the text
188        runTestOnUiThread(new Runnable() {
189            public void run() {
190                textView.setText("");
191            }
192        });
193        instrumentation.waitForIdleSync();
194
195        // Drop-down should be hidden when text is cleared
196        waitAssertPopupShowState("isPopupShowing() after text cleared", textView, false);
197
198        // Set the text, without filtering
199        runTestOnUiThread(new Runnable() {
200            public void run() {
201                textView.setText("a", false);
202            }
203        });
204        instrumentation.waitForIdleSync();
205
206        // Drop-down should still be hidden
207        waitAssertPopupShowState("isPopupShowing() after setText(\"a\", false)", textView, false);
208
209        // Set the text, now with filtering
210        runTestOnUiThread(new Runnable() {
211            public void run() {
212                textView.setText("a");
213            }
214        });
215        instrumentation.waitForIdleSync();
216
217        // Drop-down should show up after setText() with filtering
218        waitAssertPopupShowState("isPopupShowing() after text set", textView, true);
219
220        // TODO: FlakyTest repeat runs will not currently call setUp, clear state
221        clearText(textView);
222    }
223
224    private void waitAssertPopupShowState(String message, AutoCompleteTextView textView,
225            boolean expected) throws InterruptedException {
226        for (int i = 0; i < LOOP_AMOUNT; i++) {
227            if (textView.isPopupShowing() == expected) {
228                return;
229            }
230            Thread.sleep(SLEEP_TIME);
231        }
232        assertEquals(message, expected, textView.isPopupShowing());
233    }
234
235    private void waitAssertListSelection(AutoCompleteTextView textView, int expected)
236            throws Exception {
237        waitAssertListSelection("getListSelection()", textView, expected);
238    }
239
240    private void waitAssertListSelection(String message, AutoCompleteTextView textView,
241            int expected) throws Exception {
242        int currentSelection = ListView.INVALID_POSITION;
243        for (int i = 0; i < LOOP_AMOUNT; i++) {
244            currentSelection = textView.getListSelection();
245            if (expected == currentSelection) {
246                return;
247            }
248            Thread.sleep(SLEEP_TIME);
249        }
250        assertEquals(message, expected, textView.getListSelection());
251    }
252
253    private void clearText(final AutoCompleteTextView textView) throws Throwable {
254        runTestOnUiThread(new Runnable() {
255            public void run() {
256                textView.setText("");
257            }
258        });
259    }
260}
261