acfs 1.4.0 → 1.7.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 +26 -0
- data/README.md +22 -39
- data/acfs.gemspec +8 -14
- data/lib/acfs/adapter/base.rb +2 -0
- data/lib/acfs/adapter/typhoeus.rb +16 -11
- data/lib/acfs/collections/paginatable.rb +1 -1
- data/lib/acfs/configuration.rb +13 -3
- data/lib/acfs/errors.rb +41 -21
- data/lib/acfs/global.rb +2 -2
- data/lib/acfs/location.rb +26 -32
- data/lib/acfs/middleware/base.rb +2 -2
- data/lib/acfs/middleware/json.rb +4 -2
- data/lib/acfs/middleware/logger.rb +4 -6
- data/lib/acfs/middleware/serializer.rb +1 -1
- data/lib/acfs/operation.rb +21 -8
- data/lib/acfs/request/callbacks.rb +4 -4
- data/lib/acfs/request.rb +4 -11
- data/lib/acfs/resource/attributes/date_time.rb +1 -1
- data/lib/acfs/resource/attributes/uuid.rb +1 -1
- data/lib/acfs/resource/attributes.rb +16 -15
- data/lib/acfs/resource/dirty.rb +2 -2
- data/lib/acfs/resource/initialization.rb +5 -5
- data/lib/acfs/resource/locatable.rb +11 -8
- data/lib/acfs/resource/operational.rb +6 -3
- data/lib/acfs/resource/persistence.rb +13 -15
- data/lib/acfs/resource/query_methods.rb +10 -10
- data/lib/acfs/resource/service.rb +2 -2
- data/lib/acfs/resource/validation.rb +17 -7
- data/lib/acfs/response.rb +5 -5
- data/lib/acfs/runner.rb +15 -15
- data/lib/acfs/service.rb +16 -19
- data/lib/acfs/singleton_resource.rb +2 -2
- data/lib/acfs/stub.rb +41 -31
- data/lib/acfs/version.rb +2 -2
- data/spec/acfs/adapter/typhoeus_spec.rb +2 -2
- data/spec/acfs/collection_spec.rb +66 -41
- data/spec/acfs/configuration_spec.rb +22 -12
- data/spec/acfs/global_spec.rb +11 -9
- data/spec/acfs/location_spec.rb +2 -2
- data/spec/acfs/middleware/json_spec.rb +22 -8
- data/spec/acfs/middleware/{msgpack_spec.rb → message_pack_spec.rb} +6 -6
- data/spec/acfs/operation_spec.rb +3 -2
- data/spec/acfs/request/callbacks_spec.rb +19 -10
- data/spec/acfs/request_spec.rb +16 -20
- data/spec/acfs/resource/attributes/boolean_spec.rb +32 -32
- data/spec/acfs/resource/attributes/date_time_spec.rb +16 -8
- data/spec/acfs/resource/attributes/dict_spec.rb +15 -9
- data/spec/acfs/resource/attributes/float_spec.rb +20 -10
- data/spec/acfs/resource/attributes/integer_spec.rb +10 -5
- data/spec/acfs/resource/attributes/list_spec.rb +13 -8
- data/spec/acfs/resource/attributes/uuid_spec.rb +12 -6
- data/spec/acfs/resource/attributes_spec.rb +37 -38
- data/spec/acfs/resource/dirty_spec.rb +6 -3
- data/spec/acfs/resource/initialization_spec.rb +4 -5
- data/spec/acfs/resource/loadable_spec.rb +3 -1
- data/spec/acfs/resource/locatable_spec.rb +24 -18
- data/spec/acfs/resource/{persistance_spec.rb → persistence_spec.rb} +122 -90
- data/spec/acfs/resource/query_methods_spec.rb +143 -110
- data/spec/acfs/resource/validation_spec.rb +34 -27
- data/spec/acfs/response/formats_spec.rb +8 -8
- data/spec/acfs/response/status_spec.rb +16 -9
- data/spec/acfs/runner_spec.rb +10 -8
- data/spec/acfs/service/middleware_spec.rb +3 -3
- data/spec/acfs/service_spec.rb +6 -5
- data/spec/acfs/singleton_resource_spec.rb +2 -1
- data/spec/acfs/stub_spec.rb +57 -53
- data/spec/acfs_spec.rb +111 -93
- data/spec/spec_helper.rb +1 -2
- data/spec/support/response.rb +2 -2
- data/spec/support/service.rb +1 -1
- data/spec/support/shared/find_callbacks.rb +14 -10
- metadata +30 -29
data/lib/acfs/service.rb
CHANGED
@@ -28,33 +28,27 @@ module Acfs
|
|
28
28
|
|
29
29
|
# @api private
|
30
30
|
#
|
31
|
-
def initialize(options
|
31
|
+
def initialize(**options)
|
32
32
|
@options = options
|
33
33
|
end
|
34
34
|
|
35
35
|
# @api private
|
36
36
|
# @return [Location]
|
37
37
|
#
|
38
|
-
def location(resource_class,
|
39
|
-
|
38
|
+
def location(resource_class, path: nil, action: :list, **)
|
39
|
+
path ||= options[:path]
|
40
40
|
|
41
|
-
|
41
|
+
if path.is_a?(Hash) && path.key?(action)
|
42
|
+
path = path.fetch(action)
|
43
|
+
else
|
44
|
+
path = path.is_a?(Hash) ? path[:all].to_s : path.to_s
|
42
45
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
path = if opts[:path].is_a?(Hash)
|
47
|
-
opts[:path][:all].to_s
|
48
|
-
else
|
49
|
-
opts[:path].to_s
|
50
|
-
end
|
51
|
-
|
52
|
-
if path.blank?
|
53
|
-
path = (resource_class.name || 'class').pluralize.underscore
|
54
|
-
end
|
46
|
+
if path.blank?
|
47
|
+
path = (resource_class.name || 'class').pluralize.underscore
|
48
|
+
end
|
55
49
|
|
56
|
-
|
57
|
-
|
50
|
+
path = resource_class.location_default_path(action, path.strip)
|
51
|
+
end
|
58
52
|
|
59
53
|
if path.nil?
|
60
54
|
raise ArgumentError.new "Location for `#{action}' explicit disabled by set to nil."
|
@@ -87,7 +81,10 @@ module Acfs
|
|
87
81
|
#
|
88
82
|
def base_url
|
89
83
|
unless (base = Acfs::Configuration.current.locate identity)
|
90
|
-
raise ArgumentError.new
|
84
|
+
raise ArgumentError.new \
|
85
|
+
"#{identity} not configured. Add `locate '" \
|
86
|
+
"#{identity.to_s.underscore}', 'http://service.url/'` " \
|
87
|
+
'to your configuration.'
|
91
88
|
end
|
92
89
|
|
93
90
|
base.to_s
|
@@ -27,10 +27,10 @@ module Acfs
|
|
27
27
|
# @return [undefined]
|
28
28
|
# @see #delete
|
29
29
|
#
|
30
|
-
def delete!(opts
|
30
|
+
def delete!(**opts)
|
31
31
|
opts[:params] ||= {}
|
32
32
|
|
33
|
-
operation
|
33
|
+
operation(:delete, **opts) do |data|
|
34
34
|
update_with data
|
35
35
|
freeze
|
36
36
|
end
|
data/lib/acfs/stub.rb
CHANGED
@@ -16,16 +16,16 @@ module Acfs
|
|
16
16
|
@opts[:with].stringify_keys! if @opts[:with].is_a? Hash
|
17
17
|
@opts[:return].stringify_keys! if @opts[:return].is_a? Hash
|
18
18
|
|
19
|
-
if @opts[:return].is_a?
|
19
|
+
if @opts[:return].is_a?(Array) # rubocop:disable Style/GuardClause
|
20
20
|
@opts[:return].map! {|h| h.stringify_keys! if h.is_a? Hash }
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
def accept?(
|
25
|
-
return opts[:with].call
|
24
|
+
def accept?(operation)
|
25
|
+
return opts[:with].call(operation) if opts[:with].respond_to?(:call)
|
26
26
|
|
27
|
-
params =
|
28
|
-
data =
|
27
|
+
params = operation.full_params.stringify_keys
|
28
|
+
data = operation.data.stringify_keys
|
29
29
|
with = opts[:with]
|
30
30
|
|
31
31
|
return true if with.nil?
|
@@ -33,10 +33,10 @@ module Acfs
|
|
33
33
|
case opts.fetch(:match, :inclusion)
|
34
34
|
when :legacy
|
35
35
|
return true if with.empty? && params.empty? && data.empty?
|
36
|
-
if with.
|
36
|
+
if with.compact == params.compact
|
37
37
|
return true
|
38
38
|
end
|
39
|
-
if with.
|
39
|
+
if with.compact == data.compact
|
40
40
|
return true
|
41
41
|
end
|
42
42
|
|
@@ -53,28 +53,30 @@ module Acfs
|
|
53
53
|
end
|
54
54
|
|
55
55
|
def called?(count = nil)
|
56
|
-
if count.respond_to?
|
57
|
-
|
58
|
-
end # For `5.times` Enumerators
|
56
|
+
count = count.count if count.respond_to?(:count)
|
57
|
+
|
59
58
|
count.nil? ? calls.any? : calls.size == count
|
60
59
|
end
|
61
60
|
|
62
|
-
def call(
|
63
|
-
calls <<
|
61
|
+
def call(operation)
|
62
|
+
calls << operation
|
64
63
|
|
65
64
|
err = opts[:raise]
|
66
65
|
data = opts[:return]
|
67
66
|
|
68
67
|
if err
|
69
|
-
raise_error
|
68
|
+
raise_error(operation, err, opts[:return])
|
70
69
|
elsif data
|
71
|
-
data = data.call(
|
70
|
+
data = data.call(operation) if data.respond_to?(:call)
|
72
71
|
|
73
|
-
response = Acfs::Response.new
|
72
|
+
response = Acfs::Response.new(
|
73
|
+
operation.request,
|
74
74
|
headers: opts[:headers] || {},
|
75
75
|
status: opts[:status] || 200,
|
76
|
-
data: data || {}
|
77
|
-
|
76
|
+
data: data || {},
|
77
|
+
)
|
78
|
+
|
79
|
+
operation.call(data, response)
|
78
80
|
else
|
79
81
|
raise ArgumentError.new 'Unsupported stub.'
|
80
82
|
end
|
@@ -82,12 +84,18 @@ module Acfs
|
|
82
84
|
|
83
85
|
private
|
84
86
|
|
85
|
-
def raise_error(
|
87
|
+
def raise_error(operation, name, data)
|
86
88
|
raise name if name.is_a? Class
|
87
89
|
|
88
|
-
data.stringify_keys! if data.respond_to?
|
90
|
+
data.stringify_keys! if data.respond_to?(:stringify_keys!)
|
89
91
|
|
90
|
-
|
92
|
+
operation.handle_failure(
|
93
|
+
::Acfs::Response.new(
|
94
|
+
operation.request,
|
95
|
+
status: Rack::Utils.status_code(name),
|
96
|
+
data: data,
|
97
|
+
),
|
98
|
+
)
|
91
99
|
end
|
92
100
|
|
93
101
|
class << self
|
@@ -137,33 +145,35 @@ module Acfs
|
|
137
145
|
@stubs ||= {}
|
138
146
|
end
|
139
147
|
|
140
|
-
def stub_for(
|
141
|
-
return false unless (classes = stubs[
|
142
|
-
return false unless (stubs = classes[
|
148
|
+
def stub_for(operation)
|
149
|
+
return false unless (classes = stubs[operation.resource])
|
150
|
+
return false unless (stubs = classes[operation.action])
|
143
151
|
|
144
|
-
accepted_stubs = stubs.select {|stub| stub.accept?
|
152
|
+
accepted_stubs = stubs.select {|stub| stub.accept?(operation) }
|
145
153
|
|
146
154
|
if accepted_stubs.size > 1
|
147
|
-
raise AmbiguousStubError.new
|
155
|
+
raise AmbiguousStubError.new(stubs: accepted_stubs, operation: operation)
|
148
156
|
end
|
149
157
|
|
150
158
|
accepted_stubs.first
|
151
159
|
end
|
152
160
|
|
153
|
-
def stubbed(
|
154
|
-
stub = stub_for
|
161
|
+
def stubbed(operation)
|
162
|
+
stub = stub_for(operation)
|
155
163
|
unless stub
|
156
164
|
return false if allow_requests?
|
157
165
|
|
158
|
-
raise RealRequestsNotAllowedError.new
|
159
|
-
No stub found for `#{
|
166
|
+
raise RealRequestsNotAllowedError.new <<~ERROR
|
167
|
+
No stub found for `#{operation.action}' on `#{operation.resource.name}' \
|
168
|
+
with params `#{operation.full_params.inspect}', data `#{operation.data.inspect}' \
|
169
|
+
and id `#{operation.id}'.
|
160
170
|
|
161
171
|
Available stubs:
|
162
172
|
#{pretty_print}
|
163
|
-
|
173
|
+
ERROR
|
164
174
|
end
|
165
175
|
|
166
|
-
stub.call
|
176
|
+
stub.call(operation)
|
167
177
|
true
|
168
178
|
end
|
169
179
|
|
data/lib/acfs/version.rb
CHANGED
@@ -19,8 +19,8 @@ describe Acfs::Adapter::Typhoeus do
|
|
19
19
|
adapter.queue request1
|
20
20
|
adapter.queue request2
|
21
21
|
|
22
|
-
expect { adapter.start }.to raise_error(/404
|
23
|
-
expect { adapter.start }.
|
22
|
+
expect { adapter.start }.to raise_error(/404-[12]/)
|
23
|
+
expect { adapter.start }.not_to raise_error
|
24
24
|
end
|
25
25
|
|
26
26
|
it 'raises timeout' do
|
@@ -6,149 +6,174 @@ describe Acfs::Collection do
|
|
6
6
|
let(:model) { MyUser }
|
7
7
|
|
8
8
|
describe 'Pagination' do
|
9
|
+
subject do
|
10
|
+
Acfs.run
|
11
|
+
collection
|
12
|
+
end
|
13
|
+
|
9
14
|
let(:params) { {} }
|
10
15
|
let!(:collection) { model.all params }
|
11
16
|
|
12
|
-
subject { Acfs.run; collection }
|
13
|
-
|
14
17
|
context 'without explicit page parameter' do
|
15
18
|
before do
|
16
19
|
stub_request(:get, 'http://users.example.org/users')
|
17
20
|
.to_return response([{id: 1, name: 'Anon', age: 12, born_at: 'Berlin'}],
|
18
21
|
headers: {
|
19
22
|
'X-Total-Pages' => '2',
|
20
|
-
'X-Total-Count' => '10'
|
21
|
-
})
|
23
|
+
'X-Total-Count' => '10',
|
24
|
+
},)
|
22
25
|
end
|
23
26
|
|
24
|
-
its(:total_pages) {
|
25
|
-
its(:current_page) {
|
26
|
-
its(:total_count) {
|
27
|
+
its(:total_pages) { is_expected.to eq 2 }
|
28
|
+
its(:current_page) { is_expected.to eq 1 }
|
29
|
+
its(:total_count) { is_expected.to eq 10 }
|
27
30
|
end
|
28
31
|
|
29
32
|
context 'with page parameter' do
|
30
33
|
let(:params) { {page: 2} }
|
34
|
+
|
31
35
|
before do
|
32
36
|
stub_request(:get, 'http://users.example.org/users?page=2')
|
33
37
|
.to_return response([{id: 1, name: 'Anon', age: 12, born_at: 'Berlin'}],
|
34
38
|
headers: {
|
35
39
|
'X-Total-Pages' => '2',
|
36
|
-
'X-Total-Count' => '10'
|
37
|
-
})
|
40
|
+
'X-Total-Count' => '10',
|
41
|
+
},)
|
38
42
|
end
|
39
43
|
|
40
|
-
its(:total_pages) {
|
41
|
-
its(:current_page) {
|
42
|
-
its(:total_count) {
|
44
|
+
its(:total_pages) { is_expected.to eq 2 }
|
45
|
+
its(:current_page) { is_expected.to eq 2 }
|
46
|
+
its(:total_count) { is_expected.to eq 10 }
|
43
47
|
end
|
44
48
|
|
45
49
|
context 'with non-numerical page parameter' do
|
46
50
|
let(:params) { {page: 'e546f5'} }
|
51
|
+
|
47
52
|
before do
|
48
53
|
stub_request(:get, 'http://users.example.org/users?page=e546f5')
|
49
54
|
.to_return response([{id: 1, name: 'Anon', age: 12, born_at: 'Berlin'}],
|
50
55
|
headers: {
|
51
56
|
'X-Total-Pages' => '2',
|
52
|
-
'X-Total-Count' => '10'
|
53
|
-
})
|
57
|
+
'X-Total-Count' => '10',
|
58
|
+
},)
|
54
59
|
end
|
55
60
|
|
56
|
-
its(:total_pages) {
|
57
|
-
its(:current_page) {
|
58
|
-
its(:total_count) {
|
61
|
+
its(:total_pages) { is_expected.to eq 2 }
|
62
|
+
its(:current_page) { is_expected.to eq 'e546f5' }
|
63
|
+
its(:total_count) { is_expected.to eq 10 }
|
59
64
|
end
|
60
65
|
|
61
66
|
describe '#next_page' do
|
67
|
+
subject(:request_page) do
|
68
|
+
Acfs.run
|
69
|
+
collection.next_page
|
70
|
+
end
|
71
|
+
|
62
72
|
before do
|
63
73
|
stub_request(:get, 'http://users.example.org/users')
|
64
74
|
.to_return response([{id: 1, name: 'Anon', age: 12, born_at: 'Berlin'}],
|
65
75
|
headers: {
|
66
76
|
'X-Total-Pages' => '2',
|
67
|
-
'Link' => '<http://users.example.org/users?page=2>; rel="next"'
|
68
|
-
})
|
77
|
+
'Link' => '<http://users.example.org/users?page=2>; rel="next"',
|
78
|
+
},)
|
69
79
|
end
|
80
|
+
|
70
81
|
let!(:req) do
|
71
82
|
stub_request(:get, 'http://users.example.org/users?page=2').to_return response([])
|
72
83
|
end
|
73
84
|
let!(:collection) { model.all }
|
74
|
-
subject { Acfs.run; collection.next_page }
|
75
85
|
|
76
|
-
it {
|
86
|
+
it { is_expected.to be_a Acfs::Collection }
|
77
87
|
|
78
|
-
it '
|
79
|
-
|
88
|
+
it 'has fetched page 2' do
|
89
|
+
request_page
|
80
90
|
Acfs.run
|
81
91
|
expect(req).to have_been_requested
|
82
92
|
end
|
83
93
|
end
|
84
94
|
|
85
95
|
describe '#prev_page' do
|
96
|
+
subject(:request_page) do
|
97
|
+
Acfs.run
|
98
|
+
collection.prev_page
|
99
|
+
end
|
100
|
+
|
86
101
|
before do
|
87
102
|
stub_request(:get, 'http://users.example.org/users?page=2')
|
88
103
|
.to_return response([{id: 2, name: 'Anno', age: 1604, born_at: 'Santa Maria'}],
|
89
104
|
headers: {
|
90
105
|
'X-Total-Pages' => '2',
|
91
|
-
'Link' => '<http://users.example.org/users>; rel="prev"'
|
92
|
-
})
|
106
|
+
'Link' => '<http://users.example.org/users>; rel="prev"',
|
107
|
+
},)
|
93
108
|
end
|
109
|
+
|
94
110
|
let!(:req) do
|
95
111
|
stub_request(:get, 'http://users.example.org/users').to_return response([])
|
96
112
|
end
|
97
113
|
let!(:collection) { model.all page: 2 }
|
98
|
-
subject { Acfs.run; collection.prev_page }
|
99
114
|
|
100
|
-
it {
|
115
|
+
it { is_expected.to be_a Acfs::Collection }
|
101
116
|
|
102
|
-
it '
|
103
|
-
|
117
|
+
it 'has fetched page 1' do
|
118
|
+
request_page
|
104
119
|
Acfs.run
|
105
120
|
expect(req).to have_been_requested
|
106
121
|
end
|
107
122
|
end
|
108
123
|
|
109
124
|
describe '#first_page' do
|
125
|
+
subject(:request_page) do
|
126
|
+
Acfs.run
|
127
|
+
collection.first_page
|
128
|
+
end
|
129
|
+
|
110
130
|
before do
|
111
131
|
stub_request(:get, 'http://users.example.org/users?page=2')
|
112
132
|
.to_return response([{id: 2, name: 'Anno', age: 1604, born_at: 'Santa Maria'}],
|
113
133
|
headers: {
|
114
134
|
'X-Total-Pages' => '2',
|
115
|
-
'Link' => '<http://users.example.org/users>; rel="first"'
|
116
|
-
})
|
135
|
+
'Link' => '<http://users.example.org/users>; rel="first"',
|
136
|
+
},)
|
117
137
|
end
|
138
|
+
|
118
139
|
let!(:req) do
|
119
140
|
stub_request(:get, 'http://users.example.org/users').to_return response([])
|
120
141
|
end
|
121
142
|
let!(:collection) { model.all page: 2 }
|
122
|
-
subject { Acfs.run; collection.first_page }
|
123
143
|
|
124
|
-
it {
|
144
|
+
it { is_expected.to be_a Acfs::Collection }
|
125
145
|
|
126
|
-
it '
|
127
|
-
|
146
|
+
it 'has fetched page 1' do
|
147
|
+
request_page
|
128
148
|
Acfs.run
|
129
149
|
expect(req).to have_been_requested
|
130
150
|
end
|
131
151
|
end
|
132
152
|
|
133
153
|
describe '#last_page' do
|
154
|
+
subject(:request_page) do
|
155
|
+
Acfs.run
|
156
|
+
collection.last_page
|
157
|
+
end
|
158
|
+
|
134
159
|
before do
|
135
160
|
stub_request(:get, 'http://users.example.org/users?page=2')
|
136
161
|
.to_return response([{id: 2, name: 'Anno', age: 1604, born_at: 'Santa Maria'}],
|
137
162
|
headers: {
|
138
163
|
'X-Total-Pages' => '2',
|
139
|
-
'Link' => '<http://users.example.org/users?page=12>; rel="last"'
|
140
|
-
})
|
164
|
+
'Link' => '<http://users.example.org/users?page=12>; rel="last"',
|
165
|
+
},)
|
141
166
|
end
|
167
|
+
|
142
168
|
let!(:req) do
|
143
169
|
stub_request(:get, 'http://users.example.org/users?page=12').to_return response([])
|
144
170
|
end
|
145
171
|
let!(:collection) { model.all page: 2 }
|
146
|
-
subject { Acfs.run; collection.last_page }
|
147
172
|
|
148
|
-
it {
|
173
|
+
it { is_expected.to be_a Acfs::Collection }
|
149
174
|
|
150
|
-
it '
|
151
|
-
|
175
|
+
it 'has fetched page 1' do
|
176
|
+
request_page
|
152
177
|
Acfs.run
|
153
178
|
expect(req).to have_been_requested
|
154
179
|
end
|
@@ -4,11 +4,16 @@ require 'spec_helper'
|
|
4
4
|
|
5
5
|
describe Acfs::Configuration do
|
6
6
|
let(:cfg) { Acfs::Configuration.new }
|
7
|
-
|
8
|
-
|
7
|
+
|
8
|
+
around do |example|
|
9
|
+
configuration = Acfs::Configuration.current.dup
|
10
|
+
example.run
|
11
|
+
ensure
|
12
|
+
Acfs::Configuration.set(configuration)
|
13
|
+
end
|
9
14
|
|
10
15
|
describe 'Acfs.configure' do
|
11
|
-
it '
|
16
|
+
it 'invokes configure on current configuration' do
|
12
17
|
expect(Acfs::Configuration.current).to receive(:configure).once.and_call_original
|
13
18
|
|
14
19
|
Acfs.configure do |c|
|
@@ -18,26 +23,31 @@ describe Acfs::Configuration do
|
|
18
23
|
end
|
19
24
|
|
20
25
|
describe '.load' do
|
21
|
-
it '
|
26
|
+
it 'is able to load YAML' do
|
22
27
|
cfg.configure do
|
23
28
|
load 'spec/fixtures/config.yml'
|
24
29
|
end
|
25
30
|
|
26
|
-
expect(cfg.locate(UserService).to_s).to
|
27
|
-
expect(cfg.locate(CommentService).to_s).to
|
31
|
+
expect(cfg.locate(UserService).to_s).to eq 'http://localhost:3001/'
|
32
|
+
expect(cfg.locate(CommentService).to_s).to eq 'http://localhost:3002/'
|
28
33
|
end
|
29
34
|
|
30
35
|
context 'with RACK_ENV' do
|
31
|
-
|
32
|
-
|
36
|
+
around do |example|
|
37
|
+
env = ENV['RACK_ENV']
|
38
|
+
ENV['RACK_ENV'] = 'production'
|
39
|
+
example.run
|
40
|
+
ensure
|
41
|
+
ENV['RACK_ENV'] = env
|
42
|
+
end
|
33
43
|
|
34
|
-
it '
|
44
|
+
it 'loads ENV block' do
|
35
45
|
cfg.configure do
|
36
46
|
load 'spec/fixtures/config.yml'
|
37
47
|
end
|
38
48
|
|
39
|
-
expect(cfg.locate(UserService).to_s).to
|
40
|
-
expect(cfg.locate(CommentService).to_s).to
|
49
|
+
expect(cfg.locate(UserService).to_s).to eq 'http://user.example.org/'
|
50
|
+
expect(cfg.locate(CommentService).to_s).to eq 'http://comment.example.org/'
|
41
51
|
end
|
42
52
|
end
|
43
53
|
end
|
@@ -45,7 +55,7 @@ describe Acfs::Configuration do
|
|
45
55
|
describe '#adapter' do
|
46
56
|
let(:object) { Object.new }
|
47
57
|
|
48
|
-
it '
|
58
|
+
it 'is a accessor' do
|
49
59
|
cfg.adapter = object
|
50
60
|
expect(cfg.adapter).to eq object
|
51
61
|
end
|
data/spec/acfs/global_spec.rb
CHANGED
@@ -28,7 +28,8 @@ describe ::Acfs::Global do
|
|
28
28
|
before do
|
29
29
|
::ActiveSupport::Notifications.subscribe 'acfs.run', collector
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
|
+
it 'triggers event' do
|
32
33
|
Acfs.run
|
33
34
|
expect(collector.events).to have(1).items
|
34
35
|
end
|
@@ -38,7 +39,8 @@ describe ::Acfs::Global do
|
|
38
39
|
before do
|
39
40
|
::ActiveSupport::Notifications.subscribe 'acfs.reset', collector
|
40
41
|
end
|
41
|
-
|
42
|
+
|
43
|
+
it 'triggers event' do
|
42
44
|
Acfs.reset
|
43
45
|
expect(collector.events).to have(1).items
|
44
46
|
end
|
@@ -50,11 +52,11 @@ describe ::Acfs::Global do
|
|
50
52
|
stub_request(:get, %r{http://users.example.org/users/\d+}).to_return(
|
51
53
|
status: 200,
|
52
54
|
body: '{}',
|
53
|
-
headers: {'Content-Type' => 'application/json'}
|
55
|
+
headers: {'Content-Type' => 'application/json'},
|
54
56
|
)
|
55
57
|
end
|
56
58
|
|
57
|
-
it '
|
59
|
+
it 'invokes when both resources' do
|
58
60
|
user1 = MyUser.find 1
|
59
61
|
user2 = MyUser.find 2
|
60
62
|
|
@@ -64,7 +66,7 @@ describe ::Acfs::Global do
|
|
64
66
|
end.to yield_with_args(user1, user2)
|
65
67
|
end
|
66
68
|
|
67
|
-
it '
|
69
|
+
it 'invokes when both resources when loaded' do
|
68
70
|
user1 = MyUser.find 1
|
69
71
|
user2 = MyUser.find 2
|
70
72
|
|
@@ -82,7 +84,7 @@ describe ::Acfs::Global do
|
|
82
84
|
.to_return(
|
83
85
|
status: 200,
|
84
86
|
body: '{}',
|
85
|
-
headers: {'Content-Type' => 'application/json'}
|
87
|
+
headers: {'Content-Type' => 'application/json'},
|
86
88
|
)
|
87
89
|
end
|
88
90
|
|
@@ -122,10 +124,10 @@ describe ::Acfs::Global do
|
|
122
124
|
|
123
125
|
describe '#runner' do
|
124
126
|
it 'returns per-thread runner' do
|
125
|
-
runner1 = Thread.new { acfs.runner }
|
126
|
-
runner2 = Thread.new { acfs.runner }
|
127
|
+
runner1 = Thread.new { acfs.runner }.value
|
128
|
+
runner2 = Thread.new { acfs.runner }.value
|
127
129
|
|
128
|
-
expect(runner1).
|
130
|
+
expect(runner1).not_to equal runner2
|
129
131
|
end
|
130
132
|
|
131
133
|
it 'uses configurated adapter' do
|
data/spec/acfs/location_spec.rb
CHANGED
@@ -5,7 +5,7 @@ require 'spec_helper'
|
|
5
5
|
describe ::Acfs::Location do
|
6
6
|
let(:location) { described_class.new(uri, args) }
|
7
7
|
let(:uri) { 'http://localhost/users/:id' }
|
8
|
-
let(:args) { {id
|
8
|
+
let(:args) { {'id' => 4} }
|
9
9
|
|
10
10
|
describe '#str' do
|
11
11
|
subject(:str) { location.str }
|
@@ -15,7 +15,7 @@ describe ::Acfs::Location do
|
|
15
15
|
end
|
16
16
|
|
17
17
|
context 'with special characters' do
|
18
|
-
let(:args) { {id
|
18
|
+
let(:args) { {'id' => '4 [@(\/!^$'} }
|
19
19
|
|
20
20
|
it 'escapes special characters' do
|
21
21
|
expect(str).to eq 'http://localhost/users/4+%5B%40%28%5C%2F%21%5E%24'
|
@@ -16,18 +16,32 @@ describe Acfs::Middleware::JSON do
|
|
16
16
|
|
17
17
|
describe 'encode' do
|
18
18
|
context 'with not serialized request' do
|
19
|
-
it '
|
19
|
+
it 'sets Content-Type' do
|
20
20
|
expect(request.headers['Content-Type']).to eq 'application/json'
|
21
21
|
end
|
22
22
|
|
23
|
-
it '
|
23
|
+
it 'appends Accept header' do
|
24
24
|
expect(request.headers['Accept']).to eq 'application/json;q=1'
|
25
25
|
end
|
26
26
|
|
27
|
-
it '
|
27
|
+
it 'serializes data to JSON' do
|
28
28
|
expect(JSON.parse(request.body)).to eq data.map(&:stringify_keys)
|
29
29
|
end
|
30
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 'serializes data with #to_json' do
|
42
|
+
expect(JSON.parse(request.body)).to eq 'a' => 1, 'b' => 2
|
43
|
+
end
|
44
|
+
end
|
31
45
|
end
|
32
46
|
|
33
47
|
describe 'decode' do
|
@@ -35,10 +49,10 @@ describe Acfs::Middleware::JSON do
|
|
35
49
|
let(:headers) { {'Content-Type' => 'application/json; charset=utf-8'} }
|
36
50
|
let(:body) { data.to_json }
|
37
51
|
|
38
|
-
it '
|
52
|
+
it 'decodes body data' do
|
39
53
|
request.complete! response
|
40
54
|
|
41
|
-
expect(response.data).to
|
55
|
+
expect(response.data).to eq data.map(&:stringify_keys)
|
42
56
|
end
|
43
57
|
end
|
44
58
|
|
@@ -46,8 +60,8 @@ describe Acfs::Middleware::JSON do
|
|
46
60
|
let(:headers) { {'Content-Type' => 'application/json'} }
|
47
61
|
let(:body) { data.to_json[4..-4] }
|
48
62
|
|
49
|
-
it '
|
50
|
-
expect { request.complete! response }.to raise_error(
|
63
|
+
it 'raises an error' do
|
64
|
+
expect { request.complete! response }.to raise_error(::JSON::ParserError)
|
51
65
|
end
|
52
66
|
end
|
53
67
|
|
@@ -55,7 +69,7 @@ describe Acfs::Middleware::JSON do
|
|
55
69
|
let(:headers) { {'Content-Type' => 'application/text'} }
|
56
70
|
let(:body) { data.to_json }
|
57
71
|
|
58
|
-
it '
|
72
|
+
it 'does not decode non-JSON encoded responses' do
|
59
73
|
request.complete! response
|
60
74
|
|
61
75
|
expect(response.data).to be_nil
|