pusher-fake 0.1.0 → 0.1.1

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.
@@ -16,11 +16,10 @@ end
16
16
  When %{I subscribe to the "$channel" channel with presence events} do |channel|
17
17
  page.execute_script(%{
18
18
  var list = document.querySelector("#presence ul"),
19
+ count = document.querySelector("#presence header h1 span"),
19
20
  channel = Pusher.instance.subscribe(#{channel.to_json});
20
21
 
21
22
  channel.bind("pusher:subscription_succeeded", function(clients) {
22
- var
23
- count = document.querySelector("#presence header h1 span");
24
23
  count.innerHTML = clients.count;
25
24
 
26
25
  clients.each(function(client) {
@@ -30,8 +29,6 @@ When %{I subscribe to the "$channel" channel with presence events} do |channel|
30
29
  });
31
30
  });
32
31
  channel.bind("pusher:member_added", function(client) {
33
- var
34
- count = document.querySelector("#presence header h1 span");
35
32
  count.innerHTML = parseInt(count.innerHTML, 10) + 1;
36
33
 
37
34
  var
@@ -39,8 +36,7 @@ When %{I subscribe to the "$channel" channel with presence events} do |channel|
39
36
  element.setAttribute("id", "client-" + client.id);
40
37
  });
41
38
  channel.bind("pusher:member_removed", function(client) {
42
- var item = list.querySelector("li#client-" + client.id),
43
- count = document.querySelector("#presence header h1 span");
39
+ var item = list.querySelector("li#client-" + client.id);
44
40
 
45
41
  count.innerHTML = parseInt(count.innerHTML, 10) - 1;
46
42
 
@@ -14,28 +14,24 @@ When %{I manually trigger the "$event" event on the "$channel" channel} do |even
14
14
  page.execute_script(%{Pusher.instance.send_event(#{event.to_json}, {}, #{channel.to_json})})
15
15
  end
16
16
 
17
- Then /^I should receive a "([^"]+)" event on the "([^"]+)" channel$/ do |event, channel|
18
- wait do
19
- events = page.evaluate_script("Pusher.instance.events[#{[channel, event].join(":").to_json}]")
20
- events.length.should == 1
21
- end
22
- end
23
-
24
- Then /^I should not receive a "([^"]+)" event on the "([^"]+)" channel$/ do |event, channel|
25
- wait do
26
- events = page.evaluate_script("Pusher.instance.events[#{[channel, event].join(":").to_json}]")
27
- events.should be_nil
28
- end
29
- end
17
+ Then /^([^ ]+) should receive a "([^"]+)" event on the "([^"]+)" channel$/ do |name, event, channel|
18
+ name = nil if name == "I"
30
19
 
31
- Then /^([^I]+) should receive a "([^"]+)" event on the "([^"]+)" channel$/ do |name, event, channel|
32
20
  using_session(name) do
33
- step %{I should receive a "#{event}" event on the "#{channel}" channel}
21
+ wait do
22
+ events = page.evaluate_script("Pusher.instance.events[#{[channel, event].join(":").to_json}]")
23
+ events.length.should == 1
24
+ end
34
25
  end
35
26
  end
36
27
 
37
- Then /^([^I]+) should not receive a "([^"]+)" event on the "([^"]+)" channel$/ do |name, event, channel|
28
+ Then /^([^ ]+) should not receive a "([^"]+)" event on the "([^"]+)" channel$/ do |name, event, channel|
29
+ name = nil if name == "I"
30
+
38
31
  using_session(name) do
39
- step %{I should not receive a "#{event}" event on the "#{channel}" channel}
32
+ wait do
33
+ events = page.evaluate_script("Pusher.instance.events[#{[channel, event].join(":").to_json}]")
34
+ events.should be_nil
35
+ end
40
36
  end
41
37
  end
@@ -15,15 +15,13 @@ class Sinatra::Application
15
15
  end
16
16
 
17
17
  post "/pusher/auth" do
18
+ data = nil
18
19
  channel = Pusher[params[:channel_name]]
19
20
 
20
- if params[:channel_name] =~ /^private-/
21
- channel.authenticate(params[:socket_id]).to_json
22
- elsif params[:channel_name] =~ /^presence-/
23
- channel.authenticate(params[:socket_id], {
24
- user_id: params[:socket_id],
25
- user_info: {}
26
- }).to_json
21
+ if params[:channel_name] =~ /^presence-/
22
+ data = { user_id: params[:socket_id], user_info: {} }
27
23
  end
24
+
25
+ channel.authenticate(params[:socket_id], data).to_json
28
26
  end
29
27
  end
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Pusher JavaScript Library v1.11.0
2
+ * Pusher JavaScript Library v1.11.2
3
3
  * http://pusherapp.com/
4
4
  *
5
5
  * Copyright 2011, Pusher
@@ -181,7 +181,7 @@ Pusher.warn = function() {
181
181
  };
182
182
 
183
183
  // Pusher defaults
184
- Pusher.VERSION = '1.11.0';
184
+ Pusher.VERSION = '1.11.2';
185
185
 
186
186
  Pusher.host = 'ws.pusherapp.com';
187
187
  Pusher.ws_port = 80;
@@ -307,6 +307,11 @@ Example:
307
307
  var stateCallbacks = this.stateActions;
308
308
 
309
309
  if (prevState && (Pusher.Util.arrayIndexOf(this.transitions[prevState], nextState) == -1)) {
310
+ this.emit('invalid_transition_attempt', {
311
+ oldState: prevState,
312
+ newState: nextState
313
+ });
314
+
310
315
  throw new Error('Invalid transition [' + prevState + ' to ' + nextState + ']');
311
316
  }
312
317
 
@@ -350,6 +355,7 @@ Example:
350
355
  A little bauble to interface with window.navigator.onLine,
351
356
  window.ononline and window.onoffline. Easier to mock.
352
357
  */
358
+
353
359
  var NetInfo = function() {
354
360
  var self = this;
355
361
  Pusher.EventsDispatcher.call(this);
@@ -376,7 +382,7 @@ Example:
376
382
  };
377
383
 
378
384
  Pusher.Util.extend(NetInfo.prototype, Pusher.EventsDispatcher.prototype);
379
-
385
+
380
386
  this.Pusher.NetInfo = NetInfo;
381
387
  }).call(this);
382
388
 
@@ -431,7 +437,7 @@ Example:
431
437
  this.netInfo.bind('online', function(){
432
438
  if (self._machine.is('waiting')) {
433
439
  self._machine.transition('connecting');
434
- triggerStateChange('connecting');
440
+ updateState('connecting');
435
441
  }
436
442
  });
437
443
 
@@ -452,8 +458,6 @@ Example:
452
458
 
453
459
  // define the state machine that runs the connection
454
460
  this._machine = new Pusher.Machine('initialized', machineTransitions, {
455
-
456
- // TODO: Use the constructor for this.
457
461
  initializedPre: function() {
458
462
  self.compulsorySecure = self.options.encrypted;
459
463
 
@@ -469,16 +473,18 @@ Example:
469
473
  self.emit('connecting_in', self.connectionWait);
470
474
  }
471
475
 
472
- if (self.netInfo.isOnLine() === false || self.connectionAttempts > 4){
473
- triggerStateChange('unavailable');
476
+ if (self.netInfo.isOnLine() && self.connectionAttempts <= 4) {
477
+ updateState('connecting');
474
478
  } else {
475
- triggerStateChange('connecting');
479
+ updateState('unavailable');
476
480
  }
477
481
 
478
- if (self.netInfo.isOnLine() === true) {
482
+ // When in the unavailable state we attempt to connect, but don't
483
+ // broadcast that fact
484
+ if (self.netInfo.isOnLine()) {
479
485
  self._waitingTimer = setTimeout(function() {
480
486
  self._machine.transition('connecting');
481
- }, self.connectionWait);
487
+ }, connectionDelay());
482
488
  }
483
489
  },
484
490
 
@@ -491,7 +497,7 @@ Example:
491
497
  // state even when offline.
492
498
  if (self.netInfo.isOnLine() === false) {
493
499
  self._machine.transition('waiting');
494
- triggerStateChange('unavailable');
500
+ updateState('unavailable');
495
501
 
496
502
  return;
497
503
  }
@@ -545,6 +551,11 @@ Example:
545
551
  },
546
552
 
547
553
  openToImpermanentlyClosing: function() {
554
+ // Possible to receive connection_established event after transition to impermanentlyClosing
555
+ // but before socket close. Prevent this triggering a transition from impermanentlyClosing to connected
556
+ // by unbinding onmessage callback.
557
+ self.socket.onmessage = undefined;
558
+
548
559
  updateConnectionParameters();
549
560
  },
550
561
 
@@ -556,17 +567,18 @@ Example:
556
567
  self.socket.onclose = transitionToWaiting;
557
568
 
558
569
  resetConnectionParameters(self);
570
+ self.connectedAt = new Date().getTime();
559
571
 
560
572
  resetActivityCheck();
561
573
  },
562
574
 
563
575
  connectedPost: function() {
564
- triggerStateChange('connected');
576
+ updateState('connected');
565
577
  },
566
578
 
567
579
  connectedExit: function() {
568
580
  stopActivityCheck();
569
- triggerStateChange('disconnected');
581
+ updateState('disconnected');
570
582
  },
571
583
 
572
584
  impermanentlyClosingPost: function() {
@@ -591,8 +603,12 @@ Example:
591
603
  },
592
604
 
593
605
  failedPre: function() {
594
- triggerStateChange('failed');
606
+ updateState('failed');
595
607
  Pusher.debug('WebSockets are not available in this browser.');
608
+ },
609
+
610
+ permanentlyClosedPost: function() {
611
+ updateState('disconnected');
596
612
  }
597
613
  });
598
614
 
@@ -633,7 +649,11 @@ Example:
633
649
  protocol = 'wss://';
634
650
  }
635
651
 
636
- return protocol + Pusher.host + ':' + port + '/app/' + key + '?client=js&version=' + Pusher.VERSION;
652
+ var flash = (Pusher.TransportType === "flash") ? "true" : "false";
653
+
654
+ return protocol + Pusher.host + ':' + port + '/app/' + key + '?protocol=5&client=js'
655
+ + '&version=' + Pusher.VERSION
656
+ + '&flash=' + flash;
637
657
  }
638
658
 
639
659
  // callback for close and retry. Used on timeouts.
@@ -657,6 +677,25 @@ Example:
657
677
  if (self._activityTimer) { clearTimeout(self._activityTimer); }
658
678
  }
