twilio-ruby 3.11.5 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. checksums.yaml +13 -5
  2. data/.gitignore +1 -1
  3. data/.travis.yml +20 -9
  4. data/AUTHORS.md +32 -25
  5. data/CHANGES.md +203 -0
  6. data/Gemfile +8 -1
  7. data/{LICENSE → LICENSE.md} +4 -2
  8. data/Makefile +1 -2
  9. data/README.md +70 -39
  10. data/Rakefile +8 -10
  11. data/docs/faq.rst +3 -3
  12. data/docs/getting-started.rst +17 -12
  13. data/docs/index.rst +15 -0
  14. data/docs/usage/accounts.rst +6 -6
  15. data/docs/usage/addresses.rst +101 -0
  16. data/docs/usage/applications.rst +10 -10
  17. data/docs/usage/basics.rst +17 -4
  18. data/docs/usage/caller-ids.rst +4 -2
  19. data/docs/usage/conferences.rst +11 -11
  20. data/docs/usage/errors.rst +7 -7
  21. data/docs/usage/messages.rst +48 -20
  22. data/docs/usage/notifications.rst +6 -4
  23. data/docs/usage/phone-calls.rst +33 -14
  24. data/docs/usage/phone-numbers.rst +45 -31
  25. data/docs/usage/queues.rst +8 -8
  26. data/docs/usage/recordings.rst +12 -10
  27. data/docs/usage/sip.rst +15 -14
  28. data/docs/usage/taskrouter-tokens.rst +98 -0
  29. data/docs/usage/taskrouter.rst +226 -0
  30. data/docs/usage/token-generation.rst +19 -4
  31. data/docs/usage/transcriptions.rst +3 -2
  32. data/docs/usage/twiml.rst +7 -7
  33. data/docs/usage/validation.rst +39 -3
  34. data/examples/examples.rb +44 -20
  35. data/examples/print-call-log.rb +1 -1
  36. data/lib/rack/twilio_webhook_authentication.rb +47 -0
  37. data/lib/twilio-ruby/rest/accounts.rb +2 -1
  38. data/lib/twilio-ruby/rest/addresses/dependent_phone_numbers.rb +6 -0
  39. data/lib/twilio-ruby/rest/addresses.rb +12 -0
  40. data/lib/twilio-ruby/rest/base_client.rb +127 -0
  41. data/lib/twilio-ruby/rest/call_feedback.rb +28 -0
  42. data/lib/twilio-ruby/rest/call_feedback_summary.rb +13 -0
  43. data/lib/twilio-ruby/rest/calls.rb +10 -5
  44. data/lib/twilio-ruby/rest/client.rb +44 -109
  45. data/lib/twilio-ruby/rest/conferences/participants.rb +2 -2
  46. data/lib/twilio-ruby/rest/incoming_phone_numbers.rb +1 -1
  47. data/lib/twilio-ruby/rest/instance_resource.rb +2 -16
  48. data/lib/twilio-ruby/rest/list_resource.rb +20 -30
  49. data/lib/twilio-ruby/rest/lookups/phone_numbers.rb +17 -0
  50. data/lib/twilio-ruby/rest/lookups_client.rb +99 -0
  51. data/lib/twilio-ruby/rest/messages.rb +5 -0
  52. data/lib/twilio-ruby/rest/next_gen_list_resource.rb +36 -0
  53. data/lib/twilio-ruby/rest/outgoing_caller_ids.rb +1 -1
  54. data/lib/twilio-ruby/rest/queues/members.rb +1 -1
  55. data/lib/twilio-ruby/rest/sip.rb +1 -3
  56. data/lib/twilio-ruby/rest/sms/messages.rb +23 -0
  57. data/lib/twilio-ruby/rest/task_router/activities.rb +8 -0
  58. data/lib/twilio-ruby/rest/task_router/events.rb +8 -0
  59. data/lib/twilio-ruby/rest/task_router/reservations.rb +8 -0
  60. data/lib/twilio-ruby/rest/task_router/statistics.rb +26 -0
  61. data/lib/twilio-ruby/rest/task_router/task_queues.rb +17 -0
  62. data/lib/twilio-ruby/rest/task_router/task_queues_statistics.rb +15 -0
  63. data/lib/twilio-ruby/rest/task_router/tasks.rb +15 -0
  64. data/lib/twilio-ruby/rest/task_router/workers.rb +13 -0
  65. data/lib/twilio-ruby/rest/task_router/workers_statistics.rb +8 -0
  66. data/lib/twilio-ruby/rest/task_router/workflow_statistics.rb +7 -0
  67. data/lib/twilio-ruby/rest/task_router/workflows.rb +11 -0
  68. data/lib/twilio-ruby/rest/task_router/workspace_statistics.rb +7 -0
  69. data/lib/twilio-ruby/rest/task_router/workspaces.rb +17 -0
  70. data/lib/twilio-ruby/rest/task_router_client.rb +176 -0
  71. data/lib/twilio-ruby/rest/tokens.rb +7 -0
  72. data/lib/twilio-ruby/rest/usage/records.rb +2 -2
  73. data/lib/twilio-ruby/rest/utils.rb +35 -11
  74. data/lib/twilio-ruby/task_router/capability.rb +87 -0
  75. data/lib/twilio-ruby/task_router.rb +0 -0
  76. data/lib/twilio-ruby/twiml/response.rb +1 -0
  77. data/lib/twilio-ruby/util/capability.rb +10 -7
  78. data/lib/twilio-ruby/util/client_config.rb +29 -0
  79. data/lib/twilio-ruby/util/configuration.rb +7 -0
  80. data/lib/twilio-ruby/util/request_validator.rb +18 -3
  81. data/lib/twilio-ruby/version.rb +1 -1
  82. data/lib/twilio-ruby.rb +48 -0
  83. data/spec/rack/twilio_webhook_authentication_spec.rb +110 -0
  84. data/spec/rest/account_spec.rb +51 -20
  85. data/spec/rest/address_spec.rb +11 -0
  86. data/spec/rest/call_feedback_spec.rb +12 -0
  87. data/spec/rest/call_feedback_summary_spec.rb +9 -0
  88. data/spec/rest/call_spec.rb +8 -4
  89. data/spec/rest/client_spec.rb +209 -51
  90. data/spec/rest/conference_spec.rb +4 -2
  91. data/spec/rest/instance_resource_spec.rb +4 -4
  92. data/spec/rest/lookups/phone_number_spec.rb +8 -0
  93. data/spec/rest/message_spec.rb +2 -2
  94. data/spec/rest/numbers_spec.rb +25 -13
  95. data/spec/rest/queue_spec.rb +4 -2
  96. data/spec/rest/recording_spec.rb +4 -2
  97. data/spec/rest/sms/message_spec.rb +37 -0
  98. data/spec/rest/sms/messages_spec.rb +31 -0
  99. data/spec/rest/task_router/reservation_spec.rb +9 -0
  100. data/spec/rest/task_router/task_queue_spec.rb +9 -0
  101. data/spec/rest/token_spec.rb +7 -0
  102. data/spec/rest/utils_spec.rb +45 -0
  103. data/spec/spec_helper.rb +12 -3
  104. data/spec/support/fakeweb.rb +2 -0
  105. data/spec/task_router_spec.rb +114 -0
  106. data/spec/twilio_spec.rb +15 -0
  107. data/spec/util/capability_spec.rb +167 -118
  108. data/spec/util/client_config_spec.rb +21 -0
  109. data/spec/util/configuration_spec.rb +15 -0
  110. data/spec/util/request_validator_spec.rb +31 -3
  111. data/spec/util/url_encode_spec.rb +2 -2
  112. data/twilio-ruby.gemspec +28 -27
  113. metadata +93 -71
  114. data/CHANGES +0 -47
