acfs 1.3.3 → 1.6.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 (96) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +372 -0
  3. data/LICENSE +22 -0
  4. data/README.md +321 -0
  5. data/acfs.gemspec +38 -0
  6. data/lib/acfs.rb +51 -0
  7. data/lib/acfs/adapter/base.rb +26 -0
  8. data/lib/acfs/adapter/typhoeus.rb +82 -0
  9. data/lib/acfs/collection.rb +28 -0
  10. data/lib/acfs/collections/paginatable.rb +76 -0
  11. data/lib/acfs/configuration.rb +120 -0
  12. data/lib/acfs/errors.rb +147 -0
  13. data/lib/acfs/global.rb +101 -0
  14. data/lib/acfs/location.rb +76 -0
  15. data/lib/acfs/middleware/base.rb +24 -0
  16. data/lib/acfs/middleware/json.rb +31 -0
  17. data/lib/acfs/middleware/logger.rb +23 -0
  18. data/lib/acfs/middleware/msgpack.rb +32 -0
  19. data/lib/acfs/middleware/print.rb +23 -0
  20. data/lib/acfs/middleware/serializer.rb +41 -0
  21. data/lib/acfs/operation.rb +96 -0
  22. data/lib/acfs/request.rb +32 -0
  23. data/lib/acfs/request/callbacks.rb +54 -0
  24. data/lib/acfs/resource.rb +39 -0
  25. data/lib/acfs/resource/attributes.rb +270 -0
  26. data/lib/acfs/resource/attributes/base.rb +29 -0
  27. data/lib/acfs/resource/attributes/boolean.rb +39 -0
  28. data/lib/acfs/resource/attributes/date_time.rb +32 -0
  29. data/lib/acfs/resource/attributes/dict.rb +39 -0
  30. data/lib/acfs/resource/attributes/float.rb +33 -0
  31. data/lib/acfs/resource/attributes/integer.rb +29 -0
  32. data/lib/acfs/resource/attributes/list.rb +36 -0
  33. data/lib/acfs/resource/attributes/string.rb +26 -0
  34. data/lib/acfs/resource/attributes/uuid.rb +48 -0
  35. data/lib/acfs/resource/dirty.rb +37 -0
  36. data/lib/acfs/resource/initialization.rb +31 -0
  37. data/lib/acfs/resource/loadable.rb +35 -0
  38. data/lib/acfs/resource/locatable.rb +135 -0
  39. data/lib/acfs/resource/operational.rb +26 -0
  40. data/lib/acfs/resource/persistence.rb +258 -0
  41. data/lib/acfs/resource/query_methods.rb +266 -0
  42. data/lib/acfs/resource/service.rb +44 -0
  43. data/lib/acfs/resource/validation.rb +49 -0
  44. data/lib/acfs/response.rb +30 -0
  45. data/lib/acfs/response/formats.rb +27 -0
  46. data/lib/acfs/response/status.rb +33 -0
  47. data/lib/acfs/rspec.rb +13 -0
  48. data/lib/acfs/runner.rb +102 -0
  49. data/lib/acfs/service.rb +94 -0
  50. data/lib/acfs/service/middleware.rb +58 -0
  51. data/lib/acfs/service/middleware/stack.rb +65 -0
  52. data/lib/acfs/singleton_resource.rb +85 -0
  53. data/lib/acfs/stub.rb +199 -0
  54. data/lib/acfs/util.rb +22 -0
  55. data/lib/acfs/version.rb +16 -0
  56. data/lib/acfs/yard.rb +6 -0
  57. data/spec/acfs/adapter/typhoeus_spec.rb +55 -0
  58. data/spec/acfs/collection_spec.rb +157 -0
  59. data/spec/acfs/configuration_spec.rb +53 -0
  60. data/spec/acfs/global_spec.rb +140 -0
  61. data/spec/acfs/location_spec.rb +25 -0
  62. data/spec/acfs/middleware/json_spec.rb +79 -0
  63. data/spec/acfs/middleware/msgpack_spec.rb +62 -0
  64. data/spec/acfs/operation_spec.rb +12 -0
  65. data/spec/acfs/request/callbacks_spec.rb +48 -0
  66. data/spec/acfs/request_spec.rb +79 -0
  67. data/spec/acfs/resource/attributes/boolean_spec.rb +58 -0
  68. data/spec/acfs/resource/attributes/date_time_spec.rb +51 -0
  69. data/spec/acfs/resource/attributes/dict_spec.rb +77 -0
  70. data/spec/acfs/resource/attributes/float_spec.rb +61 -0
  71. data/spec/acfs/resource/attributes/integer_spec.rb +36 -0
  72. data/spec/acfs/resource/attributes/list_spec.rb +60 -0
  73. data/spec/acfs/resource/attributes/uuid_spec.rb +42 -0
  74. data/spec/acfs/resource/attributes_spec.rb +179 -0
  75. data/spec/acfs/resource/dirty_spec.rb +49 -0
  76. data/spec/acfs/resource/initialization_spec.rb +36 -0
  77. data/spec/acfs/resource/loadable_spec.rb +22 -0
  78. data/spec/acfs/resource/locatable_spec.rb +118 -0
  79. data/spec/acfs/resource/persistance_spec.rb +322 -0
  80. data/spec/acfs/resource/query_methods_spec.rb +548 -0
  81. data/spec/acfs/resource/validation_spec.rb +129 -0
  82. data/spec/acfs/response/formats_spec.rb +52 -0
  83. data/spec/acfs/response/status_spec.rb +71 -0
  84. data/spec/acfs/runner_spec.rb +95 -0
  85. data/spec/acfs/service/middleware_spec.rb +35 -0
  86. data/spec/acfs/service_spec.rb +48 -0
  87. data/spec/acfs/singleton_resource_spec.rb +17 -0
  88. data/spec/acfs/stub_spec.rb +345 -0
  89. data/spec/acfs_spec.rb +205 -0
  90. data/spec/fixtures/config.yml +14 -0
  91. data/spec/spec_helper.rb +42 -0
  92. data/spec/support/hash.rb +11 -0
  93. data/spec/support/response.rb +12 -0
  94. data/spec/support/service.rb +92 -0
  95. data/spec/support/shared/find_callbacks.rb +50 -0
  96. metadata +159 -26
