main
js 125 lines 3.27 KB
Raw
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 * @emails react-core
8 * @jest-environment node
9 */
10
11 'use strict';
12
13 let React;
14 let ReactFabric;
15 let createReactNativeComponentClass;
16 let act;
17 let View;
18 let Text;
19
20 describe('Fabric FragmentRefs', () => {
21 beforeEach(() => {
22 jest.resetModules();
23
24 require('react-native/Libraries/ReactPrivate/InitializeNativeFabricUIManager');
25
26 React = require('react');
27 ReactFabric = require('react-native-renderer/fabric');
28 createReactNativeComponentClass =
29 require('react-native/react-private-interface')
30 .ReactNativeViewConfigRegistry.register;
31 ({act} = require('internal-test-utils'));
32 View = createReactNativeComponentClass('RCTView', () => ({
33 validAttributes: {nativeID: true},
34 uiViewClassName: 'RCTView',
35 }));
36 Text = createReactNativeComponentClass('RCTText', () => ({
37 validAttributes: {nativeID: true},
38 uiViewClassName: 'RCTText',
39 }));
40 });
41
42 // @gate enableFragmentRefs
43 it('attaches a ref to Fragment', async () => {
44 const fragmentRef = React.createRef();
45
46 await act(() =>
47 ReactFabric.render(
48 <View>
49 <React.Fragment ref={fragmentRef}>
50 <View>
51 <Text>Hi</Text>
52 </View>
53 </React.Fragment>
54 </View>,
55 11,
56 null,
57 true,
58 ),
59 );
60
61 expect(fragmentRef.current).not.toBe(null);
62 });
63
64 // @gate enableFragmentRefs
65 it('accepts a ref callback', async () => {
66 let fragmentRef;
67
68 await act(() => {
69 ReactFabric.render(
70 <React.Fragment ref={ref => (fragmentRef = ref)}>
71 <View nativeID="child">
72 <Text>Hi</Text>
73 </View>
74 </React.Fragment>,
75 11,
76 null,
77 true,
78 );
79 });
80
81 expect(fragmentRef && fragmentRef._fragmentFiber).toBeTruthy();
82 });
83
84 describe('observers', () => {
85 // @gate enableFragmentRefs
86 it('observes children, newly added children', async () => {
87 let logs = [];
88 const observer = {
89 observe: entry => {
90 // Here we reference internals because we don't need to mock the native observer
91 // We only need to test that each child node is observed on insertion
92 logs.push(entry.__internalInstanceHandle.pendingProps.nativeID);
93 },
94 };
95 function Test({showB}) {
96 const fragmentRef = React.useRef(null);
97 React.useEffect(() => {
98 fragmentRef.current.observeUsing(observer);
99 const lastRefValue = fragmentRef.current;
100 return () => {
101 lastRefValue.unobserveUsing(observer);
102 };
103 }, []);
104 return (
105 <View nativeID="parent">
106 <React.Fragment ref={fragmentRef}>
107 <View nativeID="A" />
108 {showB && <View nativeID="B" />}
109 </React.Fragment>
110 </View>
111 );
112 }
113
114 await act(() => {
115 ReactFabric.render(<Test showB={false} />, 11, null, true);
116 });
117 expect(logs).toEqual(['A']);
118 logs = [];
119 await act(() => {
120 ReactFabric.render(<Test showB={true} />, 11, null, true);
121 });
122 expect(logs).toEqual(['B']);
123 });
124 });
125 });