diff --git a/packages/react-native-fantom/src/__tests__/Fantom-itest.js b/packages/react-native-fantom/src/__tests__/Fantom-itest.js index f16d30bd10fbee..97c65c8eaa6616 100644 --- a/packages/react-native-fantom/src/__tests__/Fantom-itest.js +++ b/packages/react-native-fantom/src/__tests__/Fantom-itest.js @@ -7,13 +7,47 @@ * @flow strict-local * @format * @oncall react_native + * @fantom_flags enableAccessToHostTreeInFabric:true */ import 'react-native/Libraries/Core/InitializeCore'; +import type {Root} from '..'; + import {createRoot, runTask} from '..'; import * as React from 'react'; import {Text, View} from 'react-native'; +import ReactNativeElement from 'react-native/src/private/webapis/dom/nodes/ReactNativeElement'; + +function getActualViewportDimensions(root: Root): { + viewportWidth: number, + viewportHeight: number, +} { + let maybeNode; + + runTask(() => { + root.render( + { + maybeNode = node; + }} + />, + ); + }); + + if (!(maybeNode instanceof ReactNativeElement)) { + throw new Error( + `Expected instance of ReactNativeElement but got ${String(maybeNode)}`, + ); + } + + const rect = maybeNode.getBoundingClientRect(); + return { + viewportWidth: rect.width, + viewportHeight: rect.height, + }; +} describe('Fantom', () => { describe('runTask', () => { @@ -101,6 +135,29 @@ describe('Fantom', () => { }); }); + describe('createRoot', () => { + it('allows creating a root with specific dimensions', () => { + const rootWithDefaults = createRoot(); + + expect(getActualViewportDimensions(rootWithDefaults)).toEqual({ + viewportWidth: 1000, + viewportHeight: 1000, + }); + + const rootWithCustomWidthAndHeight = createRoot({ + viewportWidth: 200, + viewportHeight: 600, + }); + + expect(getActualViewportDimensions(rootWithCustomWidthAndHeight)).toEqual( + { + viewportWidth: 200, + viewportHeight: 600, + }, + ); + }); + }); + describe('getRenderedOutput', () => { describe('toJSX', () => { it('default config', () => { diff --git a/packages/react-native-fantom/src/index.js b/packages/react-native-fantom/src/index.js index 67795cc5c67f79..92e0bf0558ffdc 100644 --- a/packages/react-native-fantom/src/index.js +++ b/packages/react-native-fantom/src/index.js @@ -24,18 +24,41 @@ const nativeRuntimeScheduler = global.nativeRuntimeScheduler; const schedulerPriorityImmediate = nativeRuntimeScheduler.unstable_ImmediatePriority; +export type RootConfig = { + viewportWidth?: number, + viewportHeight?: number, + devicePixelRatio?: number, +}; + +const DEFAULT_VIEWPORT_WIDTH = 1000; +const DEFAULT_VIEWPORT_HEIGHT = 1000; +const DEFAULT_DEVICE_PIXEL_RATIO = 1; + class Root { #surfaceId: number; + #viewportWidth: number; + #viewportHeight: number; + #devicePixelRatio: number; + #hasRendered: boolean = false; - constructor() { + constructor(config?: RootConfig) { this.#surfaceId = globalSurfaceIdCounter; + this.#viewportWidth = config?.viewportWidth ?? DEFAULT_VIEWPORT_WIDTH; + this.#viewportHeight = config?.viewportHeight ?? DEFAULT_VIEWPORT_HEIGHT; + this.#devicePixelRatio = + config?.devicePixelRatio ?? DEFAULT_DEVICE_PIXEL_RATIO; globalSurfaceIdCounter += 10; } render(element: MixedElement) { if (!this.#hasRendered) { - NativeFantom.startSurface(this.#surfaceId); + NativeFantom.startSurface( + this.#surfaceId, + this.#viewportWidth, + this.#viewportHeight, + this.#devicePixelRatio, + ); this.#hasRendered = true; } @@ -59,6 +82,8 @@ class Root { // TODO: add an API to check if all surfaces were deallocated when tests are finished. } +export type {Root}; + const DEFAULT_TASK_PRIORITY = schedulerPriorityImmediate; /** @@ -108,6 +133,6 @@ 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(): Root { - return new Root(); +export function createRoot(rootConfig?: RootConfig): Root { + return new Root(rootConfig); } diff --git a/packages/react-native/src/private/specs/modules/NativeFantom.js b/packages/react-native/src/private/specs/modules/NativeFantom.js index 34c04f2eaebf61..f4b5ce24d49b3a 100644 --- a/packages/react-native/src/private/specs/modules/NativeFantom.js +++ b/packages/react-native/src/private/specs/modules/NativeFantom.js @@ -19,7 +19,12 @@ export type RenderFormatOptions = { }; interface Spec extends TurboModule { - startSurface: (surfaceId: number) => void; + startSurface: ( + surfaceId: number, + viewportWidth: number, + viewportHeight: number, + devicePixelRatio: number, + ) => void; stopSurface: (surfaceId: number) => void; getMountingManagerLogs: (surfaceId: number) => Array; flushMessageQueue: () => void;