Skip to content

Commit 00184ac

Browse files
lunaleapsmeta-codesync[bot]
authored andcommitted
Add Intersection Observer E2E tests for FB (facebook#55656)
Summary: Pull Request resolved: facebook#55656 Changelog: [Internal] - Update IO examples for easier E2E testing Meta: Updated approach to render IntersectionObserver examples for E2E testing. Updated some of the examples to be friendlier for e2e assertions Reviewed By: rubennorte Differential Revision: D92897290 fbshipit-source-id: 1ee827036951798495a7e5840fd60d2b18877e64
1 parent 863f5c0 commit 00184ac

File tree

2 files changed

+62
-62
lines changed

2 files changed

+62
-62
lines changed

packages/rn-tester/js/examples/IntersectionObserver/IntersectionObserverClippingParent.js

Lines changed: 55 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -15,55 +15,41 @@ import type IntersectionObserverEntry from 'react-native/src/private/webapis/int
1515
import * as React from 'react';
1616
import {useCallback, useLayoutEffect, useRef, useState} from 'react';
1717
import {Button, StyleSheet, Text, TextInput, View} from 'react-native';
18+
import DOMRectReadOnly from 'react-native/src/private/webapis/geometry/DOMRectReadOnly';
1819

1920
export const name = 'IntersectionObserver Parent Clipping Example';
2021
export const title = name;
2122
export const description = 'A clipping parent clips both the root and target';
2223

2324
declare var IntersectionObserver: Class<IntersectionObserverType>;
2425

25-
export function render(): React.Node {
26-
return <IntersectionObserverCustomClippingRootExample />;
26+
export function render(options?: {e2eTest?: boolean}): React.Node {
27+
return (
28+
<IntersectionObserverCustomClippingRootExample
29+
e2eTest={options?.e2eTest ?? false}
30+
/>
31+
);
2732
}
2833

2934
/**
30-
* Showcase threshold of two overlapping elements
35+
* Formats a DOMRectReadOnly for display with a label.
3136
*/
32-
function roundRect(rect: unknown): ?{
33-
x: number,
34-
y: number,
35-
width: number,
36-
height: number,
37-
} {
37+
function formatRect(label: string, rect: ?DOMRectReadOnly): ?string {
3838
if (rect == null || typeof rect !== 'object') {
3939
return null;
4040
}
41-
// $FlowFixMe[prop-missing]
42-
const x = rect.x;
43-
// $FlowFixMe[prop-missing]
44-
const y = rect.y;
45-
// $FlowFixMe[prop-missing]
4641
const width = rect.width;
47-
// $FlowFixMe[prop-missing]
4842
const height = rect.height;
4943

50-
if (
51-
typeof x !== 'number' ||
52-
typeof y !== 'number' ||
53-
typeof width !== 'number' ||
54-
typeof height !== 'number'
55-
) {
44+
if (typeof width !== 'number' || typeof height !== 'number') {
5645
return null;
5746
}
58-
return {
59-
x: Math.round(x),
60-
y: Math.round(y),
61-
width: Math.round(width),
62-
height: Math.round(height),
63-
};
47+
return `${label}: width:${Math.round(width)}, height:${Math.round(height)}`;
6448
}
6549

66-
component IntersectionObserverCustomClippingRootExample() {
50+
component IntersectionObserverCustomClippingRootExample(
51+
e2eTest: boolean = false,
52+
) {
6753
const rootRef = useRef<?HostInstance>(null);
6854
const targetRef = useRef<?HostInstance>(null);
6955
const [intersectionEntry, setIntersectionEntry] =
@@ -136,35 +122,39 @@ component IntersectionObserverCustomClippingRootExample() {
136122
<Text style={styles.currentMargin}>
137123
Current Root Margin: {rootMarginValue}
138124
</Text>
139-
<Text style={styles.description}>
140-
This example highlights a clipping parent to both the explicit root
141-
(blue) and target (yellow). The dashed borders show the full extent of
142-
the root and target, while the solid colors show what's actually visible
143-
after clipping. The purple dashed border shows the root bounds after
144-
applying rootMargin.
145-
</Text>
146-
<View style={styles.legend}>
147-
<View style={styles.legendItem}>
148-
<View style={[styles.legendBox, styles.legendClipping]} />
149-
<Text style={styles.legendText}>Clipping Area (100x100)</Text>
150-
</View>
151-
<View style={styles.legendItem}>
152-
<View style={[styles.legendBox, styles.legendRoot]} />
153-
<Text style={styles.legendText}>Root (visible)</Text>
154-
</View>
155-
<View style={styles.legendItem}>
156-
<View style={[styles.legendBox, styles.legendTarget]} />
157-
<Text style={styles.legendText}>Target (visible)</Text>
158-
</View>
159-
<View style={styles.legendItem}>
160-
<View style={[styles.legendBox, styles.legendIndicator]} />
161-
<Text style={styles.legendText}>Full extent (dashed)</Text>
162-
</View>
163-
<View style={styles.legendItem}>
164-
<View style={[styles.legendBox, styles.legendRootMargin]} />
165-
<Text style={styles.legendText}>Root + Margin (purple)</Text>
125+
{!e2eTest && (
126+
<Text style={styles.description}>
127+
This example highlights a clipping parent to both the explicit root
128+
(blue) and target (yellow). The dashed borders show the full extent of
129+
the root and target, while the solid colors show what's actually
130+
visible after clipping. The purple dashed border shows the root bounds
131+
after applying rootMargin.
132+
</Text>
133+
)}
134+
{!e2eTest && (
135+
<View style={styles.legend}>
136+
<View style={styles.legendItem}>
137+
<View style={[styles.legendBox, styles.legendClipping]} />
138+
<Text style={styles.legendText}>Clipping Area (100x100)</Text>
139+
</View>
140+
<View style={styles.legendItem}>
141+
<View style={[styles.legendBox, styles.legendRoot]} />
142+
<Text style={styles.legendText}>Root (visible)</Text>
143+
</View>
144+
<View style={styles.legendItem}>
145+
<View style={[styles.legendBox, styles.legendTarget]} />
146+
<Text style={styles.legendText}>Target (visible)</Text>
147+
</View>
148+
<View style={styles.legendItem}>
149+
<View style={[styles.legendBox, styles.legendIndicator]} />
150+
<Text style={styles.legendText}>Full extent (dashed)</Text>
151+
</View>
152+
<View style={styles.legendItem}>
153+
<View style={[styles.legendBox, styles.legendRootMargin]} />
154+
<Text style={styles.legendText}>Root + Margin (purple)</Text>
155+
</View>
166156
</View>
167-
</View>
157+
)}
168158
<View style={styles.visualizationContainer}>
169159
<View style={styles.clippingParent}>
170160
<View ref={rootRef} style={styles.root}>
@@ -214,16 +204,19 @@ component IntersectionObserverCustomClippingRootExample() {
214204
{(intersectionEntry.intersectionRatio * 100).toFixed(1)}%
215205
</Text>
216206
<Text style={styles.metric}>
217-
Intersection Rect:{' '}
218-
{JSON.stringify(roundRect(intersectionEntry.intersectionRect))}
207+
{formatRect(
208+
'Intersection Rect',
209+
intersectionEntry.intersectionRect,
210+
)}
219211
</Text>
220212
<Text style={styles.metric}>
221-
Bounding Client Rect:{' '}
222-
{JSON.stringify(roundRect(intersectionEntry.boundingClientRect))}
213+
{formatRect(
214+
'Bounding Client Rect',
215+
intersectionEntry.boundingClientRect,
216+
)}
223217
</Text>
224218
<Text style={styles.metric}>
225-
Root Bounds:{' '}
226-
{JSON.stringify(roundRect(intersectionEntry.rootBounds))}
219+
{formatRect('Root Bounds', intersectionEntry.rootBounds)}
227220
</Text>
228221
</View>
229222
)}

packages/rn-tester/js/examples/IntersectionObserver/IntersectionObserverExplicitRootScroll.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ component IntersectionObserverExplicitRootScrollExample() {
6565
}}
6666
ref={roofRef}>
6767
<Button
68+
testID="toggle_margin"
6869
title={`Click to ${showMargin ? 'remove' : 'add'} margin`}
6970
onPress={() => {
7071
setShowMargin(show => !show);
@@ -148,6 +149,12 @@ function ListItem(props: {
148149
props.style,
149150
]}
150151
ref={itemRef}>
152+
{intersectionRatio >= props.threshold ? (
153+
<Text>Intersecting by threshold</Text>
154+
) : null}
155+
{intersectionRootRatio >= (props.rootThreshold ?? 1) ? (
156+
<Text>Intersecting by rootThreshold</Text>
157+
) : null}
151158
<Text style={styles.description}>{props.description}</Text>
152159
{props.rootThreshold != null && (
153160
<Text>rootThreshold: {props.rootThreshold}</Text>

0 commit comments

Comments
 (0)