restify 1.15.2 → 2.0.1

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +34 -2
  3. data/README.md +23 -31
  4. data/doc/file.README.html +192 -0
  5. data/lib/restify/adapter/base.rb +4 -0
  6. data/lib/restify/adapter/telemetry.rb +54 -0
  7. data/lib/restify/adapter/typhoeus.rb +37 -4
  8. data/lib/restify/context.rb +3 -3
  9. data/lib/restify/error.rb +2 -2
  10. data/lib/restify/link.rb +4 -4
  11. data/lib/restify/processors/base/parsing.rb +2 -21
  12. data/lib/restify/processors/base.rb +1 -1
  13. data/lib/restify/promise.rb +2 -2
  14. data/lib/restify/registry.rb +1 -1
  15. data/lib/restify/relation.rb +45 -17
  16. data/lib/restify/request.rb +6 -6
  17. data/lib/restify/timeout.rb +2 -2
  18. data/lib/restify/version.rb +3 -3
  19. data/lib/restify.rb +0 -1
  20. data/spec/restify/cache_spec.rb +16 -12
  21. data/spec/restify/context_spec.rb +8 -3
  22. data/spec/restify/error_spec.rb +13 -16
  23. data/spec/restify/features/head_requests_spec.rb +5 -4
  24. data/spec/restify/features/opentelemetry_spec.rb +46 -0
  25. data/spec/restify/features/request_bodies_spec.rb +8 -8
  26. data/spec/restify/features/request_errors_spec.rb +2 -2
  27. data/spec/restify/features/request_headers_spec.rb +3 -6
  28. data/spec/restify/features/response_errors_spec.rb +1 -1
  29. data/spec/restify/features/webmock_spec.rb +27 -0
  30. data/spec/restify/global_spec.rb +10 -10
  31. data/spec/restify/processors/base_spec.rb +6 -7
  32. data/spec/restify/processors/json_spec.rb +21 -62
  33. data/spec/restify/processors/msgpack_spec.rb +33 -70
  34. data/spec/restify/promise_spec.rb +31 -31
  35. data/spec/restify/registry_spec.rb +5 -7
  36. data/spec/restify/relation_spec.rb +185 -7
  37. data/spec/restify/resource_spec.rb +47 -53
  38. data/spec/restify/timeout_spec.rb +3 -3
  39. data/spec/restify_spec.rb +12 -73
  40. data/spec/spec_helper.rb +12 -15
  41. data/spec/support/opentelemetry.rb +29 -0
  42. data/spec/support/stub_server.rb +4 -0
  43. metadata +37 -64
  44. data/lib/restify/adapter/em.rb +0 -134
  45. data/lib/restify/adapter/pooled_em.rb +0 -269
@@ -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(subject).to eq pattern
14
+ expect(relation).to eq pattern
14
15
  end
15
16
  end
16
17
 
17
18
  describe '#expand' do
18
- subject(:expaned) { relation.expand params }
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(expaned.to_s).to eq 'http://test.host/resource/42' }
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(expaned.to_s).to eq 'http://test.host/resource?a=1&b=2&c=3' }
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(expaned.to_s).to eq 'http://test.host/resource/5?abc=cde' }
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(expaned.to_s).to eq 'http://test.host/resource/5?abc=42' }
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
@@ -3,18 +3,12 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe Restify::Resource do
6
- subject { resource }
6
+ subject(:resource) { described_class.new(context, response:, data:, relations:) }
7
7
 
8
8
  let(:data) { {} }
9
9
  let(:relations) { {} }
10
- let(:context) { double 'context' }
11
- let(:response) { double 'response' }
12
- let(:resource) { described_class.new(context, response: response, data: data, relations: relations) }
13
-
14
- before do
15
- allow(context).to receive(:relation?).and_return(false)
16
- allow(context).to receive(:relation).and_raise(KeyError)
17
- end
10
+ let(:context) { instance_double(Restify::Context) }
11
+ let(:response) { instance_double(Restify::Response) }
18
12
 
19
13
  context 'relations' do
20
14
  let(:relations) do
@@ -26,41 +20,41 @@ describe Restify::Resource do
26
20
 
27
21
  describe '#relation?' do
28
22
  it 'matches relations' do
