1212
1313const {
1414 configureAppForSwift,
15+ createHardlinks,
1516 findXcodeProjectDirectory,
1617 runIosPrebuild,
1718 runPodDeintegrate,
@@ -24,6 +25,12 @@ jest.mock('child_process');
2425// Mock fs module
2526jest . mock ( 'fs' ) ;
2627
28+ // Mock headers-utils module
29+ jest . mock ( '../headers-utils' ) ;
30+
31+ // Mock prepare-app-dependencies-headers module
32+ jest . mock ( '../prepare-app-dependencies-headers' ) ;
33+
2734// Mock path module for absolute paths
2835jest . mock ( 'path' , ( ) => {
2936 const actualPath = jest . requireActual ( 'path' ) ;
@@ -34,6 +41,204 @@ jest.mock('path', () => {
3441 } ;
3542} ) ;
3643
44+ describe ( 'createHardlinks' , ( ) => {
45+ let mockSymlinkReactNativeHeaders ;
46+ let mockSymlinkThirdPartyDependenciesHeaders ;
47+ let mockPath ;
48+ let mockConsoleLog ;
49+
50+ beforeEach ( ( ) => {
51+ // Setup mocks
52+ const headersUtils = require ( '../headers-utils' ) ;
53+ const prepareAppDependenciesHeaders = require ( '../prepare-app-dependencies-headers' ) ;
54+
55+ mockSymlinkReactNativeHeaders =
56+ prepareAppDependenciesHeaders . symlinkReactNativeHeaders ;
57+ mockSymlinkThirdPartyDependenciesHeaders =
58+ headersUtils . symlinkThirdPartyDependenciesHeaders ;
59+
60+ mockPath = require ( 'path' ) ;
61+ mockConsoleLog = console . log ;
62+
63+ // Clear and reset all mocks completely
64+ jest . clearAllMocks ( ) ;
65+ jest . resetAllMocks ( ) ;
66+
67+ // Set up fresh mock implementations
68+ mockSymlinkReactNativeHeaders . mockImplementation ( ( ) => { } ) ;
69+ mockSymlinkThirdPartyDependenciesHeaders . mockImplementation ( ( ) => { } ) ;
70+
71+ // Mock path.join to return realistic paths
72+ mockPath . join . mockImplementation ( ( ...args ) => args . join ( '/' ) ) ;
73+ } ) ;
74+
75+ it ( 'should create hard links successfully' , async ( ) => {
76+ // Setup
77+ const reactNativePath = '/path/to/react-native' ;
78+
79+ mockSymlinkReactNativeHeaders . mockImplementation ( ( ) => { } ) ;
80+ mockSymlinkThirdPartyDependenciesHeaders . mockImplementation ( ( ) => { } ) ;
81+
82+ // Execute
83+ await createHardlinks ( reactNativePath ) ;
84+
85+ // Assert
86+ const expectedReactIncludesPath = '/path/to/react-native/React' ;
87+
88+ expect ( mockSymlinkReactNativeHeaders ) . toHaveBeenCalledWith (
89+ reactNativePath ,
90+ expectedReactIncludesPath ,
91+ 'includes' ,
92+ ) ;
93+ expect ( mockSymlinkThirdPartyDependenciesHeaders ) . toHaveBeenCalledWith (
94+ reactNativePath ,
95+ expectedReactIncludesPath ,
96+ 'includes' ,
97+ ) ;
98+
99+ expect ( mockSymlinkReactNativeHeaders ) . toHaveBeenCalledTimes ( 1 ) ;
100+ expect ( mockSymlinkThirdPartyDependenciesHeaders ) . toHaveBeenCalledTimes ( 1 ) ;
101+
102+ // Verify console output
103+ expect ( mockConsoleLog ) . toHaveBeenCalledWith (
104+ 'Creating hard links for React Native headers...' ,
105+ ) ;
106+ expect ( mockConsoleLog ) . toHaveBeenCalledWith (
107+ '✓ React Native hard links created in React/includes' ,
108+ ) ;
109+ expect ( mockConsoleLog ) . toHaveBeenCalledWith (
110+ 'Creating hard links for third-party dependencies...' ,
111+ ) ;
112+ expect ( mockConsoleLog ) . toHaveBeenCalledWith (
113+ '✓ Third-party dependencies hard links created in React/includes' ,
114+ ) ;
115+ } ) ;
116+
117+ it ( 'should throw error when symlinkReactNativeHeaders fails' , async ( ) => {
118+ // Setup
119+ const reactNativePath = '/path/to/react-native' ;
120+ const originalError = new Error ( 'React Native headers linking failed' ) ;
121+
122+ mockSymlinkReactNativeHeaders . mockImplementation ( ( ) => {
123+ throw originalError ;
124+ } ) ;
125+
126+ // Execute & Assert
127+ await expect ( createHardlinks ( reactNativePath ) ) . rejects . toThrow (
128+ 'Hard link creation failed: React Native headers linking failed' ,
129+ ) ;
130+
131+ const expectedReactIncludesPath = '/path/to/react-native/React' ;
132+
133+ expect ( mockSymlinkReactNativeHeaders ) . toHaveBeenCalledWith (
134+ reactNativePath ,
135+ expectedReactIncludesPath ,
136+ 'includes' ,
137+ ) ;
138+ expect ( mockSymlinkThirdPartyDependenciesHeaders ) . not . toHaveBeenCalled ( ) ;
139+
140+ expect ( mockConsoleLog ) . toHaveBeenCalledWith (
141+ 'Creating hard links for React Native headers...' ,
142+ ) ;
143+ expect ( mockConsoleLog ) . not . toHaveBeenCalledWith (
144+ '✓ React Native hard links created in React/includes' ,
145+ ) ;
146+ } ) ;
147+
148+ it ( 'should throw error when symlinkThirdPartyDependenciesHeaders fails' , async ( ) => {
149+ // Setup
150+ const reactNativePath = '/path/to/react-native' ;
151+ const originalError = new Error ( 'Third-party dependencies linking failed' ) ;
152+
153+ mockSymlinkReactNativeHeaders . mockImplementation ( ( ) => { } ) ;
154+ mockSymlinkThirdPartyDependenciesHeaders . mockImplementation ( ( ) => {
155+ throw originalError ;
156+ } ) ;
157+
158+ // Execute & Assert
159+ await expect ( createHardlinks ( reactNativePath ) ) . rejects . toThrow (
160+ 'Hard link creation failed: Third-party dependencies linking failed' ,
161+ ) ;
162+
163+ const expectedReactIncludesPath = '/path/to/react-native/React' ;
164+
165+ expect ( mockSymlinkReactNativeHeaders ) . toHaveBeenCalledWith (
166+ reactNativePath ,
167+ expectedReactIncludesPath ,
168+ 'includes' ,
169+ ) ;
170+ expect ( mockSymlinkThirdPartyDependenciesHeaders ) . toHaveBeenCalledWith (
171+ reactNativePath ,
172+ expectedReactIncludesPath ,
173+ 'includes' ,
174+ ) ;
175+
176+ expect ( mockConsoleLog ) . toHaveBeenCalledWith (
177+ 'Creating hard links for React Native headers...' ,
178+ ) ;
179+ expect ( mockConsoleLog ) . toHaveBeenCalledWith (
180+ '✓ React Native hard links created in React/includes' ,
181+ ) ;
182+ expect ( mockConsoleLog ) . toHaveBeenCalledWith (
183+ 'Creating hard links for third-party dependencies...' ,
184+ ) ;
185+ expect ( mockConsoleLog ) . not . toHaveBeenCalledWith (
186+ '✓ Third-party dependencies hard links created in React/includes' ,
187+ ) ;
188+ } ) ;
189+
190+ it ( 'should handle different React Native paths correctly' , async ( ) => {
191+ // Setup
192+ const reactNativePath = '/Users/developer/custom-react-native-path' ;
193+
194+ mockSymlinkReactNativeHeaders . mockImplementation ( ( ) => { } ) ;
195+ mockSymlinkThirdPartyDependenciesHeaders . mockImplementation ( ( ) => { } ) ;
196+
197+ // Execute
198+ await createHardlinks ( reactNativePath ) ;
199+
200+ // Assert
201+ const expectedReactIncludesPath =
202+ '/Users/developer/custom-react-native-path/React' ;
203+
204+ expect ( mockSymlinkReactNativeHeaders ) . toHaveBeenCalledWith (
205+ reactNativePath ,
206+ expectedReactIncludesPath ,
207+ 'includes' ,
208+ ) ;
209+ expect ( mockSymlinkThirdPartyDependenciesHeaders ) . toHaveBeenCalledWith (
210+ reactNativePath ,
211+ expectedReactIncludesPath ,
212+ 'includes' ,
213+ ) ;
214+ } ) ;
215+
216+ it ( 'should handle paths with spaces correctly' , async ( ) => {
217+ // Setup
218+ const reactNativePath = '/path/to/react native project' ;
219+
220+ mockSymlinkReactNativeHeaders . mockImplementation ( ( ) => { } ) ;
221+ mockSymlinkThirdPartyDependenciesHeaders . mockImplementation ( ( ) => { } ) ;
222+
223+ // Execute
224+ await createHardlinks ( reactNativePath ) ;
225+
226+ // Assert
227+ const expectedReactIncludesPath = '/path/to/react native project/React' ;
228+
229+ expect ( mockSymlinkReactNativeHeaders ) . toHaveBeenCalledWith (
230+ reactNativePath ,
231+ expectedReactIncludesPath ,
232+ 'includes' ,
233+ ) ;
234+ expect ( mockSymlinkThirdPartyDependenciesHeaders ) . toHaveBeenCalledWith (
235+ reactNativePath ,
236+ expectedReactIncludesPath ,
237+ 'includes' ,
238+ ) ;
239+ } ) ;
240+ } ) ;
241+
37242// Mock console methods - disable React Native's strict console checking
38243const originalConsole = global . console ;
39244
0 commit comments