action_sms 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,11 +1,46 @@
1
1
  require 'net/https'
2
2
 
3
- module ActionSms #:nodoc:
4
- module ConnectionAdapters #:nodoc:
3
+ module ActionSms
4
+ module ConnectionAdapters
5
5
  # All the concrete gateway adapters follow the interface laid down in this
6
- # class. You can use this interface directly by borrowing the gateway
6
+ # class. You can use this interface directly by borrowing the gateway
7
7
  # connection from the Base with Base.connection.
8
8
  class AbstractAdapter
9
+ require 'uri'
10
+
11
+ def initialize(config = {}) #:nodoc:
12
+ @config = config
13
+ end
14
+
15
+ def authenticate(params)
16
+ params["authentication_key"] == @config[:authentication_key] ?
17
+ params.delete("authentication_key") : nil
18
+ end
19
+
20
+ def authentication_key=(value)
21
+ @config[:authentication_key] = value
22
+ end
23
+
24
+ def authentication_key
25
+ @config[:authentication_key]
26
+ end
27
+
28
+ def configuration
29
+ @config
30
+ end
31
+
32
+ def configuration=(value)
33
+ @config = value
34
+ end
35
+
36
+ def use_ssl
37
+ @config[:use_ssl]
38
+ end
39
+
40
+ def use_ssl=(value)
41
+ @config[:use_ssl] = value
42
+ end
43
+
9
44
  protected
10
45
  # Helper method to send an HTTP POST request to +url+ with paramaters
11
46
  # specified by the +params+ hash.
@@ -16,11 +51,18 @@ module ActionSms #:nodoc:
16
51
 
17
52
  http = Net::HTTP.new(uri.host, uri.port)
18
53
  http.use_ssl = true if uri.scheme == 'https'
54
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
19
55
  resp = http.start do
20
56
  http.request(req)
21
57
  end
22
58
  resp.body
23
59
  end
60
+
61
+ def service_url(service_uri)
62
+ service_uri = URI.parse(service_uri)
63
+ service_uri.scheme = @config[:use_ssl] ? "https" : "http"
64
+ service_uri.to_s
65
+ end
24
66
  end
25
67
  end
26
68
  end
