From f794bdc3c11fe3f03a7efb76b2ff58b27fa9e3aa Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Tue, 16 Jul 2024 11:18:55 -0500 Subject: [PATCH] Fix UI Tests (#1345) * Updates to have UI Tests pass as expected * Adds changes from PR Test Venmo UI tests in CI/CD #1328 and Add scene(_:willConnectTo:options:) to the MockVenmo App #1290 * Bumps timeouts --- .github/workflows/tests.yml | 6 +++--- Demo/Demo.xcodeproj/project.pbxproj | 2 ++ Demo/MockVenmo/SceneDelegate.swift | 5 +++++ .../AmericanExpress_UITests.swift | 2 +- Demo/UI Tests/Helpers/BTUITest.swift | 4 ++-- .../PayPalMessaging_UITests.swift | 7 ++++--- .../PayPal_Checkout_UITests.swift | 2 +- .../ThreeDSecure_V2_UITests.swift | 13 ++++++++++--- .../Venmo UI Tests/Venmo_UITests.swift | 18 ++++++++++-------- 9 files changed, 38 insertions(+), 21 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 88197b0768..8715aeb9d2 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -20,7 +20,7 @@ jobs: - name: Install CocoaPod dependencies run: pod install - name: Run Unit Tests - run: set -o pipefail && xcodebuild -workspace 'Braintree.xcworkspace' -sdk 'iphonesimulator' -configuration 'Debug' -scheme 'UnitTests' -destination 'name=iPhone 14,OS=17.2,platform=iOS Simulator' test | ./Pods/xcbeautify/xcbeautify + run: set -o pipefail && xcodebuild -workspace 'Braintree.xcworkspace' -sdk 'iphonesimulator' -configuration 'Debug' -scheme 'UnitTests' -destination 'name=iPhone 15,OS=17.2,platform=iOS Simulator' test | ./Pods/xcbeautify/xcbeautify ui_test_job: name: UI runs-on: macOS-14-xlarge @@ -35,7 +35,7 @@ jobs: - name: Install CocoaPod dependencies run: pod install - name: Run UI Tests - run: set -o pipefail && xcodebuild -workspace 'Braintree.xcworkspace' -sdk 'iphonesimulator' -configuration 'Release' -scheme 'UITests' -destination 'name=iPhone 14,OS=17.2,platform=iOS Simulator' test | ./Pods/xcbeautify/xcbeautify + run: set -o pipefail && xcodebuild -workspace 'Braintree.xcworkspace' -sdk 'iphonesimulator' -configuration 'Release' -scheme 'UITests' -destination 'name=iPhone 15,OS=17.2,platform=iOS Simulator' test | ./Pods/xcbeautify/xcbeautify integration_test_job: name: Integration runs-on: macOS-14-xlarge @@ -52,4 +52,4 @@ jobs: - name: Install CocoaPod dependencies run: pod install - name: Run Integration Tests - run: set -o pipefail && xcodebuild -workspace 'Braintree.xcworkspace' -sdk 'iphonesimulator' -configuration 'Release' -scheme 'IntegrationTests' -destination 'name=iPhone 14,OS=17.2,platform=iOS Simulator' test | ./Pods/xcbeautify/xcbeautify + run: set -o pipefail && xcodebuild -workspace 'Braintree.xcworkspace' -sdk 'iphonesimulator' -configuration 'Release' -scheme 'IntegrationTests' -destination 'name=iPhone 15,OS=17.2,platform=iOS Simulator' test | ./Pods/xcbeautify/xcbeautify diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index d7b26657a2..fb67457966 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -992,6 +992,7 @@ "$(inherited)", "@executable_path/Frameworks", "@loader_path/Frameworks", + "$(FRAMEWORK_SEARCH_PATHS)", ); PRODUCT_BUNDLE_IDENTIFIER = com.braintree.DemoUITests; "PRODUCT_BUNDLE_IDENTIFIER[sdk=macosx*]" = ""; @@ -1015,6 +1016,7 @@ "$(inherited)", "@executable_path/Frameworks", "@loader_path/Frameworks", + "$(FRAMEWORK_SEARCH_PATHS)", ); PRODUCT_BUNDLE_IDENTIFIER = com.braintree.DemoUITests; "PRODUCT_BUNDLE_IDENTIFIER[sdk=macosx*]" = ""; diff --git a/Demo/MockVenmo/SceneDelegate.swift b/Demo/MockVenmo/SceneDelegate.swift index a5b0fe536f..35e7856be1 100644 --- a/Demo/MockVenmo/SceneDelegate.swift +++ b/Demo/MockVenmo/SceneDelegate.swift @@ -7,5 +7,10 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { func scene(_ scene: UIScene, openURLContexts URLContexts: Set) { AppSwitcher.openVenmoURL = URLContexts.first?.url } + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + let urlContexts = connectionOptions.urlContexts + AppSwitcher.openVenmoURL = urlContexts.first?.url + } } diff --git a/Demo/UI Tests/American Express UI Tests/AmericanExpress_UITests.swift b/Demo/UI Tests/American Express UI Tests/AmericanExpress_UITests.swift index 40ab4f587b..a27d0b1872 100644 --- a/Demo/UI Tests/American Express UI Tests/AmericanExpress_UITests.swift +++ b/Demo/UI Tests/American Express UI Tests/AmericanExpress_UITests.swift @@ -19,7 +19,7 @@ class AmericanExpress_UITests: XCTestCase { app.buttons["Valid card"].tap() sleep(2) - XCTAssertTrue(app.buttons["45256433 Points, 316795.03 USD"].waitForExistence(timeout: 10)) + XCTAssertTrue(app.buttons["45256433 Points, 316795.03 USD"].waitForExistence(timeout: 20)) } func testInsufficientPointsCard_receivesErrorMessage() { diff --git a/Demo/UI Tests/Helpers/BTUITest.swift b/Demo/UI Tests/Helpers/BTUITest.swift index 617195d8bb..f98bf3073a 100644 --- a/Demo/UI Tests/Helpers/BTUITest.swift +++ b/Demo/UI Tests/Helpers/BTUITest.swift @@ -1,7 +1,7 @@ import XCTest extension XCTestCase { - func waitForElementToAppear(_ element: XCUIElement, timeout: TimeInterval = 15) { + func waitForElementToAppear(_ element: XCUIElement, timeout: TimeInterval = 30) { let existsPredicate = NSPredicate(format: "exists == true") expectation(for: existsPredicate, evaluatedWith: element) @@ -9,7 +9,7 @@ extension XCTestCase { waitForExpectations(timeout: timeout) } - func waitForElementToBeHittable(_ element: XCUIElement, timeout: TimeInterval = 15) { + func waitForElementToBeHittable(_ element: XCUIElement, timeout: TimeInterval = 30) { let existsPredicate = NSPredicate(format: "exists == true && hittable == true") expectation(for: existsPredicate, evaluatedWith: element) diff --git a/Demo/UI Tests/PayPal Messaging UI Tests/PayPalMessaging_UITests.swift b/Demo/UI Tests/PayPal Messaging UI Tests/PayPalMessaging_UITests.swift index 26032110dc..e8ff8dbd61 100644 --- a/Demo/UI Tests/PayPal Messaging UI Tests/PayPalMessaging_UITests.swift +++ b/Demo/UI Tests/PayPal Messaging UI Tests/PayPalMessaging_UITests.swift @@ -16,7 +16,7 @@ final class PayPalMessaging_Success_UITests: XCTestCase { } func testStart_withValidRequest_firesDelegates() { - XCTAssertTrue(app.buttons["DELEGATE: didAppear fired"].waitForExistence(timeout: 10)) + XCTAssertTrue(app.buttons["DELEGATE: didAppear fired"].waitForExistence(timeout: 30)) let expectedButtonText = "PayPal - Pay monthly for purchases of $199-$10,000. Learn more" waitForElementToBeHittable(app.buttons[expectedButtonText]) @@ -26,7 +26,7 @@ final class PayPalMessaging_Success_UITests: XCTestCase { app.buttons["PayPal learn more modal close"].tap() sleep(2) - XCTAssertTrue(app.buttons["DELEGATE: didSelect fired"].waitForExistence(timeout: 10)) + XCTAssertTrue(app.buttons["DELEGATE: didSelect fired"].waitForExistence(timeout: 30)) } } @@ -46,6 +46,7 @@ final class PayPalMessaging_Failure_UITests: XCTestCase { func testStart_withInvalidTokenizationKey_firesErrorDelegate() { let expectedErrorText = "DELEGATE: onError fired with Could not find PayPal client ID in Braintree configuration." - XCTAssertTrue(app.buttons[expectedErrorText].waitForExistence(timeout: 10)) + + XCTAssertTrue(app.buttons[expectedErrorText].waitForExistence(timeout: 20)) } } diff --git a/Demo/UI Tests/PayPal UI Tests/PayPal_Checkout_UITests.swift b/Demo/UI Tests/PayPal UI Tests/PayPal_Checkout_UITests.swift index 13ddfd2c6a..a92f963b7a 100644 --- a/Demo/UI Tests/PayPal UI Tests/PayPal_Checkout_UITests.swift +++ b/Demo/UI Tests/PayPal UI Tests/PayPal_Checkout_UITests.swift @@ -42,7 +42,7 @@ class PayPal_Checkout_UITests: XCTestCase { func testPayPal_checkout_cancelsSuccessfully_whenTappingCancelButtonOnPayPalSite() { let webviewElementsQuery = app.webViews.element.otherElements - self.waitForElementToAppear(webviewElementsQuery.links["Cancel Sandbox Purchase"], timeout: 20) + self.waitForElementToAppear(webviewElementsQuery.links["Cancel Sandbox Purchase"]) webviewElementsQuery.links["Cancel Sandbox Purchase"].forceTapElement() diff --git a/Demo/UI Tests/ThreeDSecure UI Tests/ThreeDSecure_V2_UITests.swift b/Demo/UI Tests/ThreeDSecure UI Tests/ThreeDSecure_V2_UITests.swift index cd6c099530..70b084d362 100644 --- a/Demo/UI Tests/ThreeDSecure UI Tests/ThreeDSecure_V2_UITests.swift +++ b/Demo/UI Tests/ThreeDSecure UI Tests/ThreeDSecure_V2_UITests.swift @@ -12,11 +12,10 @@ class ThreeDSecure_V2_UITests: XCTestCase { app.launchArguments.append("-UITestHardcodedClientToken") app.launchArguments.append("-Integration:ThreeDSecureViewController") app.launch() - - waitForElementToAppear(app.cardNumberTextField) } func testThreeDSecurePaymentFlowV2_frictionlessFlow_andTransacts() { + waitForElementToAppear(app.cardNumberTextField) app.enterCardDetailsWith(cardNumber: "4000000000001000", expirationDate: expirationDate) app.tokenizeButton.tap() sleep(2) @@ -25,6 +24,7 @@ class ThreeDSecure_V2_UITests: XCTestCase { } func testThreeDSecurePaymentFlowV2_challengeFlow_andTransacts() { + waitForElementToAppear(app.cardNumberTextField) app.enterCardDetailsWith(cardNumber: "4000000000001091", expirationDate: expirationDate) app.tokenizeButton.tap() sleep(2) @@ -44,6 +44,7 @@ class ThreeDSecure_V2_UITests: XCTestCase { } func testThreeDSecurePaymentFlowV2_noChallenge_andFails() { + waitForElementToAppear(app.cardNumberTextField) app.enterCardDetailsWith(cardNumber: "5200000000001013", expirationDate: expirationDate) app.tokenizeButton.tap() sleep(2) @@ -52,6 +53,7 @@ class ThreeDSecure_V2_UITests: XCTestCase { } func testThreeDSecurePaymentFlowV2_challengeFlow_andFails() { + waitForElementToAppear(app.cardNumberTextField) app.enterCardDetailsWith(cardNumber: "4000000000001109", expirationDate: expirationDate) app.tokenizeButton.tap() sleep(2) @@ -71,6 +73,7 @@ class ThreeDSecure_V2_UITests: XCTestCase { } func testThreeDSecurePaymentFlowV2_acceptsPassword_failsToAuthenticateNonce_dueToCardinalError() { + waitForElementToAppear(app.cardNumberTextField) app.enterCardDetailsWith(cardNumber: "4000000000001125") app.tokenizeButton.tap() sleep(2) @@ -90,6 +93,7 @@ class ThreeDSecure_V2_UITests: XCTestCase { } func testThreeDSecurePaymentFlowV2_returnsToApp_whenCancelTapped() { + waitForElementToAppear(app.cardNumberTextField) app.enterCardDetailsWith(cardNumber: "4000000000001091") app.tokenizeButton.tap() sleep(2) @@ -102,6 +106,7 @@ class ThreeDSecure_V2_UITests: XCTestCase { } func testThreeDSecurePaymentFlowV2_bypassedAuthentication() { + waitForElementToAppear(app.cardNumberTextField) app.enterCardDetailsWith(cardNumber: "4000000000001083") app.tokenizeButton.tap() sleep(2) @@ -110,6 +115,7 @@ class ThreeDSecure_V2_UITests: XCTestCase { } func testThreeDSecurePaymentFlowV2_lookupError() { + waitForElementToAppear(app.cardNumberTextField) app.enterCardDetailsWith(cardNumber: "4000000000001034") app.tokenizeButton.tap() sleep(2) @@ -118,10 +124,11 @@ class ThreeDSecure_V2_UITests: XCTestCase { } func testThreeDSecurePaymentFlowV2_timeout() { + waitForElementToAppear(app.cardNumberTextField) app.enterCardDetailsWith(cardNumber: "4000000000001075") app.tokenizeButton.tap() sleep(2) - waitForElementToAppear(app.liabilityCouldNotBeShiftedMessage, timeout:30) + waitForElementToAppear(app.liabilityCouldNotBeShiftedMessage, timeout:45) } } diff --git a/Demo/UI Tests/Venmo UI Tests/Venmo_UITests.swift b/Demo/UI Tests/Venmo UI Tests/Venmo_UITests.swift index 8ce2682d91..4ad9fd743c 100644 --- a/Demo/UI Tests/Venmo UI Tests/Venmo_UITests.swift +++ b/Demo/UI Tests/Venmo UI Tests/Venmo_UITests.swift @@ -17,53 +17,55 @@ class Venmo_UITests: XCTestCase { demoApp.launchArguments.append("-ClientToken") demoApp.launchArguments.append("-Integration:VenmoViewController") demoApp.launch() - - waitForElementToBeHittable(demoApp.buttons["Venmo"]) - waitForElementToBeHittable(demoApp.buttons["Venmo (with ECD options)"]) } func testTokenizeVenmo_whenSignInSuccessfulWithPaymentContext_returnsNonce() { + waitForElementToBeHittable(demoApp.buttons["Venmo"]) demoApp.buttons["Venmo"].tap() waitForElementToBeHittable(mockVenmo.buttons["SUCCESS WITH PAYMENT CONTEXT"]) mockVenmo.buttons["SUCCESS WITH PAYMENT CONTEXT"].tap() - XCTAssertTrue(demoApp.buttons["Got a nonce. Tap to make a transaction."].waitForExistence(timeout: 15)) + XCTAssertTrue(demoApp.buttons["Got a nonce. Tap to make a transaction."].waitForExistence(timeout: 30)) } func testTokenizeVenmo_withECDOptions_whenSignInSuccessfulWithPaymentContext_returnsNonce() { + waitForElementToBeHittable(demoApp.buttons["Venmo (with ECD options)"]) demoApp.buttons["Venmo (with ECD options)"].tap() waitForElementToBeHittable(mockVenmo.buttons["SUCCESS WITH PAYMENT CONTEXT"]) mockVenmo.buttons["SUCCESS WITH PAYMENT CONTEXT"].tap() - XCTAssertTrue(demoApp.buttons["Got a nonce. Tap to make a transaction."].waitForExistence(timeout: 15)) + XCTAssertTrue(demoApp.buttons["Got a nonce. Tap to make a transaction."].waitForExistence(timeout: 30)) } func testTokenizeVenmo_whenSignInSuccessfulWithoutPaymentContext_returnsNonce() { + waitForElementToBeHittable(demoApp.buttons["Venmo"]) demoApp.buttons["Venmo"].tap() waitForElementToBeHittable(mockVenmo.buttons["SUCCESS WITHOUT PAYMENT CONTEXT"]) mockVenmo.buttons["SUCCESS WITHOUT PAYMENT CONTEXT"].tap() - XCTAssertTrue(demoApp.buttons["Got a nonce. Tap to make a transaction."].waitForExistence(timeout: 15)) + XCTAssertTrue(demoApp.buttons["Got a nonce. Tap to make a transaction."].waitForExistence(timeout: 30)) } func testTokenizeVenmo_whenErrorOccurs_returnsError() { + waitForElementToBeHittable(demoApp.buttons["Venmo"]) demoApp.buttons["Venmo"].tap() waitForElementToBeHittable(mockVenmo.buttons["ERROR"]) mockVenmo.buttons["ERROR"].tap() - XCTAssertTrue(demoApp.buttons["An error occurred during the Venmo flow"].waitForExistence(timeout: 15)) + XCTAssertTrue(demoApp.buttons["An error occurred during the Venmo flow"].waitForExistence(timeout: 30)) } func testTokenizeVenmo_whenUserCancels_returnsCancel() { + waitForElementToBeHittable(demoApp.buttons["Venmo"]) demoApp.buttons["Venmo"].tap() waitForElementToBeHittable(mockVenmo.buttons["Cancel"]) mockVenmo.buttons["Cancel"].tap() - XCTAssertTrue(demoApp.buttons["Canceled 🔰"].waitForExistence(timeout: 15)) + XCTAssertTrue(demoApp.buttons["Canceled 🔰"].waitForExistence(timeout: 30)) } }