@@ -4,7 +4,11 @@ import { beforeEach, describe, expect, it, jest } from '@jest/globals';
44import fs from 'fs/promises' ;
55import path from 'path' ;
66
7- import { modifyAppDelegateAsync , modifyObjcAppDelegate } from '../src/ios/appDelegate' ;
7+ import {
8+ modifyAppDelegateAsync ,
9+ modifyObjcAppDelegate ,
10+ modifySwiftAppDelegate ,
11+ } from '../src/ios/appDelegate' ;
812
913describe ( 'Config Plugin iOS Tests' , function ( ) {
1014 beforeEach ( function ( ) {
@@ -74,17 +78,52 @@ describe('Config Plugin iOS Tests', function () {
7478 ) ;
7579 } ) ;
7680
77- it ( "doesn't support Swift AppDelegate" , async function ( ) {
78- jest . spyOn ( fs , 'writeFile' ) . mockImplementation ( async ( ) => { } ) ;
81+ it ( 'supports Swift AppDelegate' , async function ( ) {
82+ // Use MockedFunction to properly type the mock
83+ const writeFileMock = jest
84+ . spyOn ( fs , 'writeFile' )
85+ . mockImplementation ( async ( ) => { } ) as jest . MockedFunction < typeof fs . writeFile > ;
86+
87+ const swiftContents = `import Expo
88+ import React
89+
90+ @UIApplicationMain
91+ class AppDelegate: ExpoAppDelegate {
92+ override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
93+ // Initialize the factory
94+ let factory = ExpoReactNativeFactory(delegate: delegate)
95+ factory.startReactNative(withModuleName: "main", in: window, launchOptions: launchOptions)
96+ return super.application(application, didFinishLaunchingWithOptions: launchOptions)
97+ }
98+ }` ;
7999
80100 const appDelegateFileInfo : AppDelegateProjectFile = {
81- path : '. ' ,
101+ path : '/app/ios/App/AppDelegate.swift ' ,
82102 language : 'swift' ,
83- contents : 'some dummy content' ,
103+ contents : swiftContents ,
84104 } ;
85105
86- await expect ( modifyAppDelegateAsync ( appDelegateFileInfo ) ) . rejects . toThrow ( ) ;
87- expect ( fs . writeFile ) . not . toHaveBeenCalled ( ) ;
106+ await modifyAppDelegateAsync ( appDelegateFileInfo ) ;
107+
108+ // Check if writeFile was called
109+ expect ( writeFileMock ) . toHaveBeenCalled ( ) ;
110+
111+ // Get the modified content with explicit string type assertion
112+ const modifiedContents = writeFileMock . mock . calls [ 0 ] [ 1 ] as string ;
113+
114+ // Verify import was added
115+ expect ( modifiedContents ) . toContain ( 'import RNFBAppCheck' ) ;
116+
117+ // Verify initialization code was added
118+ expect ( modifiedContents ) . toContain ( 'RNFBAppCheckModule.sharedInstance()' ) ;
119+
120+ // Verify Firebase.configure() was added
121+ expect ( modifiedContents ) . toContain ( 'FirebaseApp.configure()' ) ;
122+
123+ // Verify the code was added before startReactNative (with explicit type assertion)
124+ const codeIndex = ( modifiedContents as string ) . indexOf ( 'RNFBAppCheckModule.sharedInstance()' ) ;
125+ const startReactNativeIndex = ( modifiedContents as string ) . indexOf ( 'factory.startReactNative' ) ;
126+ expect ( codeIndex ) . toBeLessThan ( startReactNativeIndex ) ;
88127 } ) ;
89128
90129 it ( 'does not add the firebase import multiple times' , async function ( ) {
@@ -104,4 +143,30 @@ describe('Config Plugin iOS Tests', function () {
104143 expect ( twiceModifiedAppDelegate ) . toContain ( singleImport ) ;
105144 expect ( twiceModifiedAppDelegate ) . not . toContain ( doubleImport ) ;
106145 } ) ;
146+
147+ it ( 'does not add the swift import multiple times' , async function ( ) {
148+ const swiftContents = `import Expo
149+ import React
150+
151+ @UIApplicationMain
152+ class AppDelegate: ExpoAppDelegate {
153+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
154+ let factory = ExpoReactNativeFactory(delegate: delegate)
155+ factory.startReactNative(withModuleName: "main", in: window, launchOptions: launchOptions)
156+ return super.application(application, didFinishLaunchingWithOptions: launchOptions)
157+ }
158+ }` ;
159+
160+ const onceModifiedContents = modifySwiftAppDelegate ( swiftContents ) ;
161+ expect ( onceModifiedContents ) . toContain ( 'import RNFBAppCheck' ) ;
162+
163+ // Count occurrences of the import
164+ const importCount = ( onceModifiedContents . match ( / i m p o r t R N F B A p p C h e c k / g) || [ ] ) . length ;
165+ expect ( importCount ) . toBe ( 1 ) ;
166+
167+ // Modify a second time and ensure imports aren't duplicated
168+ const twiceModifiedContents = modifySwiftAppDelegate ( onceModifiedContents ) ;
169+ const secondImportCount = ( twiceModifiedContents . match ( / i m p o r t R N F B A p p C h e c k / g) || [ ] ) . length ;
170+ expect ( secondImportCount ) . toBe ( 1 ) ;
171+ } ) ;
107172} ) ;
0 commit comments