diff --git a/packages/react-native-fantom/runner/getFantomTestConfig.js b/packages/react-native-fantom/runner/getFantomTestConfig.js index d4d34a365ea2..660fe4dcd3d7 100644 --- a/packages/react-native-fantom/runner/getFantomTestConfig.js +++ b/packages/react-native-fantom/runner/getFantomTestConfig.js @@ -47,7 +47,7 @@ const DEFAULT_MODE: FantomTestConfigMode = const FANTOM_FLAG_FORMAT = /^(\w+):(\w+)$/; const FANTOM_BENCHMARK_FILENAME_RE = /[Bb]enchmark-itest\./g; -const FANTOM_BENCHMARK_SUITE_RE = /\nunstable_benchmark(\s*)\.suite\(/g; +const FANTOM_BENCHMARK_SUITE_RE = /\nFantom.unstable_benchmark(\s*)\.suite\(/g; /** * Extracts the Fantom configuration from the test file, specified as part of diff --git a/packages/react-native-fantom/src/__tests__/Fantom-itest.js b/packages/react-native-fantom/src/__tests__/Fantom-itest.js index 09669e63d434..fffd228f8707 100644 --- a/packages/react-native-fantom/src/__tests__/Fantom-itest.js +++ b/packages/react-native-fantom/src/__tests__/Fantom-itest.js @@ -14,13 +14,7 @@ import 'react-native/Libraries/Core/InitializeCore'; import type {Root} from '..'; -import { - createRoot, - dispatchNativeEvent, - runOnUIThread, - runTask, - runWorkLoop, -} from '..'; +import Fantom from '..'; import * as React from 'react'; import {ScrollView, Text, TextInput, View} from 'react-native'; import ensureInstance from 'react-native/src/private/utilities/ensureInstance'; @@ -32,7 +26,7 @@ function getActualViewportDimensions(root: Root): { } { let maybeNode; - runTask(() => { + Fantom.runTask(() => { root.render( { it('should run a task synchronously', () => { const task = jest.fn(); - runTask(task); + Fantom.runTask(task); expect(task).toHaveBeenCalledTimes(1); }); @@ -66,7 +60,7 @@ describe('Fantom', () => { // eslint-disable-next-line jest/no-disabled-tests it.skip('should re-throw errors from the task synchronously', () => { expect(() => { - runTask(() => { + Fantom.runTask(() => { throw new Error('test error'); }); }).toThrow('test error'); @@ -75,7 +69,7 @@ describe('Fantom', () => { it('should exhaust the microtask queue synchronously', () => { const lastMicrotask = jest.fn(); - runTask(() => { + Fantom.runTask(() => { queueMicrotask(() => { queueMicrotask(() => { queueMicrotask(() => { @@ -92,7 +86,7 @@ describe('Fantom', () => { // eslint-disable-next-line jest/no-disabled-tests it.skip('should re-throw errors from microtasks synchronously', () => { expect(() => { - runTask(() => { + Fantom.runTask(() => { queueMicrotask(() => { throw new Error('test error'); }); @@ -103,7 +97,7 @@ describe('Fantom', () => { it('should run async tasks synchronously', () => { let completed = false; - runTask(async () => { + Fantom.runTask(async () => { await Promise.resolve(6); completed = true; }); @@ -115,10 +109,10 @@ describe('Fantom', () => { it('should throw when running a task inside another task', () => { let threw = false; - runTask(() => { + Fantom.runTask(() => { // TODO replace with expect(() => { ... }).toThrow() when error handling is fixed try { - runTask(() => {}); + Fantom.runTask(() => {}); } catch { threw = true; } @@ -127,10 +121,10 @@ describe('Fantom', () => { threw = false; - runTask(() => { + Fantom.runTask(() => { queueMicrotask(() => { try { - runTask(() => {}); + Fantom.runTask(() => {}); } catch { threw = true; } @@ -142,14 +136,14 @@ describe('Fantom', () => { describe('createRoot', () => { it('allows creating a root with specific dimensions', () => { - const rootWithDefaults = createRoot(); + const rootWithDefaults = Fantom.createRoot(); expect(getActualViewportDimensions(rootWithDefaults)).toEqual({ viewportWidth: 390, viewportHeight: 844, }); - const rootWithCustomWidthAndHeight = createRoot({ + const rootWithCustomWidthAndHeight = Fantom.createRoot({ viewportWidth: 200, viewportHeight: 600, }); @@ -166,9 +160,9 @@ describe('Fantom', () => { describe('getRenderedOutput', () => { describe('toJSX', () => { it('default config', () => { - const root = createRoot(); + const root = Fantom.createRoot(); - runTask(() => { + Fantom.runTask(() => { root.render( , ); @@ -182,9 +176,9 @@ describe('Fantom', () => { }); it('default config, list of children', () => { - const root = createRoot(); + const root = Fantom.createRoot(); - runTask(() => { + Fantom.runTask(() => { root.render( <> { }); it('include root', () => { - const root = createRoot(); + const root = Fantom.createRoot(); - runTask(() => { + Fantom.runTask(() => { root.render( , ); @@ -230,9 +224,9 @@ describe('Fantom', () => { }); it('include layout metrics', () => { - const root = createRoot(); + const root = Fantom.createRoot(); - runTask(() => { + Fantom.runTask(() => { root.render( , ); @@ -258,9 +252,9 @@ describe('Fantom', () => { }); it('take props', () => { - const root = createRoot(); + const root = Fantom.createRoot(); - runTask(() => { + Fantom.runTask(() => { root.render( , ); @@ -278,9 +272,9 @@ describe('Fantom', () => { }); it('skip props', () => { - const root = createRoot(); + const root = Fantom.createRoot(); - runTask(() => { + Fantom.runTask(() => { root.render( , ); @@ -298,9 +292,9 @@ describe('Fantom', () => { }); it('filter out all props', () => { - const root = createRoot(); + const root = Fantom.createRoot(); - runTask(() => { + Fantom.runTask(() => { root.render( <> { describe('toJSON', () => { it('nested text', () => { - const root = createRoot(); + const root = Fantom.createRoot(); - runTask(() => { + Fantom.runTask(() => { root.render( Testing native{' '} @@ -378,12 +372,12 @@ describe('Fantom', () => { describe('runOnUIThread + dispatchNativeEvent', () => { it('sends event without payload', () => { - const root = createRoot(); + const root = Fantom.createRoot(); let maybeNode; let focusEvent = jest.fn(); - runTask(() => { + Fantom.runTask(() => { root.render( { expect(focusEvent).toHaveBeenCalledTimes(0); - runOnUIThread(() => { - dispatchNativeEvent(element, 'focus'); + Fantom.runOnUIThread(() => { + Fantom.dispatchNativeEvent(element, 'focus'); }); // The tasks have not run. expect(focusEvent).toHaveBeenCalledTimes(0); - runWorkLoop(); + Fantom.runWorkLoop(); expect(focusEvent).toHaveBeenCalledTimes(1); }); }); it('sends event with payload', () => { - const root = createRoot(); + const root = Fantom.createRoot(); let maybeNode; const onChange = jest.fn(); - runTask(() => { + Fantom.runTask(() => { root.render( { @@ -431,13 +425,13 @@ describe('Fantom', () => { const element = ensureInstance(maybeNode, ReactNativeElement); - runOnUIThread(() => { - dispatchNativeEvent(element, 'change', { + Fantom.runOnUIThread(() => { + Fantom.dispatchNativeEvent(element, 'change', { text: 'Hello World', }); }); - runWorkLoop(); + Fantom.runWorkLoop(); expect(onChange).toHaveBeenCalledTimes(1); const [entry] = onChange.mock.lastCall; @@ -445,11 +439,11 @@ describe('Fantom', () => { }); it('it batches events with isUnique option', () => { - const root = createRoot(); + const root = Fantom.createRoot(); let maybeNode; const onScroll = jest.fn(); - runTask(() => { + Fantom.runTask(() => { root.render( { @@ -464,14 +458,14 @@ describe('Fantom', () => { const element = ensureInstance(maybeNode, ReactNativeElement); - runOnUIThread(() => { - dispatchNativeEvent(element, 'scroll', { + Fantom.runOnUIThread(() => { + Fantom.dispatchNativeEvent(element, 'scroll', { contentOffset: { x: 0, y: 1, }, }); - dispatchNativeEvent( + Fantom.dispatchNativeEvent( element, 'scroll', { @@ -486,7 +480,7 @@ describe('Fantom', () => { ); }); - runWorkLoop(); + Fantom.runWorkLoop(); expect(onScroll).toHaveBeenCalledTimes(1); const [entry] = onScroll.mock.lastCall; diff --git a/packages/react-native-fantom/src/index.js b/packages/react-native-fantom/src/index.js index d73ad04e57aa..ae1280c41b6a 100644 --- a/packages/react-native-fantom/src/index.js +++ b/packages/react-native-fantom/src/index.js @@ -97,7 +97,7 @@ const DEFAULT_TASK_PRIORITY = schedulerPriorityImmediate; * If the work loop is running, it will be executed according to its priority. * Otherwise, it will wait in the queue until the work loop runs. */ -export function scheduleTask(task: () => void | Promise) { +function scheduleTask(task: () => void | Promise) { nativeRuntimeScheduler.unstable_scheduleCallback(DEFAULT_TASK_PRIORITY, task); } @@ -108,7 +108,7 @@ let flushingQueue = false; * * React must run inside of event loop to ensure scheduling environment is closer to production. */ -export function runTask(task: () => void | Promise) { +function runTask(task: () => void | Promise) { if (flushingQueue) { throw new Error( 'Nested `runTask` calls are not allowed. If you want to schedule a task from inside another task, use `scheduleTask` instead.', @@ -122,7 +122,7 @@ export function runTask(task: () => void | Promise) { /* * Simmulates running a task on the UI thread and forces side effect to drain the event queue, dispatching events to JavaScript. */ -export function runOnUIThread(task: () => void) { +function runOnUIThread(task: () => void) { task(); NativeFantom.flushEventQueue(); } @@ -130,7 +130,7 @@ export function runOnUIThread(task: () => void) { /** * Runs the event loop until all tasks are executed. */ -export function runWorkLoop(): void { +function runWorkLoop(): void { if (flushingQueue) { throw new Error( 'Cannot start the work loop because it is already running. If you want to schedule a task from inside another task, use `scheduleTask` instead.', @@ -147,11 +147,11 @@ export function runWorkLoop(): void { // TODO: Add option to define surface props and pass it to startSurface // Surfacep rops: concurrentRoot, surfaceWidth, surfaceHeight, layoutDirection, pointScaleFactor. -export function createRoot(rootConfig?: RootConfig): Root { +function createRoot(rootConfig?: RootConfig): Root { return new Root(rootConfig); } -export function dispatchNativeEvent( +function dispatchNativeEvent( node: ReactNativeElement, type: string, payload?: {[key: string]: mixed}, @@ -167,8 +167,6 @@ export function dispatchNativeEvent( ); } -export const unstable_benchmark = Benchmark; - type FantomConstants = $ReadOnly<{ isRunningFromCI: boolean, }>; @@ -248,3 +246,13 @@ if (typeof global.EventTarget === 'undefined') { 'The global Event class is already defined. If this API is already defined by React Native, you might want to remove this logic.', ); } + +export default { + scheduleTask, + runTask, + runOnUIThread, + runWorkLoop, + createRoot, + dispatchNativeEvent, + unstable_benchmark: Benchmark, +}; diff --git a/packages/react-native/Libraries/Components/ScrollView/__tests__/ScrollView-itest.js b/packages/react-native/Libraries/Components/ScrollView/__tests__/ScrollView-itest.js index 99579c7fed6c..4e32320256a4 100644 --- a/packages/react-native/Libraries/Components/ScrollView/__tests__/ScrollView-itest.js +++ b/packages/react-native/Libraries/Components/ScrollView/__tests__/ScrollView-itest.js @@ -14,7 +14,7 @@ import '../../../Core/InitializeCore.js'; import ensureInstance from '../../../../src/private/utilities/ensureInstance'; import ReactNativeElement from '../../../../src/private/webapis/dom/nodes/ReactNativeElement'; import ScrollView from '../ScrollView'; -import * as Fantom from '@react-native/fantom'; +import Fantom from '@react-native/fantom'; import * as React from 'react'; describe('onScroll', () => { 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 bd5789b5f8e4..9a4fa533e77a 100644 --- a/packages/react-native/Libraries/Components/TextInput/__tests__/TextInput-itest.js +++ b/packages/react-native/Libraries/Components/TextInput/__tests__/TextInput-itest.js @@ -15,7 +15,7 @@ import '../../../Core/InitializeCore.js'; import ensureInstance from '../../../../src/private/utilities/ensureInstance'; import ReactNativeElement from '../../../../src/private/webapis/dom/nodes/ReactNativeElement'; import TextInput from '../TextInput'; -import * as Fantom from '@react-native/fantom'; +import Fantom from '@react-native/fantom'; import * as React from 'react'; import {useEffect, useLayoutEffect, useRef} from 'react'; diff --git a/packages/react-native/Libraries/Components/View/__tests__/View-itest.js b/packages/react-native/Libraries/Components/View/__tests__/View-itest.js index faf23d4e17be..228aba8203e5 100644 --- a/packages/react-native/Libraries/Components/View/__tests__/View-itest.js +++ b/packages/react-native/Libraries/Components/View/__tests__/View-itest.js @@ -11,7 +11,7 @@ import '../../../Core/InitializeCore.js'; -import * as Fantom from '@react-native/fantom'; +import Fantom from '@react-native/fantom'; import * as React from 'react'; const View = require('../View'); diff --git a/packages/react-native/Libraries/ReactNative/ReactFabricPublicInstance/__tests__/ReactFabricPublicInstance-benchmark-itest.js b/packages/react-native/Libraries/ReactNative/ReactFabricPublicInstance/__tests__/ReactFabricPublicInstance-benchmark-itest.js index 3f2c52cb3848..0bd47f3dde63 100644 --- a/packages/react-native/Libraries/ReactNative/ReactFabricPublicInstance/__tests__/ReactFabricPublicInstance-benchmark-itest.js +++ b/packages/react-native/Libraries/ReactNative/ReactFabricPublicInstance/__tests__/ReactFabricPublicInstance-benchmark-itest.js @@ -17,7 +17,7 @@ import type { import ReactNativeElement from '../../../../src/private/webapis/dom/nodes/ReactNativeElement'; import ReactFabricHostComponent from '../../../ReactNative/ReactFabricPublicInstance/ReactFabricHostComponent'; -import {unstable_benchmark} from '@react-native/fantom'; +import Fantom from '@react-native/fantom'; // Create fake parameters for the class. const tag = 11; @@ -30,7 +30,7 @@ const viewConfig: ViewConfig = { // $FlowExpectedError[incompatible-type] const internalInstanceHandle: InternalInstanceHandle = {}; -unstable_benchmark +Fantom.unstable_benchmark .suite('ReactNativeElement vs. ReactFabricHostComponent') .add('ReactNativeElement', () => { // eslint-disable-next-line no-new diff --git a/packages/react-native/Libraries/ReactNative/ReactFabricPublicInstance/__tests__/setUpReactFabricPublicInstanceFantomTests.js b/packages/react-native/Libraries/ReactNative/ReactFabricPublicInstance/__tests__/setUpReactFabricPublicInstanceFantomTests.js index a2f2c8a98c3e..034c5ba39b47 100644 --- a/packages/react-native/Libraries/ReactNative/ReactFabricPublicInstance/__tests__/setUpReactFabricPublicInstanceFantomTests.js +++ b/packages/react-native/Libraries/ReactNative/ReactFabricPublicInstance/__tests__/setUpReactFabricPublicInstanceFantomTests.js @@ -15,7 +15,7 @@ import ReactNativeElement from '../../../../src/private/webapis/dom/nodes/ReactN import TextInputState from '../../../Components/TextInput/TextInputState'; import View from '../../../Components/View/View'; import ReactFabricHostComponent from '../ReactFabricHostComponent'; -import * as Fantom from '@react-native/fantom'; +import Fantom from '@react-native/fantom'; import nullthrows from 'nullthrows'; import * as React from 'react'; diff --git a/packages/react-native/Libraries/ReactNative/__tests__/InterruptibleRendering-itest.js b/packages/react-native/Libraries/ReactNative/__tests__/InterruptibleRendering-itest.js index 19edf96e4bfb..2caef8d70277 100644 --- a/packages/react-native/Libraries/ReactNative/__tests__/InterruptibleRendering-itest.js +++ b/packages/react-native/Libraries/ReactNative/__tests__/InterruptibleRendering-itest.js @@ -15,7 +15,7 @@ import ensureInstance from '../../../src/private/utilities/ensureInstance'; import ReactNativeElement from '../../../src/private/webapis/dom/nodes/ReactNativeElement'; import TextInput from '../../Components/TextInput/TextInput'; import Text from '../../Text/Text'; -import * as Fantom from '@react-native/fantom'; +import Fantom from '@react-native/fantom'; import * as React from 'react'; import {startTransition, useDeferredValue, useEffect, useState} from 'react'; diff --git a/packages/react-native/Libraries/ReactNative/__tests__/ReactFabric-Suspense-itest.js b/packages/react-native/Libraries/ReactNative/__tests__/ReactFabric-Suspense-itest.js index a6fb24ad8bc9..0eba5f05e706 100644 --- a/packages/react-native/Libraries/ReactNative/__tests__/ReactFabric-Suspense-itest.js +++ b/packages/react-native/Libraries/ReactNative/__tests__/ReactFabric-Suspense-itest.js @@ -11,7 +11,7 @@ import '../../Core/InitializeCore.js'; import View from '../../Components/View/View'; -import * as Fantom from '@react-native/fantom'; +import Fantom from '@react-native/fantom'; import * as React from 'react'; import {Suspense, startTransition} from 'react'; 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 4e2b2f53a401..3d11c591ea57 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 @@ -24,7 +24,7 @@ import NodeList from '../../oldstylecollections/NodeList'; import ReactNativeElement from '../ReactNativeElement'; import ReadOnlyElement from '../ReadOnlyElement'; import ReadOnlyNode from '../ReadOnlyNode'; -import * as Fantom from '@react-native/fantom'; +import Fantom from '@react-native/fantom'; import * as React from 'react'; function ensureReactNativeElement(value: mixed): ReactNativeElement { 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 808f2f53e9ed..cdfb85ca2de1 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 @@ -17,7 +17,7 @@ import ensureInstance from '../../../../utilities/ensureInstance'; import ReactNativeElement from '../ReactNativeElement'; import ReadOnlyNode from '../ReadOnlyNode'; import ReadOnlyText from '../ReadOnlyText'; -import * as Fantom from '@react-native/fantom'; +import Fantom from '@react-native/fantom'; import invariant from 'invariant'; import * as React from 'react'; 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 aebb8226a1b4..db7f2365a946 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 @@ -14,7 +14,7 @@ import type IntersectionObserverType from '../IntersectionObserver'; import DOMRectReadOnly from '../../dom/geometry/DOMRectReadOnly'; -import * as Fantom from '@react-native/fantom'; +import Fantom from '@react-native/fantom'; import setUpIntersectionObserver from '../../../setup/setUpIntersectionObserver'; import ReactNativeElement from '../../dom/nodes/ReactNativeElement'; import IntersectionObserverEntry from '../IntersectionObserverEntry'; 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 e031d529a0ad..91130eb2fe3f 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 @@ -16,7 +16,7 @@ import View from '../../../../../Libraries/Components/View/View'; import setUpMutationObserver from '../../../setup/setUpMutationObserver'; import ensureInstance from '../../../utilities/ensureInstance'; import ReactNativeElement from '../../dom/nodes/ReactNativeElement'; -import * as Fantom from '@react-native/fantom'; +import Fantom from '@react-native/fantom'; import nullthrows from 'nullthrows'; import * as React from 'react'; diff --git a/packages/react-native/src/private/webapis/performance/__tests__/LongTaskAPI-itest.js b/packages/react-native/src/private/webapis/performance/__tests__/LongTaskAPI-itest.js index 3c6836101caa..7bba4474cd25 100644 --- a/packages/react-native/src/private/webapis/performance/__tests__/LongTaskAPI-itest.js +++ b/packages/react-native/src/private/webapis/performance/__tests__/LongTaskAPI-itest.js @@ -14,7 +14,7 @@ import type {PerformanceObserverCallbackOptions} from '../PerformanceObserver'; import setUpPerformanceObserver from '../../../setup/setUpPerformanceObserver'; import {PerformanceLongTaskTiming} from '../LongTasks'; -import * as Fantom from '@react-native/fantom'; +import Fantom from '@react-native/fantom'; import nullthrows from 'nullthrows'; import '../../../../../Libraries/Core/InitializeCore.js'; diff --git a/packages/react-native/src/private/webapis/performance/__tests__/UserTimingAPI-itest.js b/packages/react-native/src/private/webapis/performance/__tests__/UserTimingAPI-itest.js index f016bd201608..bbf3786756e1 100644 --- a/packages/react-native/src/private/webapis/performance/__tests__/UserTimingAPI-itest.js +++ b/packages/react-native/src/private/webapis/performance/__tests__/UserTimingAPI-itest.js @@ -13,7 +13,7 @@ import setUpPerformanceObserver from '../../../setup/setUpPerformanceObserver'; import ensureInstance from '../../../utilities/ensureInstance'; import {PerformanceMark} from '../UserTiming'; -import {runWorkLoop} from '@react-native/fantom'; +import Fantom from '@react-native/fantom'; import '../../../../../Libraries/Core/InitializeCore.js'; @@ -43,7 +43,7 @@ describe('User Timing API', () => { expect(callback).not.toHaveBeenCalled(); - runWorkLoop(); + Fantom.runWorkLoop(); expect(callback).toHaveBeenCalledTimes(1);