Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XCTestCase with Auth0: How to dismiss security alert “XXXX” Wants to Use “auth0.com” to Sign In

So recently Apple introduced this prompt: “XXXX” Wants to Use “auth0.com” to Sign In Where “XXXX” is the ios app name.

enter image description here

This alert/dialog comes up when in the case of Auth0 the user clicks on “Login with Google” or “Login with Facebook”. That’s all nice but when running IOS UI tests, this dialog doesn’t go away when using the usual way of dismissing system dialogs:

func doUserLogin(_ app: XCUIApplication) {

    app.staticTexts["notLoggedInActivelabel"].tap()
    // this will bring up oauth0 login window in ios

    // setup a handler to dismiss the system alert
    let handler = self.addUIInterruptionMonitor (withDescription: "allow oauth") { (alert) -> Bool in
        // code should come here where the dialog is presented, 
        // but it never does ....   
        alert.buttons["Continue"].tap() // click Continue Button 
        return true
    }

    // click the login with GOOGLE button. This brings up dialog “XXXX” Wants to Use “auth0.com” to Login
    app.scrollViews.otherElements.buttons["LOG IN WITH GOOGLE"].tap()

    // this step is required when using addUIInterruptionMonitor
    app.tap()

    removeUIInterruptionMonitor(handler)
}

It kinda makes sense to me: This is a security system dialog introduced by Apple in order to improve security. Having it easily dismissed in the code would defeat the purpose.
But still, anyone knows if it's possible to dismiss this dialog in an XCTestCase?

like image 442
chrisl08 Avatar asked May 30 '18 16:05

chrisl08


1 Answers

I think Apple expects from a developer to make use of the introduced addUIInterruptionMonitor.

In fact, the addUIInterruptionMonitor(withDescription: )is not working, so I went down the road to access the Springboard and select the appropriate permission on the system alert.

1. Extended the XCTestCase to reuse this function, if necessary

extension XCTestCase {

    // I hope this code is mostly reusable
    // I didn't test it for Location Permission While in Use vs. Always...
    func setPermission(for alert:XCUIElement, allow: Bool) -> Bool {
        if alert.elementType == .alert {

            // make sure to support any language
            // Might also be "allow" for some dialogs
            let buttonIdentifier = allow ? "Continue" : "Cancel"
            let identifierButton = alert.buttons[buttonIdentifier]
            if identifierButton.exists && identifierButton.isHittable {
                identifierButton.tap()
                return true
            }

            // Or, if you don't want to bother with the language/identifiers
            // Allow = Last button Index (probably 1), Cancel = 0
            let buttonIndex = allow ? alert.buttons.count - 1 : 0
            let indexButton = alert.buttons.element(boundBy: buttonIndex)
            if indexButton.exists && indexButton.isHittable {
                indexButton.tap()
                return true
            }
        }
        return false
    }
}

2. Call this function in your test like

// This holds a reference to your SignIn/Login XCUIElement
yourSignInButton.tap()

let systemAlerts = XCUIApplication(bundleIdentifier: "com.apple.springboard").alerts
if systemAlerts.count > 0 {
    _ = self.setPermission(for: systemAlerts.element(boundBy: 0), allow: true)
}

Optional: Springboard Class

I also created a Springboard Class, as I have also System Settings tests etc. running...

class Springboard {
    static let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
}

This way, you could call your XCUITestCase extension the following way:

let systemAlerts = Springboard.springboard.alerts
if systemAlerts.count > 0 {
    self.setPermission(for: systemAlerts.element(boundBy: 0), allow: true)
}

If, the addUIInterruptionMonitor(withDescription: ) was actually working, this could then look like the following:

Caution: currently, only working for Authorization/Permission alerts of Location, Microphone, etc.

let interruptionMonitor = addUIInterruptionMonitor(withDescription: "Allow the app and website to share information") { (alert) -> Bool in
    return self.setPermission(for: systemAlerts.element(boundBy: 0), allow: true)
}

// This holds a reference to your SignIn/Login XCUIElement
yourSignInButton.tap()

removeUIInterruptionMonitor(interruptionMonitor)
like image 144
Lepidopteron Avatar answered Sep 19 '22 10:09

Lepidopteron