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.
- 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
|
+
|