ddy_remote_resource 0.4.11 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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