From fdaeb97591bf286e049377cac8e9c3d5aadc7271 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Wed, 12 Nov 2025 14:26:35 +0000 Subject: [PATCH 1/7] fix: update password title --- .../FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift | 7 +++++++ .../Sources/Views/UpdatePasswordView.swift | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift index f119cf91b8..8b155a94ae 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift @@ -103,6 +103,13 @@ public class StringUtils { return localizedString(for: "EnterYourPassword") } + /// Update password title + /// found in: + /// - UpdatePasswordView + public var updatePasswordTitle: String { + return localizedString(for: "UpdatePasswordTitle") + } + /// Password recovery title /// found in: /// - PasswordRecoveryView diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/UpdatePasswordView.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/UpdatePasswordView.swift index d6ff5eea26..9e8a1cb263 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/UpdatePasswordView.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/UpdatePasswordView.swift @@ -103,7 +103,7 @@ extension UpdatePasswordView: View { } .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top) .safeAreaPadding() - .navigationTitle(authService.string.passwordRecoveryTitle) + .navigationTitle(authService.string.updatePasswordTitle) .alert( "Password Updated", isPresented: $showAlert From f424606815a3b26caebb0814b114922549c43648 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Wed, 12 Nov 2025 14:51:24 +0000 Subject: [PATCH 2/7] chore: include message for user to follow --- .../FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift index d66848437c..ba2ec531aa 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift @@ -148,6 +148,7 @@ extension SignedInView: View { VStack(spacing: 24) { Text(authService.string.verifyEmailSheetMessage) .font(.headline) + Text("Please tap on the link in your email to complete verification.") Button { showEmailVerificationSent = false } label: { From ee477103fc0592f4cfb066c87157ce5c2a3e0f64 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Wed, 12 Nov 2025 14:54:41 +0000 Subject: [PATCH 3/7] chore: local strings --- .../Sources/Strings/Localizable.xcstrings | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Strings/Localizable.xcstrings b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Strings/Localizable.xcstrings index 746fadc043..66e12e28f6 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Strings/Localizable.xcstrings +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Strings/Localizable.xcstrings @@ -3053,6 +3053,10 @@ } } }, + "Please tap on the link in your email to complete verification." : { + "comment" : "A message displayed in a sheet that appears after a user requests email verification. It instructs the user to tap on the link in their email to complete the verification process.", + "isCommentAutoGenerated" : true + }, "PrivacyPolicy" : { "comment" : "Text linked to a web page with the Privacy Policy content.", "extractionState" : "manual", @@ -4963,5 +4967,5 @@ } }, - "version" : "1.0" + "version" : "1.1" } \ No newline at end of file From b84868969f207de003df13991ee151560face05c Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Wed, 12 Nov 2025 15:13:34 +0000 Subject: [PATCH 4/7] chore: remove stale comment --- .../FirebaseAuthSwiftUI/Sources/Views/MFAManagementView.swift | 1 - .../FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/MFAManagementView.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/MFAManagementView.swift index 0614373a1c..a79be1d2f3 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/MFAManagementView.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/MFAManagementView.swift @@ -134,7 +134,6 @@ extension MFAManagementView: View { .onAppear { loadEnrolledFactors() } - // Password prompt sheet now centralized in AuthPickerView } @ViewBuilder diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift index ba2ec531aa..4f3e8bd933 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift @@ -20,7 +20,7 @@ public struct SignedInView { @Environment(AuthService.self) private var authService @Environment(\.reportError) private var reportError @State private var showDeleteConfirmation = false - @State private var showEmailVerificationSent = false + @State private var showEmailVerificationSent = true private func sendEmailVerification() async throws { do { @@ -143,7 +143,6 @@ extension SignedInView: View { ) .presentationDetents([.medium]) } - // Password prompt sheet now centralized in AuthPickerView .sheet(isPresented: $showEmailVerificationSent) { VStack(spacing: 24) { Text(authService.string.verifyEmailSheetMessage) From bf99d15313e0f06da77e661a489c4345d9e21b5d Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Wed, 12 Nov 2025 15:15:16 +0000 Subject: [PATCH 5/7] chore: revert state --- .../FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift index 4f3e8bd933..663e94d55e 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift @@ -20,7 +20,7 @@ public struct SignedInView { @Environment(AuthService.self) private var authService @Environment(\.reportError) private var reportError @State private var showDeleteConfirmation = false - @State private var showEmailVerificationSent = true + @State private var showEmailVerificationSent = false private func sendEmailVerification() async throws { do { From 7440d4e9a383014b2448f198698461f93edc63a6 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Wed, 12 Nov 2025 15:39:16 +0000 Subject: [PATCH 6/7] fix: move to alert --- .../Sources/Views/SignedInView.swift | 26 ++++++------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift index 663e94d55e..960ad1d376 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift @@ -143,25 +143,15 @@ extension SignedInView: View { ) .presentationDetents([.medium]) } - .sheet(isPresented: $showEmailVerificationSent) { - VStack(spacing: 24) { - Text(authService.string.verifyEmailSheetMessage) - .font(.headline) - Text("Please tap on the link in your email to complete verification.") - Button { - showEmailVerificationSent = false - } label: { - Text(authService.string.okButtonLabel) - .padding(.vertical, 8) - .frame(maxWidth: .infinity) - } - .buttonStyle(.borderedProminent) - .padding([.top, .bottom], 8) - .frame(maxWidth: .infinity) + .alert( + authService.string.verifyEmailSheetMessage, + isPresented: $showEmailVerificationSent + ) { + Button(authService.string.okButtonLabel) { + showEmailVerificationSent = false } - .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top) - .safeAreaPadding() - .presentationDetents([.medium]) + } message: { + Text("Please tap on the link in your email to complete verification.") } } } From c9a1f5515c0d9588b101155446b765b9102c0971 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Wed, 12 Nov 2025 15:39:22 +0000 Subject: [PATCH 7/7] format --- .../MFAEnrolmentUITests.swift | 14 +++++++------- .../FirebaseSwiftUIExampleUITests/TestUtils.swift | 15 +++++++++------ 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/e2eTest/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests/MFAEnrolmentUITests.swift b/e2eTest/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests/MFAEnrolmentUITests.swift index c524097952..c5563be16e 100644 --- a/e2eTest/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests/MFAEnrolmentUITests.swift +++ b/e2eTest/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests/MFAEnrolmentUITests.swift @@ -23,21 +23,21 @@ import XCTest final class MFAEnrollmentUITests: XCTestCase { var app: XCUIApplication! - + override func setUpWithError() throws { continueAfterFailure = false } - + override func tearDownWithError() throws { // Clean up: Terminate app if let app = app { app.terminate() } app = nil - + // Small delay between tests to allow emulator to settle Thread.sleep(forTimeInterval: 0.5) - + try super.tearDownWithError() } @@ -226,7 +226,7 @@ final class MFAEnrollmentUITests: XCTestCase { let phoneField = app.textFields["phone-number-field"] XCTAssertTrue(phoneField.waitForExistence(timeout: 10)) // Generate unique phone number using timestamp to avoid conflicts between tests - let uniqueId = Int(Date().timeIntervalSince1970 * 1000) % 1000000 + let uniqueId = Int(Date().timeIntervalSince1970 * 1000) % 1_000_000 let phoneNumberWithoutDialCode = "7\(String(format: "%09d", uniqueId))" UIPasteboard.general.string = phoneNumberWithoutDialCode phoneField.tap() @@ -258,9 +258,9 @@ final class MFAEnrollmentUITests: XCTestCase { // Paste each digit into the corresponding text field let codeDigits = Array(code) - let fields = [verificationCodeField1, verificationCodeField2, verificationCodeField3, + let fields = [verificationCodeField1, verificationCodeField2, verificationCodeField3, verificationCodeField4, verificationCodeField5, verificationCodeField6] - + for (index, digit) in codeDigits.enumerated() where index < fields.count { let field = fields[index] UIPasteboard.general.string = String(digit) diff --git a/e2eTest/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests/TestUtils.swift b/e2eTest/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests/TestUtils.swift index bef4c7f5de..b1e6e5df53 100644 --- a/e2eTest/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests/TestUtils.swift +++ b/e2eTest/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests/TestUtils.swift @@ -139,7 +139,9 @@ func createEmail() -> String { guard let http = sendResp as? HTTPURLResponse, http.statusCode == 200 else { let errorBody = String(data: sendData, encoding: .utf8) ?? "Unknown error" throw NSError(domain: "EmulatorError", code: 1, - userInfo: [NSLocalizedDescriptionKey: "Failed to send verification email: \(errorBody)"]) + userInfo: [ + NSLocalizedDescriptionKey: "Failed to send verification email: \(errorBody)", + ]) } // Add a small delay to ensure the OOB code is registered in the emulator @@ -156,12 +158,12 @@ func createEmail() -> String { // Step 2: Fetch OOB codes from emulator with retry logic let oobURL = URL(string: "\(base)/emulator/v1/projects/\(projectID)/oobCodes")! - + var codeItem: OobItem? var attempts = 0 let maxAttempts = 5 - - while codeItem == nil && attempts < maxAttempts { + + while codeItem == nil, attempts < maxAttempts { let (oobData, oobResp) = try await URLSession.shared.data(from: oobURL) guard (oobResp as? HTTPURLResponse)?.statusCode == 200 else { throw NSError(domain: "EmulatorError", code: 2, @@ -182,7 +184,7 @@ func createEmail() -> String { return d0 > d1 } .first - + if codeItem == nil { attempts += 1 if attempts < maxAttempts { @@ -190,7 +192,8 @@ func createEmail() -> String { try await Task.sleep(nanoseconds: 500_000_000) // 0.5 seconds } else { // Log available codes for debugging - let availableCodes = envelope.oobCodes.map { "Email: \($0.email), Type: \($0.requestType)" }.joined(separator: "; ") + let availableCodes = envelope.oobCodes.map { "Email: \($0.email), Type: \($0.requestType)" } + .joined(separator: "; ") throw NSError(domain: "EmulatorError", code: 3, userInfo: [ NSLocalizedDescriptionKey: "No VERIFY_EMAIL OOB code found for \(email) after \(maxAttempts) attempts. Available codes: \(availableCodes)",