/** * 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. * * @flow strict-local * @format */ import type {PlatformTestComponentBaseProps} from '../PlatformTest/RNTesterPlatformTestTypes'; import type {ElementRef} from 'react'; import type {PointerEvent} from 'react-native'; import RNTesterPlatformTest from '../PlatformTest/RNTesterPlatformTest'; import * as React from 'react'; import {useCallback, useRef} from 'react'; import {StyleSheet, Text, View} from 'react-native'; // adapted from https://github.com/web-platform-tests/wpt/blob/master/pointerevents/pointerevent_capture_mouse.html function PointerEventCaptureMouseTestCase( props: PlatformTestComponentBaseProps, ) { const {harness} = props; const target0Ref = useRef | null>(null); const target1Ref = useRef | null>(null); const isPointerCaptureRef = useRef(false); const pointermoveNoCaptureGot0Ref = useRef(false); const pointermoveCaptureGot0Ref = useRef(false); const pointermoveNoCaptureGot1Ref = useRef(false); const ownEventForTheCapturedTargetGotRef = useRef(false); const testGotPointerCapture = harness.useAsyncTest( 'gotpointercapture event received"', ); const testLostPointerCapture = harness.useAsyncTest( 'lostpointercapture event received"', ); const handleCaptureButtonDown = useCallback((evt: PointerEvent) => { const target0 = target0Ref.current; if (target0 != null && isPointerCaptureRef.current === false) { isPointerCaptureRef.current = true; try { // $FlowFixMe[prop-missing] target0.setPointerCapture(evt.nativeEvent.pointerId); } catch (e) {} } }, []); const handleTarget0GotPointerCapture = useCallback( (evt: PointerEvent) => { testGotPointerCapture.done(); }, [testGotPointerCapture], ); const handleTarget0LostPointerCapture = useCallback( (evt: PointerEvent) => { testLostPointerCapture.done(); isPointerCaptureRef.current = false; }, [testLostPointerCapture], ); const testPointerMove0 = harness.useAsyncTest( 'pointerover event for black rectangle received', ); const testPointerMove1 = harness.useAsyncTest( 'pointerover event for purple rectangle received', ); const handleTarget0PointerMove = useCallback( (evt: PointerEvent) => { const target0 = target0Ref.current; if (!pointermoveNoCaptureGot0Ref.current) { testPointerMove0.done(); pointermoveNoCaptureGot0Ref.current = true; } if (isPointerCaptureRef.current && target0 != null) { const {clientX, clientY} = evt.nativeEvent; const {left, right, top, bottom} = // $FlowFixMe[prop-missing] target0.getBoundingClientRect(); if (!pointermoveCaptureGot0Ref.current) { harness.test( ({assert_equals}) => { assert_equals( evt.nativeEvent.relatedTarget, null, 'relatedTarget is null when the capture is set', ); }, 'relatedTarget is null when the capture is set.', {skip: true}, ); harness.test(({assert_true}) => { assert_true( clientX < left || clientX > right || clientY < top || clientY > bottom, 'pointermove received for captured element while out of it', ); }, 'pointermove received for captured element while out of it'); pointermoveCaptureGot0Ref.current = true; } if ( clientX > left && clientX < right && clientY > top && clientY < bottom && !ownEventForTheCapturedTargetGotRef.current ) { harness.test(({assert_true}) => { assert_true( true, 'pointermove received for captured element while inside of it', ); }, 'pointermove received for captured element while inside of it'); ownEventForTheCapturedTargetGotRef.current = true; } } }, [harness, testPointerMove0], ); const handleTarget1PointerMove = useCallback( (evt: PointerEvent) => { harness.test(({assert_equals}) => { assert_equals( isPointerCaptureRef.current, false, "pointermove shouldn't trigger for this target when capture is enabled", ); }, "pointermove shouldn't trigger for the purple rectangle while the black rectangle has capture"); if (!pointermoveNoCaptureGot1Ref.current) { testPointerMove1.done(); pointermoveNoCaptureGot1Ref.current = true; } }, [harness, testPointerMove1], ); return ( Set Capture ); } const styles = StyleSheet.create({ captureButton: { alignSelf: 'flex-start', backgroundColor: 'lightblue', paddingHorizontal: 32, paddingVertical: 16, borderRadius: 8, }, container: {}, target0: { backgroundColor: 'black', padding: 32, marginBottom: 16, }, target1: { backgroundColor: 'purple', padding: 32, marginBottom: 16, }, }); type Props = $ReadOnly<{}>; export default function PointerEventCaptureMouse( props: Props, ): React.MixedElement { return ( ); }