pusher-fake 0.1.4 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  When %{a "$event" event is triggered on the "$channel" channel} do |event, channel|
2
- Pusher[channel].trigger(event, {})
2
+ Pusher.trigger([channel], event, {})
3
3
  end
4
4
 
5
5
  When %{I trigger the "$event" event on the "$channel" channel} do |event, channel|
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Pusher JavaScript Library v1.12.1
2
+ * Pusher JavaScript Library v1.12.5
3
3
  * http://pusherapp.com/
4
4
  *
5
5
  * Copyright 2011, Pusher
@@ -183,11 +183,17 @@
183
183
  };
184
184
 
185
185
  // Pusher defaults
186
- Pusher.VERSION = '1.12.1';
187
-
186
+ Pusher.VERSION = '1.12.5';
187
+ // WS connection parameters
188
188
  Pusher.host = 'ws.pusherapp.com';
189
189
  Pusher.ws_port = 80;
190
190
  Pusher.wss_port = 443;
191
+ // SockJS fallback parameters
192
+ Pusher.sockjs_host = 'sockjs.pusher.com';
193
+ Pusher.sockjs_http_port = 80
194
+ Pusher.sockjs_https_port = 443
195
+ Pusher.sockjs_path = "/pusher"
196
+ // Other settings
191
197
  Pusher.channel_auth_endpoint = '/pusher/auth';
192
198
  Pusher.cdn_http = 'http://js.pusher.com/'
193
199
  Pusher.cdn_https = 'https://d3dy5gmtp8yhk7.cloudfront.net/'
@@ -220,44 +226,67 @@ Example:
220
226
  emitter.bind('foo_event', function(data){ alert(data)} );
221
227
 
222
228
  // Bind to all
223
- emitter.bind_all(function(event_name, data){ alert(data) });
229
+ emitter.bind_all(function(eventName, data){ alert(data) });
224
230
 
225
231
  --------------------------------------------------------*/
232
+
233
+ function CallbackRegistry() {
234
+ this._callbacks = {};
235
+ };
236
+
237
+ CallbackRegistry.prototype.get = function(eventName) {
238
+ return this._callbacks[this._prefix(eventName)];
239
+ };
240
+
241
+ CallbackRegistry.prototype.add = function(eventName, callback) {
242
+ var prefixedEventName = this._prefix(eventName);
243
+ this._callbacks[prefixedEventName] = this._callbacks[prefixedEventName] || [];
244
+ this._callbacks[prefixedEventName].push(callback);
245
+ };
246
+
247
+ CallbackRegistry.prototype.remove = function(eventName, callback) {
248
+ if(this.get(eventName)) {
249
+ var index = Pusher.Util.arrayIndexOf(this.get(eventName), callback);
250
+ this._callbacks[this._prefix(eventName)].splice(index, 1);
251
+ }
252
+ };
253
+
254
+ CallbackRegistry.prototype._prefix = function(eventName) {
255
+ return "_" + eventName;
256
+ };
257
+
258
+
226
259
  function EventsDispatcher(failThrough) {
227
- this.callbacks = {};
260
+ this.callbacks = new CallbackRegistry();
228
261
  this.global_callbacks = [];
229
262
  // Run this function when dispatching an event when no callbacks defined
230
263
  this.failThrough = failThrough;
231
264
  }
232
265
 
