ddy_remote_resource 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.rspec +2 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +3 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +182 -0
  10. data/Rakefile +7 -0
  11. data/lib/extensions/ethon/easy/queryable.rb +36 -0
  12. data/lib/remote_resource.rb +64 -0
  13. data/lib/remote_resource/base.rb +126 -0
  14. data/lib/remote_resource/builder.rb +53 -0
  15. data/lib/remote_resource/collection.rb +31 -0
  16. data/lib/remote_resource/connection.rb +24 -0
  17. data/lib/remote_resource/connection_options.rb +41 -0
  18. data/lib/remote_resource/http_errors.rb +33 -0
  19. data/lib/remote_resource/querying/finder_methods.rb +34 -0
  20. data/lib/remote_resource/querying/persistence_methods.rb +38 -0
  21. data/lib/remote_resource/request.rb +106 -0
  22. data/lib/remote_resource/response.rb +69 -0
  23. data/lib/remote_resource/response_handeling.rb +48 -0
  24. data/lib/remote_resource/rest.rb +29 -0
  25. data/lib/remote_resource/url_naming.rb +34 -0
  26. data/lib/remote_resource/url_naming_determination.rb +39 -0
  27. data/lib/remote_resource/version.rb +3 -0
  28. data/remote_resource.gemspec +32 -0
  29. data/spec/lib/extensions/ethon/easy/queryable_spec.rb +135 -0
  30. data/spec/lib/remote_resource/base_spec.rb +388 -0
  31. data/spec/lib/remote_resource/builder_spec.rb +245 -0
  32. data/spec/lib/remote_resource/collection_spec.rb +148 -0
  33. data/spec/lib/remote_resource/connection_options_spec.rb +124 -0
  34. data/spec/lib/remote_resource/connection_spec.rb +61 -0
  35. data/spec/lib/remote_resource/querying/finder_methods_spec.rb +105 -0
  36. data/spec/lib/remote_resource/querying/persistence_methods_spec.rb +174 -0
  37. data/spec/lib/remote_resource/request_spec.rb +594 -0
  38. data/spec/lib/remote_resource/response_spec.rb +196 -0
  39. data/spec/lib/remote_resource/rest_spec.rb +98 -0
  40. data/spec/lib/remote_resource/url_naming_determination_spec.rb +225 -0
  41. data/spec/lib/remote_resource/url_naming_spec.rb +72 -0
  42. data/spec/lib/remote_resource/version_spec.rb +8 -0
  43. data/spec/spec_helper.rb +4 -0
  44. metadata +242 -0
