mirror of
https://github.com/ditkrg/rswag.git
synced 2026-01-22 22:06:43 +00:00
Merge branch 'master' of github.com:rswag/rswag
This commit is contained in:
commit
71423cffb6
11
CHANGELOG.md
11
CHANGELOG.md
@ -12,15 +12,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
### Fixed
|
||||
### Security
|
||||
|
||||
## [2.1.0] - 2019-10-17
|
||||
### Added
|
||||
- New Spec Generator [#75](https://github.com/rswag/rswag/pull/75)
|
||||
- Support for Options and Trace verbs; You must use a framework that supports this, for Options Rails 6.1+ Rails 6 does not support Trace. [#237](https://github.com/rswag/rswag/pull/75)
|
||||
### Changed
|
||||
- Update swagger-ui to 3.18.2 [#240](https://github.com/rswag/rswag/pull/240)
|
||||
|
||||
## [2.0.6] - 2019-10-03
|
||||
### Added
|
||||
- Support for Rails 6 [#228](https://github.com/rswag/rswag/pull/228)
|
||||
- Support for Windows paths [#176](https://github.com/rswag/rswag/pull/176)
|
||||
### Changed
|
||||
- Show response body when error code is not expected [#117](https://github.com/rswag/rswag/pull/177)
|
||||
### Deprecated
|
||||
### Removed
|
||||
### Fixed
|
||||
### Security
|
||||
|
||||
## [2.0.5] - 2018-07-10
|
||||
|
||||
@ -14,8 +14,8 @@ Once you have an API that can describe itself in Swagger, you've opened the trea
|
||||
|
||||
|Rswag Version|Swagger (OpenAPI) Spec.|swagger-ui|
|
||||
|----------|----------|----------|
|
||||
|[master](https://github.com/rswag/rswag/tree/master)|2.0|3.17.3|
|
||||
|[2.0.6](https://github.com/rswag/rswag/tree/2.0.6)|2.0|3.17.3|
|
||||
|[master](https://github.com/rswag/rswag/tree/master)|2.0|3.18.2|
|
||||
|[2.1.0](https://github.com/rswag/rswag/tree/2.1.0)|2.0|3.18.2|
|
||||
|[1.6.0](https://github.com/rswag/rswag/tree/1.6.0)|2.0|2.2.5|
|
||||
|
||||
## Getting Started ##
|
||||
@ -48,7 +48,8 @@ Once you have an API that can describe itself in Swagger, you've opened the trea
|
||||
Or run the install generators for each package separately if you installed Rswag as separate gems, as indicated above:
|
||||
|
||||
```ruby
|
||||
rails g rswag:api:install rswag:ui:install
|
||||
rails g rswag:api:install
|
||||
rails g rswag:ui:install
|
||||
RAILS_ENV=test rails g rswag:specs:install
|
||||
```
|
||||
|
||||
|
||||
9
rswag-specs/lib/generators/rspec/USAGE
Normal file
9
rswag-specs/lib/generators/rspec/USAGE
Normal file
@ -0,0 +1,9 @@
|
||||
Description:
|
||||
This creates an RSpec request spec to define Swagger documentation for a
|
||||
controller. It will create a test for each of the controller's methods.
|
||||
|
||||
Example:
|
||||
rails generate rspec:swagger V3::AccountsController
|
||||
|
||||
This will create:
|
||||
spec/requests/v3/accounts_spec.rb
|
||||
22
rswag-specs/lib/generators/rspec/swagger_generator.rb
Normal file
22
rswag-specs/lib/generators/rspec/swagger_generator.rb
Normal file
@ -0,0 +1,22 @@
|
||||
require 'rswag/route_parser'
|
||||
require 'rails/generators'
|
||||
|
||||
module Rspec
|
||||
class SwaggerGenerator < ::Rails::Generators::NamedBase
|
||||
source_root File.expand_path('../templates', __FILE__)
|
||||
|
||||
def setup
|
||||
@routes = Rswag::RouteParser.new(controller_path).routes
|
||||
end
|
||||
|
||||
def create_spec_file
|
||||
template 'spec.rb', File.join('spec', 'requests', "#{controller_path}_spec.rb")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def controller_path
|
||||
file_path.chomp('_controller')
|
||||
end
|
||||
end
|
||||
end
|
||||
30
rswag-specs/lib/generators/rspec/templates/spec.rb
Normal file
30
rswag-specs/lib/generators/rspec/templates/spec.rb
Normal file
@ -0,0 +1,30 @@
|
||||
require 'swagger_helper'
|
||||
|
||||
RSpec.describe '<%= controller_path %>', type: :request do
|
||||
<% @routes.each do | template, path_item | %>
|
||||
path '<%= template %>' do
|
||||
<% unless path_item[:params].empty? -%>
|
||||
# You'll want to customize the parameter types...
|
||||
<% path_item[:params].each do |param| -%>
|
||||
parameter name: '<%= param %>', in: :path, type: :string, description: '<%= param %>'
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
<% path_item[:actions].each do | action, details | %>
|
||||
<%= action %>('<%= details[:summary] %>') do
|
||||
response(200, 'successful') do
|
||||
<% unless path_item[:params].empty? -%>
|
||||
<% path_item[:params].each do |param| -%>
|
||||
let(:<%= param %>) { '123' }
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
|
||||
after do |example|
|
||||
example.metadata[:response][:examples] = { 'application/json' => JSON.parse(response.body, symbolize_names: true) }
|
||||
end
|
||||
run_test!
|
||||
end
|
||||
end
|
||||
<% end -%>
|
||||
end
|
||||
<% end -%>
|
||||
end
|
||||
58
rswag-specs/lib/rswag/route_parser.rb
Normal file
58
rswag-specs/lib/rswag/route_parser.rb
Normal file
@ -0,0 +1,58 @@
|
||||
module Rswag
|
||||
class RouteParser
|
||||
attr_reader :controller
|
||||
|
||||
def initialize(controller)
|
||||
@controller = controller
|
||||
end
|
||||
|
||||
def routes
|
||||
::Rails.application.routes.routes.select do |route|
|
||||
route.defaults[:controller] == controller
|
||||
end.reduce({}) do |tree, route|
|
||||
path = path_from(route)
|
||||
verb = verb_from(route)
|
||||
tree[path] ||= { params: params_from(route), actions: {} }
|
||||
tree[path][:actions][verb] = { summary: summary_from(route) }
|
||||
tree
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def path_from(route)
|
||||
route.path.spec.to_s
|
||||
.chomp('(.:format)') # Ignore any format suffix
|
||||
.gsub(/:([^\/.?]+)/, '{\1}') # Convert :id to {id}
|
||||
end
|
||||
|
||||
def verb_from(route)
|
||||
verb = route.verb
|
||||
if verb.kind_of? String
|
||||
verb.downcase
|
||||
else
|
||||
verb.source.gsub(/[$^]/, '').downcase
|
||||
end
|
||||
end
|
||||
|
||||
def summary_from(route)
|
||||
verb = route.requirements[:action]
|
||||
noun = route.requirements[:controller].split('/').last.singularize
|
||||
|
||||
# Apply a few customizations to make things more readable
|
||||
case verb
|
||||
when 'index'
|
||||
verb = 'list'
|
||||
noun = noun.pluralize
|
||||
when 'destroy'
|
||||
verb = 'delete'
|
||||
end
|
||||
|
||||
"#{verb} #{noun}"
|
||||
end
|
||||
|
||||
def params_from(route)
|
||||
route.segments - ['format']
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -3,7 +3,7 @@ require 'json-schema'
|
||||
module Rswag
|
||||
module Specs
|
||||
class ExtendedSchema < JSON::Schema::Draft4
|
||||
|
||||
|
||||
def initialize
|
||||
super
|
||||
@attributes['type'] = ExtendedTypeAttribute
|
||||
@ -13,7 +13,7 @@ module Rswag
|
||||
end
|
||||
|
||||
class ExtendedTypeAttribute < JSON::Schema::TypeV4Attribute
|
||||
|
||||
|
||||
def self.validate(current_schema, data, fragments, processor, validator, options={})
|
||||
return if data.nil? && current_schema.schema['x-nullable'] == true
|
||||
super
|
||||
|
||||
@ -5,6 +5,10 @@ module Rswag
|
||||
rake_tasks do
|
||||
load File.expand_path('../../../tasks/rswag-specs_tasks.rake', __FILE__)
|
||||
end
|
||||
|
||||
generators do
|
||||
require 'generators/rspec/swagger/swagger_generator.rb'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -54,7 +54,7 @@ module Rswag
|
||||
definitions[key]
|
||||
end
|
||||
|
||||
def add_verb(request, metadata)
|
||||
def add_verb(request, metadata)
|
||||
request[:verb] = metadata[:operation][:verb]
|
||||
end
|
||||
|
||||
@ -104,7 +104,7 @@ module Rswag
|
||||
end
|
||||
|
||||
# Content-Type header
|
||||
consumes = metadata[:operation][:consumes] || swagger_doc[:consumes]
|
||||
consumes = metadata[:operation][:consumes] || swagger_doc[:consumes]
|
||||
if consumes
|
||||
content_type = example.respond_to?(:'Content-Type') ? example.send(:'Content-Type') : consumes.first
|
||||
tuples << [ 'Content-Type', content_type ]
|
||||
|
||||
44
rswag-specs/spec/generators/rspec/swagger_generator_spec.rb
Normal file
44
rswag-specs/spec/generators/rspec/swagger_generator_spec.rb
Normal file
@ -0,0 +1,44 @@
|
||||
require 'generator_spec'
|
||||
require 'generators/rspec/swagger_generator'
|
||||
require 'tmpdir'
|
||||
|
||||
module Rspec
|
||||
describe SwaggerGenerator do
|
||||
include GeneratorSpec::TestCase
|
||||
destination Dir.mktmpdir
|
||||
|
||||
before(:all) do
|
||||
prepare_destination
|
||||
fixtures_dir = File.expand_path('../fixtures', __FILE__)
|
||||
FileUtils.cp_r("#{fixtures_dir}/spec", destination_root)
|
||||
end
|
||||
|
||||
after(:all) do
|
||||
|
||||
end
|
||||
|
||||
it 'installs the swagger_helper for rspec' do
|
||||
allow_any_instance_of(Rswag::RouteParser).to receive(:routes).and_return(fake_routes)
|
||||
run_generator ['Posts::CommentsController']
|
||||
|
||||
assert_file('spec/requests/posts/comments_spec.rb') do |content|
|
||||
assert_match(/parameter name: 'post_id', in: :path, type: :string/, content)
|
||||
assert_match(/patch\('update_comments comment'\)/, content)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def fake_routes
|
||||
{
|
||||
"/posts/{post_id}/comments/{id}" => {
|
||||
:params => ["post_id", "id"],
|
||||
:actions => {
|
||||
"get" => { :summary=>"show comment" },
|
||||
"patch" => { :summary=>"update_comments comment" }
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -4,7 +4,7 @@ require 'generators/rswag/specs/install/install_generator'
|
||||
module Rswag
|
||||
module Specs
|
||||
|
||||
describe InstallGenerator do
|
||||
RSpec.describe InstallGenerator do
|
||||
include GeneratorSpec::TestCase
|
||||
destination File.expand_path('../tmp', __FILE__)
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ require 'rswag/specs/configuration'
|
||||
module Rswag
|
||||
module Specs
|
||||
|
||||
describe Configuration do
|
||||
RSpec.describe Configuration do
|
||||
subject { described_class.new(rspec_config) }
|
||||
|
||||
let(:rspec_config) { OpenStruct.new(swagger_root: swagger_root, swagger_docs: swagger_docs) }
|
||||
|
||||
@ -3,7 +3,7 @@ require 'rswag/specs/example_group_helpers'
|
||||
module Rswag
|
||||
module Specs
|
||||
|
||||
describe ExampleGroupHelpers do
|
||||
RSpec.describe ExampleGroupHelpers do
|
||||
subject { double('example_group') }
|
||||
|
||||
before do
|
||||
|
||||
@ -3,7 +3,7 @@ require 'rswag/specs/example_helpers'
|
||||
module Rswag
|
||||
module Specs
|
||||
|
||||
describe ExampleHelpers do
|
||||
RSpec.describe ExampleHelpers do
|
||||
subject { double('example') }
|
||||
|
||||
before do
|
||||
@ -12,7 +12,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: {
|
||||
|
||||
@ -3,13 +3,13 @@ require 'rswag/specs/request_factory'
|
||||
module Rswag
|
||||
module Specs
|
||||
|
||||
describe RequestFactory do
|
||||
RSpec.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
|
||||
|
||||
@ -3,13 +3,13 @@ require 'rswag/specs/response_validator'
|
||||
module Rswag
|
||||
module Specs
|
||||
|
||||
describe ResponseValidator do
|
||||
RSpec.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
|
||||
|
||||
@ -3,8 +3,8 @@ require 'ostruct'
|
||||
|
||||
module Rswag
|
||||
module Specs
|
||||
|
||||
describe SwaggerFormatter do
|
||||
|
||||
RSpec.describe SwaggerFormatter do
|
||||
subject { described_class.new(output, config) }
|
||||
|
||||
# Mock out some infrastructure
|
||||
@ -47,7 +47,7 @@ module Rswag
|
||||
end
|
||||
|
||||
describe '#stop' do
|
||||
before do
|
||||
before do
|
||||
FileUtils.rm_r(swagger_root) if File.exists?(swagger_root)
|
||||
allow(config).to receive(:swagger_docs).and_return(
|
||||
'v1/swagger.json' => { info: { version: 'v1' } },
|
||||
|
||||
6
rswag-ui/package-lock.json
generated
6
rswag-ui/package-lock.json
generated
@ -5,9 +5,9 @@
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"swagger-ui-dist": {
|
||||
"version": "3.17.3",
|
||||
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-3.17.3.tgz",
|
||||
"integrity": "sha1-37lkCMzEZ3UVX3NpGQxdSyAW/lw="
|
||||
"version": "3.18.2",
|
||||
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-3.18.2.tgz",
|
||||
"integrity": "sha512-pWAEiKkgWUJvjmLW9AojudnutJ+NTn5g6OdNLj1iIJWwCkoy40K3Upwa24DqFbmIE4vLX4XplND61hp2L+s5vg=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,6 @@
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"swagger-ui-dist": "3.17.3"
|
||||
"swagger-ui-dist": "3.18.2"
|
||||
}
|
||||
}
|
||||
|
||||
2
test-app/app/assets/config/manifest.js
Normal file
2
test-app/app/assets/config/manifest.js
Normal file
@ -0,0 +1,2 @@
|
||||
//= link_tree ../images
|
||||
//= link_directory ../stylesheets .css
|
||||
0
test-app/app/assets/images/.keep
Normal file
0
test-app/app/assets/images/.keep
Normal file
@ -2,15 +2,15 @@
|
||||
# of editing this file, please use the migrations feature of Active Record to
|
||||
# incrementally modify your database, and then regenerate this schema definition.
|
||||
#
|
||||
# This file is the source Rails uses to define your schema when running `rails
|
||||
# db:schema:load`. When creating a new database, `rails db:schema:load` tends to
|
||||
# be faster and is potentially less error prone than running all of your
|
||||
# migrations from scratch. Old migrations may fail to apply correctly if those
|
||||
# migrations use external dependencies or application code.
|
||||
# Note that this schema.rb definition is the authoritative source for your
|
||||
# database schema. If you need to create the application database on another
|
||||
# system, you should be using db:schema:load, not running all the migrations
|
||||
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
||||
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 2016_02_18_212104) do
|
||||
ActiveRecord::Schema.define(version: 20160218212104) do
|
||||
|
||||
create_table "blogs", force: :cascade do |t|
|
||||
t.string "title"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
require 'rails_helper'
|
||||
|
||||
feature 'swagger-ui', js: true do
|
||||
RSpec.feature 'swagger-ui', js: true do
|
||||
|
||||
scenario 'browsing api-docs' do
|
||||
visit '/api-docs'
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
require 'swagger_helper'
|
||||
|
||||
describe 'Auth Tests API', type: :request, swagger_doc: 'v1/swagger.json' do
|
||||
RSpec.describe 'Auth Tests API', type: :request, swagger_doc: 'v1/swagger.json' do
|
||||
|
||||
path '/auth-tests/basic' do
|
||||
post 'Authenticates with basic auth' do
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
require 'swagger_helper'
|
||||
|
||||
describe 'Blogs API', type: :request, swagger_doc: 'v1/swagger.json' do
|
||||
RSpec.describe 'Blogs API', type: :request, swagger_doc: 'v1/swagger.json' do
|
||||
let(:api_key) { 'fake_key' }
|
||||
|
||||
path '/blogs' do
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
require 'spec_helper'
|
||||
require 'rake'
|
||||
|
||||
describe 'rswag:specs:swaggerize' do
|
||||
RSpec.describe 'rswag:specs:swaggerize' do
|
||||
let(:swagger_root) { Rails.root.to_s + '/swagger' }
|
||||
before do
|
||||
before do
|
||||
TestApp::Application.load_tasks
|
||||
FileUtils.rm_r(swagger_root) if File.exists?(swagger_root)
|
||||
end
|
||||
|
||||
Loading…
Reference in New Issue
Block a user