Handling Alert with UIAutomation
Asked Answered
B

7

14

I'm trying to test the presence of an UIAlertView with UIAutomation but my handler never gets called.

At the beginning of my javascript i write :

UIATarget.onAlert = function onAlert(alert) {
    UIALogger.logMessage("alertShown");
    return false;
}

As i understand it, as soon as i specify my onAlert function, it should get called when an alertView appears during my tests. So i run a test that shows an alertView, here is the code that shows the alert :

UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:message message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
alertView.accessibilityLabel = @"alerte d'avertissement";
[alertView show];

I run my test in instruments, the alert shows up but my handler is never called. Has anybody been able to use event handlers with UIAutomation ?

Thanks, Vincent.

Brigittebriley answered 6/9, 2010 at 12:10 Comment(0)
R
19

The documentation seems to be wrong. It turns out that alerts are handled on the same thread your script tries to run. So if you want the alert handler to be called, you need to sleep, e.g.,

UIATarget.onAlert = { ... }
window.buttons().triggerAlertButton.tap();
UIATarget.localTarget().delay(4);

Also, it appears that the alert's name and value are always set to null. I was, however, able to access the first static text which contained the alert's title.

Roldan answered 23/12, 2010 at 18:48 Comment(5)
In many cases when element has no name specified but has static text inside, this text can be used like name property... for me that worked for buttons, views, tables....Guadalupe
hi, im also having the same problem. can u tel me how do u get the static txt from alertview? thanks in advanceHautboy
@Hautboy inside the onAlert callback function, try alert.logElementTree(). From there, I see that alert.name() is its title and alert.elements()[2].name() is its message.Bronchia
Instead of delay(4), frontMostApp().alert() is faster: https://mcmap.net/q/799248/-handling-alert-with-uiautomationBronchia
Drew, you mean the alerts are handled on a different thread than the main automation script, correct? (Because the main script keeps going while the alert is being addressed.) @MattDiPasquale, I did not find app.alert() in the main thread to work particularly; target.delay(4) had much better results.Krugersdorp
B
6

Make sure the UI Automation script is still running when the UIAlertView shows.

For example, adding the following line to the end of your script will keep it running until an alert becomes accessible or the grace period for object resolution expires.

// Wait for UIAlert to appear so that UIATarget.onAlert gets called.
target.frontMostApp().alert();

I figured this out by thoroughly reading & understanding Instruments User Guide: Automating UI Testing, which I highly recommend doing as an introduction to UI Automation.

It may also be helpful to review the UIATarget Class Reference, specifically the methods popTimeout, pushTimeout, setTimeout, timeout, and delay.

Bronchia answered 4/10, 2012 at 12:4 Comment(1)
This fixed my problem. Calling .alert() will wait up to 5 seconds (by default, configurable with target.setTimeout) for it to show up.Transubstantiation
S
4

The below code works for me. The function is handling the alert and "alert Shown" is printed on the logs.

var target = UIATarget.localTarget();
var application = target.frontMostApp();
var window = application.mainWindow();

UIATarget.onAlert = function onAlert(alert){
    UIALogger.logMessage("alert Shown");    
}

target.frontMostApp().mainWindow().tableViews()[0]
    .cells()["Fhgui"].buttons()["Images"].tap();
// Alert detected. Expressions for handling alerts 
// should be moved into the UIATarget.onAlert function definition.
target.frontMostApp().alert().defaultButton().tap();
Suzannesuzerain answered 11/9, 2012 at 12:1 Comment(0)
G
3

@vdaubry the solution is simple.

According to Apple documentation, if you want to handle alerts manually then you should return true instead of false in onAlert(alert)

 UIATarget.onAlert = function onAlert(alert) {
    UIALogger.logMessage("alertShown");
    return true;
}

@Drew Crawford the delays will not work because by default can button is clicked by UI Automation. The documentation is not wrong but it is not clearly explained.

Graybeard answered 20/3, 2015 at 8:48 Comment(0)
P
0

I was having "never called alert handler" problem too. Simply restarting apple's Instruments solved it for me :-).

Pesky answered 15/3, 2011 at 12:4 Comment(0)
A
0

e.g. - onAlert is not called

var target = UIATarget.localTarget(); 
target.buttons()["ShowAlert"].tap()
UIAtarget.onAlert = function onAlert(alert)
{...}

-

e.g. - onAlert is called

var target = UIATarget.localTarget(); 
UIAtarget.onAlert = function onAlert(alert)
{......}
target.buttons()["ShowAlert"].tap()

or

#import "onAlert.js"
var target = UIATarget.localTarget(); 
target.buttons()["ShowAlert"].tap()

Try it out.

Akkad answered 26/7, 2013 at 5:11 Comment(0)
B
0

Following snippet works for me on XCode 6.3.1 & Instruments(6.3.1 (6D1002)) :

    var target = UIATarget.localTarget();

    // Following line shows an internal alert with 'Cancel' & 'Continue' buttons
    target.frontMostApp().mainWindow().buttons()["ShowAlert"].tap();

    // Handle an internal alert
    UIATarget.onAlert = function onAlert(alert) {
            return true;
     }

    // Perform Tap on alert.
    target.frontMostApp().alert().buttons()["Continue"].tap();
Bouncing answered 28/5, 2015 at 11:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.