29
- expect(subject.relation?(:users)).to eq true
30
- expect(subject.relation?('users')).to eq true
31
- expect(subject.relation?(:projects)).to eq true
32
- expect(subject.relation?('projects')).to eq true
33
- expect(subject.relation?('fuu')).to eq false
34
-
35
- expect(subject).to have_relation :users
36
- expect(subject).to have_relation :projects
37
-
38
- expect(subject.rel?(:users)).to eq true
39
- expect(subject.rel?('users')).to eq true
40
- expect(subject.rel?(:projects)).to eq true
41
- expect(subject.rel?('projects')).to eq true
42
- expect(subject.rel?('fuu')).to eq false
43
-
44
- expect(subject).to have_rel :users
45
- expect(subject).to have_rel :projects
23
+ expect(resource.relation?(:users)).to be true
24
+ expect(resource.relation?('users')).to be true
25
+ expect(resource.relation?(:projects)).to be true
26
+ expect(resource.relation?('projects')).to be true
27
+ expect(resource.relation?('fuu')).to be false
28
+
29
+ expect(resource).to have_relation :users
30
+ expect(resource).to have_relation :projects
31
+
32
+ expect(resource.rel?(:users)).to be true
33
+ expect(resource.rel?('users')).to be true
34
+ expect(resource.rel?(:projects)).to be true
35
+ expect(resource.rel?('projects')).to be true
36
+ expect(resource.rel?('fuu')).to be false
37
+
38
+ expect(resource).to have_rel :users
39
+ expect(resource).to have_rel :projects
46
40
  end
47
41
  end
48
42
 
49
43
  describe '#relation' do
50
44
  it 'returns relation' do
51
- expect(subject.rel(:users)).to be_a Restify::Relation
52
-
53
- expect(subject.rel(:users)).to eq 'http://example.org/users'
54
- expect(subject.rel('users')).to eq 'http://example.org/users'
55
- expect(subject.rel(:projects)).to eq 'http://example.org/projects'
56
- expect(subject.rel('projects')).to eq 'http://example.org/projects'
57
- expect { subject.rel(:fuu) }.to raise_error KeyError
58
-
59
- expect(subject.relation(:users)).to eq 'http://example.org/users'
60
- expect(subject.relation('users')).to eq 'http://example.org/users'
61
- expect(subject.relation(:projects)).to eq 'http://example.org/projects'
62
- expect(subject.relation('projects')).to eq 'http://example.org/projects'
63
- expect { subject.relation(:fuu) }.to raise_error KeyError
45
+ expect(resource.rel(:users)).to be_a Restify::Relation
46
+
47
+ expect(resource.rel(:users)).to eq 'http://example.org/users'
48
+ expect(resource.rel('users')).to eq 'http://example.org/users'
49
+ expect(resource.rel(:projects)).to eq 'http://example.org/projects'
50
+ expect(resource.rel('projects')).to eq 'http://example.org/projects'
51
+ expect { resource.rel(:fuu) }.to raise_error KeyError
52
+
53
+ expect(resource.relation(:users)).to eq 'http://example.org/users'
54
+ expect(resource.relation('users')).to eq 'http://example.org/users'
55
+ expect(resource.relation(:projects)).to eq 'http://example.org/projects'
56
+ expect(resource.relation('projects')).to eq 'http://example.org/projects'
57
+ expect { resource.relation(:fuu) }.to raise_error KeyError
64
58
  end
65
59
  end
66
60
 
@@ -68,15 +62,15 @@ describe Restify::Resource do
68
62
  let(:relations) { {_restify_follow: 'http://localhost/10'} }
69
63
 
70
64
  it 'returns follow relation' do
71
- expect(subject.follow).to be_a Restify::Relation
72
- expect(subject.follow).to eq 'http://localhost/10'
65
+ expect(resource.follow).to be_a Restify::Relation
66
+ expect(resource.follow).to eq 'http://localhost/10'
73
67
  end
74
68
 
75
69
  context 'when nil' do
76
70
  let(:relations) { {} }
77
71
 
78
72
  it 'returns nil' do
79
- expect(subject.follow).to be nil
73
+ expect(resource.follow).to be_nil
80
74
  end
81
75
  end
82
76
  end
@@ -85,15 +79,15 @@ describe Restify::Resource do
85
79
  let(:relations) { {_restify_follow: 'http://localhost/10'} }
86
80
 
