From 77c7f445707eab90f22640077834d38daace77d7 Mon Sep 17 00:00:00 2001 From: Shane Tomlinson <stomlinson@mozilla.com> Date: Sun, 20 Nov 2011 21:58:45 +0000 Subject: [PATCH] JavascriptMVC is now removed as a dependency. * StealJS is still the script loader. * Putting OpenAjax.hub into lib. * Adding a Class/SubClass mechanism. * Converting all controllers to be Subclassed from Modules.PageModule. * All Modules are registered first, then created/started on demand.\ --- .../{addemail_controller.js => addemail.js} | 8 +- ...enticate_controller.js => authenticate.js} | 8 +- ...ion_controller.js => checkregistration.js} | 8 +- .../{dialog_controller.js => dialog.js} | 48 +++-- ...ssword_controller.js => forgotpassword.js} | 8 +- .../{page_controller.js => page.js} | 21 +- .../{pickemail_controller.js => pickemail.js} | 14 +- ..._email_controller.js => required_email.js} | 8 +- resources/static/dialog/dialog.js | 51 +++-- resources/static/lib/module.js | 4 +- resources/static/lib/openajax.js | 201 ++++++++++++++++++ resources/static/shared/class.js | 56 +++++ resources/static/shared/mediator.js | 46 ++++ ...ler_unit_test.js => addemail_unit_test.js} | 23 +- ...unit_test.js => authenticate_unit_test.js} | 15 +- ...test.js => checkregistration_unit_test.js} | 20 +- ...oller_unit_test.js => dialog_unit_test.js} | 24 +-- ...it_test.js => forgotpassword_unit_test.js} | 12 +- ...troller_unit_test.js => page_unit_test.js} | 55 +++-- ...er_unit_test.js => pickemail_unit_test.js} | 10 +- ...it_test.js => required_email_unit_test.js} | 58 ++--- .../test/qunit/shared/class_unit_test.js | 134 ++++++++++++ 22 files changed, 669 insertions(+), 163 deletions(-) rename resources/static/dialog/controllers/{addemail_controller.js => addemail.js} (94%) rename resources/static/dialog/controllers/{authenticate_controller.js => authenticate.js} (96%) rename resources/static/dialog/controllers/{checkregistration_controller.js => checkregistration.js} (93%) rename resources/static/dialog/controllers/{dialog_controller.js => dialog.js} (90%) rename resources/static/dialog/controllers/{forgotpassword_controller.js => forgotpassword.js} (93%) rename resources/static/dialog/controllers/{page_controller.js => page.js} (93%) rename resources/static/dialog/controllers/{pickemail_controller.js => pickemail.js} (92%) rename resources/static/dialog/controllers/{required_email_controller.js => required_email.js} (97%) create mode 100644 resources/static/lib/openajax.js create mode 100644 resources/static/shared/class.js create mode 100644 resources/static/shared/mediator.js rename resources/static/test/qunit/controllers/{addemail_controller_unit_test.js => addemail_unit_test.js} (91%) rename resources/static/test/qunit/controllers/{authenticate_controller_unit_test.js => authenticate_unit_test.js} (95%) rename resources/static/test/qunit/controllers/{checkregistration_controller_unit_test.js => checkregistration_unit_test.js} (88%) rename resources/static/test/qunit/controllers/{dialog_controller_unit_test.js => dialog_unit_test.js} (92%) rename resources/static/test/qunit/controllers/{forgotpassword_controller_unit_test.js => forgotpassword_unit_test.js} (92%) rename resources/static/test/qunit/controllers/{page_controller_unit_test.js => page_unit_test.js} (89%) rename resources/static/test/qunit/controllers/{pickemail_controller_unit_test.js => pickemail_unit_test.js} (97%) rename resources/static/test/qunit/controllers/{required_email_controller_unit_test.js => required_email_unit_test.js} (91%) create mode 100644 resources/static/test/qunit/shared/class_unit_test.js diff --git a/resources/static/dialog/controllers/addemail_controller.js b/resources/static/dialog/controllers/addemail.js similarity index 94% rename from resources/static/dialog/controllers/addemail_controller.js rename to resources/static/dialog/controllers/addemail.js index 12b37b9e5..8ebdd41e2 100644 --- a/resources/static/dialog/controllers/addemail_controller.js +++ b/resources/static/dialog/controllers/addemail.js @@ -34,7 +34,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -(function() { +BrowserID.Modules.AddEmail = (function() { "use strict"; var bid = BrowserID, @@ -66,18 +66,20 @@ this.close("cancel_add_email"); } - PageController.extend("Addemail", {}, { + var AddEmail = bid.Modules.PageModule.extend({ start: function(options) { var self=this; self.renderDialog("addemail"); self.bind("#cancelNewEmail", "click", cancelAddEmail); - self._super(); + AddEmail.sc.start.call(self, options); }, submit: addEmail, addEmail: addEmail, cancelAddEmail: cancelAddEmail }); + return AddEmail; + }()); diff --git a/resources/static/dialog/controllers/authenticate_controller.js b/resources/static/dialog/controllers/authenticate.js similarity index 96% rename from resources/static/dialog/controllers/authenticate_controller.js rename to resources/static/dialog/controllers/authenticate.js index 31e8a1145..970a9a71f 100644 --- a/resources/static/dialog/controllers/authenticate_controller.js +++ b/resources/static/dialog/controllers/authenticate.js @@ -34,7 +34,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -(function() { +BrowserID.Modules.Authenticate = (function() { "use strict"; var ANIMATION_TIME = 250, @@ -155,7 +155,7 @@ } } - PageController.extend("Authenticate", {}, { + var Authenticate = bid.Modules.PageModule.extend({ start: function(options) { var self=this; self.renderDialog("authenticate", { @@ -172,7 +172,7 @@ self.bind("#email", "keyup", emailKeyUp); self.bind("#forgotPassword", "click", forgotPassword); - self._super(); + Authenticate.sc.start.call(self, options); }, checkEmail: checkEmail, @@ -181,4 +181,6 @@ forgotPassword: forgotPassword }); + return Authenticate; + }()); diff --git a/resources/static/dialog/controllers/checkregistration_controller.js b/resources/static/dialog/controllers/checkregistration.js similarity index 93% rename from resources/static/dialog/controllers/checkregistration_controller.js rename to resources/static/dialog/controllers/checkregistration.js index 78038e683..437f9fc1d 100644 --- a/resources/static/dialog/controllers/checkregistration_controller.js +++ b/resources/static/dialog/controllers/checkregistration.js @@ -34,7 +34,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -(function() { +BrowserID.Modules.CheckRegistration = (function() { "use strict"; var bid = BrowserID, @@ -42,7 +42,7 @@ dom = bid.DOM, errors = bid.Errors; - PageController.extend("Checkregistration", {}, { + var CheckRegistration = bid.Modules.PageModule.extend({ start: function(options) { var self=this; self.renderWait("confirmemail", { @@ -54,7 +54,7 @@ self.bind("#back", "click", self.cancel); - self._super(); + CheckRegistration.sc.start.call(self, options); }, startCheck: function() { @@ -78,6 +78,6 @@ }); - + return CheckRegistration; }()); diff --git a/resources/static/dialog/controllers/dialog_controller.js b/resources/static/dialog/controllers/dialog.js similarity index 90% rename from resources/static/dialog/controllers/dialog_controller.js rename to resources/static/dialog/controllers/dialog.js index 82c2e7688..7c548e0ea 100644 --- a/resources/static/dialog/controllers/dialog_controller.js +++ b/resources/static/dialog/controllers/dialog.js @@ -1,5 +1,5 @@ /*jshint browser:true, jQuery: true, forin: true, laxbreak:true */ -/*global setupChannel:true, BrowserID: true, PageController: true, OpenAjax: true */ +/*global setupChannel:true, BrowserID: true */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -35,11 +35,8 @@ * * ***** END LICENSE BLOCK ***** */ -// -// a JMVC controller for the browserid dialog -// -(function() { +BrowserID.Modules.Dialog = (function() { "use strict"; var bid = BrowserID, @@ -49,26 +46,36 @@ offline = false, win = window, subscriptions = [], - hub = OpenAjax.hub; + mediator = bid.Mediator, + serviceManager = bid.module, + runningService; function subscribe(message, cb) { - subscriptions.push(hub.subscribe(message, cb)); + subscriptions.push(mediator.subscribe(message, cb)); + } + + function startService(name, options) { + // Only one service outside of the main dialog allowed. + if(runningService) { + serviceManager.stop(runningService); + } + runningService = name; + return serviceManager.start(name, options); } function createCheckRegistrationController(email, verifier, message) { this.confirmEmail = email; - var controller = this.element.checkregistration({ + var controller = startService("check_registration", { email: email, verifier: verifier, verificationMessage: message - }).controller("checkregistration"); // specify the name of the controller - // or else the dialog controller is returned. + }); controller.startCheck(); } - PageController.extend("Dialog", {}, { - init: function(el, options) { + var Dialog = bid.Modules.PageModule.extend({ + init: function(options) { offline = false; options = options || {}; @@ -80,7 +87,7 @@ var self=this; self.domEvents = []; - self._super(); + Dialog.sc.init.call(self, options); // keep track of where we are and what we do on success and error self.onsuccess = null; @@ -100,10 +107,10 @@ var subscription; while(subscription = subscriptions.pop()) { - hub.unsubscribe(subscription); + mediator.unsubscribe(subscription); } - this._super(); + Dialog.sc.destroy.call(this); }, getVerifiedEmail: function(origin_url, onsuccess, onerror) { @@ -269,7 +276,7 @@ doPickEmail: function() { var self=this; self.returnFromStageCancel = self.doPickEmail.bind(self); - self.element.pickemail({ + startService("pick_email", { // XXX ideal is to get rid of this and have a User function // that takes care of getting email addresses AND the last used email // for this site. @@ -279,7 +286,7 @@ }, doAddEmail: function() { - this.element.addemail({}); + startService("add_email", {}); }, doAuthenticate: function(info) { @@ -288,17 +295,17 @@ // Save this off in case the user forgets their password or goes to add // a new password but has to cancel. self.returnFromStageCancel = self.doAuthenticate.bind(self, info); - self.element.authenticate(info); + startService("authenticate", info); }, doAuthenticateWithRequiredEmail: function(info) { var self=this; self.returnFromStageCancel = self.doAuthenticateWithRequiredEmail.bind(self, info); - self.element.requiredemail(info); + startService("required_email", info); }, doForgotPassword: function(email) { - this.element.forgotpassword({ + startService("forgot_password", { email: email }); }, @@ -355,5 +362,6 @@ }); + return Dialog; }()); diff --git a/resources/static/dialog/controllers/forgotpassword_controller.js b/resources/static/dialog/controllers/forgotpassword.js similarity index 93% rename from resources/static/dialog/controllers/forgotpassword_controller.js rename to resources/static/dialog/controllers/forgotpassword.js index d1bdda2d7..25bb28fef 100644 --- a/resources/static/dialog/controllers/forgotpassword_controller.js +++ b/resources/static/dialog/controllers/forgotpassword.js @@ -34,7 +34,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -(function() { +BrowserID.Modules.ForgotPassword = (function() { "use strict"; var ANIMATION_TIME = 250, @@ -61,7 +61,7 @@ this.close("cancel_forgot_password"); } - PageController.extend("Forgotpassword", {}, { + var ForgotPassword = bid.Modules.PageModule.extend({ start: function(options) { var self=this; self.email = options.email; @@ -71,7 +71,7 @@ self.bind("#cancel_forgot_password", "click", cancelResetPassword); - self._super(); + ForgotPassword.sc.start.call(self, options); }, submit: resetPassword, @@ -79,4 +79,6 @@ cancelResetPassword: cancelResetPassword }); + return ForgotPassword; + }()); diff --git a/resources/static/dialog/controllers/page_controller.js b/resources/static/dialog/controllers/page.js similarity index 93% rename from resources/static/dialog/controllers/page_controller.js rename to resources/static/dialog/controllers/page.js index 0c66dfe58..0aada5d79 100644 --- a/resources/static/dialog/controllers/page_controller.js +++ b/resources/static/dialog/controllers/page.js @@ -34,13 +34,15 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -(function() { +BrowserID.Modules = BrowserID.Modules || {}; +BrowserID.Modules.PageModule = (function() { "use strict"; var ANIMATION_TIME = 250, bid = BrowserID, dom = bid.DOM, - screens = bid.Screens; + screens = bid.Screens, + mediator = bid.Mediator; function onSubmit(event) { event.stopPropagation(); @@ -52,10 +54,8 @@ return false; } - - $.Controller.extend("PageController", { - }, { - init: function(el, options) { + var PageController = BrowserID.Class({ + init: function(options) { options = options || {}; var self=this; @@ -73,8 +73,6 @@ if(options.errorTemplate) { self.renderError(options.errorTemplate, options.errorVars); } - - self.start(options); }, start: function() { @@ -91,7 +89,6 @@ destroy: function() { this.stop(); - this._super(); }, bind: function(target, type, callback, context) { @@ -157,6 +154,10 @@ } }, + publish: function(message, data) { + mediator.publish(message, data); + }, + /** * Get a curried function to an error dialog. * @method getErrorDialog @@ -173,4 +174,6 @@ } }); + return PageController; + }()); diff --git a/resources/static/dialog/controllers/pickemail_controller.js b/resources/static/dialog/controllers/pickemail.js similarity index 92% rename from resources/static/dialog/controllers/pickemail_controller.js rename to resources/static/dialog/controllers/pickemail.js index d7c96093b..bec32eedb 100644 --- a/resources/static/dialog/controllers/pickemail_controller.js +++ b/resources/static/dialog/controllers/pickemail.js @@ -34,7 +34,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -(function() { +BrowserID.Modules.PickEmail = (function() { "use strict"; var ANIMATION_TIME = 250, @@ -55,12 +55,12 @@ cancelEvent(event); var self=this; - if (!self.find("input[type=radio]:checked").length) { + if (!dom.getElements("input[type=radio]:checked").length) { // If none are already checked, select the first one. - self.find('input[type=radio]').eq(0).attr('checked', true); + dom.setAttr('input[type=radio]:eq(0)', 'checked', true); } // focus whichever is checked. - self.find("input[type=radio]:checked").focus(); + dom.focus("input[type=radio]:checked"); self.submit = signIn; } @@ -100,7 +100,7 @@ } } - PageController.extend("Pickemail", {}, { + var PickEmail = bid.Modules.PageModule.extend({ start: function(options) { var origin = user.getOrigin(), self=this; @@ -128,7 +128,7 @@ self.bind("#useNewEmail", "click", addEmail); - self._super(); + PickEmail.sc.start.call(self, options); pickEmailState.call(self); }, @@ -137,4 +137,6 @@ addEmail: addEmail }); + return PickEmail; + }()); diff --git a/resources/static/dialog/controllers/required_email_controller.js b/resources/static/dialog/controllers/required_email.js similarity index 97% rename from resources/static/dialog/controllers/required_email_controller.js rename to resources/static/dialog/controllers/required_email.js index eb49e0c32..f84368eac 100644 --- a/resources/static/dialog/controllers/required_email_controller.js +++ b/resources/static/dialog/controllers/required_email.js @@ -34,7 +34,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -(function() { +BrowserID.Modules.RequiredEmail = (function() { "use strict"; var ANIMATION_TIME = 250, @@ -112,7 +112,7 @@ this.close("cancel"); } - PageController.extend("Requiredemail", {}, { + var RequiredEmail = bid.Modules.PageModule.extend({ start: function(options) { var self=this, email = options.email || "", @@ -153,7 +153,7 @@ self.bind("#cancel", "click", cancel); } - self._super(); + RequiredEmail.sc.start.call(self, options); }, signIn: signIn, @@ -162,4 +162,6 @@ cancel: cancel }); + return RequiredEmail; + }()); diff --git a/resources/static/dialog/dialog.js b/resources/static/dialog/dialog.js index 6bbaaeb03..c0f655bc3 100644 --- a/resources/static/dialog/dialog.js +++ b/resources/static/dialog/dialog.js @@ -39,21 +39,21 @@ window.console = window.console || { log: function() {} }; -steal - .plugins( - 'jquery/controller', // a widget factory - 'jquery/controller/subscribe') // subscribe to OpenAjax.hub - - .resources( 'channel') - .then( +steal.then( + 'resources/channel', + '../lib/jquery-1.6.2.min.js', '../lib/jschannel', '../lib/base64', '../lib/underscore-min', '../lib/vepbundle', '../lib/ejs', '../shared/browserid', + '../lib/openajax', '../lib/dom-jquery', + '../lib/module', + '../shared/mediator', + '../shared/class', '../shared/storage', '../shared/templates', '../shared/renderer', @@ -68,21 +68,34 @@ steal '../shared/browserid-extensions', '../shared/wait-messages', '../shared/helpers', - 'resources/helpers' - ) - .controllers('page', - 'dialog', - 'authenticate', - 'forgotpassword', - 'checkregistration', - 'pickemail', - 'addemail', - 'required_email' + 'resources/helpers', + + 'controllers/page', + 'controllers/dialog', + 'controllers/authenticate', + 'controllers/forgotpassword', + 'controllers/checkregistration', + 'controllers/pickemail', + 'controllers/addemail', + 'controllers/required_email' ) // loads files in controllers folder .then(function() { $(function() { - $('body').dialog().show(); + var bid = BrowserID, + moduleManager = bid.module, + modules = bid.Modules; + + moduleManager.register("dialog", modules.Dialog); + moduleManager.register("add_email", modules.AddEmail); + moduleManager.register("authenticate", modules.Authenticate); + moduleManager.register("check_registration", modules.CheckRegistration); + moduleManager.register("forgot_password", modules.ForgotPassword); + moduleManager.register("pick_email", modules.PickEmail); + moduleManager.register("required_email", modules.RequiredEmail); + + moduleManager.start("dialog"); + }); - }); // adds views to be added to build + }); diff --git a/resources/static/lib/module.js b/resources/static/lib/module.js index e9b06f406..69b0d510c 100644 --- a/resources/static/lib/module.js +++ b/resources/static/lib/module.js @@ -51,14 +51,14 @@ BrowserID.module = (function() { module = new constr(); created[service] = module; - module.init(config); + module.init(config || {}); } else { throw "module not registered for " + service; } } - module.start(data); + module.start(data || {}); running[service] = module; return module; diff --git a/resources/static/lib/openajax.js b/resources/static/lib/openajax.js new file mode 100644 index 000000000..9160f49d2 --- /dev/null +++ b/resources/static/lib/openajax.js @@ -0,0 +1,201 @@ +//@steal-clean +/******************************************************************************* + * OpenAjax.js + * + * Reference implementation of the OpenAjax Hub, as specified by OpenAjax Alliance. + * Specification is under development at: + * + * http://www.openajax.org/member/wiki/OpenAjax_Hub_Specification + * + * Copyright 2006-2008 OpenAjax Alliance + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 . Unless + * required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + ******************************************************************************/ +(function() { + // prevent re-definition of the OpenAjax object + if(!window["OpenAjax"]){ + /** + * @class OpenAjax + * Use OpenAjax.hub to publish and subscribe to messages. + */ + OpenAjax = new function(){ + var t = true; + var f = false; + var g = window; + var ooh = "org.openajax.hub."; + + var h = {}; + this.hub = h; + h.implementer = "http://openajax.org"; + h.implVersion = "1.0"; + h.specVersion = "1.0"; + h.implExtraData = {}; + var libs = {}; + h.libraries = libs; + + h.registerLibrary = function(prefix, nsURL, version, extra){ + libs[prefix] = { + prefix: prefix, + namespaceURI: nsURL, + version: version, + extraData: extra + }; + this.publish(ooh+"registerLibrary", libs[prefix]); + } + h.unregisterLibrary = function(prefix){ + this.publish(ooh+"unregisterLibrary", libs[prefix]); + delete libs[prefix]; + } + + h._subscriptions = { c:{}, s:[] }; + h._cleanup = []; + h._subIndex = 0; + h._pubDepth = 0; + + h.subscribe = function(name, callback, scope, subscriberData, filter) + { + if(!scope){ + scope = window; + } + var handle = name + "." + this._subIndex; + var sub = { scope: scope, cb: callback, fcb: filter, data: subscriberData, sid: this._subIndex++, hdl: handle }; + var path = name.split("."); + this._subscribe(this._subscriptions, path, 0, sub); + return handle; + } + + h.publish = function(name, message) + { + var path = name.split("."); + this._pubDepth++; + this._publish(this._subscriptions, path, 0, name, message); + this._pubDepth--; + if((this._cleanup.length > 0) && (this._pubDepth == 0)) { + for(var i = 0; i < this._cleanup.length; i++) + this.unsubscribe(this._cleanup[i].hdl); + delete(this._cleanup); + this._cleanup = []; + } + } + + h.unsubscribe = function(sub) + { + var path = sub.split("."); + var sid = path.pop(); + this._unsubscribe(this._subscriptions, path, 0, sid); + } + + h._subscribe = function(tree, path, index, sub) + { + var token = path[index]; + if(index == path.length) + tree.s.push(sub); + else { + if(typeof tree.c == "undefined") + tree.c = {}; + if(typeof tree.c[token] == "undefined") { + tree.c[token] = { c: {}, s: [] }; + this._subscribe(tree.c[token], path, index + 1, sub); + } + else + this._subscribe( tree.c[token], path, index + 1, sub); + } + } + + h._publish = function(tree, path, index, name, msg, pcb, pcid) { + if(typeof tree != "undefined") { + var node; + if(index == path.length) { + node = tree; + } else { + this._publish(tree.c[path[index]], path, index + 1, name, msg, pcb, pcid); + this._publish(tree.c["*"], path, index + 1, name, msg, pcb, pcid); + node = tree.c["**"]; + } + if(typeof node != "undefined") { + var callbacks = node.s; + var max = callbacks.length; + for(var i = 0; i < max; i++) { + if(callbacks[i].cb) { + var sc = callbacks[i].scope; + var cb = callbacks[i].cb; + var fcb = callbacks[i].fcb; + var d = callbacks[i].data; + var sid = callbacks[i].sid; + var scid = callbacks[i].cid; + if(typeof cb == "string"){ + // get a function object + cb = sc[cb]; + } + if(typeof fcb == "string"){ + // get a function object + fcb = sc[fcb]; + } + if((!fcb) || (fcb.call(sc, name, msg, d))) { + if((!pcb) || (pcb(name, msg, pcid, scid))) { + cb.call(sc, name, msg, d, sid); + } + } + } + } + } + } + } + + h._unsubscribe = function(tree, path, index, sid) { + if(typeof tree != "undefined") { + if(index < path.length) { + var childNode = tree.c[path[index]]; + this._unsubscribe(childNode, path, index + 1, sid); + if(childNode.s.length == 0) { + for(var x in childNode.c) + return; + delete tree.c[path[index]]; + } + return; + } + else { + var callbacks = tree.s; + var max = callbacks.length; + for(var i = 0; i < max; i++) + if(sid == callbacks[i].sid) { + if(this._pubDepth > 0) { + callbacks[i].cb = null; + this._cleanup.push(callbacks[i]); + } + else + callbacks.splice(i, 1); + return; + } + } + } + } + // The following function is provided for automatic testing purposes. + // It is not expected to be deployed in run-time OpenAjax Hub implementations. + h.reinit = function() + { + for (var lib in OpenAjax.hub.libraries) { + delete OpenAjax.hub.libraries[lib]; + } + OpenAjax.hub.registerLibrary("OpenAjax", "http://openajax.org/hub", "1.0", {}); + + delete OpenAjax._subscriptions; + OpenAjax._subscriptions = {c:{},s:[]}; + delete OpenAjax._cleanup; + OpenAjax._cleanup = []; + OpenAjax._subIndex = 0; + OpenAjax._pubDepth = 0; + } + }; + // Register the OpenAjax Hub itself as a library. + OpenAjax.hub.registerLibrary("OpenAjax", "http://openajax.org/hub", "1.0", {}); + } + +}()); diff --git a/resources/static/shared/class.js b/resources/static/shared/class.js new file mode 100644 index 000000000..2668bf247 --- /dev/null +++ b/resources/static/shared/class.js @@ -0,0 +1,56 @@ + +BrowserID.Class = (function() { + function create(constr, config) { + var inst = new constr; + inst.init(config); + return inst; + } + + function extend(sup, extension) { + // No superclass + if(!extension) { + extension = sup; + sup = null; + } + + var subclass = extension.hasOwnProperty("constructor") ? extension.constructor : function() {}; + + if(sup) { + // there is a superclass, set it up. + // Object.create would work well here. + var F = function() {}; + F.prototype = sup.prototype; + subclass.prototype = new F; + subclass.sc = sup.prototype; + } + else { + // no superclass, create a prototype object. + subclass.prototype = {}; + } + + for(var key in extension) { + subclass.prototype[key] = extension[key]; + } + subclass.prototype.constructor = subclass; + + /** + * Extend a class to create a subclass. + * @method extend + * @param {object} extensions - prototype extensions + * @returns {function} subclass + */ + subclass.extend = extend.bind(null, subclass); + /** + * Create an instance of a class + * @method create + * @param {object} [config] - configuration, passed on to init. + */ + subclass.create = create.bind(null, subclass); + + return subclass; + } + + return extend; + +}()); + diff --git a/resources/static/shared/mediator.js b/resources/static/shared/mediator.js new file mode 100644 index 000000000..33faab020 --- /dev/null +++ b/resources/static/shared/mediator.js @@ -0,0 +1,46 @@ +/*globals 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 ***** */ + +BrowserID.Mediator = (function() { + var hub = OpenAjax.hub; + + return { + subscribe: hub.subscribe.bind(hub), + unsubscribe: hub.unsubscribe.bind(hub), + publish: hub.publish.bind(hub) + }; +}()); + diff --git a/resources/static/test/qunit/controllers/addemail_controller_unit_test.js b/resources/static/test/qunit/controllers/addemail_unit_test.js similarity index 91% rename from resources/static/test/qunit/controllers/addemail_controller_unit_test.js rename to resources/static/test/qunit/controllers/addemail_unit_test.js index 26fb2bc14..38ea061f3 100644 --- a/resources/static/test/qunit/controllers/addemail_controller_unit_test.js +++ b/resources/static/test/qunit/controllers/addemail_unit_test.js @@ -44,18 +44,19 @@ steal.then(function() { user = bid.User, network = bid.Network, xhr = bid.Mocks.xhr, - hub = OpenAjax.hub, + mediator = bid.Mediator, + modules = bid.Modules, testOrigin = "http://browserid.org", registrations = []; function register(message, cb) { - registrations.push(hub.subscribe(message, cb)); + registrations.push(mediator.subscribe(message, cb)); } function unregisterAll() { var registration; while(registration = registrations.pop()) { - hub.unsubscribe(registration); + mediator.unsubscribe(registration); } } @@ -83,18 +84,18 @@ steal.then(function() { } }); - function createController() { - return $("body").addemail({}).controller(); + function createController(options) { + controller = modules.AddEmail.create(options); } test("addemail controller renders correctly", function() { - controller = createController(); + createController(); equal($("#addEmail").length, 1, "control rendered correctly"); }); test("addEmail with valid email", function() { - controller = createController(); + createController(); $("#newEmail").val("unregistered@testuser.com"); register("email_staged", function(msg, info) { @@ -106,7 +107,7 @@ steal.then(function() { }); test("addEmail with valid email with leading/trailing whitespace", function() { - controller = createController(); + createController(); $("#newEmail").val(" unregistered@testuser.com "); register("email_staged", function(msg, info) { @@ -118,7 +119,7 @@ steal.then(function() { }); test("addEmail with invalid email", function() { - controller = createController(); + createController(); $("#newEmail").val("unregistered"); var handlerCalled = false; @@ -136,7 +137,7 @@ steal.then(function() { }); test("addEmail with previously registered email - allows for account consolidation", function() { - controller = createController(); + createController(); $("#newEmail").val("registered@testuser.com"); register("email_staged", function(msg, info) { @@ -148,7 +149,7 @@ steal.then(function() { }); test("cancelAddEmail", function() { - controller = createController(); + createController(); register("cancel_add_email", function(msg, info) { ok(true, "cancelling the add email"); diff --git a/resources/static/test/qunit/controllers/authenticate_controller_unit_test.js b/resources/static/test/qunit/controllers/authenticate_unit_test.js similarity index 95% rename from resources/static/test/qunit/controllers/authenticate_controller_unit_test.js rename to resources/static/test/qunit/controllers/authenticate_unit_test.js index 9039e019a..0090a10f4 100644 --- a/resources/static/test/qunit/controllers/authenticate_controller_unit_test.js +++ b/resources/static/test/qunit/controllers/authenticate_unit_test.js @@ -45,17 +45,17 @@ steal.then(function() { xhr = bid.Mocks.xhr, emailRegistered = false, userCreated = true, - hub = OpenAjax.hub, + mediator = bid.Mediator, registrations = []; function register(message, cb) { - registrations.push(hub.subscribe(message, cb)); + registrations.push(mediator.subscribe(message, cb)); } function unregisterAll() { var registration; while(registration = registrations.pop()) { - hub.unsubscribe(registration); + mediator.unsubscribe(registration); } } @@ -69,13 +69,17 @@ steal.then(function() { userCreated = true; } + function createController(options) { + controller = bid.Modules.Authenticate.create(options); + } + module("controllers/authenticate_controller", { setup: function() { reset(); storage.clear(); network.setXHR(xhr); xhr.useResult("valid"); - controller = el.authenticate().controller(); + createController(); }, teardown: function() { @@ -93,10 +97,11 @@ steal.then(function() { } }); + test("setting email address prefills address field", function() { controller.destroy(); $("#email").val(""); - controller = el.authenticate({ email: "registered@testuser.com" }).controller(); + createController({ email: "registered@testuser.com" }); equal($("#email").val(), "registered@testuser.com", "email prefilled"); }); diff --git a/resources/static/test/qunit/controllers/checkregistration_controller_unit_test.js b/resources/static/test/qunit/controllers/checkregistration_unit_test.js similarity index 88% rename from resources/static/test/qunit/controllers/checkregistration_controller_unit_test.js rename to resources/static/test/qunit/controllers/checkregistration_unit_test.js index ee15db686..199d63703 100644 --- a/resources/static/test/qunit/controllers/checkregistration_controller_unit_test.js +++ b/resources/static/test/qunit/controllers/checkregistration_unit_test.js @@ -34,7 +34,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -steal.plugins("jquery").then("/dialog/controllers/page_controller", "/dialog/controllers/checkregistration_controller", function() { +steal.then(function() { "use strict"; var controller, @@ -42,27 +42,27 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", "/dialog/con bid = BrowserID, xhr = bid.Mocks.xhr, network = bid.Network, - hub = OpenAjax.hub, + mediator = bid.Mediator, listeners = []; function subscribe(message, cb) { - listeners.push(hub.subscribe(message, cb)); + listeners.push(mediator.subscribe(message, cb)); } function unsubscribeAll() { var registration; while(registration = listeners.pop()) { - hub.unsubscribe(registration); + mediator.unsubscribe(registration); } } - function initController(verifier, message) { + function createController(verifier, message) { el = $("body"); - controller = el.checkregistration({ + controller = bid.Modules.CheckRegistration.create({ email: "registered@testuser.com", verifier: verifier, verificationMessage: message - }).controller(); + }); } module("controllers/checkregistration_controller", { @@ -86,7 +86,7 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", "/dialog/con }); function testVerifiedUserEvent(event_name, message) { - initController("waitForUserValidation", event_name); + createController("waitForUserValidation", event_name); subscribe(event_name, function() { ok(true, message); start(); @@ -114,7 +114,7 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", "/dialog/con test("user validation with XHR error", function() { xhr.useResult("ajaxError"); - initController("waitForUserValidation", "user_verified"); + createController("waitForUserValidation", "user_verified"); subscribe("user_verified", function() { ok(false, "on XHR error, should not complete"); }); @@ -129,7 +129,7 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", "/dialog/con }); test("cancel raises cancel_user_verified", function() { - initController("waitForUserValidation", "user_verified"); + createController("waitForUserValidation", "user_verified"); subscribe("cancel_user_verified", function() { ok(true, "on cancel, cancel_user_verified is triggered"); start(); diff --git a/resources/static/test/qunit/controllers/dialog_controller_unit_test.js b/resources/static/test/qunit/controllers/dialog_unit_test.js similarity index 92% rename from resources/static/test/qunit/controllers/dialog_controller_unit_test.js rename to resources/static/test/qunit/controllers/dialog_unit_test.js index a0cf4452d..f8c910f91 100644 --- a/resources/static/test/qunit/controllers/dialog_controller_unit_test.js +++ b/resources/static/test/qunit/controllers/dialog_unit_test.js @@ -34,7 +34,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -steal.plugins("jquery").then("/dialog/controllers/page_controller", "/dialog/controllers/dialog_controller", function() { +steal.then(function() { "use strict"; var controller, @@ -50,7 +50,7 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", "/dialog/con channelError = false; } - function initController(config) { + function createController(config) { var config = $.extend(config, { window: { setupChannel: function() { @@ -59,7 +59,7 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", "/dialog/con } }); - controller = el.dialog(config).controller(); + controller = BrowserID.Modules.Dialog.create(config); } module("controllers/dialog_controller", { @@ -75,20 +75,20 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", "/dialog/con test("initialization with channel error", function() { channelError = true; - initController(); + createController(); ok($("#error .contents").text().length, "contents have been written"); }); test("doOffline", function() { - initController(); + createController(); controller.doOffline(); ok($("#error .contents").text().length, "contents have been written"); ok($("#error #offline").text().length, "offline error message has been written"); }); test("doXHRError while online, no network info given", function() { - initController(); + createController(); controller.doXHRError(); ok($("#error .contents").text().length, "contents have been written"); ok($("#error #action").text().length, "action contents have been written"); @@ -96,7 +96,7 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", "/dialog/con }); test("doXHRError while online, network info given", function() { - initController(); + createController(); controller.doXHRError({ network: { type: "POST", @@ -109,7 +109,7 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", "/dialog/con }); test("doXHRError while offline does not update contents", function() { - initController(); + createController(); controller.doOffline(); $("#error #action").remove(); @@ -120,7 +120,7 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", "/dialog/con /* test("doCheckAuth with registered requiredEmail, authenticated", function() { - initController({ + createController({ requiredEmail: "registered@testuser.com" }); @@ -128,7 +128,7 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", "/dialog/con }); test("doCheckAuth with registered requiredEmail, not authenticated", function() { - initController({ + createController({ requiredEmail: "registered@testuser.com" }); @@ -136,7 +136,7 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", "/dialog/con }); test("doCheckAuth with unregistered requiredEmail, not authenticated", function() { - initController({ + createController({ requiredEmail: "unregistered@testuser.com" }); @@ -144,7 +144,7 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", "/dialog/con }); test("doCheckAuth with unregistered requiredEmail, authenticated as other user", function() { - initController({ + createController({ requiredEmail: "unregistered@testuser.com" }); diff --git a/resources/static/test/qunit/controllers/forgotpassword_controller_unit_test.js b/resources/static/test/qunit/controllers/forgotpassword_unit_test.js similarity index 92% rename from resources/static/test/qunit/controllers/forgotpassword_controller_unit_test.js rename to resources/static/test/qunit/controllers/forgotpassword_unit_test.js index d42e9fa93..66228f6ab 100644 --- a/resources/static/test/qunit/controllers/forgotpassword_controller_unit_test.js +++ b/resources/static/test/qunit/controllers/forgotpassword_unit_test.js @@ -43,17 +43,17 @@ steal.then(function() { storage = bid.Storage, network = bid.Network, xhr = bid.Mocks.xhr, - hub = OpenAjax.hub, + mediator = bid.Mediator, registrations = []; function register(message, cb) { - registrations.push(hub.subscribe(message, cb)); + registrations.push(mediator.subscribe(message, cb)); } function unregisterAll() { var registration; while(registration = registrations.pop()) { - hub.unsubscribe(registration); + mediator.unsubscribe(registration); } } @@ -64,6 +64,10 @@ steal.then(function() { el.find("#error .contents").html(""); } + function createController(options) { + controller = bid.Modules.ForgotPassword.create(options); + } + module("controllers/forgotpassword_controller", { setup: function() { $("#email").val(""); @@ -71,7 +75,7 @@ steal.then(function() { storage.clear(); network.setXHR(xhr); xhr.useResult("valid"); - controller = el.forgotpassword({ email: "registered@testuser.com" }).controller(); + createController({ email: "registered@testuser.com" }); }, teardown: function() { diff --git a/resources/static/test/qunit/controllers/page_controller_unit_test.js b/resources/static/test/qunit/controllers/page_unit_test.js similarity index 89% rename from resources/static/test/qunit/controllers/page_controller_unit_test.js rename to resources/static/test/qunit/controllers/page_unit_test.js index 00a21936d..99295d5b3 100644 --- a/resources/static/test/qunit/controllers/page_controller_unit_test.js +++ b/resources/static/test/qunit/controllers/page_unit_test.js @@ -34,12 +34,15 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -steal.plugins("jquery").then("/dialog/controllers/page_controller", function() { +steal.then(function() { "use strict"; var controller, el, bodyTemplate = "testBodyTemplate", - waitTemplate = "wait"; + waitTemplate = "wait", + bid = BrowserID, + mediator = bid.Mediator, + modules = bid.Modules; function reset() { el = $("#controller_head"); @@ -49,6 +52,10 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", function() { el.find("#error .contents").html(""); } + function createController(options) { + controller = bid.Modules.PageModule.create(options); + } + module("/controllers/page_controller", { setup: function() { reset(); @@ -61,7 +68,7 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", function() { }); test("page controller with no template causes no side effects", function() { - controller = el.page().controller(); + createController(); var html = el.find("#formWrap .contents").html(); equal(html, "", "with no template specified, no text is loaded"); @@ -71,13 +78,13 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", function() { }); test("page controller with body template renders in #formWrap .contents", function() { - controller = el.page({ + createController({ bodyTemplate: bodyTemplate, bodyVars: { title: "Test title", message: "Test message" } - }).controller(); + }); var html = el.find("#formWrap .contents").html(); ok(html.length, "with template specified, form text is loaded"); @@ -92,13 +99,13 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", function() { }); test("page controller with wait template renders in #wait .contents", function() { - controller = el.page({ + createController({ waitTemplate: waitTemplate, waitVars: { title: "Test title", message: "Test message" } - }).controller(); + }); var html = el.find("#formWrap .contents").html(); equal(html, "", "with wait template specified, form is ignored"); @@ -108,13 +115,13 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", function() { }); test("page controller with error template renders in #error .contents", function() { - controller = el.page({ + createController({ errorTemplate: waitTemplate, errorVars: { title: "Test title", message: "Test message" } - }).controller(); + }); var html = el.find("#formWrap .contents").html(); equal(html, "", "with error template specified, form is ignored"); @@ -124,13 +131,13 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", function() { }); test("renderError renders an error message", function() { - controller = el.page({ + createController({ waitTemplate: waitTemplate, waitVars: { title: "Test title", message: "Test message" } - }).controller(); + }); controller.renderError("wait", { title: "error title", @@ -143,13 +150,13 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", function() { }); test("renderError allows us to open expanded error info", function() { - controller = el.page({ + createController({ waitTemplate: waitTemplate, waitVars: { title: "Test title", message: "Test message" } - }).controller(); + }); controller.renderError("error", { action: { @@ -174,13 +181,13 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", function() { }); test("getErrorDialog gets a function that can be used to render an error message", function() { - controller = el.page({ + createController({ waitTemplate: waitTemplate, waitVars: { title: "Test title", message: "Test message" } - }).controller(); + }); // This is the medium level info. var func = controller.getErrorDialog({ @@ -198,7 +205,7 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", function() { }); test("bind DOM Events", function() { - controller = el.page().controller(); + createController(); controller.bind("body", "click", function(event) { event.preventDefault(); @@ -212,7 +219,7 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", function() { }); test("unbindAll removes all listeners", function() { - controller = el.page().controller(); + createController(); var listenerCalled = false; controller.bind("body", "click", function(event) { @@ -232,5 +239,19 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", function() { }, 100); }); + test("publish", function() { + createController(); + + mediator.subscribe("message", function(msg, data) { + equal(msg, "message", "message is correct"); + equal(data.field, 1, "data passed correctly"); + start(); + }); + + controller.publish("message", { + field: 1 + }); + }); + }); diff --git a/resources/static/test/qunit/controllers/pickemail_controller_unit_test.js b/resources/static/test/qunit/controllers/pickemail_unit_test.js similarity index 97% rename from resources/static/test/qunit/controllers/pickemail_controller_unit_test.js rename to resources/static/test/qunit/controllers/pickemail_unit_test.js index 42822c93c..f9e2611b2 100644 --- a/resources/static/test/qunit/controllers/pickemail_controller_unit_test.js +++ b/resources/static/test/qunit/controllers/pickemail_unit_test.js @@ -44,18 +44,18 @@ steal.then(function() { user = bid.User, network = bid.Network, xhr = bid.Mocks.xhr, - hub = OpenAjax.hub, + mediator = bid.Mediator, testOrigin = "http://browserid.org", registrations = []; function register(message, cb) { - registrations.push(hub.subscribe(message, cb)); + registrations.push(mediator.subscribe(message, cb)); } function unregisterAll() { var registration; while(registration = registrations.pop()) { - hub.unsubscribe(registration); + mediator.unsubscribe(registration); } } @@ -93,9 +93,9 @@ steal.then(function() { function createController(allowPersistent) { - controller = el.pickemail({ + controller = bid.Modules.PickEmail.create({ allow_persistent: allowPersistent || false - }).controller(); + }); } test("pickemail controller with email associated with site", function() { diff --git a/resources/static/test/qunit/controllers/required_email_controller_unit_test.js b/resources/static/test/qunit/controllers/required_email_unit_test.js similarity index 91% rename from resources/static/test/qunit/controllers/required_email_controller_unit_test.js rename to resources/static/test/qunit/controllers/required_email_unit_test.js index 8eef389d6..6ff0ee75c 100644 --- a/resources/static/test/qunit/controllers/required_email_controller_unit_test.js +++ b/resources/static/test/qunit/controllers/required_email_unit_test.js @@ -44,18 +44,18 @@ steal.then(function() { user = bid.User, network = bid.Network, storage = bid.Storage, - hub = OpenAjax.hub, + mediator = bid.Mediator, listeners = []; // XXX TODO Share this code with the other tests. function subscribe(message, cb) { - listeners.push(hub.subscribe(message, cb)); + listeners.push(mediator.subscribe(message, cb)); } function unsubscribeAll() { var registration; while(registration = listeners.pop()) { - hub.unsubscribe(registration); + mediator.unsubscribe(registration); } } @@ -86,6 +86,10 @@ steal.then(function() { } }); + function createController(options) { + controller = bid.Modules.RequiredEmail.create(options); + } + function testSignIn(email, cb) { setTimeout(function() { var el = $("#required_email"); @@ -121,20 +125,20 @@ steal.then(function() { test("user who is not authenticated, email is registered", function() { var email = "registered@testuser.com"; - controller = el.requiredemail({ + createController({ email: email, authenticated: false - }).controller(); + }); testSignIn(email, testPasswordSection); }); test("user who is not authenticated, email not registered", function() { var email = "unregistered@testuser.com"; - controller = el.requiredemail({ + createController({ email: email, authenticated: false - }).controller(); + }); testVerify(email); }); @@ -142,10 +146,10 @@ steal.then(function() { test("user who is not authenticated, XHR error", function() { xhr.useResult("ajaxError"); var email = "registered@testuser.com"; - controller = el.requiredemail({ + createController({ email: email, authenticated: false - }).controller(); + }); stop(); @@ -162,10 +166,10 @@ steal.then(function() { var email = "registered@testuser.com"; user.syncEmailKeypair(email, function() { - controller = el.requiredemail({ + createController({ email: email, authenticated: true - }).controller(); + }); }); testSignIn(email, testNoPasswordSection); @@ -177,10 +181,10 @@ steal.then(function() { }); var email = "registered@testuser.com"; - controller = el.requiredemail({ + createController({ email: email, authenticated: true - }).controller(); + }); // This means the current user is going to take the address from the other // account. @@ -193,10 +197,10 @@ steal.then(function() { }); var email = "unregistered@testuser.com"; - controller = el.requiredemail({ + createController({ email: email, authenticated: true - }).controller(); + }); testVerify(email); }); @@ -209,10 +213,10 @@ steal.then(function() { var email = "registered@testuser.com"; user.syncEmailKeypair(email, function() { - controller = el.requiredemail({ + createController({ email: email, authenticated: true - }).controller(); + }); subscribe("assertion_generated", function(item, info) { ok(info.assertion, "we have an assertion"); @@ -231,10 +235,10 @@ steal.then(function() { }); var email = "registered@testuser.com"; - controller = el.requiredemail({ + createController({ email: email, authenticated: false - }).controller(); + }); subscribe("assertion_generated", function(item, info) { ok(info.assertion, "we have an assertion"); @@ -254,10 +258,10 @@ steal.then(function() { }); var email = "registered@testuser.com"; - controller = el.requiredemail({ + createController({ email: email, authenticated: false - }).controller(); + }); var assertion; @@ -288,10 +292,10 @@ steal.then(function() { authenticated: authenticated }); - controller = el.requiredemail({ + createController({ email: email, authenticated: authenticated - }).controller(); + }); subscribe(message, function(item, info) { @@ -324,10 +328,10 @@ steal.then(function() { authenticated: authenticated }); - controller = el.requiredemail({ + createController({ email: email, authenticated: authenticated - }).controller(); + }); subscribe(message, function(item, info) { @@ -348,10 +352,10 @@ steal.then(function() { authenticated: authenticated }); - controller = el.requiredemail({ + createController({ email: email, authenticated: authenticated - }).controller(); + }); subscribe(message, function(item, info) { diff --git a/resources/static/test/qunit/shared/class_unit_test.js b/resources/static/test/qunit/shared/class_unit_test.js new file mode 100644 index 000000000..46e39af26 --- /dev/null +++ b/resources/static/test/qunit/shared/class_unit_test.js @@ -0,0 +1,134 @@ +/*jshint browsers:true, forin: true, laxbreak: true */ +/*global steal: true, 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 ***** */ +steal.then(function() { + module("shared/class", { + }); + + test("create a class with no superclass", function() { + var Class = BrowserID.Class({ + constructor: function() { + this.constRun = true; + }, + + init: function(config) { + this.val = true; + }, + + getVal: function() { + return this.val; + } + }); + + equal(typeof Class, "function", "Class created"); + equal(typeof Class.sc, "undefined", "no superclass"); + + var inst = Class.create(); + ok(inst instanceof Class, "instance created"); + equal(inst.constRun, true, "constructor was run"); + equal(inst.getVal(), true, "init was run, getVal correctly added"); + }); + + test("create a class with a superclass", function() { + var Sup = BrowserID.Class({ + init: function() { }, + + val: true, + getVal: function() { + return this.val; + }, + + anotherVal: 3, + getAnotherVal: function() { + return this.anotherVal; + } + }); + + var Sub = BrowserID.Class(Sup, { + val2: false, + getVal2: function() { + return this.val2; + }, + + getAnotherVal: function() { + return Sub.sc.getAnotherVal.call(this) + 1; + } + }); + + strictEqual(Sub.sc, Sup.prototype, "Sub classes superclass points to Sup.prototype"); + var inst = Sub.create(); + + equal(inst.getVal(), true, "superclass function added"); + equal(inst.getVal2(), false, "sublcass function added"); + equal(inst.getAnotherVal(), 4, "overridden function works properly"); + }); + + test("Class.extend", function() { + var Sup = BrowserID.Class({ + init: function() { }, + + val: true, + getVal: function() { + return this.val; + }, + + anotherVal: 3, + getAnotherVal: function() { + return this.anotherVal; + } + }); + + var Sub = Sup.extend({ + val2: false, + getVal2: function() { + return this.val2; + }, + + getAnotherVal: function() { + return Sub.sc.getAnotherVal.call(this) + 1; + } + }); + + strictEqual(Sub.sc, Sup.prototype, "Sub classes superclass points to Sup.prototype"); + var inst = Sub.create(); + + equal(inst.getVal(), true, "superclass function added"); + equal(inst.getVal2(), false, "sublcass function added"); + equal(inst.getAnotherVal(), 4, "overridden function works properly"); + + }); + +}); -- GitLab