flexirest 1.3.35 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,392 @@
1
+ require 'spec_helper'
2
+
3
+ class JsonAPIAssociationExampleAuthor < Flexirest::Base; end
4
+
5
+ class JsonAPIAssociationExampleTag < Flexirest::Base
6
+ proxy :json_api
7
+ has_many :authors, JsonAPIAssociationExampleAuthor
8
+ end
9
+
10
+ class JsonAPIAssociationExampleAuthor < Flexirest::Base
11
+ proxy :json_api
12
+ has_one :tag, JsonAPIAssociationExampleTag
13
+ end
14
+
15
+ class JsonAPIExampleArticle < Flexirest::Base
16
+ proxy :json_api
17
+ has_many :tags, JsonAPIAssociationExampleTag
18
+ has_one :author, JsonAPIAssociationExampleAuthor
19
+
20
+ faker1 = {
21
+ data: {
22
+ id: 1, type: 'articles', attributes: { item: 'item one' },
23
+ relationships: {
24
+ 'tags' => { data: [{ id: 1, type: 'tags' }, { id: 2, type: 'tags' }] }
25
+ }
26
+ },
27
+ included: [
28
+ { id: 1, type: 'tags', attributes: { item: 'item two' } },
29
+ { id: 2, type: 'tags', attributes: { item: 'item three' } }
30
+ ]
31
+ }
32
+ faker2 = {
33
+ data: [
34
+ {
35
+ id: 1, type: 'articles', attributes: { item: 'item one' },
36
+ relationships: {
37
+ 'tags' => { data: [{ id: 1, type: 'tags' }, { id: 2, type: 'tags' }] }
38
+ }
39
+ },
40
+ {
41
+ id: 2, type: 'articles', attributes: { item: 'item four' },
42
+ relationships: {
43
+ 'tags' => { data: [{ id: 2, type: 'tags' }] }
44
+ }
45
+ }
46
+ ],
47
+ included: [
48
+ { id: 1, type: 'tags', attributes: { item: 'item two' } },
49
+ { id: 2, type: 'tags', attributes: { item: 'item three' } }
50
+ ]
51
+ }
52
+ faker3 = {
53
+ data: {
54
+ id: 1, type: 'articles', attributes: { item: 'item one' },
55
+ relationships: { 'author' => { data: { id: 1, type: 'authors' } } }
56
+ },
57
+ included: [{ id: 1, type: 'authors', attributes: { item: 'item two' } }]
58
+ }
59
+ faker4 = {
60
+ data: {
61
+ id: 1, type: 'articles', attributes: { item: 'item one' },
62
+ relationships: { 'author' => { data: { id: 1, type: 'authors' } } }
63
+ },
64
+ included: [
65
+ { id: 1, type: 'authors', attributes: { item: 'item two' },
66
+ relationships: { 'tag' => { data: { id: 1, type: 'tags' } } } },
67
+ { id: 1, type: 'tags', attributes: { item: 'item three' } }
68
+ ]
69
+ }
70
+ faker5 = {
71
+ data: {
72
+ id: 1, type: 'articles', attributes: { item: 'item one' },
73
+ relationships: { 'tags' => { data: [{ id: 1, type: 'tags' }] } }
74
+ },
75
+ included: [
76
+ { id: 1, type: 'tags', attributes: { item: 'item three' },
77
+ relationships: { 'authors' => { data: [{ id: 1, type: 'tags' }] } } },
78
+ { id: 1, type: 'authors', attributes: { item: 'item two' } }
79
+ ]
80
+ }
81
+ faker6 = {
82
+ data: {
83
+ id: 1, type: 'articles', attributes: { item: 'item one' },
84
+ relationships: { 'tags' => { data: [] }, 'author' => { data: nil } }
85
+ }
86
+ }
87
+
88
+ get(
89
+ :find,
90
+ '/articles/:id',
91
+ fake: faker1.to_json,
92
+ fake_content_type: 'application/vnd.api+json'
93
+ )
94
+
95
+ get(
96
+ :find_all,
97
+ '/articles',
98
+ fake: faker2.to_json,
99
+ fake_content_type: 'application/vnd.api+json'
100
+ )
101
+
102
+ get(
103
+ :find_single_author,
104
+ '/articles/:id',
105
+ fake: faker3.to_json,
106
+ fake_content_type: 'application/vnd.api+json'
107
+ )
108
+
109
+ get(
110
+ :find_single_nested,
111
+ '/articles/:id',
112
+ fake: faker4.to_json,
113
+ fake_content_type: 'application/vnd.api+json'
114
+ )
115
+
116
+ get(
117
+ :find_multi_nested,
118
+ '/articles/:id',
119
+ fake: faker5.to_json,
120
+ fake_content_type: 'application/vnd.api+json'
121
+ )
122
+
123
+ get(
124
+ :no_assocs,
125
+ '/articles/:id',
126
+ fake: faker6.to_json,
127
+ fake_content_type: 'application/vnd.api+json'
128
+ )
129
+ end
130
+
131
+ module JsonAPIExample
132
+ class Author < Flexirest::Base
133
+ proxy :json_api
134
+ base_url 'http://www.example.com'
135
+
136
+ author_faker = {
137
+ data: { id: 1, type: 'authors', attributes: { item: 'item three' } }
138
+ }
139
+
140
+ get(
141
+ :find_author,
142
+ '/articles/:article_id/author',
143
+ fake: author_faker.to_json,
144
+ fake_content_type: 'application/vnd.api+json'
145
+ )
146
+ end
147
+
148
+ class Tag < Flexirest::Base
149
+ proxy :json_api
150
+ base_url 'http://www.example.com'
151
+
152
+ tags_faker = {
153
+ data: [{ id: 1, type: 'tags', attributes: { item: 'item two' } }]
154
+ }
155
+
156
+ get(
157
+ :find_tags,
158
+ '/articles/:article_id/tags',
159
+ fake: tags_faker.to_json,
160
+ fake_content_type: 'application/vnd.api+json'
161
+ )
162
+ end
163
+
164
+ class Article < Flexirest::Base
165
+ base_url 'http://www.example.com'
166
+ proxy :json_api
167
+ has_one :author, Author
168
+ has_many :tags, Tag
169
+
170
+ faker = {
171
+ data: { id: 1, type: 'articles', attributes: { item: 'item one' } }
172
+ }
173
+
174
+ faker_lazy = {
175
+ data: {
176
+ id: 1, type: 'articles', attributes: { item: 'item one' },
177
+ relationships: {
178
+ 'tags' => {
179
+ links: {
180
+ self: 'http://www.example.com/articles/1/relationships/tags',
181
+ related: 'http://www.example.com/articles/1/tags'
182
+ }
183
+ },
184
+ 'author' => {
185
+ links: {
186
+ self: 'http://www.example.com/articles/1/relationships/author',
187
+ related: 'http://www.example.com/articles/1/author'
188
+ }
189
+ }
190
+ }
191
+ }
192
+ }
193
+
194
+ get(
195
+ :find_lazy,
196
+ '/articles/:id',
197
+ fake: faker_lazy.to_json,
198
+ fake_content_type: 'application/vnd.api+json'
199
+ )
200
+
201
+ get(
202
+ :find,
203
+ '/articles/:id',
204
+ fake: faker.to_json,
205
+ fake_content_type: 'application/vnd.api+json'
206
+ )
207
+
208
+ post :create, '/articles', fake_content_type: 'application/vnd.api+json'
209
+
210
+ patch(
211
+ :update,
212
+ '/articles/:id',
213
+ fake_content_type: 'application/vnd.api+json'
214
+ )
215
+
216
+ delete(
217
+ :delete,
218
+ '/articles/:id',
219
+ fake_content_type: 'application/vnd.api+json'
220
+ )
221
+ end
222
+
223
+ class AuthorAlias < Flexirest::Base
224
+ alias_type :authors
225
+ proxy :json_api
226
+ end
227
+
228
+ class ArticleAlias < Flexirest::Base
229
+ alias_type :articles
230
+ base_url 'http://www.example.com'
231
+ proxy :json_api
232
+ has_one :author, AuthorAlias
233
+
234
+ faker = {
235
+ data: { id: 1, type: 'articles', attributes: { item: 'item one' } }
236
+ }
237
+
238
+ get(
239
+ :find,
240
+ '/articles/:id',
241
+ fake: faker.to_json,
242
+ fake_content_type: 'application/vnd.api+json'
243
+ )
244
+
245
+ patch :update, '/articles/:id'
246
+ end
247
+ end
248
+
249
+ describe 'JSON API' do
250
+ let(:subject) { JsonAPIExampleArticle }
251
+ let(:article) { JsonAPIExample::Article }
252
+ let(:tags) { JsonAPIExample::Tag }
253
+ let(:author) { JsonAPIExample::Author }
254
+
255
+ context 'responses' do
256
+ it 'should return the data object if the response contains only one data instance' do
257
+ expect(subject.find(1)).to be_an_instance_of(JsonAPIExampleArticle)
258
+ end
259
+
260
+ it 'should return a Flexirest::ResultIterator if the response contains more than one data instance' do
261
+ expect(subject.find_all).to be_an_instance_of(Flexirest::ResultIterator)
262
+ end
263
+ end
264
+
265
+ context 'attributes' do
266
+ it 'should return the attributes as part of the data instance' do
267
+ expect(subject.find(1).item).to_not be_nil
268
+ end
269
+
270
+ it 'should return the association\'s attributes as part of the association instance' do
271
+ expect(subject.includes(:author).find_single_author(1).author.item).to_not be_nil
272
+ end
273
+ end
274
+
275
+ context 'associations' do
276
+ it 'should retrieve the resource\'s associations via its relationships object' do
277
+ expect(subject.includes(:tags).find(1).tags.size).to eq(2)
278
+ end
279
+
280
+ it 'should retrieve the response object if the relationship type is singular' do
281
+ expect(subject.includes(:author).find_single_author(1).author).to be_an_instance_of(JsonAPIAssociationExampleAuthor)
282
+ end
283
+
284
+ it 'should retrieve a Flexirest::ResultIterator if the relationship type is plural' do
285
+ expect(subject.includes(:tags).find(1).tags).to be_an_instance_of(Flexirest::ResultIterator)
286
+ end
287
+
288
+ it 'should retrieve nested linked resources' do
289
+ expect(subject.includes(author: [:tag]).find_single_nested(1).author.tag).to be_an_instance_of(JsonAPIAssociationExampleTag)
290
+ expect(subject.includes(author: [:tag]).find_single_nested(1).author.tag.id).to_not be_nil
291
+ expect(subject.includes(tags: [:authors]).find_multi_nested(1).tags.first.authors.first).to be_an_instance_of(JsonAPIAssociationExampleAuthor)
292
+ expect(subject.includes(tags: [:authors]).find_multi_nested(1).tags.first.authors.first.id).to_not be_nil
293
+ end
294
+
295
+ it 'should retrieve a nil if the singular relationship type is empty' do
296
+ expect(subject.includes(:author).no_assocs(1).author).to be_nil
297
+ end
298
+
299
+ it 'should retrieve empty array if the plural relationship type is empty' do
300
+ expect(subject.includes(:tags).no_assocs(1).tags).to be_empty
301
+ end
302
+ end
303
+
304
+ context 'lazy loading' do
305
+ it 'should fetch association lazily' do
306
+ stub_request(:get, /www.example.com\/articles\/1\/tags/)
307
+ .to_return(body: tags.find_tags(article_id: 1).to_json)
308
+ stub_request(:get, /www.example.com\/articles\/1\/author/)
309
+ .to_return(body: author.find_author(article_id: 1).to_json)
310
+
311
+ expect(article.find_lazy(1).tags).to be_an_instance_of(Flexirest::LazyAssociationLoader)
312
+ expect(article.find_lazy(1).tags.count).to be_an(Integer)
313
+ expect(article.find_lazy(1).tags.first.id).to_not be_nil
314
+ expect(article.find_lazy(1).author).to be_an_instance_of(JsonAPIExample::Author)
315
+ expect(article.find_lazy(1).author.id).to_not be_nil
316
+ end
317
+ end
318
+
319
+ context 'client' do
320
+ it 'should request with json api format, and expect a json api response' do
321
+ expect_any_instance_of(Flexirest::Connection).to receive(:post) { |_, _, _, options|
322
+ expect(options[:headers]).to include('Content-Type' => 'application/vnd.api+json')
323
+ expect(options[:headers]).to include('Accept' => 'application/vnd.api+json')
324
+ }.and_return(::FaradayResponseMock.new(OpenStruct.new(body:'{}', response_headers:{})))
325
+ JsonAPIExample::Article.new.create
326
+ end
327
+
328
+ it 'should perform a post request in proper json api format' do
329
+ expect_any_instance_of(Flexirest::Connection).to receive(:post) { |_, path, data|
330
+ hash = MultiJson.load(data)
331
+ expect(path).to eq('/articles')
332
+ expect(hash['data']).to_not be_nil
333
+ expect(hash['data']['id']).to be_nil
334
+ expect(hash['data']['type']).to eq('articles')
335
+ expect(hash['data']['relationships']['author']['data']['type']).to eq('authors')
336
+ expect(hash['data']['relationships']['tags']['data'].first['type']).to eq('tags')
337
+ }.and_return(::FaradayResponseMock.new(OpenStruct.new(body:'{}', response_headers:{})))
338
+ author = JsonAPIExample::Author.new
339
+ tag = JsonAPIExample::Tag.new
340
+ article = JsonAPIExample::Article.new
341
+ article.item = 'item one'
342
+ article.author = author
343
+ article.tags = [tag]
344
+ article.create
345
+ end
346
+
347
+ it 'should raise a Flexirest error when two different classes are in one relationship' do
348
+ author = JsonAPIExample::Author.new
349
+ tag = JsonAPIExample::Tag.new
350
+ article = JsonAPIExample::Article.new
351
+ article.item = 'item one'
352
+ article.tags = [tag, author]
353
+ expect(lambda { article.create }).to raise_error(Exception)
354
+ end
355
+
356
+ it 'should perform a patch request in proper json api format' do
357
+ expect_any_instance_of(Flexirest::Connection).to receive(:patch) { |_, path, data|
358
+ hash = MultiJson.load(data)
359
+ expect(path).to eq('/articles/1')
360
+ expect(hash['data']).to_not be_nil
361
+ expect(hash['data']['id']).to_not be_nil
362
+ expect(hash['data']['type']).to_not be_nil
363
+ }.and_return(::FaradayResponseMock.new(OpenStruct.new(body:'{}', response_headers:{})))
364
+ article = JsonAPIExample::Article.find(1)
365
+ article.item = 'item one'
366
+ article.update
367
+ end
368
+
369
+ it 'should perform a delete request in proper json api format' do
370
+ expect_any_instance_of(Flexirest::Connection).to receive(:delete) { |_, path, data|
371
+ expect(path).to eq('/articles/1')
372
+ expect(data).to eq('')
373
+ }.and_return(::FaradayResponseMock.new(OpenStruct.new(body:'{}', response_headers:{})))
374
+ JsonAPIExample::Article.find(1).delete
375
+ end
376
+
377
+ it 'should have placed the right type value in the request' do
378
+ expect_any_instance_of(Flexirest::Connection).to receive(:patch) { |_, _, data|
379
+ hash = MultiJson.load(data)
380
+ expect(hash['data']['type']).to eq(JsonAPIExample::ArticleAlias.alias_type.to_s)
381
+ expect(hash['data']['relationships']['author']['data']['type']).to eq(JsonAPIExample::AuthorAlias.alias_type.to_s)
382
+ }.and_return(::FaradayResponseMock.new(OpenStruct.new(body:'{}', response_headers:{})))
383
+ author = JsonAPIExample::AuthorAlias.new
384
+ author.id = 1
385
+ article = JsonAPIExample::ArticleAlias.find(1)
386
+ article.item = 'item one'
387
+ article.author = author
388
+ article.update
389
+ end
390
+
391
+ end
392
+ end
@@ -501,6 +501,7 @@ describe Flexirest::Request do
501
501
  with("/create", "first_name=John&should_disappear=true", an_instance_of(Hash)).