659
679
 
680
+ // Returns the delay before the next connection attempt should be made
681
+ //
682
+ // This function guards against attempting to connect more frequently than
683
+ // once every second
684
+ //
685
+ function connectionDelay() {
686
+ var delay = self.connectionWait;
687
+ if (delay === 0) {
688
+ if (self.connectedAt) {
689
+ var t = 1000;
690
+ var connectedFor = new Date().getTime() - self.connectedAt;
691
+ if (connectedFor < t) {
692
+ delay = t - connectedFor;
693
+ }
694
+ }
695
+ }
696
+ return delay;
697
+ }
698
+
660
699
  /*-----------------------------------------------
661
700
  WebSocket Callbacks
662
701
  -----------------------------------------------*/
@@ -666,28 +705,40 @@ Example:
666
705
  self._machine.transition('open');
667
706
  };
668
707
 
708
+ function handleCloseCode(code, message) {
709
+ // first inform the end-developer of this error
710
+ self.emit('error', {type: 'PusherError', data: {code: code, message: message}});
711
+
712
+ if (code === 4000) {
713
+ // SSL only app
714
+ self.compulsorySecure = true;
715
+ self.connectionSecure = true;
716
+ self.options.encrypted = true;
717
+
718
+ self._machine.transition('impermanentlyClosing')
719
+ } else if (code < 4100) {
720
+ // Permentently close connection
721
+ self._machine.transition('permanentlyClosing')
722
+ } else if (code < 4200) {
723
+ // Backoff before reconnecting
724
+ self.connectionWait = 1000;
725
+ self._machine.transition('waiting')
726
+ } else if (code < 4300) {
727
+ // Reconnect immediately
728
+ self._machine.transition('impermanentlyClosing')
729
+ } else {
730
+ // Unknown error
731
+ self._machine.transition('permanentlyClosing')
732
+ }
733
+ }
734
+
669
735
  function ws_onMessageOpen(event) {
670
736
  var params = parseWebSocketEvent(event);
671
737
  if (params !== undefined) {
672
738
  if (params.event === 'pusher:connection_established') {
673
739
  self._machine.transition('connected', params.data.socket_id);
674
740
  } else if (params.event === 'pusher:error') {
675
- // first inform the end-developer of this error
676
- self.emit('error', {type: 'PusherError', data: params.data});
677
-
678
- switch (params.data.code) {
679
- case 4000:
680
- Pusher.warn(params.data.message);
681
-
682
- self.compulsorySecure = true;
683
- self.connectionSecure = true;
684
- self.options.encrypted = true;
685
- break;
686
- case 4001:
687
- // App not found by key - close connection
688
- self._machine.transition('permanentlyClosing');
689
- break;
690
- }
741
+ handleCloseCode(params.data.code, params.data.message)
691
742
  }
692
743
  }
693
744
  }
