I'm setting up protractor for our web app, and all works fine, except one thing: When someone clicks the "login" button, while the HTTP request is running, the button should have class "loading". However, when I try to test this, protractor waits for the HTTP request to finish before it runs the expectation, which then fails, because the loading class is removed again.
How can I assert that the loading class is added?
describe('Authorization', function() {
it('the site loads', () => {
browser.get('/');
expect(browser.getCurrentUrl()).toBe('http://localhost:8000/#/login');
element(by.model('vm.credentials.username')).sendKeys('username');
element(by.model('vm.credentials.password')).sendKeys('password');
element(by.css('#sign-in')).click();
expect(element(by.css('#sign-in')).getAttribute('class')).toMatch(/\bloading\b/);
});
});
I think I found the solution.
The element() function waits for angular to settle in, but browser.driver.findElement() doesn't. So by changing the assertion line to
expect(browser.driver.findElement(by.css('#sign-in')).getAttribute('class')).toMatch(/\bloading\b/);
the tests now pass
As per your problem, protractor is executing your expect statement along with click() function. Protractor is async and fast so it executes everything that it can and then waits for promise/callback to be returned. Try waiting for the click to happen first and then try to assert the class. Here's how you can do it -
element(by.css('#sign-in')).click().then(function(){
expect(element(by.css('#sign-in')).getAttribute('class')).toMatch(/\bloading\b/);
});
Also if the http request is blocking your execution, then try to wait for the element to be displayed. If the element is displayed then it's as good as your element is verified.
browser.wait(protractor.ExpectedConditions.visibilityOf($('.loading')), 10000)
.then(function(){
expect(true).toBe(true);
});
Hope this helps.