@@ -0,0 +1,114 @@
1
+ require 'spec_helper'
2
+
3
+ describe Twilio::TaskRouter::Capability do
4
+ describe 'with a capability' do
5
+ before :each do
6
+ @capability = Twilio::TaskRouter::Capability.new 'AC123', 'foobar', 'WS456', 'WK789'
7
+ end
8
+
9
+ it 'should return a valid jwt when #generate_token is called' do
10
+ token = @capability.generate_token
11
+ decoded, header = JWT.decode token, 'foobar'
12
+ expect(decoded['policies']).not_to be_nil
13
+ expect(decoded['iss']).not_to be_nil
14
+ expect(decoded['exp']).not_to be_nil
15
+ end
16
+
17
+ it 'should properly set the iss key in the payload' do
18
+ token = @capability.generate_token
19
+ decoded, header = JWT.decode token, 'foobar'
20
+ expect(decoded['iss']).to eq('AC123')
21
+ end
22
+
23
+ it 'should properly set exp based on the default 1-hour ttl' do
24
+ seconds = Time.now.to_i
25
+ token = @capability.generate_token
26
+ decoded, header = JWT.decode token, 'foobar'
27
+ expect(decoded['exp']).to eq(seconds + 3600)
28
+ end
29
+
30
+ it 'should properly set exp based on the ttl arg to #generate_token' do
31
+ seconds = Time.now.to_i
32
+ ttl = rand 10000
33
+ token = @capability.generate_token ttl
34
+ decoded, header = JWT.decode token, 'foobar'
35
+ expect(decoded['exp']).to eq(seconds + ttl)
36
+ end
37
+
38
+ it 'should allow websocket operations and activity list fetches by default' do
39
+ token = @capability.generate_token
40
+ decoded, header = JWT.decode token, 'foobar'
41
+ expect(decoded['policies'].size).to eq(3)
42
+ get_policy = {
43
+ "url" => 'https://event-bridge.twilio.com/v1/wschannels/AC123/WK789',
44
+ "method" => 'GET',
45
+ "query_filter" => {},
46
+ "post_filter" => {},
47
+ "allow" => true
48
+ }
49
+ expect(decoded['policies'][0]).to eq(get_policy)
50
+ post_policy = {
51
+ "url" => 'https://event-bridge.twilio.com/v1/wschannels/AC123/WK789',
52
+ "method" => 'POST',
53
+ "query_filter" => {},
54
+ "post_filter" => {},
55
+ "allow" => true
56
+ }
57
+ expect(decoded['policies'][1]).to eq(post_policy)
58
+
59
+ activities_policy = {
60
+ 'url' => 'https://taskrouter.twilio.com/v1/Workspaces/WS456/Activities',
61
+ 'method' => 'GET',
62
+ 'query_filter' => {},
63
+ 'post_filter' => {},
64
+ 'allow' => true
65
+ }
66
+ expect(decoded['policies'][2]).to eq(activities_policy)
67
+ end
68
+
69
+ it 'should add a policy when #allow_worker_activity_updates is called' do
70
+ @capability.allow_worker_activity_updates
71
+ token = @capability.generate_token
72
+ decoded, header = JWT.decode token, 'foobar'
73
+ expect(decoded['policies'].size).to eq(4)
74
+ activity_policy = {
75
+ 'url' => 'https://taskrouter.twilio.com/v1/Workspaces/WS456/Workers/WK789',
76
+ 'method' => 'POST',
77
+ 'query_filter' => {},
78
+ 'post_filter' => {'ActivitySid' => {'required' => true}},
79
+ 'allow' => true
80
+ }
81
+ expect(decoded['policies'][-1]).to eq(activity_policy)
82
+ end
83
+
84
+ it 'should add a policy when #allow_worker_fetch_attributes is called' do
85
+ @capability.allow_worker_fetch_attributes
86
+ token = @capability.generate_token
87
+ decoded, header = JWT.decode token, 'foobar'
88
+ expect(decoded['policies'].size).to eq(4)
89
+ worker_policy = {
90
+ 'url' => 'https://taskrouter.twilio.com/v1/Workspaces/WS456/Workers/WK789',
91
+ 'method' => 'GET',
92
+ 'query_filter' => {},
93
+ 'post_filter' => {},
94
+ 'allow' => true
95
+ }
96
+ expect(decoded['policies'][-1]).to eq(worker_policy)
97
+ end
98
+
99
+ it 'should add a policy when #allow_task_reservation_updates is called' do
100
+ @capability.allow_task_reservation_updates
101
+ token = @capability.generate_token
102
+ decoded, header = JWT.decode token, 'foobar'
103
+ expect(decoded['policies'].size).to eq(4)
104
+ task_policy = {
105
+ 'url' => 'https://taskrouter.twilio.com/v1/Workspaces/WS456/Tasks/**',
106
+ 'method' => 'POST',
107
+ 'query_filter' => {},
108
+ 'post_filter' => {'ReservationStatus' => {'required' => true}},
109
+ 'allow' => true
110
+ }
111
+ expect(decoded['policies'][-1]).to eq(task_policy)
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,15 @@
1
+ describe Twilio do
2
+ after(:each) do
3
+ Twilio.instance_variable_set('@configuration', nil)
4
+ end
5
+
6
+ it 'should set the account sid and auth token with a config block' do
7
+ Twilio.configure do |config|
8
+ config.account_sid = 'someSid'
9
+ config.auth_token = 'someToken'
10
+ end
11
+
12
+ expect(Twilio.account_sid).to eq('someSid')
13
+ expect(Twilio.auth_token).to eq('someToken')
14
+ end
15
+ end
@@ -1,137 +1,186 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Twilio::Util::Capability do
4
- before :each do
5
- @capability = Twilio::Util::Capability.new 'myAccountSid', 'myAuthToken'
6
- end
4
+ describe 'config' do
5
+ after(:each) do
6
+ Twilio.instance_variable_set('@configuration', nil)
7
+ end
7
8
 