@@ -753,19 +804,21 @@ Example:
753
804
  self._machine.transition('impermanentlyClosing');
754
805
  }
755
806
 
756
- function triggerStateChange(newState, data) {
757
- // avoid emitting and changing the state
758
- // multiple times when it's the same.
759
- if (self.state === newState) return;
760
-
807
+ // Updates the public state information exposed by connection
808
+ //
809
+ // This is distinct from the internal state information used by _machine
810
+ // to manage the connection
811
+ //
812
+ function updateState(newState, data) {
761
813
  var prevState = self.state;
762
-
763
814
  self.state = newState;
764
815
 
765
- Pusher.debug('State changed', prevState + ' -> ' + newState);
766
-
767
- self.emit('state_change', {previous: prevState, current: newState});
768
- self.emit(newState, data);
816
+ // Only emit when the state changes
817
+ if (prevState !== newState) {
818
+ Pusher.debug('State changed', prevState + ' -> ' + newState);
819
+ self.emit('state_change', {previous: prevState, current: newState});
820
+ self.emit(newState, data);
821
+ }
769
822
  }
770
823
  };
771
824
 
@@ -785,14 +838,24 @@ Example:
785
838
  }
786
839
  // user re-opening connection after closing it
787
840
  else if(this._machine.is("permanentlyClosed")) {
841
+ resetConnectionParameters(this);
788
842
  this._machine.transition('waiting');
789
843
  }
