diff --git a/static/cosmopolite.js b/static/cosmopolite.js index 2517598..0bd8dbf 100644 --- a/static/cosmopolite.js +++ b/static/cosmopolite.js @@ -41,20 +41,11 @@ String.prototype.hashCode = function() { /** * @see https://www.cosmopolite.org/reference#constructor * @constructor - * @param {?Cosmopolite.typeCallbacks=} opt_callbacks * @param {?string=} opt_urlPrefix * @param {?string=} opt_namespace * @param {?string=} opt_trackingID */ -var Cosmopolite = function( - opt_callbacks, opt_urlPrefix, opt_namespace, opt_trackingID) { - /** - * @type {Cosmopolite.typeCallbacks} - * @const - * @private - */ - this.callbacks_ = - opt_callbacks || /** @type {Cosmopolite.typeCallbacks} */ ({}); +var Cosmopolite = function(opt_urlPrefix, opt_namespace, opt_trackingID) { /** * @type {string} * @const @@ -119,6 +110,19 @@ var Cosmopolite = function( */ this.instanceID_ = this.uuid(); + /** + * @type {DocumentFragment} + * @private + * Weep for all our souls. + */ + this.eventTarget_ = document.createDocumentFragment(); + this.addEventListener = + this.eventTarget_.addEventListener.bind(this.eventTarget_); + this.removeEventListener = + this.eventTarget_.removeEventListener.bind(this.eventTarget_); + this.dispatchEvent = + this.eventTarget_.dispatchEvent.bind(this.eventTarget_); + /** * @type {string} * @const @@ -153,16 +157,6 @@ var Cosmopolite = function( }; -/** @typedef {{onConnect: (function()|undefined), - onDisconnect: (function()|undefined), - onLogin: (function(string, string)|undefined), - onLogout: (function(string)|undefined), - onMessage: (function(Cosmopolite.typeMessage)|undefined), - onPin: (function(Cosmopolite.typeMessage)|undefined), - onUnpin: (function(Cosmopolite.typeMessage)|undefined)}} */ -Cosmopolite.typeCallbacks; - - /** * @typedef {{event_type: string}} * @private @@ -396,11 +390,11 @@ Cosmopolite.prototype.unsubscribe = function(subject) { */ Cosmopolite.prototype.sendMessage = function(subject, message) { return this.newPromise_(function(resolve, reject) { - var args = { + var args = /** @type {Cosmopolite.typeMessage} */ ({ 'subject': this.canonicalSubject_(subject), 'message': JSON.stringify(message), 'sender_message_id': this.uuid() - }; + }); // No message left behind. var messageQueue = JSON.parse(localStorage[this.messageQueueKey_]); @@ -868,7 +862,7 @@ Cosmopolite.prototype.onRPCResponse_ = } // Handle events that were immediately available as if they came over the - // channel. Fire them before the message callbacks, so clients can use + // channel. Fire them before the message events, so clients can use // events like the subscribe promise fulfillment as a barrier for initial // data. data['events'].forEach(this.onServerEvent_, this); @@ -1068,9 +1062,7 @@ Cosmopolite.prototype.onSocketOpen_ = function() { if (this.channelState_ == Cosmopolite.ChannelState_.OPENING) { this.channelState_ = Cosmopolite.ChannelState_.OPEN; - if (this.callbacks_.onConnect) { - this.callbacks_.onConnect(); - } + this.onConnect_(); } else { return; } @@ -1093,9 +1085,7 @@ Cosmopolite.prototype.onSocketClose_ = function() { if (this.channelState_ == Cosmopolite.ChannelState_.OPEN) { this.channelState_ = Cosmopolite.ChannelState_.CLOSED; - if (this.callbacks_.onDisconnect) { - this.callbacks_.onDisconnect(); - } + this.onDisconnect_(); } else { return; } @@ -1155,6 +1145,34 @@ Cosmopolite.prototype.onClose_ = function() { }; +/** + * Callback on connection to server + * + * @private + */ +Cosmopolite.prototype.onConnect_ = function() { + var e = new CustomEvent('connect', { + 'detail': { + } + }); + this.dispatchEvent(e); +}; + + +/** + * Callback on disconnection from server + * + * @private + */ +Cosmopolite.prototype.onDisconnect_ = function() { + var e = new CustomEvent('disconnect', { + 'detail': { + } + }); + this.dispatchEvent(e); +}; + + /** * Callback on receiving a 'login' event from the server * @@ -1162,11 +1180,13 @@ Cosmopolite.prototype.onClose_ = function() { * @private */ Cosmopolite.prototype.onLogin_ = function(e) { - if (this.callbacks_.onLogin) { - this.callbacks_.onLogin( - e['google_user'], - this.urlPrefix_ + '/auth/logout'); - } + var e2 = new CustomEvent('login', { + 'detail': { + 'username': e['google_user'], + 'logout_url': this.urlPrefix_ + '/auth/logout' + } + }); + this.dispatchEvent(e2); }; @@ -1177,10 +1197,12 @@ Cosmopolite.prototype.onLogin_ = function(e) { * @private */ Cosmopolite.prototype.onLogout_ = function(e) { - if (this.callbacks_.onLogout) { - this.callbacks_.onLogout( - this.urlPrefix_ + '/auth/login'); - } + var e2 = new CustomEvent('logout', { + 'detail': { + 'login_url': this.urlPrefix_ + '/auth/login' + } + }); + this.dispatchEvent(e2); }; @@ -1226,9 +1248,10 @@ Cosmopolite.prototype.onMessage_ = function(e) { } subscription.messages.splice(insertAfter + 1, 0, e); - if (this.callbacks_.onMessage) { - this.callbacks_.onMessage(e); - } + var e2 = new CustomEvent('message', { + 'detail': e + }); + this.dispatchEvent(e2); }; @@ -1260,9 +1283,11 @@ Cosmopolite.prototype.onPin_ = function(e) { e['message'] = JSON.parse(e['message']); subscription.pins.push(e); - if (this.callbacks_.onPin) { - this.callbacks_.onPin(e); - } + + var e2 = new CustomEvent('pin', { + 'detail': e + }); + this.dispatchEvent(e2); }; @@ -1298,9 +1323,11 @@ Cosmopolite.prototype.onUnpin_ = function(e) { e['message'] = JSON.parse(e['message']); subscription.pins.splice(index, 1); - if (this.callbacks_.onUnpin) { - this.callbacks_.onUnpin(e); - } + + var e2 = new CustomEvent('unpin', { + 'detail': e + }); + this.dispatchEvent(e2); }; @@ -1342,7 +1369,6 @@ Cosmopolite.prototype.onServerEvent_ = function(e) { /** @type {function(new:Cosmopolite, - ?Cosmopolite.typeCallbacks=, ?string=, ?string=)} */ window.Cosmopolite = Cosmopolite; diff --git a/static/debug-unity.html b/static/debug-unity.html deleted file mode 100644 index 4206edd..0000000 --- a/static/debug-unity.html +++ /dev/null @@ -1,79 +0,0 @@ - - - Cosmopolite Unity Demo - - - - - -
- - - diff --git a/static/debug.js b/static/debug.js index 121b8d5..da28d71 100644 --- a/static/debug.js +++ b/static/debug.js @@ -23,16 +23,16 @@ var onReady = function() { elements[elementIDs[i]] = document.getElementById(elementIDs[i]); } - var callbacks = { - 'onConnect': onConnect, - 'onDisconnect': onDisconnect, - 'onLogin': onLogin, - 'onLogout': onLogout, - 'onMessage': onMessage, - 'onPin': onPin, - 'onUnpin': onUnpin, - } - cosmo = new Cosmopolite(callbacks, null, null, 'UA-37845853-3'); + cosmo = new Cosmopolite(null, null, 'UA-37845853-3'); + + cosmo.addEventListener('connect', onConnect); + cosmo.addEventListener('disconnect', onDisconnect); + cosmo.addEventListener('login', onLogin); + cosmo.addEventListener('logout', onLogout); + cosmo.addEventListener('message', onMessage); + cosmo.addEventListener('pin', onPin); + cosmo.addEventListener('unpin', onUnpin); + cosmo.trackEvent('send', 'pageview'); elements['messageText'].addEventListener('keypress', messageKeyPress); @@ -57,22 +57,22 @@ var onDisconnect = function() { document.createTextNode('Disconnected')); }; -var onLogin = function(username, logout_url) { +var onLogin = function(e) { elements['loginStatus'].innerHTML = ''; elements['loginStatus'].appendChild(document.createTextNode('Logged in')); elements['username'].innerHTML = ''; - elements['username'].appendChild(document.createTextNode(username)); + elements['username'].appendChild(document.createTextNode(e.detail.username)); elements['loginAction'].innerHTML = ''; var link = document.createElement('a'); - link.href = logout_url; + link.href = e.detail.logout_url; link.target = '_blank'; link.appendChild(document.createTextNode('Log out')); elements['loginAction'].appendChild(link); }; -var onLogout = function(login_url) { +var onLogout = function(e) { elements['loginStatus'].innerHTML = ''; elements['loginStatus'].appendChild( document.createTextNode('Not logged in')); @@ -81,25 +81,25 @@ var onLogout = function(login_url) { elements['loginAction'].innerHTML = ''; var link = document.createElement('a'); - link.href = login_url; + link.href = e.detail.login_url; link.target = '_blank'; link.appendChild(document.createTextNode('Log in')); elements['loginAction'].appendChild(link); }; -var onMessage = function(msg) { - addToList(msg, elements['messageList']); +var onMessage = function(e) { + addToList(e.detail, elements['messageList']); }; -var onPin = function(msg) { - var item = addToList(msg, elements['pinList'], pins); - if (msg['sender'] == cosmo.currentProfile()) { +var onPin = function(e) { + var item = addToList(e.detail, elements['pinList'], pins); + if (e.detail['sender'] == cosmo.currentProfile()) { item.addEventListener('contextmenu', deletePin); } }; -var onUnpin = function(msg) { - var item = pins[msg['id']]; +var onUnpin = function(e) { + var item = pins[e.detail['id']]; item.parentNode.removeChild(item); }; @@ -114,10 +114,14 @@ var selectSubject = function() { selectedSubject = this; elements['messageList'].innerHTML = ''; - cosmo.getMessages(this.subject).forEach(onMessage); + cosmo.getMessages(this.subject).forEach(function(msg) { + onMessage({'detail': msg}); + }); elements['pinList'].innerHTML = ''; - cosmo.getPins(this.subject).forEach(onPin); + cosmo.getPins(this.subject).forEach(function(pin) { + onPin({'detail': pin}); + }); }; var addToList = function(msg, list, trackobj) { diff --git a/static/debug.unity3d b/static/debug.unity3d deleted file mode 100644 index 63fecbf..0000000 Binary files a/static/debug.unity3d and /dev/null differ diff --git a/static/test.js b/static/test.js index 80638d9..1685383 100644 --- a/static/test.js +++ b/static/test.js @@ -67,7 +67,7 @@ QUnit.module('All platforms'); QUnit.test('Construct/shutdown', function(assert) { assert.expect(2); - var cosmo = new Cosmopolite({}, null, randstring()); + var cosmo = new Cosmopolite(null, randstring()); assert.ok(true, 'new Cosmopolite() succeeds'); cosmo.shutdown(); assert.ok(true, 'shutdown() succeeds'); @@ -79,23 +79,23 @@ QUnit.asyncTest('onConnect/onLogout fires', function(assert) { var numCallbacks = 0; logout(function() { - var callbacks = { - 'onConnect': function() { - assert.ok(true, 'onConnect fired'); - if (++numCallbacks == 2) { - cosmo.shutdown(); - QUnit.start(); - } - }, - 'onLogout': function(login_url) { - assert.ok(true, 'onLogout fired'); - if (++numCallbacks == 2) { - cosmo.shutdown(); - QUnit.start(); - } + var cosmo = new Cosmopolite(null, randstring()); + + cosmo.addEventListener('connect', function(e) { + assert.ok(true, 'onConnect fired'); + if (++numCallbacks == 2) { + cosmo.shutdown(); + QUnit.start(); } - }; - var cosmo = new Cosmopolite(callbacks, null, randstring()); + }); + + cosmo.addEventListener('logout', function(e) { + assert.ok(true, 'onLogout fired'); + if (++numCallbacks == 2) { + cosmo.shutdown(); + QUnit.start(); + } + }); }); }); @@ -105,16 +105,15 @@ QUnit.asyncTest('Message round trip', function(assert) { var subject = randstring(); var message = randstring(); - var callbacks = { - 'onMessage': function(e) { - assert.equal(e['subject']['name'], subject, 'subject matches'); - assert.equal(e['message'], message, 'message matches'); - cosmo.shutdown(); - QUnit.start(); - } - }; + var cosmo = new Cosmopolite(null, randstring()); + + cosmo.addEventListener('message', function(e) { + assert.equal(e.detail['subject']['name'], subject, 'subject matches'); + assert.equal(e.detail['message'], message, 'message matches'); + cosmo.shutdown(); + QUnit.start(); + }); - var cosmo = new Cosmopolite(callbacks, null, randstring()); cosmo.sendMessage(subject, message); cosmo.subscribe(subject, -1); }); @@ -125,16 +124,15 @@ QUnit.asyncTest('Message round trip without channel', function(assert) { var subject = randstring(); var message = randstring(); - var callbacks = { - 'onMessage': function(e) { - assert.equal(e['subject']['name'], subject, 'subject matches'); - assert.equal(e['message'], message, 'message matches'); - cosmo.shutdown(); - QUnit.start(); - } - }; + var cosmo = new Cosmopolite(null, randstring()); + + cosmo.addEventListener('message', function(e) { + assert.equal(e.detail['subject']['name'], subject, 'subject matches'); + assert.equal(e.detail['message'], message, 'message matches'); + cosmo.shutdown(); + QUnit.start(); + }); - var cosmo = new Cosmopolite(callbacks, null, randstring()); cosmo.channelState_ = Cosmopolite.ChannelState_.OPENING; cosmo.sendMessage(subject, message); cosmo.subscribe(subject, -1); @@ -149,17 +147,15 @@ QUnit.asyncTest('Bulk subscribe', function(assert) { var messages = 0; - var callbacks = { - 'onMessage': function(e) { - assert.equal(e['message'], message, 'message matches'); - if (++messages == 2) { - cosmo.shutdown(); - QUnit.start(); - } - } - }; + var cosmo = new Cosmopolite(null, randstring()); - var cosmo = new Cosmopolite(callbacks, null, randstring()); + cosmo.addEventListener('message', function(e) { + assert.equal(e.detail['message'], message, 'message matches'); + if (++messages == 2) { + cosmo.shutdown(); + QUnit.start(); + } + }); cosmo.sendMessage(subject1, message); cosmo.sendMessage(subject2, message); cosmo.subscribe([subject1, subject2], -1); @@ -180,16 +176,15 @@ QUnit.asyncTest('Complex object', function(assert) { 'unicode': '☠☣☃𠜎' }; - var callbacks = { - 'onMessage': function(e) { - assert.equal(e['subject']['name'], subject, 'subject matches'); - assert.deepEqual(e['message'], message, 'message matches'); - cosmo.shutdown(); - QUnit.start(); - } - }; + var cosmo = new Cosmopolite(null, randstring()); + + cosmo.addEventListener('message', function(e) { + assert.equal(e.detail['subject']['name'], subject, 'subject matches'); + assert.deepEqual(e.detail['message'], message, 'message matches'); + cosmo.shutdown(); + QUnit.start(); + }); - var cosmo = new Cosmopolite(callbacks, null, randstring()); cosmo.sendMessage(subject, message); cosmo.subscribe(subject, -1); }); @@ -200,7 +195,7 @@ QUnit.asyncTest('sendMessage Promise', function(assert) { var subject = randstring(); var message = randstring(); - var cosmo = new Cosmopolite({}, null, randstring()); + var cosmo = new Cosmopolite(null, randstring()); cosmo.sendMessage(subject, message).then(function(msg) { assert.ok(true, 'sendMessage Promise fulfilled'); assert.equal(msg['subject']['name'], subject); @@ -216,7 +211,7 @@ QUnit.asyncTest('subscribe/unsubscribe Promise', function(assert) { var subject = randstring(); var message = randstring(); - var cosmo = new Cosmopolite({}, null, randstring()); + var cosmo = new Cosmopolite(null, randstring()); cosmo.subscribe(subject).then(function() { assert.ok(true, 'subscribe Promise fulfilled'); cosmo.unsubscribe(subject).then(function() { @@ -234,22 +229,22 @@ QUnit.asyncTest('Duplicate message suppression', function(assert) { var message1 = randstring(); var message2 = randstring(); - var callbacks = { - 'onMessage': function(msg) { - assert.equal(msg['subject']['name'], subject, 'subject matches'); - assert.equal(msg['message'], message1, 'message matches'); - cosmo.shutdown(); - QUnit.start(); - } - }; + var cosmo = new Cosmopolite(null, randstring()); - var cosmo = new Cosmopolite(callbacks, null, randstring()); // Break cosmo's UUID generator so that it generates duplicate values. cosmo.uuid_ = function() { return '4'; // chosen by fair dice roll. // guaranteed to be random. }; + + cosmo.addEventListener('message', function(e) { + assert.equal(e.detail['subject']['name'], subject, 'subject matches'); + assert.equal(e.detail['message'], message1, 'message matches'); + cosmo.shutdown(); + QUnit.start(); + }); + cosmo.sendMessage(subject, message1).then(function() { cosmo.sendMessage(subject, message2).then(function() { cosmo.subscribe(subject, -1); @@ -265,20 +260,19 @@ QUnit.asyncTest('Message persistence', function(assert) { var namespace = randstring(); // Send a message and shut down too fast for it to hit the wire. - var cosmo1 = new Cosmopolite({}, null, namespace); + var cosmo1 = new Cosmopolite(null, namespace); cosmo1.sendMessage(subject, message); cosmo1.shutdown(); - var callbacks = { - 'onMessage': function(msg) { - assert.equal(msg['subject']['name'], subject, 'subject matches'); - assert.equal(msg['message'], message, 'message matches'); - cosmo2.shutdown(); - QUnit.start(); - } - }; + var cosmo2 = new Cosmopolite(null, namespace); + + cosmo2.addEventListener('message', function(e) { + assert.equal(e.detail['subject']['name'], subject, 'subject matches'); + assert.equal(e.detail['message'], message, 'message matches'); + cosmo2.shutdown(); + QUnit.start(); + }); - var cosmo2 = new Cosmopolite(callbacks, null, namespace); cosmo2.subscribe(subject, -1); // Should pick up the message from the persistent queue. }); @@ -288,7 +282,7 @@ QUnit.test('getMessages/subscribe', function(assert) { var subject = randstring(); - var cosmo = new Cosmopolite({}, null, randstring()); + var cosmo = new Cosmopolite(null, randstring()); assert.throws( cosmo.getMessages.bind(undefined, subject), 'getMessages before subscribe fails'); @@ -306,7 +300,7 @@ QUnit.asyncTest('subscribe barrier', function(assert) { var subject = randstring(); var message = randstring(); - var cosmo = new Cosmopolite({}, null, randstring()); + var cosmo = new Cosmopolite(null, randstring()); cosmo.sendMessage(subject, message).then(function() { cosmo.subscribe(subject, -1).then(function() { @@ -331,7 +325,7 @@ QUnit.asyncTest('resubscribe', function(assert) { var subject = randstring(); var message = randstring(); - var cosmo = new Cosmopolite({}, null, randstring()); + var cosmo = new Cosmopolite(null, randstring()); cosmo.sendMessage(subject, message).then(function() { cosmo.subscribe(subject).then(function() { @@ -355,7 +349,7 @@ QUnit.asyncTest('Message ordering', function(assert) { var subject = randstring(); var messages = ['A', 'B', 'C', 'D']; - var cosmo = new Cosmopolite({}, null, randstring()); + var cosmo = new Cosmopolite(null, randstring()); var sendNextMessage = function() { if (messages.length) { @@ -383,22 +377,23 @@ QUnit.asyncTest('Reconnect channel', function(assert) { var subject = randstring(); var message = randstring(); - var callbacks = { - 'onConnect': function() { - assert.ok(true, 'onConnect fired'); - }, - 'onDisconnect': function() { - assert.ok(true, 'onDisconnect fired'); - }, - 'onMessage': function(msg) { - assert.equal(msg['subject']['name'], subject, 'subject matches'); - assert.equal(msg['message'], message, 'message matches'); - cosmo.shutdown(); - QUnit.start(); - } - }; + var cosmo = new Cosmopolite(null, randstring()); + + cosmo.addEventListener('connect', function(e) { + assert.ok(true, 'onConnect fired'); + }); + + cosmo.addEventListener('disconnect', function(e) { + assert.ok(true, 'onDisconnect fired'); + }); + + cosmo.addEventListener('message', function(e) { + assert.equal(e.detail['subject']['name'], subject, 'subject matches'); + assert.equal(e.detail['message'], message, 'message matches'); + cosmo.shutdown(); + QUnit.start(); + }); - var cosmo = new Cosmopolite(callbacks, null, randstring()); cosmo.subscribe(subject, 0).then(function() { // Reach inside to forcefully close the socket cosmo.socket_.close(); @@ -412,11 +407,11 @@ QUnit.asyncTest('subscribe ACL', function(assert) { var subject = randstring(); logout(function() { - var tempCosmo = new Cosmopolite({}, null, randstring()); + var tempCosmo = new Cosmopolite(null, randstring()); tempCosmo.getProfile().then(function(tempProfile) { tempCosmo.shutdown(); - var cosmo = new Cosmopolite({}, null, randstring()); + var cosmo = new Cosmopolite(null, randstring()); cosmo.getProfile().then(function(profile) { cosmo.subscribe({ 'name': subject, @@ -446,11 +441,11 @@ QUnit.asyncTest('sendMessage ACL', function(assert) { var message = randstring(); logout(function() { - var tempCosmo = new Cosmopolite({}, null, randstring()); + var tempCosmo = new Cosmopolite(null, randstring()); tempCosmo.getProfile().then(function(tempProfile) { tempCosmo.shutdown(); - var cosmo = new Cosmopolite({}, null, randstring()); + var cosmo = new Cosmopolite(null, randstring()); cosmo.getProfile().then(function(profile) { cosmo.sendMessage({ 'name': subject, @@ -483,22 +478,23 @@ QUnit.asyncTest('"me" ACL', function(assert) { }; var message = randstring(); - var callbacks = { - 'onMessage': function(e) { - assert.equal(e['subject']['name'], subject['name'], 'subject matches'); - assert.equal(e['subject']['readable_only_by'], 'me', - 'readable_only_by matches'); - assert.equal(e['subject']['writable_only_by'], 'me', - 'writable_only_by matches'); - assert.equal(e['message'], message, 'message matches'); - cosmo.shutdown(); - QUnit.start(); - } - }; + var cosmo = new Cosmopolite(null, randstring()); + + cosmo.addEventListener('message', function(e) { + assert.equal(e.detail['subject']['name'], subject['name'], + 'subject matches'); + assert.equal(e.detail['subject']['readable_only_by'], 'me', + 'readable_only_by matches'); + assert.equal(e.detail['subject']['writable_only_by'], 'me', + 'writable_only_by matches'); + assert.equal(e.detail['message'], message, 'message matches'); + cosmo.shutdown(); + QUnit.start(); + }); - var cosmo = new Cosmopolite(callbacks, null, randstring()); cosmo.sendMessage(subject, message).then(function(msg) { - assert.equal(msg['subject']['name'], subject['name'], 'subject matches'); + assert.equal(msg['subject']['name'], subject['name'], + 'subject matches'); assert.equal(msg['subject']['readable_only_by'], 'me', 'readable_only_by matches'); assert.equal(msg['subject']['writable_only_by'], 'me', @@ -513,24 +509,28 @@ QUnit.asyncTest('pin/unpin', function(assert) { var subject = randstring(); var message = randstring(); - var callbacks = { - 'onPin': function(e) { - assert.equal(subject, e['subject']['name'], 'onPin: subject matches'); - assert.equal(message, e['message'], 'onPin: message matches'); - assert.equal(cosmo.getPins(subject).length, 1); - pin.then(function(id) { - cosmo.unpin(id); - }); - }, - 'onUnpin': function(e) { - assert.equal(subject, e['subject']['name'], 'onUnpin: subject matches'); - assert.equal(message, e['message'], 'onUnpin: message matches'); - cosmo.shutdown(); - QUnit.start(); - } - }; + var cosmo = new Cosmopolite(null, randstring()); + + cosmo.addEventListener('pin', function(e) { + assert.equal(subject, e.detail['subject']['name'], + 'onPin: subject matches'); + assert.equal(message, e.detail['message'], + 'onPin: message matches'); + assert.equal(cosmo.getPins(subject).length, 1); + pin.then(function(id) { + cosmo.unpin(id); + }); + }); + + cosmo.addEventListener('unpin', function(e) { + assert.equal(subject, e.detail['subject']['name'], + 'onUnpin: subject matches'); + assert.equal(message, e.detail['message'], + 'onUnpin: message matches'); + cosmo.shutdown(); + QUnit.start(); + }); - var cosmo = new Cosmopolite(callbacks, null, randstring()); cosmo.subscribe(subject); var pin = cosmo.pin(subject, message); }); @@ -543,25 +543,29 @@ QUnit.asyncTest('Repin', function(assert) { var pins = 0; - var callbacks = { - 'onPin': function(e) { - assert.equal(subject, e['subject']['name'], 'onPin: subject matches'); - assert.equal(message, e['message'], 'onPin: message matches'); - assert.equal(cosmo.getPins(subject).length, 1); - if (++pins == 1) { - cosmo.socket_.close(); - } else { - cosmo.shutdown(); - QUnit.start(); - } - }, - 'onUnpin': function(e) { - assert.equal(subject, e['subject']['name'], 'onUnpin: subject matches'); - assert.equal(message, e['message'], 'onUnpin: message matches'); - } - }; + var cosmo = new Cosmopolite(null, randstring()); + + cosmo.addEventListener('pin', function(e) { + assert.equal(subject, e.detail['subject']['name'], + 'onPin: subject matches'); + assert.equal(message, e.detail['message'], + 'onPin: message matches'); + assert.equal(cosmo.getPins(subject).length, 1); + if (++pins == 1) { + cosmo.socket_.close(); + } else { + cosmo.shutdown(); + QUnit.start(); + } + }); + + cosmo.addEventListener('unpin', function(e) { + assert.equal(subject, e.detail['subject']['name'], + 'onUnpin: subject matches'); + assert.equal(message, e.detail['message'], + 'onUnpin: message matches'); + }); - var cosmo = new Cosmopolite(callbacks, null, randstring()); cosmo.subscribe(subject); var pin = cosmo.pin(subject, message); }); @@ -575,27 +579,26 @@ QUnit.asyncTest('Duplicate subject', function(assert) { var messages = 0; - var callbacks = { - 'onConnect': function() { - cosmo.sendMessage(subject, message1); - cosmo.sendMessage(subject, message2); - cosmo.subscribe(subject, -1); - }, - 'onMessage': function(e) { - assert.equal(subject, e['subject']['name'], 'subject matches'); - if (e['message'] == message1) { - assert.equal(message1, e['message'], 'message1 matches'); - } else { - assert.equal(message2, e['message'], 'message2 matches'); - } - if (++messages == 2) { - cosmo.shutdown(); - QUnit.start(); - } - } - }; + var cosmo = new Cosmopolite(null, randstring()); - var cosmo = new Cosmopolite(callbacks, null, randstring()); + cosmo.addEventListener('connect', function(e) { + cosmo.sendMessage(subject, message1); + cosmo.sendMessage(subject, message2); + cosmo.subscribe(subject, -1); + }); + + cosmo.addEventListener('message', function(e) { + assert.equal(subject, e.detail['subject']['name'], 'subject matches'); + if (e.detail['message'] == message1) { + assert.equal(message1, e.detail['message'], 'message1 matches'); + } else { + assert.equal(message2, e.detail['message'], 'message2 matches'); + } + if (++messages == 2) { + cosmo.shutdown(); + QUnit.start(); + } + }); }); @@ -607,25 +610,25 @@ QUnit.asyncTest('Login', function(assert) { var anonymousProfile; logout(function() { - var callbacks = { - 'onLogout': function(login_url) { - assert.ok(true, 'onLogout fired'); - anonymousProfile = cosmo.currentProfile(); - // Entirely magic URL that sets the login cookie and redirects. - window.open( - '/_ah/login?email=test%40example.com&action=Login' + - '&continue=/cosmopolite/static/login_complete.html'); - }, - 'onLogin': function(login_url) { - assert.ok(true, 'onLogin fired'); - assert.notEqual(anonymousProfile, cosmo.currentProfile(), - 'profile changed'); - cosmo.shutdown(); - logout(); - QUnit.start(); - } - }; - var cosmo = new Cosmopolite(callbacks, null, randstring()); + var cosmo = new Cosmopolite(null, randstring()); + + cosmo.addEventListener('login', function(e) { + assert.ok(true, 'onLogin fired'); + assert.notEqual(anonymousProfile, cosmo.currentProfile(), + 'profile changed'); + cosmo.shutdown(); + logout(); + QUnit.start(); + }); + + cosmo.addEventListener('logout', function(e) { + assert.ok(true, 'onLogout fired'); + anonymousProfile = cosmo.currentProfile(); + // Entirely magic URL that sets the login cookie and redirects. + window.open( + '/_ah/login?email=test%40example.com&action=Login' + + '&continue=/cosmopolite/static/login_complete.html'); + }); }); }); @@ -638,32 +641,33 @@ QUnit.asyncTest('Profile merge', function(assert) { var messages = 0; logout(function() { - var callbacks = { - 'onMessage': function(msg) { - messages++; - assert.equal(msg['subject']['name'], subject, - 'message #' + messages + ': subject matches'); - assert.equal(msg['message'], message, - 'message #' + messages + ': message matches'); - assert.equal(msg['sender'], cosmo.currentProfile(), - 'message #' + messages + ': profile matches'); - if (messages == 1) { - cosmo.unsubscribe(subject); - // Entirely magic URL that sets the login cookie and redirects. - window.open( - '/_ah/login?email=test%40example.com&action=Login' + - '&continue=/cosmopolite/static/login_complete.html'); - } - if (messages == 2) { - cosmo.shutdown(); - QUnit.start(); - } - }, - 'onLogin': function(logout_url) { - cosmo.subscribe(subject, -1); + var cosmo = new Cosmopolite(null, randstring()); + + cosmo.addEventListener('login', function(e) { + cosmo.subscribe(subject, -1); + }); + + cosmo.addEventListener('message', function(e) { + messages++; + assert.equal(e.detail['subject']['name'], subject, + 'message #' + messages + ': subject matches'); + assert.equal(e.detail['message'], message, + 'message #' + messages + ': message matches'); + assert.equal(e.detail['sender'], cosmo.currentProfile(), + 'message #' + messages + ': profile matches'); + if (messages == 1) { + cosmo.unsubscribe(subject); + // Entirely magic URL that sets the login cookie and redirects. + window.open( + '/_ah/login?email=test%40example.com&action=Login' + + '&continue=/cosmopolite/static/login_complete.html'); } - }; - var cosmo = new Cosmopolite(callbacks, null, randstring()); + if (messages == 2) { + cosmo.shutdown(); + QUnit.start(); + } + }); + cosmo.sendMessage(subject, message); cosmo.subscribe(subject, -1); }); @@ -676,18 +680,17 @@ QUnit.asyncTest('Two channels, one client', function(assert) { var subject = randstring(); var message = randstring(); - var callbacks = { - 'onMessage': function(msg) { - assert.equal(msg['subject']['name'], subject, 'subject matches'); - assert.equal(msg['message'], message, 'message matches'); - cosmo1.shutdown(); - QUnit.start(); - } - }; + var cosmo1 = new Cosmopolite(null, namespace); + + cosmo1.addEventListener('message', function(e) { + assert.equal(e.detail['subject']['name'], subject, 'subject matches'); + assert.equal(e.detail['message'], message, 'message matches'); + cosmo1.shutdown(); + QUnit.start(); + }); - var cosmo1 = new Cosmopolite(callbacks, null, namespace); cosmo1.subscribe(subject).then(function() { - var cosmo2 = new Cosmopolite({}, null, namespace); + var cosmo2 = new Cosmopolite(null, namespace); cosmo2.sendMessage(subject, message).then(function() { cosmo2.shutdown(); }); @@ -700,20 +703,20 @@ QUnit.asyncTest('subscribe admin ACL', function(assert) { var subject = randstring(); logout(function() { - var callbacks = { - 'onLogin': function() { - cosmo.subscribe({ - 'name': subject, - 'readable_only_by': 'admin' - }).then(function() { - assert.ok(true, 'logged in succeeds'); + var cosmo = new Cosmopolite(null, randstring()); + + cosmo.addEventListener('login', function(e) { + cosmo.subscribe({ + 'name': subject, + 'readable_only_by': 'admin' + }).then(function() { + assert.ok(true, 'logged in succeeds'); + + cosmo.shutdown(); + QUnit.start(); + }); + }); - cosmo.shutdown(); - QUnit.start(); - }); - } - }; - var cosmo = new Cosmopolite(callbacks, null, randstring()); cosmo.subscribe({ 'name': subject, 'readable_only_by': 'admin' @@ -734,20 +737,20 @@ QUnit.asyncTest('sendMessage admin ACL', function(assert) { var message = randstring(); logout(function() { - var callbacks = { - 'onLogin': function() { - cosmo.sendMessage({ - 'name': subject, - 'writable_only_by': 'admin' - }, message).then(function() { - assert.ok(true, 'logged in succeeds'); + var cosmo = new Cosmopolite(null, randstring()); + + cosmo.addEventListener('login', function(e) { + cosmo.sendMessage({ + 'name': subject, + 'writable_only_by': 'admin' + }, message).then(function() { + assert.ok(true, 'logged in succeeds'); + + cosmo.shutdown(); + QUnit.start(); + }); + }); - cosmo.shutdown(); - QUnit.start(); - }); - } - }; - var cosmo = new Cosmopolite(callbacks, null, randstring()); cosmo.sendMessage({ 'name': subject, 'writable_only_by': 'admin'