Skip to content

Commit 5198778

Browse files
rubennortemeta-codesync[bot]
authored andcommitted
Migrate Image, Text, and NativeComponent Jest tests to Fantom (#57262)
Summary: Pull Request resolved: #57262 Migrates `Image`, `Text`, and `NativeComponent` unit tests from regular Jest (`-test.js`) to Fantom (`-itest.js`). Folded missing cases into the existing `Image`, `ImageBackground`, and `Text` Fantom tests (asserting real Fabric output such as `rn-image`/`rn-paragraph` instead of the previously mocked `RCTImageView`/`RCTText`), and migrated the pure-logic helpers `AssetUtils`, `ImageSourceUtils`, `assetRelativePathInSnapshot`, and `StaticViewConfigValidator`. Obsolete mocked-output snapshots were removed. `resolveAssetSource` remains on Jest because it relies on `jest.resetModules` to reset module-level state between cases, which Fantom does not support. Changelog: [Internal] Reviewed By: sammy-SC Differential Revision: D108759081 fbshipit-source-id: 5863056c3f7a754f37e3ebe6d6f646a0f7a4da5e
1 parent f5c7510 commit 5198778

14 files changed

Lines changed: 644 additions & 1146 deletions

packages/react-native/Libraries/Image/__tests__/AssetUtils-test.js renamed to packages/react-native/Libraries/Image/__tests__/AssetUtils-itest.js

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,24 @@
88
* @format
99
*/
1010

11+
import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
12+
1113
import {getUrlCacheBreaker, setUrlCacheBreaker} from '../AssetUtils';
1214

15+
const originalConsoleWarn = console.warn;
16+
1317
describe('AssetUtils', () => {
1418
afterEach(() => {
19+
// $FlowFixMe[cannot-write]
20+
console.warn = originalConsoleWarn;
1521
// $FlowFixMe[cannot-write]
1622
global.__DEV__ = true;
17-
jest.clearAllMocks();
1823
});
1924

2025
it('should return empty string and warn once if no cacheBreaker set (DEV)', () => {
21-
const mockWarn = jest.spyOn(console, 'warn').mockReturnValue(undefined);
26+
const mockWarn = jest.fn();
27+
// $FlowFixMe[cannot-write]
28+
console.warn = mockWarn;
2229
// $FlowFixMe[cannot-write]
2330
global.__DEV__ = true;
2431
expect(getUrlCacheBreaker()).toEqual('');
@@ -27,7 +34,9 @@ describe('AssetUtils', () => {
2734
});
2835

2936
it('should return empty string if no cacheBreaker set in prod', () => {
30-
const mockWarn = jest.spyOn(console, 'warn');
37+
const mockWarn = jest.fn();
38+
// $FlowFixMe[cannot-write]
39+
console.warn = mockWarn;
3140
// $FlowFixMe[cannot-write]
3241
global.__DEV__ = false;
3342
expect(getUrlCacheBreaker()).toEqual('');

packages/react-native/Libraries/Image/__tests__/Image-itest.js

Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import * as Fantom from '@react-native/fantom';
1616
import * as React from 'react';
1717
import {createRef} from 'react';
1818
import {Image} from 'react-native';
19+
import * as ImageInjection from 'react-native/Libraries/Image/ImageInjection';
1920
import accessibilityPropsSuite from 'react-native/src/private/__tests__/utilities/accessibilityPropsSuite';
2021
import {testIDPropSuite} from 'react-native/src/private/__tests__/utilities/commonPropsSuite';
2122
import ensureInstance from 'react-native/src/private/__tests__/utilities/ensureInstance';
@@ -657,6 +658,275 @@ describe('<Image>', () => {
657658
});
658659
});
659660

661+
describe('resolveAssetSource', () => {
662+
it('resolves a plain source object to itself', () => {
663+
expect(Image.resolveAssetSource({uri: 'foo-bar.jpg'})).toEqual({
664+
uri: 'foo-bar.jpg',
665+
});
666+
});
667+
});
668+
669+
describe('image attached callbacks', () => {
670+
it('invokes original ref callbacks correctly when using image attached callbacks', () => {
671+
let imageInstanceFromCallback = null;
672+
let imageInstanceFromRef1 = null;
673+
let imageInstanceFromRef2 = null;
674+
675+
const callback = jest.fn((instance: HostInstance) => {
676+
imageInstanceFromCallback = instance;
677+
678+
return () => {
679+
imageInstanceFromCallback = null;
680+
};
681+
});
682+
683+
ImageInjection.unstable_registerImageAttachedCallback(callback);
684+
685+
expect(imageInstanceFromCallback).toBe(null);
686+
687+
const root = Fantom.createRoot();
688+
689+
const ref1 = jest.fn();
690+
const ref1Setter = (instance: HostInstance | null): void => {
691+
imageInstanceFromRef1 = instance;
692+
ref1(instance);
693+
};
694+
695+
Fantom.runTask(() => {
696+
root.render(<Image source={LOGO_SOURCE} ref={ref1Setter} />);
697+
});
698+
699+
expect(imageInstanceFromCallback).not.toBe(null);
700+
expect(imageInstanceFromRef1).not.toBe(null);
701+
expect(imageInstanceFromCallback).toBe(imageInstanceFromRef1);
702+
expect(callback).toHaveBeenCalledTimes(1);
703+
expect(ref1).toHaveBeenCalledTimes(1);
704+
705+
const ref2 = jest.fn();
706+
const ref2Setter = (instance: HostInstance | null): void => {
707+
imageInstanceFromRef2 = instance;
708+
ref2(instance);
709+
};
710+
711+
Fantom.runTask(() => {
712+
root.render(<Image source={LOGO_SOURCE} ref={ref2Setter} />);
713+
});
714+
715+
expect(imageInstanceFromCallback).not.toBe(null);
716+
expect(imageInstanceFromRef1).toBe(null);
717+
expect(imageInstanceFromRef2).not.toBe(null);
718+
expect(imageInstanceFromCallback).toBe(imageInstanceFromRef2);
719+
expect(callback).toHaveBeenCalledTimes(2);
720+
expect(ref1).toHaveBeenCalledTimes(2);
721+
expect(ref2).toHaveBeenCalledTimes(1);
722+
723+
Fantom.runTask(() => {
724+
root.render(<Image source={LOGO_SOURCE} ref={ref2Setter} />);
725+
});
726+
727+
expect(callback).toHaveBeenCalledTimes(2);
728+
expect(ref2).toHaveBeenCalledTimes(1);
729+
730+
ImageInjection.unstable_unregisterImageAttachedCallback(callback);
731+
Fantom.runTask(() => {
732+
root.render(<></>);
733+
});
734+
});
735+
736+
it('calls image attached callbacks (basic)', () => {
737+
let imageInstanceFromCallback = null;
738+
let imageInstanceFromRef = null;
739+
740+
const callback = (instance: HostInstance) => {
741+
imageInstanceFromCallback = instance;
742+
743+
return () => {
744+
imageInstanceFromCallback = null;
745+
};
746+
};
747+
748+
ImageInjection.unstable_registerImageAttachedCallback(callback);
749+
750+
expect(imageInstanceFromCallback).toBe(null);
751+
752+
const root = Fantom.createRoot();
753+
754+
Fantom.runTask(() => {
755+
root.render(
756+
<Image
757+
source={LOGO_SOURCE}
758+
ref={instance => {
759+
imageInstanceFromRef = instance;
760+
}}
761+
/>,
762+
);
763+
});
764+
765+
expect(imageInstanceFromCallback).not.toBe(null);
766+
expect(imageInstanceFromRef).not.toBe(null);
767+
expect(imageInstanceFromCallback).toBe(imageInstanceFromRef);
768+
769+
Fantom.runTask(() => {
770+
root.render(<></>);
771+
});
772+
773+
expect(imageInstanceFromCallback).toBe(null);
774+
expect(imageInstanceFromRef).toBe(null);
775+
776+
ImageInjection.unstable_unregisterImageAttachedCallback(callback);
777+
778+
Fantom.runTask(() => {
779+
root.render(
780+
<Image
781+
source={LOGO_SOURCE}
782+
ref={instance => {
783+
imageInstanceFromRef = instance;
784+
}}
785+
/>,
786+
);
787+
});
788+
789+
expect(imageInstanceFromRef).not.toBe(null);
790+
expect(imageInstanceFromCallback).toBe(null);
791+
792+
Fantom.runTask(() => {
793+
root.render(<></>);
794+
});
795+
});
796+
797+
it('calls image attached callbacks (multiple callbacks)', () => {
798+
let imageInstanceFromCallback1 = null;
799+
let imageInstanceFromCallback2 = null;
800+
let imageInstanceFromRef = null;
801+
802+
const callback1 = (instance: HostInstance) => {
803+
imageInstanceFromCallback1 = instance;
804+
805+
return () => {
806+
imageInstanceFromCallback1 = null;
807+
};
808+
};
809+
const callback2 = (instance: HostInstance) => {
810+
imageInstanceFromCallback2 = instance;
811+
812+
return () => {
813+
imageInstanceFromCallback2 = null;
814+
};
815+
};
816+
817+
ImageInjection.unstable_registerImageAttachedCallback(callback1);
818+
ImageInjection.unstable_registerImageAttachedCallback(callback2);
819+
820+
expect(imageInstanceFromCallback1).toBe(null);
821+
expect(imageInstanceFromCallback2).toBe(null);
822+
823+
const root = Fantom.createRoot();
824+
825+
Fantom.runTask(() => {
826+
root.render(
827+
<Image
828+
source={LOGO_SOURCE}
829+
ref={instance => {
830+
imageInstanceFromRef = instance;
831+
}}
832+
/>,
833+
);
834+
});
835+
836+
expect(imageInstanceFromRef).not.toBe(null);
837+
expect(imageInstanceFromCallback1).not.toBe(null);
838+
expect(imageInstanceFromCallback2).not.toBe(null);
839+
expect(imageInstanceFromCallback1).toBe(imageInstanceFromRef);
840+
expect(imageInstanceFromCallback2).toBe(imageInstanceFromRef);
841+
842+
Fantom.runTask(() => {
843+
root.render(<></>);
844+
});
845+
846+
expect(imageInstanceFromRef).toBe(null);
847+
expect(imageInstanceFromCallback1).toBe(null);
848+
expect(imageInstanceFromCallback2).toBe(null);
849+
850+
ImageInjection.unstable_unregisterImageAttachedCallback(callback1);
851+
ImageInjection.unstable_unregisterImageAttachedCallback(callback2);
852+
});
853+
854+
it('calls image attached callbacks (multiple images)', () => {
855+
let imageInstancesFromCallback = new Set<HostInstance>();
856+
857+
const callback = (instance: HostInstance) => {
858+
imageInstancesFromCallback.add(instance);
859+
860+
return () => {
861+
imageInstancesFromCallback.delete(instance);
862+
};
863+
};
864+
865+
ImageInjection.unstable_registerImageAttachedCallback(callback);
866+
867+
expect(imageInstancesFromCallback.size).toBe(0);
868+
869+
const root = Fantom.createRoot();
870+
871+
let firstInstance;
872+
let secondInstance;
873+
874+
const firstImageElement = (
875+
<Image
876+
key="first-image"
877+
source={LOGO_SOURCE}
878+
ref={instance => {
879+
firstInstance = instance;
880+
}}
881+
/>
882+
);
883+
884+
const secondImageElement = (
885+
<Image
886+
key="second-image"
887+
source={LOGO_SOURCE}
888+
ref={instance => {
889+
secondInstance = instance;
890+
}}
891+
/>
892+
);
893+
894+
Fantom.runTask(() => {
895+
root.render(
896+
<>
897+
{firstImageElement}
898+
{secondImageElement}
899+
</>,
900+
);
901+
});
902+
903+
expect(firstInstance).not.toBe(null);
904+
expect(secondInstance).not.toBe(null);
905+
expect(imageInstancesFromCallback.size).toBe(2);
906+
expect([...imageInstancesFromCallback][0]).toBe(firstInstance);
907+
expect([...imageInstancesFromCallback][1]).toBe(secondInstance);
908+
909+
Fantom.runTask(() => {
910+
root.render(<>{secondImageElement}</>);
911+
});
912+
913+
expect(firstInstance).toBe(null);
914+
expect(secondInstance).not.toBe(null);
915+
expect(imageInstancesFromCallback.size).toBe(1);
916+
expect([...imageInstancesFromCallback][0]).toBe(secondInstance);
917+
918+
Fantom.runTask(() => {
919+
root.render(<></>);
920+
});
921+
922+
expect(firstInstance).toBe(null);
923+
expect(secondInstance).toBe(null);
924+
expect(imageInstancesFromCallback.size).toBe(0);
925+
926+
ImageInjection.unstable_unregisterImageAttachedCallback(callback);
927+
});
928+
});
929+
660930
describe('static methods', () => {
661931
afterEach(() => {
662932
NativeFantom.clearAllImages();

0 commit comments

Comments
 (0)