| package io.flutter.embedding.engine.mutatorsstack; |
| |
| import static android.view.View.OnFocusChangeListener; |
| import static junit.framework.TestCase.*; |
| import static org.mockito.Mockito.*; |
| |
| import android.graphics.Matrix; |
| import android.view.MotionEvent; |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.view.ViewTreeObserver; |
| import io.flutter.embedding.android.AndroidTouchProcessor; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.mockito.ArgumentCaptor; |
| import org.robolectric.RobolectricTestRunner; |
| import org.robolectric.RuntimeEnvironment; |
| import org.robolectric.annotation.Config; |
| |
| @Config(manifest = Config.NONE) |
| @RunWith(RobolectricTestRunner.class) |
| public class FlutterMutatorViewTest { |
| |
| @Test |
| public void canDragViews() { |
| final AndroidTouchProcessor touchProcessor = mock(AndroidTouchProcessor.class); |
| final FlutterMutatorView view = |
| new FlutterMutatorView(RuntimeEnvironment.systemContext, 1.0f, touchProcessor); |
| final FlutterMutatorsStack mutatorStack = mock(FlutterMutatorsStack.class); |
| |
| assertTrue(view.onInterceptTouchEvent(mock(MotionEvent.class))); |
| |
| { |
| view.readyToDisplay(mutatorStack, /*left=*/ 1, /*top=*/ 2, /*width=*/ 0, /*height=*/ 0); |
| view.onTouchEvent(MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0.0f, 0.0f, 0)); |
| final ArgumentCaptor<Matrix> matrixCaptor = ArgumentCaptor.forClass(Matrix.class); |
| verify(touchProcessor).onTouchEvent(any(), matrixCaptor.capture()); |
| |
| final Matrix screenMatrix = new Matrix(); |
| screenMatrix.postTranslate(1, 2); |
| assertTrue(matrixCaptor.getValue().equals(screenMatrix)); |
| } |
| |
| reset(touchProcessor); |
| |
| { |
| view.readyToDisplay(mutatorStack, /*left=*/ 3, /*top=*/ 4, /*width=*/ 0, /*height=*/ 0); |
| view.onTouchEvent(MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0.0f, 0.0f, 0)); |
| final ArgumentCaptor<Matrix> matrixCaptor = ArgumentCaptor.forClass(Matrix.class); |
| verify(touchProcessor).onTouchEvent(any(), matrixCaptor.capture()); |
| |
| final Matrix screenMatrix = new Matrix(); |
| screenMatrix.postTranslate(1, 2); |
| assertTrue(matrixCaptor.getValue().equals(screenMatrix)); |
| } |
| |
| reset(touchProcessor); |
| |
| { |
| view.readyToDisplay(mutatorStack, /*left=*/ 5, /*top=*/ 6, /*width=*/ 0, /*height=*/ 0); |
| view.onTouchEvent(MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0.0f, 0.0f, 0)); |
| final ArgumentCaptor<Matrix> matrixCaptor = ArgumentCaptor.forClass(Matrix.class); |
| verify(touchProcessor).onTouchEvent(any(), matrixCaptor.capture()); |
| |
| final Matrix screenMatrix = new Matrix(); |
| screenMatrix.postTranslate(3, 4); |
| assertTrue(matrixCaptor.getValue().equals(screenMatrix)); |
| } |
| |
| reset(touchProcessor); |
| |
| { |
| view.readyToDisplay(mutatorStack, /*left=*/ 7, /*top=*/ 8, /*width=*/ 0, /*height=*/ 0); |
| view.onTouchEvent(MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0.0f, 0.0f, 0)); |
| final ArgumentCaptor<Matrix> matrixCaptor = ArgumentCaptor.forClass(Matrix.class); |
| verify(touchProcessor).onTouchEvent(any(), matrixCaptor.capture()); |
| |
| final Matrix screenMatrix = new Matrix(); |
| screenMatrix.postTranslate(7, 8); |
| assertTrue(matrixCaptor.getValue().equals(screenMatrix)); |
| } |
| } |
| |
| @Test |
| public void childHasFocus_rootHasFocus() { |
| final View rootView = mock(View.class); |
| when(rootView.hasFocus()).thenReturn(true); |
| assertTrue(FlutterMutatorView.childHasFocus(rootView)); |
| } |
| |
| @Test |
| public void childHasFocus_rootDoesNotHaveFocus() { |
| final View rootView = mock(View.class); |
| when(rootView.hasFocus()).thenReturn(false); |
| assertFalse(FlutterMutatorView.childHasFocus(rootView)); |
| } |
| |
| @Test |
| public void childHasFocus_rootIsNull() { |
| assertFalse(FlutterMutatorView.childHasFocus(null)); |
| } |
| |
| @Test |
| public void childHasFocus_childHasFocus() { |
| final View childView = mock(View.class); |
| when(childView.hasFocus()).thenReturn(true); |
| |
| final ViewGroup rootView = mock(ViewGroup.class); |
| when(rootView.getChildCount()).thenReturn(1); |
| when(rootView.getChildAt(0)).thenReturn(childView); |
| |
| assertTrue(FlutterMutatorView.childHasFocus(rootView)); |
| } |
| |
| @Test |
| public void childHasFocus_childDoesNotHaveFocus() { |
| final View childView = mock(View.class); |
| when(childView.hasFocus()).thenReturn(false); |
| |
| final ViewGroup rootView = mock(ViewGroup.class); |
| when(rootView.getChildCount()).thenReturn(1); |
| when(rootView.getChildAt(0)).thenReturn(childView); |
| |
| assertFalse(FlutterMutatorView.childHasFocus(rootView)); |
| } |
| |
| @Test |
| public void focusChangeListener_hasFocus() { |
| final ViewTreeObserver viewTreeObserver = mock(ViewTreeObserver.class); |
| when(viewTreeObserver.isAlive()).thenReturn(true); |
| |
| final FlutterMutatorView view = |
| new FlutterMutatorView(RuntimeEnvironment.systemContext) { |
| @Override |
| public ViewTreeObserver getViewTreeObserver() { |
| return viewTreeObserver; |
| } |
| |
| @Override |
| public boolean hasFocus() { |
| return true; |
| } |
| }; |
| |
| final OnFocusChangeListener focusListener = mock(OnFocusChangeListener.class); |
| view.setOnDescendantFocusChangeListener(focusListener); |
| |
| final ArgumentCaptor<ViewTreeObserver.OnGlobalFocusChangeListener> focusListenerCaptor = |
| ArgumentCaptor.forClass(ViewTreeObserver.OnGlobalFocusChangeListener.class); |
| verify(viewTreeObserver).addOnGlobalFocusChangeListener(focusListenerCaptor.capture()); |
| |
| focusListenerCaptor.getValue().onGlobalFocusChanged(null, null); |
| verify(focusListener).onFocusChange(view, true); |
| } |
| |
| @Test |
| public void focusChangeListener_doesNotHaveFocus() { |
| final ViewTreeObserver viewTreeObserver = mock(ViewTreeObserver.class); |
| when(viewTreeObserver.isAlive()).thenReturn(true); |
| |
| final FlutterMutatorView view = |
| new FlutterMutatorView(RuntimeEnvironment.systemContext) { |
| @Override |
| public ViewTreeObserver getViewTreeObserver() { |
| return viewTreeObserver; |
| } |
| |
| @Override |
| public boolean hasFocus() { |
| return false; |
| } |
| }; |
| |
| final OnFocusChangeListener focusListener = mock(OnFocusChangeListener.class); |
| view.setOnDescendantFocusChangeListener(focusListener); |
| |
| final ArgumentCaptor<ViewTreeObserver.OnGlobalFocusChangeListener> focusListenerCaptor = |
| ArgumentCaptor.forClass(ViewTreeObserver.OnGlobalFocusChangeListener.class); |
| verify(viewTreeObserver).addOnGlobalFocusChangeListener(focusListenerCaptor.capture()); |
| |
| focusListenerCaptor.getValue().onGlobalFocusChanged(null, null); |
| verify(focusListener).onFocusChange(view, false); |
| } |
| |
| @Test |
| public void focusChangeListener_viewTreeObserverIsAliveFalseDoesNotThrow() { |
| final FlutterMutatorView view = |
| new FlutterMutatorView(RuntimeEnvironment.systemContext) { |
| @Override |
| public ViewTreeObserver getViewTreeObserver() { |
| final ViewTreeObserver viewTreeObserver = mock(ViewTreeObserver.class); |
| when(viewTreeObserver.isAlive()).thenReturn(false); |
| return viewTreeObserver; |
| } |
| }; |
| view.setOnDescendantFocusChangeListener(mock(OnFocusChangeListener.class)); |
| } |
| |
| @Test |
| public void setOnDescendantFocusChangeListener_keepsSingleListener() { |
| final ViewTreeObserver viewTreeObserver = mock(ViewTreeObserver.class); |
| when(viewTreeObserver.isAlive()).thenReturn(true); |
| |
| final FlutterMutatorView view = |
| new FlutterMutatorView(RuntimeEnvironment.systemContext) { |
| @Override |
| public ViewTreeObserver getViewTreeObserver() { |
| return viewTreeObserver; |
| } |
| }; |
| |
| assertNull(view.activeFocusListener); |
| |
| view.setOnDescendantFocusChangeListener(mock(OnFocusChangeListener.class)); |
| assertNotNull(view.activeFocusListener); |
| |
| final ViewTreeObserver.OnGlobalFocusChangeListener activeFocusListener = |
| view.activeFocusListener; |
| |
| view.setOnDescendantFocusChangeListener(mock(OnFocusChangeListener.class)); |
| assertNotNull(view.activeFocusListener); |
| |
| verify(viewTreeObserver, times(1)).removeOnGlobalFocusChangeListener(activeFocusListener); |
| } |
| |
| @Test |
| public void unsetOnDescendantFocusChangeListener_removesActiveListener() { |
| final ViewTreeObserver viewTreeObserver = mock(ViewTreeObserver.class); |
| when(viewTreeObserver.isAlive()).thenReturn(true); |
| |
| final FlutterMutatorView view = |
| new FlutterMutatorView(RuntimeEnvironment.systemContext) { |
| @Override |
| public ViewTreeObserver getViewTreeObserver() { |
| return viewTreeObserver; |
| } |
| }; |
| |
| assertNull(view.activeFocusListener); |
| |
| view.setOnDescendantFocusChangeListener(mock(OnFocusChangeListener.class)); |
| assertNotNull(view.activeFocusListener); |
| |
| final ViewTreeObserver.OnGlobalFocusChangeListener activeFocusListener = |
| view.activeFocusListener; |
| |
| view.unsetOnDescendantFocusChangeListener(); |
| assertNull(view.activeFocusListener); |
| |
| view.unsetOnDescendantFocusChangeListener(); |
| verify(viewTreeObserver, times(1)).removeOnGlobalFocusChangeListener(activeFocusListener); |
| } |
| } |