Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Protractor wait command is not able to wait for the bootstrap modal to appear

Scenario: Whenever user sign in using incorrect credentials, a bootstrap modal appears for 1-2 second with message "sorry, incorrect credentials". Below is the HTML of the modal.

<div class="modal-content">
<div class="modal-body note-error text-center ng-binding"> Sorry, invalid credentials! </div>
</div>

I need to verify if the expected error text is equal to actual error text.

My code

PageObject.js

var errorModal = element(by.css('.modal-body.note-error.text-center.ng-binding'));

this.getErrorText = function(){

var until = protractor.ExpectedConditions;
browser.wait(until.textToBePresentInElement(errorModal, "Sorry, invalid credentials!"), 3000, "Not able to find");


     return errorModal.getText();

 };

Spec.js

expect(Login_Page.getErrorText()).toMatch('Sorry, invalid credentials!');

Output

Message: Expected '' to match 'Sorry, invalid credentials!'.

I dont know why this wait is not working.

like image 568
hello_abhishek Avatar asked Jan 24 '17 13:01

hello_abhishek


2 Answers

I have found the rootCause of the problem after taking a look at your [app]. The error modal you are looking for always exists in dom - That means isPresent() will always return a true. But it is visible only for 1 or 2 secs on invalid input - That means isDisplayed() will return true for those only few seconds

The side effect of this is the return value of getText(). It returns only visible innerText. Check the below extract from official documentation

Get the visible innerText of this element, including sub-elements, without any leading or trailing whitespace. Visible elements are not hidden by CSS.

Thats the reason you are seeing an empty value from getText()

I suggest a work-around where you extract the innerText by browser.executeScript()

replace return errorModal.getText() with return browser.executeScript('return arguments[0].textContent',errorModal) and you should be all good

Let me know if this works

like image 100
AdityaReddy Avatar answered Nov 14 '22 11:11

AdityaReddy


This is the answer contributed by pittgoose as a part of https://github.com/angular/protractor/issues/4030. I just thought to share over here

Ok, before every webdriver action protractor performs browser.waitForAngular() which waits for all angular scripts to finish running before performing the next action. In this case I believe protractor is waiting for the popup modal to disappear before it performs its search.

Also, I just proved my theory because when I added browser.waitForAngularEnabled(false) before the browser.wait(...) the test passed. Ex:

browser.get('https://app.p3fy.com/#/login');
        element(by.css('[name="email"]')).sendKeys('[email protected]');
        element(by.css('[name="password"]')).sendKeys('blah');
        element(by.css('[type="submit"]')).click();
        browser.waitForAngularEnabled(false); // THIS MAKES THE TEST PASS
        browser.wait(ExpectedConditions.textToBePresentInElement(element(by.id('errorDialog')), 'Sorry, invalid credentials!'), 3000, 'No!');

This would not be an issue with Selenium Webdriver api since it doesn't wait for Angular to load.

like image 1
hello_abhishek Avatar answered Nov 14 '22 12:11

hello_abhishek