rdstation-ruby-client 1.2.0 → 2.3.0

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.
Files changed (47) hide show
  1. checksums.yaml +5 -5
  2. data/.github/ISSUE_TEMPLATE/rdsm-ruby-client-issue-template.md +49 -0
  3. data/.rspec +2 -0
  4. data/CHANGELOG.md +163 -0
  5. data/README.md +243 -43
  6. data/lib/rdstation-ruby-client.rb +6 -0
  7. data/lib/rdstation.rb +19 -0
  8. data/lib/rdstation/api_response.rb +3 -3
  9. data/lib/rdstation/authentication.rb +32 -3
  10. data/lib/rdstation/authorization.rb +24 -0
  11. data/lib/rdstation/builder/field.rb +70 -0
  12. data/lib/rdstation/client.rb +17 -70
  13. data/lib/rdstation/contacts.rb +21 -16
  14. data/lib/rdstation/error.rb +22 -15
  15. data/lib/rdstation/error/format.rb +21 -3
  16. data/lib/rdstation/error/formatter.rb +53 -7
  17. data/lib/rdstation/error_handler.rb +29 -26
  18. data/lib/rdstation/error_handler/bad_request.rb +30 -0
  19. data/lib/rdstation/error_handler/unauthorized.rb +17 -9
  20. data/lib/rdstation/events.rb +7 -19
  21. data/lib/rdstation/fields.rb +31 -7
  22. data/lib/rdstation/retryable_request.rb +35 -0
  23. data/lib/rdstation/version.rb +1 -1
  24. data/lib/rdstation/webhooks.rb +25 -17
  25. data/rdstation-ruby-client.gemspec +4 -1
  26. data/spec/lib/rdstation-ruby-client_spec.rb +1 -1
  27. data/spec/lib/rdstation/api_response_spec.rb +34 -0
  28. data/spec/lib/rdstation/authentication_spec.rb +164 -0
  29. data/spec/lib/rdstation/authorization_spec.rb +24 -0
  30. data/spec/lib/rdstation/builder/field_spec.rb +69 -0
  31. data/spec/lib/rdstation/client_spec.rb +37 -0
  32. data/spec/lib/rdstation/contacts_spec.rb +54 -41
  33. data/spec/lib/rdstation/error/format_spec.rb +46 -0
  34. data/spec/lib/rdstation/error/formatter_spec.rb +83 -0
  35. data/spec/lib/rdstation/error_handler/unauthorized_spec.rb +0 -29
  36. data/spec/lib/rdstation/error_handler_spec.rb +153 -26
  37. data/spec/lib/rdstation/events_spec.rb +20 -9
  38. data/spec/lib/rdstation/fields_spec.rb +10 -3
  39. data/spec/lib/rdstation/retryable_request_spec.rb +142 -0
  40. data/spec/lib/rdstation/webhooks_spec.rb +41 -13
  41. data/spec/lib/rdstation_spec.rb +18 -0
  42. metadata +40 -13
  43. data/Gemfile.lock +0 -59
  44. data/lib/rdstation/error_handler/default.rb +0 -15
  45. data/lib/rdstation/error_handler/resource_not_found.rb +0 -24
  46. data/spec/lib/rdstation/error_handler/default_spec.rb +0 -14
  47. data/spec/lib/rdstation/error_handler/resource_not_found_spec.rb +0 -54
@@ -52,5 +52,51 @@ RSpec.describe RDStation::Error::Format do
52
52
  expect(result).to eq(RDStation::Error::Format::ARRAY_OF_HASHES)
53
53
  end
54
54
  end