@@ -0,0 +1,76 @@
1
+ require 'action_sms/connection_adapters/abstract_adapter'
2
+
3
+ module ActionSms
4
+ class Base
5
+ def self.sms_global_connection(config) #:nodoc:
6
+ if config[:environment].to_s == "test"
7
+ test_helper = File.expand_path(File.dirname(__FILE__) + '/test_helpers/sms_global')
8
+ if File.exists?("#{test_helper}.rb")
9
+ require test_helper
10
+ ConnectionAdapters::SMSGlobalAdapter.class_eval do
11
+ include ActionSms::ConnectionAdapters::TestHelpers::SMSGlobal
12
+ end
13
+ end
14
+ end
15
+ ConnectionAdapters::SMSGlobalAdapter.new(config)
16
+ end
17
+ end
18
+
19
+ module ConnectionAdapters
20
+ # All the concrete gateway adapters follow the interface laid down in this
21
+ # class. You can use this interface directly by borrowing the gateway
22
+ # connection from the Base with Base.connection.
23
+ class SMSGlobalAdapter < AbstractAdapter
24
+
25
+ SERVICE_URL = "http://smsglobal.com.au/http-api.php"
26
+
27
+ def deliver(sms, options = {})
28
+ params = {
29
+ :action => 'sendsms',
30
+ :user => @config[:user],
31
+ :password => @config[:password],
32
+ :maxsplit => @config[:maxsplit] || "19",
33
+ :from => sms.respond_to?(:from) ? sms.from : "reply2email",
34
+ :to => sms.recipient,
35
+ :text => (sms.body || "")
36
+ }
37
+ params.merge!(
38
+ :userfield => sms.userfield
39
+ ) if sms.respond_to?(:userfield)
40
+ send_http_request(service_url, params)
41
+ end
42
+
43
+ def delivery_request_successful?(gateway_response)
44
+ gateway_response =~ /^OK/
45
+ end
46
+
47
+ def message_id(data)
48
+ sms_global_message_id_prefix = "SMSGlobalMsgID:"
49
+ if data.is_a?(Hash)
50
+ message_id = data["msgid"]
51
+ sms_global_message_id_prefix + message_id if message_id
52
+ elsif data.is_a?(String)
53
+ match = /#{sms_global_message_id_prefix}\s*(\d+)/.match(data)
54
+ sms_global_message_id_prefix + $1 if $1
55
+ end
56
+ end
57
+
58
+ def message_text(params)
59
+ params["msg"]
60
+ end
61
+
62
+ def sender(params)
63
+ params["from"]
64
+ end
65
+
66
+ def service_url
67
+ super(SERVICE_URL)
68
+ end
69
+
70
+ def status(delivery_receipt)
71
+ delivery_receipt["dlrstatus"]
72
+ end
73
+ end
74
+ end
75
+ end
76
+
@@ -0,0 +1,68 @@
1
+ module ActionSms
2
+ module ConnectionAdapters
3
+ module TestHelpers
4
+ module SMSGlobal
5
+
6
+ def sample_configuration(options = {})
7
+ config = {
8
+ :adapter => "sms_global",
9
+ :user => "SMSGlobal Username",
10
+ :password => "SMSGlobal Password"
11
+ }
12
+ config.merge!(
13
+ :authentication_key => "My Unique Authentication Key"
14
+ ) if options[:authentication_key]
15
+ config
16
+ end
17
+
18
+ def sample_delivery_receipt(options = {})
19
+ options[:message_id] ||= "6942744494999745"
20
+ options[:message_id].gsub!("SMSGlobalMsgID:", "")
21
+ options[:status] ||= "DELIVRD"
22
+ options[:error] ||= "000"
23
+ options[:date] ||= "1005132312"
24
+ {
25
+ "msgid"=> options[:message_id],
26
+ "dlrstatus"=> options[:status],
27
+ "dlr_err"=> options[:error],
28
+ "donedate"=> options[:date]
29
+ }
30
+ end
31
+
32
+ def sample_delivery_response(options = {})
33
+ options[:failed] ||= false
34
+ options[:message_id] ||= "6942744494999745"
35
+ options[:failed] ? "ERROR: No action requested" : "OK: 0; Sent queued message ID: 86b1a945370734f4 #{sample_message_id(:message_id => options[:message_id])}"
36
+ end
37
+
38
+ def sample_delivery_response_with_message_id(message_id, options = {})
39
+ options.merge!(:message_id => message_id)
40
+ sample_delivery_response(options)
41
+ end
42
+
43
+ def sample_incoming_sms(options = {})
44
+ options[:message] ||= "Endia kasdf ofeao"
45
+ options[:to] ||= "61447100308"
46
+ options[:from] ||= "61447100399"
47
+ options[:date] ||= "2010-05-13 23:59:11"
48
+ sample = {
49
+ "to" => options[:to],
50
+ "from" => options[:from],
51
+ "msg"=> options[:message],
52
+ "date" => options[:date]
53
+ }
54
+ sample.merge!(
55
+ "authentication_key" => @config[:authentication_key]
56
+ ) if options[:authentic]
57
+ sample
58
+ end
59
+
60
+ def sample_message_id(options = {})
61
+ options[:message_id] ||= "6942744494999745"
62
+ "SMSGlobalMsgID:#{options[:message_id]}"
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+
@@ -0,0 +1,67 @@
1
+ module ActionSms
2
+ module ConnectionAdapters
3
+ module TestHelpers
4
+ module Tropo
5
+
6
+ def sample_configuration(options = {})
7
+ config = {
8
+ :adapter => "tropo",
9
+ :outgoing_token => "Tropo Outgoing Token"
10
+ }
11
+ config.merge!(
12
+ :authentication_key => "My Unique Authentication Key"
13
+ ) if options[:authentication_key]
14
+ config
15
+ end
16
+
17
+ def sample_delivery_response(options = {})
18
+ options[:failed] ? "<session><success>false</success><token></token><reason>FAILED TO ROUTE TOKEN</reason></session>" : "<session><success>true</success></session>"
19
+ end
20
+
21
+ def sample_incoming_sms(options = {})
22
+ options[:message] ||= "Endia kasdf ofeao"
23
+ options[:to] ||= "61447100308"
24
+ options[:from] ||= "61447100399"
25
+ options[:date] ||= "Mon Oct 11 09:21:38 UTC 2010"
26
+ params = {
27
+ "session" => {
28
+ "id"=>"12349516546e59746d6a89a990466789",
29
+ "account_id"=>"12345",
30
+ "timestamp"=> options[:date],
31
+ "user_type"=>"HUMAN",
32
+ "initial_text"=> options[:message],
33
+ "call_id"=>"123e71195545ad204bdd99f2070a7d86",
34
+ "to"=>{
35
+ "id"=> options[:to],
36
+ "name"=>"unknown",
37
+ "channel"=>"TEXT",
38
+ "network"=>"SMS"
39
+ },
40
+ "from" => {
41
+ "id"=> options[:from],
42
+ "name"=>"unknown",
43
+ "channel"=>"TEXT",
44
+ "network"=>"SMS"
45
+ },
46
+ "headers" => {
47
+ "_max-_forwards"=>"70",
48
+ "_content-_length"=>"124",
49
+ "_contact"=>"<sip:11.8.93.101:5066;transport=udp>",
50
+ "_to"=>"<sip:1231454582@10.6.69.203:5061;to=#{options[:to]}>",
51
+ "_c_seq"=>"1 INVITE",
52
+ "_via"=>"SIP/2.0/UDP 11.8.93.101:5066;branch=h0hG4bKk5sy1e",
53
+ "_call-_i_d"=>"ieeg18",
54
+ "_content-_type"=>"application/sdp",
55
+
56
+ "_from"=>"<sip:15EB6BAB-99DF-44C2-871DFBA75C319776@11.8.93.201;channel=private;user=#{options[:to]};msg=#{options[:message]};network=SMS;step=1>;tag=zm13kt"
57
+ }
58
+ }
59
+ }
60
+ params.merge!("authentication_key" => @config[:authentication_key]) unless options[:authentic] == false
61
+ params
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+
@@ -0,0 +1,73 @@
1
+ require 'action_sms/connection_adapters/abstract_adapter'
2
+
3
+ module ActionSms
4
+ class Base
5
+ def self.tropo_connection(config) #:nodoc:
6
+ if config[:environment].to_s == "test"
7
+ test_helper = File.expand_path(File.dirname(__FILE__) + '/test_helpers/tropo')
8
+ if File.exists?("#{test_helper}.rb")
9
+ require test_helper
10
+ ConnectionAdapters::TropoAdapter.class_eval do
11
+ include ActionSms::ConnectionAdapters::TestHelpers::Tropo
12
+ end
13
+ end
14
+ end
15
+ ConnectionAdapters::TropoAdapter.new(config)
16
+ end
17
+ end
18
+
19
+ module ConnectionAdapters
20
+ # All the concrete gateway adapters follow the interface laid down in this
21
+ # class. You can use this interface directly by borrowing the gateway
22
+ # connection from the Base with Base.connection.
23
+ class TropoAdapter < AbstractAdapter
24
+ require 'tropo_message'
25
+
26
+ SERVICE_URL = "http://api.tropo.com/1.0/sessions"
27
+
28
+ def deliver(sms, options = {})
29
+ tropo_message = Tropo::Message.new
30
+ tropo_message.to = sms.recipient
31
+ tropo_message.text = sms.body || ""
32
+ tropo_message.from = sms.from if sms.respond_to?(:from)
33
+ tropo_message.token = @config[:outgoing_token]
34
+ response = send_http_request(service_url, tropo_message.request_xml)
35
+ options[:filter_response] ? filter_response(response) : response
36
+ end
37
+
38
+ def delivery_request_successful?(gateway_response)
39
+ gateway_response =~ /\<success\>true\<\/success\>/
40
+ end
41
+
42
+ def message_id(data)
43
+ # this method is supposed to return nil
44
+ end
45
+
46
+ def message_text(params)
47
+ session(params)["initial_text"]
48
+ end
49
+
50
+ def sender(params)
51
+ session(params)["from"]["id"]
52
+ end
53
+
54
+ def service_url
55
+ super(SERVICE_URL)
56
+ end
57
+
58
+ def status(delivery_receipt)
59
+ # this method is supposed to return nil
60
+ end
61
+
62
+ private
63
+ def session(params)
64
+ params["session"]
65
+ end
66
+
67
+ def filter_response(raw_response)
68
+ raw_response.gsub(/\<token\>\w+\<\/token\>/, "")
69
+ end
70
+ end
71
+ end
72
+ end
73
+
@@ -0,0 +1,4 @@
1
+ module ActionSms
2
+ VERSION = "0.1.0"
3
+ end
4
+
@@ -5,8 +5,35 @@ module ActionSms
5
5
  @source_root ||= File.join(File.dirname(__FILE__), 'templates')
