Skip to content

Commit 8689174

Browse files
committed
Add ignore_response_error and ignore_request_error
to configure which request/response errors should not raise an error during testing.
1 parent 21fd731 commit 8689174

6 files changed

Lines changed: 101 additions & 73 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
- Added `OpenapiFirst::ValidatedRequest#unknown?` and `OpenapiFirst::ValidatedResponse#unknown?`
2121

22+
- Added `OpenapiFirst::Test::Configuration#ignore_response_error` and `OpenapiFirst::Test::Configuration#ignore_request_error` to configure which request/response errors should not raise an error during testing.
23+
2224
## 3.1.1
2325

2426
- Changed: Return uniqe errors in default error responses

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,23 @@ Here is how to set it up:
231231
232232
### Configure test coverage
233233
234+
You can ignore errors for certain requests/responses:
235+
236+
```ruby
237+
OpenapiFirst::Test.setup do |test|
238+
test.ignore_request_error do |validated_request|
239+
# Ignore unknown requests on certain paths
240+
validated_request.path.start_with?('/api/v1') && validated_request.unknown?
241+
end
242+
243+
test.ignore_response_error do |validated_response, rack_request|
244+
# Ignore invalid response bodies on certain paths
245+
validated_request.path.start_with?('/api/legacy/stuff') && validated_request.error.type == :invalid_body
246+
end
247+
end
248+
```
249+
250+
234251
OpenapiFirst::Test raises an error when a response status is not defined except for 404 and 500. You can change this:
235252
236253
```ruby

lib/openapi_first/test.rb

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def self.registered?(oad)
4040
end
4141

4242
# Sets up OpenAPI test coverage and OAD registration.
43-
# @yieldparam [OpenapiFirst::Test::Configuration] configuration A configuration to setup test integration
43+
# @yield [OpenapiFirst::Test::Configuration] configuration A configuration to setup test integration
4444
def self.setup
4545
install
4646
yield configuration if block_given?
@@ -154,20 +154,16 @@ def unknown_parameters_message(unknown_parameters, validated_request)
154154

155155
def raise_request_error?(validated_request)
156156
return false if validated_request.valid?
157-
return false unless configuration.raise_error_for_request.call(validated_request)
158-
return false if validated_request.known?
159157

160-
!configuration.ignore_unknown_requests
158+
configuration.raise_request_error?(validated_request)
161159
end
162160

163161
def many?(array) = array.length > 1
164162

165163
def raise_response_error?(validated_response, rack_request)
166164
return false if validated_response.valid?
167-
return false unless configuration.response_raise_error
168-
return false unless configuration.raise_error_for_response.call(validated_response, rack_request)
169165

170-
!configuration.ignore_response?(validated_response)
166+
configuration.raise_response_error?(validated_response, rack_request)
171167
end
172168
end
173169
end

lib/openapi_first/test/configuration.rb

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ def initialize
1515
@ignore_unknown_response_status = false
1616
@report_coverage = true
1717
@ignore_unknown_requests = false
18-
@raise_error_for_request = ->(_validated_request) { true }
19-
@raise_error_for_response = ->(_validated_response, _rack_request) { true }
18+
@ignore_request_error = nil
19+
@ignore_response_error = nil
2020
end
2121

2222
# Register OADs, but don't load them just yet
@@ -32,8 +32,7 @@ def observe(app, api: :default)
3232
end
3333

3434
attr_accessor :coverage_formatter_options, :coverage_formatter, :response_raise_error,
35-
:ignore_unknown_requests, :ignore_unknown_response_status, :minimum_coverage,
36-
:raise_error_for_request, :raise_error_for_response
35+
:ignore_unknown_requests, :ignore_unknown_response_status, :minimum_coverage
3736
attr_reader :report_coverage, :ignored_unknown_status
3837

3938
# Set ignored unknown status codes.
@@ -53,6 +52,23 @@ def report_coverage=(value)
5352
@report_coverage = value
5453
end
5554

55+
# Ignore certain errors for certain requests
56+
# @param block A Proc that will be called with [OpenapiFirst::ValidatedRequest]
57+
def ignore_request_error(&block)
58+
raise ArgumentError, 'You have to pass a block' unless block_given?
59+
60+
@ignore_request_error = block
61+
end
62+
63+
# Ignore certain errors for certain responses
64+
# @param block A Proc that will be called with [OpenapiFirst::ValidatedResponse, Rack::Request]
65+
def ignore_response_error(&block)
66+
raise ArgumentError, 'You have to pass a block' unless block_given?
67+
68+
@ignore_response_error = block
69+
end
70+
71+
# @param block A Proc that will be called with [OpenapiFirst::ValidatedResponse, Rack::Request]
5672
def skip_response_coverage(&block)
5773
return @skip_response_coverage unless block_given?
5874

@@ -66,12 +82,22 @@ def skip_coverage(&block)
6682
end
6783

6884
alias ignore_unknown_response_status? ignore_unknown_response_status
85+
alias ignore_unknown_requests? ignore_unknown_requests
86+
87+
def raise_request_error?(validated_request)
88+
return false if @ignore_request_error&.call(validated_request)
89+
return false if ignore_unknown_requests? && validated_request.unknown?
90+
91+
validated_request.unknown?
92+
end
6993

70-
def ignore_response?(validated_response)
71-
return false if validated_response.known?
72-
return true if ignored_unknown_status.include?(validated_response.status)
94+
def raise_response_error?(validated_response, rack_request)
95+
return false if @ignore_response_error&.call(validated_response, rack_request)
96+
return false if response_raise_error == false
97+
return false if ignored_unknown_status.include?(validated_response.status)
98+
return false if ignore_unknown_response_status? && validated_response.error.type == :response_status_not_found
7399

74-
ignore_unknown_response_status? && validated_response.error.type == :response_status_not_found
100+
true
75101
end
76102
end
77103
end

spec/test/configuration_spec.rb

Lines changed: 22 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -20,61 +20,48 @@
2020
end
2121
end
2222

23-
describe 'raise_error_for_request' do
24-
it 'has a default lambda that returns true always' do
25-
expect(configuration.raise_error_for_request).to be_a(Proc)
26-
expect(configuration.raise_error_for_request.call(nil)).to eq(true)
27-
end
28-
end
29-
30-
describe 'raise_error_for_response' do
31-
it 'has a default lambda that returns true always' do
32-
expect(configuration.raise_error_for_response).to be_a(Proc)
33-
expect(configuration.raise_error_for_response.call(nil, nil)).to eq(true)
34-
end
35-
end
36-
37-
describe '#ignore_response?' do
38-
let(:valid_response) { double(valid?: true, known?: true, status: 302) }
39-
let(:invalid_response) { double(valid?: false, known?: true, status: 302) }
40-
let(:unknown_response_status) { double(valid?: false, known?: false, status: 302, error: OpenapiFirst::Failure.new(:response_status_not_found)) }
41-
42-
it 'returns false by default for a valid responses' do
43-
expect(configuration.ignore_response?(valid_response)).to eq(false)
23+
describe '#raise_response_error?' do
24+
let(:valid_response) { double(valid?: true, unknown?: false, status: 302) }
25+
let(:invalid_response) { double(valid?: false, unknown?: false, status: 302) }
26+
let(:unknown_response_status) { double(valid?: false, unknown?: true, status: 302, error: OpenapiFirst::Failure.new(:response_status_not_found)) }
27+
let(:rack_request) { Rack::Request.new({}) }
28+
29+
it 'returns true by default for valid responses' do
30+
expect(configuration.raise_response_error?(valid_response, rack_request)).to eq(true)
4431
end
4532

46-
it 'returns false by default for an invalid responses' do
47-
expect(configuration.ignore_response?(invalid_response)).to eq(false)
33+
it 'returns true by default for invalid responses' do
34+
expect(configuration.raise_response_error?(invalid_response, rack_request)).to eq(true)
4835
end
4936

50-
it 'returns false by default for an unkonwn responses' do
51-
expect(configuration.ignore_response?(unknown_response_status)).to eq(false)
37+
it 'returns true by default for unkonwn responses' do
38+
expect(configuration.raise_response_error?(unknown_response_status, rack_request)).to eq(true)
5239
end
5340

5441
context 'when status is ignored' do
5542
before { configuration.ignored_unknown_status << unknown_response_status.status }
5643

57-
it 'returns true for an unknown response with that status' do
58-
expect(configuration.ignore_response?(unknown_response_status)).to eq(true)
44+
it 'returns false for an unknown response with that status' do
45+
expect(configuration.raise_response_error?(unknown_response_status, rack_request)).to eq(false)
5946
end
6047

61-
it 'returns false for an unknown response with another status' do
62-
unknown_response_status = double(valid?: false, known?: false, status: 409)
63-
expect(configuration.ignore_response?(unknown_response_status)).to eq(false)
48+
it 'returns true for an unknown response with another status' do
49+
unknown_response_status = double(valid?: false, unknown?: true, status: 409, error: OpenapiFirst::Failure.new(:response_status_not_found))
50+
expect(configuration.raise_response_error?(unknown_response_status, rack_request)).to eq(true)
6451
end
6552
end
6653

6754
context 'when all unknown response status are ignored' do
6855
before { configuration.ignore_unknown_response_status = true }
6956

70-
it 'returns true for any unknown response status' do
71-
expect(configuration.ignore_response?(unknown_response_status)).to eq(true)
57+
it 'returns false for any unknown response status' do
58+
expect(configuration.raise_response_error?(unknown_response_status, rack_request)).to eq(false)
7259
end
7360

74-
it 'returns false for an unknown response with a known status' do
75-
unknown_response_content_type = double(valid?: false, known?: false, status: 302, error: OpenapiFirst::Failure.new(:response_content_type_not_found))
61+
it 'returns true for an unknown response with a known status' do
62+
unknown_response_content_type = double(valid?: false, unknown?: true, status: 302, error: OpenapiFirst::Failure.new(:response_content_type_not_found))
7663

77-
expect(configuration.ignore_response?(unknown_response_content_type)).to eq(false)
64+
expect(configuration.raise_response_error?(unknown_response_content_type, rack_request)).to eq(true)
7865
end
7966
end
8067
end

spec/test_spec.rb

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -425,9 +425,9 @@ def call(_env)
425425
end.to raise_error(OpenapiFirst::RequestInvalidError)
426426
end
427427

428-
it 'does not raise an error for an invalid request when raises_error_for_request returns false' do
428+
it 'does not raise an error for an invalid request when request is ignored' do
429429
described_class.setup do |test|
430-
test.raise_error_for_request = ->(_validated_request) { false }
430+
test.ignore_request_error { true }
431431
end
432432

433433
config = OpenapiFirst.configuration
@@ -460,9 +460,9 @@ def call(_env)
460460
end.to raise_error(OpenapiFirst::ResponseInvalidError)
461461
end
462462

463-
it 'does not raise an error for an invalid response when raises_error_for_response returns false' do
463+
it 'does not raise an error for an invalid response when response error is ignored' do
464464
described_class.setup do |test|
465-
test.raise_error_for_response = ->(_validated_response, _rack_request) { false }
465+
test.ignore_response_error { true }
466466
end
467467

468468
config = OpenapiFirst.configuration
@@ -595,22 +595,22 @@ def call(_env)
595595
end.to raise_error(OpenapiFirst::NotFoundError)
596596
end
597597

598-
context 'with raise_error_for_request returning false' do
598+
context 'with ignore_request_error returning true' do
599599
before(:each) do
600600
described_class.uninstall
601-
described_class.setup do |test|
602-
test.register(definition)
603-
test.ignore_unknown_requests = false
604-
test.report_coverage = false
605-
end
606601
end
607602

608603
it 'does not raise an error' do
609604
called = false
610-
described_class.configuration.raise_error_for_request = lambda do |validated_request|
611-
called = true
612-
expect(validated_request).to be_a(OpenapiFirst::ValidatedRequest)
613-
false
605+
described_class.setup do |test|
606+
test.register(definition)
607+
test.ignore_unknown_requests = false
608+
test.report_coverage = false
609+
test.ignore_request_error do |validated_request|
610+
called = true
611+
expect(validated_request).to be_a(OpenapiFirst::ValidatedRequest)
612+
true
613+
end
614614
end
615615

616616
expect do
@@ -736,21 +736,21 @@ def call(_env)
736736
end.to raise_error(OpenapiFirst::ResponseInvalidError)
737737
end
738738

739-
context 'with raise_error_for_response returning false' do
739+
context 'with ignore_response_error? returning true' do
740740
before(:each) do
741741
described_class.uninstall
742-
described_class.setup do |test|
743-
test.register(definition)
744-
end
745742
end
746743

747744
it 'does not raise an error' do
748745
called = false
749-
described_class.configuration.raise_error_for_response = lambda do |validated_response, rack_request|
750-
called = true
751-
expect(validated_response).to be_a(OpenapiFirst::ValidatedResponse)
752-
expect(rack_request).to be_a(Rack::Request)
753-
false
746+
described_class.setup do |test|
747+
test.register(definition)
748+
test.ignore_response_error do |validated_response, rack_request|
749+
called = true
750+
expect(validated_response).to be_a(OpenapiFirst::ValidatedResponse)
751+
expect(rack_request).to be_a(Rack::Request)
752+
true
753+
end
754754
end
755755

756756
expect do

0 commit comments

Comments
 (0)