502
502
  and_return(::FaradayResponseMock.new(OpenStruct.new(body:"{\"first_name\":\"John\", \"id\":1234}", response_headers:{}, status:200)))
503
503
  expect(Flexirest::Logger).to receive(:info).with(%r'Requesting http://www.example.com/create')
504
+ allow(Flexirest::Logger).to receive(:debug)
504
505
  expect(Flexirest::Logger).to receive(:debug).at_least(1).times.with(%r'(Response received \d+ bytes|Trying to read from cache)')
505
506
 
506
507
  object = ExampleClient.new(first_name:"John", should_disappear:true)
@@ -514,6 +515,7 @@ describe Flexirest::Request do
514
515
  with("/create", "first_name=John&should_disappear=true", an_instance_of(Hash)).
515
516
  and_return(::FaradayResponseMock.new(OpenStruct.new(body:"{\"first_name\":\"John\", \"id\":1234}", response_headers:{}, status:200)))
516
517
  expect(Flexirest::Logger).to receive(:info).with(%r'Requesting http://www.example.com/create')
518
+ allow(Flexirest::Logger).to receive(:debug)
517
519
  expect(Flexirest::Logger).to receive(:debug).at_least(1).times.with(%r'(Response received \d+ bytes|Trying to read from cache)')
518
520
 
