action_sms 0.0.3 → 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 -3
- data/Gemfile +4 -0
- data/README.markdown +141 -8
- data/Rakefile +2 -38
- data/action_sms.gemspec +16 -42
- data/lib/action_sms/base.rb +113 -3
- data/lib/action_sms/connection_adapters.rb +4 -1
- data/lib/action_sms/connection_adapters/abstract_adapter.rb +45 -3
- data/lib/action_sms/connection_adapters/sms_global_adapter.rb +76 -0
- data/lib/action_sms/connection_adapters/test_helpers/sms_global.rb +68 -0
- data/lib/action_sms/connection_adapters/test_helpers/tropo.rb +67 -0
- data/lib/action_sms/connection_adapters/tropo_adapter.rb +73 -0
- data/lib/action_sms/version.rb +4 -0
- data/lib/generators/action_sms/initializer/initializer_generator.rb +29 -2
- data/lib/generators/action_sms/initializer/templates/action_sms.rb +28 -8
- data/spec/base_spec.rb +649 -0
- data/spec/connection_adapters/abstract_adapter_spec.rb +58 -0
- data/spec/connection_adapters/sms_global_adapter_spec.rb +259 -0
- data/spec/connection_adapters/test_helpers/sms_global_spec.rb +204 -0
- data/spec/connection_adapters/test_helpers/tropo_spec.rb +135 -0
- data/spec/connection_adapters/tropo_adapter_spec.rb +198 -0
- data/spec/spec_helper.rb +6 -0
- data/todo +0 -2
- metadata +39 -14
- data/VERSION +0 -1
@@ -1,11 +1,46 @@
|
|
1
1
|
require 'net/https'
|
2
2
|
|
3
|
-
module ActionSms
|
4
|
-
module ConnectionAdapters
|
3
|
+
module ActionSms
|
4
|
+
module ConnectionAdapters
|
5
5
|
# All the concrete gateway adapters follow the interface laid down in this
|
6
|
-
# class.
|
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
|
+
|
@@ -5,8 +5,35 @@ module ActionSms
|
|
5
5
|
@source_root ||= File.join(File.dirname(__FILE__), 'templates')
|
6
6
|
end
|
7
7
|
|
8
|
-
def
|
9
|
-
|
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/
|
2
|
-
# for
|
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
|
-
#
|
4
|
+
# Built In Adapters
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
#
|
9
|
-
|
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
|
+
|