8
- def queries(q)
9
- q.scan(/scope:client:(incoming|outgoing)\?(\S+)/).map{|(type, query)| [type, Rack::Utils.parse_query(query)]}
10
- end
9
+ it 'should set the account sid and auth token from a configuration block' do
10
+ Twilio.configure do |config|
11
+ config.account_sid = 'someSid'
12
+ config.auth_token = 'someToken'
13
+ end
11
14
 
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
15
+ capability = Twilio::Util::Capability.new
16
+ expect(capability.instance_variable_get('@account_sid')).to eq('someSid')
17
+ expect(capability.instance_variable_get('@auth_token')).to eq('someToken')
18
+ end
19
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
20
+ it 'should overwrite account sid and auth token if passed to initializer' do
21
+ Twilio.configure do |config|
22
+ config.account_sid = 'someSid'
23
+ config.auth_token = 'someToken'
24
+ end
25
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
26
+ capability = Twilio::Util::Capability.new'otherSid', 'otherToken'
27
+ expect(capability.instance_variable_get('@account_sid')).to eq('otherSid')
28
+ expect(capability.instance_variable_get('@auth_token')).to eq('otherToken')
29
+ end
32
30
 
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
31
+ it 'should overwrite the account sid if only the sid is given' do
32
+ Twilio.configure do |config|
33
+ config.account_sid = 'someSid'
34
+ config.auth_token = 'someToken'
35
+ end
40
36
 
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
37
+ capability = Twilio::Util::Capability.new 'otherSid'
38
+ expect(capability.instance_variable_get('@account_sid')).to eq('otherSid')
39
+ expect(capability.instance_variable_get('@auth_token')).to eq('someToken')
40
+ end
47
41
 
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
42
+ it 'should throw an argument error if the sid and token isn\'t set' do
43
+ expect { Twilio::Util::Capability.new }.to raise_error(ArgumentError)
44
+ end
58
45
 
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'}]]
46
+ it 'should throw an argument error if only the account_sid is set' do
47
+ expect { Twilio::Util::Capability.new 'someSid' }.to raise_error(ArgumentError)
48
+ end
64
49
  end
