mollie-sms 0.2.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,104 @@
1
+ A Ruby client that allows you to send SMS messages via
2
+ {http://www.mollie.nl/sms-diensten/sms-gateway Mollie.nl}.
3
+
4
+ See {Mollie::SMS} for the API documentation. Or, if you are reading this as
5
+ plain text, on {http://rdoc.info/projects/Fingertips/Mollie-SMS rdoc.info}.
6
+
7
+ See the Mollie.nl API
8
+ {http://www.mollie.nl/support/documentatie/sms-diensten/sms/http/en documentation}
9
+ for more info.
10
+
11
+ *Note* that it currently only does what we need, for our app, at this point in
12
+ time. Which means that it connects to the webservice via SSL, and only sends a
13
+ message to *one* recipient at a time. Finally, it assumes ActiveSupport is
14
+ available for XML parsing. (A patch that adds a fallback, to REXML, is much
15
+ appreciated.)
16
+
17
+ = Install
18
+
19
+ $ gem install mollie-sms
20
+
21
+ Or if you have a checkout of the source and have installed Jeweler:
22
+
23
+ $ rake install
24
+
25
+ = Configuration
26
+
27
+ The minimum required settings are:
28
+ * {Mollie::SMS.username username}
29
+ * {Mollie::SMS.password password}
30
+ * {Mollie::SMS.originator originator}
31
+
32
+ For example, a Rails initializer might look like:
33
+
34
+ module Mollie
35
+ SMS.username = 'Fingertips'
36
+ SMS.password = 'secret'
37
+ SMS.originator = 'fngtps.nl'
38
+ end
39
+
40
+ = Examples
41
+
42
+ == Normal usage
43
+
44
+ require 'mollie/sms'
45
+
46
+ sms = Mollie::SMS.new('+31681664814', 'You have won a bowl of chicken noodle soup!')
47
+ => #<Mollie::SMS from: <fngtps.nl> to: <+31681664814> body: "You have won a bowl of chicken noodle soup!">
48
+
49
+ response = sms.deliver # => #<Mollie::SMS::Response succeeded (10) `Message successfully sent.'>
50
+
51
+ response.success? # => true
52
+ response.result_code # => 10
53
+ response.message # => "Message successfully sent."
54
+
55
+ == Test usage
56
+
57
+ require 'mollie/sms'
58
+ require 'mollie/sms/test_helper'
59
+
60
+ Mollie::SMS.http_failure!
61
+
62
+ response = sms.deliver # => #<Mollie::SMS::Response failed (400) `[HTTP: 400] Bad request'>
63
+ response.success? # => false
64
+ response.result_code # => 400
65
+ response.message # => "[HTTP: 400] Bad request"
66
+
67
+ Mollie::SMS.gateway_failure! # => #<Mollie::SMS::Response failed (20) `No username given.'>
68
+
69
+ response = sms.deliver # => #<Mollie::SMS::Response failed (20) `No username given.'>
70
+ response.success? # => false
71
+ response.result_code # => 20
72
+ response.message # => "No username given."
73
+
74
+ Mollie::SMS.deliveries
75
+ => [#<Mollie::SMS from: <fngtps.nl> to: <+31681664814> body: "You have won a bowl of chicken noodle soup!">,
76
+ #<Mollie::SMS from: <fngtps.nl> to: <+31681664814> body: "You have won a bowl of chicken noodle soup!">]
77
+
78
+ = Rails
79
+
80
+ If you are using Rails and load the Mollie::SMS gem, it will automatically
81
+ require the test helper in test mode.
82
+
83
+ It also requires the test helper in development mode, so no actual SMS
84
+ messages can be send. Instead, the messages are logged to the
85
+ development.log.
86
+
87
+ = Contributing
88
+
89
+ Once you've made your great commits:
90
+
91
+ 1. {http://help.github.com/forking Fork} Mollie-SMS
92
+ 2. Create a topic branch
93
+ git checkout -b my_branch
94
+ 3. Push to your branch
95
+ git push origin my_branch
96
+ 4. Create an {http://github.com/Fingertips/Mollie-SMS/issues issue} with a link
97
+ to your branch
98
+ 5. That's it!
99
+
100
+ = Copyright
101
+
102
+ Copyright (c) 2010 Eloy Duran, Fingertips <eloy@fngtps.com>
103
+
104
+ This software is MIT licensed. See {file:LICENSE} for more info.
data/Rakefile CHANGED
@@ -5,8 +5,18 @@ task :spec do
5
5
  sh "ruby ./spec/functional_sms_deliver_spec.rb"
6
6
  end
7
7
 
8
+ desc "Run the specs with Kicker"
9
+ task :kick do
10
+ sh "kicker -c -e rake"
11
+ end
12
+
8
13
  task :default => :spec
9
14
 
15
+ desc "Generate the docs with YARD"
16
+ task :doc do ||
17
+ sh "yardoc - README.rdoc LICENSE"
18
+ end
19
+
10
20
  begin
11
21
  require 'rubygems'
12
22
  require 'jeweler'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.1
1
+ 1.0.0
@@ -8,10 +8,56 @@ rescue LoadError
8
8
  end
9
9
  require "active_support"
10
10
 
11
+ # The namespace for the Mollie.nl webservices.
12
+ #
13
+ # @see Mollie::SMS
11
14
  module Mollie
15
+ # A class that allows you to send SMS messages through the Mollie.nl SMS
16
+ # webservice.
17
+ #
18
+ # See the {file:README.rdoc README} for examples on how to use this.
19
+ #
12
20
  class SMS
21
+ # A collection of exception classes raised by Mollie::SMS.
22
+ module Exceptions
23
+ # The base class for Mollie::SMS exceptions.
24
+ class StandardError < ::StandardError; end
25
+
26
+ # The exception class which is used to indicate a validation error of one
27
+ # of the {SMS#params parameters} that would be send to the gateway.
28
+ class ValidationError < StandardError; end
29
+
30
+ # The exception class which is used to indicate a delivery failure, when
31
+ # the {SMS#deliver!} method is used and delivery fails.
32
+ class DeliveryFailure < StandardError
33
+ # @return [SMS] The Mollie::SMS instance.
34
+ attr_reader :sms
35
+
36
+ # @return [Response] The Mollie::SMS::Response instance.
37
+ attr_reader :response
38
+
39
+ # @param [SMS] sms The Mollie::SMS instance.
40
+ # @param [Response] response The Mollie::SMS::Response instance.
41
+ def initialize(sms, response)
42
+ @sms, @response = sms, response
43
+ end
44
+
45
+ # @return [String] A string representation of the exception.
46
+ def message
47
+ "(#{@response.message}) #{@sms.to_s}"
48
+ end
49
+ end
50
+ end
51
+
52
+ # The SSL URI to which the parameters of a SMS are posted.
53
+ #
54
+ # Note that the certificate is *not* verified.
13
55
  GATEWAY_URI = URI.parse("https://secure.mollie.nl/xml/sms")
14
56
 
57
+ # The possible values that indicate which {SMS.gateway= SMS gateway} should
58
+ # be used.
59
+ #
60
+ # @see http://www.mollie.nl/sms-diensten/sms-gateway/gateways
15
61
  GATEWAYS = {
16
62
  'basic' => '2',
17
63
  'business' => '4',
@@ -19,31 +65,69 @@ module Mollie
19
65
  'landline' => '8'
20
66
  }
21
67
 
22
- class StandardError < ::StandardError; end
23
- class ValidationError < StandardError; end
24
- class MissingRequiredParam < StandardError; end
25
-
26
- class DeliveryFailure < StandardError
27
- attr_reader :sms, :response
28
-
29
- def initialize(sms, response)
30
- @sms, @response = sms, response
31
- end
32
-
33
- def message
34
- "(#{@response.message}) #{@sms.to_s}"
35
- end
36
- end
37
-
68
+ # A list of paramaters that *must* to be included in the
69
+ # {SMS#params parameters} send to the gateway.
38
70
  REQUIRED_PARAMS = %w{ username md5_password originator gateway charset type recipients message }
39
71
 
40
72
  class << self
41
- attr_accessor :username, :password, :originator, :charset, :type, :gateway
73
+ # @return [String] Your username for the Mollie.nl SMS webservice.
74
+ attr_accessor :username
42
75
 
76
+ # @return [String] A MD5 hashed version of your password for the
77
+ # Mollie.nl SMS webservice.
78
+ attr_reader :password
43
79
  def password=(password)
44
80
  @password = Digest::MD5.hexdigest(password)
45
81
  end
46
82
 
83
+ # The number, or display name, that will be used to indicate the
84
+ # originator of a message.
85
+ #
86
+ # It should be upto either fourteen numerical characters, or eleven
87
+ # alphanumerical characters.
88
+ #
89
+ # @see SMS#validate_params!
90
+ #
91
+ # @return [String] The originator
92
+ attr_accessor :originator
93
+
94
+ # @return [String] A character set name, describing the message’s body
95
+ # encoding. Defaults to ‘UTF-8’.
96
+ attr_accessor :charset
97
+
98
+ # The type of messages that will be send. Possible values are:
99
+ # * normal
100
+ # * wappush
101
+ # * vcard
102
+ # * flash
103
+ # * binary
104
+ # * long
105
+ #
106
+ # Defaults to ‘normal’
107
+ #
108
+ # @return [String] The message type.
109
+ attr_accessor :type
110
+
111
+ # The gateway that should be used to send messages. Possible values are:
112
+ # * {GATEWAYS GATEWAYS['basic']}
113
+ # * {GATEWAYS GATEWAYS['business']}
114
+ # * {GATEWAYS GATEWAYS['business+']}
115
+ # * {GATEWAYS GATEWAYS['landline']}
116
+ #
117
+ # Defaults to ‘basic’.
118
+ #
119
+ # @see http://www.mollie.nl/sms-diensten/sms-gateway/gateways
120
+ #
121
+ # @return [String] The gateway ID.
122
+ attr_accessor :gateway
123
+
124
+ # Returns the default parameters that will be we merged with each
125
+ # instance’s params.
126
+ #
127
+ # This includes +username+, +md5_password+, +originator+, +gateway+,
128
+ # +charset+, and +type+.
129
+ #
130
+ # @return [Hash]
47
131
  def default_params
48
132
  {
49
133
  'username' => @username,
@@ -60,42 +144,78 @@ module Mollie
60
144
  self.type = 'normal'
61
145
  self.gateway = GATEWAYS['basic']
62
146
 
147
+ # @return [Hash] The parameters that will be send to the gateway.
63
148
  attr_reader :params
64
149
 
150
+ # Initializes a new Mollie::SMS instance.
151
+ #
152
+ # You can either specify the recipient’s telephone number and message
153
+ # body here, or later on through the accessors for these attributes.
154
+ #
155
+ # @param [String] telephone_number The recipient’s telephone number.
156
+ #
157
+ # @param [String] body The message body.
158
+ #
159
+ # @param [Hash] extra_params Optional parameters that are to be merged with
160
+ # the {SMS.default_params default parameters}.
65
161
  def initialize(telephone_number = nil, body = nil, extra_params = {})
66
162
  @params = self.class.default_params.merge(extra_params)
67
163
  self.telephone_number = telephone_number if telephone_number
68
164
  self.body = body if body
69
165
  end
70
166
 
167
+ # @return [String] The recipient’s telephone number.
71
168
  def telephone_number
72
169
  @params['recipients']
73
170
  end
74
171
 
172
+ # Assigns the recipient’s telephone number.
173
+ #
174
+ # @param [String] telephone_number The recipient’s telephone number.
175
+ # @return [String] The recipient’s telephone number.
75
176
  def telephone_number=(telephone_number)
76
177
  @params['recipients'] = telephone_number
77
178
  end
78
179
 
180
+ # @return [String] The message body.
79
181
  def body
80
182
  @params['message']
81
183
  end
82
184
 
185
+ # Assigns the message’s body.
186
+ #
187
+ # @param [String] body The message’s body.
188
+ # @return [String] The message’s body.
83
189
  def body=(body)
84
190
  @params['message'] = body
85
191
  end
86
192
 
193
+ # Compares whether or not this and the +other+ Mollie::SMS instance are
194
+ # equal in recipient, body, and other parameters.
195
+ #
196
+ # @param [SMS] other The Mollie::SMS instance to compare against.
197
+ # @return [Boolean]
87
198
  def ==(other)
88
199
  other.is_a?(SMS) && other.params == params
89
200
  end
90
201
 
202
+ # @return [String] A string representation of this instance.
91
203
  def to_s
92
204
  %{from: <#{params['originator']}> to: <#{telephone_number}> body: "#{body}"}
93
205
  end
94
206
 
207
+ # @return [String] A `inspect' string representation of this instance.
95
208
  def inspect
96
209
  %{#<#{self.class.name} #{to_s}>}
97
210
  end
98
211
 
212
+ # Posts the {#params parameters} to the gateway, through SSL.
213
+ #
214
+ # The params are validated before attempting to post them.
215
+ # @see #validate_params!
216
+ #
217
+ # @return [Response] A response object which encapsulates the result of the
218
+ # request.
99
219
  def deliver
100
220
  validate_params!
101
221
 
@@ -103,60 +223,120 @@ module Mollie
103
223
  post.form_data = params
104
224
  request = Net::HTTP.new(GATEWAY_URI.host, GATEWAY_URI.port)
105
225
  request.use_ssl = true
226
+ request.verify_mode = OpenSSL::SSL::VERIFY_NONE
106
227
  request.start do |http|
107
228
  response = http.request(post)
108
229
  Response.new(response)
109
230
  end
110
231
  end
111
232
 
233
+ # Posts the {#params parameters} through {#deliver}, but raises a
234
+ # DeliveryFailure in case the request fails.
235
+ #
236
+ # This happens if an HTTP error occurs, or the gateway didn’t accept the
237
+ # {#params parameters}.
238
+ #
239
+ # @return [Response] Upon success, a response object which encapsulates the
240
+ # result of the request.
241
+ #
242
+ # @raise [DeliveryFailure] An exception which encapsulates this {SMS SMS}
243
+ # instance and the {Response} object.
112
244
  def deliver!
113
245
  response = deliver
114
- raise DeliveryFailure.new(self, response) unless response.success?
246
+ raise Exceptions::DeliveryFailure.new(self, response) unless response.success?
115
247
  response
116
248
  end
117
249
 
250
+ # Checks if all {REQUIRED_PARAMS required parameters} are present and if
251
+ # the {SMS.originator} is of the right size.
252
+ #
253
+ # @see SMS.originator
254
+ #
255
+ # @raise [ValidationError] If any of the validations fail.
256
+ #
257
+ # @return [nil]
118
258
  def validate_params!
119
259
  params.slice(*REQUIRED_PARAMS).each do |key, value|
120
- raise MissingRequiredParam, "The required parameter `#{key}' is missing." if value.blank?
260
+ raise Exceptions::ValidationError, "The required parameter `#{key}' is missing." if value.blank?
121
261
  end
122
262
 
123
263
  originator = params['originator']
124
264
  if originator =~ /^\d+$/
125
265
  if originator.size > 14
126
- raise ValidationError, "Originator may have a maximimun of 14 numerical characters."
266
+ raise Exceptions::ValidationError, "Originator may have a maximimun of 14 numerical characters."
127
267
  end
128
268
  elsif originator.size > 11
129
- raise ValidationError, "Originator may have a maximimun of 11 alphanumerical characters."
269
+ raise Exceptions::ValidationError, "Originator may have a maximimun of 11 alphanumerical characters."
130
270
  end
131
271
  end
132
272
 
273
+ # This class encapsulates the HTTP response and the response from the
274
+ # gateway. Put shortly, instances of this class return whether or not a SMS
275
+ # message has been delivered.
133
276
  class Response
277
+ # @return [Net::HTTPResponse] The raw HTTP response object.
134
278
  attr_reader :http_response
135
279
 
280
+ # Initializes a new Mollie::SMS::Response instance.
281
+ #
282
+ # @param [Net::HTTPResponse] http_response The HTTP response object.
136
283
  def initialize(http_response)
137
284
  @http_response = http_response
138
285
  end
139
286
 
287
+ # @return [Hash] The response parameters from the gateway. Or an empty
288
+ # Hash if a HTTP error occurred.
140
289
  def params
141
290
  @params ||= http_failure? ? {} : Hash.from_xml(@http_response.read_body)['response']['item']
142
291
  end
143
292
 
293
+ # Upon success, returns the result code from the gateway. Otherwise the
294
+ # HTTP response code.
295
+ #
296
+ # The possible gateway result codes are:
297
+ # * 10 - message sent
298
+ # * 20 - no ‘username’
299
+ # * 21 - no ‘password’
300
+ # * 22 - no, or incorrect, ‘originator’
301
+ # * 23 - no ‘recipients’
302
+ # * 24 - no ‘message’
303
+ # * 25 - incorrect ‘recipients’
304
+ # * 26 - incorrect ‘originator’
305
+ # * 27 - incorrect ‘message’
306
+ # * 28 - charset failure
307
+ # * 29 - parameter failure
308
+ # * 30 - incorrect ‘username’ or ‘password’
309
+ # * 31 - not enough credits to send message
310
+ # * 38 - binary UDH parameter misformed
311
+ # * 39 - ‘deliverydate’ format is not correct
312
+ # * 98 - gateway unreachable
313
+ # * 99 - unknown error
314
+ #
315
+ # @return [Integer] The result code from the gateway or HTTP response
316
+ # code.
144
317
  def result_code
145
318
  (http_failure? ? @http_response.code : params['resultcode']).to_i
146
319
  end
147
320
 
321
+ # @return [String] The message from the gateway, or the HTTP message in
322
+ # case of a HTTP error.
323
+ #
324
+ # @see #result_code #result_code for a list of possible messages.
148
325
  def message
149
326
  http_failure? ? "[HTTP: #{@http_response.code}] #{@http_response.message}" : params['resultmessage']
150
327
  end
151
328
 
329
+ # @return [Boolean] Whether or not the SMS message has been delivered.
152
330
  def success?
153
331
  !http_failure? && params['success'] == 'true'
154
332
  end
155
333
 
334
+ # @return [Boolean] Whether or not the HTTP request was a success.
156
335
  def http_failure?
157
336
  !@http_response.is_a?(Net::HTTPSuccess)
158
337
  end
159
338
 
339
+ # @return [String] A `inspect' string representation of this instance.
160
340
  def inspect
161
341
  "#<#{self.class.name} #{ success? ? 'succeeded' : 'failed' } (#{result_code}) `#{message}'>"
162
342
  end
@@ -1,44 +1,13 @@
1
1
  module Mollie
2
2
  class SMS
3
- def self.deliveries
4
- @deliveries ||= []
5
- end
6
-
7
- def self.reset!
8
- @deliveries = []
9
- success!
10
- end
11
-
12
- def self.success!
13
- http_response = Net::HTTPOK.new('1.1', '200', 'OK')
14
- http_response.add_field('Content-type', 'application/xml')
15
- def http_response.read_body; TestHelper::SUCCESS_BODY; end
16
- @stubbed_response = Mollie::SMS::Response.new(http_response)
17
- end
18
-
19
- def self.gateway_failure!
20
- http_response = Net::HTTPOK.new('1.1', '200', 'OK')
21
- http_response.add_field('Content-type', 'application/xml')
22
- def http_response.read_body; TestHelper::FAILURE_BODY; end
23
- @stubbed_response = Mollie::SMS::Response.new(http_response)
24
- end
25
-
26
- def self.http_failure!
27
- @stubbed_response = Mollie::SMS::Response.new(Net::HTTPBadRequest.new('1.1', '400', 'Bad request'))
28
- end
29
-
30
- def self.stubbed_response
31
- @stubbed_response || success!
32
- end
33
-
34
- def deliver
35
- validate_params!
36
- self.class.deliveries << self
37
- self.class.stubbed_response
38
- end
39
-
3
+ # A collection of helpers for testing the delivery of SMS messages.
4
+ #
5
+ # This includes:
6
+ # * a couple of Test::Unit {Mollie::SMS::TestHelper::Assertions assertions}
7
+ # * {Mollie::SMS::TestHelper::SMSExt Mollie::SMS} class extensions and
8
+ # overrides
40
9
  module TestHelper
41
- SUCCESS_BODY = %{
10
+ SUCCESS_BODY = %{
42
11
  <?xml version="1.0" ?>
43
12
  <response>
44
13
  <item type="sms">
@@ -49,7 +18,7 @@ module Mollie
49
18
  </item>
50
19
  </response>}
51
20
 
52
- FAILURE_BODY = %{
21
+ FAILURE_BODY = %{
53
22
  <?xml version="1.0"?>
54
23
  <response>
55
24
  <item type="sms">
@@ -60,17 +29,175 @@ module Mollie
60
29
  </item>
61
30
  </response>}
62
31
 
63
- def assert_sms_messages(number_of_messages)
64
- before = Mollie::SMS.deliveries.length
65
- yield
66
- diff = Mollie::SMS.deliveries.length - before
67
- assert(diff == number_of_messages, "expected `#{number_of_messages}' SMS messages to be sent, actually sent `#{diff}'")
32
+ # A couple of Test::Unit assertions, to test the amount of sent messages.
33
+ module Assertions
34
+ # Asserts that a specific number of SMS messages have been sent, for the
35
+ # duration of the given block.
36
+ #
37
+ # def test_invitation_message_is_sent
38
+ # assert_sms_messages(1) do
39
+ # Account.create(:telephone_number => "+31621212121")
40
+ # end
41
+ # end
42
+ #
43
+ # @yield The context that will be used to check the number of sent
44
+ # messages.
45
+ #
46
+ # @return [nil]
47
+ #
48
+ # @see Mollie::SMS::TestHelper::SMSExt::ClassMethods#deliveries
49
+ # Mollie::SMS.deliveries
50
+ def assert_sms_messages(number_of_messages)
51
+ before = Mollie::SMS.deliveries.length
52
+ yield
53
+ diff = Mollie::SMS.deliveries.length - before
54
+ assert(diff == number_of_messages, "expected `#{number_of_messages}' SMS messages to be sent, actually sent `#{diff}'")
55
+ end
56
+
57
+ # Asserts that *no* SMS messages have been sent, for the duration of the
58
+ # given block.
59
+ #
60
+ # def test_no_invitation_message_is_sent_when_account_is_invalid
61
+ # assert_no_sms_messages do
62
+ # Account.create(:telephone_number => "invalid")
63
+ # end
64
+ # end
65
+ #
66
+ # @yield The context that will be used to check the number of sent
67
+ # messages.
68
+ #
69
+ # @return [nil]
70
+ #
71
+ # @see Mollie::SMS::TestHelper::SMSExt::ClassMethods#deliveries
72
+ # Mollie::SMS.deliveries
73
+ def assert_no_sms_messages
74
+ assert_sms_messages(0) { yield }
75
+ end
68
76
  end
69
77
 
70
- def assert_no_sms_messages
71
- assert_sms_messages(0) { yield }
78
+ # Extensions and overrides of the Mollie::SMS class for testing purposes.
79
+ #
80
+ # The class method extensions are defined on the
81
+ # {Mollie::SMS::TestHelper::SMSExt::ClassMethods ClassMethods} module.
82
+ module SMSExt
83
+ # @private
84
+ def self.included(klass)
85
+ klass.class_eval do
86
+ undef_method :deliver
87
+ alias_method :deliver, :test_deliver
88
+ extend ClassMethods
89
+ end
90
+ end
91
+
92
+ # Overrides the normal {Mollie::SMS#deliver deliver} method to *never*
93
+ # make an actual request.
94
+ #
95
+ # Instead, the SMS message, that’s to be delivered, is added to the
96
+ # {Mollie::SMS::TestHelper::SMSExt::ClassMethods#deliveries
97
+ # Mollie::SMS.deliveries} list for later inspection.
98
+ #
99
+ # The parameters are still validated.
100
+ #
101
+ # @return [Response] The stubbed Response instance.
102
+ #
103
+ # @see Mollie::SMS::TestHelper::SMSExt::ClassMethods#stubbed_response
104
+ # Mollie::SMS.stubbed_response
105
+ def deliver
106
+ validate_params!
107
+ self.class.deliveries << self
108
+ self.class.stubbed_response
109
+ end
110
+
111
+ alias_method :test_deliver, :deliver
112
+
113
+ module ClassMethods
114
+ # @return [Array<Mollie::SMS>] A list of sent SMS messages.
115
+ #
116
+ # @see Mollie::SMS::TestHelper::SMSExt#deliver
117
+ # Mollie::SMS#deliver
118
+ def deliveries
119
+ @deliveries ||= []
120
+ end
121
+
122
+ # Clears the {#deliveries deliveries} list and stubs a {#success!
123
+ # ‘success’} Response instance.
124
+ #
125
+ # @return [Response] The stubbed ‘success’ Response instance.
126
+ def reset!
127
+ @deliveries = []
128
+ success!
129
+ end
130
+
131
+ # Stubs a ‘success’ Response instance.
132
+ #
133
+ # This means that any following calls to {Mollie::SMS#deliver} will
134
+ # succeed and return the stubbed ‘success’ Response instance.
135
+ #
136
+ # Mollie::SMS.success!
137
+ # response = Mollie::SMS.new(number, body).deliver
138
+ # response.success? # => true
139
+ # response.result_code # => 10
140
+ # response.message # => "Message successfully sent."
141
+ #
142
+ # @return [Response] The stubbed ‘success’ Response instance.
143
+ def success!
144
+ http_response = Net::HTTPOK.new('1.1', '200', 'OK')
145
+ http_response.add_field('Content-type', 'application/xml')
146
+ # @private
147
+ def http_response.read_body; TestHelper::SUCCESS_BODY; end
148
+ @stubbed_response = Mollie::SMS::Response.new(http_response)
149
+ end
150
+
151
+ # Stubs a ‘gateway failure’ Response instance.
152
+ #
153
+ # This means that any following calls to {Mollie::SMS#deliver} will
154
+ # fail at the gateway and return the stubbed ‘gateway failure’
155
+ # Response instance.
156
+ #
157
+ # Mollie::SMS.gateway_failure!
158
+ # response = Mollie::SMS.new(number, body).deliver
159
+ # response.success? # => false
160
+ # response.result_code # => 20
161
+ # response.message # => "No username given."
162
+ #
163
+ # @return [Response] The stubbed ‘gateway failure’ Response
164
+ # instance.
165
+ def gateway_failure!
166
+ http_response = Net::HTTPOK.new('1.1', '200', 'OK')
167
+ http_response.add_field('Content-type', 'application/xml')
168
+ # @private
169
+ def http_response.read_body; TestHelper::FAILURE_BODY; end
170
+ @stubbed_response = Mollie::SMS::Response.new(http_response)
171
+ end
172
+
173
+ # Stubs a ‘HTTP failure’ Response instance.
174
+ #
175
+ # This means that any following calls to {Mollie::SMS#deliver} will
176
+ # fail at the HTTP level and return the stubbed ‘HTTP failure’
177
+ # Response instance.
178
+ #
179
+ # Mollie::SMS.http_failure!
180
+ # response = Mollie::SMS.new(number, body).deliver
181
+ # response.success? # => false
182
+ # response.result_code # => 400
183
+ # response.message # => "[HTTP: 400] Bad request"
184
+ #
185
+ # @return [Response] The stubbed ‘HTTP failure’ Response
186
+ # instance.
187
+ def http_failure!
188
+ @stubbed_response = Mollie::SMS::Response.new(Net::HTTPBadRequest.new('1.1', '400', 'Bad request'))
189
+ end
190
+
191
+ # @return [Response] The stubbed Response instance that will be
192
+ # returned for all requests from
193
+ # {Mollie::SMS#deliver}.
194
+ def stubbed_response
195
+ @stubbed_response || success!
196
+ end
197
+ end
72
198
  end
73
199
  end
74
200
  end
75
201
  end
76
202
 
203
+ Mollie::SMS.send(:include, Mollie::SMS::TestHelper::SMSExt)
@@ -5,20 +5,20 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{mollie-sms}
8
- s.version = "0.2.1"
8
+ s.version = "1.0.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Eloy Duran"]
12
- s.date = %q{2010-08-03}
12
+ s.date = %q{2010-08-06}
13
13
  s.description = %q{Send SMS text messages via the Mollie.nl SMS gateway.}
14
14
  s.email = ["eloy@fngtps.com"]
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE",
17
- "README"
17
+ "README.rdoc"
18
18
  ]
19
19
  s.files = [
20
20
  "LICENSE",
21
- "README",
21
+ "README.rdoc",
22
22
  "Rakefile",
23
23
  "VERSION",
24
24
  "lib/mollie/sms.rb",
@@ -2,7 +2,7 @@ case Rails.env
2
2
  when "test"
3
3
  require 'mollie/sms/test_helper'
4
4
  require 'active_support/test_case'
5
- ActiveSupport::TestCase.send(:include, Mollie::SMS::TestHelper)
5
+ ActiveSupport::TestCase.send(:include, Mollie::SMS::TestHelper::Assertions)
6
6
  when "development"
7
7
  require 'mollie/sms/test_helper'
8
8
  class Mollie::SMS
@@ -110,7 +110,7 @@ describe "When sending a Mollie::SMS message" do
110
110
  exception = nil
111
111
  begin
112
112
  @sms.deliver!
113
- rescue Mollie::SMS::DeliveryFailure => exception
113
+ rescue Mollie::SMS::Exceptions::DeliveryFailure => exception
114
114
  end
115
115
 
116
116
  exception.message.should == "(No username given.) #{@sms.to_s}"
@@ -210,7 +210,7 @@ describe "Mollie::SMS, concerning validation" do
210
210
  @sms.params['originator'] = "000000000011112"
211
211
  lambda do
212
212
  @sms.deliver
213
- end.should.raise(Mollie::SMS::ValidationError, "Originator may have a maximimun of 14 numerical characters.")
213
+ end.should.raise(Mollie::SMS::Exceptions::ValidationError, "Originator may have a maximimun of 14 numerical characters.")
214
214
  end
215
215
 
216
216
  it "accepts an originator of upto 11 alphanumerical characters" do
@@ -222,6 +222,6 @@ describe "Mollie::SMS, concerning validation" do
222
222
  @sms.params['originator'] = "0123456789AB"
223
223
  lambda do
224
224
  @sms.deliver
225
- end.should.raise(Mollie::SMS::ValidationError, "Originator may have a maximimun of 11 alphanumerical characters.")
225
+ end.should.raise(Mollie::SMS::Exceptions::ValidationError, "Originator may have a maximimun of 11 alphanumerical characters.")
226
226
  end
227
227
  end
@@ -44,8 +44,8 @@ describe "Mollie::SMS ext" do
44
44
  end
45
45
  end
46
46
 
47
- describe "Mollie::SMS::TestHelper" do
48
- extend Mollie::SMS::TestHelper
47
+ describe "Mollie::SMS::TestHelper::Assertions" do
48
+ extend Mollie::SMS::TestHelper::Assertions
49
49
 
50
50
  before do
51
51
  Mollie::SMS.reset!
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mollie-sms
3
3
  version: !ruby/object:Gem::Version
4
- hash: 21
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
- - 0
8
- - 2
9
7
  - 1
10
- version: 0.2.1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Eloy Duran
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-08-03 00:00:00 +02:00
18
+ date: 2010-08-06 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -43,10 +43,10 @@ extensions: []
43
43
 
44
44
  extra_rdoc_files:
45
45
  - LICENSE
46
- - README
46
+ - README.rdoc
47
47
  files:
48
48
  - LICENSE
49
- - README
49
+ - README.rdoc
50
50
  - Rakefile
51
51
  - VERSION
52
52
  - lib/mollie/sms.rb
data/README DELETED
@@ -1,7 +0,0 @@
1
- A Ruby client that allows you to send SMS messages via http://mollie.nl.
2
-
3
- It does only what we need, for our app, at this point in time. Which means that
4
- connects to the webservice via SSL, and only sends a message to one recipient
5
- at a time.
6
-
7
- Patches are accepted.