ddy_remote_resource 0.4.11 → 1.0.0.rc1

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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -0
  3. data/Guardfile +3 -0
  4. data/lib/remote_resource.rb +77 -34
  5. data/lib/remote_resource/base.rb +20 -8
  6. data/lib/remote_resource/connection.rb +26 -5
  7. data/lib/remote_resource/connection_options.rb +5 -3
  8. data/lib/remote_resource/querying/finder_methods.rb +3 -3
  9. data/lib/remote_resource/querying/persistence_methods.rb +17 -12
  10. data/lib/remote_resource/request.rb +96 -62
  11. data/lib/remote_resource/response.rb +5 -1
  12. data/lib/remote_resource/rest.rb +13 -17
  13. data/lib/remote_resource/url_naming.rb +4 -10
  14. data/lib/remote_resource/url_naming_determination.rb +1 -3
  15. data/lib/remote_resource/util.rb +64 -0
  16. data/lib/remote_resource/version.rb +1 -1
  17. data/remote_resource.gemspec +2 -2
  18. data/spec/fixtures/text_file.txt +1 -0
  19. data/spec/integration/all_spec.rb +166 -0
  20. data/spec/integration/collection_prefix_spec.rb +99 -0
  21. data/spec/integration/create_spec.rb +181 -0
  22. data/spec/integration/destroy_spec.rb +252 -0
  23. data/spec/integration/find_by_spec.rb +168 -0
  24. data/spec/integration/find_spec.rb +139 -0
  25. data/spec/integration/headers_spec.rb +222 -0
  26. data/spec/integration/naming_spec.rb +138 -0
  27. data/spec/integration/save_spec.rb +320 -0
  28. data/spec/integration/update_attributes_spec.rb +221 -0
  29. data/spec/integration/where_spec.rb +152 -0
  30. data/spec/lib/extensions/ethon/easy/queryable_spec.rb +4 -4
  31. data/spec/lib/remote_resource/base_spec.rb +54 -110
  32. data/spec/lib/remote_resource/builder_spec.rb +1 -1
  33. data/spec/lib/remote_resource/collection_spec.rb +1 -1
  34. data/spec/lib/remote_resource/connection_options_spec.rb +20 -17
  35. data/spec/lib/remote_resource/connection_spec.rb +36 -27
  36. data/spec/lib/remote_resource/querying/finder_methods_spec.rb +199 -72
  37. data/spec/lib/remote_resource/querying/persistence_methods_spec.rb +228 -220
  38. data/spec/lib/remote_resource/request_spec.rb +313 -342
  39. data/spec/lib/remote_resource/response_spec.rb +9 -3
  40. data/spec/lib/remote_resource/rest_spec.rb +11 -11
  41. data/spec/lib/remote_resource/url_naming_determination_spec.rb +1 -1
  42. data/spec/lib/remote_resource/url_naming_spec.rb +7 -22
  43. data/spec/lib/remote_resource/util_spec.rb +56 -0
  44. data/spec/lib/remote_resource/version_spec.rb +2 -3
  45. data/spec/spec_helper.rb +37 -0
  46. metadata +33 -22
  47. data/lib/remote_resource/http_errors.rb +0 -33
  48. data/lib/remote_resource/response_handeling.rb +0 -48
