Skip to content

Commit 409514d

Browse files
committed
Pick up :api metadata when using RSpec to find the OAD
1 parent ce90faf commit 409514d

6 files changed

Lines changed: 125 additions & 12 deletions

File tree

examples/openapi.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ tags:
1212
paths:
1313
/:
1414
get:
15-
operationId: things#index
15+
operationId: example#root
1616
summary: Get metadata from the root of the API
1717
tags: ["Metadata"]
1818
responses:

examples/rack_handler.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
not_found = ->(_request) { [404, {}, []] }
1212
handlers = {
13-
'things#index' => lambda do |_request|
13+
'example#root' => lambda do |_request|
1414
[200, { Rack::CONTENT_TYPE => 'application/json' }, ['{"hello": "world"}']]
1515
end
1616
}

lib/openapi_first/test/methods.rb

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,54 @@ module OpenapiFirst
77
module Test
88
# Methods to use in integration tests
99
module Methods
10-
def self.[](application_under_test = nil, api: :default)
10+
def self.included(base)
11+
base.include(DefaultApiMethod)
12+
base.include(AssertionMethod)
13+
end
14+
15+
def self.[](application_under_test = nil, api: nil)
1116
mod = Module.new do
1217
def self.included(base)
13-
OpenapiFirst::Test::Methods.included(base)
18+
base.include OpenapiFirst::Test::Methods::AssertionMethod
1419
end
1520
end
16-
mod.define_method(:app) { OpenapiFirst::Test.app(application_under_test, api:) } if application_under_test
21+
22+
if api
23+
mod.define_method(:openapi_first_default_api) { api }
24+
else
25+
mod.include(DefaultApiMethod)
26+
end
27+
28+
if application_under_test
29+
mod.define_method(:app) { OpenapiFirst::Test.app(application_under_test, api: openapi_first_default_api) }
30+
end
31+
1732
mod
1833
end
1934

20-
def self.included(base)
21-
if Test.minitest?(base)
22-
base.include(OpenapiFirst::Test::MinitestHelpers)
23-
else
24-
base.include(OpenapiFirst::Test::PlainHelpers)
35+
# Default methods
36+
module DefaultApiMethod
37+
# This is the default api that is used by assert_api_conform
38+
# :default is the default name that is used if you don't pass an `api:` option to `OpenapiFirst::Test.register`
39+
# This is overwritten if you pass an `api:` option to `include OpenapiFirst::Test::Methods[…]`
40+
def openapi_first_default_api
41+
klass = self.class
42+
if klass.respond_to?(:metadata) && klass.metadata[:api]
43+
klass.metadata[:api]
44+
else
45+
:default
46+
end
47+
end
48+
end
49+
50+
# @visibility private
51+
module AssertionMethod
52+
def self.included(base)
53+
if Test.minitest?(base)
54+
base.include(OpenapiFirst::Test::MinitestHelpers)
55+
else
56+
base.include(OpenapiFirst::Test::PlainHelpers)
57+
end
2558
end
2659
end
2760
end

lib/openapi_first/test/minitest_helpers.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module Test
55
# Assertion methods for Minitest
66
module MinitestHelpers
77
# :nocov:
8-
def assert_api_conform(status: nil, api: :default)
8+
def assert_api_conform(status: nil, api: openapi_first_default_api)
99
api = OpenapiFirst::Test[api]
1010
request = respond_to?(:last_request) ? last_request : @request
1111
response = respond_to?(:last_response) ? last_response : @response

lib/openapi_first/test/plain_helpers.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module Test
55
# Assertion methods to use when no known test framework was found
66
# These methods just raise an exception if an error was found
77
module PlainHelpers
8-
def assert_api_conform(status: nil, api: :default)
8+
def assert_api_conform(status: nil, api: openapi_first_default_api)
99
api = OpenapiFirst::Test[api]
1010
# :nocov:
1111
request = respond_to?(:last_request) ? last_request : @request

spec/test/methods_spec.rb

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

27+
context 'with RSpec' do
28+
let(:app) do
29+
lambda do |_|
30+
res = Rack::Response.new(JSON.generate(hello: 'there'))
31+
res.content_type = 'application/json'
32+
res.finish
33+
end
34+
end
35+
36+
context 'with metadata', api: :v1 do
37+
include OpenapiFirst::Test::Methods
38+
include Rack::Test::Methods
39+
40+
it 'targets that api when calling assert_api_conform' do
41+
expect do
42+
assert_api_conform(status: 200)
43+
end.to raise_error(OpenapiFirst::Test::NotRegisteredError) do |ex|
44+
expect(ex.message).to start_with("API description ':v1' not found.")
45+
end
46+
end
47+
end
48+
49+
context 'with an [api:] option', api: :v2 do
50+
include OpenapiFirst::Test::Methods[api: :v1]
51+
52+
it 'targets the api from the argument when calling assert_api_conform' do
53+
expect do
54+
assert_api_conform(status: 200)
55+
end.to raise_error(OpenapiFirst::Test::NotRegisteredError) do |ex|
56+
expect(ex.message).to start_with("API description ':v1' not found.")
57+
end
58+
end
59+
end
60+
61+
context 'with an [Application] argument and metadata', api: :v2 do
62+
include OpenapiFirst::Test::Methods[->(_) { Rack::Response.new('hey').finish }]
63+
include Rack::Test::Methods
64+
65+
it 'targets that api when calling the app' do
66+
OpenapiFirst::Test.register('./examples/openapi.yaml', as: :v2)
67+
68+
get('/')
69+
70+
expect(last_request.env[OpenapiFirst::REQUEST].operation_id).to eq('example#root')
71+
end
72+
end
73+
end
74+
2775
context 'with Minitest' do
2876
it 'includes MinitestHelpers when included' do
2977
minitest_class = Class.new(Minitest::Test) do
@@ -78,6 +126,38 @@ def last_response = Rack::Response.new
78126
expect(env[OpenapiFirst::REQUEST]).to be_valid
79127
end
80128

129+
it 'adds an assert_api_conform method that targets the specified API' do
130+
OpenapiFirst::Test.register('./examples/openapi.yaml', as: :v1)
131+
test_class = Class.new do
132+
include OpenapiFirst::Test::Methods[api: :v1]
133+
134+
def last_request = Rack::Request.new(Rack::MockRequest.env_for('/'))
135+
def last_response = Rack::Response.new
136+
end
137+
138+
expect(test_class.new.openapi_first_default_api).to eq(:v1)
139+
140+
expect do
141+
test_class.new.assert_api_conform(status: 444)
142+
end.to raise_error(OpenapiFirst::Error)
143+
end
144+
145+
it 'adds an assert_api_conform method that still can target another API' do
146+
OpenapiFirst::Test.register('./examples/openapi.yaml', as: :v1)
147+
test_class = Class.new do
148+
include OpenapiFirst::Test::Methods[api: :v1]
149+
150+
def last_request = Rack::Request.new(Rack::MockRequest.env_for('/'))
151+
def last_response = Rack::Response.new
152+
end
153+
154+
expect do
155+
test_class.new.assert_api_conform(status: 444, api: :other)
156+
end.to raise_error(OpenapiFirst::Test::NotRegisteredError) do |ex|
157+
expect(ex.message).to start_with("API description ':other' not found.")
158+
end
159+
end
160+
81161
it 'does not add an app method if app is nil' do
82162
OpenapiFirst::Test.register('./examples/openapi.yaml', as: :v1)
83163

0 commit comments

Comments
 (0)