55
+
56
+ context 'when receives a mixed type of errors' do
57
+ let(:errors) do
58
+ {
59
+ 'label': {
60
+ 'pt-BR': [
61
+ {
62
+ 'error_type': 'CANNOT_BE_BLANK',
63
+ 'error_message': 'cannot be blank'
64
+ }
65
+ ]
66
+ },
67
+ 'api_identifier': [
68
+ {
69
+ 'error_type': 'CANNOT_BE_BLANK',
70
+ 'error_message': 'cannot be blank'
71
+ }
72
+ ]
73
+ }
74
+ end
75
+
76
+ it 'returns the HASH_OF_MULTIPLE_TYPES format' do
77
+ result = error_format.format
78
+ expect(result).to eq(RDStation::Error::Format::HASH_OF_MULTIPLE_TYPES)
79
+ end
80
+ end
81
+
82
+ context 'when receives a hash of hashes errors' do
83
+ let(:errors) do
84
+ {
85
+ label: {
86
+ 'pt-BR': [
87
+ {
88
+ 'error_type': 'CANNOT_BE_BLANK',
89
+ 'error_message': 'cannot be blank'
90
+ }
91
+ ]
92
+ }
93
+ }
94
+ end
95
+
96
+ it 'returns the HASH_OF_MULTILINGUAL format' do
97
+ result = error_format.format
98
+ expect(result).to eq(RDStation::Error::Format::HASH_OF_HASHES)
99
+ end
100
+ end
55
101
  end
56
102
  end
@@ -132,5 +132,88 @@ RSpec.describe RDStation::Error::Formatter do
132
132
  expect(result).to eq(expected_result)
133
133
  end
134
134
  end
135
+
136
+ context 'when receives a hash of multiple type errors' do
137
+ let(:error_format) { instance_double(RDStation::Error::Format, format: RDStation::Error::Format::HASH_OF_MULTIPLE_TYPES) }
138
+
139
+ let(:error_response) do
140
+ {
141
+ 'errors' => {
142
+ 'label' => {
143
+ 'pt-BR' => [
144
+ {
145
+ 'error_type' => 'CANNOT_BE_BLANK',
146
+ 'error_message' => 'cannot be blank'
147
+ }
148
+ ]
149
+ },
150
+ 'api_identifier' => [
151
+ {
152
+ 'error_type' => 'CANNOT_BE_BLANK',
153
+ 'error_message' => 'cannot be blank'
154
+ }
155
+ ]
156
+ }
157
+ }
158
+ end
159
+
160
+ let(:error_formatter) { described_class.new(error_response) }
161
+
162
+ let(:expected_result) do
163
+ [
164
+ {
165
+ 'error_type' => 'CANNOT_BE_BLANK',
166
+ 'error_message' => 'cannot be blank',
167
+ 'path' => 'body.label.pt-BR'
168
+ },
169
+ {
170
+ 'error_type' => 'CANNOT_BE_BLANK',
171
+ 'error_message' => 'cannot be blank',
172
+ 'path' => 'body.api_identifier'
173
+ }
174
+ ]
175
+ end
176
+
177
+ it 'returns an array of errors' do
178
+ result = error_formatter.to_array
179
+ expect(result).to eq(expected_result)
180
+ end
181
+ end
182
+
183
+ context 'when receives a hash of hashes type errors' do
184
+ let(:error_format) { instance_double(RDStation::Error::Format, format: RDStation::Error::Format::HASH_OF_HASHES) }
185
+
186
+ let(:error_response) do
187
+ {
188
+ 'errors' => {
189
+ 'label' => {
190
+ 'pt-BR' => [
191
+ {
192
+ 'error_type' => 'CANNOT_BE_BLANK',
193
+ 'error_message' => 'cannot be blank'
194
+ }
195
+ ]
196
+ }
197
+ }
198
+ }
199
+ end
200
+
201
+ let(:error_formatter) { described_class.new(error_response) }
202
+
203
+ let(:expected_result) do
204
+ [
205
+ {
206
+ 'error_type' => 'CANNOT_BE_BLANK',
207
+ 'error_message' => 'cannot be blank',
208
+ 'path' => 'body.label.pt-BR'
209
+ }
210
+ ]
211
+ end
212
+
213
+ it 'returns an array of errors' do
214
+ result = error_formatter.to_array
215
+ expect(result).to eq(expected_result)
216
+ end
217
+ end
135
218
  end
136
219
  end
@@ -21,34 +21,5 @@ RSpec.describe RDStation::ErrorHandler::Unauthorized do
21
21
  end.to raise_error(RDStation::Error::Unauthorized, 'Error Message')
22
22
  end
23
23
  end