@@ -0,0 +1,345 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ class SpecialCustomError < StandardError; end
6
+
7
+ describe Acfs::Stub do
8
+ let(:stub) { Class.new(Acfs::Stub) }
9
+
10
+ before(:all) { Acfs::Stub.enable }
11
+ after(:all) { Acfs::Stub.disable }
12
+
13
+ before do
14
+ Acfs::Stub.allow_requests = false
15
+ end
16
+
17
+ describe '#called?' do
18
+ context 'without specified number' do
19
+ let!(:operation) { Acfs::Stub.resource MyUser, :read, with: {id: 1}, return: {id: 1, name: 'John Smith', age: 32} }
20
+
21
+ it 'should allow to test if stub was called' do
22
+ MyUser.find 1
23
+ Acfs.run
24
+
25
+ expect(operation).to be_called
26
+ end
27
+
28
+ it 'should allow to test if stub was called a specific number of times' do
29
+ MyUser.find 1
30
+ Acfs.run
31
+
32
+ MyUser.find 1
33
+ Acfs.run
34
+
35
+ expect(operation).to be_called 2.times
36
+ end
37
+ end
38
+ end
39
+
40
+ describe '.resource' do
41
+ context 'with ambiguous stubs' do
42
+ before do
43
+ Acfs::Stub.resource MyUser, :read, with: {id: 1}, return: {id: 1, name: 'John Smith', age: 32}
44
+ Acfs::Stub.resource MyUser, :read, with: {id: 1}, raise: :not_found
45
+ end
46
+
47
+ it 'should raise error' do
48
+ MyUser.find 1
49
+
50
+ expect { Acfs.run }.to raise_error(Acfs::AmbiguousStubError)
51
+ end
52
+ end
53
+
54
+ context 'with read action' do
55
+ before do
56
+ Acfs::Stub.resource MyUser, :read, with: {id: 1}, return: {id: 1, name: 'John Smith', age: 32}
57
+ Acfs::Stub.resource MyUser, :read, with: {id: 2}, raise: SpecialCustomError
58
+ Acfs::Stub.resource MyUser, :read, with: {id: 3}, raise: :not_found
59
+ end
60
+
61
+ it 'should allow to stub resource reads' do
62
+ user = MyUser.find 1
63
+ Acfs.run
64
+
65
+ expect(user.id).to be == 1
66
+ expect(user.name).to be == 'John Smith'
67
+ expect(user.age).to be == 32
68
+ end
69
+
70
+ context 'with error' do
71
+ it 'should allow to raise errors' do
72
+ MyUser.find 2
73
+
74
+ expect { Acfs.run }.to raise_error(SpecialCustomError)
75
+ end
76
+
77
+ it 'should allow to raise symbolic errors' do
78
+ MyUser.find 3
79
+
80
+ expect { Acfs.run }.to raise_error(Acfs::ResourceNotFound)
81
+ end
82
+ end
83
+
84
+ context 'with type parameter' do
85
+ before do
86
+ Acfs::Stub.resource Computer, :read, with: {id: 1}, return: {id: 1, type: 'PC'}
87
+ Acfs::Stub.resource Computer, :read, with: {id: 2}, return: {id: 2, type: 'Mac'}
88
+ end
89
+
90
+ it 'should create inherited type' do
91
+ pc = Computer.find 1
92
+ mac = Computer.find 2
93
+
94
+ Acfs.run
95
+
96
+ expect(pc).to be_a PC
97
+ expect(mac).to be_a Mac
98
+ end
99
+ end
100
+ end
101
+
102
+ context 'with create action' do
103
+ before do
104
+ Acfs::Stub.resource Session, :create, with: {ident: 'john@exmaple.org', password: 's3cr3t'}, return: {id: 'longhash', user: 1}
105
+ Acfs::Stub.resource Session, :create, with: ->(op) { op.data[:ident] == 'john@exmaple.org' && op.data[:password] == 'wrong' }, raise: 422
106
+ end
107
+
108
+ it 'should allow stub resource creation' do
109
+ session = Session.create! ident: 'john@exmaple.org', password: 's3cr3t'
110
+
111
+ expect(session.id).to be == 'longhash'
112
+ expect(session.user).to be == 1
113
+ end
114
+
115
+ it 'should allow to raise error' do
116
+ expect do
117
+ Session.create! ident: 'john@exmaple.org', password: 'wrong'
118
+ end.to raise_error(::Acfs::InvalidResource)
119
+ end
120
+ end
121
+
122
+ context 'with list action' do
123
+ before do
124
+ Acfs::Stub.resource MyUser, :list,
125
+ return: [{id: 1, name: 'John Smith', age: 32}, {id: 2, name: 'Anon', age: 12}]
126
+ end
127
+
128
+ it 'should return collection' do
129
+ users = MyUser.all
130
+ Acfs.run
131
+
132
+ expect(users).to have(2).items
133
+ end
134
+
135
+ it 'should return defined resources' do
136
+ users = MyUser.all
137
+ Acfs.run
138
+
139
+ expect(users[0].id).to eq 1
140
+ expect(users[1].id).to eq 2
141
+ expect(users[0].name).to eq 'John Smith'
142
+ expect(users[1].name).to eq 'Anon'
143
+ end
144
+
145
+ context 'with type parameter' do
146
+ before do
147
+ Acfs::Stub.resource Computer, :list,
148
+ return: [{id: 1, type: 'PC'}, {id: 2, type: 'Mac'}]
149
+ end
150
+
151
+ it 'should create inherited type' do
152
+ computers = Computer.all
153
+ Acfs.run
154
+
155
+ expect(computers.first).to be_a PC
156
+ expect(computers.last).to be_a Mac
157
+ end
158
+ end
159
+
160
+ context 'with header' do
161
+ before do
162
+ Acfs::Stub.resource Comment, :list,
163
+ return: [{id: 1, text: 'Foo'}, {id: 2, text: 'Bar'}],
164
+ headers: headers
165
+ end
166
+
167
+ let!(:comments) { Comment.all }
168
+ let(:headers) do
169
+ {
170
+ 'X-Total-Pages' => '2',
171
+ 'X-Total-Count' => '10'
172
+ }
173
+ end
174
+ subject { Acfs.run; comments }
175
+
176
+ its(:total_pages) { should eq 2 }
177
+ its(:total_count) { should eq 10 }
178
+ end
179
+ end
180
+
181
+ context 'with update action' do
182
+ before do
183
+ Acfs::Stub.resource MyUser, :read, with: {id: 1}, return: {id: 1, name: 'John Smith', age: 32}
184
+ Acfs::Stub.resource MyUser, :update, with: {id: 1, name: 'John Smith', age: 22}, return: {id: 1, name: 'John Smith', age: 23}
185
+ Acfs::Stub.resource MyUser, :update, with: {id: 1, name: 'John Smith', age: 0}, raise: 422
186
+ end
187
+
188
+ let!(:update_stub) do
189
+ Acfs::Stub.resource MyUser, :update,
190
+ with: {id: 1, name: 'Jane Smith'},
191
+ return: ->(op) { Hash[op.data.map {|k, v| [k, v.to_s.upcase] }] }
192
+ end
193
+
194
+ it 'should allow stub resource update' do
195
+ user = MyUser.find 1
196
+ Acfs.run
197
+
198
+ user.age = 22
199
+ user.save!
200
+
201
+ expect(user.age).to be == 23
202
+ end
203
+
204
+ it 'should allow to raise error' do
205
+ user = MyUser.find 1
206
+ Acfs.run
207
+
208
+ user.age = 0
209
+ user.save
210
+
211
+ expect do
212
+ user.save!
213
+ end.to raise_error(::Acfs::InvalidResource)
214
+ end
215
+
216
+ it 'should match partial :with' do
217
+ user = MyUser.find 1
218
+ Acfs.run
219
+
220
+ user.age = 5
221
+ user.name = 'Jane Smith'
222
+ user.save!
223
+
224
+ expect(update_stub).to be_called
225
+ end
226
+
227
+ it 'should process response body' do
228
+ user = MyUser.find 1
229
+ Acfs.run
230
+
231
+ user.age = 5
232
+ user.name = 'Jane Smith'
233
+ user.save!
234
+
235
+ expect(user.name).to eq 'JANE SMITH'
236
+ end
237
+ end
238
+
239
+ context 'with create action' do
240
+ before do
241
+ Acfs::Stub.resource MyUser, :create, with: {name: 'John Smith', age: 0}, raise: 422
242
+ end
243
+
244
+ it 'should allow to raise error' do
245
+ expect do
246
+ MyUser.create! name: 'John Smith', age: 0
247
+ end.to raise_error(::Acfs::InvalidResource)
248
+ end
249
+ end
250
+ end
251
+
252
+ describe '.allow_requests=' do
253
+ context 'when enabled' do
254
+ before do
255
+ Acfs::Stub.allow_requests = true
256
+ stub_request(:get, 'http://users.example.org/users/2').to_return response(id: 2, name: 'John', age: 26)
257
+ end
258
+
259
+ it 'should allow real requests' do
260
+ @user = MyUser.find 2
261
+ expect { Acfs.run }.to_not raise_error
262
+ end
263
+ end
264
+
265
+ context 'when disabled' do
266
+ before do
267
+ Acfs::Stub.allow_requests = false
268
+ end
269
+
270
+ it 'should not allow real requests' do
271
+ @user = MyUser.find 2
272
+ expect { Acfs.run }.to raise_error(Acfs::RealRequestsNotAllowedError)
273
+ end
274
+ end
275
+ end
276
+
277
+ describe 'accept?' do
278
+ subject { stub.accept?(op) }
279
+
280
+ context 'with a match in params' do
281
+ let(:op) do
282
+ double('operation').tap do |op|
283
+ allow(op).to receive(:full_params).and_return(id: 1337, blub: 'abc')
284
+ allow(op).to receive(:data).and_return({})
285
+ end
286
+ end
287
+
288
+ let(:stub) { Acfs::Stub.resource MyUser, :read, with: {id: 1337} }
289
+
290
+ it { is_expected.to be true }
291
+ end
292
+
293
+ context 'with a match in data' do
294
+ let(:op) do
295
+ double('operation').tap do |op|
296
+ allow(op).to receive(:full_params).and_return({})
297
+ allow(op).to receive(:data).and_return(id: 1337, blub: 'abc')
298
+ end
299
+ end
300
+
301
+ let(:stub) { Acfs::Stub.resource MyUser, :read, with: {id: 1337} }
302
+
303
+ it { is_expected.to be true }
304
+ end
305
+
306
+ context 'with no match in params nor data' do
307
+ let(:op) do
308
+ double('operation').tap do |op|
309
+ allow(op).to receive(:full_params).and_return(id: 1337)
310
+ allow(op).to receive(:data).and_return({})
311
+ end
312
+ end
313
+
314
+ let(:stub) { Acfs::Stub.resource MyUser, :read, with: {abc: '123'} }
315
+
316
+ it { is_expected.to be false }
317
+ end
318
+
319
+ context 'with a wrong match' do
320
+ let(:op) do
321
+ double('operation').tap do |op|
322
+ allow(op).to receive(:full_params).and_return(id: 1337, blub: 'abc')
323
+ allow(op).to receive(:data).and_return({})
324
+ end
325
+ end
326
+
327
+ let(:stub) { Acfs::Stub.resource MyUser, :read, with: {id: 1337, blub: '123'} }
328
+
329
+ it { is_expected.to be false }
330
+ end
331
+
332
+ context 'with a missing match' do
333
+ let(:op) do
334
+ double('operation').tap do |op|
335
+ allow(op).to receive(:full_params).and_return(id: 1337, blub: 'abc')
336
+ allow(op).to receive(:data).and_return({})
337
+ end
338
+ end
339
+
340
+ let(:stub) { Acfs::Stub.resource MyUser, :read, with: {id: 1337, answer: 42} }
341
+
342
+ it { is_expected.to be false }
343
+ end
344
+ end
345
+ end
@@ -0,0 +1,205 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'Acfs' do
6
+ before do
7
+ stub_request(:get, 'http://users.example.org/users').to_return response([{id: 1, name: 'Anon', age: 12}, {id: 2, name: 'John', age: 26}])
8
+ stub_request(:get, 'http://users.example.org/users/2').to_return response(id: 2, name: 'John', age: 26)
9
+ stub_request(:get, 'http://users.example.org/users/3').to_return response(id: 3, name: 'Miraculix', age: 122)
10
+ stub_request(:get, 'http://users.example.org/users/100').to_return response(id: 100, name: 'Jimmy', age: 45)
11
+ stub_request(:get, 'http://users.example.org/users/2/friends').to_return response([{id: 1, name: 'Anon', age: 12}])
12
+ stub_request(:get, 'http://comments.example.org/comments?user=2').to_return response([{id: 1, text: 'Comment #1'}, {id: 2, text: 'Comment #2'}])
13
+ end
14
+
15
+ it 'should update single resource synchronously' do
16
+ stub = stub_request(:put, 'http://users.example.org/users/2')
17
+ .to_return {|request| {body: request.body, headers: {'Content-Type' => request.headers['Content-Type']}} }
18
+
19
+ @user = MyUser.find 2
20
+ Acfs.run
21
+
22
+ expect(@user).to_not be_changed
23
+ expect(@user).to be_persisted
24
+
25
+ @user.name = 'Johnny'
26
+
27
+ expect(@user).to be_changed
28
+ expect(@user).to be_persisted
29
+
30
+ @user.save
31
+
32
+ expect(stub).to have_been_requested
33
+ expect(@user).to_not be_changed
34
+ expect(@user).to be_persisted
35
+ end
36
+
37
+ it 'should create a single resource synchronously' do
38
+ stub = stub_request(:post, 'http://users.example.org/sessions').to_return response(id: 'sessionhash', user: 1)
39
+
40
+ session = Session.create ident: 'Anon'
41
+
42
+ expect(stub).to have_been_requested
43
+ expect(session.id).to be == 'sessionhash'
44
+ expect(session.user).to be == 1
45
+ end
46
+
47
+ it 'should load single resource' do
48
+ @user = MyUser.find(2)
49
+
50
+ expect(@user).to_not be_loaded
51
+
52
+ Acfs.run
53
+
54
+ expect(@user).to be_loaded
55
+ expect(@user.id).to be == 2
56
+ expect(@user.name).to be == 'John'
57
+ expect(@user.age).to be == 26
58
+ end
59
+
60
+ describe 'singleton' do
61
+ before do
62
+ stub_request(:get, 'http://users.example.org/singles?user_id=5').to_return response(score: 250, user_id: 5)
63
+ end
64
+
65
+ it 'should create a singleton resource' do
66
+ stub = stub_request(:post, 'http://users.example.org/singles').to_return response(score: 250, user_id: 5)
67
+
68
+ @single = Single.new user_id: 5, score: 250
69
+ expect(@single.new?).to eq true
70
+
71
+ @single.save
72
+ expect(stub).to have_been_requested
73
+
74
+ expect(@single.new?).to eq false
75
+ expect(@single.user_id).to eq 5
76
+ expect(@single.score).to eq 250
77
+ end
78
+
79
+ it 'should load singleton resource' do
80
+ @single = Single.find user_id: 5
81
+ Acfs.run
82
+
83
+ expect(@single.score).to eq 250
84
+ end
85
+
86
+ it 'should update singleton resource' do
87
+ stub = stub_request(:put, 'http://users.example.org/singles').to_return do |request|
88
+ {
89
+ body: request.body,
90
+ headers: {'Content-Type' => request.headers['Content-Type']}
91
+ }
92
+ end
93
+
94
+ @single = Single.find user_id: 5
95
+ Acfs.run
96
+
97
+ expect(@single.score).to eq 250
98
+
99
+ @single.score = 300
100
+ @single.save
101
+
102
+ expect(stub).to have_been_requested
103
+
104
+ expect(@single.score).to eq 300
105
+ end
106
+
107
+ it 'should delete singleton resource' do
108
+ stub = stub_request(:delete, 'http://users.example.org/singles').to_return do |request|
109
+ {
110
+ body: request.body,
111
+ headers: {'Content-Type' => request.headers['Content-Type']}
112
+ }
113
+ end
114
+
115
+ @single = Single.find user_id: 5
116
+ Acfs.run
117
+
118
+ expect(@single.new?).to eq false
119
+
120
+ @single.delete
121
+
122
+ expect(stub).to have_been_requested
123
+ end
124
+
125
+ it 'should raise error when calling `all\'' do
126
+ expect { Single.all }.to raise_error ::Acfs::UnsupportedOperation
127
+ end
128
+ end
129
+
130
+ it 'should load multiple single resources' do
131
+ @users = MyUser.find([2, 3, 100]) do |users|
132
+ # This block should be called only after *all* resources are loaded.
133
+ @john = users[0]
134
+ @mirx = users[1]
135
+ @jimy = users[2]
136
+ end
137
+
138
+ expect(@users).to_not be_loaded
139
+
140
+ Acfs.run
141
+
142
+ expect(@users).to be_loaded
143
+ expect(@users).to have(3).items
144
+
145
+ expect(@users[0].id).to be == 2
146
+ expect(@users[0].name).to be == 'John'
147
+ expect(@users[0].age).to be == 26
148
+ expect(@users[0]).to be == @john
149
+
150
+ expect(@users[1].id).to be == 3
151
+ expect(@users[1].name).to be == 'Miraculix'
152
+ expect(@users[1].age).to be == 122
153
+ expect(@users[1]).to be == @mirx
154
+
155
+ expect(@users[2].id).to be == 100
156
+ expect(@users[2].name).to be == 'Jimmy'
157
+ expect(@users[2].age).to be == 45
158
+ expect(@users[2]).to be == @jimy
159
+ end
160
+
161
+ it 'should load multiple resources' do
162
+ @users = MyUser.all
163
+
164
+ expect(@users).to_not be_loaded
165
+
166
+ Acfs.run
167
+
168
+ expect(@users).to be_loaded
169
+ expect(@users).to have(2).items
170
+ expect(@users[0].name).to be == 'Anon'
171
+ expect(@users[0].age).to be == 12
172
+ expect(@users[1].name).to be == 'John'
173
+ expect(@users[1].age).to be == 26
174
+ end
175
+
176
+ it 'should load associated resources' do
177
+ pending 'TODO: Implement high level feature'
178
+
179
+ @user = MyUser.find(2) do |user|
180
+ @friends = user.friends.all
181
+ end
182
+
183
+ Acfs.run
184
+
185
+ expect(@user.name).to be == 'John'
186
+ expect(@user.age).to be == 26
187
+
188
+ expect(@friends).to have(1).items
189
+ end
190
+
191
+ it 'should load associated resources from different service' do
192
+ @user = MyUser.find 2 do |user|
193
+ expect(user.id).to be == 2
194
+ @comments = Comment.where({user: user.id})
195
+ end
196
+
197
+ Acfs.run
198
+
199
+ expect(@user.id).to be == 2
200
+ expect(@user.name).to be == 'John'
201
+ expect(@user.age).to be == 26
202
+
203
+ expect(@comments).to have(2).items
204
+ end
205
+ end