87
81
  it 'returns follow relation' do
88
- expect(subject.follow!).to be_a Restify::Relation
89
- expect(subject.follow!).to eq 'http://localhost/10'
82
+ expect(resource.follow!).to be_a Restify::Relation
83
+ expect(resource.follow!).to eq 'http://localhost/10'
90
84
  end
91
85
 
92
86
  context 'when nil' do
93
87
  let(:relations) { {} }
94
88
 
95
89
  it 'raise runtime error' do
96
- expect { subject.follow! }.to raise_error RuntimeError do |err|
90
+ expect { resource.follow! }.to raise_error RuntimeError do |err|
97
91
  expect(err.message).to eq 'Nothing to follow'
98
92
  end
99
93
  end
@@ -102,25 +96,25 @@ describe Restify::Resource do
102
96
  end
103
97
 
104
98
  context 'data' do
105
- let(:data) { double 'data' }
99
+ let(:data) { double 'data' } # rubocop:disable RSpec/VerifiedDoubles
106
100
 
107
101
  it 'delegates methods (I)' do
108
- expect(data).to receive(:some_method).and_return(42)
102
+ allow(data).to receive(:some_method).and_return(42)
109
103
 
110
- expect(subject).to respond_to :some_method
111
- expect(subject.some_method).to eq 42
104
+ expect(resource).to respond_to :some_method
105
+ expect(resource.some_method).to eq 42
112
106
  end
113
107
 
114
108
  it 'delegates methods (II)' do
115
- expect(data).to receive(:[]).with(1).and_return(2)
109
+ allow(data).to receive(:[]).with(1).and_return(2)
116
110
 
117
- expect(subject).to respond_to :[]
118
- expect(subject[1]).to eq 2
111
+ expect(resource).to respond_to :[]
112
+ expect(resource[1]).to eq 2
119
113
  end
120
114
 
121
115
  describe '#data' do
122
116
  it 'returns data' do
123
- expect(subject.data).to equal data
117
+ expect(resource.data).to equal data
124
118
  end
125
119
  end
126
120
  end
@@ -16,7 +16,7 @@ describe Restify::Timeout do
16
16
  it 'calls given block' do
17
17
  expect { timer.timeout! }.not_to raise_error
18
18
  sleep timer.send(:wait_interval)
19
- expect { timer.timeout! }.to raise_error ::Restify::Timeout::Error
19
+ expect { timer.timeout! }.to raise_error Restify::Timeout::Error
20
20
  end
21
21
  end
22
22
  end
@@ -25,13 +25,13 @@ describe Restify::Timeout do
25
25
  it 'calls block on IVar timeout' do
26
26
  expect do
27
27
  timer.wait_on!(Concurrent::IVar.new)
28
- end.to raise_error ::Restify::Timeout::Error
28
+ end.to raise_error Restify::Timeout::Error
29
29
  end
30
30
 
31
31
  it 'calls block on Promise timeout' do
32
32
  expect do
33
33
  timer.wait_on!(Restify::Promise.new)
34
- end.to raise_error ::Restify::Timeout::Error
34
+ end.to raise_error Restify::Timeout::Error
35
35
  end
36
36
 
37
37
  it 'does nothing on successful IVar' do
data/spec/restify_spec.rb CHANGED
@@ -132,21 +132,21 @@ describe Restify do
132
132
  # Because we forgot to send a "name" the server complains
133
133
  # with an error code that will lead to a raised error.
134
134
 
135
- expect(e.status).to eq :unprocessable_entity
135
+ expect(e.status).to eq :unprocessable_content
136
136
  expect(e.code).to eq 422
137
137
  expect(e.errors).to eq 'name' => ["can't be blank"]
138
138
  end
139
139
 
140
140
  # Let's try again.
141
- created_user = users_relation.post(name: 'John Smith').value!
141
+ created_user = users_relation.post({name: 'John Smith'}).value!
142
142
 
143
143
  # The server returns a 201 Created response with the created
144
144
  # resource.
145
145
  expect(created_user.response.status).to eq :created
146
146
  expect(created_user.response.code).to eq 201
147
147
 
148
- expect(created_user).to have_key :name
149
- expect(created_user.name).to eq 'John Smith'
148
+ expect(created_user).to have_key 'name'
149
+ expect(created_user['name']).to eq 'John Smith'
150
150
 