24
-
25
- context 'when none of the errors are unauthorized errors' do
26
- let(:errors) do
27
- [
28
- {
29
- 'error_message' => 'Error Message',
30
- 'error_type' => 'RANDOM_ERROR_TYPE'
31
- },
32
- {
33
- 'error_message' => 'Another Error Message',
34
- 'error_type' => 'ANOTHER_RANDOM_ERROR_TYPE'
35
- }
36
- ]
37
- end
38
-
39
- it 'does not raise an Unauthorized error' do
40
- result = unauthorized_error.raise_error
41
- expect(result).to be_nil
42
- end
43
- end
44
-
45
- context 'when there are no errors' do
46
- let(:errors) { [] }
47
-
48
- it 'does not raise an Unauthorized error' do
49
- result = unauthorized_error.raise_error
50
- expect(result).to be_nil
51
- end
52
- end
53
24
  end
54
25
  end
@@ -4,45 +4,172 @@ RSpec.describe RDStation::ErrorHandler do
4
4
  describe '#raise_errors' do
5
5
  subject(:error_handler) { described_class.new(error_response) }
6
6
 
7
- context 'when the error type is recognized' do
8
- let(:error_response) do
9
- OpenStruct.new(
10
- code: 400,
11
- body: {
7
+ let(:array_of_errors) do
8
+ [
9
+ {
10
+ 'error_type' => 'ERROR_TYPE',
11
+ 'error_message' => 'Error Message',
12
+ 'headers' => { 'error' => 'header' },
13
+ 'http_status' => http_status,
14
+ 'body' => {
12
15
  'errors' => {
13
- 'error_type' => 'CONFLICTING_FIELD',
16
+ 'error_type' => 'ERROR_TYPE',
14
17
  'error_message' => 'Error Message'
15
18
  }
16
- }.to_json
17
- )
19
+ }
20
+ }
21
+ ]
22
+ end
23
+
24
+ let(:error_response) do
25
+ OpenStruct.new(
26
+ code: http_status,
27
+ headers: { 'error' => 'header' },
28
+ body: {
29
+ 'errors' => {
30
+ 'error_type' => 'ERROR_TYPE',
31
+ 'error_message' => 'Error Message'
32
+ }
33
+ }.to_json
34
+ )
35
+ end
36
+
37
+ context 'with an error 400' do
38
+ let(:http_status) { 400 }
39
+
40
+ let(:bad_request_handler) { instance_double(RDStation::ErrorHandler::BadRequest, raise_error: 'raised error') }
41
+
42
+ before do
43
+ allow(RDStation::ErrorHandler::BadRequest).to receive(:new).with(array_of_errors).and_return(bad_request_handler)
44
+ end
45
+
46
+ it 'calls the bad request error handler' do
47
+ error_handler.raise_error
48
+ expect(bad_request_handler).to have_received(:raise_error)
49
+ end
50
+ end
51
+
52
+ context 'with an error 401' do
53
+ let(:http_status) { 401 }
54
+
55
+ let(:unauthorized_handler) { instance_double(RDStation::ErrorHandler::Unauthorized, raise_error: 'raised error') }
56
+
57
+ before do
58
+ allow(RDStation::ErrorHandler::Unauthorized).to receive(:new).with(array_of_errors).and_return(unauthorized_handler)
59
+ end
60
+
61
+ it 'calls the unauthorized error handler' do
62
+ error_handler.raise_error
63
+ expect(unauthorized_handler).to have_received(:raise_error)
64
+ end
65
+ end
66
+
67
+ context 'with an error 403' do
68
+ let(:http_status) { 403 }
69
+
70
+ it 'raises a forbidden error' do
71
+ expect { error_handler.raise_error }.to raise_error(RDStation::Error::Forbidden, 'Error Message')
72
+ end
73
+ end
74
+
75
+ context 'with an error 404' do
76
+ let(:http_status) { 404 }
77
+
78
+ it 'raises a not found error' do
79
+ expect { error_handler.raise_error }.to raise_error(RDStation::Error::NotFound, 'Error Message')
80
+ end
81
+ end
82
+
83
+ context 'with an error 405' do
84
+ let(:http_status) { 405 }
85
+
86
+ it 'raises a method not allowed error' do
87
+ expect { error_handler.raise_error }.to raise_error(RDStation::Error::MethodNotAllowed, 'Error Message')
88
+ end
89
+ end
90
+
91
+ context 'with an error 406' do
92
+ let(:http_status) { 406 }
93
+
94
+ it 'raises a not acceptable error' do
95
+ expect { error_handler.raise_error }.to raise_error(RDStation::Error::NotAcceptable, 'Error Message')
18
96
  end
