nexmos 0.1
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.
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/.rvmrc +1 -0
- data/.travis.yml +7 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +22 -0
- data/README.md +67 -0
- data/Rakefile +6 -0
- data/lib/api.yml +113 -0
- data/lib/nexmos.rb +47 -0
- data/lib/nexmos/account.rb +5 -0
- data/lib/nexmos/base.rb +103 -0
- data/lib/nexmos/message.rb +5 -0
- data/lib/nexmos/number.rb +5 -0
- data/lib/nexmos/railties.rb +7 -0
- data/lib/nexmos/search.rb +5 -0
- data/lib/nexmos/version.rb +3 -0
- data/nexmos.gemspec +24 -0
- data/spec/nexmos/account_spec.rb +188 -0
- data/spec/nexmos/base_spec.rb +203 -0
- data/spec/nexmos/number_spec.rb +113 -0
- data/spec/nexmos_spec.rb +63 -0
- data/spec/spec_helper.rb +21 -0
- metadata +169 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use 1.9.3@nexmos --create
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Alexander Simonov
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# Nexmos [](https://travis-ci.org/phenomena/nexmos)[](https://codeclimate.com/github/phenomena/nexmos)
|
2
|
+
|
3
|
+
Nexmo API wrapper
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'nexmos'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install nexmos
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
### Send text message
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
# Nexmos specific client
|
25
|
+
client = ::Nexmos::Message.new('api-key', 'api-secret')
|
26
|
+
# get result from Nexmo
|
27
|
+
res = client.send_text(from: 'your number', to: '+1234567890', text: 'Hello world!')
|
28
|
+
# check if send is success
|
29
|
+
if res.success?
|
30
|
+
puts "ok"
|
31
|
+
else
|
32
|
+
puts "fail"
|
33
|
+
end
|
34
|
+
```
|
35
|
+
|
36
|
+
### Get balance
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
client = ::Nexmos::Account.new('api-key', 'api-secret')
|
40
|
+
res = client.get_balance
|
41
|
+
my_balance = res.value
|
42
|
+
```
|
43
|
+
|
44
|
+
## Rails integration
|
45
|
+
|
46
|
+
You can create `config/initializer/nexmos.rb` file with next content:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
Nexmos.setup do |n|
|
50
|
+
n.api_key = 'api_key'
|
51
|
+
n.api_secret = 'api_secret'
|
52
|
+
end
|
53
|
+
```
|
54
|
+
|
55
|
+
And then you can call all clients without providing key and secret.
|
56
|
+
|
57
|
+
## More details about api calls
|
58
|
+
|
59
|
+
More details about api calls you can found in the lib/api.yml file.
|
60
|
+
|
61
|
+
## Contributing
|
62
|
+
|
63
|
+
1. Fork it
|
64
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
65
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
66
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
67
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/lib/api.yml
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
:message:
|
2
|
+
:send_text:
|
3
|
+
:method: :get
|
4
|
+
:url: /sms/json
|
5
|
+
:required:
|
6
|
+
- from
|
7
|
+
- to
|
8
|
+
- text
|
9
|
+
:send_binary:
|
10
|
+
:method: :get
|
11
|
+
:url: /sms/json
|
12
|
+
:required:
|
13
|
+
- body
|
14
|
+
- udh
|
15
|
+
:params:
|
16
|
+
type: binary
|
17
|
+
:wap_push:
|
18
|
+
:method: :get
|
19
|
+
:url: /sms/json
|
20
|
+
:required:
|
21
|
+
- title
|
22
|
+
- url
|
23
|
+
:optional:
|
24
|
+
- validity
|
25
|
+
:params:
|
26
|
+
type: wappush
|
27
|
+
:search:
|
28
|
+
:message:
|
29
|
+
:method: :get
|
30
|
+
:url: /search/message
|
31
|
+
:required:
|
32
|
+
- id
|
33
|
+
:messages:
|
34
|
+
:method: :get
|
35
|
+
:url: /search/messages
|
36
|
+
:optional:
|
37
|
+
- ids
|
38
|
+
- date
|
39
|
+
- to
|
40
|
+
:rejections:
|
41
|
+
:method: :get
|
42
|
+
:url: /search/rejections
|
43
|
+
:required:
|
44
|
+
- date
|
45
|
+
:optional:
|
46
|
+
- to
|
47
|
+
:account:
|
48
|
+
:get_balance:
|
49
|
+
:method: :get
|
50
|
+
:url: /account/get-balance
|
51
|
+
:return: value
|
52
|
+
:get_pricing:
|
53
|
+
:method: :get
|
54
|
+
:url: /account/get-pricing/outbound
|
55
|
+
:required:
|
56
|
+
- country
|
57
|
+
:get_prefix_pricing:
|
58
|
+
:method: :get
|
59
|
+
:url: /account/get-prefix-pricing/outbound
|
60
|
+
:required:
|
61
|
+
- prefix
|
62
|
+
:settings:
|
63
|
+
:method: :post
|
64
|
+
:url: /account/settings
|
65
|
+
:optional:
|
66
|
+
- new_secret
|
67
|
+
- mo_call_back_url
|
68
|
+
- dr_call_back_url
|
69
|
+
:camelize: true
|
70
|
+
:get_numbers:
|
71
|
+
:method: :get
|
72
|
+
:url: /account/numbers
|
73
|
+
:optional:
|
74
|
+
- index
|
75
|
+
- size
|
76
|
+
- pattern
|
77
|
+
:top_up:
|
78
|
+
:method: :get
|
79
|
+
:url: /account/top-up
|
80
|
+
:required:
|
81
|
+
- trx
|
82
|
+
:number:
|
83
|
+
:search:
|
84
|
+
:method: :get
|
85
|
+
:url: /number/search
|
86
|
+
:required:
|
87
|
+
- country
|
88
|
+
:optional:
|
89
|
+
- pattern
|
90
|
+
- index
|
91
|
+
- size
|
92
|
+
:buy:
|
93
|
+
:method: :post
|
94
|
+
:url: /number/buy
|
95
|
+
:required:
|
96
|
+
- country
|
97
|
+
- msisdn
|
98
|
+
:cancel:
|
99
|
+
:method: :post
|
100
|
+
:url: /number/cancel
|
101
|
+
:required:
|
102
|
+
- country
|
103
|
+
- msisdn
|
104
|
+
:update:
|
105
|
+
:method: :post
|
106
|
+
:url: /number/update
|
107
|
+
:required:
|
108
|
+
- country
|
109
|
+
- msisdn
|
110
|
+
:optional:
|
111
|
+
- mo_http_url
|
112
|
+
- mo_smpp_sys_type
|
113
|
+
:camelize: true
|
data/lib/nexmos.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'active_support/core_ext/hash'
|
3
|
+
require 'faraday'
|
4
|
+
require 'faraday_middleware'
|
5
|
+
require 'nexmos/version'
|
6
|
+
require 'nexmos/base'
|
7
|
+
module Nexmos
|
8
|
+
extend self
|
9
|
+
attr_accessor :api_key, :api_secret, :debug
|
10
|
+
attr_writer :user_agent, :logger
|
11
|
+
|
12
|
+
# ensures the setup only gets run once
|
13
|
+
@_ran_once = false
|
14
|
+
|
15
|
+
def reset!
|
16
|
+
@logger = nil
|
17
|
+
@_ran_once = false
|
18
|
+
@user_agent = nil
|
19
|
+
@api_key = nil
|
20
|
+
@api_secret = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def user_agent
|
24
|
+
@user_agent ||= "Nexmos v#{::Nexmos::VERSION}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def setup
|
28
|
+
yield self unless @_ran_once
|
29
|
+
@_ran_once = true
|
30
|
+
end
|
31
|
+
|
32
|
+
def logger
|
33
|
+
@logger ||= Logger.new(STDOUT)
|
34
|
+
end
|
35
|
+
|
36
|
+
def apis
|
37
|
+
@apis ||= YAML.load_file(File.expand_path('api.yml', File.dirname(__FILE__)))
|
38
|
+
end
|
39
|
+
|
40
|
+
reset!
|
41
|
+
end
|
42
|
+
|
43
|
+
require 'nexmos/railties' if defined?(::Rails)
|
44
|
+
require 'nexmos/account'
|
45
|
+
require 'nexmos/message'
|
46
|
+
require 'nexmos/number'
|
47
|
+
require 'nexmos/search'
|
data/lib/nexmos/base.rb
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
module Nexmos
|
2
|
+
class Base
|
3
|
+
|
4
|
+
def initialize(key = ::Nexmos.api_key, secret = ::Nexmos.api_secret)
|
5
|
+
raise 'api_key should be set' if !key.present?
|
6
|
+
raise 'api_secret should be set' if !secret.present?
|
7
|
+
@default_params = {
|
8
|
+
'api_key' => key,
|
9
|
+
'api_secret' => secret
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
def connection
|
14
|
+
self.class.connection.dup
|
15
|
+
end
|
16
|
+
|
17
|
+
def make_api_call(args, params = {})
|
18
|
+
normalize_params(params)
|
19
|
+
check_required_params(args, params)
|
20
|
+
camelize_params(params) if args[:camelize]
|
21
|
+
params.merge!(@default_params)
|
22
|
+
get_response(args, params)
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_response(args, params)
|
26
|
+
method = args[:method]
|
27
|
+
url = args[:url]
|
28
|
+
raise 'url or method params missing' if !method.present? || !url.present?
|
29
|
+
res = connection.__send__(method, url, params)
|
30
|
+
if res.success?
|
31
|
+
data = if res.body.is_a?(::Hash)
|
32
|
+
res.body.merge(:success? => true)
|
33
|
+
else
|
34
|
+
::Hashie::Mash.new({:success? => true})
|
35
|
+
end
|
36
|
+
return data
|
37
|
+
end
|
38
|
+
failed_res = ::Hashie::Mash.new({:success? => false, :not_authorized? => false, :failed? => false})
|
39
|
+
case res.status
|
40
|
+
when 401
|
41
|
+
failed_res.merge! :not_authorized? => true
|
42
|
+
when 420
|
43
|
+
failed_res.merge! :failed? => true
|
44
|
+
end
|
45
|
+
failed_res
|
46
|
+
end
|
47
|
+
|
48
|
+
def normalize_params(params)
|
49
|
+
params.stringify_keys!
|
50
|
+
end
|
51
|
+
|
52
|
+
def camelize_params(params)
|
53
|
+
if params.respond_to?(:transform_keys!)
|
54
|
+
params.transform_keys!{|key| key.camelize(:lower)}
|
55
|
+
else
|
56
|
+
params.keys.each do |key|
|
57
|
+
params[key.camelize(:lower)] = params.delete(key)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def check_required_params(args, params)
|
63
|
+
if args[:required]
|
64
|
+
required = params.slice(*args[:required])
|
65
|
+
unless required.keys.sort == args[:required].sort
|
66
|
+
missed = (args[:required] - required.keys).join(',')
|
67
|
+
raise ArgumentError, "#{missed} params required"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
class << self
|
73
|
+
|
74
|
+
def define_api_calls(key)
|
75
|
+
::Nexmos.apis[key].each do |k,v|
|
76
|
+
define_method(k) do |*args|
|
77
|
+
params = args[0] || {}
|
78
|
+
make_api_call(v, params)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def faraday_options
|
84
|
+
{
|
85
|
+
:url => 'https://rest.nexmo.com',
|
86
|
+
:headers => {
|
87
|
+
:accept => 'application/json',
|
88
|
+
:user_agent => ::Nexmos.user_agent
|
89
|
+
}
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
93
|
+
def connection
|
94
|
+
@connection ||= Faraday::Connection.new(faraday_options) do |conn|
|
95
|
+
conn.request :url_encoded
|
96
|
+
conn.response :rashify
|
97
|
+
conn.response :json, :content_type => /\bjson$/
|
98
|
+
conn.adapter Faraday.default_adapter
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end # self
|
102
|
+
end # Base
|
103
|
+
end # Nexmos
|
data/nexmos.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'nexmos/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "nexmos"
|
8
|
+
gem.version = Nexmos::VERSION
|
9
|
+
gem.authors = ["Alexander Simonov"]
|
10
|
+
gem.email = ["alex@simonov.me"]
|
11
|
+
gem.description = %q{Nexmo API client}
|
12
|
+
gem.summary = %q{Nexmo API client}
|
13
|
+
gem.homepage = "https://github.com/simonoff/nexmos"
|
14
|
+
gem.files = `git ls-files`.split($/)
|
15
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
16
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
17
|
+
gem.require_paths = ["lib"]
|
18
|
+
gem.add_dependency('rash')
|
19
|
+
gem.add_dependency('faraday')
|
20
|
+
gem.add_dependency('faraday_middleware')
|
21
|
+
gem.add_dependency('activesupport', '>= 3.0.0')
|
22
|
+
gem.add_development_dependency('rspec')
|
23
|
+
gem.add_development_dependency('webmock')
|
24
|
+
end
|
@@ -0,0 +1,188 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe ::Nexmos::Account do
|
3
|
+
let(:webmock_default_headers) do
|
4
|
+
{
|
5
|
+
:headers => {
|
6
|
+
'Accept' => 'application/json',
|
7
|
+
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
|
8
|
+
'User-Agent' => ::Nexmos.user_agent
|
9
|
+
}
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:finland_prices) do
|
14
|
+
{
|
15
|
+
"mt" => "0.02500000",
|
16
|
+
"country" => "FI",
|
17
|
+
"prefix" => "358",
|
18
|
+
"networks" =>
|
19
|
+
[{"code" => "24491",
|
20
|
+
"network" => "sonera, TeleFinland",
|
21
|
+
"ranges" => ["35840", "35842", "358450"],
|
22
|
+
"mtPrice" => "0.04500000"},
|
23
|
+
{"code" => "24414",
|
24
|
+
"network" => "GSM Aland",
|
25
|
+
"ranges" => ["3584570", "3584573", "3584575"],
|
26
|
+
"mtPrice" => "0.00850000"},
|
27
|
+
{"code" => "24421",
|
28
|
+
"network" => "SAUNALAHTI, EUnet Finland",
|
29
|
+
"ranges" => ["358451", "358452", "358453", "358456", "358458"],
|
30
|
+
"mtPrice" => "0.05000000"},
|
31
|
+
{"code" => "24412",
|
32
|
+
"network" => "dna",
|
33
|
+
"ranges" =>
|
34
|
+
["35841",
|
35
|
+
"35844",
|
36
|
+
"3584574",
|
37
|
+
"3584576",
|
38
|
+
"3584577",
|
39
|
+
"3584578",
|
40
|
+
"3584579",
|
41
|
+
"3584944"],
|
42
|
+
"mtPrice" => "0.00850000"},
|
43
|
+
{"code" => "24405",
|
44
|
+
"network" => "elisa",
|
45
|
+
"ranges" => ["35846", "35850"],
|
46
|
+
"mtPrice" => "0.05000000"}],
|
47
|
+
"name" => "Finland"
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
let(:prefix_prices) do
|
52
|
+
{"count" => 1,
|
53
|
+
"prices" =>
|
54
|
+
[{"mt" => "0.02500000",
|
55
|
+
"country" => "FI",
|
56
|
+
"prefix" => "358",
|
57
|
+
"networks" =>
|
58
|
+
[{"code" => "24491",
|
59
|
+
"network" => "sonera, TeleFinland",
|
60
|
+
"ranges" => nil,
|
61
|
+
"mt_price" => "0.04500000"},
|
62
|
+
{"code" => "24414",
|
63
|
+
"network" => "GSM Aland",
|
64
|
+
"ranges" => nil,
|
65
|
+
"mtPrice" => "0.00850000"},
|
66
|
+
{"code" => "24400",
|
67
|
+
"network" => "Unknown Finland",
|
68
|
+
"ranges" => nil,
|
69
|
+
"mtPrice" => "0.02500000"},
|
70
|
+
{"code" => "24421",
|
71
|
+
"network" => "SAUNALAHTI, EUnet Finland",
|
72
|
+
"ranges" => nil,
|
73
|
+
"mtPrice" => "0.05000000"},
|
74
|
+
{"code" => "24412",
|
75
|
+
"network" => "dna",
|
76
|
+
"ranges" => nil,
|
77
|
+
"mtPrice" => "0.00850000"},
|
78
|
+
{"code" => "24405",
|
79
|
+
"network" => "elisa",
|
80
|
+
"ranges" => nil,
|
81
|
+
"mtPrice" => "0.05000000"}],
|
82
|
+
"name" => "Finland"}],
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
before(:each) do
|
87
|
+
::Nexmos.reset!
|
88
|
+
::Nexmos.setup do |c|
|
89
|
+
c.api_key = 'default_key'
|
90
|
+
c.api_secret = 'default_secret'
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
subject { ::Nexmos::Account.new }
|
95
|
+
|
96
|
+
context '#get_balance' do
|
97
|
+
|
98
|
+
it 'should return value' do
|
99
|
+
request = stub_request(:get, "https://rest.nexmo.com/account/get-balance?api_key=default_key&api_secret=default_secret").
|
100
|
+
with(webmock_default_headers).to_return(:status => 200, :body => {"value" => 4.107}, :headers => {})
|
101
|
+
res = subject.get_balance
|
102
|
+
res.should be_kind_of(::Hash)
|
103
|
+
res.value.should == 4.107
|
104
|
+
request.should have_been_made.once
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context '#get_pricing' do
|
109
|
+
it 'should return error on missed param' do
|
110
|
+
expect { subject.get_pricing }.to raise_error('country params required')
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'should be success' do
|
114
|
+
request = stub_request(:get, "https://rest.nexmo.com/account/get-pricing/outbound?api_key=default_key&api_secret=default_secret&country=FI").
|
115
|
+
with(webmock_default_headers).to_return(:status => 200, :body => finland_prices, :headers => {})
|
116
|
+
res = subject.get_pricing(:country => 'FI')
|
117
|
+
res.should be_kind_of(::Hash)
|
118
|
+
res.success?.should be_true
|
119
|
+
res.country.should == 'FI'
|
120
|
+
res.keys.sort.should == %w(country name prefix mt networks success?).sort
|
121
|
+
res.networks.should be_kind_of(::Array)
|
122
|
+
res.networks[0].keys.sort.should == %w(code network mt_price ranges).sort
|
123
|
+
request.should have_been_made.once
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
context '#get_prefix_pricing' do
|
128
|
+
it 'should return error on missed param' do
|
129
|
+
expect { subject.get_prefix_pricing }.to raise_error('prefix params required')
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'should be success' do
|
133
|
+
request = stub_request(:get, "https://rest.nexmo.com/account/get-prefix-pricing/outbound?api_key=default_key&api_secret=default_secret&prefix=358").
|
134
|
+
with(webmock_default_headers).to_return(:status => 200, :body => prefix_prices, :headers => {})
|
135
|
+
res = subject.get_prefix_pricing(:prefix => '358')
|
136
|
+
res.should be_kind_of(::Hash)
|
137
|
+
res.success?.should be_true
|
138
|
+
res.keys.sort.should == %w(count prices success?).sort
|
139
|
+
res.prices.should be_kind_of(::Array)
|
140
|
+
res.prices[0].keys.sort.should == %w(country name prefix mt networks).sort
|
141
|
+
res.prices[0].networks.should be_kind_of(::Array)
|
142
|
+
res.prices[0].networks[0].keys.sort.should == %w(code network mt_price ranges).sort
|
143
|
+
request.should have_been_made.once
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
context '#get_numbers' do
|
148
|
+
it 'should return only count on empty numbers' do
|
149
|
+
request = stub_request(:get, "https://rest.nexmo.com/account/numbers?api_key=default_key&api_secret=default_secret").
|
150
|
+
with(webmock_default_headers).to_return(:status => 200, :body => {:count => 0}, :headers => {})
|
151
|
+
res = subject.get_numbers
|
152
|
+
res.should be_kind_of(::Hash)
|
153
|
+
res.success?.should be_true
|
154
|
+
res['count'].should == 0
|
155
|
+
request.should have_been_made.once
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'should return numbers array' do
|
159
|
+
request = stub_request(:get, "https://rest.nexmo.com/account/numbers?api_key=default_key&api_secret=default_secret").
|
160
|
+
with(webmock_default_headers).to_return(:status => 200, :body => { "count" => 1,"numbers" => [{"country" => "ES","msisdn" => "34911067000","type" => "landline"}]}, :headers => {})
|
161
|
+
res = subject.get_numbers
|
162
|
+
res.should be_kind_of(::Hash)
|
163
|
+
res.success?.should be_true
|
164
|
+
res['count'].should == 1
|
165
|
+
res['numbers'].should be_kind_of(::Array)
|
166
|
+
res['numbers'].first.should be_kind_of(::Hash)
|
167
|
+
res['numbers'].first.should == {"country" => "ES","msisdn" => "34911067000","type" => "landline"}
|
168
|
+
request.should have_been_made.once
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
context '#top_up' do
|
173
|
+
it 'should return error on missed param' do
|
174
|
+
expect { subject.top_up }.to raise_error('trx params required')
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'should success top up' do
|
178
|
+
request = stub_request(:get, "https://rest.nexmo.com/account/top-up?api_key=default_key&api_secret=default_secret&trx=test_trx").
|
179
|
+
with(webmock_default_headers).to_return(:status => 200, :body => '', :headers => {})
|
180
|
+
res = subject.top_up :trx => 'test_trx'
|
181
|
+
res.should be_kind_of(::Hash)
|
182
|
+
res.success?.should be_true
|
183
|
+
request.should have_been_made.once
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
@@ -0,0 +1,203 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe ::Nexmos::Base do
|
3
|
+
|
4
|
+
let(:webmock_default_headers) do
|
5
|
+
{
|
6
|
+
:headers => {
|
7
|
+
'Accept'=>'application/json',
|
8
|
+
'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
|
9
|
+
'User-Agent'=> ::Nexmos.user_agent
|
10
|
+
}
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
before(:each) do
|
15
|
+
::Nexmos.reset!
|
16
|
+
end
|
17
|
+
context 'class' do
|
18
|
+
subject { ::Nexmos::Base }
|
19
|
+
let(:default_faraday_options) do
|
20
|
+
{
|
21
|
+
:url => 'https://rest.nexmo.com',
|
22
|
+
:headers => {
|
23
|
+
:accept => 'application/json',
|
24
|
+
:user_agent => ::Nexmos.user_agent
|
25
|
+
}
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
its(:faraday_options) { should == default_faraday_options }
|
30
|
+
its(:connection) { should be_kind_of(::Faraday::Connection) }
|
31
|
+
|
32
|
+
context 'faraday_options' do
|
33
|
+
it 'should have custom user agent' do
|
34
|
+
::Nexmos.setup do |c|
|
35
|
+
c.user_agent = 'test user agent'
|
36
|
+
end
|
37
|
+
default_faraday_options[:headers][:user_agent] = 'test user agent'
|
38
|
+
subject.faraday_options.should == default_faraday_options
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'define_api_calls' do
|
43
|
+
it 'should call define_method' do
|
44
|
+
::Nexmos.apis[:account].keys.each do |k|
|
45
|
+
subject.should_receive(:define_method).with(k)
|
46
|
+
end
|
47
|
+
subject.define_api_calls(:account)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should define dynamic method and call make_api_call inside' do
|
51
|
+
subject.define_api_calls(:account)
|
52
|
+
instance = subject.new('test_key', 'test_secret')
|
53
|
+
instance.should_receive(:make_api_call).with(::Nexmos.apis[:account][:get_balance], {})
|
54
|
+
instance.get_balance
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'instance' do
|
61
|
+
subject { ::Nexmos::Base.new('test_api', 'test_secret') }
|
62
|
+
context 'new' do
|
63
|
+
it 'should raise on empty api_key' do
|
64
|
+
expect {::Nexmos::Base.new('', 'test_secret')}.to raise_error('api_key should be set')
|
65
|
+
end
|
66
|
+
it 'should raise on empty api_secret' do
|
67
|
+
expect {::Nexmos::Base.new('test_key', '')}.to raise_error('api_secret should be set')
|
68
|
+
end
|
69
|
+
it 'should set default_params with values from ::Nexmos module' do
|
70
|
+
::Nexmos.setup do |c|
|
71
|
+
c.api_key = 'default_key'
|
72
|
+
c.api_secret = 'default_secret'
|
73
|
+
end
|
74
|
+
instance = ::Nexmos::Base.new
|
75
|
+
instance.instance_variable_get('@default_params').should == {'api_key' => 'default_key', 'api_secret' => 'default_secret'}
|
76
|
+
end
|
77
|
+
it 'should set default_params with custom api key and secret' do
|
78
|
+
instance = ::Nexmos::Base.new('test_key', 'test_secret')
|
79
|
+
instance.instance_variable_get('@default_params').should == {'api_key' => 'test_key', 'api_secret' => 'test_secret'}
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
its(:connection) { should be_kind_of(::Faraday::Connection) }
|
84
|
+
|
85
|
+
context 'make_api_call' do
|
86
|
+
|
87
|
+
before(:each) do
|
88
|
+
stub_request(:get, "https://rest.nexmo.com/test/url?api_key=test_api&api_secret=test_secret").
|
89
|
+
with(:headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=> ::Nexmos.user_agent}).
|
90
|
+
to_return(:status => 200, :body => {'key' => 'value'}, :headers => {})
|
91
|
+
end
|
92
|
+
|
93
|
+
let(:api_params_without_required) do
|
94
|
+
{
|
95
|
+
:method => :get,
|
96
|
+
:url => '/test/url'
|
97
|
+
}
|
98
|
+
end
|
99
|
+
|
100
|
+
let(:api_params_with_required) do
|
101
|
+
{
|
102
|
+
:method => :get,
|
103
|
+
:url => '/test/url',
|
104
|
+
:required => %w(key1 key2)
|
105
|
+
}
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'should call check_required_params' do
|
109
|
+
subject.should_receive(:check_required_params)
|
110
|
+
subject.make_api_call(api_params_with_required)
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'should raise if all required params missing' do
|
114
|
+
expect{subject.make_api_call(api_params_with_required)}.to raise_error('key1,key2 params required')
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'should raise if some required params missing' do
|
118
|
+
expect{subject.make_api_call(api_params_with_required,{:key1 => 'val'})}.to raise_error('key2 params required')
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'should call normalize_params' do
|
122
|
+
subject.should_receive(:normalize_params).and_call_original
|
123
|
+
subject.make_api_call(api_params_without_required)
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'should not call camelize_params' do
|
127
|
+
stub_request(:get, "https://rest.nexmo.com/test/url?api_key=test_api&api_secret=test_secret&test_call=value").
|
128
|
+
with(webmock_default_headers).
|
129
|
+
to_return(:status => 200, :body => {}, :headers => {})
|
130
|
+
subject.should_not_receive(:camelize_params)
|
131
|
+
subject.make_api_call(api_params_without_required, {'test_call' => 'value'})
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'should call camelize_params' do
|
135
|
+
stub_request(:get, "https://rest.nexmo.com/test/url?api_key=test_api&api_secret=test_secret&testCall=value").
|
136
|
+
with(webmock_default_headers).
|
137
|
+
to_return(:status => 200, :body => {}, :headers => {})
|
138
|
+
subject.should_receive(:camelize_params).and_call_original
|
139
|
+
subject.make_api_call(api_params_without_required.merge(:camelize => true), {'test_call' => 'value'})
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'should call get_response' do
|
143
|
+
stub_request(:get, "https://rest.nexmo.com/test/url?api_key=test_api&api_secret=test_secret").
|
144
|
+
with(webmock_default_headers).
|
145
|
+
to_return(:status => 200, :body => {}, :headers => {})
|
146
|
+
subject.should_receive(:get_response).and_call_original
|
147
|
+
subject.make_api_call(api_params_without_required)
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'should return hash' do
|
151
|
+
subject.make_api_call(api_params_without_required).should be_a_kind_of(::Hash)
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'should return Hashie::Mash' do
|
155
|
+
subject.make_api_call(api_params_without_required).should be_a_kind_of(::Hashie::Mash)
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'should respond to success? method in result' do
|
159
|
+
subject.make_api_call(api_params_without_required).should respond_to(:success?)
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'should have success? key in hash' do
|
163
|
+
subject.make_api_call(api_params_without_required)[:success?].should be
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'should have success? == true' do
|
167
|
+
subject.make_api_call(api_params_without_required)[:success?].should be_true
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'should have success? == false on response with status != 200' do
|
171
|
+
stub_request(:get, "https://rest.nexmo.com/test/url?api_key=test_api&api_secret=test_secret&testCall=value").
|
172
|
+
with(webmock_default_headers).
|
173
|
+
to_return(:status => 410, :body => {}, :headers => {})
|
174
|
+
res = subject.make_api_call(api_params_without_required.merge(:camelize => true), {'test_call' => 'value'})
|
175
|
+
res[:success?].should be_false
|
176
|
+
res[:failed?].should be_false
|
177
|
+
res[:not_authorized?].should be_false
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'should have not_authorized? == true' do
|
181
|
+
stub_request(:get, "https://rest.nexmo.com/test/url?api_key=test_api&api_secret=test_secret&testCall=value").
|
182
|
+
with(webmock_default_headers).
|
183
|
+
to_return(:status => 401, :body => {}, :headers => {})
|
184
|
+
res = subject.make_api_call(api_params_without_required.merge(:camelize => true), {'test_call' => 'value'})
|
185
|
+
res[:success?].should be_false
|
186
|
+
res[:not_authorized?].should be_true
|
187
|
+
res[:failed?].should be_false
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'should have failed? == true' do
|
191
|
+
stub_request(:get, "https://rest.nexmo.com/test/url?api_key=test_api&api_secret=test_secret&testCall=value").
|
192
|
+
with(webmock_default_headers).
|
193
|
+
to_return(:status => 420, :body => {}, :headers => {})
|
194
|
+
res = subject.make_api_call(api_params_without_required.merge(:camelize => true), {'test_call' => 'value'})
|
195
|
+
res[:success?].should be_false
|
196
|
+
res[:not_authorized?].should be_false
|
197
|
+
res[:failed?].should be_true
|
198
|
+
end
|
199
|
+
|
200
|
+
end
|
201
|
+
|
202
|
+
end
|
203
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe ::Nexmos::Number do
|
3
|
+
let(:webmock_default_headers) do
|
4
|
+
{
|
5
|
+
:headers => {
|
6
|
+
'Accept' => 'application/json',
|
7
|
+
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
|
8
|
+
'User-Agent' => ::Nexmos.user_agent
|
9
|
+
}
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:finland_numbers_search) do
|
14
|
+
{"numbers" => [
|
15
|
+
{"type" => "mobile-lvn",
|
16
|
+
"msisdn" => "3584573950816",
|
17
|
+
"country" => "FI",
|
18
|
+
"cost" => "3.00"},
|
19
|
+
{"type" => "mobile-lvn",
|
20
|
+
"msisdn" => "3584573950815",
|
21
|
+
"country" => "FI",
|
22
|
+
"cost" => "3.00"},
|
23
|
+
{"type" => "mobile-lvn",
|
24
|
+
"msisdn" => "3584573950814",
|
25
|
+
"country" => "FI",
|
26
|
+
"cost" => "3.00"},
|
27
|
+
{"type" => "mobile-lvn",
|
28
|
+
"msisdn" => "3584573950813",
|
29
|
+
"country" => "FI",
|
30
|
+
"cost" => "3.00"},
|
31
|
+
{"type" => "mobile-lvn",
|
32
|
+
"msisdn" => "3584573950812",
|
33
|
+
"country" => "FI",
|
34
|
+
"cost" => "3.00"},
|
35
|
+
{"type" => "mobile-lvn",
|
36
|
+
"msisdn" => "3584573950806",
|
37
|
+
"country" => "FI",
|
38
|
+
"cost" => "3.00"},
|
39
|
+
{"type" => "mobile-lvn",
|
40
|
+
"msisdn" => "3584573950805",
|
41
|
+
"country" => "FI",
|
42
|
+
"cost" => "3.00"},
|
43
|
+
{"type" => "mobile-lvn",
|
44
|
+
"msisdn" => "3584573950804",
|
45
|
+
"country" => "FI",
|
46
|
+
"cost" => "3.00"},
|
47
|
+
{"type" => "mobile-lvn",
|
48
|
+
"msisdn" => "3584573950798",
|
49
|
+
"country" => "FI",
|
50
|
+
"cost" => "3.00"},
|
51
|
+
{"type" => "mobile-lvn",
|
52
|
+
"msisdn" => "3584573950796",
|
53
|
+
"country" => "FI",
|
54
|
+
"cost" => "3.00"}],
|
55
|
+
"count" => 22}
|
56
|
+
end
|
57
|
+
|
58
|
+
before(:each) do
|
59
|
+
::Nexmos.reset!
|
60
|
+
::Nexmos.setup do |c|
|
61
|
+
c.api_key = 'default_key'
|
62
|
+
c.api_secret = 'default_secret'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
subject { ::Nexmos::Number.new }
|
67
|
+
|
68
|
+
context '#search' do
|
69
|
+
it 'should return error on missed param' do
|
70
|
+
expect { subject.search }.to raise_error('country params required')
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should return list of numbers' do
|
74
|
+
request = stub_request(:get, "https://rest.nexmo.com/number/search?api_key=default_key&api_secret=default_secret&country=FI").
|
75
|
+
with(webmock_default_headers).to_return(:status => 200, :body => finland_numbers_search, :headers => {})
|
76
|
+
res = subject.search(:country => 'FI')
|
77
|
+
res.should be_kind_of(::Hash)
|
78
|
+
res.success?.should be_true
|
79
|
+
res['count'].should == 22
|
80
|
+
res['numbers'].should be_kind_of(::Array)
|
81
|
+
res['numbers'].size.should == 10
|
82
|
+
res['numbers'].first.keys.sort.should == ["cost", "country", "msisdn", "type"]
|
83
|
+
request.should have_been_made.once
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context '#buy' do
|
88
|
+
it 'should return error on missed params' do
|
89
|
+
expect { subject.buy }.to raise_error('country,msisdn params required')
|
90
|
+
end
|
91
|
+
it 'should return error on missed params' do
|
92
|
+
expect { subject.buy :country => 'FI' }.to raise_error('msisdn params required')
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'should buy number' do
|
96
|
+
request = stub_request(:post, "https://rest.nexmo.com/number/buy").
|
97
|
+
with(
|
98
|
+
:headers => {'Accept'=>'application/json', 'Content-Type'=>'application/x-www-form-urlencoded', 'User-Agent'=> ::Nexmos.user_agent},
|
99
|
+
:body => {"api_key"=>"default_key", "api_secret"=>"default_secret", "country"=>"FI", "msisdn"=>"3584573950816"}
|
100
|
+
).to_return(:status => 200, :body => "", :headers => {})
|
101
|
+
res = subject.buy(:country => 'FI', :msisdn => '3584573950816' )
|
102
|
+
res.should be_kind_of(::Hash)
|
103
|
+
res.success?.should be_true
|
104
|
+
request.should have_been_made.once
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
context '#cancel' do
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
data/spec/nexmos_spec.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe ::Nexmos do
|
3
|
+
subject{ ::Nexmos }
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
subject.reset!
|
7
|
+
end
|
8
|
+
|
9
|
+
context '#reset!' do
|
10
|
+
its(:user_agent) { should == "Nexmos v#{::Nexmos::VERSION}" }
|
11
|
+
its(:api_key) { should be_nil }
|
12
|
+
its(:api_secret) { should be_nil }
|
13
|
+
its(:logger) { should be_kind_of(::Logger) }
|
14
|
+
end
|
15
|
+
|
16
|
+
context '#setup' do
|
17
|
+
|
18
|
+
context 'single call' do
|
19
|
+
it 'should set user_agent' do
|
20
|
+
subject.setup do |c|
|
21
|
+
c.user_agent = 'Test1245'
|
22
|
+
end
|
23
|
+
subject.user_agent.should == 'Test1245'
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should set logger' do
|
27
|
+
newlogger = ::Logger.new(STDERR)
|
28
|
+
subject.setup do |c|
|
29
|
+
c.logger = newlogger
|
30
|
+
end
|
31
|
+
subject.logger.should == newlogger
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should set api_key' do
|
35
|
+
subject.setup do |c|
|
36
|
+
c.api_key = 'test-api-key'
|
37
|
+
end
|
38
|
+
subject.api_key.should == 'test-api-key'
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should set api_secret' do
|
42
|
+
subject.setup do |c|
|
43
|
+
c.api_secret = 'test-api-secret'
|
44
|
+
end
|
45
|
+
subject.api_secret.should == 'test-api-secret'
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'double call' do
|
51
|
+
it 'should not accept running setup more then once' do
|
52
|
+
subject.setup do |c|
|
53
|
+
c.api_key = 'test-api-key'
|
54
|
+
end
|
55
|
+
subject.setup do |c|
|
56
|
+
c.api_key = 'test-api-key2'
|
57
|
+
end
|
58
|
+
subject.api_key.should == 'test-api-key'
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
require 'webmock'
|
8
|
+
require 'webmock/rspec'
|
9
|
+
require 'nexmos'
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
13
|
+
config.run_all_when_everything_filtered = true
|
14
|
+
config.filter_run :focus
|
15
|
+
|
16
|
+
# Run specs in random order to surface order dependencies. If you find an
|
17
|
+
# order dependency and want to debug it, you can fix the order by providing
|
18
|
+
# the seed, which is printed after each run.
|
19
|
+
# --seed 1234
|
20
|
+
config.order = 'random'
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nexmos
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Alexander Simonov
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-02-26 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rash
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: faraday
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: faraday_middleware
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: activesupport
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 3.0.0
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 3.0.0
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rspec
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: webmock
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
description: Nexmo API client
|
111
|
+
email:
|
112
|
+
- alex@simonov.me
|
113
|
+
executables: []
|
114
|
+
extensions: []
|
115
|
+
extra_rdoc_files: []
|
116
|
+
files:
|
117
|
+
- .gitignore
|
118
|
+
- .rspec
|
119
|
+
- .rvmrc
|
120
|
+
- .travis.yml
|
121
|
+
- Gemfile
|
122
|
+
- LICENSE.txt
|
123
|
+
- README.md
|
124
|
+
- Rakefile
|
125
|
+
- lib/api.yml
|
126
|
+
- lib/nexmos.rb
|
127
|
+
- lib/nexmos/account.rb
|
128
|
+
- lib/nexmos/base.rb
|
129
|
+
- lib/nexmos/message.rb
|
130
|
+
- lib/nexmos/number.rb
|
131
|
+
- lib/nexmos/railties.rb
|
132
|
+
- lib/nexmos/search.rb
|
133
|
+
- lib/nexmos/version.rb
|
134
|
+
- nexmos.gemspec
|
135
|
+
- spec/nexmos/account_spec.rb
|
136
|
+
- spec/nexmos/base_spec.rb
|
137
|
+
- spec/nexmos/number_spec.rb
|
138
|
+
- spec/nexmos_spec.rb
|
139
|
+
- spec/spec_helper.rb
|
140
|
+
homepage: https://github.com/simonoff/nexmos
|
141
|
+
licenses: []
|
142
|
+
post_install_message:
|
143
|
+
rdoc_options: []
|
144
|
+
require_paths:
|
145
|
+
- lib
|
146
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
147
|
+
none: false
|
148
|
+
requirements:
|
149
|
+
- - ! '>='
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
152
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ! '>='
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
158
|
+
requirements: []
|
159
|
+
rubyforge_project:
|
160
|
+
rubygems_version: 1.8.24
|
161
|
+
signing_key:
|
162
|
+
specification_version: 3
|
163
|
+
summary: Nexmo API client
|
164
|
+
test_files:
|
165
|
+
- spec/nexmos/account_spec.rb
|
166
|
+
- spec/nexmos/base_spec.rb
|
167
|
+
- spec/nexmos/number_spec.rb
|
168
|
+
- spec/nexmos_spec.rb
|
169
|
+
- spec/spec_helper.rb
|