I have a button that once clicked sends out an AJAX call in Angular's $promise format. When the login is successful, a $scope variable is changed and an element that looks like:
<section id="logged-in-section" ng-if="auth.user !== null">
// Section to display if logged in
</section>
is displayed. I am currently testing the above with the following:
loginButton.click();
browser.sleep(2000);
expect($("#logged-in-section").isDisplayed()).toBeTruthy();
browser.sleep(2000) idles the browser for two seconds before Protractor checks to see if logged-in-section has been displayed. If I take out browser.sleep(2000), the test fails since there is a lag between hitting the login button and the response returned from the server.
What's the syntax to chain the login button to the expect statement so that Protractor is only checking for #logged-in-section after the $promise is resolved?
$promise is not a service in Angular. Are you using some special module? Do you mean $q or $http?
Hey Julie, I meant to say $q. I want to check for elements on the DOM after an AJAX request is fulfilled. Right now, I am just using a timer (browser.sleep(2000)), but figured there should be a better way of doing this.
Protractor should automatically wait for all $q defers to finish. If you're doing something fancy that gets around that, you can use browser.wait. to wait until the logged in section is displayed.
I've never seen Protractor automatically wait for a $q call before. I have the following:
email.sendKeys(emailAddress);
password.sendKeys(registrationPassword);
passwordRepeat.sendKeys(registrationPassword);
createButton.click();
// Wait 3 seconds for operation to process and for user to be redirected to the success page
browser.sleep(3000);
// Test that sections that are shown when account creation is successful is displayed
expect($("#create-account-success").isDisplayed()).toBeTruthy();
createButton.click() sends out a $q call. Ifbrowser.sleep(3000) is taken out from the code, the test will fail every time.
Does anyone have insight on how to do this?
Well you should do:
createButton.click().then(function() {
expect($("#create-account-success").isDisplayed()).toBeTruthy();
});
In my case, I have to wait for a field to get a value - some number, so I'll be able to compare it
to what it had before.
The problem is that I have to wait for the ajax to fill the field with a value, and as you say -
when I take off the browser.sleep(3000);, the test will fail.
I tried some getText().then, etc, but no one really waits for $q :-)
If anyone knows some simple way to replace this browser.sleep(3000), i'll be happy
to hear :)
Thanks !!!
Doubt you're still looking for it but you can use browser.wait(fn, timeout).
docs
Same problem as OP.
From what I've experienced in my E2E tests, Protractor _does not_ wait for $q to finish.
According to the documentation and various posts on e.g. stack overflow, Protractor _does_ wait for e.g. $http, $timeout etc., but still has some gaps and $q seems to be one of them.
I hope you all would have figured out by now :) If not try: browser.waitForAngular
This Instructs webdriver to wait until Angular has finished rendering and has no outstanding $http or $timeout calls before continuing. Note that Protractor automatically applies this command before every WebDriver action.
Ref: https://angular.github.io/protractor/#/api?view=Protractor.prototype.waitForAngular
@shankscript
That's great. Thanks a lot.
And I think add
jasmineNodeOpts: {defaultTimeoutInterval: 60000},
is neccessary too.
This is obsolete now, thanks @shankscript for the good docs!
Most helpful comment
I hope you all would have figured out by now :) If not try: browser.waitForAngular
This Instructs webdriver to wait until Angular has finished rendering and has no outstanding $http or $timeout calls before continuing. Note that Protractor automatically applies this command before every WebDriver action.
Ref: https://angular.github.io/protractor/#/api?view=Protractor.prototype.waitForAngular