Skip to content

Commit d75c649

Browse files
orionstudtahx
authored andcommitted
support test request validation after request handling
1 parent 093d30f commit d75c649

4 files changed

Lines changed: 68 additions & 8 deletions

File tree

lib/openapi_first/test.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,9 @@ def self.report_coverage(formatter: Coverage::TerminalFormatter, **)
9595
# Returns the Rack app wrapped with silent request, response validation
9696
# You can use this if you want to track coverage via Test::Coverage, but don't want to use
9797
# the middlewares or manual request, response validation.
98-
def self.app(app, spec: nil, api: :default)
98+
def self.app(app, spec: nil, api: :default, validate_request_after_handling: false)
9999
spec ||= self[api]
100-
App.new(app, api: spec)
100+
App.new(app, api: spec, validate_request_after_handling:)
101101
end
102102

103103
def self.install

lib/openapi_first/test/app.rb

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,24 @@ module Test
1010
# A wrapper of the original app
1111
# with silent request/response validation to track requests/responses.
1212
class App < SimpleDelegator
13-
def initialize(app, api:)
13+
def initialize(app, api:, validate_request_after_handling:)
1414
super(app)
1515
@app = app
1616
@definition = Test[api]
17+
@validate_request_after_handling = validate_request_after_handling
1718
end
1819

1920
def call(env)
2021
request = Rack::Request.new(env)
21-
env[Test::REQUEST] = @definition.validate_request(request, raise_error: false)
22+
unless @validate_request_after_handling
23+
env[Test::REQUEST] = @definition.validate_request(request, raise_error: false)
24+
end
25+
2226
response = @app.call(env)
27+
if @validate_request_after_handling
28+
env[Test::REQUEST] = @definition.validate_request(request, raise_error: false)
29+
end
30+
2331
status, headers, body = response
2432
env[Test::RESPONSE] =
2533
@definition.validate_response(request, Rack::Response[status, headers, body], raise_error: false)

lib/openapi_first/test/methods.rb

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@ def self.included(base)
1212
base.include(AssertionMethod)
1313
end
1414

15-
def self.[](application_under_test = nil, api: nil)
15+
def self.[](application_under_test = nil, api: nil, validate_request_after_handling: false)
1616
mod = Module.new do
1717
def self.included(base)
1818
base.include OpenapiFirst::Test::Methods::AssertionMethod
1919
end
2020
end
21+
mod.define_method(:openapi_first_validate_request_after_handling?) { validate_request_after_handling }
2122

2223
if api
2324
mod.define_method(:openapi_first_default_api) { api }
@@ -26,7 +27,12 @@ def self.included(base)
2627
end
2728

2829
if application_under_test
29-
mod.define_method(:app) { OpenapiFirst::Test.app(application_under_test, api: openapi_first_default_api) }
30+
mod.define_method(:app) do
31+
OpenapiFirst::Test.app(
32+
application_under_test, api: openapi_first_default_api,
33+
validate_request_after_handling: openapi_first_validate_request_after_handling?
34+
)
35+
end
3036
end
3137

3238
mod

spec/test/methods_spec.rb

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,10 @@ def last_response = Rack::Response.new
9090
context 'with [arguments]' do
9191
it 'adds an app method that wraps the default API' do
9292
OpenapiFirst::Test.register('./examples/openapi.yaml')
93-
myapp = ->(_env) { Rack::Response.new('hello').finish }
93+
myapp = lambda do |env|
94+
expect(env[OpenapiFirst::Test::REQUEST]).to be_a(OpenapiFirst::ValidatedRequest)
95+
Rack::Response.new('hello').finish
96+
end
9497

9598
minitest_class = Class.new(Minitest::Test) do
9699
include OpenapiFirst::Test::Methods[myapp]
@@ -101,11 +104,34 @@ def last_response = Rack::Response.new
101104
env = Rack::MockRequest.env_for('/')
102105
expect(test_app.call(env)).to eq(Rack::Response.new('hello').finish)
103106
expect(env[OpenapiFirst::Test::REQUEST]).to be_valid
107+
expect(env[OpenapiFirst::Test::RESPONSE]).to be_a(OpenapiFirst::ValidatedResponse)
108+
end
109+
110+
it 'can run validation after handling the request, for the default API' do
111+
OpenapiFirst::Test.register('./examples/openapi.yaml')
112+
myapp = lambda do |env|
113+
expect(env[OpenapiFirst::Test::REQUEST]).to be_nil
114+
Rack::Response.new('hello').finish
115+
end
116+
117+
minitest_class = Class.new(Minitest::Test) do
118+
include OpenapiFirst::Test::Methods[myapp, validate_request_after_handling: true]
119+
end
120+
121+
expect(minitest_class.included_modules).to include(OpenapiFirst::Test::MinitestHelpers)
122+
test_app = minitest_class.new(1).app
123+
env = Rack::MockRequest.env_for('/')
124+
expect(test_app.call(env)).to eq(Rack::Response.new('hello').finish)
125+
expect(env[OpenapiFirst::Test::REQUEST]).to be_valid
126+
expect(env[OpenapiFirst::Test::RESPONSE]).to be_a(OpenapiFirst::ValidatedResponse)
104127
end
105128

106129
it 'adds an app method that wraps the app for a specific API' do
107130
OpenapiFirst::Test.register('./examples/openapi.yaml', as: :v1)
108-
myapp = ->(_env) { Rack::Response.new('hello').finish }
131+
myapp = lambda do |env|
132+
expect(env[OpenapiFirst::Test::REQUEST]).to be_a(OpenapiFirst::ValidatedRequest)
133+
Rack::Response.new('hello').finish
134+
end
109135

110136
minitest_class = Class.new(Minitest::Test) do
111137
include OpenapiFirst::Test::Methods[myapp, api: :v1]
@@ -116,6 +142,26 @@ def last_response = Rack::Response.new
116142
env = Rack::MockRequest.env_for('/')
117143
expect(test_app.call(env)).to eq(Rack::Response.new('hello').finish)
118144
expect(env[OpenapiFirst::Test::REQUEST]).to be_valid
145+
expect(env[OpenapiFirst::Test::RESPONSE]).to be_a(OpenapiFirst::ValidatedResponse)
146+
end
147+
148+
it 'can run validation after handling the request, for a specific API' do
149+
OpenapiFirst::Test.register('./examples/openapi.yaml', as: :v1)
150+
myapp = lambda do |env|
151+
expect(env[OpenapiFirst::Test::REQUEST]).to be_nil
152+
Rack::Response.new('hello').finish
153+
end
154+
155+
minitest_class = Class.new(Minitest::Test) do
156+
include OpenapiFirst::Test::Methods[myapp, api: :v1, validate_request_after_handling: true]
157+
end
158+
159+
expect(minitest_class.included_modules).to include(OpenapiFirst::Test::MinitestHelpers)
160+
test_app = minitest_class.new(1).app
161+
env = Rack::MockRequest.env_for('/')
162+
expect(test_app.call(env)).to eq(Rack::Response.new('hello').finish)
163+
expect(env[OpenapiFirst::Test::REQUEST]).to be_valid
164+
expect(env[OpenapiFirst::Test::RESPONSE]).to be_a(OpenapiFirst::ValidatedResponse)
119165
end
120166

121167
it 'adds an assert_api_conform method that targets the specified API' do

0 commit comments

Comments
 (0)