twilio-ruby 3.7.0 → 3.7.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/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