rfsms 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: