From 04af0b955d9ab0f605b4b4ee32b0eb25e8680850 Mon Sep 17 00:00:00 2001 From: Alex Danoff Date: Wed, 28 Jun 2023 13:19:55 -0700 Subject: [PATCH] W3CPointerEvents: add unit test for JSPointerDispatcher (#38114) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/38114 Changelog: [Android] [Internal] - W3CPointerEvents: add unit test for JSPointerDispatcher This adds a basic test for JSPointerDispatcher. Right now this asserts that when a MotionEvent with ACTION_DOWN is received, we send out a pointerdown event. There's a lot to be desired here in terms of e.g. ensuring that we're dispatching the event to the right target, which we can pursue as future work (of course, more complex test cases should also be added). I suspect we'll need to do a bit more refactoring to make this code more deeply testable (e.g. right now it's not straightforward to access Event properties from the test). Reviewed By: javache Differential Revision: D47035119 fbshipit-source-id: 1b49e2458325d6f0cc53d3b7ade8d6328141360f --- .../uimanager/JSPointerDispatcherTest.java | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/JSPointerDispatcherTest.java diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/JSPointerDispatcherTest.java b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/JSPointerDispatcherTest.java new file mode 100644 index 00000000000000..1e2e256af6b7d9 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/JSPointerDispatcherTest.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.uimanager; + +import android.content.Context; +import android.graphics.Rect; +import android.os.SystemClock; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.TextView; +import com.facebook.react.uimanager.events.Event; +import com.facebook.react.uimanager.events.EventDispatcher; +import com.facebook.react.uimanager.events.PointerEventHelper; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentMatcher; +import org.mockito.Mockito; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; + +@RunWith(RobolectricTestRunner.class) +public class JSPointerDispatcherTest { + + private ViewGroup mRoot; + private JSPointerDispatcher mPointerDispatcher; + + class EventWithName implements ArgumentMatcher { + private String mEventName; + + public EventWithName(String eventName) { + mEventName = eventName; + } + + @Override + public boolean matches(Event argument) { + return argument.getEventName().equals(mEventName); + } + + @Override + public String toString() { + return "[event with name: " + mEventName + "]"; + } + } + + @Before + public void setupViewHierarchy() { + Context ctx = RuntimeEnvironment.getApplication(); + mRoot = new LinearLayout(ctx); + TextView childView = new TextView(ctx); + childView.append("Hello, world!"); + // need > 0 ID to consider it as a react view (see + // TouchTargetHelper::findTargetPathAndCoordinatesForTouch) + childView.setId(100); + mRoot.addView(childView); + // needed for test to ensure that child has dimensions + mRoot.measure(500, 500); + mRoot.layout(0, 0, 500, 500); + mPointerDispatcher = new JSPointerDispatcher(mRoot); + } + + private static MotionEvent createMotionEvent(int action, float x, float y) { + long downTime = SystemClock.uptimeMillis(); + long eventTime = downTime; + int metaState = 0; // no modifiers pressed + + return MotionEvent.obtain(downTime, eventTime, action, x, y, metaState); + } + + private Rect getChildViewRectInRootCoordinates(int childIndex) { + View child = mRoot.getChildAt(childIndex); + Rect outRect = new Rect(); + child.getDrawingRect(outRect); + + mRoot.offsetDescendantRectToMyCoords(child, outRect); + + return outRect; + } + + @Test + public void testPointerEnter() { + Rect childRect = getChildViewRectInRootCoordinates(0); + MotionEvent ev = + createMotionEvent(MotionEvent.ACTION_DOWN, childRect.centerX(), childRect.centerY()); + EventDispatcher mockDispatcher = Mockito.mock(EventDispatcher.class); + mPointerDispatcher.handleMotionEvent(ev, mockDispatcher, false); + Mockito.verify(mockDispatcher) + .dispatchEvent(Mockito.argThat(new EventWithName(PointerEventHelper.POINTER_DOWN))); + } +}