Reputation: 43491
I'm using Angular-ui Router not $routeProvider. My controller is:
myApp.controller('LoginController', [
'$scope', '$rootScope', '$state', 'userService', function($scope, $rootScope, $state, userService) {
$scope.init = function() {
$rootScope.pageTitle = 'Login';
$scope.auth = {};
return $scope.errors = null;
};
$scope.login = function() {
return userService.login($scope.auth).then(function(response) {
console.log(response);
if (response.authenticated === true) {
console.log("Movin states!");
return $state.go('dashboard');
} else {
return $scope.errors = {
message: 'Invalid credentials',
type: 'error'
};
}
});
};
return $scope.init();
}
]);
In my test, I'm doing:
it('should properly authenticate a user', function() {
$scope.init();
$scope.auth = {
username: '[email protected]',
password: 'mypassword'
};
$scope.login();
deferred.resolve({
authenticated: true
});
$rootScope.$apply();
expect($state.current.name).toEqual('dashboard');
});
However, the $state.current.name
stays as ''
. Why won't it update?
Upvotes: 0
Views: 1984
Reputation: 48972
Try this plunker:
beforeEach(inject(function($rootScope, $controller, userService,$q,$state) {
$scope = $rootScope.$new();
ctrl = $controller('LoginController', {
$scope: $scope,
$rootScope:$rootScope,
userService:userService,
$state:$state
});
_userService = userService;
_$q = $q;
_$state = $state;
}));
it('should properly authenticate a user', function() {
// $scope.init();
// $scope.auth = {
// username: '[email protected]',
// password: 'mypassword'
// };
//Set up
var deferred = _$q.defer();
spyOn(_userService,"login").and.callFake(function(){//fake the real implementation
//we don't need parameters in our fake function.
//we only care about our return value.
return deferred.promise;
});
spyOn(_$state,"go"); //mock the $state.go method so that we can verify whether it was called.
$scope.login();
deferred.resolve({
authenticated: true
});
$scope.$digest();
expect(_$state.go).toHaveBeenCalledWith('dashboard');//verify
});
Some points to note:
Unit tests should be isolated from each other and from other real implementations. Therefore when you set up a test, the test should not rely on $scope.init();
to set up your test. This implementation may change which may introduce failure to your test inadvertently.
Instead of testing for $state.current.name
, you should test whether $state.go
was called with correct parameters as it's more direct.
Upvotes: 2
Reputation: 2030
You have messed all things in your controller try below things in structured format for a login :
var app = angular.module('app', [...Define dependencies here..]);
//Contant For Login Process
app.constant(
'AUTH_EVENTS', {
loginSuccess: 'auth-login-success',
loginFailed: 'auth-login-failed',
logoutSuccess: 'auth-logout-success',
sessionTimeout: 'auth-session-timeout',
notAuthenticated: 'auth-not-authenticated',
notAuthorized: 'auth-not-authorized'
}
)
//Service to maintain User Session after Login
.service('Session', function () {
this.setSession = function(sessionId, userId, userRole){
this.id = sessionId;
this.userId = userId;
this.userRole = userRole;
};
this.create = function (sessionId, userId, userRole) {
localStorage.setItem("sessionId" , sessionId);
localStorage.setItem("userId" , userId);
localStorage.setItem("userRole" , userRole);
this.setSession(sessionId, userId, userRole);
};
this.destroy = function () {
localStorage.clear();
this.id = null;
this.userId = null;
this.userRole = null;
};
return this;
}
)
//Auth Service Factory for login logic
.factory('AuthService', function ($http, Session) {
return {
login: function (credentials) {
return $http
.post('LOGIN_API_URL_HERE', credentials)
.then(function (res) {
Session.create('1', '1', 'Employee');
});
},
isAuthenticated: function () {
return !!Session.userId;
},
isAuthorized: function (authorizedRoles) {
if (!angular.isArray(authorizedRoles)) {
authorizedRoles = [authorizedRoles];
}
return (this.isAuthenticated() && authorizedRoles.indexOf(Session.userRole) !== -1);
}
};
})
//Controller
.controller('loginController', ['$scope','$location', 'AUTH_EVENTS', 'AuthService', function($scope, $location, AUTH_EVENTS, AuthService){
if (AuthService.isAuthenticated() === false) {
$scope.page_heading = "App";
$scope.credentials = {
username: '',
password: ''
};
$scope.login = function (credentials) {
if(credentials.username != "" && credentials.password != ""){
AuthService.login(credentials).then(function () {
$scope.login_message = AUTH_EVENTS.loginSuccess;
// Path After login
$location.path("/");
}, function () {
$scope.login_message = AUTH_EVENTS.loginFailed;
});
}else{
$scope.login_message = credentials.username == "" ? 'Username Required' : $scope.login_message;
$scope.login_message = credentials.password == "" ? 'Password Required' : $scope.login_message;
$scope.login_message = credentials.username == "" && credentials.password == "" ? 'Username & Password Required' : $scope.login_message;
}
};
}else{
// Path After login
$location.path("/");
}
}]);
Now after login you can check anywhere for session like this
if (localStorage.getItem('sessionId') != "")
// Check for session in localstorage used in case of single time login
Session.setSession(localStorage.getItem('sessionId'),localStorage.getItem('userId'), localStorage.getItem('userRole'));
if (AuthService.isAuthenticated()){
// Redirect to Dashboard
}else{
//Redirect to Login
}
Upvotes: 0