pusher 0.17.0 → 2.0.3

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/spec/client_spec.rb DELETED
@@ -1,488 +0,0 @@
1
- require 'spec_helper'
2
-
3
- require 'em-http'
4
-
5
- describe Pusher do
6
- # The behaviour should be the same when using the Client object, or the
7
- # 'global' client delegated through the Pusher class
8
- [lambda { Pusher }, lambda { Pusher::Client.new }].each do |client_gen|
9
- before :each do
10
- @client = client_gen.call
11
- end
12
-
13
- describe 'default configuration' do
14
- it 'should be preconfigured for api host' do
15
- expect(@client.host).to eq('api.pusherapp.com')
16
- end
17
-
18
- it 'should be preconfigured for port 80' do
19
- expect(@client.port).to eq(80)
20
- end
21
-
22
- it 'should use standard logger if no other logger if defined' do
23
- Pusher.logger.debug('foo')
24
- expect(Pusher.logger).to be_kind_of(Logger)
25
- end
26
- end
27
-
28
- describe 'logging configuration' do
29
- it "can be configured to use any logger" do
30
- logger = double("ALogger")
31
- expect(logger).to receive(:debug).with('foo')
32
- Pusher.logger = logger
33
- Pusher.logger.debug('foo')
34
- Pusher.logger = nil
35
- end
36
- end
37
-
38
- describe "configuration using url" do
39
- it "should be possible to configure everything by setting the url" do
40
- @client.url = "test://somekey:somesecret@api.staging.pusherapp.com:8080/apps/87"
41
-
42
- expect(@client.scheme).to eq('test')
43
- expect(@client.host).to eq('api.staging.pusherapp.com')
44
- expect(@client.port).to eq(8080)
45
- expect(@client.key).to eq('somekey')
46
- expect(@client.secret).to eq('somesecret')
47
- expect(@client.app_id).to eq('87')
48
- end
49
-
50
- it "should override scheme and port when setting encrypted=true after url" do
51
- @client.url = "http://somekey:somesecret@api.staging.pusherapp.com:8080/apps/87"
52
- @client.encrypted = true
53
-
54
- expect(@client.scheme).to eq('https')
55
- expect(@client.port).to eq(443)
56
- end
57
-
58
- it "should fail on bad urls" do
59
- expect { @client.url = "gopher/somekey:somesecret@://api.staging.pusherapp.co://m:8080\apps\87" }.to raise_error(URI::InvalidURIError)
60
- end
61
- end
62
-
63
- describe 'configuring the cluster' do
64
- it 'should set a new default host' do
65
- @client.cluster = 'eu'
66
- expect(@client.host).to eq('api-eu.pusher.com')
67
- end
68
-
69
- it 'should be overridden by host if it comes after' do
70
- @client.cluster = 'eu'
71
- @client.host = 'api.staging.pusher.com'
72
- expect(@client.host).to eq('api.staging.pusher.com')
73
- end
74
-
75
- it 'should be overridden by url if it comes after' do
76
- @client.cluster = 'eu'
77
- @client.url = "http://somekey:somesecret@api.staging.pusherapp.com:8080/apps/87"
78
-
79
- expect(@client.host).to eq('api.staging.pusherapp.com')
80
- end
81
-
82
- it 'should get override the url configuration if it comes after' do
83
- @client.url = "http://somekey:somesecret@api.staging.pusherapp.com:8080/apps/87"
84
- @client.cluster = 'eu'
85
- expect(@client.host).to eq('api-eu.pusher.com')
86
- end
87
-
88
- it 'should overrie by the host configuration if it comes after' do
89
- @client.host = 'api.staging.pusher.com'
90
- @client.cluster = 'eu'
91
- expect(@client.host).to eq('api-eu.pusher.com')
92
- end
93
- end
94
-
95
- describe 'configuring a http proxy' do
96
- it "should be possible to configure everything by setting the http_proxy" do
97
- @client.http_proxy = 'http://someuser:somepassword@proxy.host.com:8080'
98
-
99
- expect(@client.proxy).to eq({:scheme => 'http', :host => 'proxy.host.com', :port => 8080, :user => 'someuser', :password => 'somepassword'})
100
- end
101
- end
102
-
103
- describe 'when configured' do
104
- before :each do
105
- @client.app_id = '20'
106
- @client.key = '12345678900000001'
107
- @client.secret = '12345678900000001'
108
- end
109
-
110
- describe '#[]' do
111
- before do
112
- @channel = @client['test_channel']
113
- end
114
-
115
- it 'should return a channel' do
116
- expect(@channel).to be_kind_of(Pusher::Channel)
117
- end
118
-
119
- %w{app_id key secret}.each do |config|
120
- it "should raise exception if #{config} not configured" do
121
- @client.send("#{config}=", nil)
122
- expect {
123
- @client['test_channel']
124
- }.to raise_error(Pusher::ConfigurationError)
125
- end
126
- end
127
- end
128
-
129
- describe '#channels' do
130
- it "should call the correct URL and symbolise response correctly" do
131
- api_path = %r{/apps/20/channels}
132
- stub_request(:get, api_path).to_return({
133
- :status => 200,
134
- :body => MultiJson.encode('channels' => {
135
- "channel1" => {},
136
- "channel2" => {}
137
- })
138
- })
139
- expect(@client.channels).to eq({
140
- :channels => {
141
- "channel1" => {},
142
- "channel2" => {}
143
- }
144
- })
145
- end
146
- end
147
-
148
- describe '#channel_info' do
149
- it "should call correct URL and symbolise response" do
150
- api_path = %r{/apps/20/channels/mychannel}
151
- stub_request(:get, api_path).to_return({
152
- :status => 200,
153
- :body => MultiJson.encode({
154
- 'occupied' => false,
155
- })
156
- })
157
- expect(@client.channel_info('mychannel')).to eq({
158
- :occupied => false,
159
- })
160
- end
161
- end
162
-
163
- describe '#channel_users' do
164
- it "should call correct URL and symbolise response" do
165
- api_path = %r{/apps/20/channels/mychannel/users}
166
- stub_request(:get, api_path).to_return({
167
- :status => 200,
168
- :body => MultiJson.encode({
169
- 'users' => [{ 'id' => 1 }]
170
- })
171
- })
172
- expect(@client.channel_users('mychannel')).to eq({
173
- :users => [{ 'id' => 1}]
174
- })
175
- end
176
- end
177
-
178
- describe '#authenticate' do
179
- before :each do
180
- @custom_data = {:uid => 123, :info => {:name => 'Foo'}}
181
- end
182
-
183
- it 'should return a hash with signature including custom data and data as json string' do
184
- allow(MultiJson).to receive(:encode).with(@custom_data).and_return 'a json string'
185
-
186
- response = @client.authenticate('test_channel', '1.1', @custom_data)
187
-
188
- expect(response).to eq({
189
- :auth => "12345678900000001:#{hmac(@client.secret, "1.1:test_channel:a json string")}",
190
- :channel_data => 'a json string'
191
- })
192
- end
193
-
194
- end
195
-
196
- describe '#trigger' do
197
- before :each do
198
- @api_path = %r{/apps/20/events}
199
- stub_request(:post, @api_path).to_return({
200
- :status => 200,
201
- :body => MultiJson.encode({})
202
- })
203
- end
204
-
205
- it "should call correct URL" do
206
- expect(@client.trigger(['mychannel'], 'event', {'some' => 'data'})).
207
- to eq({})
208
- end
209
-
210
- it "should not allow too many channels" do
211
- expect {
212
- @client.trigger((0..11).map{|i| 'mychannel#{i}'},
213
- 'event', {'some' => 'data'}, {
214
- :socket_id => "12.34"
215
- })}.to raise_error(Pusher::Error)
216
- end
217
-
218
- it "should pass any parameters in the body of the request" do
219
- @client.trigger(['mychannel', 'c2'], 'event', {'some' => 'data'}, {
220
- :socket_id => "12.34"
221
- })
222
- expect(WebMock).to have_requested(:post, @api_path).with { |req|
223
- parsed = MultiJson.decode(req.body)
224
- expect(parsed["name"]).to eq('event')
225
- expect(parsed["channels"]).to eq(["mychannel", "c2"])
226
- expect(parsed["socket_id"]).to eq('12.34')
227
- }
228
- end
229
-
230
- it "should convert non string data to JSON before posting" do
231
- @client.trigger(['mychannel'], 'event', {'some' => 'data'})
232
- expect(WebMock).to have_requested(:post, @api_path).with { |req|
233
- expect(MultiJson.decode(req.body)["data"]).to eq('{"some":"data"}')
234
- }
235
- end
236
-
237
- it "should accept a single channel as well as an array" do
238
- @client.trigger('mychannel', 'event', {'some' => 'data'})
239
- expect(WebMock).to have_requested(:post, @api_path).with { |req|
240
- expect(MultiJson.decode(req.body)["channels"]).to eq(['mychannel'])
241
- }
242
- end
243
- end
244
-
245
- describe '#trigger_async' do
246
- before :each do
247
- @api_path = %r{/apps/20/events}
248
- stub_request(:post, @api_path).to_return({
249
- :status => 200,
250
- :body => MultiJson.encode({})
251
- })
252
- end
253
-
254
- it "should call correct URL" do
255
- EM.run {
256
- @client.trigger_async('mychannel', 'event', {'some' => 'data'}).callback { |r|
257
- expect(r).to eq({})
258
- EM.stop
259
- }
260
- }
261
- end
262
-
263
- it "should pass any parameters in the body of the request" do
264
- EM.run {
265
- @client.trigger_async('mychannel', 'event', {'some' => 'data'}, {
266
- :socket_id => "12.34"
267
- }).callback {
268
- expect(WebMock).to have_requested(:post, @api_path).with { |req|
269
- expect(MultiJson.decode(req.body)["socket_id"]).to eq('12.34')
270
- }
271
- EM.stop
272
- }
273
- }
274
- end
275
-
276
- it "should convert non string data to JSON before posting" do
277
- EM.run {
278
- @client.trigger_async('mychannel', 'event', {'some' => 'data'}).callback {
279
- expect(WebMock).to have_requested(:post, @api_path).with { |req|
280
- expect(MultiJson.decode(req.body)["data"]).to eq('{"some":"data"}')
281
- }
282
- EM.stop
283
- }
284
- }
285
- end
286
- end
287
-
288
- [:get, :post].each do |verb|
289
- describe "##{verb}" do
290
- before :each do
291
- @url_regexp = %r{api.pusherapp.com}
292
- stub_request(verb, @url_regexp).
293
- to_return(:status => 200, :body => "{}")
294
- end
295
-
296
- let(:call_api) { @client.send(verb, '/path') }
297
-
298
- it "should use http by default" do
299
- call_api
300
- expect(WebMock).to have_requested(verb, %r{http://api.pusherapp.com/apps/20/path})
301
- end
302
-
303
- it "should use https if configured" do
304
- @client.encrypted = true
305
- call_api
306
- expect(WebMock).to have_requested(verb, %r{https://api.pusherapp.com})
307
- end
308
-
309
- it "should format the respose hash with symbols at first level" do
310
- stub_request(verb, @url_regexp).to_return({
311
- :status => 200,
312
- :body => MultiJson.encode({'something' => {'a' => 'hash'}})
313
- })
314
- expect(call_api).to eq({
315
- :something => {'a' => 'hash'}
316
- })
317
- end
318
-
319
- it "should catch all http exceptions and raise a Pusher::HTTPError wrapping the original error" do
320
- stub_request(verb, @url_regexp).to_raise(HTTPClient::TimeoutError)
321
-
322
- error = nil
323
- begin
324
- call_api
325
- rescue => e
326
- error = e
327
- end
328
-
329
- expect(error.class).to eq(Pusher::HTTPError)
330
- expect(error).to be_kind_of(Pusher::Error)
331
- expect(error.message).to eq('Exception from WebMock (HTTPClient::TimeoutError)')
332
- expect(error.original_error.class).to eq(HTTPClient::TimeoutError)
333
- end
334
-
335
- it "should raise Pusher::Error if call returns 400" do
336
- stub_request(verb, @url_regexp).to_return({:status => 400})
337
- expect { call_api }.to raise_error(Pusher::Error)
338
- end
339
-
340
- it "should raise AuthenticationError if pusher returns 401" do
341
- stub_request(verb, @url_regexp).to_return({:status => 401})
342
- expect { call_api }.to raise_error(Pusher::AuthenticationError)
343
- end
344
-
345
- it "should raise Pusher::Error if pusher returns 404" do
346
- stub_request(verb, @url_regexp).to_return({:status => 404})
347
- expect { call_api }.to raise_error(Pusher::Error, '404 Not found (/apps/20/path)')
348
- end
349
-
350
- it "should raise Pusher::Error if pusher returns 407" do
351
- stub_request(verb, @url_regexp).to_return({:status => 407})
352
- expect { call_api }.to raise_error(Pusher::Error, 'Proxy Authentication Required')
353
- end
354
-
355
- it "should raise Pusher::Error if pusher returns 500" do
356
- stub_request(verb, @url_regexp).to_return({:status => 500, :body => "some error"})
357
- expect { call_api }.to raise_error(Pusher::Error, 'Unknown error (status code 500): some error')
358
- end
359
- end
360
- end
361
-
362
- describe "async calling without eventmachine" do
363
- [[:get, :get_async], [:post, :post_async]].each do |verb, method|
364
- describe "##{method}" do
365
- before :each do
366
- @url_regexp = %r{api.pusherapp.com}
367
- stub_request(verb, @url_regexp).
368
- to_return(:status => 200, :body => "{}")
369
- end
370
-
371
- let(:call_api) {
372
- @client.send(method, '/path').tap { |c|
373
- # Allow the async thread (inside httpclient) to run
374
- while !c.finished?
375
- sleep 0.01
376
- end
377
- }
378
- }
379
-
380
- it "should use http by default" do
381
- call_api
382
- expect(WebMock).to have_requested(verb, %r{http://api.pusherapp.com/apps/20/path})
383
- end
384
-
385
- it "should use https if configured" do
386
- @client.encrypted = true
387
- call_api
388
- expect(WebMock).to have_requested(verb, %r{https://api.pusherapp.com})
389
- end
390
-
391
- # Note that the raw httpclient connection object is returned and
392
- # the response isn't handled (by handle_response) in the normal way.
393
- it "should return a httpclient connection object" do
394
- connection = call_api
395
- expect(connection.finished?).to be_truthy
396
- response = connection.pop
397
- expect(response.status).to eq(200)
398
- expect(response.body.read).to eq("{}")
399
- end
400
- end
401
- end
402
- end
403
-
404
- describe "async calling with eventmachine" do
405
- [[:get, :get_async], [:post, :post_async]].each do |verb, method|
406
- describe "##{method}" do
407
- before :each do
408
- @url_regexp = %r{api.pusherapp.com}
409
- stub_request(verb, @url_regexp).
410
- to_return(:status => 200, :body => "{}")
411
- end
412
-
413
- let(:call_api) { @client.send(method, '/path') }
414
-
415
- it "should use http by default" do
416
- EM.run {
417
- call_api.callback {
418
- expect(WebMock).to have_requested(verb, %r{http://api.pusherapp.com/apps/20/path})
419
- EM.stop
420
- }
421
- }
422
- end
423
-
424
- it "should use https if configured" do
425
- EM.run {
426
- @client.encrypted = true
427
- call_api.callback {
428
- expect(WebMock).to have_requested(verb, %r{https://api.pusherapp.com})
429
- EM.stop
430
- }
431
- }
432
- end
433
-
434
- it "should format the respose hash with symbols at first level" do
435
- EM.run {
436
- stub_request(verb, @url_regexp).to_return({
437
- :status => 200,
438
- :body => MultiJson.encode({'something' => {'a' => 'hash'}})
439
- })
440
- call_api.callback { |response|
441
- expect(response).to eq({
442
- :something => {'a' => 'hash'}
443
- })
444
- EM.stop
445
- }
446
- }
447
- end
448
-
449
- it "should errback with Pusher::Error on unsuccessful response" do
450
- EM.run {
451
- stub_request(verb, @url_regexp).to_return({:status => 400})
452
-
453
- call_api.errback { |e|
454
- expect(e.class).to eq(Pusher::Error)
455
- EM.stop
456
- }.callback {
457
- fail
458
- }
459
- }
460
- end
461
- end
462
- end
463
- end
464
- end
465
- end
466
-
467
- describe 'configuring cluster' do
468
- it 'should allow clients to specify the cluster only with the default host' do
469
- client = Pusher::Client.new({
470
- :scheme => 'http',
471
- :cluster => 'eu',
472
- :port => 80
473
- })
474
- expect(client.host).to eq('api-eu.pusher.com')
475
- end
476
-
477
- it 'should always have host override any supplied cluster value' do
478
- client = Pusher::Client.new({
479
- :scheme => 'http',
480
- :host => 'api.staging.pusherapp.com',
481
- :cluster => 'eu',
482
- :port => 80
483
- })
484
- expect(client.host).to eq('api.staging.pusherapp.com')
485
- end
486
- end
487
- end
488
-
data/spec/spec_helper.rb DELETED
@@ -1,26 +0,0 @@
1
- begin
2
- require 'bundler/setup'
3
- rescue LoadError
4
- puts 'although not required, it is recommended that you use bundler when running the tests'
5
- end
6
-
7
- ENV['PUSHER_URL']= 'http://some:secret@api.secret.pusherapp.com:441/apps/54'
8
-
9
- require 'rspec'
10
- require 'em-http' # As of webmock 1.4.0, em-http must be loaded first
11
- require 'webmock/rspec'
12
-
13
- require 'pusher'
14
- require 'eventmachine'
15
-
16
- RSpec.configure do |config|
17
- config.before(:each) do
18
- WebMock.reset!
19
- WebMock.disable_net_connect!
20
- end
21
- end
22
-
23
- def hmac(key, data)
24
- digest = OpenSSL::Digest::SHA256.new
25
- OpenSSL::HMAC.hexdigest(digest, key, data)
26
- end
@@ -1,117 +0,0 @@
1
- require 'spec_helper'
2
-
3
- require 'rack'
4
- require 'stringio'
5
-
6
- describe Pusher::WebHook do
7
- before :each do
8
- @hook_data = {
9
- "time_ms" => 123456,
10
- "events" => [
11
- {"name" => 'foo'}
12
- ]
13
- }
14
- end
15
-
16
- describe "initialization" do
17
- it "can be initialized with Rack::Request" do
18
- request = Rack::Request.new({
19
- 'HTTP_X_PUSHER_KEY' => '1234',
20
- 'HTTP_X_PUSHER_SIGNATURE' => 'asdf',
21
- 'CONTENT_TYPE' => 'application/json',
22
- 'rack.input' => StringIO.new(MultiJson.encode(@hook_data))
23
- })
24
- wh = Pusher::WebHook.new(request)
25
- expect(wh.key).to eq('1234')
26
- expect(wh.signature).to eq('asdf')
27
- expect(wh.data).to eq(@hook_data)
28
- end
29
-
30
- it "can be initialized with a hash" do
31
- request = {
32
- :key => '1234',
33
- :signature => 'asdf',
34
- :content_type => 'application/json',
35
- :body => MultiJson.encode(@hook_data),
36
- }
37
- wh = Pusher::WebHook.new(request)
38
- expect(wh.key).to eq('1234')
39
- expect(wh.signature).to eq('asdf')
40
- expect(wh.data).to eq(@hook_data)
41
- end
42
- end
43
-
44
- describe "after initialization" do
45
- before :each do
46
- @body = MultiJson.encode(@hook_data)
47
- request = {
48
- :key => '1234',
49
- :signature => hmac('asdf', @body),
50
- :content_type => 'application/json',
51
- :body => @body
52
- }
53
-
54
- @client = Pusher::Client.new
55
- @wh = Pusher::WebHook.new(request, @client)
56
- end
57
-
58
- it "should validate" do
59
- @client.key = '1234'
60
- @client.secret = 'asdf'
61
- expect(@wh).to be_valid
62
- end
63
-
64
- it "should not validate if key is wrong" do
65
- @client.key = '12345'
66
- @client.secret = 'asdf'
67
- expect(Pusher.logger).to receive(:warn).with("Received webhook with unknown key: 1234")
68
- expect(@wh).not_to be_valid
69
- end
70
-
71
- it "should not validate if secret is wrong" do
72
- @client.key = '1234'
73
- @client.secret = 'asdfxxx'
74
- digest = OpenSSL::Digest::SHA256.new
75
- expected = OpenSSL::HMAC.hexdigest(digest, @client.secret, @body)
76
- expect(Pusher.logger).to receive(:warn).with("Received WebHook with invalid signature: got #{@wh.signature}, expected #{expected}")
77
- expect(@wh).not_to be_valid
78
- end
79
-
80
- it "should validate with an extra token" do
81
- @client.key = '12345'
82
- @client.secret = 'xxx'
83
- expect(@wh.valid?({:key => '1234', :secret => 'asdf'})).to be_truthy
84
- end
85
-
86
- it "should validate with an array of extra tokens" do
87
- @client.key = '123456'
88
- @client.secret = 'xxx'
89
- expect(@wh.valid?([
90
- {:key => '12345', :secret => 'wtf'},
91
- {:key => '1234', :secret => 'asdf'}
92
- ])).to be_truthy
93
- end
94
-
95
- it "should not validate if all keys are wrong with extra tokens" do
96
- @client.key = '123456'
97
- @client.secret = 'asdf'
98
- expect(Pusher.logger).to receive(:warn).with("Received webhook with unknown key: 1234")
99
- expect(@wh.valid?({:key => '12345', :secret => 'asdf'})).to be_falsey
100
- end
101
-
102
- it "should not validate if secret is wrong with extra tokens" do
103
- @client.key = '123456'
104
- @client.secret = 'asdfxxx'
105
- expect(Pusher.logger).to receive(:warn).with(/Received WebHook with invalid signature/)
106
- expect(@wh.valid?({:key => '1234', :secret => 'wtf'})).to be_falsey
107
- end
108
-
109
- it "should expose events" do
110
- expect(@wh.events).to eq(@hook_data["events"])
111
- end
112
-
113
- it "should expose time" do
114
- expect(@wh.time).to eq(Time.at(123.456))
115
- end
116
- end
117
- end