开发者

iOS UIAutomation UIAElement.isVisible() throwing stale response?

I'm trying to use isVisible() within a loop to create a waitForElement type of a function for my iOS UIAutomation. When I try to use the following code, it fails while waiting for an element when a new screen pops up. The element is clearly there because if I do a delay(2) before tapping the element it works perfectly fine. How is everyone else accomplishing this, because I am at a loss...

Here's the waitForElement code that I am using:

function waitForElement(element, timeout, step) {
        i开发者_开发百科f (step == null) {
                step = 0.5;
        }

        if (timeout == null) {
            timeout = 10;
        }

        var stop = timeout/step;

        for (var i = 0; i < stop; i++) {
                if (element.isVisible()) {
                        return;
                }
                target.delay(step);
        }
        element.logElement();
        throw("Not visible");
}


Here is a simple wait_for_element method that could be used:

this.wait_for_element = function(element, preDelay) {
    if (!preDelay) {
        target.delay(0);
    }
    else {
        target.delay(preDelay);
    }

    var found = false;
    var counter = 0;      
    while ((!found) && (counter < 60)) {    
        if (!element.isValid()) {
            target.delay(0.5);
            counter++;
        }
        else {
            found = true;
            target.delay(1);
        }
    }
}


I tend to stay away from my wait_for_element and look for any activityIndicator objects on screen. I use this method to actual wait for the page to load.

this.wait_for_page_load = function(preDelay) {        
    if (!preDelay) {
        target.delay(0);
    }
    else {
        target.delay(preDelay);
    }

    var done = false;
    var counter = 0;      
    while ((!done) && (counter < 60)) {
        var progressIndicator = UIATarget.localTarget().frontMostApp().windows()[0].activityIndicators()[0];
        if (progressIndicator != "[object UIAElementNil]") {
            target.delay(0.25);
            counter++;  
        }
        else {
            done = true;           
        }
    }
    target.delay(0.25);
}


Here is a simple and better one using recursion. "return true" is not needed but incase u want it.

waitForElementToDismiss:function(elementToWait,waitTime){ //Using recursion to wait for an element. pass in 0 for waitTime 

    if(elementToWait && elementToWait.isValid() && elementToWait.isVisible() && (waitTime < 30)){
        this.log("Waiting for element to invisible");
        target.delay(1);
        this.waitForElementToDismiss(elementToWait, waitTime++);
    }

    if(waitTime >=30){
        fail("Possible login failed or too long to login. Took more than     "+waitTime +" seconds")
    }

    return true;

}


Solution

I know this is an old question but here is my solution for a situation where I have to perform a repetitive task against a variable timed event. Since UIAutomation runs on javascript I use a recursive function with an empty while loop that checks the critical control state required before proceeding to the next screen. This way one never has to hard code a delay.

// Local target is the running simulator
var target = UIATarget.localTarget();
// Get the frontmost app running in the target
var app = target.frontMostApp();
// Grab the main window of the application
var window = app.mainWindow();
//Get the array of images on the screen
var allImages = window.images();

var helpButton = window.buttons()[0];
var nextButton = window.buttons()[2];

doSomething();

function doSomething ()
{   
    //only need to tap button for half the items in array
    for (var i=0; i<(allImages.length/2); i++){
        helpButton.tap();
    }

    //loop while my control is NOT enabled
    while (!nextButton.isEnabled())
    {
        //wait  
    }   

    //proceed to next screen
    nextButton.tap();

    //go again
    doSomething();
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