65
50
 
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
- @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
51
+ describe 'with a capability' do
52
+ before :each do
53
+ @capability = Twilio::Util::Capability.new 'myAccountSid', 'myAuthToken'
54
+ end
76
55
 
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
56
+ def queries(q)
57
+ q.scan(/scope:client:(incoming|outgoing)\?(\S+)/).map{|(type, query)| [type, Rack::Utils.parse_query(query)]}
58
+ end
88
59
 
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
60
+ it 'should return a valid jwt when #generate is called' do
61
+ token = @capability.generate
62
+ decoded, header = JWT.decode token, 'myAuthToken'
63
+ expect(decoded['scope']).not_to be_nil
64
+ expect(decoded['iss']).not_to be_nil
65
+ expect(decoded['exp']).not_to be_nil
66
+ end
97
67
 
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
- @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
68
+ it 'should properly set the iss key in the payload' do
69
+ token = @capability.generate
70
+ decoded, header = JWT.decode token, 'myAuthToken'
71
+ expect(decoded['iss']).to eq('myAccountSid')
72
+ end
73
+
74
+ it 'should properly set the exp key based on the default hour ttl' do
75
+ seconds = Time.now.to_i
76
+ token = @capability.generate
77
+ decoded, header = JWT.decode token, 'myAuthToken'
78
+ expect(decoded['exp']).to eq(seconds + 3600)
79
+ end
80
+
81
+ it 'should properly set the exp key based on the ttl passed to #generate' do
82
+ ttl = rand 10000
83
+ seconds = Time.now.to_i
84
+ token = @capability.generate ttl
85
+ decoded, header = JWT.decode token, 'myAuthToken'
86
+ expect(decoded['exp']).to eq(seconds + ttl)
87
+ end
88
+
89
+ it 'should generate a proper incoming client scope string' do
90
+ @capability.allow_client_incoming 'andrew'
91
+ token = @capability.generate
92
+ decoded, header = JWT.decode token, 'myAuthToken'
93
+ expect(queries(decoded['scope'])).to eq([['incoming', {'clientName' => 'andrew'}]])
94
+ end
95
+
96
+ it 'should generate multiple proper incoming client scope strings' do
97
+ @capability.allow_client_incoming 'andrew'
98
+ @capability.allow_client_incoming 'bridget'
99
+ token = @capability.generate
100
+ decoded, header = JWT.decode token, 'myAuthToken'
101
+ expect(queries(decoded['scope'])).to eq([
102
+ ['incoming', {'clientName' => 'andrew'}],
103
+ ['incoming', {'clientName' => 'bridget'}]
104
+ ])
105
+ end
106
+
107
+ it 'should generate a proper outgoing client scope string' do
108
+ @capability.allow_client_outgoing 'myAppSid'
109
+ token = @capability.generate
110
+ decoded, header = JWT.decode token, 'myAuthToken'
111
+ expect(queries(decoded['scope'])).to eq([['outgoing', {'appSid' => 'myAppSid'}]])
112
+ end
113
+
114
+ it 'should generate a proper outgoing client scope string with parameters' do
115
+ app_params_hash = {'key' => 'a value', :foo => 'bar/baz'}
116
+ @capability.allow_client_outgoing 'myAppSid', app_params_hash
117
+ app_params = @capability.instance_eval {url_encode(app_params_hash)}
118
+ params_hash = {'appSid' => 'myAppSid', 'appParams' => app_params}
119
+ @capability.instance_eval {url_encode(params_hash)}
120
+ token = @capability.generate
121
+ decoded, header= JWT.decode token, 'myAuthToken'
122
+ expect(queries(decoded['scope'])).to eq([['outgoing', params_hash]])
123
+ end
124
+
125
+ it 'should generate a proper outgoing client scope string based on the ' +
126
+ 'client name when calling #allow_client_incoming first' do
127
+ @capability.allow_client_incoming 'andrew'
128
+ @capability.allow_client_outgoing 'myAppSid'
129
+ token = @capability.generate
130
+ decoded, header = JWT.decode token, 'myAuthToken'
131
+ expect(queries(decoded['scope'])).to eq([
132
+ ['incoming', {'clientName' => 'andrew'}],
133
+ ['outgoing', {'clientName' => 'andrew', 'appSid' => 'myAppSid'}]
134
+ ])
135
+ end
136
+
137
+ it 'should generate a proper outgoing client scope string based on the ' +
138
+ 'client name when calling #allow_client_incoming second' do
139
+ @capability.allow_client_outgoing 'myAppSid'
140
+ @capability.allow_client_incoming 'andrew'
141
+ token = @capability.generate
142
+ decoded, header = JWT.decode token, 'myAuthToken'
143
+ expect(queries(decoded['scope'])).to eq([["incoming", {"clientName"=>"andrew"}], ["outgoing", {"clientName"=>"andrew", "appSid"=>"myAppSid"}]])
144
+ end
145
+
146
+ it 'should generate a proper outgoing client scope string with parameters ' +
147
+ 'and a client name when calling #allow_client_incoming first' do
148
+ @capability.allow_client_incoming 'andrew'
149
+ app_params_hash = {'key' => 'a value', :foo => 'bar/baz'}
150
+ @capability.allow_client_outgoing 'myAppSid', app_params_hash
151
+ app_params = @capability.instance_eval {url_encode(app_params_hash)}
152
+ params_hash = {'appSid' => 'myAppSid', 'appParams' => app_params, 'clientName' => 'andrew'}
153
+ @capability.instance_eval {url_encode(params_hash)}
154
+ token = @capability.generate
155
+ decoded, header = JWT.decode token, 'myAuthToken'
156
+ scopes = queries(decoded['scope'])
157
+ expect(scopes.shift).to eq(["incoming", {"clientName"=>"andrew"}])
158
+ scope = scopes.shift
159
+ expect(scope.first).to eq('outgoing')
160
+ expect(Rack::Utils.parse_query(scope.last['appParams'])).to eq({'key' => 'a value', 'foo' => 'bar/baz'})
161
+ expect(scope.last["clientName"]).to eq("andrew")
162
+ expect(scope.last["appSid"]).to eq("myAppSid")
163
+ expect(scopes).to be_empty
164
+ end
117
165
 
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
- @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
166
+ it 'should generate a proper outgoing client scope string with parameters ' +
167
+ 'and a client name when calling #allow_client_incoming second' do
168
+ app_params_hash = {'key' => 'a value', :foo => 'bar/baz'}
169
+ @capability.allow_client_outgoing 'myAppSid', app_params_hash
170
+ @capability.allow_client_incoming 'andrew'
171
+ app_params = @capability.instance_eval {url_encode(app_params_hash)}
172
+ params_hash = {'appSid' => 'myAppSid', 'appParams' => app_params, 'clientName' => 'andrew'}
173
+ @capability.instance_eval {url_encode(params_hash)}
174
+ token = @capability.generate
175
+ decoded, header = JWT.decode token, 'myAuthToken'
176
+ scopes = queries(decoded['scope'])
177
+ expect(scopes.shift).to eq(["incoming", {"clientName"=>"andrew"}])
178
+ scope = scopes.shift
179
+ expect(scope.first).to eq('outgoing')
180
+ expect(Rack::Utils.parse_query(scope.last['appParams'])).to eq({'key' => 'a value', 'foo' => 'bar/baz'})
181
+ expect(scope.last["clientName"]).to eq("andrew")
182
+ expect(scope.last["appSid"]).to eq("myAppSid")
183
+ expect(scopes).to be_empty
184
+ end
136
185
  end