@@ -0,0 +1,245 @@
1
+ require 'spec_helper'
2
+
3
+ describe RemoteResource::Builder do
4
+
5
+ module RemoteResource
6
+ class BuilderDummy
7
+ include RemoteResource::Base
8
+
9
+ self.site = 'https://foobar.com'
10
+
11
+ attr_accessor :username
12
+
13
+ end
14
+ end
15
+
16
+ let(:dummy_class) { RemoteResource::BuilderDummy }
17
+ let(:dummy) { dummy_class.new }
18
+
19
+ describe '.build_resource_from_response' do
20
+ let(:response) { RemoteResource::Response.new double.as_null_object }
21
+ let(:sanitized_response_body) do
22
+ { "id" => "12", "username" => "foobar" }
23
+ end
24
+
25
+ before { allow(response).to receive(:sanitized_response_body) { sanitized_response_body } }
26
+
27
+ it 'calls the .build_resource' do
28
+ expect(dummy_class).to receive(:build_resource).with sanitized_response_body, { _response: an_instance_of(RemoteResource::Response) }
29
+ dummy_class.build_resource_from_response response
30
+ end
31
+ end
32
+
33
+ describe '.build_resource' do
34
+ let(:response) { RemoteResource::Response.new double.as_null_object }
35
+ let(:response_hash) { dummy_class.send :response_hash, response }
36
+
37
+ context 'when collection is a Hash' do
38
+ let(:collection) do
39
+ { "id" => "12", "username" => "foobar" }
40
+ end
41
+
42
+ context 'and response_hash is given' do
43
+ it 'instantiates the resource with the collection AND response_hash' do
44
+ expect(dummy_class).to receive(:new).with(collection.merge(response_hash)).and_call_original
45
+ dummy_class.build_resource collection, response_hash
46
+ end
47
+
48
+ it 'returns the resource' do
49
+ expect(dummy_class.build_resource collection, response_hash).to be_a dummy_class
50
+ end
51
+ end
52
+
53
+ context 'and NO response_hash is given' do
54
+ it 'instantiates the resource with the collection' do
55
+ expect(dummy_class).to receive(:new).with(collection).and_call_original
56
+ dummy_class.build_resource collection
57
+ end
58
+
59
+ it 'returns the resource' do
60
+ expect(dummy_class.build_resource collection).to be_a dummy_class
61
+ end
62
+ end
63
+ end
64
+
65
+ context 'when collection is NOT a Hash' do
66
+ let(:collection) { [] }
67
+
68
+ it 'returns nil' do
69
+ expect(dummy_class.build_resource collection, response_hash).to be_nil
70
+ end
71
+ end
72
+ end
73
+
74
+ describe '.build_collection_from_response' do
75
+ let(:response) { RemoteResource::Response.new double.as_null_object }
76
+ let(:sanitized_response_body) do
77
+ [
78
+ { "id" => "10", "username" => "foobar" },
79
+ { "id" => "11", "username" => "bazbar" },
80
+ { "id" => "12", "username" => "aapmies" }
81
+ ]
82
+ end
83
+
84
+ before { allow(response).to receive(:sanitized_response_body) { sanitized_response_body } }
85
+
86
+ it 'calls the .build_collection' do
87
+ expect(dummy_class).to receive(:build_collection).with sanitized_response_body, { _response: an_instance_of(RemoteResource::Response) }
88
+ dummy_class.build_collection_from_response response
89
+ end
90
+ end
91
+
92
+ describe '.build_collection' do
93
+ let(:response) { RemoteResource::Response.new double.as_null_object }
94
+ let(:response_hash) { dummy_class.send :response_hash, response }
95
+
96
+ context 'when collection is an Array' do
97
+ let(:collection) do
98
+ [
99
+ { "id" => "10", "username" => "foobar" },
100
+ { "id" => "11", "username" => "bazbar" },
101
+ { "id" => "12", "username" => "aapmies" }
102
+ ]
103
+ end
104
+
105
+ context 'and response_hash is given' do
106
+ it 'instantiates a RemoteResource::Collection with the class, collection AND response_hash' do
107
+ expect(RemoteResource::Collection).to receive(:new).with(dummy_class, collection, response_hash).and_call_original
108
+ dummy_class.build_collection collection, response_hash
109
+ end
110
+
111
+ it 'returns the resources' do
112
+ resources = dummy_class.build_collection collection, response_hash
113
+ resources.each { |resource| expect(resource).to be_a dummy_class }
114
+ end
115
+ end
116
+
117
+ context 'and NO response_hash is given' do
118
+ it 'instantiates a RemoteResource::Collection with the class and collection' do
119
+ expect(RemoteResource::Collection).to receive(:new).with(dummy_class, collection, {}).and_call_original
120
+ dummy_class.build_collection collection
121
+ end
122
+
123
+ it 'returns the resources' do
124
+ resources = dummy_class.build_collection collection
125
+ resources.each { |resource| expect(resource).to be_a dummy_class }
126
+ end
127
+ end
128
+ end
129
+
130
+ context 'when collection is NOT an Array' do
131
+ let(:collection) { {} }
132
+
133
+ it 'returns nil' do
134
+ expect(dummy_class.build_collection collection, response_hash).to be_nil
135
+ end
136
+ end
137
+ end
138
+
139
+ describe '#rebuild_resource_from_response' do
140
+ let(:response) { RemoteResource::Response.new double.as_null_object }
141
+ let(:sanitized_response_body) do
142
+ { "id" => "12", "username" => "foobar" }
143
+ end
144
+
145
+ before { allow(response).to receive(:sanitized_response_body) { sanitized_response_body } }
146
+
147
+ it 'calls the #rebuild_resource' do
148
+ expect(dummy).to receive(:rebuild_resource).with sanitized_response_body, { _response: an_instance_of(RemoteResource::Response) }
149
+ dummy.rebuild_resource_from_response response
150
+ end
151
+ end
152
+
153
+ describe '#rebuild_resource' do
154
+ let(:response) { RemoteResource::Response.new double.as_null_object }
155
+ let(:response_hash) { dummy.send :response_hash, response }
156
+
157
+ before do
158
+ dummy.id = nil
159
+ dummy.username = "foo"
160
+ end
161
+
162
+ context 'when the collection is a Hash' do
163
+ let(:collection) do
164
+ { "id" => "12", "username" => "foobar" }
165
+ end
166
+
167
+ context 'and response_hash is given' do
168
+ it 'mass-assigns the attributes of the resource with the collection AND with response_hash' do
169
+ expect(dummy.id).to be_nil
170
+ expect(dummy.username).to eql 'foo'
171
+ expect(dummy._response).to be_nil
172
+
173
+ dummy.rebuild_resource collection, response_hash
174
+
175
+ expect(dummy.id).to eql '12'
176
+ expect(dummy.username).to eql 'foobar'
177
+ expect(dummy._response).to be_a RemoteResource::Response
178
+ end
179
+
180
+ it 'returns the resource' do
181
+ expect(dummy.rebuild_resource collection, response_hash).to be_a dummy_class
182
+ end
183
+ end
184
+
185
+ context 'and NO response_hash is given' do
186
+ it 'mass-assigns the attributes of the resource with the collection' do
187
+ expect(dummy.id).to be_nil
188
+ expect(dummy.username).to eql 'foo'
189
+ expect(dummy._response).to be_nil
190
+
191
+ dummy.rebuild_resource collection
192
+
193
+ expect(dummy.id).to eql '12'
194
+ expect(dummy.username).to eql 'foobar'
195
+ expect(dummy._response).to be_nil
196
+ end
197
+
198
+ it 'returns the resource' do
199
+ expect(dummy.rebuild_resource collection).to be_a dummy_class
200
+ end
201
+ end
202
+ end
203
+
204
+ context 'when the collection is something else' do
205
+ let(:collection) { 'foobar' }
206
+
207
+ context 'and response_hash is given' do
208
+ it 'assigns the response_hash of the resource' do
209
+ expect(dummy.id).to be_nil
210
+ expect(dummy.username).to eql 'foo'
211
+ expect(dummy._response).to be_nil
212
+
213
+ dummy.rebuild_resource collection, response_hash
214
+
215
+ expect(dummy.id).to be_nil
216
+ expect(dummy.username).to eql 'foo'
217
+ expect(dummy._response).to be_a RemoteResource::Response
218
+ end
219
+
220
+ it 'returns the resource' do
221
+ expect(dummy.rebuild_resource collection, response_hash).to be_a dummy_class
222
+ end
223
+ end
224
+
225
+ context 'and NO response_hash is given' do
226
+ it 'does NOT assign the response_hash of the resource' do
227
+ expect(dummy.id).to be_nil
228
+ expect(dummy.username).to eql 'foo'
229
+ expect(dummy._response).to be_nil
230
+
231
+ dummy.rebuild_resource collection
232
+
233
+ expect(dummy.id).to be_nil
234
+ expect(dummy.username).to eql 'foo'
235
+ expect(dummy._response).to be_nil
236
+ end
237
+
238
+ it 'returns the resource' do
239
+ expect(dummy.rebuild_resource collection).to be_a dummy_class
240
+ end
241
+ end
242
+ end
243
+ end
244
+
245
+ end
@@ -0,0 +1,148 @@
1
+ require 'spec_helper'
2
+
3
+ describe RemoteResource::Collection do
4
+
5
+ module RemoteResource
6
+ class CollectionDummy
7
+ include RemoteResource::Base
8
+
9
+ self.site = 'https://foobar.com'
10
+
11
+ attr_accessor :username
12
+ end
13
+ end
14
+
15
+ let(:dummy_class) { RemoteResource::CollectionDummy }
16
+ let(:dummy) { dummy_class.new }
17
+
18
+ let(:response) { RemoteResource::Response.new double.as_null_object }
19
+ let(:response_hash) do
20
+ { _response: response }
21
+ end
22
+
23
+ let(:resources_collection) do
24
+ [
25
+ { id: 1, username: 'mies_1' },
26
+ { id: 2, username: 'mies_2' }
27
+ ]
28
+ end
29
+
30
+ let(:collection) { described_class.new dummy_class, resources_collection, response_hash }
31
+
32
+ specify { expect(described_class).to include Enumerable }
33
+
34
+ describe '#[]' do
35
+ let(:to_a) { collection.dup.to_a }
36
+
37
+ it 'delegates to the #to_a' do
38
+ expect(collection[0].id).to eql to_a[0].id
39
+ end
40
+ end
41
+
42
+ describe '#at' do
43
+ let(:to_a) { collection.dup.to_a }
44
+
45
+ it 'delegates to the #to_a' do
46
+ expect(collection.at(0).id).to eql to_a.at(0).id
47
+ end
48
+ end
49
+
50
+ describe '#reverse' do
51
+ let(:to_a) { collection.dup.to_a }
52
+
53
+ it 'delegates to the #to_a' do
54
+ expect(collection.reverse[0].id).to eql to_a.reverse[0].id
55
+ end
56
+ end
57
+
58
+ describe '#size' do
59
+ let(:to_a) { collection.dup.to_a }
60
+
61
+ it 'delegates to the #to_a' do
62
+ expect(collection.size).to eql to_a.size
63
+ end
64
+ end
65
+
66
+ describe '#each' do
67
+ context 'when the resources_collection is an Array' do
68
+ it 'instantiates each element in the resources_collection as resource' do
69
+ expect(dummy_class).to receive(:new).with(resources_collection[0].merge(response_hash)).and_call_original
70
+ expect(dummy_class).to receive(:new).with(resources_collection[1].merge(response_hash)).and_call_original
71
+ collection.all?
72
+ end
73
+
74
+ it 'returns an Enumerable' do
75
+ expect(collection).to be_an Enumerable
76
+ end
77
+
78
+ context 'Enumerable' do
79
+ it 'includes the resources' do
80
+ expect(collection[0]).to be_a RemoteResource::CollectionDummy
81
+ expect(collection[1]).to be_a RemoteResource::CollectionDummy
82
+ end
83
+
84
+ it 'includes the instantiated resources' do
85
+ expect(collection[0].username).to eql 'mies_1'
86
+ expect(collection[1].username).to eql 'mies_2'
87
+ end
88
+
89
+ it 'includes the responses in the instantiated resources' do
90
+ expect(collection[0]._response).to eql response
91
+ expect(collection[1]._response).to eql response
92
+ end
93
+ end
94
+ end
95
+
96
+ context 'when the resources_collection is NOT an Array' do
97
+ let(:resources_collection) { {} }
98
+
99
+ it 'returns nil' do
100
+ expect(collection.each).to be_nil
101
+ end
102
+ end
103
+ end
104
+
105
+ describe '#empty?' do
106
+ context 'when the resources_collection is nil' do
107
+ let(:resources_collection) { nil }
108
+
109
+ it 'returns true' do
110
+ expect(collection.empty?).to eql true
111
+ end
112
+ end
113
+
114
+ context 'when the resources_collection is blank' do
115
+ let(:resources_collection) { '' }
116
+
117
+ it 'returns true' do
118
+ expect(collection.empty?).to eql true
119
+ end
120
+ end
121
+
122
+ context 'when the resources_collection is NOT nil or blank' do
123
+ it 'returns false' do
124
+ expect(collection.empty?).to eql false
125
+ end
126
+ end
127
+ end
128
+
129
+ describe '#success?' do
130
+ context 'when response is successful' do
131
+ before { allow(response).to receive(:success?) { true } }
132
+
133
+ it 'returns true' do
134
+ expect(collection.success?).to eql true
135
+ end
136
+ end
137
+
138
+ context 'when response is NOT successful' do
139
+ before { allow(response).to receive(:success?) { false } }
140
+
141
+ it 'returns false' do
142
+ expect(collection.success?).to eql false
143
+ end
144
+ end
145
+ end
146
+
147
+
148
+ end
@@ -0,0 +1,124 @@
1
+ require 'spec_helper'
2
+
3
+ describe RemoteResource::ConnectionOptions do
4
+
5
+ module RemoteResource
6
+ class ConnectionOptionsDummy
7
+ include RemoteResource::Base
8
+
9
+ self.site = 'https://foobar.com'
10
+ self.content_type = ''
11
+ self.extra_headers = { "X-Locale" => "nl" }
12
+ self.version = '/v1'
13
+ self.path_prefix = '/prefix'
14
+ self.path_postfix = '/postfix'
15
+ self.content_type = '.json'
16
+ self.collection = true
17
+ self.root_element = :test_dummy
18
+
19
+ end
20
+ end
21
+
22
+ let(:dummy_class) { RemoteResource::ConnectionOptionsDummy }
23
+ let(:dummy) { dummy_class.new }
24
+
25
+ let(:connection_options) { described_class.new dummy_class }
26
+
27
+ describe '#initialize' do
28
+ it 'assigns the given class as #base_class' do
29
+ allow_any_instance_of(described_class).to receive(:initialize_connection_options)
30
+
31
+ expect(connection_options.base_class).to eql RemoteResource::ConnectionOptionsDummy
32
+ end
33
+
34
+ context 'RemoteResource::Base::OPTIONS' do
35
+ it 'calls #initialize_connection_options' do
36
+ expect_any_instance_of(described_class).to receive(:initialize_connection_options)
37
+ connection_options
38
+ end
39
+
40
+ it 'sets the accessor of the option from the RemoteResource::Base::OPTIONS' do
41
+ RemoteResource::Base::OPTIONS.each do |option|
42
+ expect(connection_options).to respond_to "#{option}"
43
+ expect(connection_options).to respond_to "#{option}="
44
+ end
45
+ end
46
+
47
+ it 'assigns the value of the option from the RemoteResource::Base::OPTIONS' do
48
+ RemoteResource::Base::OPTIONS.each do |option|
49
+ expect(connection_options.public_send(option)).to eql dummy_class.public_send(option)
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ describe '#merge' do
56
+ let(:custom_connection_options) do
57
+ {
58
+ site: 'https://dummy.foobar.com',
59
+ content_type: '.xml',
60
+ root_element: :test_dummy_api
61
+ }
62
+ end
63
+
64
+ it 'merges the custom connection_options in the connection_options' do
65
+ connection_options.merge custom_connection_options
66
+
67
+ expect(connection_options.site).to eql 'https://dummy.foobar.com'
68
+ expect(connection_options.content_type).to eql '.xml'
69
+ expect(connection_options.root_element).to eql :test_dummy_api
70
+ end
71
+
72
+ it 'returns self' do
73
+ expect(connection_options.merge custom_connection_options).to eql connection_options
74
+ end
75
+ end
76
+
77
+ describe '#to_hash' do
78
+ let(:connection_options_hash) do
79
+ {
80
+ base_url: 'https://foobar.com/v1/prefix/connection_options_dummies/postfix',
81
+ site: 'https://foobar.com',
82
+ headers: { "Accept" => "application/json", "X-Locale" => "nl" },
83
+ version: '/v1',
84
+ path_prefix: '/prefix',
85
+ path_postfix: '/postfix',
86
+ content_type: '.json',
87
+ collection: true,
88
+ collection_name: nil,
89
+ root_element: :test_dummy
90
+ }
91
+ end
92
+
93
+ it 'returns the connection_options as Hash' do
94
+ expect(connection_options.to_hash).to eql connection_options_hash
95
+ end
96
+ end
97
+
98
+ describe '#reload' do
99
+ it 'does NOT return self' do
100
+ expect(connection_options.reload).not_to eql connection_options
101
+ end
102
+
103
+ context 'RemoteResource::Base::OPTIONS' do
104
+ it 'calls #initialize_connection_options' do
105
+ expect_any_instance_of(described_class).to receive(:initialize_connection_options).twice
106
+ connection_options.reload
107
+ end
108
+ end
109
+ end
110
+
111
+ describe '#reload!' do
112
+ it 'returns self' do
113
+ expect(connection_options.reload!).to eql connection_options
114
+ end
115
+
116
+ context 'RemoteResource::Base::OPTIONS' do
117
+ it 'calls #initialize_connection_options' do
118
+ expect_any_instance_of(described_class).to receive(:initialize_connection_options).twice
119
+ connection_options.reload!
120
+ end
121
+ end
122
+ end
123
+
124
+ end