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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +372 -0
- data/LICENSE +22 -0
- data/README.md +321 -0
- data/acfs.gemspec +38 -0
- data/lib/acfs.rb +51 -0
- data/lib/acfs/adapter/base.rb +26 -0
- data/lib/acfs/adapter/typhoeus.rb +82 -0
- data/lib/acfs/collection.rb +28 -0
- data/lib/acfs/collections/paginatable.rb +76 -0
- data/lib/acfs/configuration.rb +120 -0
- data/lib/acfs/errors.rb +147 -0
- data/lib/acfs/global.rb +101 -0
- data/lib/acfs/location.rb +76 -0
- data/lib/acfs/middleware/base.rb +24 -0
- data/lib/acfs/middleware/json.rb +31 -0
- data/lib/acfs/middleware/logger.rb +23 -0
- data/lib/acfs/middleware/msgpack.rb +32 -0
- data/lib/acfs/middleware/print.rb +23 -0
- data/lib/acfs/middleware/serializer.rb +41 -0
- data/lib/acfs/operation.rb +96 -0
- data/lib/acfs/request.rb +32 -0
- data/lib/acfs/request/callbacks.rb +54 -0
- data/lib/acfs/resource.rb +39 -0
- data/lib/acfs/resource/attributes.rb +270 -0
- data/lib/acfs/resource/attributes/base.rb +29 -0
- data/lib/acfs/resource/attributes/boolean.rb +39 -0
- data/lib/acfs/resource/attributes/date_time.rb +32 -0
- data/lib/acfs/resource/attributes/dict.rb +39 -0
- data/lib/acfs/resource/attributes/float.rb +33 -0
- data/lib/acfs/resource/attributes/integer.rb +29 -0
- data/lib/acfs/resource/attributes/list.rb +36 -0
- data/lib/acfs/resource/attributes/string.rb +26 -0
- data/lib/acfs/resource/attributes/uuid.rb +48 -0
- data/lib/acfs/resource/dirty.rb +37 -0
- data/lib/acfs/resource/initialization.rb +31 -0
- data/lib/acfs/resource/loadable.rb +35 -0
- data/lib/acfs/resource/locatable.rb +135 -0
- data/lib/acfs/resource/operational.rb +26 -0
- data/lib/acfs/resource/persistence.rb +258 -0
- data/lib/acfs/resource/query_methods.rb +266 -0
- data/lib/acfs/resource/service.rb +44 -0
- data/lib/acfs/resource/validation.rb +49 -0
- data/lib/acfs/response.rb +30 -0
- data/lib/acfs/response/formats.rb +27 -0
- data/lib/acfs/response/status.rb +33 -0
- data/lib/acfs/rspec.rb +13 -0
- data/lib/acfs/runner.rb +102 -0
- data/lib/acfs/service.rb +94 -0
- data/lib/acfs/service/middleware.rb +58 -0
- data/lib/acfs/service/middleware/stack.rb +65 -0
- data/lib/acfs/singleton_resource.rb +85 -0
- data/lib/acfs/stub.rb +199 -0
- data/lib/acfs/util.rb +22 -0
- data/lib/acfs/version.rb +16 -0
- data/lib/acfs/yard.rb +6 -0
- data/spec/acfs/adapter/typhoeus_spec.rb +55 -0
- data/spec/acfs/collection_spec.rb +157 -0
- data/spec/acfs/configuration_spec.rb +53 -0
- data/spec/acfs/global_spec.rb +140 -0
- data/spec/acfs/location_spec.rb +25 -0
- data/spec/acfs/middleware/json_spec.rb +79 -0
- data/spec/acfs/middleware/msgpack_spec.rb +62 -0
- data/spec/acfs/operation_spec.rb +12 -0
- data/spec/acfs/request/callbacks_spec.rb +48 -0
- data/spec/acfs/request_spec.rb +79 -0
- data/spec/acfs/resource/attributes/boolean_spec.rb +58 -0
- data/spec/acfs/resource/attributes/date_time_spec.rb +51 -0
- data/spec/acfs/resource/attributes/dict_spec.rb +77 -0
- data/spec/acfs/resource/attributes/float_spec.rb +61 -0
- data/spec/acfs/resource/attributes/integer_spec.rb +36 -0
- data/spec/acfs/resource/attributes/list_spec.rb +60 -0
- data/spec/acfs/resource/attributes/uuid_spec.rb +42 -0
- data/spec/acfs/resource/attributes_spec.rb +179 -0
- data/spec/acfs/resource/dirty_spec.rb +49 -0
- data/spec/acfs/resource/initialization_spec.rb +36 -0
- data/spec/acfs/resource/loadable_spec.rb +22 -0
- data/spec/acfs/resource/locatable_spec.rb +118 -0
- data/spec/acfs/resource/persistance_spec.rb +322 -0
- data/spec/acfs/resource/query_methods_spec.rb +548 -0
- data/spec/acfs/resource/validation_spec.rb +129 -0
- data/spec/acfs/response/formats_spec.rb +52 -0
- data/spec/acfs/response/status_spec.rb +71 -0
- data/spec/acfs/runner_spec.rb +95 -0
- data/spec/acfs/service/middleware_spec.rb +35 -0
- data/spec/acfs/service_spec.rb +48 -0
- data/spec/acfs/singleton_resource_spec.rb +17 -0
- data/spec/acfs/stub_spec.rb +345 -0
- data/spec/acfs_spec.rb +205 -0
- data/spec/fixtures/config.yml +14 -0
- data/spec/spec_helper.rb +42 -0
- data/spec/support/hash.rb +11 -0
- data/spec/support/response.rb +12 -0
- data/spec/support/service.rb +92 -0
- data/spec/support/shared/find_callbacks.rb +50 -0
- metadata +159 -26
@@ -0,0 +1,157 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Acfs::Collection do
|
6
|
+
let(:model) { MyUser }
|
7
|
+
|
8
|
+
describe 'Pagination' do
|
9
|
+
let(:params) { {} }
|
10
|
+
let!(:collection) { model.all params }
|
11
|
+
|
12
|
+
subject { Acfs.run; collection }
|
13
|
+
|
14
|
+
context 'without explicit page parameter' do
|
15
|
+
before do
|
16
|
+
stub_request(:get, 'http://users.example.org/users')
|
17
|
+
.to_return response([{id: 1, name: 'Anon', age: 12, born_at: 'Berlin'}],
|
18
|
+
headers: {
|
19
|
+
'X-Total-Pages' => '2',
|
20
|
+
'X-Total-Count' => '10'
|
21
|
+
})
|
22
|
+
end
|
23
|
+
|
24
|
+
its(:total_pages) { should eq 2 }
|
25
|
+
its(:current_page) { should eq 1 }
|
26
|
+
its(:total_count) { should eq 10 }
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'with page parameter' do
|
30
|
+
let(:params) { {page: 2} }
|
31
|
+
before do
|
32
|
+
stub_request(:get, 'http://users.example.org/users?page=2')
|
33
|
+
.to_return response([{id: 1, name: 'Anon', age: 12, born_at: 'Berlin'}],
|
34
|
+
headers: {
|
35
|
+
'X-Total-Pages' => '2',
|
36
|
+
'X-Total-Count' => '10'
|
37
|
+
})
|
38
|
+
end
|
39
|
+
|
40
|
+
its(:total_pages) { should eq 2 }
|
41
|
+
its(:current_page) { should eq 2 }
|
42
|
+
its(:total_count) { should eq 10 }
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'with non-numerical page parameter' do
|
46
|
+
let(:params) { {page: 'e546f5'} }
|
47
|
+
before do
|
48
|
+
stub_request(:get, 'http://users.example.org/users?page=e546f5')
|
49
|
+
.to_return response([{id: 1, name: 'Anon', age: 12, born_at: 'Berlin'}],
|
50
|
+
headers: {
|
51
|
+
'X-Total-Pages' => '2',
|
52
|
+
'X-Total-Count' => '10'
|
53
|
+
})
|
54
|
+
end
|
55
|
+
|
56
|
+
its(:total_pages) { should eq 2 }
|
57
|
+
its(:current_page) { should eq 'e546f5' }
|
58
|
+
its(:total_count) { should eq 10 }
|
59
|
+
end
|
60
|
+
|
61
|
+
describe '#next_page' do
|
62
|
+
before do
|
63
|
+
stub_request(:get, 'http://users.example.org/users')
|
64
|
+
.to_return response([{id: 1, name: 'Anon', age: 12, born_at: 'Berlin'}],
|
65
|
+
headers: {
|
66
|
+
'X-Total-Pages' => '2',
|
67
|
+
'Link' => '<http://users.example.org/users?page=2>; rel="next"'
|
68
|
+
})
|
69
|
+
end
|
70
|
+
let!(:req) do
|
71
|
+
stub_request(:get, 'http://users.example.org/users?page=2').to_return response([])
|
72
|
+
end
|
73
|
+
let!(:collection) { model.all }
|
74
|
+
subject { Acfs.run; collection.next_page }
|
75
|
+
|
76
|
+
it { should be_a Acfs::Collection }
|
77
|
+
|
78
|
+
it 'should have fetched page 2' do
|
79
|
+
subject
|
80
|
+
Acfs.run
|
81
|
+
expect(req).to have_been_requested
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe '#prev_page' do
|
86
|
+
before do
|
87
|
+
stub_request(:get, 'http://users.example.org/users?page=2')
|
88
|
+
.to_return response([{id: 2, name: 'Anno', age: 1604, born_at: 'Santa Maria'}],
|
89
|
+
headers: {
|
90
|
+
'X-Total-Pages' => '2',
|
91
|
+
'Link' => '<http://users.example.org/users>; rel="prev"'
|
92
|
+
})
|
93
|
+
end
|
94
|
+
let!(:req) do
|
95
|
+
stub_request(:get, 'http://users.example.org/users').to_return response([])
|
96
|
+
end
|
97
|
+
let!(:collection) { model.all page: 2 }
|
98
|
+
subject { Acfs.run; collection.prev_page }
|
99
|
+
|
100
|
+
it { should be_a Acfs::Collection }
|
101
|
+
|
102
|
+
it 'should have fetched page 1' do
|
103
|
+
subject
|
104
|
+
Acfs.run
|
105
|
+
expect(req).to have_been_requested
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe '#first_page' do
|
110
|
+
before do
|
111
|
+
stub_request(:get, 'http://users.example.org/users?page=2')
|
112
|
+
.to_return response([{id: 2, name: 'Anno', age: 1604, born_at: 'Santa Maria'}],
|
113
|
+
headers: {
|
114
|
+
'X-Total-Pages' => '2',
|
115
|
+
'Link' => '<http://users.example.org/users>; rel="first"'
|
116
|
+
})
|
117
|
+
end
|
118
|
+
let!(:req) do
|
119
|
+
stub_request(:get, 'http://users.example.org/users').to_return response([])
|
120
|
+
end
|
121
|
+
let!(:collection) { model.all page: 2 }
|
122
|
+
subject { Acfs.run; collection.first_page }
|
123
|
+
|
124
|
+
it { should be_a Acfs::Collection }
|
125
|
+
|
126
|
+
it 'should have fetched page 1' do
|
127
|
+
subject
|
128
|
+
Acfs.run
|
129
|
+
expect(req).to have_been_requested
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe '#last_page' do
|
134
|
+
before do
|
135
|
+
stub_request(:get, 'http://users.example.org/users?page=2')
|
136
|
+
.to_return response([{id: 2, name: 'Anno', age: 1604, born_at: 'Santa Maria'}],
|
137
|
+
headers: {
|
138
|
+
'X-Total-Pages' => '2',
|
139
|
+
'Link' => '<http://users.example.org/users?page=12>; rel="last"'
|
140
|
+
})
|
141
|
+
end
|
142
|
+
let!(:req) do
|
143
|
+
stub_request(:get, 'http://users.example.org/users?page=12').to_return response([])
|
144
|
+
end
|
145
|
+
let!(:collection) { model.all page: 2 }
|
146
|
+
subject { Acfs.run; collection.last_page }
|
147
|
+
|
148
|
+
it { should be_a Acfs::Collection }
|
149
|
+
|
150
|
+
it 'should have fetched page 1' do
|
151
|
+
subject
|
152
|
+
Acfs.run
|
153
|
+
expect(req).to have_been_requested
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Acfs::Configuration do
|
6
|
+
let(:cfg) { Acfs::Configuration.new }
|
7
|
+
before { @configuration = Acfs::Configuration.current.dup }
|
8
|
+
after { Acfs::Configuration.set @configuration }
|
9
|
+
|
10
|
+
describe 'Acfs.configure' do
|
11
|
+
it 'should invoke configure on current configuration' do
|
12
|
+
expect(Acfs::Configuration.current).to receive(:configure).once.and_call_original
|
13
|
+
|
14
|
+
Acfs.configure do |c|
|
15
|
+
expect(c).to be_a Acfs::Configuration
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '.load' do
|
21
|
+
it 'should be able to load YAML' do
|
22
|
+
cfg.configure do
|
23
|
+
load 'spec/fixtures/config.yml'
|
24
|
+
end
|
25
|
+
|
26
|
+
expect(cfg.locate(UserService).to_s).to be == 'http://localhost:3001/'
|
27
|
+
expect(cfg.locate(CommentService).to_s).to be == 'http://localhost:3002/'
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'with RACK_ENV' do
|
31
|
+
before { @env = ENV['RACK_ENV']; ENV['RACK_ENV'] = 'production' }
|
32
|
+
after { ENV['RACK_ENV'] = @env }
|
33
|
+
|
34
|
+
it 'should load ENV block' do
|
35
|
+
cfg.configure do
|
36
|
+
load 'spec/fixtures/config.yml'
|
37
|
+
end
|
38
|
+
|
39
|
+
expect(cfg.locate(UserService).to_s).to be == 'http://user.example.org/'
|
40
|
+
expect(cfg.locate(CommentService).to_s).to be == 'http://comment.example.org/'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#adapter' do
|
46
|
+
let(:object) { Object.new }
|
47
|
+
|
48
|
+
it 'should be a accessor' do
|
49
|
+
cfg.adapter = object
|
50
|
+
expect(cfg.adapter).to eq object
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
class NotificationCollector
|
6
|
+
def call(*args)
|
7
|
+
events << ActiveSupport::Notifications::Event.new(*args)
|
8
|
+
end
|
9
|
+
|
10
|
+
def events
|
11
|
+
@events ||= []
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe ::Acfs::Global do
|
16
|
+
let(:adapter) { ::NullAdapter.new }
|
17
|
+
let(:runner) { double 'runner' }
|
18
|
+
let(:collector) { NotificationCollector.new }
|
19
|
+
let(:acfs) { Object.new.tap {|o| o.extend ::Acfs::Global } }
|
20
|
+
|
21
|
+
describe 'instrumentation' do
|
22
|
+
before do
|
23
|
+
# allow(runner).to receive(:start)
|
24
|
+
allow(acfs).to receive(:runner).and_return runner
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#run' do
|
28
|
+
before do
|
29
|
+
::ActiveSupport::Notifications.subscribe 'acfs.run', collector
|
30
|
+
end
|
31
|
+
it 'should trigger event' do
|
32
|
+
Acfs.run
|
33
|
+
expect(collector.events).to have(1).items
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#reset' do
|
38
|
+
before do
|
39
|
+
::ActiveSupport::Notifications.subscribe 'acfs.reset', collector
|
40
|
+
end
|
41
|
+
it 'should trigger event' do
|
42
|
+
Acfs.reset
|
43
|
+
expect(collector.events).to have(1).items
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#on' do
|
49
|
+
before do
|
50
|
+
stub_request(:get, %r{http://users.example.org/users/\d+}).to_return(
|
51
|
+
status: 200,
|
52
|
+
body: '{}',
|
53
|
+
headers: {'Content-Type' => 'application/json'}
|
54
|
+
)
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should invoke when both resources' do
|
58
|
+
user1 = MyUser.find 1
|
59
|
+
user2 = MyUser.find 2
|
60
|
+
|
61
|
+
expect do |cb|
|
62
|
+
Acfs.on(user1, user2, &cb)
|
63
|
+
Acfs.run
|
64
|
+
end.to yield_with_args(user1, user2)
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should invoke when both resources when loaded' do
|
68
|
+
user1 = MyUser.find 1
|
69
|
+
user2 = MyUser.find 2
|
70
|
+
|
71
|
+
Acfs.on(user1, user2) do |u1, u2|
|
72
|
+
expect(u1).to be_loaded
|
73
|
+
expect(u2).to be_loaded
|
74
|
+
end
|
75
|
+
Acfs.run
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'with an empty result for a find_by call' do
|
79
|
+
before do
|
80
|
+
stub_request(:get, %r{http://users.example.org/users})
|
81
|
+
.with(query: {id: '2'})
|
82
|
+
.to_return(
|
83
|
+
status: 200,
|
84
|
+
body: '{}',
|
85
|
+
headers: {'Content-Type' => 'application/json'}
|
86
|
+
)
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'invokes once both requests are finished' do
|
90
|
+
user1 = MyUser.find 1
|
91
|
+
user2 = MyUser.find_by id: 2
|
92
|
+
|
93
|
+
expect do |cb|
|
94
|
+
Acfs.on(user1, user2, &cb)
|
95
|
+
Acfs.run
|
96
|
+
end.to yield_with_args(user1, be_nil)
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'invokes once remaining requests are finished' do
|
100
|
+
user1 = MyUser.find 1
|
101
|
+
Acfs.run # Finish the first request
|
102
|
+
|
103
|
+
user2 = MyUser.find_by id: 2
|
104
|
+
|
105
|
+
expect do |cb|
|
106
|
+
Acfs.on(user1, user2, &cb)
|
107
|
+
Acfs.run
|
108
|
+
end.to yield_with_args(user1, be_nil)
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'invokes immediately when all requests have already been finished' do
|
112
|
+
user1 = MyUser.find 1
|
113
|
+
user2 = MyUser.find_by id: 2
|
114
|
+
Acfs.run
|
115
|
+
|
116
|
+
expect do |cb|
|
117
|
+
Acfs.on(user1, user2, &cb)
|
118
|
+
end.to yield_with_args(user1, be_nil)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe '#runner' do
|
124
|
+
it 'returns per-thread runner' do
|
125
|
+
runner1 = Thread.new { acfs.runner }.value
|
126
|
+
runner2 = Thread.new { acfs.runner }.value
|
127
|
+
|
128
|
+
expect(runner1).to_not equal runner2
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'uses configurated adapter' do
|
132
|
+
adapter = double :adapter
|
133
|
+
expect(Acfs::Configuration.current).to receive(:adapter).and_return(-> { adapter })
|
134
|
+
|
135
|
+
runner = Thread.new { acfs.runner }.value
|
136
|
+
|
137
|
+
expect(runner.adapter).to equal adapter
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe ::Acfs::Location do
|
6
|
+
let(:location) { described_class.new(uri, args) }
|
7
|
+
let(:uri) { 'http://localhost/users/:id' }
|
8
|
+
let(:args) { {'id' => 4} }
|
9
|
+
|
10
|
+
describe '#str' do
|
11
|
+
subject(:str) { location.str }
|
12
|
+
|
13
|
+
it 'replaces variables with values' do
|
14
|
+
expect(str).to eq 'http://localhost/users/4'
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'with special characters' do
|
18
|
+
let(:args) { {'id' => '4 [@(\/!^$'} }
|
19
|
+
|
20
|
+
it 'escapes special characters' do
|
21
|
+
expect(str).to eq 'http://localhost/users/4+%5B%40%28%5C%2F%21%5E%24'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Acfs::Middleware::JSON do
|
6
|
+
let(:data) { [{id: 1, name: 'Anon'}, {id: 2, name: 'John', friends: [1]}] }
|
7
|
+
let(:body) { '' }
|
8
|
+
let(:headers) { {} }
|
9
|
+
let(:request) { Acfs::Request.new 'url', method: 'GET', data: data }
|
10
|
+
let(:response) { Acfs::Response.new request, status: 200, headers: headers, body: body }
|
11
|
+
let(:decoder) { Acfs::Middleware::JSON.new ->(req) { req } }
|
12
|
+
|
13
|
+
before do
|
14
|
+
decoder.call request
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'encode' do
|
18
|
+
context 'with not serialized request' do
|
19
|
+
it 'should set Content-Type' do
|
20
|
+
expect(request.headers['Content-Type']).to eq 'application/json'
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should append Accept header' do
|
24
|
+
expect(request.headers['Accept']).to eq 'application/json;q=1'
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should serialize data to JSON' do
|
28
|
+
expect(JSON.parse(request.body)).to eq data.map(&:stringify_keys)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'with #to_json objects' do
|
33
|
+
let(:data) do
|
34
|
+
Class.new do
|
35
|
+
def to_json(*)
|
36
|
+
'{"a": 1, "b": 2}'
|
37
|
+
end
|
38
|
+
end.new
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should serialize data with #to_json' do
|
42
|
+
expect(JSON.parse(request.body)).to eq 'a' => 1, 'b' => 2
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe 'decode' do
|
48
|
+
context 'with JSON response' do
|
49
|
+
let(:headers) { {'Content-Type' => 'application/json; charset=utf-8'} }
|
50
|
+
let(:body) { data.to_json }
|
51
|
+
|
52
|
+
it 'should decode body data' do
|
53
|
+
request.complete! response
|
54
|
+
|
55
|
+
expect(response.data).to be == data.map(&:stringify_keys)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'with invalid JSON response' do
|
60
|
+
let(:headers) { {'Content-Type' => 'application/json'} }
|
61
|
+
let(:body) { data.to_json[4..-4] }
|
62
|
+
|
63
|
+
it 'should raise an error' do
|
64
|
+
expect { request.complete! response }.to raise_error(::JSON::ParserError)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'without JSON response' do
|
69
|
+
let(:headers) { {'Content-Type' => 'application/text'} }
|
70
|
+
let(:body) { data.to_json }
|
71
|
+
|
72
|
+
it 'should not decode non-JSON encoded responses' do
|
73
|
+
request.complete! response
|
74
|
+
|
75
|
+
expect(response.data).to be_nil
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|