137
186
  end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Twilio::Util::ClientConfig do
4
+ Twilio::Util::ClientConfig::DEFAULTS.each do |attribute, value|
5
+ it "sets an attribute with a default value" do
6
+ config = Twilio::Util::ClientConfig.new
7
+ expect(config.send(attribute)).to eq(value)
8
+ end
9
+
10
+ it "can update the value for the attribute" do
11
+ config = Twilio::Util::ClientConfig.new
12
+ config.send("#{attribute}=", "blah")
13
+ expect(config.send(attribute)).to eq("blah")
14
+ end
15
+
16
+ it "can set the value from a hash in the initializer" do
17
+ config = Twilio::Util::ClientConfig.new(attribute => 'blah')
18
+ expect(config.send(attribute)).to eq("blah")
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Twilio::Util::Configuration do
4
+ it 'should have an account sid attribute' do
5
+ config = Twilio::Util::Configuration.new
6
+ config.account_sid = 'someSid'
7
+ expect(config.account_sid).to eq('someSid')
8
+ end
9
+
10
+ it 'should have an auth token attribute' do
11
+ config = Twilio::Util::Configuration.new
12
+ config.auth_token = 'someToken'
13
+ expect(config.auth_token).to eq('someToken')
14
+ end
15
+ end
@@ -1,6 +1,34 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Twilio::Util::RequestValidator do
4
+ describe 'configuration' do
5
+ after(:each) do
6
+ Twilio.instance_variable_set('@configuration', nil)
7
+ end
8
+
9
+ it 'should set the auth token from a configuration block' do
10
+ Twilio.configure do |config|
11
+ config.auth_token = 'someToken'
12
+ end
13
+
14
+ validator = Twilio::Util::RequestValidator.new
15
+ expect(validator.instance_variable_get('@auth_token')).to eq('someToken')
16
+ end
17
+
18
+ it 'should overwrite the auth token if passed to initializer' do
19
+ Twilio.configure do |config|
20
+ config.auth_token = 'someToken'
21
+ end
22
+
23
+ validator = Twilio::Util::RequestValidator.new 'otherToken'
24
+ expect(validator.instance_variable_get('@auth_token')).to eq('otherToken')
25
+ end
26
+
27
+ it 'should throw an argument error if the auth token isn\'t set' do
28
+ expect { Twilio::Util::RequestValidator.new }.to raise_error(ArgumentError)
29
+ end
30
+ end
31
+
4
32
  it 'should properly validate a Twilio Voice request' do
