rfsms 0.1.2

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.
@@ -0,0 +1,29 @@
1
+ #
2
+ # To change this template, choose Tools | Templates
3
+ # and open the template in the editor.
4
+
5
+ require 'rubygems'
6
+ require 'rake'
7
+ require 'rake/clean'
8
+ #require 'rake/rdoctask'
9
+ #require 'rdoc/task'
10
+ require 'rake/testtask'
11
+ require 'rspec/core/rake_task'
12
+
13
+ #Rake::RDocTask.new do |rdoc|
14
+ # files =['README', 'LICENSE', 'lib/**/*.rb']
15
+ # rdoc.rdoc_files.add(files)
16
+ # rdoc.main = "README" # page to start on
17
+ # rdoc.title = "Rfsms Docs"
18
+ # rdoc.rdoc_dir = 'doc/rdoc' # rdoc output folder
19
+ # rdoc.options << '--line-numbers'
20
+ #end
21
+
22
+ Rake::TestTask.new do |t|
23
+ t.test_files = FileList['test/**/*.rb']
24
+ end
25
+
26
+ RSpec::Core::RakeTask.new do |spec|
27
+ spec.pattern = 'spec/**/*.rb'
28
+ spec.rspec_opts = ['--backtrace']
29
+ end
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'autospec' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rspec-core', 'autospec')
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'htmldiff' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('diff-lcs', 'htmldiff')
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'ldiff' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('diff-lcs', 'ldiff')
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'nokogiri' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('nokogiri', 'nokogiri')
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rackup' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rack', 'rackup')
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rake' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rake', 'rake')
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rspec' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rspec-core', 'rspec')
@@ -0,0 +1,307 @@
1
+ #encoding: utf-8
2
+ # Sender SMS via rfsms.ru
3
+ # v0.1.1
4
+
5
+ require 'net/http'
6
+ require 'net/https'
7
+ require 'nori'
8
+ require 'i18n'
9
+ require 'active_support/all'
10
+
11
+ Nori.configure do |config|
12
+ config.convert_tags_to { |tag| tag.to_s.underscore.to_sym }
13
+ end
14
+
15
+ module Rfsms
16
+ DATEREGEXP = /^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2]\d|3[01]) (?:[01]\d|2[0-4]):(?:[0-5]\d):(?:[0-5]\d)$/
17
+ DATEFORMAT = "%Y-%m-%d %H:%M:%S"
18
+ INTEGER_REGEXP = /^\d+$/
19
+ FLOAT_REGEXP = /^\d+(?:\.\d+)?$/
20
+
21
+ class AnswerError < RuntimeError; end
22
+ class IncorrectAnswerError < AnswerError; end
23
+
24
+ class Answer
25
+ attr_reader :descr
26
+
27
+ # Инициализация объекта ответа с проверкой элементов в передаваемом блоке validate.
28
+ # Если validate возвращает false или nil возникает исключение Rfsms::IncorrectAnswerError
29
+ def initialize(body, &validate)
30
+ body_e = Nori.parse(body, :nokogiri)
31
+ p body_e if $DEBUG
32
+
33
+ elements = body_e[:data]
34
+ raise IncorrectAnswerError unless elements.is_a?(Hash)
35
+ p elements if $DEBUG
36
+
37
+ if code = elements.delete(:code) and @descr = elements.delete(:descr)
38
+ if code == '1'
39
+ raise IncorrectAnswerError if validate and !validate.call(elements)
40
+ elements.each_pair do |tag, value|
41
+ instance_variable_set(:"@#{tag}", value)
42
+ end
43
+ else
44
+ raise AnswerError, "#{code}: #{@descr}"
45
+ end
46
+ else
47
+ raise IncorrectAnswerError
48
+ end
49
+ end
50
+ end
51
+
52
+ class CancelAnswer < Answer
53
+ attr_reader :action, :cancel_col
54
+
55
+ def initialize(body)
56
+ super(body) do |e|
57
+ e[:action] =~ /^(?:check|make)$/
58
+ end
59
+ @cancel_col = @cancel_col.to_i
60
+ end
61
+ end
62
+
63
+ class SendAnswer < Answer
64
+ attr_reader :smsid, :datetime, :action, :all_recivers,
65
+ :col_send_abonent, :col_non_send_abonent, :price_of_sending,
66
+ :colsms_of_sending, :price
67
+
68
+ def initialize(body)
69
+ super(body) do |e|
70
+ e.has_key?(:smsid) and
71
+ e[:datetime] =~ DATEREGEXP and
72
+ e[:action] =~ /^(?:check|make|send)$/ and
73
+ e[:all_recivers] =~ INTEGER_REGEXP and
74
+ e[:col_send_abonent] =~ INTEGER_REGEXP and
75
+ e[:col_non_send_abonent] =~ INTEGER_REGEXP and
76
+ e[:price_of_sending] =~ FLOAT_REGEXP and
77
+ e[:colsms_of_sending] =~ INTEGER_REGEXP and
78
+ e[:price] =~ FLOAT_REGEXP
79
+ end
80
+ @datetime = DateTime.strptime(@datetime, DATEFORMAT)
81
+ @all_recivers = @all_recivers.to_i
82
+ @col_send_abonent = @col_send_abonent.to_i
83
+ @col_non_send_abonent = @col_non_send_abonent.to_i
84
+ @price_of_sending = @price_of_sending.to_f
85
+ @colsms_of_sending = @colsms_of_sending.to_i
86
+ @price = @price.to_f
87
+ end
88
+ end
89
+
90
+ class BalanceAnswer < Answer
91
+ attr_reader :account
92
+
93
+ def to_f
94
+ self.account
95
+ end
96
+
97
+ def to_s
98
+ self.to_f.to_s
99
+ end
100
+
101
+ def to_str
102
+ self.to_s
103
+ end
104
+
105
+ def +(other)
106
+ case other
107
+ when Float
108
+ self.to_f + other
109
+ when Integer, BalanceAnswer
110
+ self.to_f + other.to_f
111
+ else
112
+ n1, n2 = other.coerce(self)
113
+ n1 + n2
114
+ end
115
+ end
116
+
117
+ def coerce(other)
118
+ case other
119
+ when Float
120
+ return other, self.to_f
121
+ when Integer
122
+ return other.to_f, self
123
+ when String
124
+ return other, self.to_s
125
+ end
126
+ end
127
+
128
+ def initialize(body)
129
+ super(body) do |e|
130
+ e[:account] =~ FLOAT_REGEXP
131
+ end
132
+ @account = @account.to_f
133
+ end
134
+ end
135
+
136
+ class ReportAnswer < Answer
137
+ attr_reader :sms
138
+ class SMS
139
+ attr_reader :smsid, :datetime, :text, :source, :all_col, :delivered_col,
140
+ :not_delivered_col, :waiting_col, :enqueued_col, :payment
141
+
142
+ def initialize(elements)
143
+ p elements if $DEBUG
144
+ unless @smsid = elements[:smsid] and
145
+ @datetime = elements[:datetime] and @datetime =~ DATEREGEXP and
146
+ @text = elements[:text] and
147
+ @source = elements[:source] and
148
+ @all_col = elements[:all_col] and
149
+ @delivered_col = elements[:delivered_col] and
150
+ @not_delivered_col = elements[:not_delivered_col] and
151
+ @waiting_col = elements[:waiting_col] and
152
+ @enqueued_col = elements[:enqueued_col] and
153
+ @payment = elements[:payment]
154
+ raise IncorrectAnswerError
155
+ end
156
+ end
157
+ end
158
+
159
+ def initialize(body)
160
+ super(body)
161
+ @sms = case @sms
162
+ when Hash
163
+ [SMS.new(@sms)]
164
+ when Array
165
+ @sms.map {|sms| SMS.new(sms) }
166
+ else
167
+ []
168
+ end
169
+ end
170
+ end
171
+
172
+ class Connection
173
+ def initialize(url, login, password)
174
+ @uri = URI.parse(url)
175
+ @connection = Net::HTTP.new(@uri.host, @uri.port)
176
+ @connection.use_ssl = true
177
+ @connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
178
+ @login = login
179
+ @password = password
180
+ end
181
+
182
+ # отправляет text по указанным phones = [].
183
+ #
184
+ # @param [String] text текст сообщения
185
+ # @param [Array<String, Hash>] phones телефоны на которые будет отправлено, может быть хэшем где значения - индивидуальный текст
186
+ # @param [Time] datetime время в которое необходимо отправить, nil - сейчас
187
+ # @param [String] source кто отправил
188
+ # @param [Boolean] onlydelivery)
189
+ # @return [Rfsms::SendAnswer]
190
+ def send(text, phones, datetime = nil, source = nil, onlydelivery = false)
191
+ message = message_header
192
+ message << "<text>#{text}</text>"
193
+
194
+ case phones
195
+ when Array
196
+ phones.each do |phone|
197
+ message << " <to number='#{phone}'></to>\n"
198
+ end
199
+ when Hash
200
+ phones.each_pair do |phone, t|
201
+ message << " <to number='#{phone}'>#{t}</to>\n"
202
+ end
203
+ end
204
+
205
+ message << "<datetime>#{datetime.strftime(DATEFORMAT)}</datetime>" if datetime
206
+ message << "<source>#{source}</source>" if source
207
+ message << "<onlydelivery>1</onlydelivery>" if onlydelivery
208
+ message << message_footer
209
+
210
+ STDERR.puts "+SENDED:\n"+message+"\n-SENDED\n" if $DEBUG
211
+ @connection.request_post('/send.xml', message) do |response|
212
+ case response
213
+ when Net::HTTPSuccess
214
+ return SendAnswer.new(response.body)
215
+ else
216
+ response.error!
217
+ end
218
+ end
219
+ end
220
+
221
+ # получает отчет о списке рассылки при указанных датах начала(start) и
222
+ # конца(stop) типа Time
223
+ # если даты не указаны получает за весь период
224
+ #
225
+ # @param [Hash{Symbol => Time}] options :start - начало, :stop - окончание
226
+ # @return [Rfsms::ReportAnswer]
227
+ def report(options = {})
228
+ message = message_header
229
+ unless options.empty?
230
+ start, stop = options[:start].strftime(DATEFORMAT), options[:stop].strftime(DATEFORMAT)
231
+ if start =~ DATEREGEXP and stop =~ DATEREGEXP
232
+ message << <<-PERIOD
233
+ <start>#{start}</start>
234
+ <stop>#{stop}</stop>
235
+ PERIOD
236
+ else
237
+ raise ArgumentError, "Date #{start} or date #{stop} is incorrect!"
238
+ end
239
+ end
240
+ message << message_footer
241
+
242
+ STDERR.puts "+SENDED:\n"+message+"\n-SENDED\n" if $DEBUG
243
+ @connection.request_post('/report.xml', message) do |response|
244
+ case response
245
+ when Net::HTTPSuccess
246
+ return ReportAnswer.new(response.body)
247
+ else
248
+ response.error!
249
+ end
250
+ end
251
+ end
252
+
253
+ # возвращает текущий баланс
254
+ #
255
+ # @return [Rfsms::BalanceAnwer]
256
+ def balance
257
+ message = message_header + message_footer
258
+ STDERR.puts "+SENDED:\n"+message+"\n-SENDED\n" if $DEBUG
259
+ @connection.request_post('/balance.xml', message) do |response|
260
+ case response
261
+ when Net::HTTPSuccess
262
+ return BalanceAnswer.new(response.body)
263
+ else
264
+ response.error!
265
+ end
266
+ end
267
+ end
268
+
269
+ # отменяет СМС с идентификатором smsid
270
+ #
271
+ # @param [Integer, String] smsid
272
+ # @return [Rfsms::CancelAnswer]
273
+ def cancel(smsid)
274
+ message = message_header
275
+ message << <<END
276
+ <smsid>#{smsid}</smsid>
277
+ END
278
+ message << message_footer
279
+ STDERR.puts "+SENDED:\n"+message+"\n-SENDED\n" if $DEBUG
280
+ @connection.request_post('/cancel.xml', message) do |response|
281
+ case response
282
+ when Net::HTTPSuccess
283
+ return CancelAnswer.new(response.body)
284
+ else
285
+ response.error!
286
+ end
287
+ end
288
+ end
289
+
290
+ private
291
+
292
+ # формирует заголовок с данными авторизации
293
+ def message_header
294
+ <<END
295
+ <data>
296
+ <login>#{@login}</login>
297
+ <password>#{@password}</password>
298
+ END
299
+ end
300
+
301
+ # формирует подвал запроса
302
+ def message_footer
303
+ "</data>"
304
+ end
305
+ end
306
+
307
+ end
@@ -0,0 +1,40 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe Rfsms::Answer do
5
+ before(:each) do
6
+ @correct_body = <<-ANSWER
7
+ <data>
8
+ <code>1</code>
9
+ <descr>Операция успешно завершена</descr>
10
+ </data>
11
+ ANSWER
12
+ @correct_elements = Nori.parse(@correct_body, :nokogiri)[:data]
13
+ end
14
+
15
+ describe "конструктор" do
16
+ it "при корректных входных данных должен создавать экземпляр с соответствующими входу полями" do
17
+ answer = Rfsms::Answer.new(@correct_body)
18
+ answer.should be_an_instance_of(Rfsms::Answer)
19
+ answer.descr.should be == @correct_elements[:descr]
20
+ end
21
+
22
+ it "при значении элемента code отличного от 1 должен вызывать исключение Rfsms::AnswerError" do
23
+ lambda do
24
+ Rfsms::Answer.new(@correct_body.gsub(%r{(?<=<code>)\d+(?=</code>)}, '500'))
25
+ end.should raise_error Rfsms::AnswerError
26
+ end
27
+
28
+ it "при отсутствии одного из входных элементов вызывает исключение Rfsms::IncorrectAnswerError" do
29
+ lambda do
30
+ incorrect_elements = @correct_body.gsub(%r{<code>.*</code>}, '')
31
+ Rfsms::Answer.new(incorrect_elements)
32
+ end.should raise_error(Rfsms::IncorrectAnswerError)
33
+ lambda do
34
+ incorrect_elements = @correct_body.gsub(%r{<descr>.*</descr>}, '')
35
+ Rfsms::Answer.new(incorrect_elements)
36
+ end.should raise_error(Rfsms::IncorrectAnswerError)
37
+ end
38
+ end
39
+ end
40
+
@@ -0,0 +1,38 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe Rfsms::BalanceAnswer do
5
+ before(:each) do
6
+ @correct_body = <<-ANSWER
7
+ <data>
8
+ <code>1</code>
9
+ <descr>Операция успешно завершена</descr>
10
+ <account>10000.94</account>
11
+ </data>
12
+ ANSWER
13
+ @correct_elements = Nori.parse(@correct_body, :nokogiri)[:data]
14
+ end
15
+
16
+ it "при корректных входных данных конструктор создает объект с соответствующими входу полями" do
17
+ correct_balance_answer = Rfsms::BalanceAnswer.new(@correct_body)
18
+ correct_balance_answer.should be_an_instance_of(Rfsms::BalanceAnswer)
19
+ correct_balance_answer.descr.should be == @correct_elements[:descr]
20
+ correct_balance_answer.account.should be == @correct_elements[:account].to_f
21
+ end
22
+
23
+ it "при отсутствии одного из входных элементов конструктор вызывает исключение Rfsms::IncorrectAnswerError" do
24
+ lambda do
25
+ incorrect_elements = @correct_body.gsub(%r{<code>.*</code>}, '')
26
+ Rfsms::BalanceAnswer.new(incorrect_elements)
27
+ end.should raise_error(Rfsms::IncorrectAnswerError)
28
+ lambda do
29
+ incorrect_elements = @correct_body.gsub(%r{<descr>.*</descr>}, '')
30
+ Rfsms::BalanceAnswer.new(incorrect_elements)
31
+ end.should raise_error(Rfsms::IncorrectAnswerError)
32
+ lambda do
33
+ incorrect_elements = @correct_body.gsub(%r{<account>.*</account>}, '')
34
+ Rfsms::BalanceAnswer.new(incorrect_elements)
35
+ end.should raise_error(Rfsms::IncorrectAnswerError)
36
+ end
37
+ end
38
+
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe Rfsms::CancelAnswer do
5
+ before(:each) do
6
+ @correct_body = <<-ANSWER
7
+ <data>
8
+ <code>1</code>
9
+ <descr>Операция завершена успешно</descr>
10
+ <action>make</action>
11
+ </data>
12
+ ANSWER
13
+ @correct_elements = Nori.parse(@correct_body, :nokogiri)[:data]
14
+ end
15
+
16
+ describe "конструктор" do
17
+ it "при корректных входных данных создает экземпляр ответа с соответствующими входу полями" do
18
+ cancel_answer = Rfsms::CancelAnswer.new(@correct_body)
19
+ cancel_answer.should be_an_instance_of(Rfsms::CancelAnswer)
20
+ cancel_answer.descr.should be == @correct_elements[:descr]
21
+ cancel_answer.action.should be == @correct_elements[:action]
22
+ end
23
+
24
+ it "при отсутствии одного из входных элементов вызывает исключение Rfsms::IncorrectAnswerError" do
25
+ lambda do
26
+ incorrect_elements = @correct_body.gsub(%r{<code>\d+</code>}, '')
27
+ Rfsms::CancelAnswer.new(incorrect_elements)
28
+ end.should raise_error(Rfsms::IncorrectAnswerError)
29
+ lambda do
30
+ incorrect_elements = @correct_body.gsub(%r{<descr>.+</descr>}, '')
31
+ Rfsms::CancelAnswer.new(incorrect_elements)
32
+ end.should raise_error(Rfsms::IncorrectAnswerError)
33
+ lambda do
34
+ incorrect_elements = @correct_body.gsub(%r{<action>.+</action>}, '')
35
+ Rfsms::CancelAnswer.new(incorrect_elements)
36
+ end.should raise_error(Rfsms::IncorrectAnswerError)
37
+ end
38
+
39
+ it "при значении входного элемента action отличного от make или check вызывает исключение Rfsms::IncorrectAnswerError" do
40
+ lambda do
41
+ Rfsms::CancelAnswer.new(@correct_body.gsub(%r{(?<=<action>).+(?=</action>)}, 'make'))
42
+ end.should_not raise_error(Rfsms::IncorrectAnswerError)
43
+ lambda do
44
+ Rfsms::CancelAnswer.new(@correct_body.gsub(%r{(?<=<action>).+(?=</action>)}, 'check'))
45
+ end.should_not raise_error(Rfsms::IncorrectAnswerError)
46
+ lambda do
47
+ Rfsms::CancelAnswer.new(@correct_body.gsub(%r{(?<=<action>).+(?=</action>)}, 'incorrect'))
48
+ end.should raise_error(Rfsms::IncorrectAnswerError)
49
+ end
50
+ end
51
+ end
52
+
@@ -0,0 +1,83 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe Rfsms::Connection do
5
+ before(:all) do
6
+ @connection = Rfsms::Connection.new('https://transport.rfsms.ru:7214', 'newcom', 'newc0w2m2')
7
+ end
8
+
9
+ describe "Метод send(message, phones)" do
10
+ it "при отправке SMS по списку правильных номеров должен возвращать ответ (Rfsms::Answer)" do
11
+ correct_phones = [PHONE, '8-909-190-9409']
12
+ send_answer = nil
13
+ lambda { send_answer = @connection.send('test', correct_phones) }.should_not raise_error
14
+ send_answer.should be_an_instance_of(Rfsms::SendAnswer)
15
+ end
16
+
17
+ it "должен вызывать исключение AnswerError, если все номера некорректны" do
18
+ incorrect_phones = ['8912383887', '8-909-190-94097']
19
+ lambda { @connection.send('test', incorrect_phones) }.should raise_error Rfsms::AnswerError
20
+ end
21
+
22
+ it "должен возвращать количество отправленных SMS соответствующее количеству корректных номеров" do
23
+ correct_phones = [PHONE, '8-909-190-9409']
24
+ incorrect_phones = ['8912383887', '8-909-190-94097']
25
+ answer = nil
26
+ lambda { answer = @connection.send('test', incorrect_phones.concat(correct_phones)) }.should_not raise_error
27
+ answer.col_send_abonent.should be == 2
28
+ end
29
+ end
30
+
31
+ describe "Метод report(start, stop)" do
32
+ it "должен получать список рассылки за определенный период при корректно указанных датах начала и конца" do
33
+ start = Time.now - 2.hour
34
+ correct_phones = [PHONE]
35
+ @connection.send('test', correct_phones).should be_an_instance_of(Rfsms::SendAnswer)
36
+ stop = Time.now + 2.hour
37
+
38
+ report = @connection.report(:start => start, :stop => stop)
39
+ report.should be_an_instance_of(Rfsms::ReportAnswer)
40
+ report.sms.size.should be > 0
41
+ end
42
+
43
+ it "должен получать список рассылки за весь период при неуказанных дате начала и конца" do
44
+ # TODO: Исключить это дублирование
45
+ # start = Time.now
46
+ # correct_phones = ['89123838878']
47
+ # @connection.send('test', correct_phones)
48
+ # stop = Time.now
49
+ #
50
+ # @connection.send('test2', correct_phones)
51
+ #
52
+ # report_with_period = @connection.report(:start => start, :stop => stop)
53
+ # report_with_period.should be_an_instance_of(Rfsms::ReportAnswer)
54
+ #
55
+ # report = @connection.report
56
+ # report.should be_an_instance_of(Rfsms::ReportAnswer)
57
+ #
58
+ # report.sms.size.should be > report_with_period.sms.size
59
+ end
60
+ end
61
+
62
+ describe "Метод balance()" do
63
+ it "должен возвращать текущее значение баланса типа Float в поле account созданного объекта" do
64
+ balance = nil
65
+ lambda { balance = @connection.balance }.should_not raise_error
66
+ balance.should be_an_instance_of(Rfsms::BalanceAnswer)
67
+ balance.account.should be_an_instance_of(Float)
68
+ end
69
+ end
70
+
71
+ describe "Метод cancel(smsid)" do
72
+ it "должен отменять отложенную SMS (группу SMS) с идентификатором smsid и возвращать Rfsms::CancelAnswer" do
73
+ send_answer = @connection.send(
74
+ "Проверка отмены рассылки",
75
+ [PHONE],
76
+ Time.now + 1.hour
77
+ )
78
+ canceled = @connection.cancel(send_answer.smsid)
79
+ canceled.should be_an_instance_of(Rfsms::CancelAnswer)
80
+ canceled.cancel_col.should be > 0
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,95 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe Rfsms::SendAnswer do
5
+ before(:each) do
6
+ # Элементы ответа от сервера при отправке 2 правильных sms
7
+ @correct_answer_body_for_2sms = <<-ANSWER
8
+ <data>
9
+ <code>1</code>
10
+ <descr>Операция успешно завершена</descr>
11
+ <smsid>un1quine221d</smsid>
12
+ <datetime>#{Time.now.strftime(DATETIME_FORMAT)}</datetime>
13
+ <action>send</action>
14
+ <allRecivers>2</allRecivers>
15
+ <colSendAbonent>2</colSendAbonent>
16
+ <colNonSendAbonent>0</colNonSendAbonent>
17
+ <priceOfSending>0.76</priceOfSending>
18
+ <colsmsOfSending>2</colsmsOfSending>
19
+ <price>0.38</price>
20
+ </data>
21
+ ANSWER
22
+ @correct_answer_elements_for_2sms = Nori.parse(@correct_answer_body_for_2sms, :nokogiri)[:data]
23
+ end
24
+
25
+ describe "конструктор" do
26
+ it "при корректных входных данных должен создавать экземпляр с соответствующими входу полями" do
27
+ send_answer = Rfsms::SendAnswer.new(@correct_answer_body_for_2sms)
28
+ send_answer.should be_an_instance_of(Rfsms::SendAnswer)
29
+ send_answer.descr.should be == @correct_answer_elements_for_2sms[:descr]
30
+ send_answer.smsid.should be == @correct_answer_elements_for_2sms[:smsid]
31
+ send_answer.datetime.should be == DateTime.strptime(@correct_answer_elements_for_2sms[:datetime], DATETIME_FORMAT)
32
+ send_answer.action.should be == @correct_answer_elements_for_2sms[:action]
33
+ send_answer.all_recivers.should be == @correct_answer_elements_for_2sms[:all_recivers].to_i
34
+ send_answer.col_send_abonent.should be == @correct_answer_elements_for_2sms[:col_send_abonent].to_i
35
+ send_answer.col_non_send_abonent.should be == @correct_answer_elements_for_2sms[:col_non_send_abonent].to_i
36
+ send_answer.price_of_sending.should be == @correct_answer_elements_for_2sms[:price_of_sending].to_f
37
+ send_answer.colsms_of_sending.should be == @correct_answer_elements_for_2sms[:colsms_of_sending].to_i
38
+ send_answer.price.should be == @correct_answer_elements_for_2sms[:price].to_f
39
+ end
40
+
41
+ it "при значении элемента code отличного от 1 должен вызывать исключение Rfsms::AnswerError" do
42
+ lambda do
43
+ Rfsms::SendAnswer.new(@correct_answer_body_for_2sms.gsub(%r{(?<=<code>).*(?=</code>)}, '500'))
44
+ end.should raise_error Rfsms::AnswerError
45
+ end
46
+
47
+ it "при отсутствии любого из входных данных должен вызывать исключение Rfsms::IncorrectAnswerError" do
48
+ lambda do
49
+ incorrect_elements = @correct_answer_body_for_2sms.gsub(%r{<code>.*</code>}, '')
50
+ Rfsms::SendAnswer.new(incorrect_elements)
51
+ end.should raise_error(Rfsms::IncorrectAnswerError)
52
+ lambda do
53
+ incorrect_elements = @correct_answer_body_for_2sms.gsub(%r{<descr>.*</descr>}, '')
54
+ Rfsms::SendAnswer.new(incorrect_elements)
55
+ end.should raise_error Rfsms::IncorrectAnswerError
56
+ lambda do
57
+ incorrect_elements = @correct_answer_body_for_2sms.gsub(%r{<smsid>.*</smsid>}, '')
58
+ Rfsms::SendAnswer.new(incorrect_elements)
59
+ end.should raise_error Rfsms::IncorrectAnswerError
60
+ lambda do
61
+ incorrect_elements = @correct_answer_body_for_2sms.gsub(%r{<datetime>.*</datetime>}, '')
62
+ Rfsms::SendAnswer.new(incorrect_elements)
63
+ end.should raise_error Rfsms::IncorrectAnswerError
64
+ lambda do
65
+ incorrect_elements = @correct_answer_body_for_2sms.gsub(%r{<action>.*</action>}, '')
66
+ Rfsms::SendAnswer.new(incorrect_elements)
67
+ end.should raise_error Rfsms::IncorrectAnswerError
68
+ lambda do
69
+ incorrect_elements = @correct_answer_body_for_2sms.gsub(%r{<allRecivers>.*</allRecivers>}, '')
70
+ Rfsms::SendAnswer.new(incorrect_elements)
71
+ end.should raise_error Rfsms::IncorrectAnswerError
72
+ lambda do
73
+ incorrect_elements = @correct_answer_body_for_2sms.gsub(%r{<colSendAbonent>.*</colSendAbonent>}, '')
74
+ Rfsms::SendAnswer.new(incorrect_elements)
75
+ end.should raise_error Rfsms::IncorrectAnswerError
76
+ lambda do
77
+ incorrect_elements = @correct_answer_body_for_2sms.gsub(%r{<colNonSendAbonent>.*</colNonSendAbonent>}, '')
78
+ Rfsms::SendAnswer.new(incorrect_elements)
79
+ end.should raise_error Rfsms::IncorrectAnswerError
80
+ lambda do
81
+ incorrect_elements = @correct_answer_body_for_2sms.gsub(%r{<priceOfSending>.*</priceOfSending>}, '')
82
+ Rfsms::SendAnswer.new(incorrect_elements)
83
+ end.should raise_error Rfsms::IncorrectAnswerError
84
+ lambda do
85
+ incorrect_elements = @correct_answer_body_for_2sms.gsub(%r{<colsmsOfSending>.*</colsmsOfSending>}, '')
86
+ Rfsms::SendAnswer.new(incorrect_elements)
87
+ end.should raise_error Rfsms::IncorrectAnswerError
88
+ lambda do
89
+ incorrect_elements = @correct_answer_body_for_2sms.gsub(%r{<price>.*</price>}, '')
90
+ Rfsms::SendAnswer.new(incorrect_elements)
91
+ end.should raise_error Rfsms::IncorrectAnswerError
92
+ end
93
+ end
94
+ end
95
+
@@ -0,0 +1,5 @@
1
+ require 'rfsms'
2
+
3
+ $DEBUG = true
4
+ DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
5
+ PHONE = '89123123123'
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rfsms
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Danil Korotaev
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-01-11 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: nokogiri
16
+ requirement: &14005300 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 1.5.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *14005300
25
+ - !ruby/object:Gem::Dependency
26
+ name: nori
27
+ requirement: &14001060 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 1.0.2
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *14001060
36
+ - !ruby/object:Gem::Dependency
37
+ name: activesupport
38
+ requirement: &14013340 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: 3.1.1
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *14013340
47
+ description: Sender SMS via rfsms.ru
48
+ email: greyd@mail333.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - Rakefile
54
+ - bin/rspec
55
+ - bin/rackup
56
+ - bin/autospec
57
+ - bin/rake
58
+ - bin/ldiff
59
+ - bin/htmldiff
60
+ - bin/nokogiri
61
+ - lib/rfsms.rb
62
+ - spec/rfsms/answer_spec.rb
63
+ - spec/rfsms/cancel_answer_spec.rb
64
+ - spec/rfsms/send_answer_spec.rb
65
+ - spec/rfsms/balance_answer_spec.rb
66
+ - spec/rfsms/connection_spec.rb
67
+ - spec/spec_helper.rb
68
+ homepage: http://rubygems.org/gems/rfsms
69
+ licenses: []
70
+ post_install_message:
71
+ rdoc_options: []
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ! '>='
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ requirements: []
87
+ rubyforge_project:
88
+ rubygems_version: 1.8.15
89
+ signing_key:
90
+ specification_version: 3
91
+ summary: rfsms is sender SMS via rfsms.ru
92
+ test_files: []
93
+ has_rdoc: