From 7f8218a67c71ee096234f6842ab86d05637e69ae Mon Sep 17 00:00:00 2001 From: Simon Woolf Date: Fri, 8 May 2015 15:35:10 +0100 Subject: [PATCH 1/8] Move data normalisation from #enter to #enterClient To avoid having to do it separately if someone calls enterClient directly --- common/lib/client/presence.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/common/lib/client/presence.js b/common/lib/client/presence.js index 86b2f26286..2cda2c1c63 100644 --- a/common/lib/client/presence.js +++ b/common/lib/client/presence.js @@ -15,16 +15,16 @@ var Presence = (function() { Utils.inherits(Presence, EventEmitter); Presence.prototype.enter = function(data, callback) { - if (!callback && (typeof(data)==='function')) { - callback = data; - data = ''; - } if(!this.clientId) throw new Error('clientId must be specified to enter a presence channel'); this.enterClient(this.clientId, data, callback); }; Presence.prototype.enterClient = function(clientId, data, callback) { + if (!callback && (typeof(data)==='function')) { + callback = data; + data = ''; + } Logger.logAction(Logger.LOG_MICRO, 'Presence.enterClient()', 'entering; channel = ' + this.channel.name + ', client = ' + clientId); var presence = PresenceMessage.fromValues({ action : presenceAction.ENTER, From c1c7606f6061f490d9f6f7767a93ba161f23eaf1 Mon Sep 17 00:00:00 2001 From: Simon Woolf Date: Sat, 9 May 2015 14:34:19 +0100 Subject: [PATCH 2/8] Fix test names in failure messages --- spec/realtime/presence.test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/realtime/presence.test.js b/spec/realtime/presence.test.js index bcc2469455..d52f2dc765 100644 --- a/spec/realtime/presence.test.js +++ b/spec/realtime/presence.test.js @@ -338,7 +338,7 @@ define(['ably', 'shared_helper', 'async'], function(Ably, helper, async) { exitOnState('failed'); exitOnState('suspended'); } catch(e) { - test.ok(false, 'presence.enter0 failed with exception: ' + e.stack); + test.ok(false, 'presence.enter3 failed with exception: ' + e.stack); done(); } }; @@ -480,7 +480,7 @@ define(['ably', 'shared_helper', 'async'], function(Ably, helper, async) { exitOnState('failed'); exitOnState('suspended'); } catch(e) { - test.ok(false, 'presence.enter0 failed with exception: ' + e.stack); + test.ok(false, 'presence.get0 failed with exception: ' + e.stack); done(); } }; @@ -660,7 +660,7 @@ define(['ably', 'shared_helper', 'async'], function(Ably, helper, async) { exitOnState('failed'); exitOnState('suspended'); } catch(e) { - test.ok(false, 'presence.enter0 failed with exception: ' + e.stack); + test.ok(false, 'presence.attach0 failed with exception: ' + e.stack); done(); } }; @@ -760,7 +760,7 @@ define(['ably', 'shared_helper', 'async'], function(Ably, helper, async) { }); }); } catch(e) { - test.ok(false, 'presence.enter0 failed with exception: ' + e.stack); + test.ok(false, 'presence.member0 failed with exception: ' + e.stack); done(); } }; From 440f4ec11d3231f3587de1f0c5be64400211bb22 Mon Sep 17 00:00:00 2001 From: Simon Woolf Date: Mon, 11 May 2015 18:32:40 +0100 Subject: [PATCH 3/8] Allow message and presencemessage to work without data --- common/lib/client/presence.js | 2 +- common/lib/types/message.js | 14 ++++++++------ common/lib/types/presencemessage.js | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/common/lib/client/presence.js b/common/lib/client/presence.js index 2cda2c1c63..d6113eb244 100644 --- a/common/lib/client/presence.js +++ b/common/lib/client/presence.js @@ -23,7 +23,7 @@ var Presence = (function() { Presence.prototype.enterClient = function(clientId, data, callback) { if (!callback && (typeof(data)==='function')) { callback = data; - data = ''; + data = null; } Logger.logAction(Logger.LOG_MICRO, 'Presence.enterClient()', 'entering; channel = ' + this.channel.name + ', client = ' + clientId); var presence = PresenceMessage.fromValues({ diff --git a/common/lib/types/message.js b/common/lib/types/message.js index d64407c85f..9bd5eec052 100644 --- a/common/lib/types/message.js +++ b/common/lib/types/message.js @@ -24,11 +24,11 @@ var Message = (function() { encoding: this.encoding }; - /* encode to base64 if we're returning real JSON; + /* encode data to base64 if present and we're returning real JSON; * although msgpack calls toJSON(), we know it is a stringify() * call if it has a non-empty arguments list */ var data = this.data; - if(arguments.length > 0 && BufferUtils.isBuffer(data)) { + if(data && arguments.length > 0 && BufferUtils.isBuffer(data)) { var encoding = this.encoding; result.encoding = encoding ? (encoding + '/base64') : 'base64'; data = BufferUtils.base64Encode(data); @@ -78,10 +78,12 @@ var Message = (function() { }; Message.encode = function(msg, options) { - var data = msg.data, encoding; - if(typeof(data) != 'string' && !BufferUtils.isBuffer(data)) { - msg.data = JSON.stringify(data); - msg.encoding = (encoding = msg.encoding) ? (encoding + '/json') : 'json'; + if(msg.data){ + var data = msg.data, encoding; + if(typeof(data) != 'string' && !BufferUtils.isBuffer(data)) { + msg.data = JSON.stringify(data); + msg.encoding = (encoding = msg.encoding) ? (encoding + '/json') : 'json'; + } } if(options != null && options.encrypted) Message.encrypt(msg, options); diff --git a/common/lib/types/presencemessage.js b/common/lib/types/presencemessage.js index 5d221e21f0..26a40cf668 100644 --- a/common/lib/types/presencemessage.js +++ b/common/lib/types/presencemessage.js @@ -36,7 +36,7 @@ var PresenceMessage = (function() { * although msgpack calls toJSON(), we know it is a stringify() * call if it passes on the stringify arguments */ var data = this.data; - if(arguments.length > 0 && BufferUtils.isBuffer(data)) { + if(data && arguments.length > 0 && BufferUtils.isBuffer(data)) { var encoding = this.encoding; result.encoding = encoding ? (encoding + '/base64') : 'base64'; data = data.toString('base64'); From a248d05ed80959b963b39e7d3f41602360b7c209 Mon Sep 17 00:00:00 2001 From: Simon Woolf Date: Mon, 11 May 2015 18:38:49 +0100 Subject: [PATCH 4/8] Add specs for variations of calling channel#publish & presence#enter --- spec/realtime/message.test.js | 107 ++++++++++++++++++++ spec/realtime/presence.test.js | 174 ++++++++++++++++++++++++++++++++- 2 files changed, 280 insertions(+), 1 deletion(-) diff --git a/spec/realtime/message.test.js b/spec/realtime/message.test.js index 196d8a5a8f..ab6fb68346 100644 --- a/spec/realtime/message.test.js +++ b/spec/realtime/message.test.js @@ -66,6 +66,113 @@ define(['ably', 'shared_helper'], function(Ably, helper) { } }; + exports.publishVariations = function(test) { + var transport = 'binary'; + + test.expect(32); + try { + /* set up realtime */ + var realtime = helper.AblyRealtime(); + var rest = helper.AblyRest(); + + /* connect and attach */ + realtime.connection.on('connected', function() { + var rtChannel = realtime.channels.get('publishVariations'); + var testData = 'Some data' + var errorCallback = function(err){ + if(err) { + test.ok(false, 'Error received by publish callback ' + err); + test.done(); + realtime.close(); + return; + } + } + rtChannel.attach(function(err) { + if(err) { + test.ok(false, 'Attach failed with error: ' + err); + test.done(); + realtime.close(); + return; + } + + /* subscribe to different message types */ + var messagesReceived = 0 + rtChannel.subscribe(function(msg) { + test.ok(true, 'Received ' + msg.name); + ++messagesReceived; + switch(msg.name) { + case 'objectWithName': + case 'objectWithNameAndCallback': + case 'objectWithNameAndNullData': + case 'objectWithNameAndUndefinedData': + case 'nameAndNullData': + case 'nameAndUndefinedData': + test.equal(typeof(msg.data), 'undefined', 'Msg data was received where none expected'); + break; + case 'nameAndData': + case 'nameAndDataAndCallback': + case 'objectWithNameAndData': + case 'objectWithNameAndDataAndCallback': + test.equal(msg.data, testData, 'Msg data ' + msg.data + 'Unexpected message data received'); + break; + case undefined: + if (msg.data) { + // 3 messages: null name and data, null name and data and callback, object with null name and data + test.equal(msg.data, testData, 'Msg data ' + msg.data + 'Unexpected message data received'); + } else { + // 3 messages: null name and null data, object with null name and no data, object with null name and null data + test.equal(typeof(msg.data), 'undefined', 'Msg data was received where none expected'); + } + break; + default: + test.ok(false, 'Unexpected message ' + msg.name + 'received'); + test.done(); + realtime.close(); + } + + if (messagesReceived == 16) { + test.done(); + realtime.close(); + } + }); + + /* publish events */ + var restChannel = rest.channels.get('publishVariations'); + restChannel.publish({name: 'objectWithName'}); + restChannel.publish({name: 'objectWithNameAndCallback'}, errorCallback); + restChannel.publish({name: 'objectWithNameAndNullData', data: null}); + restChannel.publish({name: 'objectWithNameAndUndefinedData', data: undefined}); + restChannel.publish('nameAndNullData', null); + restChannel.publish('nameAndUndefinedData', undefined); + restChannel.publish('nameAndData', testData); + restChannel.publish('nameAndDataAndCallback', testData, errorCallback); + restChannel.publish({name: 'objectWithNameAndData', data: testData}); + restChannel.publish({name: 'objectWithNameAndDataAndCallback', data: testData}, errorCallback); + // 6 messages with null name: + restChannel.publish(null, testData); + restChannel.publish(null, testData, errorCallback); + restChannel.publish({name: null, data: testData}); + restChannel.publish(null, null); + restChannel.publish({name: null}); + restChannel.publish({name: null, data: null}); + }); + }); + var exitOnState = function(state) { + realtime.connection.on(state, function () { + test.ok(false, transport + ' connection to server failed'); + test.done(); + realtime.close(); + }); + }; + exitOnState('failed'); + exitOnState('suspended'); + } catch(e) { + test.ok(false, 'Channel attach failed with exception: ' + e.stack); + test.done(); + realtime.close(); + } + }; + exports.restpublish = function(test) { var count = 10; var rest = helper.AblyRest(); diff --git a/spec/realtime/presence.test.js b/spec/realtime/presence.test.js index d52f2dc765..f0257f3196 100644 --- a/spec/realtime/presence.test.js +++ b/spec/realtime/presence.test.js @@ -100,7 +100,7 @@ define(['ably', 'shared_helper', 'async'], function(Ably, helper, async) { }; /* - * Attach to channel, enter presence channel and await entered event + * Attach to channel, enter presence channel with data and await entered event */ exports.enter0 = function(test) { var clientRealtime; @@ -343,6 +343,178 @@ define(['ably', 'shared_helper', 'async'], function(Ably, helper, async) { } }; + /* + * Attach to channel, enter presence channel with a callback but no data and await entered event + */ + exports.enter4 = function(test) { + var clientRealtime; + var isDone = false, done = function() { + if(!isDone) { + isDone = true; + setTimeout(function() { + test.done(); clientRealtime.close(); + }, 3000); + } + }; + try { + var transport = 'web_socket'; + + test.expect(2); + /* listen for the enter event, test is complete when received */ + var presenceHandler = function() { + if(this.event == 'enter') { + test.ok(true, 'Presence event received'); + done(); + presenceChannel.presence.off(presenceHandler); + } + }; + presenceChannel.presence.on(presenceHandler); + + /* set up authenticated connection */ + clientRealtime = helper.AblyRealtime({ clientId: testClientId, authToken: authToken, transports: [transport] }); + clientRealtime.connection.on('connected', function() { + /* get channel, attach, and enter */ + var clientChannel = clientRealtime.channels.get('presence0'); + clientChannel.attach(function(err) { + if(err) { + test.ok(false, 'Attach failed with error: ' + err); + done(); + return; + } + clientChannel.presence.enter(function(err) { + if(err) { + test.ok(false, 'Enter failed with error: ' + err); + done(); + return; + } + test.ok(true, 'Presence event sent'); + }); + }); + }); + var exitOnState = function(state) { + clientRealtime.connection.on(state, function () { + test.ok(false, transport + ' connection to server failed'); + done(); + }); + }; + exitOnState('failed'); + exitOnState('suspended'); + } catch(e) { + test.ok(false, 'presence.enter4 failed with exception: ' + e.stack); + done(); + } + }; + + /* + * Attach to channel, enter presence channel with neither callback nor data and await entered event + */ + exports.enter5 = function(test) { + var clientRealtime; + var isDone = false, done = function() { + if(!isDone) { + isDone = true; + setTimeout(function() { + test.done(); clientRealtime.close(); + }, 3000); + } + }; + try { + var transport = 'web_socket'; + + test.expect(1); + /* listen for the enter event, test is complete when received */ + var presenceHandler = function() { + if(this.event == 'enter') { + test.ok(true, 'Presence event received'); + done(); + presenceChannel.presence.off(presenceHandler); + } + }; + presenceChannel.presence.on(presenceHandler); + + /* set up authenticated connection */ + clientRealtime = helper.AblyRealtime({ clientId: testClientId, authToken: authToken, transports: [transport] }); + clientRealtime.connection.on('connected', function() { + /* get channel, attach, and enter */ + var clientChannel = clientRealtime.channels.get('presence0'); + clientChannel.attach(function(err) { + if(err) { + test.ok(false, 'Attach failed with error: ' + err); + done(); + return; + } + clientChannel.presence.enter(); + }); + }); + var exitOnState = function(state) { + clientRealtime.connection.on(state, function () { + test.ok(false, transport + ' connection to server failed'); + done(); + }); + }; + exitOnState('failed'); + exitOnState('suspended'); + } catch(e) { + test.ok(false, 'presence.enter5 failed with exception: ' + e.stack); + done(); + } + }; + + /* + * Attach to channel, enter presence channel with data but no callback and await entered event + */ + exports.enter6 = function(test) { + var clientRealtime; + var isDone = false, done = function() { + if(!isDone) { + isDone = true; + setTimeout(function() { + test.done(); clientRealtime.close(); + }, 3000); + } + }; + try { + var transport = 'web_socket'; + + test.expect(1); + /* listen for the enter event, test is complete when received */ + var presenceHandler = function() { + if(this.event == 'enter') { + test.ok(true, 'Presence event received'); + done(); + presenceChannel.presence.off(presenceHandler); + } + }; + presenceChannel.presence.on(presenceHandler); + + /* set up authenticated connection */ + clientRealtime = helper.AblyRealtime({ clientId: testClientId, authToken: authToken, transports: [transport] }); + clientRealtime.connection.on('connected', function() { + /* get channel, attach, and enter */ + var clientChannel = clientRealtime.channels.get('presence0'); + clientChannel.attach(function(err) { + if(err) { + test.ok(false, 'Attach failed with error: ' + err); + done(); + return; + } + clientChannel.presence.enter('Test client data (enter6)'); + }); + }); + var exitOnState = function(state) { + clientRealtime.connection.on(state, function () { + test.ok(false, transport + ' connection to server failed'); + done(); + }); + }; + exitOnState('failed'); + exitOnState('suspended'); + } catch(e) { + test.ok(false, 'presence.enter6 failed with exception: ' + e.stack); + done(); + } + }; + /* * Attach to channel, enter+leave presence channel and await leave event */ From 19ca64167ddab5cb1c3766ed154caec2317d44a7 Mon Sep 17 00:00:00 2001 From: Simon Woolf Date: Mon, 11 May 2015 18:36:10 +0100 Subject: [PATCH 5/8] Regenerated --- browser/static/ably.js | 25 +++++++++++++------------ browser/static/ably.noencryption.js | 25 +++++++++++++------------ spec/support/browser_file_list.js | 2 +- 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/browser/static/ably.js b/browser/static/ably.js index 769f5b7ce1..bb100a4046 100644 --- a/browser/static/ably.js +++ b/browser/static/ably.js @@ -4423,11 +4423,11 @@ var Message = (function() { encoding: this.encoding }; - /* encode to base64 if we're returning real JSON; + /* encode data to base64 if present and we're returning real JSON; * although msgpack calls toJSON(), we know it is a stringify() * call if it has a non-empty arguments list */ var data = this.data; - if(arguments.length > 0 && BufferUtils.isBuffer(data)) { + if(data && arguments.length > 0 && BufferUtils.isBuffer(data)) { var encoding = this.encoding; result.encoding = encoding ? (encoding + '/base64') : 'base64'; data = BufferUtils.base64Encode(data); @@ -4477,10 +4477,12 @@ var Message = (function() { }; Message.encode = function(msg, options) { - var data = msg.data, encoding; - if(typeof(data) != 'string' && !BufferUtils.isBuffer(data)) { - msg.data = JSON.stringify(data); - msg.encoding = (encoding = msg.encoding) ? (encoding + '/json') : 'json'; + if(msg.data){ + var data = msg.data, encoding; + if(typeof(data) != 'string' && !BufferUtils.isBuffer(data)) { + msg.data = JSON.stringify(data); + msg.encoding = (encoding = msg.encoding) ? (encoding + '/json') : 'json'; + } } if(options != null && options.encrypted) Message.encrypt(msg, options); @@ -4592,7 +4594,6 @@ var PresenceMessage = (function() { */ PresenceMessage.prototype.toJSON = function() { var result = { - name: this.name, clientId: this.clientId, connectionId: this.connectionId, timestamp: this.timestamp, @@ -4604,7 +4605,7 @@ var PresenceMessage = (function() { * although msgpack calls toJSON(), we know it is a stringify() * call if it passes on the stringify arguments */ var data = this.data; - if(arguments.length > 0 && BufferUtils.isBuffer(data)) { + if(data && arguments.length > 0 && BufferUtils.isBuffer(data)) { var encoding = this.encoding; result.encoding = encoding ? (encoding + '/base64') : 'base64'; data = data.toString('base64'); @@ -7652,16 +7653,16 @@ var Presence = (function() { Utils.inherits(Presence, EventEmitter); Presence.prototype.enter = function(data, callback) { - if (!callback && (typeof(data)==='function')) { - callback = data; - data = ''; - } if(!this.clientId) throw new Error('clientId must be specified to enter a presence channel'); this.enterClient(this.clientId, data, callback); }; Presence.prototype.enterClient = function(clientId, data, callback) { + if (!callback && (typeof(data)==='function')) { + callback = data; + data = null; + } Logger.logAction(Logger.LOG_MICRO, 'Presence.enterClient()', 'entering; channel = ' + this.channel.name + ', client = ' + clientId); var presence = PresenceMessage.fromValues({ action : presenceAction.ENTER, diff --git a/browser/static/ably.noencryption.js b/browser/static/ably.noencryption.js index d04e4162cb..153fc1d84a 100644 --- a/browser/static/ably.noencryption.js +++ b/browser/static/ably.noencryption.js @@ -3075,11 +3075,11 @@ var Message = (function() { encoding: this.encoding }; - /* encode to base64 if we're returning real JSON; + /* encode data to base64 if present and we're returning real JSON; * although msgpack calls toJSON(), we know it is a stringify() * call if it has a non-empty arguments list */ var data = this.data; - if(arguments.length > 0 && BufferUtils.isBuffer(data)) { + if(data && arguments.length > 0 && BufferUtils.isBuffer(data)) { var encoding = this.encoding; result.encoding = encoding ? (encoding + '/base64') : 'base64'; data = BufferUtils.base64Encode(data); @@ -3129,10 +3129,12 @@ var Message = (function() { }; Message.encode = function(msg, options) { - var data = msg.data, encoding; - if(typeof(data) != 'string' && !BufferUtils.isBuffer(data)) { - msg.data = JSON.stringify(data); - msg.encoding = (encoding = msg.encoding) ? (encoding + '/json') : 'json'; + if(msg.data){ + var data = msg.data, encoding; + if(typeof(data) != 'string' && !BufferUtils.isBuffer(data)) { + msg.data = JSON.stringify(data); + msg.encoding = (encoding = msg.encoding) ? (encoding + '/json') : 'json'; + } } if(options != null && options.encrypted) Message.encrypt(msg, options); @@ -3244,7 +3246,6 @@ var PresenceMessage = (function() { */ PresenceMessage.prototype.toJSON = function() { var result = { - name: this.name, clientId: this.clientId, connectionId: this.connectionId, timestamp: this.timestamp, @@ -3256,7 +3257,7 @@ var PresenceMessage = (function() { * although msgpack calls toJSON(), we know it is a stringify() * call if it passes on the stringify arguments */ var data = this.data; - if(arguments.length > 0 && BufferUtils.isBuffer(data)) { + if(data && arguments.length > 0 && BufferUtils.isBuffer(data)) { var encoding = this.encoding; result.encoding = encoding ? (encoding + '/base64') : 'base64'; data = data.toString('base64'); @@ -6304,16 +6305,16 @@ var Presence = (function() { Utils.inherits(Presence, EventEmitter); Presence.prototype.enter = function(data, callback) { - if (!callback && (typeof(data)==='function')) { - callback = data; - data = ''; - } if(!this.clientId) throw new Error('clientId must be specified to enter a presence channel'); this.enterClient(this.clientId, data, callback); }; Presence.prototype.enterClient = function(clientId, data, callback) { + if (!callback && (typeof(data)==='function')) { + callback = data; + data = null; + } Logger.logAction(Logger.LOG_MICRO, 'Presence.enterClient()', 'entering; channel = ' + this.channel.name + ', client = ' + clientId); var presence = PresenceMessage.fromValues({ action : presenceAction.ENTER, diff --git a/spec/support/browser_file_list.js b/spec/support/browser_file_list.js index 33df9823a8..4822eb9a53 100644 --- a/spec/support/browser_file_list.js +++ b/spec/support/browser_file_list.js @@ -1,2 +1,2 @@ window.__karma__ = { base: '../' }; -window.__karma__.files = {"browser/static/ably.js":true,"browser/static/ably.min.js":true,"browser/static/ably.noencryption.js":true,"browser/static/ably.noencryption.min.js":true,"browser/static/compat-pubnub.js":true,"browser/static/compat-pubnub.min.js":true,"browser/static/compat-pusher.js":true,"browser/static/compat-pusher.min.js":true,"browser/static/iframe.js":true,"browser/static/iframe.min.js":true,"browser/static/iframe-0.7.9.html":true,"browser/static/iframe.min-0.7.9.html":true,"browser/lib/util/base64.js":true,"node_modules/async/lib/async.js":true,"spec/common/globals/environment.js":true,"spec/common/globals/named_dependencies.js":true,"spec/common/modules/client_module.js":true,"spec/common/modules/shared_helper.js":true,"spec/common/modules/testapp_manager.js":true,"spec/common/modules/testapp_module.js":true,"spec/common/modules/testdata_module.js":true,"spec/support/browser_file_list.js":true,"spec/support/browser_setup.js":true,"spec/support/environment.vars.js":true,"spec/support/modules_helper.js":true,"spec/support/tear_down.js":true,"spec/support/test_helper.js":true,"spec/realtime/assets/crypto-data-128.json":true,"spec/realtime/assets/crypto-data-256.json":true,"spec/realtime/auth.test.js":true,"spec/realtime/channel.test.js":true,"spec/realtime/crypto.test.js":true,"spec/realtime/init.test.js":true,"spec/realtime/message.test.js":true,"spec/realtime/presence.test.js":true,"spec/realtime/resume.test.js":true,"spec/realtime/upgrade.test.js":true,"spec/rest/auth.test.js":true,"spec/rest/capability.test.js":true,"spec/rest/defaults.test.js":true,"spec/rest/history.test.js":true,"spec/rest/init.test.js":true,"spec/rest/stats.test.js":true,"spec/rest/time.test.js":true,"spec/browser/simple.test.js":true}; \ No newline at end of file +window.__karma__.files = {"browser/static/ably.js":true,"browser/static/ably.min.js":true,"browser/static/ably.noencryption.js":true,"browser/static/ably.noencryption.min.js":true,"browser/static/compat-pubnub.js":true,"browser/static/compat-pubnub.min.js":true,"browser/static/compat-pusher.js":true,"browser/static/compat-pusher.min.js":true,"browser/static/iframe.js":true,"browser/static/iframe.min.js":true,"browser/static/iframe-0.8.0.html":true,"browser/static/iframe.min-0.8.0.html":true,"browser/lib/util/base64.js":true,"node_modules/async/lib/async.js":true,"spec/common/globals/environment.js":true,"spec/common/globals/named_dependencies.js":true,"spec/common/modules/client_module.js":true,"spec/common/modules/shared_helper.js":true,"spec/common/modules/testapp_manager.js":true,"spec/common/modules/testapp_module.js":true,"spec/common/modules/testdata_module.js":true,"spec/support/browser_file_list.js":true,"spec/support/browser_setup.js":true,"spec/support/environment.vars.js":true,"spec/support/modules_helper.js":true,"spec/support/tear_down.js":true,"spec/support/test_helper.js":true,"spec/realtime/assets/crypto-data-128.json":true,"spec/realtime/assets/crypto-data-256.json":true,"spec/realtime/auth.test.js":true,"spec/realtime/channel.test.js":true,"spec/realtime/crypto.test.js":true,"spec/realtime/init.test.js":true,"spec/realtime/message.test.js":true,"spec/realtime/presence.test.js":true,"spec/realtime/resume.test.js":true,"spec/realtime/upgrade.test.js":true,"spec/rest/auth.test.js":true,"spec/rest/capability.test.js":true,"spec/rest/defaults.test.js":true,"spec/rest/history.test.js":true,"spec/rest/init.test.js":true,"spec/rest/stats.test.js":true,"spec/rest/time.test.js":true,"spec/browser/simple.test.js":true}; \ No newline at end of file From 448b73f4824e5afdf1e99e0807f5c465f5a09d2a Mon Sep 17 00:00:00 2001 From: Simon Woolf Date: Tue, 12 May 2015 10:13:14 +0100 Subject: [PATCH 6/8] fixup! Allow message and presencemessage to work without data --- common/lib/types/message.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/common/lib/types/message.js b/common/lib/types/message.js index 9bd5eec052..186b589e84 100644 --- a/common/lib/types/message.js +++ b/common/lib/types/message.js @@ -78,12 +78,10 @@ var Message = (function() { }; Message.encode = function(msg, options) { - if(msg.data){ - var data = msg.data, encoding; - if(typeof(data) != 'string' && !BufferUtils.isBuffer(data)) { - msg.data = JSON.stringify(data); - msg.encoding = (encoding = msg.encoding) ? (encoding + '/json') : 'json'; - } + var data = msg.data, encoding; + if(data && typeof(data) != 'string' && !BufferUtils.isBuffer(data)) { + msg.data = JSON.stringify(data); + msg.encoding = (encoding = msg.encoding) ? (encoding + '/json') : 'json'; } if(options != null && options.encrypted) Message.encrypt(msg, options); From 00e46b5b654da1e43ac68ba58733951a32d788fd Mon Sep 17 00:00:00 2001 From: Simon Woolf Date: Tue, 12 May 2015 10:39:01 +0100 Subject: [PATCH 7/8] fixup! Add specs for variations of calling channel#publish & presence#enter --- spec/realtime/message.test.js | 69 ++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/spec/realtime/message.test.js b/spec/realtime/message.test.js index ab6fb68346..565751a821 100644 --- a/spec/realtime/message.test.js +++ b/spec/realtime/message.test.js @@ -68,8 +68,38 @@ define(['ably', 'shared_helper'], function(Ably, helper) { exports.publishVariations = function(test) { var transport = 'binary'; + var testData = 'Some data' + var errorCallback = function(err){ + if(err) { + test.ok(false, 'Error received by publish callback ' + err); + test.done(); + realtime.close(); + return; + } + }; + var testArguments = [ + [{name: 'objectWithName'}], + [{name: 'objectWithNameAndCallback'}, errorCallback], + [{name: 'objectWithNameAndNullData', data: null}], + [{name: 'objectWithNameAndUndefinedData', data: undefined}], + [{name: 'objectWithNameAndEmptyStringData', data: ''}], + ['nameAndNullData', null], + ['nameAndUndefinedData', undefined], + ['nameAndEmptyStringData', ''], + ['nameAndData', testData], + ['nameAndDataAndCallback', testData, errorCallback], + [{name: 'objectWithNameAndData', data: testData}], + [{name: 'objectWithNameAndDataAndCallback', data: testData}, errorCallback], + // 6 messages with null name, + [null, testData], + [null, testData, errorCallback], + [{name: null, data: testData}], + [null, null], + [{name: null}], + [{name: null, data: null}] + ]; - test.expect(32); + test.expect(testArguments.length * 2); try { /* set up realtime */ var realtime = helper.AblyRealtime(); @@ -78,15 +108,6 @@ define(['ably', 'shared_helper'], function(Ably, helper) { /* connect and attach */ realtime.connection.on('connected', function() { var rtChannel = realtime.channels.get('publishVariations'); - var testData = 'Some data' - var errorCallback = function(err){ - if(err) { - test.ok(false, 'Error received by publish callback ' + err); - test.done(); - realtime.close(); - return; - } - } rtChannel.attach(function(err) { if(err) { test.ok(false, 'Attach failed with error: ' + err); @@ -109,6 +130,10 @@ define(['ably', 'shared_helper'], function(Ably, helper) { case 'nameAndUndefinedData': test.equal(typeof(msg.data), 'undefined', 'Msg data was received where none expected'); break; + case 'nameAndEmptyStringData': + case 'objectWithNameAndEmptyStringData': + test.strictEqual(msg.data, '', 'Msg data received was a ' + typeof(msg.data) + ' when should have been an empty string'); + break; case 'nameAndData': case 'nameAndDataAndCallback': case 'objectWithNameAndData': @@ -123,14 +148,14 @@ define(['ably', 'shared_helper'], function(Ably, helper) { // 3 messages: null name and null data, object with null name and no data, object with null name and null data test.equal(typeof(msg.data), 'undefined', 'Msg data was received where none expected'); } - break; + break; default: test.ok(false, 'Unexpected message ' + msg.name + 'received'); test.done(); realtime.close(); } - if (messagesReceived == 16) { + if (messagesReceived == testArguments.length) { test.done(); realtime.close(); } @@ -138,23 +163,9 @@ define(['ably', 'shared_helper'], function(Ably, helper) { /* publish events */ var restChannel = rest.channels.get('publishVariations'); - restChannel.publish({name: 'objectWithName'}); - restChannel.publish({name: 'objectWithNameAndCallback'}, errorCallback); - restChannel.publish({name: 'objectWithNameAndNullData', data: null}); - restChannel.publish({name: 'objectWithNameAndUndefinedData', data: undefined}); - restChannel.publish('nameAndNullData', null); - restChannel.publish('nameAndUndefinedData', undefined); - restChannel.publish('nameAndData', testData); - restChannel.publish('nameAndDataAndCallback', testData, errorCallback); - restChannel.publish({name: 'objectWithNameAndData', data: testData}); - restChannel.publish({name: 'objectWithNameAndDataAndCallback', data: testData}, errorCallback); - // 6 messages with null name: - restChannel.publish(null, testData); - restChannel.publish(null, testData, errorCallback); - restChannel.publish({name: null, data: testData}); - restChannel.publish(null, null); - restChannel.publish({name: null}); - restChannel.publish({name: null, data: null}); + for(var i = 0; i < testArguments.length; i++) { + restChannel.publish.apply(restChannel, testArguments[i]); + } }); }); var exitOnState = function(state) { From a2e615b5753240016f0d9a3cae242ef0e7e64a78 Mon Sep 17 00:00:00 2001 From: Simon Woolf Date: Tue, 12 May 2015 10:39:33 +0100 Subject: [PATCH 8/8] fixup! Regenerated --- browser/static/ably.js | 10 ++++------ browser/static/ably.noencryption.js | 10 ++++------ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/browser/static/ably.js b/browser/static/ably.js index bb100a4046..9329a95c8a 100644 --- a/browser/static/ably.js +++ b/browser/static/ably.js @@ -4477,12 +4477,10 @@ var Message = (function() { }; Message.encode = function(msg, options) { - if(msg.data){ - var data = msg.data, encoding; - if(typeof(data) != 'string' && !BufferUtils.isBuffer(data)) { - msg.data = JSON.stringify(data); - msg.encoding = (encoding = msg.encoding) ? (encoding + '/json') : 'json'; - } + var data = msg.data, encoding; + if(data && typeof(data) != 'string' && !BufferUtils.isBuffer(data)) { + msg.data = JSON.stringify(data); + msg.encoding = (encoding = msg.encoding) ? (encoding + '/json') : 'json'; } if(options != null && options.encrypted) Message.encrypt(msg, options); diff --git a/browser/static/ably.noencryption.js b/browser/static/ably.noencryption.js index 153fc1d84a..a61dfaef98 100644 --- a/browser/static/ably.noencryption.js +++ b/browser/static/ably.noencryption.js @@ -3129,12 +3129,10 @@ var Message = (function() { }; Message.encode = function(msg, options) { - if(msg.data){ - var data = msg.data, encoding; - if(typeof(data) != 'string' && !BufferUtils.isBuffer(data)) { - msg.data = JSON.stringify(data); - msg.encoding = (encoding = msg.encoding) ? (encoding + '/json') : 'json'; - } + var data = msg.data, encoding; + if(data && typeof(data) != 'string' && !BufferUtils.isBuffer(data)) { + msg.data = JSON.stringify(data); + msg.encoding = (encoding = msg.encoding) ? (encoding + '/json') : 'json'; } if(options != null && options.encrypted) Message.encrypt(msg, options);