5
33
  token = '2bd9e9638872de601313dc77410d3b23'
6
34
  validator = Twilio::Util::RequestValidator.new token
@@ -34,7 +62,7 @@ describe Twilio::Util::RequestValidator do
34
62
  'ApplicationSid' => 'AP44efecad51364e80b133bb7c07eb8204'
35
63
  }
36
64
  signature = 'oVb2kXoVy8GEfwBDjR8bk/ZZ6eA='
37
- validator.validate(url, params, signature).should == true
65
+ expect(validator.validate(url, params, signature)).to eq(true)
38
66
  end
39
67
 
40
68
  it 'should properly validate a Twilio SMS request' do
@@ -60,6 +88,6 @@ describe Twilio::Util::RequestValidator do
60
88
  'SmsSid' => 'SM2003cbd5e6a3701999aa3e5f20ff2787'
61
89
  }
62
90
  signature = 'mxeiv65lEe0b8L6LdVw2jgJi8yw='
63
- validator.validate(url, params, signature).should == true
91
+ expect(validator.validate(url, params, signature)).to eq(true)
64
92
  end
65
- end
93
+ end
@@ -5,8 +5,8 @@ describe Twilio::Util do
5
5
 
6
6
  it 'should parse a Date object' do
7
7
  today = Time.now
