pusher 1.4.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/spec/channel_spec.rb DELETED
@@ -1,170 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- require 'spec_helper'
3
-
4
- describe Pusher::Channel do
5
- before do
6
- @client = Pusher::Client.new({
7
- :app_id => '20',
8
- :key => '12345678900000001',
9
- :secret => '12345678900000001',
10
- :host => 'api.pusherapp.com',
11
- :port => 80,
12
- })
13
- @channel = @client['test_channel']
14
- end
15
-
16
- let(:pusher_url_regexp) { %r{/apps/20/events} }
17
-
18
- def stub_post(status, body = nil)
19
- options = {:status => status}
20
- options.merge!({:body => body}) if body
21
-
22
- stub_request(:post, pusher_url_regexp).to_return(options)
23
- end
24
-
25
- def stub_post_to_raise(e)
26
- stub_request(:post, pusher_url_regexp).to_raise(e)
27
- end
28
-
29
- describe '#trigger!' do
30
- it "should use @client.trigger internally" do
31
- expect(@client).to receive(:trigger)
32
- @channel.trigger('new_event', 'Some data')
33
- end
34
- end
35
-
36
- describe '#trigger' do
37
- it "should log failure if error raised in http call" do
38
- stub_post_to_raise(HTTPClient::BadResponseError)
39
-
40
- expect(Pusher.logger).to receive(:error).with("Exception from WebMock (HTTPClient::BadResponseError) (Pusher::HTTPError)")
41
- expect(Pusher.logger).to receive(:debug) #backtrace
42
- channel = Pusher::Channel.new(@client.url, 'test_channel', @client)
43
- channel.trigger('new_event', 'Some data')
44
- end
45
-
46
- it "should log failure if Pusher returns an error response" do
47
- stub_post 401, "some signature info"
48
- expect(Pusher.logger).to receive(:error).with("some signature info (Pusher::AuthenticationError)")
49
- expect(Pusher.logger).to receive(:debug) #backtrace
50
- channel = Pusher::Channel.new(@client.url, 'test_channel', @client)
51
- channel.trigger('new_event', 'Some data')
52
- end
53
- end
54
-
55
- describe "#initialization" do
56
- it "should not be too long" do
57
- expect { @client['b'*201] }.to raise_error(Pusher::Error)
58
- end
59
-
60
- it "should not use bad characters" do
61
- expect { @client['*^!±`/""'] }.to raise_error(Pusher::Error)
62
- end
63
- end
64
-
65
- describe "#trigger_async" do
66
- it "should use @client.trigger_async internally" do
67
- expect(@client).to receive(:trigger_async)
68
- @channel.trigger_async('new_event', 'Some data')
69
- end
70
- end
71
-
72
- describe '#info' do
73
- it "should call the Client#channel_info" do
74
- expect(@client).to receive(:get)
75
- .with("/channels/mychannel", anything)
76
- .and_return({:occupied => true, :subscription_count => 12})
77
- @channel = @client['mychannel']
78
- @channel.info
79
- end
80
-
81
- it "should assemble the requested attributes into the info option" do
82
- expect(@client).to receive(:get)
83
- .with(anything, {:info => "user_count,connection_count"})
84
- .and_return({:occupied => true, :subscription_count => 12, :user_count => 12})
85
- @channel = @client['presence-foo']
86
- @channel.info(%w{user_count connection_count})
87
- end
88
- end
89
-
90
- describe '#users' do
91
- it "should call the Client#channel_users" do
92
- expect(@client).to receive(:get).with("/channels/presence-mychannel/users", {}).and_return({:users => {'id' => '4'}})
93
- @channel = @client['presence-mychannel']
94
- @channel.users
95
- end
96
- end
97
-
98
- describe "#authentication_string" do
99
- def authentication_string(*data)
100
- lambda { @channel.authentication_string(*data) }
101
- end
102
-
103
- it "should return an authentication string given a socket id" do
104
- auth = @channel.authentication_string('1.1')
105
-
106
- expect(auth).to eq('12345678900000001:02259dff9a2a3f71ea8ab29ac0c0c0ef7996c8f3fd3702be5533f30da7d7fed4')
107
- end
108
-
109
- it "should raise error if authentication is invalid" do
110
- [nil, ''].each do |invalid|
111
- expect(authentication_string(invalid)).to raise_error Pusher::Error
112
- end
113
- end
114
-
115
- describe 'with extra string argument' do
116
- it 'should be a string or nil' do
117
- expect(authentication_string('1.1', 123)).to raise_error Pusher::Error
118
- expect(authentication_string('1.1', {})).to raise_error Pusher::Error
119
-
120
- expect(authentication_string('1.1', 'boom')).not_to raise_error
121
- expect(authentication_string('1.1', nil)).not_to raise_error
122
- end
123
-
124
- it "should return an authentication string given a socket id and custom args" do
125
- auth = @channel.authentication_string('1.1', 'foobar')
126
-
127
- expect(auth).to eq("12345678900000001:#{hmac(@client.secret, "1.1:test_channel:foobar")}")
128
- end
129
- end
130
- end
131
-
132
- describe '#authenticate' do
133
- before :each do
134
- @custom_data = {:uid => 123, :info => {:name => 'Foo'}}
135
- end
136
-
137
- it 'should return a hash with signature including custom data and data as json string' do
138
- allow(MultiJson).to receive(:encode).with(@custom_data).and_return 'a json string'
139
-
140
- response = @channel.authenticate('1.1', @custom_data)
141
-
142
- expect(response).to eq({
143
- :auth => "12345678900000001:#{hmac(@client.secret, "1.1:test_channel:a json string")}",
144
- :channel_data => 'a json string'
145
- })
146
- end
147
-
148
- it 'should fail on invalid socket_ids' do
149
- expect {
150
- @channel.authenticate('1.1:')
151
- }.to raise_error Pusher::Error
152
-
153
- expect {
154
- @channel.authenticate('1.1foo', 'channel')
155
- }.to raise_error Pusher::Error
156
-
157
- expect {
158
- @channel.authenticate(':1.1')
159
- }.to raise_error Pusher::Error
160
-
161
- expect {
162
- @channel.authenticate('foo1.1', 'channel')
163
- }.to raise_error Pusher::Error
164
-
165
- expect {
166
- @channel.authenticate('foo', 'channel')
167
- }.to raise_error Pusher::Error
168
- end
169
- end
170
- end
data/spec/client_spec.rb DELETED
@@ -1,773 +0,0 @@
1
- require 'base64'
2
-
3
- require 'rbnacl'
4
- require 'em-http'
5
-
6
- require 'spec_helper'
7
-
8
- encryption_master_key = RbNaCl::Random.random_bytes(32)
9
-
10
- describe Pusher do
11
- # The behaviour should be the same when using the Client object, or the
12
- # 'global' client delegated through the Pusher class
13
- [lambda { Pusher }, lambda { Pusher::Client.new }].each do |client_gen|
14
- before :each do
15
- @client = client_gen.call
16
- end
17
-
18
- describe 'default configuration' do
19
- it 'should be preconfigured for api host' do
20
- expect(@client.host).to eq('api.pusherapp.com')
21
- end
22
-
23
- it 'should be preconfigured for port 80' do
24
- expect(@client.port).to eq(80)
25
- end
26
-
27
- it 'should use standard logger if no other logger if defined' do
28
- Pusher.logger.debug('foo')
29
- expect(Pusher.logger).to be_kind_of(Logger)
30
- end
31
- end
32
-
33
- describe 'logging configuration' do
34
- it "can be configured to use any logger" do
35
- logger = double("ALogger")
36
- expect(logger).to receive(:debug).with('foo')
37
- Pusher.logger = logger
38
- Pusher.logger.debug('foo')
39
- Pusher.logger = nil
40
- end
41
- end
42
-
43
- describe "configuration using url" do
44
- it "should be possible to configure everything by setting the url" do
45
- @client.url = "test://somekey:somesecret@api.staging.pusherapp.com:8080/apps/87"
46
-
47
- expect(@client.scheme).to eq('test')
48
- expect(@client.host).to eq('api.staging.pusherapp.com')
49
- expect(@client.port).to eq(8080)
50
- expect(@client.key).to eq('somekey')
51
- expect(@client.secret).to eq('somesecret')
52
- expect(@client.app_id).to eq('87')
53
- end
54
-
55
- it "should override scheme and port when setting encrypted=true after url" do
56
- @client.url = "http://somekey:somesecret@api.staging.pusherapp.com:8080/apps/87"
57
- @client.encrypted = true
58
-
59
- expect(@client.scheme).to eq('https')
60
- expect(@client.port).to eq(443)
61
- end
62
-
63
- it "should fail on bad urls" do
64
- expect { @client.url = "gopher/somekey:somesecret@://api.staging.pusherapp.co://m:8080\apps\87" }.to raise_error(URI::InvalidURIError)
65
- end
66
-
67
- it "should raise exception if app_id is not configured" do
68
- @client.app_id = nil
69
- expect {
70
- @client.url
71
- }.to raise_error(Pusher::ConfigurationError)
72
- end
73
-
74
- end
75
-
76
- describe 'configuring the cluster' do
77
- it 'should set a new default host' do
78
- @client.cluster = 'eu'
79
- expect(@client.host).to eq('api-eu.pusher.com')
80
- end
81
-
82
- it 'should be overridden by host if it comes after' do
83
- @client.cluster = 'eu'
84
- @client.host = 'api.staging.pusher.com'
85
- expect(@client.host).to eq('api.staging.pusher.com')
86
- end
87
-
88
- it 'should be overridden by url if it comes after' do
89
- @client.cluster = 'eu'
90
- @client.url = "http://somekey:somesecret@api.staging.pusherapp.com:8080/apps/87"
91
-
92
- expect(@client.host).to eq('api.staging.pusherapp.com')
93
- end
94
-
95
- it 'should override the url configuration if it comes after' do
96
- @client.url = "http://somekey:somesecret@api.staging.pusherapp.com:8080/apps/87"
97
- @client.cluster = 'eu'
98
- expect(@client.host).to eq('api-eu.pusher.com')
99
- end
100
-
101
- it 'should override the host configuration if it comes after' do
102
- @client.host = 'api.staging.pusher.com'
103
- @client.cluster = 'eu'
104
- expect(@client.host).to eq('api-eu.pusher.com')
105
- end
106
- end
107
-
108
- describe 'configuring TLS' do
109
- it 'should set port and scheme if "use_tls" enabled' do
110
- client = Pusher::Client.new({
111
- :use_tls => true,
112
- })
113
- expect(client.scheme).to eq('https')
114
- expect(client.port).to eq(443)
115
- end
116
-
117
- it 'should set port and scheme if "encrypted" enabled' do
118
- client = Pusher::Client.new({
119
- :encrypted => true,
120
- })
121
- expect(client.scheme).to eq('https')
122
- expect(client.port).to eq(443)
123
- end
124
-
125
- it 'should use non-TLS port and scheme if "encrypted" or "use_tls" are not set' do
126
- client = Pusher::Client.new
127
- expect(client.scheme).to eq('http')
128
- expect(client.port).to eq(80)
129
- end
130
-
131
- it 'should override port if "use_tls" option set but a different port is specified' do
132
- client = Pusher::Client.new({
133
- :use_tls => true,
134
- :port => 8443
135
- })
136
- expect(client.scheme).to eq('https')
137
- expect(client.port).to eq(8443)
138
- end
139
-
140
- end
141
-
142
- describe 'configuring a http proxy' do
143
- it "should be possible to configure everything by setting the http_proxy" do
144
- @client.http_proxy = 'http://someuser:somepassword@proxy.host.com:8080'
145
-
146
- expect(@client.proxy).to eq({:scheme => 'http', :host => 'proxy.host.com', :port => 8080, :user => 'someuser', :password => 'somepassword'})
147
- end
148
- end
149
-
150
- describe 'configuring from env' do
151
- after do
152
- ENV['PUSHER_URL'] = nil
153
- end
154
-
155
- it "works" do
156
- url = "http://somekey:somesecret@api.staging.pusherapp.com:8080/apps/87"
157
- ENV['PUSHER_URL'] = url
158
-
159
- client = Pusher::Client.from_env
160
- expect(client.key).to eq("somekey")
161
- expect(client.secret).to eq("somesecret")
162
- expect(client.app_id).to eq("87")
163
- expect(client.url.to_s).to eq("http://api.staging.pusherapp.com:8080/apps/87")
164
- end
165
- end
166
-
167
- describe 'configuring from url' do
168
- it "works" do
169
- url = "http://somekey:somesecret@api.staging.pusherapp.com:8080/apps/87"
170
-
171
- client = Pusher::Client.from_url(url)
172
- expect(client.key).to eq("somekey")
173
- expect(client.secret).to eq("somesecret")
174
- expect(client.app_id).to eq("87")
175
- expect(client.url.to_s).to eq("http://api.staging.pusherapp.com:8080/apps/87")
176
- end
177
- end
178
-
179
- describe 'can set encryption_master_key_base64' do
180
- it "sets encryption_master_key" do
181
- @client.encryption_master_key_base64 =
182
- Base64.encode64(encryption_master_key)
183
-
184
- expect(@client.encryption_master_key).to eq(encryption_master_key)
185
- end
186
- end
187
-
188
- describe 'when configured' do
189
- before :each do
190
- @client.app_id = '20'
191
- @client.key = '12345678900000001'
192
- @client.secret = '12345678900000001'
193
- @client.encryption_master_key_base64 =
194
- Base64.encode64(encryption_master_key)
195
- end
196
-
197
- describe '#[]' do
198
- before do
199
- @channel = @client['test_channel']
200
- end
201
-
202
- it 'should return a channel' do
203
- expect(@channel).to be_kind_of(Pusher::Channel)
204
- end
205
-
206
- it "should raise exception if app_id is not configured" do
207
- @client.app_id = nil
208
- expect {
209
- @channel.trigger!('foo', 'bar')
210
- }.to raise_error(Pusher::ConfigurationError)
211
- end
212
- end
213
-
214
- describe '#channels' do
215
- it "should call the correct URL and symbolise response correctly" do
216
- api_path = %r{/apps/20/channels}
217
- stub_request(:get, api_path).to_return({
218
- :status => 200,
219
- :body => MultiJson.encode('channels' => {
220
- "channel1" => {},
221
- "channel2" => {}
222
- })
223
- })
224
- expect(@client.channels).to eq({
225
- :channels => {
226
- "channel1" => {},
227
- "channel2" => {}
228
- }
229
- })
230
- end
231
- end
232
-
233
- describe '#channel_info' do
234
- it "should call correct URL and symbolise response" do
235
- api_path = %r{/apps/20/channels/mychannel}
236
- stub_request(:get, api_path).to_return({
237
- :status => 200,
238
- :body => MultiJson.encode({
239
- 'occupied' => false,
240
- })
241
- })
242
- expect(@client.channel_info('mychannel')).to eq({
243
- :occupied => false,
244
- })
245
- end
246
- end
247
-
248
- describe '#channel_users' do
249
- it "should call correct URL and symbolise response" do
250
- api_path = %r{/apps/20/channels/mychannel/users}
251
- stub_request(:get, api_path).to_return({
252
- :status => 200,
253
- :body => MultiJson.encode({
254
- 'users' => [{ 'id' => 1 }]
255
- })
256
- })
257
- expect(@client.channel_users('mychannel')).to eq({
258
- :users => [{ 'id' => 1}]
259
- })
260
- end
261
- end
262
-
263
- describe '#authenticate' do
264
- before :each do
265
- @custom_data = {:uid => 123, :info => {:name => 'Foo'}}
266
- end
267
-
268
- it 'should return a hash with signature including custom data and data as json string' do
269
- allow(MultiJson).to receive(:encode).with(@custom_data).and_return 'a json string'
270
-
271
- response = @client.authenticate('test_channel', '1.1', @custom_data)
272
-
273
- expect(response).to eq({
274
- :auth => "12345678900000001:#{hmac(@client.secret, "1.1:test_channel:a json string")}",
275
- :channel_data => 'a json string'
276
- })
277
- end
278
-
279
- end
280
-
281
- describe '#trigger' do
282
- before :each do
283
- @api_path = %r{/apps/20/events}
284
- stub_request(:post, @api_path).to_return({
285
- :status => 200,
286
- :body => MultiJson.encode({})
287
- })
288
- end
289
-
290
- it "should call correct URL" do
291
- expect(@client.trigger(['mychannel'], 'event', {'some' => 'data'})).
292
- to eq({})
293
- end
294
-
295
- it "should not allow too many channels" do
296
- expect {
297
- @client.trigger((0..11).map{|i| 'mychannel#{i}'},
298
- 'event', {'some' => 'data'}, {
299
- :socket_id => "12.34"
300
- })}.to raise_error(Pusher::Error)
301
- end
302
-
303
- it "should pass any parameters in the body of the request" do
304
- @client.trigger(['mychannel', 'c2'], 'event', {'some' => 'data'}, {
305
- :socket_id => "12.34"
306
- })
307
- expect(WebMock).to have_requested(:post, @api_path).with { |req|
308
- parsed = MultiJson.decode(req.body)
309
- expect(parsed["name"]).to eq('event')
310
- expect(parsed["channels"]).to eq(["mychannel", "c2"])
311
- expect(parsed["socket_id"]).to eq('12.34')
312
- }
313
- end
314
-
315
- it "should convert non string data to JSON before posting" do
316
- @client.trigger(['mychannel'], 'event', {'some' => 'data'})
317
- expect(WebMock).to have_requested(:post, @api_path).with { |req|
318
- expect(MultiJson.decode(req.body)["data"]).to eq('{"some":"data"}')
319
- }
320
- end
321
-
322
- it "should accept a single channel as well as an array" do
323
- @client.trigger('mychannel', 'event', {'some' => 'data'})
324
- expect(WebMock).to have_requested(:post, @api_path).with { |req|
325
- expect(MultiJson.decode(req.body)["channels"]).to eq(['mychannel'])
326
- }
327
- end
328
-
329
- %w[app_id key secret].each do |key|
330
- it "should fail in missing #{key}" do
331
- @client.public_send("#{key}=", nil)
332
- expect {
333
- @client.trigger('mychannel', 'event', {'some' => 'data'})
334
- }.to raise_error(Pusher::ConfigurationError)
335
- expect(WebMock).not_to have_requested(:post, @api_path).with { |req|
336
- expect(MultiJson.decode(req.body)["channels"]).to eq(['mychannel'])
337
- }
338
- end
339
- end
340
-
341
- it "should fail to publish to encrypted channels when missing key" do
342
- @client.encryption_master_key_base64 = nil
343
- expect {
344
- @client.trigger('private-encrypted-channel', 'event', {'some' => 'data'})
345
- }.to raise_error(Pusher::ConfigurationError)
346
- expect(WebMock).not_to have_requested(:post, @api_path)
347
- end
348
-
349
- it "should fail to publish to multiple channels if one is encrypted" do
350
- expect {
351
- @client.trigger(
352
- ['private-encrypted-channel', 'some-other-channel'],
353
- 'event',
354
- {'some' => 'data'},
355
- )
356
- }.to raise_error(Pusher::Error)
357
- expect(WebMock).not_to have_requested(:post, @api_path)
358
- end
359
-
360
- it "should encrypt publishes to encrypted channels" do
361
- @client.trigger(
362
- 'private-encrypted-channel',
363
- 'event',
364
- {'some' => 'data'},
365
- )
366
-
367
- expect(WebMock).to have_requested(:post, @api_path).with { |req|
368
- data = MultiJson.decode(MultiJson.decode(req.body)["data"])
369
-
370
- key = RbNaCl::Hash.sha256(
371
- 'private-encrypted-channel' + encryption_master_key
372
- )
373
-
374
- expect(MultiJson.decode(RbNaCl::SecretBox.new(key).decrypt(
375
- Base64.decode64(data["nonce"]),
376
- Base64.decode64(data["ciphertext"]),
377
- ))).to eq({ 'some' => 'data' })
378
- }
379
- end
380
- end
381
-
382
- describe '#trigger_batch' do
383
- before :each do
384
- @api_path = %r{/apps/20/batch_events}
385
- stub_request(:post, @api_path).to_return({
386
- :status => 200,
387
- :body => MultiJson.encode({})
388
- })
389
- end
390
-
391
- it "should call correct URL" do
392
- expect(@client.trigger_batch(channel: 'mychannel', name: 'event', data: {'some' => 'data'})).
393
- to eq({})
394
- end
395
-
396
- it "should convert non string data to JSON before posting" do
397
- @client.trigger_batch(
398
- {channel: 'mychannel', name: 'event', data: {'some' => 'data'}},
399
- {channel: 'mychannel', name: 'event', data: 'already encoded'},
400
- )
401
- expect(WebMock).to have_requested(:post, @api_path).with { |req|
402
- parsed = MultiJson.decode(req.body)
403
- expect(parsed).to eq(
404
- "batch" => [
405
- { "channel" => "mychannel", "name" => "event", "data" => "{\"some\":\"data\"}"},
406
- { "channel" => "mychannel", "name" => "event", "data" => "already encoded"}
407
- ]
408
- )
409
- }
410
- end
411
-
412
- it "should fail to publish to encrypted channels when missing key" do
413
- @client.encryption_master_key_base64 = nil
414
- expect {
415
- @client.trigger_batch(
416
- {
417
- channel: 'private-encrypted-channel',
418
- name: 'event',
419
- data: {'some' => 'data'},
420
- },
421
- {channel: 'mychannel', name: 'event', data: 'already encoded'},
422
- )
423
- }.to raise_error(Pusher::ConfigurationError)
424
- expect(WebMock).not_to have_requested(:post, @api_path)
425
- end
426
-
427
- it "should encrypt publishes to encrypted channels" do
428
- @client.trigger_batch(
429
- {
430
- channel: 'private-encrypted-channel',
431
- name: 'event',
432
- data: {'some' => 'data'},
433
- },
434
- {channel: 'mychannel', name: 'event', data: 'already encoded'},
435
- )
436
-
437
- expect(WebMock).to have_requested(:post, @api_path).with { |req|
438
- batch = MultiJson.decode(req.body)["batch"]
439
- expect(batch.length).to eq(2)
440
-
441
- expect(batch[0]["channel"]).to eq("private-encrypted-channel")
442
- expect(batch[0]["name"]).to eq("event")
443
-
444
- data = MultiJson.decode(batch[0]["data"])
445
-
446
- key = RbNaCl::Hash.sha256(
447
- 'private-encrypted-channel' + encryption_master_key
448
- )
449
-
450
- expect(MultiJson.decode(RbNaCl::SecretBox.new(key).decrypt(
451
- Base64.decode64(data["nonce"]),
452
- Base64.decode64(data["ciphertext"]),
453
- ))).to eq({ 'some' => 'data' })
454
-
455
- expect(batch[1]["channel"]).to eq("mychannel")
456
- expect(batch[1]["name"]).to eq("event")
457
- expect(batch[1]["data"]).to eq("already encoded")
458
- }
459
- end
460
- end
461
-
462
- describe '#trigger_async' do
463
- before :each do
464
- @api_path = %r{/apps/20/events}
465
- stub_request(:post, @api_path).to_return({
466
- :status => 200,
467
- :body => MultiJson.encode({})
468
- })
469
- end
470
-
471
- it "should call correct URL" do
472
- EM.run {
473
- @client.trigger_async('mychannel', 'event', {'some' => 'data'}).callback { |r|
474
- expect(r).to eq({})
475
- EM.stop
476
- }
477
- }
478
- end
479
-
480
- it "should pass any parameters in the body of the request" do
481
- EM.run {
482
- @client.trigger_async('mychannel', 'event', {'some' => 'data'}, {
483
- :socket_id => "12.34"
484
- }).callback {
485
- expect(WebMock).to have_requested(:post, @api_path).with { |req|
486
- expect(MultiJson.decode(req.body)["socket_id"]).to eq('12.34')
487
- }
488
- EM.stop
489
- }
490
- }
491
- end
492
-
493
- it "should convert non string data to JSON before posting" do
494
- EM.run {
495
- @client.trigger_async('mychannel', 'event', {'some' => 'data'}).callback {
496
- expect(WebMock).to have_requested(:post, @api_path).with { |req|
497
- expect(MultiJson.decode(req.body)["data"]).to eq('{"some":"data"}')
498
- }
499
- EM.stop
500
- }
501
- }
502
- end
503
- end
504
-
505
- [:get, :post].each do |verb|
506
- describe "##{verb}" do
507
- before :each do
508
- @url_regexp = %r{api.pusherapp.com}
509
- stub_request(verb, @url_regexp).
510
- to_return(:status => 200, :body => "{}")
511
- end
512
-
513
- let(:call_api) { @client.send(verb, '/path') }
514
-
515
- it "should use http by default" do
516
- call_api
517
- expect(WebMock).to have_requested(verb, %r{http://api.pusherapp.com/apps/20/path})
518
- end
519
-
520
- it "should use https if configured" do
521
- @client.encrypted = true
522
- call_api
523
- expect(WebMock).to have_requested(verb, %r{https://api.pusherapp.com})
524
- end
525
-
526
- it "should format the respose hash with symbols at first level" do
527
- stub_request(verb, @url_regexp).to_return({
528
- :status => 200,
529
- :body => MultiJson.encode({'something' => {'a' => 'hash'}})
530
- })
531
- expect(call_api).to eq({
532
- :something => {'a' => 'hash'}
533
- })
534
- end
535
-
536
- it "should catch all http exceptions and raise a Pusher::HTTPError wrapping the original error" do
537
- stub_request(verb, @url_regexp).to_raise(HTTPClient::TimeoutError)
538
-
539
- error = nil
540
- begin
541
- call_api
542
- rescue => e
543
- error = e
544
- end
545
-
546
- expect(error.class).to eq(Pusher::HTTPError)
547
- expect(error).to be_kind_of(Pusher::Error)
548
- expect(error.message).to eq('Exception from WebMock (HTTPClient::TimeoutError)')
549
- expect(error.original_error.class).to eq(HTTPClient::TimeoutError)
550
- end
551
-
552
- it "should raise Pusher::Error if call returns 400" do
553
- stub_request(verb, @url_regexp).to_return({:status => 400})
554
- expect { call_api }.to raise_error(Pusher::Error)
555
- end
556
-
557
- it "should raise AuthenticationError if pusher returns 401" do
558
- stub_request(verb, @url_regexp).to_return({:status => 401})
559
- expect { call_api }.to raise_error(Pusher::AuthenticationError)
560
- end
561
-
562
- it "should raise Pusher::Error if pusher returns 404" do
563
- stub_request(verb, @url_regexp).to_return({:status => 404})
564
- expect { call_api }.to raise_error(Pusher::Error, '404 Not found (/apps/20/path)')
565
- end
566
-
567
- it "should raise Pusher::Error if pusher returns 407" do
568
- stub_request(verb, @url_regexp).to_return({:status => 407})
569
- expect { call_api }.to raise_error(Pusher::Error, 'Proxy Authentication Required')
570
- end
571
-
572
- it "should raise Pusher::Error if pusher returns 413" do
573
- stub_request(verb, @url_regexp).to_return({:status => 413})
574
- expect { call_api }.to raise_error(Pusher::Error, 'Payload Too Large > 10KB')
575
- end
576
-
577
- it "should raise Pusher::Error if pusher returns 500" do
578
- stub_request(verb, @url_regexp).to_return({:status => 500, :body => "some error"})
579
- expect { call_api }.to raise_error(Pusher::Error, 'Unknown error (status code 500): some error')
580
- end
581
- end
582
- end
583
-
584
- describe "async calling without eventmachine" do
585
- [[:get, :get_async], [:post, :post_async]].each do |verb, method|
586
- describe "##{method}" do
587
- before :each do
588
- @url_regexp = %r{api.pusherapp.com}
589
- stub_request(verb, @url_regexp).
590
- to_return(:status => 200, :body => "{}")
591
- end
592
-
593
- let(:call_api) {
594
- @client.send(method, '/path').tap { |c|
595
- # Allow the async thread (inside httpclient) to run
596
- while !c.finished?
597
- sleep 0.01
598
- end
599
- }
600
- }
601
-
602
- it "should use http by default" do
603
- call_api
604
- expect(WebMock).to have_requested(verb, %r{http://api.pusherapp.com/apps/20/path})
605
- end
606
-
607
- it "should use https if configured" do
608
- @client.encrypted = true
609
- call_api
610
- expect(WebMock).to have_requested(verb, %r{https://api.pusherapp.com})
611
- end
612
-
613
- # Note that the raw httpclient connection object is returned and
614
- # the response isn't handled (by handle_response) in the normal way.
615
- it "should return a httpclient connection object" do
616
- connection = call_api
617
- expect(connection.finished?).to be_truthy
618
- response = connection.pop
619
- expect(response.status).to eq(200)
620
- expect(response.body.read).to eq("{}")
621
- end
622
- end
623
- end
624
- end
625
-
626
- describe "async calling with eventmachine" do
627
- [[:get, :get_async], [:post, :post_async]].each do |verb, method|
628
- describe "##{method}" do
629
- before :each do
630
- @url_regexp = %r{api.pusherapp.com}
631
- stub_request(verb, @url_regexp).
632
- to_return(:status => 200, :body => "{}")
633
- end
634
-
635
- let(:call_api) { @client.send(method, '/path') }
636
-
637
- it "should use http by default" do
638
- EM.run {
639
- call_api.callback {
640
- expect(WebMock).to have_requested(verb, %r{http://api.pusherapp.com/apps/20/path})
641
- EM.stop
642
- }
643
- }
644
- end
645
-
646
- it "should use https if configured" do
647
- EM.run {
648
- @client.encrypted = true
649
- call_api.callback {
650
- expect(WebMock).to have_requested(verb, %r{https://api.pusherapp.com})
651
- EM.stop
652
- }
653
- }
654
- end
655
-
656
- it "should format the respose hash with symbols at first level" do
657
- EM.run {
658
- stub_request(verb, @url_regexp).to_return({
659
- :status => 200,
660
- :body => MultiJson.encode({'something' => {'a' => 'hash'}})
661
- })
662
- call_api.callback { |response|
663
- expect(response).to eq({
664
- :something => {'a' => 'hash'}
665
- })
666
- EM.stop
667
- }
668
- }
669
- end
670
-
671
- it "should errback with Pusher::Error on unsuccessful response" do
672
- EM.run {
673
- stub_request(verb, @url_regexp).to_return({:status => 400})
674
-
675
- call_api.errback { |e|
676
- expect(e.class).to eq(Pusher::Error)
677
- EM.stop
678
- }.callback {
679
- fail
680
- }
681
- }
682
- end
683
- end
684
- end
685
- end
686
- end
687
-
688
- describe "native notifications" do
689
- before :each do
690
- @client.app_id = "20"
691
- @client.key = "testytest"
692
- @client.secret = "mysupersecretkey"
693
- end
694
-
695
- it "should configure a native notification client using the pusher client object" do
696
- expect(@client.notification_client).to_not be(nil)
697
- end
698
-
699
- it "should use the default host if not provided" do
700
- expect(@client.notification_host).to eq("nativepush-cluster1.pusher.com")
701
- end
702
-
703
- it "should use a newly provided host" do
704
- @client.notification_host = "test.com"
705
- expect(@client.notification_host).to eq("test.com")
706
- end
707
-
708
- it "should set the native notification client host to the same one" do
709
- expect(@client.notification_host).to eq(@client.notification_client.host)
710
- end
711
-
712
- it "should raise an error if no interest is provided" do
713
- payload = {
714
- gcm: {
715
- notification: {
716
- title: "Hello",
717
- icon: "icon",
718
- }
719
- }
720
- }
721
-
722
- expect { @client.notify([], payload) }.to raise_error(Pusher::Error)
723
- end
724
-
725
- it "should send a request to the notifications endpoint" do
726
- notification_host_regexp = %r{nativepush-cluster1.pusher.com}
727
- payload = {
728
- interests: ["test"],
729
- gcm: {
730
- notification: {
731
- title: "Hello",
732
- icon: "icon",
733
- }
734
- }
735
- }
736
-
737
- stub_request(
738
- :post,
739
- notification_host_regexp,
740
- ).with(
741
- body: MultiJson.encode(payload)
742
- ).to_return({
743
- :status => 200,
744
- :body => MultiJson.encode({ :foo => "bar" })
745
- })
746
-
747
- res = @client.notify(["test"], payload)
748
- expect(res).to eq({foo: "bar"})
749
- end
750
- end
751
- end
752
-
753
- describe 'configuring cluster' do
754
- it 'should allow clients to specify the cluster only with the default host' do
755
- client = Pusher::Client.new({
756
- :scheme => 'http',
757
- :cluster => 'eu',
758
- :port => 80
759
- })
760
- expect(client.host).to eq('api-eu.pusher.com')
761
- end
762
-
763
- it 'should always have host override any supplied cluster value' do
764
- client = Pusher::Client.new({
765
- :scheme => 'http',
766
- :host => 'api.staging.pusherapp.com',
767
- :cluster => 'eu',
768
- :port => 80
769
- })
770
- expect(client.host).to eq('api.staging.pusherapp.com')
771
- end
772
- end
773
- end