6
6
  end
7
7
 
8
- def copy_conversation_file
9
- copy_file "action_sms.rb", "config/initializers/action_sms.rb"
8
+ def copy_initializer
9
+ template "action_sms.rb", "config/initializers/action_sms.rb"
10
+ end
11
+
12
+ private
13
+
14
+ def built_in_adapter_configurations
15
+ output = ""
16
+ adapters = ActionSms::Base.adapters(
17
+ :sample_configuration, :environment => "test"
18
+ )
19
+ adapters.each do |adapter|
20
+ config = adapter.sample_configuration
21
+ output << "## " << config[:adapter].titleize << "\n\n" <<
22
+ "# ActionSms::Base.establish_connection(" << "\n" <<
23
+ pretty_print_adapter_configuration(config) << "\n" <<
24
+ "# )"
25
+ output << "\n\n" unless adapters.last == adapter
26
+ end
27
+ output
28
+ end
29
+
30
+ def pretty_print_adapter_configuration(config)
31
+ output = ""
32
+ config.each do |key, value|
33
+ output << "# " << ":#{key}" << " => " << "\"#{value}\""
34
+ output << ",\n" unless config.keys.last == key
35
+ end
36
+ output
10
37
  end
11
38
  end
12
39
  end
@@ -1,11 +1,31 @@
1
- # see http://github.com/dwilkie/action_sms_gateways
2
- # for preconfigured sms gateways and more details on how to make your own adapter
1
+ # see also http://github.com/dwilkie/action_sms
2
+ # for more configuration options and details on how to make your own adapter
3
3
 
