diff --git a/packages/react-native/Libraries/StyleSheet/__tests__/StyleSheet-test.js b/packages/react-native/Libraries/StyleSheet/__tests__/StyleSheet-itest.js
similarity index 61%
rename from packages/react-native/Libraries/StyleSheet/__tests__/StyleSheet-test.js
rename to packages/react-native/Libraries/StyleSheet/__tests__/StyleSheet-itest.js
index 5b5502940e50..59ce8acefec2 100644
--- a/packages/react-native/Libraries/StyleSheet/__tests__/StyleSheet-test.js
+++ b/packages/react-native/Libraries/StyleSheet/__tests__/StyleSheet-itest.js
@@ -8,31 +8,36 @@
* @format
*/
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import StyleSheet from '../StyleSheet';
const setStyleAttributePreprocessor = StyleSheet.setStyleAttributePreprocessor;
-describe(setStyleAttributePreprocessor, () => {
- beforeEach(() => {
- jest.resetModules();
- jest.spyOn(console, 'warn').mockImplementation(() => {});
- });
+describe('setStyleAttributePreprocessor', () => {
+ const originalConsoleWarn = console.warn;
afterEach(() => {
- jest.restoreAllMocks();
+ // $FlowExpectedError[cannot-write]
+ console.warn = originalConsoleWarn;
});
it('should not show warning when set preprocessor first time', () => {
- const spyConsole = jest.spyOn(global.console, 'warn');
+ const mockConsoleWarn = jest.fn();
+ // $FlowExpectedError[cannot-write]
+ console.warn = mockConsoleWarn;
+
setStyleAttributePreprocessor(
'fontFamily',
(fontFamily: string) => fontFamily,
);
- expect(spyConsole).not.toHaveBeenCalled();
+ expect(mockConsoleWarn).not.toHaveBeenCalled();
});
it('should show warning when overwrite the preprocessor', () => {
- const spyConsole = jest.spyOn(global.console, 'warn');
+ const mockConsoleWarn = jest.fn();
+ // $FlowExpectedError[cannot-write]
+ console.warn = mockConsoleWarn;
+
setStyleAttributePreprocessor(
'fontFamily',
(fontFamily: string) => fontFamily,
@@ -41,7 +46,7 @@ describe(setStyleAttributePreprocessor, () => {
'fontFamily',
(fontFamily: string) => `Scoped-${fontFamily}`,
);
- expect(spyConsole).toHaveBeenCalledWith(
+ expect(mockConsoleWarn).toHaveBeenCalledWith(
'Overwriting fontFamily style attribute preprocessor',
);
});
diff --git a/packages/react-native/Libraries/StyleSheet/__tests__/__snapshots__/processAspectRatio-test.js.snap b/packages/react-native/Libraries/StyleSheet/__tests__/__snapshots__/processAspectRatio-test.js.snap
deleted file mode 100644
index 2c6ddd3490df..000000000000
--- a/packages/react-native/Libraries/StyleSheet/__tests__/__snapshots__/processAspectRatio-test.js.snap
+++ /dev/null
@@ -1,13 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`processAspectRatio should not accept invalid formats 1`] = `"aspectRatio must either be a number, a ratio string or \`auto\`. You passed: 0a"`;
-
-exports[`processAspectRatio should not accept invalid formats 2`] = `"aspectRatio must either be a number, a ratio string or \`auto\`. You passed: 1 / 1 1"`;
-
-exports[`processAspectRatio should not accept invalid formats 3`] = `"aspectRatio must either be a number, a ratio string or \`auto\`. You passed: auto 1/1"`;
-
-exports[`processAspectRatio should not accept non string truthy types 1`] = `"aspectRatio must either be a number, a ratio string or \`auto\`. You passed: () => {}"`;
-
-exports[`processAspectRatio should not accept non string truthy types 2`] = `"aspectRatio must either be a number, a ratio string or \`auto\`. You passed: 1,2,3"`;
-
-exports[`processAspectRatio should not accept non string truthy types 3`] = `"aspectRatio must either be a number, a ratio string or \`auto\`. You passed: [object Object]"`;
diff --git a/packages/react-native/Libraries/StyleSheet/__tests__/__snapshots__/processTransform-test.js.snap b/packages/react-native/Libraries/StyleSheet/__tests__/__snapshots__/processTransform-test.js.snap
deleted file mode 100644
index 119c7344a130..000000000000
--- a/packages/react-native/Libraries/StyleSheet/__tests__/__snapshots__/processTransform-test.js.snap
+++ /dev/null
@@ -1,39 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`processTransform validation should throw on invalid transform property 1`] = `"Invalid transform translateW: {\\"translateW\\":10}"`;
-
-exports[`processTransform validation should throw on invalid transform property 2`] = `"Invalid transform translateW: {\\"translateW\\":10}"`;
-
-exports[`processTransform validation should throw on object with multiple properties 1`] = `"You must specify exactly one property per transform object. Passed properties: {\\"scale\\":0.5,\\"translateY\\":10}"`;
-
-exports[`processTransform validation should throw when not passing an array to an array prop 1`] = `"Transform with key of matrix must have an array as the value: {\\"matrix\\":\\"not-a-matrix\\"}"`;
-
-exports[`processTransform validation should throw when not passing an array to an array prop 2`] = `"Transform with key of translate must have an array as the value: {\\"translate\\":10}"`;
-
-exports[`processTransform validation should throw when passing a matrix of the wrong size 1`] = `"Matrix transform must have a length of 9 (2d) or 16 (3d). Provided matrix has a length of 4: {\\"matrix\\":[1,1,1,1]}"`;
-
-exports[`processTransform validation should throw when passing a matrix of the wrong size 2`] = `"Matrix transform must have a length of 9 (2d) or 16 (3d). Provided matrix has a length of 4: {\\"matrix\\":[1,1,1,1]}"`;
-
-exports[`processTransform validation should throw when passing a perspective of 0 1`] = `"Transform with key of \\"perspective\\" cannot be zero: {\\"perspective\\":0}"`;
-
-exports[`processTransform validation should throw when passing a translate of the wrong size 1`] = `"Transform with key translate must be an array of length 2 or 3, found 1: {\\"translate\\":[1]}"`;
-
-exports[`processTransform validation should throw when passing a translate of the wrong size 2`] = `"Transform with key translate must be an array of length 2 or 3, found 4: {\\"translate\\":[1,1,1,1]}"`;
-
-exports[`processTransform validation should throw when passing a translate of the wrong size 3`] = `"Transform with key translate must be an string with 1 or 2 parameters, found 4: translate(1px, 1px, 1px, 1px)"`;
-
-exports[`processTransform validation should throw when passing an Animated.Value 1`] = `"You passed an Animated.Value to a normal component. You need to wrap that component in an Animated. For example, replace by ."`;
-
-exports[`processTransform validation should throw when passing an invalid angle prop 1`] = `"Transform with key of \\"rotate\\" must be a string: {\\"rotate\\":10}"`;
-
-exports[`processTransform validation should throw when passing an invalid angle prop 2`] = `"Transform with key of \\"rotate\\" must be a string: {\\"rotate\\":10}"`;
-
-exports[`processTransform validation should throw when passing an invalid angle prop 3`] = `"Rotate transform must be expressed in degrees (deg) or radians (rad): {\\"skewX\\":\\"10drg\\"}"`;
-
-exports[`processTransform validation should throw when passing an invalid angle prop 4`] = `"Rotate transform must be expressed in degrees (deg) or radians (rad): {\\"skewX\\":\\"10drg\\"}"`;
-
-exports[`processTransform validation should throw when passing an invalid value to a number prop 1`] = `"Transform with key of \\"translateY\\" must be number or a percentage. Passed value: {\\"translateY\\":\\"20deg\\"}."`;
-
-exports[`processTransform validation should throw when passing an invalid value to a number prop 2`] = `"Transform with key of \\"scale\\" must be a number: {\\"scale\\":{\\"x\\":10,\\"y\\":10}}"`;
-
-exports[`processTransform validation should throw when passing an invalid value to a number prop 3`] = `"Transform with key of \\"perspective\\" must be a number: {\\"perspective\\":[]}"`;
diff --git a/packages/react-native/Libraries/StyleSheet/__tests__/__snapshots__/processTransformOrigin-test.js.snap b/packages/react-native/Libraries/StyleSheet/__tests__/__snapshots__/processTransformOrigin-test.js.snap
deleted file mode 100644
index 8d6455d0b55c..000000000000
--- a/packages/react-native/Libraries/StyleSheet/__tests__/__snapshots__/processTransformOrigin-test.js.snap
+++ /dev/null
@@ -1,5 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`processTransformOrigin validation only accepts three values 1`] = `"Transform origin must have exactly 3 values."`;
-
-exports[`processTransformOrigin validation only accepts three values 2`] = `"Transform origin must have exactly 3 values."`;
\ No newline at end of file
diff --git a/packages/react-native/Libraries/StyleSheet/__tests__/flattenStyle-test.js b/packages/react-native/Libraries/StyleSheet/__tests__/flattenStyle-itest.js
similarity index 98%
rename from packages/react-native/Libraries/StyleSheet/__tests__/flattenStyle-test.js
rename to packages/react-native/Libraries/StyleSheet/__tests__/flattenStyle-itest.js
index e380443585b4..784de0674786 100644
--- a/packages/react-native/Libraries/StyleSheet/__tests__/flattenStyle-test.js
+++ b/packages/react-native/Libraries/StyleSheet/__tests__/flattenStyle-itest.js
@@ -8,7 +8,7 @@
* @format
*/
-'use strict';
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
const flattenStyle = require('../flattenStyle').default;
const StyleSheet = require('../StyleSheet').default;
diff --git a/packages/react-native/Libraries/StyleSheet/__tests__/normalizeColor-test.js b/packages/react-native/Libraries/StyleSheet/__tests__/normalizeColor-itest.js
similarity index 92%
rename from packages/react-native/Libraries/StyleSheet/__tests__/normalizeColor-test.js
rename to packages/react-native/Libraries/StyleSheet/__tests__/normalizeColor-itest.js
index 2ed9a653af8b..860f7aa64792 100644
--- a/packages/react-native/Libraries/StyleSheet/__tests__/normalizeColor-test.js
+++ b/packages/react-native/Libraries/StyleSheet/__tests__/normalizeColor-itest.js
@@ -8,16 +8,15 @@
* @format
*/
-'use strict';
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
const {OS} = require('../../Utilities/Platform').default;
const normalizeColor = require('../normalizeColor').default;
it('forwards calls to @react-native/normalize-colors', () => {
- jest.resetModules().mock('@react-native/normalize-colors', () => jest.fn());
-
- expect(require('../normalizeColor').default('#abc')).not.toBe(null);
- expect(require('@react-native/normalize-colors')).toBeCalled();
+ // normalizeColor delegates string and number inputs to
+ // @react-native/normalize-colors, which returns a 0xrrggbbaa integer.
+ expect(normalizeColor('#abcdef')).toBe(0xabcdefff);
});
describe('iOS', () => {
diff --git a/packages/react-native/Libraries/StyleSheet/__tests__/processAspectRatio-test.js b/packages/react-native/Libraries/StyleSheet/__tests__/processAspectRatio-itest.js
similarity index 70%
rename from packages/react-native/Libraries/StyleSheet/__tests__/processAspectRatio-test.js
rename to packages/react-native/Libraries/StyleSheet/__tests__/processAspectRatio-itest.js
index d4fd8cf122df..2caf20f6cdc2 100644
--- a/packages/react-native/Libraries/StyleSheet/__tests__/processAspectRatio-test.js
+++ b/packages/react-native/Libraries/StyleSheet/__tests__/processAspectRatio-itest.js
@@ -8,6 +8,7 @@
* @format
*/
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import processAspectRatio from '../processAspectRatio';
describe('processAspectRatio', () => {
@@ -41,9 +42,15 @@ describe('processAspectRatio', () => {
});
it('should not accept invalid formats', () => {
- expect(() => processAspectRatio('0a')).toThrowErrorMatchingSnapshot();
- expect(() => processAspectRatio('1 / 1 1')).toThrowErrorMatchingSnapshot();
- expect(() => processAspectRatio('auto 1/1')).toThrowErrorMatchingSnapshot();
+ expect(() => processAspectRatio('0a')).toThrow(
+ 'aspectRatio must either be a number, a ratio string or `auto`. You passed: 0a',
+ );
+ expect(() => processAspectRatio('1 / 1 1')).toThrow(
+ 'aspectRatio must either be a number, a ratio string or `auto`. You passed: 1 / 1 1',
+ );
+ expect(() => processAspectRatio('auto 1/1')).toThrow(
+ 'aspectRatio must either be a number, a ratio string or `auto`. You passed: auto 1/1',
+ );
});
it('should ignore non string falsy types', () => {
@@ -57,8 +64,12 @@ describe('processAspectRatio', () => {
it('should not accept non string truthy types', () => {
const invalidThings = [() => {}, [1, 2, 3], {}];
for (const thing of invalidThings) {
- // $FlowExpectedError[incompatible-type]
- expect(() => processAspectRatio(thing)).toThrowErrorMatchingSnapshot();
+ expect(() =>
+ // $FlowExpectedError[incompatible-type]
+ processAspectRatio(thing),
+ ).toThrow(
+ `aspectRatio must either be a number, a ratio string or \`auto\`. You passed: ${String(thing)}`,
+ );
}
});
});
diff --git a/packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundImage-test.js b/packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundImage-itest.js
similarity index 99%
rename from packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundImage-test.js
rename to packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundImage-itest.js
index 87b7fbdc38d0..08a0ca0b9700 100644
--- a/packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundImage-test.js
+++ b/packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundImage-itest.js
@@ -8,6 +8,8 @@
* @format
*/
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
+
import type {BackgroundImageValue} from '../StyleSheetTypes';
import processBackgroundImage from '../processBackgroundImage';
diff --git a/packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundPosition-test.js b/packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundPosition-itest.js
similarity index 99%
rename from packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundPosition-test.js
rename to packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundPosition-itest.js
index 16b4968233dc..c8d7a6049b33 100644
--- a/packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundPosition-test.js
+++ b/packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundPosition-itest.js
@@ -8,8 +8,7 @@
* @format
*/
-'use strict';
-
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import processBackgroundPosition from '../processBackgroundPosition';
describe('processBackgroundPosition', () => {
diff --git a/packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundRepeat-test.js b/packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundRepeat-itest.js
similarity index 99%
rename from packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundRepeat-test.js
rename to packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundRepeat-itest.js
index 586bc433a228..0bbad8c6aec7 100644
--- a/packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundRepeat-test.js
+++ b/packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundRepeat-itest.js
@@ -8,8 +8,7 @@
* @format
*/
-'use strict';
-
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import processBackgroundRepeat from '../processBackgroundRepeat';
describe('processBackgroundRepeat', () => {
diff --git a/packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundSize-test.js b/packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundSize-itest.js
similarity index 98%
rename from packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundSize-test.js
rename to packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundSize-itest.js
index a985732868a0..82cd5c66ba75 100644
--- a/packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundSize-test.js
+++ b/packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundSize-itest.js
@@ -8,8 +8,7 @@
* @format
*/
-'use strict';
-
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import processBackgroundSize from '../processBackgroundSize';
describe('processBackgroundSize', () => {
diff --git a/packages/react-native/Libraries/StyleSheet/__tests__/processColor-test.js b/packages/react-native/Libraries/StyleSheet/__tests__/processColor-itest.js
similarity index 98%
rename from packages/react-native/Libraries/StyleSheet/__tests__/processColor-test.js
rename to packages/react-native/Libraries/StyleSheet/__tests__/processColor-itest.js
index 1c9d8f52fd6b..5084f8787785 100644
--- a/packages/react-native/Libraries/StyleSheet/__tests__/processColor-test.js
+++ b/packages/react-native/Libraries/StyleSheet/__tests__/processColor-itest.js
@@ -8,7 +8,7 @@
* @format
*/
-'use strict';
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
const {OS} = require('../../Utilities/Platform').default;
const PlatformColorAndroid =
diff --git a/packages/react-native/Libraries/StyleSheet/__tests__/processColorArray-test.js b/packages/react-native/Libraries/StyleSheet/__tests__/processColorArray-itest.js
similarity index 88%
rename from packages/react-native/Libraries/StyleSheet/__tests__/processColorArray-test.js
rename to packages/react-native/Libraries/StyleSheet/__tests__/processColorArray-itest.js
index 6d04bdb3017c..a20fc55d8b02 100644
--- a/packages/react-native/Libraries/StyleSheet/__tests__/processColorArray-test.js
+++ b/packages/react-native/Libraries/StyleSheet/__tests__/processColorArray-itest.js
@@ -8,7 +8,7 @@
* @format
*/
-'use strict';
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
const {OS} = require('../../Utilities/Platform').default;
const PlatformColorAndroid =
@@ -28,6 +28,13 @@ const platformSpecific =
: x => x;
describe('processColorArray', () => {
+ const originalConsoleError = console.error;
+
+ afterEach(() => {
+ // $FlowExpectedError[cannot-write]
+ console.error = originalConsoleError;
+ });
+
describe('predefined color name array', () => {
it('should convert array of color name type', () => {
const colorFromStringArray = processColorArray(['red', 'white', 'black']);
@@ -46,8 +53,7 @@ describe('processColorArray', () => {
const expectedIntArray = [0xff0a141e, 0xff1e140a, 0xff3296fa].map(
platformSpecific,
);
- // $FlowFixMe[incompatible-type]
- expect(colorFromRGBArray).toEqual(platformSpecific(expectedIntArray));
+ expect(colorFromRGBArray).toEqual(expectedIntArray);
});
it('should convert array of color type hsl(x, y%, z%)', () => {
@@ -59,8 +65,7 @@ describe('processColorArray', () => {
const expectedIntArray = [0xffdb3dac, 0xff234786, 0xff1e541d].map(
platformSpecific,
);
- // $FlowFixMe[incompatible-type]
- expect(colorFromHSLArray).toEqual(platformSpecific(expectedIntArray));
+ expect(colorFromHSLArray).toEqual(expectedIntArray);
});
it('should return null if no array', () => {
@@ -69,7 +74,9 @@ describe('processColorArray', () => {
});
it('converts invalid colors to transparent', () => {
- const spy = jest.spyOn(console, 'error').mockReturnValue(undefined);
+ const mockConsoleError = jest.fn();
+ // $FlowExpectedError[cannot-write]
+ console.error = mockConsoleError;
const colors = ['red', '???', null, undefined, false];
// $FlowExpectedError[incompatible-type]
@@ -80,13 +87,11 @@ describe('processColorArray', () => {
expect(colorFromStringArray).toEqual(expectedIntArray);
for (const color of colors.slice(1)) {
- expect(spy).toHaveBeenCalledWith(
+ expect(mockConsoleError).toHaveBeenCalledWith(
'Invalid value in color array:',
color,
);
}
-
- spy.mockRestore();
});
});
diff --git a/packages/react-native/Libraries/StyleSheet/__tests__/processFilter-test.js b/packages/react-native/Libraries/StyleSheet/__tests__/processFilter-itest.js
similarity index 99%
rename from packages/react-native/Libraries/StyleSheet/__tests__/processFilter-test.js
rename to packages/react-native/Libraries/StyleSheet/__tests__/processFilter-itest.js
index a80a62c963dc..213f375d9a75 100644
--- a/packages/react-native/Libraries/StyleSheet/__tests__/processFilter-test.js
+++ b/packages/react-native/Libraries/StyleSheet/__tests__/processFilter-itest.js
@@ -10,6 +10,8 @@
'use strict';
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
+
import type {FilterFunction} from '../StyleSheetTypes';
import processColor from '../processColor';
diff --git a/packages/react-native/Libraries/StyleSheet/__tests__/processFontVariant-test.js b/packages/react-native/Libraries/StyleSheet/__tests__/processFontVariant-itest.js
similarity index 95%
rename from packages/react-native/Libraries/StyleSheet/__tests__/processFontVariant-test.js
rename to packages/react-native/Libraries/StyleSheet/__tests__/processFontVariant-itest.js
index 0c93e06a9217..2474777f2864 100644
--- a/packages/react-native/Libraries/StyleSheet/__tests__/processFontVariant-test.js
+++ b/packages/react-native/Libraries/StyleSheet/__tests__/processFontVariant-itest.js
@@ -8,7 +8,7 @@
* @format
*/
-'use strict';
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
const processFontVariant = require('../processFontVariant').default;
diff --git a/packages/react-native/Libraries/StyleSheet/__tests__/processTransform-itest.js b/packages/react-native/Libraries/StyleSheet/__tests__/processTransform-itest.js
new file mode 100644
index 000000000000..83f94d7a3cd5
--- /dev/null
+++ b/packages/react-native/Libraries/StyleSheet/__tests__/processTransform-itest.js
@@ -0,0 +1,151 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @flow strict-local
+ * @format
+ */
+
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
+
+const processTransform = require('../processTransform').default;
+
+describe('processTransform', () => {
+ describe('validation', () => {
+ it('should accept an empty array', () => {
+ processTransform([]);
+ });
+
+ it('should accept an empty string', () => {
+ processTransform('');
+ });
+
+ it('should accept a simple valid transform', () => {
+ processTransform([
+ {scale: 0.5},
+ {translateX: 10},
+ {translateY: 20},
+ {rotate: '10deg'},
+ ]);
+ processTransform(
+ 'scale(0.5) translateX(10px) translateY(20px) rotate(10deg)',
+ );
+ });
+
+ it('should accept a percentage translate transform', () => {
+ processTransform([{translateY: '20%'}, {translateX: '10%'}]);
+ processTransform('translateX(10%)');
+ });
+
+ it('should throw on object with multiple properties', () => {
+ expect(() => processTransform([{scale: 0.5, translateY: 10}])).toThrow(
+ 'You must specify exactly one property per transform object. Passed properties: {"scale":0.5,"translateY":10}',
+ );
+ });
+
+ it('should throw on invalid transform property', () => {
+ expect(() => processTransform([{translateW: 10}])).toThrow(
+ 'Invalid transform translateW: {"translateW":10}',
+ );
+ expect(() => processTransform('translateW(10)')).toThrow(
+ 'Invalid transform translateW: {"translateW":10}',
+ );
+ });
+
+ it('should throw when not passing an array to an array prop', () => {
+ expect(() => processTransform([{matrix: 'not-a-matrix'}])).toThrow(
+ 'Transform with key of matrix must have an array as the value: {"matrix":"not-a-matrix"}',
+ );
+ expect(() => processTransform([{translate: 10}])).toThrow(
+ 'Transform with key of translate must have an array as the value: {"translate":10}',
+ );
+ });
+
+ it('should accept a valid matrix', () => {
+ processTransform([{matrix: [1, 1, 1, 1, 1, 1, 1, 1, 1]}]);
+ processTransform('matrix(1, 1, 1, 1, 1, 1, 1, 1, 1)');
+ processTransform([
+ {matrix: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]},
+ ]);
+ processTransform(
+ 'matrix(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)',
+ );
+ });
+
+ it('should throw when passing a matrix of the wrong size', () => {
+ expect(() => processTransform([{matrix: [1, 1, 1, 1]}])).toThrow(
+ 'Matrix transform must have a length of 9 (2d) or 16 (3d). Provided matrix has a length of 4: {"matrix":[1,1,1,1]}',
+ );
+ expect(() => processTransform('matrix(1, 1, 1, 1)')).toThrow(
+ 'Matrix transform must have a length of 9 (2d) or 16 (3d). Provided matrix has a length of 4: {"matrix":[1,1,1,1]}',
+ );
+ });
+
+ it('should accept a valid translate', () => {
+ processTransform([{translate: [1, 1]}]);
+ processTransform('translate(1px)');
+ processTransform('translate(1px, 1px)');
+ processTransform([{translate: [1, 1, 1]}]);
+ });
+
+ it('should throw when passing a translate of the wrong size', () => {
+ expect(() => processTransform([{translate: [1]}])).toThrow(
+ 'Transform with key translate must be an array of length 2 or 3, found 1: {"translate":[1]}',
+ );
+ expect(() => processTransform([{translate: [1, 1, 1, 1]}])).toThrow(
+ 'Transform with key translate must be an array of length 2 or 3, found 4: {"translate":[1,1,1,1]}',
+ );
+ expect(() => processTransform('translate(1px, 1px, 1px, 1px)')).toThrow(
+ 'Transform with key translate must be an string with 1 or 2 parameters, found 4: translate(1px, 1px, 1px, 1px)',
+ );
+ });
+
+ it('should throw when passing an invalid value to a number prop', () => {
+ expect(() => processTransform([{translateY: '20deg'}])).toThrow(
+ 'Transform with key of "translateY" must be number or a percentage. Passed value: {"translateY":"20deg"}.',
+ );
+ expect(() => processTransform([{scale: {x: 10, y: 10}}])).toThrow(
+ 'Transform with key of "scale" must be a number: {"scale":{"x":10,"y":10}}',
+ );
+ expect(() => processTransform([{perspective: []}])).toThrow(
+ 'Transform with key of "perspective" must be a number: {"perspective":[]}',
+ );
+ });
+
+ it('should throw when passing a perspective of 0', () => {
+ expect(() => processTransform([{perspective: 0}])).toThrow(
+ 'Transform with key of "perspective" cannot be zero: {"perspective":0}',
+ );
+ });
+
+ it('should accept an angle in degrees or radians', () => {
+ processTransform([{skewY: '10deg'}]);
+ processTransform('skewY(10deg)');
+ processTransform([{rotateX: '1.16rad'}]);
+ processTransform('rotateX(1.16rad)');
+ });
+
+ it('should throw when passing an invalid angle prop', () => {
+ expect(() => processTransform([{rotate: 10}])).toThrow(
+ 'Transform with key of "rotate" must be a string: {"rotate":10}',
+ );
+ expect(() => processTransform('rotate(10)')).toThrow(
+ 'Transform with key of "rotate" must be a string: {"rotate":10}',
+ );
+ expect(() => processTransform([{skewX: '10drg'}])).toThrow(
+ 'Rotate transform must be expressed in degrees (deg) or radians (rad): {"skewX":"10drg"}',
+ );
+ expect(() => processTransform('skewX(10drg)')).toThrow(
+ 'Rotate transform must be expressed in degrees (deg) or radians (rad): {"skewX":"10drg"}',
+ );
+ });
+
+ it('should throw when passing an Animated.Value', () => {
+ expect(() => processTransform([{rotate: {getValue: () => {}}}])).toThrow(
+ 'You passed an Animated.Value to a normal component. You need to wrap that component in an Animated. For example, replace by .',
+ );
+ });
+ });
+});
diff --git a/packages/react-native/Libraries/StyleSheet/__tests__/processTransform-test.js b/packages/react-native/Libraries/StyleSheet/__tests__/processTransform-test.js
deleted file mode 100644
index 5feafd9725a2..000000000000
--- a/packages/react-native/Libraries/StyleSheet/__tests__/processTransform-test.js
+++ /dev/null
@@ -1,151 +0,0 @@
-/**
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
- * @flow strict-local
- * @format
- */
-
-'use strict';
-
-const processTransform = require('../processTransform').default;
-
-describe('processTransform', () => {
- describe('validation', () => {
- it('should accept an empty array', () => {
- processTransform([]);
- });
-
- it('should accept an empty string', () => {
- processTransform('');
- });
-
- it('should accept a simple valid transform', () => {
- processTransform([
- {scale: 0.5},
- {translateX: 10},
- {translateY: 20},
- {rotate: '10deg'},
- ]);
- processTransform(
- 'scale(0.5) translateX(10px) translateY(20px) rotate(10deg)',
- );
- });
-
- it('should accept a percentage translate transform', () => {
- processTransform([{translateY: '20%'}, {translateX: '10%'}]);
- processTransform('translateX(10%)');
- });
-
- it('should throw on object with multiple properties', () => {
- expect(() =>
- processTransform([{scale: 0.5, translateY: 10}]),
- ).toThrowErrorMatchingSnapshot();
- });
-
- it('should throw on invalid transform property', () => {
- expect(() =>
- processTransform([{translateW: 10}]),
- ).toThrowErrorMatchingSnapshot();
- expect(() =>
- processTransform('translateW(10)'),
- ).toThrowErrorMatchingSnapshot();
- });
-
- it('should throw when not passing an array to an array prop', () => {
- expect(() =>
- processTransform([{matrix: 'not-a-matrix'}]),
- ).toThrowErrorMatchingSnapshot();
- expect(() =>
- processTransform([{translate: 10}]),
- ).toThrowErrorMatchingSnapshot();
- });
-
- it('should accept a valid matrix', () => {
- processTransform([{matrix: [1, 1, 1, 1, 1, 1, 1, 1, 1]}]);
- processTransform('matrix(1, 1, 1, 1, 1, 1, 1, 1, 1)');
- processTransform([
- {matrix: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]},
- ]);
- processTransform(
- 'matrix(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)',
- );
- });
-
- it('should throw when passing a matrix of the wrong size', () => {
- expect(() =>
- processTransform([{matrix: [1, 1, 1, 1]}]),
- ).toThrowErrorMatchingSnapshot();
- expect(() =>
- processTransform('matrix(1, 1, 1, 1)'),
- ).toThrowErrorMatchingSnapshot();
- });
-
- it('should accept a valid translate', () => {
- processTransform([{translate: [1, 1]}]);
- processTransform('translate(1px)');
- processTransform('translate(1px, 1px)');
- processTransform([{translate: [1, 1, 1]}]);
- });
-
- it('should throw when passing a translate of the wrong size', () => {
- expect(() =>
- processTransform([{translate: [1]}]),
- ).toThrowErrorMatchingSnapshot();
- expect(() =>
- processTransform([{translate: [1, 1, 1, 1]}]),
- ).toThrowErrorMatchingSnapshot();
- expect(() =>
- processTransform('translate(1px, 1px, 1px, 1px)'),
- ).toThrowErrorMatchingSnapshot();
- });
-
- it('should throw when passing an invalid value to a number prop', () => {
- expect(() =>
- processTransform([{translateY: '20deg'}]),
- ).toThrowErrorMatchingSnapshot();
- expect(() =>
- processTransform([{scale: {x: 10, y: 10}}]),
- ).toThrowErrorMatchingSnapshot();
- expect(() =>
- processTransform([{perspective: []}]),
- ).toThrowErrorMatchingSnapshot();
- });
-
- it('should throw when passing a perspective of 0', () => {
- expect(() =>
- processTransform([{perspective: 0}]),
- ).toThrowErrorMatchingSnapshot();
- });
-
- it('should accept an angle in degrees or radians', () => {
- processTransform([{skewY: '10deg'}]);
- processTransform('skewY(10deg)');
- processTransform([{rotateX: '1.16rad'}]);
- processTransform('rotateX(1.16rad)');
- });
-
- it('should throw when passing an invalid angle prop', () => {
- expect(() =>
- processTransform([{rotate: 10}]),
- ).toThrowErrorMatchingSnapshot();
- expect(() =>
- processTransform('rotate(10)'),
- ).toThrowErrorMatchingSnapshot();
- expect(() =>
- processTransform([{skewX: '10drg'}]),
- ).toThrowErrorMatchingSnapshot();
- expect(() =>
- processTransform('skewX(10drg)'),
- ).toThrowErrorMatchingSnapshot();
- });
-
- it('should throw when passing an Animated.Value', () => {
- expect(() =>
- processTransform([{rotate: {getValue: () => {}}}]),
- ).toThrowErrorMatchingSnapshot();
- });
- });
-});
diff --git a/packages/react-native/Libraries/StyleSheet/__tests__/processTransformOrigin-test.js b/packages/react-native/Libraries/StyleSheet/__tests__/processTransformOrigin-itest.js
similarity index 73%
rename from packages/react-native/Libraries/StyleSheet/__tests__/processTransformOrigin-test.js
rename to packages/react-native/Libraries/StyleSheet/__tests__/processTransformOrigin-itest.js
index 736642797530..976060faab26 100644
--- a/packages/react-native/Libraries/StyleSheet/__tests__/processTransformOrigin-test.js
+++ b/packages/react-native/Libraries/StyleSheet/__tests__/processTransformOrigin-itest.js
@@ -8,6 +8,7 @@
* @format
*/
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import processTransformOrigin from '../processTransformOrigin';
describe('processTransformOrigin', () => {
@@ -15,10 +16,10 @@ describe('processTransformOrigin', () => {
it('only accepts three values', () => {
expect(() => {
processTransformOrigin([]);
- }).toThrowErrorMatchingSnapshot();
+ }).toThrow('Transform origin must have exactly 3 values.');
expect(() => {
processTransformOrigin(['50%', '50%']);
- }).toThrowErrorMatchingSnapshot();
+ }).toThrow('Transform origin must have exactly 3 values.');
});
it('should transform a string', () => {
@@ -65,34 +66,22 @@ describe('processTransformOrigin', () => {
it('should not allow specifying same position twice', () => {
expect(() => {
processTransformOrigin('top top');
- }).toThrowErrorMatchingInlineSnapshot(
- `"Could not parse transform-origin: top top"`,
- );
+ }).toThrow('Could not parse transform-origin: top top');
expect(() => {
processTransformOrigin('right right');
- }).toThrowErrorMatchingInlineSnapshot(
- `"Transform-origin right can only be used for x-position"`,
- );
+ }).toThrow('Transform-origin right can only be used for x-position');
expect(() => {
processTransformOrigin('bottom bottom');
- }).toThrowErrorMatchingInlineSnapshot(
- `"Could not parse transform-origin: bottom bottom"`,
- );
+ }).toThrow('Could not parse transform-origin: bottom bottom');
expect(() => {
processTransformOrigin('left left');
- }).toThrowErrorMatchingInlineSnapshot(
- `"Transform-origin left can only be used for x-position"`,
- );
+ }).toThrow('Transform-origin left can only be used for x-position');
expect(() => {
processTransformOrigin('top bottom');
- }).toThrowErrorMatchingInlineSnapshot(
- `"Could not parse transform-origin: top bottom"`,
- );
+ }).toThrow('Could not parse transform-origin: top bottom');
expect(() => {
processTransformOrigin('left right');
- }).toThrowErrorMatchingInlineSnapshot(
- `"Transform-origin right can only be used for x-position"`,
- );
+ }).toThrow('Transform-origin right can only be used for x-position');
});
it('should handle three values', () => {
@@ -113,22 +102,16 @@ describe('processTransformOrigin', () => {
it('should enforce two value ordering', () => {
expect(() => {
processTransformOrigin('top 30%');
- }).toThrowErrorMatchingInlineSnapshot(
- `"Could not parse transform-origin: top 30%"`,
- );
+ }).toThrow('Could not parse transform-origin: top 30%');
});
it('should not allow percents for z-position', () => {
expect(() => {
processTransformOrigin('top 30% 30%');
- }).toThrowErrorMatchingInlineSnapshot(
- `"Could not parse transform-origin: top 30% 30%"`,
- );
+ }).toThrow('Could not parse transform-origin: top 30% 30%');
expect(() => {
processTransformOrigin('top 30% center');
- }).toThrowErrorMatchingInlineSnapshot(
- `"Could not parse transform-origin: top 30% center"`,
- );
+ }).toThrow('Could not parse transform-origin: top 30% center');
});
});
});
diff --git a/packages/react-native/Libraries/StyleSheet/__tests__/setNormalizedColorAlpha-test.js b/packages/react-native/Libraries/StyleSheet/__tests__/setNormalizedColorAlpha-itest.js
similarity index 94%
rename from packages/react-native/Libraries/StyleSheet/__tests__/setNormalizedColorAlpha-test.js
rename to packages/react-native/Libraries/StyleSheet/__tests__/setNormalizedColorAlpha-itest.js
index 03ab1e957f13..434139c0db02 100644
--- a/packages/react-native/Libraries/StyleSheet/__tests__/setNormalizedColorAlpha-test.js
+++ b/packages/react-native/Libraries/StyleSheet/__tests__/setNormalizedColorAlpha-itest.js
@@ -8,6 +8,7 @@
* @format
*/
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import normalizeColor from '../normalizeColor';
import setNormalizedColorAlpha from '../setNormalizedColorAlpha';
diff --git a/packages/react-native/Libraries/StyleSheet/__tests__/splitLayoutProps-test.js b/packages/react-native/Libraries/StyleSheet/__tests__/splitLayoutProps-itest.js
similarity index 94%
rename from packages/react-native/Libraries/StyleSheet/__tests__/splitLayoutProps-test.js
rename to packages/react-native/Libraries/StyleSheet/__tests__/splitLayoutProps-itest.js
index 4b2a49aa4208..75b494fa41de 100644
--- a/packages/react-native/Libraries/StyleSheet/__tests__/splitLayoutProps-test.js
+++ b/packages/react-native/Libraries/StyleSheet/__tests__/splitLayoutProps-itest.js
@@ -8,6 +8,7 @@
* @format
*/
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import splitLayoutProps from '../splitLayoutProps';
test('splits style objects', () => {
diff --git a/packages/react-native/Libraries/Utilities/__tests__/DeviceInfo-test.js b/packages/react-native/Libraries/Utilities/__tests__/DeviceInfo-itest.js
similarity index 73%
rename from packages/react-native/Libraries/Utilities/__tests__/DeviceInfo-test.js
rename to packages/react-native/Libraries/Utilities/__tests__/DeviceInfo-itest.js
index 558934824cda..22b6f0ebc498 100644
--- a/packages/react-native/Libraries/Utilities/__tests__/DeviceInfo-test.js
+++ b/packages/react-native/Libraries/Utilities/__tests__/DeviceInfo-itest.js
@@ -8,12 +8,12 @@
* @format
*/
-'use strict';
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
describe('DeviceInfo', () => {
const DeviceInfo = require('../DeviceInfo').default;
it('should give device info', () => {
- expect(DeviceInfo.getConstants()).toHaveProperty('Dimensions');
+ expect(DeviceInfo.getConstants().Dimensions).toBeDefined();
});
});
diff --git a/packages/react-native/Libraries/Utilities/__tests__/Dimensions-test.js b/packages/react-native/Libraries/Utilities/__tests__/Dimensions-itest.js
similarity index 96%
rename from packages/react-native/Libraries/Utilities/__tests__/Dimensions-test.js
rename to packages/react-native/Libraries/Utilities/__tests__/Dimensions-itest.js
index 4154ee6be09d..e4481e8f8be1 100644
--- a/packages/react-native/Libraries/Utilities/__tests__/Dimensions-test.js
+++ b/packages/react-native/Libraries/Utilities/__tests__/Dimensions-itest.js
@@ -8,6 +8,7 @@
* @format
*/
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import Dimensions from '../Dimensions';
import Platform from '../Platform';
diff --git a/packages/react-native/Libraries/Utilities/__tests__/PixelRatio-test.js b/packages/react-native/Libraries/Utilities/__tests__/PixelRatio-itest.js
similarity index 94%
rename from packages/react-native/Libraries/Utilities/__tests__/PixelRatio-test.js
rename to packages/react-native/Libraries/Utilities/__tests__/PixelRatio-itest.js
index 962c5014de47..b36433b2faf4 100644
--- a/packages/react-native/Libraries/Utilities/__tests__/PixelRatio-test.js
+++ b/packages/react-native/Libraries/Utilities/__tests__/PixelRatio-itest.js
@@ -8,6 +8,7 @@
* @format
*/
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import Dimensions from '../Dimensions';
import PixelRatio from '../PixelRatio';
diff --git a/packages/react-native/Libraries/Utilities/__tests__/Platform-test.js b/packages/react-native/Libraries/Utilities/__tests__/Platform-itest.js
similarity index 95%
rename from packages/react-native/Libraries/Utilities/__tests__/Platform-test.js
rename to packages/react-native/Libraries/Utilities/__tests__/Platform-itest.js
index b48f80600ecb..9ab174cea21e 100644
--- a/packages/react-native/Libraries/Utilities/__tests__/Platform-test.js
+++ b/packages/react-native/Libraries/Utilities/__tests__/Platform-itest.js
@@ -8,6 +8,8 @@
* @format
*/
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
+
import type {PlatformSelectSpec} from '../PlatformTypes';
// $FlowFixMe[missing-platform-support]
diff --git a/packages/react-native/Libraries/Utilities/__tests__/SceneTracker-test.js b/packages/react-native/Libraries/Utilities/__tests__/SceneTracker-itest.js
similarity index 92%
rename from packages/react-native/Libraries/Utilities/__tests__/SceneTracker-test.js
rename to packages/react-native/Libraries/Utilities/__tests__/SceneTracker-itest.js
index 524241a77f57..392f8fad5c32 100644
--- a/packages/react-native/Libraries/Utilities/__tests__/SceneTracker-test.js
+++ b/packages/react-native/Libraries/Utilities/__tests__/SceneTracker-itest.js
@@ -8,7 +8,7 @@
* @format
*/
-'use strict';
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
const SceneTracker = require('../SceneTracker').default;
diff --git a/packages/react-native/Libraries/Utilities/__tests__/binaryToBase64-itest.js b/packages/react-native/Libraries/Utilities/__tests__/binaryToBase64-itest.js
new file mode 100644
index 000000000000..bf39041e9805
--- /dev/null
+++ b/packages/react-native/Libraries/Utilities/__tests__/binaryToBase64-itest.js
@@ -0,0 +1,47 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @flow strict
+ */
+
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
+import binaryToBase64 from '../binaryToBase64';
+import base64 from 'base64-js';
+
+describe('binaryToBase64', () => {
+ it('should encode a Uint8Array', () => {
+ const bytes = new TextEncoder().encode('Test string');
+
+ expect(decodeBase64(binaryToBase64(bytes))).toEqual(Array.from(bytes));
+ });
+
+ it('should encode an ArrayBuffer', () => {
+ const bytes = new TextEncoder().encode('Test string');
+
+ expect(decodeBase64(binaryToBase64(bytes.buffer))).toEqual(
+ Array.from(bytes),
+ );
+ });
+
+ it('should encode a DataView', () => {
+ const bytes = new TextEncoder().encode('Test string');
+
+ expect(decodeBase64(binaryToBase64(new DataView(bytes.buffer)))).toEqual(
+ Array.from(bytes),
+ );
+ });
+
+ it('should not encode a non-ArrayBuffer or non-TypedArray', () => {
+ const input = ['i', 'n', 'v', 'a', 'l', 'i', 'd'];
+
+ // $FlowExpectedError[incompatible-type]
+ expect(() => binaryToBase64(input)).toThrow();
+ });
+});
+
+function decodeBase64(base64String: string): Array {
+ return Array.from(base64.toByteArray(base64String));
+}
diff --git a/packages/react-native/Libraries/Utilities/__tests__/binaryToBase64-test.js b/packages/react-native/Libraries/Utilities/__tests__/binaryToBase64-test.js
deleted file mode 100644
index 3e00f9170ae8..000000000000
--- a/packages/react-native/Libraries/Utilities/__tests__/binaryToBase64-test.js
+++ /dev/null
@@ -1,46 +0,0 @@
-/**
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
- * @flow strict
- */
-
-import binaryToBase64 from '../binaryToBase64';
-import base64 from 'base64-js';
-import {TextDecoder, TextEncoder} from 'util';
-
-describe('binaryToBase64', () => {
- it('should encode a Uint8Array', () => {
- const input = new TextEncoder().encode('Test string');
-
- expect(base64ToString(binaryToBase64(input))).toEqual('Test string');
- });
-
- it('should encode an ArrayBuffer', () => {
- const input = new TextEncoder().encode('Test string').buffer;
-
- expect(base64ToString(binaryToBase64(input))).toEqual('Test string');
- });
-
- it('should encode a DataView', () => {
- const input = new DataView(new TextEncoder().encode('Test string').buffer);
-
- expect(base64ToString(binaryToBase64(input))).toEqual('Test string');
- });
-
- it('should not encode a non-ArrayBuffer or non-TypedArray', () => {
- const input = ['i', 'n', 'v', 'a', 'l', 'i', 'd'];
-
- // $FlowExpectedError[incompatible-type]
- expect(() => binaryToBase64(input)).toThrowError();
- });
-});
-
-function base64ToString(base64String: string) {
- const byteArray = base64.toByteArray(base64String);
-
- // $FlowFixMe[incompatible-type] - `TextEncoder` constructor type is wrong.
- return new TextDecoder().decode(byteArray);
-}
diff --git a/packages/react-native/Libraries/Utilities/__tests__/deepFreezeAndThrowOnMutationInDev-test.js b/packages/react-native/Libraries/Utilities/__tests__/deepFreezeAndThrowOnMutationInDev-itest.js
similarity index 93%
rename from packages/react-native/Libraries/Utilities/__tests__/deepFreezeAndThrowOnMutationInDev-test.js
rename to packages/react-native/Libraries/Utilities/__tests__/deepFreezeAndThrowOnMutationInDev-itest.js
index 4188a7bef10d..4ecec82d63e6 100644
--- a/packages/react-native/Libraries/Utilities/__tests__/deepFreezeAndThrowOnMutationInDev-test.js
+++ b/packages/react-native/Libraries/Utilities/__tests__/deepFreezeAndThrowOnMutationInDev-itest.js
@@ -8,6 +8,8 @@
* @format
*/
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
+
const deepFreezeAndThrowOnMutationInDev =
require('../deepFreezeAndThrowOnMutationInDev').default;
@@ -53,7 +55,7 @@ describe('deepFreezeAndThrowOnMutationInDev', () => {
deepFreezeAndThrowOnMutationInDev(o);
expect(() => {
o.key = 'newValue';
- }).toThrowError(
+ }).toThrow(
'You attempted to set the key `key` with the value `"newValue"` ' +
'on an object that is meant to be immutable and has been frozen.',
);
@@ -66,7 +68,7 @@ describe('deepFreezeAndThrowOnMutationInDev', () => {
deepFreezeAndThrowOnMutationInDev(o);
expect(() => {
o.key = 'newValue';
- }).toThrowError(
+ }).toThrow(
'You attempted to set the key `key` with the value `"newValue"` ' +
'on an object that is meant to be immutable and has been frozen.',
);
@@ -80,7 +82,7 @@ describe('deepFreezeAndThrowOnMutationInDev', () => {
deepFreezeAndThrowOnMutationInDev(o);
expect(() => {
o.key1.key2.key3 = 'newValue';
- }).toThrowError(
+ }).toThrow(
'You attempted to set the key `key3` with the value `"newValue"` ' +
'on an object that is meant to be immutable and has been frozen.',
);
@@ -93,7 +95,7 @@ describe('deepFreezeAndThrowOnMutationInDev', () => {
deepFreezeAndThrowOnMutationInDev(o);
expect(() => {
o.key1.key2.key3 = 'newValue';
- }).toThrowError(
+ }).toThrow(
'You attempted to set the key `key3` with the value `"newValue"` ' +
'on an object that is meant to be immutable and has been frozen.',
);
@@ -105,12 +107,14 @@ describe('deepFreezeAndThrowOnMutationInDev', () => {
__DEV__ = true;
const o = {oldKey: 'value'};
deepFreezeAndThrowOnMutationInDev(o);
- expect(() => {
+ let message;
+ try {
// $FlowExpectedError[prop-missing]
o.newKey = 'value';
- }).toThrowError(
- /(Cannot|Can't) add property newKey, object is not extensible/,
- );
+ } catch (error: unknown) {
+ message = error instanceof Error ? error.message : String(error);
+ }
+ expect(message).toMatch(/Cannot add new property 'newKey'/);
// $FlowExpectedError[prop-missing]
expect(o.newKey).toBe(undefined);
});
diff --git a/packages/react-native/Libraries/Utilities/__tests__/logError-test.js b/packages/react-native/Libraries/Utilities/__tests__/logError-itest.js
similarity index 52%
rename from packages/react-native/Libraries/Utilities/__tests__/logError-test.js
rename to packages/react-native/Libraries/Utilities/__tests__/logError-itest.js
index 45d946df06ad..2b2f935027d4 100644
--- a/packages/react-native/Libraries/Utilities/__tests__/logError-test.js
+++ b/packages/react-native/Libraries/Utilities/__tests__/logError-itest.js
@@ -8,40 +8,50 @@
* @format
*/
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import logError from '../logError';
describe('logError', () => {
+ const originalConsoleError = console.error;
+
+ afterEach(() => {
+ // $FlowFixMe[cannot-write]
+ console.error = originalConsoleError;
+ });
+
it('logs error messages to the console', () => {
- console.error.apply = jest.fn();
+ const mockConsoleError = jest.fn();
+ // $FlowFixMe[cannot-write]
+ console.error = mockConsoleError;
logError('This is a log message');
- expect(console.error.apply).toHaveBeenCalledWith(console, [
- 'This is a log message',
- ]);
+ expect(mockConsoleError).toHaveBeenCalledWith('This is a log message');
});
it('logs error messages with multiple arguments to the console', () => {
- console.error.apply = jest.fn();
+ const mockConsoleError = jest.fn();
+ // $FlowFixMe[cannot-write]
+ console.error = mockConsoleError;
const data = 'log';
logError('This is a', data, 'message');
- expect(console.error.apply).toHaveBeenCalledWith(console, [
+ expect(mockConsoleError).toHaveBeenCalledWith(
'This is a',
'log',
'message',
- ]);
+ );
});
it('logs errors to the console', () => {
+ const mockConsoleError = jest.fn();
// $FlowFixMe[cannot-write]
- console.error = jest.fn();
+ console.error = mockConsoleError;
logError(new Error('The error message'));
- // $FlowFixMe[prop-missing]
- expect(console.error.mock.calls[0][0]).toContain(
+ expect(mockConsoleError.mock.calls[0][0]).toContain(
'Error: "The error message". Stack:',
);
});
diff --git a/packages/react-native/Libraries/Utilities/__tests__/mapWithSeparator-test.js b/packages/react-native/Libraries/Utilities/__tests__/mapWithSeparator-itest.js
similarity index 95%
rename from packages/react-native/Libraries/Utilities/__tests__/mapWithSeparator-test.js
rename to packages/react-native/Libraries/Utilities/__tests__/mapWithSeparator-itest.js
index 76ea9e87b801..c596be9a2a56 100644
--- a/packages/react-native/Libraries/Utilities/__tests__/mapWithSeparator-test.js
+++ b/packages/react-native/Libraries/Utilities/__tests__/mapWithSeparator-itest.js
@@ -8,6 +8,7 @@
* @format
*/
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import mapWithSeparator from '../mapWithSeparator';
describe('mapWithSeparator', () => {
diff --git a/packages/react-native/Libraries/Utilities/__tests__/stringifySafe-test.js b/packages/react-native/Libraries/Utilities/__tests__/stringifySafe-itest.js
similarity index 97%
rename from packages/react-native/Libraries/Utilities/__tests__/stringifySafe-test.js
rename to packages/react-native/Libraries/Utilities/__tests__/stringifySafe-itest.js
index 9836df4c1678..468fc9001462 100644
--- a/packages/react-native/Libraries/Utilities/__tests__/stringifySafe-test.js
+++ b/packages/react-native/Libraries/Utilities/__tests__/stringifySafe-itest.js
@@ -8,6 +8,7 @@
* @format
*/
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import stringifySafe, {createStringifySafeWithLimits} from '../stringifySafe';
describe('stringifySafe', () => {
@@ -24,7 +25,7 @@ describe('stringifySafe', () => {
});
it('stringifySafe stringifies function values', () => {
- expect(stringifySafe(function () {})).toEqual('function () {}');
+ expect(stringifySafe(function () {})).toEqual('function () { [bytecode] }');
});
it('stringifySafe stringifies non-circular objects', () => {
diff --git a/packages/react-native/Libraries/Utilities/__tests__/useColorScheme-itest.js b/packages/react-native/Libraries/Utilities/__tests__/useColorScheme-itest.js
new file mode 100644
index 000000000000..97259dbf97cd
--- /dev/null
+++ b/packages/react-native/Libraries/Utilities/__tests__/useColorScheme-itest.js
@@ -0,0 +1,60 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @flow strict-local
+ * @format
+ */
+
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
+
+import View from '../../Components/View/View';
+import * as Appearance from '../Appearance';
+import useColorScheme from '../useColorScheme';
+import * as Fantom from '@react-native/fantom';
+import * as React from 'react';
+
+describe('useColorScheme', () => {
+ const originalGetColorScheme = Appearance.getColorScheme;
+
+ afterEach(() => {
+ // $FlowFixMe[cannot-write]
+ Appearance.getColorScheme = originalGetColorScheme;
+ });
+
+ it('returns the color scheme reported by Appearance', () => {
+ const getColorScheme = jest.fn(() => 'dark');
+ // $FlowFixMe[cannot-write]
+ Appearance.getColorScheme = getColorScheme;
+
+ let observed;
+ function TestComponent() {
+ observed = useColorScheme();
+ return ;
+ }
+
+ const root = Fantom.createRoot();
+ Fantom.runTask(() => {
+ root.render();
+ });
+
+ expect(getColorScheme).toHaveBeenCalled();
+ expect(observed).toBe('dark');
+ });
+
+ it('throws when called outside of a component', () => {
+ let error;
+ try {
+ // $FlowFixMe[react-rule-hook]
+ useColorScheme();
+ } catch (e) {
+ error = e;
+ }
+
+ expect(error?.message).toContain(
+ 'Invalid hook call. Hooks can only be called inside of the body of a function component.',
+ );
+ });
+});
diff --git a/packages/react-native/Libraries/Utilities/__tests__/useColorScheme-test.js b/packages/react-native/Libraries/Utilities/__tests__/useColorScheme-test.js
deleted file mode 100644
index 8d7c2ee7b1e9..000000000000
--- a/packages/react-native/Libraries/Utilities/__tests__/useColorScheme-test.js
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
- * @flow strict-local
- * @format
- */
-
-import useColorScheme from '../useColorScheme';
-
-describe('useColorScheme', () => {
- it('should return a mocked light theme by default', () => {
- expect(jest.isMockFunction(useColorScheme)).toBe(true);
- // $FlowFixMe[react-rule-hook]
- expect(useColorScheme()).toBe('light');
- });
-
- it('should have console.error when not using mock', () => {
- const useColorSchemeActual = jest.requireActual<{
- default: typeof useColorScheme,
- }>('../useColorScheme').default;
- const spy = jest.spyOn(console, 'error').mockImplementationOnce(() => {
- // Simulate LogBox console.error() call to throw an error and stop the further execution
- throw new Error('console.error() was called');
- });
-
- expect(() => {
- // $FlowFixMe[react-rule-hook]
- useColorSchemeActual();
- }).toThrow();
-
- expect(spy).toHaveBeenCalledWith(
- expect.stringMatching(
- /Invalid hook call. Hooks can only be called inside of the body of a function component./,
- ),
- );
- });
-});
diff --git a/packages/react-native/Libraries/Utilities/__tests__/useMergeRefs-test.js b/packages/react-native/Libraries/Utilities/__tests__/useMergeRefs-itest.js
similarity index 56%
rename from packages/react-native/Libraries/Utilities/__tests__/useMergeRefs-test.js
rename to packages/react-native/Libraries/Utilities/__tests__/useMergeRefs-itest.js
index e3c31be93a2d..3e730c50e5e7 100644
--- a/packages/react-native/Libraries/Utilities/__tests__/useMergeRefs-test.js
+++ b/packages/react-native/Libraries/Utilities/__tests__/useMergeRefs-itest.js
@@ -8,33 +8,16 @@
* @format
*/
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
+
import type {HostInstance} from '../../../src/private/types/HostInstance';
-import type {ReactTestRenderer} from 'react-test-renderer';
+import ensureInstance from '../../../src/private/__tests__/utilities/ensureInstance';
+import ReactNativeElement from '../../../src/private/webapis/dom/nodes/ReactNativeElement';
import View from '../../Components/View/View';
import useMergeRefs from '../useMergeRefs';
+import * as Fantom from '@react-native/fantom';
import * as React from 'react';
-import {act, create} from 'react-test-renderer';
-
-class Screen {
- #root: ?ReactTestRenderer;
-
- render(children: () => React.MixedElement): void {
- act(() => {
- if (this.#root == null) {
- this.#root = create({children});
- } else {
- this.#root.update({children});
- }
- });
- }
-
- unmount(): void {
- act(() => {
- this.#root?.unmount();
- });
- }
-}
function TestComponent(
props: Readonly<{children: () => React.MixedElement}>,
@@ -43,29 +26,49 @@ function TestComponent(
}
function id(instance: HostInstance | null): string | null {
- // $FlowFixMe[prop-missing] - Intentional.
- return instance?.props?.id ?? null;
+ if (instance == null) {
+ return null;
+ }
+ return ensureInstance(instance, ReactNativeElement).id;
}
test('accepts a ref callback', () => {
- const screen = new Screen();
+ const root = Fantom.createRoot();
const ledger: Array<{[string]: string | null}> = [];
const ref = (current: HostInstance | null) => {
ledger.push({ref: id(current)});
};
- // $FlowFixMe[react-rule-hook]
- screen.render(() => );
+ Fantom.runTask(() => {
+ root.render(
+
+ {() => (
+ // $FlowFixMe[react-rule-hook]
+
+ )}
+ ,
+ );
+ });
expect(ledger).toEqual([{ref: 'foo'}]);
- // $FlowFixMe[react-rule-hook]
- screen.render(() => );
+ Fantom.runTask(() => {
+ root.render(
+
+ {() => (
+ // $FlowFixMe[react-rule-hook]
+
+ )}
+ ,
+ );
+ });
expect(ledger).toEqual([{ref: 'foo'}, {ref: null}, {ref: 'bar'}]);
- screen.unmount();
+ Fantom.runTask(() => {
+ root.render(<>>);
+ });
expect(ledger).toEqual([
{ref: 'foo'},
@@ -76,7 +79,7 @@ test('accepts a ref callback', () => {
});
test('accepts a ref callback that returns a cleanup function', () => {
- const screen = new Screen();
+ const root = Fantom.createRoot();
const ledger: Array<{[string]: string | null}> = [];
// TODO: Remove `| null` after Flow supports ref cleanup functions.
@@ -87,17 +90,35 @@ test('accepts a ref callback that returns a cleanup function', () => {
};
};
- // $FlowFixMe[react-rule-hook]
- screen.render(() => );
+ Fantom.runTask(() => {
+ root.render(
+
+ {() => (
+ // $FlowFixMe[react-rule-hook]
+
+ )}
+ ,
+ );
+ });
expect(ledger).toEqual([{ref: 'foo'}]);
- // $FlowFixMe[react-rule-hook]
- screen.render(() => );
+ Fantom.runTask(() => {
+ root.render(
+
+ {() => (
+ // $FlowFixMe[react-rule-hook]
+
+ )}
+ ,
+ );
+ });
expect(ledger).toEqual([{ref: 'foo'}, {ref: null}, {ref: 'bar'}]);
- screen.unmount();
+ Fantom.runTask(() => {
+ root.render(<>>);
+ });
expect(ledger).toEqual([
{ref: 'foo'},
@@ -108,7 +129,7 @@ test('accepts a ref callback that returns a cleanup function', () => {
});
test('accepts a ref object', () => {
- const screen = new Screen();
+ const root = Fantom.createRoot();
const ledger: Array<{[string]: string | null}> = [];
const ref = {
@@ -118,17 +139,35 @@ test('accepts a ref object', () => {
},
};
- // $FlowFixMe[react-rule-hook]
- screen.render(() => );
+ Fantom.runTask(() => {
+ root.render(
+
+ {() => (
+ // $FlowFixMe[react-rule-hook]
+
+ )}
+ ,
+ );
+ });
expect(ledger).toEqual([{ref: 'foo'}]);
- // $FlowFixMe[react-rule-hook]
- screen.render(() => );
+ Fantom.runTask(() => {
+ root.render(
+
+ {() => (
+ // $FlowFixMe[react-rule-hook]
+
+ )}
+ ,
+ );
+ });
expect(ledger).toEqual([{ref: 'foo'}, {ref: null}, {ref: 'bar'}]);
- screen.unmount();
+ Fantom.runTask(() => {
+ root.render(<>>);
+ });
expect(ledger).toEqual([
{ref: 'foo'},
@@ -139,7 +178,7 @@ test('accepts a ref object', () => {
});
test('invokes refs in order', () => {
- const screen = new Screen();
+ const root = Fantom.createRoot();
const ledger: Array<{[string]: string | null}> = [];
const refA = (current: HostInstance | null) => {
@@ -161,10 +200,16 @@ test('invokes refs in order', () => {
},
};
- screen.render(() => (
- // $FlowFixMe[react-rule-hook]
-
- ));
+ Fantom.runTask(() => {
+ root.render(
+
+ {() => (
+ // $FlowFixMe[react-rule-hook]
+
+ )}
+ ,
+ );
+ });
expect(ledger).toEqual([
{refA: 'foo'},
@@ -173,7 +218,9 @@ test('invokes refs in order', () => {
{refD: 'foo'},
]);
- screen.unmount();
+ Fantom.runTask(() => {
+ root.render(<>>);
+ });
expect(ledger).toEqual([
{refA: 'foo'},
@@ -190,7 +237,7 @@ test('invokes refs in order', () => {
// This is actually undesirable behavior, but it's what we have so let's make
// sure it does not change unexpectedly.
test('invokes all refs if any ref changes', () => {
- const screen = new Screen();
+ const root = Fantom.createRoot();
const ledger: Array<{[string]: string | null}> = [];
const refA = (current: HostInstance | null) => {
@@ -200,19 +247,31 @@ test('invokes all refs if any ref changes', () => {
ledger.push({refB: id(current)});
};
- screen.render(() => (
- // $FlowFixMe[react-rule-hook]
-
- ));
+ Fantom.runTask(() => {
+ root.render(
+
+ {() => (
+ // $FlowFixMe[react-rule-hook]
+
+ )}
+ ,
+ );
+ });
const refAPrime = (current: HostInstance | null) => {
ledger.push({refAPrime: id(current)});
};
- screen.render(() => (
- // $FlowFixMe[react-rule-hook]
-
- ));
+ Fantom.runTask(() => {
+ root.render(
+
+ {() => (
+ // $FlowFixMe[react-rule-hook]
+
+ )}
+ ,
+ );
+ });
expect(ledger).toEqual([
{refA: 'foo'},
@@ -223,7 +282,9 @@ test('invokes all refs if any ref changes', () => {
{refB: 'foo'},
]);
- screen.unmount();
+ Fantom.runTask(() => {
+ root.render(<>>);
+ });
expect(ledger).toEqual([
{refA: 'foo'},
diff --git a/packages/react-native/Libraries/Utilities/__tests__/useRefEffect-itest.js b/packages/react-native/Libraries/Utilities/__tests__/useRefEffect-itest.js
new file mode 100644
index 000000000000..06e85b476f81
--- /dev/null
+++ b/packages/react-native/Libraries/Utilities/__tests__/useRefEffect-itest.js
@@ -0,0 +1,213 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @flow strict-local
+ * @format
+ */
+
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
+
+import type {HostInstance} from '../../../src/private/types/HostInstance';
+
+import ensureInstance from '../../../src/private/__tests__/utilities/ensureInstance';
+import ReactNativeElement from '../../../src/private/webapis/dom/nodes/ReactNativeElement';
+import View from '../../Components/View/View';
+import useRefEffect from '../useRefEffect';
+import * as Fantom from '@react-native/fantom';
+import * as React from 'react';
+
+type RegistryEntry = {kind: 'effect' | 'cleanup', name: string, key: ?string};
+
+/**
+ * TestView provide a component execution environment to test hooks.
+ */
+function TestView({
+ childKey = null,
+ effect,
+}: {
+ childKey: ?string,
+ effect: (?HostInstance) => (() => void) | void,
+}) {
+ const ref = useRefEffect(effect);
+ return ;
+}
+
+function keyOf(instance: ?HostInstance): ?string {
+ if (instance == null) {
+ return null;
+ }
+ return ensureInstance(instance, ReactNativeElement).id;
+}
+
+function effectEntry(name: string, key: ?string): RegistryEntry {
+ return {kind: 'effect', name, key};
+}
+
+function cleanupEntry(name: string, key: ?string): RegistryEntry {
+ return {kind: 'cleanup', name, key};
+}
+
+function mockEffectRegistry(): {
+ mockEffect: string => (?HostInstance) => () => void,
+ mockEffectWithoutCleanup: string => (?HostInstance) => void,
+ registry: Array,
+} {
+ const registry: Array = [];
+ return {
+ mockEffect(name: string): (?HostInstance) => () => void {
+ return instance => {
+ const key = keyOf(instance);
+ registry.push(effectEntry(name, key));
+ return () => {
+ registry.push(cleanupEntry(name, key));
+ };
+ };
+ },
+ mockEffectWithoutCleanup(name: string): (?HostInstance) => void {
+ return instance => {
+ const key = keyOf(instance);
+ registry.push(effectEntry(name, key));
+ };
+ },
+ registry,
+ };
+}
+
+test('calls effect without cleanup', () => {
+ const root = Fantom.createRoot();
+
+ const {mockEffectWithoutCleanup, registry} = mockEffectRegistry();
+ const effectA = mockEffectWithoutCleanup('A');
+
+ Fantom.runTask(() => {
+ root.render();
+ });
+
+ expect(registry).toEqual([effectEntry('A', 'foo')]);
+
+ Fantom.runTask(() => {
+ root.render(<>>);
+ });
+
+ expect(registry).toEqual([effectEntry('A', 'foo')]);
+});
+
+test('calls effect and cleanup', () => {
+ const root = Fantom.createRoot();
+
+ const {mockEffect, registry} = mockEffectRegistry();
+ const effectA = mockEffect('A');
+
+ Fantom.runTask(() => {
+ root.render();
+ });
+
+ expect(registry).toEqual([effectEntry('A', 'foo')]);
+
+ Fantom.runTask(() => {
+ root.render(<>>);
+ });
+
+ expect(registry).toEqual([effectEntry('A', 'foo'), cleanupEntry('A', 'foo')]);
+});
+
+test('cleans up old effect before calling new effect', () => {
+ const root = Fantom.createRoot();
+
+ const {mockEffect, registry} = mockEffectRegistry();
+ const effectA = mockEffect('A');
+ const effectB = mockEffect('B');
+
+ Fantom.runTask(() => {
+ root.render();
+ });
+
+ Fantom.runTask(() => {
+ root.render();
+ });
+
+ expect(registry).toEqual([
+ effectEntry('A', 'foo'),
+ cleanupEntry('A', 'foo'),
+ effectEntry('B', 'foo'),
+ ]);
+
+ Fantom.runTask(() => {
+ root.render(<>>);
+ });
+
+ expect(registry).toEqual([
+ effectEntry('A', 'foo'),
+ cleanupEntry('A', 'foo'),
+ effectEntry('B', 'foo'),
+ cleanupEntry('B', 'foo'),
+ ]);
+});
+
+test('calls cleanup and effect on new instance', () => {
+ const root = Fantom.createRoot();
+
+ const {mockEffect, registry} = mockEffectRegistry();
+ const effectA = mockEffect('A');
+
+ Fantom.runTask(() => {
+ root.render();
+ });
+
+ Fantom.runTask(() => {
+ root.render();
+ });
+
+ expect(registry).toEqual([
+ effectEntry('A', 'foo'),
+ cleanupEntry('A', 'foo'),
+ effectEntry('A', 'bar'),
+ ]);
+
+ Fantom.runTask(() => {
+ root.render(<>>);
+ });
+
+ expect(registry).toEqual([
+ effectEntry('A', 'foo'),
+ cleanupEntry('A', 'foo'),
+ effectEntry('A', 'bar'),
+ cleanupEntry('A', 'bar'),
+ ]);
+});
+
+test('cleans up old effect before calling new effect with new instance', () => {
+ const root = Fantom.createRoot();
+
+ const {mockEffect, registry} = mockEffectRegistry();
+ const effectA = mockEffect('A');
+ const effectB = mockEffect('B');
+
+ Fantom.runTask(() => {
+ root.render();
+ });
+
+ Fantom.runTask(() => {
+ root.render();
+ });
+
+ expect(registry).toEqual([
+ effectEntry('A', 'foo'),
+ cleanupEntry('A', 'foo'),
+ effectEntry('B', 'bar'),
+ ]);
+
+ Fantom.runTask(() => {
+ root.render(<>>);
+ });
+
+ expect(registry).toEqual([
+ effectEntry('A', 'foo'),
+ cleanupEntry('A', 'foo'),
+ effectEntry('B', 'bar'),
+ cleanupEntry('B', 'bar'),
+ ]);
+});
diff --git a/packages/react-native/Libraries/Utilities/__tests__/useRefEffect-test.js b/packages/react-native/Libraries/Utilities/__tests__/useRefEffect-test.js
deleted file mode 100644
index 8dec217c19c2..000000000000
--- a/packages/react-native/Libraries/Utilities/__tests__/useRefEffect-test.js
+++ /dev/null
@@ -1,249 +0,0 @@
-/**
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
- * @flow strict-local
- * @format
- */
-
-import type {HostInstance} from '../../../src/private/types/HostInstance';
-
-import View from '../../Components/View/View';
-import useRefEffect from '../useRefEffect';
-import * as React from 'react';
-import {act, create} from 'react-test-renderer';
-
-/**
- * TestView provide a component execution environment to test hooks.
- */
-function TestView({
- childKey = null,
- effect,
-}: {
- childKey: ?string,
- effect: () => (() => void) | void,
-}) {
- const ref = useRefEffect(effect);
- return ;
-}
-
-/**
- * TestEffect represents an effect invocation.
- */
-class TestEffect {
- name: string;
- key: ?string;
- constructor(name: string, key: ?string) {
- this.name = name;
- this.key = key;
- }
- static called(name: string, key: ?string): $FlowFixMe {
- // $FlowFixMe[prop-missing] - Flow does not support type augmentation.
- return expect.effect(name, key);
- }
-}
-
-/**
- * TestEffectCleanup represents an effect cleanup invocation.
- */
-class TestEffectCleanup {
- name: string;
- key: ?string;
- constructor(name: string, key: ?string) {
- this.name = name;
- this.key = key;
- }
- static called(name: string, key: ?string): $FlowFixMe {
- // $FlowFixMe[prop-missing] - Flow does not support type augmentation.
- return expect.effectCleanup(name, key);
- }
-}
-
-/**
- * extend.effect and expect.extendCleanup make it easier to assert expected
- * values. But use TestEffect.called and TestEffectCleanup.called instead of
- * extend.effect and expect.extendCleanup because of Flow.
- */
-expect.extend({
- effect(received, name, key) {
- const pass =
- received instanceof TestEffect &&
- received.name === name &&
- received.key === key;
- return {pass};
- },
- effectCleanup(received, name, key) {
- const pass =
- received instanceof TestEffectCleanup &&
- received.name === name &&
- received.key === key;
- return {pass};
- },
-});
-
-function mockEffectRegistry(): {
- mockEffect: string => () => () => void,
- mockEffectWithoutCleanup: string => () => void,
- registry: ReadonlyArray,
-} {
- const registry: Array = [];
- return {
- mockEffect(name: string): () => () => void {
- return instance => {
- const key = instance?.props?.testID;
- registry.push(new TestEffect(name, key));
- return () => {
- registry.push(new TestEffectCleanup(name, key));
- };
- };
- },
- mockEffectWithoutCleanup(name: string): () => void {
- return instance => {
- const key = instance?.props?.testID;
- registry.push(new TestEffect(name, key));
- };
- },
- registry,
- };
-}
-
-test('calls effect without cleanup', () => {
- let root;
-
- const {mockEffectWithoutCleanup, registry} = mockEffectRegistry();
- const effectA = mockEffectWithoutCleanup('A');
-
- act(() => {
- root = create();
- });
-
- expect(registry).toEqual([TestEffect.called('A', 'foo')]);
-
- act(() => {
- root.unmount();
- });
-
- expect(registry).toEqual([TestEffect.called('A', 'foo')]);
-});
-
-test('calls effect and cleanup', () => {
- let root;
-
- const {mockEffect, registry} = mockEffectRegistry();
- const effectA = mockEffect('A');
-
- act(() => {
- root = create();
- });
-
- expect(registry).toEqual([TestEffect.called('A', 'foo')]);
-
- act(() => {
- root.unmount();
- });
-
- expect(registry).toEqual([
- TestEffect.called('A', 'foo'),
- TestEffectCleanup.called('A', 'foo'),
- ]);
-});
-
-test('cleans up old effect before calling new effect', () => {
- let root;
-
- const {mockEffect, registry} = mockEffectRegistry();
- const effectA = mockEffect('A');
- const effectB = mockEffect('B');
-
- act(() => {
- root = create();
- });
-
- act(() => {
- root.update();
- });
-
- expect(registry).toEqual([
- TestEffect.called('A', 'foo'),
- TestEffectCleanup.called('A', 'foo'),
- TestEffect.called('B', 'foo'),
- ]);
-
- act(() => {
- root.unmount();
- });
-
- expect(registry).toEqual([
- TestEffect.called('A', 'foo'),
- TestEffectCleanup.called('A', 'foo'),
- TestEffect.called('B', 'foo'),
- TestEffectCleanup.called('B', 'foo'),
- ]);
-});
-
-test('calls cleanup and effect on new instance', () => {
- let root;
-
- const {mockEffect, registry} = mockEffectRegistry();
- const effectA = mockEffect('A');
-
- act(() => {
- root = create();
- });
-
- act(() => {
- root.update();
- });
-
- expect(registry).toEqual([
- TestEffect.called('A', 'foo'),
- TestEffectCleanup.called('A', 'foo'),
- TestEffect.called('A', 'bar'),
- ]);
-
- act(() => {
- root.unmount();
- });
-
- expect(registry).toEqual([
- TestEffect.called('A', 'foo'),
- TestEffectCleanup.called('A', 'foo'),
- TestEffect.called('A', 'bar'),
- TestEffectCleanup.called('A', 'bar'),
- ]);
-});
-
-test('cleans up old effect before calling new effect with new instance', () => {
- let root;
-
- const {mockEffect, registry} = mockEffectRegistry();
- const effectA = mockEffect('A');
- const effectB = mockEffect('B');
-
- act(() => {
- root = create();
- });
-
- act(() => {
- root.update();
- });
-
- expect(registry).toEqual([
- TestEffect.called('A', 'foo'),
- TestEffectCleanup.called('A', 'foo'),
- TestEffect.called('B', 'bar'),
- ]);
-
- act(() => {
- root.unmount();
- });
-
- expect(registry).toEqual([
- TestEffect.called('A', 'foo'),
- TestEffectCleanup.called('A', 'foo'),
- TestEffect.called('B', 'bar'),
- TestEffectCleanup.called('B', 'bar'),
- ]);
-});
diff --git a/packages/react-native/Libraries/Utilities/__tests__/warnOnce-test.js b/packages/react-native/Libraries/Utilities/__tests__/warnOnce-itest.js
similarity index 51%
rename from packages/react-native/Libraries/Utilities/__tests__/warnOnce-test.js
rename to packages/react-native/Libraries/Utilities/__tests__/warnOnce-itest.js
index 766a1715288b..31256284c522 100644
--- a/packages/react-native/Libraries/Utilities/__tests__/warnOnce-test.js
+++ b/packages/react-native/Libraries/Utilities/__tests__/warnOnce-itest.js
@@ -8,17 +8,26 @@
* @format
*/
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import warnOnce from '../warnOnce';
describe('warnOnce', () => {
+ const originalConsoleWarn = console.warn;
+
+ afterEach(() => {
+ // $FlowFixMe[cannot-write]
+ console.warn = originalConsoleWarn;
+ });
+
it('logs warning messages to the console exactly once', () => {
- jest.restoreAllMocks();
- jest.spyOn(console, 'warn').mockReturnValue(undefined);
+ const mockConsoleWarn = jest.fn();
+ // $FlowFixMe[cannot-write]
+ console.warn = mockConsoleWarn;
warnOnce('test-message', 'This is a log message');
warnOnce('test-message', 'This is a second log message');
- expect(console.warn).toHaveBeenCalledWith('This is a log message');
- expect(console.warn).toHaveBeenCalledTimes(1);
+ expect(mockConsoleWarn).toHaveBeenCalledTimes(1);
+ expect(mockConsoleWarn).toHaveBeenCalledWith('This is a log message');
});
});
diff --git a/packages/react-native/Libraries/Utilities/differ/__tests__/deepDiffer-test.js b/packages/react-native/Libraries/Utilities/differ/__tests__/deepDiffer-itest.js
similarity index 89%
rename from packages/react-native/Libraries/Utilities/differ/__tests__/deepDiffer-test.js
rename to packages/react-native/Libraries/Utilities/differ/__tests__/deepDiffer-itest.js
index 5a4967d99f7e..2625e2504848 100644
--- a/packages/react-native/Libraries/Utilities/differ/__tests__/deepDiffer-test.js
+++ b/packages/react-native/Libraries/Utilities/differ/__tests__/deepDiffer-itest.js
@@ -8,11 +8,15 @@
* @format
*/
-'use strict';
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
const deepDiffer = require('../deepDiffer').default;
describe('deepDiffer', function () {
+ afterEach(() => {
+ deepDiffer.unstable_setLogListeners(null);
+ });
+
it('should diff primitives of the same type', () => {
expect(deepDiffer(1, 2)).toBe(true);
expect(deepDiffer(42, 42)).toBe(false);
@@ -167,31 +171,25 @@ describe('deepDiffer', function () {
function b() {}
const listeners = {onDifferentFunctionsIgnored: jest.fn()};
deepDiffer.unstable_setLogListeners(listeners);
- try {
- deepDiffer(a, a);
- expect(listeners.onDifferentFunctionsIgnored).not.toHaveBeenCalled();
- deepDiffer(a, b);
- expect(listeners.onDifferentFunctionsIgnored.mock.calls).toEqual([
- ['a', 'b'],
- ]);
- } finally {
- deepDiffer.unstable_setLogListeners(null);
- }
+ deepDiffer(a, a);
+ expect(listeners.onDifferentFunctionsIgnored).not.toHaveBeenCalled();
+
+ deepDiffer(a, b);
+ expect(listeners.onDifferentFunctionsIgnored.mock.calls).toEqual([
+ ['a', 'b'],
+ ]);
});
it('should not log when explicitly considering two different functions equal', () => {
function a() {}
function b() {}
const listeners = {onDifferentFunctionsIgnored: jest.fn()};
deepDiffer.unstable_setLogListeners(listeners);
- try {
- deepDiffer(a, a, {unsafelyIgnoreFunctions: true});
- expect(listeners.onDifferentFunctionsIgnored).not.toHaveBeenCalled();
- deepDiffer(a, b, {unsafelyIgnoreFunctions: true});
- expect(listeners.onDifferentFunctionsIgnored).not.toHaveBeenCalled();
- } finally {
- deepDiffer.unstable_setLogListeners(null);
- }
+ deepDiffer(a, a, {unsafelyIgnoreFunctions: true});
+ expect(listeners.onDifferentFunctionsIgnored).not.toHaveBeenCalled();
+
+ deepDiffer(a, b, {unsafelyIgnoreFunctions: true});
+ expect(listeners.onDifferentFunctionsIgnored).not.toHaveBeenCalled();
});
});
diff --git a/packages/react-native/Libraries/Utilities/differ/__tests__/matricesDiffer-test.js b/packages/react-native/Libraries/Utilities/differ/__tests__/matricesDiffer-itest.js
similarity index 94%
rename from packages/react-native/Libraries/Utilities/differ/__tests__/matricesDiffer-test.js
rename to packages/react-native/Libraries/Utilities/differ/__tests__/matricesDiffer-itest.js
index ae4ae736a757..e1100fb7f630 100644
--- a/packages/react-native/Libraries/Utilities/differ/__tests__/matricesDiffer-test.js
+++ b/packages/react-native/Libraries/Utilities/differ/__tests__/matricesDiffer-itest.js
@@ -8,7 +8,7 @@
* @format
*/
-'use strict';
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
const matricesDiffer = require('../matricesDiffer').default;
diff --git a/packages/react-native/Libraries/vendor/emitter/__tests__/EventEmitter-test.js b/packages/react-native/Libraries/vendor/emitter/__tests__/EventEmitter-itest.js
similarity index 99%
rename from packages/react-native/Libraries/vendor/emitter/__tests__/EventEmitter-test.js
rename to packages/react-native/Libraries/vendor/emitter/__tests__/EventEmitter-itest.js
index c65c5b74ecd7..7a746f0b47a5 100644
--- a/packages/react-native/Libraries/vendor/emitter/__tests__/EventEmitter-test.js
+++ b/packages/react-native/Libraries/vendor/emitter/__tests__/EventEmitter-itest.js
@@ -8,6 +8,8 @@
* @format
*/
+import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
+
import type {EventSubscription} from '../EventEmitter';
import EventEmitter from '../EventEmitter';