diff --git a/resources/static/pages/js/signin.js b/resources/static/pages/js/signin.js index 918be1d87402be93a0feac5be9677fdccee85054..a000e9985cf97fe31e10b1d643ac40ed6057efbb 100644 --- a/resources/static/pages/js/signin.js +++ b/resources/static/pages/js/signin.js @@ -149,6 +149,10 @@ BrowserID.signIn = (function() { self.bind("#email", "change", onEmailChange); self.bind("#email", "keyup", onEmailChange); + // a redirect to the signup page using the link needs to clear the stored + // email address or else the user may be redirected here. + self.bind(".redirect", "click", pageHelpers.clearStoredEmail); + sc.start.call(self, options); // If there is an email already set up in pageHelpers.setupEmail, see if diff --git a/resources/static/pages/js/signup.js b/resources/static/pages/js/signup.js index 1284ebf88418cac8dff4d94fbeeb705a0830f7c4..f1821cc296fe33334fc7a76ab9d8ef591a300152 100644 --- a/resources/static/pages/js/signup.js +++ b/resources/static/pages/js/signup.js @@ -15,10 +15,13 @@ BrowserID.signUp = (function() { validation = bid.Validation, errors = bid.Errors, tooltip = BrowserID.Tooltip, + complete = helpers.complete, ANIMATION_SPEED = 250, storedEmail = pageHelpers, winchan = window.WinChan, + doc = document, primaryUserInfo, + lastEmail, sc; function showNotice(selector) { @@ -28,7 +31,7 @@ BrowserID.signUp = (function() { function authWithPrimary(oncomplete) { pageHelpers.openPrimaryAuth(winchan, primaryUserInfo.email, primaryUserInfo.auth, primaryAuthComplete); - oncomplete && oncomplete(); + complete(oncomplete); } function primaryAuthComplete(error, result, oncomplete) { @@ -42,19 +45,15 @@ BrowserID.signUp = (function() { } function createPrimaryUser(info, oncomplete) { - function complete(status) { - oncomplete && oncomplete(status); - } - user.createPrimaryUser(info, function onComplete(status, info) { switch(status) { case "primary.verified": - pageHelpers.replaceFormWithNotice("#congrats", complete.bind(null, true)); + pageHelpers.replaceFormWithNotice("#congrats", complete.curry(oncomplete, true)); break; case "primary.verify": primaryUserInfo = info; dom.setInner("#primary_email", info.email); - pageHelpers.replaceInputsWithNotice("#primary_verify", complete.bind(null, false)); + pageHelpers.replaceInputsWithNotice("#primary_verify", complete.curry(oncomplete, false)); break; case "primary.could_not_add": // XXX Can this happen? @@ -66,14 +65,17 @@ BrowserID.signUp = (function() { } function enterPasswordState(info) { + /*jshint validthis: true*/ var self=this; self.emailToStage = info.email; self.submit = passwordSubmit; dom.addClass("body", "enter_password"); + dom.focus("#password"); } function passwordSubmit(oncomplete) { + /*jshint validthis: true*/ var pass = dom.getInner("#password"), vpass = dom.getInner("#vpassword"), valid = validation.passwordAndValidationPassword(pass, vpass); @@ -85,44 +87,42 @@ BrowserID.signUp = (function() { } else { tooltip.showTooltip("#could_not_add"); - oncomplete && oncomplete(false); + complete(oncomplete, false); } }, pageHelpers.getFailure(errors.createUser, oncomplete)); } else { - oncomplete && oncomplete(false); + complete(oncomplete, false); } } function emailSubmit(oncomplete) { + /*jshint validthis: true*/ var email = helpers.getAndValidateEmail("#email"), self = this; if (email) { dom.setAttr('#email', 'disabled', 'disabled'); - user.isEmailRegistered(email, function(isRegistered) { - if(isRegistered) { - dom.removeAttr('#email', 'disabled'); - $('#registeredEmail').html(email); - showNotice(".alreadyRegistered"); - oncomplete && oncomplete(false); + user.addressInfo(email, function(info) { + dom.removeAttr('#email', 'disabled'); + + var known = info.known; + + if(info.type === "secondary" && known) { + doc.location = "/signin"; + complete(oncomplete, false); } - else { - user.addressInfo(email, function(info) { - dom.removeAttr('#email', 'disabled'); - if(info.type === "primary") { - createPrimaryUser.call(self, info, oncomplete); - } - else { - enterPasswordState.call(self, info); - oncomplete && oncomplete(!isRegistered); - } - }, pageHelpers.getFailure(errors.addressInfo, oncomplete)); + else if(info.type === "secondary" && !known) { + enterPasswordState.call(self, info); + complete(oncomplete, !known); + } + else if(info.type === "primary") { + createPrimaryUser.call(self, info, oncomplete); } - }, pageHelpers.getFailure(errors.isEmailRegistered, oncomplete)); + }, pageHelpers.getFailure(errors.addressInfo, oncomplete)); } else { - oncomplete && oncomplete(false); + complete(oncomplete, false); } } @@ -130,8 +130,16 @@ BrowserID.signUp = (function() { pageHelpers.cancelEmailSent(oncomplete); } - function onEmailKeyUp(event) { - if (event.which !== 13) $(".notification").fadeOut(ANIMATION_SPEED); + function onEmailChange(event) { + /*jshint validthis: true*/ + + // this is basically a state reset. + var email = dom.getInner("#email"); + if(email !== lastEmail) { + dom.removeClass("body", "enter_password"); + this.submit = emailSubmit; + lastEmail = email; + } } var Module = bid.Modules.PageModule.extend({ @@ -139,19 +147,33 @@ BrowserID.signUp = (function() { var self=this; options = options || {}; - if (options.winchan) { - winchan = options.winchan; - } + if (options.winchan) winchan = options.winchan; + if (options.document) doc = options.document; dom.focus("form input[autofocus]"); pageHelpers.setupEmail(); - self.bind("#email", "keyup", onEmailKeyUp); + self.bind("#email", "keyup", onEmailChange); + self.bind("#email", "change", onEmailChange); self.click("#back", back); self.click("#authWithPrimary", authWithPrimary); + // a redirect to the signin page using the link needs to clear + // the stored email address or else the user may be redirected here. + self.bind(".redirect", "click", pageHelpers.clearStoredEmail); + sc.start.call(self, options); + + // If there is an email already set up in pageHelpers.setupEmail, + // see if the email address is a primary, secondary, known or + // unknown. Redirect if needed. + if (dom.getInner("#email")) { + self.submit(options.ready); + } + else { + complete(options.ready); + } }, submit: emailSubmit, diff --git a/resources/static/test/cases/pages/js/signup.js b/resources/static/test/cases/pages/js/signup.js index 736e1a3b636b7166812c39f8af524fe3f3164b44..1514a22e68615c2115aa0a4147314cf4260d2e72 100644 --- a/resources/static/test/cases/pages/js/signup.js +++ b/resources/static/test/cases/pages/js/signup.js @@ -1,5 +1,5 @@ /*jshint browser: true, forin: true, laxbreak: true */ -/*global test: true, start: true, module: true, ok: true, equal: true, BrowserID:true */ +/*global test: true, start: true, module: true, ok: true, equal: true, BrowserID:true, strictEqual */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -11,22 +11,38 @@ network = bid.Network, xhr = bid.Mocks.xhr, WinChanMock = bid.Mocks.WinChan, + WindowMock = bid.Mocks.WindowMock, testHelpers = bid.TestHelpers, + testDocumentRedirected = testHelpers.testDocumentRedirected, + testDocumentNotRedirected = testHelpers.testDocumentNotRedirected, + testHasClass = testHelpers.testHasClass, + pageHelpers = bid.PageHelpers, provisioning = bid.Mocks.Provisioning, winchan, + docMock, controller; + function createController(options) { + winchan = new WinChanMock(); + docMock = new WindowMock().document; + + options = options || {}; + _.extend(options, { + document: docMock, + winchan: winchan + }); + + controller = bid.signUp.create(); + controller.start(options); + } + module("pages/js/signup", { setup: function() { testHelpers.setup(); bid.Renderer.render("#page_head", "site/signup", {}); $(".emailsent").hide(); - $(".notification").hide() - winchan = new WinChanMock(); - controller = bid.signUp.create(); - controller.start({ - winchan: winchan - }); + $(".notification").hide(); + createController(); }, teardown: function() { testHelpers.teardown(); @@ -45,11 +61,59 @@ }); } + asyncTest("start with no email stored - nothing fancy", function() { + createController({ + ready: function() { + testDocumentNotRedirected(docMock, "user not signed in"); + start(); + } + }); + }); + + asyncTest("start with unknown secondary email stored - show password fields", function() { + xhr.useResult("unknown_secondary"); + pageHelpers.setStoredEmail("unregistered@testuser.com"); + createController({ + ready: function() { + start(); + testHasClass("body", "enter_password", "enter_password class added to body"); + testDocumentNotRedirected(docMock); + } + }); + }); + + asyncTest("start with known secondary email stored - redirect to /signin", function() { + xhr.useResult("known_secondary"); + pageHelpers.setStoredEmail("registered@testuser.com"); + createController({ + ready: function() { + testDocumentRedirected(docMock, "/signin", "user sent to /signin page"); + start(); + } + }); + }); + + /* + asyncTest("start with known primary email stored - show verify primary", function() { + xhr.useResult("primary"); + provisioning.setStatus(provisioning.NOT_AUTHENTICATED); + pageHelpers.setStoredEmail("registered@testuser.com"); + + createController({ + ready: function() { + testHasClass("body", "verify_primary", "verify_primary class added to body"); + + testDocumentNotRedirected(docMock); + start(); + } + }); + }); +*/ asyncTest("signup with valid unregistered secondary email - show password", function() { $("#email").val("unregistered@testuser.com"); controller.submit(function() { - equal($("body").hasClass("enter_password"), true, "new email, password section shown"); + testHasClass("body", "enter_password", "new email, password section shown"); start(); }); @@ -60,7 +124,7 @@ $("#email").val(" unregistered@testuser.com "); controller.submit(function() { - equal($("body").hasClass("enter_password"), true, "new email, password section shown"); + testHasClass("body", "enter_password", "new email, password section shown"); start(); }); }); @@ -146,6 +210,7 @@ asyncTest("signup with primary email address, user must verify with primary", function() { xhr.useResult("primary"); + provisioning.setStatus(provisioning.NOT_AUTHENTICATED); $("#email").val("unregistered@testuser.com"); controller.submit(function(status) { diff --git a/resources/views/signin.ejs b/resources/views/signin.ejs index 1db91fa2c5c7024c205c0cd5f7abdd54d20d0ef1..ea4e9f6b889d785e2af193866e9a24a94a5bcbaa 100644 --- a/resources/views/signin.ejs +++ b/resources/views/signin.ejs @@ -43,7 +43,7 @@ <div class="submit cf forminputs"> <button tabindex="5"><%- gettext('Sign In') %></button> <div class="remember cf"> - <a class="action" href="/signup"><%- gettext('New to Persona? Sign up today.') %></a> + <a class="action redirect" href="/signup"><%- gettext('New to Persona? Sign up today.') %></a> </div> </div> diff --git a/resources/views/signup.ejs b/resources/views/signup.ejs index 7019371f5eca286d60f36768b0cdd090a5091738..b1d5d09db5485ef67e44ad1b1934d67a59810668 100644 --- a/resources/views/signup.ejs +++ b/resources/views/signup.ejs @@ -77,7 +77,7 @@ <div class="submit cf forminputs"> <p class="cf"> <button><%- gettext('Verify Email') %></button> - <a class="action remember" href="/signin" tabindex="2"><%- gettext('Existing account? Sign in.') %></a> + <a class="action remember redirect" href="/signin" tabindex="2"><%- gettext('Existing account? Sign in.') %></a> </p> <p class="tospp">