restify 1.15.2 → 2.0.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 +25 -2
- data/README.md +23 -31
- data/lib/restify/adapter/base.rb +4 -0
- data/lib/restify/adapter/telemetry.rb +54 -0
- data/lib/restify/adapter/typhoeus.rb +21 -3
- data/lib/restify/context.rb +3 -3
- data/lib/restify/error.rb +2 -2
- data/lib/restify/link.rb +4 -4
- data/lib/restify/processors/base/parsing.rb +2 -21
- data/lib/restify/processors/base.rb +1 -1
- data/lib/restify/promise.rb +2 -2
- data/lib/restify/registry.rb +1 -1
- data/lib/restify/relation.rb +45 -17
- data/lib/restify/request.rb +6 -6
- data/lib/restify/timeout.rb +2 -2
- data/lib/restify/version.rb +3 -3
- data/lib/restify.rb +0 -1
- data/spec/restify/cache_spec.rb +16 -12
- data/spec/restify/context_spec.rb +8 -3
- data/spec/restify/error_spec.rb +13 -16
- data/spec/restify/features/head_requests_spec.rb +5 -4
- data/spec/restify/features/request_bodies_spec.rb +8 -8
- data/spec/restify/features/request_errors_spec.rb +2 -2
- data/spec/restify/features/request_headers_spec.rb +3 -6
- data/spec/restify/features/response_errors_spec.rb +1 -1
- data/spec/restify/global_spec.rb +10 -10
- data/spec/restify/processors/base_spec.rb +6 -7
- data/spec/restify/processors/json_spec.rb +21 -62
- data/spec/restify/processors/msgpack_spec.rb +33 -70
- data/spec/restify/promise_spec.rb +31 -31
- data/spec/restify/registry_spec.rb +5 -7
- data/spec/restify/relation_spec.rb +185 -7
- data/spec/restify/resource_spec.rb +47 -53
- data/spec/restify/timeout_spec.rb +3 -3
- data/spec/restify_spec.rb +12 -73
- data/spec/spec_helper.rb +11 -15
- metadata +33 -64
- data/lib/restify/adapter/em.rb +0 -134
- data/lib/restify/adapter/pooled_em.rb +0 -269
@@ -4,95 +4,94 @@ require 'spec_helper'
|
|
4
4
|
|
5
5
|
describe Restify::Processors::Msgpack do
|
6
6
|
let(:context) { Restify::Context.new('http://test.host/') }
|
7
|
-
let(:response) {
|
7
|
+
let(:response) { instance_double(Restify::Response) }
|
8
8
|
|
9
9
|
before do
|
10
|
-
allow(response).to
|
11
|
-
allow(response).to receive(:follow_location).and_return nil
|
10
|
+
allow(response).to receive_messages(links: [], follow_location: nil)
|
12
11
|
end
|
13
12
|
|
14
13
|
describe 'class' do
|
15
14
|
describe '#accept?' do
|
16
|
-
subject { described_class.accept?
|
15
|
+
subject(:accept) { described_class.accept?(response) }
|
17
16
|
|
18
17
|
it 'accepts msgpack mime type (I)' do
|
19
|
-
|
20
|
-
expect(
|
18
|
+
allow(response).to receive(:content_type).and_return('application/msgpack')
|
19
|
+
expect(accept).to be_truthy
|
21
20
|
end
|
22
21
|
|
23
22
|
it 'accepts msgpack mime type (II)' do
|
24
|
-
|
25
|
-
expect(
|
23
|
+
allow(response).to receive(:content_type).and_return('application/msgpack; abc')
|
24
|
+
expect(accept).to be_truthy
|
26
25
|
end
|
27
26
|
|
28
27
|
it 'accepts x-msgpack mime type (I)' do
|
29
|
-
|
30
|
-
expect(
|
28
|
+
allow(response).to receive(:content_type).and_return('application/x-msgpack')
|
29
|
+
expect(accept).to be_truthy
|
31
30
|
end
|
32
31
|
|
33
32
|
it 'accepts x-msgpack mime type (II)' do
|
34
|
-
|
35
|
-
expect(
|
33
|
+
allow(response).to receive(:content_type).and_return('application/x-msgpack; abc')
|
34
|
+
expect(accept).to be_truthy
|
36
35
|
end
|
37
36
|
end
|
38
37
|
end
|
39
38
|
|
40
39
|
describe '#resource' do
|
41
|
-
subject { described_class.new(context, response).resource }
|
40
|
+
subject(:resource) { described_class.new(context, response).resource }
|
42
41
|
|
43
42
|
before { allow(response).to receive(:body).and_return(body) }
|
44
43
|
|
45
44
|
describe 'parsing' do
|
46
45
|
context 'single object' do
|
47
46
|
let(:body) do
|
48
|
-
|
47
|
+
MessagePack.dump('msg' => 'value')
|
49
48
|
end
|
50
49
|
|
51
50
|
it { is_expected.to be_a Restify::Resource }
|
52
|
-
it { expect(
|
51
|
+
it { expect(resource.response).to be response }
|
53
52
|
it { is_expected.to eq 'msg' => 'value' }
|
54
53
|
end
|
55
54
|
|
56
55
|
context 'object with relation fields' do
|
57
56
|
let(:body) do
|
58
|
-
|
57
|
+
MessagePack.dump(
|
59
58
|
'msg' => 'value',
|
60
59
|
'search_url' => 'https://google.com{?q}',
|
61
60
|
)
|
62
61
|
end
|
63
62
|
|
64
63
|
it do
|
65
|
-
expect(
|
64
|
+
expect(resource).to eq \
|
66
65
|
'msg' => 'value', 'search_url' => 'https://google.com{?q}'
|
67
66
|
end
|
68
67
|
|
69
68
|
it { is_expected.to have_relation :search }
|
70
|
-
it { expect(
|
69
|
+
it { expect(resource.relation(:search)).to eq 'https://google.com{?q}' }
|
71
70
|
end
|
72
71
|
|
73
72
|
context 'object with implicit self relation' do
|
74
73
|
let(:body) do
|
75
|
-
|
74
|
+
MessagePack.dump(
|
76
75
|
'url' => '/self',
|
77
76
|
)
|
78
77
|
end
|
79
78
|
|
80
|
-
it { expect(
|
79
|
+
it { expect(resource.relation(:self)).to eq '/self' }
|
81
80
|
end
|
82
81
|
|
83
82
|
context 'single array' do
|
84
83
|
let(:body) do
|
85
|
-
|
84
|
+
MessagePack.dump([1, 2, nil, 'STR'])
|
86
85
|
end
|
87
86
|
|
88
87
|
it { is_expected.to be_a Restify::Resource }
|
89
|
-
it { expect(
|
88
|
+
it { expect(resource.response).to be response }
|
90
89
|
it { is_expected.to eq [1, 2, nil, 'STR'] }
|
91
90
|
end
|
92
91
|
|
93
92
|
context 'array with objects' do
|
94
93
|
let(:body) do
|
95
|
-
|
94
|
+
MessagePack.dump([{'a' => 0}, {'b' => 1}])
|
96
95
|
end
|
97
96
|
|
98
97
|
it { is_expected.to eq [{'a' => 0}, {'b' => 1}] }
|
@@ -100,87 +99,51 @@ describe Restify::Processors::Msgpack do
|
|
100
99
|
|
101
100
|
context 'array with resources' do
|
102
101
|
let(:body) do
|
103
|
-
|
102
|
+
MessagePack.dump([
|
104
103
|
{'name' => 'John', 'self_url' => '/users/john'},
|
105
104
|
{'name' => 'Jane', 'self_url' => '/users/jane'},
|
106
105
|
])
|
107
106
|
end
|
108
107
|
|
109
108
|
it 'parses objects as resources' do
|
110
|
-
expect(
|
109
|
+
expect(resource).to all(be_a(Restify::Resource))
|
111
110
|
end
|
112
111
|
|
113
112
|
it 'parses relations of resources' do
|
114
|
-
expect(
|
113
|
+
expect(resource.map {|r| r.relation :self }).to eq \
|
115
114
|
['/users/john', '/users/jane']
|
116
115
|
end
|
117
116
|
end
|
118
117
|
|
119
118
|
context 'nested objects' do
|
120
119
|
let(:body) do
|
121
|
-
|
120
|
+
MessagePack.dump(
|
122
121
|
'john' => {'name' => 'John'},
|
123
122
|
'jane' => {'name' => 'Jane'},
|
124
123
|
)
|
125
124
|
end
|
126
125
|
|
127
126
|
it { is_expected.to be_a Restify::Resource }
|
128
|
-
it { expect(
|
127
|
+
it { expect(resource.response).to be response }
|
129
128
|
|
130
129
|
it 'parses objects as resources' do
|
131
|
-
expect(
|
132
|
-
expect(
|
130
|
+
expect(resource['john']).to be_a Restify::Resource
|
131
|
+
expect(resource['jane']).to be_a Restify::Resource
|
133
132
|
|
134
|
-
expect(
|
135
|
-
expect(
|
133
|
+
expect(resource['john']['name']).to eq 'John'
|
134
|
+
expect(resource['jane']['name']).to eq 'Jane'
|
136
135
|
end
|
137
136
|
end
|
138
137
|
|
139
138
|
context 'single value' do
|
140
139
|
let(:body) do
|
141
|
-
|
140
|
+
MessagePack.dump('BLUB')
|
142
141
|
end
|
143
142
|
|
144
143
|
it { is_expected.to be_a Restify::Resource }
|
145
|
-
it { expect(
|
144
|
+
it { expect(resource.response).to be response }
|
146
145
|
it { is_expected.to eq 'BLUB' }
|
147
146
|
end
|
148
|
-
|
149
|
-
context 'with indifferent access' do
|
150
|
-
let(:body) do
|
151
|
-
::MessagePack.dump('name' => 'John', 'age' => 24)
|
152
|
-
end
|
153
|
-
|
154
|
-
it '#key?' do
|
155
|
-
expect(subject).to have_key 'name'
|
156
|
-
expect(subject).to have_key 'age'
|
157
|
-
|
158
|
-
expect(subject).to have_key :name
|
159
|
-
expect(subject).to have_key :age
|
160
|
-
end
|
161
|
-
|
162
|
-
it '#[]' do
|
163
|
-
expect(subject['name']).to eq 'John'
|
164
|
-
expect(subject['age']).to eq 24
|
165
|
-
|
166
|
-
expect(subject[:name]).to eq 'John'
|
167
|
-
expect(subject[:age]).to eq 24
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
context 'with method getter access' do
|
172
|
-
let(:body) do
|
173
|
-
::MessagePack.dump('name' => 'John', 'age' => 24)
|
174
|
-
end
|
175
|
-
|
176
|
-
it '#<method getter>' do
|
177
|
-
expect(subject).to respond_to :name
|
178
|
-
expect(subject).to respond_to :age
|
179
|
-
|
180
|
-
expect(subject.name).to eq 'John'
|
181
|
-
expect(subject.age).to eq 24
|
182
|
-
end
|
183
|
-
end
|
184
147
|
end
|
185
148
|
end
|
186
149
|
end
|
@@ -7,42 +7,42 @@ describe Restify::Promise do
|
|
7
7
|
|
8
8
|
describe 'factory methods' do
|
9
9
|
describe '#fulfilled' do
|
10
|
-
subject { described_class.fulfilled(fulfill_value) }
|
10
|
+
subject(:promise) { described_class.fulfilled(fulfill_value) }
|
11
11
|
|
12
12
|
let(:fulfill_value) { 42 }
|
13
13
|
|
14
14
|
it 'returns a fulfilled promise' do
|
15
|
-
expect(
|
16
|
-
expect(
|
15
|
+
expect(promise.fulfilled?).to be true
|
16
|
+
expect(promise.rejected?).to be false
|
17
17
|
end
|
18
18
|
|
19
19
|
it 'wraps the given value' do
|
20
|
-
expect(
|
20
|
+
expect(promise.value!).to eq 42
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
24
|
describe '#rejected' do
|
25
|
-
subject { described_class.rejected(rejection_reason) }
|
25
|
+
subject(:promise) { described_class.rejected(rejection_reason) }
|
26
26
|
|
27
27
|
let(:rejection_reason) { ArgumentError }
|
28
28
|
|
29
29
|
it 'returns a rejected promise' do
|
30
|
-
expect(
|
31
|
-
expect(
|
30
|
+
expect(promise.fulfilled?).to be false
|
31
|
+
expect(promise.rejected?).to be true
|
32
32
|
end
|
33
33
|
|
34
34
|
it 'bubbles up the caught exception on #value!' do
|
35
|
-
expect {
|
35
|
+
expect { promise.value! }.to raise_error(ArgumentError)
|
36
36
|
end
|
37
37
|
|
38
38
|
it 'swallows the exception on #value' do
|
39
|
-
expect(
|
39
|
+
expect(promise.value).to be_nil
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
43
|
describe '#create' do
|
44
44
|
context 'when fulfilling the promise in the writer block' do
|
45
|
-
subject do
|
45
|
+
subject(:promise) do
|
46
46
|
described_class.create do |writer|
|
47
47
|
# Calculate a value and fulfill the promise with it
|
48
48
|
writer.fulfill 42
|
@@ -50,17 +50,17 @@ describe Restify::Promise do
|
|
50
50
|
end
|
51
51
|
|
52
52
|
it 'returns a fulfilled promise' do
|
53
|
-
expect(
|
54
|
-
expect(
|
53
|
+
expect(promise.fulfilled?).to be true
|
54
|
+
expect(promise.rejected?).to be false
|
55
55
|
end
|
56
56
|
|
57
57
|
it 'wraps the given value' do
|
58
|
-
expect(
|
58
|
+
expect(promise.value!).to eq 42
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
62
|
context 'when rejecting the promise in the writer block' do
|
63
|
-
subject do
|
63
|
+
subject(:promise) do
|
64
64
|
described_class.create do |writer|
|
65
65
|
# Calculate a value and fulfill the promise with it
|
66
66
|
writer.reject ArgumentError
|
@@ -68,21 +68,21 @@ describe Restify::Promise do
|
|
68
68
|
end
|
69
69
|
|
70
70
|
it 'returns a rejected promise' do
|
71
|
-
expect(
|
72
|
-
expect(
|
71
|
+
expect(promise.fulfilled?).to be false
|
72
|
+
expect(promise.rejected?).to be true
|
73
73
|
end
|
74
74
|
|
75
75
|
it 'bubbles up the caught exception on #value!' do
|
76
|
-
expect {
|
76
|
+
expect { promise.value! }.to raise_error(ArgumentError)
|
77
77
|
end
|
78
78
|
|
79
79
|
it 'swallows the exception on #value' do
|
80
|
-
expect(
|
80
|
+
expect(promise.value).to be_nil
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
84
84
|
context 'when fulfilling the promise asynchronously' do
|
85
|
-
subject do
|
85
|
+
subject(:promise) do
|
86
86
|
described_class.create do |writer|
|
87
87
|
Thread.new do
|
88
88
|
sleep 0.1
|
@@ -92,20 +92,20 @@ describe Restify::Promise do
|
|
92
92
|
end
|
93
93
|
|
94
94
|
it 'returns a pending promise' do
|
95
|
-
expect(
|
96
|
-
expect(
|
97
|
-
expect(
|
95
|
+
expect(promise.fulfilled?).to be false
|
96
|
+
expect(promise.rejected?).to be false
|
97
|
+
expect(promise.pending?).to be true
|
98
98
|
end
|
99
99
|
|
100
100
|
it 'waits for the fulfillment value' do
|
101
|
-
expect(
|
101
|
+
expect(promise.value!).to eq 42
|
102
102
|
end
|
103
103
|
end
|
104
104
|
end
|
105
105
|
end
|
106
106
|
|
107
107
|
describe 'result' do
|
108
|
-
subject { described_class.new(*dependencies, &task).value! }
|
108
|
+
subject(:result) { described_class.new(*dependencies, &task).value! }
|
109
109
|
|
110
110
|
let(:dependencies) { [] }
|
111
111
|
let(:task) { nil }
|
@@ -119,7 +119,7 @@ describe Restify::Promise do
|
|
119
119
|
end
|
120
120
|
|
121
121
|
it 'is calculated using the task block' do
|
122
|
-
expect(
|
122
|
+
expect(result).to eq 42
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
@@ -133,7 +133,7 @@ describe Restify::Promise do
|
|
133
133
|
end
|
134
134
|
|
135
135
|
it 'is an array of the dependencies\' results' do
|
136
|
-
expect(
|
136
|
+
expect(result).to eq [1, 2, 3]
|
137
137
|
end
|
138
138
|
end
|
139
139
|
|
@@ -147,7 +147,7 @@ describe Restify::Promise do
|
|
147
147
|
end
|
148
148
|
|
149
149
|
it 'is an array of the dependencies\' results' do
|
150
|
-
expect(
|
150
|
+
expect(result).to eq [1, 2, 3]
|
151
151
|
end
|
152
152
|
end
|
153
153
|
|
@@ -163,7 +163,7 @@ describe Restify::Promise do
|
|
163
163
|
end
|
164
164
|
|
165
165
|
it 'can use the dependencies to calculate the value' do
|
166
|
-
expect(
|
166
|
+
expect(result).to eq 17
|
167
167
|
end
|
168
168
|
end
|
169
169
|
|
@@ -178,19 +178,19 @@ describe Restify::Promise do
|
|
178
178
|
|
179
179
|
describe '#wait' do
|
180
180
|
it 'can time out' do
|
181
|
-
expect { promise.wait(0.1) }.to raise_error
|
181
|
+
expect { promise.wait(0.1) }.to raise_error Timeout::Error
|
182
182
|
end
|
183
183
|
end
|
184
184
|
|
185
185
|
describe '#value' do
|
186
186
|
it 'can time out' do
|
187
|
-
expect { promise.value(0.1) }.to raise_error
|
187
|
+
expect { promise.value(0.1) }.to raise_error Timeout::Error
|
188
188
|
end
|
189
189
|
end
|
190
190
|
|
191
191
|
describe '#value!' do
|
192
192
|
it 'can time out' do
|
193
|
-
expect { promise.value!(0.1) }.to raise_error
|
193
|
+
expect { promise.value!(0.1) }.to raise_error Timeout::Error
|
194
194
|
end
|
195
195
|
end
|
196
196
|
end
|
@@ -3,15 +3,13 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
describe Restify::Registry do
|
6
|
-
|
6
|
+
subject(:registry) { described_class.instance }
|
7
7
|
|
8
8
|
describe 'class' do
|
9
9
|
describe '#instance' do
|
10
|
-
subject { described_class.instance }
|
11
|
-
|
12
10
|
it 'returns singleton instance' do
|
13
|
-
expect(
|
14
|
-
expect(
|
11
|
+
expect(registry).to be_a described_class
|
12
|
+
expect(registry).to be described_class.instance
|
15
13
|
end
|
16
14
|
end
|
17
15
|
|
@@ -36,14 +34,14 @@ describe Restify::Registry do
|
|
36
34
|
end
|
37
35
|
|
38
36
|
describe '#store / #fetch' do
|
39
|
-
subject { registry.store
|
37
|
+
subject(:store) { registry.store(name, uri, **opts) }
|
40
38
|
|
41
39
|
let(:name) { 'remote' }
|
42
40
|
let(:uri) { 'http://remote/entry/point' }
|
43
41
|
let(:opts) { {accept: 'application/vnd.remote+json'} }
|
44
42
|
|
45
43
|
it 'stores registry item' do
|
46
|
-
|
44
|
+
store
|
47
45
|
|
48
46
|
item = registry.fetch name
|
49
47
|
|
@@ -1,21 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
|
+
require 'active_support'
|
4
5
|
|
5
6
|
describe Restify::Relation do
|
6
7
|
subject(:relation) { described_class.new context, pattern }
|
7
8
|
|
8
9
|
let(:context) { Restify::Context.new('http://test.host/') }
|
9
|
-
let(:pattern) { '/resource/{id}' }
|
10
|
+
let(:pattern) { '/resource/{id}{?q*}' }
|
10
11
|
|
11
12
|
describe '#==' do
|
12
13
|
it 'equals pattern' do
|
13
|
-
expect(
|
14
|
+
expect(relation).to eq pattern
|
14
15
|
end
|
15
16
|
end
|
16
17
|
|
17
18
|
describe '#expand' do
|
18
|
-
subject(:
|
19
|
+
subject(:expanded) { relation.expand params }
|
19
20
|
|
20
21
|
let(:params) { {id: 1337} }
|
21
22
|
let(:cls_to_param) do
|
@@ -28,29 +29,206 @@ describe Restify::Relation do
|
|
28
29
|
|
29
30
|
it { is_expected.to be_a Addressable::URI }
|
30
31
|
|
32
|
+
context 'with nil' do
|
33
|
+
let(:params) { {id: nil} }
|
34
|
+
|
35
|
+
it { expect(expanded.to_s).to eq 'http://test.host/resource/' }
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'with false' do
|
39
|
+
let(:params) { {id: false} }
|
40
|
+
|
41
|
+
it { expect(expanded.to_s).to eq 'http://test.host/resource/' }
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'with true' do
|
45
|
+
let(:params) { {id: true} }
|
46
|
+
|
47
|
+
it { expect(expanded.to_s).to eq 'http://test.host/resource/true' }
|
48
|
+
end
|
49
|
+
|
31
50
|
context 'with #to_param object' do
|
32
51
|
let(:params) { {id: cls_to_param.new} }
|
33
52
|
|
34
|
-
it { expect(
|
53
|
+
it { expect(expanded.to_s).to eq 'http://test.host/resource/42' }
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'with array parameter' do
|
57
|
+
let(:params) { {id: [1, 2]} }
|
58
|
+
|
59
|
+
it { expect(expanded.to_s).to eq 'http://test.host/resource/1,2' }
|
35
60
|
end
|
36
61
|
|
37
62
|
context 'with unknown additional query parameter' do
|
38
63
|
let(:pattern) { '/resource{?a,b}' }
|
39
64
|
let(:params) { {a: 1, b: 2, c: 3} }
|
40
65
|
|
41
|
-
it { expect(
|
66
|
+
it { expect(expanded.to_s).to eq 'http://test.host/resource?a=1&b=2&c=3' }
|
42
67
|
end
|
43
68
|
|
44
69
|
context 'with additional parameters' do
|
45
70
|
let(:params) { {id: '5', abc: 'cde'} }
|
46
71
|
|
47
|
-
it { expect(
|
72
|
+
it { expect(expanded.to_s).to eq 'http://test.host/resource/5?abc=cde' }
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'with additional nil parameters' do
|
76
|
+
let(:params) { {id: '5', abc: nil} }
|
77
|
+
|
78
|
+
it { expect(expanded.to_s).to eq 'http://test.host/resource/5?abc' }
|
79
|
+
end
|
80
|
+
|
81
|
+
context 'with additional false parameters' do
|
82
|
+
let(:params) { {id: '5', abc: false} }
|
83
|
+
|
84
|
+
it { expect(expanded.to_s).to eq 'http://test.host/resource/5?abc=false' }
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'with additional true parameters' do
|
88
|
+
let(:params) { {id: '5', abc: true} }
|
89
|
+
|
90
|
+
it { expect(expanded.to_s).to eq 'http://test.host/resource/5?abc=true' }
|
48
91
|
end
|
49
92
|
|
50
93
|
context 'with additional #to_param parameter' do
|
51
94
|
let(:params) { {id: '5', abc: cls_to_param.new} }
|
52
95
|
|
53
|
-
it { expect(
|
96
|
+
it { expect(expanded.to_s).to eq 'http://test.host/resource/5?abc=42' }
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'with additional array parameter' do
|
100
|
+
let(:params) { {id: 5, abc: [1, 2]} }
|
101
|
+
|
102
|
+
it { expect(expanded.to_s).to eq 'http://test.host/resource/5?abc=1&abc=2' }
|
54
103
|
end
|
104
|
+
|
105
|
+
context 'with additional array parameter with objects' do
|
106
|
+
let(:params) { {id: 5, abc: [1, 2, cls_to_param.new]} }
|
107
|
+
|
108
|
+
it { expect(expanded.to_s).to eq 'http://test.host/resource/5?abc=1&abc=2&abc=42' }
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'with additional nested array parameter' do
|
112
|
+
let(:params) { {id: 5, abc: [1, 2, [1]]} }
|
113
|
+
|
114
|
+
it { expect { expanded }.to raise_exception TypeError, /Can't convert Array into String./ }
|
115
|
+
end
|
116
|
+
|
117
|
+
context 'with additional hash parameter' do
|
118
|
+
let(:params) { {id: 5, abc: {a: 1, b: 2}} }
|
119
|
+
|
120
|
+
it { expect { expanded }.to raise_exception TypeError, /Can't convert Hash into String./ }
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
shared_examples 'non-data-request' do |method|
|
125
|
+
it "issues a #{method.upcase} request" do
|
126
|
+
expect(context).to receive(:request) do |meth, uri, opts|
|
127
|
+
expect(meth).to eq method
|
128
|
+
expect(uri.to_s).to eq 'http://test.host/resource/'
|
129
|
+
expect(opts).to be_nil
|
130
|
+
end
|
131
|
+
relation.send(method)
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'accepts params as keyword argument' do
|
135
|
+
expect(context).to receive(:request) do |meth, uri, opts|
|
136
|
+
expect(meth).to eq method
|
137
|
+
expect(uri.to_s).to eq 'http://test.host/resource/1'
|
138
|
+
expect(opts).to be_nil
|
139
|
+
end
|
140
|
+
relation.send(method, params: {id: 1})
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'accepts params as positional argument' do
|
144
|
+
expect(context).to receive(:request) do |meth, uri, opts|
|
145
|
+
expect(meth).to eq method
|
146
|
+
expect(uri.to_s).to eq 'http://test.host/resource/1'
|
147
|
+
expect(opts).to be_nil
|
148
|
+
end
|
149
|
+
relation.send(method, {id: 1})
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'merges keyword params into positional params' do
|
153
|
+
expect(context).to receive(:request) do |meth, uri, opts|
|
154
|
+
expect(meth).to eq method
|
155
|
+
expect(uri.to_s).to eq 'http://test.host/resource/1?a=2&b=3'
|
156
|
+
expect(opts).to be_nil
|
157
|
+
end
|
158
|
+
relation.send(method, {id: 1, q: {a: 1, c: 1}}, params: {q: {a: 2, b: 3}})
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
describe '#get' do
|
163
|
+
include_examples 'non-data-request', :get
|
164
|
+
end
|
165
|
+
|
166
|
+
describe '#head' do
|
167
|
+
include_examples 'non-data-request', :head
|
168
|
+
end
|
169
|
+
|
170
|
+
describe '#delete' do
|
171
|
+
include_examples 'non-data-request', :delete
|
172
|
+
end
|
173
|
+
|
174
|
+
shared_examples 'data-request' do |method|
|
175
|
+
let(:data) { Object.new }
|
176
|
+
|
177
|
+
it "issues a #{method.upcase} request" do
|
178
|
+
expect(context).to receive(:request) do |meth, uri, opts|
|
179
|
+
expect(meth).to eq method
|
180
|
+
expect(uri.to_s).to eq 'http://test.host/resource/'
|
181
|
+
expect(opts).to eq({data: nil})
|
182
|
+
end
|
183
|
+
relation.send(method)
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'accepts params as keyword argument' do
|
187
|
+
expect(context).to receive(:request) do |meth, uri, opts|
|
188
|
+
expect(meth).to eq method
|
189
|
+
expect(uri.to_s).to eq 'http://test.host/resource/1'
|
190
|
+
expect(opts).to eq({data: nil})
|
191
|
+
end
|
192
|
+
relation.send(method, params: {id: 1})
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'accepts data as keyword argument' do
|
196
|
+
expect(context).to receive(:request) do |meth, uri, opts|
|
197
|
+
expect(meth).to eq method
|
198
|
+
expect(uri.to_s).to eq 'http://test.host/resource/1'
|
199
|
+
expect(opts).to eq({data:})
|
200
|
+
end
|
201
|
+
relation.send(method, data:, params: {id: 1})
|
202
|
+
end
|
203
|
+
|
204
|
+
it 'accepts data as position argument' do
|
205
|
+
expect(context).to receive(:request) do |meth, uri, opts|
|
206
|
+
expect(meth).to eq method
|
207
|
+
expect(uri.to_s).to eq 'http://test.host/resource/1'
|
208
|
+
expect(opts).to eq({data:})
|
209
|
+
end
|
210
|
+
relation.send(method, data, params: {id: 1})
|
211
|
+
end
|
212
|
+
|
213
|
+
it 'prefers data from keyword argument' do
|
214
|
+
expect(context).to receive(:request) do |meth, uri, opts|
|
215
|
+
expect(meth).to eq method
|
216
|
+
expect(uri.to_s).to eq 'http://test.host/resource/1'
|
217
|
+
expect(opts).to eq({data:})
|
218
|
+
end
|
219
|
+
relation.send(method, 'DATA', data:, params: {id: 1})
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
describe '#post' do
|
224
|
+
include_examples 'data-request', :post
|
225
|
+
end
|
226
|
+
|
227
|
+
describe '#put' do
|
228
|
+
include_examples 'data-request', :put
|
229
|
+
end
|
230
|
+
|
231
|
+
describe '#patch' do
|
232
|
+
include_examples 'data-request', :patch
|
55
233
|
end
|
56
234
|
end
|