Skip to content

Commit 9ed469e

Browse files
authored
Merge pull request #436 from ahx/test-track-after-handle
Test: Track request after calling the app
2 parents 573efd6 + a03336a commit 9ed469e

5 files changed

Lines changed: 85 additions & 10 deletions

File tree

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,21 @@
22

33
## Unreleased
44

5+
### Changed
6+
- Changed OpenapiFirst::Test to track the request _after_ the app has handled the request. See [PR #434](https://github.com/ahx/openapi_first/pull/434). You can restore the old behavior with
7+
```ruby
8+
include OpenapiFirst::Test::Methods[MyApp, validate_request_before_handling: true]
9+
```
10+
11+
### Added
12+
13+
- Added support for a static `path_prefix` value to be set on the creation of a Definition. See [PR #432](https://github.com/ahx/openapi_first/pull/432):
14+
```ruby
15+
OpenapiFirst.configure do |config|
16+
config.register('openapi/openapi.yaml' path_prefix: '/weather')
17+
end
18+
```
19+
520
## 3.1.1
621

722
- Changed: Return uniqe errors in default error responses

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_before_handling: false)
9999
spec ||= self[api]
100-
App.new(app, api: spec)
100+
App.new(app, api: spec, validate_request_before_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_before_handling:)
1414
super(app)
1515
@app = app
1616
@definition = Test[api]
17+
@validate_request_before_handling = validate_request_before_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+
if @validate_request_before_handling
23+
env[Test::REQUEST] = @definition.validate_request(request, raise_error: false)
24+
end
25+
2226
response = @app.call(env)
27+
unless @validate_request_before_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_before_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_before_handling?) { validate_request_before_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_before_handling: openapi_first_validate_request_before_handling?
34+
)
35+
end
3036
end
3137

3238
mod

spec/test/methods_spec.rb

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,25 @@ def last_response = Rack::Response.new
2424
end.to raise_error(OpenapiFirst::Error)
2525
end
2626

27+
it 'runs request validation after handling the request' do
28+
OpenapiFirst::Test.register('./examples/openapi.yaml')
29+
myapp = lambda do |env|
30+
expect(env[OpenapiFirst::Test::REQUEST]).to be_nil
31+
Rack::Response.new('hello').finish
32+
end
33+
34+
minitest_class = Class.new(Minitest::Test) do
35+
include OpenapiFirst::Test::Methods[myapp]
36+
end
37+
38+
expect(minitest_class.included_modules).to include(OpenapiFirst::Test::MinitestHelpers)
39+
test_app = minitest_class.new(1).app
40+
env = Rack::MockRequest.env_for('/')
41+
expect(test_app.call(env)).to eq(Rack::Response.new('hello').finish)
42+
expect(env[OpenapiFirst::Test::REQUEST]).to be_valid
43+
expect(env[OpenapiFirst::Test::RESPONSE]).to be_a(OpenapiFirst::ValidatedResponse)
44+
end
45+
2746
context 'with RSpec' do
2847
context 'with metadata', api: :v1 do
2948
include OpenapiFirst::Test::Methods
@@ -88,24 +107,31 @@ def last_response = Rack::Response.new
88107
end
89108

90109
context 'with [arguments]' do
91-
it 'adds an app method that wraps the default API' do
110+
it 'can run validation before handling the request' do
92111
OpenapiFirst::Test.register('./examples/openapi.yaml')
93-
myapp = ->(_env) { Rack::Response.new('hello').finish }
112+
myapp = lambda do |env|
113+
expect(env[OpenapiFirst::Test::REQUEST]).to be_a(OpenapiFirst::ValidatedRequest)
114+
Rack::Response.new('hello').finish
115+
end
94116

95117
minitest_class = Class.new(Minitest::Test) do
96-
include OpenapiFirst::Test::Methods[myapp]
118+
include OpenapiFirst::Test::Methods[myapp, validate_request_before_handling: true]
97119
end
98120

99121
expect(minitest_class.included_modules).to include(OpenapiFirst::Test::MinitestHelpers)
100122
test_app = minitest_class.new(1).app
101123
env = Rack::MockRequest.env_for('/')
102124
expect(test_app.call(env)).to eq(Rack::Response.new('hello').finish)
103125
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_nil
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 before 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_a(OpenapiFirst::ValidatedRequest)
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_before_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)