elk 0.0.11 → 0.0.12
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/README.MD +42 -26
- data/lib/elk/sms.rb +10 -1
- data/lib/elk/version.rb +1 -1
- data/spec/elk/number_spec.rb +117 -0
- data/spec/elk/sms_spec.rb +168 -0
- data/spec/elk_spec.rb +37 -299
- metadata +16 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ffe981763600225095d75aaf6c9906060fca7be7
|
4
|
+
data.tar.gz: 411313ddbd7e12b1b2fd8b78f2135e9bfd1ab425
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f504ba330456a3d3b9ebd292d0baf0b0eacd07d2b4d1fa213f9431cd5d4f97879f9ff10ffcd128dae87ddfa4e8176a0dbb9cb9b64149a7818e886d4ff3542aad
|
7
|
+
data.tar.gz: 878e51be0a7383459fbf04aff9a259c837a7866c249f9ae6c11953c80a8c4e816cdf76921caaf6a6b5d107d5cbd910485b2eca301b8ef5dd555bddb8cc05f0f5
|
data/README.MD
CHANGED
@@ -29,60 +29,76 @@ elk can be used to allocate a phone numbers, manage the numbers and send/recieve
|
|
29
29
|
|
30
30
|
First thing when using elk is to set the authentication parameters
|
31
31
|
|
32
|
-
|
32
|
+
```Ruby
|
33
|
+
require 'elk'
|
33
34
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
35
|
+
Elk.configure do |config|
|
36
|
+
config.username = 'USERNAME'
|
37
|
+
config.password = 'PASSWORD'
|
38
|
+
end
|
39
|
+
```
|
38
40
|
|
39
41
|
### Numbers
|
40
42
|
|
41
43
|
To be able to send and recieve messages, a number is needed. Several numbers can be allocated.
|
42
44
|
|
43
|
-
|
44
|
-
|
45
|
+
```Ruby
|
46
|
+
number = Elk::Number.allocate(:sms_url => 'http://myservice.se/callback/newsms.php', :country => 'se')
|
47
|
+
# => #<Elk::Number:0x0000010282aa70 @country="se", @sms_url="http://myservice.se/callback/newsms.php", @status="yes", @number_id="n03e7db70cc06c1ff85e09a2b3f86dd62", @number="+46766861034", @capabilities=[:sms], @loaded_at=2011-07-17 15:23:55 +0200>
|
48
|
+
```
|
45
49
|
|
46
50
|
Get all numbers
|
47
51
|
|
48
|
-
|
49
|
-
|
52
|
+
```Ruby
|
53
|
+
numbers = Elk::Number.all
|
54
|
+
# => [#<Elk::Number ...>, #<Elk::Number ...>]
|
55
|
+
```
|
50
56
|
|
51
57
|
Change number settings
|
52
58
|
|
53
|
-
|
54
|
-
|
55
|
-
|
59
|
+
```Ruby
|
60
|
+
number.sms_url = 'http://myservice.se/callback/newsms.php'
|
61
|
+
number.save
|
62
|
+
# => true
|
63
|
+
```
|
56
64
|
|
57
65
|
Deallocate a number.
|
58
66
|
Beware that there is no way to get your number back once it has been deallocated!
|
59
67
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
68
|
+
```Ruby
|
69
|
+
number.deallocate!
|
70
|
+
# => true
|
71
|
+
number.status
|
72
|
+
# => :deallocated
|
73
|
+
```
|
64
74
|
|
65
75
|
### SMS
|
66
76
|
|
67
77
|
Send SMS. Messages can be sent from one of the allocated numbers or an arbitrary alphanumeric string of at most 11 characters.
|
68
78
|
|
69
|
-
|
70
|
-
|
79
|
+
```Ruby
|
80
|
+
Elk::SMS.send(:from => 'MyService', :to => '+46704508449', :message => 'Your order #171 has now been sent!')
|
81
|
+
# => #<Elk::SMS:0x0000010179d7e8 @from="MyService", @to="+46704508449", @message="Your order #171 has now been sent!", @message_id="sdc39a7926d37159b6985283e32f43251", @created_at=2011-07-17 16:21:13 +0200, @loaded_at=2011-07-17 16:21:13 +0200>
|
82
|
+
```
|
71
83
|
|
72
84
|
Receiving SMS does not require Elk, but should be of interest anyway.
|
73
85
|
Example with Sinatra:
|
74
86
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
87
|
+
```Ruby
|
88
|
+
post '/receive' do
|
89
|
+
if request.params['message'] == 'Hello'
|
90
|
+
# Sends a return SMS with message "world!"
|
91
|
+
"world!"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
```
|
81
95
|
|
82
96
|
SMS history
|
83
97
|
|
84
|
-
|
85
|
-
|
98
|
+
```Ruby
|
99
|
+
Elk::SMS.all
|
100
|
+
# => [#<Elk::SMS ...>, #<Elk::SMS ...>, <Elk::SMS ...>]
|
101
|
+
```
|
86
102
|
|
87
103
|
## Copyright
|
88
104
|
|
data/lib/elk/sms.rb
CHANGED
@@ -33,13 +33,22 @@ module Elk
|
|
33
33
|
# Required parameters
|
34
34
|
#
|
35
35
|
# * :from - Either the one of the allocated numbers or arbitrary alphanumeric string of at most 11 characters
|
36
|
-
# * :to - Any phone number capable of receiving SMS
|
36
|
+
# * :to - Any phone number capable of receiving SMS. Multiple numbers can be given as Array or comma separated String
|
37
37
|
# * :message - Any UTF-8 text Splitting and joining multi-part SMS messages are automatically handled by the API
|
38
|
+
#
|
39
|
+
# Optional parameters
|
40
|
+
# * :flash - if set to non-false value SMS is sent as a "Flash SMS"
|
41
|
+
#
|
38
42
|
def send(parameters)
|
39
43
|
verify_parameters(parameters, [:from, :message, :to])
|
40
44
|
|
41
45
|
parameters[:to] = Array(parameters[:to]).join(',')
|
42
46
|
|
47
|
+
if parameters[:flash]
|
48
|
+
parameters.delete(:flash)
|
49
|
+
parameters[:flashsms] = 'yes'
|
50
|
+
end
|
51
|
+
|
43
52
|
# Warn if the from string will be capped by the sms gateway
|
44
53
|
if parameters[:from] && parameters[:from].match(/^(\w{11,})$/)
|
45
54
|
warn "SMS 'from' value #{parameters[:from]} will be capped at 11 chars"
|
data/lib/elk/version.rb
CHANGED
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'elk'
|
3
|
+
|
4
|
+
describe Elk::Number do
|
5
|
+
before { configure_elk }
|
6
|
+
|
7
|
+
it 'allocates a number' do
|
8
|
+
stub_request(:post, "https://USERNAME:PASSWORD@api.46elks.com/a1/Numbers").
|
9
|
+
with(:body => {"country" => "se", "sms_url" => "http://localhost/receive"},
|
10
|
+
:headers => {'Accept'=>'application/json', 'Content-Type'=>'application/x-www-form-urlencoded'}).
|
11
|
+
to_return(fixture('allocates_a_number.txt'))
|
12
|
+
|
13
|
+
number = described_class.allocate(:sms_url => 'http://localhost/receive', :country => 'se')
|
14
|
+
number.status.should == :active
|
15
|
+
number.sms_url.should == 'http://localhost/receive'
|
16
|
+
number.country.should == 'se'
|
17
|
+
number.number.should == '+46766861012'
|
18
|
+
number.capabilities.should == [:sms]
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'gets allocated numbers' do
|
22
|
+
stub_request(:get, "https://USERNAME:PASSWORD@api.46elks.com/a1/Numbers").
|
23
|
+
with(:headers => {'Accept'=>'application/json'}).
|
24
|
+
to_return(fixture('gets_allocated_numbers.txt'))
|
25
|
+
|
26
|
+
numbers = described_class.all
|
27
|
+
numbers.size.should == 2
|
28
|
+
numbers[0].number_id.should == 'nea19c8e291676fb7003fa1d63bba7899'
|
29
|
+
numbers[0].number.should == '+46704508449'
|
30
|
+
numbers[0].sms_url == 'http://localhost/receive1'
|
31
|
+
|
32
|
+
numbers[1].number_id.should == 'nea19c8e291676fb7003fa1d63bba789A'
|
33
|
+
numbers[1].number.should == '+46761042247'
|
34
|
+
numbers[0].sms_url == 'http://localhost/receive2'
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'updates a number' do
|
38
|
+
stub_request(:get, "https://USERNAME:PASSWORD@api.46elks.com/a1/Numbers").
|
39
|
+
with(:headers => {'Accept'=>'application/json'}).
|
40
|
+
to_return(fixture('gets_allocated_numbers.txt'))
|
41
|
+
stub_request(:post, "https://USERNAME:PASSWORD@api.46elks.com/a1/Numbers/nea19c8e291676fb7003fa1d63bba7899").
|
42
|
+
with(:body => {"sms_url" => "http://otherhost/receive", "voice_start" => ""},
|
43
|
+
:headers => {'Accept'=>'application/json', 'Content-Type'=>'application/x-www-form-urlencoded'}).
|
44
|
+
to_return(fixture('updates_a_number.txt'))
|
45
|
+
|
46
|
+
number = described_class.all[0]
|
47
|
+
number.country = 'no'
|
48
|
+
number.sms_url = 'http://otherhost/receive'
|
49
|
+
number.save.should == true
|
50
|
+
number.country.should == 'no'
|
51
|
+
number.sms_url.should == 'http://otherhost/receive'
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'deallocates a number' do
|
55
|
+
stub_request(:get, "https://USERNAME:PASSWORD@api.46elks.com/a1/Numbers").
|
56
|
+
with(:headers => {'Accept'=>'application/json'}).
|
57
|
+
to_return(fixture('gets_allocated_numbers.txt'))
|
58
|
+
stub_request(:post, "https://USERNAME:PASSWORD@api.46elks.com/a1/Numbers/nea19c8e291676fb7003fa1d63bba7899").
|
59
|
+
with(:body => {"active" => "no"},
|
60
|
+
:headers => {'Accept'=>'application/json', 'Content-Type'=>'application/x-www-form-urlencoded'}).
|
61
|
+
to_return(fixture('deallocates_a_number.txt'))
|
62
|
+
|
63
|
+
number = described_class.all[0]
|
64
|
+
number.status.should == :active
|
65
|
+
number.deallocate!.should == true
|
66
|
+
number.status.should == :deallocated
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'reloads a number' do
|
70
|
+
stub_request(:get, "https://USERNAME:PASSWORD@api.46elks.com/a1/Numbers").
|
71
|
+
with(:headers => {'Accept'=>'application/json'}).
|
72
|
+
to_return(fixture('gets_allocated_numbers.txt'))
|
73
|
+
stub_request(:get, "https://USERNAME:PASSWORD@api.46elks.com/a1/Numbers/nea19c8e291676fb7003fa1d63bba7899").
|
74
|
+
with(:headers => {'Accept'=>'application/json'}).
|
75
|
+
to_return(fixture('reloads_a_number.txt'))
|
76
|
+
|
77
|
+
number = described_class.all[0]
|
78
|
+
object_id = number.object_id
|
79
|
+
loaded_at = number.loaded_at
|
80
|
+
number.country = 'blah'
|
81
|
+
number.reload.should == true
|
82
|
+
number.country.should == 'se'
|
83
|
+
number.object_id.should == object_id
|
84
|
+
number.loaded_at.should_not == loaded_at
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'has wrong password' do
|
88
|
+
stub_request(:get, "https://USERNAME:WRONG@api.46elks.com/a1/Numbers").
|
89
|
+
with(:headers => {'Accept'=>'application/json'}).
|
90
|
+
to_return(fixture('auth_error.txt'))
|
91
|
+
|
92
|
+
Elk.configure do |config|
|
93
|
+
config.username = 'USERNAME'
|
94
|
+
config.password = 'WRONG'
|
95
|
+
end
|
96
|
+
|
97
|
+
expect {
|
98
|
+
described_class.all
|
99
|
+
}.to raise_error(Elk::AuthError)
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'gets server error when looking for all numbers' do
|
103
|
+
stub_request(:get, "https://USERNAME:PASSWORD@api.46elks.com/a1/Numbers").
|
104
|
+
with(:headers => {'Accept'=>'application/json'}).
|
105
|
+
to_return(fixture('server_error.txt'))
|
106
|
+
|
107
|
+
expect {
|
108
|
+
described_class.all
|
109
|
+
}.to raise_error(Elk::ServerError)
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'should handle no parameters' do
|
113
|
+
expect {
|
114
|
+
sms = described_class.allocate({})
|
115
|
+
}.to raise_error(Elk::MissingParameter)
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'elk'
|
3
|
+
|
4
|
+
describe Elk::SMS do
|
5
|
+
before { configure_elk }
|
6
|
+
let(:url) { "https://USERNAME:PASSWORD@api.46elks.com/a1/SMS" }
|
7
|
+
|
8
|
+
it 'sends a SMS' do
|
9
|
+
stub_request(:post, url).
|
10
|
+
with(:body => {:from => "+46761042247", :message => "Your order #171 has now been sent!", :to => "+46704508449"},
|
11
|
+
:headers => {'Accept'=>'application/json', 'Content-Type'=>'application/x-www-form-urlencoded'}).
|
12
|
+
to_return(fixture('sends_a_sms.txt'))
|
13
|
+
|
14
|
+
# Fake $stderr to check warnings
|
15
|
+
begin
|
16
|
+
old_stderr, $stderr = $stderr, StringIO.new
|
17
|
+
|
18
|
+
sms = described_class.send(:from => '+46761042247',
|
19
|
+
:to => '+46704508449',
|
20
|
+
:message => 'Your order #171 has now been sent!')
|
21
|
+
|
22
|
+
$stderr.string.should == ""
|
23
|
+
ensure
|
24
|
+
$stderr = old_stderr
|
25
|
+
end
|
26
|
+
|
27
|
+
sms.class.should == described_class
|
28
|
+
sms.from.should == '+46761042247'
|
29
|
+
sms.to.should == '+46704508449'
|
30
|
+
sms.message.should == 'Your order #171 has now been sent!'
|
31
|
+
sms.direction.should == 'outgoing'
|
32
|
+
sms.status.should == 'delivered'
|
33
|
+
end
|
34
|
+
|
35
|
+
it "sends a flash SMS" do
|
36
|
+
stub = stub_request(:post, url).
|
37
|
+
to_return(fixture('sends_a_sms.txt'))
|
38
|
+
|
39
|
+
described_class.send(
|
40
|
+
:from => '+46761042247',
|
41
|
+
:to => '+46704508449',
|
42
|
+
:message => 'Your order #171 has now been sent!',
|
43
|
+
:flash => true
|
44
|
+
)
|
45
|
+
|
46
|
+
stub.with(
|
47
|
+
:body => {
|
48
|
+
:from => '+46761042247',
|
49
|
+
:to => '+46704508449',
|
50
|
+
:message => 'Your order #171 has now been sent!',
|
51
|
+
:flashsms => 'yes'
|
52
|
+
},
|
53
|
+
:headers => {'Accept'=>'application/json', 'Content-Type'=>'application/x-www-form-urlencoded'}).
|
54
|
+
should have_been_made
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'when sending a SMS to multiple recipients' do
|
58
|
+
before do
|
59
|
+
stub_request(:post, url).
|
60
|
+
with(:body => {:from => "+46761042247", :message => "Your order #171 has now been sent!", :to => "+46704508449,+46704508449"},
|
61
|
+
:headers => {'Accept'=>'application/json', 'Content-Type'=>'application/x-www-form-urlencoded'}).
|
62
|
+
to_return(fixture('sends_a_sms_to_multiple_recipients.txt'))
|
63
|
+
end
|
64
|
+
|
65
|
+
it "sends the SMS when passing `to` as comma separated string" do
|
66
|
+
smses = described_class.send(:from => '+46761042247',
|
67
|
+
:to => '+46704508449,+46704508449',
|
68
|
+
:message => 'Your order #171 has now been sent!')
|
69
|
+
|
70
|
+
smses.size.should == 2
|
71
|
+
smses[0].class.should == described_class
|
72
|
+
smses[0].to.should == "+46704508449"
|
73
|
+
|
74
|
+
smses[0].message_id.should == "sb326c7a214f9f4abc90a11bd36d6abc3"
|
75
|
+
smses[1].message_id.should == "s47a89d6cc51d8db395d45ae7e16e86b7"
|
76
|
+
end
|
77
|
+
|
78
|
+
it "sends the SMS when passing `to` as array" do
|
79
|
+
smses = described_class.send(:from => '+46761042247',
|
80
|
+
:to => ['+46704508449', '+46704508449'],
|
81
|
+
:message => 'Your order #171 has now been sent!')
|
82
|
+
|
83
|
+
smses.size.should == 2
|
84
|
+
smses[0].class.should == described_class
|
85
|
+
smses[0].to.should == "+46704508449"
|
86
|
+
|
87
|
+
smses[0].message_id.should == "sb326c7a214f9f4abc90a11bd36d6abc3"
|
88
|
+
smses[1].message_id.should == "s47a89d6cc51d8db395d45ae7e16e86b7"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'gets SMS-history' do
|
93
|
+
stub_request(:get, url).
|
94
|
+
with(:headers => {'Accept'=>'application/json'}).
|
95
|
+
to_return(fixture('sms_history.txt'))
|
96
|
+
|
97
|
+
sms_history = described_class.all
|
98
|
+
|
99
|
+
sms_history.size.should == 3
|
100
|
+
sms_history[0].class.should == described_class
|
101
|
+
sms_history[0].created_at.class.should == Time
|
102
|
+
|
103
|
+
sms_history[0].message.should == "Your order #171 has now been sent!"
|
104
|
+
sms_history[1].message.should == "I'd like to order a pair of elks!"
|
105
|
+
sms_history[2].message.should == "Want an elk?"
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'reloads a SMS' do
|
109
|
+
stub_request(:get, url).
|
110
|
+
with(:headers => {'Accept'=>'application/json'}).
|
111
|
+
to_return(fixture('sms_history.txt'))
|
112
|
+
stub_request(:get, "https://USERNAME:PASSWORD@api.46elks.com/a1/SMS/s8952031bb83bf3e64f8e13b071c131c0").
|
113
|
+
with(:headers => {'Accept'=>'application/json'}).
|
114
|
+
to_return(fixture('reloads_a_sms.txt'))
|
115
|
+
|
116
|
+
sms_history = described_class.all
|
117
|
+
sms = sms_history[0]
|
118
|
+
loaded_at = sms.loaded_at
|
119
|
+
object_id = sms.object_id
|
120
|
+
sms.reload.should == true
|
121
|
+
sms.object_id.should == object_id
|
122
|
+
sms.loaded_at.should_not == loaded_at
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'should warn about capped sms sender' do
|
126
|
+
stub_request(:post, url).
|
127
|
+
with(:body => {:from => "VeryVeryVeryVeryLongSenderName", :message => "Your order #171 has now been sent!", :to => "+46704508449"},
|
128
|
+
:headers => {'Accept'=>'application/json', 'Content-Type'=>'application/x-www-form-urlencoded'}).
|
129
|
+
to_return(fixture('sends_a_sms_with_long_sender.txt'))
|
130
|
+
|
131
|
+
# Fake $stderr to check warnings
|
132
|
+
begin
|
133
|
+
old_stderr, $stderr = $stderr, StringIO.new
|
134
|
+
|
135
|
+
sms = described_class.send(:from => 'VeryVeryVeryVeryLongSenderName',
|
136
|
+
:to => '+46704508449',
|
137
|
+
:message => 'Your order #171 has now been sent!')
|
138
|
+
|
139
|
+
$stderr.string.should == "SMS 'from' value VeryVeryVeryVeryLongSenderName will be capped at 11 chars\n"
|
140
|
+
ensure
|
141
|
+
$stderr = old_stderr
|
142
|
+
end
|
143
|
+
|
144
|
+
sms.class.should == described_class
|
145
|
+
sms.from.should == 'VeryVeryVeryVeryLongSenderName'
|
146
|
+
sms.to.should == '+46704508449'
|
147
|
+
sms.message.should == 'Your order #171 has now been sent!'
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'should handle invalid to number' do
|
151
|
+
stub_request(:post, url).
|
152
|
+
with(:body => {:from => "+46761042247", :message => "Your order #171 has now been sent!", :to => "monkey"},
|
153
|
+
:headers => {'Accept'=>'application/json', 'Content-Type'=>'application/x-www-form-urlencoded'}).
|
154
|
+
to_return(fixture('invalid_to_number.txt'))
|
155
|
+
|
156
|
+
expect {
|
157
|
+
sms = described_class.send(:from => '+46761042247',
|
158
|
+
:to => 'monkey',
|
159
|
+
:message => 'Your order #171 has now been sent!')
|
160
|
+
}.to raise_error(Elk::BadRequest, 'Invalid to number')
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'should handle no parameters' do
|
164
|
+
expect {
|
165
|
+
sms = described_class.send({})
|
166
|
+
}.to raise_error(Elk::MissingParameter)
|
167
|
+
end
|
168
|
+
end
|
data/spec/elk_spec.rb
CHANGED
@@ -2,319 +2,57 @@ require 'spec_helper'
|
|
2
2
|
require 'elk'
|
3
3
|
|
4
4
|
describe Elk do
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
Elk.configure do |config|
|
16
|
-
config.username = 'USERNAME'
|
17
|
-
config.password = nil
|
18
|
-
end
|
19
|
-
|
20
|
-
expect { Elk.base_url }.to raise_error(Elk::AuthError)
|
21
|
-
|
22
|
-
Elk.configure do |config|
|
23
|
-
config.username = 'USERNAME'
|
24
|
-
config.password = 'PASSWORD'
|
25
|
-
end
|
26
|
-
|
27
|
-
expect { Elk.base_url }.to_not raise_error(Elk::AuthError)
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'should handle garbage json' do
|
31
|
-
bad_response_body = fixture('bad_response_body.txt').read
|
32
|
-
|
33
|
-
expect {
|
34
|
-
Elk.parse_json(bad_response_body)
|
35
|
-
}.to raise_error(Elk::BadResponse)
|
36
|
-
end
|
37
|
-
|
38
|
-
describe Elk::Number do
|
39
|
-
it 'allocates a number' do
|
40
|
-
stub_request(:post, "https://USERNAME:PASSWORD@api.46elks.com/a1/Numbers").
|
41
|
-
with(:body => {"country" => "se", "sms_url" => "http://localhost/receive"},
|
42
|
-
:headers => {'Accept'=>'application/json', 'Content-Type'=>'application/x-www-form-urlencoded'}).
|
43
|
-
to_return(fixture('allocates_a_number.txt'))
|
44
|
-
|
45
|
-
configure_elk
|
46
|
-
|
47
|
-
number = Elk::Number.allocate(:sms_url => 'http://localhost/receive', :country => 'se')
|
48
|
-
number.status.should == :active
|
49
|
-
number.sms_url.should == 'http://localhost/receive'
|
50
|
-
number.country.should == 'se'
|
51
|
-
number.number.should == '+46766861012'
|
52
|
-
number.capabilities.should == [:sms]
|
53
|
-
end
|
54
|
-
|
55
|
-
it 'gets allocated numbers' do
|
56
|
-
stub_request(:get, "https://USERNAME:PASSWORD@api.46elks.com/a1/Numbers").
|
57
|
-
with(:headers => {'Accept'=>'application/json'}).
|
58
|
-
to_return(fixture('gets_allocated_numbers.txt'))
|
59
|
-
|
60
|
-
configure_elk
|
61
|
-
|
62
|
-
numbers = Elk::Number.all
|
63
|
-
numbers.size.should == 2
|
64
|
-
numbers[0].number_id.should == 'nea19c8e291676fb7003fa1d63bba7899'
|
65
|
-
numbers[0].number.should == '+46704508449'
|
66
|
-
numbers[0].sms_url == 'http://localhost/receive1'
|
67
|
-
|
68
|
-
numbers[1].number_id.should == 'nea19c8e291676fb7003fa1d63bba789A'
|
69
|
-
numbers[1].number.should == '+46761042247'
|
70
|
-
numbers[0].sms_url == 'http://localhost/receive2'
|
71
|
-
end
|
72
|
-
|
73
|
-
it 'updates a number' do
|
74
|
-
stub_request(:get, "https://USERNAME:PASSWORD@api.46elks.com/a1/Numbers").
|
75
|
-
with(:headers => {'Accept'=>'application/json'}).
|
76
|
-
to_return(fixture('gets_allocated_numbers.txt'))
|
77
|
-
stub_request(:post, "https://USERNAME:PASSWORD@api.46elks.com/a1/Numbers/nea19c8e291676fb7003fa1d63bba7899").
|
78
|
-
with(:body => {"sms_url" => "http://otherhost/receive", "voice_start" => ""},
|
79
|
-
:headers => {'Accept'=>'application/json', 'Content-Type'=>'application/x-www-form-urlencoded'}).
|
80
|
-
to_return(fixture('updates_a_number.txt'))
|
81
|
-
|
82
|
-
configure_elk
|
83
|
-
|
84
|
-
number = Elk::Number.all[0]
|
85
|
-
number.country = 'no'
|
86
|
-
number.sms_url = 'http://otherhost/receive'
|
87
|
-
number.save.should == true
|
88
|
-
number.country.should == 'no'
|
89
|
-
number.sms_url.should == 'http://otherhost/receive'
|
90
|
-
end
|
91
|
-
|
92
|
-
it 'deallocates a number' do
|
93
|
-
stub_request(:get, "https://USERNAME:PASSWORD@api.46elks.com/a1/Numbers").
|
94
|
-
with(:headers => {'Accept'=>'application/json'}).
|
95
|
-
to_return(fixture('gets_allocated_numbers.txt'))
|
96
|
-
stub_request(:post, "https://USERNAME:PASSWORD@api.46elks.com/a1/Numbers/nea19c8e291676fb7003fa1d63bba7899").
|
97
|
-
with(:body => {"active" => "no"},
|
98
|
-
:headers => {'Accept'=>'application/json', 'Content-Type'=>'application/x-www-form-urlencoded'}).
|
99
|
-
to_return(fixture('deallocates_a_number.txt'))
|
100
|
-
|
101
|
-
configure_elk
|
102
|
-
|
103
|
-
number = Elk::Number.all[0]
|
104
|
-
number.status.should == :active
|
105
|
-
number.deallocate!.should == true
|
106
|
-
number.status.should == :deallocated
|
107
|
-
end
|
108
|
-
|
109
|
-
it 'reloads a number' do
|
110
|
-
stub_request(:get, "https://USERNAME:PASSWORD@api.46elks.com/a1/Numbers").
|
111
|
-
with(:headers => {'Accept'=>'application/json'}).
|
112
|
-
to_return(fixture('gets_allocated_numbers.txt'))
|
113
|
-
stub_request(:get, "https://USERNAME:PASSWORD@api.46elks.com/a1/Numbers/nea19c8e291676fb7003fa1d63bba7899").
|
114
|
-
with(:headers => {'Accept'=>'application/json'}).
|
115
|
-
to_return(fixture('reloads_a_number.txt'))
|
116
|
-
|
117
|
-
configure_elk
|
118
|
-
|
119
|
-
number = Elk::Number.all[0]
|
120
|
-
object_id = number.object_id
|
121
|
-
loaded_at = number.loaded_at
|
122
|
-
number.country = 'blah'
|
123
|
-
number.reload.should == true
|
124
|
-
number.country.should == 'se'
|
125
|
-
number.object_id.should == object_id
|
126
|
-
number.loaded_at.should_not == loaded_at
|
127
|
-
end
|
128
|
-
|
129
|
-
it 'has wrong password' do
|
130
|
-
stub_request(:get, "https://USERNAME:WRONG@api.46elks.com/a1/Numbers").
|
131
|
-
with(:headers => {'Accept'=>'application/json'}).
|
132
|
-
to_return(fixture('auth_error.txt'))
|
133
|
-
|
134
|
-
Elk.configure do |config|
|
135
|
-
config.username = 'USERNAME'
|
136
|
-
config.password = 'WRONG'
|
5
|
+
context "detect missing username and/or password" do
|
6
|
+
context "when nothing is configured" do
|
7
|
+
specify do
|
8
|
+
Elk.configure do |config|
|
9
|
+
config.username = nil
|
10
|
+
config.password = nil
|
11
|
+
end
|
12
|
+
|
13
|
+
expect { Elk.base_url }.to raise_error(Elk::AuthError)
|
137
14
|
end
|
138
|
-
|
139
|
-
expect {
|
140
|
-
Elk::Number.all
|
141
|
-
}.to raise_error(Elk::AuthError)
|
142
15
|
end
|
143
16
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
17
|
+
context "when username is missing" do
|
18
|
+
specify do
|
19
|
+
Elk.configure do |config|
|
20
|
+
config.username = nil
|
21
|
+
config.password = 'PASSWORD'
|
22
|
+
end
|
148
23
|
|
149
|
-
|
150
|
-
|
151
|
-
expect {
|
152
|
-
Elk::Number.all
|
153
|
-
}.to raise_error(Elk::ServerError)
|
154
|
-
end
|
155
|
-
|
156
|
-
it 'should handle no parameters' do
|
157
|
-
configure_elk
|
158
|
-
|
159
|
-
expect {
|
160
|
-
sms = Elk::Number.allocate({})
|
161
|
-
}.to raise_error(Elk::MissingParameter)
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
describe Elk::SMS do
|
166
|
-
it 'sends a SMS' do
|
167
|
-
stub_request(:post, "https://USERNAME:PASSWORD@api.46elks.com/a1/SMS").
|
168
|
-
with(:body => {"from" => "+46761042247", :message => "Your order #171 has now been sent!", :to => "+46704508449"},
|
169
|
-
:headers => {'Accept'=>'application/json', 'Content-Type'=>'application/x-www-form-urlencoded'}).
|
170
|
-
to_return(fixture('sends_a_sms.txt'))
|
171
|
-
|
172
|
-
configure_elk
|
173
|
-
|
174
|
-
# Fake $stderr to check warnings
|
175
|
-
begin
|
176
|
-
old_stderr, $stderr = $stderr, StringIO.new
|
177
|
-
|
178
|
-
sms = Elk::SMS.send(:from => '+46761042247',
|
179
|
-
:to => '+46704508449',
|
180
|
-
:message => 'Your order #171 has now been sent!')
|
181
|
-
|
182
|
-
$stderr.string.should == ""
|
183
|
-
ensure
|
184
|
-
$stderr = old_stderr
|
24
|
+
expect { Elk.base_url }.to raise_error(Elk::AuthError)
|
185
25
|
end
|
186
|
-
|
187
|
-
sms.class.should == Elk::SMS
|
188
|
-
sms.from.should == '+46761042247'
|
189
|
-
sms.to.should == '+46704508449'
|
190
|
-
sms.message.should == 'Your order #171 has now been sent!'
|
191
|
-
sms.direction.should == 'outgoing'
|
192
|
-
sms.status.should == 'delivered'
|
193
26
|
end
|
194
27
|
|
28
|
+
context "when password is missing" do
|
29
|
+
specify do
|
30
|
+
Elk.configure do |config|
|
31
|
+
config.username = 'USERNAME'
|
32
|
+
config.password = nil
|
33
|
+
end
|
195
34
|
|
196
|
-
|
197
|
-
before do
|
198
|
-
stub_request(:post, "https://USERNAME:PASSWORD@api.46elks.com/a1/SMS").
|
199
|
-
with(:body => {"from" => "+46761042247", :message => "Your order #171 has now been sent!", :to => "+46704508449,+46704508449"},
|
200
|
-
:headers => {'Accept'=>'application/json', 'Content-Type'=>'application/x-www-form-urlencoded'}).
|
201
|
-
to_return(fixture('sends_a_sms_to_multiple_recipients.txt'))
|
202
|
-
|
203
|
-
configure_elk
|
204
|
-
end
|
205
|
-
|
206
|
-
it "sends the SMS when passing `to` as comma separated string" do
|
207
|
-
smses = Elk::SMS.send(:from => '+46761042247',
|
208
|
-
:to => '+46704508449,+46704508449',
|
209
|
-
:message => 'Your order #171 has now been sent!')
|
210
|
-
|
211
|
-
smses.size.should == 2
|
212
|
-
smses[0].class.should == Elk::SMS
|
213
|
-
smses[0].to.should == "+46704508449"
|
214
|
-
|
215
|
-
smses[0].message_id.should == "sb326c7a214f9f4abc90a11bd36d6abc3"
|
216
|
-
smses[1].message_id.should == "s47a89d6cc51d8db395d45ae7e16e86b7"
|
217
|
-
end
|
218
|
-
|
219
|
-
it "sends the SMS when passing `to` as array" do
|
220
|
-
smses = Elk::SMS.send(:from => '+46761042247',
|
221
|
-
:to => ['+46704508449', '+46704508449'],
|
222
|
-
:message => 'Your order #171 has now been sent!')
|
223
|
-
|
224
|
-
smses.size.should == 2
|
225
|
-
smses[0].class.should == Elk::SMS
|
226
|
-
smses[0].to.should == "+46704508449"
|
227
|
-
|
228
|
-
smses[0].message_id.should == "sb326c7a214f9f4abc90a11bd36d6abc3"
|
229
|
-
smses[1].message_id.should == "s47a89d6cc51d8db395d45ae7e16e86b7"
|
35
|
+
expect { Elk.base_url }.to raise_error(Elk::AuthError)
|
230
36
|
end
|
231
37
|
end
|
232
38
|
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
sms_history = Elk::SMS.all
|
39
|
+
context "when all is configured" do
|
40
|
+
specify do
|
41
|
+
Elk.configure do |config|
|
42
|
+
config.username = 'USERNAME'
|
43
|
+
config.password = 'PASSWORD'
|
44
|
+
end
|
241
45
|
|
242
|
-
|
243
|
-
sms_history[0].class.should == Elk::SMS
|
244
|
-
sms_history[0].created_at.class.should == Time
|
245
|
-
|
246
|
-
sms_history[0].message.should == "Your order #171 has now been sent!"
|
247
|
-
sms_history[1].message.should == "I'd like to order a pair of elks!"
|
248
|
-
sms_history[2].message.should == "Want an elk?"
|
249
|
-
end
|
250
|
-
|
251
|
-
it 'reloads a SMS' do
|
252
|
-
stub_request(:get, "https://USERNAME:PASSWORD@api.46elks.com/a1/SMS").
|
253
|
-
with(:headers => {'Accept'=>'application/json'}).
|
254
|
-
to_return(fixture('sms_history.txt'))
|
255
|
-
stub_request(:get, "https://USERNAME:PASSWORD@api.46elks.com/a1/SMS/s8952031bb83bf3e64f8e13b071c131c0").
|
256
|
-
with(:headers => {'Accept'=>'application/json'}).
|
257
|
-
to_return(fixture('reloads_a_sms.txt'))
|
258
|
-
|
259
|
-
configure_elk
|
260
|
-
|
261
|
-
sms_history = Elk::SMS.all
|
262
|
-
sms = sms_history[0]
|
263
|
-
loaded_at = sms.loaded_at
|
264
|
-
object_id = sms.object_id
|
265
|
-
sms.reload.should == true
|
266
|
-
sms.object_id.should == object_id
|
267
|
-
sms.loaded_at.should_not == loaded_at
|
268
|
-
end
|
269
|
-
|
270
|
-
it 'should warn about capped sms sender' do
|
271
|
-
stub_request(:post, "https://USERNAME:PASSWORD@api.46elks.com/a1/SMS").
|
272
|
-
with(:body => {"from" => "VeryVeryVeryVeryLongSenderName", :message => "Your order #171 has now been sent!", :to => "+46704508449"},
|
273
|
-
:headers => {'Accept'=>'application/json', 'Content-Type'=>'application/x-www-form-urlencoded'}).
|
274
|
-
to_return(fixture('sends_a_sms_with_long_sender.txt'))
|
275
|
-
|
276
|
-
configure_elk
|
277
|
-
|
278
|
-
# Fake $stderr to check warnings
|
279
|
-
begin
|
280
|
-
old_stderr, $stderr = $stderr, StringIO.new
|
281
|
-
|
282
|
-
sms = Elk::SMS.send(:from => 'VeryVeryVeryVeryLongSenderName',
|
283
|
-
:to => '+46704508449',
|
284
|
-
:message => 'Your order #171 has now been sent!')
|
285
|
-
|
286
|
-
$stderr.string.should == "SMS 'from' value VeryVeryVeryVeryLongSenderName will be capped at 11 chars\n"
|
287
|
-
ensure
|
288
|
-
$stderr = old_stderr
|
46
|
+
expect { Elk.base_url }.to_not raise_error(Elk::AuthError)
|
289
47
|
end
|
290
|
-
|
291
|
-
sms.class.should == Elk::SMS
|
292
|
-
sms.from.should == 'VeryVeryVeryVeryLongSenderName'
|
293
|
-
sms.to.should == '+46704508449'
|
294
|
-
sms.message.should == 'Your order #171 has now been sent!'
|
295
|
-
end
|
296
|
-
|
297
|
-
it 'should handle invalid to number' do
|
298
|
-
stub_request(:post, "https://USERNAME:PASSWORD@api.46elks.com/a1/SMS").
|
299
|
-
with(:body => {"from" => "+46761042247", :message => "Your order #171 has now been sent!", :to => "monkey"},
|
300
|
-
:headers => {'Accept'=>'application/json', 'Content-Type'=>'application/x-www-form-urlencoded'}).
|
301
|
-
to_return(fixture('invalid_to_number.txt'))
|
302
|
-
|
303
|
-
configure_elk
|
304
|
-
|
305
|
-
expect {
|
306
|
-
sms = Elk::SMS.send(:from => '+46761042247',
|
307
|
-
:to => 'monkey',
|
308
|
-
:message => 'Your order #171 has now been sent!')
|
309
|
-
}.to raise_error(Elk::BadRequest, 'Invalid to number')
|
310
48
|
end
|
49
|
+
end
|
311
50
|
|
312
|
-
|
313
|
-
|
51
|
+
it 'should handle garbage json' do
|
52
|
+
bad_response_body = fixture('bad_response_body.txt').read
|
314
53
|
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
end
|
54
|
+
expect {
|
55
|
+
Elk.parse_json(bad_response_body)
|
56
|
+
}.to raise_error(Elk::BadResponse)
|
319
57
|
end
|
320
|
-
end
|
58
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: elk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Johan Eckerstroem
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-09-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: multi_json
|
@@ -16,70 +16,70 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ~>
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.
|
19
|
+
version: '1.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ~>
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 1.
|
26
|
+
version: '1.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rest-client
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ~>
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 1.6
|
33
|
+
version: '1.6'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ~>
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 1.6
|
40
|
+
version: '1.6'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ~>
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0
|
47
|
+
version: '10.0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0
|
54
|
+
version: '10.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rspec
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 2.
|
61
|
+
version: '2.0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - ~>
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 2.
|
68
|
+
version: '2.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: webmock
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ~>
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: 1.
|
75
|
+
version: '1.0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - ~>
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: 1.
|
82
|
+
version: '1.0'
|
83
83
|
description: Elk can be used to allocate a phone numbers, manage the numbers and send
|
84
84
|
SMS through these numbers.
|
85
85
|
email: johan@duh.se
|
@@ -96,6 +96,8 @@ files:
|
|
96
96
|
- lib/elk/util.rb
|
97
97
|
- lib/elk/version.rb
|
98
98
|
- lib/elk.rb
|
99
|
+
- spec/elk/number_spec.rb
|
100
|
+
- spec/elk/sms_spec.rb
|
99
101
|
- spec/elk_spec.rb
|
100
102
|
- spec/fixtures/allocates_a_number.txt
|
101
103
|
- spec/fixtures/auth_error.txt
|
@@ -135,8 +137,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
135
137
|
requirements:
|
136
138
|
- API account at 46elks.com
|
137
139
|
rubyforge_project:
|
138
|
-
rubygems_version: 2.0.
|
140
|
+
rubygems_version: 2.0.3
|
139
141
|
signing_key:
|
140
142
|
specification_version: 4
|
141
143
|
summary: Client library for 46elks SMS/MMS/Voice service.
|
142
144
|
test_files: []
|
145
|
+
has_rdoc: true
|