Taking another look at our Mozilla Persona spike, we need something like this:
var loggedInUser = '{{ user.email }}' || null;
var csrf_token = '{{ csrf_token }}';
console.log(loggedInUser);
navigator.id.watch({
loggedInUser: loggedInUser, //(1)
onlogin: function(assertion) {
$.post('/accounts/login', {assertion: assertion, csrfmiddlewaretoken: csrf_token}) //(2)
.done(function() { window.location.reload(); })
.fail(function() { navigator.id.logout();});
},
onlogout: function() {
$.post('/accounts/logout')
.always(function() { window.location.reload(); });
}
});
Decoding that, the watch function needs to know a couple of things from the global scope:
-
the current user’s email, to be passed in as the
loggedInUser
parameter to watch -
the current CSRF token, to pass in the Ajax POST request to the login view
We’ve also got two hard-coded URLs in there, which it would be better to get from Django, something like this:
var urls = { login: "{% url 'login' %}", logout: "{% url 'logout' %}", };
So that would be a third parameter to pass in from the global scope. We’ve already got an initialize function, so let’s imagine using it like this:
Superlists.Accounts.initialize(navigator, loggedInUser, urls);
So how would we re-write all this, in a TDD way, with unit tests first? What will the unit tests be like? Mock central!
test("initialize calls navigator.id.watch", function () { var loggedInUser = 'current user'; var urls = { login: 'login url', logout: 'logout url'}; var watchFunctionCalled = false; var mockWatchFunction = function (params) { equal(params.loggedInUser, loggedInUser, 'wrong user'); equal(params.onlogin, Superlists.Accounts.onLogin, 'wrong onlogin function'); equal(params.onlogout, Superlists.Accounts.onLogout, 'wrong onlogout function'); }; var mockNavigator = { id: { watch: mockWatchFunction } }; Superlists.Accounts.initialize(mockNavigator, loggedInUser, urls); equal(watchFunctionCalled, true, 'never called watch function'); });