pling 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.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
|