Reputation: 611
I'm starting some tests in my Angular 2 application and in the first test I'm having some problems.
I want to test the login page, so I am trying to fill email. Here is my test code:
describe('login page', function() {
it('should login', function() {
browser.get('http://localhost:3000/#/login');
element(by.css('.form-control.ng-pristine.ng-valid.ng-untouched')).sendKeys('[email protected]');
});
});
My render HTML code is:
<form class="login-form mt-lg ng-pristine ng-valid ng-touched">
<!--template bindings={}-->
<!--template bindings={}-->
<div class="form-group">
<input class="form-control ng-pristine ng-valid ng-touched" name="email" placeholder="E-mail" type="email">
</div>
<div class="form-group">
<input class="form-control ng-untouched ng-pristine ng-valid" name="password" placeholder="Password" type="password">
</div>
<div class="clearfix">
<div class="btn-toolbar float-xs-right m-t-1">
<button class="btn btn-primary btn-sm" type="submit">Log in</button>
</div>
<div class="float-xs-left m-t-1">
<a class="mt help-block">Forgot your password?</a>
</div>
</div>
</form>
The "original" HTML code is:
<form class="login-form mt-lg" (ngSubmit)="login($event)">
<div *ngIf="error" class="alert alert-danger">{{error}}</div>
<div *ngIf="info" class="alert alert-info">{{info}}</div>
<div class="form-group">
<input type="email" class="form-control" name="email" placeholder="E-mail" [(ngModel)]="user.email" #email="ngModel">
</div>
<div class="form-group">
<input class="form-control" name="password" type="password" placeholder="Senha" [(ngModel)]="user.password" #password="ngModel">
</div>
<div class="clearfix">
<div class="btn-toolbar float-xs-right m-t-1">
<button [disabled]="loading" class="btn btn-primary btn-sm" type="submit">Entrar</button>
</div>
<div class="float-xs-left m-t-1">
<a class="mt help-block" (click)="modal.show()">Esqueceu sua senha?</a>
</div>
</div>
</form>
When I execute the test the browser opens, the page fully loads but then it times out:
Failed: Timed out waiting for asynchronous Angular tasks to finish after 11 seconds. This may be because the current page is not an Angular application. Please see the FAQ for more details: https://github.com/angular/protractor/blob/master/docs/timeouts.md#waiting-for-angular
While waiting for element with locator - Locator: By(css selector, .form-control.ng-pristine.ng-valid.ng-untouched)
If I search for this selector in Chrome console it returns the expected element:
document.querySelector('.form-control.ng-pristine.ng-valid.ng-untouched')
The problem is when the browser opens I can see the page fully loaded and the input is there! And after 11 seconds (or so) the browser closes with the error message. I also tryed to increase timeout on configuration file:
allScriptsTimeout: 50000
But it still does not identify the element:
Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
Upvotes: 4
Views: 4913
Reputation: 1048
browser.ignoreSynchronization
is deprecated.
Use...
describe('login page', function() {
it('should login', function() {
browser.waitForAngularEnabled();
browser.get('http://localhost:3000/#/login');
element(by.css('.form-control.ng-pristine.ng-valid.ng-untouched')).sendKeys('[email protected]');
});
});
Upvotes: 1
Reputation: 2004
In our case the problem was in a super-long timeout. We had an autologout feature implemented with 16 hour timeout. Protractor calls waitForAngular
function every time we execute any action. waitForAngular
is waiting for two things: the unfinished http-requests and the unfinished timeouts. Check your code for those.
Upvotes: 1
Reputation: 31
browser.get
returns a promise so to make sure DOM is loaded before selecting your element, you could do it like this :
browser.get(MY_URL).then(() => {
// Your instructions to select and tests DOM elements
});
Upvotes: 0
Reputation: 1485
browser.ignoreSynchronization = true;
The above code makes protractor not to wait for Angular promises. This will be used when we test non-angular web pages.
Here in your issue, you can just set or increase the getPageTimeout value in jasmineNodeOptions.
getPageTimeout: 50000
Upvotes: 1
Reputation: 611
I think I figured it out. For some reason in Chrome console network tab there is a websocket request as "Pending" so apparently Pratractor keeps waiting this request to finish. This request has 101 HTTP status, I really don't know what it means but after a quick search I learned that it is suposed to be marked as "Pending" in Chrome console.
To solve this issue I prevent syncronization:
browser.ignoreSynchronization = true;
And defined a timeout in configuration file:
allScriptsTimeout: 50000
And it worked!
Here is how the final code was:
describe('login page', function() {
it('should login', function() {
browser.ignoreSynchronization = true;
browser.get('http://localhost:3000/#/login');
element(by.css('.form-control.ng-pristine.ng-valid.ng-untouched')).sendKeys('[email protected]');
});
});
If someone knows a better solution or how to avoid this "websocket" request please let me know.
Upvotes: 11
Reputation: 41581
The timeout occured because you have two elements with same classes so include the index as below
element(by.css('.form-control.ng-pristine.ng-valid.ng-untouched')[0]).sendKeys('[email protected]');
Update 1:
Try this
element(by.css('input[name=email]')).setAttribute('value','[email protected]').then((value: string) => {
expect(value).toBe('[email protected]');
});
Update 2 :
element(by.css('input[name=email]')).setAttribute('value','[email protected]').then((value: string) => {
expect(value).toBe('[email protected]');
});
browser.wait(ExpectedConditions.not(
ExpectedConditions.presenceOf(element(by.css('input[name=email]')))))
.then(() => screenshot('received value '));
});
Upvotes: 1
Reputation: 9010
why don't you try to select element by name instead?
element(by.name('email')).sendKeys("[email protected]");
element(by.name('password')).sendKeys("mypassword");
Upvotes: 1