pusher-fake 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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