97
+ end
98
+
99
+ context 'with an error 409' do
100
+ let(:http_status) { 409 }
19
101
 
20
- it 'raises the corresponding error class' do
21
- expect { error_handler.raise_errors }.to raise_error(RDStation::Error::ConflictingField, 'Error Message')
102
+ it 'raises a conflict error' do
103
+ expect { error_handler.raise_error }.to raise_error(RDStation::Error::Conflict, 'Error Message')
22
104
  end
23
105
  end
24
106
 
25
- context 'when the error type is not recognized' do
107
+ context 'with an error 415' do
108
+ let(:http_status) { 415 }
109
+
110
+ it 'raises an unsupported media type error' do
111
+ expect { error_handler.raise_error }.to raise_error(RDStation::Error::UnsupportedMediaType, 'Error Message')
112
+ end
113
+ end
114
+
115
+ context 'with an error 422' do
116
+ let(:http_status) { 422 }
117
+
118
+ it 'raises an unprocessable entity error' do
119
+ expect { error_handler.raise_error }.to raise_error(RDStation::Error::UnprocessableEntity, 'Error Message')
120
+ end
121
+ end
122
+
123
+ context 'with an error 500' do
124
+ let(:http_status) { 500 }
125
+
126
+ it 'raises an internal server error' do
127
+ expect { error_handler.raise_error }.to raise_error(RDStation::Error::InternalServerError, 'Error Message')
128
+ end
129
+ end
130
+
131
+ context 'with an error 501' do
132
+ let(:http_status) { 501 }
133
+
134
+ it 'raises a not implemented error' do
135
+ expect { error_handler.raise_error }.to raise_error(RDStation::Error::NotImplemented, 'Error Message')
136
+ end
137
+ end
138
+
139
+ context 'with an error 502' do
140
+ let(:http_status) { 502 }
141
+
142
+ it 'raises a bad gateway error' do
143
+ expect { error_handler.raise_error }.to raise_error(RDStation::Error::BadGateway, 'Error Message')
144
+ end
145
+ end
146
+
147
+ context 'with an error 503' do
148
+ let(:http_status) { 503 }
149
+
150
+ it 'raises a service unavailable error' do
151
+ expect { error_handler.raise_error }.to raise_error(RDStation::Error::ServiceUnavailable, 'Error Message')
152
+ end
153
+ end
154
+ context 'with 5xx error' do
155
+ let(:http_status) { 505 }
156
+
157
+ it 'raises a server error' do
158
+ expect { error_handler.raise_error }.to raise_error(RDStation::Error::ServerError, 'Error Message')
159
+ end
160
+ end
161
+
162
+ context "when response body is not JSON-parseable" do
26
163
  let(:error_response) do
27
164
  OpenStruct.new(
28
- code: 400,
29
- headers: { 'Content-Type' => 'application/json' },
30
- body: {
31
- 'errors' => {
32
- 'error_type' => 'UNRECOGNIZED_ERROR_TYPE',
33
- 'error_message' => 'Error Message'
34
- }
35
- }.to_json
165
+ code: 502,
166
+ headers: { 'error' => 'header' },
167
+ body: '<html><body>HTML error response</body></html>'
36
168
  )
37
169
  end
38
170
 
39
- it 'raises the Default error' do
40
- expect { error_handler.raise_errors }.to raise_error(RDStation::Error::Default, 'Error Message') do |error|
41
- expect(error.details).to be
42
- expect(error.headers).to be
43
- expect(error.body).to be
44
- expect(error.http_status).to be
45
- end
171
+ it 'raises the correct error' do
172
+ expect { error_handler.raise_error }.to raise_error(RDStation::Error::BadGateway, '<html><body>HTML error response</body></html>')
46
173
  end
