cellular 2.1.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +0 -2
- data/cellular.gemspec +5 -5
- data/lib/cellular.rb +1 -1
- data/lib/cellular/backends.rb +5 -3
- data/lib/cellular/backends/backend.rb +3 -2
- data/lib/cellular/backends/cool_sms.rb +3 -4
- data/lib/cellular/backends/link_mobility.rb +72 -0
- data/lib/cellular/backends/log.rb +1 -0
- data/lib/cellular/backends/sendega.rb +12 -13
- data/lib/cellular/backends/test.rb +1 -0
- data/lib/cellular/backends/twilio.rb +4 -4
- data/lib/cellular/configuration.rb +3 -6
- data/lib/cellular/jobs.rb +2 -1
- data/lib/cellular/jobs/async_messenger.rb +1 -0
- data/lib/cellular/logger.rb +2 -5
- data/lib/cellular/models/sms.rb +7 -5
- data/lib/cellular/version.rb +1 -1
- data/spec/cellular/backends/backend_spec.rb +19 -0
- data/spec/cellular/backends/cool_sms_spec.rb +31 -27
- data/spec/cellular/backends/link_mobility_spec.rb +118 -0
- data/spec/cellular/backends/log_spec.rb +3 -5
- data/spec/cellular/backends/log_with_rails_spec.rb +5 -7
- data/spec/cellular/backends/sendega_spec.rb +35 -37
- data/spec/cellular/backends/test_spec.rb +1 -12
- data/spec/cellular/backends/twilio_spec.rb +47 -42
- data/spec/cellular/configuration_spec.rb +1 -3
- data/spec/cellular/jobs/async_messenger_spec.rb +4 -4
- data/spec/cellular/logger_spec.rb +0 -2
- data/spec/cellular/models/sms_spec.rb +15 -15
- data/spec/cellular_spec.rb +0 -2
- data/spec/fixtures/backends/link_mobility/failure.json +1 -0
- data/spec/fixtures/backends/link_mobility/success.json +1 -0
- data/spec/spec_helper.rb +0 -2
- metadata +17 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 798ef5b207911f8698d8199cc06900afd9304152
|
4
|
+
data.tar.gz: 4854425f3b5a9348c2e42f1786991a4887c3f0a5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c902309c6f7ec95b0bc5dd478f87fbcceb8cce9a8046e79a1318ee757d978cd19d47e54507eca6bebcf420c98f31ad16756f4da602674133ab2de041ff981ea8
|
7
|
+
data.tar.gz: bb89b59775574a107503149b0a0a089d493b7157e77050a41f4413b232ab0c8867c1b3bcdeee5884b49b9be64ff3cbc8c6a4198cab0d30d28f4085d97259c0ed
|
data/.travis.yml
CHANGED
data/cellular.gemspec
CHANGED
@@ -10,18 +10,18 @@ Gem::Specification.new do |gem|
|
|
10
10
|
gem.version = Cellular::VERSION
|
11
11
|
gem.authors = ['Sindre Moen', 'Tim Kurvers']
|
12
12
|
gem.email = ['ruby@hyper.no']
|
13
|
-
gem.description =
|
14
|
-
gem.summary =
|
13
|
+
gem.description = 'Sending and receiving SMSs through pluggable backends'
|
14
|
+
gem.summary = 'Sending and receiving SMSs through pluggable backends'
|
15
15
|
gem.homepage = ''
|
16
16
|
|
17
17
|
gem.files = `git ls-files`.split($/)
|
18
|
-
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
18
|
+
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
19
19
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
20
20
|
gem.require_paths = ['lib']
|
21
21
|
|
22
|
-
gem.add_dependency 'httparty', '~> 0.13
|
22
|
+
gem.add_dependency 'httparty', '~> 0.13'
|
23
23
|
gem.add_dependency 'savon', '~> 2.0'
|
24
|
-
gem.add_dependency 'rails', '
|
24
|
+
gem.add_dependency 'rails', '~> 4.2'
|
25
25
|
|
26
26
|
gem.add_development_dependency 'pry', '~> 0.10'
|
27
27
|
|
data/lib/cellular.rb
CHANGED
@@ -4,6 +4,7 @@ require 'cellular/models/sms'
|
|
4
4
|
require 'cellular/backends'
|
5
5
|
require 'cellular/jobs'
|
6
6
|
|
7
|
+
# Sending and receiving SMSs through pluggable backends
|
7
8
|
module Cellular
|
8
9
|
autoload :Logger, 'cellular/logger'
|
9
10
|
|
@@ -21,5 +22,4 @@ module Cellular
|
|
21
22
|
@config ||= Configuration.new
|
22
23
|
end
|
23
24
|
end
|
24
|
-
|
25
25
|
end
|
data/lib/cellular/backends.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
module Cellular
|
2
|
+
# Encapsulates all available backends for Cellular
|
2
3
|
module Backends
|
3
4
|
autoload :Backend, 'cellular/backends/backend'
|
4
5
|
autoload :CoolSMS, 'cellular/backends/cool_sms'
|
5
6
|
autoload :Sendega, 'cellular/backends/sendega'
|
6
|
-
autoload :Twilio,
|
7
|
-
autoload :
|
8
|
-
autoload :
|
7
|
+
autoload :Twilio, 'cellular/backends/twilio'
|
8
|
+
autoload :LinkMobility, 'cellular/backends/link_mobility'
|
9
|
+
autoload :Log, 'cellular/backends/log'
|
10
|
+
autoload :Test, 'cellular/backends/test'
|
9
11
|
end
|
10
12
|
end
|
@@ -1,11 +1,12 @@
|
|
1
1
|
module Cellular
|
2
2
|
module Backends
|
3
|
+
# Base class for a Cellular backend
|
3
4
|
class Backend
|
4
|
-
def self.deliver(
|
5
|
+
def self.deliver(_options = {})
|
5
6
|
raise NotImplementedError
|
6
7
|
end
|
7
8
|
|
8
|
-
def self.receive(
|
9
|
+
def self.receive(_data)
|
9
10
|
raise NotImplementedError
|
10
11
|
end
|
11
12
|
end
|
@@ -2,17 +2,17 @@ require 'httparty'
|
|
2
2
|
|
3
3
|
module Cellular
|
4
4
|
module Backends
|
5
|
+
# Cool SMS backend (http://www.coolsms.com)
|
5
6
|
class CoolSMS < Backend
|
6
|
-
|
7
7
|
# Documentation: http://www.coolsms.com/support/dokumentation/http-gateway.sms
|
8
|
-
GATEWAY_URL = 'https://sms.coolsmsc.dk/'
|
8
|
+
GATEWAY_URL = 'https://sms.coolsmsc.dk/'.freeze
|
9
9
|
|
10
10
|
def self.deliver(options = {})
|
11
11
|
request_queue = {}
|
12
12
|
|
13
13
|
recipients_batch(options).each_with_index do |recipient, index|
|
14
14
|
options[:batch] = recipient
|
15
|
-
result = HTTParty.get(GATEWAY_URL, query: defaults_with(options)
|
15
|
+
result = HTTParty.get(GATEWAY_URL, query: defaults_with(options))
|
16
16
|
request_queue[index] = {
|
17
17
|
recipient: recipient,
|
18
18
|
response: parse_response(result.parsed_response['smsc'])
|
@@ -55,7 +55,6 @@ module Cellular
|
|
55
55
|
options[:recipients]
|
56
56
|
end
|
57
57
|
end
|
58
|
-
|
59
58
|
end
|
60
59
|
end
|
61
60
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
|
3
|
+
module Cellular
|
4
|
+
module Backends
|
5
|
+
# LinkMobility backend (https://www.linkmobility.com)
|
6
|
+
class LinkMobility < Backend
|
7
|
+
# Documentation: https://www.linkmobility.com/developers/
|
8
|
+
BASE_URL = 'https://wsx.sp247.net/'.freeze
|
9
|
+
|
10
|
+
HTTP_HEADERS = {
|
11
|
+
'Content-Type' => 'application/json; charset=utf-8',
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
def self.deliver(options = {})
|
15
|
+
request_queue = {}
|
16
|
+
recipients_batch(options).each_with_index do |recipient, index|
|
17
|
+
options[:batch] = recipient
|
18
|
+
|
19
|
+
request = HTTParty.post(
|
20
|
+
sms_url,
|
21
|
+
body: payload(options),
|
22
|
+
basic_auth: link_mobility_config,
|
23
|
+
headers: HTTP_HEADERS
|
24
|
+
)
|
25
|
+
|
26
|
+
request_queue[index] = {
|
27
|
+
recipient: options[:batch],
|
28
|
+
response: parse_response(request)
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
# return first response for now
|
33
|
+
request_queue[0][:response]
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.parse_response(response)
|
37
|
+
[
|
38
|
+
response['description']
|
39
|
+
]
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.sms_url
|
43
|
+
"#{BASE_URL}sms/send"
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.link_mobility_config
|
47
|
+
{
|
48
|
+
username: Cellular.config.username,
|
49
|
+
password: Cellular.config.password
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.payload(options)
|
54
|
+
{
|
55
|
+
source: options[:sender],
|
56
|
+
destination: options[:batch],
|
57
|
+
userData: options[:message],
|
58
|
+
platformId: 'COMMON_API',
|
59
|
+
platformPartnerId: Cellular.config.partner_id,
|
60
|
+
}.to_json
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.recipients_batch(options)
|
64
|
+
if options[:recipients].blank?
|
65
|
+
[options[:recipient]]
|
66
|
+
else
|
67
|
+
options[:recipients]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -2,9 +2,9 @@ require 'savon'
|
|
2
2
|
|
3
3
|
module Cellular
|
4
4
|
module Backends
|
5
|
+
# Sendega backend (http://sendega.com)
|
5
6
|
class Sendega < Backend
|
6
|
-
|
7
|
-
GATEWAY_URL = 'https://smsc.sendega.com/Content.asmx?WSDL'
|
7
|
+
GATEWAY_URL = 'https://smsc.sendega.com/Content.asmx?WSDL'.freeze
|
8
8
|
|
9
9
|
def self.deliver(options = {}, savon_options = {})
|
10
10
|
# Send an SMS and return its initial delivery status code.
|
@@ -45,7 +45,7 @@ module Cellular
|
|
45
45
|
request_queue[index] = {
|
46
46
|
batch: batch,
|
47
47
|
result: result,
|
48
|
-
body:result.body[:send_response][:send_result],
|
48
|
+
body: result.body[:send_response][:send_result],
|
49
49
|
response: map_response(result.body[:send_response][:send_result])
|
50
50
|
}
|
51
51
|
end
|
@@ -54,20 +54,20 @@ module Cellular
|
|
54
54
|
request_queue[0][:response]
|
55
55
|
end
|
56
56
|
|
57
|
-
def self.receive(
|
57
|
+
def self.receive(_data)
|
58
58
|
raise NotImplementedError
|
59
59
|
end
|
60
60
|
|
61
61
|
def self.savon_config
|
62
62
|
{
|
63
|
-
|
64
|
-
|
65
|
-
|
63
|
+
username: Cellular.config.username,
|
64
|
+
password: Cellular.config.password,
|
65
|
+
dlrUrl: Cellular.config.delivery_url
|
66
66
|
}
|
67
67
|
end
|
68
68
|
|
69
69
|
def self.defaults_with(options)
|
70
|
-
|
70
|
+
{
|
71
71
|
sender: options[:sender],
|
72
72
|
destination: options[:batch],
|
73
73
|
pricegroup: options[:price] || 0, # default price to 0
|
@@ -85,9 +85,9 @@ module Cellular
|
|
85
85
|
}.merge!(savon_config)
|
86
86
|
end
|
87
87
|
|
88
|
-
def self.map_response(
|
89
|
-
msg =
|
90
|
-
[
|
88
|
+
def self.map_response(body)
|
89
|
+
msg = body[:success] ? success_message : body[:error_message]
|
90
|
+
[body[:error_number].to_i, msg]
|
91
91
|
end
|
92
92
|
|
93
93
|
def self.success_message
|
@@ -98,10 +98,9 @@ module Cellular
|
|
98
98
|
if options[:recipients].blank?
|
99
99
|
[options[:recipient]]
|
100
100
|
else
|
101
|
-
options[:recipients].each_slice(100).to_a.map{|x| x.join(',') }
|
101
|
+
options[:recipients].each_slice(100).to_a.map { |x| x.join(',') }
|
102
102
|
end
|
103
103
|
end
|
104
|
-
|
105
104
|
end
|
106
105
|
end
|
107
106
|
end
|
@@ -2,10 +2,11 @@ require 'httparty'
|
|
2
2
|
|
3
3
|
module Cellular
|
4
4
|
module Backends
|
5
|
+
# Twilio backend (https://www.twilio.com)
|
5
6
|
class Twilio < Backend
|
6
7
|
# Documentation: https://www.twilio.com/docs/api/rest
|
7
|
-
API_VERSION = '2010-04-01'
|
8
|
-
BASE_URL = 'https://api.twilio.com/'
|
8
|
+
API_VERSION = '2010-04-01'.freeze
|
9
|
+
BASE_URL = 'https://api.twilio.com/'.freeze
|
9
10
|
API_URL = BASE_URL + API_VERSION
|
10
11
|
|
11
12
|
HTTP_HEADERS = {
|
@@ -14,7 +15,7 @@ module Cellular
|
|
14
15
|
'User-Agent' => "cellular/#{Cellular::VERSION}" \
|
15
16
|
" (#{RUBY_ENGINE}/#{RUBY_PLATFORM}" \
|
16
17
|
" #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL})"
|
17
|
-
}
|
18
|
+
}.freeze
|
18
19
|
|
19
20
|
def self.deliver(options = {})
|
20
21
|
request_queue = {}
|
@@ -71,7 +72,6 @@ module Cellular
|
|
71
72
|
options[:recipients]
|
72
73
|
end
|
73
74
|
end
|
74
|
-
|
75
75
|
end
|
76
76
|
end
|
77
77
|
end
|
@@ -1,15 +1,12 @@
|
|
1
1
|
module Cellular
|
2
|
+
# Configuration for Cellular
|
2
3
|
class Configuration
|
3
|
-
|
4
4
|
attr_accessor :username, :password, :delivery_url, :backend
|
5
|
-
|
6
|
-
attr_accessor :country_code, :price, :sender
|
7
|
-
|
5
|
+
attr_accessor :country_code, :price, :sender, :partner_id
|
8
6
|
attr_accessor :logger
|
9
|
-
|
7
|
+
|
10
8
|
def logger
|
11
9
|
@logger ||= Object.const_defined?(:Rails) ? Rails.logger : Logger.new
|
12
10
|
end
|
13
|
-
|
14
11
|
end
|
15
12
|
end
|
data/lib/cellular/jobs.rb
CHANGED
data/lib/cellular/logger.rb
CHANGED
@@ -1,12 +1,9 @@
|
|
1
1
|
module Cellular
|
2
|
-
|
3
|
-
#
|
4
|
-
# logs to stdout
|
2
|
+
# API compatible logger when not in a Rails environment
|
3
|
+
# Logs to stdout
|
5
4
|
class Logger
|
6
5
|
def info(message)
|
7
6
|
$stdout.puts message
|
8
7
|
end
|
9
8
|
end
|
10
|
-
|
11
9
|
end
|
12
|
-
|
data/lib/cellular/models/sms.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
require 'active_support/time'
|
2
2
|
|
3
3
|
module Cellular
|
4
|
+
# Represents an SMS
|
4
5
|
class SMS
|
5
|
-
|
6
6
|
attr_accessor :recipient, :sender, :message, :price, :country_code
|
7
7
|
attr_accessor :recipients, :delivery_status, :delivery_message
|
8
|
+
|
8
9
|
def initialize(options = {})
|
9
10
|
@backend = Cellular.config.backend
|
10
11
|
|
@@ -24,15 +25,17 @@ module Cellular
|
|
24
25
|
end
|
25
26
|
|
26
27
|
def deliver_async(delivery_options = {})
|
27
|
-
Cellular::Jobs::AsyncMessenger.set(delivery_options)
|
28
|
+
Cellular::Jobs::AsyncMessenger.set(delivery_options)
|
29
|
+
.perform_later(options)
|
28
30
|
end
|
31
|
+
|
29
32
|
alias_method :deliver_later, :deliver_async
|
30
33
|
|
31
|
-
def save(
|
34
|
+
def save(_options = {})
|
32
35
|
raise NotImplementedError
|
33
36
|
end
|
34
37
|
|
35
|
-
def receive(
|
38
|
+
def receive(_options = {})
|
36
39
|
raise NotImplementedError
|
37
40
|
end
|
38
41
|
|
@@ -52,6 +55,5 @@ module Cellular
|
|
52
55
|
country_code: @country_code
|
53
56
|
}
|
54
57
|
end
|
55
|
-
|
56
58
|
end
|
57
59
|
end
|
data/lib/cellular/version.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cellular::Backends::Backend do
|
4
|
+
describe '::deliver' do
|
5
|
+
it 'has not been implemented yet' do
|
6
|
+
expect do
|
7
|
+
described_class.deliver
|
8
|
+
end.to raise_error NotImplementedError
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '::receive' do
|
13
|
+
it 'has not been implemented yet' do
|
14
|
+
expect do
|
15
|
+
described_class.receive ''
|
16
|
+
end.to raise_error NotImplementedError
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,20 +1,19 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Cellular::Backends::CoolSMS do
|
4
|
-
|
5
4
|
let(:recipient) { '47xxxxxxxx' }
|
6
5
|
let(:sender) { 'Custom sender' }
|
7
6
|
let(:message) { 'This is an SMS message' }
|
8
7
|
|
9
|
-
let(:options)
|
8
|
+
let(:options) do
|
10
9
|
{
|
11
10
|
recipient: recipient,
|
12
11
|
sender: sender,
|
13
12
|
message: message
|
14
13
|
}
|
15
|
-
|
14
|
+
end
|
16
15
|
|
17
|
-
let(:payload)
|
16
|
+
let(:payload) do
|
18
17
|
{
|
19
18
|
username: 'username',
|
20
19
|
password: 'password',
|
@@ -25,7 +24,7 @@ describe Cellular::Backends::CoolSMS do
|
|
25
24
|
resulttype: 'xml',
|
26
25
|
lang: 'en'
|
27
26
|
}
|
28
|
-
|
27
|
+
end
|
29
28
|
|
30
29
|
before do
|
31
30
|
Cellular.config.username = 'username'
|
@@ -34,13 +33,15 @@ describe Cellular::Backends::CoolSMS do
|
|
34
33
|
|
35
34
|
describe '::deliver' do
|
36
35
|
before do
|
37
|
-
stub_request(:get, 'https://sms.coolsmsc.dk/?charset=utf-8&from=Custom%20sender&lang=en&message=This%20is%20an%20SMS%20message&password=password&resulttype=xml&to=47xxxxxxxx&username=username')
|
38
|
-
to_return headers: { 'Content-Type' => 'text/xml' }, body: fixture('backends/cool_sms/success.xml')
|
36
|
+
stub_request(:get, 'https://sms.coolsmsc.dk/?charset=utf-8&from=Custom%20sender&lang=en&message=This%20is%20an%20SMS%20message&password=password&resulttype=xml&to=47xxxxxxxx&username=username')
|
37
|
+
.to_return headers: { 'Content-Type' => 'text/xml' }, body: fixture('backends/cool_sms/success.xml')
|
39
38
|
end
|
40
39
|
|
41
40
|
it 'uses HTTParty to deliver an SMS' do
|
42
|
-
expect(HTTParty).to receive(:get).with(
|
43
|
-
|
41
|
+
expect(HTTParty).to receive(:get).with(
|
42
|
+
described_class::GATEWAY_URL,
|
43
|
+
query: payload
|
44
|
+
).and_call_original
|
44
45
|
|
45
46
|
described_class.deliver(options)
|
46
47
|
end
|
@@ -56,8 +57,8 @@ describe Cellular::Backends::CoolSMS do
|
|
56
57
|
|
57
58
|
context 'when not successful' do
|
58
59
|
before do
|
59
|
-
stub_request(:get, 'https://sms.coolsmsc.dk/?charset=utf-8&from=Custom%20sender&lang=en&message=This%20is%20an%20SMS%20message&password=password&resulttype=xml&to=47xxxxxxxx&username=username')
|
60
|
-
to_return headers: { 'Content-Type' => 'text/xml' }, body: fixture('backends/cool_sms/failure.xml')
|
60
|
+
stub_request(:get, 'https://sms.coolsmsc.dk/?charset=utf-8&from=Custom%20sender&lang=en&message=This%20is%20an%20SMS%20message&password=password&resulttype=xml&to=47xxxxxxxx&username=username')
|
61
|
+
.to_return headers: { 'Content-Type' => 'text/xml' }, body: fixture('backends/cool_sms/failure.xml')
|
61
62
|
end
|
62
63
|
|
63
64
|
it 'returns failure and a message' do
|
@@ -70,12 +71,14 @@ describe Cellular::Backends::CoolSMS do
|
|
70
71
|
end
|
71
72
|
|
72
73
|
describe '::parse_response' do
|
73
|
-
it '
|
74
|
+
it 'returns the correct response' do
|
74
75
|
message = ['success', 'The message was sent correctly.']
|
75
76
|
|
76
77
|
check = { 'status' => message[0], 'result' => message[1] }
|
77
|
-
second_check =
|
78
|
-
|
78
|
+
second_check = {
|
79
|
+
'status' => message[0],
|
80
|
+
'message' => { 'result' => message[1] }
|
81
|
+
}
|
79
82
|
|
80
83
|
expect(described_class.parse_response(check)).to eq(message)
|
81
84
|
expect(described_class.parse_response(second_check)).to eq(message)
|
@@ -83,31 +86,32 @@ describe Cellular::Backends::CoolSMS do
|
|
83
86
|
end
|
84
87
|
|
85
88
|
describe '::coolsms_config' do
|
86
|
-
it '
|
89
|
+
it 'returns the config for coolsms' do
|
87
90
|
expect(described_class.coolsms_config).to eq(
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
})
|
91
|
+
username: Cellular.config.username,
|
92
|
+
password: Cellular.config.password
|
93
|
+
)
|
92
94
|
end
|
93
95
|
end
|
94
96
|
|
95
97
|
describe '::defaults_with' do
|
96
|
-
it '
|
98
|
+
it 'returns the whole query' do
|
97
99
|
options[:batch] = recipient
|
98
100
|
expect(described_class.defaults_with(options)).to eq(payload)
|
99
101
|
end
|
100
102
|
end
|
101
103
|
|
102
104
|
describe '::recipients_batch' do
|
103
|
-
it '
|
104
|
-
|
105
|
-
|
105
|
+
it 'wraps recipient option into an array' do
|
106
|
+
result = described_class.recipients_batch(recipient: recipient)
|
107
|
+
expect(result).to eq([recipient])
|
106
108
|
end
|
107
|
-
|
108
|
-
|
109
|
-
|
109
|
+
|
110
|
+
it 'returns recipients option as-is' do
|
111
|
+
result = described_class.recipients_batch(
|
112
|
+
recipients: [recipient, recipient]
|
113
|
+
)
|
114
|
+
expect(result).to eq([recipient, recipient])
|
110
115
|
end
|
111
116
|
end
|
112
|
-
|
113
117
|
end
|