From 562f5f0583a785d12b11e785485ad7ca44090bf7 Mon Sep 17 00:00:00 2001 From: Shane Tomlinson <stomlinson@mozilla.com> Date: Wed, 28 Dec 2011 16:27:36 +0000 Subject: [PATCH] Starting a set_password controller. * Not actually hooked up in the dialog yet. * Need backend support. --- .../static/dialog/controllers/add_email.js | 2 +- .../static/dialog/controllers/email_chosen.js | 2 +- resources/static/dialog/controllers/page.js | 4 +- .../static/dialog/controllers/pick_email.js | 2 +- .../dialog/controllers/required_email.js | 2 +- .../static/dialog/controllers/set_password.js | 95 ++++++++++++ .../static/dialog/views/set_password.ejs | 40 +++++ resources/static/shared/error-messages.js | 4 + resources/static/shared/network.js | 18 ++- resources/static/test/index.html | 2 + .../controllers/set_password_unit_test.js | 137 ++++++++++++++++++ resources/static/test/qunit/mocks/xhr.js | 3 + .../test/qunit/shared/network_unit_test.js | 32 ++-- .../static/test/qunit/testHelpers/helpers.js | 5 + resources/views/dialog_layout.ejs | 1 + resources/views/verifyuser.ejs | 2 +- scripts/compress.sh | 2 +- 17 files changed, 319 insertions(+), 34 deletions(-) create mode 100644 resources/static/dialog/controllers/set_password.js create mode 100644 resources/static/dialog/views/set_password.ejs create mode 100644 resources/static/test/qunit/controllers/set_password_unit_test.js diff --git a/resources/static/dialog/controllers/add_email.js b/resources/static/dialog/controllers/add_email.js index da7755705..f4b1b3c1b 100644 --- a/resources/static/dialog/controllers/add_email.js +++ b/resources/static/dialog/controllers/add_email.js @@ -1,4 +1,4 @@ -/*jshint brgwser:true, jQuery: true, forin: true, laxbreak:true */ +/*jshint browser:true, jQuery: true, forin: true, laxbreak:true */ /*global _: true, BrowserID: true, PageController: true */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 diff --git a/resources/static/dialog/controllers/email_chosen.js b/resources/static/dialog/controllers/email_chosen.js index 1042d1eef..0eed93025 100644 --- a/resources/static/dialog/controllers/email_chosen.js +++ b/resources/static/dialog/controllers/email_chosen.js @@ -1,4 +1,4 @@ -/*jshint brgwser:true, jQuery: true, forin: true, laxbreak:true */ +/*jshint browser:true, jQuery: true, forin: true, laxbreak:true */ /*global _: true, BrowserID: true, PageController: true */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 diff --git a/resources/static/dialog/controllers/page.js b/resources/static/dialog/controllers/page.js index e0dceb821..8f29623cd 100644 --- a/resources/static/dialog/controllers/page.js +++ b/resources/static/dialog/controllers/page.js @@ -129,7 +129,9 @@ BrowserID.Modules.PageModule = (function() { bid.ErrorDisplay.start(); - $("#error").stop().css('opacity', 1).hide().fadeIn(ANIMATION_TIME, oncomplete); + $("#error").stop().css('opacity', 1).hide().fadeIn(ANIMATION_TIME, function() { + if(oncomplete) oncomplete(false); + }); }, validate: function() { diff --git a/resources/static/dialog/controllers/pick_email.js b/resources/static/dialog/controllers/pick_email.js index 55b678918..2d88fefee 100644 --- a/resources/static/dialog/controllers/pick_email.js +++ b/resources/static/dialog/controllers/pick_email.js @@ -1,4 +1,4 @@ -/*jshint brgwser:true, jQuery: true, forin: true, laxbreak:true */ +/*jshint browser:true, jQuery: true, forin: true, laxbreak:true */ /*global _: true, BrowserID: true, PageController: true */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 diff --git a/resources/static/dialog/controllers/required_email.js b/resources/static/dialog/controllers/required_email.js index a027061cb..b7754ca18 100644 --- a/resources/static/dialog/controllers/required_email.js +++ b/resources/static/dialog/controllers/required_email.js @@ -1,4 +1,4 @@ -/*jshint brgwser:true, jQuery: true, forin: true, laxbreak:true */ +/*jshint browser:true, jQuery: true, forin: true, laxbreak:true */ /*global _: true, BrowserID: true, PageController: true */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 diff --git a/resources/static/dialog/controllers/set_password.js b/resources/static/dialog/controllers/set_password.js new file mode 100644 index 000000000..cd84ddd44 --- /dev/null +++ b/resources/static/dialog/controllers/set_password.js @@ -0,0 +1,95 @@ +/*jshint browser:true, jQuery: true, forin: true, laxbreak:true */ +/*global _: true, BrowserID: true, PageController: true */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla BrowserID. + * + * The Initial Developer of the Original Code is Mozilla. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +BrowserID.Modules.SetPassword = (function() { + "use strict"; + + var bid = BrowserID, + user = bid.User, + errors = bid.Errors, + helpers = bid.Helpers, + dom = bid.DOM, + sc; + + + function setPassword(oncomplete) { + function complete(status) { + if(oncomplete) oncomplete(status); + } + + var self = this, + pass = dom.getInner("#password"), + vpass = dom.getInner("#vpassword"), + valid = bid.Validation.passwordAndValidationPassword(pass, vpass); + + if(valid) { + user.setPassword( + pass, + function(status) { + self.publish("password_set"); + complete(true); + }, + self.getErrorDialog(errors.setPassword, complete) + ); + } + else { + complete(false); + } + } + + var Module = bid.Modules.PageModule.extend({ + start: function(options) { + var self=this; + sc.start.call(self, options); + + self.renderDialog("set_password", options); + }, + + submit: setPassword + + // BEGIN TESTING API + , + + setPassword: setPassword + // END TESTING API + }); + + sc = Module.sc; + + return Module; + +}()); + diff --git a/resources/static/dialog/views/set_password.ejs b/resources/static/dialog/views/set_password.ejs new file mode 100644 index 000000000..75572ed6c --- /dev/null +++ b/resources/static/dialog/views/set_password.ejs @@ -0,0 +1,40 @@ + <strong> + Sign in using + </strong> + + <div class="form_section" id="set_password"> + <ul class="inputs"> + <li> + <label for="password" class="serif">Password</label> + <input class="sans" id="password" placeholder="Enter a Password" type="password" autofocus maxlength=80> + + <div class="tooltip" id="password_required" for="password"> + Password is required. + </div> + + <div class="tooltip" id="password_too_short" for="password"> + Password must be at least 8 characters long. + </div> + <li> + + <li> + <label for="vpassword" class="serif">Verify Password</label> + <input class="sans" id="vpassword" placeholder="Repeat Password" type="password" maxlength=80> + + <div class="tooltip" id="vpassword_required" for="vpassword"> + Verification password is required. + </div> + + <div class="tooltip" id="passwords_no_match" for="vpassword"> + Passwords do not match. + </div> + <li> + + + </ul> + + <div class="submit cf"> + <button tabindex="1">Reset Password</button> + <!--button id="cancel_set_password" tabindex="2">Cancel</button--> + </div> + </div> diff --git a/resources/static/shared/error-messages.js b/resources/static/shared/error-messages.js index 894f84ec5..9f9622051 100644 --- a/resources/static/shared/error-messages.js +++ b/resources/static/shared/error-messages.js @@ -126,6 +126,10 @@ BrowserID.Errors = (function(){ title: "Remove Email Address from Account" }, + setPassword: { + title: "Setting Password" + }, + signIn: { title: "Signin Failed" }, diff --git a/resources/static/shared/network.js b/resources/static/shared/network.js index 847f487a9..23b707986 100644 --- a/resources/static/shared/network.js +++ b/resources/static/shared/network.js @@ -387,15 +387,23 @@ BrowserID.Network = (function() { }, /** - * Update the password of the current user. This is for a password reseT - * @method resetPassword + * Set the password of the current user. + * @method setPassword * @param {string} password - new password. * @param {function} [onComplete] - Callback to call when complete. * @param {function} [onFailure] - Called on XHR failure. */ - resetPassword: function(password, onComplete, onFailure) { - // XXX fill this in. - if (onComplete) onComplete(); + setPassword: function(password, onComplete, onFailure) { + post({ + url: "/wsapi/set_password", + data: { + password: password + }, + success: function(status) { + if (onComplete) onComplete(status.success); + }, + error: onFailure + }); }, /** diff --git a/resources/static/test/index.html b/resources/static/test/index.html index d5c1e0a22..bc796b39b 100644 --- a/resources/static/test/index.html +++ b/resources/static/test/index.html @@ -132,6 +132,7 @@ <script type="text/javascript" src="/dialog/controllers/email_chosen.js"></script> <script type="text/javascript" src="/dialog/controllers/provision_primary_user.js"></script> <script type="text/javascript" src="/dialog/controllers/primary_user_provisioned.js"></script> + <script type="text/javascript" src="/dialog/controllers/set_password.js"></script> <script type="text/javascript" src="/pages/page_helpers.js"></script> <script type="text/javascript" src="/pages/add_email_address.js"></script> @@ -182,6 +183,7 @@ <script type="text/javascript" src="qunit/controllers/email_chosen_unit_test.js"></script> <script type="text/javascript" src="qunit/controllers/provision_primary_user_unit_test.js"></script> <script type="text/javascript" src="qunit/controllers/primary_user_provisioned_unit_test.js"></script> + <script type="text/javascript" src="qunit/controllers/set_password_unit_test.js"></script> <!-- must go last or all other tests will fail. --> <script type="text/javascript" src="qunit/controllers/dialog_unit_test.js"></script> diff --git a/resources/static/test/qunit/controllers/set_password_unit_test.js b/resources/static/test/qunit/controllers/set_password_unit_test.js new file mode 100644 index 000000000..e58f84bee --- /dev/null +++ b/resources/static/test/qunit/controllers/set_password_unit_test.js @@ -0,0 +1,137 @@ +/*jshint browsers:true, forin: true, laxbreak: true */ +/*global test: true, start: true, stop: true, module: true, ok: true, equal: true, BrowserID:true */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla BrowserID. + * + * The Initial Developer of the Original Code is Mozilla. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +(function() { + "use strict"; + + var controller, + bid = BrowserID, + storage = bid.Storage, + testHelpers = bid.TestHelpers, + xhr = bid.Mocks.xhr, + register = bid.TestHelpers.register; + + module("controllers/set_password", { + setup: function() { + testHelpers.setup(); + createController(); + $("#password").val(""); + $("#vpassword").val(""); + }, + + teardown: function() { + if (controller) { + try { + controller.destroy(); + controller = null; + } catch(e) { + // could already be destroyed from the close + } + } + testHelpers.setup(); + } + }); + + + function createController(options) { + controller = bid.Modules.SetPassword.create(); + controller.start(options); + } + + function testInvalidInput() { + controller.setPassword(function(status) { + equal(false, status, "status is false"); + testHelpers.testTooltipVisible(); + start(); + }); + } + + test("create displays the correct template", function() { + equal($("#set_password").length, 1, "the correct template is displayed"); + }); + + asyncTest("setPassword with no password", function() { + $("#password").val(""); + $("#vpassword").val("password"); + testInvalidInput(); + }); + + asyncTest("setPassword with no verification password", function() { + $("#password").val("password"); + $("#vpassword").val(""); + testInvalidInput(); + }); + + asyncTest("setPassword with too short of a password", function() { + $("#password").val("pass"); + $("#vpassword").val("pass"); + testInvalidInput(); + }); + + asyncTest("setPassword with mismatched passwords", function() { + $("#password").val("passwords"); + $("#vpassword").val("password"); + testInvalidInput(); + }); + + asyncTest("setPassword with XHR error", function() { + $("#password").val("password"); + $("#vpassword").val("password"); + xhr.useResult("ajaxError"); + + controller.setPassword(function(status) { + equal(status, false, "correct status"); + testHelpers.testErrorVisible(); + start(); + }); + }); + + asyncTest("setPassword happy case", function() { + $("#password").val("password"); + $("#vpassword").val("password"); + + + register("password_set", function(msg, info) { + ok(true, msg + " message received"); + start(); + }); + + controller.setPassword(function(status) { + equal(status, true, "correct status"); + }); + }); +}()); + diff --git a/resources/static/test/qunit/mocks/xhr.js b/resources/static/test/qunit/mocks/xhr.js index c1f50c5db..b6c2cbde8 100644 --- a/resources/static/test/qunit/mocks/xhr.js +++ b/resources/static/test/qunit/mocks/xhr.js @@ -117,6 +117,9 @@ BrowserID.Mocks.xhr = (function() { "get /wsapi/list_emails ajaxError": undefined, // Used in conjunction with registration to do a complete userflow "get /wsapi/list_emails complete": {"registered@testuser.com":{}}, + "post /wsapi/set_password valid": { success: true }, + "post /wsapi/set_password invalid": { success: false }, + "post /wsapi/set_password ajaxError": undefined, "post /wsapi/update_password valid": { success: true }, "post /wsapi/update_password incorrectPassword": { success: false }, "post /wsapi/update_password invalid": undefined, diff --git a/resources/static/test/qunit/shared/network_unit_test.js b/resources/static/test/qunit/shared/network_unit_test.js index c09235b23..ce9edf9b1 100644 --- a/resources/static/test/qunit/shared/network_unit_test.js +++ b/resources/static/test/qunit/shared/network_unit_test.js @@ -587,32 +587,20 @@ failureCheck(network.requestPasswordReset, "address", "origin"); }); - asyncTest("resetPassword", function() { - network.resetPassword("password", function onSuccess() { - // XXX need a test here; - ok(true); - start(); - }, function onFailure() { - ok(false); + asyncTest("setPassword happy case expects true status", function() { + network.setPassword("password", function onComplete(status) { + equal(status, true, "correct status"); start(); - }); - + }, testHelpers.unexpectedXHRFailure); }); - asyncTest("resetPassword with XHR failure", function() { + asyncTest("setPassword with XHR failure", function() { xhr.useResult("ajaxError"); -/* - the body of this function is not yet written - - network.resetPassword("password", function onSuccess() { - ok(false, "XHR failure should never call success"); - start(); - }, function onFailure() { - ok(true, "XHR failure should always call failure"); - start(); - }); -*/ - start(); + network.setPassword( + "password", + testHelpers.unexpectedSuccess, + testHelpers.expectedXHRFailure + ); }); asyncTest("serverTime", function() { diff --git a/resources/static/test/qunit/testHelpers/helpers.js b/resources/static/test/qunit/testHelpers/helpers.js index 3775abd0e..ac78a203c 100644 --- a/resources/static/test/qunit/testHelpers/helpers.js +++ b/resources/static/test/qunit/testHelpers/helpers.js @@ -102,6 +102,11 @@ unexpectedXHRFailure: function() { ok(false, "unexpected XHR failure"); start(); + }, + + testTooltipVisible: function() { + equal(tooltip.shown, true, "tooltip is visible"); } + }; }()); diff --git a/resources/views/dialog_layout.ejs b/resources/views/dialog_layout.ejs index fbfafcfbd..212eb3b0e 100644 --- a/resources/views/dialog_layout.ejs +++ b/resources/views/dialog_layout.ejs @@ -94,6 +94,7 @@ <script type="text/javascript" src="/dialog/controllers/verify_primary_user.js"></script> <script type="text/javascript" src="/dialog/controllers/provision_primary_user.js"></script> <script type="text/javascript" src="/dialog/controllers/primary_user_provisioned.js"></script> + <script type="text/javascript" src="/dialog/controllers/set_password.js"></script> <script type="text/javascript" src="/dialog/controllers/email_chosen.js"></script> <script type="text/javascript" src="/dialog/start.js"></script> <% } %> diff --git a/resources/views/verifyuser.ejs b/resources/views/verifyuser.ejs index 357644f2d..7a54af789 100644 --- a/resources/views/verifyuser.ejs +++ b/resources/views/verifyuser.ejs @@ -37,7 +37,7 @@ </div> <div class="tooltip" id="passwords_no_match" for="vpassword"> - Passwords do not match + Passwords do not match. </div> </li> </ul> diff --git a/scripts/compress.sh b/scripts/compress.sh index d7d5ce845..6c1260f74 100755 --- a/scripts/compress.sh +++ b/scripts/compress.sh @@ -54,7 +54,7 @@ cp templates.js $BUILD_PATH/templates.js cd ../.. # produce the dialog js -cat lib/jquery-1.6.2.min.js lib/winchan.js lib/underscore-min.js lib/vepbundle.js lib/ejs.js shared/browserid.js lib/hub.js lib/dom-jquery.js lib/module.js shared/javascript-extensions.js shared/mediator.js shared/class.js shared/storage.js $BUILD_PATH/templates.js shared/renderer.js shared/error-display.js shared/screens.js shared/tooltip.js shared/validation.js shared/network.js shared/provisioning.js shared/user.js shared/error-messages.js shared/browser-support.js shared/wait-messages.js shared/helpers.js dialog/resources/internal_api.js dialog/resources/helpers.js dialog/resources/state_machine.js dialog/controllers/page.js dialog/controllers/code_check.js dialog/controllers/actions.js dialog/controllers/dialog.js dialog/controllers/authenticate.js dialog/controllers/forgot_password.js dialog/controllers/check_registration.js dialog/controllers/pick_email.js dialog/controllers/add_email.js dialog/controllers/required_email.js dialog/controllers/verify_primary_user.js dialog/controllers/provision_primary_user.js dialog/controllers/primary_user_provisioned.js dialog/controllers/email_chosen.js dialog/start.js > $BUILD_PATH/dialog.uncompressed.js +cat lib/jquery-1.6.2.min.js lib/winchan.js lib/underscore-min.js lib/vepbundle.js lib/ejs.js shared/browserid.js lib/hub.js lib/dom-jquery.js lib/module.js shared/javascript-extensions.js shared/mediator.js shared/class.js shared/storage.js $BUILD_PATH/templates.js shared/renderer.js shared/error-display.js shared/screens.js shared/tooltip.js shared/validation.js shared/network.js shared/provisioning.js shared/user.js shared/error-messages.js shared/browser-support.js shared/wait-messages.js shared/helpers.js dialog/resources/internal_api.js dialog/resources/helpers.js dialog/resources/state_machine.js dialog/controllers/page.js dialog/controllers/code_check.js dialog/controllers/actions.js dialog/controllers/dialog.js dialog/controllers/authenticate.js dialog/controllers/forgot_password.js dialog/controllers/check_registration.js dialog/controllers/pick_email.js dialog/controllers/add_email.js dialog/controllers/required_email.js dialog/controllers/verify_primary_user.js dialog/controllers/provision_primary_user.js dialog/controllers/primary_user_provisioned.js dialog/controllers/set_password.js dialog/controllers/email_chosen.js dialog/start.js > $BUILD_PATH/dialog.uncompressed.js # produce the dialog css cat css/common.css dialog/css/popup.css dialog/css/m.css > $BUILD_PATH/dialog.uncompressed.css -- GitLab