pusher 1.3.1 → 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,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