151
151
  # Let's follow the "Location" header.
152
152
  followed_resource = created_user.follow.get.value!
@@ -154,8 +154,8 @@ describe Restify do
154
154
  expect(followed_resource.response.status).to eq :ok
155
155
  expect(followed_resource.response.code).to eq 200
156
156
 
157
- expect(followed_resource).to have_key :name
158
- expect(followed_resource.name).to eq 'John Smith'
157
+ expect(followed_resource).to have_key 'name'
158
+ expect(followed_resource['name']).to eq 'John Smith'
159
159
 
160
160
  # Now we will fetch a list of all users.
161
161
  users = users_relation.get.value!
@@ -168,80 +168,19 @@ describe Restify do
168
168
 
169
169
  # We have all our attributes and relations here as defined in the
170
170
  # responses from the server.
171
- expect(user).to have_key :name
172
- expect(user[:name]).to eq 'John Smith'
171
+ expect(user).to have_key 'name'
172
+ expect(user['name']).to eq 'John Smith'
173
173
  expect(user).to have_relation :self
174
174
  expect(user).to have_relation :blurb
175
175
 
176
176
  # Let's get the blurb.
177
177
  blurb = user.rel(:blurb).get.value!
178
178
 
179
- expect(blurb).to have_key :title
180
- expect(blurb).to have_key :image
179
+ expect(blurb).to have_key 'title'
180
+ expect(blurb).to have_key 'image'
181
181
 
182
- expect(blurb[:title]).to eq 'Prof. Dr. John Smith'
183
- expect(blurb[:image]).to eq 'http://example.org/avatar.png'
184
- end
185
- end
186
-
187
- context 'within EM-synchrony' do
188
- it 'consumes the API' do
189
- skip 'Seems to be impossible to detect EM scheduled fibers from within'
190
-
191
- EM.synchrony do
192
- root = Restify.new('http://localhost:9292/base').get.value!
193
-
194
- users_relation = root.rel(:users)
195
-
196
- expect(users_relation).to be_a Restify::Relation
197
-
198
- create_user_promise = users_relation.post
199
- expect(create_user_promise).to be_a Restify::Promise
200
-
201
- expect { create_user_promise.value! }.to \
202
- raise_error(Restify::ClientError) do |e|
203
- expect(e.status).to eq :unprocessable_entity
204
- expect(e.code).to eq 422
205
- expect(e.errors).to eq 'name' => ["can't be blank"]
206
- end
207
-
208
- created_user = users_relation.post(name: 'John Smith').value!
209
-
210
- expect(created_user.response.status).to eq :created
211
- expect(created_user.response.code).to eq 201
212
-
213
- expect(created_user).to have_key :name
214
- expect(created_user.name).to eq 'John Smith'
215
-
216
- followed_resource = created_user.follow.get.value!
217
-
218
- expect(followed_resource.response.status).to eq :ok
219
- expect(followed_resource.response.code).to eq 200
220
-
221
- expect(followed_resource).to have_key :name
222
- expect(followed_resource.name).to eq 'John Smith'
223
-
224
- users = users_relation.get.value!
225
-
226
- expect(users).to have(2).items
227
-
228
- user = users.first
229
-
230
- expect(user).to have_key :name
231
- expect(user[:name]).to eq 'John Smith'
232
- expect(user).to have_relation :self
233
- expect(user).to have_relation :blurb
234
-
235
- blurb = user.rel(:blurb).get.value!
236
-
237
- expect(blurb).to have_key :title
238
- expect(blurb).to have_key :image
239
-
240
- expect(blurb[:title]).to eq 'Prof. Dr. John Smith'
241
- expect(blurb[:image]).to eq 'http://example.org/avatar.png'
242
-
243
- EventMachine.stop
244
- end
182
+ expect(blurb['title']).to eq 'Prof. Dr. John Smith'
183
+ expect(blurb['image']).to eq 'http://example.org/avatar.png'
245
184
  end
246
185
  end
247
186
  end
data/spec/spec_helper.rb CHANGED
@@ -4,25 +4,21 @@ require 'rspec'
4
4
  require 'rspec/collection_matchers'
5
5
 
6
6
  require 'simplecov'
7
+ require 'simplecov-cobertura'
8
+
7
9
  SimpleCov.start do
