I'm creating a SPA using AngularJs and the ui-router from Angular-UI. Now I'm trying to create the authentication logic.
$rootScope.$on("$stateChangeStart", function (event, toState) {
if(toState.authenticate && !MainService.isAuthenticated()) {
if($cookieStore.get('authToken')) {
MainService.loginWithToken($cookieStore.get('authToken'))
.then(function() {
$state.go(toState.name);
event.preventDefault();
});
}
$rootScope.requestPath = toState.name;
$state.go('public.login');
event.preventDefault();
}
if(toState.url == '/login' && MainService.isAuthenticated()) {
$state.go('private.main');
event.preventDefault();
}
});
On state change, this checks if state requires authentication and transfer to login state if necessary. Also if user is logged in it prevents from reaching the login state. Authentication is done by token stored in cookie.
This is my protractor test scenario:
describe('Routes', function() {
it('Should go to the selected path if user logged in', function() {
browser.get('/');
expect(browser.getLocationAbsUrl()).toMatch("/login");
browser.manage().addCookie("authToken", "aaa");
browser.manage().getCookie("authToken").then(function(cookie) {
expect(cookie.name).toBe('authToken');
expect(cookie.value).toBe('aaa');
});
browser.get('/');
expect(browser.getLocationAbsUrl()).toMatch("/main");
browser.get('/#/main');
expect(browser.getLocationAbsUrl()).toMatch("/main");
/* This part fails, because, when the user is logged in,
he should be transfered to main state, if he is trying to reach the
login page. In this failing case, the user is able to reach the
/login even if he is logged in. */
browser.get('/#/login');
expect(browser.getLocationAbsUrl()).toMatch("/main");
browser.manage().deleteCookie("authToken");
browser.get('/#/login');
expect(browser.getLocationAbsUrl()).toMatch("/login");
browser.get('/#/main');
expect(browser.getLocationAbsUrl()).toMatch("/login");
});
});
When I try to simulate the test behaviour myself, everything is ok, but when I run protractor:
Message:
Expected 'http://localhost/#/login' to match '/main'.
Stacktrace: Error: Failed expectation
I bumped into another question which resolved this issue.
Basically, you wait for an element in the new page to appear instead of relying on protractor to wait for state/page finish loading. At the time of writing this answer, protractor is still unreliable on waiting page fully loaded for ui-router. Protractor waits for $timeout and $http to be done.
official doc
so if you are using websocket, it might not be covered (at least according my observation).
The api you need to use is browser.wait
browser.wait(function() {
return $('#test321').isPresent(); // keeps waiting until this statement resolves to true
},
timeToWaitInMilliseconds,
'message to log to console if element is not present after that time'
);
expect($('#test321').isPresent()).toBe(true);
You can find details in the following link Protractor, AngularJS, Parse -- Protractor does not wait for Angular to resolve
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With