main
js 212 lines 5.57 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
8 'use strict';
9
10 // Mock of the Native Hooks
11
12 const roots = new Map();
13 const allocatedTags = new Set();
14
15 function dumpSubtree(info, indent) {
16 let out = '';
17 out += ' '.repeat(indent) + info.viewName + ' ' + JSON.stringify(info.props);
18 // eslint-disable-next-line no-for-of-loops/no-for-of-loops
19 for (const child of info.children) {
20 out += '\n' + dumpSubtree(child, indent + 2);
21 }
22 return out;
23 }
24
25 const RCTFabricUIManager = {
26 __dumpChildSetForJestTestsOnly: function (childSet) {
27 const result = [];
28 // eslint-disable-next-line no-for-of-loops/no-for-of-loops
29 for (const child of childSet) {
30 result.push(dumpSubtree(child, 0));
31 }
32 return result.join('\n');
33 },
34 __dumpHierarchyForJestTestsOnly: function () {
35 const result = [];
36 // eslint-disable-next-line no-for-of-loops/no-for-of-loops
37 for (const [rootTag, childSet] of roots) {
38 result.push(rootTag);
39 // eslint-disable-next-line no-for-of-loops/no-for-of-loops
40 for (const child of childSet) {
41 result.push(dumpSubtree(child, 1));
42 }
43 }
44 return result.join('\n');
45 },
46 createNode: jest.fn(
47 function createNode(reactTag, viewName, rootTag, props, eventTarget) {
48 if (allocatedTags.has(reactTag)) {
49 throw new Error(`Created two native views with tag ${reactTag}`);
50 }
51
52 allocatedTags.add(reactTag);
53 return {
54 reactTag: reactTag,
55 viewName: viewName,
56 props: props,
57 children: [],
58 };
59 },
60 ),
61 cloneNode: jest.fn(function cloneNode(node) {
62 return {
63 reactTag: node.reactTag,
64 viewName: node.viewName,
65 props: node.props,
66 children: node.children,
67 };
68 }),
69 cloneNodeWithNewChildren: jest.fn(
70 function cloneNodeWithNewChildren(node, children) {
71 return {
72 reactTag: node.reactTag,
73 viewName: node.viewName,
74 props: node.props,
75 children: children ?? [],
76 };
77 },
78 ),
79 cloneNodeWithNewProps: jest.fn(
80 function cloneNodeWithNewProps(node, newPropsDiff) {
81 return {
82 reactTag: node.reactTag,
83 viewName: node.viewName,
84 props: {...node.props, ...newPropsDiff},
85 children: node.children,
86 };
87 },
88 ),
89 cloneNodeWithNewChildrenAndProps: jest.fn(
90 function cloneNodeWithNewChildrenAndProps(node, newPropsDiff) {
91 let children = [];
92 if (arguments.length === 3) {
93 children = newPropsDiff;
94 newPropsDiff = arguments[2];
95 }
96
97 return {
98 reactTag: node.reactTag,
99 viewName: node.viewName,
100 props: {...node.props, ...newPropsDiff},
101 children,
102 };
103 },
104 ),
105 appendChild: jest.fn(function appendChild(parentNode, childNode) {
106 parentNode.children.push(childNode);
107 }),
108
109 createChildSet: jest.fn(function createChildSet() {
110 return [];
111 }),
112
113 appendChildToSet: jest.fn(function appendChildToSet(childSet, childNode) {
114 childSet.push(childNode);
115 }),
116
117 completeRoot: jest.fn(function completeRoot(rootTag, newChildSet) {
118 roots.set(rootTag, newChildSet);
119 }),
120
121 dispatchCommand: jest.fn(),
122
123 setNativeProps: jest.fn(),
124
125 sendAccessibilityEvent: jest.fn(),
126
127 registerEventHandler: jest.fn(function registerEventHandler(callback) {}),
128
129 measure: jest.fn(function measure(node, callback) {
130 if (typeof node !== 'object') {
131 throw new Error(
132 `Expected node to be an object, was passed "${typeof node}"`,
133 );
134 }
135
136 if (typeof node.viewName !== 'string') {
137 throw new Error('Expected node to be a host node.');
138 }
139
140 callback(10, 10, 100, 100, 0, 0);
141 }),
142 measureInWindow: jest.fn(function measureInWindow(node, callback) {
143 if (typeof node !== 'object') {
144 throw new Error(
145 `Expected node to be an object, was passed "${typeof node}"`,
146 );
147 }
148
149 if (typeof node.viewName !== 'string') {
150 throw new Error('Expected node to be a host node.');
151 }
152
153 callback(10, 10, 100, 100);
154 }),
155 getBoundingClientRect: jest.fn(function getBoundingClientRect(node) {
156 if (typeof node !== 'object') {
157 throw new Error(
158 `Expected node to be an object, was passed "${typeof node}"`,
159 );
160 }
161
162 if (typeof node.viewName !== 'string') {
163 throw new Error('Expected node to be a host node.');
164 }
165
166 return [10, 10, 100, 100];
167 }),
168 measureLayout: jest.fn(
169 function measureLayout(node, relativeNode, fail, success) {
170 if (typeof node !== 'object') {
171 throw new Error(
172 `Expected node to be an object, was passed "${typeof node}"`,
173 );
174 }
175
176 if (typeof node.viewName !== 'string') {
177 throw new Error('Expected node to be a host node.');
178 }
179
180 if (typeof relativeNode !== 'object') {
181 throw new Error(
182 `Expected relative node to be an object, was passed "${typeof relativeNode}"`,
183 );
184 }
185
186 if (typeof relativeNode.viewName !== 'string') {
187 throw new Error('Expected relative node to be a host node.');
188 }
189
190 success(1, 1, 100, 100);
191 },
192 ),
193 setIsJSResponder: jest.fn(),
194 };
195
196 global.nativeFabricUIManager = RCTFabricUIManager;
197
198 // DOMRect isn't provided by jsdom, but it's used by `ReactFabricHostComponent`.
199 // This is a basic implementation for testing.
200 global.DOMRect = class DOMRect {
201 constructor(x, y, width, height) {
202 this.x = x;
203 this.y = y;
204 this.width = width;
205 this.height = height;
206 }
207
208 toJSON() {
209 const {x, y, width, height} = this;
210 return {x, y, width, height};
211 }
212 };