519
521
  object = ExampleClient.new(first_name:"John", should_disappear:true)
@@ -526,7 +528,7 @@ describe Flexirest::Request do
526
528
  with("/create", "first_name=John&should_disappear=true", an_instance_of(Hash)).
527
529
  and_return(::FaradayResponseMock.new(OpenStruct.new(body:"{\"first_name\":\"John\", \"id\":1234}", response_headers:{}, status:200)))
528
530
  expect(Flexirest::Logger).to receive(:debug).with(/ POST /)
529
- allow(Flexirest::Logger).to receive(:debug).with(any_args)
531
+ allow(Flexirest::Logger).to receive(:debug)
530
532
 
531
533
  object = VerboseExampleClient.new(first_name:"John", should_disappear:true)
532
534
  object.create
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flexirest
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.35
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Jeffries
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-13 00:00:00.000000000 Z
11
+ date: 2017-07-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -242,6 +242,7 @@ files:
242
242
  - lib/flexirest/connection_manager.rb
243
243
  - lib/flexirest/headers_list.rb
244
244
  - lib/flexirest/instrumentation.rb
245
+ - lib/flexirest/json_api_proxy.rb
245
246
  - lib/flexirest/lazy_association_loader.rb
246
247
  - lib/flexirest/lazy_loader.rb
247
248
  - lib/flexirest/logger.rb
@@ -266,6 +267,7 @@ files:
266
267
  - spec/lib/flexirest_spec.rb
267
268
  - spec/lib/headers_list_spec.rb
268
269
  - spec/lib/instrumentation_spec.rb
270
+ - spec/lib/json_api_spec.rb
269
271
  - spec/lib/lazy_association_loader_spec.rb
270
272
  - spec/lib/lazy_loader_spec.rb
271
273
  - spec/lib/logger_spec.rb
@@ -317,6 +319,7 @@ test_files:
317
319
  - spec/lib/flexirest_spec.rb
318
320
  - spec/lib/headers_list_spec.rb
319
321
  - spec/lib/instrumentation_spec.rb
322
+ - spec/lib/json_api_spec.rb
320
323
  - spec/lib/lazy_association_loader_spec.rb
321
324
  - spec/lib/lazy_loader_spec.rb
322
325
  - spec/lib/logger_spec.rb