I am in the process of developing an automated test suite for an AngularJS app using Protractor.
While developing my test script, I have been using browser.pause() so that I manually have to tell it to continue with each step of the tests while I'm executing the script. I am now at the point where I'm happy that my tests are executing correctly, and want to remove the calls to browser.pause(), so that I can just let the script run through to completion on its own.
I am aware however, that I won't be able to just remove the calls to browser.pause() without adding something in to allow my tests to pause/ wait for the browser to load before executing the next step (currently, the time taken for me to tell the script to continue after a call to browser.pause() is run is enough time for the browser to have loaded the elements required for the next step of the test).
I am trying to use browser.wait() to do this, passing the last line of each test as a parameter to browser.wait(), along with a timeout value (i.e. 10 seconds). For example:
it('should log the user in to the application', function() {
browser.wait(loginAsUser(username, password), 10000);
});
where that test was originally just:
browser.pause();
it('should log the user in to the application', function() {
loginAsUser(username, password);
});
i.e. the call to browser.pause() outside of the test case would cause the browser to pause in between each step of each test.
The loginAsUser() function is defined with:
function loginAsUser(username, password) {
usernameInputField.sendKeys(username);
passwordInputField.sendKeys(password);
loginBtn.click();
}
When I currently run my test script, having added browser.wait() to the last executable line of each test as with the log in test, I get the following failure on the first test (the log in one above), and the remaining tests all fail because they are dependent on that one passing:
Failed: Wait condition must be a promise-like object, function, or a Condition object
I don't understand why I'm getting this error, since the wait condition is a function... it's being given the loginAsUser() function that I have defined above...? Can anyone explain to me what I'm doing wrong here?
Edit
So, it seems the problem is actually with the rest of my tests (i.e. the login test is run first, then a number of other tests are run sequentially after it).
With my login test as it was originally, the test case currently logs in correctly, however the next test to be run fails, giving the error:
Failed: No element found using locator: By(link text, Pages)
It seems that this is failing because the page hasn't had time to load following the log in, which it did have when I was running the tests with the calls to browser.pause().
The next test to be run is:
it('should display the Pages menu', function() {
browser.waitForAngularEnabled(false);
browser.actions().mouseMove(pagesMenuBtn).perform();
expect(pageTagBrowserBtn.isDisplayed()).toBeTruthy();
browser.actions().mouseMove(userCircle).perform();
expect(pageTagBrowserBtn.isDisplayed()).toBeFalsy();
browser.waitForAngularEnabled(true);
});
The pagesMenuBtn is defined as a global variable with:
var pagesMenuBtn = element(by.linkText("Pages"));
So, it seems that I need to somehow give my application time for the page to load following the login, before running this next test, or else the element won't be found.
Edit
I tried adding a call to browser.wait() within the 'Pages' test, so that the test would wait for the button to be displayed before hovering the cursor over it:
it('should display the Pages menu', function() {
browser.waitForAngularEnabled(false);
browser.wait(function() {
pagesMenuBtn.isDisplayed().then(function(isDisplayed){
/* if(!isDisplayed) {
console.log("Display Pages menu test returning false ");
return false;
}
console.log("Display Pages menu test returning true "); */
//return true;
browser.actions().mouseMove(pagesMenuBtn).perform().then(function(isDisplayed){
expect(pageTagBrowserBtn.isDisplayed()).toBeTruthy();
});
browser.actions().mouseMove(userCircle).perform().then(function(isDisplayed){
expect(pageTagBrowserBtn.isDisplayed()).toBeFalsy();
});
});
}, 5000);
});
but I still get the same error:
Failed: No element found using locator: By(link text, Pages)
indicating that the button that the test is trying to hover over can't be found (i.e. it doesn't appear to have loaded in the browser at the point at which the test script is trying to click on it).
Edit
Ok, so I've updated my test again- it now looks like this:
it('should display the Pages menu', function() {
browser.waitForAngularEnabled(false);
browser.wait(EC.visibilityOf(pagesMenuBtn), 5000).then(
browser.actions().mouseMove(pagesMenuBtn).perform().then(function(){
expect(pageTagBrowserBtn.isDisplayed()).toBeTruthy();
})).then(
browser.actions().mouseMove(userCircle).perform().then(function(){
expect(pageTagBrowserBtn.isDisplayed()).toBeFalsy();
}));
});
My intention for this was that the browser would wait for the pagesMenuBtn element to be displayed, and then, once it was, the cursor would move to the button, and once that had happened, it should check whether the pageTagBrowserBtn element was displayed (expecting it to return a 'true' value). The cursor would then move to another element on the page (userCircle), and check again whether the the pageTagBrowserBtn was displayed (this time expecting it to return a 'false' value).
However, when I now run my test, it fails, stating that:
Expected false to be truthy
I'm not sure why this is...? As I understand, the test should wait for the condition of EC.visibilityOf(pagesMenuBtn) to return true before it tries to continue with the test... so I wouldn't expect it to be failing due to the value being false at all- if the value is false, it should wait until it's true before continuing- at least that's my intention from what I've written.
Can anyone explain to me what's going wrong here?
browser.waitwith something like() => myCriterion(), i.e. something it can call over and over again until it returnstrue. You're passing the result of calling your function, which anyway is a function you probably don't want to keep calling. - jonrsharpe