8
- url = url_encode({'DateSent>' => today})
8
+ url = url_encode('DateSent>' => today)
9
9
 
10
- url.should == "DateSent%3E=#{today.strftime('%Y-%m-%d')}"
10
+ expect(url).to eq("DateSent%3E=#{today.strftime('%Y-%m-%d')}")
11
11
  end
12
12
  end
data/twilio-ruby.gemspec CHANGED
@@ -1,33 +1,34 @@
1
- require './lib/twilio-ruby/version'
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'twilio-ruby/version'
2
5
 
3
- Gem::Specification.new do |s|
4
- s.name = 'twilio-ruby'
5
- s.version = Twilio::VERSION
6
- s.author = 'Andrew Benton'
7
- s.email = 'andrew@twilio.com'
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'twilio-ruby'
8
+ spec.version = Twilio::VERSION
9
+ spec.authors = ['Andrew Benton']
10
+ spec.email = ['andrew@twilio.com']
11
+ spec.summary = 'A simple library for communicating with the Twilio REST API, building TwiML, and generating Twilio Client Capability Tokens'
12
+ spec.description = 'A simple library for communicating with the Twilio REST API, building TwiML, and generating Twilio Client Capability Tokens'
13
+ spec.homepage = 'http://github.com/twilio/twilio-ruby'
14
+ spec.license = 'MIT'
8
15
 