233
- EventsDispatcher.prototype.bind = function(event_name, callback) {
234
- this.callbacks[event_name] = this.callbacks[event_name] || [];
235
- this.callbacks[event_name].push(callback);
266
+ EventsDispatcher.prototype.bind = function(eventName, callback) {
267
+ this.callbacks.add(eventName, callback);
236
268
  return this;// chainable
237
269
  };
238
-
270
+
239
271
  EventsDispatcher.prototype.unbind = function(eventName, callback) {
240
- if(this.callbacks[eventName]) {
241
- var index = Pusher.Util.arrayIndexOf(this.callbacks[eventName], callback);
242
- this.callbacks[eventName].splice(index, 1);
243
- }
272
+ this.callbacks.remove(eventName, callback);
244
273
  return this;
245
274
  };
246
275
 
247
- EventsDispatcher.prototype.emit = function(event_name, data) {
276
+ EventsDispatcher.prototype.emit = function(eventName, data) {
248
277
  // Global callbacks
249
278
  for (var i = 0; i < this.global_callbacks.length; i++) {
250
- this.global_callbacks[i](event_name, data);
279
+ this.global_callbacks[i](eventName, data);
251
280
  }
252
281
 
253
282
  // Event callbacks
254
- var callbacks = this.callbacks[event_name];
283
+ var callbacks = this.callbacks.get(eventName);
255
284
  if (callbacks) {
256
285
  for (var i = 0; i < callbacks.length; i++) {
257
286
  callbacks[i](data);
258
287
  }
259
288
  } else if (this.failThrough) {
260
- this.failThrough(event_name, data)
289
+ this.failThrough(eventName, data)
261
290
  }
262
291
 
263
292
  return this;
@@ -402,32 +431,30 @@ Example:
402
431
  'connected': ['permanentlyClosing', 'waiting'],
403
432
  'impermanentlyClosing': ['waiting', 'permanentlyClosing'],
404
433
  'permanentlyClosing': ['permanentlyClosed'],
405
- 'permanentlyClosed': ['waiting'],
434
+ 'permanentlyClosed': ['waiting', 'failed'],
406
435
  'failed': ['permanentlyClosed']
407
436
  };
408
437
 
409
438
 
410
- // Amount to add to time between connection attemtpts per failed attempt.
411
- var UNSUCCESSFUL_CONNECTION_ATTEMPT_ADDITIONAL_WAIT = 2000;
412
- var UNSUCCESSFUL_OPEN_ATTEMPT_ADDITIONAL_TIMEOUT = 2000;
413
- var UNSUCCESSFUL_CONNECTED_ATTEMPT_ADDITIONAL_TIMEOUT = 2000;
439
+ var OPEN_TIMEOUT_INCREMENT = 2000;
440
+ var CONNECTED_TIMEOUT_INCREMENT = 2000;
414
441
 
415
- var MAX_CONNECTION_ATTEMPT_WAIT = 5 * UNSUCCESSFUL_CONNECTION_ATTEMPT_ADDITIONAL_WAIT;
416
- var MAX_OPEN_ATTEMPT_TIMEOUT = 5 * UNSUCCESSFUL_OPEN_ATTEMPT_ADDITIONAL_TIMEOUT;
417
- var MAX_CONNECTED_ATTEMPT_TIMEOUT = 5 * UNSUCCESSFUL_CONNECTED_ATTEMPT_ADDITIONAL_TIMEOUT;
442
+ var MAX_OPEN_TIMEOUT = 10000;
443
+ var MAX_CONNECTED_TIMEOUT = 10000;
418
444
 
419
445
  function resetConnectionParameters(connection) {
420
446
  connection.connectionWait = 0;
421
447
 
422
- if (Pusher.TransportType === 'flash') {
423
- // Flash needs a bit more time
424
- connection.openTimeout = 5000;
425
- } else {
426
- connection.openTimeout = 2000;
448
+ if (Pusher.TransportType === 'native') {
449
+ connection.openTimeout = 4000;
450
+ } else if (Pusher.TransportType === 'flash') {
451
+ connection.openTimeout = 7000;
452
+ } else { // SockJS
453
+ connection.openTimeout = 6000;
427
454
  }
428
455
  connection.connectedTimeout = 2000;
429
456
  connection.connectionSecure = connection.compulsorySecure;
430
- connection.connectionAttempts = 0;
457
+ connection.failedAttempts = 0;
431
458
  }
432
459
 
433
460
  function Connection(key, options) {
@@ -435,6 +462,7 @@ Example:
435
462
 
436
463
  Pusher.EventsDispatcher.call(this);
437
464
 
465
+ this.ping = true
438
466
  this.options = Pusher.Util.extend({encrypted: false}, options);
439
467
 
440
468
  this.netInfo = new Pusher.NetInfo();
@@ -474,22 +502,25 @@ Example:
474
502
  },
475
503
 
476
504
  waitingPre: function() {
477
- if (self.connectionWait > 0) {
478
- self.emit('connecting_in', self.connectionWait);
479
- }
505
+ if (self.netInfo.isOnLine()) {
506
+ if (self.failedAttempts < 2) {
507
+ updateState('connecting');
508
+ } else {
509
+ updateState('unavailable');
510
+ // Delay 10s between connection attempts on entering unavailable
511
+ self.connectionWait = 10000;
512
+ }
480
513
 
481
- if (self.netInfo.isOnLine() && self.connectionAttempts <= 4) {
482
- updateState('connecting');
483
- } else {
484
- updateState('unavailable');
485
- }
514
+ if (self.connectionWait > 0) {
515
+ self.emit('connecting_in', connectionDelay());
516
+ }
486
517
 
487
- // When in the unavailable state we attempt to connect, but don't
488
- // broadcast that fact
489
- if (self.netInfo.isOnLine()) {
490
518
  self._waitingTimer = setTimeout(function() {
519
+ // Even when unavailable we try connecting (not changing state)
491
520
  self._machine.transition('connecting');
492
521
  }, connectionDelay());
522
+ } else {
523
+ updateState('unavailable');
493
524
  }
494
525
  },
495
526
 
@@ -507,12 +538,27 @@ Example:
507
538
  return;
508
539
  }
509
540
 
510
- var url = formatURL(self.key, self.connectionSecure);
511
- Pusher.debug('Connecting', url);
512
- self.socket = new Pusher.Transport(url);
513
- // now that the socket connection attempt has been started,
514
- // set up the callbacks fired by the socket for different outcomes
515
- self.socket.onopen = ws_onopen;
541
+ var path = connectPath(self.key);
542
+ if (Pusher.TransportType === 'sockjs') {
543
+ Pusher.debug('Connecting to sockjs', Pusher.sockjs);
544
+ var url = buildSockJSURL(self.connectionSecure);
545
+
546
+ self.ping = false
547
+ self.socket = new SockJS(url);
548
+ self.socket.onopen = function() {
549
+ // SockJS does not yet support custom paths and query params
550
+ self.socket.send(JSON.stringify({path: path}));
551
+ self._machine.transition('open');
552
+ }
553
+ } else {
554
+ var url = connectBaseURL(self.connectionSecure) + path;
555
+ Pusher.debug('Connecting', url);
556
+ self.socket = new Pusher.Transport(url);
557
+ self.socket.onopen = function() {
558
+ self._machine.transition('open');
559
+ }
560
+ }
561
+
516
562
  self.socket.onclose = transitionToWaiting;
517
563
  self.socket.onerror = ws_onError;
518
564
 
@@ -616,44 +662,45 @@ Example:
616
662
  -----------------------------------------------*/
617
663
 
618
664
  function updateConnectionParameters() {
619
- if (self.connectionWait < MAX_CONNECTION_ATTEMPT_WAIT) {
620
- self.connectionWait += UNSUCCESSFUL_CONNECTION_ATTEMPT_ADDITIONAL_WAIT;
621
- }
622
-
623
- if (self.openTimeout < MAX_OPEN_ATTEMPT_TIMEOUT) {
624
- self.openTimeout += UNSUCCESSFUL_OPEN_ATTEMPT_ADDITIONAL_TIMEOUT;
665
+ if (self.openTimeout < MAX_OPEN_TIMEOUT) {
666
+ self.openTimeout += OPEN_TIMEOUT_INCREMENT;
625
667
  }
626
668
 
627
- if (self.connectedTimeout < MAX_CONNECTED_ATTEMPT_TIMEOUT) {
628
- self.connectedTimeout += UNSUCCESSFUL_CONNECTED_ATTEMPT_ADDITIONAL_TIMEOUT;
669
+ if (self.connectedTimeout < MAX_CONNECTED_TIMEOUT) {
670
+ self.connectedTimeout += CONNECTED_TIMEOUT_INCREMENT;
629
671
  }
630
672
 
673
+ // Toggle between ws & wss
631
674
  if (self.compulsorySecure !== true) {
632
675
  self.connectionSecure = !self.connectionSecure;
633
676
  }
634
677
 
635
- self.connectionAttempts++;
678
+ self.failedAttempts++;
636
679
  }
637
680
 
638
- function formatURL(key, isSecure) {
639
- var port = Pusher.ws_port;
640
- var protocol = 'ws://';
641
-
642
- // Always connect with SSL if the current page has
643
- // been loaded via HTTPS.
644
- //
645
- // FUTURE: Always connect using SSL.
646
- //
647
- if (isSecure || document.location.protocol === 'https:') {
648
- port = Pusher.wss_port;
649
- protocol = 'wss://';
650
- }
681
+ function connectBaseURL(isSecure) {
682
+ // Always connect with SSL if the current page served over https
683
+ var ssl = (isSecure || document.location.protocol === 'https:');
684
+ var port = ssl ? Pusher.wss_port : Pusher.ws_port;
685
+ var scheme = ssl ? 'wss://' : 'ws://';
651
686
 
652
- var flash = (Pusher.TransportType === "flash") ? "true" : "false";
687
+ return scheme + Pusher.host + ':' + port;
688
+ }
653
689
 
654
- return protocol + Pusher.host + ':' + port + '/app/' + key + '?protocol=5&client=js'
690
+ function connectPath(key) {
691
+ var flash = (Pusher.TransportType === "flash") ? "true" : "false";
692
+ var path = '/app/' + key + '?protocol=5&client=js'
655
693
  + '&version=' + Pusher.VERSION
656
694
  + '&flash=' + flash;
695
+ return path;
696
+ }
697
+
698
+ function buildSockJSURL(isSecure) {
699
+ var ssl = (isSecure || document.location.protocol === 'https:');
700
+ var port = ssl ? Pusher.sockjs_https_port : Pusher.sockjs_http_port;
701
+ var scheme = ssl ? 'https://' : 'http://';
702
+
703
+ return scheme + Pusher.sockjs_host + ':' + port + Pusher.sockjs_path;
657
704
  }
658
705
 
659
706
  // callback for close and retry. Used on timeouts.
@@ -664,13 +711,15 @@ Example:
664
711
  function resetActivityCheck() {
665
712
  if (self._activityTimer) { clearTimeout(self._activityTimer); }
666
713
  // Send ping after inactivity
667
- self._activityTimer = setTimeout(function() {
668
- self.send_event('pusher:ping', {})
669
- // Wait for pong response
714
+ if (self.ping) {
670
715
  self._activityTimer = setTimeout(function() {
671
- self.socket.close();
672
- }, (self.options.pong_timeout || Pusher.pong_timeout))
673
- }, (self.options.activity_timeout || Pusher.activity_timeout))
716
+ self.send_event('pusher:ping', {})
717
+ // Wait for pong response
718
+ self._activityTimer = setTimeout(function() {
719
+ self.socket.close();
720
+ }, (self.options.pong_timeout || Pusher.pong_timeout))
721
+ }, (self.options.activity_timeout || Pusher.activity_timeout))
722
+ }
674
723
  }
675
724
 
676
725
  function stopActivityCheck() {
@@ -700,11 +749,6 @@ Example:
700
749
  WebSocket Callbacks
701
750
  -----------------------------------------------*/
702
751
 
703
- // no-op, as we only care when we get pusher:connection_established
704
- function ws_onopen() {
705
- self._machine.transition('open');
706
- };
707
-
708
752
  function handleCloseCode(code, message) {
709
753
  // first inform the end-developer of this error
710
754
  self.emit('error', {type: 'PusherError', data: {code: code, message: message}});
@@ -819,7 +863,7 @@ Example:
819
863
 
820
864
  Connection.prototype.connect = function() {
821
865
  // no WebSockets
822
- if (Pusher.Transport === null || Pusher.Transport === undefined) {
866
+ if (!this._machine.is('failed') && !Pusher.Transport) {
823
867
  this._machine.transition('failed');
824
868
  }
825
869
  // initial open of connection
@@ -840,17 +884,12 @@ Example:
840
884
 
841
885
  Connection.prototype.send = function(data) {
842
886
  if (this._machine.is('connected')) {
843
- // Bug in iOS (reproduced in 5.0.1) Mobile Safari:
844
- // 1. Open page/tab, connect WS, get some data.
845
- // 2. Switch tab or close Mobile Safari and wait for WS connection to get closed (probably by server).
846
- // 3. Switch back to tab or open Mobile Safari and Mobile Safari crashes.
847
- // The problem is that WS tries to send data on closed WS connection before it realises it is closed.
848
- // The timeout means that by the time the send happens, the WS readyState correctly reflects closed state.
887
+ // Workaround for MobileSafari bug (see https://gist.github.com/2052006)
849
888
  var self = this;
850
889
  setTimeout(function() {
851
890
  self.socket.send(data);
852
891
  }, 0);
853
- return true; // only a reflection of fact that WS thinks it is open - could get returned before some lower-level failure.
892
+ return true;
854
893
  } else {
855
894
  return false;
856
895
  }
@@ -1145,73 +1184,83 @@ Example:
1145
1184
  }
1146
1185
  };
1147
1186
  }).call(this);
1148
- var _require = (function () {
1149
-
1150
- var handleScriptLoaded;
1151
- if (document.addEventListener) {
1152
- handleScriptLoaded = function (elem, callback) {
1153
- elem.addEventListener('load', callback, false)
1154
- }
1155
- } else {
1156
- handleScriptLoaded = function(elem, callback) {
1187
+ // _require(dependencies, callback) takes an array of dependency urls and a
1188
+ // callback to call when all the dependecies have finished loading
1189
+ var _require = (function() {
1190
+ function handleScriptLoaded(elem, callback) {
1191
+ if (document.addEventListener) {
1192
+ elem.addEventListener('load', callback, false);
1193
+ } else {
1157
1194
  elem.attachEvent('onreadystatechange', function () {
1158
- if(elem.readyState == 'loaded' || elem.readyState == 'complete') callback()
1159
- })
1195
+ if (elem.readyState == 'loaded' || elem.readyState == 'complete') {
1196
+ callback();
1197
+ }
1198
+ });
1160
1199
  }
1161
1200
  }
1162
1201
 
1163
- return function (deps, callback) {
1164
- var dep_count = 0,
1165
- dep_length = deps.length;
1202
+ function addScript(src, callback) {
1203
+ var head = document.getElementsByTagName('head')[0];
1204
+ var script = document.createElement('script');
1205
+ script.setAttribute('src', src);
1206
+ script.setAttribute("type","text/javascript");
1207
+ script.setAttribute('async', true);
1166
1208
 
1167
- function checkReady (callback) {
1168
- dep_count++;
1169
- if ( dep_length == dep_count ) {
1170
- // Opera needs the timeout for page initialization weirdness
1171
- setTimeout(callback, 0);
1172
- }
1173
- }
1209
+ handleScriptLoaded(script, function() {
1210
+ callback();
1211
+ });
1174
1212
 
1175
- function addScript (src, callback) {
1176
- callback = callback || function(){}
1177
- var head = document.getElementsByTagName('head')[0];
1178
- var script = document.createElement('script');
1179
- script.setAttribute('src', src);
1180
- script.setAttribute("type","text/javascript");
1181
- script.setAttribute('async', true);
1213
+ head.appendChild(script);
1214
+ }
1182
1215
 
1183
- handleScriptLoaded(script, function () {
1184
- checkReady(callback);
1216
+ return function(deps, callback) {
1217
+ var deps_loaded = 0;
1218
+ for (var i = 0; i < deps.length; i++) {
1219
+ addScript(deps[i], function() {
1220
+ if (deps.length == ++deps_loaded) {
1221
+ // This setTimeout is a workaround for an Opera issue
1222
+ setTimeout(callback, 0);
1223
+ }
1185
1224
  });
1186
-
1187
- head.appendChild(script);
1188
- }
1189
-
1190
- for(var i = 0; i < dep_length; i++) {
1191
- addScript(deps[i], callback);
1192
1225
  }
1193
1226
  }
1194
1227
  })();
1195
1228
 
1196
1229
  ;(function() {
1230
+ // Support Firefox versions which prefix WebSocket
1231
+ if (!window['WebSocket'] && window['MozWebSocket']) {
1232
+ window['WebSocket'] = window['MozWebSocket']
1233
+ }
1234
+
1235
+ if (window['WebSocket']) {
1236
+ Pusher.Transport = window['WebSocket'];
1237
+ Pusher.TransportType = 'native';
1238
+ }
1239
+
1197
1240
  var cdn = (document.location.protocol == 'http:') ? Pusher.cdn_http : Pusher.cdn_https;
1198
1241
  var root = cdn + Pusher.VERSION;
1199
1242
  var deps = [];
1200
1243
 
1201
- if (window['JSON'] === undefined) {
1244
+ if (!window['JSON']) {
1202
1245
  deps.push(root + '/json2' + Pusher.dependency_suffix + '.js');
1203
1246
  }
1204
- if (window['WebSocket'] === undefined && window['MozWebSocket'] === undefined) {
1205
- // We manually initialize web-socket-js to iron out cross browser issues
1247
+ if (!window['WebSocket']) {
1248
+ // Try to use web-socket-js (flash WebSocket emulation)
1206
1249
  window.WEB_SOCKET_DISABLE_AUTO_INITIALIZATION = true;
1250
+ window.WEB_SOCKET_SUPPRESS_CROSS_DOMAIN_SWF_ERROR = true;
1207
1251
  deps.push(root + '/flashfallback' + Pusher.dependency_suffix + '.js');
1208
1252
  }
1209
1253
 
1210
1254
  var initialize = function() {
1211
- if (window['WebSocket'] === undefined && window['MozWebSocket'] === undefined) {
1255
+ if (window['WebSocket']) {
1256
+ // Initialize function in the case that we have native WebSocket support
1257
+ return function() {
1258
+ Pusher.ready();
1259
+ }
1260
+ } else {
1261
+ // Initialize function for fallback case
1212
1262
  return function() {
1213
- // This runs after flashfallback.js has loaded
1214
- if (window['WebSocket'] !== undefined && window['MozWebSocket'] === undefined) {
1263
+ if (window['WebSocket']) {
1215
1264
  // window['WebSocket'] is a flash emulation of WebSocket
1216
1265
  Pusher.Transport = window['WebSocket'];
1217
1266
  Pusher.TransportType = 'flash';
@@ -1222,31 +1271,19 @@ var _require = (function () {
1222
1271
  })
1223
1272
  WebSocket.__initialize();
1224
1273
  } else {
1225
- // Flash must not be installed
1226
- Pusher.Transport = null;
1227
- Pusher.TransportType = 'none';
1228
- Pusher.ready();
1229
- }
1230
- }
1231
- } else {
1232
- return function() {
1233
- // This is because Mozilla have decided to
1234
- // prefix the WebSocket constructor with "Moz".
1235
- if (window['MozWebSocket'] !== undefined) {
1236
- Pusher.Transport = window['MozWebSocket'];
1237
- } else {
1238
- Pusher.Transport = window['WebSocket'];
1274
+ // web-socket-js cannot initialize (most likely flash not installed)
1275
+ sockjsPath = root + '/sockjs' + Pusher.dependency_suffix + '.js';
1276
+ _require([sockjsPath], function() {
1277
+ Pusher.Transport = SockJS;
1278
+ Pusher.TransportType = 'sockjs';
1279
+ Pusher.ready();
1280
+ })
1239
1281
  }
1240
- // We have some form of a native websocket,
1241
- // even if the constructor is prefixed:
1242
- Pusher.TransportType = 'native';
1243
-
1244
- // Initialise Pusher.
1245
- Pusher.ready();
1246
1282
  }
1247
1283
  }
1248
1284
  }();
1249
1285
 
1286
+ // Allows calling a function when the document body is available
1250
1287
  var ondocumentbody = function(callback) {
1251
1288
  var load_body = function() {
1252
1289
  document.body ? callback() : setTimeout(load_body, 0);
@@ -14,7 +14,7 @@
14
14
  </ul>
15
15
  </section>
16
16
 
17
- <script src="/javascripts/vendor/pusher-1.11.js"></script>
17
+ <script src="/javascripts/vendor/pusher-1.12.5.js"></script>
18
18
  <script>
19
19
  window.addEventListener("DOMContentLoaded", function() {
20
20
  // Use the PusherFake server.
@@ -14,7 +14,7 @@ require "pusher-fake/server/application"
14
14
 
15
15
  module PusherFake
16
16
  # The current version string.
17
- VERSION = "0.1.4"
17
+ VERSION = "0.1.5"
18
18
 
19
19
  # Call this method to modify the defaults.
20
20
  #
@@ -2,61 +2,20 @@ module PusherFake
2
2
  module Server
3
3
  class Application
4
4
  # Process an API request by emitting the event with data to the
5
- # requested channel.
5
+ # requested channels.
6
6
  #
7
7
  # @param [Hash] environment The request environment.
8
8
  # @return [Rack::Response] A successful response.
9
9
  def self.call(environment)
10
- @environment = environment
10
+ request = Rack::Request.new(environment)
11
+ event = Yajl::Parser.parse(request.body.read)
11
12
 
12
- Channel.factory(channel).emit(event, data)
13
+ event["channels"].each do |channel|
14
+ Channel.factory(channel).emit(event["name"], event["data"])
15
+ end
13
16
 
14
17
  Rack::Response.new("{}").finish
15
18
  end
16
-
17
- # Determine the channel name from the request path.
18
- #
19
- # @return [String] The channel name.
20
- def self.channel
21
- matcher = %r{/apps/#{PusherFake.configuration.app_id}/channels/(.+)/events}i
22
- matches = path.match(matcher)
23
- matches[1]
24
- end
25
-
26
- # Parse and return the event data from the request JSON.
27
- #
28
- # @return [Hash] The parsed event data.
29
- def self.data
30
- Yajl::Parser.parse(request.body.read)
31
- end
32
-
33
- # Get the environment.
34
- #
35
- # @return [Hash] The request environment.
36
- def self.environment
37
- @environment
38
- end
39
-
40
- # Get the event name from the request parameters.
41
- #
42
- # @return [String] The event name.
43
- def self.event
44
- request.params["name"]
45
- end
46
-
47
- # Get the request path from the environment.
48
- #
49
- # @return [String] The request path.
50
- def self.path
51
- environment["PATH_INFO"]
52
- end
53
-
54
- # Create a +Rack::Request+ from the environment.
55
- #
56
- # @return [Rack::Request] The request object.
57
- def self.request
58
- Rack::Request.new(environment)
59
- end
60
19
  end
61
20
  end
62
21
  end
@@ -1,35 +1,52 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe PusherFake::Server::Application, ".call" do
4
- let(:data) { mock }
5
- let(:event) { mock }
6
- let(:channel) { stub(emit: nil) }
7
- let(:response) { mock }
8
- let(:environment) { mock }
9
- let(:channel_name) { mock }
4
+ let(:body) { stub(read: json) }
5
+ let(:data) { mock }
6
+ let(:json) { mock }
7
+ let(:name) { "event-name" }
8
+ let(:event) { { "channels" => channels, "name" => name, "data" => data } }
9
+ let(:request) { stub(body: body) }
10
+ let(:channels) { ["channel-1", "channel-2"] }
11
+ let(:response) { mock }
12
+ let(:channel_1) { stub(emit: true) }
13
+ let(:channel_2) { stub(emit: true) }
14
+ let(:environment) { mock }
10
15
 
11
16
  subject { PusherFake::Server::Application }
12
17
 
13
18
  before do
14
- subject.stubs(channel: channel_name, data: data, event: event)
15
- PusherFake::Channel.stubs(factory: channel)
16
19
  response.stubs(finish: response)
20
+
21
+ Yajl::Parser.stubs(parse: event)
22
+ Rack::Request.stubs(new: request)
17
23
  Rack::Response.stubs(new: response)
24
+ PusherFake::Channel.stubs(:factory).with(channels[0]).returns(channel_1)
25
+ PusherFake::Channel.stubs(:factory).with(channels[1]).returns(channel_2)
18
26
  end
19
27
 
20
- it "assigns the environment" do
28
+ it "creates a request" do
21
29
  subject.call(environment)
22
- subject.environment.should == environment
30
+ Rack::Request.should have_received(:new).with(environment)
23
31
  end
24
32
 
25
- it "creates the channel by name" do
33
+ it "parses the request body as JSON" do
26
34
  subject.call(environment)
27
- PusherFake::Channel.should have_received(:factory).with(channel_name)
35
+ Yajl::Parser.should have_received(:parse).with(json)
28
36
  end
29
37
 
30
- it "emits the event to the channel" do
38
+ it "creates channels by name" do
31
39
  subject.call(environment)
32
- channel.should have_received(:emit).with(event, data)
40
+
41
+ channels.each do |channel|
42
+ PusherFake::Channel.should have_received(:factory).with(channel)
43
+ end
44
+ end
45
+
46
+ it "emits the event to the channels" do
47
+ subject.call(environment)
48
+ channel_1.should have_received(:emit).with(name, data)
49
+ channel_2.should have_received(:emit).with(name, data)
33
50
  end
34
51
 
35
52
  it "creates a Rack response with an empty JSON object" do
@@ -46,101 +63,3 @@ describe PusherFake::Server::Application, ".call" do
46
63
  subject.call(environment).should == response
47
64
  end
48
65
  end
49
-
50
- describe PusherFake::Server::Application, ".channel" do
51
- let(:path) { "/apps/PUSHER_APP_ID/channels/#{channel}/events" }
52
- let(:channel) { "channel-name" }
53
-
54
- subject { PusherFake::Server::Application }
55
-
56
- before do
57
- subject.stubs(path: path)
58
- end
59
-
60
- it "returns the channel name from the path" do
61
- subject.channel.should == channel
62
- end
63
-
64
- context "with a custom application ID" do
65
- let(:path) { "/apps/#{app_id}/channels/#{channel}/events" }
66
- let(:app_id) { "test-id" }
67
-
68
- before do
69
- PusherFake.configuration.app_id = app_id
70
- end
71
-
72
- it "returns the channel name from the path" do
73
- subject.channel.should == channel
74
- end
75
- end
76
- end
77
-
78
- describe PusherFake::Server::Application, ".data" do
79
- let(:data) { mock }
80
- let(:body) { stub(read: json) }
81
- let(:json) { mock }
82
- let(:request) { stub(body: body) }
83
-
84
- subject { PusherFake::Server::Application }
85
-
86
- before do
87
- subject.stubs(request: request)
88
- Yajl::Parser.stubs(parse: data)
89
- end
90
-
91
- it "parses the request body as JSON" do
92
- subject.data
93
- Yajl::Parser.should have_received(:parse).with(json)
94
- end
95
-
96
- it "returns the parsed JSON" do
97
- subject.data.should == data
98
- end
99
- end
100
-
101
- describe PusherFake::Server::Application, ".event" do
102
- let(:name) { mock }
103
- let(:params) { { "name" => name } }
104
- let(:request) { stub(params: params) }
105
-
106
- subject { PusherFake::Server::Application }
107
-
108
- before do
109
- subject.stubs(request: request)
110
- end
111
-
112
- it "creates a reqeust from the environment" do
113
- subject.event.should == name
114
- end
115
- end
116
-
117
- describe PusherFake::Server::Application, ".path" do
118
- let(:path) { mock }
119
- let(:environment) { { "PATH_INFO" => path } }
120
-
121
- subject { PusherFake::Server::Application }
122
-
123
- before do
124
- subject.stubs(environment: environment)
125
- end
126
-
127
- it "returns the path for the environment" do
128
- subject.path.should == path
129
- end
130
- end
131
-
132
- describe PusherFake::Server::Application, ".request" do
133
- let(:environment) { mock }
134
-
135
- subject { PusherFake::Server::Application }
136
-
137
- before do
138
- Rack::Request.stubs(:new)
139
- subject.stubs(environment: environment)
140
- end
141
-
142
- it "creates a reqeust from the environment" do
143
- subject.request
144
- Rack::Request.should have_received(:new).with(environment)
145
- end
146
- end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pusher-fake
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-15 00:00:00.000000000 Z
12
+ date: 2012-11-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: em-websocket
@@ -50,7 +50,7 @@ dependencies:
50
50
  requirements:
51
51
  - - '='
52
52
  - !ruby/object:Gem::Version
53
- version: 1.4.1
53
+ version: 1.5.0
54
54
  type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
@@ -58,7 +58,7 @@ dependencies:
58
58
  requirements:
59
59
  - - '='
60
60
  - !ruby/object:Gem::Version
61
- version: 1.4.1
61
+ version: 1.5.0
62
62
  - !ruby/object:Gem::Dependency
63
63
  name: yajl-ruby
64
64
  requirement: !ruby/object:Gem::Requirement
@@ -82,7 +82,7 @@ dependencies:
82
82
  requirements:
83
83
  - - '='
84
84
  - !ruby/object:Gem::Version
85
- version: 1.1.2
85
+ version: 1.2.0
86
86
  type: :development
87
87
  prerelease: false
88
88
  version_requirements: !ruby/object:Gem::Requirement
@@ -90,7 +90,7 @@ dependencies:
90
90
  requirements:
91
91
  - - '='
92
92
  - !ruby/object:Gem::Version
93
- version: 1.1.2
93
+ version: 1.2.0
94
94
  - !ruby/object:Gem::Dependency
95
95
  name: bundler
96
96
  requirement: !ruby/object:Gem::Requirement
@@ -114,7 +114,7 @@ dependencies:
114
114
  requirements:
115
115
  - - '='
116
116
  - !ruby/object:Gem::Version
117
- version: 1.1.2
117
+ version: 1.1.3
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
@@ -122,7 +122,7 @@ dependencies:
122
122
  requirements:
123
123
  - - '='
124
124
  - !ruby/object:Gem::Version
125
- version: 1.1.2
125
+ version: 1.1.3
126
126
  - !ruby/object:Gem::Dependency
127
127
  name: capybara-webkit
128
128
  requirement: !ruby/object:Gem::Requirement
@@ -130,7 +130,7 @@ dependencies:
130
130
  requirements:
131
131
  - - '='
132
132
  - !ruby/object:Gem::Version
133
- version: 0.12.1
133
+ version: 0.13.0
134
134
  type: :development
135
135
  prerelease: false
136
136
  version_requirements: !ruby/object:Gem::Requirement
@@ -138,7 +138,7 @@ dependencies:
138
138
  requirements:
139
139
  - - '='
140
140
  - !ruby/object:Gem::Version
141
- version: 0.12.1
141
+ version: 0.13.0
142
142
  - !ruby/object:Gem::Dependency
143
143
  name: cucumber
144
144
  requirement: !ruby/object:Gem::Requirement
@@ -162,7 +162,7 @@ dependencies:
162
162
  requirements:
163
163
  - - '='
164
164
  - !ruby/object:Gem::Version
165
- version: 0.9.4
165
+ version: 0.10.0
166
166
  type: :development
167
167
  prerelease: false
168
168
  version_requirements: !ruby/object:Gem::Requirement
@@ -170,7 +170,7 @@ dependencies:
170
170
  requirements:
171
171
  - - '='
172
172
  - !ruby/object:Gem::Version
173
- version: 0.9.4
173
+ version: 0.10.0
174
174
  - !ruby/object:Gem::Dependency
175
175
  name: rake
176
176
  requirement: !ruby/object:Gem::Requirement
@@ -178,7 +178,7 @@ dependencies:
178
178
  requirements:
179
179
  - - '='
180
180
  - !ruby/object:Gem::Version
181
- version: 0.9.2.2
181
+ version: 10.0.0
182
182
  type: :development
183
183
  prerelease: false
184
184
  version_requirements: !ruby/object:Gem::Requirement
@@ -186,7 +186,7 @@ dependencies:
186
186
  requirements:
187
187
  - - '='
188
188
  - !ruby/object:Gem::Version
189
- version: 0.9.2.2
189
+ version: 10.0.0
190
190
  - !ruby/object:Gem::Dependency
191
191
  name: redcarpet
192
192
  requirement: !ruby/object:Gem::Requirement
@@ -194,7 +194,7 @@ dependencies:
194
194
  requirements:
195
195
  - - '='
196
196
  - !ruby/object:Gem::Version
197
- version: 2.1.1
197
+ version: 2.2.2
198
198
  type: :development
199
199
  prerelease: false
200
200
  version_requirements: !ruby/object:Gem::Requirement
@@ -202,7 +202,7 @@ dependencies:
202
202
  requirements:
203
203
  - - '='
204
204
  - !ruby/object:Gem::Version
205
- version: 2.1.1
205
+ version: 2.2.2
206
206
  - !ruby/object:Gem::Dependency
207
207
  name: rspec
208
208
  requirement: !ruby/object:Gem::Requirement
@@ -226,7 +226,7 @@ dependencies:
226
226
  requirements:
227
227
  - - '='
228
228
  - !ruby/object:Gem::Version
229
- version: 1.3.2
229
+ version: 1.3.3
230
230
  type: :development
231
231
  prerelease: false
232
232
  version_requirements: !ruby/object:Gem::Requirement
@@ -234,7 +234,7 @@ dependencies:
234
234
  requirements:
235
235
  - - '='
236
236
  - !ruby/object:Gem::Version
237
- version: 1.3.2
237
+ version: 1.3.3
238
238
  - !ruby/object:Gem::Dependency
239
239
  name: yard
240
240
  requirement: !ruby/object:Gem::Requirement
@@ -242,7 +242,7 @@ dependencies:
242
242
  requirements:
243
243
  - - '='
244
244
  - !ruby/object:Gem::Version
245
- version: 0.8.2.1
245
+ version: 0.8.3
246
246
  type: :development
247
247
  prerelease: false
248
248
  version_requirements: !ruby/object:Gem::Requirement
@@ -250,7 +250,7 @@ dependencies:
250
250
  requirements:
251
251
  - - '='
252
252
  - !ruby/object:Gem::Version
253
- version: 0.8.2.1
253
+ version: 0.8.3
254
254
  description: A fake Pusher server for development and testing.
255
255
  email: hello@tristandunn.com
256
256
  executables: []
@@ -275,7 +275,7 @@ files:
275
275
  - features/step_definitions/event_steps.rb
276
276
  - features/step_definitions/navigation_steps.rb
277
277
  - features/step_definitions/presence_steps.rb
278
- - features/support/application/public/javascripts/vendor/pusher-1.11.js
278
+ - features/support/application/public/javascripts/vendor/pusher-1.12.5.js
279
279
  - features/support/application/views/index.erb
280
280
  - features/support/application.rb
281
281
  - features/support/environment.rb
@@ -306,7 +306,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
306
306
  version: '0'
307
307
  segments:
308
308
  - 0
309
- hash: 1370365380025237123
309
+ hash: 2596033998219902442
310
310
  required_rubygems_version: !ruby/object:Gem::Requirement
311
311
  none: false
312
312
  requirements:
@@ -315,7 +315,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
315
315
  version: '0'
316
316
  segments:
317
317
  - 0
318
- hash: 1370365380025237123
318
+ hash: 2596033998219902442
319
319
  requirements: []
320
320
  rubyforge_project:
321
321
  rubygems_version: 1.8.23
@@ -332,7 +332,7 @@ test_files:
332
332
  - features/step_definitions/event_steps.rb
333
333
  - features/step_definitions/navigation_steps.rb
334
334
  - features/step_definitions/presence_steps.rb
335
- - features/support/application/public/javascripts/vendor/pusher-1.11.js
335
+ - features/support/application/public/javascripts/vendor/pusher-1.12.5.js
336
336
  - features/support/application/views/index.erb
337
337
  - features/support/application.rb
338
338
  - features/support/environment.rb