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