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.
- data/features/step_definitions/channel_steps.rb +2 -6
- data/features/step_definitions/event_steps.rb +13 -17
- data/features/support/application.rb +5 -7
- data/features/support/application/public/javascripts/vendor/pusher-1.11.js +107 -44
- data/features/support/environment.rb +0 -4
- data/lib/pusher-fake.rb +1 -1
- data/lib/pusher-fake/channel.rb +1 -1
- data/lib/pusher-fake/configuration.rb +4 -0
- data/lib/pusher-fake/server/application.rb +1 -1
- data/spec/lib/pusher-fake/configuration_spec.rb +1 -0
- data/spec/lib/pusher-fake/server/application_spec.rb +13 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/support/have_configuration_option_matcher.rb +30 -14
- metadata +48 -37
@@ -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
|
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 /^
|
18
|
-
|
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
|
-
|
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 /^([^
|
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
|
-
|
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] =~ /^
|
21
|
-
|
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.
|
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.
|
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
|
-
|
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()
|
473
|
-
|
476
|
+
if (self.netInfo.isOnLine() && self.connectionAttempts <= 4) {
|
477
|
+
updateState('connecting');
|
474
478
|
} else {
|
475
|
-
|
479
|
+
updateState('unavailable');
|
476
480
|
}
|
477
481
|
|
478
|
-
|
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
|
-
},
|
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
|
-
|
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
|
-
|
576
|
+
updateState('connected');
|
565
577
|
},
|
566
578
|
|
567
579
|
connectedExit: function() {
|
568
580
|
stopActivityCheck();
|
569
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
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
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
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
|
-
|
795
|
-
|
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
|
}
|
data/lib/pusher-fake.rb
CHANGED
data/lib/pusher-fake/channel.rb
CHANGED
@@ -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/
|
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
@@ -1,19 +1,35 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
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
|
-
|
10
|
-
|
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
|
-
|
14
|
-
|
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.
|
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-
|
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: &
|
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: *
|
24
|
+
version_requirements: *70195226755160
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: ruby-hmac
|
27
|
-
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: *
|
35
|
+
version_requirements: *70195226768900
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: thin
|
38
|
-
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: *
|
46
|
+
version_requirements: *70195226779500
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: yajl-ruby
|
49
|
-
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: *
|
57
|
+
version_requirements: *70195226774260
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: bourne
|
60
|
-
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.
|
65
|
+
version: 1.1.2
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70195226798680
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: bundler
|
71
|
-
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: *
|
79
|
+
version_requirements: *70195226812420
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: capybara
|
82
|
-
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: *
|
90
|
+
version_requirements: *70195226808740
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: capybara-webkit
|
93
|
-
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.
|
98
|
+
version: 0.11.0
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *70195226819740
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: cucumber
|
104
|
-
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: *
|
112
|
+
version_requirements: *70195226816180
|
113
113
|
- !ruby/object:Gem::Dependency
|
114
114
|
name: pusher
|
115
|
-
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: *
|
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: &
|
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.
|
142
|
+
version: 2.1.1
|
132
143
|
type: :development
|
133
144
|
prerelease: false
|
134
|
-
version_requirements: *
|
145
|
+
version_requirements: *70195226822700
|
135
146
|
- !ruby/object:Gem::Dependency
|
136
147
|
name: rspec
|
137
|
-
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.
|
153
|
+
version: 2.9.0
|
143
154
|
type: :development
|
144
155
|
prerelease: false
|
145
|
-
version_requirements: *
|
156
|
+
version_requirements: *70195230220940
|
146
157
|
- !ruby/object:Gem::Dependency
|
147
158
|
name: sinatra
|
148
|
-
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: *
|
167
|
+
version_requirements: *70195230219480
|
157
168
|
- !ruby/object:Gem::Dependency
|
158
169
|
name: yard
|
159
|
-
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: *
|
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:
|
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:
|
243
|
+
hash: 1138384851111270143
|
233
244
|
requirements: []
|
234
245
|
rubyforge_project:
|
235
246
|
rubygems_version: 1.8.11
|