pling 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/Gemfile +4 -1
- data/Guardfile +4 -0
- data/README.md +82 -21
- data/Rakefile +6 -1
- data/lib/pling.rb +86 -1
- data/lib/pling/adapter.rb +5 -0
- data/lib/pling/adapter/base.rb +17 -0
- data/lib/pling/configurable.rb +29 -0
- data/lib/pling/delayed_initializer.rb +13 -0
- data/lib/pling/device.rb +68 -0
- data/lib/pling/gateway.rb +17 -0
- data/lib/pling/gateway/apn.rb +85 -0
- data/lib/pling/gateway/base.rb +64 -0
- data/lib/pling/gateway/c2dm.rb +102 -0
- data/lib/pling/message.rb +56 -0
- data/lib/pling/middleware.rb +5 -0
- data/lib/pling/middleware/base.rb +15 -0
- data/lib/pling/version.rb +1 -1
- data/pling.gemspec +4 -4
- data/spec/pling/adapter/base_spec.rb +22 -0
- data/spec/pling/delayed_initializer_spec.rb +31 -0
- data/spec/pling/device_spec.rb +75 -0
- data/spec/pling/gateway/apn_spec.rb +103 -0
- data/spec/pling/gateway/base_spec.rb +61 -0
- data/spec/pling/gateway/c2dm_spec.rb +182 -0
- data/spec/pling/gateway_spec.rb +50 -0
- data/spec/pling/message_spec.rb +44 -0
- data/spec/pling_spec.rb +117 -0
- metadata +64 -11
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Pling::Gateway::APN do
|
4
|
+
|
5
|
+
let(:valid_configuration) { { :certificate => '/path/to/certificate.pem' } }
|
6
|
+
|
7
|
+
let(:message) { Pling::Message.new('Hello from Pling') }
|
8
|
+
let(:device) { Pling::Device.new(:identifier => 'DEVICEIDENTIFIER', :type => :iphone) }
|
9
|
+
|
10
|
+
let(:ssl_context) { double(OpenSSL::SSL::SSLContext).as_null_object }
|
11
|
+
let(:x509_certificate) { double(OpenSSL::X509::Certificate).as_null_object }
|
12
|
+
let(:pkey_rsa) { double(OpenSSL::PKey::RSA).as_null_object }
|
13
|
+
let(:tcp_socket) { double(TCPSocket).as_null_object }
|
14
|
+
let(:ssl_socket) { double(OpenSSL::SSL::SSLSocket).as_null_object }
|
15
|
+
|
16
|
+
before do
|
17
|
+
File.stub(:read).with('/path/to/certificate.pem').and_return('--- CERT CONTENT ---')
|
18
|
+
OpenSSL::SSL::SSLContext.stub(:new).and_return(ssl_context)
|
19
|
+
OpenSSL::X509::Certificate.stub(:new).and_return(x509_certificate)
|
20
|
+
OpenSSL::PKey::RSA.stub(:new).and_return(pkey_rsa)
|
21
|
+
TCPSocket.stub(:new).and_return(tcp_socket)
|
22
|
+
OpenSSL::SSL::SSLSocket.stub(:new).and_return(ssl_socket)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should handle various apn related device types' do
|
26
|
+
Pling::Gateway::APN.handled_types.should =~ [:apple, :apn, :ios, :ipad, :iphone, :ipod]
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'when created with an invalid configuration' do
|
30
|
+
it "should raise an error when :certificate is missing" do
|
31
|
+
expect { Pling::Gateway::APN.new({}) }.to raise_error(ArgumentError, /:certificate is missing/)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'when created with a valid configuration' do
|
36
|
+
it 'should allow configuration of the :certificate' do
|
37
|
+
File.should_receive(:read).with('/some/path').and_return('--- SOME CERT CONTENT ---')
|
38
|
+
gateway = Pling::Gateway::APN.new(valid_configuration.merge(:certificate => '/some/path'))
|
39
|
+
gateway.deliver(message, device)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should allow configuration of the :host' do
|
43
|
+
TCPSocket.should_receive(:new).with('some-host', anything).and_return(tcp_socket)
|
44
|
+
gateway = Pling::Gateway::APN.new(valid_configuration.merge(:host => 'some-host'))
|
45
|
+
gateway.deliver(message, device)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should allow configuration of the :port' do
|
49
|
+
TCPSocket.should_receive(:new).with(anything, 1234).and_return(tcp_socket)
|
50
|
+
gateway = Pling::Gateway::APN.new(valid_configuration.merge(:port => 1234))
|
51
|
+
gateway.deliver(message, device)
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should establish a connection' do
|
55
|
+
ssl_socket.should_receive(:connect)
|
56
|
+
Pling::Gateway::APN.new(valid_configuration)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe '#deliver' do
|
61
|
+
subject { Pling::Gateway::APN.new(valid_configuration) }
|
62
|
+
|
63
|
+
it 'should raise an error if no message is given' do
|
64
|
+
expect { subject.deliver(nil, device) }.to raise_error
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should raise an error the device is given' do
|
68
|
+
expect { subject.deliver(message, nil) }.to raise_error
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should call #to_pling_message on the given message' do
|
72
|
+
message.should_receive(:to_pling_message).and_return(message)
|
73
|
+
subject.deliver(message, device)
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should call #to_pling_device on the given device' do
|
77
|
+
device.should_receive(:to_pling_device).and_return(device)
|
78
|
+
subject.deliver(message, device)
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'should raise an exception when the payload exceeds 256 bytes' do
|
82
|
+
message.body = "X" * 256
|
83
|
+
expect { subject.deliver(message, device) }.to raise_error(Pling::DeliveryFailed, /Payload size of \d+ exceeds allowed size of 256 bytes/)
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should try to deliver the given message' do
|
87
|
+
expected_header = "\x00\x00 \xDE\xF2\xCE-\xE7\xD2\xF2\xEB\x00"
|
88
|
+
expected_payload = {
|
89
|
+
'aps' => {
|
90
|
+
'alert' => 'Hello from Pling'
|
91
|
+
}
|
92
|
+
}
|
93
|
+
|
94
|
+
ssl_socket.stub(:write) do |packet|
|
95
|
+
header, payload = packet.split('$')
|
96
|
+
header.should eq(expected_header)
|
97
|
+
JSON.parse(payload).should eq(expected_payload)
|
98
|
+
end
|
99
|
+
|
100
|
+
subject.deliver(message, device)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Pling::Gateway::Base do
|
4
|
+
|
5
|
+
let(:gateway_class) do
|
6
|
+
Class.new(Pling::Gateway::Base).tap do |klass|
|
7
|
+
klass.handles :android, :c2dm
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:gateway) { gateway_class.new }
|
12
|
+
let(:message) { Pling::Message.new }
|
13
|
+
let(:device) { Pling::Device.new }
|
14
|
+
|
15
|
+
describe '#handles?' do
|
16
|
+
it 'should return true if the gateway supports the given device\'s type' do
|
17
|
+
device.type = :android
|
18
|
+
gateway.handles?(device).should be_true
|
19
|
+
|
20
|
+
device.type = :c2dm
|
21
|
+
gateway.handles?(device).should be_true
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should return false if the gateway does not support the given device\'s type' do
|
25
|
+
device.type = :random
|
26
|
+
gateway.handles?(device).should be_false
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#deliver' do
|
31
|
+
|
32
|
+
it 'should call each middleware in the given order' do
|
33
|
+
first_middleware = double(Pling::Middleware::Base)
|
34
|
+
first_middleware.should_receive(:deliver).
|
35
|
+
with(message, device).and_yield(message, device)
|
36
|
+
|
37
|
+
second_middleware = double(Pling::Middleware::Base)
|
38
|
+
second_middleware.should_receive(:deliver).
|
39
|
+
with(message, device)
|
40
|
+
|
41
|
+
gateway = gateway_class.new(:middlewares => [first_middleware, second_middleware])
|
42
|
+
gateway.stub(:deliver!)
|
43
|
+
|
44
|
+
gateway.deliver(message, device)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should raise an error if #deliver! is not overwritten' do
|
48
|
+
expect { gateway.deliver(message, device) }.to raise_error(/Please implement/)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should not modify the middleware configuration' do
|
52
|
+
middlewares = [Pling::Middleware::Base.new, Pling::Middleware::Base.new]
|
53
|
+
|
54
|
+
gateway = gateway_class.new(:middlewares => middlewares)
|
55
|
+
gateway.stub(:deliver!)
|
56
|
+
|
57
|
+
expect { gateway.deliver(message, device) }.to_not change(middlewares, :count)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Pling::Gateway::C2DM do
|
4
|
+
|
5
|
+
let(:valid_configuration) do
|
6
|
+
{ :email => 'someone@gmail.com', :password => 'random', :source => 'some-source' }
|
7
|
+
end
|
8
|
+
|
9
|
+
let(:authentication_response_mock) do
|
10
|
+
mock('Faraday authentication response', :success? => true, :status => 200, :body => "SID=SOMESID\nAuth=S0ME-ToKeN123")
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:push_response_mock) do
|
14
|
+
mock('Faraday send response', :success? => true, :status => 200, :body => "")
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:connection_mock) do
|
18
|
+
mock('Faraday connection').tap do |mock|
|
19
|
+
mock.stub(:post).
|
20
|
+
with('https://www.google.com/accounts/ClientLogin', anything).
|
21
|
+
and_return(authentication_response_mock)
|
22
|
+
|
23
|
+
mock.stub(:post).
|
24
|
+
with('https://android.apis.google.com/c2dm/send', anything, anything).
|
25
|
+
and_return(push_response_mock)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
before { Faraday.stub(:new).and_return(connection_mock) }
|
30
|
+
|
31
|
+
context 'when created with an invalid configuration' do
|
32
|
+
[:email, :password, :source].each do |attribute|
|
33
|
+
it "should raise an error when :#{attribute} is missing" do
|
34
|
+
configuration = valid_configuration
|
35
|
+
configuration.delete(attribute)
|
36
|
+
expect { Pling::Gateway::C2DM.new(configuration) }.to raise_error(ArgumentError, /:#{attribute} is missing/)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'when created with valid configuration' do
|
42
|
+
|
43
|
+
context 'authenticating' do
|
44
|
+
let(:valid_authentication_params) do
|
45
|
+
{
|
46
|
+
:accountType => 'HOSTED_OR_GOOGLE',
|
47
|
+
:service => 'ac2dm',
|
48
|
+
:Email => valid_configuration[:email],
|
49
|
+
:Passwd => valid_configuration[:password],
|
50
|
+
:source => valid_configuration[:source]
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should not raise an error' do
|
55
|
+
expect { Pling::Gateway::C2DM.new(valid_configuration) }.to_not raise_error
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should try to authenticate' do
|
59
|
+
connection_mock.should_receive(:post).
|
60
|
+
with('https://www.google.com/accounts/ClientLogin', valid_authentication_params).
|
61
|
+
and_return(authentication_response_mock)
|
62
|
+
|
63
|
+
Pling::Gateway::C2DM.new(valid_configuration)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should extract the token from the response body' do
|
67
|
+
gateway = Pling::Gateway::C2DM.new(valid_configuration)
|
68
|
+
gateway.token.should eq('S0ME-ToKeN123')
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should raise an error if authentication was not successful' do
|
72
|
+
authentication_response_mock.stub(:status => 403, :success? => false, :body => 'Error=BadAuthentication')
|
73
|
+
|
74
|
+
expect { Pling::Gateway::C2DM.new(valid_configuration) }.to raise_error(Pling::AuthenticationFailed, /Authentication failed: \[403\] Error=BadAuthentication/)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should raise an error if it could not extract a token from the response' do
|
78
|
+
authentication_response_mock.stub(:body).and_return('SOMERANDOMBODY')
|
79
|
+
|
80
|
+
expect { Pling::Gateway::C2DM.new(valid_configuration) }.to raise_error(Pling::AuthenticationFailed, /Token extraction failed/)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'configuration' do
|
85
|
+
it 'should allow configuring Faraday\'s :connection settings' do
|
86
|
+
Faraday.should_receive(:new).with(:ssl => { :verify => false })
|
87
|
+
Pling::Gateway::C2DM.new(valid_configuration.merge(:connection => { :ssl => { :verify => false }}))
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should use Faraday::Response::Logger when :debug is set to true' do
|
91
|
+
builder = mock(:use => true, :adapter => true)
|
92
|
+
builder.should_receive(:use).with(Faraday::Response::Logger)
|
93
|
+
Faraday.stub(:new).and_yield(builder).and_return(connection_mock)
|
94
|
+
|
95
|
+
Pling::Gateway::C2DM.new(valid_configuration.merge(:debug => true))
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'should use the adapter set with :adapter' do
|
99
|
+
builder = mock(:use => true, :adapter => true)
|
100
|
+
builder.should_receive(:adapter).with(:typheus)
|
101
|
+
Faraday.stub(:new).and_yield(builder).and_return(connection_mock)
|
102
|
+
|
103
|
+
Pling::Gateway::C2DM.new(valid_configuration.merge(:adapter => :typheus))
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'should allow configuring the authentication_url' do
|
107
|
+
connection_mock.should_receive(:post).
|
108
|
+
with('http://example.com/authentication', anything).
|
109
|
+
and_return(authentication_response_mock)
|
110
|
+
|
111
|
+
Pling::Gateway::C2DM.new(valid_configuration.merge(:authentication_url => 'http://example.com/authentication'))
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe '#deliver' do
|
117
|
+
subject { Pling::Gateway::C2DM.new(valid_configuration) }
|
118
|
+
|
119
|
+
let(:message) { Pling::Message.new('Hello from Pling') }
|
120
|
+
let(:device) { Pling::Device.new(:identifier => 'DEVICEIDENTIFIER', :type => :android) }
|
121
|
+
|
122
|
+
let(:valid_push_params) do
|
123
|
+
{
|
124
|
+
:registration_id => device.identifier,
|
125
|
+
:'data.body' => message.body,
|
126
|
+
:collapse_key => message.body.hash
|
127
|
+
}
|
128
|
+
end
|
129
|
+
|
130
|
+
let(:valid_push_headers) do
|
131
|
+
{
|
132
|
+
:Authorization => 'GoogleLogin auth=S0ME-ToKeN123'
|
133
|
+
}
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'should raise an error if no message is given' do
|
137
|
+
expect { subject.deliver(nil, device) }.to raise_error
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'should raise an error the device is given' do
|
141
|
+
expect { subject.deliver(message, nil) }.to raise_error
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'should call #to_pling_message on the given message' do
|
145
|
+
message.should_receive(:to_pling_message).and_return(message)
|
146
|
+
subject.deliver(message, device)
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'should call #to_pling_device on the given device' do
|
150
|
+
device.should_receive(:to_pling_device).and_return(device)
|
151
|
+
subject.deliver(message, device)
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'should try to deliver the given message' do
|
155
|
+
connection_mock.should_receive(:post).
|
156
|
+
with('https://android.apis.google.com/c2dm/send', valid_push_params, valid_push_headers).
|
157
|
+
and_return(push_response_mock)
|
158
|
+
|
159
|
+
subject.deliver(message, device)
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'should raise a Pling::DeliveryFailed exception if the delivery was not successful' do
|
163
|
+
connection_mock.should_receive(:post).
|
164
|
+
with('https://android.apis.google.com/c2dm/send', valid_push_params, valid_push_headers).
|
165
|
+
and_return(push_response_mock)
|
166
|
+
|
167
|
+
push_response_mock.stub(:status => 401, :success? => false, :body => "Something went wrong")
|
168
|
+
|
169
|
+
expect { subject.deliver(message, device) }.to raise_error Pling::DeliveryFailed, /Something went wrong/
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'should raise a Pling::DeliveryFailed exception if the response body contained an error' do
|
173
|
+
connection_mock.should_receive(:post).
|
174
|
+
with('https://android.apis.google.com/c2dm/send', valid_push_params, valid_push_headers).
|
175
|
+
and_return(push_response_mock)
|
176
|
+
|
177
|
+
push_response_mock.stub(:status => 200, :success? => true, :body => "Error=SomeError")
|
178
|
+
|
179
|
+
expect { subject.deliver(message, device) }.to raise_error Pling::DeliveryFailed, /Error=SomeError/
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Pling::Gateway do
|
4
|
+
|
5
|
+
subject { Pling::Gateway }
|
6
|
+
|
7
|
+
let(:message) { Pling::Message.new('Hello from Pling') }
|
8
|
+
let(:device) { Pling::Device.new(:identifier => 'DEVICEIDENTIFIER', :type => :android) }
|
9
|
+
|
10
|
+
let(:gateway_class) do
|
11
|
+
Class.new(Pling::Gateway::Base).tap do |klass|
|
12
|
+
klass.instance_eval do
|
13
|
+
handles :android
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:gateway) { gateway_class.new }
|
19
|
+
|
20
|
+
before { Pling.stub(:gateways).and_return(Pling::DelayedInitializer.new([gateway])) }
|
21
|
+
|
22
|
+
it { should respond_to(:discover) }
|
23
|
+
|
24
|
+
describe '.discover' do
|
25
|
+
it 'should do a delayed initialization' do
|
26
|
+
Pling.stub(:gateways).and_return(Pling::DelayedInitializer.new([[gateway_class, { :some => :option }]]))
|
27
|
+
gateway_class.should_receive(:new).with({ :some => :option }).and_return(mock.as_null_object)
|
28
|
+
subject.discover(device)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should require an argument' do
|
32
|
+
expect { subject.discover }.to raise_error ArgumentError
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should call #to_pling_device on the given argument' do
|
36
|
+
device.should_receive(:to_pling_device).and_return(device)
|
37
|
+
subject.discover(device)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should return a gateway that can handle the given device' do
|
41
|
+
subject.discover(device).should be == gateway
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should raise an Pling::NoGatewayFound error if no gateway was found' do
|
45
|
+
device.type = :random
|
46
|
+
expect { subject.discover(device) }.to raise_error Pling::NoGatewayFound, /Could not find a gateway for Pling::Device with type :random/
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Pling::Message do
|
4
|
+
|
5
|
+
context 'when created with no arguments' do
|
6
|
+
it 'should not require an argument' do
|
7
|
+
expect { Pling::Message.new() }.to_not raise_error ArgumentError
|
8
|
+
end
|
9
|
+
|
10
|
+
specify { Pling::Message.new().should_not be_valid }
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'when created with a string as first argument' do
|
14
|
+
subject { Pling::Message.new('Hello from Pling') }
|
15
|
+
its(:body) { should eq('Hello from Pling') }
|
16
|
+
it { should be_valid }
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'when created with a hash that contains a :body key as first argument' do
|
20
|
+
subject { Pling::Message.new(:body => 'Hello from Pling') }
|
21
|
+
its(:body) { should eq('Hello from Pling') }
|
22
|
+
it { should be_valid }
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'when created with an hash of invalid attributes' do
|
26
|
+
it 'should ignore the invalid paramters' do
|
27
|
+
expect { Pling::Message.new({ :random_param => true }) }.to_not raise_error
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#body=' do
|
32
|
+
it 'should call #to_s on the given body' do
|
33
|
+
subject.body = stub(:to_s => 'Hello from Pling')
|
34
|
+
subject.body.should eq('Hello from Pling')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#to_pling_message' do
|
39
|
+
it 'should return self' do
|
40
|
+
subject.to_pling_message.should be === subject
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
data/spec/pling_spec.rb
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Pling do
|
4
|
+
|
5
|
+
subject { Pling }
|
6
|
+
|
7
|
+
it { should respond_to(:configure) }
|
8
|
+
|
9
|
+
describe '.configure' do
|
10
|
+
it 'should require a block' do
|
11
|
+
expect { subject.configure }.to raise_error(ArgumentError, /no block given/i)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should call the block' do
|
15
|
+
expect { Pling.configure { throw :executed } }.to throw_symbol(:executed)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should pass Pling to the block' do
|
19
|
+
Pling.configure do |config|
|
20
|
+
config.should be(Pling)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it { should respond_to(:gateways) }
|
26
|
+
it { should respond_to(:gateways=) }
|
27
|
+
its(:gateways) { should eq([]) }
|
28
|
+
its(:gateways) { should be_kind_of Pling::DelayedInitializer }
|
29
|
+
|
30
|
+
describe '.gateways=' do
|
31
|
+
it 'should not change its type when set to an other array' do
|
32
|
+
subject.gateways = []
|
33
|
+
subject.gateways.should be_kind_of Pling::DelayedInitializer
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it { should respond_to(:middlewares) }
|
38
|
+
it { should respond_to(:middlewares=) }
|
39
|
+
its(:middlewares) { should eq([]) }
|
40
|
+
its(:middlewares) { should be_kind_of Pling::DelayedInitializer }
|
41
|
+
|
42
|
+
describe '.middlewares=' do
|
43
|
+
it 'should not change its type when set to an other array' do
|
44
|
+
subject.middlewares = []
|
45
|
+
subject.middlewares.should be_kind_of Pling::DelayedInitializer
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
it { should respond_to(:adapter) }
|
50
|
+
it { should respond_to(:adapter=) }
|
51
|
+
|
52
|
+
describe '.adapter' do
|
53
|
+
it 'should default to Pling::Adapter::Base' do
|
54
|
+
subject.adapter.class.should eq(Pling::Adapter::Base)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe '.deliver' do
|
59
|
+
|
60
|
+
let(:message) { Pling::Message.new }
|
61
|
+
let(:device) { Pling::Device.new }
|
62
|
+
let(:adapter) { mock(:deliver => true) }
|
63
|
+
|
64
|
+
before do
|
65
|
+
Pling.stub(:adapter).and_return(adapter)
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should raise an error if no message is given' do
|
69
|
+
expect { Pling.deliver(nil, device) }.to raise_error
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should raise an error the device is given' do
|
73
|
+
expect { Pling.deliver(message, nil) }.to raise_error
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should call #to_pling_message on the given message' do
|
77
|
+
message.should_receive(:to_pling_message).and_return(message)
|
78
|
+
Pling.deliver(message, device)
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'should call #to_pling_device on the given device' do
|
82
|
+
device.should_receive(:to_pling_device).and_return(device)
|
83
|
+
Pling.deliver(message, device)
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should call the adapter' do
|
87
|
+
adapter.should_receive(:deliver).with(message, device)
|
88
|
+
Pling.deliver(message, device)
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'should call each middleware in the given order' do
|
92
|
+
first_middleware = double(Pling::Middleware::Base)
|
93
|
+
first_middleware.should_receive(:deliver).
|
94
|
+
with(message, device).and_yield(message, device)
|
95
|
+
|
96
|
+
second_middleware = double(Pling::Middleware::Base)
|
97
|
+
second_middleware.should_receive(:deliver).
|
98
|
+
with(message, device)
|
99
|
+
|
100
|
+
Pling.stub(:middlewares).and_return(Pling::DelayedInitializer.new([first_middleware, second_middleware]))
|
101
|
+
|
102
|
+
Pling.deliver(message, device)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe Pling::AuthenticationFailed do
|
108
|
+
it { should be_kind_of Pling::Error }
|
109
|
+
end
|
110
|
+
|
111
|
+
describe Pling::DeliveryFailed do
|
112
|
+
it { should be_kind_of Pling::Error }
|
113
|
+
end
|
114
|
+
|
115
|
+
describe Pling::NoGatewayFound do
|
116
|
+
it { should be_kind_of Pling::Error }
|
117
|
+
end
|