Skip to content

Commit 5c47fd3

Browse files
authored
Merge pull request #382 from ahx/observe-rack-urlmap
Support observice proc like objects with Test.observe
2 parents e64dafc + 43f0357 commit 5c47fd3

File tree

4 files changed

+65
-2
lines changed

4 files changed

+65
-2
lines changed

CHANGELOG.md

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

33
## Unreleased
44

5+
- OpenapiFirst::Test.observe now works with `Rack::URLMap` (returned by `Rack::Builder.app`) and probably all objects that respond to `.call`
6+
57
## 2.10.1
68

79
- Don't try to track coverage for skipped requests

lib/openapi_first/test/observe.rb

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,23 @@ module Observed; end
1010
# Inject silent request/response validation to observe rack apps during testing
1111
module Observe
1212
def self.observe(app, api: :default)
13+
definition = OpenapiFirst::Test[api]
14+
mod = OpenapiFirst::Test::Callable[definition]
15+
16+
if app.respond_to?(:call)
17+
return if app.singleton_class.include?(Observed)
18+
19+
app.singleton_class.prepend(mod)
20+
app.singleton_class.include(Observed)
21+
return
22+
end
23+
1324
unless app.instance_methods.include?(:call)
1425
raise ObserveError, "Don't know how to observe #{app}, because it has no call instance method."
1526
end
1627

1728
return if app.include?(Observed)
1829

19-
definition = OpenapiFirst::Test[api]
20-
mod = OpenapiFirst::Test::Callable[definition]
2130
app.prepend(mod)
2231
app.include(Observed)
2332
end
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# frozen_string_literal: true
2+
3+
module OpenapiFirst
4+
module Test
5+
# Middleware that observes requests and responses. This is used to trigger hooks added by OpenapiFirst::Tests.
6+
class ObserverMiddleware
7+
def initialize(app, options = {})
8+
@app = app
9+
@definition = OpenapiFirst::Test[options.fetch(:api, :default)]
10+
end
11+
12+
def call(env)
13+
request = Rack::Request.new(env)
14+
15+
@definition.validate_request(request, raise_error: false)
16+
response = @app.call(env)
17+
status, headers, body = response
18+
@definition.validate_response(request, Rack::Response[status, headers, body], raise_error: false)
19+
response
20+
end
21+
end
22+
end
23+
end

spec/test/observe_spec.rb

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,33 @@ def call(_env)
8585

8686
it_behaves_like 'an observed app'
8787
end
88+
89+
context 'with a proc' do
90+
let(:app) do
91+
->(_env) { Rack::Response.new.finish }
92+
end
93+
94+
it_behaves_like 'an observed app'
95+
96+
it 'injects request/response validation only once' do
97+
2.times { described_class.observe(app) }
98+
99+
expect(definition).to receive(:validate_request).once
100+
expect(definition).to receive(:validate_response).once
101+
102+
callable.call({})
103+
end
104+
end
105+
106+
context 'with Rack::Builder.app' do
107+
let(:app) do
108+
Rack::Builder.app do
109+
map '/' do
110+
run ->(_env) { Rack::Response.new.finish }
111+
end
112+
end
113+
end
114+
115+
it_behaves_like 'an observed app'
116+
end
88117
end

0 commit comments

Comments
 (0)