From 248930887164b7669c53fb3e0007f443b78fcf2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Fri, 25 Apr 2025 09:22:02 -0700 Subject: [PATCH] Improve pattern to access host instances in tests (#50938) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/50938 Changelog: [internal] No more `maybeNode`s. Using ref objects makes the tests cleaner and the JSX easier to read than injecting lambdas. This speaks for itself: * 617 lines added * 1393 lines removed {F1977434870} Reviewed By: lenaic Differential Revision: D73659018 fbshipit-source-id: d1c23e6457bb1d351ce02b9f6fa8778b06ee0e55 --- .../src/__tests__/Fantom-itest.js | 120 ++-- .../ScrollView/__tests__/ScrollView-itest.js | 18 +- .../__tests__/ScrollView-viewCulling-itest.js | 149 ++--- .../TextInput/__tests__/TextInput-itest.js | 35 +- .../__tests__/InterruptibleRendering-itest.js | 77 +-- .../State-ForcedCloneCommitHook-itest.js | 12 +- .../__tests__/UIConsistency-itest.js | 26 +- .../mounting/__tests__/Mounting-itest.js | 36 +- .../__tests__/ReactNativeDocument-itest.js | 92 +-- .../__tests__/ReactNativeElement-itest.js | 550 ++++++------------ .../dom/nodes/__tests__/ReadOnlyText-itest.js | 172 ++---- .../IntersectionObserver-benchmark-itest.js | 62 +- .../__tests__/IntersectionObserver-itest.js | 288 +++------ .../__tests__/MutationObserver-itest.js | 373 ++++-------- 14 files changed, 617 insertions(+), 1393 deletions(-) diff --git a/packages/react-native-fantom/src/__tests__/Fantom-itest.js b/packages/react-native-fantom/src/__tests__/Fantom-itest.js index 41139758cae..a30c058464d 100644 --- a/packages/react-native-fantom/src/__tests__/Fantom-itest.js +++ b/packages/react-native-fantom/src/__tests__/Fantom-itest.js @@ -12,6 +12,7 @@ import 'react-native/Libraries/Core/InitializeCore'; import type {Root} from '@react-native/fantom'; +import type {HostInstance} from 'react-native'; import * as Fantom from '@react-native/fantom'; import * as React from 'react'; @@ -421,22 +422,16 @@ describe('Fantom', () => { describe('runOnUIThread + enqueueNativeEvent', () => { it('sends event without payload', () => { const root = Fantom.createRoot(); - let maybeNode; let focusEvent = jest.fn(); + const ref = React.createRef(); + Fantom.runTask(() => { - root.render( - { - maybeNode = node; - }} - />, - ); + root.render(); }); - const element = ensureInstance(maybeNode, ReactNativeElement); + const element = ensureInstance(ref.current, ReactNativeElement); expect(focusEvent).toHaveBeenCalledTimes(0); @@ -454,7 +449,7 @@ describe('Fantom', () => { it('sends event with payload', () => { const root = Fantom.createRoot(); - let maybeNode; + const ref = React.createRef(); const onChange = jest.fn(); Fantom.runTask(() => { @@ -463,14 +458,12 @@ describe('Fantom', () => { onChange={event => { onChange(event.nativeEvent); }} - ref={node => { - maybeNode = node; - }} + ref={ref} />, ); }); - const element = ensureInstance(maybeNode, ReactNativeElement); + const element = ensureInstance(ref.current, ReactNativeElement); Fantom.runOnUIThread(() => { Fantom.enqueueNativeEvent(element, 'change', { @@ -487,7 +480,7 @@ describe('Fantom', () => { it('it batches events with isUnique option', () => { const root = Fantom.createRoot(); - let maybeNode; + const ref = React.createRef(); const onScroll = jest.fn(); Fantom.runTask(() => { @@ -496,14 +489,12 @@ describe('Fantom', () => { onScroll={event => { onScroll(event.nativeEvent); }} - ref={node => { - maybeNode = node; - }} + ref={ref} />, ); }); - const element = ensureInstance(maybeNode, ReactNativeElement); + const element = ensureInstance(ref.current, ReactNativeElement); Fantom.runOnUIThread(() => { Fantom.enqueueNativeEvent(element, 'scroll', { @@ -541,22 +532,15 @@ describe('Fantom', () => { describe('dispatchNativeEvent', () => { it('flushes the event and runs the work loop', () => { const root = Fantom.createRoot(); - let maybeNode; + const ref = React.createRef(); let focusEvent = jest.fn(); Fantom.runTask(() => { - root.render( - { - maybeNode = node; - }} - />, - ); + root.render(); }); - const element = ensureInstance(maybeNode, ReactNativeElement); + const element = ensureInstance(ref.current, ReactNativeElement); expect(focusEvent).toHaveBeenCalledTimes(0); @@ -569,19 +553,13 @@ describe('Fantom', () => { describe('enqueueScrollEvent', () => { it('throws error if called on node that is not scroll view', () => { const root = Fantom.createRoot(); - let maybeNode; + const ref = React.createRef(); Fantom.runTask(() => { - root.render( - { - maybeNode = node; - }} - />, - ); + root.render(); }); - const element = ensureInstance(maybeNode, ReactNativeElement); + const element = ensureInstance(ref.current, ReactNativeElement); expect(() => { Fantom.runOnUIThread(() => { @@ -597,8 +575,8 @@ describe('Fantom', () => { it('delivers onScroll event and affects position of elements on screen', () => { const root = Fantom.createRoot(); - let maybeScrollViewNode; - let maybeNode; + const viewRef = React.createRef(); + const scrollViewRef = React.createRef(); const onScroll = jest.fn(); Fantom.runTask(() => { @@ -607,21 +585,14 @@ describe('Fantom', () => { onScroll={event => { onScroll(event.nativeEvent); }} - ref={node => { - maybeScrollViewNode = node; - }}> - { - maybeNode = node; - }} - /> + ref={scrollViewRef}> + , ); }); const scrollViewElement = ensureInstance( - maybeScrollViewNode, + scrollViewRef.current, ReactNativeElement, ); @@ -636,7 +607,7 @@ describe('Fantom', () => { expect(onScroll).toHaveBeenCalledTimes(1); - const viewElement = ensureInstance(maybeNode, ReactNativeElement); + const viewElement = ensureInstance(viewRef.current, ReactNativeElement); let rect; @@ -673,19 +644,13 @@ describe('Fantom', () => { describe('scrollTo', () => { it('throws error if called on node that is not scroll view', () => { const root = Fantom.createRoot(); - let maybeNode; + const ref = React.createRef(); Fantom.runTask(() => { - root.render( - { - maybeNode = node; - }} - />, - ); + root.render(); }); - const element = ensureInstance(maybeNode, ReactNativeElement); + const element = ensureInstance(ref.current, ReactNativeElement); expect(() => { Fantom.scrollTo(element, { @@ -699,8 +664,8 @@ describe('Fantom', () => { it('delivers onScroll event and affects position of elements on screen', () => { const root = Fantom.createRoot(); - let maybeScrollViewNode; - let maybeNode; + const scrollViewRef = React.createRef(); + const viewRef = React.createRef(); const onScroll = jest.fn(); Fantom.runTask(() => { @@ -709,21 +674,14 @@ describe('Fantom', () => { onScroll={event => { onScroll(event.nativeEvent); }} - ref={node => { - maybeScrollViewNode = node; - }}> - { - maybeNode = node; - }} - /> + ref={scrollViewRef}> + , ); }); const scrollViewElement = ensureInstance( - maybeScrollViewNode, + scrollViewRef.current, ReactNativeElement, ); @@ -738,7 +696,7 @@ describe('Fantom', () => { expect(onScroll).toHaveBeenCalledTimes(1); - const viewElement = ensureInstance(maybeNode, ReactNativeElement); + const viewElement = ensureInstance(viewRef.current, ReactNativeElement); let rect; @@ -798,19 +756,13 @@ describe('Fantom', () => { describe('enqueueModalSizeUpdate', () => { it('throws error if called on node that is not ', () => { const root = Fantom.createRoot(); - let maybeNode; + const ref = React.createRef(); Fantom.runTask(() => { - root.render( - { - maybeNode = node; - }} - />, - ); + root.render(); }); - const element = ensureInstance(maybeNode, ReactNativeElement); + const element = ensureInstance(ref.current, ReactNativeElement); expect(() => { Fantom.runOnUIThread(() => { @@ -832,7 +784,7 @@ describe('Fantom', () => { Fantom.runTask(() => { root.render( ) => { + ref={(node: ?HostInstance) => { maybeModalNode = node; }}> { it('delivers onScroll event', () => { const root = Fantom.createRoot(); - let maybeNode; + const scrollViewRef = React.createRef(); const onScroll = jest.fn(); Fantom.runTask(() => { @@ -29,14 +31,12 @@ describe('onScroll', () => { onScroll={event => { onScroll(event.nativeEvent); }} - ref={node => { - maybeNode = node; - }} + ref={scrollViewRef} />, ); }); - const element = ensureInstance(maybeNode, ReactNativeElement); + const element = ensureInstance(scrollViewRef.current, ReactNativeElement); Fantom.runOnUIThread(() => { Fantom.enqueueNativeEvent( @@ -66,7 +66,7 @@ describe('onScroll', () => { it('batches onScroll event per UI tick', () => { const root = Fantom.createRoot(); - let maybeNode; + const scrollViewRef = React.createRef(); const onScroll = jest.fn(); Fantom.runTask(() => { @@ -75,14 +75,12 @@ describe('onScroll', () => { onScroll={event => { onScroll(event.nativeEvent); }} - ref={node => { - maybeNode = node; - }} + ref={scrollViewRef} />, ); }); - const element = ensureInstance(maybeNode, ReactNativeElement); + const element = ensureInstance(scrollViewRef.current, ReactNativeElement); Fantom.runOnUIThread(() => { Fantom.enqueueNativeEvent(element, 'scroll', { diff --git a/packages/react-native/Libraries/Components/ScrollView/__tests__/ScrollView-viewCulling-itest.js b/packages/react-native/Libraries/Components/ScrollView/__tests__/ScrollView-viewCulling-itest.js index c80348ff0a5..d35ce874e3b 100644 --- a/packages/react-native/Libraries/Components/ScrollView/__tests__/ScrollView-viewCulling-itest.js +++ b/packages/react-native/Libraries/Components/ScrollView/__tests__/ScrollView-viewCulling-itest.js @@ -14,6 +14,8 @@ import 'react-native/Libraries/Core/InitializeCore.js'; +import type {HostInstance} from 'react-native'; + import ensureInstance from '../../../../src/private/__tests__/utilities/ensureInstance'; import * as Fantom from '@react-native/fantom'; import * as React from 'react'; @@ -22,15 +24,11 @@ import ReactNativeElement from 'react-native/src/private/webapis/dom/nodes/React test('basic culling', () => { const root = Fantom.createRoot({viewportWidth: 100, viewportHeight: 100}); - let maybeNode; + const nodeRef = React.createRef(); Fantom.runTask(() => { root.render( - { - maybeNode = node; - }}> + { 'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}', ]); - const element = ensureInstance(maybeNode, ReactNativeElement); + const element = ensureInstance(nodeRef.current, ReactNativeElement); Fantom.scrollTo(element, { x: 0, @@ -80,15 +78,11 @@ test('basic culling', () => { test('recursive culling', () => { const root = Fantom.createRoot({viewportHeight: 100, viewportWidth: 100}); - let maybeNode; + const nodeRef = React.createRef(); Fantom.runTask(() => { root.render( - { - maybeNode = node; - }}> + @@ -125,7 +119,7 @@ test('recursive culling', () => { 'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}', ]); - const element = ensureInstance(maybeNode, ReactNativeElement); + const element = ensureInstance(nodeRef.current, ReactNativeElement); // === Scroll down to the edge of child AA === Fantom.scrollTo(element, { @@ -241,16 +235,14 @@ test('recursive culling', () => { test('recursive culling when initial offset is negative', () => { const root = Fantom.createRoot({viewportHeight: 874, viewportWidth: 402}); - let maybeNode; + const nodeRef = React.createRef(); Fantom.runTask(() => { root.render( { - maybeNode = node; - }}> + ref={nodeRef}> { 'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}', ]); - const element = ensureInstance(maybeNode, ReactNativeElement); + const element = ensureInstance(nodeRef.current, ReactNativeElement); Fantom.scrollTo(element, { x: 0, @@ -298,15 +290,11 @@ test('recursive culling when initial offset is negative', () => { test('deep nesting', () => { const root = Fantom.createRoot({viewportHeight: 100, viewportWidth: 100}); - let maybeNode; + const nodeRef = React.createRef(); Fantom.runTask(() => { root.render( - { - maybeNode = node; - }}> + { 'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}', ]); - const element = ensureInstance(maybeNode, ReactNativeElement); + const element = ensureInstance(nodeRef.current, ReactNativeElement); Fantom.scrollTo(element, { x: 0, @@ -469,16 +457,14 @@ test('adding new item into area that is culled', () => { }); test('initial render', () => { - let maybeNode; + const nodeRef = React.createRef(); const root = Fantom.createRoot({viewportHeight: 100, viewportWidth: 100}); Fantom.runTask(() => { root.render( { - maybeNode = node; - }} + ref={nodeRef} style={{height: 100, width: 100}}> { 'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}', ]); - const element = ensureInstance(maybeNode, ReactNativeElement); + const element = ensureInstance(nodeRef.current, ReactNativeElement); Fantom.scrollTo(element, { x: 0, @@ -555,16 +541,12 @@ test('unmounting culled elements', () => { // TODO: only elements in ScrollView are culled. test('basic culling smaller ScrollView', () => { - let maybeNode; + const nodeRef = React.createRef(); const root = Fantom.createRoot({viewportWidth: 100, viewportHeight: 100}); Fantom.runTask(() => { root.render( - { - maybeNode = node; - }} - style={{height: 50, width: 50, marginTop: 25}}> + , ); @@ -580,7 +562,7 @@ test('basic culling smaller ScrollView', () => { 'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}', ]); - const element = ensureInstance(maybeNode, ReactNativeElement); + const element = ensureInstance(nodeRef.current, ReactNativeElement); Fantom.scrollTo(element, { x: 0, @@ -617,15 +599,11 @@ test('views are not culled when outside of viewport', () => { test('culling with transform move', () => { const root = Fantom.createRoot({viewportWidth: 100, viewportHeight: 100}); - let maybeNode; + const nodeRef = React.createRef(); Fantom.runTask(() => { root.render( - { - maybeNode = node; - }}> + { 'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}', ]); - const element = ensureInstance(maybeNode, ReactNativeElement); + const element = ensureInstance(nodeRef.current, ReactNativeElement); Fantom.scrollTo(element, { x: 0, @@ -663,15 +641,11 @@ test('culling with transform move', () => { test('culling with recursive transform move', () => { const root = Fantom.createRoot({viewportWidth: 100, viewportHeight: 100}); - let maybeNode; + const nodeRef = React.createRef(); Fantom.runTask(() => { root.render( - { - maybeNode = node; - }}> + { 'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}', ]); - const element = ensureInstance(maybeNode, ReactNativeElement); + const element = ensureInstance(nodeRef.current, ReactNativeElement); Fantom.scrollTo(element, { x: 0, @@ -712,15 +686,11 @@ test('culling with recursive transform move', () => { test('culling with transform scale', () => { const root = Fantom.createRoot({viewportWidth: 100, viewportHeight: 100}); - let maybeNode; + const nodeRef = React.createRef(); Fantom.runTask(() => { root.render( - { - maybeNode = node; - }}> + { 'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}', ]); - const element = ensureInstance(maybeNode, ReactNativeElement); + const element = ensureInstance(nodeRef.current, ReactNativeElement); Fantom.scrollTo(element, { x: 0, @@ -791,7 +761,7 @@ test('culling when ScrollView parent has transform', () => { test('culling inside of Modal', () => { const root = Fantom.createRoot({viewportWidth: 100, viewportHeight: 100}); - let maybeNode; + const nodeRef = React.createRef(); Fantom.runTask(() => { root.render( @@ -800,16 +770,12 @@ test('culling inside of Modal', () => { - ) => { - maybeNode = node; - }} - /> + , ); }); - const element = ensureInstance(maybeNode, ReactNativeElement); + const element = ensureInstance(nodeRef.current, ReactNativeElement); Fantom.runOnUIThread(() => { Fantom.enqueueModalSizeUpdate(element, { @@ -836,10 +802,7 @@ test('culling inside of Modal', () => { - ) => { - maybeNode = node; - }}> + { describe('reparenting', () => { test('view flattening with culling', () => { const root = Fantom.createRoot({viewportWidth: 100, viewportHeight: 100}); - let maybeNode; + const nodeRef = React.createRef(); Fantom.runTask(() => { root.render( - { - maybeNode = node; - }}> + { 'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}', ]); - const element = ensureInstance(maybeNode, ReactNativeElement); + const element = ensureInstance(nodeRef.current, ReactNativeElement); Fantom.scrollTo(element, { x: 0, @@ -904,11 +863,7 @@ describe('reparenting', () => { // force view to be unflattened. Fantom.runTask(() => { root.render( - { - maybeNode = node; - }}> + { // force view to be flattened. Fantom.runTask(() => { root.render( - { - maybeNode = node; - }}> + { 'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}', ]); - let maybeNode = null; + const nodeRef = React.createRef(); // Now update opacity to unflattned the container and add a child that has a culled descendant. Fantom.runTask(() => { root.render( { - maybeNode = node; - }} + ref={nodeRef} contentOffset={{x: 0, y: 111}}> { 'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: "child"}', ]); - const element = ensureInstance(maybeNode, ReactNativeElement); + const element = ensureInstance(nodeRef.current, ReactNativeElement); // Scroll down to see the grandchild. Fantom.scrollTo(element, { @@ -1509,16 +1458,14 @@ describe('reparenting', () => { 'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}', ]); - let maybeNode = null; + const nodeRef = React.createRef(); // Now change unflattened view container to flattened and change its child to be unflattened. Fantom.runTask(() => { root.render( { - maybeNode = node; - }} + ref={nodeRef} contentOffset={{x: 0, y: 60}}> { 'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: (N/A)}', ]); - const element = ensureInstance(maybeNode, ReactNativeElement); + const element = ensureInstance(nodeRef.current, ReactNativeElement); // Scroll to reveal grandchild. Fantom.scrollTo(element, { @@ -1601,16 +1548,14 @@ describe('reparenting', () => { 'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}', ]); - let maybeNode = null; + const nodeRef = React.createRef(); // Now change unflattened view container to flattened and change its child to be unflattened. Fantom.runTask(() => { root.render( { - maybeNode = node; - }} + ref={nodeRef} contentOffset={{x: 0, y: 60}}> { 'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: (N/A)}', ]); - const element = ensureInstance(maybeNode, ReactNativeElement); + const element = ensureInstance(nodeRef.current, ReactNativeElement); // Scroll to reveal grandchild. Fantom.scrollTo(element, { diff --git a/packages/react-native/Libraries/Components/TextInput/__tests__/TextInput-itest.js b/packages/react-native/Libraries/Components/TextInput/__tests__/TextInput-itest.js index 7686c7caed7..8627613dc9c 100644 --- a/packages/react-native/Libraries/Components/TextInput/__tests__/TextInput-itest.js +++ b/packages/react-native/Libraries/Components/TextInput/__tests__/TextInput-itest.js @@ -11,6 +11,8 @@ import 'react-native/Libraries/Core/InitializeCore'; +import type {HostInstance} from 'react-native'; + import ensureInstance from '../../../../src/private/__tests__/utilities/ensureInstance'; import * as Fantom from '@react-native/fantom'; import * as React from 'react'; @@ -100,24 +102,18 @@ describe('focus view command', () => { describe('focus and blur event', () => { it('sends focus and blur events', () => { const root = Fantom.createRoot(); - let maybeNode; + const nodeRef = React.createRef(); let focusEvent = jest.fn(); let blurEvent = jest.fn(); Fantom.runTask(() => { root.render( - { - maybeNode = node; - }} - />, + , ); }); - const element = ensureInstance(maybeNode, ReactNativeElement); + const element = ensureInstance(nodeRef.current, ReactNativeElement); expect(focusEvent).toHaveBeenCalledTimes(0); expect(blurEvent).toHaveBeenCalledTimes(0); @@ -149,7 +145,7 @@ describe('focus and blur event', () => { describe('onChange', () => { it('delivers onChange event', () => { const root = Fantom.createRoot(); - let maybeNode; + const nodeRef = React.createRef(); const onChange = jest.fn(); Fantom.runTask(() => { @@ -158,14 +154,12 @@ describe('onChange', () => { onChange={event => { onChange(event.nativeEvent); }} - ref={node => { - maybeNode = node; - }} + ref={nodeRef} />, ); }); - const element = ensureInstance(maybeNode, ReactNativeElement); + const element = ensureInstance(nodeRef.current, ReactNativeElement); Fantom.runOnUIThread(() => { Fantom.enqueueNativeEvent(element, 'change', { @@ -184,21 +178,14 @@ describe('onChange', () => { describe('onChangeText', () => { it('delivers onChangeText event', () => { const root = Fantom.createRoot(); - let maybeNode; + const nodeRef = React.createRef(); const onChangeText = jest.fn(); Fantom.runTask(() => { - root.render( - { - maybeNode = node; - }} - />, - ); + root.render(); }); - const element = ensureInstance(maybeNode, ReactNativeElement); + const element = ensureInstance(nodeRef.current, ReactNativeElement); Fantom.runOnUIThread(() => { Fantom.enqueueNativeEvent(element, 'change', { diff --git a/packages/react-native/Libraries/ReactNative/__tests__/InterruptibleRendering-itest.js b/packages/react-native/Libraries/ReactNative/__tests__/InterruptibleRendering-itest.js index 80c5adf56fe..e5711f04a48 100644 --- a/packages/react-native/Libraries/ReactNative/__tests__/InterruptibleRendering-itest.js +++ b/packages/react-native/Libraries/ReactNative/__tests__/InterruptibleRendering-itest.js @@ -11,6 +11,8 @@ import 'react-native/Libraries/Core/InitializeCore'; +import type {HostInstance} from 'react-native'; + import ensureInstance from '../../../src/private/__tests__/utilities/ensureInstance'; import * as Fantom from '@react-native/fantom'; import * as React from 'react'; @@ -26,9 +28,9 @@ function ensureReactNativeElement(value: mixed): ReactNativeElement { describe('discrete event category', () => { it('interrupts React rendering and higher priority update is committed first', () => { const root = Fantom.createRoot(); - let maybeTextInputNode; - let importantTextNode; - let deferredTextNode; + const textInputRef = React.createRef(); + const importantTextNodeRef = React.createRef(); + const deferredTextNodeRef = React.createRef(); let interruptRendering = false; let effectMock = jest.fn(); let afterUpdate; @@ -40,7 +42,7 @@ describe('discrete event category', () => { if (interruptRendering) { interruptRendering = false; - const element = ensureReactNativeElement(maybeTextInputNode); + const element = ensureReactNativeElement(textInputRef.current); Fantom.runOnUIThread(() => { Fantom.enqueueNativeEvent( element, @@ -64,24 +66,9 @@ describe('discrete event category', () => { return ( <> - { - maybeTextInputNode = node; - }} - /> - { - importantTextNode = node; - }}> - Important text: {text} - - { - deferredTextNode = node; - }}> - Deferred text: {deferredText} - + + Important text: {text} + Deferred text: {deferredText} ); } @@ -90,10 +77,12 @@ describe('discrete event category', () => { root.render(); }); - const importantTextNativeElement = - ensureReactNativeElement(importantTextNode); - const deferredTextNativeElement = - ensureReactNativeElement(deferredTextNode); + const importantTextNativeElement = ensureReactNativeElement( + importantTextNodeRef.current, + ); + const deferredTextNativeElement = ensureReactNativeElement( + deferredTextNodeRef.current, + ); expect(importantTextNativeElement.textContent).toBe( 'Important text: initial text', @@ -146,9 +135,9 @@ describe('discrete event category', () => { describe('continuous event category', () => { it('interrupts React rendering but update from continous event is delayed', () => { const root = Fantom.createRoot(); - let maybeTextInputNode; - let importantTextNode; - let deferredTextNode; + const textInputRef = React.createRef(); + const importantTextNodeRef = React.createRef(); + const deferredTextNodeRef = React.createRef(); let interruptRendering = false; let effectMock = jest.fn(); @@ -159,7 +148,7 @@ describe('continuous event category', () => { if (interruptRendering) { interruptRendering = false; - const element = ensureReactNativeElement(maybeTextInputNode); + const element = ensureReactNativeElement(textInputRef.current); Fantom.runOnUIThread(() => { Fantom.enqueueNativeEvent( element, @@ -188,22 +177,10 @@ describe('continuous event category', () => { `start: ${event.nativeEvent.selection.start}, end: ${event.nativeEvent.selection.end}`, ); }} - ref={node => { - maybeTextInputNode = node; - }} + ref={textInputRef} /> - { - importantTextNode = node; - }}> - Important text: {text} - - { - deferredTextNode = node; - }}> - Deferred text: {deferredText} - + Important text: {text} + Deferred text: {deferredText} ); } @@ -212,10 +189,12 @@ describe('continuous event category', () => { root.render(); }); - const importantTextNativeElement = - ensureReactNativeElement(importantTextNode); - const deferredTextNativeElement = - ensureReactNativeElement(deferredTextNode); + const importantTextNativeElement = ensureReactNativeElement( + importantTextNodeRef.current, + ); + const deferredTextNativeElement = ensureReactNativeElement( + deferredTextNodeRef.current, + ); expect(importantTextNativeElement.textContent).toBe( 'Important text: initial text', diff --git a/packages/react-native/Libraries/ReactNative/__tests__/State-ForcedCloneCommitHook-itest.js b/packages/react-native/Libraries/ReactNative/__tests__/State-ForcedCloneCommitHook-itest.js index 5430a4f470c..35985de655c 100644 --- a/packages/react-native/Libraries/ReactNative/__tests__/State-ForcedCloneCommitHook-itest.js +++ b/packages/react-native/Libraries/ReactNative/__tests__/State-ForcedCloneCommitHook-itest.js @@ -12,6 +12,8 @@ import 'react-native/Libraries/Core/InitializeCore'; +import type {HostInstance} from 'react-native'; + import ensureInstance from '../../../src/private/__tests__/utilities/ensureInstance'; import * as Fantom from '@react-native/fantom'; import * as React from 'react'; @@ -24,23 +26,19 @@ NativeFantomForcedCloneCommitHook.setup(); describe('ScrollViewShadowNode', () => { it('maintains state after commit hook processing', () => { const root = Fantom.createRoot(); - let maybeScrollViewNode; + const scrollViewRef = React.createRef(); Fantom.runTask(() => { root.render( - { - maybeScrollViewNode = node; - }} - /> + , ); }); const scrollViewElement = ensureInstance( - maybeScrollViewNode, + scrollViewRef.current, ReactNativeElement, ); diff --git a/packages/react-native/src/private/renderer/consistency/__tests__/UIConsistency-itest.js b/packages/react-native/src/private/renderer/consistency/__tests__/UIConsistency-itest.js index 1e1185c6d31..6d2a6549c7c 100644 --- a/packages/react-native/src/private/renderer/consistency/__tests__/UIConsistency-itest.js +++ b/packages/react-native/src/private/renderer/consistency/__tests__/UIConsistency-itest.js @@ -13,6 +13,8 @@ import 'react-native/Libraries/Core/InitializeCore'; +import type {HostInstance} from 'react-native'; + import ensureInstance from '../../../__tests__/utilities/ensureInstance'; import * as Fantom from '@react-native/fantom'; import * as React from 'react'; @@ -24,14 +26,12 @@ describe('UIConsistency', () => { it('should provide consistent data from the tree within the same synchronous function', () => { const root = Fantom.createRoot(); - let maybeScrollViewNode; + const scrollViewRef = React.createRef(); Fantom.runTask(() => { root.render( { - maybeScrollViewNode = node; - }} + ref={scrollViewRef} style={{height: 100}} contentContainerStyle={{height: 1000}} />, @@ -39,7 +39,7 @@ describe('UIConsistency', () => { }); const scrollViewNode = ensureInstance( - maybeScrollViewNode, + scrollViewRef.current, ReactNativeElement, ); @@ -59,14 +59,12 @@ describe('UIConsistency', () => { it('should provide up-to-date data in the first access to the tree', () => { const root = Fantom.createRoot(); - let maybeScrollViewNode; + const scrollViewRef = React.createRef(); Fantom.runTask(() => { root.render( { - maybeScrollViewNode = node; - }} + ref={scrollViewRef} style={{height: 100}} contentContainerStyle={{height: 1000}} />, @@ -74,7 +72,7 @@ describe('UIConsistency', () => { }); const scrollViewNode = ensureInstance( - maybeScrollViewNode, + scrollViewRef.current, ReactNativeElement, ); @@ -93,7 +91,7 @@ describe('UIConsistency', () => { it('should provide up-to-date data after commit', () => { const root = Fantom.createRoot(); - let maybeScrollViewNode; + const scrollViewRef = React.createRef(); function InnerComponent(props: { text: string, @@ -114,9 +112,7 @@ describe('UIConsistency', () => { Fantom.runTask(() => { root.render( { - maybeScrollViewNode = node; - }} + ref={scrollViewRef} style={{height: 100}} contentContainerStyle={{height: 1000}}> @@ -125,7 +121,7 @@ describe('UIConsistency', () => { }); const scrollViewNode = ensureInstance( - maybeScrollViewNode, + scrollViewRef.current, ReactNativeElement, ); diff --git a/packages/react-native/src/private/renderer/mounting/__tests__/Mounting-itest.js b/packages/react-native/src/private/renderer/mounting/__tests__/Mounting-itest.js index 8d5c22905a4..0fe39d08cbd 100644 --- a/packages/react-native/src/private/renderer/mounting/__tests__/Mounting-itest.js +++ b/packages/react-native/src/private/renderer/mounting/__tests__/Mounting-itest.js @@ -12,6 +12,8 @@ import 'react-native/Libraries/Core/InitializeCore'; +import type {HostInstance} from 'react-native'; + import ensureInstance from '../../../__tests__/utilities/ensureInstance'; import * as Fantom from '@react-native/fantom'; import * as React from 'react'; @@ -354,14 +356,12 @@ test('parent-child switching from flattened-unflattened to unflattened-flattened describe('reconciliation of setNativeProps and React commit', () => { it('props set by setNativeProps must not be overriden by React commit', () => { const root = Fantom.createRoot(); - let maybeNode; + const nodeRef = React.createRef(); Fantom.runTask(() => { root.render( { - maybeNode = node; - }} + ref={nodeRef} nativeID="first native id" testID="first test id" />, @@ -378,7 +378,7 @@ describe('reconciliation of setNativeProps and React commit', () => { , ); - const element = ensureInstance(maybeNode, ReactNativeElement); + const element = ensureInstance(nodeRef.current, ReactNativeElement); Fantom.runTask(() => { // Calling `setNativeProps` forces bug https://github.com/facebook/react-native/issues/47476 to manifest. @@ -401,9 +401,7 @@ describe('reconciliation of setNativeProps and React commit', () => { Fantom.runTask(() => { root.render( { - maybeNode = node; - }} + ref={nodeRef} nativeID="second native id" // testID was changed by `setNativeProps` and React does not know about it. // Therefore, it will treat testID as unchanged. @@ -426,17 +424,10 @@ describe('reconciliation of setNativeProps and React commit', () => { it('allows React commit to override value set by setNativeProps', () => { const root = Fantom.createRoot(); - let maybeNode; + const nodeRef = React.createRef(); Fantom.runTask(() => { - root.render( - { - maybeNode = node; - }} - nativeID="first native id" - />, - ); + root.render(); }); expect( @@ -447,7 +438,7 @@ describe('reconciliation of setNativeProps and React commit', () => { .toJSX(), ).toEqual(); - const element = ensureInstance(maybeNode, ReactNativeElement); + const element = ensureInstance(nodeRef.current, ReactNativeElement); Fantom.runTask(() => { element.setNativeProps({nativeID: 'second native id'}); @@ -462,14 +453,7 @@ describe('reconciliation of setNativeProps and React commit', () => { ).toEqual(); Fantom.runTask(() => { - root.render( - { - maybeNode = node; - }} - nativeID="third native id" - />, - ); + root.render(); }); expect( diff --git a/packages/react-native/src/private/webapis/dom/nodes/__tests__/ReactNativeDocument-itest.js b/packages/react-native/src/private/webapis/dom/nodes/__tests__/ReactNativeDocument-itest.js index e8e121c317b..6d53e314102 100644 --- a/packages/react-native/src/private/webapis/dom/nodes/__tests__/ReactNativeDocument-itest.js +++ b/packages/react-native/src/private/webapis/dom/nodes/__tests__/ReactNativeDocument-itest.js @@ -11,6 +11,8 @@ import 'react-native/Libraries/Core/InitializeCore'; +import type {HostInstance} from 'react-native'; + import ensureInstance from '../../../../__tests__/utilities/ensureInstance'; import isUnreachable from '../../../../__tests__/utilities/isUnreachable'; import * as Fantom from '@react-native/fantom'; @@ -23,20 +25,14 @@ import ReadOnlyNode from 'react-native/src/private/webapis/dom/nodes/ReadOnlyNod describe('ReactNativeDocument', () => { it('is connected until the surface is destroyed', () => { - let lastNode; + const nodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - lastNode = node; - }} - />, - ); + root.render(); }); - const element = ensureInstance(lastNode, ReactNativeElement); + const element = ensureInstance(nodeRef.current, ReactNativeElement); const document = ensureInstance(element.ownerDocument, ReactNativeDocument); expect(document.isConnected).toBe(true); @@ -55,20 +51,14 @@ describe('ReactNativeDocument', () => { }); it('allows traversal as a regular node', () => { - let lastNode; + const nodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - lastNode = node; - }} - />, - ); + root.render(); }); - const element = ensureInstance(lastNode, ReactNativeElement); + const element = ensureInstance(nodeRef.current, ReactNativeElement); const document = ensureInstance(element.ownerDocument, ReactNativeDocument); expect(document.childNodes.length).toBe(1); @@ -80,20 +70,14 @@ describe('ReactNativeDocument', () => { }); it('allows traversal through document-specific methods', () => { - let lastNode; + const nodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - lastNode = node; - }} - />, - ); + root.render(); }); - const element = ensureInstance(lastNode, ReactNativeElement); + const element = ensureInstance(nodeRef.current, ReactNativeElement); const document = ensureInstance(element.ownerDocument, ReactNativeDocument); expect(document.childElementCount).toBe(1); @@ -104,20 +88,14 @@ describe('ReactNativeDocument', () => { }); it('implements the abstract methods from ReadOnlyNode', () => { - let lastNode; + const nodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - lastNode = node; - }} - />, - ); + root.render(); }); - const element = ensureInstance(lastNode, ReactNativeElement); + const element = ensureInstance(nodeRef.current, ReactNativeElement); const document = ensureInstance(element.ownerDocument, ReactNativeDocument); expect(document.nodeName).toBe('#document'); @@ -127,20 +105,14 @@ describe('ReactNativeDocument', () => { }); it('provides a documentElement node that behaves like a regular element', () => { - let lastNode; + const nodeRef = React.createRef(); const root = Fantom.createRoot({viewportWidth: 200, viewportHeight: 100}); Fantom.runTask(() => { - root.render( - { - lastNode = node; - }} - />, - ); + root.render(); }); - const element = ensureInstance(lastNode, ReactNativeElement); + const element = ensureInstance(nodeRef.current, ReactNativeElement); const document = ensureInstance(element.ownerDocument, ReactNativeDocument); const {x, y, width, height} = @@ -153,20 +125,14 @@ describe('ReactNativeDocument', () => { }); it('implements compareDocumentPosition correctly', () => { - let lastNode; + const nodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - lastNode = node; - }} - />, - ); + root.render(); }); - const element = ensureInstance(lastNode, ReactNativeElement); + const element = ensureInstance(nodeRef.current, ReactNativeElement); const document = ensureInstance(element.ownerDocument, ReactNativeDocument); const documentElement = document.documentElement; @@ -206,17 +172,11 @@ describe('ReactNativeDocument', () => { }); it('is released when the root is destroyed', () => { - let lastNode; + const nodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - lastNode = node; - }} - />, - ); + root.render(); }); let maybeWeakNode; @@ -224,11 +184,13 @@ describe('ReactNativeDocument', () => { Fantom.runTask(() => { maybeWeakDocument = new WeakRef( ensureInstance( - ensureInstance(lastNode, ReactNativeElement).ownerDocument, + ensureInstance(nodeRef.current, ReactNativeElement).ownerDocument, ReactNativeDocument, ), ); - maybeWeakNode = new WeakRef(ensureInstance(lastNode, ReactNativeElement)); + maybeWeakNode = new WeakRef( + ensureInstance(nodeRef.current, ReactNativeElement), + ); }); const weakDocument = nullthrows(maybeWeakDocument); @@ -241,7 +203,7 @@ describe('ReactNativeDocument', () => { root.destroy(); }); - expect(lastNode).toBe(null); + expect(nodeRef.current).toBe(null); expect(isUnreachable(weakDocument)).toBe(true); expect(isUnreachable(weakNode)).toBe(true); }); diff --git a/packages/react-native/src/private/webapis/dom/nodes/__tests__/ReactNativeElement-itest.js b/packages/react-native/src/private/webapis/dom/nodes/__tests__/ReactNativeElement-itest.js index 1703abc0604..bcbf4ddd735 100644 --- a/packages/react-native/src/private/webapis/dom/nodes/__tests__/ReactNativeElement-itest.js +++ b/packages/react-native/src/private/webapis/dom/nodes/__tests__/ReactNativeElement-itest.js @@ -11,6 +11,8 @@ import 'react-native/Libraries/Core/InitializeCore'; +import type {HostInstance} from 'react-native'; + import ensureInstance from '../../../../__tests__/utilities/ensureInstance'; import * as Fantom from '@react-native/fantom'; import * as React from 'react'; @@ -33,82 +35,51 @@ function ensureReactNativeElement(value: mixed): ReactNativeElement { describe('ReactNativeElement', () => { it('should be used to create public instances when the `enableAccessToHostTreeInFabric` feature flag is enabled', () => { - let node; + const ref = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - node = receivedNode; - }} - />, - ); + root.render(); }); - expect(node).toBeInstanceOf(ReactNativeElement); + expect(ref.current).toBeInstanceOf(ReactNativeElement); }); describe('extends `ReadOnlyNode`', () => { it('should be an instance of `ReadOnlyNode`', () => { - let lastNode; + const ref = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - lastNode = node; - }} - />, - ); + root.render(); }); - expect(lastNode).toBeInstanceOf(ReadOnlyNode); + expect(ref.current).toBeInstanceOf(ReadOnlyNode); }); describe('nodeType', () => { it('returns ReadOnlyNode.ELEMENT_NODE', () => { - let lastParentNode; - let lastChildNodeA; - let lastChildNodeB; - let lastChildNodeC; + const parentRef = React.createRef(); + const childNodeARef = React.createRef(); + const childNodeBRef = React.createRef(); + const childNodeCRef = React.createRef(); // Initial render with 3 children const root = Fantom.createRoot(); Fantom.runTask(() => { root.render( - { - lastParentNode = node; - }}> - { - lastChildNodeA = node; - }} - /> - { - lastChildNodeB = node; - }} - /> - { - lastChildNodeC = node; - }} - /> + + + + , ); }); - const parentNode = ensureReactNativeElement(lastParentNode); - const childNodeA = ensureReactNativeElement(lastChildNodeA); - const childNodeB = ensureReactNativeElement(lastChildNodeB); - const childNodeC = ensureReactNativeElement(lastChildNodeC); + const parentNode = ensureReactNativeElement(parentRef.current); + const childNodeA = ensureReactNativeElement(childNodeARef.current); + const childNodeB = ensureReactNativeElement(childNodeBRef.current); + const childNodeC = ensureReactNativeElement(childNodeCRef.current); expect(parentNode.nodeType).toBe(ReadOnlyNode.ELEMENT_NODE); expect(childNodeA.nodeType).toBe(ReadOnlyNode.ELEMENT_NODE); @@ -119,46 +90,27 @@ describe('ReactNativeElement', () => { describe('nodeValue', () => { it('returns null', () => { - let lastParentNode; - let lastChildNodeA; - let lastChildNodeB; - let lastChildNodeC; + const parentRef = React.createRef(); + const childNodeARef = React.createRef(); + const childNodeBRef = React.createRef(); + const childNodeCRef = React.createRef(); // Initial render with 3 children const root = Fantom.createRoot(); Fantom.runTask(() => { root.render( - { - lastParentNode = node; - }}> - { - lastChildNodeA = node; - }} - /> - { - lastChildNodeB = node; - }} - /> - { - lastChildNodeC = node; - }} - /> + + + + , ); }); - const parentNode = ensureReactNativeElement(lastParentNode); - const childNodeA = ensureReactNativeElement(lastChildNodeA); - const childNodeB = ensureReactNativeElement(lastChildNodeB); - const childNodeC = ensureReactNativeElement(lastChildNodeC); + const parentNode = ensureReactNativeElement(parentRef.current); + const childNodeA = ensureReactNativeElement(childNodeARef.current); + const childNodeB = ensureReactNativeElement(childNodeBRef.current); + const childNodeC = ensureReactNativeElement(childNodeCRef.current); expect(parentNode.nodeValue).toBe(null); expect(childNodeA.nodeValue).toBe(null); @@ -169,46 +121,27 @@ describe('ReactNativeElement', () => { describe('childNodes / hasChildNodes()', () => { it('returns updated child nodes information', () => { - let lastParentNode; - let lastChildNodeA; - let lastChildNodeB; - let lastChildNodeC; + const parentRef = React.createRef(); + const childNodeARef = React.createRef(); + const childNodeBRef = React.createRef(); + const childNodeCRef = React.createRef(); // Initial render with 3 children const root = Fantom.createRoot(); Fantom.runTask(() => { root.render( - { - lastParentNode = node; - }}> - { - lastChildNodeA = node; - }} - /> - { - lastChildNodeB = node; - }} - /> - { - lastChildNodeC = node; - }} - /> + + + + , ); }); - const parentNode = ensureReactNativeElement(lastParentNode); - const childNodeA = ensureReactNativeElement(lastChildNodeA); - const childNodeB = ensureReactNativeElement(lastChildNodeB); - const childNodeC = ensureReactNativeElement(lastChildNodeC); + const parentNode = ensureReactNativeElement(parentRef.current); + const childNodeA = ensureReactNativeElement(childNodeARef.current); + const childNodeB = ensureReactNativeElement(childNodeBRef.current); + const childNodeC = ensureReactNativeElement(childNodeCRef.current); const childNodes = parentNode.childNodes; expect(childNodes).toBeInstanceOf(NodeList); @@ -253,47 +186,29 @@ describe('ReactNativeElement', () => { describe('getRootNode()', () => { // This is the desired implementation (not implemented yet). it('returns a root node representing the document', () => { - let lastParentANode; - let lastParentBNode; - let lastChildANode; - let lastChildBNode; + const parentANodeRef = React.createRef(); + const parentBNodeRef = React.createRef(); + const childANodeRef = React.createRef(); + const childBNodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { root.render( <> - { - lastParentANode = node; - }}> - { - lastChildANode = node; - }} - /> + + - { - lastParentBNode = node; - }}> - { - lastChildBNode = node; - }} - /> + + , ); }); - const parentANode = ensureReactNativeElement(lastParentANode); - const childANode = ensureReactNativeElement(lastChildANode); - const parentBNode = ensureReactNativeElement(lastParentBNode); - const childBNode = ensureReactNativeElement(lastChildBNode); + const parentANode = ensureReactNativeElement(parentANodeRef.current); + const childANode = ensureReactNativeElement(childANodeRef.current); + const parentBNode = ensureReactNativeElement(parentBNodeRef.current); + const childBNode = ensureReactNativeElement(childBNodeRef.current); expect(childANode.getRootNode()).toBe(childBNode.getRootNode()); const document = childANode.getRootNode(); @@ -329,46 +244,27 @@ describe('ReactNativeElement', () => { describe('firstChild / lastChild / previousSibling / nextSibling / parentNode / parentElement', () => { it('return updated relative nodes', () => { - let lastParentNode; - let lastChildNodeA; - let lastChildNodeB; - let lastChildNodeC; + const parentRef = React.createRef(); + const childNodeARef = React.createRef(); + const childNodeBRef = React.createRef(); + const childNodeCRef = React.createRef(); // Initial render with 3 children const root = Fantom.createRoot(); Fantom.runTask(() => { root.render( - { - lastParentNode = node; - }}> - { - lastChildNodeA = node; - }} - /> - { - lastChildNodeB = node; - }} - /> - { - lastChildNodeC = node; - }} - /> + + + + , ); }); - const parentNode = ensureReactNativeElement(lastParentNode); - const childNodeA = ensureReactNativeElement(lastChildNodeA); - const childNodeB = ensureReactNativeElement(lastChildNodeB); - const childNodeC = ensureReactNativeElement(lastChildNodeC); + const parentNode = ensureReactNativeElement(parentRef.current); + const childNodeA = ensureReactNativeElement(childNodeARef.current); + const childNodeB = ensureReactNativeElement(childNodeBRef.current); + const childNodeC = ensureReactNativeElement(childNodeCRef.current); expect(parentNode.isConnected).toBe(true); expect(parentNode.firstChild).toBe(childNodeA); @@ -486,54 +382,32 @@ describe('ReactNativeElement', () => { describe('compareDocumentPosition / contains', () => { it('handles containment, order and connection', () => { - let lastParentNode; - let lastChildNodeA; - let lastChildNodeAA; - let lastChildNodeB; - let lastChildNodeBB; + const parentRef = React.createRef(); + const childNodeARef = React.createRef(); + const childNodeAARef = React.createRef(); + const childNodeBRef = React.createRef(); + const childNodeBBRef = React.createRef(); // Initial render with 2 children const root = Fantom.createRoot(); Fantom.runTask(() => { root.render( - { - lastParentNode = node; - }}> - { - lastChildNodeA = node; - }}> - { - lastChildNodeAA = node; - }} - /> + + + - { - lastChildNodeB = node; - }}> - { - lastChildNodeBB = node; - }} - /> + + , ); }); - const parentNode = ensureReactNativeElement(lastParentNode); - const childNodeA = ensureReactNativeElement(lastChildNodeA); - const childNodeAA = ensureReactNativeElement(lastChildNodeAA); - const childNodeB = ensureReactNativeElement(lastChildNodeB); - const childNodeBB = ensureReactNativeElement(lastChildNodeBB); + const parentNode = ensureReactNativeElement(parentRef.current); + const childNodeA = ensureReactNativeElement(childNodeARef.current); + const childNodeAA = ensureReactNativeElement(childNodeAARef.current); + const childNodeB = ensureReactNativeElement(childNodeBRef.current); + const childNodeBB = ensureReactNativeElement(childNodeBBRef.current); // Node/self expect(parentNode.compareDocumentPosition(parentNode)).toBe(0); @@ -617,24 +491,22 @@ describe('ReactNativeElement', () => { expect(childNodeBB.compareDocumentPosition(childNodeBB)).toBe(0); expect(childNodeBB.contains(childNodeBB)).toBe(true); - let lastAltParentNode; + const altParentNodeRef = React.createRef(); // Similar structure in a different tree const root2 = Fantom.createRoot(); Fantom.runTask(() => { root2.render( - { - lastAltParentNode = node; - }}> + , ); }); - const altParentNode = ensureReactNativeElement(lastAltParentNode); + const altParentNode = ensureReactNativeElement( + altParentNodeRef.current, + ); // Node/same position in different tree expect(altParentNode.compareDocumentPosition(parentNode)).toBe( @@ -676,64 +548,45 @@ describe('ReactNativeElement', () => { describe('extends `ReadOnlyElement`', () => { it('should be an instance of `ReadOnlyElement`', () => { - let lastNode; + const ref = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - lastNode = node; - }} - />, - ); + root.render(); }); - expect(lastNode).toBeInstanceOf(ReadOnlyElement); + expect(ref.current).toBeInstanceOf(ReadOnlyElement); }); describe('children / childElementCount', () => { it('return updated element children information', () => { - let lastParentElement; - let lastChildElementA; - let lastChildElementB; - let lastChildElementC; + const parentRef = React.createRef(); + const childElementARef = React.createRef(); + const childElementBRef = React.createRef(); + const childElementCRef = React.createRef(); // Initial render with 3 children const root = Fantom.createRoot(); Fantom.runTask(() => { root.render( - { - lastParentElement = element; - }}> - { - lastChildElementA = element; - }} - /> - { - lastChildElementB = element; - }} - /> - { - lastChildElementC = element; - }} - /> + + + + , ); }); - const parentElement = ensureReactNativeElement(lastParentElement); - const childElementA = ensureReactNativeElement(lastChildElementA); - const childElementB = ensureReactNativeElement(lastChildElementB); - const childElementC = ensureReactNativeElement(lastChildElementC); + const parentElement = ensureReactNativeElement(parentRef.current); + const childElementA = ensureReactNativeElement( + childElementARef.current, + ); + const childElementB = ensureReactNativeElement( + childElementBRef.current, + ); + const childElementC = ensureReactNativeElement( + childElementCRef.current, + ); const children = parentElement.children; expect(children).toBeInstanceOf(HTMLCollection); @@ -777,46 +630,33 @@ describe('ReactNativeElement', () => { describe('firstElementChild / lastElementChild / previousElementSibling / nextElementSibling', () => { it('return updated relative elements', () => { - let lastParentElement; - let lastChildElementA; - let lastChildElementB; - let lastChildElementC; + const parentRef = React.createRef(); + const childElementARef = React.createRef(); + const childElementBRef = React.createRef(); + const childElementCRef = React.createRef(); // Initial render with 3 children const root = Fantom.createRoot(); Fantom.runTask(() => { root.render( - { - lastParentElement = element; - }}> - { - lastChildElementA = element; - }} - /> - { - lastChildElementB = element; - }} - /> - { - lastChildElementC = element; - }} - /> + + + + , ); }); - const parentElement = ensureReactNativeElement(lastParentElement); - const childElementA = ensureReactNativeElement(lastChildElementA); - const childElementB = ensureReactNativeElement(lastChildElementB); - const childElementC = ensureReactNativeElement(lastChildElementC); + const parentElement = ensureReactNativeElement(parentRef.current); + const childElementA = ensureReactNativeElement( + childElementARef.current, + ); + const childElementB = ensureReactNativeElement( + childElementBRef.current, + ); + const childElementC = ensureReactNativeElement( + childElementCRef.current, + ); expect(parentElement.firstElementChild).toBe(childElementA); expect(parentElement.lastElementChild).toBe(childElementC); @@ -902,36 +742,28 @@ describe('ReactNativeElement', () => { describe('textContent', () => { it('should return the concatenated values of all its text node descendants (using DFS)', () => { - let lastParentNode; - let lastChildNodeA; + const parentRef = React.createRef(); + const childNodeARef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { root.render( - { - lastParentNode = node; - }}> + Hello - { - lastChildNodeA = node; - }}> + world! , ); }); - const parentNode = ensureReactNativeElement(lastParentNode); - const childNodeA = ensureReactNativeElement(lastChildNodeA); + const parentNode = ensureReactNativeElement(parentRef.current); + const childNodeA = ensureReactNativeElement(childNodeARef.current); expect(parentNode.textContent).toBe('Hello world!'); expect(childNodeA.textContent).toBe('world!'); - let lastChildNodeB; + const childNodeBRef = React.createRef(); Fantom.runTask(() => { root.render( @@ -939,11 +771,7 @@ describe('ReactNativeElement', () => { world - { - lastChildNodeB = node; - }}> + again @@ -955,7 +783,7 @@ describe('ReactNativeElement', () => { ); }); - const childNodeB = ensureReactNativeElement(lastChildNodeB); + const childNodeB = ensureReactNativeElement(childNodeBRef.current); expect(parentNode.textContent).toBe('Hello world again and again!'); expect(childNodeA.textContent).toBe('world '); @@ -965,7 +793,7 @@ describe('ReactNativeElement', () => { describe('getBoundingClientRect', () => { it('returns a DOMRect with its size and position, or an empty DOMRect when disconnected', () => { - let lastElement; + const elementRef = React.createRef(); const root = Fantom.createRoot(); @@ -980,14 +808,12 @@ describe('ReactNativeElement', () => { width: 50.3, height: 100.4, }} - ref={element => { - lastElement = element; - }} + ref={elementRef} />, ); }); - const element = ensureReactNativeElement(lastElement); + const element = ensureReactNativeElement(elementRef.current); const boundingClientRect = element.getBoundingClientRect(); expect(boundingClientRect).toBeInstanceOf(DOMRect); @@ -1011,7 +837,7 @@ describe('ReactNativeElement', () => { describe('scrollLeft / scrollTop', () => { it('return the scroll position on each axis', () => { - let lastElement; + const elementRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { @@ -1019,14 +845,12 @@ describe('ReactNativeElement', () => { { - lastElement = element; - }} + ref={elementRef} />, ); }); - const element = ensureReactNativeElement(lastElement); + const element = ensureReactNativeElement(elementRef.current); expect(element.scrollLeft).toBeCloseTo(5.1); expect(element.scrollTop).toBeCloseTo(10.2); @@ -1042,7 +866,7 @@ describe('ReactNativeElement', () => { describe('scrollWidth / scrollHeight', () => { it('return the scroll size on each axis', () => { - let lastElement; + const elementRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { @@ -1050,15 +874,13 @@ describe('ReactNativeElement', () => { { - lastElement = element; - }}> + ref={elementRef}> , ); }); - const element = ensureReactNativeElement(lastElement); + const element = ensureReactNativeElement(elementRef.current); expect(element.scrollWidth).toBe(200); expect(element.scrollHeight).toBe(1500); @@ -1074,7 +896,7 @@ describe('ReactNativeElement', () => { describe('clientWidth / clientHeight', () => { it('return the inner size of the node', () => { - let lastElement; + const elementRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { @@ -1085,14 +907,12 @@ describe('ReactNativeElement', () => { width: 200, height: 250, }} - ref={element => { - lastElement = element; - }} + ref={elementRef} />, ); }); - const element = ensureReactNativeElement(lastElement); + const element = ensureReactNativeElement(elementRef.current); expect(element.clientWidth).toBe(200); expect(element.clientHeight).toBe(250); @@ -1108,7 +928,7 @@ describe('ReactNativeElement', () => { describe('clientLeft / clientTop', () => { it('return the border size of the node', () => { - let lastElement; + const elementRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { @@ -1119,14 +939,12 @@ describe('ReactNativeElement', () => { borderTopWidth: 250, borderLeftWidth: 200, }} - ref={element => { - lastElement = element; - }} + ref={elementRef} />, ); }); - const element = ensureReactNativeElement(lastElement); + const element = ensureReactNativeElement(elementRef.current); expect(element.clientLeft).toBe(200); expect(element.clientTop).toBe(250); @@ -1142,7 +960,7 @@ describe('ReactNativeElement', () => { describe('id', () => { it('returns the current `id` prop from the node', () => { - let lastElement; + const elementRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { @@ -1150,20 +968,18 @@ describe('ReactNativeElement', () => { { - lastElement = element; - }} + ref={elementRef} />, ); }); - const element = ensureReactNativeElement(lastElement); + const element = ensureReactNativeElement(elementRef.current); expect(element.id).toBe(''); }); it('returns the current `nativeID` prop from the node', () => { - let lastElement; + const elementRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { @@ -1171,14 +987,12 @@ describe('ReactNativeElement', () => { { - lastElement = element; - }} + ref={elementRef} />, ); }); - const element = ensureReactNativeElement(lastElement); + const element = ensureReactNativeElement(elementRef.current); expect(element.id).toBe(''); }); @@ -1186,20 +1000,14 @@ describe('ReactNativeElement', () => { describe('tagName', () => { it('returns the normalized tag name for the node', () => { - let lastElement; + const elementRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - lastElement = element; - }} - />, - ); + root.render(); }); - const element = ensureReactNativeElement(lastElement); + const element = ensureReactNativeElement(elementRef.current); expect(element.tagName).toBe('RN:View'); }); @@ -1208,27 +1016,21 @@ describe('ReactNativeElement', () => { describe('extends `ReactNativeElement`', () => { it('should be an instance of `ReactNativeElement`', () => { - let lastNode; + const ref = React.createRef(); // Initial render with 3 children const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - lastNode = node; - }} - />, - ); + root.render(); }); - const node = ensureReactNativeElement(lastNode); + const node = ensureReactNativeElement(ref.current); expect(node).toBeInstanceOf(ReactNativeElement); }); describe('offsetWidth / offsetHeight', () => { it('return the rounded width and height, or 0 when disconnected', () => { - let lastElement; + const elementRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { @@ -1242,14 +1044,12 @@ describe('ReactNativeElement', () => { width: 50.3, height: 100.5, }} - ref={element => { - lastElement = element; - }} + ref={elementRef} />, ); }); - const element = ensureReactNativeElement(lastElement); + const element = ensureReactNativeElement(elementRef.current); expect(element.offsetWidth).toBe(50); expect(element.offsetHeight).toBe(100); @@ -1265,31 +1065,25 @@ describe('ReactNativeElement', () => { describe('offsetParent / offsetTop / offsetLeft', () => { it('retun the rounded offset values and the parent, or null and zeros when disconnected or hidden', () => { - let lastParentElement; - let lastElement; + const parentRef = React.createRef(); + const elementRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { root.render( - { - lastParentElement = element; - }}> + { - lastElement = element; - }} + ref={elementRef} /> , ); }); - const parentElement = ensureReactNativeElement(lastParentElement); - const element = ensureReactNativeElement(lastElement); + const parentElement = ensureReactNativeElement(parentRef.current); + const element = ensureReactNativeElement(elementRef.current); expect(element.offsetTop).toBe(11); expect(element.offsetLeft).toBe(5); diff --git a/packages/react-native/src/private/webapis/dom/nodes/__tests__/ReadOnlyText-itest.js b/packages/react-native/src/private/webapis/dom/nodes/__tests__/ReadOnlyText-itest.js index 7a2c16a8930..ff10962d336 100644 --- a/packages/react-native/src/private/webapis/dom/nodes/__tests__/ReadOnlyText-itest.js +++ b/packages/react-native/src/private/webapis/dom/nodes/__tests__/ReadOnlyText-itest.js @@ -11,6 +11,8 @@ import 'react-native/Libraries/Core/InitializeCore'; +import type {HostInstance} from 'react-native'; + import ensureInstance from '../../../../__tests__/utilities/ensureInstance'; import * as Fantom from '@react-native/fantom'; import invariant from 'invariant'; @@ -34,22 +36,15 @@ function ensureReactNativeElement(value: mixed): ReactNativeElement { describe('ReadOnlyText', () => { it('should be used to create public text instances when the `enableAccessToHostTreeInFabric` feature flag is enabled', () => { - let lastParentNode; + const parentNodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - lastParentNode = node; - }}> - Some text - , - ); + root.render(Some text); }); - const parentNode = ensureReadOnlyNode(lastParentNode); + const parentNode = ensureReadOnlyNode(parentNodeRef.current); const textNode = parentNode.childNodes[0]; expect(textNode).toBeInstanceOf(ReadOnlyText); @@ -58,22 +53,15 @@ describe('ReadOnlyText', () => { describe('extends `ReadOnlyNode`', () => { describe('nodeName', () => { it('returns "#text"', () => { - let lastParentNode; + const parentNodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - lastParentNode = node; - }}> - Some text - , - ); + root.render(Some text); }); - const parentNode = ensureReadOnlyNode(lastParentNode); + const parentNode = ensureReadOnlyNode(parentNodeRef.current); const textNode = parentNode.childNodes[0]; expect(textNode.nodeName).toBe('#text'); @@ -82,22 +70,15 @@ describe('ReadOnlyText', () => { describe('nodeType', () => { it('returns ReadOnlyNode.TEXT_NODE', () => { - let lastParentNode; + const parentNodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - lastParentNode = node; - }}> - Some text - , - ); + root.render(Some text); }); - const parentNode = ensureReadOnlyNode(lastParentNode); + const parentNode = ensureReadOnlyNode(parentNodeRef.current); const textNode = parentNode.childNodes[0]; expect(textNode.nodeType).toBe(ReadOnlyNode.TEXT_NODE); @@ -106,22 +87,15 @@ describe('ReadOnlyText', () => { describe('nodeValue / textContent', () => { it('returns the string data contained in the node', () => { - let lastParentNode; + const parentNodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - lastParentNode = node; - }}> - Some text - , - ); + root.render(Some text); }); - const parentNode = ensureReadOnlyNode(lastParentNode); + const parentNode = ensureReadOnlyNode(parentNodeRef.current); const textNode = parentNode.childNodes[0]; expect(textNode.nodeValue).toBe('Some text'); @@ -131,34 +105,27 @@ describe('ReadOnlyText', () => { describe('traversal', () => { it('only preserves text nodes when their contents do not change', () => { - let lastParentElement; - let lastChildElementA; + const parentElementRef = React.createRef(); + const childElementARef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { root.render( - { - lastParentElement = element; - }}> + Text A - { - lastChildElementA = element; - }} - /> + Text B , ); }); - const parentElement: ReactNativeElement = - ensureReactNativeElement(lastParentElement); - const childElementA: ReactNativeElement = - ensureReactNativeElement(lastChildElementA); + const parentElement: ReactNativeElement = ensureReactNativeElement( + parentElementRef.current, + ); + const childElementA: ReactNativeElement = ensureReactNativeElement( + childElementARef.current, + ); // Get text nodes and refine them as text nodes for Flow const childTextA = parentElement.childNodes[0]; @@ -183,18 +150,9 @@ describe('ReadOnlyText', () => { // Change contents of the second text only Fantom.runTask(() => { root.render( - { - lastParentElement = element; - }}> + Text A - { - lastChildElementA = element; - }} - /> + Text B modified , ); @@ -216,22 +174,17 @@ describe('ReadOnlyText', () => { describe('extends `ReadOnlyCharacterData`', () => { describe('data / length', () => { it('returns the string data and its length, respectively', () => { - let lastParentNode; + const parentNodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - lastParentNode = node; - }}> - Some text - , - ); + root.render(Some text); }); - const parentNode: ReadOnlyNode = ensureReadOnlyNode(lastParentNode); + const parentNode: ReadOnlyNode = ensureReadOnlyNode( + parentNodeRef.current, + ); const textNode = ensureReadOnlyText(parentNode.childNodes[0]); expect(textNode.data).toBe('Some text'); @@ -241,50 +194,39 @@ describe('ReadOnlyText', () => { describe('previousElementSibling / nextElementSibling', () => { it('return updated relative elements', () => { - let lastParentElement; - let lastChildElementA; - let lastChildElementB; - let lastChildElementC; + const parentElementRef = React.createRef(); + const childElementARef = React.createRef(); + const childElementBRef = React.createRef(); + const childElementCRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { root.render( - { - lastParentElement = element; - }}> + Text A - { - lastChildElementA = element; - }} - /> + Text B - { - lastChildElementB = element; - }} - /> + Text C - { - lastChildElementC = element; - }} - /> + Text D , ); }); - const parentElement = ensureReactNativeElement(lastParentElement); - const childElementA = ensureReactNativeElement(lastChildElementA); - const childElementB = ensureReactNativeElement(lastChildElementB); - const childElementC = ensureReactNativeElement(lastChildElementC); + const parentElement = ensureReactNativeElement( + parentElementRef.current, + ); + const childElementA = ensureReactNativeElement( + childElementARef.current, + ); + const childElementB = ensureReactNativeElement( + childElementBRef.current, + ); + const childElementC = ensureReactNativeElement( + childElementCRef.current, + ); // Get text nodes and refine them as text nodes for Flow const childTextA = parentElement.childNodes[0]; @@ -334,23 +276,21 @@ describe('ReadOnlyText', () => { describe('substringData', () => { it('returns a slice of the text content', () => { - let lastParentElement; + const parentElementRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { root.render( - { - lastParentElement = element; - }}> + Text A , ); }); - const parentElement = ensureReactNativeElement(lastParentElement); + const parentElement = ensureReactNativeElement( + parentElementRef.current, + ); // Get text nodes and refine them as text nodes for Flow const childTextA = parentElement.childNodes[0]; diff --git a/packages/react-native/src/private/webapis/intersectionobserver/__tests__/IntersectionObserver-benchmark-itest.js b/packages/react-native/src/private/webapis/intersectionobserver/__tests__/IntersectionObserver-benchmark-itest.js index 73987bd4209..a726776d527 100644 --- a/packages/react-native/src/private/webapis/intersectionobserver/__tests__/IntersectionObserver-benchmark-itest.js +++ b/packages/react-native/src/private/webapis/intersectionobserver/__tests__/IntersectionObserver-benchmark-itest.js @@ -13,6 +13,7 @@ import 'react-native/Libraries/Core/InitializeCore'; import type {Root} from '@react-native/fantom'; +import type {HostInstance} from 'react-native'; import type IntersectionObserverType from 'react-native/src/private/webapis/intersectionobserver/IntersectionObserver'; import ensureInstance from '../../../__tests__/utilities/ensureInstance'; @@ -27,10 +28,10 @@ declare const IntersectionObserver: Class; setUpIntersectionObserver(); -let maybeNode; +const nodeRef = React.createRef(); let node: ReactNativeElement; -let maybeScrollViewNode; +const scrollViewRef = React.createRef(); let scrollViewNode: ReactNativeElement; let observer: IntersectionObserverType; const VIEWPORT_HEIGHT = 100; @@ -106,17 +107,10 @@ Fantom.unstable_benchmark beforeEach: () => { mockCallback = jest.fn(); Fantom.runTask(() => { - root.render( - { - maybeNode = receivedNode; - }} - />, - ); + root.render(); observer = new IntersectionObserver(mockCallback); }); - node = ensureInstance(maybeNode, ReactNativeElement); + node = ensureInstance(nodeRef.current, ReactNativeElement); }, afterEach: () => { expect(mockCallback).toHaveBeenCalledTimes(1); @@ -137,10 +131,7 @@ Fantom.unstable_benchmark beforeEach: () => { Fantom.runTask(() => { root.render( - { - maybeScrollViewNode = receivedNode; - }}> + {renderElementAtYScrollPosition( VIEWPORT_HEIGHT + 50, , @@ -149,7 +140,7 @@ Fantom.unstable_benchmark ); }); scrollViewNode = ensureInstance( - maybeScrollViewNode, + scrollViewRef.current, ReactNativeElement, ); }, @@ -167,10 +158,7 @@ Fantom.unstable_benchmark beforeEach: () => { Fantom.runTask(() => { root.render( - { - maybeScrollViewNode = receivedNode; - }}> + {renderElementAtYScrollPosition( -5, , @@ -179,7 +167,7 @@ Fantom.unstable_benchmark ); }); scrollViewNode = ensureInstance( - maybeScrollViewNode, + scrollViewRef.current, ReactNativeElement, ); }, @@ -199,27 +187,19 @@ Fantom.unstable_benchmark Fantom.runTask(() => { root.render( - { - maybeScrollViewNode = receivedNode; - }}> + {renderElementAtYScrollPosition( VIEWPORT_HEIGHT + 50, - { - maybeNode = receivedNode; - }} - style={{width: 100, height: 10}} - />, + , )} , ); }); scrollViewNode = ensureInstance( - maybeScrollViewNode, + scrollViewRef.current, ReactNativeElement, ); - node = ensureInstance(maybeNode, ReactNativeElement); + node = ensureInstance(nodeRef.current, ReactNativeElement); Fantom.runTask(() => { observer = new IntersectionObserver(mockCallback, {}); observer.observe(node); @@ -247,27 +227,19 @@ Fantom.unstable_benchmark Fantom.runTask(() => { root.render( - { - maybeScrollViewNode = receivedNode; - }}> + {renderElementAtYScrollPosition( -5, - { - maybeNode = receivedNode; - }} - style={{width: 100, height: 10}} - />, + , )} , ); }); scrollViewNode = ensureInstance( - maybeScrollViewNode, + scrollViewRef.current, ReactNativeElement, ); - node = ensureInstance(maybeNode, ReactNativeElement); + node = ensureInstance(nodeRef.current, ReactNativeElement); Fantom.runTask(() => { observer = new IntersectionObserver(mockCallback, {threshold: 1}); observer.observe(node); diff --git a/packages/react-native/src/private/webapis/intersectionobserver/__tests__/IntersectionObserver-itest.js b/packages/react-native/src/private/webapis/intersectionobserver/__tests__/IntersectionObserver-itest.js index 5cf1cae7d51..742ea105baf 100644 --- a/packages/react-native/src/private/webapis/intersectionobserver/__tests__/IntersectionObserver-itest.js +++ b/packages/react-native/src/private/webapis/intersectionobserver/__tests__/IntersectionObserver-itest.js @@ -11,6 +11,7 @@ import 'react-native/Libraries/Core/InitializeCore'; +import type {HostInstance} from 'react-native'; import type IntersectionObserverType from 'react-native/src/private/webapis/intersectionobserver/IntersectionObserver'; import ensureInstance from '../../../__tests__/utilities/ensureInstance'; @@ -87,20 +88,14 @@ describe('IntersectionObserver', () => { }); it('should throw if `root` is provided', () => { - let maybeNode; + const nodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - maybeNode = receivedNode; - }} - />, - ); + root.render(); }); - const node = ensureReactNativeElement(maybeNode); + const node = ensureReactNativeElement(nodeRef.current); expect(() => { // $FlowExpectedError[prop-missing] root is not even defined in Flow. @@ -332,23 +327,16 @@ describe('IntersectionObserver', () => { }); it('should start observing the target when called for the first time (using normalized thresholds)', () => { - let maybeNode; + const nodeRef = React.createRef(); const root = Fantom.createRoot({ viewportWidth: 1000, viewportHeight: 1000, }); Fantom.runTask(() => { - root.render( - { - maybeNode = receivedNode; - }} - />, - ); + root.render(); }); - const node = ensureReactNativeElement(maybeNode); + const node = ensureReactNativeElement(nodeRef.current); const intersectionObserverCallback = jest.fn(); @@ -391,20 +379,13 @@ describe('IntersectionObserver', () => { }); it('should ignore subsequent calls to observe a target already being observed', () => { - let maybeNode; + const nodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - maybeNode = receivedNode; - }} - />, - ); + root.render(); }); - const node = ensureReactNativeElement(maybeNode); + const node = ensureReactNativeElement(nodeRef.current); const intersectionObserverCallback = jest.fn(); @@ -436,21 +417,14 @@ describe('IntersectionObserver', () => { }); it('should ignore disconnected targets', () => { - let maybeNode; + const nodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - maybeNode = receivedNode; - }} - />, - ); + root.render(); }); - const node = ensureReactNativeElement(maybeNode); + const node = ensureReactNativeElement(nodeRef.current); Fantom.runTask(() => { root.render(<>); @@ -469,8 +443,8 @@ describe('IntersectionObserver', () => { }); it('should report completely non-intersecting initial state correctly', () => { - let maybeNode; - let maybeScrollNode; + const nodeRef = React.createRef(); + const scrollNodeRef = React.createRef(); const root = Fantom.createRoot({ viewportWidth: 1000, @@ -478,21 +452,16 @@ describe('IntersectionObserver', () => { }); Fantom.runTask(() => { root.render( - (maybeScrollNode = receivedNode)}> - { - maybeNode = receivedNode; - }} - /> + + , ); }); - const scrollNode = ensureReactNativeElement(maybeScrollNode); + const scrollNode = ensureReactNativeElement(scrollNodeRef.current); // Ensure View is not intersecting with ScrollView Fantom.scrollTo(scrollNode, {x: 0, y: 200}); - const node = ensureReactNativeElement(maybeNode); + const node = ensureReactNativeElement(nodeRef.current); const intersectionObserverCallback = jest.fn(); @@ -537,8 +506,8 @@ describe('IntersectionObserver', () => { }); it('should report partial non-intersecting initial state correctly', () => { - let maybeNode; - let maybeScrollNode; + const nodeRef = React.createRef(); + const scrollNodeRef = React.createRef(); const root = Fantom.createRoot({ viewportWidth: 1000, @@ -547,19 +516,14 @@ describe('IntersectionObserver', () => { Fantom.runTask(() => { root.render( - (maybeScrollNode = receivedNode)}> - { - maybeNode = receivedNode; - }} - /> + + , ); }); - const scrollNode = ensureReactNativeElement(maybeScrollNode); - const node = ensureReactNativeElement(maybeNode); + const scrollNode = ensureReactNativeElement(scrollNodeRef.current); + const node = ensureReactNativeElement(nodeRef.current); // Scroll such that View is partially intersecting Fantom.scrollTo(scrollNode, {x: 0, y: 25}); @@ -606,8 +570,8 @@ describe('IntersectionObserver', () => { }); it('should report partial intersecting initial state correctly', () => { - let maybeNode; - let maybeScrollNode; + const nodeRef = React.createRef(); + const scrollNodeRef = React.createRef(); const root = Fantom.createRoot({ viewportWidth: 1000, @@ -615,18 +579,13 @@ describe('IntersectionObserver', () => { }); Fantom.runTask(() => { root.render( - (maybeScrollNode = receivedNode)}> - { - maybeNode = receivedNode; - }} - /> + + , ); }); - const scrollNode = ensureReactNativeElement(maybeScrollNode); - const node = ensureReactNativeElement(maybeNode); + const scrollNode = ensureReactNativeElement(scrollNodeRef.current); + const node = ensureReactNativeElement(nodeRef.current); // Scroll such that View is partially intersecting Fantom.scrollTo(scrollNode, {x: 0, y: 25}); @@ -673,8 +632,8 @@ describe('IntersectionObserver', () => { }); it('should report subsequent updates correctly', () => { - let maybeNode; - let maybeScrollNode; + const nodeRef = React.createRef(); + const scrollNodeRef = React.createRef(); const root = Fantom.createRoot({ viewportWidth: 1000, @@ -683,19 +642,14 @@ describe('IntersectionObserver', () => { Fantom.runTask(() => { root.render( - (maybeScrollNode = receivedNode)}> - { - maybeNode = receivedNode; - }} - /> + + , ); }); - const node = ensureReactNativeElement(maybeNode); - const scrollNode = ensureReactNativeElement(maybeScrollNode); + const node = ensureReactNativeElement(nodeRef.current); + const scrollNode = ensureReactNativeElement(scrollNodeRef.current); expect(node.isConnected).toBe(true); @@ -771,7 +725,7 @@ describe('IntersectionObserver', () => { it('should report updates to the right observers', () => { let maybeNode1; let maybeNode2; - let maybeScrollNode; + const scrollNodeRef = React.createRef(); let observer1: IntersectionObserver; let observer2: IntersectionObserver; @@ -782,7 +736,7 @@ describe('IntersectionObserver', () => { Fantom.runTask(() => { root.render( - (maybeScrollNode = receivedNode)}> + { @@ -800,7 +754,7 @@ describe('IntersectionObserver', () => { }); const node1 = ensureReactNativeElement(maybeNode1); const node2 = ensureReactNativeElement(maybeNode2); - const scrollNode = ensureReactNativeElement(maybeScrollNode); + const scrollNode = ensureReactNativeElement(scrollNodeRef.current); // Scroll such that node1 is not intersecting and node 2 is intersecting Fantom.scrollTo(scrollNode, {x: 0, y: 100}); @@ -891,24 +845,17 @@ describe('IntersectionObserver', () => { describe('rootThreshold', () => { it('should report partial intersecting initial state correctly', () => { - let maybeNode; + const nodeRef = React.createRef(); const root = Fantom.createRoot({ viewportWidth: 1000, viewportHeight: 1000, }); Fantom.runTask(() => { - root.render( - { - maybeNode = receivedNode; - }} - />, - ); + root.render(); }); - const node = ensureReactNativeElement(maybeNode); + const node = ensureReactNativeElement(nodeRef.current); const intersectionObserverCallback = jest.fn(); @@ -953,8 +900,8 @@ describe('IntersectionObserver', () => { }); it('should report partial non-intersecting initial state correctly', () => { - let maybeNode; - let maybeScrollNode; + const nodeRef = React.createRef(); + const scrollNodeRef = React.createRef(); const root = Fantom.createRoot({ viewportWidth: 1000, @@ -962,18 +909,13 @@ describe('IntersectionObserver', () => { }); Fantom.runTask(() => { root.render( - (maybeScrollNode = receivedNode)}> - { - maybeNode = receivedNode; - }} - /> + + , ); }); - const node = ensureReactNativeElement(maybeNode); - const scrollNode = ensureReactNativeElement(maybeScrollNode); + const node = ensureReactNativeElement(nodeRef.current); + const scrollNode = ensureReactNativeElement(scrollNodeRef.current); Fantom.scrollTo(scrollNode, {x: 0, y: 25}); @@ -1019,8 +961,8 @@ describe('IntersectionObserver', () => { }); it('should report completely non-intersecting initial state correctly', () => { - let maybeNode; - let maybeScrollNode; + const nodeRef = React.createRef(); + const scrollNodeRef = React.createRef(); const root = Fantom.createRoot({ viewportWidth: 1000, @@ -1028,18 +970,13 @@ describe('IntersectionObserver', () => { }); Fantom.runTask(() => { root.render( - (maybeScrollNode = receivedNode)}> - { - maybeNode = receivedNode; - }} - /> + + , ); }); - const node = ensureReactNativeElement(maybeNode); - const scrollNode = ensureReactNativeElement(maybeScrollNode); + const node = ensureReactNativeElement(nodeRef.current); + const scrollNode = ensureReactNativeElement(scrollNodeRef.current); Fantom.scrollTo(scrollNode, {x: 0, y: 200}); @@ -1085,8 +1022,8 @@ describe('IntersectionObserver', () => { }); it('should report subsequent updates correctly', () => { - let maybeNode; - let maybeScrollNode; + const nodeRef = React.createRef(); + const scrollNodeRef = React.createRef(); const root = Fantom.createRoot({ viewportWidth: 1000, @@ -1095,15 +1032,13 @@ describe('IntersectionObserver', () => { Fantom.runTask(() => { root.render( - (maybeScrollNode = receivedNode)}> + { - maybeNode = receivedNode; - }} + ref={nodeRef} /> { ); }); - const node = ensureReactNativeElement(maybeNode); - const scrollNode = ensureReactNativeElement(maybeScrollNode); + const node = ensureReactNativeElement(nodeRef.current); + const scrollNode = ensureReactNativeElement(scrollNodeRef.current); // Scroll such that target View is not intersecting Fantom.scrollTo(scrollNode, {x: 0, y: 2000}); @@ -1210,20 +1145,14 @@ describe('IntersectionObserver', () => { }); it('should ignore the call if `target` was not observed (not fail)', () => { - let maybeNode; + const nodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - maybeNode = receivedNode; - }} - />, - ); + root.render(); }); - const node = ensureReactNativeElement(maybeNode); + const node = ensureReactNativeElement(nodeRef.current); const callback = jest.fn(); Fantom.runTask(() => { @@ -1235,26 +1164,21 @@ describe('IntersectionObserver', () => { }); it('should stop observing the target if it was observed', () => { - let maybeNode; - let maybeScrollNode; + const nodeRef = React.createRef(); + const scrollNodeRef = React.createRef(); const root = Fantom.createRoot(); // View is not intersecting with ScrollView Fantom.runTask(() => { root.render( - (maybeScrollNode = receivedNode)}> - { - maybeNode = receivedNode; - }} - /> + + , ); }); - const node = ensureReactNativeElement(maybeNode); - const scrollNode = ensureReactNativeElement(maybeScrollNode); + const node = ensureReactNativeElement(nodeRef.current); + const scrollNode = ensureReactNativeElement(scrollNodeRef.current); Fantom.scrollTo(scrollNode, {x: 0, y: 100}); @@ -1279,12 +1203,7 @@ describe('IntersectionObserver', () => { Fantom.runTask(() => { root.render( - { - maybeNode = receivedNode; - }} - /> + , ); }); @@ -1294,20 +1213,14 @@ describe('IntersectionObserver', () => { }); it('should stop observing the target if it was observed (detached target after observing)', () => { - let maybeNode; + const nodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - maybeNode = receivedNode; - }} - />, - ); + root.render(); }); - const node = ensureReactNativeElement(maybeNode); + const node = ensureReactNativeElement(nodeRef.current); const callback = jest.fn(); @@ -1333,20 +1246,14 @@ describe('IntersectionObserver', () => { }); it('should stop observing the target if it was observed (detached target before observing)', () => { - let maybeNode; + const nodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - maybeNode = receivedNode; - }} - />, - ); + root.render(); }); - const node = ensureReactNativeElement(maybeNode); + const node = ensureReactNativeElement(nodeRef.current); Fantom.runTask(() => { root.render(<>); @@ -1359,20 +1266,14 @@ describe('IntersectionObserver', () => { }); it('should not report the initial state if the target is unobserved before it is delivered', () => { - let maybeNode; + const nodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - maybeNode = receivedNode; - }} - />, - ); + root.render(); }); - const node = ensureReactNativeElement(maybeNode); + const node = ensureReactNativeElement(nodeRef.current); const intersectionObserverCallback = jest.fn(); @@ -1386,27 +1287,22 @@ describe('IntersectionObserver', () => { }); it('should not report updates if the target is unobserved before they are delivered', () => { - let maybeNode; - let maybeScrollNode; + const nodeRef = React.createRef(); + const scrollNodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { root.render( { - maybeScrollNode = receivedNode; + scrollNodeRef.current = receivedNode; }}> - { - maybeNode = receivedNode; - }} - /> + , ); }); - const scrollNode = ensureReactNativeElement(maybeScrollNode); + const scrollNode = ensureReactNativeElement(scrollNodeRef.current); // Scroll such that view is not intersecting with ScrollView Fantom.scrollTo(scrollNode, { @@ -1414,7 +1310,7 @@ describe('IntersectionObserver', () => { y: 100, }); - const node = ensureReactNativeElement(maybeNode); + const node = ensureReactNativeElement(nodeRef.current); const callback = jest.fn(); @@ -1515,22 +1411,16 @@ describe('IntersectionObserver', () => { // target was incorrectly cleaned up when a single observer stopped // observing it. it('should work with multiple intersection observer instances', () => { - let maybeNode; + const nodeRef = React.createRef(); let observer1: IntersectionObserver; let observer2: IntersectionObserver; const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - maybeNode = receivedNode; - }} - />, - ); + root.render(); }); - const node = ensureReactNativeElement(maybeNode); + const node = ensureReactNativeElement(nodeRef.current); Fantom.runTask(() => { observer1 = new IntersectionObserver(() => {}); diff --git a/packages/react-native/src/private/webapis/mutationobserver/__tests__/MutationObserver-itest.js b/packages/react-native/src/private/webapis/mutationobserver/__tests__/MutationObserver-itest.js index 1392c0f5cf5..082faf30de0 100644 --- a/packages/react-native/src/private/webapis/mutationobserver/__tests__/MutationObserver-itest.js +++ b/packages/react-native/src/private/webapis/mutationobserver/__tests__/MutationObserver-itest.js @@ -11,6 +11,7 @@ import 'react-native/Libraries/Core/InitializeCore'; +import type {HostInstance} from 'react-native'; import type MutationObserverType from 'react-native/src/private/webapis/mutationobserver/MutationObserver'; import type MutationRecordType from 'react-native/src/private/webapis/mutationobserver/MutationRecord'; @@ -72,20 +73,14 @@ describe('MutationObserver', () => { }); it('should throw if the `childList` option is not provided', () => { - let maybeNode; + const nodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - maybeNode = receivedNode; - }} - />, - ); + root.render(); }); - const node = ensureReactNativeElement(maybeNode); + const node = ensureReactNativeElement(nodeRef.current); expect(() => { const observer = new MutationObserver(() => {}); @@ -115,20 +110,14 @@ describe('MutationObserver', () => { }); it('should throw if the `attributes` option is provided', () => { - let maybeNode; + const nodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - maybeNode = receivedNode; - }} - />, - ); + root.render(); }); - const node = ensureReactNativeElement(maybeNode); + const node = ensureReactNativeElement(nodeRef.current); expect(() => { const observer = new MutationObserver(() => {}); @@ -139,20 +128,14 @@ describe('MutationObserver', () => { }); it('should throw if the `attributeFilter` option is provided', () => { - let maybeNode; + const nodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - maybeNode = receivedNode; - }} - />, - ); + root.render(); }); - const node = ensureReactNativeElement(maybeNode); + const node = ensureReactNativeElement(nodeRef.current); expect(() => { const observer = new MutationObserver(() => {}); @@ -163,20 +146,14 @@ describe('MutationObserver', () => { }); it('should throw if the `attributeOldValue` option is provided', () => { - let maybeNode; + const nodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - maybeNode = receivedNode; - }} - />, - ); + root.render(); }); - const node = ensureReactNativeElement(maybeNode); + const node = ensureReactNativeElement(nodeRef.current); expect(() => { const observer = new MutationObserver(() => {}); @@ -188,20 +165,14 @@ describe('MutationObserver', () => { }); it('should throw if the `characterData` option is provided', () => { - let maybeNode; + const nodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - maybeNode = receivedNode; - }} - />, - ); + root.render(); }); - const node = ensureReactNativeElement(maybeNode); + const node = ensureReactNativeElement(nodeRef.current); expect(() => { const observer = new MutationObserver(() => {}); @@ -212,20 +183,14 @@ describe('MutationObserver', () => { }); it('should throw if the `characterDataOldValue` option is provided', () => { - let maybeNode; + const nodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - maybeNode = receivedNode; - }} - />, - ); + root.render(); }); - const node = ensureReactNativeElement(maybeNode); + const node = ensureReactNativeElement(nodeRef.current); expect(() => { const observer = new MutationObserver(() => {}); @@ -236,21 +201,14 @@ describe('MutationObserver', () => { }); it('should ignore calls to observe disconnected targets', () => { - let maybeNode; + const nodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - maybeNode = receivedNode; - }} - />, - ); + root.render(); }); - const node = ensureReactNativeElement(maybeNode); + const node = ensureReactNativeElement(nodeRef.current); Fantom.runTask(() => { root.render(<>); @@ -267,21 +225,14 @@ describe('MutationObserver', () => { }); it('should report direct children added to and removed from an observed node (childList: true, subtree: false) ', () => { - let maybeNode; + const nodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - maybeNode = receivedNode; - }} - />, - ); + root.render(); }); - const node = ensureReactNativeElement(maybeNode); + const node = ensureReactNativeElement(nodeRef.current); const observerCallbackCallArgs = []; const observerCallback = (...args: $ReadOnlyArray) => { @@ -293,29 +244,20 @@ describe('MutationObserver', () => { // Does not report anything initially expect(observerCallbackCallArgs.length).toBe(0); - let maybeChildNode1, maybeChildNode2; + const childNode1Ref = React.createRef(); + const childNode2Ref = React.createRef(); Fantom.runTask(() => { root.render( - { - maybeChildNode1 = receivedChildNode; - }} - /> - { - maybeChildNode2 = receivedChildNode; - }} - /> + + , ); }); - const childNode1 = ensureReactNativeElement(maybeChildNode1); - const childNode2 = ensureReactNativeElement(maybeChildNode2); + const childNode1 = ensureReactNativeElement(childNode1Ref.current); + const childNode2 = ensureReactNativeElement(childNode2Ref.current); expect(observerCallbackCallArgs.length).toBe(1); const firstCall = nullthrows(observerCallbackCallArgs.at(-1)); @@ -365,22 +307,18 @@ describe('MutationObserver', () => { }); it('should NOT report changes in transitive children when `subtree` is not set to true', () => { - let maybeObservedNode; + const observedNodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { root.render( - { - maybeObservedNode = receivedNode; - }}> + , ); }); - const observedNode = ensureReactNativeElement(maybeObservedNode); + const observedNode = ensureReactNativeElement(observedNodeRef.current); const observerCallback = jest.fn(); const observer = new MutationObserver(observerCallback); @@ -413,22 +351,18 @@ describe('MutationObserver', () => { }); it('should report changes in transitive children when `subtree` is set to true', () => { - let maybeNode; + const nodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { root.render( - { - maybeNode = receivedNode; - }}> + , ); }); - const node = ensureReactNativeElement(maybeNode); + const node = ensureReactNativeElement(nodeRef.current); const observerCallback = jest.fn(); const observer = new MutationObserver(observerCallback); @@ -437,24 +371,19 @@ describe('MutationObserver', () => { // Does not report anything initially expect(observerCallback).not.toHaveBeenCalled(); - let maybeNode111; + const node111Ref = React.createRef(); Fantom.runTask(() => { root.render( - { - maybeNode111 = receivedGrandchildNode; - }} - /> + , ); }); - const node111 = ensureReactNativeElement(maybeNode111); + const node111 = ensureReactNativeElement(node111Ref.current); expect(observerCallback).toHaveBeenCalledTimes(1); const firstCall = observerCallback.mock.lastCall; @@ -481,23 +410,19 @@ describe('MutationObserver', () => { }); it('should report changes in different parts of the subtree as separate entries (subtree = true)', () => { - let maybeNode; + const nodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { root.render( - { - maybeNode = receivedNode; - }}> + , ); }); - const node = ensureReactNativeElement(maybeNode); + const node = ensureReactNativeElement(nodeRef.current); const observerCallback = jest.fn(); const observer = new MutationObserver(observerCallback); @@ -506,33 +431,24 @@ describe('MutationObserver', () => { // Does not report anything initially expect(observerCallback).not.toHaveBeenCalled(); - let maybeNode111, maybeNode121; + const node111Ref = React.createRef(); + const node121Ref = React.createRef(); Fantom.runTask(() => { root.render( - { - maybeNode111 = receivedGrandchildNode; - }} - /> + - { - maybeNode121 = receivedGrandchildNode; - }} - /> + , ); }); - const node111 = ensureReactNativeElement(maybeNode111); - const node121 = ensureReactNativeElement(maybeNode121); + const node111 = ensureReactNativeElement(node111Ref.current); + const node121 = ensureReactNativeElement(node121Ref.current); expect(observerCallback).toHaveBeenCalledTimes(1); const firstCall = observerCallback.mock.lastCall; @@ -566,31 +482,21 @@ describe('MutationObserver', () => { describe('multiple observers', () => { it('should report changes to multiple observers observing different subtrees', () => { - let maybeNode1; - let maybeNode2; + const node1Ref = React.createRef(); + const node2Ref = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { root.render( <> - { - maybeNode1 = receivedNode; - }} - /> - { - maybeNode2 = receivedNode; - }} - /> + + , ); }); - const node1 = ensureReactNativeElement(maybeNode1); - const node2 = ensureReactNativeElement(maybeNode2); + const node1 = ensureReactNativeElement(node1Ref.current); + const node2 = ensureReactNativeElement(node2Ref.current); const observerCallback1 = jest.fn(); const observer1 = new MutationObserver(observerCallback1); @@ -604,34 +510,24 @@ describe('MutationObserver', () => { expect(observerCallback1).not.toHaveBeenCalled(); expect(observerCallback2).not.toHaveBeenCalled(); - let maybeChildNode11; - let maybeChildNode21; + const childNode11Ref = React.createRef(); + const childNode21Ref = React.createRef(); Fantom.runTask(() => { root.render( <> - { - maybeChildNode11 = receivedNode; - }} - /> + - { - maybeChildNode21 = receivedNode; - }} - /> + , ); }); - const childNode11 = ensureReactNativeElement(maybeChildNode11); - const childNode21 = ensureReactNativeElement(maybeChildNode21); + const childNode11 = ensureReactNativeElement(childNode11Ref.current); + const childNode21 = ensureReactNativeElement(childNode21Ref.current); expect(observerCallback1).toHaveBeenCalledTimes(1); const observer1Records1 = ensureMutationRecordArray( @@ -676,29 +572,20 @@ describe('MutationObserver', () => { }); it('should report changes to multiple observers observing the same subtree', () => { - let maybeNode1; - let maybeNode2; + const node1Ref = React.createRef(); + const node2Ref = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { root.render( - { - maybeNode1 = receivedNode; - }}> - { - maybeNode2 = receivedNode; - }} - /> + + , ); }); - const node1 = ensureReactNativeElement(maybeNode1); - const node2 = ensureReactNativeElement(maybeNode2); + const node1 = ensureReactNativeElement(node1Ref.current); + const node2 = ensureReactNativeElement(node2Ref.current); const observerCallback1 = jest.fn(); const observer1 = new MutationObserver(observerCallback1); @@ -712,24 +599,19 @@ describe('MutationObserver', () => { expect(observerCallback1).not.toHaveBeenCalled(); expect(observerCallback2).not.toHaveBeenCalled(); - let maybeChildNode111; + const childNode111Ref = React.createRef(); Fantom.runTask(() => { root.render( - { - maybeChildNode111 = receivedNode; - }} - /> + , ); }); - const childNode111 = ensureReactNativeElement(maybeChildNode111); + const childNode111 = ensureReactNativeElement(childNode111Ref.current); expect(observerCallback1).toHaveBeenCalledTimes(1); const observer1Records1 = ensureMutationRecordArray( @@ -776,31 +658,21 @@ describe('MutationObserver', () => { describe('multiple observed nodes in the same observer', () => { it('should report changes in disjoint observations', () => { - let maybeNode1; - let maybeNode2; + const node1Ref = React.createRef(); + const node2Ref = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { root.render( <> - { - maybeNode1 = receivedNode; - }} - /> - { - maybeNode2 = receivedNode; - }} - /> + + , ); }); - const node1 = ensureReactNativeElement(maybeNode1); - const node2 = ensureReactNativeElement(maybeNode2); + const node1 = ensureReactNativeElement(node1Ref.current); + const node2 = ensureReactNativeElement(node2Ref.current); const observerCallback = jest.fn(); const observer = new MutationObserver(observerCallback); @@ -810,34 +682,24 @@ describe('MutationObserver', () => { // Does not report anything initially expect(observerCallback).not.toHaveBeenCalled(); - let maybeChildNode11; - let maybeChildNode21; + const childNode11Ref = React.createRef(); + const childNode21Ref = React.createRef(); Fantom.runTask(() => { root.render( <> - { - maybeChildNode11 = receivedNode; - }} - /> + - { - maybeChildNode21 = receivedNode; - }} - /> + , ); }); - const childNode11 = ensureReactNativeElement(maybeChildNode11); - const childNode21 = ensureReactNativeElement(maybeChildNode21); + const childNode11 = ensureReactNativeElement(childNode11Ref.current); + const childNode21 = ensureReactNativeElement(childNode21Ref.current); expect(observerCallback).toHaveBeenCalledTimes(1); const records = ensureMutationRecordArray( @@ -870,29 +732,20 @@ describe('MutationObserver', () => { }); it('should report changes in joint observations', () => { - let maybeNode1; - let maybeNode11; + const node1Ref = React.createRef(); + const node11Ref = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { root.render( - { - maybeNode1 = receivedNode; - }}> - { - maybeNode11 = receivedNode; - }} - /> + + , ); }); - const node1 = ensureReactNativeElement(maybeNode1); - const node11 = ensureReactNativeElement(maybeNode11); + const node1 = ensureReactNativeElement(node1Ref.current); + const node11 = ensureReactNativeElement(node11Ref.current); const observerCallback = jest.fn(); const observer = new MutationObserver(observerCallback); @@ -902,24 +755,19 @@ describe('MutationObserver', () => { // Does not report anything initially expect(observerCallback).not.toHaveBeenCalled(); - let maybeChildNode111; + const childNode111Ref = React.createRef(); Fantom.runTask(() => { root.render( - { - maybeChildNode111 = receivedNode; - }} - /> + , ); }); - const childNode111 = ensureReactNativeElement(maybeChildNode111); + const childNode111 = ensureReactNativeElement(childNode111Ref.current); expect(observerCallback).toHaveBeenCalledTimes(1); const records = ensureMutationRecordArray( @@ -950,21 +798,14 @@ describe('MutationObserver', () => { describe('disconnect()', () => { it('should stop observing targets', () => { - let maybeObservedNode; + const observedNodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - maybeObservedNode = receivedNode; - }} - />, - ); + root.render(); }); - const observedNode = ensureReactNativeElement(maybeObservedNode); + const observedNode = ensureReactNativeElement(observedNodeRef.current); const observerCallback = jest.fn(); const observer = new MutationObserver(observerCallback); @@ -998,21 +839,14 @@ describe('MutationObserver', () => { }); it('should correctly unobserve targets that are disconnected after observing', () => { - let maybeObservedNode; + const observedNodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - maybeObservedNode = receivedNode; - }} - />, - ); + root.render(); }); - const observedNode = ensureReactNativeElement(maybeObservedNode); + const observedNode = ensureReactNativeElement(observedNodeRef.current); const observerCallback = jest.fn(); const observer = new MutationObserver(observerCallback); @@ -1030,21 +864,14 @@ describe('MutationObserver', () => { }); it('should correctly unobserve targets that are disconnected before observing', () => { - let maybeObservedNode; + const observedNodeRef = React.createRef(); const root = Fantom.createRoot(); Fantom.runTask(() => { - root.render( - { - maybeObservedNode = receivedNode; - }} - />, - ); + root.render(); }); - const observedNode = ensureReactNativeElement(maybeObservedNode); + const observedNode = ensureReactNativeElement(observedNodeRef.current); Fantom.runTask(() => { root.render(<>);