790
844
  };
791
845
 
792
846
  Connection.prototype.send = function(data) {
793
847
  if (this._machine.is('connected')) {
794
- this.socket.send(data);
795
- return true;
848
+ // Bug in iOS (reproduced in 5.0.1) Mobile Safari:
849
+ // 1. Open page/tab, connect WS, get some data.
850
+ // 2. Switch tab or close Mobile Safari and wait for WS connection to get closed (probably by server).
851
+ // 3. Switch back to tab or open Mobile Safari and Mobile Safari crashes.
852
+ // The problem is that WS tries to send data on closed WS connection before it realises it is closed.
853
+ // The timeout means that by the time the send happens, the WS readyState correctly reflects closed state.
854
+ var self = this;
855
+ setTimeout(function() {
856
+ self.socket.send(data);
857
+ }, 0);
858
+ return true; // only a reflection of fact that WS thinks it is open - could get returned before some lower-level failure.
796
859
  } else {
797
860
  return false;
798
861
  }
@@ -4,9 +4,5 @@ require "capybara/cucumber"
4
4
 
5
5
  Bundler.require(:default, :development)
6
6
 
7
- Dir[File.expand_path("../support/**/*.rb", __FILE__)].each do |file|
8
- require file
9
- end
10
-
11
7
  Capybara.app = Sinatra::Application
12
8
  Capybara.javascript_driver = :webkit
data/lib/pusher-fake.rb CHANGED
@@ -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.0"
17
+ VERSION = "0.1.1"
18
18
 
19
19
  # Call this method to modify the defaults.
20
20
  #
@@ -6,7 +6,7 @@ module PusherFake
6
6
 
7
7
  attr_accessor :channels
8
8
 
9
- # Create a channel, determing the type by the name.
9
+ # Create a channel, determining the type by the name.
10
10
  #
11
11
  # @param [String] name The channel name.
12
12
  # @return [Public|Private] The channel object.
@@ -1,5 +1,8 @@
1
1
  module PusherFake
2
2
  class Configuration
3
+ # @return [String] The Pusher Applicaiton ID. (Defaults to +PUSHER_APP_ID+.)
4
+ attr_accessor :app_id
5
+
3
6
  # @return [String] The Pusher API key. (Defaults to +PUSHER_API_KEY+.)
4
7
  attr_accessor :key
5
8
 
@@ -20,6 +23,7 @@ module PusherFake
20
23
 
21
24
  # Instantiated from {PusherFake.configuration}. Sets the defaults.
22
25
  def initialize
26
+ self.app_id = "PUSHER_APP_ID"
23
27
  self.key = "PUSHER_API_KEY"
24
28
  self.secret = "PUSHER_API_SECRET"
25
29
  self.socket_host = "127.0.0.1"
@@ -18,7 +18,7 @@ module PusherFake
18
18
  #
19
19
  # @return [String] The channel name.
20
20
  def self.channel
21
- path.match(%r{/apps/PUSHER_APP_ID/channels/(.+)/events}i)[1]
21
+ path.match(%r{/apps/#{PusherFake.configuration.app_id}/channels/(.+)/events}i)[1]
22
22
  end
23
23
 
24
24
  # Parse and return the event data from the request JSON.
@@ -1,6 +1,7 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe PusherFake::Configuration do
4
+ it { should have_configuration_option(:app_id).with_default("PUSHER_APP_ID") }
4
5
  it { should have_configuration_option(:key).with_default("PUSHER_API_KEY") }
5
6
  it { should have_configuration_option(:secret).with_default("PUSHER_API_SECRET") }
6
7
  it { should have_configuration_option(:socket_host).with_default("127.0.0.1") }
@@ -60,6 +60,19 @@ describe PusherFake::Server::Application, ".channel" do
60
60
  it "returns the channel name from the path" do
61
61
  subject.channel.should == channel
62
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
63
76
  end
64
77
 
65
78
  describe PusherFake::Server::Application, ".data" do
data/spec/spec_helper.rb CHANGED
@@ -9,4 +9,5 @@ end
9
9
 
10
10
  RSpec.configure do |config|
11
11
  config.mock_with :mocha
12
+ config.include(BartenderHelper)
12
13
  end
@@ -1,19 +1,35 @@
1
- RSpec::Matchers.define :have_configuration_option do |option|
2
- match do |configuration|
3
- configuration.should respond_to(option)
4
- configuration.__send__(option).should == @default if defined?(@default)
5
- configuration.__send__(:"#{option}=", "value")
6
- configuration.__send__(option).should == "value"
7
- end
1
+ module BartenderHelper
2
+ class ConfigurationOption
3
+ def initialize(option)
4
+ @option = option
5
+ end
6
+
7
+ def matches?(configuration)
8
+ @configuration = configuration
9
+
10
+ @configuration.respond_to?(@option).should == true
11
+
12
+ @configuration.__send__(@option).should == @default if instance_variables.include?("@default")
13
+
14
+ @configuration.__send__(:"#{@option}=", "value")
15
+ @configuration.__send__(@option).should == "value"
16
+ end
17
+
18
+ def with_default(default)
19
+ @default = default
20
+
21
+ self
22
+ end
8
23
 
9
- chain :with_default do |default|
10
- @default = default
24
+ def failure_message
25
+ description = "expected #{@configuration} to have"
26
+ description << " configuration option #{@option.inspect}"
27
+ description << " with a default of #{@default.inspect}" if instance_variables.include?("@default")
28
+ description
29
+ end
11
30
  end
12
31
 
13
- failure_message do
14
- description = "expected #{subject} to have"
15
- description << " configuration option #{option.inspect}"
16
- description << " with a default of #{@default.inspect}" if defined?(@default)
17
- description
32
+ def have_configuration_option(option)
33
+ ConfigurationOption.new(option)
18
34
  end
19
35
  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.0
4
+ version: 0.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-15 00:00:00.000000000 Z
12
+ date: 2012-03-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: em-websocket
16
- requirement: &70110876177100 !ruby/object:Gem::Requirement
16
+ requirement: &70195226755160 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - =
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 0.3.6
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70110876177100
24
+ version_requirements: *70195226755160
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: ruby-hmac
27
- requirement: &70110876176520 !ruby/object:Gem::Requirement
27
+ requirement: &70195226768900 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - =
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 0.4.0
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70110876176520
35
+ version_requirements: *70195226768900
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: thin
38
- requirement: &70110876176040 !ruby/object:Gem::Requirement
38
+ requirement: &70195226779500 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - =
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 1.3.1
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70110876176040
46
+ version_requirements: *70195226779500
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: yajl-ruby
49
- requirement: &70110876175560 !ruby/object:Gem::Requirement
49
+ requirement: &70195226774260 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - =
@@ -54,32 +54,32 @@ dependencies:
54
54
  version: 1.1.0
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70110876175560
57
+ version_requirements: *70195226774260
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: bourne
60
- requirement: &70110876175000 !ruby/object:Gem::Requirement
60
+ requirement: &70195226798680 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - =
64
64
  - !ruby/object:Gem::Version
65
- version: 1.1.1
65
+ version: 1.1.2
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70110876175000
68
+ version_requirements: *70195226798680
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: bundler
71
- requirement: &70110876174540 !ruby/object:Gem::Requirement
71
+ requirement: &70195226812420 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
- - - =
74
+ - - ! '>='
75
75
  - !ruby/object:Gem::Version
76
76
  version: 1.1.0
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70110876174540
79
+ version_requirements: *70195226812420
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: capybara
82
- requirement: &70110876173940 !ruby/object:Gem::Requirement
82
+ requirement: &70195226808740 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - =
@@ -87,21 +87,21 @@ dependencies:
87
87
  version: 1.1.2
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *70110876173940
90
+ version_requirements: *70195226808740
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: capybara-webkit
93
- requirement: &70110876173440 !ruby/object:Gem::Requirement
93
+ requirement: &70195226819740 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - =
97
97
  - !ruby/object:Gem::Version
98
- version: 0.10.1
98
+ version: 0.11.0
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *70110876173440
101
+ version_requirements: *70195226819740
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: cucumber
104
- requirement: &70110876172820 !ruby/object:Gem::Requirement
104
+ requirement: &70195226816180 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - =
@@ -109,10 +109,10 @@ dependencies:
109
109
  version: 1.1.9
110
110
  type: :development
111
111
  prerelease: false
112
- version_requirements: *70110876172820
112
+ version_requirements: *70195226816180
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: pusher
115
- requirement: &70110876172220 !ruby/object:Gem::Requirement
115
+ requirement: &70195226828020 !ruby/object:Gem::Requirement
116
116
  none: false
117
117
  requirements:
118
118
  - - =
@@ -120,32 +120,43 @@ dependencies:
120
120
  version: 0.9.2
121
121
  type: :development
122
122
  prerelease: false
123
- version_requirements: *70110876172220
123
+ version_requirements: *70195226828020
124
+ - !ruby/object:Gem::Dependency
125
+ name: rake
126
+ requirement: &70195226824580 !ruby/object:Gem::Requirement
127
+ none: false
128
+ requirements:
129
+ - - =
130
+ - !ruby/object:Gem::Version
131
+ version: 0.9.2.2
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: *70195226824580
124
135
  - !ruby/object:Gem::Dependency
125
136
  name: redcarpet
126
- requirement: &70110876171320 !ruby/object:Gem::Requirement
137
+ requirement: &70195226822700 !ruby/object:Gem::Requirement
127
138
  none: false
128
139
  requirements:
129
140
  - - =
130
141
  - !ruby/object:Gem::Version
131
- version: 2.1.0
142
+ version: 2.1.1
132
143
  type: :development
133
144
  prerelease: false
134
- version_requirements: *70110876171320
145
+ version_requirements: *70195226822700
135
146
  - !ruby/object:Gem::Dependency
136
147
  name: rspec
137
- requirement: &70110876170800 !ruby/object:Gem::Requirement
148
+ requirement: &70195230220940 !ruby/object:Gem::Requirement
138
149
  none: false
139
150
  requirements:
140
151
  - - =
141
152
  - !ruby/object:Gem::Version
142
- version: 2.8.0
153
+ version: 2.9.0
143
154
  type: :development
144
155
  prerelease: false
145
- version_requirements: *70110876170800
156
+ version_requirements: *70195230220940
146
157
  - !ruby/object:Gem::Dependency
147
158
  name: sinatra
148
- requirement: &70110876170320 !ruby/object:Gem::Requirement
159
+ requirement: &70195230219480 !ruby/object:Gem::Requirement
149
160
  none: false
150
161
  requirements:
151
162
  - - =
@@ -153,10 +164,10 @@ dependencies:
153
164
  version: 1.3.2
154
165
  type: :development
155
166
  prerelease: false
156
- version_requirements: *70110876170320
167
+ version_requirements: *70195230219480
157
168
  - !ruby/object:Gem::Dependency
158
169
  name: yard
159
- requirement: &70110876169640 !ruby/object:Gem::Requirement
170
+ requirement: &70195230217620 !ruby/object:Gem::Requirement
160
171
  none: false
161
172
  requirements:
162
173
  - - =
@@ -164,7 +175,7 @@ dependencies:
164
175
  version: 0.7.5
165
176
  type: :development
166
177
  prerelease: false
167
- version_requirements: *70110876169640
178
+ version_requirements: *70195230217620
168
179
  description: A fake Pusher server for development and testing.
169
180
  email: hello@tristandunn.com
170
181
  executables: []
@@ -220,7 +231,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
220
231
  version: '0'
221
232
  segments:
222
233
  - 0
223
- hash: -4069294578046260452
234
+ hash: 1138384851111270143
224
235
  required_rubygems_version: !ruby/object:Gem::Requirement
225
236
  none: false
226
237
  requirements:
@@ -229,7 +240,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
229
240
  version: '0'
230
241
  segments:
231
242
  - 0
232
- hash: -4069294578046260452
243
+ hash: 1138384851111270143
233
244
  requirements: []
234
245
  rubyforge_project:
235
246
  rubygems_version: 1.8.11