adbarads
adbarads

Reputation: 1303

Why is Protractor running every line of code immediately?

Why is Protractor running every line of code immediately?

So I have a webpage that is not written in angular. That I need my selenium based automation to hit. I have used selenium webdriver-js code to hit it. Example below. Once you login, you are taken to a page with 3 questions. The order of the questions are randomized each time you login. So you may never get the same questions in the same order each time you login.

Question 1) What is your name?

Question 2) What time is it?

Question 3) Wy are you here?

The answers to each question are the last word of the question.

Answer 1) name

Answer 2) it

Answer 3) here

So what I was thinking an easy way to solve this problem is to create an if conditional statement

var foo = browser.driver.findElement(By.id('question1')).getText();
if(foo == What is your name?) {
browser.driver.findElement(By.id('answer1')).sendKeys('name');
}
else {
blah
}

and so forth... etc...

But the problem I am running into is that Protractor immediately runs the if statement before it gets to that point. In the example below, the console immediately prints out the console log 'this sucks', because it runs through the if statement immediately without going through the first steps to get to the page and then checking.

  this.foo_test = function() {
      console.log('starting foo test');
      browser.driver.get('http://my-test-url.com/');
      browser.sleep(3000);
      browser.driver.findElement(By.id('login')).click();
      browser.sleep(3000);
      browser.driver.findElement(By.id('user')).sendKeys('user');
      browser.driver.findElement(By.id('login_button')).click();
      browser.sleep(3000);

      console.log('getting variable');
      var foo = browser.driver.findElement(By.id('question1')).getText();
      console.log(foo);
      if (foo == 'What was the name of your first pet?') {
          console.log('this is cool');
      }
      else{
          console.log('this sucks');
      }
  };

Upvotes: 2

Views: 828

Answers (3)

P.T.
P.T.

Reputation: 25177

Protractor builds on WebdriverJS, which uses an implicit-promise-queuing style of programming. See:

https://github.com/angular/protractor/blob/master/docs/control-flow.md

What that means is that each statement in a protractor test should be read as enqueuing a promise, not as actually executing. So for example, the line:

browser.driver.findElement(By.id('question1')).getText()

Does not return text, but returns a promise to return text. You must pass this promise to the other promise-expecting APIs, or provide a direct handler with .then().

The expect call you see in Protractor tests has been modified to wait for a promise to resolve. So something like:

expect(name.getText()).toEqual('Jane Doe');

Is actually enqueuing a promise to compare the result of the promise on the left to the value on the right.

Upvotes: 3

CharlieS
CharlieS

Reputation: 1452

It appears your page is still loading even though selenium thinks it is complete. This happens alot with dynamic/asynchronous pages.

browser.sleep() is not really appropriate, you never really know how long you need to wait for.

You can investigate the class WebDriverWait, which allows you to wait for an element to appear, or timeout.

Wait<WebDriver> wait = new WebDriverWait(driver, 50); // timeout is 50 secs
wait.until(new Function<WebDriver, Boolean>() {
    public Boolean apply(WebDriver driver) {
        return (driver.findElement(By.id('question1'))).isDisplayed();
    }
});

You can also try running some javascript to check the document ready status :

Wait<WebDriver> wait = new WebDriverWait(driver, 60); // timeout is 60 secs
wait.until(new Function<WebDriver, Boolean>() {
    public Boolean apply(WebDriver driver) {
        String docReady = "";
        Boolean rc = true;
        if (null != ((RemoteWebDriver)driver).getSessionId()) {
            docReady = String.valueOf(((JavascriptExecutor) driver).executeScript("return document.readyState"));
            rc = docReady.equals("complete");
        }
        return rc;
    }
});

Upvotes: 0

takinola
takinola

Reputation: 1773

I don't know much about Protractor specifically but this sounds like an issue of not recognizing asynchronous code. If the first assignment statement is asynchronous, then the rest of the code will run without waiting for it to complete. Hence, the values you expect will not be there when you try to test for them in the IF statement.

Your best bet is to run the rest of the code in a callback or promise .

Upvotes: 0

Related Questions