pusher 1.3.1 → 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,615 +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
-
62
- it "should raise exception if app_id is not configured" do
63
- @client.app_id = nil
64
- expect {
65
- @client.url
66
- }.to raise_error(Pusher::ConfigurationError)
67
- end
68
-
69
- end
70
-
71
- describe 'configuring the cluster' do
72
- it 'should set a new default host' do
73
- @client.cluster = 'eu'
74
- expect(@client.host).to eq('api-eu.pusher.com')
75
- end
76
-
77
- it 'should be overridden by host if it comes after' do
78
- @client.cluster = 'eu'
79
- @client.host = 'api.staging.pusher.com'
80
- expect(@client.host).to eq('api.staging.pusher.com')
81
- end
82
-
83
- it 'should be overridden by url if it comes after' do
84
- @client.cluster = 'eu'
85
- @client.url = "http://somekey:somesecret@api.staging.pusherapp.com:8080/apps/87"
86
-
87
- expect(@client.host).to eq('api.staging.pusherapp.com')
88
- end
89
-
90
- it 'should get override the url configuration if it comes after' do
91
- @client.url = "http://somekey:somesecret@api.staging.pusherapp.com:8080/apps/87"
92
- @client.cluster = 'eu'
93
- expect(@client.host).to eq('api-eu.pusher.com')
94
- end
95
-
96
- it 'should overrie by the host configuration if it comes after' do
97
- @client.host = 'api.staging.pusher.com'
98
- @client.cluster = 'eu'
99
- expect(@client.host).to eq('api-eu.pusher.com')
100
- end
101
- end
102
-
103
- describe 'configuring a http proxy' do
104
- it "should be possible to configure everything by setting the http_proxy" do
105
- @client.http_proxy = 'http://someuser:somepassword@proxy.host.com:8080'
106
-
107
- expect(@client.proxy).to eq({:scheme => 'http', :host => 'proxy.host.com', :port => 8080, :user => 'someuser', :password => 'somepassword'})
108
- end
109
- end
110
-
111
- describe 'configuring from env' do
112
- it "works" do
113
- url = "http://somekey:somesecret@api.staging.pusherapp.com:8080/apps/87"
114
- ENV['PUSHER_URL'] = url
115
-
116
- client = Pusher::Client.from_env
117
- expect(client.key).to eq("somekey")
118
- expect(client.secret).to eq("somesecret")
119
- expect(client.app_id).to eq("87")
120
- expect(client.url.to_s).to eq("http://api.staging.pusherapp.com:8080/apps/87")
121
- ENV['PUSHER_URL'] = nil
122
- end
123
- end
124
-
125
- describe 'when configured' do
126
- before :each do
127
- @client.app_id = '20'
128
- @client.key = '12345678900000001'
129
- @client.secret = '12345678900000001'
130
- end
131
-
132
- describe '#[]' do
133
- before do
134
- @channel = @client['test_channel']
135
- end
136
-
137
- it 'should return a channel' do
138
- expect(@channel).to be_kind_of(Pusher::Channel)
139
- end
140
-
141
- it "should raise exception if app_id is not configured" do
142
- @client.app_id = nil
143
- expect {
144
- @channel.trigger!('foo', 'bar')
145
- }.to raise_error(Pusher::ConfigurationError)
146
- end
147
- end
148
-
149
- describe '#channels' do
150
- it "should call the correct URL and symbolise response correctly" do
151
- api_path = %r{/apps/20/channels}
152
- stub_request(:get, api_path).to_return({
153
- :status => 200,
154
- :body => MultiJson.encode('channels' => {
155
- "channel1" => {},
156
- "channel2" => {}
157
- })
158
- })
159
- expect(@client.channels).to eq({
160
- :channels => {
161
- "channel1" => {},
162
- "channel2" => {}
163
- }
164
- })
165
- end
166
- end
167
-
168
- describe '#channel_info' do
169
- it "should call correct URL and symbolise response" do
170
- api_path = %r{/apps/20/channels/mychannel}
171
- stub_request(:get, api_path).to_return({
172
- :status => 200,
173
- :body => MultiJson.encode({
174
- 'occupied' => false,
175
- })
176
- })
177
- expect(@client.channel_info('mychannel')).to eq({
178
- :occupied => false,
179
- })
180
- end
181
- end
182
-
183
- describe '#channel_users' do
184
- it "should call correct URL and symbolise response" do
185
- api_path = %r{/apps/20/channels/mychannel/users}
186
- stub_request(:get, api_path).to_return({
187
- :status => 200,
188
- :body => MultiJson.encode({
189
- 'users' => [{ 'id' => 1 }]
190
- })
191
- })
192
- expect(@client.channel_users('mychannel')).to eq({
193
- :users => [{ 'id' => 1}]
194
- })
195
- end
196
- end
197
-
198
- describe '#authenticate' do
199
- before :each do
200
- @custom_data = {:uid => 123, :info => {:name => 'Foo'}}
201
- end
202
-
203
- it 'should return a hash with signature including custom data and data as json string' do
204
- allow(MultiJson).to receive(:encode).with(@custom_data).and_return 'a json string'
205
-
206
- response = @client.authenticate('test_channel', '1.1', @custom_data)
207
-
208
- expect(response).to eq({
209
- :auth => "12345678900000001:#{hmac(@client.secret, "1.1:test_channel:a json string")}",
210
- :channel_data => 'a json string'
211
- })
212
- end
213
-
214
- end
215
-
216
- describe '#trigger' do
217
- before :each do
218
- @api_path = %r{/apps/20/events}
219
- stub_request(:post, @api_path).to_return({
220
- :status => 200,
221
- :body => MultiJson.encode({})
222
- })
223
- end
224
-
225
- it "should call correct URL" do
226
- expect(@client.trigger(['mychannel'], 'event', {'some' => 'data'})).
227
- to eq({})
228
- end
229
-
230
- it "should not allow too many channels" do
231
- expect {
232
- @client.trigger((0..11).map{|i| 'mychannel#{i}'},
233
- 'event', {'some' => 'data'}, {
234
- :socket_id => "12.34"
235
- })}.to raise_error(Pusher::Error)
236
- end
237
-
238
- it "should pass any parameters in the body of the request" do
239
- @client.trigger(['mychannel', 'c2'], 'event', {'some' => 'data'}, {
240
- :socket_id => "12.34"
241
- })
242
- expect(WebMock).to have_requested(:post, @api_path).with { |req|
243
- parsed = MultiJson.decode(req.body)
244
- expect(parsed["name"]).to eq('event')
245
- expect(parsed["channels"]).to eq(["mychannel", "c2"])
246
- expect(parsed["socket_id"]).to eq('12.34')
247
- }
248
- end
249
-
250
- it "should convert non string data to JSON before posting" do
251
- @client.trigger(['mychannel'], 'event', {'some' => 'data'})
252
- expect(WebMock).to have_requested(:post, @api_path).with { |req|
253
- expect(MultiJson.decode(req.body)["data"]).to eq('{"some":"data"}')
254
- }
255
- end
256
-
257
- it "should accept a single channel as well as an array" do
258
- @client.trigger('mychannel', 'event', {'some' => 'data'})
259
- expect(WebMock).to have_requested(:post, @api_path).with { |req|
260
- expect(MultiJson.decode(req.body)["channels"]).to eq(['mychannel'])
261
- }
262
- end
263
-
264
- %w[app_id key secret].each do |key|
265
- it "should fail in missing #{key}" do
266
- @client.public_send("#{key}=", nil)
267
- expect {
268
- @client.trigger('mychannel', 'event', {'some' => 'data'})
269
- }.to raise_error(Pusher::ConfigurationError)
270
- expect(WebMock).not_to have_requested(:post, @api_path).with { |req|
271
- expect(MultiJson.decode(req.body)["channels"]).to eq(['mychannel'])
272
- }
273
- end
274
- end
275
- end
276
-
277
- describe '#trigger_batch' do
278
- before :each do
279
- @api_path = %r{/apps/20/batch_events}
280
- stub_request(:post, @api_path).to_return({
281
- :status => 200,
282
- :body => MultiJson.encode({})
283
- })
284
- end
285
-
286
- it "should call correct URL" do
287
- expect(@client.trigger_batch(channel: 'mychannel', name: 'event', data: {'some' => 'data'})).
288
- to eq({})
289
- end
290
-
291
- it "should convert non string data to JSON before posting" do
292
- @client.trigger_batch(
293
- {channel: 'mychannel', name: 'event', data: {'some' => 'data'}},
294
- {channel: 'mychannel', name: 'event', data: 'already encoded'},
295
- )
296
- expect(WebMock).to have_requested(:post, @api_path).with { |req|
297
- parsed = MultiJson.decode(req.body)
298
- expect(parsed).to eq(
299
- "batch" => [
300
- { "channel" => "mychannel", "name" => "event", "data" => "{\"some\":\"data\"}"},
301
- { "channel" => "mychannel", "name" => "event", "data" => "already encoded"}
302
- ]
303
- )
304
- }
305
- end
306
- end
307
-
308
- describe '#trigger_async' do
309
- before :each do
310
- @api_path = %r{/apps/20/events}
311
- stub_request(:post, @api_path).to_return({
312
- :status => 200,
313
- :body => MultiJson.encode({})
314
- })
315
- end
316
-
317
- it "should call correct URL" do
318
- EM.run {
319
- @client.trigger_async('mychannel', 'event', {'some' => 'data'}).callback { |r|
320
- expect(r).to eq({})
321
- EM.stop
322
- }
323
- }
324
- end
325
-
326
- it "should pass any parameters in the body of the request" do
327
- EM.run {
328
- @client.trigger_async('mychannel', 'event', {'some' => 'data'}, {
329
- :socket_id => "12.34"
330
- }).callback {
331
- expect(WebMock).to have_requested(:post, @api_path).with { |req|
332
- expect(MultiJson.decode(req.body)["socket_id"]).to eq('12.34')
333
- }
334
- EM.stop
335
- }
336
- }
337
- end
338
-
339
- it "should convert non string data to JSON before posting" do
340
- EM.run {
341
- @client.trigger_async('mychannel', 'event', {'some' => 'data'}).callback {
342
- expect(WebMock).to have_requested(:post, @api_path).with { |req|
343
- expect(MultiJson.decode(req.body)["data"]).to eq('{"some":"data"}')
344
- }
345
- EM.stop
346
- }
347
- }
348
- end
349
- end
350
-
351
- [:get, :post].each do |verb|
352
- describe "##{verb}" do
353
- before :each do
354
- @url_regexp = %r{api.pusherapp.com}
355
- stub_request(verb, @url_regexp).
356
- to_return(:status => 200, :body => "{}")
357
- end
358
-
359
- let(:call_api) { @client.send(verb, '/path') }
360
-
361
- it "should use http by default" do
362
- call_api
363
- expect(WebMock).to have_requested(verb, %r{http://api.pusherapp.com/apps/20/path})
364
- end
365
-
366
- it "should use https if configured" do
367
- @client.encrypted = true
368
- call_api
369
- expect(WebMock).to have_requested(verb, %r{https://api.pusherapp.com})
370
- end
371
-
372
- it "should format the respose hash with symbols at first level" do
373
- stub_request(verb, @url_regexp).to_return({
374
- :status => 200,
375
- :body => MultiJson.encode({'something' => {'a' => 'hash'}})
376
- })
377
- expect(call_api).to eq({
378
- :something => {'a' => 'hash'}
379
- })
380
- end
381
-
382
- it "should catch all http exceptions and raise a Pusher::HTTPError wrapping the original error" do
383
- stub_request(verb, @url_regexp).to_raise(HTTPClient::TimeoutError)
384
-
385
- error = nil
386
- begin
387
- call_api
388
- rescue => e
389
- error = e
390
- end
391
-
392
- expect(error.class).to eq(Pusher::HTTPError)
393
- expect(error).to be_kind_of(Pusher::Error)
394
- expect(error.message).to eq('Exception from WebMock (HTTPClient::TimeoutError)')
395
- expect(error.original_error.class).to eq(HTTPClient::TimeoutError)
396
- end
397
-
398
- it "should raise Pusher::Error if call returns 400" do
399
- stub_request(verb, @url_regexp).to_return({:status => 400})
400
- expect { call_api }.to raise_error(Pusher::Error)
401
- end
402
-
403
- it "should raise AuthenticationError if pusher returns 401" do
404
- stub_request(verb, @url_regexp).to_return({:status => 401})
405
- expect { call_api }.to raise_error(Pusher::AuthenticationError)
406
- end
407
-
408
- it "should raise Pusher::Error if pusher returns 404" do
409
- stub_request(verb, @url_regexp).to_return({:status => 404})
410
- expect { call_api }.to raise_error(Pusher::Error, '404 Not found (/apps/20/path)')
411
- end
412
-
413
- it "should raise Pusher::Error if pusher returns 407" do
414
- stub_request(verb, @url_regexp).to_return({:status => 407})
415
- expect { call_api }.to raise_error(Pusher::Error, 'Proxy Authentication Required')
416
- end
417
-
418
- it "should raise Pusher::Error if pusher returns 500" do
419
- stub_request(verb, @url_regexp).to_return({:status => 500, :body => "some error"})
420
- expect { call_api }.to raise_error(Pusher::Error, 'Unknown error (status code 500): some error')
421
- end
422
- end
423
- end
424
-
425
- describe "async calling without eventmachine" do
426
- [[:get, :get_async], [:post, :post_async]].each do |verb, method|
427
- describe "##{method}" do
428
- before :each do
429
- @url_regexp = %r{api.pusherapp.com}
430
- stub_request(verb, @url_regexp).
431
- to_return(:status => 200, :body => "{}")
432
- end
433
-
434
- let(:call_api) {
435
- @client.send(method, '/path').tap { |c|
436
- # Allow the async thread (inside httpclient) to run
437
- while !c.finished?
438
- sleep 0.01
439
- end
440
- }
441
- }
442
-
443
- it "should use http by default" do
444
- call_api
445
- expect(WebMock).to have_requested(verb, %r{http://api.pusherapp.com/apps/20/path})
446
- end
447
-
448
- it "should use https if configured" do
449
- @client.encrypted = true
450
- call_api
451
- expect(WebMock).to have_requested(verb, %r{https://api.pusherapp.com})
452
- end
453
-
454
- # Note that the raw httpclient connection object is returned and
455
- # the response isn't handled (by handle_response) in the normal way.
456
- it "should return a httpclient connection object" do
457
- connection = call_api
458
- expect(connection.finished?).to be_truthy
459
- response = connection.pop
460
- expect(response.status).to eq(200)
461
- expect(response.body.read).to eq("{}")
462
- end
463
- end
464
- end
465
- end
466
-
467
- describe "async calling with eventmachine" do
468
- [[:get, :get_async], [:post, :post_async]].each do |verb, method|
469
- describe "##{method}" do
470
- before :each do
471
- @url_regexp = %r{api.pusherapp.com}
472
- stub_request(verb, @url_regexp).
473
- to_return(:status => 200, :body => "{}")
474
- end
475
-
476
- let(:call_api) { @client.send(method, '/path') }
477
-
478
- it "should use http by default" do
479
- EM.run {
480
- call_api.callback {
481
- expect(WebMock).to have_requested(verb, %r{http://api.pusherapp.com/apps/20/path})
482
- EM.stop
483
- }
484
- }
485
- end
486
-
487
- it "should use https if configured" do
488
- EM.run {
489
- @client.encrypted = true
490
- call_api.callback {
491
- expect(WebMock).to have_requested(verb, %r{https://api.pusherapp.com})
492
- EM.stop
493
- }
494
- }
495
- end
496
-
497
- it "should format the respose hash with symbols at first level" do
498
- EM.run {
499
- stub_request(verb, @url_regexp).to_return({
500
- :status => 200,
501
- :body => MultiJson.encode({'something' => {'a' => 'hash'}})
502
- })
503
- call_api.callback { |response|
504
- expect(response).to eq({
505
- :something => {'a' => 'hash'}
506
- })
507
- EM.stop
508
- }
509
- }
510
- end
511
-
512
- it "should errback with Pusher::Error on unsuccessful response" do
513
- EM.run {
514
- stub_request(verb, @url_regexp).to_return({:status => 400})
515
-
516
- call_api.errback { |e|
517
- expect(e.class).to eq(Pusher::Error)
518
- EM.stop
519
- }.callback {
520
- fail
521
- }
522
- }
523
- end
524
- end
525
- end
526
- end
527
- end
528
-
529
- describe "native notifications" do
530
- before :each do
531
- @client.app_id = "20"
532
- @client.key = "testytest"
533
- @client.secret = "mysupersecretkey"
534
- end
535
-
536
- it "should configure a native notification client using the pusher client object" do
537
- expect(@client.notification_client).to_not be(nil)
538
- end
539
-
540
- it "should use the default host if not provided" do
541
- expect(@client.notification_host).to eq("nativepush-cluster1.pusher.com")
542
- end
543
-
544
- it "should use a newly provided host" do
545
- @client.notification_host = "test.com"
546
- expect(@client.notification_host).to eq("test.com")
547
- end
548
-
549
- it "should set the native notification client host to the same one" do
550
- expect(@client.notification_host).to eq(@client.notification_client.host)
551
- end
552
-
553
- it "should raise an error if no interest is provided" do
554
- payload = {
555
- gcm: {
556
- notification: {
557
- title: "Hello",
558
- icon: "icon",
559
- }
560
- }
561
- }
562
-
563
- expect { @client.notify([], payload) }.to raise_error(Pusher::Error)
564
- end
565
-
566
- it "should send a request to the notifications endpoint" do
567
- notification_host_regexp = %r{nativepush-cluster1.pusher.com}
568
- payload = {
569
- interests: ["test"],
570
- gcm: {
571
- notification: {
572
- title: "Hello",
573
- icon: "icon",
574
- }
575
- }
576
- }
577
-
578
- stub_request(
579
- :post,
580
- notification_host_regexp,
581
- ).with(
582
- body: MultiJson.encode(payload)
583
- ).to_return({
584
- :status => 200,
585
- :body => MultiJson.encode({ :foo => "bar" })
586
- })
587
-
588
- res = @client.notify(["test"], payload)
589
- expect(res).to eq({foo: "bar"})
590
- end
591
- end
592
- end
593
-
594
- describe 'configuring cluster' do
595
- it 'should allow clients to specify the cluster only with the default host' do
596
- client = Pusher::Client.new({
597
- :scheme => 'http',
598
- :cluster => 'eu',
599
- :port => 80
600
- })
601
- expect(client.host).to eq('api-eu.pusher.com')
602
- end
603
-
604
- it 'should always have host override any supplied cluster value' do
605
- client = Pusher::Client.new({
606
- :scheme => 'http',
607
- :host => 'api.staging.pusherapp.com',
608
- :cluster => 'eu',
609
- :port => 80
610
- })
611
- expect(client.host).to eq('api.staging.pusherapp.com')
612
- end
613
- end
614
- end
615
-
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