8
10
  add_filter 'spec'
9
11
  end
10
12
 
11
- if ENV['CI']
12
- require 'codecov'
13
- SimpleCov.formatter = SimpleCov::Formatter::Codecov
14
- end
13
+ SimpleCov.formatters = [
14
+ SimpleCov::Formatter::HTMLFormatter,
15
+ SimpleCov::Formatter::CoberturaFormatter,
16
+ ]
15
17
 
16
18
  require 'restify'
17
19
 
18
20
  if ENV['ADAPTER']
19
21
  case ENV['ADAPTER'].to_s.downcase
20
- when 'em'
21
- require 'restify/adapter/em'
22
- Restify.adapter = Restify::Adapter::EM.new
23
- when 'em-pooled'
24
- require 'restify/adapter/pooled_em'
25
- Restify.adapter = Restify::Adapter::PooledEM.new
26
22
  when 'typhoeus'
27
23
  require 'restify/adapter/typhoeus'
28
24
  Restify.adapter = Restify::Adapter::Typhoeus.new
@@ -34,27 +30,28 @@ if ENV['ADAPTER']
34
30
  end
35
31
  end
36
32
 
33
+ require_relative 'support/opentelemetry'
37
34
  require_relative 'support/stub_server'
38
35
 
39
36
  RSpec.configure do |config|
40
37
  config.order = 'random'
41
38
 
42
39
  config.before(:suite) do
43
- ::Restify::Timeout.default_timeout = 1.0
40
+ Restify::Timeout.default_timeout = 1.0
44
41
  end
45
42
 
46
43
  config.before do |example|
47
44
  next unless (adapter = example.metadata[:adapter])
48
- next if Restify.adapter.is_a?(adapter)
45
+ next if Restify.adapter.class.ancestors.map(&:to_s).include?(adapter)
49
46
 
50
47
  skip 'Spec not enabled for current adapter'
51
48
  end
52
49
 
53
50
  config.before do
54
- Ethon.logger = ::Logging.logger[Ethon] if defined?(Ethon)
51
+ Ethon.logger = Logging.logger[Ethon] if defined?(Ethon)
55
52
 
56
- ::Logging.logger.root.level = :debug
57
- ::Logging.logger.root.add_appenders ::Logging.appenders.stdout
53
+ Logging.logger.root.level = :debug
54
+ Logging.logger.root.add_appenders Logging.appenders.stdout
58
55
  end
59
56
 
60
57
  config.warnings = true
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'opentelemetry/sdk'
4
+ require 'opentelemetry/instrumentation/ethon'
5
+
6
+ OTLE_EXPORTER = OpenTelemetry::SDK::Trace::Export::InMemorySpanExporter.new
7
+ span_processor = OpenTelemetry::SDK::Trace::Export::SimpleSpanProcessor.new(OTLE_EXPORTER)
8
+
9
+ OpenTelemetry::SDK.configure do |c|
10
+ c.error_handler = ->(exception:, message:) { raise(exception || message) }
11
+ c.logger = Logger.new($stderr, level: ENV.fetch('OTEL_LOG_LEVEL', 'fatal').to_sym)
12
+ c.add_span_processor span_processor
13
+
14
+ c.use 'OpenTelemetry::Instrumentation::Ethon'
15
+ end
16
+
17
+ RSpec.configure do |config|
18
+ config.around do |example|
19
+ OTLE_EXPORTER.reset
20
+
21
+ original_propagation = OpenTelemetry.propagation
22
+ propagator = OpenTelemetry::Trace::Propagation::TraceContext.text_map_propagator
23
+ OpenTelemetry.propagation = propagator
24
+
25
+ example.run
26
+ ensure
27
+ OpenTelemetry.propagation = original_propagation
28
+ end
29
+ end
@@ -18,6 +18,10 @@ module Stub
18
18
  # If no stub is found a special HTTP 599 error code will be returned.
19
19
  class Handler
20
20
  def call(env)
21
+ if env['REQUEST_URI'] == '/echo'
22
+ return [200, {'content-type': 'application/json'}, [env.to_json]]
23
+ end
24
+
21
25
  signature = WebMock::RequestSignature.new(
22
26
  env['REQUEST_METHOD'].downcase,
23
27
  "http://stubserver#{env['REQUEST_URI']}",