diff --git a/rswag-api/lib/generators/rswag/api/install/templates/rswag_api.rb b/rswag-api/lib/generators/rswag/api/install/templates/rswag_api.rb index 28d4297..5f3ddc4 100644 --- a/rswag-api/lib/generators/rswag/api/install/templates/rswag_api.rb +++ b/rswag-api/lib/generators/rswag/api/install/templates/rswag_api.rb @@ -1,4 +1,4 @@ -OpenApi::Rswag::Api.configure do |c| +Rswag::Api.configure do |c| # Specify a root folder where Swagger JSON files are located # This is used by the Swagger middleware to serve requests for API descriptions diff --git a/rswag-api/spec/rswag/api/middleware_spec.rb b/rswag-api/spec/rswag/api/middleware_spec.rb index 3ff0594..e8cc23a 100644 --- a/rswag-api/spec/rswag/api/middleware_spec.rb +++ b/rswag-api/spec/rswag/api/middleware_spec.rb @@ -61,7 +61,7 @@ module Rswag it 'locates files at the provided swagger_root' do expect(response.length).to eql(3) expect(response[1]).to include( 'Content-Type' => 'application/json') - expect(response[2].join).to include('"swagger":"2.0"') + expect(response[2].join).to include('"openapi":"3.0.1"') end end diff --git a/test-app/db/schema.rb b/test-app/db/schema.rb index 8accba1..440d919 100644 --- a/test-app/db/schema.rb +++ b/test-app/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160218212104) do +ActiveRecord::Schema.define(version: 2016_02_18_212104) do create_table "blogs", force: :cascade do |t| t.string "title" diff --git a/test-app/spec/integration/blogs_spec.rb b/test-app/spec/integration/blogs_spec.rb index d395dc7..f9c66a9 100644 --- a/test-app/spec/integration/blogs_spec.rb +++ b/test-app/spec/integration/blogs_spec.rb @@ -1,5 +1,3 @@ -# frozen_string_literal: true - require 'swagger_helper' RSpec.describe 'Blogs API', type: :request, swagger_doc: 'v1/swagger.json' do @@ -12,24 +10,19 @@ RSpec.describe 'Blogs API', type: :request, swagger_doc: 'v1/swagger.json' do operationId 'createBlog' consumes 'application/json' produces 'application/json' + parameter name: :blog, in: :body, schema: { '$ref' => '#/definitions/blog' } - request_body_json schema: { '$ref' => '#/components/schemas/blog' }, - examples: :blog - - request_body_text_plain - request_body_xml schema: { '$ref' => '#/components/schemas/blog' } - - let(:blog) { { blog: { title: 'foo', content: 'bar' } } } + let(:blog) { { title: 'foo', content: 'bar' } } response '201', 'blog created' do - schema '$ref' => '#/components/schemas/blog' + # schema '$ref' => '#/definitions/blog' run_test! end response '422', 'invalid request' do - schema '$ref' => '#/components/schemas/errors_object' - let(:blog) { { blog: { title: 'foo' } } } + schema '$ref' => '#/definitions/errors_object' + let(:blog) { { title: 'foo' } } run_test! do |response| expect(response.body).to include("can't be blank") end @@ -46,69 +39,18 @@ RSpec.describe 'Blogs API', type: :request, swagger_doc: 'v1/swagger.json' do let(:keywords) { 'foo bar' } response '200', 'success' do - schema type: 'array', items: { '$ref' => '#/components/schemas/blog' } - run_test! + schema type: 'array', items: { '$ref' => '#/definitions/blog' } end response '406', 'unsupported accept header' do - let(:Accept) { 'application/foo' } + let(:'Accept') { 'application/foo' } run_test! end end end - path '/blogs/flexible' do - post 'Creates a blog flexible body' do - tags 'Blogs' - description 'Creates a flexible blog from provided data' - operationId 'createFlexibleBlog' - consumes 'application/json' - produces 'application/json' - - request_body_json schema: { - :oneOf => [{'$ref' => '#/components/schemas/blog'}, - {'$ref' => '#/components/schemas/flexible_blog'}] - }, - examples: :flexible_blog - - let(:flexible_blog) { { blog: { headline: 'my headline', text: 'my text' } } } - - response '201', 'flexible blog created' do - schema :oneOf => [{'$ref' => '#/components/schemas/blog'},{'$ref' => '#/components/schemas/flexible_blog'}] - run_test! - end - end - end - - path '/blogs/alternate' do - post 'Creates a blog - different :examples in requestBody' do - tags 'Blogs' - description 'Creates a new blog from provided data' - operationId 'createAlternateBlog' - consumes 'application/json' - produces 'application/json' - - # NOTE: the externalValue: http://... is valid 3.0 spec, but swagger-UI does NOT support it yet - # https://github.com/swagger-api/swagger-ui/issues/5433 - request_body_json schema: { '$ref' => '#/components/schemas/blog' }, - examples: [:blog, {name: :external_blog, - externalValue: 'http://api.sample.org/myjson_example'}, - {name: :another_example, - '$ref' => '#/components/examples/flexible_blog_example'}] - - let(:blog) { { blog: { title: 'alt title', content: 'alt bar' } } } - - response '201', 'blog created' do - schema '$ref' => '#/components/schemas/blog' - run_test! - end - end - end - - - path '/blogs/{id}' do - + parameter name: :id, in: :path, type: :string let(:id) { blog.id } let(:blog) { Blog.create(title: 'foo', content: 'bar', thumbnail: 'thumbnail.png') } @@ -119,14 +61,12 @@ RSpec.describe 'Blogs API', type: :request, swagger_doc: 'v1/swagger.json' do operationId 'getBlog' produces 'application/json' - parameter name: :id, in: :path, type: :string - response '200', 'blog found' do header 'ETag', type: :string header 'Last-Modified', type: :string header 'Cache-Control', type: :string - schema '$ref' => '#/components/schemas/blog' + schema '$ref' => '#/definitions/blog' examples 'application/json' => { id: 1, @@ -146,23 +86,21 @@ RSpec.describe 'Blogs API', type: :request, swagger_doc: 'v1/swagger.json' do end end - path '/blogs/{id}/upload' do + parameter name: :id, in: :path, type: :string + let(:id) { blog.id } let(:blog) { Blog.create(title: 'foo', content: 'bar') } put 'Uploads a blog thumbnail' do - parameter name: :id, in: :path, type: :string - tags 'Blogs' description 'Upload a thumbnail for specific blog by id' operationId 'uploadThumbnailBlog' consumes 'multipart/form-data' - - request_body_multipart schema: {properties: {:orderId => { type: :integer }, file: { type: :string, format: :binary }} } + parameter name: :file, :in => :formData, :type => :file, required: true response '200', 'blog updated' do - let(:file) { Rack::Test::UploadedFile.new(Rails.root.join('spec/fixtures/thumbnail.png')) } + let(:file) { Rack::Test::UploadedFile.new(Rails.root.join("spec/fixtures/thumbnail.png")) } run_test! end end diff --git a/test-app/spec/integration/new_blogs_spec.rb b/test-app/spec/integration/new_blogs_spec.rb new file mode 100644 index 0000000..9706648 --- /dev/null +++ b/test-app/spec/integration/new_blogs_spec.rb @@ -0,0 +1,170 @@ +# # frozen_string_literal: true + +# require 'swagger_helper' + +# RSpec.describe 'Blogs API', type: :request, swagger_doc: 'v1/swagger.json' do +# let(:api_key) { 'fake_key' } + +# path '/blogs' do +# post 'Creates a blog' do +# tags 'Blogs' +# description 'Creates a new blog from provided data' +# operationId 'createBlog' +# consumes 'application/json' +# produces 'application/json' + +# request_body_json schema: { '$ref' => '#/components/schemas/blog' }, +# examples: :blog + +# request_body_text_plain +# request_body_xml schema: { '$ref' => '#/components/schemas/blog' } + +# let(:blog) { { blog: { title: 'foo', content: 'bar' } } } + +# response '201', 'blog created' do +# schema '$ref' => '#/components/schemas/blog' +# run_test! +# end + +# response '422', 'invalid request' do +# schema '$ref' => '#/components/schemas/errors_object' +# let(:blog) { { blog: { title: 'foo' } } } + +# run_test! do |response| +# expect(response.body).to include("can't be blank") +# end +# end +# end + +# get 'Searches blogs' do +# tags 'Blogs' +# description 'Searches blogs by keywords' +# operationId 'searchBlogs' +# produces 'application/json' +# parameter name: :keywords, in: :query, type: 'string' + +# let(:keywords) { 'foo bar' } + +# response '200', 'success' do +# schema type: 'array', items: { '$ref' => '#/components/schemas/blog' } +# run_test! +# end + +# response '406', 'unsupported accept header' do +# let(:Accept) { 'application/foo' } +# run_test! +# end +# end +# end + +# path '/blogs/flexible' do +# post 'Creates a blog flexible body' do +# tags 'Blogs' +# description 'Creates a flexible blog from provided data' +# operationId 'createFlexibleBlog' +# consumes 'application/json' +# produces 'application/json' + +# request_body_json schema: { +# :oneOf => [{'$ref' => '#/components/schemas/blog'}, +# {'$ref' => '#/components/schemas/flexible_blog'}] +# }, +# examples: :flexible_blog + +# let(:flexible_blog) { { blog: { headline: 'my headline', text: 'my text' } } } + +# response '201', 'flexible blog created' do +# schema :oneOf => [{'$ref' => '#/components/schemas/blog'},{'$ref' => '#/components/schemas/flexible_blog'}] +# run_test! +# end +# end +# end + +# path '/blogs/alternate' do +# post 'Creates a blog - different :examples in requestBody' do +# tags 'Blogs' +# description 'Creates a new blog from provided data' +# operationId 'createAlternateBlog' +# consumes 'application/json' +# produces 'application/json' + +# # NOTE: the externalValue: http://... is valid 3.0 spec, but swagger-UI does NOT support it yet +# # https://github.com/swagger-api/swagger-ui/issues/5433 +# request_body_json schema: { '$ref' => '#/components/schemas/blog' }, +# examples: [:blog, {name: :external_blog, +# externalValue: 'http://api.sample.org/myjson_example'}, +# {name: :another_example, +# '$ref' => '#/components/examples/flexible_blog_example'}] + +# let(:blog) { { blog: { title: 'alt title', content: 'alt bar' } } } + +# response '201', 'blog created' do +# schema '$ref' => '#/components/schemas/blog' +# run_test! +# end +# end +# end + + + +# path '/blogs/{id}' do + + +# let(:id) { blog.id } +# let(:blog) { Blog.create(title: 'foo', content: 'bar', thumbnail: 'thumbnail.png') } + +# get 'Retrieves a blog' do +# tags 'Blogs' +# description 'Retrieves a specific blog by id' +# operationId 'getBlog' +# produces 'application/json' + +# parameter name: :id, in: :path, type: :string + +# response '200', 'blog found' do +# header 'ETag', type: :string +# header 'Last-Modified', type: :string +# header 'Cache-Control', type: :string + +# schema '$ref' => '#/components/schemas/blog' + +# examples 'application/json' => { +# id: 1, +# title: 'Hello world!', +# content: 'Hello world and hello universe. Thank you all very much!!!', +# thumbnail: 'thumbnail.png' +# } + +# let(:id) { blog.id } +# run_test! +# end + +# response '404', 'blog not found' do +# let(:id) { 'invalid' } +# run_test! +# end +# end +# end + + +# path '/blogs/{id}/upload' do +# let(:id) { blog.id } +# let(:blog) { Blog.create(title: 'foo', content: 'bar') } + +# put 'Uploads a blog thumbnail' do +# parameter name: :id, in: :path, type: :string + +# tags 'Blogs' +# description 'Upload a thumbnail for specific blog by id' +# operationId 'uploadThumbnailBlog' +# consumes 'multipart/form-data' + +# request_body_multipart schema: {properties: {:orderId => { type: :integer }, file: { type: :string, format: :binary }} } + +# response '200', 'blog updated' do +# let(:file) { Rack::Test::UploadedFile.new(Rails.root.join('spec/fixtures/thumbnail.png')) } +# run_test! +# end +# end +# end +# end diff --git a/test-app/spec/swagger_helper.rb b/test-app/spec/swagger_helper.rb index 06f597b..e19a1d3 100644 --- a/test-app/spec/swagger_helper.rb +++ b/test-app/spec/swagger_helper.rb @@ -32,63 +32,39 @@ RSpec.configure do |config| } } ], - - components: { - schemas: { - errors_object: { - type: 'object', - properties: { - errors: { '$ref' => '#/components/schemas/errors_map' } - } - }, - errors_map: { - type: 'object', - additionalProperties: { - type: 'array', - items: { type: 'string' } - } - }, - blog: { - type: 'object', - properties: { - id: { type: 'integer' }, - title: { type: 'string' }, - content: { type: 'string', nullable: true }, - thumbnail: { type: 'string', nullable: true } - }, - required: %w[id title] - }, - flexible_blog: { - type: 'object', - properties: { - id: { type: 'integer' }, - headline: { type: 'string' }, - text: { type: 'string', nullable: true }, - thumbnail: { type: 'string', nullable:true } - }, - required: %w[id headline] + definitions: { + errors_object: { + type: 'object', + properties: { + errors: { '$ref' => '#/definitions/errors_map' } } }, - examples: { - flexible_blog_example: { - summary: 'Sample example of a flexible blog', - value: { - id: 1, - headline: 'This is a headline', - text: 'Some sample text' - } - } - }, - securitySchemes: { - basic_auth: { - type: :http, - scheme: :basic - }, - api_key: { - type: :apiKey, - name: 'api_key', - in: :query + errors_map: { + type: 'object', + additionalProperties: { + type: 'array', + items: { type: 'string' } } + }, + blog: { + type: 'object', + properties: { + id: { type: 'integer' }, + title: { type: 'string' }, + content: { type: 'string', 'x-nullable': true }, + thumbnail: { type: 'string'} + }, + required: [ 'id', 'title', 'content', 'thumbnail' ] + } + }, + securityDefinitions: { + basic_auth: { + type: :basic + }, + api_key: { + type: :apiKey, + name: 'api_key', + in: :query } } } diff --git a/test-app/swagger/v1/swagger.json b/test-app/swagger/v1/swagger.json index ed7938c..5deaf19 100644 --- a/test-app/swagger/v1/swagger.json +++ b/test-app/swagger/v1/swagger.json @@ -88,71 +88,29 @@ ], "description": "Creates a new blog from provided data", "operationId": "createBlog", - "requestBody": { - "required": true, - "content": { - "application/json": { - "examples": { - "blog": { - "value": { - "blog": { - "title": "foo", - "content": "bar" - } - } - } - }, - "schema": { - "$ref": "#/components/schemas/blog" - } - }, - "test/plain": { - "schema": { - "type": "string" - } - }, - "application/xml": { - "schema": { - "$ref": "#/components/schemas/blog" - } + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "blog", + "in": "body", + "schema": { + "$ref": "#/definitions/blog" } } - }, - "parameters": [ - ], "responses": { "201": { - "description": "blog created", - "content": { - "application/json": { - "example": { - "id": 1, - "title": "foo", - "content": "bar", - "thumbnail": null - }, - "schema": { - "$ref": "#/components/schemas/blog" - } - } - } + "description": "blog created" }, "422": { "description": "invalid request", - "content": { - "application/json": { - "example": { - "errors": { - "content": [ - "can't be blank" - ] - } - }, - "schema": { - "$ref": "#/components/schemas/errors_object" - } - } + "schema": { + "$ref": "#/definitions/errors_object" } } } @@ -164,158 +122,32 @@ ], "description": "Searches blogs by keywords", "operationId": "searchBlogs", + "produces": [ + "application/json" + ], "parameters": [ { "name": "keywords", "in": "query", - "schema": { - "type": "string" - } + "type": "string" } ], "responses": { - "200": { - "description": "success", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/blog" - } - } - } - } - }, "406": { "description": "unsupported accept header" } } } }, - "/blogs/flexible": { - "post": { - "summary": "Creates a blog flexible body", - "tags": [ - "Blogs" - ], - "description": "Creates a flexible blog from provided data", - "operationId": "createFlexibleBlog", - "requestBody": { - "required": true, - "content": { - "application/json": { - "examples": { - "flexible_blog": { - "value": { - "blog": { - "headline": "my headline", - "text": "my text" - } - } - } - }, - "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/blog" - }, - { - "$ref": "#/components/schemas/flexible_blog" - } - ] - } - } - } - }, - "parameters": [ - - ], - "responses": { - "201": { - "description": "flexible blog created", - "content": { - "application/json": { - "example": { - "id": 1, - "title": "my headline", - "content": "my text", - "thumbnail": null - }, - "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/blog" - }, - { - "$ref": "#/components/schemas/flexible_blog" - } - ] - } - } - } - } - } - } - }, - "/blogs/alternate": { - "post": { - "summary": "Creates a blog - different :examples in requestBody", - "tags": [ - "Blogs" - ], - "description": "Creates a new blog from provided data", - "operationId": "createAlternateBlog", - "requestBody": { - "required": true, - "content": { - "application/json": { - "examples": { - "blog": { - "value": { - "blog": { - "title": "alt title", - "content": "alt bar" - } - } - }, - "external_blog": { - "externalValue": "http://api.sample.org/myjson_example" - }, - "another_example": { - "$ref": "#/components/examples/flexible_blog_example" - } - }, - "schema": { - "$ref": "#/components/schemas/blog" - } - } - } - }, - "parameters": [ - - ], - "responses": { - "201": { - "description": "blog created", - "content": { - "application/json": { - "example": { - "id": 1, - "title": "alt title", - "content": "alt bar", - "thumbnail": null - }, - "schema": { - "$ref": "#/components/schemas/blog" - } - } - } - } - } - } - }, "/blogs/{id}": { + "parameters": [ + { + "name": "id", + "in": "path", + "type": "string", + "required": true + } + ], "get": { "summary": "Retrieves a blog", "tags": [ @@ -323,47 +155,32 @@ ], "description": "Retrieves a specific blog by id", "operationId": "getBlog", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } + "produces": [ + "application/json" ], "responses": { "200": { "description": "blog found", "headers": { "ETag": { - "schema": { - "type": "string" - } + "type": "string" }, "Last-Modified": { - "schema": { - "type": "string" - } + "type": "string" }, "Cache-Control": { - "schema": { - "type": "string" - } + "type": "string" } }, - "content": { + "schema": { + "$ref": "#/definitions/blog" + }, + "examples": { "application/json": { - "example": { - "id": 1, - "title": "Hello world!", - "content": "Hello world and hello universe. Thank you all very much!!!", - "thumbnail": "thumbnail.png" - }, - "schema": { - "$ref": "#/components/schemas/blog" - } + "id": 1, + "title": "Hello world!", + "content": "Hello world and hello universe. Thank you all very much!!!", + "thumbnail": "thumbnail.png" } } }, @@ -374,40 +191,32 @@ } }, "/blogs/{id}/upload": { + "parameters": [ + { + "name": "id", + "in": "path", + "type": "string", + "required": true + } + ], "put": { "summary": "Uploads a blog thumbnail", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], "tags": [ "Blogs" ], "description": "Upload a thumbnail for specific blog by id", "operationId": "uploadThumbnailBlog", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "properties": { - "orderId": { - "type": "integer" - }, - "file": { - "type": "string", - "format": "binary" - } - } - } - } + "consumes": [ + "multipart/form-data" + ], + "parameters": [ + { + "name": "file", + "in": "formData", + "type": "file", + "required": true } - }, + ], "responses": { "200": { "description": "blog updated" @@ -426,92 +235,57 @@ } } ], - "components": { - "schemas": { - "errors_object": { - "type": "object", - "properties": { - "errors": { - "$ref": "#/components/schemas/errors_map" - } - } - }, - "errors_map": { - "type": "object", - "additionalProperties": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "blog": { - "type": "object", - "properties": { - "id": { - "type": "integer" - }, - "title": { - "type": "string" - }, - "content": { - "type": "string", - "nullable": true - }, - "thumbnail": { - "type": "string", - "nullable": true - } - }, - "required": [ - "id", - "title" - ] - }, - "flexible_blog": { - "type": "object", - "properties": { - "id": { - "type": "integer" - }, - "headline": { - "type": "string" - }, - "text": { - "type": "string", - "nullable": true - }, - "thumbnail": { - "type": "string", - "nullable": true - } - }, - "required": [ - "id", - "headline" - ] - } - }, - "examples": { - "flexible_blog_example": { - "summary": "Sample example of a flexible blog", - "value": { - "id": 1, - "headline": "This is a headline", - "text": "Some sample text" + "definitions": { + "errors_object": { + "type": "object", + "properties": { + "errors": { + "$ref": "#/definitions/errors_map" } } }, - "securitySchemes": { - "basic_auth": { - "type": "http", - "scheme": "basic" - }, - "api_key": { - "type": "apiKey", - "name": "api_key", - "in": "query" + "errors_map": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } } + }, + "blog": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "content": { + "type": "string", + "x-nullable": true + }, + "thumbnail": { + "type": "string" + } + }, + "required": [ + "id", + "title", + "content", + "thumbnail" + ] + } + }, + "securityDefinitions": { + "basic_auth": { + "type": "basic" + }, + "api_key": { + "type": "apiKey", + "name": "api_key", + "in": "query" } } } \ No newline at end of file