9
- s.description = 'A simple library for communicating with the Twilio REST API, building TwiML, and generating Twilio Client Capability Tokens'
10
- s.summary = 'A simple library for communicating with the Twilio REST API, building TwiML, and generating Twilio Client Capability Tokens'
11
- s.homepage = 'http://github.com/twilio/twilio-ruby'
12
- s.license = 'MIT'
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+ spec.required_ruby_version = '>= 1.9.3'
21
+ spec.extra_rdoc_files = ['README.md', 'LICENSE.md']
22
+ spec.rdoc_options = ['--line-numbers', '--inline-source', '--title', 'twilio-ruby', '--main', 'README.md']
13
23
 
14
- s.platform = Gem::Platform::RUBY
15
- s.require_paths = %w[lib]
16
- s.files = `git ls-files`.split("\n")
17
- s.test_files = Dir['spec/**/*.rb']
18
-
19
- s.add_dependency('multi_json', '>= 1.3.0')
20
- s.add_dependency('builder', '>= 2.1.2')
21
- s.add_dependency('jwt', '>= 0.1.2')
22
- s.add_dependency('jruby-openssl') if RUBY_PLATFORM == 'java'
24
+ spec.add_dependency('multi_json', '>= 1.3.0')
25
+ spec.add_dependency('builder', '>= 2.1.2')
26
+ spec.add_dependency('jwt', '~> 1.0')
27
+ spec.add_dependency('jruby-openssl') if RUBY_PLATFORM == 'java'
23
28
  # Workaround for RBX <= 2.2.1, should be fixed in next version
24
- s.add_dependency('rubysl') if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
25
-
26
- s.add_development_dependency 'rake', '~> 0.9.0'
27
- s.add_development_dependency 'rspec', '~> 2.6.0'
28
- s.add_development_dependency 'fakeweb', '~> 1.3.0'
29
- s.add_development_dependency 'rack', '~> 1.3.0'
29
+ spec.add_dependency('rubysl') if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
30
30
 
31
- s.extra_rdoc_files = ['README.md', 'LICENSE']
32
- s.rdoc_options = ['--line-numbers', '--inline-source', '--title', 'twilio-ruby', '--main', 'README.md']
31
+ spec.add_development_dependency 'bundler', '~> 1.5'
32
+ spec.extra_rdoc_files = ['README.md', 'LICENSE.md']
33
+ spec.rdoc_options = ['--line-numbers', '--inline-source', '--title', 'twilio-ruby', '--main', 'README.md']
33
34
  end