pusher 1.3.2 → 2.0.3

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