@@ -15,6 +15,7 @@ const {
1515 createHardlinks,
1616 findXcodeProjectDirectory,
1717 generateCodegenArtifacts,
18+ prepareHeaders,
1819 runIosPrebuild,
1920 runPodDeintegrate,
2021 setBuildFromSource,
@@ -364,6 +365,323 @@ describe('generateCodegenArtifacts', () => {
364365 } ) ;
365366} ) ;
366367
368+ describe ( 'prepareHeaders' , ( ) => {
369+ let mockPrepareAppDependenciesHeaders ;
370+ let mockPath ;
371+ let mockConsoleLog ;
372+
373+ beforeEach ( ( ) => {
374+ // Setup mocks
375+ const prepareAppDependenciesHeadersModule = require ( '../prepare-app-dependencies-headers' ) ;
376+ mockPrepareAppDependenciesHeaders =
377+ prepareAppDependenciesHeadersModule . prepareAppDependenciesHeaders ;
378+
379+ mockPath = require ( 'path' ) ;
380+ mockConsoleLog = console . log ;
381+
382+ // Clear and reset all mocks completely
383+ jest . clearAllMocks ( ) ;
384+ jest . resetAllMocks ( ) ;
385+
386+ // Set up fresh mock implementations
387+ mockPrepareAppDependenciesHeaders . mockImplementation ( ( ) => { } ) ;
388+
389+ // Mock path.join to return realistic paths
390+ mockPath . join . mockImplementation ( ( ...args ) => args . join ( '/' ) ) ;
391+ } ) ;
392+
393+ it ( 'should prepare all three types of headers successfully' , async ( ) => {
394+ // Setup
395+ const reactNativePath = '/path/to/react-native' ;
396+ const appIosPath = '/path/to/app/ios' ;
397+
398+ mockPrepareAppDependenciesHeaders . mockImplementation ( ( ) => { } ) ;
399+
400+ // Execute
401+ await prepareHeaders ( reactNativePath , appIosPath ) ;
402+
403+ // Assert
404+ const expectedOutputFolder =
405+ '/path/to/app/ios/build/generated/ios/ReactAppDependencyProvider' ;
406+ const expectedCodegenOutputFolder =
407+ '/path/to/app/ios/build/generated/ios/ReactCodegen' ;
408+
409+ // Verify all three calls with correct parameters
410+ expect ( mockPrepareAppDependenciesHeaders ) . toHaveBeenCalledTimes ( 3 ) ;
411+
412+ // 1. Codegen headers
413+ expect ( mockPrepareAppDependenciesHeaders ) . toHaveBeenNthCalledWith (
414+ 1 ,
415+ reactNativePath ,
416+ appIosPath ,
417+ expectedOutputFolder ,
418+ 'codegen' ,
419+ ) ;
420+
421+ // 2. React Native headers
422+ expect ( mockPrepareAppDependenciesHeaders ) . toHaveBeenNthCalledWith (
423+ 2 ,
424+ reactNativePath ,
425+ appIosPath ,
426+ expectedCodegenOutputFolder ,
427+ 'react-native' ,
428+ ) ;
429+
430+ // 3. Third-party dependencies headers
431+ expect ( mockPrepareAppDependenciesHeaders ) . toHaveBeenNthCalledWith (
432+ 3 ,
433+ reactNativePath ,
434+ appIosPath ,
435+ expectedCodegenOutputFolder ,
436+ 'third-party-dependencies' ,
437+ ) ;
438+
439+ // Verify console output
440+ expect ( mockConsoleLog ) . toHaveBeenCalledWith ( 'Preparing codegen headers...' ) ;
441+ expect ( mockConsoleLog ) . toHaveBeenCalledWith ( '✓ Codegen headers prepared' ) ;
442+ expect ( mockConsoleLog ) . toHaveBeenCalledWith (
443+ 'Preparing react-native headers...' ,
444+ ) ;
445+ expect ( mockConsoleLog ) . toHaveBeenCalledWith (
446+ '✓ React Native headers prepared' ,
447+ ) ;
448+ expect ( mockConsoleLog ) . toHaveBeenCalledWith (
449+ 'Preparing third-party dependencies headers...' ,
450+ ) ;
451+ expect ( mockConsoleLog ) . toHaveBeenCalledWith (
452+ '✓ Third-party dependencies headers prepared' ,
453+ ) ;
454+ } ) ;
455+
456+ it ( 'should throw error when codegen header preparation fails' , async ( ) => {
457+ // Setup
458+ const reactNativePath = '/path/to/react-native' ;
459+ const appIosPath = '/path/to/app/ios' ;
460+ const originalError = new Error ( 'Codegen header preparation failed' ) ;
461+
462+ mockPrepareAppDependenciesHeaders . mockImplementationOnce ( ( ) => {
463+ throw originalError ;
464+ } ) ;
465+
466+ // Execute & Assert
467+ await expect ( prepareHeaders ( reactNativePath , appIosPath ) ) . rejects . toThrow (
468+ 'Header preparation failed: Codegen header preparation failed' ,
469+ ) ;
470+
471+ const expectedOutputFolder =
472+ '/path/to/app/ios/build/generated/ios/ReactAppDependencyProvider' ;
473+
474+ expect ( mockPrepareAppDependenciesHeaders ) . toHaveBeenCalledTimes ( 1 ) ;
475+ expect ( mockPrepareAppDependenciesHeaders ) . toHaveBeenCalledWith (
476+ reactNativePath ,
477+ appIosPath ,
478+ expectedOutputFolder ,
479+ 'codegen' ,
480+ ) ;
481+
482+ expect ( mockConsoleLog ) . toHaveBeenCalledWith ( 'Preparing codegen headers...' ) ;
483+ expect ( mockConsoleLog ) . not . toHaveBeenCalledWith (
484+ '✓ Codegen headers prepared' ,
485+ ) ;
486+ } ) ;
487+
488+ it ( 'should throw error when react-native header preparation fails' , async ( ) => {
489+ // Setup
490+ const reactNativePath = '/path/to/react-native' ;
491+ const appIosPath = '/path/to/app/ios' ;
492+ const originalError = new Error ( 'React Native header preparation failed' ) ;
493+
494+ mockPrepareAppDependenciesHeaders
495+ . mockImplementationOnce ( ( ) => { } ) // First call succeeds
496+ . mockImplementationOnce ( ( ) => {
497+ // Second call fails
498+ throw originalError ;
499+ } ) ;
500+
501+ // Execute & Assert
502+ await expect ( prepareHeaders ( reactNativePath , appIosPath ) ) . rejects . toThrow (
503+ 'Header preparation failed: React Native header preparation failed' ,
504+ ) ;
505+
506+ const expectedOutputFolder =
507+ '/path/to/app/ios/build/generated/ios/ReactAppDependencyProvider' ;
508+ const expectedCodegenOutputFolder =
509+ '/path/to/app/ios/build/generated/ios/ReactCodegen' ;
510+
511+ expect ( mockPrepareAppDependenciesHeaders ) . toHaveBeenCalledTimes ( 2 ) ;
512+ expect ( mockPrepareAppDependenciesHeaders ) . toHaveBeenNthCalledWith (
513+ 1 ,
514+ reactNativePath ,
515+ appIosPath ,
516+ expectedOutputFolder ,
517+ 'codegen' ,
518+ ) ;
519+ expect ( mockPrepareAppDependenciesHeaders ) . toHaveBeenNthCalledWith (
520+ 2 ,
521+ reactNativePath ,
522+ appIosPath ,
523+ expectedCodegenOutputFolder ,
524+ 'react-native' ,
525+ ) ;
526+
527+ expect ( mockConsoleLog ) . toHaveBeenCalledWith ( 'Preparing codegen headers...' ) ;
528+ expect ( mockConsoleLog ) . toHaveBeenCalledWith ( '✓ Codegen headers prepared' ) ;
529+ expect ( mockConsoleLog ) . toHaveBeenCalledWith (
530+ 'Preparing react-native headers...' ,
531+ ) ;
532+ expect ( mockConsoleLog ) . not . toHaveBeenCalledWith (
533+ '✓ React Native headers prepared' ,
534+ ) ;
535+ } ) ;
536+
537+ it ( 'should throw error when third-party dependencies header preparation fails' , async ( ) => {
538+ // Setup
539+ const reactNativePath = '/path/to/react-native' ;
540+ const appIosPath = '/path/to/app/ios' ;
541+ const originalError = new Error (
542+ 'Third-party dependencies header preparation failed' ,
543+ ) ;
544+
545+ mockPrepareAppDependenciesHeaders
546+ . mockImplementationOnce ( ( ) => { } ) // First call succeeds
547+ . mockImplementationOnce ( ( ) => { } ) // Second call succeeds
548+ . mockImplementationOnce ( ( ) => {
549+ // Third call fails
550+ throw originalError ;
551+ } ) ;
552+
553+ // Execute & Assert
554+ await expect ( prepareHeaders ( reactNativePath , appIosPath ) ) . rejects . toThrow (
555+ 'Header preparation failed: Third-party dependencies header preparation failed' ,
556+ ) ;
557+
558+ const expectedOutputFolder =
559+ '/path/to/app/ios/build/generated/ios/ReactAppDependencyProvider' ;
560+ const expectedCodegenOutputFolder =
561+ '/path/to/app/ios/build/generated/ios/ReactCodegen' ;
562+
563+ expect ( mockPrepareAppDependenciesHeaders ) . toHaveBeenCalledTimes ( 3 ) ;
564+ expect ( mockPrepareAppDependenciesHeaders ) . toHaveBeenNthCalledWith (
565+ 1 ,
566+ reactNativePath ,
567+ appIosPath ,
568+ expectedOutputFolder ,
569+ 'codegen' ,
570+ ) ;
571+ expect ( mockPrepareAppDependenciesHeaders ) . toHaveBeenNthCalledWith (
572+ 2 ,
573+ reactNativePath ,
574+ appIosPath ,
575+ expectedCodegenOutputFolder ,
576+ 'react-native' ,
577+ ) ;
578+ expect ( mockPrepareAppDependenciesHeaders ) . toHaveBeenNthCalledWith (
579+ 3 ,
580+ reactNativePath ,
581+ appIosPath ,
582+ expectedCodegenOutputFolder ,
583+ 'third-party-dependencies' ,
584+ ) ;
585+
586+ expect ( mockConsoleLog ) . toHaveBeenCalledWith ( 'Preparing codegen headers...' ) ;
587+ expect ( mockConsoleLog ) . toHaveBeenCalledWith ( '✓ Codegen headers prepared' ) ;
588+ expect ( mockConsoleLog ) . toHaveBeenCalledWith (
589+ 'Preparing react-native headers...' ,
590+ ) ;
591+ expect ( mockConsoleLog ) . toHaveBeenCalledWith (
592+ '✓ React Native headers prepared' ,
593+ ) ;
594+ expect ( mockConsoleLog ) . toHaveBeenCalledWith (
595+ 'Preparing third-party dependencies headers...' ,
596+ ) ;
597+ expect ( mockConsoleLog ) . not . toHaveBeenCalledWith (
598+ '✓ Third-party dependencies headers prepared' ,
599+ ) ;
600+ } ) ;
601+
602+ it ( 'should handle different paths correctly' , async ( ) => {
603+ // Setup
604+ const reactNativePath = '/Users/developer/react-native' ;
605+ const appIosPath = '/Users/developer/MyApp/ios' ;
606+
607+ mockPrepareAppDependenciesHeaders . mockImplementation ( ( ) => { } ) ;
608+
609+ // Execute
610+ await prepareHeaders ( reactNativePath , appIosPath ) ;
611+
612+ // Assert
613+ const expectedOutputFolder =
614+ '/Users/developer/MyApp/ios/build/generated/ios/ReactAppDependencyProvider' ;
615+ const expectedCodegenOutputFolder =
616+ '/Users/developer/MyApp/ios/build/generated/ios/ReactCodegen' ;
617+
618+ expect ( mockPrepareAppDependenciesHeaders ) . toHaveBeenCalledTimes ( 3 ) ;
619+
620+ expect ( mockPrepareAppDependenciesHeaders ) . toHaveBeenNthCalledWith (
621+ 1 ,
622+ reactNativePath ,
623+ appIosPath ,
624+ expectedOutputFolder ,
625+ 'codegen' ,
626+ ) ;
627+ expect ( mockPrepareAppDependenciesHeaders ) . toHaveBeenNthCalledWith (
628+ 2 ,
629+ reactNativePath ,
630+ appIosPath ,
631+ expectedCodegenOutputFolder ,
632+ 'react-native' ,
633+ ) ;
634+ expect ( mockPrepareAppDependenciesHeaders ) . toHaveBeenNthCalledWith (
635+ 3 ,
636+ reactNativePath ,
637+ appIosPath ,
638+ expectedCodegenOutputFolder ,
639+ 'third-party-dependencies' ,
640+ ) ;
641+ } ) ;
642+
643+ it ( 'should handle paths with spaces correctly' , async ( ) => {
644+ // Setup
645+ const reactNativePath = '/path/to/react native' ;
646+ const appIosPath = '/path/to/my app/ios folder' ;
647+
648+ mockPrepareAppDependenciesHeaders . mockImplementation ( ( ) => { } ) ;
649+
650+ // Execute
651+ await prepareHeaders ( reactNativePath , appIosPath ) ;
652+
653+ // Assert
654+ const expectedOutputFolder =
655+ '/path/to/my app/ios folder/build/generated/ios/ReactAppDependencyProvider' ;
656+ const expectedCodegenOutputFolder =
657+ '/path/to/my app/ios folder/build/generated/ios/ReactCodegen' ;
658+
659+ expect ( mockPrepareAppDependenciesHeaders ) . toHaveBeenCalledTimes ( 3 ) ;
660+
661+ expect ( mockPrepareAppDependenciesHeaders ) . toHaveBeenNthCalledWith (
662+ 1 ,
663+ reactNativePath ,
664+ appIosPath ,
665+ expectedOutputFolder ,
666+ 'codegen' ,
667+ ) ;
668+ expect ( mockPrepareAppDependenciesHeaders ) . toHaveBeenNthCalledWith (
669+ 2 ,
670+ reactNativePath ,
671+ appIosPath ,
672+ expectedCodegenOutputFolder ,
673+ 'react-native' ,
674+ ) ;
675+ expect ( mockPrepareAppDependenciesHeaders ) . toHaveBeenNthCalledWith (
676+ 3 ,
677+ reactNativePath ,
678+ appIosPath ,
679+ expectedCodegenOutputFolder ,
680+ 'third-party-dependencies' ,
681+ ) ;
682+ } ) ;
683+ } ) ;
684+
367685// Mock console methods - disable React Native's strict console checking
368686const originalConsole = global . console ;
369687
0 commit comments