/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.widget.focus; import static com.google.testing.littlemock.LittleMock.inOrder; import static com.google.testing.littlemock.LittleMock.mock; import android.os.Handler; import android.test.ActivityInstrumentationTestCase2; import android.test.UiThreadTest; import android.test.suitebuilder.annotation.LargeTest; import android.test.suitebuilder.annotation.MediumTest; import android.util.AndroidRuntimeException; import android.view.View; import android.view.View.OnFocusChangeListener; import android.view.ViewTreeObserver.OnGlobalFocusChangeListener; import android.widget.Button; import com.android.frameworks.coretests.R; import com.google.testing.littlemock.LittleMock.InOrder; /** * {@link RequestFocusTest} is set up to exercise cases where the views that * have focus become invisible or GONE. */ public class RequestFocusTest extends ActivityInstrumentationTestCase2<RequestFocus> { private Button mTopLeftButton; private Button mBottomLeftButton; private Button mTopRightButton; private Button mBottomRightButton; private Handler mHandler; public RequestFocusTest() { super(RequestFocus.class); } @Override public void setUp() throws Exception { super.setUp(); final RequestFocus a = getActivity(); mHandler = a.getHandler(); mTopLeftButton = (Button) a.findViewById(R.id.topLeftButton); mBottomLeftButton = (Button) a.findViewById(R.id.bottomLeftButton); mTopRightButton = (Button) a.findViewById(R.id.topRightButton); mBottomRightButton = (Button) a.findViewById(R.id.bottomRightButton); } // Test that setUp did what we expect it to do. These asserts // can't go in SetUp, or the test will hang. @MediumTest public void testSetUpConditions() throws Exception { assertNotNull(mHandler); assertNotNull(mTopLeftButton); assertNotNull(mTopRightButton); assertNotNull(mBottomLeftButton); assertNotNull(mBottomRightButton); assertTrue("requestFocus() should work from onCreate.", mBottomRightButton.hasFocus()); } // Test that a posted requestFocus works. @LargeTest public void testPostedRequestFocus() throws Exception { mHandler.post(new Runnable() { public void run() { mBottomLeftButton.requestFocus(); }}); synchronized(this) { try { wait(500); } catch (InterruptedException e) { // Don't care. } } assertTrue("Focus should move to bottom left", mBottomLeftButton.hasFocus()); } // Test that a requestFocus from the wrong thread fails. @MediumTest public void testWrongThreadRequestFocusFails() throws Exception { try { mTopRightButton.requestFocus(); fail("requestFocus from wrong thread should raise exception."); } catch (AndroidRuntimeException e) { // Expected. The actual exception is not public, so we can't catch it. assertEquals("android.view.ViewRootImpl$CalledFromWrongThreadException", e.getClass().getName()); } } /** * This tests checks the case in which the first focusable View clears focus. * In such a case the framework tries to give the focus to another View starting * from the top. Hence, the framework will try to give focus to the view that * wants to clear its focus. * * @throws Exception If an error occurs. */ @UiThreadTest public void testOnFocusChangeCallbackOrderWhenClearingFocusOfFirstFocusable() throws Exception { // Get the first focusable. Button clearingFocusButton = mTopLeftButton; Button gainingFocusButton = mTopLeftButton; // Make sure that the clearing focus View is the first focusable. View focusCandidate = clearingFocusButton.getRootView().getParent().focusSearch(null, View.FOCUS_FORWARD); assertSame("The clearing focus button is the first focusable.", clearingFocusButton, focusCandidate); assertSame("The gaining focus button is the first focusable.", gainingFocusButton, focusCandidate); // Focus the clearing focus button. clearingFocusButton.requestFocus(); assertTrue(clearingFocusButton.hasFocus()); // Register the invocation order checker. CombinedListeners mock = mock(CombinedListeners.class); clearingFocusButton.setOnFocusChangeListener(mock); gainingFocusButton.setOnFocusChangeListener(mock); clearingFocusButton.getViewTreeObserver().addOnGlobalFocusChangeListener(mock); // Try to clear focus. clearingFocusButton.clearFocus(); // Check that no callback was invoked since focus did not move. InOrder inOrder = inOrder(mock); inOrder.verify(mock).onFocusChange(clearingFocusButton, false); inOrder.verify(mock).onGlobalFocusChanged(clearingFocusButton, gainingFocusButton); inOrder.verify(mock).onFocusChange(gainingFocusButton, true); } public interface CombinedListeners extends OnFocusChangeListener, OnGlobalFocusChangeListener {} /** * This tests check whether the on focus change callbacks are invoked in * the proper order when a View loses focus and the framework gives it to * the fist focusable one. * * @throws Exception */ @UiThreadTest public void testOnFocusChangeCallbackOrderWhenClearingFocusOfNotFirstFocusable() throws Exception { Button clearingFocusButton = mTopRightButton; Button gainingFocusButton = mTopLeftButton; // Make sure that the clearing focus View is not the first focusable. View focusCandidate = clearingFocusButton.getRootView().getParent().focusSearch(null, View.FOCUS_FORWARD); assertNotSame("The clearing focus button is not the first focusable.", clearingFocusButton, focusCandidate); assertSame("The gaining focus button is the first focusable.", gainingFocusButton, focusCandidate); // Focus the clearing focus button. clearingFocusButton.requestFocus(); assertTrue(clearingFocusButton.hasFocus()); // Register the invocation order checker. CombinedListeners mock = mock(CombinedListeners.class); clearingFocusButton.setOnFocusChangeListener(mock); gainingFocusButton.setOnFocusChangeListener(mock); clearingFocusButton.getViewTreeObserver().addOnGlobalFocusChangeListener(mock); // Try to clear focus. clearingFocusButton.clearFocus(); // Check that no callback was invoked since focus did not move. InOrder inOrder = inOrder(mock); inOrder.verify(mock).onFocusChange(clearingFocusButton, false); inOrder.verify(mock).onGlobalFocusChanged(clearingFocusButton, gainingFocusButton); inOrder.verify(mock).onFocusChange(gainingFocusButton, true); } }