Gets v3 request example saving as well as response example saving

Adds rubocop to the gemset

adds guard to the gemset for testing
This commit is contained in:
Jay Danielian
2019-07-05 15:59:47 -04:00
parent 5d7fc44af4
commit 297cc447c8
24 changed files with 458 additions and 261 deletions

View File

@@ -1,8 +1,9 @@
# frozen_string_literal: true
require 'rswag/specs/configuration'
module Rswag
module Specs
describe Configuration do
subject { described_class.new(rspec_config) }

View File

@@ -1,8 +1,9 @@
# frozen_string_literal: true
require 'rswag/specs/example_group_helpers'
module Rswag
module Specs
describe ExampleGroupHelpers do
subject { double('example_group') }
@@ -48,12 +49,12 @@ module Rswag
it "adds to the 'operation' metadata" do
expect(api_metadata[:operation]).to match(
tags: [ 'Blogs', 'Admin' ],
tags: %w[Blogs Admin],
description: 'Some description',
operationId: 'createBlog',
consumes: [ 'application/json', 'application/xml' ],
produces: [ 'application/json', 'application/xml' ],
schemes: [ 'http', 'https' ],
consumes: ['application/json', 'application/xml'],
produces: ['application/json', 'application/xml'],
schemes: %w[http https],
deprecated: true
)
end
@@ -74,27 +75,59 @@ module Rswag
it "adds to the 'operation' metadata" do
expect(api_metadata[:operation]).to match(
tags: [ 'Blogs', 'Admin' ],
tags: %w[Blogs Admin],
description: 'Some description',
operationId: 'createBlog',
consumes: [ 'application/json', 'application/xml' ],
produces: [ 'application/json', 'application/xml' ],
schemes: [ 'http', 'https' ],
consumes: ['application/json', 'application/xml'],
produces: ['application/json', 'application/xml'],
schemes: %w[http https],
deprecated: true,
security: { api_key: [] }
)
end
end
describe '#parameter(attributes)' do
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' } } }
)
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' } ]
[name: :blog, in: :body, schema: { type: 'object' }]
)
end
end
@@ -105,7 +138,7 @@ module Rswag
it "adds to the 'operation parameters' metadata" do
expect(api_metadata[:operation][:parameters]).to match(
[ name: :blog, in: :body, schema: { type: 'object' } ]
[name: :blog, in: :body, schema: { type: 'object' }]
)
end
end
@@ -116,7 +149,7 @@ module Rswag
it "automatically sets the 'required' flag" do
expect(api_metadata[:operation][:parameters]).to match(
[ name: :id, in: :path, required: true ]
[name: :id, in: :path, required: true]
)
end
end
@@ -126,7 +159,7 @@ module Rswag
let(:api_metadata) { { operation: {} } }
it "does not require the 'in' parameter key" do
expect(api_metadata[:operation][:parameters]).to match([ name: :id ])
expect(api_metadata[:operation][:parameters]).to match([name: :id])
end
end
end

View File

