Skip to content

Commit

Permalink
W3CPointerEvents: add tests for click event (#37538)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: #37538

Changelog: [Internal] - W3CPointerEvents: add tests for click event

We don't have any existing tests which exercise the new (PointerEvent-based) click events. This change adds 3 tests:

1. PointerEventClickTouch: checks that the click event fires on an element when it is touched and released, and verifies that the event properties have the expected values
2. PointerEventClickTouchHierarchy: checks that the click event fires appropriately in a hierarchy of elements when the initial target of the touch is not the same as the final target (i.e. where the touch is released)
3. PointerEventClickTouchHierarchyPointerEvents: checks that the click event respects the setting of `pointerEvents` property in a hierarchy of elements

Note: these tests currently fail (at least on Android); future changes will bring the functionality in line with test expectations.

Reviewed By: vincentriemer

Differential Revision: D45121367

fbshipit-source-id: 7f22ea582e2568c418f569b7e1139388593574ab
  • Loading branch information
Alex Danoff authored and facebook-github-bot committed May 23, 2023
1 parent d810043 commit 670fa88
Show file tree
Hide file tree
Showing 5 changed files with 547 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/**
* 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.
*
* @format
* @flow
*/

import type {PlatformTestComponentBaseProps} from '../PlatformTest/RNTesterPlatformTestTypes';
import type {PointerEvent} from 'react-native/Libraries/Types/CoreEventTypes';

import {check_PointerEvent} from './PointerEventSupport';
import RNTesterPlatformTest from '../PlatformTest/RNTesterPlatformTest';
import * as React from 'react';
import {useRef, useCallback} from 'react';
import {StyleSheet, View} from 'react-native';
import type {PlatformTestContext} from '../PlatformTest/RNTesterPlatformTestTypes';

function checkClickEventProperties(
assert_equals: PlatformTestContext['assert_equals'],
event: PointerEvent,
) {
assert_equals(event.nativeEvent.width, 1, 'default width is 1');
assert_equals(event.nativeEvent.height, 1, 'default height is 1');
assert_equals(event.nativeEvent.pressure, 0, 'default pressure is 0');
assert_equals(
event.nativeEvent.tangentialPressure,
0,
'default tangentialPressure is 0',
);
assert_equals(event.nativeEvent.tiltX, 0, 'default tiltX is 0');
assert_equals(event.nativeEvent.tiltY, 0, 'default tiltY is 0');
assert_equals(event.nativeEvent.twist, 0, 'default twist is 0');
assert_equals(
event.nativeEvent.isPrimary,
false,
'default isPrimary is false',
);
}
function PointerEventClickTouchTestCase(props: PlatformTestComponentBaseProps) {
const {harness} = props;
const hasSeenPointerDown = useRef<boolean>(false);
const hasSeenPointerUp = useRef<boolean>(false);
const hasSeenClick = useRef<boolean>(false);
const testPointerClick = harness.useAsyncTest('click event received');
const handleClick = useCallback(
(e: PointerEvent) => {
if (hasSeenClick.current) {
return;
}
hasSeenClick.current = true;
testPointerClick.step(({assert_equals}) => {
assert_equals(
hasSeenPointerDown.current,
true,
'pointerdown was received',
);
assert_equals(hasSeenPointerUp.current, true, 'pointerup was received');
checkClickEventProperties(assert_equals, e);
});
check_PointerEvent(harness, e, 'click', {});
testPointerClick.done();
},
[harness, testPointerClick],
);
const handlePointerDown = useCallback(
(e: PointerEvent) => {
if (hasSeenPointerDown.current) {
return;
}
hasSeenPointerDown.current = true;
testPointerClick.step(({assert_equals}) => {
assert_equals(
hasSeenPointerUp.current,
false,
'pointerup was not received',
);
assert_equals(hasSeenClick.current, false, 'click was not received');
});
},
[testPointerClick],
);

const handlePointerUp = useCallback(
(e: PointerEvent) => {
if (hasSeenPointerUp.current) {
return;
}
hasSeenPointerUp.current = true;
testPointerClick.step(({assert_equals}) => {
assert_equals(
hasSeenPointerDown.current,
true,
'pointerdown was received',
);
assert_equals(hasSeenClick.current, false, 'click was not received');
});
},
[testPointerClick],
);

return (
<View
onClick={handleClick}
onPointerDown={handlePointerDown}
onPointerUp={handlePointerUp}
style={styles.target}
/>
);
}

const styles = StyleSheet.create({
target: {
backgroundColor: 'black',
height: 64,
width: '100%',
},
});

type Props = $ReadOnly<{}>;
export default function PointerEventClickTouch(
props: Props,
): React.MixedElement {
return (
<RNTesterPlatformTest
component={PointerEventClickTouchTestCase}
description="This test checks if the click event triggers."
instructions={['Click or tap on the black rectangle.']}
title="Click test"
/>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/**
* 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.
*
* @format
* @flow
*/

import type {PlatformTestComponentBaseProps} from '../PlatformTest/RNTesterPlatformTestTypes';

import RNTesterPlatformTest from '../PlatformTest/RNTesterPlatformTest';
import * as React from 'react';
import {useRef} from 'react';
import {StyleSheet, View} from 'react-native';
import {EventTracker} from './PointerEventSupport';
import type {EventOccurrence} from './PointerEventSupport';
import {mkEvent} from './PointerEventSupport';

const eventsToTrack = ['onClick', 'onPointerDown', 'onPointerUp'];

function PointerEventClickTouchHierarchyTestCase(
props: PlatformTestComponentBaseProps,
) {
const {harness} = props;

const eventsInOrder = useRef<Array<EventOccurrence>>([]);

const testPointerClick = harness.useAsyncTest(
'click event received in hierarchy',
);

const checkResults = () => {
testPointerClick.step(({assert_equals}) => {
const eventsReceived = eventsInOrder.current;
assert_equals(
eventsReceived.length,
14,
'received the expected number of events',
);
const childToParentEvents = eventsReceived.slice(0, 4);
const parentToChildEvents = eventsReceived.slice(4, 8);
const childOnlyEvents = eventsReceived.slice(8);
assert_equals(
JSON.stringify(childToParentEvents),
JSON.stringify([
mkEvent('child', 'onPointerDown'),
mkEvent('parent', 'onPointerDown'),
mkEvent('parent', 'onPointerUp'),
mkEvent('parent', 'onClick'),
]),
'correct events when moving child -> parent',
);
assert_equals(
JSON.stringify(parentToChildEvents),
JSON.stringify([
mkEvent('parent', 'onPointerDown'),
mkEvent('child', 'onPointerUp'),
mkEvent('parent', 'onPointerUp'),
mkEvent('parent', 'onClick'),
]),
'correct events when moving parent -> child',
);
assert_equals(
JSON.stringify(childOnlyEvents),
JSON.stringify([
mkEvent('child', 'onPointerDown'),
mkEvent('parent', 'onPointerDown'),
mkEvent('child', 'onPointerUp'),
mkEvent('parent', 'onPointerUp'),
mkEvent('child', 'onClick'),
mkEvent('parent', 'onClick'),
]),
'correct events when clicking on child',
);
});
testPointerClick.done();
};

return (
<View>
<EventTracker
id="parent"
eventsRef={eventsInOrder}
eventsToTrack={eventsToTrack}
style={styles.targetParent}>
<EventTracker
id="child"
eventsRef={eventsInOrder}
eventsToTrack={eventsToTrack}
style={styles.target}
/>
</EventTracker>
<View style={styles.checkResults} onClick={checkResults} />
</View>
);
}

const styles = StyleSheet.create({
targetParent: {
backgroundColor: 'black',
height: 64,
width: '100%',
},
target: {
backgroundColor: 'blue',
height: 64,
width: 64,
},
checkResults: {
backgroundColor: 'green',
height: 64,
width: 64,
},
});

type Props = $ReadOnly<{}>;
export default function PointerEventClickTouchHierarchy(
props: Props,
): React.MixedElement {
return (
<RNTesterPlatformTest
component={PointerEventClickTouchHierarchyTestCase}
description="This test checks if the click event triggers properly in a hierarchy."
instructions={[
'Start a touch on the blue rectangle',
'Move your finger over the black rectangle',
'Release the touch',
'Start a new touch on the black rectangle',
'Move your finger over the blue rectangle',
'Release the touch',
'Start a new touch on the blue rectangle',
'Release the touch (still on blue rectangle)',
'Tap the green rectangle to check results',
]}
title="Click hierarchy test"
/>
);
}
Loading

0 comments on commit 670fa88

Please sign in to comment.