Skip to content

Commit b2fda3e

Browse files
vincentriemerfacebook-github-bot
authored andcommitted
Add platform test for pointercancel events caused by touch scrolling
Summary: Changelog: [Internal] - Add platform test for pointercancel events caused by touch scrolling This diff adds a new ported Web Platform Test which [verifies that pointercancel events are properly emitted once a touch causes scrolling](https://github.com/web-platform-tests/wpt/blob/master/pointerevents/pointerevent_pointercancel_touch.html). Reviewed By: lunaleaps Differential Revision: D43855277 fbshipit-source-id: 94a106058ba2c5e5fe4c1980519ceceddb2bb389
1 parent 93c1fbd commit b2fda3e

File tree

2 files changed

+191
-0
lines changed

2 files changed

+191
-0
lines changed
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @format
8+
* @flow
9+
*/
10+
11+
import type {PlatformTestComponentBaseProps} from '../PlatformTest/RNTesterPlatformTestTypes';
12+
import type {PointerEvent} from 'react-native/Libraries/Types/CoreEventTypes';
13+
14+
import RNTesterPlatformTest from '../PlatformTest/RNTesterPlatformTest';
15+
import {check_PointerEvent} from './PointerEventSupport';
16+
import * as React from 'react';
17+
import {useCallback, useRef} from 'react';
18+
import {StyleSheet, View, ScrollView} from 'react-native';
19+
20+
// adapted from https://github.com/web-platform-tests/wpt/blob/master/pointerevents/pointerevent_pointercancel_touch.html
21+
function PointerEventPointerCancelTouchTestCase(
22+
props: PlatformTestComponentBaseProps,
23+
) {
24+
const {harness} = props;
25+
26+
const testPointerEvent = harness.useAsyncTest('pointercancel event recieved');
27+
28+
const pointerDownEventRef = useRef<PointerEvent | null>(null);
29+
const pointerCancelEventRef = useRef<PointerEvent | null>(null);
30+
31+
const handlePointerDown = useCallback((event: PointerEvent) => {
32+
event.persist();
33+
pointerDownEventRef.current = event;
34+
}, []);
35+
36+
const handlePointerCancel = useCallback(
37+
(event: PointerEvent) => {
38+
event.persist();
39+
pointerCancelEventRef.current = event;
40+
41+
testPointerEvent.step(({assert_equals, assert_not_equals}) => {
42+
const pointerDownEvent = pointerDownEventRef.current;
43+
assert_not_equals(pointerDownEvent, null, 'pointerdown was recieved: ');
44+
if (pointerDownEvent != null) {
45+
assert_equals(
46+
event.nativeEvent.pointerId,
47+
pointerDownEvent.nativeEvent.pointerId,
48+
'pointerId should be the same for pointerdown and pointercancel',
49+
);
50+
assert_equals(
51+
event.nativeEvent.pointerType,
52+
pointerDownEvent.nativeEvent.pointerType,
53+
'pointerType should be the same for pointerdown and pointercancel',
54+
);
55+
assert_equals(
56+
event.nativeEvent.isPrimary,
57+
pointerDownEvent.nativeEvent.isPrimary,
58+
'isPrimary should be the same for pointerdown and pointercancel',
59+
);
60+
}
61+
});
62+
63+
check_PointerEvent(harness, event, 'pointerCancel', {});
64+
65+
testPointerEvent.step(({assert_equals}) => {
66+
assert_equals(event.nativeEvent.x, 0, 'pointercancel.x must be zero');
67+
assert_equals(event.nativeEvent.y, 0, 'pointercancel.y must be zero');
68+
assert_equals(
69+
event.nativeEvent.clientX,
70+
0,
71+
'pointercancel.clientX must be zero',
72+
);
73+
assert_equals(
74+
event.nativeEvent.clientY,
75+
0,
76+
'pointercancel.clientY must be zero',
77+
);
78+
});
79+
},
80+
[harness, testPointerEvent],
81+
);
82+
83+
const handlePointerOut = useCallback(
84+
(event: PointerEvent) => {
85+
testPointerEvent.step(({assert_equals, assert_not_equals}) => {
86+
const pointerCancelEvent = pointerCancelEventRef.current;
87+
assert_not_equals(
88+
pointerCancelEvent,
89+
null,
90+
'pointercancel was recieved: ',
91+
);
92+
if (pointerCancelEvent != null) {
93+
assert_equals(
94+
event.nativeEvent.pointerId,
95+
pointerCancelEvent.nativeEvent.pointerId,
96+
'pointerId should be the same for pointerout and pointercancel',
97+
);
98+
assert_equals(
99+
event.nativeEvent.pointerType,
100+
pointerCancelEvent.nativeEvent.pointerType,
101+
'pointerType should be the same for pointerout and pointercancel',
102+
);
103+
assert_equals(
104+
event.nativeEvent.isPrimary,
105+
pointerCancelEvent.nativeEvent.isPrimary,
106+
'isPrimary should be the same for pointerout and pointercancel',
107+
);
108+
}
109+
});
110+
},
111+
[testPointerEvent],
112+
);
113+
114+
const handlePointerLeave = useCallback(
115+
(event: PointerEvent) => {
116+
testPointerEvent.step(({assert_equals, assert_not_equals}) => {
117+
const pointerCancelEvent = pointerCancelEventRef.current;
118+
assert_not_equals(
119+
pointerCancelEvent,
120+
null,
121+
'pointercancel was recieved: ',
122+
);
123+
if (pointerCancelEvent != null) {
124+
assert_equals(
125+
event.nativeEvent.pointerId,
126+
pointerCancelEvent.nativeEvent.pointerId,
127+
'pointerId should be the same for pointerleave and pointercancel',
128+
);
129+
assert_equals(
130+
event.nativeEvent.pointerType,
131+
pointerCancelEvent.nativeEvent.pointerType,
132+
'pointerType should be the same for pointerleave and pointercancel',
133+
);
134+
assert_equals(
135+
event.nativeEvent.isPrimary,
136+
pointerCancelEvent.nativeEvent.isPrimary,
137+
'isPrimary should be the same for pointerleave and pointercancel',
138+
);
139+
}
140+
});
141+
testPointerEvent.done();
142+
},
143+
[testPointerEvent],
144+
);
145+
146+
return (
147+
<ScrollView style={styles.scrollContainer}>
148+
<View
149+
onPointerDown={handlePointerDown}
150+
onPointerCancel={handlePointerCancel}
151+
onPointerOut={handlePointerOut}
152+
onPointerLeave={handlePointerLeave}
153+
style={styles.target}
154+
/>
155+
</ScrollView>
156+
);
157+
}
158+
159+
const styles = StyleSheet.create({
160+
scrollContainer: {width: '100%', height: '100%'},
161+
target: {
162+
backgroundColor: 'black',
163+
padding: 32,
164+
},
165+
});
166+
167+
type Props = $ReadOnly<{}>;
168+
export default function PoitnerEventPointerCancelTouch(
169+
props: Props,
170+
): React.MixedElement {
171+
return (
172+
<RNTesterPlatformTest
173+
component={PointerEventPointerCancelTouchTestCase}
174+
description="This test checks if pointercancel event triggers."
175+
title="Pointer Events pointercancel Tests"
176+
instructions={[
177+
'Start touch over the black rectangle.',
178+
'Then move your finger to scroll the page.',
179+
]}
180+
/>
181+
);
182+
}

packages/rn-tester/js/examples/Experimental/W3CPointerEventsExample.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import PointerEventPointerMoveEventOrder from './W3CPointerEventPlatformTests/Po
2323
import PointerEventPointerMoveBetween from './W3CPointerEventPlatformTests/PointerEventPointerMoveBetween';
2424
import PointerEventPointerOverOut from './W3CPointerEventPlatformTests/PointerEventPointerOverOut';
2525
import PointerEventLayoutChangeShouldFirePointerOver from './W3CPointerEventPlatformTests/PointerEventLayoutChangeShouldFirePointerOver';
26+
import PointerEventPointerCancelTouch from './W3CPointerEventPlatformTests/PointerEventPointerCancelTouch';
2627
import EventfulView from './W3CPointerEventsEventfulView';
2728
import ManyPointersPropertiesExample from './Compatibility/ManyPointersPropertiesExample';
2829

@@ -232,6 +233,14 @@ export default {
232233
return <PointerEventLayoutChangeShouldFirePointerOver />;
233234
},
234235
},
236+
{
237+
name: 'pointerevent_pointercancel_touch',
238+
description: '',
239+
title: 'WPT 11: Pointer Events pointercancel Tests',
240+
render(): React.Node {
241+
return <PointerEventPointerCancelTouch />;
242+
},
243+
},
235244
{
236245
name: 'relative',
237246
description: 'Children laid out using relative positioning',

0 commit comments

Comments
 (0)