pusher-fake 0.2.0 → 0.3.0
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/channel_trigger.feature +10 -0
- data/features/channel_webhooks.feature +40 -0
- data/features/step_definitions/channel_steps.rb +32 -35
- data/features/step_definitions/client_steps.rb +2 -2
- data/features/step_definitions/event_steps.rb +12 -6
- data/features/step_definitions/presence_steps.rb +1 -1
- data/features/step_definitions/webhook_steps.rb +21 -0
- data/features/support/application.rb +1 -1
- data/features/support/application/views/index.erb +5 -6
- data/features/support/environment.rb +0 -1
- data/features/support/webhooks.rb +36 -0
- data/lib/pusher-fake.rb +3 -1
- data/lib/pusher-fake/channel/presence.rb +6 -2
- data/lib/pusher-fake/channel/public.rb +12 -0
- data/lib/pusher-fake/configuration.rb +4 -0
- data/lib/pusher-fake/webhook.rb +30 -0
- data/spec/lib/pusher-fake/channel/presence_spec.rb +49 -6
- data/spec/lib/pusher-fake/channel/private_spec.rb +24 -2
- data/spec/lib/pusher-fake/channel/public_spec.rb +28 -7
- data/spec/lib/pusher-fake/channel_spec.rb +16 -6
- data/spec/lib/pusher-fake/configuration_spec.rb +1 -0
- data/spec/lib/pusher-fake/server_spec.rb +3 -3
- data/spec/lib/pusher-fake/webhook_spec.rb +41 -0
- data/spec/spec_helper.rb +0 -1
- data/spec/support/have_configuration_option_matcher.rb +0 -3
- metadata +29 -36
|
@@ -72,3 +72,13 @@ Feature: Triggering events on a channel
|
|
|
72
72
|
When I trigger the "client-message" event on the "chat" channel
|
|
73
73
|
Then I should not receive a "client-message" event on the "chat" channel
|
|
74
74
|
And Bob should not receive a "client-message" event on the "chat" channel
|
|
75
|
+
|
|
76
|
+
Scenario: Server triggers an event on multiple private channels
|
|
77
|
+
Given I am subscribed to the "private-chat-1" channel
|
|
78
|
+
And Bob is subscribed to the "private-chat-2" channel
|
|
79
|
+
When a "message" event is triggered on the following channels:
|
|
80
|
+
| name |
|
|
81
|
+
| private-chat-1 |
|
|
82
|
+
| private-chat-2 |
|
|
83
|
+
Then I should receive a "message" event on the "private-chat-1" channel
|
|
84
|
+
And Bob should receive a "message" event on the "private-chat-2" channel
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
@javascript
|
|
2
|
+
Feature: Triggering channel webhooks
|
|
3
|
+
|
|
4
|
+
Background:
|
|
5
|
+
Given I am connected
|
|
6
|
+
And Bob is connected
|
|
7
|
+
|
|
8
|
+
Scenario: Occupying and vacating a channel
|
|
9
|
+
When I subscribe to the "game-1" channel
|
|
10
|
+
Then the server should have received the following event:
|
|
11
|
+
| name | channel_occupied |
|
|
12
|
+
| channel | game-1 |
|
|
13
|
+
When Bob is subscribed to the "game-1" channel
|
|
14
|
+
Then the server should have received no events
|
|
15
|
+
When Bob unsubscribes from the "game-1" channel
|
|
16
|
+
Then the server should have received no events
|
|
17
|
+
When I unsubscribe from the "game-1" channel
|
|
18
|
+
Then the server should have received the following event:
|
|
19
|
+
| name | channel_vacated |
|
|
20
|
+
| channel | game-1 |
|
|
21
|
+
|
|
22
|
+
Scenario: Subscribing and unsubscribing from a presence channel
|
|
23
|
+
When I subscribe to the "presence-chat-1" channel
|
|
24
|
+
Then the server should have received the following user event:
|
|
25
|
+
| name | member_added |
|
|
26
|
+
| channel | presence-chat-1 |
|
|
27
|
+
When Bob is subscribed to the "presence-chat-1" channel
|
|
28
|
+
Then the server should have received the following user event:
|
|
29
|
+
| user | Bob |
|
|
30
|
+
| name | member_added |
|
|
31
|
+
| channel | presence-chat-1 |
|
|
32
|
+
When Bob unsubscribes from the "presence-chat-1" channel
|
|
33
|
+
Then the server should have received the following user event:
|
|
34
|
+
| user | Bob |
|
|
35
|
+
| name | member_removed |
|
|
36
|
+
| channel | presence-chat-1 |
|
|
37
|
+
When I unsubscribe from the "presence-chat-1" channel
|
|
38
|
+
Then the server should have received the following user event:
|
|
39
|
+
| name | member_removed |
|
|
40
|
+
| channel | presence-chat-1 |
|
|
@@ -10,51 +10,48 @@ Given %{$name is subscribed to the "$channel" channel} do |name, channel|
|
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
When %{I subscribe to the "$channel" channel} do |channel|
|
|
13
|
-
page.execute_script("Pusher.instance.subscribe(#{channel
|
|
13
|
+
page.execute_script("Pusher.instance.subscribe(#{MultiJson.dump(channel)})")
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
When %{I subscribe to the "$channel" channel with presence events} do |channel|
|
|
17
17
|
page.execute_script(%{
|
|
18
|
-
var list
|
|
19
|
-
count
|
|
20
|
-
|
|
18
|
+
var list = list || document.querySelector("section ul"),
|
|
19
|
+
count = count || document.querySelector("section header h1 span"),
|
|
20
|
+
addClient = addClient || function(client) {
|
|
21
|
+
var
|
|
22
|
+
element = list.appendChild(document.createElement("li"));
|
|
23
|
+
element.setAttribute("id", "client-" + client.id);
|
|
21
24
|
|
|
22
|
-
|
|
23
|
-
|
|
25
|
+
if (client.info) {
|
|
26
|
+
element.innerHTML = client.info.name;
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
changeCount = changeCount || function(delta) {
|
|
30
|
+
count.innerHTML = parseInt(count.innerHTML, 10) + delta;
|
|
31
|
+
};
|
|
24
32
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
element.setAttribute("id", "client-" + client.id);
|
|
33
|
+
Pusher.instance.subscribe(#{MultiJson.dump(channel)})
|
|
34
|
+
.bind("pusher:subscription_succeeded", function(clients) {
|
|
35
|
+
clients.each(addClient);
|
|
29
36
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
var
|
|
39
|
-
element = list.appendChild(document.createElement("li"));
|
|
40
|
-
element.setAttribute("id", "client-" + client.id);
|
|
37
|
+
count.innerHTML = clients.count;
|
|
38
|
+
})
|
|
39
|
+
.bind("pusher:member_added", function(client) {
|
|
40
|
+
addClient(client);
|
|
41
|
+
changeCount(1);
|
|
42
|
+
})
|
|
43
|
+
.bind("pusher:member_removed", function(client) {
|
|
44
|
+
var item = list.querySelector("li#client-" + client.id);
|
|
41
45
|
|
|
42
|
-
|
|
43
|
-
element.innerHTML = client.info.name;
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
channel.bind("pusher:member_removed", function(client) {
|
|
47
|
-
var item = list.querySelector("li#client-" + client.id);
|
|
46
|
+
list.removeChild(item);
|
|
48
47
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
list.removeChild(item);
|
|
52
|
-
});
|
|
48
|
+
changeCount(-1);
|
|
49
|
+
});
|
|
53
50
|
})
|
|
54
51
|
end
|
|
55
52
|
|
|
56
53
|
When %{I unsubscribe from the "$channel" channel} do |channel|
|
|
57
|
-
page.execute_script("Pusher.instance.unsubscribe(#{channel
|
|
54
|
+
page.execute_script("Pusher.instance.unsubscribe(#{MultiJson.dump(channel)})")
|
|
58
55
|
end
|
|
59
56
|
|
|
60
57
|
When %{$name unsubscribes from the "$channel" channel} do |name, channel|
|
|
@@ -64,10 +61,10 @@ When %{$name unsubscribes from the "$channel" channel} do |name, channel|
|
|
|
64
61
|
end
|
|
65
62
|
|
|
66
63
|
Then %{I should be subscribed to the "$channel" channel} do |channel|
|
|
67
|
-
|
|
64
|
+
Capybara.timeout do
|
|
68
65
|
subscribed = page.evaluate_script(%{
|
|
69
66
|
var
|
|
70
|
-
channel = Pusher.instance.channel(#{channel
|
|
67
|
+
channel = Pusher.instance.channel(#{MultiJson.dump(channel)});
|
|
71
68
|
channel && channel.subscribed;
|
|
72
69
|
})
|
|
73
70
|
subscribed == true
|
|
@@ -78,7 +75,7 @@ Then %{I should not be subscribed to the "$channel" channel} do |channel|
|
|
|
78
75
|
wait do
|
|
79
76
|
subscribed = page.evaluate_script(%{
|
|
80
77
|
var
|
|
81
|
-
channel = Pusher.instance.channel(#{channel
|
|
78
|
+
channel = Pusher.instance.channel(#{MultiJson.dump(channel)});
|
|
82
79
|
channel && channel.subscribed;
|
|
83
80
|
})
|
|
84
81
|
subscribed.should be_false
|
|
@@ -14,14 +14,14 @@ Given "I change my socket ID" do
|
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
Then "I should be connected" do
|
|
17
|
-
|
|
17
|
+
Capybara.timeout do
|
|
18
18
|
state = page.evaluate_script("Pusher.instance.connection.state")
|
|
19
19
|
state == "connected"
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
Then "I should not be connected" do
|
|
24
|
-
|
|
24
|
+
Capybara.timeout do
|
|
25
25
|
state = page.evaluate_script("Pusher.instance.connection.state")
|
|
26
26
|
state == "unavailable"
|
|
27
27
|
end
|
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
When %{a "$event" event is triggered on the "$channel" channel} do |event, channel|
|
|
2
|
-
Pusher.trigger(
|
|
2
|
+
Pusher.trigger(channel, event, {})
|
|
3
|
+
end
|
|
4
|
+
|
|
5
|
+
When %{a "$event" event is triggered on the following channels:} do |event, table|
|
|
6
|
+
channels = table.hashes.collect { |hash| hash["name"] }
|
|
7
|
+
|
|
8
|
+
Pusher.trigger(channels, event, {})
|
|
3
9
|
end
|
|
4
10
|
|
|
5
11
|
When %{I trigger the "$event" event on the "$channel" channel} do |event, channel|
|
|
6
12
|
page.execute_script(%{
|
|
7
13
|
var
|
|
8
|
-
channel = Pusher.instance.channel(#{channel
|
|
9
|
-
channel.trigger(#{event
|
|
14
|
+
channel = Pusher.instance.channel(#{MultiJson.dump(channel)});
|
|
15
|
+
channel.trigger(#{MultiJson.dump(event)}, {});
|
|
10
16
|
})
|
|
11
17
|
end
|
|
12
18
|
|
|
13
19
|
When %{I manually trigger the "$event" event on the "$channel" channel} do |event, channel|
|
|
14
|
-
page.execute_script(%{Pusher.instance.send_event(#{event
|
|
20
|
+
page.execute_script(%{Pusher.instance.send_event(#{MultiJson.dump(event)}, {}, #{MultiJson.dump(channel)})})
|
|
15
21
|
end
|
|
16
22
|
|
|
17
23
|
Then /^([^ ]+) should receive a "([^"]+)" event on the "([^"]+)" channel$/ do |name, event, channel|
|
|
@@ -19,7 +25,7 @@ Then /^([^ ]+) should receive a "([^"]+)" event on the "([^"]+)" channel$/ do |n
|
|
|
19
25
|
|
|
20
26
|
using_session(name) do
|
|
21
27
|
wait do
|
|
22
|
-
events = page.evaluate_script("Pusher.instance.events[#{[channel, event].join(":")
|
|
28
|
+
events = page.evaluate_script("Pusher.instance.events[#{MultiJson.dump([channel, event].join(":"))}]")
|
|
23
29
|
events.length.should == 1
|
|
24
30
|
end
|
|
25
31
|
end
|
|
@@ -30,7 +36,7 @@ Then /^([^ ]+) should not receive a "([^"]+)" event on the "([^"]+)" channel$/ d
|
|
|
30
36
|
|
|
31
37
|
using_session(name) do
|
|
32
38
|
wait do
|
|
33
|
-
events = page.evaluate_script("Pusher.instance.events[#{[channel, event].join(":")
|
|
39
|
+
events = page.evaluate_script("Pusher.instance.events[#{MultiJson.dump([channel, event].join(":"))}]")
|
|
34
40
|
events.should be_nil
|
|
35
41
|
end
|
|
36
42
|
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Then /^the server should have received the following (user )*event:$/ do |user_event, table|
|
|
2
|
+
event = table.transpose.hashes.first
|
|
3
|
+
|
|
4
|
+
using_session(event.delete("user")) do
|
|
5
|
+
page.evaluate_script("Pusher.instance.connection.socket_id").tap do |socket_id|
|
|
6
|
+
event.merge!("user_id" => socket_id.to_s)
|
|
7
|
+
end
|
|
8
|
+
end if user_event
|
|
9
|
+
|
|
10
|
+
Capybara.timeout do
|
|
11
|
+
$events.include?(event)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
$events.replace([])
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
Then /^the server should have received no events$/ do
|
|
18
|
+
wait do
|
|
19
|
+
$events.should be_empty
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -5,24 +5,23 @@
|
|
|
5
5
|
</head>
|
|
6
6
|
<body>
|
|
7
7
|
|
|
8
|
-
<section
|
|
8
|
+
<section>
|
|
9
9
|
<header>
|
|
10
10
|
<h1><span>0</span> Clients</h1>
|
|
11
11
|
</header>
|
|
12
12
|
|
|
13
|
-
<ul>
|
|
14
|
-
</ul>
|
|
13
|
+
<ul></ul>
|
|
15
14
|
</section>
|
|
16
15
|
|
|
17
16
|
<script src="/javascripts/vendor/pusher-1.12.5.js"></script>
|
|
18
17
|
<script>
|
|
19
18
|
window.addEventListener("DOMContentLoaded", function() {
|
|
20
19
|
// Use the PusherFake server.
|
|
21
|
-
Pusher.host = <%= PusherFake.configuration.socket_host
|
|
22
|
-
Pusher.ws_port = <%= PusherFake.configuration.socket_port
|
|
20
|
+
Pusher.host = <%= MultiJson.dump(PusherFake.configuration.socket_host) %>;
|
|
21
|
+
Pusher.ws_port = <%= MultiJson.dump(PusherFake.configuration.socket_port) %>;
|
|
23
22
|
|
|
24
23
|
// Create the client instance.
|
|
25
|
-
Pusher.instance = new Pusher(<%= PusherFake.configuration.key
|
|
24
|
+
Pusher.instance = new Pusher(<%= MultiJson.dump(PusherFake.configuration.key) %>);
|
|
26
25
|
Pusher.instance.events = {};
|
|
27
26
|
|
|
28
27
|
// Force the connection to go unavailable after a single attempt.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
$events = []
|
|
2
|
+
|
|
3
|
+
Thread.new do
|
|
4
|
+
# Not explicitly requiring Thin::Server occasionally results in
|
|
5
|
+
# Thin::Server.start not being defined.
|
|
6
|
+
require "thin"
|
|
7
|
+
require "thin/server"
|
|
8
|
+
|
|
9
|
+
class WebhookEndpoint
|
|
10
|
+
def self.call(environment)
|
|
11
|
+
request = Rack::Request.new(environment)
|
|
12
|
+
webhook = Pusher::WebHook.new(request)
|
|
13
|
+
|
|
14
|
+
if webhook.valid?
|
|
15
|
+
$events.concat(webhook.events)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
Rack::Response.new.finish
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
EventMachine.run do
|
|
23
|
+
Thin::Logging.silent = true
|
|
24
|
+
Thin::Server.start('0.0.0.0', 8082, WebhookEndpoint)
|
|
25
|
+
Thread.current[:ready] = true
|
|
26
|
+
end
|
|
27
|
+
end.tap do |thread|
|
|
28
|
+
at_exit { thread.exit }
|
|
29
|
+
|
|
30
|
+
# Wait for the webhook endpoint server to start.
|
|
31
|
+
Capybara.timeout do
|
|
32
|
+
thread[:ready]
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
PusherFake.configuration.webhooks = ["http://localhost:8082"]
|
data/lib/pusher-fake.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
require "em-http-request"
|
|
1
2
|
require "em-websocket"
|
|
2
3
|
require "multi_json"
|
|
3
4
|
require "openssl"
|
|
@@ -11,10 +12,11 @@ require "pusher-fake/configuration"
|
|
|
11
12
|
require "pusher-fake/connection"
|
|
12
13
|
require "pusher-fake/server"
|
|
13
14
|
require "pusher-fake/server/application"
|
|
15
|
+
require "pusher-fake/webhook"
|
|
14
16
|
|
|
15
17
|
module PusherFake
|
|
16
18
|
# The current version string.
|
|
17
|
-
VERSION = "0.
|
|
19
|
+
VERSION = "0.3.0"
|
|
18
20
|
|
|
19
21
|
# Call this method to modify the defaults.
|
|
20
22
|
#
|
|
@@ -19,6 +19,8 @@ module PusherFake
|
|
|
19
19
|
def remove(connection)
|
|
20
20
|
super
|
|
21
21
|
|
|
22
|
+
trigger("member_removed", channel: name, user_id: members[connection][:user_id])
|
|
23
|
+
|
|
22
24
|
emit("pusher_internal:member_removed", members.delete(connection))
|
|
23
25
|
end
|
|
24
26
|
|
|
@@ -43,9 +45,11 @@ module PusherFake
|
|
|
43
45
|
# @param [Connection] connection The connection a subscription succeeded for.
|
|
44
46
|
# @param [Hash] options The options for the channel.
|
|
45
47
|
def subscription_succeeded(connection, options = {})
|
|
46
|
-
members[connection] = MultiJson.load(options[:channel_data], symbolize_keys: true)
|
|
48
|
+
member = members[connection] = MultiJson.load(options[:channel_data], symbolize_keys: true)
|
|
49
|
+
|
|
50
|
+
emit("pusher_internal:member_added", member)
|
|
47
51
|
|
|
48
|
-
|
|
52
|
+
trigger("member_added", channel: name, user_id: member[:user_id])
|
|
49
53
|
|
|
50
54
|
super
|
|
51
55
|
end
|
|
@@ -46,6 +46,10 @@ module PusherFake
|
|
|
46
46
|
# @param [Connection] connection The connection to remove.
|
|
47
47
|
def remove(connection)
|
|
48
48
|
connections.delete(connection)
|
|
49
|
+
|
|
50
|
+
if connections.empty?
|
|
51
|
+
trigger("channel_vacated", channel: name)
|
|
52
|
+
end
|
|
49
53
|
end
|
|
50
54
|
|
|
51
55
|
# Return subscription data for the channel.
|
|
@@ -66,6 +70,14 @@ module PusherFake
|
|
|
66
70
|
def subscription_succeeded(connection, options = {})
|
|
67
71
|
connection.emit("pusher_internal:subscription_succeeded", subscription_data, name)
|
|
68
72
|
connections.push(connection)
|
|
73
|
+
|
|
74
|
+
if connections.length == 1
|
|
75
|
+
trigger("channel_occupied", channel: name)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def trigger(name, data = {})
|
|
80
|
+
PusherFake::Webhook.trigger(name, data)
|
|
69
81
|
end
|
|
70
82
|
end
|
|
71
83
|
end
|
|
@@ -21,6 +21,9 @@ module PusherFake
|
|
|
21
21
|
# @return [Fixnum] The port on which the web server listens. (Defaults to +8081+.)
|
|
22
22
|
attr_accessor :web_port
|
|
23
23
|
|
|
24
|
+
# @return [Array] An array of webhook URLs. (Defaults to +[]+.)
|
|
25
|
+
attr_accessor :webhooks
|
|
26
|
+
|
|
24
27
|
# Instantiated from {PusherFake.configuration}. Sets the defaults.
|
|
25
28
|
def initialize
|
|
26
29
|
self.app_id = "PUSHER_APP_ID"
|
|
@@ -30,6 +33,7 @@ module PusherFake
|
|
|
30
33
|
self.socket_port = 8080
|
|
31
34
|
self.web_host = "127.0.0.1"
|
|
32
35
|
self.web_port = 8081
|
|
36
|
+
self.webhooks = []
|
|
33
37
|
end
|
|
34
38
|
end
|
|
35
39
|
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module PusherFake
|
|
2
|
+
class Webhook
|
|
3
|
+
class << self
|
|
4
|
+
def trigger(name, data = {})
|
|
5
|
+
payload = MultiJson.dump({
|
|
6
|
+
events: [data.merge(name: name)],
|
|
7
|
+
time_ms: Time.now.to_i
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
PusherFake.configuration.webhooks.each do |url|
|
|
11
|
+
http = EventMachine::HttpRequest.new(url)
|
|
12
|
+
http.post(body: payload, head: headers_for(payload))
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def headers_for(payload)
|
|
19
|
+
{ "Content-Type" => "application/json",
|
|
20
|
+
"X-Pusher-Key" => PusherFake.configuration.key,
|
|
21
|
+
"X-Pusher-Signature" => signature_for(payload)
|
|
22
|
+
}
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def signature_for(payload)
|
|
26
|
+
OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new, PusherFake.configuration.secret, payload)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -16,16 +16,19 @@ describe PusherFake::Channel::Presence do
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
describe PusherFake::Channel::Presence, "#add" do
|
|
19
|
-
let(:data) { { auth: authentication, channel_data:
|
|
19
|
+
let(:data) { { auth: authentication, channel_data: MultiJson.dump(channel_data) } }
|
|
20
|
+
let(:name) { "name" }
|
|
21
|
+
let(:user_id) { "1234" }
|
|
20
22
|
let(:connection) { stub(emit: nil) }
|
|
21
|
-
let(:connections) { stub(push: nil) }
|
|
22
|
-
let(:channel_data) { {} }
|
|
23
|
+
let(:connections) { stub(push: nil, length: 0) }
|
|
24
|
+
let(:channel_data) { { user_id: user_id } }
|
|
23
25
|
let(:authentication) { "auth" }
|
|
24
26
|
let(:subscription_data) { { presence: { hash: {}, count: 1 } } }
|
|
25
27
|
|
|
26
|
-
subject { PusherFake::Channel::Presence.new(
|
|
28
|
+
subject { PusherFake::Channel::Presence.new(name) }
|
|
27
29
|
|
|
28
30
|
before do
|
|
31
|
+
PusherFake::Webhook.stubs(:trigger)
|
|
29
32
|
MultiJson.stubs(:load).returns(channel_data)
|
|
30
33
|
subject.stubs(connections: connections, emit: nil, subscription_data: subscription_data)
|
|
31
34
|
end
|
|
@@ -66,20 +69,55 @@ describe PusherFake::Channel::Presence, "#add" do
|
|
|
66
69
|
connections.should have_received(:push).with(connection)
|
|
67
70
|
end
|
|
68
71
|
|
|
72
|
+
it "triggers channel occupied webhook for the first connection added when authorized" do
|
|
73
|
+
subject.unstub(:connections)
|
|
74
|
+
subject.stubs(authorized?: true)
|
|
75
|
+
|
|
76
|
+
subject.add(connection, data)
|
|
77
|
+
PusherFake::Webhook.should have_received(:trigger).with("channel_occupied", channel: name).once
|
|
78
|
+
subject.add(connection, data)
|
|
79
|
+
PusherFake::Webhook.should have_received(:trigger).with("channel_occupied", channel: name).once
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it "triggers the member added webhook when authorized" do
|
|
83
|
+
subject.stubs(authorized?: true)
|
|
84
|
+
subject.add(connection, data)
|
|
85
|
+
PusherFake::Webhook.should have_received(:trigger).with("member_added", channel: name, user_id: user_id).once
|
|
86
|
+
end
|
|
87
|
+
|
|
69
88
|
it "unsuccessfully subscribes the connection when not authorized" do
|
|
70
89
|
subject.stubs(authorized?: false)
|
|
71
90
|
subject.add(connection, data)
|
|
72
91
|
connection.should have_received(:emit).with("pusher_internal:subscription_error", {}, subject.name)
|
|
73
92
|
end
|
|
93
|
+
|
|
94
|
+
it "does not trigger channel occupied webhook when not authorized" do
|
|
95
|
+
subject.unstub(:connections)
|
|
96
|
+
subject.stubs(authorized?: false)
|
|
97
|
+
|
|
98
|
+
subject.add(connection, data)
|
|
99
|
+
PusherFake::Webhook.should have_received(:trigger).never
|
|
100
|
+
subject.add(connection, data)
|
|
101
|
+
PusherFake::Webhook.should have_received(:trigger).never
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it "does not trigger the member added webhook when not authorized" do
|
|
105
|
+
subject.stubs(authorized?: false)
|
|
106
|
+
subject.add(connection, data)
|
|
107
|
+
PusherFake::Webhook.should have_received(:trigger).never
|
|
108
|
+
end
|
|
74
109
|
end
|
|
75
110
|
|
|
76
111
|
describe PusherFake::Channel::Presence, "#remove" do
|
|
112
|
+
let(:name) { "name" }
|
|
113
|
+
let(:user_id) { "1234" }
|
|
77
114
|
let(:connection) { stub }
|
|
78
|
-
let(:channel_data) { {} }
|
|
115
|
+
let(:channel_data) { { user_id: user_id } }
|
|
79
116
|
|
|
80
|
-
subject { PusherFake::Channel::Presence.new(
|
|
117
|
+
subject { PusherFake::Channel::Presence.new(name) }
|
|
81
118
|
|
|
82
119
|
before do
|
|
120
|
+
PusherFake::Webhook.stubs(:trigger)
|
|
83
121
|
subject.members[connection] = channel_data
|
|
84
122
|
subject.stubs(connections: [connection], emit: nil)
|
|
85
123
|
end
|
|
@@ -94,6 +132,11 @@ describe PusherFake::Channel::Presence, "#remove" do
|
|
|
94
132
|
subject.members.should_not have_key(connection)
|
|
95
133
|
end
|
|
96
134
|
|
|
135
|
+
it "triggers the member removed webhook" do
|
|
136
|
+
subject.remove(connection)
|
|
137
|
+
PusherFake::Webhook.should have_received(:trigger).with("member_removed", channel: name, user_id: user_id).once
|
|
138
|
+
end
|
|
139
|
+
|
|
97
140
|
it "notifies the channel of the removed member" do
|
|
98
141
|
subject.remove(connection)
|
|
99
142
|
subject.should have_received(:emit).with("pusher_internal:member_removed", channel_data)
|
|
@@ -10,13 +10,15 @@ end
|
|
|
10
10
|
|
|
11
11
|
describe PusherFake::Channel::Private, "#add" do
|
|
12
12
|
let(:data) { { auth: authentication } }
|
|
13
|
+
let(:name) { "name" }
|
|
13
14
|
let(:connection) { stub(emit: nil) }
|
|
14
|
-
let(:connections) { stub(push: nil) }
|
|
15
|
+
let(:connections) { stub(push: nil, length: 0) }
|
|
15
16
|
let(:authentication) { "auth" }
|
|
16
17
|
|
|
17
|
-
subject { PusherFake::Channel::Private.new(
|
|
18
|
+
subject { PusherFake::Channel::Private.new(name) }
|
|
18
19
|
|
|
19
20
|
before do
|
|
21
|
+
PusherFake::Webhook.stubs(:trigger)
|
|
20
22
|
subject.stubs(connections: connections)
|
|
21
23
|
end
|
|
22
24
|
|
|
@@ -38,11 +40,31 @@ describe PusherFake::Channel::Private, "#add" do
|
|
|
38
40
|
connection.should have_received(:emit).with("pusher_internal:subscription_succeeded", {}, subject.name)
|
|
39
41
|
end
|
|
40
42
|
|
|
43
|
+
it "triggers channel occupied webhook for the first connection added when authorized" do
|
|
44
|
+
subject.unstub(:connections)
|
|
45
|
+
subject.stubs(authorized?: true)
|
|
46
|
+
|
|
47
|
+
subject.add(connection, data)
|
|
48
|
+
PusherFake::Webhook.should have_received(:trigger).with("channel_occupied", channel: name).once
|
|
49
|
+
subject.add(connection, data)
|
|
50
|
+
PusherFake::Webhook.should have_received(:trigger).with("channel_occupied", channel: name).once
|
|
51
|
+
end
|
|
52
|
+
|
|
41
53
|
it "unsuccessfully subscribes the connection when not authorized" do
|
|
42
54
|
subject.stubs(authorized?: false)
|
|
43
55
|
subject.add(connection, data)
|
|
44
56
|
connection.should have_received(:emit).with("pusher_internal:subscription_error", {}, subject.name)
|
|
45
57
|
end
|
|
58
|
+
|
|
59
|
+
it "does not trigger channel occupied webhook when not authorized" do
|
|
60
|
+
subject.unstub(:connections)
|
|
61
|
+
subject.stubs(authorized?: false)
|
|
62
|
+
|
|
63
|
+
subject.add(connection, data)
|
|
64
|
+
PusherFake::Webhook.should have_received(:trigger).never
|
|
65
|
+
subject.add(connection, data)
|
|
66
|
+
PusherFake::Webhook.should have_received(:trigger).never
|
|
67
|
+
end
|
|
46
68
|
end
|
|
47
69
|
|
|
48
70
|
describe PusherFake::Channel::Private, "#authentication_for" do
|
|
@@ -17,12 +17,14 @@ describe PusherFake::Channel::Public do
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
describe PusherFake::Channel, "#add" do
|
|
20
|
+
let(:name) { "name" }
|
|
20
21
|
let(:connection) { stub(emit: nil) }
|
|
21
|
-
let(:connections) { stub(push: nil) }
|
|
22
|
+
let(:connections) { stub(push: nil, length: 0) }
|
|
22
23
|
|
|
23
|
-
subject { PusherFake::Channel::Public.new(
|
|
24
|
+
subject { PusherFake::Channel::Public.new(name) }
|
|
24
25
|
|
|
25
26
|
before do
|
|
27
|
+
PusherFake::Webhook.stubs(:trigger)
|
|
26
28
|
subject.stubs(connections: connections)
|
|
27
29
|
end
|
|
28
30
|
|
|
@@ -35,6 +37,15 @@ describe PusherFake::Channel, "#add" do
|
|
|
35
37
|
subject.add(connection)
|
|
36
38
|
connection.should have_received(:emit).with("pusher_internal:subscription_succeeded", {}, subject.name)
|
|
37
39
|
end
|
|
40
|
+
|
|
41
|
+
it "triggers channel occupied webhook for the first connection added" do
|
|
42
|
+
subject.unstub(:connections)
|
|
43
|
+
|
|
44
|
+
subject.add(connection)
|
|
45
|
+
PusherFake::Webhook.should have_received(:trigger).with("channel_occupied", channel: name).once
|
|
46
|
+
subject.add(connection)
|
|
47
|
+
PusherFake::Webhook.should have_received(:trigger).with("channel_occupied", channel: name).once
|
|
48
|
+
end
|
|
38
49
|
end
|
|
39
50
|
|
|
40
51
|
describe PusherFake::Channel, "#emit" do
|
|
@@ -75,17 +86,27 @@ describe PusherFake::Channel, "#includes?" do
|
|
|
75
86
|
end
|
|
76
87
|
|
|
77
88
|
describe PusherFake::Channel, "#remove" do
|
|
78
|
-
let(:
|
|
89
|
+
let(:name) { "name" }
|
|
90
|
+
let(:connection_1) { stub }
|
|
91
|
+
let(:connection_2) { stub }
|
|
79
92
|
|
|
80
|
-
subject { PusherFake::Channel::Public.new(
|
|
93
|
+
subject { PusherFake::Channel::Public.new(name) }
|
|
81
94
|
|
|
82
95
|
before do
|
|
83
|
-
subject.stubs(connections: [
|
|
96
|
+
subject.stubs(connections: [connection_1, connection_2])
|
|
97
|
+
PusherFake::Webhook.stubs(:trigger)
|
|
84
98
|
end
|
|
85
99
|
|
|
86
100
|
it "removes the connection from the channel" do
|
|
87
|
-
subject.remove(
|
|
88
|
-
subject.connections.
|
|
101
|
+
subject.remove(connection_1)
|
|
102
|
+
subject.connections.should_not include(connection_1)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
it "triggers channel vacated webhook when all connections are removed" do
|
|
106
|
+
subject.remove(connection_1)
|
|
107
|
+
PusherFake::Webhook.should have_received(:trigger).never
|
|
108
|
+
subject.remove(connection_2)
|
|
109
|
+
PusherFake::Webhook.should have_received(:trigger).with("channel_vacated", channel: name).once
|
|
89
110
|
end
|
|
90
111
|
end
|
|
91
112
|
|
|
@@ -6,22 +6,25 @@ describe PusherFake::Channel, ".factory" do
|
|
|
6
6
|
|
|
7
7
|
subject { PusherFake::Channel }
|
|
8
8
|
|
|
9
|
+
before do
|
|
10
|
+
PusherFake::Channel::Public.stubs(new: channel)
|
|
11
|
+
end
|
|
12
|
+
|
|
9
13
|
after do
|
|
10
14
|
PusherFake::Channel.reset
|
|
11
15
|
end
|
|
12
16
|
|
|
13
17
|
it "caches the channel" do
|
|
18
|
+
PusherFake::Channel::Public.unstub(:new)
|
|
14
19
|
subject.factory(name).should == subject.factory(name)
|
|
15
20
|
end
|
|
16
21
|
|
|
17
22
|
it "creates a public channel by name" do
|
|
18
|
-
PusherFake::Channel::Public.stubs(new: channel)
|
|
19
23
|
subject.factory(name)
|
|
20
24
|
PusherFake::Channel::Public.should have_received(:new).with(name)
|
|
21
25
|
end
|
|
22
26
|
|
|
23
27
|
it "returns the channel instance" do
|
|
24
|
-
PusherFake::Channel::Public.stubs(new: channel)
|
|
25
28
|
subject.factory(name).should == channel
|
|
26
29
|
end
|
|
27
30
|
end
|
|
@@ -32,22 +35,25 @@ describe PusherFake::Channel, ".factory, for a private channel" do
|
|
|
32
35
|
|
|
33
36
|
subject { PusherFake::Channel }
|
|
34
37
|
|
|
38
|
+
before do
|
|
39
|
+
PusherFake::Channel::Private.stubs(new: channel)
|
|
40
|
+
end
|
|
41
|
+
|
|
35
42
|
after do
|
|
36
43
|
PusherFake::Channel.reset
|
|
37
44
|
end
|
|
38
45
|
|
|
39
46
|
it "caches the channel" do
|
|
47
|
+
PusherFake::Channel::Private.unstub(:new)
|
|
40
48
|
subject.factory(name).should == subject.factory(name)
|
|
41
49
|
end
|
|
42
50
|
|
|
43
51
|
it "creates a private channel by name" do
|
|
44
|
-
PusherFake::Channel::Private.stubs(new: channel)
|
|
45
52
|
subject.factory(name)
|
|
46
53
|
PusherFake::Channel::Private.should have_received(:new).with(name)
|
|
47
54
|
end
|
|
48
55
|
|
|
49
56
|
it "returns the channel instance" do
|
|
50
|
-
PusherFake::Channel::Private.stubs(new: channel)
|
|
51
57
|
subject.factory(name).should == channel
|
|
52
58
|
end
|
|
53
59
|
end
|
|
@@ -58,22 +64,25 @@ describe PusherFake::Channel, ".factory, for a presence channel" do
|
|
|
58
64
|
|
|
59
65
|
subject { PusherFake::Channel }
|
|
60
66
|
|
|
67
|
+
before do
|
|
68
|
+
PusherFake::Channel::Presence.stubs(new: channel)
|
|
69
|
+
end
|
|
70
|
+
|
|
61
71
|
after do
|
|
62
72
|
PusherFake::Channel.reset
|
|
63
73
|
end
|
|
64
74
|
|
|
65
75
|
it "caches the channel" do
|
|
76
|
+
PusherFake::Channel::Presence.unstub(:new)
|
|
66
77
|
subject.factory(name).should == subject.factory(name)
|
|
67
78
|
end
|
|
68
79
|
|
|
69
80
|
it "creates a presence channel by name" do
|
|
70
|
-
PusherFake::Channel::Presence.stubs(new: channel)
|
|
71
81
|
subject.factory(name)
|
|
72
82
|
PusherFake::Channel::Presence.should have_received(:new).with(name)
|
|
73
83
|
end
|
|
74
84
|
|
|
75
85
|
it "returns the channel instance" do
|
|
76
|
-
PusherFake::Channel::Presence.stubs(new: channel)
|
|
77
86
|
subject.factory(name).should == channel
|
|
78
87
|
end
|
|
79
88
|
end
|
|
@@ -116,6 +125,7 @@ describe PusherFake::Channel, ".reset" do
|
|
|
116
125
|
subject { PusherFake::Channel }
|
|
117
126
|
|
|
118
127
|
it "empties the channel cache" do
|
|
128
|
+
subject.factory("example")
|
|
119
129
|
subject.reset
|
|
120
130
|
subject.channels.should == {}
|
|
121
131
|
end
|
|
@@ -8,4 +8,5 @@ describe PusherFake::Configuration do
|
|
|
8
8
|
it { should have_configuration_option(:socket_port).with_default(8080) }
|
|
9
9
|
it { should have_configuration_option(:web_host).with_default("127.0.0.1") }
|
|
10
10
|
it { should have_configuration_option(:web_port).with_default(8081) }
|
|
11
|
+
it { should have_configuration_option(:webhooks).with_default([]) }
|
|
11
12
|
end
|
|
@@ -10,7 +10,7 @@ describe PusherFake::Server, ".start" do
|
|
|
10
10
|
|
|
11
11
|
it "runs the event loop" do
|
|
12
12
|
subject.start
|
|
13
|
-
EventMachine.should have_received(:run)
|
|
13
|
+
EventMachine.should have_received(:run).with()
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
it "starts the socket web server when run yields" do
|
|
@@ -20,7 +20,7 @@ describe PusherFake::Server, ".start" do
|
|
|
20
20
|
EventMachine.stubs(:run).yields
|
|
21
21
|
|
|
22
22
|
subject.start
|
|
23
|
-
subject.should have_received(:start_web_server)
|
|
23
|
+
subject.should have_received(:start_web_server).with()
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
it "starts the socket server when run yields" do
|
|
@@ -30,7 +30,7 @@ describe PusherFake::Server, ".start" do
|
|
|
30
30
|
EventMachine.stubs(:run).yields
|
|
31
31
|
|
|
32
32
|
subject.start
|
|
33
|
-
subject.should have_received(:start_socket_server)
|
|
33
|
+
subject.should have_received(:start_socket_server).with()
|
|
34
34
|
end
|
|
35
35
|
end
|
|
36
36
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe PusherFake::Webhook, ".trigger" do
|
|
4
|
+
subject { PusherFake::Webhook }
|
|
5
|
+
|
|
6
|
+
let(:data) { { channel: "name" } }
|
|
7
|
+
let(:http) { stub(post: true) }
|
|
8
|
+
let(:name) { "channel_occupied" }
|
|
9
|
+
let(:payload) { MultiJson.dump({ events: [data.merge(name: name)], time_ms: Time.now.to_i }) }
|
|
10
|
+
let(:webhooks) { ["url"] }
|
|
11
|
+
let(:signature) { "signature" }
|
|
12
|
+
let(:configuration) { stub(key: "key", secret: "secret", webhooks: webhooks) }
|
|
13
|
+
|
|
14
|
+
before do
|
|
15
|
+
OpenSSL::HMAC.stubs(hexdigest: signature)
|
|
16
|
+
EventMachine::HttpRequest.stubs(new: http)
|
|
17
|
+
PusherFake.stubs(configuration: configuration)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "generates a signature" do
|
|
21
|
+
subject.trigger(name, data)
|
|
22
|
+
OpenSSL::HMAC.should have_received(:hexdigest).with(kind_of(OpenSSL::Digest::SHA256), configuration.secret, payload)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "creates a HTTP request for each webhook URL" do
|
|
26
|
+
subject.trigger(name, data)
|
|
27
|
+
EventMachine::HttpRequest.should have_received(:new).with(webhooks.first)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "posts the payload to the webhook URL" do
|
|
31
|
+
subject.trigger(name, data)
|
|
32
|
+
http.should have_received(:post).with(
|
|
33
|
+
body: payload,
|
|
34
|
+
head: {
|
|
35
|
+
"Content-Type" => "application/json",
|
|
36
|
+
"X-Pusher-Key" => configuration.key,
|
|
37
|
+
"X-Pusher-Signature" => signature
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
end
|
|
41
|
+
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -6,11 +6,8 @@ module BartenderHelper
|
|
|
6
6
|
|
|
7
7
|
def matches?(configuration)
|
|
8
8
|
@configuration = configuration
|
|
9
|
-
|
|
10
9
|
@configuration.respond_to?(@option).should == true
|
|
11
|
-
|
|
12
10
|
@configuration.__send__(@option).should == @default if instance_variables.include?("@default")
|
|
13
|
-
|
|
14
11
|
@configuration.__send__(:"#{@option}=", "value")
|
|
15
12
|
@configuration.__send__(@option).should == "value"
|
|
16
13
|
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.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -9,16 +9,16 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2012-
|
|
12
|
+
date: 2012-12-12 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
|
-
name: em-
|
|
15
|
+
name: em-http-request
|
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
|
17
17
|
none: false
|
|
18
18
|
requirements:
|
|
19
19
|
- - '='
|
|
20
20
|
- !ruby/object:Gem::Version
|
|
21
|
-
version: 0.3
|
|
21
|
+
version: 1.0.3
|
|
22
22
|
type: :runtime
|
|
23
23
|
prerelease: false
|
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -26,15 +26,15 @@ dependencies:
|
|
|
26
26
|
requirements:
|
|
27
27
|
- - '='
|
|
28
28
|
- !ruby/object:Gem::Version
|
|
29
|
-
version: 0.3
|
|
29
|
+
version: 1.0.3
|
|
30
30
|
- !ruby/object:Gem::Dependency
|
|
31
|
-
name:
|
|
31
|
+
name: em-websocket
|
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
|
33
33
|
none: false
|
|
34
34
|
requirements:
|
|
35
35
|
- - '='
|
|
36
36
|
- !ruby/object:Gem::Version
|
|
37
|
-
version:
|
|
37
|
+
version: 0.3.8
|
|
38
38
|
type: :runtime
|
|
39
39
|
prerelease: false
|
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -42,15 +42,15 @@ dependencies:
|
|
|
42
42
|
requirements:
|
|
43
43
|
- - '='
|
|
44
44
|
- !ruby/object:Gem::Version
|
|
45
|
-
version:
|
|
45
|
+
version: 0.3.8
|
|
46
46
|
- !ruby/object:Gem::Dependency
|
|
47
|
-
name:
|
|
47
|
+
name: thin
|
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
|
49
49
|
none: false
|
|
50
50
|
requirements:
|
|
51
51
|
- - '='
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: 1.
|
|
53
|
+
version: 1.5.0
|
|
54
54
|
type: :runtime
|
|
55
55
|
prerelease: false
|
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -58,47 +58,31 @@ dependencies:
|
|
|
58
58
|
requirements:
|
|
59
59
|
- - '='
|
|
60
60
|
- !ruby/object:Gem::Version
|
|
61
|
-
version: 1.
|
|
61
|
+
version: 1.5.0
|
|
62
62
|
- !ruby/object:Gem::Dependency
|
|
63
|
-
name:
|
|
63
|
+
name: multi_json
|
|
64
64
|
requirement: !ruby/object:Gem::Requirement
|
|
65
65
|
none: false
|
|
66
66
|
requirements:
|
|
67
67
|
- - '='
|
|
68
68
|
- !ruby/object:Gem::Version
|
|
69
|
-
version: 1.
|
|
70
|
-
type: :
|
|
69
|
+
version: 1.4.0
|
|
70
|
+
type: :runtime
|
|
71
71
|
prerelease: false
|
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
|
73
73
|
none: false
|
|
74
74
|
requirements:
|
|
75
75
|
- - '='
|
|
76
76
|
- !ruby/object:Gem::Version
|
|
77
|
-
version: 1.
|
|
77
|
+
version: 1.4.0
|
|
78
78
|
- !ruby/object:Gem::Dependency
|
|
79
|
-
name:
|
|
80
|
-
requirement: !ruby/object:Gem::Requirement
|
|
81
|
-
none: false
|
|
82
|
-
requirements:
|
|
83
|
-
- - ! '>='
|
|
84
|
-
- !ruby/object:Gem::Version
|
|
85
|
-
version: 1.1.0
|
|
86
|
-
type: :development
|
|
87
|
-
prerelease: false
|
|
88
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
89
|
-
none: false
|
|
90
|
-
requirements:
|
|
91
|
-
- - ! '>='
|
|
92
|
-
- !ruby/object:Gem::Version
|
|
93
|
-
version: 1.1.0
|
|
94
|
-
- !ruby/object:Gem::Dependency
|
|
95
|
-
name: capybara
|
|
79
|
+
name: bourne
|
|
96
80
|
requirement: !ruby/object:Gem::Requirement
|
|
97
81
|
none: false
|
|
98
82
|
requirements:
|
|
99
83
|
- - '='
|
|
100
84
|
- !ruby/object:Gem::Version
|
|
101
|
-
version: 1.
|
|
85
|
+
version: 1.3.0
|
|
102
86
|
type: :development
|
|
103
87
|
prerelease: false
|
|
104
88
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -106,7 +90,7 @@ dependencies:
|
|
|
106
90
|
requirements:
|
|
107
91
|
- - '='
|
|
108
92
|
- !ruby/object:Gem::Version
|
|
109
|
-
version: 1.
|
|
93
|
+
version: 1.3.0
|
|
110
94
|
- !ruby/object:Gem::Dependency
|
|
111
95
|
name: capybara-webkit
|
|
112
96
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -249,22 +233,26 @@ files:
|
|
|
249
233
|
- lib/pusher-fake/connection.rb
|
|
250
234
|
- lib/pusher-fake/server/application.rb
|
|
251
235
|
- lib/pusher-fake/server.rb
|
|
236
|
+
- lib/pusher-fake/webhook.rb
|
|
252
237
|
- lib/pusher-fake.rb
|
|
253
238
|
- features/channel_presence.feature
|
|
254
239
|
- features/channel_subscribe.feature
|
|
255
240
|
- features/channel_trigger.feature
|
|
241
|
+
- features/channel_webhooks.feature
|
|
256
242
|
- features/client_connect.feature
|
|
257
243
|
- features/step_definitions/channel_steps.rb
|
|
258
244
|
- features/step_definitions/client_steps.rb
|
|
259
245
|
- features/step_definitions/event_steps.rb
|
|
260
246
|
- features/step_definitions/navigation_steps.rb
|
|
261
247
|
- features/step_definitions/presence_steps.rb
|
|
248
|
+
- features/step_definitions/webhook_steps.rb
|
|
262
249
|
- features/support/application/public/javascripts/vendor/pusher-1.12.5.js
|
|
263
250
|
- features/support/application/views/index.erb
|
|
264
251
|
- features/support/application.rb
|
|
265
252
|
- features/support/environment.rb
|
|
266
253
|
- features/support/pusher-fake.rb
|
|
267
254
|
- features/support/wait.rb
|
|
255
|
+
- features/support/webhooks.rb
|
|
268
256
|
- spec/lib/pusher-fake/channel/presence_spec.rb
|
|
269
257
|
- spec/lib/pusher-fake/channel/private_spec.rb
|
|
270
258
|
- spec/lib/pusher-fake/channel/public_spec.rb
|
|
@@ -273,6 +261,7 @@ files:
|
|
|
273
261
|
- spec/lib/pusher-fake/connection_spec.rb
|
|
274
262
|
- spec/lib/pusher-fake/server/application_spec.rb
|
|
275
263
|
- spec/lib/pusher-fake/server_spec.rb
|
|
264
|
+
- spec/lib/pusher-fake/webhook_spec.rb
|
|
276
265
|
- spec/spec_helper.rb
|
|
277
266
|
- spec/support/have_configuration_option_matcher.rb
|
|
278
267
|
homepage: http://github.com/tristandunn/pusher-fake
|
|
@@ -290,7 +279,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
290
279
|
version: '0'
|
|
291
280
|
segments:
|
|
292
281
|
- 0
|
|
293
|
-
hash:
|
|
282
|
+
hash: 4186586164521781753
|
|
294
283
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
295
284
|
none: false
|
|
296
285
|
requirements:
|
|
@@ -299,7 +288,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
299
288
|
version: '0'
|
|
300
289
|
segments:
|
|
301
290
|
- 0
|
|
302
|
-
hash:
|
|
291
|
+
hash: 4186586164521781753
|
|
303
292
|
requirements: []
|
|
304
293
|
rubyforge_project:
|
|
305
294
|
rubygems_version: 1.8.23
|
|
@@ -310,18 +299,21 @@ test_files:
|
|
|
310
299
|
- features/channel_presence.feature
|
|
311
300
|
- features/channel_subscribe.feature
|
|
312
301
|
- features/channel_trigger.feature
|
|
302
|
+
- features/channel_webhooks.feature
|
|
313
303
|
- features/client_connect.feature
|
|
314
304
|
- features/step_definitions/channel_steps.rb
|
|
315
305
|
- features/step_definitions/client_steps.rb
|
|
316
306
|
- features/step_definitions/event_steps.rb
|
|
317
307
|
- features/step_definitions/navigation_steps.rb
|
|
318
308
|
- features/step_definitions/presence_steps.rb
|
|
309
|
+
- features/step_definitions/webhook_steps.rb
|
|
319
310
|
- features/support/application/public/javascripts/vendor/pusher-1.12.5.js
|
|
320
311
|
- features/support/application/views/index.erb
|
|
321
312
|
- features/support/application.rb
|
|
322
313
|
- features/support/environment.rb
|
|
323
314
|
- features/support/pusher-fake.rb
|
|
324
315
|
- features/support/wait.rb
|
|
316
|
+
- features/support/webhooks.rb
|
|
325
317
|
- spec/lib/pusher-fake/channel/presence_spec.rb
|
|
326
318
|
- spec/lib/pusher-fake/channel/private_spec.rb
|
|
327
319
|
- spec/lib/pusher-fake/channel/public_spec.rb
|
|
@@ -330,6 +322,7 @@ test_files:
|
|
|
330
322
|
- spec/lib/pusher-fake/connection_spec.rb
|
|
331
323
|
- spec/lib/pusher-fake/server/application_spec.rb
|
|
332
324
|
- spec/lib/pusher-fake/server_spec.rb
|
|
325
|
+
- spec/lib/pusher-fake/webhook_spec.rb
|
|
333
326
|
- spec/spec_helper.rb
|
|
334
327
|
- spec/support/have_configuration_option_matcher.rb
|
|
335
328
|
has_rdoc:
|