From 21e21b0c25c623d52a24e2db0f4ac0a8b5557c6c Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 30 May 2025 11:13:05 +0100 Subject: [PATCH 1/5] test: fix View UI tests that are still signing in at the point of failure --- .../FirebaseSwiftUIExampleUITests.swift | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/samples/swiftui/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests/FirebaseSwiftUIExampleUITests.swift b/samples/swiftui/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests/FirebaseSwiftUIExampleUITests.swift index 1252d35519..2d7a818f6d 100644 --- a/samples/swiftui/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests/FirebaseSwiftUIExampleUITests.swift +++ b/samples/swiftui/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests/FirebaseSwiftUIExampleUITests.swift @@ -81,10 +81,16 @@ final class FirebaseSwiftUIExampleUITests: XCTestCase { signInButton.tap() let signedInText = app.staticTexts["signed-in-text"] - XCTAssertTrue( - signedInText.waitForExistence(timeout: 10), - "SignedInView should be visible after login" - ) + let maxWaitTime: TimeInterval = 30 + let interval: TimeInterval = 1 + var waited: TimeInterval = 0 + + while !signedInText.exists && waited < maxWaitTime { + sleep(UInt32(interval)) + waited += interval + } + + XCTAssertTrue(signedInText.exists, "SignedInView should be visible after login") dismissAlert(app: app) // Check the Views are updated @@ -177,9 +183,15 @@ final class FirebaseSwiftUIExampleUITests: XCTestCase { signInButton.tap() let signedInText = app.staticTexts["signed-in-text"] - XCTAssertTrue( - signedInText.waitForExistence(timeout: 20), - "SignedInView should be visible after login" - ) + let maxWaitTime: TimeInterval = 30 + let interval: TimeInterval = 1 + var waited: TimeInterval = 0 + + while !signedInText.exists && waited < maxWaitTime { + sleep(UInt32(interval)) + waited += interval + } + + XCTAssertTrue(signedInText.exists, "SignedInView should be visible after login") } } From e33f9631e6ec2033ec13fb87b37a9dbb0fb3fa37 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Mon, 2 Jun 2025 10:50:44 +0100 Subject: [PATCH 2/5] test: revert to using waitForExistence() with longer timeout --- .../FirebaseSwiftUIExampleUITests.swift | 26 ++++++------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/samples/swiftui/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests/FirebaseSwiftUIExampleUITests.swift b/samples/swiftui/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests/FirebaseSwiftUIExampleUITests.swift index 2d7a818f6d..dd3bf97aa7 100644 --- a/samples/swiftui/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests/FirebaseSwiftUIExampleUITests.swift +++ b/samples/swiftui/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests/FirebaseSwiftUIExampleUITests.swift @@ -81,16 +81,11 @@ final class FirebaseSwiftUIExampleUITests: XCTestCase { signInButton.tap() let signedInText = app.staticTexts["signed-in-text"] - let maxWaitTime: TimeInterval = 30 - let interval: TimeInterval = 1 - var waited: TimeInterval = 0 - while !signedInText.exists && waited < maxWaitTime { - sleep(UInt32(interval)) - waited += interval - } - - XCTAssertTrue(signedInText.exists, "SignedInView should be visible after login") + XCTAssertTrue( + signedInText.waitForExistence(timeout: 30), + "SignedInView should be visible after login" + ) dismissAlert(app: app) // Check the Views are updated @@ -183,15 +178,10 @@ final class FirebaseSwiftUIExampleUITests: XCTestCase { signInButton.tap() let signedInText = app.staticTexts["signed-in-text"] - let maxWaitTime: TimeInterval = 30 - let interval: TimeInterval = 1 - var waited: TimeInterval = 0 - while !signedInText.exists && waited < maxWaitTime { - sleep(UInt32(interval)) - waited += interval - } - - XCTAssertTrue(signedInText.exists, "SignedInView should be visible after login") + XCTAssertTrue( + signedInText.waitForExistence(timeout: 30), + "SignedInView should be visible after login" + ) } } From 79a47f13ba86a156158aad95690495a7f7137832 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Mon, 2 Jun 2025 12:04:02 +0100 Subject: [PATCH 3/5] test: update to use Swift .wait() method --- .../FirebaseSwiftUIExampleUITests.swift | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/samples/swiftui/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests/FirebaseSwiftUIExampleUITests.swift b/samples/swiftui/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests/FirebaseSwiftUIExampleUITests.swift index dd3bf97aa7..2e9999bf61 100644 --- a/samples/swiftui/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests/FirebaseSwiftUIExampleUITests.swift +++ b/samples/swiftui/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests/FirebaseSwiftUIExampleUITests.swift @@ -58,7 +58,7 @@ final class FirebaseSwiftUIExampleUITests: XCTestCase { } @MainActor - func testSignInDisplaysSignedInView() async throws { + func testSignInDisplaysSignedInView() throws { let app = XCUIApplication() let email = createEmail() app.launchArguments.append("--auth-emulator") @@ -82,11 +82,16 @@ final class FirebaseSwiftUIExampleUITests: XCTestCase { let signedInText = app.staticTexts["signed-in-text"] - XCTAssertTrue( - signedInText.waitForExistence(timeout: 30), - "SignedInView should be visible after login" + let expectation = XCTNSPredicateExpectation( + predicate: NSPredicate(format: "exists == true"), + object: signedInText ) + let maxWaitTime: TimeInterval = 30 + let result = XCTWaiter().wait(for: [expectation], timeout: maxWaitTime) + + XCTAssertEqual(result, .completed, "SignedInView should be visible after login") + dismissAlert(app: app) // Check the Views are updated let signOutButton = app.buttons["sign-out-button"] @@ -179,9 +184,14 @@ final class FirebaseSwiftUIExampleUITests: XCTestCase { let signedInText = app.staticTexts["signed-in-text"] - XCTAssertTrue( - signedInText.waitForExistence(timeout: 30), - "SignedInView should be visible after login" + let expectation = XCTNSPredicateExpectation( + predicate: NSPredicate(format: "exists == true"), + object: signedInText ) + + let maxWaitTime: TimeInterval = 30 + let result = XCTWaiter().wait(for: [expectation], timeout: maxWaitTime) + + XCTAssertEqual(result, .completed, "SignedInView should be visible after login") } } From 442a3580ccda650202be64d804dd5903d4f7279b Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Mon, 2 Jun 2025 13:19:11 +0100 Subject: [PATCH 4/5] test: refactor wait for signed-in View --- .../FirebaseSwiftUIExampleUITests.swift | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/samples/swiftui/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests/FirebaseSwiftUIExampleUITests.swift b/samples/swiftui/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests/FirebaseSwiftUIExampleUITests.swift index 2e9999bf61..8e7b5d29aa 100644 --- a/samples/swiftui/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests/FirebaseSwiftUIExampleUITests.swift +++ b/samples/swiftui/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests/FirebaseSwiftUIExampleUITests.swift @@ -82,15 +82,20 @@ final class FirebaseSwiftUIExampleUITests: XCTestCase { let signedInText = app.staticTexts["signed-in-text"] - let expectation = XCTNSPredicateExpectation( - predicate: NSPredicate(format: "exists == true"), - object: signedInText - ) + let expectation = XCTestExpectation(description: "Wait for SignedInView to appear") + let checkInterval: TimeInterval = 1 let maxWaitTime: TimeInterval = 30 - let result = XCTWaiter().wait(for: [expectation], timeout: maxWaitTime) - XCTAssertEqual(result, .completed, "SignedInView should be visible after login") + Timer.scheduledTimer(withTimeInterval: checkInterval, repeats: true) { timer in + if signedInText.exists { + expectation.fulfill() + timer.invalidate() + } + } + + wait(for: [expectation], timeout: maxWaitTime) + XCTAssertTrue(signedInText.exists, "SignedInView should be visible after login") dismissAlert(app: app) // Check the Views are updated @@ -184,14 +189,19 @@ final class FirebaseSwiftUIExampleUITests: XCTestCase { let signedInText = app.staticTexts["signed-in-text"] - let expectation = XCTNSPredicateExpectation( - predicate: NSPredicate(format: "exists == true"), - object: signedInText - ) + let expectation = XCTestExpectation(description: "Wait for SignedInView to appear") + let checkInterval: TimeInterval = 1 let maxWaitTime: TimeInterval = 30 - let result = XCTWaiter().wait(for: [expectation], timeout: maxWaitTime) - XCTAssertEqual(result, .completed, "SignedInView should be visible after login") + Timer.scheduledTimer(withTimeInterval: checkInterval, repeats: true) { timer in + if signedInText.exists { + expectation.fulfill() + timer.invalidate() + } + } + + wait(for: [expectation], timeout: maxWaitTime) + XCTAssertTrue(signedInText.exists, "SignedInView should be visible after login") } } From 2eaa752f97e101b8bc980572302572a92ed3d446 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Mon, 2 Jun 2025 15:51:43 +0100 Subject: [PATCH 5/5] test: need to wrap in DispatchQueue --- .../FirebaseSwiftUIExampleUITests.swift | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/samples/swiftui/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests/FirebaseSwiftUIExampleUITests.swift b/samples/swiftui/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests/FirebaseSwiftUIExampleUITests.swift index 8e7b5d29aa..3a96824f92 100644 --- a/samples/swiftui/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests/FirebaseSwiftUIExampleUITests.swift +++ b/samples/swiftui/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests/FirebaseSwiftUIExampleUITests.swift @@ -88,9 +88,11 @@ final class FirebaseSwiftUIExampleUITests: XCTestCase { let maxWaitTime: TimeInterval = 30 Timer.scheduledTimer(withTimeInterval: checkInterval, repeats: true) { timer in - if signedInText.exists { - expectation.fulfill() - timer.invalidate() + DispatchQueue.main.async { + if signedInText.exists { + expectation.fulfill() + timer.invalidate() + } } } @@ -195,9 +197,11 @@ final class FirebaseSwiftUIExampleUITests: XCTestCase { let maxWaitTime: TimeInterval = 30 Timer.scheduledTimer(withTimeInterval: checkInterval, repeats: true) { timer in - if signedInText.exists { - expectation.fulfill() - timer.invalidate() + DispatchQueue.main.async { + if signedInText.exists { + expectation.fulfill() + timer.invalidate() + } } }