@@ -1,8 +1,9 @@
# frozen_string_literal: true
require 'rswag/specs/example_helpers'
module Rswag
module Specs
describe ExampleHelpers do
subject { double('example') }
@@ -12,7 +13,7 @@ module Rswag
allow(config).to receive(:get_swagger_doc).and_return(swagger_doc)
stub_const('Rswag::Specs::RAILS_VERSION', 3)
end
let(:config) { double('config') }
let(:config) { double('config') }
let(:swagger_doc) do
{
securityDefinitions: {
@@ -30,7 +31,7 @@ module Rswag
operation: {
verb: :put,
summary: 'Updates a blog',
consumes: [ 'application/json' ],
consumes: ['application/json'],
parameters: [
{ name: :blog_id, in: :path, type: 'integer' },
{ name: 'id', in: :path, type: 'integer' },
@@ -58,8 +59,8 @@ module Rswag
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' }
'{"text":"Some comment"}',
'CONTENT_TYPE' => 'application/json'
)
end
end

View File

@@ -1,15 +1,16 @@
# frozen_string_literal: true
require 'rswag/specs/request_factory'
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(:config) { double('config') }
let(:swagger_doc) { {} }
let(:example) { double('example') }
let(:metadata) do
@@ -53,7 +54,7 @@ module Rswag
allow(example).to receive(:q2).and_return('bar')
end
it "builds the query string from example values" do
it 'builds the query string from example values' do
expect(request[:path]).to eq('/blogs?q1=foo&q2=bar')
end
end
@@ -63,40 +64,40 @@ module Rswag
metadata[:operation][:parameters] = [
{ name: 'things', in: :query, type: :array, collectionFormat: collection_format }
]
allow(example).to receive(:things).and_return([ 'foo', 'bar' ])
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
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
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
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
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
it 'formats as multiple parameter instances' do
expect(request[:path]).to eq('/blogs?things=foo&things=bar')
end
end
@@ -104,12 +105,12 @@ module Rswag
context "'header' parameters" do
before do
metadata[:operation][:parameters] = [ { name: 'Api-Key', in: :header, type: :string } ]
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' })
expect(request[:headers]).to eq('Api-Key' => 'foobar')
end
end
@@ -127,9 +128,9 @@ module Rswag
end
end
context "consumes content" do
context 'consumes content' do
before do
metadata[:operation][:consumes] = [ 'application/json', 'application/xml' ]
metadata[:operation][:consumes] = ['application/json', 'application/xml']
end
context "no 'Content-Type' provided" do
@@ -150,18 +151,18 @@ module Rswag
context 'JSON payload' do
before do
metadata[:operation][:parameters] = [ { name: 'comment', in: :body, schema: { type: 'object' } } ]
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\"}")
expect(request[:payload]).to eq('{"text":"Some comment"}')
end
end
context 'form payload' do
before do
metadata[:operation][:consumes] = [ 'multipart/form-data' ]
metadata[:operation][:consumes] = ['multipart/form-data']
metadata[:operation][:parameters] = [
{ name: 'f1', in: :formData, type: :string },
{ name: 'f2', in: :formData, type: :string }
@@ -181,7 +182,7 @@ module Rswag
context 'produces content' do
before do
metadata[:operation][:produces] = [ 'application/json', 'application/xml' ]
metadata[:operation][:produces] = ['application/json', 'application/xml']
end
context "no 'Accept' value provided" do
@@ -192,7 +193,7 @@ module Rswag
context "explicit 'Accept' value provided" do
before do
allow(example).to receive(:'Accept').and_return('application/xml')
allow(example).to receive(:Accept).and_return('application/xml')
end
it "sets 'HTTP_ACCEPT' header to example value" do
@@ -204,7 +205,7 @@ module Rswag
context 'basic auth' do
before do
swagger_doc[:securityDefinitions] = { basic: { type: :basic } }
metadata[:operation][:security] = [ basic: [] ]
metadata[:operation][:security] = [basic: []]
allow(example).to receive(:Authorization).and_return('Basic foobar')
end
@@ -216,7 +217,7 @@ module Rswag
context 'apiKey' do
before do
swagger_doc[:securityDefinitions] = { apiKey: { type: :apiKey, name: 'api_key', in: key_location } }
metadata[:operation][:security] = [ apiKey: [] ]
metadata[:operation][:security] = [apiKey: []]
allow(example).to receive(:api_key).and_return('foobar')
end
@@ -256,8 +257,8 @@ module Rswag
context 'oauth2' do
before do
swagger_doc[:securityDefinitions] = { oauth2: { type: :oauth2, scopes: [ 'read:blogs' ] } }
metadata[:operation][:security] = [ oauth2: [ 'read:blogs' ] ]
swagger_doc[:securityDefinitions] = { oauth2: { type: :oauth2, scopes: ['read:blogs'] } }
metadata[:operation][:security] = [oauth2: ['read:blogs']]
allow(example).to receive(:Authorization).and_return('Bearer foobar')
end
@@ -272,26 +273,26 @@ module Rswag
basic: { type: :basic },
api_key: { type: :apiKey, name: 'api_key', in: :query }
}
metadata[:operation][:security] = [ { basic: [], api_key: [] } ]
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
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
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 } ]
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
it 'populates operation and path level parameters ' do
expect(request[:path]).to eq('/blogs?q1=foo&q2=bar')
end
end
@@ -299,7 +300,7 @@ module Rswag
context 'referenced parameters' do
before do
swagger_doc[:parameters] = { q1: { name: 'q1', in: :query, type: :string } }
metadata[:operation][:parameters] = [ { '$ref' => '#/parameters/q1' } ]
metadata[:operation][:parameters] = [{ '$ref' => '#/parameters/q1' }]
allow(example).to receive(:q1).and_return('foo')
end
@@ -316,18 +317,18 @@ module Rswag
end
end
context "global consumes" do
before { swagger_doc[:consumes] = [ 'application/xml' ] }
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
context 'global security requirements' do
before do
swagger_doc[:securityDefinitions] = { apiKey: { type: :apiKey, name: 'api_key', in: :query } }
swagger_doc[:security] = [ apiKey: [] ]
swagger_doc[:security] = [apiKey: []]
allow(example).to receive(:api_key).and_return('foobar')
end

View File

@@ -1,15 +1,16 @@
# frozen_string_literal: true
require 'rswag/specs/response_validator'
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(:config) { double('config') }
let(:swagger_doc) { {} }
let(:example) { double('example') }
let(:metadata) do
@@ -20,7 +21,7 @@ module Rswag
schema: {
type: :object,
properties: { text: { type: :string } },
required: [ 'text' ]
required: ['text']
}
}
}
@@ -32,26 +33,26 @@ module Rswag
OpenStruct.new(
code: '200',
headers: { 'X-Rate-Limit-Limit' => '10' },
body: "{\"text\":\"Some comment\"}"
body: '{"text":"Some comment"}'
)
end
context "response matches metadata" do
context 'response matches metadata' do
it { expect { call }.to_not raise_error }
end
context "response code differs from metadata" do
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
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\"}" }
context 'response body differs from metadata' do
before { response.body = '{"foo":"Some comment"}' }
it { expect { call }.to raise_error /Expected response body/ }
end
@@ -61,7 +62,7 @@ module Rswag
'blog' => {
type: :object,
properties: { foo: { type: :string } },
required: [ 'foo' ]
required: ['foo']
}
}
metadata[:response][:schema] = { '$ref' => '#/definitions/blog' }

View File

@@ -1,9 +1,10 @@
# frozen_string_literal: true
require 'rswag/specs/swagger_formatter'
require 'ostruct'
module Rswag
module Specs
describe SwaggerFormatter do
subject { described_class.new(output, config) }
@@ -13,7 +14,7 @@ module Rswag
end
let(:config) { double('config') }
let(:output) { double('output').as_null_object }
let(:swagger_root) { File.expand_path('../tmp/swagger', __FILE__) }
let(:swagger_root) { File.expand_path('tmp/swagger', __dir__) }
describe '#example_group_finished(notification)' do
before do
@@ -47,8 +48,8 @@ module Rswag
end
describe '#stop' do
before do
FileUtils.rm_r(swagger_root) if File.exists?(swagger_root)
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' } }
@@ -64,7 +65,7 @@ module Rswag
end
after do
FileUtils.rm_r(swagger_root) if File.exists?(swagger_root)
FileUtils.rm_r(swagger_root) if File.exist?(swagger_root)
end
end
end