Skip to content

Commit 90b2dd4

Browse files
authored
Add additional fixtures for FragmentInstance text node support (facebook#35631)
Stacked on facebook#35630 - Adds test case for compareDocumentPosition, missing before and also extending to text nodes - Adds event handling fixture case for text - Adds getRootNode fixture case for text
1 parent 875b064 commit 90b2dd4

File tree

7 files changed

+669
-48
lines changed

7 files changed

+669
-48
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import TestCase from '../../TestCase';
2+
import Fixture from '../../Fixture';
3+
import CompareDocumentPositionFragmentContainer from './CompareDocumentPositionFragmentContainer';
4+
5+
const React = window.React;
6+
7+
export default function CompareDocumentPositionCase() {
8+
return (
9+
<TestCase title="compareDocumentPosition">
10+
<TestCase.Steps>
11+
<li>Click the "Compare All Positions" button</li>
12+
</TestCase.Steps>
13+
<TestCase.ExpectedResult>
14+
The compareDocumentPosition method compares the position of the fragment
15+
relative to other elements in the DOM. The "Before Element" should be
16+
PRECEDING the fragment, and the "After Element" should be FOLLOWING.
17+
Elements inside the fragment should be CONTAINED_BY.
18+
</TestCase.ExpectedResult>
19+
<Fixture>
20+
<Fixture.Controls>
21+
<CompareDocumentPositionFragmentContainer>
22+
<div
23+
style={{
24+
padding: '10px',
25+
backgroundColor: 'lightblue',
26+
borderRadius: '4px',
27+
marginBottom: '8px',
28+
}}>
29+
First child element
30+
</div>
31+
<div
32+
style={{
33+
padding: '10px',
34+
backgroundColor: 'lightgreen',
35+
borderRadius: '4px',
36+
marginBottom: '8px',
37+
}}>
38+
Second child element
39+
</div>
40+
<div
41+
style={{
42+
padding: '10px',
43+
backgroundColor: 'lightpink',
44+
borderRadius: '4px',
45+
}}>
46+
Third child element
47+
</div>
48+
</CompareDocumentPositionFragmentContainer>
49+
</Fixture.Controls>
50+
</Fixture>
51+
</TestCase>
52+
);
53+
}
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
const React = window.React;
2+
const {Fragment, useRef, useState} = React;
3+
4+
const POSITION_FLAGS = {
5+
DISCONNECTED: 0x01,
6+
PRECEDING: 0x02,
7+
FOLLOWING: 0x04,
8+
CONTAINS: 0x08,
9+
CONTAINED_BY: 0x10,
10+
IMPLEMENTATION_SPECIFIC: 0x20,
11+
};
12+
13+
function getPositionDescription(bitmask) {
14+
const flags = [];
15+
if (bitmask & POSITION_FLAGS.DISCONNECTED) flags.push('DISCONNECTED');
16+
if (bitmask & POSITION_FLAGS.PRECEDING) flags.push('PRECEDING');
17+
if (bitmask & POSITION_FLAGS.FOLLOWING) flags.push('FOLLOWING');
18+
if (bitmask & POSITION_FLAGS.CONTAINS) flags.push('CONTAINS');
19+
if (bitmask & POSITION_FLAGS.CONTAINED_BY) flags.push('CONTAINED_BY');
20+
if (bitmask & POSITION_FLAGS.IMPLEMENTATION_SPECIFIC)
21+
flags.push('IMPLEMENTATION_SPECIFIC');
22+
return flags.length > 0 ? flags.join(' | ') : 'SAME';
23+
}
24+
25+
function ResultRow({label, result, color}) {
26+
if (!result) return null;
27+
28+
return (
29+
<div
30+
style={{
31+
padding: '10px 14px',
32+
marginBottom: '8px',
33+
backgroundColor: '#f8f9fa',
34+
borderLeft: `4px solid ${color}`,
35+
borderRadius: '4px',
36+
}}>
37+
<div
38+
style={{
39+
fontWeight: 'bold',
40+
marginBottom: '6px',
41+
color: '#333',
42+
}}>
43+
{label}
44+
</div>
45+
<div
46+
style={{
47+
display: 'grid',
48+
gridTemplateColumns: 'auto 1fr',
49+
gap: '4px 12px',
50+
fontSize: '13px',
51+
fontFamily: 'monospace',
52+
}}>
53+
<span style={{color: '#666'}}>Raw value:</span>
54+
<span style={{color: '#333'}}>{result.raw}</span>
55+
<span style={{color: '#666'}}>Flags:</span>
56+
<span style={{color: color, fontWeight: 500}}>
57+
{getPositionDescription(result.raw)}
58+
</span>
59+
</div>
60+
</div>
61+
);
62+
}
63+
64+
export default function CompareDocumentPositionFragmentContainer({children}) {
65+
const fragmentRef = useRef(null);
66+
const beforeRef = useRef(null);
67+
const afterRef = useRef(null);
68+
const insideRef = useRef(null);
69+
const [results, setResults] = useState(null);
70+
71+
const compareAll = () => {
72+
const fragment = fragmentRef.current;
73+
const beforePos = fragment.compareDocumentPosition(beforeRef.current);
74+
const afterPos = fragment.compareDocumentPosition(afterRef.current);
75+
const insidePos = insideRef.current
76+
? fragment.compareDocumentPosition(insideRef.current)
77+
: null;
78+
79+
setResults({
80+
before: {raw: beforePos},
81+
after: {raw: afterPos},
82+
inside: insidePos !== null ? {raw: insidePos} : null,
83+
});
84+
};
85+
86+
return (
87+
<Fragment>
88+
<div style={{marginBottom: '16px'}}>
89+
<button
90+
onClick={compareAll}
91+
style={{
92+
padding: '8px 16px',
93+
fontSize: '14px',
94+
fontWeight: 'bold',
95+
cursor: 'pointer',
96+
}}>
97+
Compare All Positions
98+
</button>
99+
{results && (
100+
<span style={{marginLeft: '12px', color: '#666'}}>
101+
Comparison complete
102+
</span>
103+
)}
104+
</div>
105+
106+
<div style={{display: 'flex', gap: '24px'}}>
107+
<div style={{flex: '0 0 300px'}}>
108+
<div
109+
style={{
110+
padding: '16px',
111+
backgroundColor: '#f0f0f0',
112+
borderRadius: '8px',
113+
}}>
114+
<div
115+
ref={beforeRef}
116+
style={{
117+
padding: '12px',
118+
backgroundColor: '#d4edda',
119+
border: '2px solid #28a745',
120+
borderRadius: '4px',
121+
marginBottom: '12px',
122+
textAlign: 'center',
123+
fontWeight: 'bold',
124+
color: '#155724',
125+
}}>
126+
Before Element
127+
</div>
128+
129+
<div
130+
style={{
131+
padding: '12px',
132+
backgroundColor: '#fff3cd',
133+
border: '2px dashed #ffc107',
134+
borderRadius: '4px',
135+
marginBottom: '12px',
136+
}}>
137+
<div
138+
style={{
139+
fontSize: '11px',
140+
color: '#856404',
141+
marginBottom: '8px',
142+
fontWeight: 'bold',
143+
}}>
144+
FRAGMENT
145+
</div>
146+
<div ref={insideRef}>
147+
<Fragment ref={fragmentRef}>{children}</Fragment>
148+
</div>
149+
</div>
150+
151+
<div
152+
ref={afterRef}
153+
style={{
154+
padding: '12px',
155+
backgroundColor: '#f8d7da',
156+
border: '2px solid #dc3545',
157+
borderRadius: '4px',
158+
textAlign: 'center',
159+
fontWeight: 'bold',
160+
color: '#721c24',
161+
}}>
162+
After Element
163+
</div>
164+
</div>
165+
</div>
166+
167+
<div style={{flex: 1}}>
168+
<div
169+
style={{
170+
fontSize: '14px',
171+
fontWeight: 'bold',
172+
marginBottom: '12px',
173+
color: '#333',
174+
}}>
175+
Comparison Results
176+
</div>
177+
178+
{!results && (
179+
<div
180+
style={{
181+
padding: '20px',
182+
backgroundColor: '#f8f9fa',
183+
borderRadius: '4px',
184+
color: '#666',
185+
textAlign: 'center',
186+
}}>
187+
Click "Compare All Positions" to see results
188+
</div>
189+
)}
190+
191+
{results && (
192+
<Fragment>
193+
<ResultRow
194+
label='vs "Before Element"'
195+
result={results.before}
196+
color="#28a745"
197+
/>
198+
<ResultRow
199+
label='vs "After Element"'
200+
result={results.after}
201+
color="#dc3545"
202+
/>
203+
{results.inside && (
204+
<ResultRow
205+
label='vs "Inside Element"'
206+
result={results.inside}
207+
color="#ffc107"
208+
/>
209+
)}
210+
211+
<div
212+
style={{
213+
marginTop: '16px',
214+
padding: '12px',
215+
backgroundColor: '#e7f3ff',
216+
borderRadius: '4px',
217+
fontSize: '12px',
218+
color: '#0c5460',
219+
}}>
220+
<strong>Flag Reference:</strong>
221+
<div
222+
style={{
223+
marginTop: '8px',
224+
display: 'grid',
225+
gridTemplateColumns: 'auto 1fr',
226+
gap: '2px 12px',
227+
}}>
228+
<code>0x01</code>
229+
<span>DISCONNECTED</span>
230+
<code>0x02</code>
231+
<span>PRECEDING (other is before fragment)</span>
232+
<code>0x04</code>
233+
<span>FOLLOWING (other is after fragment)</span>
234+
<code>0x08</code>
235+
<span>CONTAINS (other contains fragment)</span>
236+
<code>0x10</code>
237+
<span>CONTAINED_BY (other is inside fragment)</span>
238+
</div>
239+
</div>
240+
</Fragment>
241+
)}
242+
</div>
243+
</div>
244+
</Fragment>
245+
);
246+
}

0 commit comments

Comments
 (0)