@@ -0,0 +1,139 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe '.find' do
4
+
5
+ class Post
6
+ include RemoteResource::Base
7
+
8
+ self.site = 'https://www.example.com'
9
+ self.collection = true
10
+ self.root_element = :data
11
+
12
+ attribute :title, String
13
+ attribute :body, String
14
+ attribute :created_at, Time
15
+ end
16
+
17
+ let(:response_body) do
18
+ {
19
+ data: {
20
+ id: 12,
21
+ title: 'Lorem Ipsum',
22
+ body: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
23
+ created_at: Time.new(2015, 10, 4, 9, 30, 0),
24
+ }
25
+ }
26
+ end
27
+
28
+ let(:expected_default_headers) do
29
+ { 'Accept' => 'application/json', 'User-Agent' => "RemoteResource #{RemoteResource::VERSION}" }
30
+ end
31
+
32
+ describe 'default behaviour' do
33
+ let!(:expected_request) do
34
+ mock_request = stub_request(:get, 'https://www.example.com/posts/12.json')
35
+ mock_request.with(query: nil, body: nil, headers: expected_default_headers)
36
+ mock_request.to_return(status: 200, body: response_body.to_json)
37
+ mock_request
38
+ end
39
+
40
+ it 'performs the correct HTTP GET request' do
41
+ Post.find(12)
42
+ expect(expected_request).to have_been_requested
43
+ end
44
+
45
+ it 'builds the correct resource' do
46
+ post = Post.find(12)
47
+
48
+ aggregate_failures do
49
+ expect(post.id).to eql 12
50
+ expect(post.title).to eql 'Lorem Ipsum'
51
+ expect(post.body).to eql 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
52
+ expect(post.created_at).to eql Time.new(2015, 10, 4, 9, 30, 0)
53
+ end
54
+ end
55
+ end
56
+
57
+ describe 'with connection_options[:params]' do
58
+ let!(:expected_request) do
59
+ mock_request = stub_request(:get, 'https://www.example.com/posts/12.json')
60
+ mock_request.with(query: { pseudonym: 'pseudonym' }, body: nil, headers: expected_default_headers)
61
+ mock_request.to_return(status: 200, body: response_body.to_json)
62
+ mock_request
63
+ end
64
+
65
+ it 'performs the correct HTTP GET request' do
66
+ Post.find(12, params: { pseudonym: 'pseudonym' })
67
+ expect(expected_request).to have_been_requested
68
+ end
69
+ end
70
+
71
+ describe 'with connection_options[:headers]' do
72
+ let!(:expected_request) do
73
+ mock_request = stub_request(:get, 'https://www.example.com/posts/12.json')
74
+ mock_request.with(query: nil, body: nil, headers: { 'X-Pseudonym' => 'pseudonym' })
75
+ mock_request.to_return(status: 200, body: response_body.to_json)
76
+ mock_request
77
+ end
78
+
79
+ it 'performs the correct HTTP GET request' do
80
+ Post.find(12, headers: { 'X-Pseudonym' => 'pseudonym' })
81
+ expect(expected_request).to have_been_requested
82
+ end
83
+ end
84
+
85
+ describe 'with a 404 response' do
86
+ let!(:expected_request) do
87
+ mock_request = stub_request(:get, 'https://www.example.com/posts/12.json')
88
+ mock_request.with(query: { pseudonym: 'pseudonym' }, body: nil, headers: expected_default_headers.merge({ 'X-Pseudonym' => 'pseudonym' }))
89
+ mock_request.to_return(status: 404)
90
+ mock_request
91
+ end
92
+
93
+ it 'raises the not found error' do
94
+ expect { Post.find(12, params: { pseudonym: 'pseudonym' }, headers: { 'X-Pseudonym' => 'pseudonym' }) }.to raise_error RemoteResource::HTTPNotFound
95
+ end
96
+
97
+ it 'adds metadata to the raised error' do
98
+ begin
99
+ Post.find(12, params: { pseudonym: 'pseudonym' }, headers: { 'X-Pseudonym' => 'pseudonym' })
100
+ rescue RemoteResource::HTTPNotFound => error
101
+ aggregate_failures do
102
+ expect(error.message).to eql 'HTTP request failed for Post with response_code=404 with http_action=get with request_url=https://www.example.com/posts/12.json'
103
+ expect(error.request_url).to eql 'https://www.example.com/posts/12.json'
104
+ expect(error.response_code).to eql 404
105
+ expect(error.request_query).to eql(RemoteResource::Util.encode_params_to_query({ pseudonym: 'pseudonym' }))
106
+ expect(error.request_headers).to eql(expected_default_headers.merge({ 'X-Pseudonym' => 'pseudonym' }))
107
+ end
108
+ end
109
+ end
110
+ end
111
+
112
+ describe 'with a 500 response' do
113
+ let!(:expected_request) do
114
+ mock_request = stub_request(:get, 'https://www.example.com/posts/12.json')
115
+ mock_request.with(query: { pseudonym: 'pseudonym' }, body: nil, headers: expected_default_headers.merge({ 'X-Pseudonym' => 'pseudonym' }))
116
+ mock_request.to_return(status: 500)
117
+ mock_request
118
+ end
119
+
120
+ it 'raises the server error' do
121
+ expect { Post.find(12, params: { pseudonym: 'pseudonym' }, headers: { 'X-Pseudonym' => 'pseudonym' }) }.to raise_error RemoteResource::HTTPServerError
122
+ end
123
+
124
+ it 'adds metadata to the raised error' do
125
+ begin
126
+ Post.find(12, params: { pseudonym: 'pseudonym' }, headers: { 'X-Pseudonym' => 'pseudonym' })
127
+ rescue RemoteResource::HTTPServerError => error
128
+ aggregate_failures do
129
+ expect(error.message).to eql 'HTTP request failed for Post with response_code=500 with http_action=get with request_url=https://www.example.com/posts/12.json'
130
+ expect(error.request_url).to eql 'https://www.example.com/posts/12.json'
131
+ expect(error.response_code).to eql 500
132
+ expect(error.request_query).to eql(RemoteResource::Util.encode_params_to_query({ pseudonym: 'pseudonym' }))
133
+ expect(error.request_headers).to eql(expected_default_headers.merge({ 'X-Pseudonym' => 'pseudonym' }))
134
+ end
135
+ end
136
+ end
137
+ end
138
+
139
+ end
@@ -0,0 +1,222 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe 'headers in connection_options' do
4
+
5
+ class Post
6
+ include RemoteResource::Base
7
+
8
+ self.site = 'https://www.example.com'
9
+ self.collection = true
10
+ self.root_element = :data
11
+
12
+ attribute :title, String
13
+ attribute :body, String
14
+ attribute :featured, Boolean
15
+ attribute :created_at, Time
16
+ end
17
+
18
+ let(:response_body) do
19
+ {
20
+ data: {
21
+ id: 12,
22
+ title: 'Aliquam lobortis',
23
+ body: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
24
+ featured: false,
25
+ created_at: Time.new(2015, 10, 4, 9, 30, 0),
26
+ }
27
+ }
28
+ end
29
+
30
+ describe 'default behaviour' do
31
+ let(:expected_headers) do
32
+ {
33
+ 'Accept' => 'application/json',
34
+ 'User-Agent' => "RemoteResource #{RemoteResource::VERSION}"
35
+ }
36
+ end
37
+
38
+ let!(:expected_request) do
39
+ mock_request = stub_request(:get, 'https://www.example.com/posts/12.json')
40
+ mock_request.with(headers: expected_headers)
41
+ mock_request.to_return(status: 200, body: response_body.to_json)
42
+ mock_request
43
+ end
44
+
45
+ it 'performs the correct HTTP GET request with the default headers' do
46
+ Post.find(12)
47
+ expect(expected_request).to have_been_requested
48
+ end
49
+ end
50
+
51
+ describe 'connection_options[:headers]' do
52
+ let(:expected_headers) do
53
+ {
54
+ 'Accept' => 'application/json',
55
+ 'User-Agent' => "RemoteResource #{RemoteResource::VERSION}",
56
+ 'X-Locale' => 'From connection_options[:headers]'
57
+ }
58
+ end
59
+
60
+ let!(:expected_request) do
61
+ mock_request = stub_request(:get, 'https://www.example.com/posts/12.json')
62
+ mock_request.with(headers: expected_headers)
63
+ mock_request.to_return(status: 200, body: response_body.to_json)
64
+ mock_request
65
+ end
66
+
67
+ it 'performs the correct HTTP GET request with the default headers and connection_options[:headers]' do
68
+ Post.find(12, { headers: { 'X-Locale' => 'From connection_options[:headers]' } })
69
+ expect(expected_request).to have_been_requested
70
+ end
71
+ end
72
+
73
+ describe 'connection_options[:default_headers]' do
74
+ let(:expected_headers) do
75
+ {
76
+ 'User-Agent' => 'From connection_options[:default_headers]',
77
+ 'X-Locale' => 'From connection_options[:headers]'
78
+ }
79
+ end
80
+
81
+ let!(:expected_request) do
82
+ mock_request = stub_request(:get, 'https://www.example.com/posts/12.json')
83
+ mock_request.with(headers: expected_headers)
84
+ mock_request.to_return(status: 200, body: response_body.to_json)
85
+ mock_request
86
+ end
87
+
88
+ it 'performs the correct HTTP GET request overriding the default headers with the connection_options[:default_headers]' do
89
+ Post.find(12, { headers: { 'X-Locale' => 'From connection_options[:headers]' }, default_headers: { 'User-Agent' => 'From connection_options[:default_headers]' } })
90
+ expect(expected_request).to have_been_requested
91
+ end
92
+ end
93
+
94
+ describe '.default_headers' do
95
+ let(:expected_headers) do
96
+ {
97
+ 'User-Agent' => 'From .default_headers',
98
+ 'X-Locale' => 'From connection_options[:headers]'
99
+ }
100
+ end
101
+
102
+ let!(:expected_request) do
103
+ mock_request = stub_request(:get, 'https://www.example.com/posts/12.json')
104
+ mock_request.with(headers: expected_headers)
105
+ mock_request.to_return(status: 200, body: response_body.to_json)
106
+ mock_request
107
+ end
108
+
109
+ before { Post.default_headers = { 'User-Agent' => 'From .default_headers' } }
110
+ after { Post.default_headers = {} }
111
+
112
+ it 'performs the correct HTTP GET request overriding the default headers with the .default_headers headers' do
113
+ Post.find(12, { headers: { 'X-Locale' => 'From connection_options[:headers]' } })
114
+ expect(expected_request).to have_been_requested
115
+ end
116
+ end
117
+
118
+ describe 'connection_options[:default_headers] and .default_headers' do
119
+ let(:expected_headers) do
120
+ {
121
+ 'User-Agent' => 'From connection_options[:default_headers]',
122
+ 'X-Locale' => 'From connection_options[:headers]'
123
+ }
124
+ end
125
+
126
+ let!(:expected_request) do
127
+ mock_request = stub_request(:get, 'https://www.example.com/posts/12.json')
128
+ mock_request.with(headers: expected_headers)
129
+ mock_request.to_return(status: 200, body: response_body.to_json)
130
+ mock_request
131
+ end
132
+
133
+ before { Post.default_headers = { 'User-Agent' => 'From .default_headers' } }
134
+ after { Post.default_headers = {} }
135
+
136
+ it 'performs the correct HTTP GET request overriding the default headers with the connection_options[:default_headers]' do
137
+ Post.find(12, { headers: { 'X-Locale' => 'From connection_options[:headers]' }, default_headers: { 'User-Agent' => 'From connection_options[:default_headers]' } })
138
+ expect(expected_request).to have_been_requested
139
+ end
140
+ end
141
+
142
+ describe 'RemoteResource::Base.global_headers' do
143
+ let(:expected_headers) do
144
+ {
145
+ 'Accept' => 'application/json',
146
+ 'User-Agent' => 'From RemoteResource::Base.global_headers',
147
+ 'Authorization' => 'From RemoteResource::Base.global_headers',
148
+ 'X-Locale' => 'From connection_options[:headers]',
149
+ }
150
+ end
151
+
152
+ let!(:expected_request) do
153
+ mock_request = stub_request(:get, 'https://www.example.com/posts/12.json')
154
+ mock_request.with(headers: expected_headers)
155
+ mock_request.to_return(status: 200, body: response_body.to_json)
156
+ mock_request
157
+ end
158
+
159
+ before { RemoteResource::Base.global_headers = { 'User-Agent' => 'From RemoteResource::Base.global_headers', 'X-Locale' => 'From RemoteResource::Base.global_headers', 'Authorization' => 'From RemoteResource::Base.global_headers' } }
160
+ after { RemoteResource::Base.global_headers = nil }
161
+
162
+ it 'performs the correct HTTP GET request with the default headers and the .global_headers headers' do
163
+ Post.find(12, { headers: { 'X-Locale' => 'From connection_options[:headers]' } })
164
+ expect(expected_request).to have_been_requested
165
+ end
166
+ end
167
+
168
+ describe '.with_connection_options' do
169
+ let(:expected_headers) do
170
+ {
171
+ 'Accept' => 'application/json',
172
+ 'User-Agent' => 'From .with_connection_options',
173
+ 'Authorization' => 'From .with_connection_options',
174
+ 'X-Locale' => 'From connection_options[:headers]',
175
+ }
176
+ end
177
+
178
+ let!(:expected_request) do
179
+ mock_request = stub_request(:get, 'https://www.example.com/posts/12.json')
180
+ mock_request.with(headers: expected_headers)
181
+ mock_request.to_return(status: 200, body: response_body.to_json)
182
+ mock_request
183
+ end
184
+
185
+ it 'performs the correct HTTP GET request with the default headers and the .with_connection_options headers' do
186
+ Post.with_connection_options({ headers: { 'User-Agent' => 'From .with_connection_options', 'X-Locale' => 'From .with_connection_options', 'Authorization' => 'From .with_connection_options' } }) do
187
+ Post.find(12, { headers: { 'X-Locale' => 'From connection_options[:headers]' } })
188
+ end
189
+ expect(expected_request).to have_been_requested
190
+ end
191
+ end
192
+
193
+ describe 'RemoteResource::Base.global_headers and .with_connection_options' do
194
+ let(:expected_headers) do
195
+ {
196
+ 'Accept' => 'application/json',
197
+ 'User-Agent' => 'From RemoteResource::Base.global_headers',
198
+ 'Authorization' => 'From .with_connection_options',
199
+ 'X-Locale' => 'From connection_options[:headers]',
200
+ 'X-Country' => 'From connection_options[:headers]',
201
+ }
202
+ end
203
+
204
+ let!(:expected_request) do
205
+ mock_request = stub_request(:get, 'https://www.example.com/posts/12.json')
206
+ mock_request.with(headers: expected_headers)
207
+ mock_request.to_return(status: 200, body: response_body.to_json)
208
+ mock_request
209
+ end
210
+
211
+ before { RemoteResource::Base.global_headers = { 'User-Agent' => 'From RemoteResource::Base.global_headers', 'X-Locale' => 'From RemoteResource::Base.global_headers', 'Authorization' => 'From RemoteResource::Base.global_headers' } }
212
+ after { RemoteResource::Base.global_headers = nil }
213
+
214
+ it 'performs the correct HTTP GET request with the default headers and the .global_headers headers and the and .with_connection_options headers' do
215
+ Post.with_connection_options({ headers: { 'Authorization' => 'From .with_connection_options' } }) do
216
+ Post.find(12, { headers: { 'X-Locale' => 'From connection_options[:headers]', 'X-Country' => 'From connection_options[:headers]' } })
217
+ end
218
+ expect(expected_request).to have_been_requested
219
+ end
220
+ end
221
+
222
+ end
@@ -0,0 +1,138 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe 'connection_options for naming' do
4
+
5
+ class Post
6
+ include RemoteResource::Base
7
+
8
+ self.site = 'https://www.example.com'
9
+ self.collection = true
10
+ self.root_element = :data
11
+
12
+ attribute :title, String
13
+ attribute :body, String
14
+ attribute :featured, Boolean
15
+ attribute :created_at, Time
16
+ end
17
+
18
+ describe 'connection_options[:site]' do
19
+ let(:response_body) do
20
+ {
21
+ data: {
22
+ id: 12,
23
+ title: 'Aliquam lobortis',
24
+ body: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
25
+ featured: false,
26
+ created_at: Time.new(2015, 10, 4, 9, 30, 0),
27
+ }
28
+ }
29
+ end
30
+
31
+ let!(:expected_request) do
32
+ mock_request = stub_request(:get, 'https://api.example.com/posts/12.json')
33
+ mock_request.to_return(status: 200, body: response_body.to_json)
34
+ mock_request
35
+ end
36
+
37
+ it 'performs the correct HTTP GET request' do
38
+ Post.find(12, { site: 'https://api.example.com' })
39
+ Post.find(12, { site: 'https://api.example.com/' })
40
+ expect(expected_request).to have_been_requested.times(2)
41
+ end
42
+ end
43
+
44
+ describe 'connection_options[:version]' do
45
+ let(:response_body) do
46
+ {
47
+ data: {
48
+ id: 12,
49
+ title: 'Aliquam lobortis',
50
+ body: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
51
+ featured: false,
52
+ created_at: Time.new(2015, 10, 4, 9, 30, 0),
53
+ }
54
+ }
55
+ end
56
+
57
+ let!(:expected_request) do
58
+ mock_request = stub_request(:get, 'https://www.example.com/api/v2/posts/12.json')
59
+ mock_request.to_return(status: 200, body: response_body.to_json)
60
+ mock_request
61
+ end
62
+
63
+ it 'performs the correct HTTP GET request' do
64
+ Post.find(12, { version: '/api/v2' })
65
+ Post.find(12, { version: 'api/v2' })
66
+ Post.find(12, { version: '/api/v2/' })
67
+ expect(expected_request).to have_been_requested.times(3)
68
+ end
69
+ end
70
+
71
+ describe 'connection_options[:version] and connection_options[:path_prefix]' do
72
+ let(:response_body) do
73
+ {
74
+ data: {
75
+ id: 12,
76
+ title: 'Aliquam lobortis',
77
+ body: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
78
+ featured: false,
79
+ created_at: Time.new(2015, 10, 4, 9, 30, 0),
80
+ }
81
+ }
82
+ end
83
+
84
+ let!(:expected_request) do
85
+ mock_request = stub_request(:get, 'https://www.example.com/api/v2/archive/posts/12.json')
86
+ mock_request.to_return(status: 200, body: response_body.to_json)
87
+ mock_request
88
+ end
89
+
90
+ it 'performs the correct HTTP GET request' do
91
+ Post.find(12, { version: '/api/v2', path_prefix: '/archive' })
92
+ Post.find(12, { version: 'api/v2', path_prefix: 'archive' })
93
+ Post.find(12, { version: '/api/v2/', path_prefix: '/archive/' })
94
+ expect(expected_request).to have_been_requested.times(3)
95
+ end
96
+ end
97
+
98
+ describe 'connection_options[:path_postfix]' do
99
+ let(:response_body) do
100
+ {
101
+ data: {
102
+ id: 12,
103
+ title: 'Aliquam lobortis',
104
+ body: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
105
+ featured: false,
106
+ created_at: Time.new(2015, 10, 4, 9, 30, 0),
107
+ }
108
+ }
109
+ end
110
+
111
+ let!(:expected_request_singular) do
112
+ mock_request = stub_request(:get, 'https://www.example.com/posts/12/featured.json')
113
+ mock_request.to_return(status: 200, body: response_body.to_json)
114
+ mock_request
115
+ end
116
+
117
+ let!(:expected_request_collection) do
118
+ mock_request = stub_request(:get, 'https://www.example.com/posts/featured.json')
119
+ mock_request.to_return(status: 200, body: response_body.to_json)
120
+ mock_request
121
+ end
122
+
123
+ it 'performs the correct HTTP GET request for a singular resource' do
124
+ Post.find(12, { path_postfix: '/featured' })
125
+ Post.find(12, { path_postfix: 'featured' })
126
+ Post.find(12, { path_postfix: '/featured/' })
127
+ expect(expected_request_singular).to have_been_requested.times(3)
128
+ end
129
+
130
+ it 'performs the correct HTTP GET request for a collection resource' do
131
+ Post.all({ path_postfix: '/featured' })
132
+ Post.all({ path_postfix: 'featured' })
133
+ Post.all({ path_postfix: '/featured/' })
134
+ expect(expected_request_collection).to have_been_requested.times(3)
135
+ end
136
+ end
137
+
138
+ end