mirror of
https://github.com/ditkrg/rswag.git
synced 2026-01-25 15:22:56 +00:00
Renames and fixes specs in api and specs project to prefix OpenApi module. Gem name to open_api-rswag
This commit is contained in:
@@ -1,75 +1,77 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rswag/specs/configuration'
|
||||
require 'open_api/rswag/specs/configuration'
|
||||
|
||||
module Rswag
|
||||
module Specs
|
||||
describe Configuration do
|
||||
subject { described_class.new(rspec_config) }
|
||||
module OpenApi
|
||||
module Rswag
|
||||
module Specs
|
||||
describe Configuration do
|
||||
subject { described_class.new(rspec_config) }
|
||||
|
||||
let(:rspec_config) { OpenStruct.new(swagger_root: swagger_root, swagger_docs: swagger_docs) }
|
||||
let(:swagger_root) { 'foobar' }
|
||||
let(:swagger_docs) do
|
||||
{
|
||||
'v1/swagger.json' => { info: { title: 'v1' } },
|
||||
'v2/swagger.json' => { info: { title: 'v2' } }
|
||||
}
|
||||
end
|
||||
|
||||
describe '#swagger_root' do
|
||||
let(:response) { subject.swagger_root }
|
||||
|
||||
context 'provided in rspec config' do
|
||||
it { expect(response).to eq('foobar') }
|
||||
let(:rspec_config) { OpenStruct.new(swagger_root: swagger_root, swagger_docs: swagger_docs) }
|
||||
let(:swagger_root) { 'foobar' }
|
||||
let(:swagger_docs) do
|
||||
{
|
||||
'v1/swagger.json' => { info: { title: 'v1' } },
|
||||
'v2/swagger.json' => { info: { title: 'v2' } }
|
||||
}
|
||||
end
|
||||
|
||||
context 'not provided' do
|
||||
let(:swagger_root) { nil }
|
||||
it { expect { response }.to raise_error ConfigurationError }
|
||||
end
|
||||
end
|
||||
describe '#swagger_root' do
|
||||
let(:response) { subject.swagger_root }
|
||||
|
||||
describe '#swagger_docs' do
|
||||
let(:response) { subject.swagger_docs }
|
||||
context 'provided in rspec config' do
|
||||
it { expect(response).to eq('foobar') }
|
||||
end
|
||||
|
||||
context 'provided in rspec config' do
|
||||
it { expect(response).to be_an_instance_of(Hash) }
|
||||
end
|
||||
|
||||
context 'not provided' do
|
||||
let(:swagger_docs) { nil }
|
||||
it { expect { response }.to raise_error ConfigurationError }
|
||||
end
|
||||
|
||||
context 'provided but empty' do
|
||||
let(:swagger_docs) { {} }
|
||||
it { expect { response }.to raise_error ConfigurationError }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#get_swagger_doc(tag=nil)' do
|
||||
let(:swagger_doc) { subject.get_swagger_doc(tag) }
|
||||
|
||||
context 'no tag provided' do
|
||||
let(:tag) { nil }
|
||||
|
||||
it 'returns the first doc in rspec config' do
|
||||
expect(swagger_doc).to eq(info: { title: 'v1' })
|
||||
context 'not provided' do
|
||||
let(:swagger_root) { nil }
|
||||
it { expect { response }.to raise_error ConfigurationError }
|
||||
end
|
||||
end
|
||||
|
||||
context 'tag provided' do
|
||||
context 'matching doc' do
|
||||
let(:tag) { 'v2/swagger.json' }
|
||||
describe '#swagger_docs' do
|
||||
let(:response) { subject.swagger_docs }
|
||||
|
||||
it 'returns the matching doc in rspec config' do
|
||||
expect(swagger_doc).to eq(info: { title: 'v2' })
|
||||
context 'provided in rspec config' do
|
||||
it { expect(response).to be_an_instance_of(Hash) }
|
||||
end
|
||||
|
||||
context 'not provided' do
|
||||
let(:swagger_docs) { nil }
|
||||
it { expect { response }.to raise_error ConfigurationError }
|
||||
end
|
||||
|
||||
context 'provided but empty' do
|
||||
let(:swagger_docs) { {} }
|
||||
it { expect { response }.to raise_error ConfigurationError }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#get_swagger_doc(tag=nil)' do
|
||||
let(:swagger_doc) { subject.get_swagger_doc(tag) }
|
||||
|
||||
context 'no tag provided' do
|
||||
let(:tag) { nil }
|
||||
|
||||
it 'returns the first doc in rspec config' do
|
||||
expect(swagger_doc).to eq(info: { title: 'v1' })
|
||||
end
|
||||
end
|
||||
|
||||
context 'no matching doc' do
|
||||
let(:tag) { 'foobar' }
|
||||
it { expect { swagger_doc }.to raise_error ConfigurationError }
|
||||
context 'tag provided' do
|
||||
context 'matching doc' do
|
||||
let(:tag) { 'v2/swagger.json' }
|
||||
|
||||
it 'returns the matching doc in rspec config' do
|
||||
expect(swagger_doc).to eq(info: { title: 'v2' })
|
||||
end
|
||||
end
|
||||
|
||||
context 'no matching doc' do
|
||||
let(:tag) { 'foobar' }
|
||||
it { expect { swagger_doc }.to raise_error ConfigurationError }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,215 +1,217 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rswag/specs/example_group_helpers'
|
||||
require 'open_api/rswag/specs/example_group_helpers'
|
||||
|
||||
module Rswag
|
||||
module Specs
|
||||
describe ExampleGroupHelpers do
|
||||
subject { double('example_group') }
|
||||
module OpenApi
|
||||
module Rswag
|
||||
module Specs
|
||||
describe ExampleGroupHelpers do
|
||||
subject { double('example_group') }
|
||||
|
||||
before do
|
||||
subject.extend ExampleGroupHelpers
|
||||
allow(subject).to receive(:describe)
|
||||
allow(subject).to receive(:context)
|
||||
allow(subject).to receive(:metadata).and_return(api_metadata)
|
||||
end
|
||||
let(:api_metadata) { {} }
|
||||
|
||||
describe '#path(path)' do
|
||||
before { subject.path('/blogs') }
|
||||
|
||||
it "delegates to 'describe' with 'path' metadata" do
|
||||
expect(subject).to have_received(:describe).with(
|
||||
'/blogs', path_item: { template: '/blogs' }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#get|post|patch|put|delete|head(verb, summary)' do
|
||||
before { subject.post('Creates a blog') }
|
||||
|
||||
it "delegates to 'describe' with 'operation' metadata" do
|
||||
expect(subject).to have_received(:describe).with(
|
||||
:post, operation: { verb: :post, summary: 'Creates a blog' }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#tags|description|operationId|consumes|produces|schemes|deprecated(value)' do
|
||||
before do
|
||||
subject.tags('Blogs', 'Admin')
|
||||
subject.description('Some description')
|
||||
subject.operationId('createBlog')
|
||||
subject.consumes('application/json', 'application/xml')
|
||||
subject.produces('application/json', 'application/xml')
|
||||
subject.schemes('http', 'https')
|
||||
subject.deprecated(true)
|
||||
subject.extend ExampleGroupHelpers
|
||||
allow(subject).to receive(:describe)
|
||||
allow(subject).to receive(:context)
|
||||
allow(subject).to receive(:metadata).and_return(api_metadata)
|
||||
end
|
||||
let(:api_metadata) { { operation: {} } }
|
||||
let(:api_metadata) { {} }
|
||||
|
||||
it "adds to the 'operation' metadata" do
|
||||
expect(api_metadata[:operation]).to match(
|
||||
tags: %w[Blogs Admin],
|
||||
description: 'Some description',
|
||||
operationId: 'createBlog',
|
||||
consumes: ['application/json', 'application/xml'],
|
||||
produces: ['application/json', 'application/xml'],
|
||||
schemes: %w[http https],
|
||||
deprecated: true
|
||||
)
|
||||
end
|
||||
end
|
||||
describe '#path(path)' do
|
||||
before { subject.path('/blogs') }
|
||||
|
||||
describe '#tags|description|operationId|consumes|produces|schemes|deprecated|security(value)' do
|
||||
before do
|
||||
subject.tags('Blogs', 'Admin')
|
||||
subject.description('Some description')
|
||||
subject.operationId('createBlog')
|
||||
subject.consumes('application/json', 'application/xml')
|
||||
subject.produces('application/json', 'application/xml')
|
||||
subject.schemes('http', 'https')
|
||||
subject.deprecated(true)
|
||||
subject.security(api_key: [])
|
||||
end
|
||||
let(:api_metadata) { { operation: {} } }
|
||||
|
||||
it "adds to the 'operation' metadata" do
|
||||
expect(api_metadata[:operation]).to match(
|
||||
tags: %w[Blogs Admin],
|
||||
description: 'Some description',
|
||||
operationId: 'createBlog',
|
||||
consumes: ['application/json', 'application/xml'],
|
||||
produces: ['application/json', 'application/xml'],
|
||||
schemes: %w[http https],
|
||||
deprecated: true,
|
||||
security: { api_key: [] }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#request_body_json(schema)' do
|
||||
let(:api_metadata) { { path_item: {}, operation: {} } } # i.e. operation defined
|
||||
context 'when required is not supplied' do
|
||||
before { subject.request_body_json(schema: { type: 'object' }) }
|
||||
|
||||
it 'adds required true by default' do
|
||||
expect(api_metadata[:operation][:requestBody]).to match(
|
||||
required: true, content: { 'application/json' => { schema: { type: 'object' } } }
|
||||
it "delegates to 'describe' with 'path' metadata" do
|
||||
expect(subject).to have_received(:describe).with(
|
||||
'/blogs', path_item: { template: '/blogs' }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when required is supplied' do
|
||||
before { subject.request_body_json(schema: { type: 'object' }, required: false) }
|
||||
describe '#get|post|patch|put|delete|head(verb, summary)' do
|
||||
before { subject.post('Creates a blog') }
|
||||
|
||||
it 'adds required false' do
|
||||
expect(api_metadata[:operation][:requestBody]).to match(
|
||||
required: false, content: { 'application/json' => { schema: { type: 'object' } } }
|
||||
it "delegates to 'describe' with 'operation' metadata" do
|
||||
expect(subject).to have_received(:describe).with(
|
||||
:post, operation: { verb: :post, summary: 'Creates a blog' }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when required is supplied' do
|
||||
before { subject.request_body_json(schema: { type: 'object' }, description: 'my description') }
|
||||
|
||||
it 'adds description' do
|
||||
expect(api_metadata[:operation][:requestBody]).to match(
|
||||
description: 'my description', required: true, content: { 'application/json' => { schema: { type: 'object' } } }
|
||||
)
|
||||
describe '#tags|description|operationId|consumes|produces|schemes|deprecated(value)' do
|
||||
before do
|
||||
subject.tags('Blogs', 'Admin')
|
||||
subject.description('Some description')
|
||||
subject.operationId('createBlog')
|
||||
subject.consumes('application/json', 'application/xml')
|
||||
subject.produces('application/json', 'application/xml')
|
||||
subject.schemes('http', 'https')
|
||||
subject.deprecated(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
let(:api_metadata) { { operation: {} } }
|
||||
|
||||
describe '#parameter(attributes)' do
|
||||
context "when called at the 'path' level" do
|
||||
before { subject.parameter(name: :blog, in: :body, schema: { type: 'object' }) }
|
||||
let(:api_metadata) { { path_item: {} } } # i.e. operation not defined yet
|
||||
|
||||
it "adds to the 'path_item parameters' metadata" do
|
||||
expect(api_metadata[:path_item][:parameters]).to match(
|
||||
[name: :blog, in: :body, schema: { type: 'object' }]
|
||||
)
|
||||
it "adds to the 'operation' metadata" do
|
||||
expect(api_metadata[:operation]).to match(
|
||||
tags: %w[Blogs Admin],
|
||||
description: 'Some description',
|
||||
operationId: 'createBlog',
|
||||
consumes: ['application/json', 'application/xml'],
|
||||
produces: ['application/json', 'application/xml'],
|
||||
schemes: %w[http https],
|
||||
deprecated: true
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "when called at the 'operation' level" do
|
||||
before { subject.parameter(name: :blog, in: :body, schema: { type: 'object' }) }
|
||||
describe '#tags|description|operationId|consumes|produces|schemes|deprecated|security(value)' do
|
||||
before do
|
||||
subject.tags('Blogs', 'Admin')
|
||||
subject.description('Some description')
|
||||
subject.operationId('createBlog')
|
||||
subject.consumes('application/json', 'application/xml')
|
||||
subject.produces('application/json', 'application/xml')
|
||||
subject.schemes('http', 'https')
|
||||
subject.deprecated(true)
|
||||
subject.security(api_key: [])
|
||||
end
|
||||
let(:api_metadata) { { operation: {} } }
|
||||
|
||||
it "adds to the 'operation' metadata" do
|
||||
expect(api_metadata[:operation]).to match(
|
||||
tags: %w[Blogs Admin],
|
||||
description: 'Some description',
|
||||
operationId: 'createBlog',
|
||||
consumes: ['application/json', 'application/xml'],
|
||||
produces: ['application/json', 'application/xml'],
|
||||
schemes: %w[http https],
|
||||
deprecated: true,
|
||||
security: { api_key: [] }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#request_body_json(schema)' do
|
||||
let(:api_metadata) { { path_item: {}, operation: {} } } # i.e. operation defined
|
||||
context 'when required is not supplied' do
|
||||
before { subject.request_body_json(schema: { type: 'object' }) }
|
||||
|
||||
it "adds to the 'operation parameters' metadata" do
|
||||
expect(api_metadata[:operation][:parameters]).to match(
|
||||
[name: :blog, in: :body, schema: { type: 'object' }]
|
||||
it 'adds required true by default' do
|
||||
expect(api_metadata[:operation][:requestBody]).to match(
|
||||
required: true, content: { 'application/json' => { schema: { type: 'object' } } }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when required is supplied' do
|
||||
before { subject.request_body_json(schema: { type: 'object' }, required: false) }
|
||||
|
||||
it 'adds required false' do
|
||||
expect(api_metadata[:operation][:requestBody]).to match(
|
||||
required: false, content: { 'application/json' => { schema: { type: 'object' } } }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when required is supplied' do
|
||||
before { subject.request_body_json(schema: { type: 'object' }, description: 'my description') }
|
||||
|
||||
it 'adds description' do
|
||||
expect(api_metadata[:operation][:requestBody]).to match(
|
||||
description: 'my description', required: true, content: { 'application/json' => { schema: { type: 'object' } } }
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#parameter(attributes)' do
|
||||
context "when called at the 'path' level" do
|
||||
before { subject.parameter(name: :blog, in: :body, schema: { type: 'object' }) }
|
||||
let(:api_metadata) { { path_item: {} } } # i.e. operation not defined yet
|
||||
|
||||
it "adds to the 'path_item parameters' metadata" do
|
||||
expect(api_metadata[:path_item][:parameters]).to match(
|
||||
[name: :blog, in: :body, schema: { type: 'object' }]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "when called at the 'operation' level" do
|
||||
before { subject.parameter(name: :blog, in: :body, schema: { type: 'object' }) }
|
||||
let(:api_metadata) { { path_item: {}, operation: {} } } # i.e. operation defined
|
||||
|
||||
it "adds to the 'operation parameters' metadata" do
|
||||
expect(api_metadata[:operation][:parameters]).to match(
|
||||
[name: :blog, in: :body, schema: { type: 'object' }]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "'path' parameter" do
|
||||
before { subject.parameter(name: :id, in: :path) }
|
||||
let(:api_metadata) { { operation: {} } }
|
||||
|
||||
it "automatically sets the 'required' flag" do
|
||||
expect(api_metadata[:operation][:parameters]).to match(
|
||||
[name: :id, in: :path, required: true]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "when 'in' parameter key is not defined" do
|
||||
before { subject.parameter(name: :id) }
|
||||
let(:api_metadata) { { operation: {} } }
|
||||
|
||||
it "does not require the 'in' parameter key" do
|
||||
expect(api_metadata[:operation][:parameters]).to match([name: :id])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#response(code, description)' do
|
||||
before { subject.response('201', 'success') }
|
||||
|
||||
it "delegates to 'context' with 'response' metadata" do
|
||||
expect(subject).to have_received(:context).with(
|
||||
'success', response: { code: '201', description: 'success' }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "'path' parameter" do
|
||||
before { subject.parameter(name: :id, in: :path) }
|
||||
let(:api_metadata) { { operation: {} } }
|
||||
describe '#schema(value)' do
|
||||
before { subject.schema(type: 'object') }
|
||||
let(:api_metadata) { { response: {} } }
|
||||
|
||||
it "automatically sets the 'required' flag" do
|
||||
expect(api_metadata[:operation][:parameters]).to match(
|
||||
[name: :id, in: :path, required: true]
|
||||
)
|
||||
it "adds to the 'response' metadata" do
|
||||
expect(api_metadata[:response][:content]['application/json'][:schema]).to match(type: 'object')
|
||||
end
|
||||
end
|
||||
|
||||
context "when 'in' parameter key is not defined" do
|
||||
before { subject.parameter(name: :id) }
|
||||
let(:api_metadata) { { operation: {} } }
|
||||
describe '#header(name, attributes)' do
|
||||
before { subject.header('Date', type: 'string') }
|
||||
let(:api_metadata) { { response: {} } }
|
||||
|
||||
it "does not require the 'in' parameter key" do
|
||||
expect(api_metadata[:operation][:parameters]).to match([name: :id])
|
||||
it "adds to the 'response headers' metadata" do
|
||||
expect(api_metadata[:response][:headers]).to match(
|
||||
'Date' => {schema: { type: 'string' }}
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#response(code, description)' do
|
||||
before { subject.response('201', 'success') }
|
||||
|
||||
it "delegates to 'context' with 'response' metadata" do
|
||||
expect(subject).to have_received(:context).with(
|
||||
'success', response: { code: '201', description: 'success' }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#schema(value)' do
|
||||
before { subject.schema(type: 'object') }
|
||||
let(:api_metadata) { { response: {} } }
|
||||
|
||||
it "adds to the 'response' metadata" do
|
||||
expect(api_metadata[:response][:content]['application/json'][:schema]).to match(type: 'object')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#header(name, attributes)' do
|
||||
before { subject.header('Date', type: 'string') }
|
||||
let(:api_metadata) { { response: {} } }
|
||||
|
||||
it "adds to the 'response headers' metadata" do
|
||||
expect(api_metadata[:response][:headers]).to match(
|
||||
'Date' => {schema: { type: 'string' }}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#examples(example)' do
|
||||
let(:json_example) do
|
||||
{
|
||||
'application/json' => {
|
||||
foo: 'bar'
|
||||
describe '#examples(example)' do
|
||||
let(:json_example) do
|
||||
{
|
||||
'application/json' => {
|
||||
foo: 'bar'
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
let(:api_metadata) { { response: {} } }
|
||||
end
|
||||
let(:api_metadata) { { response: {} } }
|
||||
|
||||
before do
|
||||
subject.examples(json_example)
|
||||
end
|
||||
before do
|
||||
subject.examples(json_example)
|
||||
end
|
||||
|
||||
it "adds to the 'response examples' metadata" do
|
||||
expect(api_metadata[:response][:examples]).to eq(json_example)
|
||||
it "adds to the 'response examples' metadata" do
|
||||
expect(api_metadata[:response][:examples]).to eq(json_example)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,69 +1,71 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rswag/specs/example_helpers'
|
||||
require 'open_api/rswag/specs/example_helpers'
|
||||
|
||||
module Rswag
|
||||
module Specs
|
||||
describe ExampleHelpers do
|
||||
subject { double('example') }
|
||||
module OpenApi
|
||||
module Rswag
|
||||
module Specs
|
||||
describe ExampleHelpers do
|
||||
subject { double('example') }
|
||||
|
||||
before do
|
||||
subject.extend(ExampleHelpers)
|
||||
allow(Rswag::Specs).to receive(:config).and_return(config)
|
||||
allow(config).to receive(:get_swagger_doc).and_return(swagger_doc)
|
||||
stub_const('Rswag::Specs::RAILS_VERSION', 3)
|
||||
end
|
||||
let(:config) { double('config') }
|
||||
let(:swagger_doc) do
|
||||
{
|
||||
components: {
|
||||
securitySchemes: {
|
||||
api_key: {
|
||||
type: :apiKey,
|
||||
name: 'api_key',
|
||||
in: :query
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
let(:metadata) do
|
||||
{
|
||||
path_item: { template: '/blogs/{blog_id}/comments/{id}' },
|
||||
operation: {
|
||||
verb: :put,
|
||||
summary: 'Updates a blog',
|
||||
consumes: ['application/json'],
|
||||
parameters: [
|
||||
{ name: :blog_id, in: :path, type: 'integer' },
|
||||
{ name: 'id', in: :path, type: 'integer' },
|
||||
{ name: 'q1', in: :query, type: 'string' },
|
||||
{ name: :blog, in: :body, schema: { type: 'object' } }
|
||||
],
|
||||
security: [
|
||||
{ api_key: [] }
|
||||
]
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
describe '#submit_request(metadata)' do
|
||||
before do
|
||||
allow(subject).to receive(:blog_id).and_return(1)
|
||||
allow(subject).to receive(:id).and_return(2)
|
||||
allow(subject).to receive(:q1).and_return('foo')
|
||||
allow(subject).to receive(:api_key).and_return('fookey')
|
||||
allow(subject).to receive(:blog).and_return(text: 'Some comment')
|
||||
allow(subject).to receive(:put)
|
||||
subject.submit_request(metadata)
|
||||
subject.extend(ExampleHelpers)
|
||||
allow(OpenApi::Rswag::Specs).to receive(:config).and_return(config)
|
||||
allow(config).to receive(:get_swagger_doc).and_return(swagger_doc)
|
||||
stub_const('Rswag::Specs::RAILS_VERSION', 3)
|
||||
end
|
||||
let(:config) { double('config') }
|
||||
let(:swagger_doc) do
|
||||
{
|
||||
components: {
|
||||
securitySchemes: {
|
||||
api_key: {
|
||||
type: :apiKey,
|
||||
name: 'api_key',
|
||||
in: :query
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
let(:metadata) do
|
||||
{
|
||||
path_item: { template: '/blogs/{blog_id}/comments/{id}' },
|
||||
operation: {
|
||||
verb: :put,
|
||||
summary: 'Updates a blog',
|
||||
consumes: ['application/json'],
|
||||
parameters: [
|
||||
{ name: :blog_id, in: :path, type: 'integer' },
|
||||
{ name: 'id', in: :path, type: 'integer' },
|
||||
{ name: 'q1', in: :query, type: 'string' },
|
||||
{ name: :blog, in: :body, schema: { type: 'object' } }
|
||||
],
|
||||
security: [
|
||||
{ api_key: [] }
|
||||
]
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it "submits a request built from metadata and 'let' values" do
|
||||
expect(subject).to have_received(:put).with(
|
||||
'/blogs/1/comments/2?q1=foo&api_key=fookey',
|
||||
'{"text":"Some comment"}',
|
||||
'CONTENT_TYPE' => 'application/json'
|
||||
)
|
||||
describe '#submit_request(metadata)' do
|
||||
before do
|
||||
allow(subject).to receive(:blog_id).and_return(1)
|
||||
allow(subject).to receive(:id).and_return(2)
|
||||
allow(subject).to receive(:q1).and_return('foo')
|
||||
allow(subject).to receive(:api_key).and_return('fookey')
|
||||
allow(subject).to receive(:blog).and_return(text: 'Some comment')
|
||||
allow(subject).to receive(:put)
|
||||
subject.submit_request(metadata)
|
||||
end
|
||||
|
||||
it "submits a request built from metadata and 'let' values" do
|
||||
expect(subject).to have_received(:put).with(
|
||||
'/blogs/1/comments/2?q1=foo&api_key=fookey',
|
||||
'{"text":"Some comment"}',
|
||||
'CONTENT_TYPE' => 'application/json'
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,351 +1,353 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rswag/specs/request_factory'
|
||||
require 'open_api/rswag/specs/request_factory'
|
||||
|
||||
module Rswag
|
||||
module Specs
|
||||
describe RequestFactory do
|
||||
subject { RequestFactory.new(config) }
|
||||
module OpenApi
|
||||
module Rswag
|
||||
module Specs
|
||||
describe RequestFactory do
|
||||
subject { RequestFactory.new(config) }
|
||||
|
||||
before do
|
||||
allow(config).to receive(:get_swagger_doc).and_return(swagger_doc)
|
||||
end
|
||||
let(:config) { double('config') }
|
||||
let(:swagger_doc) { {} }
|
||||
let(:example) { double('example') }
|
||||
let(:metadata) do
|
||||
{
|
||||
path_item: { template: '/blogs' },
|
||||
operation: { verb: :get }
|
||||
}
|
||||
end
|
||||
|
||||
describe '#build_request(metadata, example)' do
|
||||
let(:request) { subject.build_request(metadata, example) }
|
||||
|
||||
it 'builds request hash for given example' do
|
||||
expect(request[:verb]).to eq(:get)
|
||||
expect(request[:path]).to eq('/blogs')
|
||||
before do
|
||||
allow(config).to receive(:get_swagger_doc).and_return(swagger_doc)
|
||||
end
|
||||
let(:config) { double('config') }
|
||||
let(:swagger_doc) { {} }
|
||||
let(:example) { double('example') }
|
||||
let(:metadata) do
|
||||
{
|
||||
path_item: { template: '/blogs' },
|
||||
operation: { verb: :get }
|
||||
}
|
||||
end
|
||||
|
||||
context "'path' parameters" do
|
||||
before do
|
||||
metadata[:path_item][:template] = '/blogs/{blog_id}/comments/{id}'
|
||||
metadata[:operation][:parameters] = [
|
||||
{ name: 'blog_id', in: :path, type: :number },
|
||||
{ name: 'id', in: :path, type: :number }
|
||||
]
|
||||
allow(example).to receive(:blog_id).and_return(1)
|
||||
allow(example).to receive(:id).and_return(2)
|
||||
end
|
||||
describe '#build_request(metadata, example)' do
|
||||
let(:request) { subject.build_request(metadata, example) }
|
||||
|
||||
it 'builds the path from example values' do
|
||||
expect(request[:path]).to eq('/blogs/1/comments/2')
|
||||
end
|
||||
end
|
||||
|
||||
context "'query' parameters" do
|
||||
before do
|
||||
metadata[:operation][:parameters] = [
|
||||
{ name: 'q1', in: :query, type: :string },
|
||||
{ name: 'q2', in: :query, type: :string }
|
||||
]
|
||||
allow(example).to receive(:q1).and_return('foo')
|
||||
allow(example).to receive(:q2).and_return('bar')
|
||||
end
|
||||
|
||||
it 'builds the query string from example values' do
|
||||
expect(request[:path]).to eq('/blogs?q1=foo&q2=bar')
|
||||
end
|
||||
end
|
||||
|
||||
context "'query' parameters of type 'array'" do
|
||||
before do
|
||||
metadata[:operation][:parameters] = [
|
||||
{ name: 'things', in: :query, type: :array, collectionFormat: collection_format }
|
||||
]
|
||||
allow(example).to receive(:things).and_return(%w[foo bar])
|
||||
end
|
||||
|
||||
context 'collectionFormat = csv' do
|
||||
let(:collection_format) { :csv }
|
||||
it 'formats as comma separated values' do
|
||||
expect(request[:path]).to eq('/blogs?things=foo,bar')
|
||||
end
|
||||
end
|
||||
|
||||
context 'collectionFormat = ssv' do
|
||||
let(:collection_format) { :ssv }
|
||||
it 'formats as space separated values' do
|
||||
expect(request[:path]).to eq('/blogs?things=foo bar')
|
||||
end
|
||||
end
|
||||
|
||||
context 'collectionFormat = tsv' do
|
||||
let(:collection_format) { :tsv }
|
||||
it 'formats as tab separated values' do
|
||||
expect(request[:path]).to eq('/blogs?things=foo\tbar')
|
||||
end
|
||||
end
|
||||
|
||||
context 'collectionFormat = pipes' do
|
||||
let(:collection_format) { :pipes }
|
||||
it 'formats as pipe separated values' do
|
||||
expect(request[:path]).to eq('/blogs?things=foo|bar')
|
||||
end
|
||||
end
|
||||
|
||||
context 'collectionFormat = multi' do
|
||||
let(:collection_format) { :multi }
|
||||
it 'formats as multiple parameter instances' do
|
||||
expect(request[:path]).to eq('/blogs?things=foo&things=bar')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "'header' parameters" do
|
||||
before do
|
||||
metadata[:operation][:parameters] = [{ name: 'Api-Key', in: :header, type: :string }]
|
||||
allow(example).to receive(:'Api-Key').and_return('foobar')
|
||||
end
|
||||
|
||||
it 'adds names and example values to headers' do
|
||||
expect(request[:headers]).to eq('Api-Key' => 'foobar')
|
||||
end
|
||||
end
|
||||
|
||||
context 'optional parameters not provided' do
|
||||
before do
|
||||
metadata[:operation][:parameters] = [
|
||||
{ name: 'q1', in: :query, type: :string, required: false },
|
||||
{ name: 'Api-Key', in: :header, type: :string, required: false }
|
||||
]
|
||||
end
|
||||
|
||||
it 'builds request hash without them' do
|
||||
it 'builds request hash for given example' do
|
||||
expect(request[:verb]).to eq(:get)
|
||||
expect(request[:path]).to eq('/blogs')
|
||||
expect(request[:headers]).to eq({})
|
||||
end
|
||||
end
|
||||
|
||||
context 'consumes content' do
|
||||
before do
|
||||
metadata[:operation][:consumes] = ['application/json', 'application/xml']
|
||||
end
|
||||
|
||||
context "no 'Content-Type' provided" do
|
||||
it "sets 'CONTENT_TYPE' header to first in list" do
|
||||
expect(request[:headers]).to eq('CONTENT_TYPE' => 'application/json')
|
||||
end
|
||||
end
|
||||
|
||||
context "explicit 'Content-Type' provided" do
|
||||
context "'path' parameters" do
|
||||
before do
|
||||
allow(example).to receive(:'Content-Type').and_return('application/xml')
|
||||
end
|
||||
|
||||
it "sets 'CONTENT_TYPE' header to example value" do
|
||||
expect(request[:headers]).to eq('CONTENT_TYPE' => 'application/xml')
|
||||
end
|
||||
end
|
||||
|
||||
context 'JSON payload' do
|
||||
before do
|
||||
metadata[:operation][:parameters] = [{ name: 'comment', in: :body, schema: { type: 'object' } }]
|
||||
allow(example).to receive(:comment).and_return(text: 'Some comment')
|
||||
end
|
||||
|
||||
it "serializes first 'body' parameter to JSON string" do
|
||||
expect(request[:payload]).to eq('{"text":"Some comment"}')
|
||||
end
|
||||
end
|
||||
|
||||
context 'form payload' do
|
||||
before do
|
||||
metadata[:operation][:consumes] = ['multipart/form-data']
|
||||
metadata[:path_item][:template] = '/blogs/{blog_id}/comments/{id}'
|
||||
metadata[:operation][:parameters] = [
|
||||
{ name: 'f1', in: :formData, type: :string },
|
||||
{ name: 'f2', in: :formData, type: :string }
|
||||
{ name: 'blog_id', in: :path, type: :number },
|
||||
{ name: 'id', in: :path, type: :number }
|
||||
]
|
||||
allow(example).to receive(:f1).and_return('foo blah')
|
||||
allow(example).to receive(:f2).and_return('bar blah')
|
||||
allow(example).to receive(:blog_id).and_return(1)
|
||||
allow(example).to receive(:id).and_return(2)
|
||||
end
|
||||
|
||||
it 'sets payload to hash of names and example values' do
|
||||
expect(request[:payload]).to eq(
|
||||
'f1' => 'foo blah',
|
||||
'f2' => 'bar blah'
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'produces content' do
|
||||
before do
|
||||
metadata[:operation][:produces] = ['application/json', 'application/xml']
|
||||
end
|
||||
|
||||
context "no 'Accept' value provided" do
|
||||
it "sets 'HTTP_ACCEPT' header to first in list" do
|
||||
expect(request[:headers]).to eq('HTTP_ACCEPT' => 'application/json')
|
||||
it 'builds the path from example values' do
|
||||
expect(request[:path]).to eq('/blogs/1/comments/2')
|
||||
end
|
||||
end
|
||||
|
||||
context "explicit 'Accept' value provided" do
|
||||
context "'query' parameters" do
|
||||
before do
|
||||
allow(example).to receive(:Accept).and_return('application/xml')
|
||||
metadata[:operation][:parameters] = [
|
||||
{ name: 'q1', in: :query, type: :string },
|
||||
{ name: 'q2', in: :query, type: :string }
|
||||
]
|
||||
allow(example).to receive(:q1).and_return('foo')
|
||||
allow(example).to receive(:q2).and_return('bar')
|
||||
end
|
||||
|
||||
it "sets 'HTTP_ACCEPT' header to example value" do
|
||||
expect(request[:headers]).to eq('HTTP_ACCEPT' => 'application/xml')
|
||||
it 'builds the query string from example values' do
|
||||
expect(request[:path]).to eq('/blogs?q1=foo&q2=bar')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'basic auth' do
|
||||
before do
|
||||
swagger_doc[:components] = { securitySchemes: {
|
||||
basic: { type: :basic }
|
||||
context "'query' parameters of type 'array'" do
|
||||
before do
|
||||
metadata[:operation][:parameters] = [
|
||||
{ name: 'things', in: :query, type: :array, collectionFormat: collection_format }
|
||||
]
|
||||
allow(example).to receive(:things).and_return(%w[foo bar])
|
||||
end
|
||||
|
||||
context 'collectionFormat = csv' do
|
||||
let(:collection_format) { :csv }
|
||||
it 'formats as comma separated values' do
|
||||
expect(request[:path]).to eq('/blogs?things=foo,bar')
|
||||
end
|
||||
end
|
||||
|
||||
context 'collectionFormat = ssv' do
|
||||
let(:collection_format) { :ssv }
|
||||
it 'formats as space separated values' do
|
||||
expect(request[:path]).to eq('/blogs?things=foo bar')
|
||||
end
|
||||
end
|
||||
|
||||
context 'collectionFormat = tsv' do
|
||||
let(:collection_format) { :tsv }
|
||||
it 'formats as tab separated values' do
|
||||
expect(request[:path]).to eq('/blogs?things=foo\tbar')
|
||||
end
|
||||
end
|
||||
|
||||
context 'collectionFormat = pipes' do
|
||||
let(:collection_format) { :pipes }
|
||||
it 'formats as pipe separated values' do
|
||||
expect(request[:path]).to eq('/blogs?things=foo|bar')
|
||||
end
|
||||
end
|
||||
|
||||
context 'collectionFormat = multi' do
|
||||
let(:collection_format) { :multi }
|
||||
it 'formats as multiple parameter instances' do
|
||||
expect(request[:path]).to eq('/blogs?things=foo&things=bar')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "'header' parameters" do
|
||||
before do
|
||||
metadata[:operation][:parameters] = [{ name: 'Api-Key', in: :header, type: :string }]
|
||||
allow(example).to receive(:'Api-Key').and_return('foobar')
|
||||
end
|
||||
|
||||
it 'adds names and example values to headers' do
|
||||
expect(request[:headers]).to eq('Api-Key' => 'foobar')
|
||||
end
|
||||
end
|
||||
|
||||
context 'optional parameters not provided' do
|
||||
before do
|
||||
metadata[:operation][:parameters] = [
|
||||
{ name: 'q1', in: :query, type: :string, required: false },
|
||||
{ name: 'Api-Key', in: :header, type: :string, required: false }
|
||||
]
|
||||
end
|
||||
|
||||
it 'builds request hash without them' do
|
||||
expect(request[:path]).to eq('/blogs')
|
||||
expect(request[:headers]).to eq({})
|
||||
end
|
||||
end
|
||||
|
||||
context 'consumes content' do
|
||||
before do
|
||||
metadata[:operation][:consumes] = ['application/json', 'application/xml']
|
||||
end
|
||||
|
||||
context "no 'Content-Type' provided" do
|
||||
it "sets 'CONTENT_TYPE' header to first in list" do
|
||||
expect(request[:headers]).to eq('CONTENT_TYPE' => 'application/json')
|
||||
end
|
||||
end
|
||||
|
||||
context "explicit 'Content-Type' provided" do
|
||||
before do
|
||||
allow(example).to receive(:'Content-Type').and_return('application/xml')
|
||||
end
|
||||
|
||||
it "sets 'CONTENT_TYPE' header to example value" do
|
||||
expect(request[:headers]).to eq('CONTENT_TYPE' => 'application/xml')
|
||||
end
|
||||
end
|
||||
|
||||
context 'JSON payload' do
|
||||
before do
|
||||
metadata[:operation][:parameters] = [{ name: :comment, in: :body, schema: { type: 'object' } }]
|
||||
allow(example).to receive(:comment).and_return(text: 'Some comment')
|
||||
end
|
||||
|
||||
it "serializes first 'body' parameter to JSON string" do
|
||||
expect(request[:payload]).to eq('{"text":"Some comment"}')
|
||||
end
|
||||
end
|
||||
|
||||
context 'form payload' do
|
||||
before do
|
||||
metadata[:operation][:consumes] = ['multipart/form-data']
|
||||
metadata[:operation][:parameters] = [
|
||||
{ name: 'f1', in: :formData, type: :string },
|
||||
{ name: 'f2', in: :formData, type: :string }
|
||||
]
|
||||
allow(example).to receive(:f1).and_return('foo blah')
|
||||
allow(example).to receive(:f2).and_return('bar blah')
|
||||
end
|
||||
|
||||
it 'sets payload to hash of names and example values' do
|
||||
expect(request[:payload]).to eq(
|
||||
'f1' => 'foo blah',
|
||||
'f2' => 'bar blah'
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'produces content' do
|
||||
before do
|
||||
metadata[:operation][:produces] = ['application/json', 'application/xml']
|
||||
end
|
||||
|
||||
context "no 'Accept' value provided" do
|
||||
it "sets 'HTTP_ACCEPT' header to first in list" do
|
||||
expect(request[:headers]).to eq('HTTP_ACCEPT' => 'application/json')
|
||||
end
|
||||
end
|
||||
|
||||
context "explicit 'Accept' value provided" do
|
||||
before do
|
||||
allow(example).to receive(:Accept).and_return('application/xml')
|
||||
end
|
||||
|
||||
it "sets 'HTTP_ACCEPT' header to example value" do
|
||||
expect(request[:headers]).to eq('HTTP_ACCEPT' => 'application/xml')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'basic auth' do
|
||||
before do
|
||||
swagger_doc[:components] = { securitySchemes: {
|
||||
basic: { type: :basic }
|
||||
}
|
||||
}
|
||||
metadata[:operation][:security] = [basic: []]
|
||||
allow(example).to receive(:Authorization).and_return('Basic foobar')
|
||||
end
|
||||
|
||||
it "sets 'HTTP_AUTHORIZATION' header to example value" do
|
||||
expect(request[:headers]).to eq('HTTP_AUTHORIZATION' => 'Basic foobar')
|
||||
end
|
||||
end
|
||||
|
||||
context 'apiKey' do
|
||||
before do
|
||||
swagger_doc[:components] = { securitySchemes: {
|
||||
apiKey: { type: :apiKey, name: 'api_key', in: key_location }
|
||||
}
|
||||
}
|
||||
metadata[:operation][:security] = [apiKey: []]
|
||||
allow(example).to receive(:api_key).and_return('foobar')
|
||||
metadata[:operation][:security] = [basic: []]
|
||||
allow(example).to receive(:Authorization).and_return('Basic foobar')
|
||||
end
|
||||
|
||||
it "sets 'HTTP_AUTHORIZATION' header to example value" do
|
||||
expect(request[:headers]).to eq('HTTP_AUTHORIZATION' => 'Basic foobar')
|
||||
end
|
||||
end
|
||||
|
||||
context 'in query' do
|
||||
let(:key_location) { :query }
|
||||
context 'apiKey' do
|
||||
before do
|
||||
swagger_doc[:components] = { securitySchemes: {
|
||||
apiKey: { type: :apiKey, name: 'api_key', in: key_location }
|
||||
}
|
||||
}
|
||||
metadata[:operation][:security] = [apiKey: []]
|
||||
allow(example).to receive(:api_key).and_return('foobar')
|
||||
end
|
||||
|
||||
it 'adds name and example value to the query string' do
|
||||
context 'in query' do
|
||||
let(:key_location) { :query }
|
||||
|
||||
it 'adds name and example value to the query string' do
|
||||
expect(request[:path]).to eq('/blogs?api_key=foobar')
|
||||
end
|
||||
end
|
||||
|
||||
context 'in header' do
|
||||
let(:key_location) { :header }
|
||||
|
||||
it 'adds name and example value to the headers' do
|
||||
expect(request[:headers]).to eq('api_key' => 'foobar')
|
||||
end
|
||||
end
|
||||
|
||||
context 'in header with auth param already added' do
|
||||
let(:key_location) { :header }
|
||||
before do
|
||||
metadata[:operation][:parameters] = [
|
||||
{ name: 'q1', in: :query, type: :string },
|
||||
{ name: 'api_key', in: :header, type: :string }
|
||||
]
|
||||
allow(example).to receive(:q1).and_return('foo')
|
||||
allow(example).to receive(:api_key).and_return('foobar')
|
||||
end
|
||||
|
||||
it 'adds authorization parameter only once' do
|
||||
expect(request[:headers]).to eq('api_key' => 'foobar')
|
||||
expect(metadata[:operation][:parameters].size).to eq 2
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'oauth2' do
|
||||
before do
|
||||
swagger_doc[:components] = { securitySchemes: {
|
||||
oauth2: { type: :oauth2, scopes: ['read:blogs'] }
|
||||
}
|
||||
}
|
||||
metadata[:operation][:security] = [oauth2: ['read:blogs']]
|
||||
allow(example).to receive(:Authorization).and_return('Bearer foobar')
|
||||
end
|
||||
|
||||
it "sets 'HTTP_AUTHORIZATION' header to example value" do
|
||||
expect(request[:headers]).to eq('HTTP_AUTHORIZATION' => 'Bearer foobar')
|
||||
end
|
||||
end
|
||||
|
||||
context 'paired security requirements' do
|
||||
before do
|
||||
swagger_doc[:components] = { securitySchemes: {
|
||||
basic: { type: :basic },
|
||||
api_key: { type: :apiKey, name: 'api_key', in: :query }
|
||||
}
|
||||
}
|
||||
metadata[:operation][:security] = [{ basic: [], api_key: [] }]
|
||||
allow(example).to receive(:Authorization).and_return('Basic foobar')
|
||||
allow(example).to receive(:api_key).and_return('foobar')
|
||||
end
|
||||
|
||||
it 'sets both params to example values' do
|
||||
expect(request[:headers]).to eq('HTTP_AUTHORIZATION' => 'Basic foobar')
|
||||
expect(request[:path]).to eq('/blogs?api_key=foobar')
|
||||
end
|
||||
end
|
||||
|
||||
context 'in header' do
|
||||
let(:key_location) { :header }
|
||||
context 'path-level parameters' do
|
||||
before do
|
||||
metadata[:operation][:parameters] = [{ name: 'q1', in: :query, type: :string }]
|
||||
metadata[:path_item][:parameters] = [{ name: 'q2', in: :query, type: :string }]
|
||||
allow(example).to receive(:q1).and_return('foo')
|
||||
allow(example).to receive(:q2).and_return('bar')
|
||||
end
|
||||
|
||||
it 'adds name and example value to the headers' do
|
||||
expect(request[:headers]).to eq('api_key' => 'foobar')
|
||||
it 'populates operation and path level parameters ' do
|
||||
expect(request[:path]).to eq('/blogs?q1=foo&q2=bar')
|
||||
end
|
||||
end
|
||||
|
||||
context 'in header with auth param already added' do
|
||||
let(:key_location) { :header }
|
||||
context 'referenced parameters' do
|
||||
before do
|
||||
metadata[:operation][:parameters] = [
|
||||
{ name: 'q1', in: :query, type: :string },
|
||||
{ name: 'api_key', in: :header, type: :string }
|
||||
]
|
||||
swagger_doc[:parameters] = { q1: { name: 'q1', in: :query, type: :string } }
|
||||
metadata[:operation][:parameters] = [{ '$ref' => '#/parameters/q1' }]
|
||||
allow(example).to receive(:q1).and_return('foo')
|
||||
end
|
||||
|
||||
it 'uses the referenced metadata to build the request' do
|
||||
expect(request[:path]).to eq('/blogs?q1=foo')
|
||||
end
|
||||
end
|
||||
|
||||
context 'global basePath' do
|
||||
before { swagger_doc[:basePath] = '/api' }
|
||||
|
||||
it 'prepends to the path' do
|
||||
expect(request[:path]).to eq('/api/blogs')
|
||||
end
|
||||
end
|
||||
|
||||
context 'global consumes' do
|
||||
before { swagger_doc[:consumes] = ['application/xml'] }
|
||||
|
||||
it "defaults 'CONTENT_TYPE' to global value(s)" do
|
||||
expect(request[:headers]).to eq('CONTENT_TYPE' => 'application/xml')
|
||||
end
|
||||
end
|
||||
|
||||
context 'global security requirements' do
|
||||
before do
|
||||
swagger_doc[:components] = {securitySchemes: { apiKey: { type: :apiKey, name: 'api_key', in: :query } }}
|
||||
swagger_doc[:security] = [apiKey: []]
|
||||
allow(example).to receive(:api_key).and_return('foobar')
|
||||
end
|
||||
|
||||
it 'adds authorization parameter only once' do
|
||||
expect(request[:headers]).to eq('api_key' => 'foobar')
|
||||
expect(metadata[:operation][:parameters].size).to eq 2
|
||||
it 'applieds the scheme by default' do
|
||||
expect(request[:path]).to eq('/blogs?api_key=foobar')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'oauth2' do
|
||||
before do
|
||||
swagger_doc[:components] = { securitySchemes: {
|
||||
oauth2: { type: :oauth2, scopes: ['read:blogs'] }
|
||||
}
|
||||
}
|
||||
metadata[:operation][:security] = [oauth2: ['read:blogs']]
|
||||
allow(example).to receive(:Authorization).and_return('Bearer foobar')
|
||||
end
|
||||
|
||||
it "sets 'HTTP_AUTHORIZATION' header to example value" do
|
||||
expect(request[:headers]).to eq('HTTP_AUTHORIZATION' => 'Bearer foobar')
|
||||
end
|
||||
end
|
||||
|
||||
context 'paired security requirements' do
|
||||
before do
|
||||
swagger_doc[:components] = { securitySchemes: {
|
||||
basic: { type: :basic },
|
||||
api_key: { type: :apiKey, name: 'api_key', in: :query }
|
||||
}
|
||||
}
|
||||
metadata[:operation][:security] = [{ basic: [], api_key: [] }]
|
||||
allow(example).to receive(:Authorization).and_return('Basic foobar')
|
||||
allow(example).to receive(:api_key).and_return('foobar')
|
||||
end
|
||||
|
||||
it 'sets both params to example values' do
|
||||
expect(request[:headers]).to eq('HTTP_AUTHORIZATION' => 'Basic foobar')
|
||||
expect(request[:path]).to eq('/blogs?api_key=foobar')
|
||||
end
|
||||
end
|
||||
|
||||
context 'path-level parameters' do
|
||||
before do
|
||||
metadata[:operation][:parameters] = [{ name: 'q1', in: :query, type: :string }]
|
||||
metadata[:path_item][:parameters] = [{ name: 'q2', in: :query, type: :string }]
|
||||
allow(example).to receive(:q1).and_return('foo')
|
||||
allow(example).to receive(:q2).and_return('bar')
|
||||
end
|
||||
|
||||
it 'populates operation and path level parameters ' do
|
||||
expect(request[:path]).to eq('/blogs?q1=foo&q2=bar')
|
||||
end
|
||||
end
|
||||
|
||||
context 'referenced parameters' do
|
||||
before do
|
||||
swagger_doc[:parameters] = { q1: { name: 'q1', in: :query, type: :string } }
|
||||
metadata[:operation][:parameters] = [{ '$ref' => '#/parameters/q1' }]
|
||||
allow(example).to receive(:q1).and_return('foo')
|
||||
end
|
||||
|
||||
it 'uses the referenced metadata to build the request' do
|
||||
expect(request[:path]).to eq('/blogs?q1=foo')
|
||||
end
|
||||
end
|
||||
|
||||
context 'global basePath' do
|
||||
before { swagger_doc[:basePath] = '/api' }
|
||||
|
||||
it 'prepends to the path' do
|
||||
expect(request[:path]).to eq('/api/blogs')
|
||||
end
|
||||
end
|
||||
|
||||
context 'global consumes' do
|
||||
before { swagger_doc[:consumes] = ['application/xml'] }
|
||||
|
||||
it "defaults 'CONTENT_TYPE' to global value(s)" do
|
||||
expect(request[:headers]).to eq('CONTENT_TYPE' => 'application/xml')
|
||||
end
|
||||
end
|
||||
|
||||
context 'global security requirements' do
|
||||
before do
|
||||
swagger_doc[:components] = {securitySchemes: { apiKey: { type: :apiKey, name: 'api_key', in: :query } }}
|
||||
swagger_doc[:security] = [apiKey: []]
|
||||
allow(example).to receive(:api_key).and_return('foobar')
|
||||
end
|
||||
|
||||
it 'applieds the scheme by default' do
|
||||
expect(request[:path]).to eq('/blogs?api_key=foobar')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,76 +1,82 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rswag/specs/response_validator'
|
||||
require 'open_api/rswag/specs/response_validator'
|
||||
|
||||
module Rswag
|
||||
module Specs
|
||||
describe ResponseValidator do
|
||||
subject { ResponseValidator.new(config) }
|
||||
module OpenApi
|
||||
module Rswag
|
||||
module Specs
|
||||
describe ResponseValidator do
|
||||
subject { ResponseValidator.new(config) }
|
||||
|
||||
before do
|
||||
allow(config).to receive(:get_swagger_doc).and_return(swagger_doc)
|
||||
end
|
||||
let(:config) { double('config') }
|
||||
let(:swagger_doc) {{}}
|
||||
let(:example) { double('example') }
|
||||
let(:metadata) do
|
||||
{
|
||||
response: {
|
||||
code: 200,
|
||||
headers: { 'X-Rate-Limit-Limit' => { type: :integer } },
|
||||
schema: {
|
||||
type: :object,
|
||||
properties: { text: { type: :string } },
|
||||
required: ['text']
|
||||
}
|
||||
before do
|
||||
allow(config).to receive(:get_swagger_doc).and_return(swagger_doc)
|
||||
end
|
||||
let(:config) { double('config') }
|
||||
let(:swagger_doc) {{}}
|
||||
let(:example) { double('example') }
|
||||
let(:metadata) do
|
||||
{
|
||||
response: {
|
||||
code: 200,
|
||||
headers: { 'X-Rate-Limit-Limit' => { type: :integer } },
|
||||
content:
|
||||
{'application/json' => {
|
||||
schema: {
|
||||
type: :object,
|
||||
properties: { text: { type: :string } },
|
||||
required: ['text']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
describe '#validate!(metadata, response)' do
|
||||
let(:call) { subject.validate!(metadata, response) }
|
||||
let(:response) do
|
||||
OpenStruct.new(
|
||||
code: '200',
|
||||
headers: { 'X-Rate-Limit-Limit' => '10' },
|
||||
body: '{"text":"Some comment"}'
|
||||
)
|
||||
end
|
||||
|
||||
context 'response matches metadata' do
|
||||
it { expect { call }.to_not raise_error }
|
||||
end
|
||||
|
||||
context 'response code differs from metadata' do
|
||||
before { response.code = '400' }
|
||||
it { expect { call }.to raise_error /Expected response code/ }
|
||||
end
|
||||
|
||||
context 'response headers differ from metadata' do
|
||||
before { response.headers = {} }
|
||||
it { expect { call }.to raise_error /Expected response header/ }
|
||||
end
|
||||
|
||||
context 'response body differs from metadata' do
|
||||
before { response.body = '{"foo":"Some comment"}' }
|
||||
it { expect { call }.to raise_error /Expected response body/ }
|
||||
end
|
||||
|
||||
context 'referenced schemas' do
|
||||
before do
|
||||
swagger_doc[:components] = {}
|
||||
swagger_doc[:components][:schemas] = {
|
||||
'blog' => {
|
||||
type: :object,
|
||||
properties: { foo: { type: :string } },
|
||||
required: ['foo']
|
||||
}
|
||||
}
|
||||
metadata[:response][:schema] = { '$ref' => '#/components/schemas/blog' }
|
||||
describe '#validate!(metadata, response)' do
|
||||
let(:call) { subject.validate!(metadata, response) }
|
||||
let(:response) do
|
||||
OpenStruct.new(
|
||||
code: '200',
|
||||
headers: { 'X-Rate-Limit-Limit' => '10' },
|
||||
body: '{"text":"Some comment"}'
|
||||
)
|
||||
end
|
||||
|
||||
it 'uses the referenced schema to validate the response body' do
|
||||
expect { call }.to raise_error /Expected response body/
|
||||
context 'response matches metadata' do
|
||||
it { expect { call }.to_not raise_error }
|
||||
end
|
||||
|
||||
context 'response code differs from metadata' do
|
||||
before { response.code = '400' }
|
||||
it { expect { call }.to raise_error /Expected response code/ }
|
||||
end
|
||||
|
||||
context 'response headers differ from metadata' do
|
||||
before { response.headers = {} }
|
||||
it { expect { call }.to raise_error /Expected response header/ }
|
||||
end
|
||||
|
||||
context 'response body differs from metadata' do
|
||||
before { response.body = '{"foo":"Some comment"}' }
|
||||
it { expect { call }.to raise_error /Expected response body/ }
|
||||
end
|
||||
|
||||
context 'referenced schemas' do
|
||||
before do
|
||||
swagger_doc[:components] = {}
|
||||
swagger_doc[:components][:schemas] = {
|
||||
'blog' => {
|
||||
type: :object,
|
||||
properties: { foo: { type: :string } },
|
||||
required: ['foo']
|
||||
}
|
||||
}
|
||||
metadata[:response][:content]['application/json'][:schema] = { '$ref' => '#/components/schemas/blog' }
|
||||
end
|
||||
|
||||
it 'uses the referenced schema to validate the response body' do
|
||||
expect { call }.to raise_error /Expected response body/
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,71 +1,73 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rswag/specs/swagger_formatter'
|
||||
require 'open_api/rswag/specs/swagger_formatter'
|
||||
require 'ostruct'
|
||||
|
||||
module Rswag
|
||||
module Specs
|
||||
describe SwaggerFormatter do
|
||||
subject { described_class.new(output, config) }
|
||||
module OpenApi
|
||||
module Rswag
|
||||
module Specs
|
||||
describe SwaggerFormatter do
|
||||
subject { described_class.new(output, config) }
|
||||
|
||||
# Mock out some infrastructure
|
||||
before do
|
||||
allow(config).to receive(:swagger_root).and_return(swagger_root)
|
||||
end
|
||||
let(:config) { double('config') }
|
||||
let(:output) { double('output').as_null_object }
|
||||
let(:swagger_root) { File.expand_path('tmp/swagger', __dir__) }
|
||||
|
||||
describe '#example_group_finished(notification)' do
|
||||
# Mock out some infrastructure
|
||||
before do
|
||||
allow(config).to receive(:get_swagger_doc).and_return(swagger_doc)
|
||||
subject.example_group_finished(notification)
|
||||
end
|
||||
let(:swagger_doc) { {} }
|
||||
let(:notification) { OpenStruct.new(group: OpenStruct.new(metadata: api_metadata)) }
|
||||
let(:api_metadata) do
|
||||
{
|
||||
path_item: { template: '/blogs' },
|
||||
operation: { verb: :post, summary: 'Creates a blog' },
|
||||
response: { code: '201', description: 'blog created' }
|
||||
}
|
||||
allow(config).to receive(:swagger_root).and_return(swagger_root)
|
||||
end
|
||||
let(:config) { double('config') }
|
||||
let(:output) { double('output').as_null_object }
|
||||
let(:swagger_root) { File.expand_path('tmp/swagger', __dir__) }
|
||||
|
||||
it 'converts to swagger and merges into the corresponding swagger doc' do
|
||||
expect(swagger_doc).to match(
|
||||
paths: {
|
||||
'/blogs' => {
|
||||
post: {
|
||||
summary: 'Creates a blog',
|
||||
responses: {
|
||||
'201' => { description: 'blog created' }
|
||||
}
|
||||
}
|
||||
}
|
||||
describe '#example_group_finished(notification)' do
|
||||
before do
|
||||
allow(config).to receive(:get_swagger_doc).and_return(swagger_doc)
|
||||
subject.example_group_finished(notification)
|
||||
end
|
||||
let(:swagger_doc) { {} }
|
||||
let(:notification) { OpenStruct.new(group: OpenStruct.new(metadata: api_metadata)) }
|
||||
let(:api_metadata) do
|
||||
{
|
||||
path_item: { template: '/blogs' },
|
||||
operation: { verb: :post, summary: 'Creates a blog' },
|
||||
response: { code: '201', description: 'blog created' }
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#stop' do
|
||||
before do
|
||||
FileUtils.rm_r(swagger_root) if File.exist?(swagger_root)
|
||||
allow(config).to receive(:swagger_docs).and_return(
|
||||
'v1/swagger.json' => { info: { version: 'v1' } },
|
||||
'v2/swagger.json' => { info: { version: 'v2' } }
|
||||
)
|
||||
subject.stop(notification)
|
||||
it 'converts to swagger and merges into the corresponding swagger doc' do
|
||||
expect(swagger_doc).to match(
|
||||
paths: {
|
||||
'/blogs' => {
|
||||
post: {
|
||||
summary: 'Creates a blog',
|
||||
responses: {
|
||||
'201' => { description: 'blog created' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
let(:notification) { double('notification') }
|
||||
describe '#stop' do
|
||||
before do
|
||||
FileUtils.rm_r(swagger_root) if File.exist?(swagger_root)
|
||||
allow(config).to receive(:swagger_docs).and_return(
|
||||
'v1/swagger.json' => { info: { version: 'v1' } },
|
||||
'v2/swagger.json' => { info: { version: 'v2' } }
|
||||
)
|
||||
subject.stop(notification)
|
||||
end
|
||||
|
||||
it 'writes the swagger_doc(s) to file' do
|
||||
expect(File).to exist("#{swagger_root}/v1/swagger.json")
|
||||
expect(File).to exist("#{swagger_root}/v2/swagger.json")
|
||||
end
|
||||
let(:notification) { double('notification') }
|
||||
|
||||
after do
|
||||
FileUtils.rm_r(swagger_root) if File.exist?(swagger_root)
|
||||
it 'writes the swagger_doc(s) to file' do
|
||||
expect(File).to exist("#{swagger_root}/v1/swagger.json")
|
||||
expect(File).to exist("#{swagger_root}/v2/swagger.json")
|
||||
end
|
||||
|
||||
after do
|
||||
FileUtils.rm_r(swagger_root) if File.exist?(swagger_root)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,4 +4,4 @@ module Rails
|
||||
end
|
||||
end
|
||||
|
||||
require 'rswag/specs'
|
||||
require 'open_api/rswag/specs'
|
||||
|
||||
Reference in New Issue
Block a user