Logging out Logging out involves undoing the effects of the log_in method, which involves deleting the user id from the session.
app/helpers/sessions_helper.js
module . exports = {
log_in : function ( req , user ) {
req . session . user_id = user . id ;
},
current_user : function ( req ) {
return ModelSync ( User . findById ( req . session . user_id ) );
},
log_out : function ( req ) {
delete req . session . user_id ;
}
};
app/controllers/sessions_controller.js
var sessionHelper = require ( '../helpers/sessions_helper.js' );
function SessionsController () {
...
this . destroy = function ( req , res , next ) {
sessionHelper . log_out ( req );
res . end ();
};
...
}
module . exports = SessionsController ;
public/app.js
sampleApp . config ([ '$stateProvider' , '$urlRouterProvider' , function ( $stateProvider , $urlRouterProvider ) {
$urlRouterProvider . otherwise ( '/home' );
$stateProvider
. state ( 'logout' , {
url : '/logout' ,
resolve : {
logout : [ '$state' , 'Sessions' , 'flashHelper' , '$rootScope' , function ( $state , Sessions , flashHelper , $rootScope ){
Sessions . delete ({}, function () {
$rootScope . logged_in = false ;
$rootScope . current_user = null ;
$state . transitionTo ( 'home' , {}, {
reload : true , inherit : false , notify : true
});
}, function ( error ) {
flashHelper . set ({ type : "danger" , content : error . statusText });
$state . transitionTo ( 'home' , {}, {
reload : true , inherit : false , notify : true
});
});
}]
}
})
...
}]);
public/partials/layouts/_header.html
<div class= "container" >
<a href ui-sref= "home" ui-sref-opts= "{reload: true}" id= "logo" > sample app</a>
<nav>
<ul class= "nav navbar-nav navbar-right" >
...
<li ng-if= "logged_in" class= "dropdown" >
<a href class= "dropdown-toggle" data-toggle= "dropdown" >
Account <b class= "caret" ></b>
</a>
<ul class= "dropdown-menu" >
....
<li><a href ui-sref= "logout" ui-sref-opts= "{reload: true}" > Log out</a></li>
</ul>
</li>
<li ng-if= "!logged_in" ><a href ui-sref= "login" ui-sref-opts= "{reload: true}" > Log in</a></li>
</ul>
</nav>
</div>
To test the logout machinery, we can add some steps to the user login test. After logging in, we use delete to issue a DELETE request to the logout path and verify that the user is logged out and redirected to the root URL.
public/test/e2e_test/integration/users_login_test.js
describe ( 'UsersLoginTest' , function () {
it ( 'login with valid information followed by logout' , function () {
var current_url = 'http://localhost:1337/#/login' ;
browser . get ( current_url );
element ( by . css ( '[name="email"]' )). clear ( '' );
element ( by . css ( '[name="password"]' )). clear ( '' );
element ( by . css ( '[name="email"]' )). sendKeys ( '[email protected] ' );
element ( by . css ( '[name="password"]' )). sendKeys ( 'password' );
element ( by . css ( '[name="commit"]' )). click ();
expect ( browser . getCurrentUrl () ). toContain ( '#/users/' );
expect ( element . all ( by . css ( '[ui-sref="login"]' )). count () ). toEqual ( 0 );
expect ( element . all ( by . css ( '[ui-sref="user_detail({id: current_user.id})"]' )). count () ). toEqual ( 1 );
element ( by . css ( '.dropdown' )). click ();
element . all ( by . css ( '[ui-sref="logout"]' )). click ();
expect ( browser . getCurrentUrl () ). toContain ( '#/home' );
expect ( element . all ( by . css ( '[ui-sref="login"]' )). count () ). toEqual ( 1 );
expect ( element . all ( by . css ( '[ui-sref="user_detail({id: current_user.id})"]' )). count () ). toEqual ( 0 );
});
...
});
With the session destroy action thus defined and tested, the initial signup/login/logout triumvirate is complete, and the test suite should be successful
~/sample_app $ protractor protractor.conf.js
Using the selenium server at http://localhost:4444/wd/hub
[ launcher] Running 1 instances of WebDriver
Started
...........
12 specs, 0 failures