@@ -56,23 +56,7 @@ final class MFAEnrollmentUITests: XCTestCase {
5656 // Sign in first to access MFA management
5757 try signInToApp ( app: app, email: email)
5858
59- // Check MFA management button exists
60- let mfaManagementButton = app. buttons [ " mfa-management-button " ]
61- XCTAssertTrue (
62- mfaManagementButton. waitForExistence ( timeout: 5 ) ,
63- " MFA management button should exist "
64- )
65- XCTAssertTrue ( mfaManagementButton. isEnabled, " MFA management button should be enabled " )
66-
67- // Tap the button
68- mfaManagementButton. tap ( )
69-
70- // Verify we navigated to MFA management view
71- let managementTitle = app. staticTexts [ " Two-Factor Authentication " ]
72- XCTAssertTrue (
73- managementTitle. waitForExistence ( timeout: 5 ) ,
74- " Should navigate to MFA management view "
75- )
59+ try navigateToMFAManagement ( app: app)
7660 }
7761
7862 @MainActor
@@ -87,16 +71,16 @@ final class MFAEnrollmentUITests: XCTestCase {
8771
8872 // Sign in and navigate to MFA management
8973 try signInToApp ( app: app, email: email)
90- app . buttons [ " mfa-management-button " ] . tap ( )
74+ try navigateToMFAManagement ( app : app )
9175
9276 // Tap setup MFA button (for users with no enrolled factors)
9377 let setupButton = app. buttons [ " setup-mfa-button " ]
94- if setupButton. waitForExistence ( timeout: 3 ) {
78+ if setupButton. waitForExistence ( timeout: 10 ) {
9579 setupButton. tap ( )
9680 } else {
9781 // If factors are already enrolled, tap add another method
9882 let addMethodButton = app. buttons [ " add-mfa-method-button " ]
99- XCTAssertTrue ( addMethodButton. waitForExistence ( timeout: 3 ) , " Add method button should exist " )
83+ XCTAssertTrue ( addMethodButton. waitForExistence ( timeout: 10 ) , " Add method button should exist " )
10084 addMethodButton. tap ( )
10185 }
10286
@@ -448,27 +432,46 @@ final class MFAEnrollmentUITests: XCTestCase {
448432 signedInText. waitForExistence ( timeout: 30 ) ,
449433 " SignedInView should be visible after login "
450434 )
435+ dismissAlert ( app: app)
451436 XCTAssertTrue ( signedInText. exists, " SignedInView should be visible after login " )
452437 }
453438
439+ @MainActor
440+ private func navigateToMFAManagement( app: XCUIApplication ) throws {
441+ dismissAlert ( app: app)
442+
443+ let mfaManagementButton = app. buttons [ " mfa-management-button " ]
444+ XCTAssertTrue (
445+ mfaManagementButton. waitForExistence ( timeout: 10 ) ,
446+ " MFA management button should exist "
447+ )
448+ XCTAssertTrue ( mfaManagementButton. isEnabled, " MFA management button should be enabled " )
449+ mfaManagementButton. tap ( )
450+
451+ let managementTitle = app. staticTexts [ " Two-Factor Authentication " ]
452+ XCTAssertTrue (
453+ managementTitle. waitForExistence ( timeout: 10 ) ,
454+ " Should navigate to MFA management view "
455+ )
456+ }
457+
454458 @MainActor
455459 private func navigateToMFAEnrollment( app: XCUIApplication ) throws {
456- // Navigate to MFA management
457- app. buttons [ " mfa-management-button " ] . tap ( )
460+ try navigateToMFAManagement ( app: app)
458461
459462 // Navigate to MFA enrollment
460463 let setupButton = app. buttons [ " setup-mfa-button " ]
461- if setupButton. waitForExistence ( timeout: 3 ) {
464+ if setupButton. waitForExistence ( timeout: 10 ) {
462465 setupButton. tap ( )
463466 } else {
464467 let addMethodButton = app. buttons [ " add-mfa-method-button " ]
465- XCTAssertTrue ( addMethodButton. waitForExistence ( timeout: 3 ) , " Add method button should exist " )
468+ XCTAssertTrue ( addMethodButton. waitForExistence ( timeout: 10 ) , " Add method button should exist " )
466469 addMethodButton. tap ( )
467470 }
468471
469472 // Verify we're in MFA enrollment view
470473 let enrollmentTitle = app. staticTexts [ " Set Up Two-Factor Authentication " ]
471- XCTAssertTrue ( enrollmentTitle. waitForExistence ( timeout: 5 ) , " Should be in MFA enrollment view " )
474+ XCTAssertTrue ( enrollmentTitle. waitForExistence ( timeout: 10 ) , " Should be in MFA enrollment view " )
472475 }
473476}
474477
@@ -486,49 +489,51 @@ struct VerificationCode: Codable {
486489/// - Returns: The verification code as a String
487490/// - Throws: Error if unable to retrieve codes
488491private func getLastSmsCode( specificPhone: String ? = nil ) async throws -> String {
489- let getSmsCodesUrl =
490- " http://127.0.0.1:9099/emulator/v1/projects/flutterfire-e2e-tests/verificationCodes "
492+ do {
493+ for projectID in authEmulatorCandidateProjectIDs ( ) {
494+ let getSmsCodesUrl =
495+ " http://127.0.0.1:9099/emulator/v1/projects/ \( projectID) /verificationCodes "
491496
492- guard let url = URL ( string: getSmsCodesUrl) else {
493- throw NSError (
494- domain: " getLastSmsCode " ,
495- code: - 1 ,
496- userInfo: [ NSLocalizedDescriptionKey: " Failed to create URL for SMS codes endpoint " ]
497- )
498- }
497+ guard let url = URL ( string: getSmsCodesUrl) else {
498+ continue
499+ }
499500
500- do {
501- let ( data, _) = try await URLSession . shared. data ( from: url)
501+ guard let ( data, _) = try ? await URLSession . shared. data ( from: url) else {
502+ continue
503+ }
502504
503- let decoder = JSONDecoder ( )
504- let codesResponse = try decoder. decode ( VerificationCodesResponse . self, from: data)
505+ let decoder = JSONDecoder ( )
506+ guard let codesResponse = try ? decoder. decode ( VerificationCodesResponse . self, from: data) else {
507+ continue
508+ }
505509
506- guard let codes = codesResponse. verificationCodes, !codes. isEmpty else {
507- throw NSError (
508- domain: " getLastSmsCode " ,
509- code: - 1 ,
510- userInfo: [ NSLocalizedDescriptionKey: " No SMS verification codes found in emulator " ]
511- )
512- }
510+ guard let codes = codesResponse. verificationCodes, !codes. isEmpty else {
511+ continue
512+ }
513513
514- if let specificPhone = specificPhone {
515- // Search backwards through codes for the specific phone number
516- for code in codes. reversed ( ) {
517- if code. phoneNumber == specificPhone {
518- return code. code
514+ if let specificPhone = specificPhone {
515+ // Search backwards through codes for the specific phone number
516+ for code in codes. reversed ( ) {
517+ if code. phoneNumber == specificPhone {
518+ return code. code
519+ }
519520 }
521+ } else if let lastCode = codes. last {
522+ return lastCode. code
520523 }
521- throw NSError (
522- domain: " getLastSmsCode " ,
523- code: - 1 ,
524- userInfo: [
525- NSLocalizedDescriptionKey: " No SMS verification code found for phone number: \( specificPhone) " ,
526- ]
527- )
524+ }
525+
526+ let description = if let specificPhone {
527+ " No SMS verification code found for phone number: \( specificPhone) "
528528 } else {
529- // Return the last code in the array
530- return codes. last!. code
529+ " No SMS verification codes found in emulator "
531530 }
531+
532+ throw NSError (
533+ domain: " getLastSmsCode " ,
534+ code: - 1 ,
535+ userInfo: [ NSLocalizedDescriptionKey: description]
536+ )
532537 } catch let error as DecodingError {
533538 throw NSError (
534539 domain: " getLastSmsCode " ,
0 commit comments