cellular 1.3.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +38 -0
- data/Guardfile +22 -5
- data/README.md +41 -8
- data/cellular.gemspec +1 -1
- data/lib/cellular.rb +2 -0
- data/lib/cellular/backends.rb +1 -0
- data/lib/cellular/backends/backend.rb +13 -0
- data/lib/cellular/backends/cool_sms.rb +40 -12
- data/lib/cellular/backends/log.rb +2 -6
- data/lib/cellular/backends/sendega.rb +58 -34
- data/lib/cellular/backends/test.rb +1 -5
- data/lib/cellular/configuration.rb +6 -0
- data/lib/cellular/jobs/async_messenger.rb +3 -4
- data/lib/cellular/logger.rb +12 -0
- data/lib/cellular/models/sms.rb +8 -13
- data/lib/cellular/version.rb +1 -1
- data/spec/cellular/backends/cool_sms_spec.rb +56 -10
- data/spec/cellular/backends/log_with_rails_spec.rb +47 -0
- data/spec/cellular/backends/sendega_spec.rb +69 -26
- data/spec/cellular/configuration_spec.rb +3 -0
- data/spec/cellular/logger_spec.rb +7 -0
- data/spec/cellular/models/sms_spec.rb +19 -42
- metadata +23 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3fdd4bd856508028b2de1f016627e9a107be0dd4
|
4
|
+
data.tar.gz: a50db77596d53823b496506604356532e9519096
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1670df114c490aae52f7ad804656c4e3d538929f07fa7cbda5121466a4cfe637b3dcec5d39bb5c80e0a575e691842b8734bbe925011195b31a14d97dd4b746b8
|
7
|
+
data.tar.gz: 9403f6ab944a9e0bba7df7b26a0e18c334f8a9bf16635c1cf4835573070aa1161c54814adc84e385fc1bac203097a9afddc0c8a83c36e4ee5e28afcdc0373bbe
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
### Next release
|
4
|
+
|
5
|
+
- Add `SMS#deliver_at` for scheduled delivery through Sidekiq.
|
6
|
+
|
7
|
+
|
8
|
+
### v1.3.0 - November 18, 2014
|
9
|
+
|
10
|
+
- Drop support for Ruby 1.9.
|
11
|
+
- Log and test backends for development purposes.
|
12
|
+
- Add `SMS#deliver_later` for asynchronous delivery through Sidekiq.
|
13
|
+
|
14
|
+
|
15
|
+
### v1.2.0 - March 5, 2014
|
16
|
+
|
17
|
+
- Global configuration for sender, price and country code.
|
18
|
+
|
19
|
+
|
20
|
+
### v1.1.0 - February 28, 2014
|
21
|
+
|
22
|
+
- Drop support for Ruby 1.9.1 and 1.9.2.
|
23
|
+
- CoolSMS backend support.
|
24
|
+
|
25
|
+
|
26
|
+
### v1.0.0 - February 3, 2014
|
27
|
+
|
28
|
+
- Metadata, copyright and license tweaks.
|
29
|
+
|
30
|
+
|
31
|
+
### v0.0.1 - August 27, 2013
|
32
|
+
|
33
|
+
- Initial release with Sendega backend support.
|
34
|
+
|
35
|
+
|
36
|
+
### v0.0.0 - May 8, 2013
|
37
|
+
|
38
|
+
- Placeholder release to secure Ruby gem.
|
data/Guardfile
CHANGED
@@ -1,6 +1,23 @@
|
|
1
|
-
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard :rspec, cmd: 'bundle exec rspec', notification: false do
|
2
5
|
watch(%r{^spec/.+_spec\.rb$})
|
3
|
-
watch(%r{^lib/(.+)\.rb$})
|
4
|
-
watch(
|
5
|
-
|
6
|
-
|
6
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
7
|
+
watch('spec/spec_helper.rb') { "spec" }
|
8
|
+
|
9
|
+
# Rails example
|
10
|
+
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
11
|
+
watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
|
12
|
+
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
|
13
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
14
|
+
watch('config/routes.rb') { "spec/routing" }
|
15
|
+
watch('app/controllers/application_controller.rb') { "spec/controllers" }
|
16
|
+
|
17
|
+
# Capybara features specs
|
18
|
+
watch(%r{^app/views/(.+)/.*\.(erb|haml|slim)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
|
19
|
+
|
20
|
+
# Turnip features and steps
|
21
|
+
watch(%r{^spec/acceptance/(.+)\.feature$})
|
22
|
+
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
|
23
|
+
end
|
data/README.md
CHANGED
@@ -42,6 +42,9 @@ Cellular.configure do |config|
|
|
42
42
|
end
|
43
43
|
```
|
44
44
|
|
45
|
+
Cellular uses Rails' [ActiveJob](http://edgeguides.rubyonrails.org/active_job_basics.html)
|
46
|
+
interface to interact with queue backends. Read appropriate documentation to set up queue.
|
47
|
+
|
45
48
|
|
46
49
|
### Available Backends
|
47
50
|
|
@@ -66,11 +69,26 @@ sms = Cellular::SMS.new(
|
|
66
69
|
|
67
70
|
sms.deliver
|
68
71
|
```
|
72
|
+
For use with multiple recipients in one request use:
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
sms = Cellular::SMS.new(
|
76
|
+
recipients: ['47xxxxxxx1','47xxxxxxx2','47xxxxxxx3'],
|
77
|
+
sender: 'Custom sender',
|
78
|
+
message: 'This is an SMS message',
|
79
|
+
price: 0,
|
80
|
+
country_code: 'NO' # defaults to Cellular.config.country_code
|
81
|
+
)
|
82
|
+
|
83
|
+
sms.deliver
|
84
|
+
```
|
85
|
+
|
69
86
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
87
|
+
#### Delayed SMSs delivery
|
88
|
+
|
89
|
+
You can also send texts asynchronously, which is great if you're in a Rails app
|
90
|
+
and are concerned that it might time out or something. To use it, just call
|
91
|
+
`deliver_async` instead of `deliver` on the SMS object:
|
74
92
|
|
75
93
|
```ruby
|
76
94
|
sms = Cellular::SMS.new(
|
@@ -79,14 +97,29 @@ sms = Cellular::SMS.new(
|
|
79
97
|
message: 'This is an SMS message'
|
80
98
|
)
|
81
99
|
|
82
|
-
sms.
|
100
|
+
sms.deliver_async
|
83
101
|
```
|
84
102
|
|
85
|
-
This will create a
|
86
|
-
that
|
103
|
+
This will create a delayed job for you on the **cellular** queue, so make sure
|
104
|
+
that your queue processor is running.
|
105
|
+
|
106
|
+
To override queue name, use **queue** option
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
sms.deliver_async(queue: :urgent)
|
110
|
+
```
|
111
|
+
Using ActiveJob, Cellular allows you to schedule the time when an SMS will be sent.
|
112
|
+
Just call `deliver_async(wait_until: timestamp)` or `deliver_async(wait: time)` on the SMS object:
|
87
113
|
|
88
|
-
|
114
|
+
```ruby
|
115
|
+
sms = Cellular::SMS.new(
|
116
|
+
recipient: '47xxxxxxxx',
|
117
|
+
sender: 'Custom sender',
|
118
|
+
message: 'This is an SMS message'
|
119
|
+
)
|
89
120
|
|
121
|
+
sms.deliver_async(wait_until: Date.tomorrow.noon)
|
122
|
+
```
|
90
123
|
|
91
124
|
## Contributing
|
92
125
|
|
data/cellular.gemspec
CHANGED
@@ -21,6 +21,7 @@ Gem::Specification.new do |gem|
|
|
21
21
|
|
22
22
|
gem.add_dependency 'httparty', '~> 0.13.0'
|
23
23
|
gem.add_dependency 'savon', '~> 2.0'
|
24
|
+
gem.add_dependency 'rails', '>= 4.2'
|
24
25
|
|
25
26
|
gem.add_development_dependency 'pry', '~> 0.10'
|
26
27
|
|
@@ -29,7 +30,6 @@ Gem::Specification.new do |gem|
|
|
29
30
|
gem.add_development_dependency 'rake', '~> 10.3'
|
30
31
|
gem.add_development_dependency 'webmock', '~> 1.19'
|
31
32
|
|
32
|
-
gem.add_development_dependency 'sidekiq', '~> 3.2'
|
33
33
|
gem.add_development_dependency 'rspec-rails', '~> 2.99'
|
34
34
|
|
35
35
|
gem.add_development_dependency 'coveralls', '~> 0.7'
|
data/lib/cellular.rb
CHANGED
data/lib/cellular/backends.rb
CHANGED
@@ -2,30 +2,58 @@ require 'httparty'
|
|
2
2
|
|
3
3
|
module Cellular
|
4
4
|
module Backends
|
5
|
-
class CoolSMS
|
5
|
+
class CoolSMS < Backend
|
6
6
|
|
7
7
|
# Documentation: http://www.coolsms.com/support/dokumentation/http-gateway.sms
|
8
8
|
GATEWAY_URL = 'https://sms.coolsmsc.dk/'
|
9
9
|
|
10
10
|
def self.deliver(options = {})
|
11
|
-
|
11
|
+
request_queue = {}
|
12
|
+
|
13
|
+
recipients_batch(options).each_with_index do |recipient, index|
|
14
|
+
options[:batch] = recipient
|
15
|
+
result = HTTParty.get(GATEWAY_URL, query: defaults_with(options) )
|
16
|
+
request_queue[index] = {
|
17
|
+
recipient: recipient,
|
18
|
+
response: parse_response(result.parsed_response['smsc'])
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
# return first response for now
|
23
|
+
request_queue[0][:response]
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.parse_response(response)
|
27
|
+
[
|
28
|
+
response['status'],
|
29
|
+
response['result'] || response['message']['result']
|
30
|
+
]
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.coolsms_config
|
34
|
+
{
|
12
35
|
username: Cellular.config.username,
|
13
|
-
password: Cellular.config.password
|
36
|
+
password: Cellular.config.password
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.defaults_with(options)
|
41
|
+
{
|
14
42
|
from: options[:sender],
|
15
|
-
to: options[:
|
43
|
+
to: options[:batch],
|
16
44
|
message: options[:message],
|
17
45
|
charset: 'utf-8',
|
18
46
|
resulttype: 'xml',
|
19
47
|
lang: 'en'
|
20
|
-
}
|
21
|
-
|
22
|
-
result = HTTParty.get(GATEWAY_URL, query: query)
|
23
|
-
response = result.parsed_response['smsc']
|
48
|
+
}.merge!(coolsms_config)
|
49
|
+
end
|
24
50
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
51
|
+
def self.recipients_batch(options)
|
52
|
+
if options[:recipients].blank?
|
53
|
+
[options[:recipient]]
|
54
|
+
else
|
55
|
+
options[:recipients]
|
56
|
+
end
|
29
57
|
end
|
30
58
|
|
31
59
|
end
|
@@ -1,12 +1,8 @@
|
|
1
1
|
module Cellular
|
2
2
|
module Backends
|
3
|
-
class Log
|
3
|
+
class Log < Backend
|
4
4
|
def self.deliver(options = {})
|
5
|
-
|
6
|
-
end
|
7
|
-
|
8
|
-
def self.receive(data)
|
9
|
-
raise NotImplementedError
|
5
|
+
Cellular.config.logger.info options[:message]
|
10
6
|
end
|
11
7
|
end
|
12
8
|
end
|
@@ -2,7 +2,7 @@ require 'savon'
|
|
2
2
|
|
3
3
|
module Cellular
|
4
4
|
module Backends
|
5
|
-
class Sendega
|
5
|
+
class Sendega < Backend
|
6
6
|
|
7
7
|
GATEWAY_URL = 'https://smsc.sendega.com/Content.asmx?WSDL'
|
8
8
|
|
@@ -35,49 +35,73 @@ module Cellular
|
|
35
35
|
# http://controlpanel.sendega.no/Content/Sendega%20-%20API%20documentation%20v2.3.pdf
|
36
36
|
|
37
37
|
savon_options[:wsdl] = GATEWAY_URL
|
38
|
-
|
38
|
+
request_queue = {}
|
39
39
|
client = Savon.client savon_options
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
sender: options[:sender],
|
45
|
-
destination: options[:recipient],
|
46
|
-
pricegroup: options[:price] || 0, # default price to 0
|
47
|
-
contentTypeID: 1,
|
48
|
-
contentHeader: '',
|
49
|
-
content: options[:message],
|
50
|
-
dlrUrl: Cellular.config.delivery_url,
|
51
|
-
ageLimit: 0,
|
52
|
-
extID: '',
|
53
|
-
sendDate: '',
|
54
|
-
refID: '',
|
55
|
-
priority: 0,
|
56
|
-
gwID: 0,
|
57
|
-
pid: 0,
|
58
|
-
dcs: 0
|
59
|
-
}
|
60
|
-
)
|
61
|
-
|
62
|
-
body = result.body[:send_response][:send_result]
|
41
|
+
recipients_batch(options).each_with_index do |batch, index|
|
42
|
+
options[:batch] = batch
|
43
|
+
result = client.call(:send, message: defaults_with(options))
|
63
44
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
[
|
71
|
-
body[:error_number].to_i,
|
72
|
-
body[:error_message]
|
73
|
-
]
|
45
|
+
request_queue[index] = {
|
46
|
+
batch: batch,
|
47
|
+
result: result,
|
48
|
+
body:result.body[:send_response][:send_result],
|
49
|
+
response: map_response(result.body[:send_response][:send_result])
|
50
|
+
}
|
74
51
|
end
|
52
|
+
|
53
|
+
# for now just resturn first response
|
54
|
+
request_queue[0][:response]
|
75
55
|
end
|
76
56
|
|
77
57
|
def self.receive(data)
|
78
58
|
raise NotImplementedError
|
79
59
|
end
|
80
60
|
|
61
|
+
def self.savon_config
|
62
|
+
{
|
63
|
+
username: Cellular.config.username,
|
64
|
+
password: Cellular.config.password,
|
65
|
+
dlrUrl: Cellular.config.delivery_url
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.defaults_with(options)
|
70
|
+
{
|
71
|
+
sender: options[:sender],
|
72
|
+
destination: options[:batch],
|
73
|
+
pricegroup: options[:price] || 0, # default price to 0
|
74
|
+
contentTypeID: 1,
|
75
|
+
contentHeader: '',
|
76
|
+
content: options[:message],
|
77
|
+
ageLimit: 0,
|
78
|
+
extID: '',
|
79
|
+
sendDate: '',
|
80
|
+
refID: '',
|
81
|
+
priority: 0,
|
82
|
+
gwID: 0,
|
83
|
+
pid: 0,
|
84
|
+
dcs: 0
|
85
|
+
}.merge!(savon_config)
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.map_response(_body)
|
89
|
+
msg = _body[:success] ? success_message : _body[:error_message]
|
90
|
+
[ _body[:error_number].to_i, msg ]
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.success_message
|
94
|
+
'Message is received and is being processed.'
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.recipients_batch(options)
|
98
|
+
if options[:recipients].blank?
|
99
|
+
[options[:recipient]]
|
100
|
+
else
|
101
|
+
options[:recipients].each_slice(100).to_a.map{|x| x.join(',') }
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
81
105
|
end
|
82
106
|
end
|
83
107
|
end
|
@@ -4,6 +4,12 @@ module Cellular
|
|
4
4
|
attr_accessor :username, :password, :delivery_url, :backend
|
5
5
|
|
6
6
|
attr_accessor :country_code, :price, :sender
|
7
|
+
|
8
|
+
attr_accessor :logger
|
9
|
+
|
10
|
+
def logger
|
11
|
+
@logger ||= Object.const_defined?(:Rails) ? Rails.logger : Logger.new
|
12
|
+
end
|
7
13
|
|
8
14
|
end
|
9
15
|
end
|
@@ -1,7 +1,7 @@
|
|
1
|
-
|
2
|
-
include Sidekiq::Worker
|
1
|
+
require 'active_job'
|
3
2
|
|
4
|
-
|
3
|
+
class Cellular::Jobs::AsyncMessenger < ActiveJob::Base
|
4
|
+
queue_as :cellular
|
5
5
|
|
6
6
|
def perform(sms_options)
|
7
7
|
sms_options.keys.each do |key|
|
@@ -11,5 +11,4 @@ class Cellular::Jobs::AsyncMessenger
|
|
11
11
|
sms = Cellular::SMS.new sms_options
|
12
12
|
sms.deliver
|
13
13
|
end
|
14
|
-
|
15
14
|
end
|
data/lib/cellular/models/sms.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
|
+
require 'active_support/time'
|
2
|
+
|
1
3
|
module Cellular
|
2
4
|
class SMS
|
3
5
|
|
4
6
|
attr_accessor :recipient, :sender, :message, :price, :country_code
|
5
|
-
|
7
|
+
attr_accessor :recipients
|
6
8
|
def initialize(options = {})
|
7
9
|
@backend = Cellular.config.backend
|
8
10
|
|
11
|
+
@recipients = options[:recipients]
|
9
12
|
@recipient = options[:recipient]
|
10
13
|
@sender = options[:sender] || Cellular.config.sender
|
11
14
|
@message = options[:message]
|
@@ -20,9 +23,10 @@ module Cellular
|
|
20
23
|
@delivered = true
|
21
24
|
end
|
22
25
|
|
23
|
-
def
|
24
|
-
Cellular::Jobs::AsyncMessenger.
|
26
|
+
def deliver_async(delivery_options = {})
|
27
|
+
Cellular::Jobs::AsyncMessenger.set(delivery_options).perform_later(options)
|
25
28
|
end
|
29
|
+
alias_method :deliver_later, :deliver_async
|
26
30
|
|
27
31
|
def save(options = {})
|
28
32
|
raise NotImplementedError
|
@@ -35,21 +39,12 @@ module Cellular
|
|
35
39
|
def delivered?
|
36
40
|
@delivered
|
37
41
|
end
|
38
|
-
|
39
|
-
def country
|
40
|
-
warn "[DEPRECATION] 'country' is deprecated; use 'country_code' instead"
|
41
|
-
@country_code
|
42
|
-
end
|
43
|
-
|
44
|
-
def country=(country)
|
45
|
-
warn "[DEPRECATION] 'country' is deprecated; use 'country_code' instead"
|
46
|
-
@country_code = country
|
47
|
-
end
|
48
42
|
|
49
43
|
private
|
50
44
|
|
51
45
|
def options
|
52
46
|
{
|
47
|
+
recipients: @recipients,
|
53
48
|
recipient: @recipient,
|
54
49
|
sender: @sender,
|
55
50
|
message: @message,
|
data/lib/cellular/version.rb
CHANGED
@@ -14,6 +14,19 @@ describe Cellular::Backends::CoolSMS do
|
|
14
14
|
}
|
15
15
|
}
|
16
16
|
|
17
|
+
let(:payload) {
|
18
|
+
{
|
19
|
+
username: 'username',
|
20
|
+
password: 'password',
|
21
|
+
from: sender,
|
22
|
+
to: recipient,
|
23
|
+
message: message,
|
24
|
+
charset: 'utf-8',
|
25
|
+
resulttype: 'xml',
|
26
|
+
lang: 'en'
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
17
30
|
before do
|
18
31
|
Cellular.config.username = 'username'
|
19
32
|
Cellular.config.password = 'password'
|
@@ -26,16 +39,8 @@ describe Cellular::Backends::CoolSMS do
|
|
26
39
|
end
|
27
40
|
|
28
41
|
it 'uses HTTParty to deliver an SMS' do
|
29
|
-
expect(HTTParty).to receive(:get).with(described_class::GATEWAY_URL, query:
|
30
|
-
|
31
|
-
password: 'password',
|
32
|
-
from: sender,
|
33
|
-
to: recipient,
|
34
|
-
message: message,
|
35
|
-
charset: 'utf-8',
|
36
|
-
resulttype: 'xml',
|
37
|
-
lang: 'en'
|
38
|
-
}).and_call_original
|
42
|
+
expect(HTTParty).to receive(:get).with(described_class::GATEWAY_URL, query:
|
43
|
+
payload).and_call_original
|
39
44
|
|
40
45
|
described_class.deliver(options)
|
41
46
|
end
|
@@ -64,4 +69,45 @@ describe Cellular::Backends::CoolSMS do
|
|
64
69
|
end
|
65
70
|
end
|
66
71
|
|
72
|
+
describe '::parse_response' do
|
73
|
+
it 'should return the correct response' do
|
74
|
+
message = ['success', 'The message was sent correctly.']
|
75
|
+
|
76
|
+
check = { 'status' => message[0], 'result' => message[1] }
|
77
|
+
second_check = { 'status' => message[0],
|
78
|
+
'message' => { 'result' => message[1] } }
|
79
|
+
|
80
|
+
expect(described_class.parse_response(check)).to eq(message)
|
81
|
+
expect(described_class.parse_response(second_check)).to eq(message)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe '::coolsms_config' do
|
86
|
+
it 'should return the config for coolsms' do
|
87
|
+
expect(described_class.coolsms_config).to eq(
|
88
|
+
{
|
89
|
+
username: Cellular.config.username,
|
90
|
+
password: Cellular.config.password
|
91
|
+
})
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe '::defaults_with' do
|
96
|
+
it 'should return the whole query' do
|
97
|
+
options[:batch] = recipient
|
98
|
+
expect(described_class.defaults_with(options)).to eq(payload)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe '::recipients_batch' do
|
103
|
+
it 'should wrap recipient option into a array' do
|
104
|
+
expect(described_class.recipients_batch({recipient: recipient}))
|
105
|
+
.to eq([recipient])
|
106
|
+
end
|
107
|
+
it 'should return recipients option as it is' do
|
108
|
+
expect(described_class.recipients_batch({recipients: [recipient,recipient]}))
|
109
|
+
.to eq([recipient,recipient])
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
67
113
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cellular::Backends::Log do
|
4
|
+
|
5
|
+
let(:recipient) { '47xxxxxxxx' }
|
6
|
+
let(:sender) { 'Custom sender' }
|
7
|
+
let(:message) { 'This is an SMS message' }
|
8
|
+
let(:price) { 100 }
|
9
|
+
let(:country) { 'NO '}
|
10
|
+
|
11
|
+
let(:options) {
|
12
|
+
{
|
13
|
+
recipient: recipient,
|
14
|
+
sender: sender,
|
15
|
+
message: message,
|
16
|
+
price: price
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
before do
|
21
|
+
# mock rails, we're pretending we're in a rails env
|
22
|
+
rails = Class.new
|
23
|
+
def rails.logger
|
24
|
+
@logger ||= Cellular::Logger.new
|
25
|
+
end
|
26
|
+
Object.const_set(:Rails, rails)
|
27
|
+
|
28
|
+
Cellular.config.username = 'username'
|
29
|
+
Cellular.config.password = 'password'
|
30
|
+
Cellular.config.delivery_url = nil
|
31
|
+
Cellular.config.logger = nil # so it will autowire
|
32
|
+
end
|
33
|
+
|
34
|
+
after do
|
35
|
+
Object.send :remove_const, :Rails
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '::deliver' do
|
39
|
+
let(:deliveries) { Cellular.deliveries }
|
40
|
+
|
41
|
+
it 'logs the message' do
|
42
|
+
expect(Rails.logger).to receive(:info)
|
43
|
+
described_class.deliver(options)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -2,13 +2,13 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Cellular::Backends::Sendega do
|
4
4
|
|
5
|
-
let(:recipient)
|
6
|
-
let(:sender)
|
7
|
-
let(:message)
|
8
|
-
let(:price)
|
9
|
-
let(:country)
|
10
|
-
|
11
|
-
let(:options)
|
5
|
+
let(:recipient) { '47xxxxxxxx' }
|
6
|
+
let(:sender) { 'Custom sender' }
|
7
|
+
let(:message) { 'This is an SMS message' }
|
8
|
+
let(:price) { 100 }
|
9
|
+
let(:country) { 'NO '}
|
10
|
+
let(:recipients) { (1..300).to_a.map!{|n| "47xxxxxxx#{n}"} }
|
11
|
+
let(:options) {
|
12
12
|
{
|
13
13
|
recipient: recipient,
|
14
14
|
sender: sender,
|
@@ -22,6 +22,28 @@ describe Cellular::Backends::Sendega do
|
|
22
22
|
}
|
23
23
|
}
|
24
24
|
|
25
|
+
let(:payload) {
|
26
|
+
{
|
27
|
+
username: Cellular.config.username,
|
28
|
+
password: Cellular.config.password,
|
29
|
+
sender: sender,
|
30
|
+
destination: recipient,
|
31
|
+
pricegroup: price,
|
32
|
+
contentTypeID: 1,
|
33
|
+
contentHeader: '',
|
34
|
+
content: message,
|
35
|
+
dlrUrl: nil,
|
36
|
+
ageLimit: 0,
|
37
|
+
extID: '',
|
38
|
+
sendDate: '',
|
39
|
+
refID: '',
|
40
|
+
priority: 0,
|
41
|
+
gwID: 0,
|
42
|
+
pid: 0,
|
43
|
+
dcs: 0
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
25
47
|
before do
|
26
48
|
stub_request(:get, described_class::GATEWAY_URL).
|
27
49
|
to_return body: fixture('backends/sendega/service.wsdl')
|
@@ -38,25 +60,8 @@ describe Cellular::Backends::Sendega do
|
|
38
60
|
|
39
61
|
result = double(body: {send_response: {send_result: {}}})
|
40
62
|
|
41
|
-
expect(client).to receive(:call).with(:send, message:
|
42
|
-
|
43
|
-
password: Cellular.config.password,
|
44
|
-
sender: sender,
|
45
|
-
destination: recipient,
|
46
|
-
pricegroup: price,
|
47
|
-
contentTypeID: 1,
|
48
|
-
contentHeader: '',
|
49
|
-
content: message,
|
50
|
-
dlrUrl: nil,
|
51
|
-
ageLimit: 0,
|
52
|
-
extID: '',
|
53
|
-
sendDate: '',
|
54
|
-
refID: '',
|
55
|
-
priority: 0,
|
56
|
-
gwID: 0,
|
57
|
-
pid: 0,
|
58
|
-
dcs: 0
|
59
|
-
}).and_return result
|
63
|
+
expect(client).to receive(:call).with(:send, message:
|
64
|
+
payload).and_return result
|
60
65
|
|
61
66
|
described_class.deliver(options, savon_options)
|
62
67
|
end
|
@@ -98,4 +103,42 @@ describe Cellular::Backends::Sendega do
|
|
98
103
|
end
|
99
104
|
end
|
100
105
|
|
106
|
+
describe '::success_message' do
|
107
|
+
it 'should return this message' do
|
108
|
+
expect(
|
109
|
+
described_class.success_message)
|
110
|
+
.to eq 'Message is received and is being processed.'
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
describe '::defaults_with' do
|
116
|
+
it 'should return the whole payload' do
|
117
|
+
options[:batch] = recipient
|
118
|
+
expect(described_class.defaults_with(options)).to eq(payload)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
describe '::savon_config' do
|
123
|
+
it 'should return a hash with config' do
|
124
|
+
expect(described_class.savon_config)
|
125
|
+
.to eq({
|
126
|
+
username: Cellular.config.username,
|
127
|
+
password: Cellular.config.password,
|
128
|
+
dlrUrl: Cellular.config.delivery_url
|
129
|
+
})
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe '::recipients_batch' do
|
134
|
+
it 'should split recipients into arrays of 100 then join them with ,' do
|
135
|
+
check = described_class.recipients_batch({recipients:recipients}).length
|
136
|
+
expect(check).to eq 3
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'should put recipient into one array' do
|
140
|
+
check = described_class.recipients_batch({receipient:recipient}).length
|
141
|
+
expect(check).to eq 1
|
142
|
+
end
|
143
|
+
end
|
101
144
|
end
|
@@ -7,9 +7,11 @@ describe Cellular::SMS do
|
|
7
7
|
let(:message) { 'This is an SMS message' }
|
8
8
|
let(:price) { 100 }
|
9
9
|
let(:country_code) { 'NO'}
|
10
|
+
let(:recipients) { nil }
|
10
11
|
|
11
12
|
subject do
|
12
13
|
described_class.new(
|
14
|
+
recipients: recipients,
|
13
15
|
recipient: recipient,
|
14
16
|
sender: sender,
|
15
17
|
message: message,
|
@@ -23,11 +25,11 @@ describe Cellular::SMS do
|
|
23
25
|
end
|
24
26
|
|
25
27
|
describe '#initialize' do
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
it{ expect(subject.recipient).to eq recipient }
|
29
|
+
it{ expect(subject.sender).to eq sender }
|
30
|
+
it{ expect(subject.message).to eq message }
|
31
|
+
it{ expect(subject.price).to eq price }
|
32
|
+
it{ expect(subject.country_code).to eq country_code }
|
31
33
|
|
32
34
|
it { should_not be_delivered }
|
33
35
|
|
@@ -37,8 +39,7 @@ describe Cellular::SMS do
|
|
37
39
|
end
|
38
40
|
|
39
41
|
subject { described_class.new }
|
40
|
-
|
41
|
-
its(:sender) { should eq 'Hyper' }
|
42
|
+
it{ expect(subject.sender).to eq 'Hyper' }
|
42
43
|
end
|
43
44
|
|
44
45
|
context 'when price omitted' do
|
@@ -48,7 +49,7 @@ describe Cellular::SMS do
|
|
48
49
|
|
49
50
|
subject { described_class.new }
|
50
51
|
|
51
|
-
|
52
|
+
it{ expect(subject.price).to be 5 }
|
52
53
|
end
|
53
54
|
|
54
55
|
context 'when country omitted' do
|
@@ -57,14 +58,14 @@ describe Cellular::SMS do
|
|
57
58
|
end
|
58
59
|
|
59
60
|
subject { described_class.new }
|
60
|
-
|
61
|
-
its(:country_code) { should eq 'NL' }
|
61
|
+
it{ expect(subject.country_code).to eq 'NL'}
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
65
|
describe '#deliver' do
|
66
66
|
before do
|
67
67
|
expect(Cellular::Backends::Sendega).to receive(:deliver).with(
|
68
|
+
recipients: recipients,
|
68
69
|
recipient: recipient,
|
69
70
|
sender: sender,
|
70
71
|
price: price,
|
@@ -79,22 +80,24 @@ describe Cellular::SMS do
|
|
79
80
|
end
|
80
81
|
end
|
81
82
|
|
82
|
-
describe "#
|
83
|
-
it "
|
83
|
+
describe "#deliver_async" do
|
84
|
+
it "makes ActiveJob schedule an SMS job" do
|
84
85
|
sms_options = {
|
85
86
|
receiver: "12345678",
|
86
87
|
message: "Test SMS"
|
87
88
|
}
|
89
|
+
wait = 100
|
88
90
|
|
89
|
-
|
90
|
-
.to receive(:
|
91
|
-
.with
|
91
|
+
expect_any_instance_of(ActiveJob::ConfiguredJob)
|
92
|
+
.to receive(:perform_later)
|
93
|
+
.with(sms_options)
|
92
94
|
|
93
95
|
sms = Cellular::SMS.new sms_options
|
94
96
|
|
97
|
+
allow(ActiveJob::Base).to receive(:queue_adapter).and_return ActiveJob::QueueAdapters::TestAdapter.new
|
95
98
|
allow(sms).to receive(:options).and_return sms_options
|
96
99
|
|
97
|
-
sms.
|
100
|
+
sms.deliver_async(wait: wait)
|
98
101
|
end
|
99
102
|
end
|
100
103
|
|
@@ -113,30 +116,4 @@ describe Cellular::SMS do
|
|
113
116
|
end.to raise_error NotImplementedError
|
114
117
|
end
|
115
118
|
end
|
116
|
-
|
117
|
-
describe '#country' do
|
118
|
-
it 'issues a deprecation warning' do
|
119
|
-
expect(subject).to receive(:warn)
|
120
|
-
subject.country
|
121
|
-
end
|
122
|
-
|
123
|
-
it 'returns country_code' do
|
124
|
-
allow(subject).to receive(:warn)
|
125
|
-
expect(subject.country).to eq(subject.country_code)
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
describe '#country=' do
|
130
|
-
it 'issues a deprecation warning' do
|
131
|
-
expect(subject).to receive(:warn)
|
132
|
-
subject.country = 'Test'
|
133
|
-
end
|
134
|
-
|
135
|
-
it 'assigns country_code' do
|
136
|
-
allow(subject).to receive(:warn)
|
137
|
-
subject.country = 'Test'
|
138
|
-
expect(subject.country_code).to eq('Test')
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
119
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cellular
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sindre Moen
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2015-03-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: httparty
|
@@ -39,6 +39,20 @@ dependencies:
|
|
39
39
|
- - "~>"
|
40
40
|
- !ruby/object:Gem::Version
|
41
41
|
version: '2.0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rails
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '4.2'
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '4.2'
|
42
56
|
- !ruby/object:Gem::Dependency
|
43
57
|
name: pry
|
44
58
|
requirement: !ruby/object:Gem::Requirement
|
@@ -109,20 +123,6 @@ dependencies:
|
|
109
123
|
- - "~>"
|
110
124
|
- !ruby/object:Gem::Version
|
111
125
|
version: '1.19'
|
112
|
-
- !ruby/object:Gem::Dependency
|
113
|
-
name: sidekiq
|
114
|
-
requirement: !ruby/object:Gem::Requirement
|
115
|
-
requirements:
|
116
|
-
- - "~>"
|
117
|
-
- !ruby/object:Gem::Version
|
118
|
-
version: '3.2'
|
119
|
-
type: :development
|
120
|
-
prerelease: false
|
121
|
-
version_requirements: !ruby/object:Gem::Requirement
|
122
|
-
requirements:
|
123
|
-
- - "~>"
|
124
|
-
- !ruby/object:Gem::Version
|
125
|
-
version: '3.2'
|
126
126
|
- !ruby/object:Gem::Dependency
|
127
127
|
name: rspec-rails
|
128
128
|
requirement: !ruby/object:Gem::Requirement
|
@@ -174,6 +174,7 @@ extra_rdoc_files: []
|
|
174
174
|
files:
|
175
175
|
- ".gitignore"
|
176
176
|
- ".travis.yml"
|
177
|
+
- CHANGELOG.md
|
177
178
|
- Gemfile
|
178
179
|
- Guardfile
|
179
180
|
- LICENSE.md
|
@@ -182,6 +183,7 @@ files:
|
|
182
183
|
- cellular.gemspec
|
183
184
|
- lib/cellular.rb
|
184
185
|
- lib/cellular/backends.rb
|
186
|
+
- lib/cellular/backends/backend.rb
|
185
187
|
- lib/cellular/backends/cool_sms.rb
|
186
188
|
- lib/cellular/backends/log.rb
|
187
189
|
- lib/cellular/backends/sendega.rb
|
@@ -189,14 +191,17 @@ files:
|
|
189
191
|
- lib/cellular/configuration.rb
|
190
192
|
- lib/cellular/jobs.rb
|
191
193
|
- lib/cellular/jobs/async_messenger.rb
|
194
|
+
- lib/cellular/logger.rb
|
192
195
|
- lib/cellular/models/sms.rb
|
193
196
|
- lib/cellular/version.rb
|
194
197
|
- spec/cellular/backends/cool_sms_spec.rb
|
195
198
|
- spec/cellular/backends/log_spec.rb
|
199
|
+
- spec/cellular/backends/log_with_rails_spec.rb
|
196
200
|
- spec/cellular/backends/sendega_spec.rb
|
197
201
|
- spec/cellular/backends/test_spec.rb
|
198
202
|
- spec/cellular/configuration_spec.rb
|
199
203
|
- spec/cellular/jobs/async_messenger_spec.rb
|
204
|
+
- spec/cellular/logger_spec.rb
|
200
205
|
- spec/cellular/models/sms_spec.rb
|
201
206
|
- spec/cellular_spec.rb
|
202
207
|
- spec/fixtures/backends/cool_sms/failure.xml
|
@@ -232,10 +237,12 @@ summary: Sending and receiving SMSs through pluggable backends
|
|
232
237
|
test_files:
|
233
238
|
- spec/cellular/backends/cool_sms_spec.rb
|
234
239
|
- spec/cellular/backends/log_spec.rb
|
240
|
+
- spec/cellular/backends/log_with_rails_spec.rb
|
235
241
|
- spec/cellular/backends/sendega_spec.rb
|
236
242
|
- spec/cellular/backends/test_spec.rb
|
237
243
|
- spec/cellular/configuration_spec.rb
|
238
244
|
- spec/cellular/jobs/async_messenger_spec.rb
|
245
|
+
- spec/cellular/logger_spec.rb
|
239
246
|
- spec/cellular/models/sms_spec.rb
|
240
247
|
- spec/cellular_spec.rb
|
241
248
|
- spec/fixtures/backends/cool_sms/failure.xml
|