47
174
  end
48
175
  end
@@ -1,13 +1,19 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe RDStation::Events do
4
- let(:valid_auth_token) { 'valid_auth_token' }
5
- let(:invalid_auth_token) { 'invalid_auth_token' }
6
- let(:expired_auth_token) { 'expired_auth_token' }
4
+ let(:valid_access_token) { 'valid_access_token' }
5
+ let(:invalid_access_token) { 'invalid_access_token' }
6
+ let(:expired_access_token) { 'expired_access_token' }
7
7
 
8
- let(:event_with_valid_token) { described_class.new(valid_auth_token) }
9
- let(:event_with_expired_token) { described_class.new(expired_auth_token) }
10
- let(:event_with_invalid_token) { described_class.new(invalid_auth_token) }
8
+ let(:event_with_valid_token) do
9
+ described_class.new(authorization: RDStation::Authorization.new(access_token: valid_access_token))
10
+ end
11
+ let(:event_with_expired_token) do
12
+ described_class.new(authorization: RDStation::Authorization.new(access_token: expired_access_token))
13
+ end
14
+ let(:event_with_invalid_token) do
15
+ described_class.new(authorization: RDStation::Authorization.new(access_token: invalid_access_token))
16
+ end
11
17
 
12
18
  let(:events_endpoint) { 'https://api.rd.services/platform/events' }
13
19
 
@@ -45,21 +51,21 @@ RSpec.describe RDStation::Events do
45
51
 
46
52
  let(:valid_headers) do
47
53
  {
48
- 'Authorization' => "Bearer #{valid_auth_token}",
54
+ 'Authorization' => "Bearer #{valid_access_token}",
49
55
  'Content-Type' => 'application/json'
50
56
  }
51
57
  end
52
58
 
53
59
  let(:invalid_token_headers) do
54
60
  {
55
- 'Authorization' => "Bearer #{invalid_auth_token}",
61
+ 'Authorization' => "Bearer #{invalid_access_token}",
56
62
  'Content-Type' => 'application/json'
57
63
  }
58
64
  end
59
65
 
60
66
  let(:expired_token_headers) do
61
67
  {
62
- 'Authorization' => "Bearer #{expired_auth_token}",
68
+ 'Authorization' => "Bearer #{expired_access_token}",
63
69
  'Content-Type' => 'application/json'
64
70
  }
65
71
  end
@@ -102,6 +108,11 @@ RSpec.describe RDStation::Events do
102
108
  }
103
109
  end
104
110
 
111
+ it 'calls retryable_request' do
112
+ expect(event_with_valid_token).to receive(:retryable_request)
113
+ event_with_valid_token.create({})
114
+ end
115
+
105
116
  context 'with a valid auth token' do
106
117
  before do
107
118
  stub_request(:post, events_endpoint)
@@ -1,12 +1,14 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe RDStation::Fields do
4
- let(:valid_auth_token) { 'valid_auth_token' }
5
- let(:rdstation_fields_with_valid_token) { described_class.new(valid_auth_token) }
4
+ let(:valid_access_token) { 'valid_access_token' }
5
+ let(:rdstation_fields_with_valid_token) do
6
+ described_class.new(authorization: RDStation::Authorization.new(access_token: valid_access_token))
7
+ end
6
8
 
7
9
  let(:valid_headers) do
8
10
  {
9
- 'Authorization' => "Bearer #{valid_auth_token}",
11
+ 'Authorization' => "Bearer #{valid_access_token}",
10
12
  'Content-Type' => 'application/json'
11
13
  }
12
14
  end
@@ -36,6 +38,11 @@ RSpec.describe RDStation::Fields do
36
38
  }
37
39
  end
38
40
 
41
+ it 'calls retryable_request' do
42
+ expect(rdstation_fields_with_valid_token).to receive(:retryable_request)
43
+ rdstation_fields_with_valid_token.all
44
+ end
45
+
39
46
  context 'with a valid auth token' do
40
47
  before do
41
48
  stub_request(:get, fields_endpoint)