twilio-ruby 3.7.0 → 3.7.1

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -8,9 +8,5 @@ Gem::PackageTask.new(spec) do |p|
8
8
  p.gem_spec = spec
9
9
  end
10
10
 
11
- RSpec::Core::RakeTask.new do |t|
12
- t.pattern = 'test/*_spec.rb'
13
- t.rspec_opts = ['-c']
14
- end
15
-
11
+ RSpec::Core::RakeTask.new
16
12
  task :default => :spec
@@ -45,6 +45,8 @@ module Twilio
45
45
  include Twilio::Util
46
46
  include Twilio::REST::Utils
47
47
 
48
+ API_VERSION = '2010-04-01'
49
+
48
50
  HTTP_HEADERS = {
49
51
  'Accept' => 'application/json',
50
52
  'Accept-Charset' => 'utf-8',
@@ -194,10 +196,8 @@ module Twilio
194
196
  ##
195
197
  # Set up +account+ and +accounts+ attributes.
196
198
  def set_up_subresources # :doc:
197
- accounts_uri = '/2010-04-01/Accounts'
198
- account_uri = "#{accounts_uri}/#{@account_sid}"
199
- @account = Twilio::REST::Account.new account_uri, self
200
- @accounts = Twilio::REST::Accounts.new accounts_uri, self
199
+ @accounts = Twilio::REST::Accounts.new "/#{API_VERSION}/Accounts", self
200
+ @account = @accounts.get @account_sid
201
201
  end
202
202
 
203
203
  ##
@@ -218,7 +218,9 @@ module Twilio
218
218
  rescue Exception
219
219
  if retries_left > 0 then retries_left -= 1; retry else raise end
220
220
  end
221
- object = MultiJson.load response.body if response.body
221
+ if response.body and !response.body.empty?
222
+ object = MultiJson.load response.body
223
+ end
222
224
  if response.kind_of? Net::HTTPClientError
223
225
  raise Twilio::REST::RequestError.new object['message'], object['code']
224
226
  end
@@ -1,3 +1,3 @@
1
1
  module Twilio
2
- VERSION = '3.7.0'
2
+ VERSION = '3.7.1'
3
3
  end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ describe Twilio::REST::Account do
4
+ it 'should set up an incoming phone numbers resources object' do
5
+ account = Twilio::REST::Account.new('someUri', 'someClient')
6
+ account.respond_to?(:incoming_phone_numbers).should == true
7
+ account.incoming_phone_numbers.instance_variable_get('@uri').should == 'someUri/IncomingPhoneNumbers'
8
+ end
9
+
10
+ it 'should set up an available phone numbers resources object' do
11
+ account = Twilio::REST::Account.new('someUri', 'someClient')
12
+ account.respond_to?(:available_phone_numbers).should == true
13
+ account.available_phone_numbers.instance_variable_get('@uri').should == 'someUri/AvailablePhoneNumbers'
14
+ end
15
+
16
+ it 'should set up an outgoing caller ids resources object' do
17
+ account = Twilio::REST::Account.new('someUri', 'someClient')
18
+ account.respond_to?(:outgoing_caller_ids).should == true
19
+ account.outgoing_caller_ids.instance_variable_get('@uri').should == 'someUri/OutgoingCallerIds'
20
+ end
21
+
22
+ it 'should set up a calls resources object' do
23
+ account = Twilio::REST::Account.new('someUri', 'someClient')
24
+ account.respond_to?(:calls).should == true
25
+ account.calls.instance_variable_get('@uri').should == 'someUri/Calls'
26
+ end
27
+
28
+ it 'should set up a conferences resources object' do
29
+ account = Twilio::REST::Account.new('someUri', 'someClient')
30
+ account.respond_to?(:conferences).should == true
31
+ account.conferences.instance_variable_get('@uri').should == 'someUri/Conferences'
32
+ end
33
+
34
+ it 'should set up a sms resource object' do
35
+ account = Twilio::REST::Account.new('someUri', 'someClient')
36
+ account.respond_to?(:sms).should == true
37
+ account.sms.instance_variable_get('@uri').should == 'someUri/SMS'
38
+ end
39
+
40
+ it 'should set up a recordings resources object' do
41
+ account = Twilio::REST::Account.new('someUri', 'someClient')
42
+ account.respond_to?(:recordings).should == true
43
+ account.recordings.instance_variable_get('@uri').should == 'someUri/Recordings'
44
+ end
45
+
46
+ it 'should set up a transcriptions resources object' do
47
+ account = Twilio::REST::Account.new('someUri', 'someClient')
48
+ account.respond_to?(:transcriptions).should == true
49
+ account.transcriptions.instance_variable_get('@uri').should == 'someUri/Transcriptions'
50
+ end
51
+
52
+ it 'should set up a notifications resources object' do
53
+ account = Twilio::REST::Account.new('someUri', 'someClient')
54
+ account.respond_to?(:notifications).should == true
55
+ account.notifications.instance_variable_get('@uri').should == 'someUri/Notifications'
56
+ end
57
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Twilio::REST::Call do
4
+ it 'should set up a recordings resources object' do
5
+ call = Twilio::REST::Call.new('someUri', 'someClient')
6
+ call.respond_to?(:recordings).should == true
7
+ call.recordings.instance_variable_get('@uri').should == 'someUri/Recordings'
8
+ end
9
+
10
+ it 'should set up a notifications resources object' do
11
+ call = Twilio::REST::Call.new('someUri', 'someClient')
12
+ call.respond_to?(:notifications).should == true
13
+ call.notifications.instance_variable_get('@uri').should == 'someUri/Notifications'
14
+ end
15
+ end
@@ -0,0 +1,100 @@
1
+ require 'spec_helper'
2
+
3
+ describe Twilio::REST::Client do
4
+ it 'should not raise an error if the response body is empty' do
5
+ FakeWeb.register_uri(:any, %r/api\.twilio\.com/, :body => '')
6
+ twilio = Twilio::REST::Client.new('someSid', 'someToken')
7
+ Twilio::REST::IncomingPhoneNumber.new('/phone_number', twilio).delete
8
+ end
9
+
10
+ it 'should not raise an error if the response body is nil' do
11
+ response = double(:response, :body => nil)
12
+ connection = double(:connection, :request => response)
13
+ twilio = Twilio::REST::Client.new('someSid', 'someToken')
14
+ twilio.instance_variable_set(:@connection, connection)
15
+ Twilio::REST::IncomingPhoneNumber.new('/phone_number', twilio).delete
16
+ end
17
+
18
+ it 'should set up a new client instance with the given sid and token' do
19
+ twilio = Twilio::REST::Client.new('someSid', 'someToken')
20
+ twilio.account_sid.should == 'someSid'
21
+ twilio.instance_variable_get('@auth_token').should == 'someToken'
22
+ end
23
+
24
+ it 'should set up the proper default http ssl connection' do
25
+ twilio = Twilio::REST::Client.new('someSid', 'someToken')
26
+ connection = twilio.instance_variable_get('@connection')
27
+ connection.address.should == 'api.twilio.com'
28
+ connection.port.should == 443
29
+ connection.use_ssl?.should == true
30
+ end
31
+
32
+ it 'should set up the requested ssl verification ca_file if provided' do
33
+ twilio = Twilio::REST::Client.new('someSid', 'someToken', :ssl_ca_file => '/path/to/ca/file')
34
+ connection = twilio.instance_variable_get('@connection')
35
+ connection.ca_file.should == '/path/to/ca/file'
36
+ end
37
+
38
+ it 'should set up the proper http ssl connection when a different domain is given' do
39
+ twilio = Twilio::REST::Client.new('someSid', 'someToken', :host => 'api.faketwilio.com')
40
+ connection = twilio.instance_variable_get('@connection')
41
+ connection.address.should == 'api.faketwilio.com'
42
+ connection.port.should == 443
43
+ connection.use_ssl?.should == true
44
+ end
45
+
46
+ it 'should adjust the open and read timeouts on the underlying Net::HTTP object when asked' do
47
+ timeout = rand(30)
48
+ twilio = Twilio::REST::Client.new('someSid', 'someToken', :timeout => timeout)
49
+ connection = twilio.instance_variable_get('@connection')
50
+ connection.port.should == 443
51
+ connection.use_ssl?.should == true
52
+ connection.open_timeout.should == timeout
53
+ connection.read_timeout.should == timeout
54
+ end
55
+
56
+ it 'should set up the proper http ssl connection when a proxy_host is given' do
57
+ twilio = Twilio::REST::Client.new('someSid', 'someToken', :host => 'api.faketwilio.com', :proxy_addr => 'localhost')
58
+ connection = twilio.instance_variable_get('@connection')
59
+ connection.proxy?.should == true
60
+ connection.proxy_address.should == 'localhost'
61
+ connection.proxy_port.should == 80
62
+ connection.address.should == 'api.faketwilio.com'
63
+ connection.port.should == 443
64
+ connection.use_ssl?.should == true
65
+ end
66
+
67
+ it 'should set up the proper http ssl connection when a proxy_host and proxy_port are given' do
68
+ twilio = Twilio::REST::Client.new('someSid', 'someToken', :host => 'api.faketwilio.com', :proxy_addr => 'localhost', :proxy_port => 13128)
69
+ connection = twilio.instance_variable_get('@connection')
70
+ connection.proxy?.should == true
71
+ connection.proxy_address.should == 'localhost'
72
+ connection.proxy_port.should == 13128
73
+ connection.address.should == 'api.faketwilio.com'
74
+ connection.port.should == 443
75
+ connection.use_ssl?.should == true
76
+ end
77
+
78
+ it 'should set up an accounts resources object' do
79
+ twilio = Twilio::REST::Client.new('someSid', 'someToken')
80
+ twilio.respond_to?(:accounts).should == true
81
+ twilio.accounts.instance_variable_get('@uri').should == '/2010-04-01/Accounts'
82
+ end
83
+
84
+ it 'should set up an account object with the given sid' do
85
+ twilio = Twilio::REST::Client.new('someSid', 'someToken')
86
+ twilio.respond_to?(:account).should == true
87
+ twilio.account.instance_variable_get('@uri').should == '/2010-04-01/Accounts/someSid'
88
+ end
89
+
90
+ it 'should convert all parameter names to Twilio-style names' do
91
+ twilio = Twilio::REST::Client.new('someSid', 'someToken')
92
+ untwilified = {:sms_url => 'someUrl', 'voiceFallbackUrl' => 'anotherUrl',
93
+ 'Status_callback' => 'yetAnotherUrl'}
94
+ twilified = {:SmsUrl => 'someUrl', :VoiceFallbackUrl => 'anotherUrl',
95
+ :StatusCallback => 'yetAnotherUrl'}
96
+ twilio.instance_eval do
97
+ twilify(untwilified).should == twilified
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe Twilio::REST::Conference do
4
+ it 'should set up a participants resources object' do
5
+ call = Twilio::REST::Conference.new('someUri', 'someClient')
6
+ call.respond_to?(:participants).should == true
7
+ call.participants.instance_variable_get('@uri').should == 'someUri/Participants'
8
+ end
9
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Twilio::REST::InstanceResource do
4
+ it 'should set up an internal reference to the uri and client' do
5
+ resource = Twilio::REST::InstanceResource.new('some/uri', 'someClient')
6
+ resource.instance_variable_get('@uri').should == 'some/uri'
7
+ resource.instance_variable_get('@client').should == 'someClient'
8
+ end
9
+
10
+ it 'should set up object properties if passed' do
11
+ params = {'SomeKey' => 'someValue'}
12
+ resource = Twilio::REST::InstanceResource.new('uri', 'client', params)
13
+ resource.some_key.should == 'someValue'
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe Twilio::REST::Recording do
4
+ it 'should set up a transcriptions resources object' do
5
+ call = Twilio::REST::Recording.new('someUri', 'someClient')
6
+ call.respond_to?(:transcriptions).should == true
7
+ call.transcriptions.instance_variable_get('@uri').should == 'someUri/Transcriptions'
8
+ end
9
+ end
@@ -0,0 +1,6 @@
1
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
2
+ require 'twilio-ruby'
3
+ require 'fakeweb'
4
+ require 'rack'
5
+
6
+ FakeWeb.allow_net_connect = false
@@ -0,0 +1,137 @@
1
+ require 'spec_helper'
2
+
3
+ describe Twilio::Util::Capability do
4
+ before :each do
5
+ @capability = Twilio::Util::Capability.new 'myAccountSid', 'myAuthToken'
6
+ end
7
+
8
+ def queries(q)
9
+ q.scan(/scope:client:(incoming|outgoing)\?(\S+)/).map{|(type, query)| [type, Rack::Utils.parse_query(query)]}
10
+ end
11
+
12
+ it 'should return a valid jwt when #generate is called' do
13
+ token = @capability.generate
14
+ decoded = JWT.decode token, 'myAuthToken'
15
+ decoded['scope'].should_not be_nil
16
+ decoded['iss'].should_not be_nil
17
+ decoded['exp'].should_not be_nil
18
+ end
19
+
20
+ it 'should properly set the iss key in the payload' do
21
+ token = @capability.generate
22
+ decoded = JWT.decode token, 'myAuthToken'
23
+ decoded['iss'].should == 'myAccountSid'
24
+ end
25
+
26
+ it 'should properly set the exp key based on the default hour ttl' do
27
+ seconds = Time.now.to_i
28
+ token = @capability.generate
29
+ decoded = JWT.decode token, 'myAuthToken'
30
+ decoded['exp'].should == seconds + 3600
31
+ end
32
+
33
+ it 'should properly set the exp key based on the ttl passed to #generate' do
34
+ ttl = rand 10000
35
+ seconds = Time.now.to_i
36
+ token = @capability.generate ttl
37
+ decoded = JWT.decode token, 'myAuthToken'
38
+ decoded['exp'].should == seconds + ttl
39
+ end
40
+
41
+ it 'should generate a proper incoming client scope string' do
42
+ @capability.allow_client_incoming 'andrew'
43
+ token = @capability.generate
44
+ decoded = JWT.decode token, 'myAuthToken'
45
+ queries(decoded['scope']).should == [['incoming', {'clientName' => 'andrew'}]]
46
+ end
47
+
48
+ it 'should generate multiple proper incoming client scope strings' do
49
+ @capability.allow_client_incoming 'andrew'
50
+ @capability.allow_client_incoming 'bridget'
51
+ token = @capability.generate
52
+ decoded = JWT.decode token, 'myAuthToken'
53
+ queries(decoded['scope']).should == [
54
+ ['incoming', {'clientName' => 'andrew'}],
55
+ ['incoming', {'clientName' => 'bridget'}]
56
+ ]
57
+ end
58
+
59
+ it 'should generate a proper outgoing client scope string' do
60
+ @capability.allow_client_outgoing 'myAppSid'
61
+ token = @capability.generate
62
+ decoded = JWT.decode token, 'myAuthToken'
63
+ queries(decoded['scope']).should == [['outgoing', {'appSid' => 'myAppSid'}]]
64
+ end
65
+
66
+ it 'should generate a proper outgoing client scope string with parameters' do
67
+ app_params_hash = {'key' => 'a value', :foo => 'bar/baz'}
68
+ @capability.allow_client_outgoing 'myAppSid', app_params_hash
69
+ app_params = @capability.instance_eval {url_encode(app_params_hash)}
70
+ params_hash = {'appSid' => 'myAppSid', 'appParams' => app_params}
71
+ params = @capability.instance_eval {url_encode(params_hash)}
72
+ token = @capability.generate
73
+ decoded = JWT.decode token, 'myAuthToken'
74
+ queries(decoded['scope']).should == [['outgoing', params_hash]]
75
+ end
76
+
77
+ it 'should generate a proper outgoing client scope string based on the ' +
78
+ 'client name when calling #allow_client_incoming first' do
79
+ @capability.allow_client_incoming 'andrew'
80
+ @capability.allow_client_outgoing 'myAppSid'
81
+ token = @capability.generate
82
+ decoded = JWT.decode token, 'myAuthToken'
83
+ queries(decoded['scope']).should == [
84
+ ['incoming', {'clientName' => 'andrew'}],
85
+ ['outgoing', {'clientName' => 'andrew', 'appSid' => 'myAppSid'}]
86
+ ]
87
+ end
88
+
89
+ it 'should generate a proper outgoing client scope string based on the ' +
90
+ 'client name when calling #allow_client_incoming second' do
91
+ @capability.allow_client_outgoing 'myAppSid'
92
+ @capability.allow_client_incoming 'andrew'
93
+ token = @capability.generate
94
+ decoded = JWT.decode token, 'myAuthToken'
95
+ queries(decoded['scope']).should == [["incoming", {"clientName"=>"andrew"}], ["outgoing", {"clientName"=>"andrew", "appSid"=>"myAppSid"}]]
96
+ end
97
+
98
+ it 'should generate a proper outgoing client scope string with parameters ' +
99
+ 'and a client name when calling #allow_client_incoming first' do
100
+ @capability.allow_client_incoming 'andrew'
101
+ app_params_hash = {'key' => 'a value', :foo => 'bar/baz'}
102
+ @capability.allow_client_outgoing 'myAppSid', app_params_hash
103
+ app_params = @capability.instance_eval {url_encode(app_params_hash)}
104
+ params_hash = {'appSid' => 'myAppSid', 'appParams' => app_params, 'clientName' => 'andrew'}
105
+ params = @capability.instance_eval {url_encode(params_hash)}
106
+ token = @capability.generate
107
+ decoded = JWT.decode token, 'myAuthToken'
108
+ scopes = queries(decoded['scope'])
109
+ scopes.shift.should == ["incoming", {"clientName"=>"andrew"}]
110
+ scope = scopes.shift
111
+ scope.first.should == 'outgoing'
112
+ Rack::Utils.parse_query(scope.last['appParams']).should == {'key' => 'a value', 'foo' => 'bar/baz'}
113
+ scope.last["clientName"].should == "andrew"
114
+ scope.last["appSid"].should == "myAppSid"
115
+ scopes.should be_empty
116
+ end
117
+
118
+ it 'should generate a proper outgoing client scope string with parameters ' +
119
+ 'and a client name when calling #allow_client_incoming second' do
120
+ app_params_hash = {'key' => 'a value', :foo => 'bar/baz'}
121
+ @capability.allow_client_outgoing 'myAppSid', app_params_hash
122
+ @capability.allow_client_incoming 'andrew'
123
+ app_params = @capability.instance_eval {url_encode(app_params_hash)}
124
+ params_hash = {'appSid' => 'myAppSid', 'appParams' => app_params, 'clientName' => 'andrew'}
125
+ params = @capability.instance_eval {url_encode(params_hash)}
126
+ token = @capability.generate
127
+ decoded = JWT.decode token, 'myAuthToken'
128
+ scopes = queries(decoded['scope'])
129
+ scopes.shift.should == ["incoming", {"clientName"=>"andrew"}]
130
+ scope = scopes.shift
131
+ scope.first.should == 'outgoing'
132
+ Rack::Utils.parse_query(scope.last['appParams']).should == {'key' => 'a value', 'foo' => 'bar/baz'}
133
+ scope.last["clientName"].should == "andrew"
134
+ scope.last["appSid"].should == "myAppSid"
135
+ scopes.should be_empty
136
+ end
137
+ end
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ describe Twilio::Util::RequestValidator do
4
+ it 'should properly validate a Twilio Voice request' do
5
+ token = '2bd9e9638872de601313dc77410d3b23'
6
+ validator = Twilio::Util::RequestValidator.new token
7
+ url = 'http://twiliotests.heroku.com/validate/voice'
8
+ params = {
9
+ 'ToState' => 'California',
10
+ 'CalledState' => 'California',
11
+ 'Direction' => 'inbound',
12
+ 'FromState' => 'CA',
13
+ 'AccountSid' => 'ACba8bc05eacf94afdae398e642c9cc32d',
14
+ 'Caller' => '+14153595711',
15
+ 'CallerZip' => '94108',
16
+ 'CallerCountry' => 'US',
17
+ 'From' => '+14153595711',
18
+ 'FromCity' => 'SAN FRANCISCO',
19
+ 'CallerCity' => 'SAN FRANCISCO',
20
+ 'To' => '+14157669926',
21
+ 'FromZip' => '94108',
22
+ 'FromCountry' => 'US',
23
+ 'ToCity' => '',
24
+ 'CallStatus' => 'ringing',
25
+ 'CalledCity' => '',
26
+ 'CallerState' => 'CA',
27
+ 'CalledZip' => '',
28
+ 'ToZip' => '',
29
+ 'ToCountry' => 'US',
30
+ 'CallSid' => 'CA136d09cd59a3c0ec8dbff44da5c03f31',
31
+ 'CalledCountry' => 'US',
32
+ 'Called' => '+14157669926',
33
+ 'ApiVersion' => '2010-04-01',
34
+ 'ApplicationSid' => 'AP44efecad51364e80b133bb7c07eb8204'
35
+ }
36
+ signature = 'oVb2kXoVy8GEfwBDjR8bk/ZZ6eA='
37
+ validator.validate(url, params, signature).should == true
38
+ end
39
+
40
+ it 'should properly validate a Twilio SMS request' do
41
+ token = '2bd9e9638872de601313dc77410d3b23'
42
+ validator = Twilio::Util::RequestValidator.new token
43
+ url = 'http://twiliotests.heroku.com/validate/sms'
44
+ params = {
45
+ 'ToState' => 'CA',
46
+ 'FromState' => 'CA',
47
+ 'AccountSid' => 'ACba8bc05eacf94afdae398e642c9cc32d',
48
+ 'SmsMessageSid' => 'SM2003cbd5e6a3701999aa3e5f20ff2787',
49
+ 'Body' => 'Orly',
50
+ 'From' => '+14159354345',
51
+ 'FromCity' => 'SAN FRANCISCO',
52
+ 'SmsStatus' => 'received',
53
+ 'FromZip' => '94107',
54
+ 'FromCountry' => 'US',
55
+ 'To' => '+14158141819',
56
+ 'ToCity' => 'SAN FRANCISCO',
57
+ 'ToZip' => '94105',
58
+ 'ToCountry' => 'US',
59
+ 'ApiVersion' => '2010-04-01',
60
+ 'SmsSid' => 'SM2003cbd5e6a3701999aa3e5f20ff2787'
61
+ }
62
+ signature = 'mxeiv65lEe0b8L6LdVw2jgJi8yw='
63
+ validator.validate(url, params, signature).should == true
64
+ end
65
+ end
data/twilio-ruby.gemspec CHANGED
@@ -9,11 +9,12 @@ Gem::Specification.new do |s|
9
9
  s.description = 'A simple library for communicating with the Twilio REST API, building TwiML, and generating Twilio Client Capability Tokens'
10
10
  s.summary = 'A simple library for communicating with the Twilio REST API, building TwiML, and generating Twilio Client Capability Tokens'
11
11
  s.homepage = 'http://github.com/twilio/twilio-ruby'
12
+ s.license = 'MIT'
12
13
 
13
14
  s.platform = Gem::Platform::RUBY
14
15
  s.require_paths = %w[lib]
15
16
  s.files = `git ls-files`.split("\n")
16
- s.test_files = Dir['test/**/*.rb']
17
+ s.test_files = Dir['spec/**/*.rb']
17
18
 
18
19
  s.add_dependency('multi_json', '>= 1.3.0')
19
20
  s.add_dependency('builder', '>= 2.1.2')
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twilio-ruby
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease:
6
6
  segments:
7
7
  - 3
8
8
  - 7
9
- - 0
10
- version: 3.7.0
9
+ - 1
10
+ version: 3.7.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Andrew Benton
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-05-02 00:00:00 -07:00
18
+ date: 2012-08-01 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -180,12 +180,20 @@ files:
180
180
  - lib/twilio-ruby/util/capability.rb
181
181
  - lib/twilio-ruby/util/request_validator.rb
182
182
  - lib/twilio-ruby/version.rb
183
- - test/twilio_spec.rb
183
+ - spec/rest/account_spec.rb
184
+ - spec/rest/call_spec.rb
185
+ - spec/rest/client_spec.rb
186
+ - spec/rest/conference_spec.rb
187
+ - spec/rest/instance_resource_spec.rb
188
+ - spec/rest/recording_spec.rb
189
+ - spec/spec_helper.rb
190
+ - spec/util/capability_spec.rb
191
+ - spec/util/request_validator_spec.rb
184
192
  - twilio-ruby.gemspec
185
193
  has_rdoc: true
186
194
  homepage: http://github.com/twilio/twilio-ruby
187
- licenses: []
188
-
195
+ licenses:
196
+ - MIT
189
197
  post_install_message:
190
198
  rdoc_options:
191
199
  - --line-numbers
@@ -222,4 +230,12 @@ signing_key:
222
230
  specification_version: 3
223
231
  summary: A simple library for communicating with the Twilio REST API, building TwiML, and generating Twilio Client Capability Tokens
224
232
  test_files:
225
- - test/twilio_spec.rb
233
+ - spec/spec_helper.rb
234
+ - spec/rest/call_spec.rb
235
+ - spec/rest/conference_spec.rb
236
+ - spec/rest/account_spec.rb
237
+ - spec/rest/instance_resource_spec.rb
238
+ - spec/rest/client_spec.rb
239
+ - spec/rest/recording_spec.rb
240
+ - spec/util/capability_spec.rb
241
+ - spec/util/request_validator_spec.rb
data/test/twilio_spec.rb DELETED
@@ -1,393 +0,0 @@
1
- $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
2
- require 'twilio-ruby'
3
- require 'fakeweb'
4
- require 'rack'
5
-
6
- describe Twilio::REST::Client do
7
- before :all do
8
- FakeWeb.register_uri(:any, %r/http:\/\/api.twilio.com\//, :body => '{"message": "You tried to reach Twilio"}')
9
- end
10
-
11
- it 'should set up a new client instance with the given sid and token' do
12
- twilio = Twilio::REST::Client.new('someSid', 'someToken')
13
- twilio.account_sid.should == 'someSid'
14
- twilio.instance_variable_get('@auth_token').should == 'someToken'
15
- end
16
-
17
- it 'should set up the proper default http ssl connection' do
18
- twilio = Twilio::REST::Client.new('someSid', 'someToken')
19
- connection = twilio.instance_variable_get('@connection')
20
- connection.address.should == 'api.twilio.com'
21
- connection.port.should == 443
22
- connection.use_ssl?.should == true
23
- end
24
-
25
- it 'should set up the requested ssl verification ca_file if provided' do
26
- twilio = Twilio::REST::Client.new('someSid', 'someToken', :ssl_ca_file => '/path/to/ca/file')
27
- connection = twilio.instance_variable_get('@connection')
28
- connection.ca_file.should == '/path/to/ca/file'
29
- end
30
-
31
- it 'should set up the proper http ssl connection when a different domain is given' do
32
- twilio = Twilio::REST::Client.new('someSid', 'someToken', :host => 'api.faketwilio.com')
33
- connection = twilio.instance_variable_get('@connection')
34
- connection.address.should == 'api.faketwilio.com'
35
- connection.port.should == 443
36
- connection.use_ssl?.should == true
37
- end
38
-
39
- it 'should adjust the open and read timeouts on the underlying Net::HTTP object when asked' do
40
- timeout = rand(30)
41
- twilio = Twilio::REST::Client.new('someSid', 'someToken', :timeout => timeout)
42
- connection = twilio.instance_variable_get('@connection')
43
- connection.port.should == 443
44
- connection.use_ssl?.should == true
45
- connection.open_timeout.should == timeout
46
- connection.read_timeout.should == timeout
47
- end
48
-
49
- it 'should set up the proper http ssl connection when a proxy_host is given' do
50
- twilio = Twilio::REST::Client.new('someSid', 'someToken', :host => 'api.faketwilio.com', :proxy_addr => 'localhost')
51
- connection = twilio.instance_variable_get('@connection')
52
- connection.proxy?.should == true
53
- connection.proxy_address.should == 'localhost'
54
- connection.proxy_port.should == 80
55
- connection.address.should == 'api.faketwilio.com'
56
- connection.port.should == 443
57
- connection.use_ssl?.should == true
58
- end
59
-
60
- it 'should set up the proper http ssl connection when a proxy_host and proxy_port are given' do
61
- twilio = Twilio::REST::Client.new('someSid', 'someToken', :host => 'api.faketwilio.com', :proxy_addr => 'localhost', :proxy_port => 13128)
62
- connection = twilio.instance_variable_get('@connection')
63
- connection.proxy?.should == true
64
- connection.proxy_address.should == 'localhost'
65
- connection.proxy_port.should == 13128
66
- connection.address.should == 'api.faketwilio.com'
67
- connection.port.should == 443
68
- connection.use_ssl?.should == true
69
- end
70
-
71
- it 'should set up an accounts resources object' do
72
- twilio = Twilio::REST::Client.new('someSid', 'someToken')
73
- twilio.respond_to?(:accounts).should == true
74
- twilio.accounts.instance_variable_get('@uri').should == '/2010-04-01/Accounts'
75
- end
76
-
77
- it 'should set up an account object with the given sid' do
78
- twilio = Twilio::REST::Client.new('someSid', 'someToken')
79
- twilio.respond_to?(:account).should == true
80
- twilio.account.instance_variable_get('@uri').should == '/2010-04-01/Accounts/someSid'
81
- end
82
-
83
- it 'should convert all parameter names to Twilio-style names' do
84
- twilio = Twilio::REST::Client.new('someSid', 'someToken')
85
- untwilified = {:sms_url => 'someUrl', 'voiceFallbackUrl' => 'anotherUrl',
86
- 'Status_callback' => 'yetAnotherUrl'}
87
- twilified = {:SmsUrl => 'someUrl', :VoiceFallbackUrl => 'anotherUrl',
88
- :StatusCallback => 'yetAnotherUrl'}
89
- twilio.instance_eval do
90
- twilify(untwilified).should == twilified
91
- end
92
- end
93
- end
94
-
95
- describe Twilio::REST::InstanceResource do
96
- it 'should set up an internal reference to the uri and client' do
97
- resource = Twilio::REST::InstanceResource.new('some/uri', 'someClient')
98
- resource.instance_variable_get('@uri').should == 'some/uri'
99
- resource.instance_variable_get('@client').should == 'someClient'
100
- end
101
-
102
- it 'should set up object properties if passed' do
103
- params = {'SomeKey' => 'someValue'}
104
- resource = Twilio::REST::InstanceResource.new('uri', 'client', params)
105
- resource.some_key.should == 'someValue'
106
- end
107
- end
108
-
109
- describe Twilio::REST::Account do
110
- it 'should set up an incoming phone numbers resources object' do
111
- account = Twilio::REST::Account.new('someUri', 'someClient')
112
- account.respond_to?(:incoming_phone_numbers).should == true
113
- account.incoming_phone_numbers.instance_variable_get('@uri').should == 'someUri/IncomingPhoneNumbers'
114
- end
115
-
116
- it 'should set up an available phone numbers resources object' do
117
- account = Twilio::REST::Account.new('someUri', 'someClient')
118
- account.respond_to?(:available_phone_numbers).should == true
119
- account.available_phone_numbers.instance_variable_get('@uri').should == 'someUri/AvailablePhoneNumbers'
120
- end
121
-
122
- it 'should set up an outgoing caller ids resources object' do
123
- account = Twilio::REST::Account.new('someUri', 'someClient')
124
- account.respond_to?(:outgoing_caller_ids).should == true
125
- account.outgoing_caller_ids.instance_variable_get('@uri').should == 'someUri/OutgoingCallerIds'
126
- end
127
-
128
- it 'should set up a calls resources object' do
129
- account = Twilio::REST::Account.new('someUri', 'someClient')
130
- account.respond_to?(:calls).should == true
131
- account.calls.instance_variable_get('@uri').should == 'someUri/Calls'
132
- end
133
-
134
- it 'should set up a conferences resources object' do
135
- account = Twilio::REST::Account.new('someUri', 'someClient')
136
- account.respond_to?(:conferences).should == true
137
- account.conferences.instance_variable_get('@uri').should == 'someUri/Conferences'
138
- end
139
-
140
- it 'should set up a sms resource object' do
141
- account = Twilio::REST::Account.new('someUri', 'someClient')
142
- account.respond_to?(:sms).should == true
143
- account.sms.instance_variable_get('@uri').should == 'someUri/SMS'
144
- end
145
-
146
- it 'should set up a recordings resources object' do
147
- account = Twilio::REST::Account.new('someUri', 'someClient')
148
- account.respond_to?(:recordings).should == true
149
- account.recordings.instance_variable_get('@uri').should == 'someUri/Recordings'
150
- end
151
-
152
- it 'should set up a transcriptions resources object' do
153
- account = Twilio::REST::Account.new('someUri', 'someClient')
154
- account.respond_to?(:transcriptions).should == true
155
- account.transcriptions.instance_variable_get('@uri').should == 'someUri/Transcriptions'
156
- end
157
-
158
- it 'should set up a notifications resources object' do
159
- account = Twilio::REST::Account.new('someUri', 'someClient')
160
- account.respond_to?(:notifications).should == true
161
- account.notifications.instance_variable_get('@uri').should == 'someUri/Notifications'
162
- end
163
- end
164
-
165
- describe Twilio::REST::Call do
166
- it 'should set up a recordings resources object' do
167
- call = Twilio::REST::Call.new('someUri', 'someClient')
168
- call.respond_to?(:recordings).should == true
169
- call.recordings.instance_variable_get('@uri').should == 'someUri/Recordings'
170
- end
171
-
172
- it 'should set up a notifications resources object' do
173
- call = Twilio::REST::Call.new('someUri', 'someClient')
174
- call.respond_to?(:notifications).should == true
175
- call.notifications.instance_variable_get('@uri').should == 'someUri/Notifications'
176
- end
177
- end
178
-
179
- describe Twilio::REST::Conference do
180
- it 'should set up a participants resources object' do
181
- call = Twilio::REST::Conference.new('someUri', 'someClient')
182
- call.respond_to?(:participants).should == true
183
- call.participants.instance_variable_get('@uri').should == 'someUri/Participants'
184
- end
185
- end
186
-
187
- describe Twilio::REST::Recording do
188
- it 'should set up a transcriptions resources object' do
189
- call = Twilio::REST::Recording.new('someUri', 'someClient')
190
- call.respond_to?(:transcriptions).should == true
191
- call.transcriptions.instance_variable_get('@uri').should == 'someUri/Transcriptions'
192
- end
193
- end
194
-
195
- describe Twilio::Util::RequestValidator do
196
- it 'should properly validate a Twilio Voice request' do
197
- token = '2bd9e9638872de601313dc77410d3b23'
198
- validator = Twilio::Util::RequestValidator.new token
199
- url = 'http://twiliotests.heroku.com/validate/voice'
200
- params = {
201
- 'ToState' => 'California',
202
- 'CalledState' => 'California',
203
- 'Direction' => 'inbound',
204
- 'FromState' => 'CA',
205
- 'AccountSid' => 'ACba8bc05eacf94afdae398e642c9cc32d',
206
- 'Caller' => '+14153595711',
207
- 'CallerZip' => '94108',
208
- 'CallerCountry' => 'US',
209
- 'From' => '+14153595711',
210
- 'FromCity' => 'SAN FRANCISCO',
211
- 'CallerCity' => 'SAN FRANCISCO',
212
- 'To' => '+14157669926',
213
- 'FromZip' => '94108',
214
- 'FromCountry' => 'US',
215
- 'ToCity' => '',
216
- 'CallStatus' => 'ringing',
217
- 'CalledCity' => '',
218
- 'CallerState' => 'CA',
219
- 'CalledZip' => '',
220
- 'ToZip' => '',
221
- 'ToCountry' => 'US',
222
- 'CallSid' => 'CA136d09cd59a3c0ec8dbff44da5c03f31',
223
- 'CalledCountry' => 'US',
224
- 'Called' => '+14157669926',
225
- 'ApiVersion' => '2010-04-01',
226
- 'ApplicationSid' => 'AP44efecad51364e80b133bb7c07eb8204'
227
- }
228
- signature = 'oVb2kXoVy8GEfwBDjR8bk/ZZ6eA='
229
- validator.validate(url, params, signature).should == true
230
- end
231
-
232
- it 'should properly validate a Twilio SMS request' do
233
- token = '2bd9e9638872de601313dc77410d3b23'
234
- validator = Twilio::Util::RequestValidator.new token
235
- url = 'http://twiliotests.heroku.com/validate/sms'
236
- params = {
237
- 'ToState' => 'CA',
238
- 'FromState' => 'CA',
239
- 'AccountSid' => 'ACba8bc05eacf94afdae398e642c9cc32d',
240
- 'SmsMessageSid' => 'SM2003cbd5e6a3701999aa3e5f20ff2787',
241
- 'Body' => 'Orly',
242
- 'From' => '+14159354345',
243
- 'FromCity' => 'SAN FRANCISCO',
244
- 'SmsStatus' => 'received',
245
- 'FromZip' => '94107',
246
- 'FromCountry' => 'US',
247
- 'To' => '+14158141819',
248
- 'ToCity' => 'SAN FRANCISCO',
249
- 'ToZip' => '94105',
250
- 'ToCountry' => 'US',
251
- 'ApiVersion' => '2010-04-01',
252
- 'SmsSid' => 'SM2003cbd5e6a3701999aa3e5f20ff2787'
253
- }
254
- signature = 'mxeiv65lEe0b8L6LdVw2jgJi8yw='
255
- validator.validate(url, params, signature).should == true
256
- end
257
- end
258
-
259
- describe Twilio::Util::Capability do
260
- before :each do
261
- @capability = Twilio::Util::Capability.new 'myAccountSid', 'myAuthToken'
262
- end
263
-
264
- def queries(q)
265
- q.scan(/scope:client:(incoming|outgoing)\?(\S+)/).map{|(type, query)| [type, Rack::Utils.parse_query(query)]}
266
- end
267
-
268
- it 'should return a valid jwt when #generate is called' do
269
- token = @capability.generate
270
- decoded = JWT.decode token, 'myAuthToken'
271
- decoded['scope'].should_not be_nil
272
- decoded['iss'].should_not be_nil
273
- decoded['exp'].should_not be_nil
274
- end
275
-
276
- it 'should properly set the iss key in the payload' do
277
- token = @capability.generate
278
- decoded = JWT.decode token, 'myAuthToken'
279
- decoded['iss'].should == 'myAccountSid'
280
- end
281
-
282
- it 'should properly set the exp key based on the default hour ttl' do
283
- seconds = Time.now.to_i
284
- token = @capability.generate
285
- decoded = JWT.decode token, 'myAuthToken'
286
- decoded['exp'].should == seconds + 3600
287
- end
288
-
289
- it 'should properly set the exp key based on the ttl passed to #generate' do
290
- ttl = rand 10000
291
- seconds = Time.now.to_i
292
- token = @capability.generate ttl
293
- decoded = JWT.decode token, 'myAuthToken'
294
- decoded['exp'].should == seconds + ttl
295
- end
296
-
297
- it 'should generate a proper incoming client scope string' do
298
- @capability.allow_client_incoming 'andrew'
299
- token = @capability.generate
300
- decoded = JWT.decode token, 'myAuthToken'
301
- queries(decoded['scope']).should == [['incoming', {'clientName' => 'andrew'}]]
302
- end
303
-
304
- it 'should generate multiple proper incoming client scope strings' do
305
- @capability.allow_client_incoming 'andrew'
306
- @capability.allow_client_incoming 'bridget'
307
- token = @capability.generate
308
- decoded = JWT.decode token, 'myAuthToken'
309
- queries(decoded['scope']).should == [
310
- ['incoming', {'clientName' => 'andrew'}],
311
- ['incoming', {'clientName' => 'bridget'}]
312
- ]
313
- end
314
-
315
- it 'should generate a proper outgoing client scope string' do
316
- @capability.allow_client_outgoing 'myAppSid'
317
- token = @capability.generate
318
- decoded = JWT.decode token, 'myAuthToken'
319
- queries(decoded['scope']).should == [['outgoing', {'appSid' => 'myAppSid'}]]
320
- end
321
-
322
- it 'should generate a proper outgoing client scope string with parameters' do
323
- app_params_hash = {'key' => 'a value', :foo => 'bar/baz'}
324
- @capability.allow_client_outgoing 'myAppSid', app_params_hash
325
- app_params = @capability.instance_eval {url_encode(app_params_hash)}
326
- params_hash = {'appSid' => 'myAppSid', 'appParams' => app_params}
327
- params = @capability.instance_eval {url_encode(params_hash)}
328
- token = @capability.generate
329
- decoded = JWT.decode token, 'myAuthToken'
330
- queries(decoded['scope']).should == [['outgoing', params_hash]]
331
- end
332
-
333
- it 'should generate a proper outgoing client scope string based on the ' +
334
- 'client name when calling #allow_client_incoming first' do
335
- @capability.allow_client_incoming 'andrew'
336
- @capability.allow_client_outgoing 'myAppSid'
337
- token = @capability.generate
338
- decoded = JWT.decode token, 'myAuthToken'
339
- queries(decoded['scope']).should == [
340
- ['incoming', {'clientName' => 'andrew'}],
341
- ['outgoing', {'clientName' => 'andrew', 'appSid' => 'myAppSid'}]
342
- ]
343
- end
344
-
345
- it 'should generate a proper outgoing client scope string based on the ' +
346
- 'client name when calling #allow_client_incoming second' do
347
- @capability.allow_client_outgoing 'myAppSid'
348
- @capability.allow_client_incoming 'andrew'
349
- token = @capability.generate
350
- decoded = JWT.decode token, 'myAuthToken'
351
- queries(decoded['scope']).should == [["incoming", {"clientName"=>"andrew"}], ["outgoing", {"clientName"=>"andrew", "appSid"=>"myAppSid"}]]
352
- end
353
-
354
- it 'should generate a proper outgoing client scope string with parameters ' +
355
- 'and a client name when calling #allow_client_incoming first' do
356
- @capability.allow_client_incoming 'andrew'
357
- app_params_hash = {'key' => 'a value', :foo => 'bar/baz'}
358
- @capability.allow_client_outgoing 'myAppSid', app_params_hash
359
- app_params = @capability.instance_eval {url_encode(app_params_hash)}
360
- params_hash = {'appSid' => 'myAppSid', 'appParams' => app_params, 'clientName' => 'andrew'}
361
- params = @capability.instance_eval {url_encode(params_hash)}
362
- token = @capability.generate
363
- decoded = JWT.decode token, 'myAuthToken'
364
- scopes = queries(decoded['scope'])
365
- scopes.shift.should == ["incoming", {"clientName"=>"andrew"}]
366
- scope = scopes.shift
367
- scope.first.should == 'outgoing'
368
- Rack::Utils.parse_query(scope.last['appParams']).should == {'key' => 'a value', 'foo' => 'bar/baz'}
369
- scope.last["clientName"].should == "andrew"
370
- scope.last["appSid"].should == "myAppSid"
371
- scopes.should be_empty
372
- end
373
-
374
- it 'should generate a proper outgoing client scope string with parameters ' +
375
- 'and a client name when calling #allow_client_incoming second' do
376
- app_params_hash = {'key' => 'a value', :foo => 'bar/baz'}
377
- @capability.allow_client_outgoing 'myAppSid', app_params_hash
378
- @capability.allow_client_incoming 'andrew'
379
- app_params = @capability.instance_eval {url_encode(app_params_hash)}
380
- params_hash = {'appSid' => 'myAppSid', 'appParams' => app_params, 'clientName' => 'andrew'}
381
- params = @capability.instance_eval {url_encode(params_hash)}
382
- token = @capability.generate
383
- decoded = JWT.decode token, 'myAuthToken'
384
- scopes = queries(decoded['scope'])
385
- scopes.shift.should == ["incoming", {"clientName"=>"andrew"}]
386
- scope = scopes.shift
387
- scope.first.should == 'outgoing'
388
- Rack::Utils.parse_query(scope.last['appParams']).should == {'key' => 'a value', 'foo' => 'bar/baz'}
389
- scope.last["clientName"].should == "andrew"
390
- scope.last["appSid"].should == "myAppSid"
391
- scopes.should be_empty
392
- end
393
- end