4
- # Then uncomment the following code and replace :adapter with your adapter
4
+ # Built In Adapters
5
5
 
6
- #ActionSms::Base.establish_connection(
7
- # :adapter => 'your_adapter',
8
- # :username => '[username]',
9
- # :password => '[password]'
10
- #)
6
+ <%= built_in_adapter_configurations %>
7
+
8
+ # Custom Adapters
9
+
10
+ # ActionSms::Base.establish_connection(
11
+ # :adapter => "your_adapter"
12
+ # # adapter specific configuration...
13
+ # )
14
+
15
+ # Incoming Message Authentication
16
+
17
+ # Using an authentication key in conjunction with a secure connection helps protect you against someone faking incoming messages to your server.
18
+
19
+ # ActionSms::Base.establish_connection(
20
+ # :use_ssl => true,
21
+ # :authentication_key => "my_secret"
22
+ # )
23
+
24
+ # Testing
25
+
26
+ # Setting: `:environment => "test"` gives you get some additional test helpers useful for testing
27
+
28
+ # ActionSms::Base.establish_connection(
29
+ # :environment => "test"
30
+ # )
11
31
 
data/spec/base_spec.rb ADDED
@@ -0,0 +1,649 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActionSms::Base do
4
+
5
+ describe "#adapters" do
6
+ let(:adapter) {mock "gateway_adapter"}
7
+ before do
8
+ ActionSms::Base.stub!(:methods).and_return(
9
+ [:gateway_adapter_connection]
10
+ )
11
+ ActionSms::Base.stub!(:gateway_adapter_connection).and_return(adapter)
12
+ end
13
+ context "an adapter responds to 'adapter_method'" do
14
+ before do
15
+ adapter.stub!(:adapter_method)
16
+ end
17
+ it "should include the adapter" do
18
+ ActionSms::Base.adapters(
19
+ :adapter_method
20
+ ).should include(adapter)
21
+ end
22
+ context "config = {}" do
23
+ context "and there's a current connection" do
24
+ before do
25
+ ActionSms::Base.stub!(:connected?).and_return(true)
26
+ end
27
+ let(:active_adapter_config) { {:adapter_name => "some_adapter"} }
28
+ before do
29
+ ActionSms::Base.stub!(:connection).and_return(mock(
30
+ "active_adapter",
31
+ :configuration => active_adapter_config
32
+ ))
33
+ end
34
+ it "should set the adapter's config to that of the current connection's" do
35
+ ActionSms::Base.should_receive(
36
+ :gateway_adapter_connection
37
+ ).with(active_adapter_config)
38
+ ActionSms::Base.adapters(:adapter_method)
39
+ end
40
+ end
41
+ context "but there's no current connection" do
42
+ it "should set the adapter's config to: '{}'" do
43
+ ActionSms::Base.should_receive(
44
+ :gateway_adapter_connection
45
+ ).with({})
46
+ ActionSms::Base.adapters(:adapter_method)
47
+ end
48
+ end
49
+ end
50
+ context "config = {:some_config => 'something'}" do
51
+ let(:config) { {:some_config => 'something'} }
52
+ it "should set the adapter's config to the passed in config" do
53
+ ActionSms::Base.should_receive(
54
+ :gateway_adapter_connection
55
+ ).with(config)
56
+ ActionSms::Base.adapters(:adapter_method, config)
57
+ end
58
+ end
59
+ end
60
+ context "an adapter does not respond to 'adapter_method'" do
61
+ it "should not include the adapter" do
62
+ ActionSms::Base.adapters(
63
+ :adapter_method
64
+ ).should_not include(:adapter)
65
+ end
66
+ end
67
+ end
68
+
69
+ describe "#connection" do
70
+ it "should set the connection" do
71
+ adapter = mock("adapter")
72
+ ActionSms::Base.connection = adapter
73
+ ActionSms::Base.connection.should == adapter
74
+ ActionSms::Base.should be_connected
75
+ end
76
+ end
77
+
78
+ describe "#establish_connection" do
79
+ context "adapter is specified in the configuration" do
80
+ let (:adapter_name) { "my_adapter" }
81
+ let (:adapter_connection) { adapter_name + "_connection" }
82
+ context "and is defined" do
83
+ let (:adapter) { mock("adapter") }
84
+ before do
85
+ ActionSms::Base.stub!(:respond_to?).with(
86
+ adapter_connection
87
+ ).and_return(true)
88
+ ActionSms::Base.stub!(
89
+ adapter_connection
90
+ ).and_return(adapter)
91
+ end
92
+ it "should be connected" do
93
+ ActionSms::Base.establish_connection(:adapter => adapter_name)
94
+ ActionSms::Base.should be_connected
95
+ end
96
+ end
97
+ context "but is not defined" do
98
+ before do
99
+ ActionSms::Base.stub!(:respond_to?).with(
100
+ adapter_connection
101
+ ).and_return(false)
102
+ end
103
+ it "should raise and 'AdapterNotFound' error" do
104
+ expect {
105
+ ActionSms::Base.establish_connection(:adapter => adapter_name)
106
+ }.to raise_error(ActionSms::AdapterNotFound)
107
+ end
108
+ end
109
+ end
110
+ context "adapter is not specified in the configuration" do
111
+ it "should raise an 'AdapterNotSpecified' error" do
112
+ expect {
113
+ ActionSms::Base.establish_connection({})
114
+ }.to raise_error(ActionSms::AdapterNotSpecified)
115
+ end
116
+ end
117
+ end
118
+
119
+ context "adapter helper methods" do
120
+ let(:active_adapter) {
121
+ mock("active_adapter")
122
+ }
123
+
124
+ let(:another_adapter) {
125
+ mock("another_adapter")
126
+ }
127
+
128
+ before do
129
+ ActionSms::Base.stub!(
130
+ :connection
131
+ ).and_return(active_adapter)
132
+
133
+ ActionSms::Base.stub!(
134
+ :methods
135
+ ).and_return([:another_adapter_connection])
136
+
137
+ ActionSms::Base.stub!(
138
+ :another_adapter_connection
139
+ ).and_return(another_adapter)
140
+
141
+ active_adapter.stub!(:configuration)
142
+ end
143
+
144
+ describe "#authenticate" do
145
+ before do
146
+ active_adapter.stub!(:respond_to?).with(
147
+ :authenticate
148
+ ).and_return(true)
149
+ end
150
+ context "active connection authenticates the message" do
151
+ before do
152
+ active_adapter.stub!(
153
+ :authenticate
154
+ ).and_return("something")
155
+ end
156
+ it "should return the active connection's response" do
157
+ ActionSms::Base.authenticate("anything").should == "something"
158
+ end
159
+ end
160
+ context "active connection does not authenticate the message" do
161
+ before do
162
+ active_adapter.stub!(:authenticate)
163
+ end
164
+ context "another adapter authenticates the message" do
165
+ before do
166
+ another_adapter.stub!(
167
+ :authenticate
168
+ ).and_return("something else")
169
+ end
170
+ it "should return the other adapter's response" do
171
+ ActionSms::Base.authenticate("anything").should == "something else"
172
+ end
173
+ end
174
+ context "no other adapter authenticates the message" do
175
+ it "should return nil" do
176
+ ActionSms::Base.authenticate("anything").should be_nil
177
+ end
178
+ end
179
+ end
180
+ end
181
+
182
+ describe "#authentication_key" do
183
+ it "should call 'authentication_key' on the connection" do
184
+ active_adapter.should_receive(:authentication_key)
185
+ ActionSms::Base.authentication_key
186
+ end
187
+ end
188
+
189
+ describe "#authentication_key=" do
190
+ it "should call 'authentication_key=' on the connection" do
191
+ active_adapter.should_receive(
192
+ :authentication_key=
193
+ ).with("something")
194
+ ActionSms::Base.authentication_key = "something"
195
+ end
196
+ end
197
+
198
+ describe "#deliver" do
199
+ it "should call 'deliver' on the connection" do
200
+ sms = mock("sms")
201
+ options = {:my_options => "something"}
202
+ active_adapter.should_receive(:deliver).with(sms, options)
203
+ ActionSms::Base.deliver(sms, options)
204
+ end
205
+ end
206
+
207
+ describe "#delivery_request_successful?" do
208
+ it "should call 'delivery_request_successful?' on the connection" do
209
+ gateway_response = mock("gateway_response")
210
+ active_adapter.should_receive(
211
+ :delivery_request_successful?
212
+ ).with(gateway_response)
213
+ ActionSms::Base.delivery_request_successful?(gateway_response)
214
+ end
215
+ end
216
+
217
+ describe "#message_id" do
218
+ before do
219
+ active_adapter.stub!(:respond_to?).with(
220
+ :message_id
221
+ ).and_return(true)
222
+ end
223
+ context "active connection returns the message id" do
224
+ before do
225
+ active_adapter.stub!(
226
+ :message_id
227
+ ).and_return("something")
228
+ end
229
+ it "should return the active connection's response" do
230
+ ActionSms::Base.message_id("anything").should == "something"
231
+ end
232
+ end
233
+ context "active connection does not return the message id" do
234
+ before do
235
+ active_adapter.stub!(:message_id)
236
+ end
237
+ context "another adapter returns the message id" do
238
+ before do
239
+ another_adapter.stub!(
240
+ :message_id
241
+ ).and_return("something else")
242
+ end
243
+
244
+ it "should return the other adapter's response" do
245
+ ActionSms::Base.message_id("anything").should == "something else"
246
+ end
247
+ end
248
+
249
+ context "no other adapter returns the message id" do
250
+ it "should return nil" do
251
+ ActionSms::Base.message_id("anything").should be_nil
252
+ end
253
+ end
254
+ end
255
+ end
256
+
257
+ describe "#message_text" do
258
+ before do
259
+ active_adapter.stub!(:respond_to?).with(
260
+ :message_text
261
+ ).and_return(true)
262
+ end
263
+ context "active connection returns the message text" do
264
+ before do
265
+ active_adapter.stub!(
266
+ :message_text
267
+ ).and_return("something")
268
+ end
269
+ it "should return the active connection's response" do
270
+ ActionSms::Base.message_text("anything").should == "something"
271
+ end
272
+ end
273
+ context "active connection does not return the message text" do
274
+ before do
275
+ active_adapter.stub!(:message_text)
276
+ end
277
+ context "another adapter returns the message text" do
278
+ before do
279
+ another_adapter.stub!(
280
+ :message_text
281
+ ).and_return("something else")
282
+ end
283
+
284
+ it "should return the other adapter's response" do
285
+ ActionSms::Base.message_text("anything").should == "something else"
286
+ end
287
+ end
288
+
289
+ context "no other adapter returns the message text" do
290
+ it "should return nil" do
291
+ ActionSms::Base.message_text("anything").should be_nil
292
+ end
293
+ end
294
+ end
295
+ end
296
+
297
+ describe "#sender" do
298
+ before do
299
+ active_adapter.stub!(:respond_to?).with(
300
+ :sender
301
+ ).and_return(true)
302
+ end
303
+ context "active connection returns the sender" do
304
+ before do
305
+ active_adapter.stub!(
306
+ :sender
307
+ ).and_return("something")
308
+ end
309
+ it "should return the active connection's response" do
310
+ ActionSms::Base.sender("anything").should == "something"
311
+ end
312
+ end
313
+ context "active connection does not return the sender" do
314
+ before do
315
+ active_adapter.stub!(:sender)
316
+ end
317
+ context "another adapter returns the sender" do
318
+ before do
319
+ another_adapter.stub!(
320
+ :sender
321
+ ).and_return("something else")
322
+ end
323
+
324
+ it "should return the other adapter's response" do
325
+ ActionSms::Base.sender("anything").should == "something else"
326
+ end
327
+ end
328
+
329
+ context "no other adapter return the sender" do
330
+ it "should return nil" do
331
+ ActionSms::Base.sender("anything").should be_nil
332
+ end
333
+ end
334
+ end
335
+ end
336
+
337
+ describe "#service_url" do
338
+ it "should call 'service_url' on the connection" do
339
+ active_adapter.should_receive(:service_url)
340
+ ActionSms::Base.service_url
341
+ end
342
+ end
343
+
344
+ describe "#status" do
345
+ before do
346
+ active_adapter.stub!(:respond_to?).with(
347
+ :status
348
+ ).and_return(true)
349
+ end
350
+ context "active connection returns the status" do
351
+ before do
352
+ active_adapter.stub!(
353
+ :status
354
+ ).and_return("something")
355
+ end
356
+ it "should return the active connection's response" do
357
+ ActionSms::Base.status("anything").should == "something"
358
+ end
359
+ end
360
+ context "active connection does not return the status" do
361
+ before do
362
+ active_adapter.stub!(:status)
363
+ end
364
+ context "another adapter returns the status" do
365
+ before do
366
+ another_adapter.stub!(
367
+ :status
368
+ ).and_return("something else")
369
+ end
370
+ it "should return the other adapter's response" do
371
+ ActionSms::Base.status("anything").should == "something else"
372
+ end
373
+ end
374
+ context "no adapters return the status" do
375
+ it "should return nil" do
376
+ ActionSms::Base.status("anything").should be_nil
377
+ end
378
+ end
379
+ end
380
+ end
381
+
382
+ describe "#use_ssl" do
383
+ it "should call 'use_ssl' on the connection" do
384
+ active_adapter.should_receive(:use_ssl)
385
+ ActionSms::Base.use_ssl
386
+ end
387
+ end
388
+
389
+ describe "#use_ssl=" do
390
+ it "should call 'use_ssl=' on the connection" do
391
+ active_adapter.should_receive(
392
+ :use_ssl=
393
+ ).with("something")
394
+ ActionSms::Base.use_ssl = "something"
395
+ end
396
+ end
397
+
398
+ # Test Helper Methods
399
+
400
+ describe "#sample_configuration" do
401
+ it "should call 'sample_configuration' on the connection" do
402
+ active_adapter.should_receive(:sample_configuration)
403
+ ActionSms::Base.sample_configuration
404
+ end
405
+ context "with options" do
406
+ it "should pass on the options" do
407
+ options = {:my_option => "12345"}
408
+ active_adapter.should_receive(
409
+ :sample_configuration
410
+ ).with(options)
411
+ ActionSms::Base.sample_configuration(options)
412
+ end
413
+ end
414
+ end
415
+
416
+ describe "#sample_delivery_receipt" do
417
+ shared_examples_for "another adapter's sample_delivery_receipt" do
418
+ context "but another adapter responds to 'sample_delivery_receipt'" do
419
+ before do
420
+ another_adapter.stub!(:sample_delivery_receipt)
421
+ end
422
+ context "and returns one" do
423
+ before do
424
+ another_adapter.stub!(
425
+ :sample_delivery_receipt
426
+ ).and_return("something else")
427
+ end
428
+ it "should return the other adapter's response" do
429
+ ActionSms::Base.sample_delivery_receipt.should == "something else"
430
+ end
431
+ end
432
+ context "but also returns nil" do
433
+ it "should return nil" do
434
+ ActionSms::Base.sample_delivery_receipt.should be_nil
435
+ end
436
+ end
437
+ end
438
+ context "and no other adapter responds to 'sample_delivery_receipt'" do
439
+ it "should return nil" do
440
+ ActionSms::Base.sample_delivery_receipt.should be_nil
441
+ end
442
+ end
443
+ end
444
+ context "active connection responds to 'sample_delivery_receipt'" do
445
+ before do
446
+ active_adapter.stub!(:sample_delivery_receipt)
447
+ end
448
+ context "and returns a sample delivery receipt" do
449
+ before do
450
+ active_adapter.stub!(
451
+ :sample_delivery_receipt
452
+ ).and_return("something")
453
+ end
454
+ it "should return the active connection's response" do
455
+ ActionSms::Base.sample_delivery_receipt.should == "something"
456
+ end
457
+ end
458
+ context "but returns nil" do
459
+ before do
460
+ active_adapter.stub!(:sample_delivery_receipt)
461
+ end
462
+ it_behaves_like "another adapter's sample_delivery_receipt"
463
+ end
464
+ end
465
+ context "active connection does not respond to 'sample_delivery_receipt'" do
466
+ it_behaves_like "another adapter's sample_delivery_receipt"
467
+ end
468
+ end
469
+
470
+ describe "#sample_delivery_response" do
471
+ it "should call 'sample_delivery_response' on the connection" do
472
+ active_adapter.should_receive(:sample_delivery_response)
473
+ ActionSms::Base.sample_delivery_response
474
+ end
475
+ context "with options" do
476
+ it "should pass on the options" do
477
+ options = {:my_option => "12345"}
478
+ active_adapter.should_receive(
479
+ :sample_delivery_response
480
+ ).with(options)
481
+ ActionSms::Base.sample_delivery_response(options)
482
+ end
483
+ end
484
+ end
485
+
486
+ describe "#sample_delivery_response_with_message_id" do
487
+ shared_examples_for "another adapter's sample_delivery_response_with_message_id" do
488
+ context "but another adapter responds to 'sample_delivery_response_with_message_id'" do
489
+ before do
490
+ another_adapter.stub!(:sample_delivery_response_with_message_id)
491
+ end
492
+ context "and returns one" do
493
+ before do
494
+ another_adapter.stub!(
495
+ :sample_delivery_response_with_message_id
496
+ ).and_return("something else")
497
+ end
498
+ it "should return the other adapter's response" do
499
+ ActionSms::Base.sample_delivery_response_with_message_id("12345") == "something else"
500
+ end
501
+ end
502
+ context "but also returns nil" do
503
+ it "should return nil" do
504
+ ActionSms::Base.sample_delivery_response_with_message_id("12345").should be_nil
505
+ end
506
+ end
507
+ end
508
+ context "and no other adapter responds to 'sample_delivery_response_with_message_id'" do
509
+ it "should return nil" do
510
+ ActionSms::Base.sample_delivery_response_with_message_id("12345").should be_nil
511
+ end
512
+ end
513
+ end
514
+ context "active connection responds to 'sample_delivery_response_with_message_id'" do
515
+ before do
516
+ active_adapter.stub!(:sample_delivery_response_with_message_id)
517
+ end
518
+ context "and returns a sample delivery response with message id" do
519
+ before do
520
+ active_adapter.stub!(
521
+ :sample_delivery_response_with_message_id
522
+ ).and_return("something")
523
+ end
524
+ it "should return the active connection's response" do
525
+ ActionSms::Base.sample_delivery_response_with_message_id("12345").should == "something"
526
+ end
527
+ end
528
+ context "but returns nil" do
529
+ before do
530
+ active_adapter.stub!(:sample_delivery_response_with_message_id)
531
+ end
532
+ it_behaves_like "another adapter's sample_delivery_response_with_message_id"
533
+ end
534
+ end
535
+ context "active connection does not respond to 'sample_delivery_response_with_message_id'" do
536
+ it_behaves_like "another adapter's sample_delivery_response_with_message_id"
537
+ end
538
+ end
539
+
540
+ describe "#sample_incoming_sms" do
541
+ shared_examples_for "another adapter's sample_incoming_sms" do
542
+ context "but another adapter responds to 'sample_incoming_sms'" do
543
+ before do
544
+ another_adapter.stub!(:sample_incoming_sms)
545
+ end
546
+ context "and returns one" do
547
+ before do
548
+ another_adapter.stub!(
549
+ :sample_incoming_sms
550
+ ).and_return("something else")
551
+ end
552
+ it "should return the other adapter's response" do
553
+ ActionSms::Base.sample_incoming_sms.should == "something else"
554
+ end
555
+ end
556
+ context "but also returns nil" do
557
+ it "should return nil" do
558
+ ActionSms::Base.sample_incoming_sms.should be_nil
559
+ end
560
+ end
561
+ end
562
+ context "and no other adapter responds to 'sample_incoming_sms'" do
563
+ it "should return nil" do
564
+ ActionSms::Base.sample_incoming_sms.should be_nil
565
+ end
566
+ end
567
+ end
568
+ context "active connection responds to 'sample_incoming_sms'" do
569
+ before do
570
+ active_adapter.stub!(:sample_incoming_sms)
571
+ end
572
+ context "and returns a sample incoming sms" do
573
+ before do
574
+ active_adapter.stub!(
575
+ :sample_incoming_sms
576
+ ).and_return("something")
577
+ end
578
+ it "should return the active connection's response" do
579
+ ActionSms::Base.sample_incoming_sms.should == "something"
580
+ end
581
+ end
582
+ context "but returns nil" do
583
+ before do
584
+ active_adapter.stub!(:sample_incoming_sms)
585
+ end
586
+ it_behaves_like "another adapter's sample_incoming_sms"
587
+ end
588
+ end
589
+ context "active connection does not respond to 'sample_incoming_sms'" do
590
+ it_behaves_like "another adapter's sample_incoming_sms"
591
+ end
592
+ end
593
+
594
+ describe "#sample_message_id" do
595
+ shared_examples_for "another adapter's sample_message_id" do
596
+ context "but another adapter responds to 'sample_message_id'" do
597
+ before do
598
+ another_adapter.stub!(:sample_message_id)
599
+ end
600
+ context "and returns one" do
601
+ before do
602
+ another_adapter.stub!(
603
+ :sample_message_id
604
+ ).and_return("something else")
605
+ end
606
+ it "should return the other adapter's response" do
607
+ ActionSms::Base.sample_message_id.should == "something else"
608
+ end
609
+ end
610
+ context "but also returns nil" do
611
+ it "should return nil" do
612
+ ActionSms::Base.sample_message_id.should be_nil
613
+ end
614
+ end
615
+ end
616
+ context "and no other adapter responds to 'sample_message_id'" do
617
+ it "should return nil" do
618
+ ActionSms::Base.sample_message_id.should be_nil
619
+ end
620
+ end
621
+ end
622
+ context "active connection responds to 'sample_message_id'" do
623
+ before do
624
+ active_adapter.stub!(:sample_message_id)
625
+ end
626
+ context "and returns a sample message id" do
627
+ before do
628
+ active_adapter.stub!(
629
+ :sample_message_id
630
+ ).and_return("something")
631
+ end
632
+ it "should return the active connection's response" do
633
+ ActionSms::Base.sample_message_id.should == "something"
634
+ end
635
+ end
636
+ context "but returns nil" do
637
+ before do
638
+ active_adapter.stub!(:sample_message_id)
639
+ end
640
+ it_behaves_like "another adapter's sample_message_id"
641
+ end
642
+ end
643
+ context "active connection does not respond to 'sample_message_id'" do
644
+ it_behaves_like "another adapter's sample_message_id"
645
+ end
646
+ end
647
+ end
648
+ end
649
+