Home | History | Annotate | Download | only in focus
      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 
     17 package android.widget.focus;
     18 
     19 import static org.mockito.Mockito.inOrder;
     20 import static org.mockito.Mockito.mock;
     21 
     22 import android.os.Handler;
     23 import android.test.ActivityInstrumentationTestCase2;
     24 import android.test.UiThreadTest;
     25 import android.test.suitebuilder.annotation.LargeTest;
     26 import android.test.suitebuilder.annotation.MediumTest;
     27 import android.util.AndroidRuntimeException;
     28 import android.view.View;
     29 import android.view.View.OnFocusChangeListener;
     30 import android.view.ViewTreeObserver.OnGlobalFocusChangeListener;
     31 import android.widget.Button;
     32 
     33 import com.android.frameworks.coretests.R;
     34 import org.mockito.InOrder;
     35 
     36 /**
     37  * {@link RequestFocusTest} is set up to exercise cases where the views that
     38  * have focus become invisible or GONE.
     39  */
     40 public class RequestFocusTest extends ActivityInstrumentationTestCase2<RequestFocus> {
     41 
     42     private Button mTopLeftButton;
     43     private Button mBottomLeftButton;
     44     private Button mTopRightButton;
     45     private Button mBottomRightButton;
     46     private Handler mHandler;
     47 
     48     public RequestFocusTest() {
     49         super(RequestFocus.class);
     50     }
     51 
     52     @Override
     53     public void setUp() throws Exception {
     54         super.setUp();
     55 
     56         final RequestFocus a = getActivity();
     57         mHandler = a.getHandler();
     58         mTopLeftButton = (Button) a.findViewById(R.id.topLeftButton);
     59         mBottomLeftButton = (Button) a.findViewById(R.id.bottomLeftButton);
     60         mTopRightButton = (Button) a.findViewById(R.id.topRightButton);
     61         mBottomRightButton = (Button) a.findViewById(R.id.bottomRightButton);
     62     }
     63 
     64     // Test that setUp did what we expect it to do.  These asserts
     65     // can't go in SetUp, or the test will hang.
     66     @MediumTest
     67     public void testSetUpConditions() throws Exception {
     68         assertNotNull(mHandler);
     69         assertNotNull(mTopLeftButton);
     70         assertNotNull(mTopRightButton);
     71         assertNotNull(mBottomLeftButton);
     72         assertNotNull(mBottomRightButton);
     73         assertTrue("requestFocus() should work from onCreate.", mBottomRightButton.hasFocus());
     74     }
     75 
     76     // Test that a posted requestFocus works.
     77     @LargeTest
     78     public void testPostedRequestFocus() throws Exception {
     79         mHandler.post(new Runnable() { public void run() {
     80             mBottomLeftButton.requestFocus();
     81         }});
     82         synchronized(this) {
     83             try {
     84                 wait(500);
     85             } catch (InterruptedException e) {
     86                 // Don't care.
     87             }
     88         }
     89         assertTrue("Focus should move to bottom left", mBottomLeftButton.hasFocus());
     90     }
     91 
     92     // Test that a requestFocus from the wrong thread fails.
     93     @MediumTest
     94     public void testWrongThreadRequestFocusFails() throws Exception {
     95         try {
     96             mTopRightButton.requestFocus();
     97             fail("requestFocus from wrong thread should raise exception.");
     98         } catch (AndroidRuntimeException e) {
     99             // Expected.  The actual exception is not public, so we can't catch it.
    100             assertEquals("android.view.ViewRootImpl$CalledFromWrongThreadException",
    101                          e.getClass().getName());
    102         }
    103     }
    104 
    105     /**
    106      * This tests checks the case in which the first focusable View clears focus.
    107      * In such a case the framework tries to give the focus to another View starting
    108      * from the top. Hence, the framework will try to give focus to the view that
    109      * wants to clear its focus.
    110      *
    111      * @throws Exception If an error occurs.
    112      */
    113     @UiThreadTest
    114     public void testOnFocusChangeCallbackOrderWhenClearingFocusOfFirstFocusable()
    115             throws Exception {
    116         // Get the first focusable.
    117         Button clearingFocusButton = mTopLeftButton;
    118         Button gainingFocusButton = mTopLeftButton;
    119 
    120         // Make sure that the clearing focus View is the first focusable.
    121         View focusCandidate = clearingFocusButton.getRootView().getParent().focusSearch(null,
    122                 View.FOCUS_FORWARD);
    123         assertSame("The clearing focus button is the first focusable.",
    124                 clearingFocusButton, focusCandidate);
    125         assertSame("The gaining focus button is the first focusable.",
    126                 gainingFocusButton, focusCandidate);
    127 
    128         // Focus the clearing focus button.
    129         clearingFocusButton.requestFocus();
    130         assertTrue(clearingFocusButton.hasFocus());
    131 
    132         // Register the invocation order checker.
    133         CombinedListeners mock = mock(CombinedListeners.class);
    134         clearingFocusButton.setOnFocusChangeListener(mock);
    135         gainingFocusButton.setOnFocusChangeListener(mock);
    136         clearingFocusButton.getViewTreeObserver().addOnGlobalFocusChangeListener(mock);
    137 
    138         // Try to clear focus.
    139         clearingFocusButton.clearFocus();
    140 
    141         // Check that no callback was invoked since focus did not move.
    142         InOrder inOrder = inOrder(mock);
    143         inOrder.verify(mock).onFocusChange(clearingFocusButton, false);
    144         inOrder.verify(mock).onGlobalFocusChanged(clearingFocusButton, gainingFocusButton);
    145         inOrder.verify(mock).onFocusChange(gainingFocusButton, true);
    146     }
    147 
    148     public interface CombinedListeners extends OnFocusChangeListener, OnGlobalFocusChangeListener {}
    149 
    150     /**
    151      * This tests check whether the on focus change callbacks are invoked in
    152      * the proper order when a View loses focus and the framework gives it to
    153      * the fist focusable one.
    154      *
    155      * @throws Exception
    156      */
    157     @UiThreadTest
    158     public void testOnFocusChangeCallbackOrderWhenClearingFocusOfNotFirstFocusable()
    159             throws Exception {
    160         Button clearingFocusButton = mTopRightButton;
    161         Button gainingFocusButton = mTopLeftButton;
    162 
    163         // Make sure that the clearing focus View is not the first focusable.
    164         View focusCandidate = clearingFocusButton.getRootView().getParent().focusSearch(null,
    165                 View.FOCUS_FORWARD);
    166         assertNotSame("The clearing focus button is not the first focusable.",
    167                 clearingFocusButton, focusCandidate);
    168         assertSame("The gaining focus button is the first focusable.",
    169                 gainingFocusButton, focusCandidate);
    170 
    171         // Focus the clearing focus button.
    172         clearingFocusButton.requestFocus();
    173         assertTrue(clearingFocusButton.hasFocus());
    174 
    175         // Register the invocation order checker.
    176         CombinedListeners mock = mock(CombinedListeners.class);
    177         clearingFocusButton.setOnFocusChangeListener(mock);
    178         gainingFocusButton.setOnFocusChangeListener(mock);
    179         clearingFocusButton.getViewTreeObserver().addOnGlobalFocusChangeListener(mock);
    180 
    181         // Try to clear focus.
    182         clearingFocusButton.clearFocus();
    183 
    184         // Check that no callback was invoked since focus did not move.
    185         InOrder inOrder = inOrder(mock);
    186         inOrder.verify(mock).onFocusChange(clearingFocusButton, false);
    187         inOrder.verify(mock).onGlobalFocusChanged(clearingFocusButton, gainingFocusButton);
    188         inOrder.verify(mock).onFocusChange(gainingFocusButton, true);
    189     }
    190 }
    191