Compare commits
No commits in common. "master" and "1.6.0" have entirely different histories.
17
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -1,17 +0,0 @@
|
|||||||
## Describe the bug
|
|
||||||
A clear and concise description of what the bug is.
|
|
||||||
|
|
||||||
## Steps to Test or Reproduce
|
|
||||||
Please provide an example repo or the steps to reproduce the behavior.
|
|
||||||
|
|
||||||
## Expected behavior
|
|
||||||
A clear and concise description of what you expected to happen.
|
|
||||||
|
|
||||||
## Screenshots
|
|
||||||
If applicable, add screenshots to help explain your problem.
|
|
||||||
|
|
||||||
## Additional context
|
|
||||||
Add any other context about the problem here.
|
|
||||||
|
|
||||||
## Rswag Version
|
|
||||||
The version of rswag are you using.
|
|
||||||
11
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@ -1,11 +0,0 @@
|
|||||||
## Is your feature request related to a problem? Please describe.
|
|
||||||
A clear and concise description of what the problem is.
|
|
||||||
|
|
||||||
## Describe the solution you'd like
|
|
||||||
A clear and concise description of what you want to happen.
|
|
||||||
|
|
||||||
## Describe alternatives you've considered
|
|
||||||
A clear and concise description of any alternative solutions or features you've considered.
|
|
||||||
|
|
||||||
## Additional context
|
|
||||||
Add any other context or screenshots about the feature request here.
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
## Problem
|
|
||||||
A clear and concise description of what the problem is.
|
|
||||||
|
|
||||||
## Solution
|
|
||||||
A clear and concise description of what the solution is.
|
|
||||||
|
|
||||||
### Related Issues
|
|
||||||
Links to any related issues.
|
|
||||||
|
|
||||||
### Checklist
|
|
||||||
- [ ] Added tests
|
|
||||||
- [ ] Changelog updated
|
|
||||||
|
|
||||||
### Steps to Test or Reproduce
|
|
||||||
Outline the steps to test or reproduce the PR here.
|
|
||||||
60
.github/workflows/ruby.yml
vendored
@ -1,60 +0,0 @@
|
|||||||
name: Ruby
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ master ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ master ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
ruby: [2.6, 2.7, truffleruby-head]
|
|
||||||
rails: [5.2.4.4, 6.0.3.4]
|
|
||||||
env:
|
|
||||||
RAILS_VERSION: ${{ matrix.rails }}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- uses: ruby/setup-ruby@v1
|
|
||||||
with: { ruby-version: 2.6 }
|
|
||||||
|
|
||||||
- uses: actions/cache@v2
|
|
||||||
id: cache
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
rswag-ui/node_modules
|
|
||||||
vendor/bundle
|
|
||||||
key: ${{ runner.os }}-ruby_${{ matrix.ruby }}-rails_${{ matrix.rails }}-${{ hashFiles('Gemfile', '**/package-lock.json') }}
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
gem update --system
|
|
||||||
bundle install
|
|
||||||
cd rswag-ui && npm install
|
|
||||||
|
|
||||||
- name: rswag-api
|
|
||||||
run: |
|
|
||||||
cd rswag-api
|
|
||||||
bundle exec rspec
|
|
||||||
|
|
||||||
- name: rswag-specs
|
|
||||||
if: success() || failure()
|
|
||||||
run: |
|
|
||||||
cd rswag-specs
|
|
||||||
bundle exec rspec
|
|
||||||
|
|
||||||
- name: rswag-ui
|
|
||||||
if: success() || failure()
|
|
||||||
run: |
|
|
||||||
cd rswag-ui
|
|
||||||
bundle exec rspec
|
|
||||||
|
|
||||||
- name: test-app
|
|
||||||
if: success() || failure()
|
|
||||||
run: |
|
|
||||||
cd test-app
|
|
||||||
bundle exec rake db:migrate db:test:prepare
|
|
||||||
bundle exec rspec
|
|
||||||
3
.gitignore
vendored
@ -3,8 +3,5 @@
|
|||||||
**/*/*.gem
|
**/*/*.gem
|
||||||
**/*/*.sqlite3
|
**/*/*.sqlite3
|
||||||
**/*/public/assets
|
**/*/public/assets
|
||||||
**/*/node_modules
|
|
||||||
*.swp
|
*.swp
|
||||||
Gemfile.lock
|
Gemfile.lock
|
||||||
/.idea/
|
|
||||||
**/.byebug_history
|
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
2.7.2
|
2.3.1
|
||||||
|
|||||||
31
.travis.yml
@ -1,27 +1,23 @@
|
|||||||
language: ruby
|
language: ruby
|
||||||
|
|
||||||
dist: bionic
|
|
||||||
services:
|
|
||||||
- xvfb
|
|
||||||
|
|
||||||
rvm:
|
rvm:
|
||||||
- 2.6.3
|
- 2.2.5
|
||||||
|
|
||||||
env:
|
env:
|
||||||
- RAILS_VERSION=6.0.0
|
- RAILS_VERSION=5.1.2
|
||||||
- RAILS_VERSION=5.2.0
|
- RAILS_VERSION=4.2.0
|
||||||
|
- RAILS_VERSION=3.2.22
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- libqtwebkit-dev
|
|
||||||
- libqtwebkit4
|
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
directories:
|
directories:
|
||||||
- /home/travis/.rvm/gems/ruby-2.6.3
|
- /home/travis/.rvm/gems/ruby-2.2.5
|
||||||
|
|
||||||
install: ./ci/build.sh
|
install: bundle install
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- export DISPLAY=:99.0
|
||||||
|
- sh -e /etc/init.d/xvfb start
|
||||||
|
- sleep 3
|
||||||
|
|
||||||
script: ./ci/test.sh
|
script: ./ci/test.sh
|
||||||
|
|
||||||
@ -29,7 +25,6 @@ jobs:
|
|||||||
include:
|
include:
|
||||||
- stage: publish components
|
- stage: publish components
|
||||||
script: 'cd rswag-api'
|
script: 'cd rswag-api'
|
||||||
if: tag IS present
|
|
||||||
deploy:
|
deploy:
|
||||||
gemspec: rswag-api.gemspec
|
gemspec: rswag-api.gemspec
|
||||||
provider: rubygems
|
provider: rubygems
|
||||||
@ -40,7 +35,6 @@ jobs:
|
|||||||
|
|
||||||
- stage: publish components
|
- stage: publish components
|
||||||
script: 'cd rswag-specs'
|
script: 'cd rswag-specs'
|
||||||
if: tag IS present
|
|
||||||
deploy:
|
deploy:
|
||||||
gemspec: rswag-specs.gemspec
|
gemspec: rswag-specs.gemspec
|
||||||
provider: rubygems
|
provider: rubygems
|
||||||
@ -51,19 +45,16 @@ jobs:
|
|||||||
|
|
||||||
- stage: publish components
|
- stage: publish components
|
||||||
script: 'cd rswag-ui'
|
script: 'cd rswag-ui'
|
||||||
if: tag IS present
|
|
||||||
deploy:
|
deploy:
|
||||||
gemspec: rswag-ui.gemspec
|
gemspec: rswag-ui.gemspec
|
||||||
provider: rubygems
|
provider: rubygems
|
||||||
api_key: $RUBYGEMS_API_KEY
|
api_key: $RUBYGEMS_API_KEY
|
||||||
skip_cleanup: true
|
|
||||||
on:
|
on:
|
||||||
branch: master
|
branch: master
|
||||||
tags: true
|
tags: true
|
||||||
|
|
||||||
- stage: publish rswag
|
- stage: publish rswag
|
||||||
script: 'cd rswag'
|
script: 'cd rswag'
|
||||||
if: tag IS present
|
|
||||||
deploy:
|
deploy:
|
||||||
gemspec: rswag.gemspec
|
gemspec: rswag.gemspec
|
||||||
provider: rubygems
|
provider: rubygems
|
||||||
|
|||||||
72
CHANGELOG.md
@ -1,72 +0,0 @@
|
|||||||
# rswag
|
|
||||||
All notable changes to this project will be documented in this file.
|
|
||||||
|
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
||||||
|
|
||||||
## [Unreleased]
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Update swagger-ui to 3.52.5
|
|
||||||
|
|
||||||
## [2.4.0] - 2021-02-09
|
|
||||||
### Added
|
|
||||||
- Added `SWAGGER_DRY_RUN` env variable [#274](https://github.com/rswag/rswag/pull/274)
|
|
||||||
|
|
||||||
## [2.3.3] - 2021-02-07
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Include response examples [#394](https://github.com/rswag/rswag/pull/394)
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Update swagger-ui to 3.42.0
|
|
||||||
|
|
||||||
## [2.3.2] - 2021-01-27
|
|
||||||
### Added
|
|
||||||
- RequestBody now supports the `required` flag [#342](https://github.com/rswag/rswag/pull/342)
|
|
||||||
### Fixed
|
|
||||||
- Fix response example rendering [#330](https://github.com/rswag/rswag/pull/330)
|
|
||||||
- Fix empty content block [#347](https://github.com/rswag/rswag/pull/347)
|
|
||||||
|
|
||||||
## [2.3.1] - 2020-04-08
|
|
||||||
### Fixed
|
|
||||||
- Remove require for byebug [#295](https://github.com/rswag/rswag/issues/295)
|
|
||||||
|
|
||||||
## [2.3.0] - 2020-04-05
|
|
||||||
### Added
|
|
||||||
- Support for OpenAPI 3.0 ! [#286](https://github.com/rswag/rswag/pull/286)
|
|
||||||
- Custom headers in rswag-api [#187](https://github.com/rswag/rswag/pull/187)
|
|
||||||
- Allow document: false rspec metatag [#255](https://github.com/rswag/rswag/pull/255)
|
|
||||||
- Add parameterized pattern for spec files [#254](https://github.com/rswag/rswag/pull/254)
|
|
||||||
- Support Basic Auth on rswag-ui [#167](https://github.com/rswag/rswag/pull/167)
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Update swagger-ui version to 3.23.11 [#239](https://github.com/rswag/rswag/pull/239)
|
|
||||||
- Rails constraint moved from < 6.1 to < 7 [#253](https://github.com/rswag/rswag/pull/253)
|
|
||||||
- Swaggerize now outputs base RSpec text on completion to avoid silent failures [#293](https://github.com/rswag/rswag/pull/293)
|
|
||||||
- Update swagger-ui version to 3.28.0
|
|
||||||
|
|
||||||
## [2.2.0] - 2019-11-01
|
|
||||||
### Added
|
|
||||||
- New swagger_format config option for setting YAML output [#251](https://github.com/rswag/rswag/pull/251)
|
|
||||||
### Changed
|
|
||||||
- rswag-api will serve yaml files as yaml [#251](https://github.com/rswag/rswag/pull/251)
|
|
||||||
|
|
||||||
## [2.1.1] - 2019-10-18
|
|
||||||
### Fixed
|
|
||||||
- Fix incorrect require reference for swagger_generator [#248](https://github.com/rswag/rswag/issues/248)
|
|
||||||
|
|
||||||
## [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)
|
|
||||||
|
|
||||||
## [2.0.5] - 2018-07-10
|
|
||||||
@ -1,83 +0,0 @@
|
|||||||
# Contributing
|
|
||||||
|
|
||||||
🎉 Thanks for taking the time to contribute! 🎉
|
|
||||||
|
|
||||||
We put forward the philosophy put forward by the [react community](https://reactcommunity.org/) about ownership, responsibility and avoiding burnout.
|
|
||||||
|
|
||||||
We also strive to achieve [semantic versioning](https://semver.org/) for this repo.
|
|
||||||
|
|
||||||
## Fork, then clone the repo:
|
|
||||||
```
|
|
||||||
git clone git@github.com:rswag/rswag.git
|
|
||||||
cd rswag
|
|
||||||
```
|
|
||||||
|
|
||||||
## Build
|
|
||||||
Set up your machine:
|
|
||||||
```
|
|
||||||
./ci/build.sh
|
|
||||||
```
|
|
||||||
Or manually
|
|
||||||
```
|
|
||||||
bundle
|
|
||||||
cd test-app
|
|
||||||
bundle exec rake db:setup
|
|
||||||
cd -
|
|
||||||
|
|
||||||
cd rswag-ui
|
|
||||||
npm install
|
|
||||||
cd -
|
|
||||||
```
|
|
||||||
|
|
||||||
## Test
|
|
||||||
Initialize the rswag-ui repo with assets.
|
|
||||||
```
|
|
||||||
ci/build.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
Make sure the tests pass:
|
|
||||||
```
|
|
||||||
./ci/test.sh
|
|
||||||
```
|
|
||||||
or manually
|
|
||||||
```
|
|
||||||
cd test-app
|
|
||||||
bundle exec rspec
|
|
||||||
```
|
|
||||||
|
|
||||||
Make your change. Add tests for your change. Make the tests pass:
|
|
||||||
|
|
||||||
```
|
|
||||||
bundle exec rspec
|
|
||||||
```
|
|
||||||
|
|
||||||
Push to your fork and [submit a Pull Request][pr].
|
|
||||||
|
|
||||||
[pr]: https://github.com/rswag/rswag/compare/
|
|
||||||
|
|
||||||
## Updating Swagger UI
|
|
||||||
|
|
||||||
Find the latest versions of swagger-ui here:
|
|
||||||
https://github.com/swagger-api/swagger-ui/releases
|
|
||||||
|
|
||||||
Update the swagger-ui-dist version in the rswag-ui dependencies
|
|
||||||
```
|
|
||||||
./rswag-ui/package.json
|
|
||||||
```
|
|
||||||
|
|
||||||
Navigate to the rswag-ui folder and run npm install to update the package-lock.json
|
|
||||||
|
|
||||||
|
|
||||||
## Release
|
|
||||||
(for maintainers)
|
|
||||||
|
|
||||||
Update the changelog.md, putting the new version number in and moving the Unreleased marker.
|
|
||||||
|
|
||||||
Merge the changes into master you wish to release.
|
|
||||||
|
|
||||||
Add and push a new git tag, annotated tags preferred:
|
|
||||||
```
|
|
||||||
git tag -s 2.0.6 -m 'v2.0.6'
|
|
||||||
```
|
|
||||||
|
|
||||||
Travis will detect the tag and release all gems with that tag version number.
|
|
||||||
42
Gemfile
@ -1,51 +1,37 @@
|
|||||||
# frozen_string_literal: true
|
source "https://rubygems.org"
|
||||||
|
|
||||||
source 'https://rubygems.org'
|
|
||||||
|
|
||||||
# Allow the rails version to come from an ENV setting so Travis can test multiple versions.
|
# Allow the rails version to come from an ENV setting so Travis can test multiple versions.
|
||||||
# See http://www.schneems.com/post/50991826838/testing-against-multiple-rails-versions/
|
# See http://www.schneems.com/post/50991826838/testing-against-multiple-rails-versions/
|
||||||
rails_version = ENV['RAILS_VERSION'] || '5.2.4.2'
|
rails_version = ENV['RAILS_VERSION'] || '5.1.2'
|
||||||
|
|
||||||
gem 'rails', rails_version.to_s
|
gem 'rails', "#{rails_version}"
|
||||||
|
|
||||||
case rails_version.split('.').first
|
case rails_version.split('.').first
|
||||||
when '3'
|
when '3'
|
||||||
gem 'strong_parameters'
|
gem 'strong_parameters'
|
||||||
when '4', '5', '6'
|
when '4', '5'
|
||||||
gem 'responders'
|
gem 'responders'
|
||||||
end
|
end
|
||||||
|
|
||||||
case rails_version.split('.').first
|
gem 'sqlite3'
|
||||||
when '3', '4', '5'
|
|
||||||
gem 'sqlite3', '~> 1.3.6'
|
|
||||||
when '6'
|
|
||||||
gem 'sqlite3', '~> 1.4.1'
|
|
||||||
end
|
|
||||||
|
|
||||||
|
gem 'rswag-specs', path: './rswag-specs'
|
||||||
gem 'rswag-api', path: './rswag-api'
|
gem 'rswag-api', path: './rswag-api'
|
||||||
gem 'rswag-ui', path: './rswag-ui'
|
gem 'rswag-ui', path: './rswag-ui'
|
||||||
|
|
||||||
group :development, :test do
|
# To use debugger
|
||||||
gem 'rswag-specs', path: './rswag-specs'
|
# gem 'debugger'
|
||||||
end
|
|
||||||
|
|
||||||
group :test do
|
group :test do
|
||||||
gem 'capybara'
|
|
||||||
gem 'geckodriver-helper'
|
|
||||||
gem 'generator_spec'
|
|
||||||
gem 'rspec-rails'
|
|
||||||
gem 'selenium-webdriver'
|
|
||||||
gem 'test-unit'
|
gem 'test-unit'
|
||||||
end
|
gem 'rspec-rails'
|
||||||
|
gem 'generator_spec'
|
||||||
group :development do
|
gem 'capybara'
|
||||||
gem 'rubocop'
|
gem 'capybara-webkit'
|
||||||
|
gem 'puma'
|
||||||
end
|
end
|
||||||
|
|
||||||
group :assets do
|
group :assets do
|
||||||
gem 'mini_racer'
|
|
||||||
gem 'uglifier'
|
gem 'uglifier'
|
||||||
|
gem 'therubyracer'
|
||||||
end
|
end
|
||||||
|
|
||||||
gem 'byebug'
|
|
||||||
gem 'puma'
|
|
||||||
|
|||||||
20
MIT-LICENCE
@ -1,20 +0,0 @@
|
|||||||
Copyright 2015 domaindrivendev
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
a copy of this software and associated documentation files (the
|
|
||||||
"Software"), to deal in the Software without restriction, including
|
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
|
||||||
included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
564
README.md
@ -1,69 +1,15 @@
|
|||||||
rswag
|
rswag (formerly swagger_rails)
|
||||||
=========
|
=========
|
||||||
[](https://travis-ci.org/rswag/rswag)
|
[](https://travis-ci.org/domaindrivendev/rswag)
|
||||||
[](https://codeclimate.com/github/rswag/rswag/maintainability)
|
|
||||||
|
|
||||||
OpenApi 3.0 and Swagger 2.0 compatible!
|
[Swagger](http://swagger.io) tooling for Rails API's. Generate beautiful API documentation, including a UI to explore and test operations, directly from your rspec integration tests.
|
||||||
|
|
||||||
Seeking maintainers! Got a pet-bug that needs fixing? Just let us know in your issue/pr that you'd like to step up to help.
|
|
||||||
|
|
||||||
Rswag extends rspec-rails "request specs" with a Swagger-based DSL for describing and testing API operations. You describe your API operations with a succinct, intuitive syntax, and it automaticaly runs the tests. Once you have green tests, run a rake task to auto-generate corresponding Swagger files and expose them as YAML or JSON endpoints. Rswag also provides an embedded version of the awesome [swagger-ui](https://github.com/swagger-api/swagger-ui) that's powered by the exposed file. This toolchain makes it seamless to go from integration specs, which youre probably doing in some form already, to living documentation for your API consumers.
|
|
||||||
|
|
||||||
Api Rswag creates [Swagger](http://swagger.io) tooling for Rails API's. Generate beautiful API documentation, including a UI to explore and test operations, directly from your rspec integration tests.
|
|
||||||
|
|
||||||
|
Rswag extends rspec-rails "request specs" with a Swagger-based DSL for describing and testing API operations. You describe your API operations with a succinct, intuitive syntax, and it automaticaly runs the tests. Once you have green tests, run a rake task to auto-generate corresponding Swagger files and expose them as JSON endpoints. Rswag also provides an embedded version of the awesome [swagger-ui](https://github.com/swagger-api/swagger-ui) that's powered by the exposed JSON. This toolchain makes it seamless to go from integration specs, which youre probably doing in some form already, to living documentation for your API consumers.
|
||||||
|
|
||||||
And that's not all ...
|
And that's not all ...
|
||||||
|
|
||||||
Once you have an API that can describe itself in Swagger, you've opened the treasure chest of Swagger-based tools including a client generator that can be targeted to a wide range of popular platforms. See [swagger-codegen](https://github.com/swagger-api/swagger-codegen) for more details.
|
Once you have an API that can describe itself in Swagger, you've opened the treasure chest of Swagger-based tools including a client generator that can be targeted to a wide range of popular platforms. See [swagger-codegen](https://github.com/swagger-api/swagger-codegen) for more details.
|
||||||
|
|
||||||
## Compatibility ##
|
|
||||||
|
|
||||||
|Rswag Version|Swagger (OpenAPI) Spec.|swagger-ui|
|
|
||||||
|----------|----------|----------|
|
|
||||||
|[master](https://github.com/rswag/rswag/tree/master)|3.0.3|3.52.5|
|
|
||||||
|[2.3.0](https://github.com/rswag/rswag/tree/2.3.0)|3.0.3|3.23.11|
|
|
||||||
|[2.2.0](https://github.com/rswag/rswag/tree/2.2.0)|2.0|3.18.2|
|
|
||||||
|[1.6.0](https://github.com/rswag/rswag/tree/1.6.0)|2.0|2.2.5|
|
|
||||||
|
|
||||||
|
|
||||||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
|
||||||
**Table of Contents**
|
|
||||||
|
|
||||||
- [rswag](#rswag)
|
|
||||||
- [Compatibility](#compatibility)
|
|
||||||
- [Getting Started](#getting-started)
|
|
||||||
- [The rspec DSL](#the-rspec-dsl)
|
|
||||||
- [Paths, Operations and Responses](#paths-operations-and-responses)
|
|
||||||
- [Null Values](#null-values)
|
|
||||||
- [Support for oneOf, anyOf or AllOf schemas](#support-for-oneof-anyof-or-allof-schemas)
|
|
||||||
- [Global Metadata](#global-metadata)
|
|
||||||
- [Supporting multiple versions of API](#supporting-multiple-versions-of-api)
|
|
||||||
- [Formatting the description literals:](#formatting-the-description-literals)
|
|
||||||
- [Specifying/Testing API Security](#specifyingtesting-api-security)
|
|
||||||
- [Configuration & Customization](#configuration--customization)
|
|
||||||
- [Output Location for Generated Swagger Files](#output-location-for-generated-swagger-files)
|
|
||||||
- [Input Location for Rspec Tests](#input-location-for-rspec-tests)
|
|
||||||
- [Referenced Parameters and Schema Definitions](#referenced-parameters-and-schema-definitions)
|
|
||||||
- [Response headers](#response-headers)
|
|
||||||
- [Response examples](#response-examples)
|
|
||||||
- [Enable auto generation examples from responses](#enable-auto-generation-examples-from-responses)
|
|
||||||
- [Running tests without documenting](#running-tests-without-documenting)
|
|
||||||
- [rswag helper methods](#rswag-helper-methods)
|
|
||||||
- [rswag response examples](#rswag-response-examples)
|
|
||||||
- [Route Prefix for Swagger JSON Endpoints](#route-prefix-for-swagger-json-endpoints)
|
|
||||||
- [Root Location for Swagger Files](#root-location-for-swagger-files)
|
|
||||||
- [Dynamic Values for Swagger JSON](#dynamic-values-for-swagger-json)
|
|
||||||
- [Custom Headers for Swagger Files](#custom-headers-for-swagger-files)
|
|
||||||
- [Enable Swagger Endpoints for swagger-ui](#enable-swagger-endpoints-for-swagger-ui)
|
|
||||||
- [Enable Simple Basic Auth for swagger-ui](#enable-simple-basic-auth-for-swagger-ui)
|
|
||||||
- [Route Prefix for the swagger-ui](#route-prefix-for-the-swagger-ui)
|
|
||||||
- [Customizing the swagger-ui](#customizing-the-swagger-ui)
|
|
||||||
- [Serve UI Assets Directly from your Web Server](#serve-ui-assets-directly-from-your-web-server)
|
|
||||||
|
|
||||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Getting Started ##
|
## Getting Started ##
|
||||||
|
|
||||||
1. Add this line to your applications _Gemfile_:
|
1. Add this line to your applications _Gemfile_:
|
||||||
@ -72,36 +18,13 @@ Once you have an API that can describe itself in Swagger, you've opened the trea
|
|||||||
gem 'rswag'
|
gem 'rswag'
|
||||||
```
|
```
|
||||||
|
|
||||||
or if you like to avoid loading rspec in other bundler groups load the rswag-specs component separately.
|
|
||||||
Note: Adding it to the :development group is not strictly necessary, but without it, generators and rake tasks must be preceded by RAILS_ENV=test.
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
# Gemfile
|
|
||||||
gem 'rswag-api'
|
|
||||||
gem 'rswag-ui'
|
|
||||||
|
|
||||||
group :development, :test do
|
|
||||||
gem 'rspec-rails'
|
|
||||||
gem 'rswag-specs'
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Run the install generator
|
2. Run the install generator
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
rails g rswag:install
|
rails g rswag:install
|
||||||
```
|
```
|
||||||
|
|
||||||
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
|
|
||||||
rails g rswag:ui:install
|
|
||||||
RAILS_ENV=test rails g rswag:specs:install
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Create an integration spec to describe and test your API.
|
3. Create an integration spec to describe and test your API.
|
||||||
There is also a generator which can help get you started `rails generate rspec:swagger API::MyController`
|
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
# spec/integration/blogs_spec.rb
|
# spec/integration/blogs_spec.rb
|
||||||
@ -113,7 +36,7 @@ There is also a generator which can help get you started `rails generate rspec:s
|
|||||||
|
|
||||||
post 'Creates a blog' do
|
post 'Creates a blog' do
|
||||||
tags 'Blogs'
|
tags 'Blogs'
|
||||||
consumes 'application/json'
|
consumes 'application/json', 'application/xml'
|
||||||
parameter name: :blog, in: :body, schema: {
|
parameter name: :blog, in: :body, schema: {
|
||||||
type: :object,
|
type: :object,
|
||||||
properties: {
|
properties: {
|
||||||
@ -138,9 +61,9 @@ There is also a generator which can help get you started `rails generate rspec:s
|
|||||||
path '/blogs/{id}' do
|
path '/blogs/{id}' do
|
||||||
|
|
||||||
get 'Retrieves a blog' do
|
get 'Retrieves a blog' do
|
||||||
tags 'Blogs', 'Another Tag'
|
tags 'Blogs'
|
||||||
produces 'application/json', 'application/xml'
|
produces 'application/json', 'application/xml'
|
||||||
parameter name: :id, in: :path, type: :string
|
parameter name: :id, :in => :path, :type => :string
|
||||||
|
|
||||||
response '200', 'blog found' do
|
response '200', 'blog found' do
|
||||||
schema type: :object,
|
schema type: :object,
|
||||||
@ -169,20 +92,12 @@ There is also a generator which can help get you started `rails generate rspec:s
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
4. Generate the Swagger JSON file(s)
|
4. Generate the Swagger JSON file(s)
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
rake rswag:specs:swaggerize
|
rake rswag:specs:swaggerize
|
||||||
```
|
```
|
||||||
|
|
||||||
This common command is also aliased as `rake rswag`.
|
|
||||||
|
|
||||||
Or if you installed your gems separately:
|
|
||||||
```
|
|
||||||
RAILS_ENV=test rails rswag
|
|
||||||
```
|
|
||||||
|
|
||||||
5. Spin up your app and check out the awesome, auto-generated docs at _/api-docs_!
|
5. Spin up your app and check out the awesome, auto-generated docs at _/api-docs_!
|
||||||
|
|
||||||
## The rspec DSL ##
|
## The rspec DSL ##
|
||||||
@ -222,7 +137,7 @@ end
|
|||||||
|
|
||||||
### Null Values ###
|
### Null Values ###
|
||||||
|
|
||||||
This library is currently using JSON::Draft4 for validation of response models. Nullable properties can be supported with the non-standard property 'x-nullable' to a definition to allow null/nil values to pass. Or you can add the new standard ```nullable``` property to a definition.
|
This library is currently using JSON::Draft4 for validation of response models. It does not support null as a value. So you can add the property 'x-nullable' to a definition to allow null/nil values to pass.
|
||||||
```ruby
|
```ruby
|
||||||
describe 'Blogs API' do
|
describe 'Blogs API' do
|
||||||
path '/blogs' do
|
path '/blogs' do
|
||||||
@ -233,8 +148,8 @@ describe 'Blogs API' do
|
|||||||
schema type: :object,
|
schema type: :object,
|
||||||
properties: {
|
properties: {
|
||||||
id: { type: :integer },
|
id: { type: :integer },
|
||||||
title: { type: :string, nullable: true }, # preferred syntax
|
title: { type: :string },
|
||||||
content: { type: :string, 'x-nullable': true } # legacy syntax, but still works
|
content: { type: :string, 'x-nullable': true }
|
||||||
}
|
}
|
||||||
....
|
....
|
||||||
end
|
end
|
||||||
@ -242,45 +157,12 @@ describe 'Blogs API' do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
*Note:* the OAI v3 may be released soon(ish?) and include a nullable property. This may have an effect on the need/use of custom extension to the draft. Do not use this property if you don't understand the implications.
|
||||||
### Support for oneOf, anyOf or AllOf schemas ###
|
<https://github.com/OAI/OpenAPI-Specification/issues/229#issuecomment-280376087>
|
||||||
|
|
||||||
Open API 3.0 now supports more flexible schema validation with the ```oneOf```, ```anyOf``` and ```allOf``` directives. rswag will handle these definitions and validate them properly.
|
|
||||||
|
|
||||||
|
|
||||||
Notice the ```schema``` inside the ```response``` section. Placing a ```schema``` method inside the response will validate (and fail the tests)
|
|
||||||
if during the integration test run the endpoint response does not match the response schema. This test validation can handle anyOf and allOf as well. See below:
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
|
|
||||||
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'
|
|
||||||
|
|
||||||
parameter name: :blog, in: :body, schema: {
|
|
||||||
oneOf: [
|
|
||||||
{ '$ref' => '#/components/schemas/blog' },
|
|
||||||
{ '$ref' => '#/components/schemas/flexible_blog' }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
response '201', 'flexible blog created' do
|
|
||||||
schema oneOf: [{ '$ref' => '#/components/schemas/blog' }, { '$ref' => '#/components/schemas/flexible_blog' }]
|
|
||||||
run_test!
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
```
|
|
||||||
This automatic schema validation is a powerful feature of rswag.
|
|
||||||
|
|
||||||
### Global Metadata ###
|
### Global Metadata ###
|
||||||
|
|
||||||
In addition to paths, operations and responses, Swagger also supports global API metadata. When you install rswag, a file called _swagger_helper.rb_ is added to your spec folder. This is where you define one or more Swagger documents and provide global metadata. Again, the format is based on Swagger so most of the global fields supported by the top level ["Swagger" object](http://swagger.io/specification/#swaggerObject) can be provided with each document definition. As an example, you could define a Swagger document for each version of your API and in each case specify a title, version string. In Open API 3.0 the pathing and server definitions have changed a bit [Swagger host/basePath](https://swagger.io/docs/specification/api-host-and-base-path/):
|
In addition to paths, operations and responses, Swagger also supports global API metadata. When you install rswag, a file called _swagger_helper.rb_ is added to your spec folder. This is where you define one or more Swagger documents and provide global metadata. Again, the format is based on Swagger so most of the global fields supported by the top level ["Swagger" object](http://swagger.io/specification/#swaggerObject) can be provided with each document definition. As an example, you could define a Swagger document for each version of your API and in each case specify a title, version string and URL basePath:
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
# spec/swagger_helper.rb
|
# spec/swagger_helper.rb
|
||||||
@ -289,52 +171,31 @@ RSpec.configure do |config|
|
|||||||
|
|
||||||
config.swagger_docs = {
|
config.swagger_docs = {
|
||||||
'v1/swagger.json' => {
|
'v1/swagger.json' => {
|
||||||
openapi: '3.0.1',
|
swagger: '2.0',
|
||||||
info: {
|
info: {
|
||||||
title: 'API V1',
|
title: 'API V1',
|
||||||
version: 'v1',
|
version: 'v1'
|
||||||
description: 'This is the first version of my API'
|
|
||||||
},
|
},
|
||||||
servers: [
|
basePath: '/api/v1'
|
||||||
{
|
|
||||||
url: 'https://{defaultHost}',
|
|
||||||
variables: {
|
|
||||||
defaultHost: {
|
|
||||||
default: 'www.example.com'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
|
|
||||||
'v2/swagger.yaml' => {
|
'v2/swagger.json' => {
|
||||||
openapi: '3.0.1',
|
swagger: '2.0',
|
||||||
info: {
|
info: {
|
||||||
title: 'API V2',
|
title: 'API V2',
|
||||||
version: 'v2',
|
version: 'v2'
|
||||||
description: 'This is the second version of my API'
|
|
||||||
},
|
},
|
||||||
servers: [
|
basePath: '/api/v2'
|
||||||
{
|
|
||||||
url: 'https://{defaultHost}',
|
|
||||||
variables: {
|
|
||||||
defaultHost: {
|
|
||||||
default: 'www.example.com'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Supporting multiple versions of API ####
|
__NOTE__: By default, the paths, operations and responses defined in your spec files will be associated with the first Swagger document in _swagger_helper.rb_. If you're using multiple documents, you'll need to tag the individual specs with their target document name:
|
||||||
By default, the paths, operations and responses defined in your spec files will be associated with the first Swagger document in _swagger_helper.rb_. If your API has multiple versions, you should be using separate documents to describe each of them. In order to assign a file with a given version of API, you'll need to add the ```swagger_doc``` tag to each spec specifying its target document name:
|
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
# spec/integration/v2/blogs_spec.rb
|
# spec/integration/v2/blogs_spec.rb
|
||||||
describe 'Blogs API', swagger_doc: 'v2/swagger.yaml' do
|
describe 'Blogs API', swagger_doc: 'v2/swagger.json' do
|
||||||
|
|
||||||
path '/blogs' do
|
path '/blogs' do
|
||||||
...
|
...
|
||||||
@ -344,30 +205,9 @@ describe 'Blogs API', swagger_doc: 'v2/swagger.yaml' do
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Formatting the description literals: ####
|
|
||||||
Swagger supports the Markdown syntax to format strings. This can be especially handy if you were to provide a long description of a given API version or endpoint. Use [this guide](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) for reference.
|
|
||||||
|
|
||||||
__NOTE:__ There is one difference between the official Markdown syntax and Swagger interpretation, namely tables. To create a table like this:
|
|
||||||
|
|
||||||
| Column1 | Collumn2 |
|
|
||||||
| ------- | -------- |
|
|
||||||
| cell1 | cell2 |
|
|
||||||
|
|
||||||
you should use the folowing syntax, making sure there are no whitespaces at the start of any of the lines:
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
| Column1 | Collumn2 |
|
|
||||||
| ------- | -------- |
|
|
||||||
| cell1 | cell2 |
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
### Specifying/Testing API Security ###
|
### Specifying/Testing API Security ###
|
||||||
|
|
||||||
Swagger allows for the specification of different security schemes and their applicability to operations in an API.
|
Swagger allows for the specification of different security schemes and their applicability to operations in an API. To leverage this in rswag, you define the schemes globally in _swagger_helper.rb_ and then use the "security" attribute at the operation level to specify which schemes, if any, are applicable to that operation. Swagger supports :basic, :apiKey and :oauth2 scheme types. See [the spec](http://swagger.io/specification/#security-definitions-object-109) for more info.
|
||||||
To leverage this in rswag, you define the schemes globally in _swagger_helper.rb_ and then use the "security" attribute at the operation level to specify which schemes, if any, are applicable to that operation.
|
|
||||||
Swagger supports :basic, :bearer, :apiKey and :oauth2 and :openIdConnect scheme types. See [the spec](https://swagger.io/docs/specification/authentication/) for more info, as this underwent major changes between Swagger 2.0 and Open API 3.0
|
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
# spec/swagger_helper.rb
|
# spec/swagger_helper.rb
|
||||||
@ -376,18 +216,15 @@ RSpec.configure do |config|
|
|||||||
|
|
||||||
config.swagger_docs = {
|
config.swagger_docs = {
|
||||||
'v1/swagger.json' => {
|
'v1/swagger.json' => {
|
||||||
... # note the new Open API 3.0 compliant security structure here, under "components"
|
...
|
||||||
components: {
|
securityDefinitions: {
|
||||||
securitySchemes: {
|
basic: {
|
||||||
basic_auth: {
|
type: :basic
|
||||||
type: :http,
|
},
|
||||||
scheme: :basic
|
apiKey: {
|
||||||
},
|
type: :apiKey,
|
||||||
api_key: {
|
name: 'api_key',
|
||||||
type: :apiKey,
|
in: :query
|
||||||
name: 'api_key',
|
|
||||||
in: :query
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -401,7 +238,7 @@ describe 'Blogs API' do
|
|||||||
|
|
||||||
post 'Creates a blog' do
|
post 'Creates a blog' do
|
||||||
tags 'Blogs'
|
tags 'Blogs'
|
||||||
security [ basic_auth: [] ]
|
security [ basic: [] ]
|
||||||
...
|
...
|
||||||
|
|
||||||
response '201', 'blog created' do
|
response '201', 'blog created' do
|
||||||
@ -416,35 +253,9 @@ describe 'Blogs API' do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# example of documenting an endpoint that handles basic auth and api key based security
|
|
||||||
describe 'Auth examples API' do
|
|
||||||
path '/auth-tests/basic-and-api-key' do
|
|
||||||
post 'Authenticates with basic auth and api key' do
|
|
||||||
tags 'Auth Tests'
|
|
||||||
operationId 'testBasicAndApiKey'
|
|
||||||
security [{ basic_auth: [], api_key: [] }]
|
|
||||||
|
|
||||||
response '204', 'Valid credentials' do
|
|
||||||
let(:Authorization) { "Basic #{::Base64.strict_encode64('jsmith:jspass')}" }
|
|
||||||
let(:api_key) { 'foobar' }
|
|
||||||
run_test!
|
|
||||||
end
|
|
||||||
|
|
||||||
response '401', 'Invalid credentials' do
|
|
||||||
let(:Authorization) { "Basic #{::Base64.strict_encode64('jsmith:jspass')}" }
|
|
||||||
let(:api_key) { 'barfoo' }
|
|
||||||
run_test!
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
__NOTE:__ Depending on the scheme types, you'll be required to assign a corresponding parameter value with each example.
|
__NOTE:__ Depending on the scheme types, you'll be required to assign a corresponding parameter value with each example. For example, :basic auth is required above and so the :Authorization (header) parameter must be set accordingly
|
||||||
For example, :basic auth is required above and so the :Authorization (header) parameter must be set accordingly
|
|
||||||
|
|
||||||
## Configuration & Customization ##
|
## Configuration & Customization ##
|
||||||
|
|
||||||
@ -453,7 +264,7 @@ The steps described above will get you up and running with minimal setup. Howeve
|
|||||||
|Gem|Description|Added/Updated|
|
|Gem|Description|Added/Updated|
|
||||||
|---------|-----------|-------------|
|
|---------|-----------|-------------|
|
||||||
|__rswag-specs__|Swagger-based DSL for rspec & accompanying rake task for generating Swagger files|_spec/swagger_helper.rb_|
|
|__rswag-specs__|Swagger-based DSL for rspec & accompanying rake task for generating Swagger files|_spec/swagger_helper.rb_|
|
||||||
|__rswag-api__ |Rails Engine that exposes your Swagger files as JSON endpoints|_config/initializers/rswag_api.rb, config/routes.rb_|
|
|__rswag-api__ |Rails Engine that exposes your Swagger files as JSON endpoints|_config/initializers/rswag-api.rb, config/routes.rb_|
|
||||||
|__rswag-ui__ |Rails Engine that includes [swagger-ui](https://github.com/swagger-api/swagger-ui) and powers it from your Swagger endpoints|_config/initializers/rswag-ui.rb, config/routes.rb_|
|
|__rswag-ui__ |Rails Engine that includes [swagger-ui](https://github.com/swagger-api/swagger-ui) and powers it from your Swagger endpoints|_config/initializers/rswag-ui.rb, config/routes.rb_|
|
||||||
|
|
||||||
### Output Location for Generated Swagger Files ###
|
### Output Location for Generated Swagger Files ###
|
||||||
@ -468,65 +279,32 @@ RSpec.configure do |config|
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
__NOTE__: If you do change this, you'll also need to update the rswag_api.rb initializer (assuming you're using rswag-api). More on this later.
|
__NOTE__: If you do change this, you'll also need to update the rswag-api.rb initializer (assuming you're using rswag-api). More on this later.
|
||||||
|
|
||||||
### Input Location for Rspec Tests ###
|
|
||||||
|
|
||||||
By default, rswag will search for integration tests in _spec/requests_, _spec/api_ and _spec/integration_. If you want to use tests from other locations, provide the PATTERN argument to rake:
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
# search for tests in spec/swagger
|
|
||||||
rake rswag:specs:swaggerize PATTERN="spec/swagger/**/*_spec.rb"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Referenced Parameters and Schema Definitions ###
|
### Referenced Parameters and Schema Definitions ###
|
||||||
|
|
||||||
Swagger allows you to describe JSON structures inline with your operation descriptions OR as referenced globals.
|
Swagger allows you to describe JSON structures inline with your operation descriptions OR as referenced globals. For example, you might have a standard response structure for all failed operations. Rather than repeating the schema in every operation spec, you can define it globally and provide a reference to it in each spec:
|
||||||
For example, you might have a standard response structure for all failed operations.
|
|
||||||
Again, this is a structure that changed since swagger 2.0. Notice the new "schemas" section for these.
|
|
||||||
Rather than repeating the schema in every operation spec, you can define it globally and provide a reference to it in each spec:
|
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
# spec/swagger_helper.rb
|
# spec/swagger_helper.rb
|
||||||
config.swagger_docs = {
|
config.swagger_docs = {
|
||||||
'v1/swagger.json' => {
|
'v1/swagger.json' => {
|
||||||
openapi: '3.0.0',
|
swagger: '2.0',
|
||||||
info: {
|
info: {
|
||||||
title: 'API V1'
|
title: 'API V1'
|
||||||
},
|
},
|
||||||
components: {
|
definitions: {
|
||||||
schemas: {
|
errors_object: {
|
||||||
errors_object: {
|
type: 'object',
|
||||||
type: 'object',
|
properties: {
|
||||||
properties: {
|
errors: { '$ref' => '#/definitions/errors_map' }
|
||||||
errors: { '$ref' => '#/components/schemas/errors_map' }
|
}
|
||||||
}
|
},
|
||||||
},
|
errors_map: {
|
||||||
errors_map: {
|
type: 'object',
|
||||||
type: 'object',
|
additionalProperties: {
|
||||||
additionalProperties: {
|
type: 'array',
|
||||||
type: 'array',
|
items: { type: 'string' }
|
||||||
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]
|
|
||||||
},
|
|
||||||
new_blog: {
|
|
||||||
type: 'object',
|
|
||||||
properties: {
|
|
||||||
title: { type: 'string' },
|
|
||||||
content: { type: 'string', nullable: true },
|
|
||||||
thumbnail: { type: 'string', format: 'binary', nullable: true }
|
|
||||||
},
|
|
||||||
required: %w[title]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -540,10 +318,8 @@ describe 'Blogs API' do
|
|||||||
|
|
||||||
post 'Creates a blog' do
|
post 'Creates a blog' do
|
||||||
|
|
||||||
parameter name: :new_blog, in: :body, schema: { '$ref' => '#/components/schemas/new_blog' }
|
|
||||||
|
|
||||||
response 422, 'invalid request' do
|
response 422, 'invalid request' do
|
||||||
schema '$ref' => '#/components/schemas/errors_object'
|
schema '$ref' => '#/definitions/errors_object'
|
||||||
...
|
...
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -555,15 +331,14 @@ describe 'Blogs API' do
|
|||||||
post 'Creates a comment' do
|
post 'Creates a comment' do
|
||||||
|
|
||||||
response 422, 'invalid request' do
|
response 422, 'invalid request' do
|
||||||
schema '$ref' => '#/components/schemas/errors_object'
|
schema '$ref' => '#/definitions/errors_object'
|
||||||
...
|
...
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
### Response headers ###
|
### Response headers ###
|
||||||
|
|
||||||
In Rswag, you could use `header` method inside the response block to specify header objects for this response.
|
In Rswag, you could use `header` method inside the response block to specify header objects for this response. Rswag will validate your response headers with those header objects and inject them into the generated swagger file:
|
||||||
Rswag will validate your response headers with those header objects and inject them into the generated swagger file:
|
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
# spec/integration/comments_spec.rb
|
# spec/integration/comments_spec.rb
|
||||||
@ -583,7 +358,7 @@ end
|
|||||||
### Response examples ###
|
### Response examples ###
|
||||||
|
|
||||||
You can provide custom response examples to the generated swagger file by calling the method `examples` inside the response block:
|
You can provide custom response examples to the generated swagger file by calling the method `examples` inside the response block:
|
||||||
However, auto generated example responses are now enabled by default in rswag. See below.
|
|
||||||
```ruby
|
```ruby
|
||||||
# spec/integration/blogs_spec.rb
|
# spec/integration/blogs_spec.rb
|
||||||
describe 'Blogs API' do
|
describe 'Blogs API' do
|
||||||
@ -602,192 +377,22 @@ describe 'Blogs API' do
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Enable generation examples from responses ###
|
||||||
### Enable auto generation examples from responses ###
|
|
||||||
|
|
||||||
|
|
||||||
To enable examples generation from responses add callback above run_test! like:
|
To enable examples generation from responses add callback above run_test! like:
|
||||||
|
```ruby
|
||||||
```
|
|
||||||
after do |example|
|
after do |example|
|
||||||
example.metadata[:response][:content] = {
|
example.metadata[:response][:examples] = { 'application/json' => JSON.parse(response.body, symbolize_names: true) }
|
||||||
'application/json' => {
|
|
||||||
example: JSON.parse(response.body, symbolize_names: true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
You need to disable --dry-run option for Rspec > 3
|
||||||
|
|
||||||
#### Dry Run Option ####
|
Add to application.rb:
|
||||||
|
|
||||||
The `--dry-run` option is enabled by default for Rspec 3, but if you need to
|
|
||||||
disable it you can use the environment varible `SWAGGER_DRY_RUN=0` during the
|
|
||||||
generation command or add the following to your `config/environments/test.rb`:
|
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
RSpec.configure do |config|
|
RSpec.configure do |config|
|
||||||
config.swagger_dry_run = false
|
config.swagger_dry_run = false
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Running tests without documenting ####
|
|
||||||
|
|
||||||
If you want to use Rswag for testing without adding it to you swagger docs, you can provide the document tag:
|
|
||||||
```ruby
|
|
||||||
describe 'Blogs API' do
|
|
||||||
path '/blogs/{blog_id}' do
|
|
||||||
get 'Retrieves a blog' do
|
|
||||||
# documentation is now disabled for this response only
|
|
||||||
response 200, 'blog found', document: false do
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also reenable documentation for specific responses only:
|
|
||||||
```ruby
|
|
||||||
# documentation is now disabled
|
|
||||||
describe 'Blogs API', document: false do
|
|
||||||
path '/blogs/{blog_id}' do
|
|
||||||
get 'Retrieves a blog' do
|
|
||||||
# documentation is reenabled for this response only
|
|
||||||
response 200, 'blog found', document: true do
|
|
||||||
...
|
|
||||||
end
|
|
||||||
|
|
||||||
response 401, 'special case' do
|
|
||||||
...
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
##### rswag helper methods #####
|
|
||||||
<!--
|
|
||||||
There are some helper methods to help with documenting request bodies.
|
|
||||||
```ruby
|
|
||||||
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
|
|
||||||
end
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
In the above example, we see methods ```request_body_json``` ```request_body_plain``` ```request_body_xml```.
|
|
||||||
These methods can be used to describe json, plain text and xml body. They are just wrapper methods to setup posting JSON, plain text or xml into your endpoint.
|
|
||||||
The simplest most common usage is for json formatted body to use the schema: to specify the location of the schema for the request body
|
|
||||||
and the examples: :blog which will create a named example "blog" under the "requestBody / content / application/json / examples" section.
|
|
||||||
Again, documenting request response examples changed in Open API 3.0. The example above would generate a swagger.json snippet that looks like this:
|
|
||||||
|
|
||||||
```json
|
|
||||||
...
|
|
||||||
{"requestBody": {
|
|
||||||
"required": true,
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"examples": {
|
|
||||||
"blog": { // takes the name from examples: :blog above
|
|
||||||
"value": { //this is open api 3.0 structure -> https://swagger.io/docs/specification/adding-examples/
|
|
||||||
"blog": { // here is the actual JSON payload that is submitted to the service, and shows up in swagger UI as an example
|
|
||||||
"title": "foo",
|
|
||||||
"content": "bar"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/blog"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"test/plain": {
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"application/xml": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/blog"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
*NOTE:* for this example request body to work in the tests properly, you need to ``let`` a variable named *blog*.
|
|
||||||
The variable with the matching name (blog in this case) is eval-ed and captured to be placed in the examples section.
|
|
||||||
This ```let``` value is used in the integration test to run the test AND captured and injected into the requestBody section.
|
|
||||||
|
|
||||||
##### rswag response examples #####
|
|
||||||
|
|
||||||
In the same way that requestBody examples can be captured and injected into the swagger output, response examples can also be captured.
|
|
||||||
Using the above example, when the integration test is run - the swagger would include the following snippet providing more useful real world examples
|
|
||||||
capturing the response from the execution of the integration test. Again 3.0 swagger changed the structure of how these are documented.
|
|
||||||
|
|
||||||
```json
|
|
||||||
... "responses": {
|
|
||||||
"201": {
|
|
||||||
"description": "blog created",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"example": {
|
|
||||||
"id": 1,
|
|
||||||
"title": "foo",
|
|
||||||
"content": "bar",
|
|
||||||
"thumbnail": null
|
|
||||||
},
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/blog"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"422": {
|
|
||||||
"description": "invalid request",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"example": {
|
|
||||||
"errors": {
|
|
||||||
"content": [
|
|
||||||
"can't be blank"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/errors_object"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
-->
|
|
||||||
### Route Prefix for Swagger JSON Endpoints ###
|
### Route Prefix for Swagger JSON Endpoints ###
|
||||||
|
|
||||||
The functionality to expose Swagger files, such as those generated by rswag-specs, as JSON endpoints is implemented as a Rails Engine. As with any Engine, you can change it's mount prefix in _routes.rb_:
|
The functionality to expose Swagger files, such as those generated by rswag-specs, as JSON endpoints is implemented as a Rails Engine. As with any Engine, you can change it's mount prefix in _routes.rb_:
|
||||||
@ -808,7 +413,7 @@ GET http://<hostname>/your-custom-prefix/v1/swagger.json
|
|||||||
|
|
||||||
### Root Location for Swagger Files ###
|
### Root Location for Swagger Files ###
|
||||||
|
|
||||||
You can adjust this in the _rswag_api.rb_ initializer that's installed with __rspec-api__:
|
You can adjust this in the _rswag-api.rb_ initializer that's installed with __rspec-api__:
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
Rswag::Api.configure do |c|
|
Rswag::Api.configure do |c|
|
||||||
@ -831,22 +436,7 @@ Rswag::Api.configure do |c|
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Note how the filter is passed the rack env for the current request. This provides a lot of flexibilty. For example, you can assign the "host" property (as shown) or you could inspect session information or an Authorization header and remove operations based on user permissions.
|
Note how the filter is passed the rack env for the current request. This provides a lot of flexibilty. For example, you can assign the "host" property (as shown) or you could inspect session information or an Authoriation header and remove operations based on user permissions.
|
||||||
|
|
||||||
### Custom Headers for Swagger Files ###
|
|
||||||
|
|
||||||
You can specify custom headers for serving your generated Swagger JSON. For example you may want to force a specific charset for the 'Content-Type' header. You can configure a hash of headers to be sent with the request:
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
Rswag::Api.configure do |c|
|
|
||||||
...
|
|
||||||
|
|
||||||
c.swagger_headers = { 'Content-Type' => 'application/json; charset=UTF-8' }
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
Take care when overriding Content-Type if you serve both YAML and JSON files as it will no longer switch the Content-Type header correctly.
|
|
||||||
|
|
||||||
|
|
||||||
### Enable Swagger Endpoints for swagger-ui ###
|
### Enable Swagger Endpoints for swagger-ui ###
|
||||||
|
|
||||||
@ -859,17 +449,6 @@ Rswag::Ui.configure do |c|
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
### Enable Simple Basic Auth for swagger-ui
|
|
||||||
|
|
||||||
You can also update the _rswag-ui.rb_ initializer, installed with rswag-ui to specify a username and password should you want to keep your documentation private.
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
Rswag::Ui.configure do |c|
|
|
||||||
c.basic_auth_enabled = true
|
|
||||||
c.basic_auth_credentials 'username', 'password'
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
### Route Prefix for the swagger-ui ###
|
### Route Prefix for the swagger-ui ###
|
||||||
|
|
||||||
Similar to rswag-api, you can customize the swagger-ui path by changing it's mount prefix in _routes.rb_:
|
Similar to rswag-api, you can customize the swagger-ui path by changing it's mount prefix in _routes.rb_:
|
||||||
@ -893,24 +472,3 @@ rails g rswag:ui:custom
|
|||||||
```
|
```
|
||||||
|
|
||||||
This will add a local version that you can modify at _app/views/rswag/ui/home/index.html.erb_
|
This will add a local version that you can modify at _app/views/rswag/ui/home/index.html.erb_
|
||||||
|
|
||||||
### Serve UI Assets Directly from your Web Server
|
|
||||||
|
|
||||||
Rswag ships with an embedded version of the [swagger-ui](https://github.com/swagger-api/swagger-ui), which is a static collection of JavaScript and CSS files. These assets are served by the rswag-ui middleware. However, for optimal performance you may want to serve them directly from your web server (e.g. Apache or NGINX). To do this, you'll need to copy them to the web server root. This is the "public" folder in a typical Rails application.
|
|
||||||
|
|
||||||
```
|
|
||||||
bundle exec rake rswag:ui:copy_assets[public/api-docs]
|
|
||||||
```
|
|
||||||
|
|
||||||
__NOTE:__: The provided subfolder MUST correspond to the UI mount prefix - "api-docs" by default.
|
|
||||||
|
|
||||||
|
|
||||||
Notes to test swagger output locally with swagger editor
|
|
||||||
```
|
|
||||||
docker pull swaggerapi/swagger-editor
|
|
||||||
```
|
|
||||||
```
|
|
||||||
docker run -d -p 80:8080 swaggerapi/swagger-editor
|
|
||||||
```
|
|
||||||
This will run the swagger editor in the docker daemon and can be accessed
|
|
||||||
at ```http://localhost```. From here, you can use the UI to load the generated swagger.json to validate the output.
|
|
||||||
|
|||||||
24
ci/build.sh
@ -1,24 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
ROOT_PATH=$PWD
|
|
||||||
set -e # abort if anything fails
|
|
||||||
|
|
||||||
echo '####################'
|
|
||||||
echo 'bundle'
|
|
||||||
echo '####################'
|
|
||||||
echo ''
|
|
||||||
|
|
||||||
echo '##### all #####'
|
|
||||||
bundle install
|
|
||||||
|
|
||||||
echo '####################'
|
|
||||||
echo 'npm'
|
|
||||||
echo '####################'
|
|
||||||
echo ''
|
|
||||||
|
|
||||||
echo '##### rswag-ui #####'
|
|
||||||
cd $ROOT_PATH/rswag-ui
|
|
||||||
npm install
|
|
||||||
|
|
||||||
# Cleanup
|
|
||||||
cd $ROOT_PATH
|
|
||||||
@ -5,4 +5,4 @@ Example:
|
|||||||
rails generate rswag:api:install
|
rails generate rswag:api:install
|
||||||
|
|
||||||
This will create:
|
This will create:
|
||||||
config/initializers/rswag_api.rb
|
config/initializers/rswag-api.rb
|
||||||
|
|||||||
@ -7,7 +7,7 @@ module Rswag
|
|||||||
source_root File.expand_path('../templates', __FILE__)
|
source_root File.expand_path('../templates', __FILE__)
|
||||||
|
|
||||||
def add_initializer
|
def add_initializer
|
||||||
template('rswag_api.rb', 'config/initializers/rswag_api.rb')
|
template('rswag-api.rb', 'config/initializers/rswag-api.rb')
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_routes
|
def add_routes
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
module Rswag
|
module Rswag
|
||||||
module Api
|
module Api
|
||||||
class Configuration
|
class Configuration
|
||||||
attr_accessor :swagger_root, :swagger_filter, :swagger_headers
|
attr_accessor :swagger_root, :swagger_filter
|
||||||
|
|
||||||
def resolve_swagger_root(env)
|
def resolve_swagger_root(env)
|
||||||
path_params = env['action_dispatch.request.path_parameters'] || {}
|
path_params = env['action_dispatch.request.path_parameters'] || {}
|
||||||
|
|||||||
@ -1,6 +1,4 @@
|
|||||||
require 'json'
|
require 'json'
|
||||||
require 'yaml'
|
|
||||||
require 'rack/mime'
|
|
||||||
|
|
||||||
module Rswag
|
module Rswag
|
||||||
module Api
|
module Api
|
||||||
@ -16,16 +14,13 @@ module Rswag
|
|||||||
filename = "#{@config.resolve_swagger_root(env)}/#{path}"
|
filename = "#{@config.resolve_swagger_root(env)}/#{path}"
|
||||||
|
|
||||||
if env['REQUEST_METHOD'] == 'GET' && File.file?(filename)
|
if env['REQUEST_METHOD'] == 'GET' && File.file?(filename)
|
||||||
swagger = parse_file(filename)
|
swagger = load_json(filename)
|
||||||
@config.swagger_filter.call(swagger, env) unless @config.swagger_filter.nil?
|
@config.swagger_filter.call(swagger, env) unless @config.swagger_filter.nil?
|
||||||
mime = Rack::Mime.mime_type(::File.extname(path), 'text/plain')
|
|
||||||
headers = { 'Content-Type' => mime }.merge(@config.swagger_headers || {})
|
|
||||||
body = unload_swagger(filename, swagger)
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'200',
|
'200',
|
||||||
headers,
|
{ 'Content-Type' => 'application/json' },
|
||||||
[ body ]
|
[ JSON.dump(swagger) ]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -34,29 +29,9 @@ module Rswag
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def parse_file(filename)
|
|
||||||
if /\.ya?ml$/ === filename
|
|
||||||
load_yaml(filename)
|
|
||||||
else
|
|
||||||
load_json(filename)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def load_yaml(filename)
|
|
||||||
YAML.safe_load(File.read(filename))
|
|
||||||
end
|
|
||||||
|
|
||||||
def load_json(filename)
|
def load_json(filename)
|
||||||
JSON.parse(File.read(filename))
|
JSON.parse(File.read(filename))
|
||||||
end
|
end
|
||||||
|
|
||||||
def unload_swagger(filename, swagger)
|
|
||||||
if /\.ya?ml$/ === filename
|
|
||||||
YAML.dump(swagger)
|
|
||||||
else
|
|
||||||
JSON.dump(swagger)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,19 +1,17 @@
|
|||||||
# frozen_string_literal: true
|
$:.push File.expand_path("../lib", __FILE__)
|
||||||
|
|
||||||
$LOAD_PATH.push File.expand_path('../lib', __FILE__)
|
|
||||||
|
|
||||||
# Describe your gem and declare its dependencies:
|
# Describe your gem and declare its dependencies:
|
||||||
Gem::Specification.new do |s|
|
Gem::Specification.new do |s|
|
||||||
s.name = 'rswag-api'
|
s.name = "rswag-api"
|
||||||
s.version = ENV['TRAVIS_TAG'] || '0.0.0'
|
s.version = ENV['TRAVIS_TAG'] || '0.0.0'
|
||||||
s.authors = ['Richie Morris', 'Greg Myers', 'Jay Danielian']
|
s.authors = ["Richie Morris"]
|
||||||
s.email = ['domaindrivendev@gmail.com']
|
s.email = ["domaindrivendev@gmail.com"]
|
||||||
s.homepage = 'https://github.com/rswag/rswag'
|
s.homepage = "https://github.com/domaindrivendev/rswag"
|
||||||
s.summary = 'A Rails Engine that exposes OpenAPI (formerly called Swagger) files as JSON endpoints'
|
s.summary = "A Rails Engine that exposes Swagger files as JSON endpoints"
|
||||||
s.description = 'Open up your API to the phenomenal OpenAPI ecosystem by exposing OpenAPI files, that describe your service, as JSON endpoints. More about the OpenAPI initiative here: http://spec.openapis.org/'
|
s.description = "Open up your API to the phenomenal Swagger ecosystem by exposing Swagger files, that describe your service, as JSON endpoints"
|
||||||
s.license = 'MIT'
|
s.license = "MIT"
|
||||||
|
|
||||||
s.files = Dir['{lib}/**/*'] + ['MIT-LICENSE', 'Rakefile']
|
s.files = Dir["{lib}/**/*"] + ["MIT-LICENSE", "Rakefile"]
|
||||||
|
|
||||||
s.add_dependency 'railties', '>= 3.1', '< 7.1'
|
s.add_dependency 'railties', '>= 3.1', '< 6.0'
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
require 'generator_spec'
|
require 'generator_spec'
|
||||||
require 'generators/rswag/api/install/install_generator'
|
require 'generators/rswag/api/install/install_generator'
|
||||||
|
|
||||||
|
|
||||||
module Rswag
|
module Rswag
|
||||||
module Api
|
module Api
|
||||||
|
|
||||||
@ -18,7 +17,7 @@ module Rswag
|
|||||||
end
|
end
|
||||||
|
|
||||||
it 'installs the Rails initializer' do
|
it 'installs the Rails initializer' do
|
||||||
assert_file('config/initializers/rswag_api.rb')
|
assert_file('config/initializers/rswag-api.rb')
|
||||||
end
|
end
|
||||||
|
|
||||||
# Don't know how to test this
|
# Don't know how to test this
|
||||||
@ -26,4 +25,3 @@ module Rswag
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.1",
|
"swagger": "2.0",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "API V1",
|
"title": "API V1",
|
||||||
"version": "v1"
|
"version": "v1"
|
||||||
|
|||||||
@ -1,5 +0,0 @@
|
|||||||
swagger: '2.0'
|
|
||||||
info:
|
|
||||||
title: API V1
|
|
||||||
version: v1
|
|
||||||
paths: {}
|
|
||||||
@ -37,42 +37,6 @@ module Rswag
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when swagger_headers is configured' do
|
|
||||||
let(:env) { env_defaults.merge('PATH_INFO' => 'v1/swagger.json') }
|
|
||||||
|
|
||||||
context 'replacing the default content type header' do
|
|
||||||
before do
|
|
||||||
config.swagger_headers = { 'Content-Type' => 'application/json; charset=UTF-8' }
|
|
||||||
end
|
|
||||||
it 'returns a 200 status' do
|
|
||||||
expect(response.length).to eql(3)
|
|
||||||
expect(response.first).to eql('200')
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'applies the headers to the response' do
|
|
||||||
expect(response[1]).to include( 'Content-Type' => 'application/json; charset=UTF-8')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'adding an additional header' do
|
|
||||||
before do
|
|
||||||
config.swagger_headers = { 'Access-Control-Allow-Origin' => '*' }
|
|
||||||
end
|
|
||||||
it 'returns a 200 status' do
|
|
||||||
expect(response.length).to eql(3)
|
|
||||||
expect(response.first).to eql('200')
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'applies the headers to the response' do
|
|
||||||
expect(response[1]).to include( 'Access-Control-Allow-Origin' => '*')
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'keeps the default header' do
|
|
||||||
expect(response[1]).to include( 'Content-Type' => 'application/json')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "given a path that doesn't map to any swagger file" do
|
context "given a path that doesn't map to any swagger file" do
|
||||||
let(:env) { env_defaults.merge('PATH_INFO' => 'foobar.json') }
|
let(:env) { env_defaults.merge('PATH_INFO' => 'foobar.json') }
|
||||||
before do
|
before do
|
||||||
@ -97,7 +61,7 @@ module Rswag
|
|||||||
it 'locates files at the provided swagger_root' do
|
it 'locates files at the provided swagger_root' do
|
||||||
expect(response.length).to eql(3)
|
expect(response.length).to eql(3)
|
||||||
expect(response[1]).to include( 'Content-Type' => 'application/json')
|
expect(response[1]).to include( 'Content-Type' => 'application/json')
|
||||||
expect(response[2].join).to include('"openapi":"3.0.1"')
|
expect(response[2].join).to include('"swagger":"2.0"')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -112,21 +76,6 @@ module Rswag
|
|||||||
expect(response[2].join).to include('"host":"tempuri.org"')
|
expect(response[2].join).to include('"host":"tempuri.org"')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when a path maps to a yaml swagger file' do
|
|
||||||
let(:env) { env_defaults.merge('PATH_INFO' => 'v1/swagger.yml') }
|
|
||||||
|
|
||||||
it 'returns a 200 status' do
|
|
||||||
expect(response.length).to eql(3)
|
|
||||||
expect(response.first).to eql('200')
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns contents of the swagger file' do
|
|
||||||
expect(response.length).to eql(3)
|
|
||||||
expect(response[1]).to include( 'Content-Type' => 'text/yaml')
|
|
||||||
expect(response[2].join).to include('title: API V1')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -20,4 +20,8 @@ RDoc::Task.new(:rdoc) do |rdoc|
|
|||||||
rdoc.rdoc_files.include('lib/**/*.rb')
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Bundler::GemHelper.install_tasks
|
Bundler::GemHelper.install_tasks
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +0,0 @@
|
|||||||
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
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'rswag/route_parser'
|
|
||||||
require 'rails/generators'
|
|
||||||
|
|
||||||
module Rspec
|
|
||||||
class SwaggerGenerator < ::Rails::Generators::NamedBase
|
|
||||||
source_root File.expand_path('templates', __dir__)
|
|
||||||
|
|
||||||
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
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
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][:content] = {
|
|
||||||
'application/json' => {
|
|
||||||
example: JSON.parse(response.body, symbolize_names: true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
end
|
|
||||||
run_test!
|
|
||||||
end
|
|
||||||
end
|
|
||||||
<% end -%>
|
|
||||||
end
|
|
||||||
<% end -%>
|
|
||||||
end
|
|
||||||
@ -1,11 +1,10 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'rails/generators'
|
require 'rails/generators'
|
||||||
|
|
||||||
module Rswag
|
module Rswag
|
||||||
module Specs
|
module Specs
|
||||||
|
|
||||||
class InstallGenerator < Rails::Generators::Base
|
class InstallGenerator < Rails::Generators::Base
|
||||||
source_root File.expand_path('templates', __dir__)
|
source_root File.expand_path('../templates', __FILE__)
|
||||||
|
|
||||||
def add_swagger_helper
|
def add_swagger_helper
|
||||||
template('swagger_helper.rb', 'spec/swagger_helper.rb')
|
template('swagger_helper.rb', 'spec/swagger_helper.rb')
|
||||||
|
|||||||
@ -1,43 +1,25 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
RSpec.configure do |config|
|
RSpec.configure do |config|
|
||||||
# Specify a root folder where Swagger JSON files are generated
|
# Specify a root folder where Swagger JSON files are generated
|
||||||
# NOTE: If you're using the rswag-api to serve API descriptions, you'll need
|
# NOTE: If you're using the rswag-api to serve API descriptions, you'll need
|
||||||
# to ensure that it's configured to serve Swagger from the same folder
|
# to ensure that it's confiugred to server Swagger from the same folder
|
||||||
config.swagger_root = Rails.root.join('swagger').to_s
|
config.swagger_root = Rails.root.to_s + '/swagger'
|
||||||
|
|
||||||
# Define one or more Swagger documents and provide global metadata for each one
|
# Define one or more Swagger documents and provide global metadata for each one
|
||||||
# When you run the 'rswag:specs:swaggerize' rake task, the complete Swagger will
|
# When you run the 'rswag:specs:to_swagger' rake task, the complete Swagger will
|
||||||
# be generated at the provided relative path under swagger_root
|
# be generated at the provided relative path under swagger_root
|
||||||
# By default, the operations defined in spec files are added to the first
|
# By default, the operations defined in spec files are added to the first
|
||||||
# document below. You can override this behavior by adding a swagger_doc tag to the
|
# document below. You can override this behavior by adding a swagger_doc tag to the
|
||||||
# the root example_group in your specs, e.g. describe '...', swagger_doc: 'v2/swagger.json'
|
# the root example_group in your specs, e.g. describe '...', swagger_doc: 'v2/swagger.json'
|
||||||
config.swagger_docs = {
|
config.swagger_docs = {
|
||||||
'v1/swagger.yaml' => {
|
'v1/swagger.json' => {
|
||||||
openapi: '3.0.1',
|
swagger: '2.0',
|
||||||
info: {
|
info: {
|
||||||
title: 'API V1',
|
title: 'API V1',
|
||||||
version: 'v1'
|
version: 'v1'
|
||||||
},
|
},
|
||||||
paths: {},
|
paths: {}
|
||||||
servers: [
|
|
||||||
{
|
|
||||||
url: 'https://{defaultHost}',
|
|
||||||
variables: {
|
|
||||||
defaultHost: {
|
|
||||||
default: 'www.example.com'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Specify the format of the output Swagger file when running 'rswag:specs:swaggerize'.
|
|
||||||
# The swagger_docs configuration option has the filename including format in
|
|
||||||
# the key, this may want to be changed to avoid putting yaml in json files.
|
|
||||||
# Defaults to json. Accepts ':json' and ':yaml'.
|
|
||||||
config.swagger_format = :yaml
|
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,60 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
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.each_with_object({}) do |route, tree|
|
|
||||||
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.is_a? 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
|
|
||||||
@ -1,5 +1,3 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'rspec/core'
|
require 'rspec/core'
|
||||||
require 'rswag/specs/example_group_helpers'
|
require 'rswag/specs/example_group_helpers'
|
||||||
require 'rswag/specs/example_helpers'
|
require 'rswag/specs/example_helpers'
|
||||||
@ -8,12 +6,12 @@ require 'rswag/specs/railtie' if defined?(Rails::Railtie)
|
|||||||
|
|
||||||
module Rswag
|
module Rswag
|
||||||
module Specs
|
module Specs
|
||||||
|
|
||||||
# Extend RSpec with a swagger-based DSL
|
# Extend RSpec with a swagger-based DSL
|
||||||
::RSpec.configure do |c|
|
::RSpec.configure do |c|
|
||||||
c.add_setting :swagger_root
|
c.add_setting :swagger_root
|
||||||
c.add_setting :swagger_docs
|
c.add_setting :swagger_docs
|
||||||
c.add_setting :swagger_dry_run
|
c.add_setting :swagger_dry_run
|
||||||
c.add_setting :swagger_format
|
|
||||||
c.extend ExampleGroupHelpers, type: :request
|
c.extend ExampleGroupHelpers, type: :request
|
||||||
c.include ExampleHelpers, type: :request
|
c.include ExampleHelpers, type: :request
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module Rswag
|
module Rswag
|
||||||
module Specs
|
module Specs
|
||||||
|
|
||||||
class Configuration
|
class Configuration
|
||||||
|
|
||||||
def initialize(rspec_config)
|
def initialize(rspec_config)
|
||||||
@rspec_config = rspec_config
|
@rspec_config = rspec_config
|
||||||
end
|
end
|
||||||
@ -12,7 +12,6 @@ module Rswag
|
|||||||
if @rspec_config.swagger_root.nil?
|
if @rspec_config.swagger_root.nil?
|
||||||
raise ConfigurationError, 'No swagger_root provided. See swagger_helper.rb'
|
raise ConfigurationError, 'No swagger_root provided. See swagger_helper.rb'
|
||||||
end
|
end
|
||||||
|
|
||||||
@rspec_config.swagger_root
|
@rspec_config.swagger_root
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -22,39 +21,21 @@ module Rswag
|
|||||||
if @rspec_config.swagger_docs.nil? || @rspec_config.swagger_docs.empty?
|
if @rspec_config.swagger_docs.nil? || @rspec_config.swagger_docs.empty?
|
||||||
raise ConfigurationError, 'No swagger_docs defined. See swagger_helper.rb'
|
raise ConfigurationError, 'No swagger_docs defined. See swagger_helper.rb'
|
||||||
end
|
end
|
||||||
|
|
||||||
@rspec_config.swagger_docs
|
@rspec_config.swagger_docs
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def swagger_dry_run
|
def swagger_dry_run
|
||||||
return @swagger_dry_run if defined? @swagger_dry_run
|
@swagger_dry_run ||= begin
|
||||||
if ENV.key?('SWAGGER_DRY_RUN')
|
@rspec_config.swagger_dry_run.nil? || @rspec_config.swagger_dry_run
|
||||||
@rspec_config.swagger_dry_run = ENV['SWAGGER_DRY_RUN'] == '1'
|
|
||||||
end
|
|
||||||
@swagger_dry_run = @rspec_config.swagger_dry_run.nil? || @rspec_config.swagger_dry_run
|
|
||||||
end
|
|
||||||
|
|
||||||
def swagger_format
|
|
||||||
@swagger_format ||= begin
|
|
||||||
@rspec_config.swagger_format = :json if @rspec_config.swagger_format.nil? || @rspec_config.swagger_format.empty?
|
|
||||||
raise ConfigurationError, "Unknown swagger_format '#{@rspec_config.swagger_format}'" unless [:json, :yaml].include?(@rspec_config.swagger_format)
|
|
||||||
|
|
||||||
@rspec_config.swagger_format
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_swagger_doc(name)
|
def get_swagger_doc(name)
|
||||||
return swagger_docs.values.first if name.nil?
|
return swagger_docs.values.first if name.nil?
|
||||||
raise ConfigurationError, "Unknown swagger_doc '#{name}'" unless swagger_docs[name]
|
raise ConfigurationError, "Unknown swagger_doc '#{name}'" unless swagger_docs[name]
|
||||||
|
|
||||||
swagger_docs[name]
|
swagger_docs[name]
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_swagger_doc_version(name)
|
|
||||||
doc = get_swagger_doc(name)
|
|
||||||
doc[:openapi] || doc[:swagger]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class ConfigurationError < StandardError; end
|
class ConfigurationError < StandardError; end
|
||||||
|
|||||||
@ -1,21 +1,20 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module Rswag
|
module Rswag
|
||||||
module Specs
|
module Specs
|
||||||
module ExampleGroupHelpers
|
module ExampleGroupHelpers
|
||||||
def path(template, metadata = {}, &block)
|
|
||||||
|
def path(template, metadata={}, &block)
|
||||||
metadata[:path_item] = { template: template }
|
metadata[:path_item] = { template: template }
|
||||||
describe(template, metadata, &block)
|
describe(template, metadata, &block)
|
||||||
end
|
end
|
||||||
|
|
||||||
[:get, :post, :patch, :put, :delete, :head, :options, :trace].each do |verb|
|
[ :get, :post, :patch, :put, :delete, :head ].each do |verb|
|
||||||
define_method(verb) do |summary, &block|
|
define_method(verb) do |summary, &block|
|
||||||
api_metadata = { operation: { verb: verb, summary: summary } }
|
api_metadata = { operation: { verb: verb, summary: summary } }
|
||||||
describe(verb, api_metadata, &block)
|
describe(verb, api_metadata, &block)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
[:operationId, :deprecated, :security].each do |attr_name|
|
[ :operationId, :deprecated, :security ].each do |attr_name|
|
||||||
define_method(attr_name) do |value|
|
define_method(attr_name) do |value|
|
||||||
metadata[:operation][attr_name] = value
|
metadata[:operation][attr_name] = value
|
||||||
end
|
end
|
||||||
@ -24,14 +23,13 @@ module Rswag
|
|||||||
# NOTE: 'description' requires special treatment because ExampleGroup already
|
# NOTE: 'description' requires special treatment because ExampleGroup already
|
||||||
# defines a method with that name. Provide an override that supports the existing
|
# defines a method with that name. Provide an override that supports the existing
|
||||||
# functionality while also setting the appropriate metadata if applicable
|
# functionality while also setting the appropriate metadata if applicable
|
||||||
def description(value = nil)
|
def description(value=nil)
|
||||||
return super() if value.nil?
|
return super() if value.nil?
|
||||||
|
|
||||||
metadata[:operation][:description] = value
|
metadata[:operation][:description] = value
|
||||||
end
|
end
|
||||||
|
|
||||||
# These are array properties - note the splat operator
|
# These are array properties - note the splat operator
|
||||||
[:tags, :consumes, :produces, :schemes].each do |attr_name|
|
[ :tags, :consumes, :produces, :schemes ].each do |attr_name|
|
||||||
define_method(attr_name) do |*value|
|
define_method(attr_name) do |*value|
|
||||||
metadata[:operation][attr_name] = value
|
metadata[:operation][attr_name] = value
|
||||||
end
|
end
|
||||||
@ -42,7 +40,7 @@ module Rswag
|
|||||||
attributes[:required] = true
|
attributes[:required] = true
|
||||||
end
|
end
|
||||||
|
|
||||||
if metadata.key?(:operation)
|
if metadata.has_key?(:operation)
|
||||||
metadata[:operation][:parameters] ||= []
|
metadata[:operation][:parameters] ||= []
|
||||||
metadata[:operation][:parameters] << attributes
|
metadata[:operation][:parameters] << attributes
|
||||||
else
|
else
|
||||||
@ -51,7 +49,7 @@ module Rswag
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def response(code, description, metadata = {}, &block)
|
def response(code, description, metadata={}, &block)
|
||||||
metadata[:response] = { code: code, description: description }
|
metadata[:response] = { code: code, description: description }
|
||||||
context(description, metadata, &block)
|
context(description, metadata, &block)
|
||||||
end
|
end
|
||||||
@ -62,7 +60,6 @@ module Rswag
|
|||||||
|
|
||||||
def header(name, attributes)
|
def header(name, attributes)
|
||||||
metadata[:response][:headers] ||= {}
|
metadata[:response][:headers] ||= {}
|
||||||
|
|
||||||
metadata[:response][:headers][name] = attributes
|
metadata[:response][:headers][name] = attributes
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -71,11 +68,7 @@ module Rswag
|
|||||||
# rspec-core ExampleGroup
|
# rspec-core ExampleGroup
|
||||||
def examples(example = nil)
|
def examples(example = nil)
|
||||||
return super() if example.nil?
|
return super() if example.nil?
|
||||||
|
metadata[:response][:examples] = example
|
||||||
metadata[:response][:content] =
|
|
||||||
example.each_with_object({}) do |(mime, example_object), memo|
|
|
||||||
memo[mime] = { example: example_object }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def run_test!(&block)
|
def run_test!(&block)
|
||||||
|
|||||||
@ -1,11 +1,10 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'rswag/specs/request_factory'
|
require 'rswag/specs/request_factory'
|
||||||
require 'rswag/specs/response_validator'
|
require 'rswag/specs/response_validator'
|
||||||
|
|
||||||
module Rswag
|
module Rswag
|
||||||
module Specs
|
module Specs
|
||||||
module ExampleHelpers
|
module ExampleHelpers
|
||||||
|
|
||||||
def submit_request(metadata)
|
def submit_request(metadata)
|
||||||
request = RequestFactory.new.build_request(metadata, self)
|
request = RequestFactory.new.build_request(metadata, self)
|
||||||
|
|
||||||
@ -20,8 +19,10 @@ module Rswag
|
|||||||
send(
|
send(
|
||||||
request[:verb],
|
request[:verb],
|
||||||
request[:path],
|
request[:path],
|
||||||
params: request[:payload],
|
{
|
||||||
headers: request[:headers]
|
params: request[:payload],
|
||||||
|
headers: request[:headers]
|
||||||
|
}
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'json-schema'
|
require 'json-schema'
|
||||||
|
|
||||||
module Rswag
|
module Rswag
|
||||||
module Specs
|
module Specs
|
||||||
class ExtendedSchema < JSON::Schema::Draft4
|
class ExtendedSchema < JSON::Schema::Draft4
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
super
|
super
|
||||||
@attributes['type'] = ExtendedTypeAttribute
|
@attributes['type'] = ExtendedTypeAttribute
|
||||||
@ -14,9 +13,9 @@ module Rswag
|
|||||||
end
|
end
|
||||||
|
|
||||||
class ExtendedTypeAttribute < JSON::Schema::TypeV4Attribute
|
class ExtendedTypeAttribute < JSON::Schema::TypeV4Attribute
|
||||||
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
|
||||||
return if data.nil? && (current_schema.schema['nullable'] == true || current_schema.schema['x-nullable'] == true)
|
|
||||||
|
|
||||||
|
def self.validate(current_schema, data, fragments, processor, validator, options={})
|
||||||
|
return if data.nil? && current_schema.schema['x-nullable'] == true
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,14 +1,9 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module Rswag
|
module Rswag
|
||||||
module Specs
|
module Specs
|
||||||
class Railtie < ::Rails::Railtie
|
class Railtie < ::Rails::Railtie
|
||||||
rake_tasks do
|
|
||||||
load File.expand_path('../../tasks/rswag-specs_tasks.rake', __dir__)
|
|
||||||
end
|
|
||||||
|
|
||||||
generators do
|
rake_tasks do
|
||||||
require 'generators/rspec/swagger_generator.rb'
|
load File.expand_path('../../../tasks/rswag-specs_tasks.rake', __FILE__)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'active_support/core_ext/hash/slice'
|
require 'active_support/core_ext/hash/slice'
|
||||||
require 'active_support/core_ext/hash/conversions'
|
require 'active_support/core_ext/hash/conversions'
|
||||||
require 'json'
|
require 'json'
|
||||||
@ -7,6 +5,7 @@ require 'json'
|
|||||||
module Rswag
|
module Rswag
|
||||||
module Specs
|
module Specs
|
||||||
class RequestFactory
|
class RequestFactory
|
||||||
|
|
||||||
def initialize(config = ::Rswag::Specs.config)
|
def initialize(config = ::Rswag::Specs.config)
|
||||||
@config = config
|
@config = config
|
||||||
end
|
end
|
||||||
@ -39,8 +38,8 @@ module Rswag
|
|||||||
|
|
||||||
def derive_security_params(metadata, swagger_doc)
|
def derive_security_params(metadata, swagger_doc)
|
||||||
requirements = metadata[:operation][:security] || swagger_doc[:security] || []
|
requirements = metadata[:operation][:security] || swagger_doc[:security] || []
|
||||||
scheme_names = requirements.flat_map(&:keys)
|
scheme_names = requirements.flat_map { |r| r.keys }
|
||||||
schemes = security_version(scheme_names, swagger_doc)
|
schemes = (swagger_doc[:securityDefinitions] || {}).slice(*scheme_names).values
|
||||||
|
|
||||||
schemes.map do |scheme|
|
schemes.map do |scheme|
|
||||||
param = (scheme[:type] == :apiKey) ? scheme.slice(:name, :in) : { name: 'Authorization', in: :header }
|
param = (scheme[:type] == :apiKey) ? scheme.slice(:name, :in) : { name: 'Authorization', in: :header }
|
||||||
@ -48,55 +47,13 @@ module Rswag
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def security_version(scheme_names, swagger_doc)
|
|
||||||
if doc_version(swagger_doc).start_with?('2')
|
|
||||||
(swagger_doc[:securityDefinitions] || {}).slice(*scheme_names).values
|
|
||||||
else # Openapi3
|
|
||||||
if swagger_doc.key?(:securityDefinitions)
|
|
||||||
ActiveSupport::Deprecation.warn('Rswag::Specs: WARNING: securityDefinitions is replaced in OpenAPI3! Rename to components/securitySchemes (in swagger_helper.rb)')
|
|
||||||
swagger_doc[:components] ||= { securitySchemes: swagger_doc[:securityDefinitions] }
|
|
||||||
swagger_doc.delete(:securityDefinitions)
|
|
||||||
end
|
|
||||||
components = swagger_doc[:components] || {}
|
|
||||||
(components[:securitySchemes] || {}).slice(*scheme_names).values
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def resolve_parameter(ref, swagger_doc)
|
def resolve_parameter(ref, swagger_doc)
|
||||||
key = key_version(ref, swagger_doc)
|
key = ref.sub('#/parameters/', '').to_sym
|
||||||
definitions = definition_version(swagger_doc)
|
definitions = swagger_doc[:parameters]
|
||||||
raise "Referenced parameter '#{ref}' must be defined" unless definitions && definitions[key]
|
raise "Referenced parameter '#{ref}' must be defined" unless definitions && definitions[key]
|
||||||
|
|
||||||
definitions[key]
|
definitions[key]
|
||||||
end
|
end
|
||||||
|
|
||||||
def key_version(ref, swagger_doc)
|
|
||||||
if doc_version(swagger_doc).start_with?('2')
|
|
||||||
ref.sub('#/parameters/', '').to_sym
|
|
||||||
else # Openapi3
|
|
||||||
if ref.start_with?('#/parameters/')
|
|
||||||
ActiveSupport::Deprecation.warn('Rswag::Specs: WARNING: #/parameters/ refs are replaced in OpenAPI3! Rename to #/components/parameters/')
|
|
||||||
ref.sub('#/parameters/', '').to_sym
|
|
||||||
else
|
|
||||||
ref.sub('#/components/parameters/', '').to_sym
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def definition_version(swagger_doc)
|
|
||||||
if doc_version(swagger_doc).start_with?('2')
|
|
||||||
swagger_doc[:parameters]
|
|
||||||
else # Openapi3
|
|
||||||
if swagger_doc.key?(:parameters)
|
|
||||||
ActiveSupport::Deprecation.warn('Rswag::Specs: WARNING: parameters is replaced in OpenAPI3! Rename to components/parameters (in swagger_helper.rb)')
|
|
||||||
swagger_doc[:parameters]
|
|
||||||
else
|
|
||||||
components = swagger_doc[:components] || {}
|
|
||||||
components[:parameters]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_verb(request, metadata)
|
def add_verb(request, metadata)
|
||||||
request[:verb] = metadata[:operation][:verb]
|
request[:verb] = metadata[:operation][:verb]
|
||||||
end
|
end
|
||||||
@ -104,22 +61,21 @@ module Rswag
|
|||||||
def add_path(request, metadata, swagger_doc, parameters, example)
|
def add_path(request, metadata, swagger_doc, parameters, example)
|
||||||
template = (swagger_doc[:basePath] || '') + metadata[:path_item][:template]
|
template = (swagger_doc[:basePath] || '') + metadata[:path_item][:template]
|
||||||
|
|
||||||
request[:path] = template.tap do |path_template|
|
request[:path] = template.tap do |template|
|
||||||
parameters.select { |p| p[:in] == :path }.each do |p|
|
parameters.select { |p| p[:in] == :path }.each do |p|
|
||||||
path_template.gsub!("{#{p[:name]}}", example.send(p[:name]).to_s)
|
template.gsub!("{#{p[:name]}}", example.send(p[:name]).to_s)
|
||||||
end
|
end
|
||||||
|
|
||||||
parameters.select { |p| p[:in] == :query }.each_with_index do |p, i|
|
parameters.select { |p| p[:in] == :query }.each_with_index do |p, i|
|
||||||
path_template.concat(i.zero? ? '?' : '&')
|
template.concat(i == 0 ? '?' : '&')
|
||||||
path_template.concat(build_query_string_part(p, example.send(p[:name])))
|
template.concat(build_query_string_part(p, example.send(p[:name])))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def build_query_string_part(param, value)
|
def build_query_string_part(param, value)
|
||||||
name = param[:name]
|
name = param[:name]
|
||||||
type = param[:type] || param.dig(:schema, :type)
|
return "#{name}=#{value.to_s}" unless param[:type].to_sym == :array
|
||||||
return "#{name}=#{value}" unless type&.to_sym == :array
|
|
||||||
|
|
||||||
case param[:collectionFormat]
|
case param[:collectionFormat]
|
||||||
when :ssv
|
when :ssv
|
||||||
@ -138,43 +94,43 @@ module Rswag
|
|||||||
def add_headers(request, metadata, swagger_doc, parameters, example)
|
def add_headers(request, metadata, swagger_doc, parameters, example)
|
||||||
tuples = parameters
|
tuples = parameters
|
||||||
.select { |p| p[:in] == :header }
|
.select { |p| p[:in] == :header }
|
||||||
.map { |p| [p[:name], example.send(p[:name]).to_s] }
|
.map { |p| [ p[:name], example.send(p[:name]).to_s ] }
|
||||||
|
|
||||||
# Accept header
|
# Accept header
|
||||||
produces = metadata[:operation][:produces] || swagger_doc[:produces]
|
produces = metadata[:operation][:produces] || swagger_doc[:produces]
|
||||||
if produces
|
if produces
|
||||||
accept = example.respond_to?(:Accept) ? example.send(:Accept) : produces.first
|
accept = example.respond_to?(:'Accept') ? example.send(:'Accept') : produces.first
|
||||||
tuples << ['Accept', accept]
|
tuples << [ 'Accept', accept ]
|
||||||
end
|
end
|
||||||
|
|
||||||
# Content-Type header
|
# Content-Type header
|
||||||
consumes = metadata[:operation][:consumes] || swagger_doc[:consumes]
|
consumes = metadata[:operation][:consumes] || swagger_doc[:consumes]
|
||||||
if consumes
|
if consumes
|
||||||
content_type = example.respond_to?(:'Content-Type') ? example.send(:'Content-Type') : consumes.first
|
content_type = example.respond_to?(:'Content-Type') ? example.send(:'Content-Type') : consumes.first
|
||||||
tuples << ['Content-Type', content_type]
|
tuples << [ 'Content-Type', content_type ]
|
||||||
end
|
end
|
||||||
|
|
||||||
# Rails test infrastructure requires rackified headers
|
# Rails test infrastructure requires rackified headers
|
||||||
rackified_tuples = tuples.map do |pair|
|
rackified_tuples = tuples.map do |pair|
|
||||||
[
|
[
|
||||||
case pair[0]
|
case pair[0]
|
||||||
when 'Accept' then 'HTTP_ACCEPT'
|
when 'Accept' then 'HTTP_ACCEPT'
|
||||||
when 'Content-Type' then 'CONTENT_TYPE'
|
when 'Content-Type' then 'CONTENT_TYPE'
|
||||||
when 'Authorization' then 'HTTP_AUTHORIZATION'
|
when 'Authorization' then 'HTTP_AUTHORIZATION'
|
||||||
else pair[0]
|
else pair[0]
|
||||||
end,
|
end,
|
||||||
pair[1]
|
pair[1]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
request[:headers] = Hash[rackified_tuples]
|
request[:headers] = Hash[ rackified_tuples ]
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_payload(request, parameters, example)
|
def add_payload(request, parameters, example)
|
||||||
content_type = request[:headers]['CONTENT_TYPE']
|
content_type = request[:headers]['CONTENT_TYPE']
|
||||||
return if content_type.nil?
|
return if content_type.nil?
|
||||||
|
|
||||||
if ['application/x-www-form-urlencoded', 'multipart/form-data'].include?(content_type)
|
if [ 'application/x-www-form-urlencoded', 'multipart/form-data' ].include?(content_type)
|
||||||
request[:payload] = build_form_payload(parameters, example)
|
request[:payload] = build_form_payload(parameters, example)
|
||||||
else
|
else
|
||||||
request[:payload] = build_json_payload(parameters, example)
|
request[:payload] = build_json_payload(parameters, example)
|
||||||
@ -188,41 +144,13 @@ module Rswag
|
|||||||
# PROS: simple to implement, CONS: serialization/deserialization is bypassed in test
|
# PROS: simple to implement, CONS: serialization/deserialization is bypassed in test
|
||||||
tuples = parameters
|
tuples = parameters
|
||||||
.select { |p| p[:in] == :formData }
|
.select { |p| p[:in] == :formData }
|
||||||
.map { |p| [p[:name], example.send(p[:name])] }
|
.map { |p| [ p[:name], example.send(p[:name]) ] }
|
||||||
Hash[tuples]
|
Hash[ tuples ]
|
||||||
end
|
end
|
||||||
|
|
||||||
def build_json_payload(parameters, example)
|
def build_json_payload(parameters, example)
|
||||||
body_param = parameters.select { |p| p[:in] == :body }.first
|
body_param = parameters.select { |p| p[:in] == :body }.first
|
||||||
|
body_param ? example.send(body_param[:name]).to_json : nil
|
||||||
return nil unless body_param
|
|
||||||
|
|
||||||
raise(MissingParameterError, body_param[:name]) unless example.respond_to?(body_param[:name])
|
|
||||||
|
|
||||||
example.send(body_param[:name]).to_json
|
|
||||||
end
|
|
||||||
|
|
||||||
def doc_version(doc)
|
|
||||||
doc[:openapi] || doc[:swagger] || '3'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class MissingParameterError < StandardError
|
|
||||||
attr_reader :body_param
|
|
||||||
|
|
||||||
def initialize(body_param)
|
|
||||||
@body_param = body_param
|
|
||||||
end
|
|
||||||
|
|
||||||
def message
|
|
||||||
<<~MSG
|
|
||||||
Missing parameter '#{body_param}'
|
|
||||||
|
|
||||||
Please check your spec. It looks like you defined a body parameter,
|
|
||||||
but did not declare usage via let. Try adding:
|
|
||||||
|
|
||||||
let(:#{body_param}) {}
|
|
||||||
MSG
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'active_support/core_ext/hash/slice'
|
require 'active_support/core_ext/hash/slice'
|
||||||
require 'json-schema'
|
require 'json-schema'
|
||||||
require 'json'
|
require 'json'
|
||||||
@ -8,6 +6,7 @@ require 'rswag/specs/extended_schema'
|
|||||||
module Rswag
|
module Rswag
|
||||||
module Specs
|
module Specs
|
||||||
class ResponseValidator
|
class ResponseValidator
|
||||||
|
|
||||||
def initialize(config = ::Rswag::Specs.config)
|
def initialize(config = ::Rswag::Specs.config)
|
||||||
@config = config
|
@config = config
|
||||||
end
|
end
|
||||||
@ -15,19 +14,17 @@ module Rswag
|
|||||||
def validate!(metadata, response)
|
def validate!(metadata, response)
|
||||||
swagger_doc = @config.get_swagger_doc(metadata[:swagger_doc])
|
swagger_doc = @config.get_swagger_doc(metadata[:swagger_doc])
|
||||||
|
|
||||||
validate_code!(metadata, response)
|
validate_code!(metadata, response.code)
|
||||||
validate_headers!(metadata, response.headers)
|
validate_headers!(metadata, response.headers)
|
||||||
validate_body!(metadata, swagger_doc, response.body)
|
validate_body!(metadata, swagger_doc, response.body)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def validate_code!(metadata, response)
|
def validate_code!(metadata, code)
|
||||||
expected = metadata[:response][:code].to_s
|
expected = metadata[:response][:code].to_s
|
||||||
if response.code != expected
|
if code != expected
|
||||||
raise UnexpectedResponse,
|
raise UnexpectedResponse, "Expected response code '#{code}' to match '#{expected}'"
|
||||||
"Expected response code '#{response.code}' to match '#{expected}'\n" \
|
|
||||||
"Response body: #{response.body}"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -42,33 +39,11 @@ module Rswag
|
|||||||
response_schema = metadata[:response][:schema]
|
response_schema = metadata[:response][:schema]
|
||||||
return if response_schema.nil?
|
return if response_schema.nil?
|
||||||
|
|
||||||
version = @config.get_swagger_doc_version(metadata[:swagger_doc])
|
|
||||||
schemas = definitions_or_component_schemas(swagger_doc, version)
|
|
||||||
|
|
||||||
validation_schema = response_schema
|
validation_schema = response_schema
|
||||||
.merge('$schema' => 'http://tempuri.org/rswag/specs/extended_schema')
|
.merge('$schema' => 'http://tempuri.org/rswag/specs/extended_schema')
|
||||||
.merge(schemas)
|
.merge(swagger_doc.slice(:definitions))
|
||||||
|
|
||||||
errors = JSON::Validator.fully_validate(validation_schema, body)
|
errors = JSON::Validator.fully_validate(validation_schema, body)
|
||||||
return unless errors.any?
|
raise UnexpectedResponse, "Expected response body to match schema: #{errors[0]}" if errors.any?
|
||||||
|
|
||||||
raise UnexpectedResponse,
|
|
||||||
"Expected response body to match schema: #{errors[0]}\n" \
|
|
||||||
"Response body: #{JSON.pretty_generate(JSON.parse(body))}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def definitions_or_component_schemas(swagger_doc, version)
|
|
||||||
if version.start_with?('2')
|
|
||||||
swagger_doc.slice(:definitions)
|
|
||||||
else # Openapi3
|
|
||||||
if swagger_doc.key?(:definitions)
|
|
||||||
ActiveSupport::Deprecation.warn('Rswag::Specs: WARNING: definitions is replaced in OpenAPI3! Rename to components/schemas (in swagger_helper.rb)')
|
|
||||||
swagger_doc.slice(:definitions)
|
|
||||||
else
|
|
||||||
components = swagger_doc[:components] || {}
|
|
||||||
{ components: components }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +1,9 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'active_support/core_ext/hash/deep_merge'
|
require 'active_support/core_ext/hash/deep_merge'
|
||||||
require 'rspec/core/formatters/base_text_formatter'
|
|
||||||
require 'swagger_helper'
|
require 'swagger_helper'
|
||||||
|
|
||||||
module Rswag
|
module Rswag
|
||||||
module Specs
|
module Specs
|
||||||
class SwaggerFormatter < ::RSpec::Core::Formatters::BaseTextFormatter
|
class SwaggerFormatter
|
||||||
|
|
||||||
# NOTE: rspec 2.x support
|
# NOTE: rspec 2.x support
|
||||||
if RSPEC_VERSION > 2
|
if RSPEC_VERSION > 2
|
||||||
@ -22,62 +19,25 @@ module Rswag
|
|||||||
|
|
||||||
def example_group_finished(notification)
|
def example_group_finished(notification)
|
||||||
# NOTE: rspec 2.x support
|
# NOTE: rspec 2.x support
|
||||||
metadata = if RSPEC_VERSION > 2
|
if RSPEC_VERSION > 2
|
||||||
notification.group.metadata
|
metadata = notification.group.metadata
|
||||||
else
|
else
|
||||||
notification.metadata
|
metadata = notification.metadata
|
||||||
end
|
end
|
||||||
|
|
||||||
# !metadata[:document] won't work, since nil means we should generate
|
return unless metadata.has_key?(:response)
|
||||||
# docs.
|
|
||||||
return if metadata[:document] == false
|
|
||||||
return unless metadata.key?(:response)
|
|
||||||
|
|
||||||
swagger_doc = @config.get_swagger_doc(metadata[:swagger_doc])
|
swagger_doc = @config.get_swagger_doc(metadata[:swagger_doc])
|
||||||
|
|
||||||
unless doc_version(swagger_doc).start_with?('2')
|
|
||||||
# This is called multiple times per file!
|
|
||||||
# metadata[:operation] is also re-used between examples within file
|
|
||||||
# therefore be careful NOT to modify its content here.
|
|
||||||
upgrade_request_type!(metadata)
|
|
||||||
upgrade_servers!(swagger_doc)
|
|
||||||
upgrade_oauth!(swagger_doc)
|
|
||||||
upgrade_response_produces!(swagger_doc, metadata)
|
|
||||||
end
|
|
||||||
|
|
||||||
swagger_doc.deep_merge!(metadata_to_swagger(metadata))
|
swagger_doc.deep_merge!(metadata_to_swagger(metadata))
|
||||||
end
|
end
|
||||||
|
|
||||||
def stop(_notification = nil)
|
def stop(notification=nil)
|
||||||
@config.swagger_docs.each do |url_path, doc|
|
@config.swagger_docs.each do |url_path, doc|
|
||||||
unless doc_version(doc).start_with?('2')
|
|
||||||
doc[:paths]&.each_pair do |_k, v|
|
|
||||||
v.each_pair do |_verb, value|
|
|
||||||
is_hash = value.is_a?(Hash)
|
|
||||||
if is_hash && value.dig(:parameters)
|
|
||||||
schema_param = value.dig(:parameters)&.find { |p| (p[:in] == :body || p[:in] == :formData) && p[:schema] }
|
|
||||||
mime_list = value.dig(:consumes) || doc[:consumes]
|
|
||||||
if value && schema_param && mime_list
|
|
||||||
value[:requestBody] = { content: {} } unless value.dig(:requestBody, :content)
|
|
||||||
value[:requestBody][:required] = true if schema_param[:required]
|
|
||||||
mime_list.each do |mime|
|
|
||||||
value[:requestBody][:content][mime] = { schema: schema_param[:schema] }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
value[:parameters].reject! { |p| p[:in] == :body || p[:in] == :formData }
|
|
||||||
end
|
|
||||||
remove_invalid_operation_keys!(value)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
file_path = File.join(@config.swagger_root, url_path)
|
file_path = File.join(@config.swagger_root, url_path)
|
||||||
dirname = File.dirname(file_path)
|
dirname = File.dirname(file_path)
|
||||||
FileUtils.mkdir_p dirname unless File.exist?(dirname)
|
FileUtils.mkdir_p dirname unless File.exists?(dirname)
|
||||||
|
|
||||||
File.open(file_path, 'w') do |file|
|
File.open(file_path, 'w') do |file|
|
||||||
file.write(pretty_generate(doc))
|
file.write(JSON.pretty_generate(doc))
|
||||||
end
|
end
|
||||||
|
|
||||||
@output.puts "Swagger doc generated at #{file_path}"
|
@output.puts "Swagger doc generated at #{file_path}"
|
||||||
@ -86,119 +46,22 @@ module Rswag
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def pretty_generate(doc)
|
|
||||||
if @config.swagger_format == :yaml
|
|
||||||
clean_doc = yaml_prepare(doc)
|
|
||||||
YAML.dump(clean_doc)
|
|
||||||
else # config errors are thrown in 'def swagger_format', no throw needed here
|
|
||||||
JSON.pretty_generate(doc)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def yaml_prepare(doc)
|
|
||||||
json_doc = JSON.pretty_generate(doc)
|
|
||||||
JSON.parse(json_doc)
|
|
||||||
end
|
|
||||||
|
|
||||||
def metadata_to_swagger(metadata)
|
def metadata_to_swagger(metadata)
|
||||||
response_code = metadata[:response][:code]
|
response_code = metadata[:response][:code]
|
||||||
response = metadata[:response].reject { |k, _v| k == :code }
|
response = metadata[:response].reject { |k,v| k == :code }
|
||||||
|
|
||||||
verb = metadata[:operation][:verb]
|
verb = metadata[:operation][:verb]
|
||||||
operation = metadata[:operation]
|
operation = metadata[:operation]
|
||||||
.reject { |k, _v| k == :verb }
|
.reject { |k,v| k == :verb }
|
||||||
.merge(responses: { response_code => response })
|
.merge(responses: { response_code => response })
|
||||||
|
|
||||||
path_template = metadata[:path_item][:template]
|
path_template = metadata[:path_item][:template]
|
||||||
path_item = metadata[:path_item]
|
path_item = metadata[:path_item]
|
||||||
.reject { |k, _v| k == :template }
|
.reject { |k,v| k == :template }
|
||||||
.merge(verb => operation)
|
.merge(verb => operation)
|
||||||
|
|
||||||
{ paths: { path_template => path_item } }
|
{ paths: { path_template => path_item } }
|
||||||
end
|
end
|
||||||
|
|
||||||
def doc_version(doc)
|
|
||||||
doc[:openapi] || doc[:swagger] || '3'
|
|
||||||
end
|
|
||||||
|
|
||||||
def upgrade_response_produces!(swagger_doc, metadata)
|
|
||||||
# Accept header
|
|
||||||
mime_list = Array(metadata[:operation][:produces] || swagger_doc[:produces])
|
|
||||||
target_node = metadata[:response]
|
|
||||||
upgrade_content!(mime_list, target_node)
|
|
||||||
metadata[:response].delete(:schema)
|
|
||||||
end
|
|
||||||
|
|
||||||
def upgrade_content!(mime_list, target_node)
|
|
||||||
schema = target_node[:schema]
|
|
||||||
return if mime_list.empty? || schema.nil?
|
|
||||||
|
|
||||||
target_node[:content] ||= {}
|
|
||||||
mime_list.each do |mime_type|
|
|
||||||
# TODO upgrade to have content-type specific schema
|
|
||||||
(target_node[:content][mime_type] ||= {}).merge!(schema: schema)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def upgrade_request_type!(metadata)
|
|
||||||
# No deprecation here as it seems valid to allow type as a shorthand
|
|
||||||
operation_nodes = metadata[:operation][:parameters] || []
|
|
||||||
path_nodes = metadata[:path_item][:parameters] || []
|
|
||||||
header_node = metadata[:response][:headers] || {}
|
|
||||||
|
|
||||||
(operation_nodes + path_nodes + [header_node]).each do |node|
|
|
||||||
if node && node[:type] && node[:schema].nil?
|
|
||||||
node[:schema] = { type: node[:type] }
|
|
||||||
node.delete(:type)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def upgrade_servers!(swagger_doc)
|
|
||||||
return unless swagger_doc[:servers].nil? && swagger_doc.key?(:schemes)
|
|
||||||
|
|
||||||
ActiveSupport::Deprecation.warn('Rswag::Specs: WARNING: schemes, host, and basePath are replaced in OpenAPI3! Rename to array of servers[{url}] (in swagger_helper.rb)')
|
|
||||||
|
|
||||||
swagger_doc[:servers] = { urls: [] }
|
|
||||||
swagger_doc[:schemes].each do |scheme|
|
|
||||||
swagger_doc[:servers][:urls] << scheme + '://' + swagger_doc[:host] + swagger_doc[:basePath]
|
|
||||||
end
|
|
||||||
|
|
||||||
swagger_doc.delete(:schemes)
|
|
||||||
swagger_doc.delete(:host)
|
|
||||||
swagger_doc.delete(:basePath)
|
|
||||||
end
|
|
||||||
|
|
||||||
def upgrade_oauth!(swagger_doc)
|
|
||||||
# find flow in securitySchemes (securityDefinitions will have been re-written)
|
|
||||||
schemes = swagger_doc.dig(:components, :securitySchemes)
|
|
||||||
return unless schemes&.any? { |_k, v| v.key?(:flow) }
|
|
||||||
|
|
||||||
schemes.each do |name, v|
|
|
||||||
next unless v.key?(:flow)
|
|
||||||
|
|
||||||
ActiveSupport::Deprecation.warn("Rswag::Specs: WARNING: securityDefinitions flow is replaced in OpenAPI3! Rename to components/securitySchemes/#{name}/flows[] (in swagger_helper.rb)")
|
|
||||||
flow = swagger_doc[:components][:securitySchemes][name].delete(:flow).to_s
|
|
||||||
if flow == 'accessCode'
|
|
||||||
ActiveSupport::Deprecation.warn("Rswag::Specs: WARNING: securityDefinitions accessCode is replaced in OpenAPI3! Rename to clientCredentials (in swagger_helper.rb)")
|
|
||||||
flow = 'authorizationCode'
|
|
||||||
end
|
|
||||||
if flow == 'application'
|
|
||||||
ActiveSupport::Deprecation.warn("Rswag::Specs: WARNING: securityDefinitions application is replaced in OpenAPI3! Rename to authorizationCode (in swagger_helper.rb)")
|
|
||||||
flow = 'clientCredentials'
|
|
||||||
end
|
|
||||||
flow_elements = swagger_doc[:components][:securitySchemes][name].except(:type).each_with_object({}) do |(k, _v), a|
|
|
||||||
a[k] = swagger_doc[:components][:securitySchemes][name].delete(k)
|
|
||||||
end
|
|
||||||
swagger_doc[:components][:securitySchemes][name].merge!(flows: { flow => flow_elements })
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def remove_invalid_operation_keys!(value)
|
|
||||||
is_hash = value.is_a?(Hash)
|
|
||||||
value.delete(:consumes) if is_hash && value.dig(:consumes)
|
|
||||||
value.delete(:produces) if is_hash && value.dig(:produces)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,24 +1,18 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'rspec/core/rake_task'
|
require 'rspec/core/rake_task'
|
||||||
|
|
||||||
namespace :rswag do
|
namespace :rswag do
|
||||||
namespace :specs do
|
namespace :specs do
|
||||||
|
|
||||||
desc 'Generate Swagger JSON files from integration specs'
|
desc 'Generate Swagger JSON files from integration specs'
|
||||||
RSpec::Core::RakeTask.new('swaggerize') do |t|
|
RSpec::Core::RakeTask.new('swaggerize') do |t|
|
||||||
t.pattern = ENV.fetch(
|
t.pattern = 'spec/requests/**/*_spec.rb, spec/api/**/*_spec.rb, spec/integration/**/*_spec.rb'
|
||||||
'PATTERN',
|
|
||||||
'spec/requests/**/*_spec.rb, spec/api/**/*_spec.rb, spec/integration/**/*_spec.rb'
|
|
||||||
)
|
|
||||||
|
|
||||||
# NOTE: rspec 2.x support
|
# NOTE: rspec 2.x support
|
||||||
if Rswag::Specs::RSPEC_VERSION > 2 && Rswag::Specs.config.swagger_dry_run
|
if Rswag::Specs::RSPEC_VERSION > 2 && Rswag::Specs.config.swagger_dry_run
|
||||||
t.rspec_opts = ['--format Rswag::Specs::SwaggerFormatter', '--dry-run', '--order defined']
|
t.rspec_opts = [ '--format Rswag::Specs::SwaggerFormatter', '--dry-run', '--order defined' ]
|
||||||
else
|
else
|
||||||
t.rspec_opts = ['--format Rswag::Specs::SwaggerFormatter', '--order defined']
|
t.rspec_opts = [ '--format Rswag::Specs::SwaggerFormatter', '--order defined' ]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
task rswag: ['rswag:specs:swaggerize']
|
|
||||||
|
|||||||
@ -1,21 +1,19 @@
|
|||||||
# frozen_string_literal: true
|
$:.push File.expand_path("../lib", __FILE__)
|
||||||
|
|
||||||
$LOAD_PATH.push File.expand_path('lib', __dir__)
|
|
||||||
|
|
||||||
# Describe your gem and declare its dependencies:
|
# Describe your gem and declare its dependencies:
|
||||||
Gem::Specification.new do |s|
|
Gem::Specification.new do |s|
|
||||||
s.name = 'rswag-specs'
|
s.name = "rswag-specs"
|
||||||
s.version = ENV['TRAVIS_TAG'] || '0.0.0'
|
s.version = ENV['TRAVIS_TAG'] || '0.0.0'
|
||||||
s.authors = ['Richie Morris', 'Greg Myers', 'Jay Danielian']
|
s.authors = ["Richie Morris"]
|
||||||
s.email = ['domaindrivendev@gmail.com']
|
s.email = ["domaindrivendev@gmail.com"]
|
||||||
s.homepage = 'https://github.com/rswag/rswag'
|
s.homepage = "https://github.com/domaindrivendev/rswag"
|
||||||
s.summary = 'An OpenAPI-based (formerly called Swagger) DSL for rspec-rails & accompanying rake task for generating OpenAPI specification files'
|
s.summary = "A Swagger-based DSL for rspec-rails & accompanying rake task for generating Swagger files"
|
||||||
s.description = 'Simplify API integration testing with a succinct rspec DSL and generate OpenAPI specification files directly from your rspecs. More about the OpenAPI initiative here: http://spec.openapis.org/'
|
s.description = "Simplify API integration testing with a succinct rspec DSL and generate Swagger files directly from your rspecs"
|
||||||
s.license = 'MIT'
|
s.license = "MIT"
|
||||||
|
|
||||||
s.files = Dir['{lib}/**/*'] + ['MIT-LICENSE', 'Rakefile']
|
s.files = Dir["{lib}/**/*"] + ["MIT-LICENSE", "Rakefile" ]
|
||||||
|
|
||||||
s.add_dependency 'activesupport', '>= 3.1', '< 7.1'
|
s.add_dependency 'activesupport', '>= 3.1', '< 6.0'
|
||||||
s.add_dependency 'railties', '>= 3.1', '< 7.1'
|
s.add_dependency 'railties', '>= 3.1', '< 6.0'
|
||||||
s.add_dependency 'json-schema', '~> 2.2'
|
s.add_dependency 'json-schema', '~> 2.2'
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,45 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
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', __dir__)
|
|
||||||
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
|
|
||||||
@ -1,17 +1,16 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'generator_spec'
|
require 'generator_spec'
|
||||||
require 'generators/rswag/specs/install/install_generator'
|
require 'generators/rswag/specs/install/install_generator'
|
||||||
|
|
||||||
module Rswag
|
module Rswag
|
||||||
module Specs
|
module Specs
|
||||||
RSpec.describe InstallGenerator do
|
|
||||||
|
describe InstallGenerator do
|
||||||
include GeneratorSpec::TestCase
|
include GeneratorSpec::TestCase
|
||||||
destination File.expand_path('tmp', __dir__)
|
destination File.expand_path('../tmp', __FILE__)
|
||||||
|
|
||||||
before(:all) do
|
before(:all) do
|
||||||
prepare_destination
|
prepare_destination
|
||||||
fixtures_dir = File.expand_path('fixtures', __dir__)
|
fixtures_dir = File.expand_path('../fixtures', __FILE__)
|
||||||
FileUtils.cp_r("#{fixtures_dir}/spec", destination_root)
|
FileUtils.cp_r("#{fixtures_dir}/spec", destination_root)
|
||||||
|
|
||||||
run_generator
|
run_generator
|
||||||
|
|||||||
@ -1,50 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
RSpec.describe Rswag::RouteParser do
|
|
||||||
describe "#routes" do
|
|
||||||
let(:controller) { "api/v1/posts" }
|
|
||||||
subject { described_class.new(controller) }
|
|
||||||
|
|
||||||
let(:routes) do
|
|
||||||
[
|
|
||||||
double(
|
|
||||||
defaults: {
|
|
||||||
controller: controller
|
|
||||||
},
|
|
||||||
path: double(
|
|
||||||
spec: double(
|
|
||||||
to_s: "/api/v1/posts/:id(.:format)"
|
|
||||||
)
|
|
||||||
),
|
|
||||||
verb: "GET",
|
|
||||||
requirements: {
|
|
||||||
action: "show",
|
|
||||||
controller: "api/v1/posts"
|
|
||||||
},
|
|
||||||
segments: ["id", "format"]
|
|
||||||
)
|
|
||||||
]
|
|
||||||
end
|
|
||||||
|
|
||||||
let(:expectation) do
|
|
||||||
{
|
|
||||||
"/api/v1/posts/{id}" => {
|
|
||||||
params: ["id"],
|
|
||||||
actions: {
|
|
||||||
"get" => {
|
|
||||||
summary: "show post"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
before do
|
|
||||||
allow(::Rails).to receive_message_chain("application.routes.routes") { routes }
|
|
||||||
end
|
|
||||||
|
|
||||||
it "returns correct routes" do
|
|
||||||
expect(subject.routes).to eq(expectation)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -1,15 +1,12 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'rswag/specs/configuration'
|
require 'rswag/specs/configuration'
|
||||||
|
|
||||||
module Rswag
|
module Rswag
|
||||||
module Specs
|
module Specs
|
||||||
RSpec.describe Configuration do
|
|
||||||
|
describe Configuration do
|
||||||
subject { described_class.new(rspec_config) }
|
subject { described_class.new(rspec_config) }
|
||||||
|
|
||||||
let(:rspec_config) do
|
let(:rspec_config) { OpenStruct.new(swagger_root: swagger_root, swagger_docs: swagger_docs) }
|
||||||
OpenStruct.new(swagger_root: swagger_root, swagger_docs: swagger_docs, swagger_format: swagger_format)
|
|
||||||
end
|
|
||||||
let(:swagger_root) { 'foobar' }
|
let(:swagger_root) { 'foobar' }
|
||||||
let(:swagger_docs) do
|
let(:swagger_docs) do
|
||||||
{
|
{
|
||||||
@ -17,7 +14,6 @@ module Rswag
|
|||||||
'v2/swagger.json' => { info: { title: 'v2' } }
|
'v2/swagger.json' => { info: { title: 'v2' } }
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
let(:swagger_format) { :yaml }
|
|
||||||
|
|
||||||
describe '#swagger_root' do
|
describe '#swagger_root' do
|
||||||
let(:response) { subject.swagger_root }
|
let(:response) { subject.swagger_root }
|
||||||
@ -50,26 +46,6 @@ module Rswag
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#swagger_format' do
|
|
||||||
let(:response) { subject.swagger_format }
|
|
||||||
|
|
||||||
context 'provided in rspec config' do
|
|
||||||
it { expect(response).to be_an_instance_of(Symbol) }
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'unsupported format provided' do
|
|
||||||
let(:swagger_format) { :xml }
|
|
||||||
|
|
||||||
it { expect { response }.to raise_error ConfigurationError }
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'not provided' do
|
|
||||||
let(:swagger_format) { nil }
|
|
||||||
|
|
||||||
it { expect(response).to eq(:json) }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#get_swagger_doc(tag=nil)' do
|
describe '#get_swagger_doc(tag=nil)' do
|
||||||
let(:swagger_doc) { subject.get_swagger_doc(tag) }
|
let(:swagger_doc) { subject.get_swagger_doc(tag) }
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'rswag/specs/example_group_helpers'
|
require 'rswag/specs/example_group_helpers'
|
||||||
|
|
||||||
module Rswag
|
module Rswag
|
||||||
module Specs
|
module Specs
|
||||||
RSpec.describe ExampleGroupHelpers do
|
|
||||||
|
describe ExampleGroupHelpers do
|
||||||
subject { double('example_group') }
|
subject { double('example_group') }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
@ -25,7 +24,7 @@ module Rswag
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#get|post|patch|put|delete|head|options|trace(verb, summary)' do
|
describe '#get|post|patch|put|delete|head(verb, summary)' do
|
||||||
before { subject.post('Creates a blog') }
|
before { subject.post('Creates a blog') }
|
||||||
|
|
||||||
it "delegates to 'describe' with 'operation' metadata" do
|
it "delegates to 'describe' with 'operation' metadata" do
|
||||||
@ -35,6 +34,31 @@ module Rswag
|
|||||||
end
|
end
|
||||||
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)
|
||||||
|
end
|
||||||
|
let(:api_metadata) { { operation: {} } }
|
||||||
|
|
||||||
|
it "adds to the 'operation' metadata" do
|
||||||
|
expect(api_metadata[:operation]).to match(
|
||||||
|
tags: [ 'Blogs', 'Admin' ],
|
||||||
|
description: 'Some description',
|
||||||
|
operationId: 'createBlog',
|
||||||
|
consumes: [ 'application/json', 'application/xml' ],
|
||||||
|
produces: [ 'application/json', 'application/xml' ],
|
||||||
|
schemes: [ 'http', 'https' ],
|
||||||
|
deprecated: true
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '#tags|description|operationId|consumes|produces|schemes|deprecated|security(value)' do
|
describe '#tags|description|operationId|consumes|produces|schemes|deprecated|security(value)' do
|
||||||
before do
|
before do
|
||||||
subject.tags('Blogs', 'Admin')
|
subject.tags('Blogs', 'Admin')
|
||||||
@ -50,12 +74,12 @@ module Rswag
|
|||||||
|
|
||||||
it "adds to the 'operation' metadata" do
|
it "adds to the 'operation' metadata" do
|
||||||
expect(api_metadata[:operation]).to match(
|
expect(api_metadata[:operation]).to match(
|
||||||
tags: ['Blogs', 'Admin'],
|
tags: [ 'Blogs', 'Admin' ],
|
||||||
description: 'Some description',
|
description: 'Some description',
|
||||||
operationId: 'createBlog',
|
operationId: 'createBlog',
|
||||||
consumes: ['application/json', 'application/xml'],
|
consumes: [ 'application/json', 'application/xml' ],
|
||||||
produces: ['application/json', 'application/xml'],
|
produces: [ 'application/json', 'application/xml' ],
|
||||||
schemes: ['http', 'https'],
|
schemes: [ 'http', 'https' ],
|
||||||
deprecated: true,
|
deprecated: true,
|
||||||
security: { api_key: [] }
|
security: { api_key: [] }
|
||||||
)
|
)
|
||||||
@ -63,13 +87,14 @@ module Rswag
|
|||||||
end
|
end
|
||||||
|
|
||||||
describe '#parameter(attributes)' do
|
describe '#parameter(attributes)' do
|
||||||
|
|
||||||
context "when called at the 'path' level" do
|
context "when called at the 'path' level" do
|
||||||
before { subject.parameter(name: :blog, in: :body, schema: { type: 'object' }) }
|
before { subject.parameter(name: :blog, in: :body, schema: { type: 'object' }) }
|
||||||
let(:api_metadata) { { path_item: {} } } # i.e. operation not defined yet
|
let(:api_metadata) { { path_item: {} } } # i.e. operation not defined yet
|
||||||
|
|
||||||
it "adds to the 'path_item parameters' metadata" do
|
it "adds to the 'path_item parameters' metadata" do
|
||||||
expect(api_metadata[:path_item][:parameters]).to match(
|
expect(api_metadata[:path_item][:parameters]).to match(
|
||||||
[name: :blog, in: :body, schema: { type: 'object' }]
|
[ name: :blog, in: :body, schema: { type: 'object' } ]
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -80,7 +105,7 @@ module Rswag
|
|||||||
|
|
||||||
it "adds to the 'operation parameters' metadata" do
|
it "adds to the 'operation parameters' metadata" do
|
||||||
expect(api_metadata[:operation][:parameters]).to match(
|
expect(api_metadata[:operation][:parameters]).to match(
|
||||||
[name: :blog, in: :body, schema: { type: 'object' }]
|
[ name: :blog, in: :body, schema: { type: 'object' } ]
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -91,7 +116,7 @@ module Rswag
|
|||||||
|
|
||||||
it "automatically sets the 'required' flag" do
|
it "automatically sets the 'required' flag" do
|
||||||
expect(api_metadata[:operation][:parameters]).to match(
|
expect(api_metadata[:operation][:parameters]).to match(
|
||||||
[name: :id, in: :path, required: true]
|
[ name: :id, in: :path, required: true ]
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -101,7 +126,7 @@ module Rswag
|
|||||||
let(:api_metadata) { { operation: {} } }
|
let(:api_metadata) { { operation: {} } }
|
||||||
|
|
||||||
it "does not require the 'in' parameter key" do
|
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
|
end
|
||||||
end
|
end
|
||||||
@ -137,10 +162,9 @@ module Rswag
|
|||||||
end
|
end
|
||||||
|
|
||||||
describe '#examples(example)' do
|
describe '#examples(example)' do
|
||||||
let(:mime) { 'application/json' }
|
|
||||||
let(:json_example) do
|
let(:json_example) do
|
||||||
{
|
{
|
||||||
mime => {
|
'application/json' => {
|
||||||
foo: 'bar'
|
foo: 'bar'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -152,11 +176,7 @@ module Rswag
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "adds to the 'response examples' metadata" do
|
it "adds to the 'response examples' metadata" do
|
||||||
expect(api_metadata[:response][:content]).to match(
|
expect(api_metadata[:response][:examples]).to eq(json_example)
|
||||||
mime => {
|
|
||||||
example: json_example[mime]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'rswag/specs/example_helpers'
|
require 'rswag/specs/example_helpers'
|
||||||
|
|
||||||
module Rswag
|
module Rswag
|
||||||
module Specs
|
module Specs
|
||||||
RSpec.describe ExampleHelpers do
|
|
||||||
|
describe ExampleHelpers do
|
||||||
subject { double('example') }
|
subject { double('example') }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
@ -16,7 +15,6 @@ module Rswag
|
|||||||
let(:config) { double('config') }
|
let(:config) { double('config') }
|
||||||
let(:swagger_doc) do
|
let(:swagger_doc) do
|
||||||
{
|
{
|
||||||
swagger: '2.0',
|
|
||||||
securityDefinitions: {
|
securityDefinitions: {
|
||||||
api_key: {
|
api_key: {
|
||||||
type: :apiKey,
|
type: :apiKey,
|
||||||
@ -26,14 +24,13 @@ module Rswag
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:metadata) do
|
let(:metadata) do
|
||||||
{
|
{
|
||||||
path_item: { template: '/blogs/{blog_id}/comments/{id}' },
|
path_item: { template: '/blogs/{blog_id}/comments/{id}' },
|
||||||
operation: {
|
operation: {
|
||||||
verb: :put,
|
verb: :put,
|
||||||
summary: 'Updates a blog',
|
summary: 'Updates a blog',
|
||||||
consumes: ['application/json'],
|
consumes: [ 'application/json' ],
|
||||||
parameters: [
|
parameters: [
|
||||||
{ name: :blog_id, in: :path, type: 'integer' },
|
{ name: :blog_id, in: :path, type: 'integer' },
|
||||||
{ name: 'id', in: :path, type: 'integer' },
|
{ name: 'id', in: :path, type: 'integer' },
|
||||||
@ -61,7 +58,7 @@ module Rswag
|
|||||||
it "submits a request built from metadata and 'let' values" do
|
it "submits a request built from metadata and 'let' values" do
|
||||||
expect(subject).to have_received(:put).with(
|
expect(subject).to have_received(:put).with(
|
||||||
'/blogs/1/comments/2?q1=foo&api_key=fookey',
|
'/blogs/1/comments/2?q1=foo&api_key=fookey',
|
||||||
'{"text":"Some comment"}',
|
"{\"text\":\"Some comment\"}",
|
||||||
{ 'CONTENT_TYPE' => 'application/json' }
|
{ 'CONTENT_TYPE' => 'application/json' }
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,17 +1,16 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'rswag/specs/request_factory'
|
require 'rswag/specs/request_factory'
|
||||||
|
|
||||||
module Rswag
|
module Rswag
|
||||||
module Specs
|
module Specs
|
||||||
RSpec.describe RequestFactory do
|
|
||||||
|
describe RequestFactory do
|
||||||
subject { RequestFactory.new(config) }
|
subject { RequestFactory.new(config) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(config).to receive(:get_swagger_doc).and_return(swagger_doc)
|
allow(config).to receive(:get_swagger_doc).and_return(swagger_doc)
|
||||||
end
|
end
|
||||||
let(:config) { double('config') }
|
let(:config) { double('config') }
|
||||||
let(:swagger_doc) { { swagger: '2.0' } }
|
let(:swagger_doc) { {} }
|
||||||
let(:example) { double('example') }
|
let(:example) { double('example') }
|
||||||
let(:metadata) do
|
let(:metadata) do
|
||||||
{
|
{
|
||||||
@ -54,7 +53,7 @@ module Rswag
|
|||||||
allow(example).to receive(:q2).and_return('bar')
|
allow(example).to receive(:q2).and_return('bar')
|
||||||
end
|
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')
|
expect(request[:path]).to eq('/blogs?q1=foo&q2=bar')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -64,40 +63,40 @@ module Rswag
|
|||||||
metadata[:operation][:parameters] = [
|
metadata[:operation][:parameters] = [
|
||||||
{ name: 'things', in: :query, type: :array, collectionFormat: collection_format }
|
{ 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([ 'foo', 'bar' ])
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'collectionFormat = csv' do
|
context 'collectionFormat = csv' do
|
||||||
let(:collection_format) { :csv }
|
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')
|
expect(request[:path]).to eq('/blogs?things=foo,bar')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'collectionFormat = ssv' do
|
context 'collectionFormat = ssv' do
|
||||||
let(:collection_format) { :ssv }
|
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')
|
expect(request[:path]).to eq('/blogs?things=foo bar')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'collectionFormat = tsv' do
|
context 'collectionFormat = tsv' do
|
||||||
let(:collection_format) { :tsv }
|
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')
|
expect(request[:path]).to eq('/blogs?things=foo\tbar')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'collectionFormat = pipes' do
|
context 'collectionFormat = pipes' do
|
||||||
let(:collection_format) { :pipes }
|
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')
|
expect(request[:path]).to eq('/blogs?things=foo|bar')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'collectionFormat = multi' do
|
context 'collectionFormat = multi' do
|
||||||
let(:collection_format) { :multi }
|
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')
|
expect(request[:path]).to eq('/blogs?things=foo&things=bar')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -105,7 +104,7 @@ module Rswag
|
|||||||
|
|
||||||
context "'header' parameters" do
|
context "'header' parameters" do
|
||||||
before 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')
|
allow(example).to receive(:'Api-Key').and_return('foobar')
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -128,9 +127,9 @@ module Rswag
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'consumes content' do
|
context "consumes content" do
|
||||||
before do
|
before do
|
||||||
metadata[:operation][:consumes] = ['application/json', 'application/xml']
|
metadata[:operation][:consumes] = [ 'application/json', 'application/xml' ]
|
||||||
end
|
end
|
||||||
|
|
||||||
context "no 'Content-Type' provided" do
|
context "no 'Content-Type' provided" do
|
||||||
@ -151,33 +150,18 @@ module Rswag
|
|||||||
|
|
||||||
context 'JSON payload' do
|
context 'JSON payload' do
|
||||||
before 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')
|
allow(example).to receive(:comment).and_return(text: 'Some comment')
|
||||||
end
|
end
|
||||||
|
|
||||||
it "serializes first 'body' parameter to JSON string" do
|
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 'missing body parameter' do
|
|
||||||
before do
|
|
||||||
metadata[:operation][:parameters] = [{ name: 'comment', in: :body, schema: { type: 'object' } }]
|
|
||||||
allow(example).to receive(:comment).and_raise(NoMethodError, "undefined method 'comment'")
|
|
||||||
allow(example).to receive(:respond_to?).with(:'Content-Type')
|
|
||||||
allow(example).to receive(:respond_to?).with('comment').and_return(false)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'uses the referenced metadata to build the request' do
|
|
||||||
expect do
|
|
||||||
request[:payload]
|
|
||||||
end.to raise_error(Rswag::Specs::MissingParameterError, /Missing parameter 'comment'/)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'form payload' do
|
context 'form payload' do
|
||||||
before do
|
before do
|
||||||
metadata[:operation][:consumes] = ['multipart/form-data']
|
metadata[:operation][:consumes] = [ 'multipart/form-data' ]
|
||||||
metadata[:operation][:parameters] = [
|
metadata[:operation][:parameters] = [
|
||||||
{ name: 'f1', in: :formData, type: :string },
|
{ name: 'f1', in: :formData, type: :string },
|
||||||
{ name: 'f2', in: :formData, type: :string }
|
{ name: 'f2', in: :formData, type: :string }
|
||||||
@ -197,7 +181,7 @@ module Rswag
|
|||||||
|
|
||||||
context 'produces content' do
|
context 'produces content' do
|
||||||
before do
|
before do
|
||||||
metadata[:operation][:produces] = ['application/json', 'application/xml']
|
metadata[:operation][:produces] = [ 'application/json', 'application/xml' ]
|
||||||
end
|
end
|
||||||
|
|
||||||
context "no 'Accept' value provided" do
|
context "no 'Accept' value provided" do
|
||||||
@ -208,7 +192,7 @@ module Rswag
|
|||||||
|
|
||||||
context "explicit 'Accept' value provided" do
|
context "explicit 'Accept' value provided" do
|
||||||
before do
|
before do
|
||||||
allow(example).to receive(:Accept).and_return('application/xml')
|
allow(example).to receive(:'Accept').and_return('application/xml')
|
||||||
end
|
end
|
||||||
|
|
||||||
it "sets 'HTTP_ACCEPT' header to example value" do
|
it "sets 'HTTP_ACCEPT' header to example value" do
|
||||||
@ -218,53 +202,21 @@ module Rswag
|
|||||||
end
|
end
|
||||||
|
|
||||||
context 'basic auth' do
|
context 'basic auth' do
|
||||||
context 'swagger 2.0' do
|
before do
|
||||||
before do
|
swagger_doc[:securityDefinitions] = { basic: { type: :basic } }
|
||||||
swagger_doc[:securityDefinitions] = { basic: { type: :basic } }
|
metadata[:operation][:security] = [ basic: [] ]
|
||||||
metadata[:operation][:security] = [basic: []]
|
allow(example).to receive(:Authorization).and_return('Basic foobar')
|
||||||
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
|
end
|
||||||
|
|
||||||
context 'openapi 3.0.1' do
|
it "sets 'HTTP_AUTHORIZATION' header to example value" do
|
||||||
let(:swagger_doc) { { openapi: '3.0.1' } }
|
expect(request[:headers]).to eq('HTTP_AUTHORIZATION' => 'Basic foobar')
|
||||||
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 'openapi 3.0.1 upgrade notice' do
|
|
||||||
let(:swagger_doc) { { openapi: '3.0.1' } }
|
|
||||||
before do
|
|
||||||
allow(ActiveSupport::Deprecation).to receive(:warn)
|
|
||||||
swagger_doc[:securityDefinitions] = { basic: { type: :basic } }
|
|
||||||
metadata[:operation][:security] = [basic: []]
|
|
||||||
allow(example).to receive(:Authorization).and_return('Basic foobar')
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'warns the user to upgrade' do
|
|
||||||
expect(request[:headers]).to eq('HTTP_AUTHORIZATION' => 'Basic foobar')
|
|
||||||
expect(ActiveSupport::Deprecation).to have_received(:warn)
|
|
||||||
.with('Rswag::Specs: WARNING: securityDefinitions is replaced in OpenAPI3! Rename to components/securitySchemes (in swagger_helper.rb)')
|
|
||||||
expect(swagger_doc[:components]).to have_key(:securitySchemes)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'apiKey' do
|
context 'apiKey' do
|
||||||
before do
|
before do
|
||||||
swagger_doc[:securityDefinitions] = { apiKey: { type: :apiKey, name: 'api_key', in: key_location } }
|
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')
|
allow(example).to receive(:api_key).and_return('foobar')
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -304,8 +256,8 @@ module Rswag
|
|||||||
|
|
||||||
context 'oauth2' do
|
context 'oauth2' do
|
||||||
before do
|
before do
|
||||||
swagger_doc[:securityDefinitions] = { oauth2: { type: :oauth2, scopes: ['read:blogs'] } }
|
swagger_doc[:securityDefinitions] = { oauth2: { type: :oauth2, scopes: [ 'read:blogs' ] } }
|
||||||
metadata[:operation][:security] = [oauth2: ['read:blogs']]
|
metadata[:operation][:security] = [ oauth2: [ 'read:blogs' ] ]
|
||||||
allow(example).to receive(:Authorization).and_return('Bearer foobar')
|
allow(example).to receive(:Authorization).and_return('Bearer foobar')
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -320,72 +272,39 @@ module Rswag
|
|||||||
basic: { type: :basic },
|
basic: { type: :basic },
|
||||||
api_key: { type: :apiKey, name: 'api_key', in: :query }
|
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(:Authorization).and_return('Basic foobar')
|
||||||
allow(example).to receive(:api_key).and_return('foobar')
|
allow(example).to receive(:api_key).and_return('foobar')
|
||||||
end
|
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[:headers]).to eq('HTTP_AUTHORIZATION' => 'Basic foobar')
|
||||||
expect(request[:path]).to eq('/blogs?api_key=foobar')
|
expect(request[:path]).to eq('/blogs?api_key=foobar')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'path-level parameters' do
|
context "path-level parameters" do
|
||||||
before do
|
before do
|
||||||
metadata[:operation][:parameters] = [{ name: 'q1', in: :query, type: :string }]
|
metadata[:operation][:parameters] = [ { name: 'q1', in: :query, type: :string } ]
|
||||||
metadata[:path_item][:parameters] = [{ name: 'q2', 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(:q1).and_return('foo')
|
||||||
allow(example).to receive(:q2).and_return('bar')
|
allow(example).to receive(:q2).and_return('bar')
|
||||||
end
|
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')
|
expect(request[:path]).to eq('/blogs?q1=foo&q2=bar')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'referenced parameters' do
|
context 'referenced parameters' do
|
||||||
context 'swagger 2.0' do
|
before do
|
||||||
before do
|
swagger_doc[:parameters] = { q1: { name: 'q1', in: :query, type: :string } }
|
||||||
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')
|
||||||
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
|
end
|
||||||
|
|
||||||
context 'openapi 3.0.1' do
|
it 'uses the referenced metadata to build the request' do
|
||||||
let(:swagger_doc) { { openapi: '3.0.1' } }
|
expect(request[:path]).to eq('/blogs?q1=foo')
|
||||||
before do
|
|
||||||
swagger_doc[:components] = { parameters: { q1: { name: 'q1', in: :query, type: :string } } }
|
|
||||||
metadata[:operation][:parameters] = [{ '$ref' => '#/components/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 'openapi 3.0.1 upgrade notice' do
|
|
||||||
let(:swagger_doc) { { openapi: '3.0.1' } }
|
|
||||||
before do
|
|
||||||
allow(ActiveSupport::Deprecation).to receive(:warn)
|
|
||||||
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 'warns the user to upgrade' do
|
|
||||||
expect(request[:path]).to eq('/blogs?q1=foo')
|
|
||||||
expect(ActiveSupport::Deprecation).to have_received(:warn)
|
|
||||||
.with('Rswag::Specs: WARNING: #/parameters/ refs are replaced in OpenAPI3! Rename to #/components/parameters/')
|
|
||||||
expect(ActiveSupport::Deprecation).to have_received(:warn)
|
|
||||||
.with('Rswag::Specs: WARNING: parameters is replaced in OpenAPI3! Rename to components/parameters (in swagger_helper.rb)')
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -397,18 +316,18 @@ module Rswag
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'global consumes' do
|
context "global consumes" do
|
||||||
before { swagger_doc[:consumes] = ['application/xml'] }
|
before { swagger_doc[:consumes] = [ 'application/xml' ] }
|
||||||
|
|
||||||
it "defaults 'CONTENT_TYPE' to global value(s)" do
|
it "defaults 'CONTENT_TYPE' to global value(s)" do
|
||||||
expect(request[:headers]).to eq('CONTENT_TYPE' => 'application/xml')
|
expect(request[:headers]).to eq('CONTENT_TYPE' => 'application/xml')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'global security requirements' do
|
context "global security requirements" do
|
||||||
before do
|
before do
|
||||||
swagger_doc[:securityDefinitions] = { apiKey: { type: :apiKey, name: 'api_key', in: :query } }
|
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')
|
allow(example).to receive(:api_key).and_return('foobar')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -1,15 +1,13 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'rswag/specs/response_validator'
|
require 'rswag/specs/response_validator'
|
||||||
|
|
||||||
module Rswag
|
module Rswag
|
||||||
module Specs
|
module Specs
|
||||||
RSpec.describe ResponseValidator do
|
|
||||||
|
describe ResponseValidator do
|
||||||
subject { ResponseValidator.new(config) }
|
subject { ResponseValidator.new(config) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(config).to receive(:get_swagger_doc).and_return(swagger_doc)
|
allow(config).to receive(:get_swagger_doc).and_return(swagger_doc)
|
||||||
allow(config).to receive(:get_swagger_doc_version).and_return('2.0')
|
|
||||||
end
|
end
|
||||||
let(:config) { double('config') }
|
let(:config) { double('config') }
|
||||||
let(:swagger_doc) { {} }
|
let(:swagger_doc) { {} }
|
||||||
@ -22,7 +20,7 @@ module Rswag
|
|||||||
schema: {
|
schema: {
|
||||||
type: :object,
|
type: :object,
|
||||||
properties: { text: { type: :string } },
|
properties: { text: { type: :string } },
|
||||||
required: ['text']
|
required: [ 'text' ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -34,89 +32,43 @@ module Rswag
|
|||||||
OpenStruct.new(
|
OpenStruct.new(
|
||||||
code: '200',
|
code: '200',
|
||||||
headers: { 'X-Rate-Limit-Limit' => '10' },
|
headers: { 'X-Rate-Limit-Limit' => '10' },
|
||||||
body: '{"text":"Some comment"}'
|
body: "{\"text\":\"Some comment\"}"
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'response matches metadata' do
|
context "response matches metadata" do
|
||||||
it { expect { call }.to_not raise_error }
|
it { expect { call }.to_not raise_error }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'response code differs from metadata' do
|
context "response code differs from metadata" do
|
||||||
before { response.code = '400' }
|
before { response.code = '400' }
|
||||||
it { expect { call }.to raise_error(/Expected response code/) }
|
it { expect { call }.to raise_error /Expected response code/ }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'response headers differ from metadata' do
|
context "response headers differ from metadata" do
|
||||||
before { response.headers = {} }
|
before { response.headers = {} }
|
||||||
it { expect { call }.to raise_error(/Expected response header/) }
|
it { expect { call }.to raise_error /Expected response header/ }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'response body differs from metadata' do
|
context "response body differs from metadata" do
|
||||||
before { response.body = '{"foo":"Some comment"}' }
|
before { response.body = "{\"foo\":\"Some comment\"}" }
|
||||||
it { expect { call }.to raise_error(/Expected response body/) }
|
it { expect { call }.to raise_error /Expected response body/ }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'referenced schemas' do
|
context 'referenced schemas' do
|
||||||
context 'swagger 2.0' do
|
before do
|
||||||
before do
|
swagger_doc[:definitions] = {
|
||||||
swagger_doc[:definitions] = {
|
'blog' => {
|
||||||
'blog' => {
|
type: :object,
|
||||||
type: :object,
|
properties: { foo: { type: :string } },
|
||||||
properties: { foo: { type: :string } },
|
required: [ 'foo' ]
|
||||||
required: ['foo']
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
metadata[:response][:schema] = { '$ref' => '#/definitions/blog' }
|
}
|
||||||
end
|
metadata[:response][:schema] = { '$ref' => '#/definitions/blog' }
|
||||||
|
|
||||||
it 'uses the referenced schema to validate the response body' do
|
|
||||||
expect { call }.to raise_error(/Expected response body/)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'openapi 3.0.1' do
|
it 'uses the referenced schema to validate the response body' do
|
||||||
context 'components/schemas' do
|
expect { call }.to raise_error /Expected response body/
|
||||||
before do
|
|
||||||
allow(ActiveSupport::Deprecation).to receive(:warn)
|
|
||||||
allow(config).to receive(:get_swagger_doc_version).and_return('3.0.1')
|
|
||||||
swagger_doc[:components] = {
|
|
||||||
schemas: {
|
|
||||||
'blog' => {
|
|
||||||
type: :object,
|
|
||||||
properties: { foo: { type: :string } },
|
|
||||||
required: ['foo']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
metadata[:response][: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
|
|
||||||
|
|
||||||
context 'deprecated definitions' do
|
|
||||||
before do
|
|
||||||
allow(ActiveSupport::Deprecation).to receive(:warn)
|
|
||||||
allow(config).to receive(:get_swagger_doc_version).and_return('3.0.1')
|
|
||||||
swagger_doc[:definitions] = {
|
|
||||||
'blog' => {
|
|
||||||
type: :object,
|
|
||||||
properties: { foo: { type: :string } },
|
|
||||||
required: ['foo']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
metadata[:response][:schema] = { '$ref' => '#/definitions/blog' }
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'warns the user to upgrade' do
|
|
||||||
expect { call }.to raise_error(/Expected response body/)
|
|
||||||
expect(ActiveSupport::Deprecation).to have_received(:warn)
|
|
||||||
.with('Rswag::Specs: WARNING: definitions is replaced in OpenAPI3! Rename to components/schemas (in swagger_helper.rb)')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,375 +1,70 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'rswag/specs/swagger_formatter'
|
require 'rswag/specs/swagger_formatter'
|
||||||
require 'ostruct'
|
require 'ostruct'
|
||||||
|
|
||||||
module Rswag
|
module Rswag
|
||||||
module Specs
|
module Specs
|
||||||
RSpec.describe SwaggerFormatter do
|
|
||||||
|
describe SwaggerFormatter do
|
||||||
subject { described_class.new(output, config) }
|
subject { described_class.new(output, config) }
|
||||||
|
|
||||||
# Mock out some infrastructure
|
# Mock out some infrastructure
|
||||||
before do
|
before do
|
||||||
allow(config).to receive(:swagger_root).and_return(swagger_root)
|
allow(config).to receive(:swagger_root).and_return(swagger_root)
|
||||||
|
|
||||||
allow(ActiveSupport::Deprecation).to receive(:warn) # Silence deprecation output from specs
|
|
||||||
end
|
end
|
||||||
let(:config) { double('config') }
|
let(:config) { double('config') }
|
||||||
let(:output) { double('output').as_null_object }
|
let(:output) { double('output').as_null_object }
|
||||||
let(:swagger_root) { File.expand_path('tmp/swagger', __dir__) }
|
let(:swagger_root) { File.expand_path('../tmp/swagger', __FILE__) }
|
||||||
|
|
||||||
describe '#example_group_finished(notification)' do
|
describe '#example_group_finished(notification)' do
|
||||||
before do
|
before do
|
||||||
allow(config).to receive(:get_swagger_doc).and_return(swagger_doc)
|
allow(config).to receive(:get_swagger_doc).and_return(swagger_doc)
|
||||||
subject.example_group_finished(notification)
|
subject.example_group_finished(notification)
|
||||||
end
|
end
|
||||||
|
let(:swagger_doc) { {} }
|
||||||
let(:notification) { OpenStruct.new(group: OpenStruct.new(metadata: api_metadata)) }
|
let(:notification) { OpenStruct.new(group: OpenStruct.new(metadata: api_metadata)) }
|
||||||
let(:api_metadata) do
|
let(:api_metadata) do
|
||||||
{
|
{
|
||||||
path_item: { template: '/blogs', parameters: [{ type: :string }] },
|
path_item: { template: '/blogs' },
|
||||||
operation: { verb: :post, summary: 'Creates a blog', parameters: [{ type: :string }] },
|
operation: { verb: :post, summary: 'Creates a blog' },
|
||||||
response: response_metadata,
|
response: { code: '201', description: 'blog created' }
|
||||||
document: document
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
let(:response_metadata) { { code: '201', description: 'blog created', headers: { type: :string }, schema: { '$ref' => '#/definitions/blog' } } }
|
|
||||||
|
|
||||||
context 'with the document tag set to false' do
|
it 'converts to swagger and merges into the corresponding swagger doc' do
|
||||||
let(:swagger_doc) { { swagger: '2.0' } }
|
expect(swagger_doc).to match(
|
||||||
let(:document) { false }
|
paths: {
|
||||||
|
'/blogs' => {
|
||||||
it 'does not update the swagger doc' do
|
post: {
|
||||||
expect(swagger_doc).to match({ swagger: '2.0' })
|
summary: 'Creates a blog',
|
||||||
end
|
responses: {
|
||||||
end
|
'201' => { description: 'blog created' }
|
||||||
|
|
||||||
context 'with the document tag set to anything but false' do
|
|
||||||
let(:swagger_doc) { { swagger: '2.0' } }
|
|
||||||
# anything works, including its absence when specifying responses.
|
|
||||||
let(:document) { nil }
|
|
||||||
|
|
||||||
it 'converts to swagger and merges into the corresponding swagger doc' do
|
|
||||||
expect(swagger_doc).to match(
|
|
||||||
swagger: '2.0',
|
|
||||||
paths: {
|
|
||||||
'/blogs' => {
|
|
||||||
parameters: [{ type: :string }],
|
|
||||||
post: {
|
|
||||||
parameters: [{ type: :string }],
|
|
||||||
summary: 'Creates a blog',
|
|
||||||
responses: {
|
|
||||||
'201' => {
|
|
||||||
description: 'blog created',
|
|
||||||
headers: { type: :string },
|
|
||||||
schema: { '$ref' => '#/definitions/blog' }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with metadata upgrades for 3.0' do
|
|
||||||
let(:swagger_doc) do
|
|
||||||
{
|
|
||||||
openapi: '3.0.1',
|
|
||||||
basePath: '/foo',
|
|
||||||
schemes: ['http', 'https'],
|
|
||||||
host: 'api.example.com',
|
|
||||||
produces: ['application/vnd.my_mime', 'application/json'],
|
|
||||||
components: {
|
|
||||||
securitySchemes: {
|
|
||||||
myClientCredentials: {
|
|
||||||
type: :oauth2,
|
|
||||||
flow: :application,
|
|
||||||
token_url: :somewhere
|
|
||||||
},
|
|
||||||
myAuthorizationCode: {
|
|
||||||
type: :oauth2,
|
|
||||||
flow: :accessCode,
|
|
||||||
token_url: :somewhere
|
|
||||||
},
|
|
||||||
myImplicit: {
|
|
||||||
type: :oauth2,
|
|
||||||
flow: :implicit,
|
|
||||||
token_url: :somewhere
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
)
|
||||||
let(:document) { nil }
|
|
||||||
|
|
||||||
it 'converts query and path params, type: to schema: { type: }' do
|
|
||||||
expect(swagger_doc.slice(:paths)).to match(
|
|
||||||
paths: {
|
|
||||||
'/blogs' => {
|
|
||||||
parameters: [{ schema: { type: :string } }],
|
|
||||||
post: {
|
|
||||||
parameters: [{ schema: { type: :string } }],
|
|
||||||
summary: 'Creates a blog',
|
|
||||||
responses: {
|
|
||||||
'201' => {
|
|
||||||
content: {
|
|
||||||
'application/vnd.my_mime' => {
|
|
||||||
schema: { '$ref' => '#/definitions/blog' }
|
|
||||||
},
|
|
||||||
'application/json' => {
|
|
||||||
schema: { '$ref' => '#/definitions/blog' }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
description: 'blog created',
|
|
||||||
headers: { schema: { type: :string } }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with response example' do
|
|
||||||
let(:response_metadata) do
|
|
||||||
{
|
|
||||||
code: '201',
|
|
||||||
description: 'blog created',
|
|
||||||
headers: { type: :string },
|
|
||||||
content: { 'application/json' => { example: { foo: :bar } } },
|
|
||||||
schema: { '$ref' => '#/definitions/blog' }
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'adds example to definition' do
|
|
||||||
expect(swagger_doc.slice(:paths)).to match(
|
|
||||||
paths: {
|
|
||||||
'/blogs' => {
|
|
||||||
parameters: [{ schema: { type: :string } }],
|
|
||||||
post: {
|
|
||||||
parameters: [{ schema: { type: :string } }],
|
|
||||||
summary: 'Creates a blog',
|
|
||||||
responses: {
|
|
||||||
'201' => {
|
|
||||||
content: {
|
|
||||||
'application/vnd.my_mime' => {
|
|
||||||
schema: { '$ref' => '#/definitions/blog' }
|
|
||||||
},
|
|
||||||
'application/json' => {
|
|
||||||
schema: { '$ref' => '#/definitions/blog' },
|
|
||||||
example: { foo: :bar }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
description: 'blog created',
|
|
||||||
headers: { schema: { type: :string } }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with empty content' do
|
|
||||||
let(:swagger_doc) do
|
|
||||||
{
|
|
||||||
openapi: '3.0.1',
|
|
||||||
basePath: '/foo',
|
|
||||||
schemes: ['http', 'https'],
|
|
||||||
host: 'api.example.com',
|
|
||||||
components: {
|
|
||||||
securitySchemes: {
|
|
||||||
myClientCredentials: {
|
|
||||||
type: :oauth2,
|
|
||||||
flow: :application,
|
|
||||||
token_url: :somewhere
|
|
||||||
},
|
|
||||||
myAuthorizationCode: {
|
|
||||||
type: :oauth2,
|
|
||||||
flow: :accessCode,
|
|
||||||
token_url: :somewhere
|
|
||||||
},
|
|
||||||
myImplicit: {
|
|
||||||
type: :oauth2,
|
|
||||||
flow: :implicit,
|
|
||||||
token_url: :somewhere
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'converts query and path params, type: to schema: { type: }' do
|
|
||||||
expect(swagger_doc.slice(:paths)).to match(
|
|
||||||
paths: {
|
|
||||||
'/blogs' => {
|
|
||||||
parameters: [{ schema: { type: :string } }],
|
|
||||||
post: {
|
|
||||||
parameters: [{ schema: { type: :string } }],
|
|
||||||
summary: 'Creates a blog',
|
|
||||||
responses: {
|
|
||||||
'201' => {
|
|
||||||
description: 'blog created',
|
|
||||||
headers: { schema: { type: :string } }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'converts basePath, schemas and host to urls' do
|
|
||||||
expect(swagger_doc.slice(:servers)).to match(
|
|
||||||
servers: {
|
|
||||||
urls: ['http://api.example.com/foo', 'https://api.example.com/foo']
|
|
||||||
}
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'upgrades oauth flow to flows' do
|
|
||||||
expect(swagger_doc.slice(:components)).to match(
|
|
||||||
components: {
|
|
||||||
securitySchemes: {
|
|
||||||
myClientCredentials: {
|
|
||||||
type: :oauth2,
|
|
||||||
flows: {
|
|
||||||
'clientCredentials' => {
|
|
||||||
token_url: :somewhere
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
myAuthorizationCode: {
|
|
||||||
type: :oauth2,
|
|
||||||
flows: {
|
|
||||||
'authorizationCode' => {
|
|
||||||
token_url: :somewhere
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
myImplicit: {
|
|
||||||
type: :oauth2,
|
|
||||||
flows: {
|
|
||||||
'implicit' => {
|
|
||||||
token_url: :somewhere
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#stop' do
|
describe '#stop' do
|
||||||
before do
|
before do
|
||||||
FileUtils.rm_r(swagger_root) if File.exist?(swagger_root)
|
FileUtils.rm_r(swagger_root) if File.exists?(swagger_root)
|
||||||
allow(config).to receive(:swagger_docs).and_return(
|
allow(config).to receive(:swagger_docs).and_return(
|
||||||
'v1/swagger.json' => doc_1,
|
'v1/swagger.json' => { info: { version: 'v1' } },
|
||||||
'v2/swagger.json' => doc_2
|
'v2/swagger.json' => { info: { version: 'v2' } }
|
||||||
)
|
)
|
||||||
allow(config).to receive(:swagger_format).and_return(swagger_format)
|
|
||||||
subject.stop(notification)
|
subject.stop(notification)
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:doc_1) { { info: { version: 'v1' } } }
|
|
||||||
let(:doc_2) { { info: { version: 'v2' } } }
|
|
||||||
let(:swagger_format) { :json }
|
|
||||||
|
|
||||||
let(:notification) { double('notification') }
|
let(:notification) { double('notification') }
|
||||||
context 'with default format' do
|
|
||||||
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")
|
|
||||||
expect { JSON.parse(File.read("#{swagger_root}/v2/swagger.json")) }.not_to raise_error
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with yaml format' do
|
it 'writes the swagger_doc(s) to file' do
|
||||||
let(:swagger_format) { :yaml }
|
expect(File).to exist("#{swagger_root}/v1/swagger.json")
|
||||||
|
expect(File).to exist("#{swagger_root}/v2/swagger.json")
|
||||||
it 'writes the swagger_doc(s) as yaml' do
|
|
||||||
expect(File).to exist("#{swagger_root}/v1/swagger.json")
|
|
||||||
expect { JSON.parse(File.read("#{swagger_root}/v1/swagger.json")) }.to raise_error(JSON::ParserError)
|
|
||||||
# Psych::DisallowedClass would be raised if we do not pre-process ruby symbols
|
|
||||||
expect { YAML.safe_load(File.read("#{swagger_root}/v1/swagger.json")) }.not_to raise_error
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with oauth3 upgrades' do
|
|
||||||
let(:doc_2) do
|
|
||||||
{
|
|
||||||
paths: {
|
|
||||||
'/path/' => {
|
|
||||||
get: {
|
|
||||||
summary: 'Retrieve Nested Paths',
|
|
||||||
tags: ['nested Paths'],
|
|
||||||
produces: ['application/json'],
|
|
||||||
consumes: ['application/xml', 'application/json'],
|
|
||||||
parameters: [{
|
|
||||||
in: :body,
|
|
||||||
schema: { foo: :bar }
|
|
||||||
}, {
|
|
||||||
in: :headers
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'removes remaining consumes/produces' do
|
|
||||||
expect(doc_2[:paths]['/path/'][:get].keys).to eql([:summary, :tags, :parameters, :requestBody])
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'duplicates params in: :body to requestBody from consumes list' do
|
|
||||||
expect(doc_2[:paths]['/path/'][:get][:parameters]).to eql([{ in: :headers }])
|
|
||||||
expect(doc_2[:paths]['/path/'][:get][:requestBody]).to eql(content: {
|
|
||||||
'application/xml' => { schema: { foo: :bar } },
|
|
||||||
'application/json' => { schema: { foo: :bar } }
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with oauth3 formData' do
|
|
||||||
let(:doc_2) do
|
|
||||||
{
|
|
||||||
paths: {
|
|
||||||
'/path/' => {
|
|
||||||
post: {
|
|
||||||
summary: 'Retrieve Nested Paths',
|
|
||||||
tags: ['nested Paths'],
|
|
||||||
produces: ['application/json'],
|
|
||||||
consumes: ['multipart/form-data'],
|
|
||||||
parameters: [{
|
|
||||||
in: :formData,
|
|
||||||
schema: { type: :file }
|
|
||||||
},{
|
|
||||||
in: :headers
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'removes remaining consumes/produces' do
|
|
||||||
expect(doc_2[:paths]['/path/'][:post].keys).to eql([:summary, :tags, :parameters, :requestBody])
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'duplicates params in: :formData to requestBody from consumes list' do
|
|
||||||
expect(doc_2[:paths]['/path/'][:post][:parameters]).to eql([{ in: :headers }])
|
|
||||||
expect(doc_2[:paths]['/path/'][:post][:requestBody]).to eql(content: {
|
|
||||||
'multipart/form-data' => { schema: { type: :file } }
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
after do
|
after do
|
||||||
FileUtils.rm_r(swagger_root) if File.exist?(swagger_root)
|
FileUtils.rm_r(swagger_root) if File.exists?(swagger_root)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module Rails
|
module Rails
|
||||||
module VERSION
|
module VERSION
|
||||||
MAJOR = 3
|
MAJOR = 3
|
||||||
|
|||||||
@ -1,4 +1,2 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
# NOTE: For the specs in this gem, all configuration is completely mocked out
|
# NOTE: For the specs in this gem, all configuration is completely mocked out
|
||||||
# The file just needs to be present because it gets required by the swagger_formatter
|
# The file just needs to be present because it gets required by the swagger_formatter
|
||||||
|
|||||||
11
rswag-ui/app/controllers/rswag/ui/home_controller.rb
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
module Rswag
|
||||||
|
module Ui
|
||||||
|
class HomeController < ActionController::Base
|
||||||
|
|
||||||
|
def index
|
||||||
|
@swagger_endpoints = Rswag::Ui.config.swagger_endpoints
|
||||||
|
render :index, layout: false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
126
rswag-ui/app/views/rswag/ui/home/index.html.erb
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Swagger UI</title>
|
||||||
|
<link rel="icon" type="image/png" href="<%= asset_path 'swagger-ui/images/favicon-32x32.png' %>" sizes="32x32" />
|
||||||
|
<link rel="icon" type="image/png" href="<%= asset_path 'swagger-ui/images/favicon-16x16.png' %>" sizes="16x16" />
|
||||||
|
<link href="<%= asset_path 'swagger-ui/css/typography.css' %>" media='screen' rel='stylesheet' type='text/css'/>
|
||||||
|
<link href="<%= asset_path 'swagger-ui/css/reset.css' %>" media='screen' rel='stylesheet' type='text/css'/>
|
||||||
|
<link href="<%= asset_path 'swagger-ui/css/screen.css' %>" media='screen' rel='stylesheet' type='text/css'/>
|
||||||
|
<link href="<%= asset_path 'swagger-ui/css/reset.css' %>" media='print' rel='stylesheet' type='text/css'/>
|
||||||
|
<link href="<%= asset_path 'swagger-ui/css/print.css' %>" media='print' rel='stylesheet' type='text/css'/>
|
||||||
|
|
||||||
|
<script src="<%= asset_path 'swagger-ui/lib/object-assign-pollyfill.js' %>" type='text/javascript'></script>
|
||||||
|
<script src="<%= asset_path 'swagger-ui/lib/jquery-1.8.0.min.js' %>" type='text/javascript'></script>
|
||||||
|
<script src="<%= asset_path 'swagger-ui/lib/jquery.slideto.min.js' %>" type='text/javascript'></script>
|
||||||
|
<script src="<%= asset_path 'swagger-ui/lib/jquery.wiggle.min.js' %>" type='text/javascript'></script>
|
||||||
|
<script src="<%= asset_path 'swagger-ui/lib/jquery.ba-bbq.min.js' %>" type='text/javascript'></script>
|
||||||
|
<script src="<%= asset_path 'swagger-ui/lib/handlebars-4.0.5.js' %>" type='text/javascript'></script>
|
||||||
|
<script src="<%= asset_path 'swagger-ui/lib/lodash.min.js' %>" type='text/javascript'></script>
|
||||||
|
<script src="<%= asset_path 'swagger-ui/lib/backbone-min.js' %>" type='text/javascript'></script>
|
||||||
|
<script src="<%= asset_path 'swagger-ui/swagger-ui.min.js' %>" type='text/javascript'></script>
|
||||||
|
<script src="<%= asset_path 'swagger-ui/lib/highlight.9.1.0.pack.js' %>" type='text/javascript'></script>
|
||||||
|
<script src="<%= asset_path 'swagger-ui/lib/highlight.9.1.0.pack_extended.js' %>" type='text/javascript'></script>
|
||||||
|
<script src="<%= asset_path 'swagger-ui/lib/jsoneditor.min.js' %>" type='text/javascript'></script>
|
||||||
|
<script src="<%= asset_path 'swagger-ui/lib/marked.js' %>" type='text/javascript'></script>
|
||||||
|
<script src="<%= asset_path 'swagger-ui/lib/swagger-oauth.js' %>" type='text/javascript'></script>
|
||||||
|
|
||||||
|
<!-- Some basic translations -->
|
||||||
|
<!-- <script src="<%= asset_path 'swagger-ui/lang/translator.js' %>" type='text/javascript'></script> -->
|
||||||
|
<!-- <script src="<%= asset_path 'swagger-ui/lang/ru.js' %>" type='text/javascript'></script> -->
|
||||||
|
<!-- <script src="<%= asset_path 'swagger-ui/lang/en.js' %>" type='text/javascript'></script> -->
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(function () {
|
||||||
|
hljs.configure({
|
||||||
|
highlightSizeThreshold: 5000
|
||||||
|
});
|
||||||
|
|
||||||
|
// Pre load translate...
|
||||||
|
if(window.SwaggerTranslator) {
|
||||||
|
window.SwaggerTranslator.translate();
|
||||||
|
}
|
||||||
|
window.swaggerUi = new SwaggerUi({
|
||||||
|
url: '<%= @swagger_endpoints.first.path %>',
|
||||||
|
dom_id: "swagger-ui-container",
|
||||||
|
supportedSubmitMethods: ['get', 'post', 'put', 'delete', 'patch'],
|
||||||
|
onComplete: function(swaggerApi, swaggerUi){
|
||||||
|
if(typeof initOAuth == "function") {
|
||||||
|
initOAuth({
|
||||||
|
clientId: "your-client-id",
|
||||||
|
clientSecret: "your-client-secret-if-required",
|
||||||
|
realm: "your-realms",
|
||||||
|
appName: "your-app-name",
|
||||||
|
scopeSeparator: " ",
|
||||||
|
additionalQueryStringParams: {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if(window.SwaggerTranslator) {
|
||||||
|
window.SwaggerTranslator.translate();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onFailure: function(data) {
|
||||||
|
log("Unable to Load SwaggerUI");
|
||||||
|
},
|
||||||
|
docExpansion: "list",
|
||||||
|
jsonEditor: false,
|
||||||
|
defaultModelRendering: 'schema',
|
||||||
|
showRequestHeaders: false
|
||||||
|
});
|
||||||
|
|
||||||
|
window.swaggerUi.load();
|
||||||
|
|
||||||
|
function log() {
|
||||||
|
if ('console' in window) {
|
||||||
|
console.log.apply(console, arguments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="swagger-section">
|
||||||
|
<div id='header'>
|
||||||
|
<div class="swagger-ui-wrap">
|
||||||
|
<a id="logo" href="http://swagger.io"><img class="logo__img" alt="swagger" height="30" width="30" src="<%= asset_path 'swagger-ui/images/logo_small.png' %>" /><span class="logo__title">swagger</span></a>
|
||||||
|
<form id='api_selector'>
|
||||||
|
<div class='input'><input placeholder="http://example.com/api" id="input_baseUrl" name="baseUrl" type="text"/></div>
|
||||||
|
<div id='auth_container'></div>
|
||||||
|
<select id="select_document">
|
||||||
|
<% @swagger_endpoints.each do |endpoint| %>
|
||||||
|
<option value='<%= endpoint.path %>'><%= endpoint.title %></option>
|
||||||
|
<% end %>
|
||||||
|
</select>
|
||||||
|
<script type="text/javascript">
|
||||||
|
// Refresh the swagger-ui when a new document is selected
|
||||||
|
$('#select_document').change(function () {
|
||||||
|
$('#input_baseUrl').val($(this).val());
|
||||||
|
window.swaggerUi.headerView.showCustom();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
#select_document {
|
||||||
|
border: none;
|
||||||
|
height: 1.85em;
|
||||||
|
border-radius: 4px;
|
||||||
|
-moz-border-radius: 4px;
|
||||||
|
-webkit-border-radius: 4px;
|
||||||
|
-o-border-radius: 4px;
|
||||||
|
-ms-border-radius: 4px;
|
||||||
|
-khtml-border-radius: 4px;
|
||||||
|
font-size: 0.85em;
|
||||||
|
font-weight: bold;
|
||||||
|
color: white;
|
||||||
|
background-color: #547f00;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="message-bar" class="swagger-ui-wrap" data-sw-translate> </div>
|
||||||
|
<div id="swagger-ui-container" class="swagger-ui-wrap"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
3
rswag-ui/config/routes.rb
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
Rswag::Ui::Engine.routes.draw do
|
||||||
|
root to: 'home#index'
|
||||||
|
end
|
||||||
@ -3,10 +3,10 @@ require 'rails/generators'
|
|||||||
module Rswag
|
module Rswag
|
||||||
module Ui
|
module Ui
|
||||||
class CustomGenerator < Rails::Generators::Base
|
class CustomGenerator < Rails::Generators::Base
|
||||||
source_root File.expand_path('../../../../../../lib/rswag/ui', __FILE__)
|
source_root File.expand_path('../../../../../../app/views/rswag/ui/home', __FILE__)
|
||||||
|
|
||||||
def add_custom_index
|
def add_custom_index
|
||||||
copy_file('index.erb', 'app/views/rswag/ui/home/index.html.erb')
|
copy_file('index.html.erb', 'app/views/rswag/ui/home/index.html.erb')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -2,13 +2,8 @@ Rswag::Ui.configure do |c|
|
|||||||
|
|
||||||
# List the Swagger endpoints that you want to be documented through the swagger-ui
|
# List the Swagger endpoints that you want to be documented through the swagger-ui
|
||||||
# The first parameter is the path (absolute or relative to the UI host) to the corresponding
|
# The first parameter is the path (absolute or relative to the UI host) to the corresponding
|
||||||
# endpoint and the second is a title that will be displayed in the document selector
|
# JSON endpoint and the second is a title that will be displayed in the document selector
|
||||||
# NOTE: If you're using rspec-api to expose Swagger files (under swagger_root) as JSON or YAML endpoints,
|
# NOTE: If you're using rspec-api to expose Swagger files (under swagger_root) as JSON endpoints,
|
||||||
# then the list below should correspond to the relative paths for those endpoints
|
# then the list below should correspond to the relative paths for those endpoints
|
||||||
|
c.swagger_endpoint '/api-docs/v1/swagger.json', 'API V1 Docs'
|
||||||
c.swagger_endpoint '/api-docs/v1/swagger.yaml', 'API V1 Docs'
|
|
||||||
|
|
||||||
# Add Basic Auth in case your API is private
|
|
||||||
# c.basic_auth_enabled = true
|
|
||||||
# c.basic_auth_credentials 'username', 'password'
|
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,31 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'rack/auth/basic'
|
|
||||||
|
|
||||||
module Rswag
|
|
||||||
module Ui
|
|
||||||
# Extend Rack HTTP Basic Authentication, as per RFC 2617.
|
|
||||||
# @api private
|
|
||||||
#
|
|
||||||
class BasicAuth < ::Rack::Auth::Basic
|
|
||||||
def call(env)
|
|
||||||
return @app.call(env) unless env_matching_path(env)
|
|
||||||
|
|
||||||
super(env)
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def env_matching_path(env)
|
|
||||||
path = base_path(env['PATH_INFO'])
|
|
||||||
Rswag::Ui.config.config_object[:urls].find do |endpoint|
|
|
||||||
base_path(endpoint[:url]) == path
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def base_path(url)
|
|
||||||
url.downcase.split('/')[1]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -1,44 +1,17 @@
|
|||||||
require 'ostruct'
|
require 'ostruct'
|
||||||
require 'rack'
|
|
||||||
|
|
||||||
module Rswag
|
module Rswag
|
||||||
module Ui
|
module Ui
|
||||||
class Configuration
|
class Configuration
|
||||||
attr_reader :template_locations
|
attr_reader :swagger_endpoints
|
||||||
attr_accessor :basic_auth_enabled
|
|
||||||
attr_accessor :config_object
|
|
||||||
attr_accessor :oauth_config_object
|
|
||||||
attr_reader :assets_root
|
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
@template_locations = [
|
@swagger_endpoints = []
|
||||||
# preffered override location
|
|
||||||
"#{Rack::Directory.new('').root}/swagger/index.erb",
|
|
||||||
# backwards compatible override location
|
|
||||||
"#{Rack::Directory.new('').root}/app/views/rswag/ui/home/index.html.erb",
|
|
||||||
# default location
|
|
||||||
File.expand_path('../index.erb', __FILE__)
|
|
||||||
]
|
|
||||||
@assets_root = File.expand_path('../../../../node_modules/swagger-ui-dist', __FILE__)
|
|
||||||
@config_object = {}
|
|
||||||
@oauth_config_object = {}
|
|
||||||
@basic_auth_enabled = false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def swagger_endpoint(url, name)
|
def swagger_endpoint(path, title)
|
||||||
@config_object[:urls] ||= []
|
@swagger_endpoints << OpenStruct.new(path: path, title: title)
|
||||||
@config_object[:urls] << { url: url, name: name }
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def basic_auth_credentials(username, password)
|
|
||||||
@config_object[:basic_auth] = { username: username, password: password }
|
|
||||||
end
|
|
||||||
|
|
||||||
# rubocop:disable Naming/AccessorMethodName
|
|
||||||
def get_binding
|
|
||||||
binding
|
|
||||||
end
|
|
||||||
# rubocop:enable Naming/AccessorMethodName
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,25 +1,20 @@
|
|||||||
require 'rswag/ui/middleware'
|
|
||||||
require 'rswag/ui/basic_auth'
|
|
||||||
|
|
||||||
module Rswag
|
module Rswag
|
||||||
module Ui
|
module Ui
|
||||||
class Engine < ::Rails::Engine
|
class Engine < ::Rails::Engine
|
||||||
isolate_namespace Rswag::Ui
|
isolate_namespace Rswag::Ui
|
||||||
|
|
||||||
initializer 'rswag-ui.initialize' do |app|
|
initializer 'rswag-ui.initialize' do |app|
|
||||||
middleware.use Rswag::Ui::Middleware, Rswag::Ui.config
|
if app.config.respond_to?(:assets)
|
||||||
|
app.config.assets.precompile += [
|
||||||
if Rswag::Ui.config.basic_auth_enabled
|
'swagger-ui/css/*',
|
||||||
c = Rswag::Ui.config
|
'swagger-ui/fonts/*',
|
||||||
app.middleware.use Rswag::Ui::BasicAuth do |username, password|
|
'swagger-ui/images/*',
|
||||||
c.config_object[:basic_auth].values == [username, password]
|
'swagger-ui/lang/*',
|
||||||
end
|
'swagger-ui/lib/*',
|
||||||
|
'swagger-ui/swagger-ui.min.js'
|
||||||
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
rake_tasks do
|
|
||||||
load File.expand_path('../../../tasks/rswag-ui_tasks.rake', __FILE__)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,103 +0,0 @@
|
|||||||
<!-- HTML for static distribution bundle build -->
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>Swagger UI</title>
|
|
||||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700" rel="stylesheet">
|
|
||||||
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" >
|
|
||||||
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
|
|
||||||
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
|
|
||||||
<style>
|
|
||||||
html
|
|
||||||
{
|
|
||||||
box-sizing: border-box;
|
|
||||||
overflow: -moz-scrollbars-vertical;
|
|
||||||
overflow-y: scroll;
|
|
||||||
}
|
|
||||||
*,
|
|
||||||
*:before,
|
|
||||||
*:after
|
|
||||||
{
|
|
||||||
box-sizing: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin:0;
|
|
||||||
background: #fafafa;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position:absolute;width:0;height:0">
|
|
||||||
<defs>
|
|
||||||
<symbol viewBox="0 0 20 20" id="unlocked">
|
|
||||||
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V6h2v-.801C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8z"></path>
|
|
||||||
</symbol>
|
|
||||||
|
|
||||||
<symbol viewBox="0 0 20 20" id="locked">
|
|
||||||
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8zM12 8H8V5.199C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8z"/>
|
|
||||||
</symbol>
|
|
||||||
|
|
||||||
<symbol viewBox="0 0 20 20" id="close">
|
|
||||||
<path d="M14.348 14.849c-.469.469-1.229.469-1.697 0L10 11.819l-2.651 3.029c-.469.469-1.229.469-1.697 0-.469-.469-.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-.469-.469-.469-1.228 0-1.697.469-.469 1.228-.469 1.697 0L10 8.183l2.651-3.031c.469-.469 1.228-.469 1.697 0 .469.469.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c.469.469.469 1.229 0 1.698z"/>
|
|
||||||
</symbol>
|
|
||||||
|
|
||||||
<symbol viewBox="0 0 20 20" id="large-arrow">
|
|
||||||
<path d="M13.25 10L6.109 2.58c-.268-.27-.268-.707 0-.979.268-.27.701-.27.969 0l7.83 7.908c.268.271.268.709 0 .979l-7.83 7.908c-.268.271-.701.27-.969 0-.268-.269-.268-.707 0-.979L13.25 10z"/>
|
|
||||||
</symbol>
|
|
||||||
|
|
||||||
<symbol viewBox="0 0 20 20" id="large-arrow-down">
|
|
||||||
<path d="M17.418 6.109c.272-.268.709-.268.979 0s.271.701 0 .969l-7.908 7.83c-.27.268-.707.268-.979 0l-7.908-7.83c-.27-.268-.27-.701 0-.969.271-.268.709-.268.979 0L10 13.25l7.418-7.141z"/>
|
|
||||||
</symbol>
|
|
||||||
|
|
||||||
|
|
||||||
<symbol viewBox="0 0 24 24" id="jump-to">
|
|
||||||
<path d="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z"/>
|
|
||||||
</symbol>
|
|
||||||
|
|
||||||
<symbol viewBox="0 0 24 24" id="expand">
|
|
||||||
<path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>
|
|
||||||
</symbol>
|
|
||||||
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
||||||
|
|
||||||
<div id="swagger-ui"></div>
|
|
||||||
|
|
||||||
<!-- Workaround for https://github.com/swagger-api/swagger-editor/issues/1371 -->
|
|
||||||
<script>
|
|
||||||
if (window.navigator.userAgent.indexOf("Edge") > -1) {
|
|
||||||
console.log("Removing native Edge fetch in favor of swagger-ui's polyfill")
|
|
||||||
window.fetch = undefined;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script src="./swagger-ui-bundle.js"> </script>
|
|
||||||
<script src="./swagger-ui-standalone-preset.js"> </script>
|
|
||||||
<script>
|
|
||||||
window.onload = function () {
|
|
||||||
var configObject = JSON.parse('<%= config_object.to_json %>');
|
|
||||||
var oauthConfigObject = JSON.parse('<%= oauth_config_object.to_json %>');
|
|
||||||
|
|
||||||
// Apply mandatory parameters
|
|
||||||
configObject.dom_id = "#swagger-ui";
|
|
||||||
configObject.presets = [SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset];
|
|
||||||
configObject.layout = "StandaloneLayout";
|
|
||||||
|
|
||||||
// If oauth2RedirectUrl isn't specified, use the built-in default
|
|
||||||
if (!configObject.hasOwnProperty("oauth2RedirectUrl"))
|
|
||||||
configObject.oauth2RedirectUrl = window.location.href.replace("index.html", "oauth2-redirect.html");
|
|
||||||
|
|
||||||
// Build a system
|
|
||||||
const ui = SwaggerUIBundle(configObject);
|
|
||||||
|
|
||||||
// Apply OAuth config
|
|
||||||
ui.initOAuth(oauthConfigObject);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
@ -1,44 +0,0 @@
|
|||||||
module Rswag
|
|
||||||
module Ui
|
|
||||||
class Middleware < Rack::Static
|
|
||||||
|
|
||||||
def initialize(app, config)
|
|
||||||
@config = config
|
|
||||||
super(app, urls: [ '' ], root: config.assets_root )
|
|
||||||
end
|
|
||||||
|
|
||||||
def call(env)
|
|
||||||
if base_path?(env)
|
|
||||||
redirect_uri = env['SCRIPT_NAME'].chomp('/') + '/index.html'
|
|
||||||
return [ 301, { 'Location' => redirect_uri }, [ ] ]
|
|
||||||
end
|
|
||||||
|
|
||||||
if index_path?(env)
|
|
||||||
return [ 200, { 'Content-Type' => 'text/html' }, [ render_template ] ]
|
|
||||||
end
|
|
||||||
|
|
||||||
super
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def base_path?(env)
|
|
||||||
env['REQUEST_METHOD'] == "GET" && env['PATH_INFO'] == "/"
|
|
||||||
end
|
|
||||||
|
|
||||||
def index_path?(env)
|
|
||||||
env['REQUEST_METHOD'] == "GET" && env['PATH_INFO'] == "/index.html"
|
|
||||||
end
|
|
||||||
|
|
||||||
def render_template
|
|
||||||
file = File.new(template_filename)
|
|
||||||
template = ERB.new(file.read)
|
|
||||||
template.result(@config.get_binding)
|
|
||||||
end
|
|
||||||
|
|
||||||
def template_filename
|
|
||||||
@config.template_locations.find { |filename| File.exists?(filename) }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
namespace :rswag do
|
|
||||||
namespace :ui do
|
|
||||||
|
|
||||||
desc 'TODO'
|
|
||||||
task :copy_assets, [ :dest ] do |t, args|
|
|
||||||
dest = args[:dest]
|
|
||||||
FileUtils.rm_r(dest, force: true)
|
|
||||||
FileUtils.mkdir_p(dest)
|
|
||||||
FileUtils.cp_r(Dir.glob("#{Rswag::Ui.config.assets_root}/{*.js,*.png,*.css}"), dest)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
13
rswag-ui/package-lock.json
generated
@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "rswag-ui",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"lockfileVersion": 1,
|
|
||||||
"requires": true,
|
|
||||||
"dependencies": {
|
|
||||||
"swagger-ui-dist": {
|
|
||||||
"version": "3.52.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-3.52.5.tgz",
|
|
||||||
"integrity": "sha512-8z18eX8G/jbTXYzyNIaobrnD7PSN7yU/YkSasMmajrXtw0FGS64XjrKn5v37d36qmU3o1xLeuYnktshRr7uIFw=="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "rswag-ui",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"private": true,
|
|
||||||
"dependencies": {
|
|
||||||
"swagger-ui-dist": "3.52.5"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,20 +1,18 @@
|
|||||||
# frozen_string_literal: true
|
$:.push File.expand_path("../lib", __FILE__)
|
||||||
|
|
||||||
$LOAD_PATH.push File.expand_path('../lib', __FILE__)
|
|
||||||
|
|
||||||
# Describe your gem and declare its dependencies:
|
# Describe your gem and declare its dependencies:
|
||||||
Gem::Specification.new do |s|
|
Gem::Specification.new do |s|
|
||||||
s.name = 'rswag-ui'
|
s.name = "rswag-ui"
|
||||||
s.version = ENV['TRAVIS_TAG'] || '0.0.0'
|
s.version = ENV['TRAVIS_TAG'] || '0.0.0'
|
||||||
s.authors = ['Richie Morris', 'Greg Myers', 'Jay Danielian']
|
s.authors = ["Richie Morris"]
|
||||||
s.email = ['domaindrivendev@gmail.com']
|
s.email = ["domaindrivendev@gmail.com"]
|
||||||
s.homepage = 'https://github.com/rswag/rswag'
|
s.homepage = "https://github.com/domaindrivendev/rswag"
|
||||||
s.summary = 'A Rails Engine that includes swagger-ui and powers it from configured OpenAPI (formerly named Swagger) endpoints'
|
s.summary = "A Rails Engine that includes swagger-ui and powers it from configured Swagger endpoints"
|
||||||
s.description = 'Expose beautiful API documentation, powered by Swagger JSON endpoints, including a UI to explore and test operations. More about the OpenAPI initiative here: http://spec.openapis.org/'
|
s.description = "Expose beautiful API documentation, that's powered by Swagger JSON endpoints, including a UI to explore and test operations"
|
||||||
s.license = 'MIT'
|
s.license = "MIT"
|
||||||
|
|
||||||
s.files = Dir.glob('{lib,node_modules}/**/*') + ['MIT-LICENSE', 'Rakefile' ]
|
s.files = Dir["{app,config,lib,vendor}/**/*"] + ["MIT-LICENSE", "Rakefile" ]
|
||||||
|
|
||||||
s.add_dependency 'actionpack', '>=3.1', '< 7.1'
|
s.add_dependency 'actionpack', '>=3.1', '< 6.0'
|
||||||
s.add_dependency 'railties', '>= 3.1', '< 7.1'
|
s.add_dependency 'railties', '>= 3.1', '< 6.0'
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,52 +0,0 @@
|
|||||||
require 'rswag/ui/configuration'
|
|
||||||
|
|
||||||
require_relative '../../spec_helper'
|
|
||||||
|
|
||||||
RSpec.describe Rswag::Ui::Configuration do
|
|
||||||
describe '#swagger_endpoints'
|
|
||||||
|
|
||||||
describe '#basic_auth_enabled' do
|
|
||||||
context 'when unspecified' do
|
|
||||||
it 'defaults to false' do
|
|
||||||
configuration = described_class.new
|
|
||||||
basic_auth_enabled = configuration.basic_auth_enabled
|
|
||||||
|
|
||||||
expect(basic_auth_enabled).to be(false)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when specified' do
|
|
||||||
context 'when set to true' do
|
|
||||||
it 'returns true' do
|
|
||||||
configuration = described_class.new
|
|
||||||
configuration.basic_auth_enabled = true
|
|
||||||
basic_auth_enabled = configuration.basic_auth_enabled
|
|
||||||
|
|
||||||
expect(basic_auth_enabled).to be(true)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when set to false' do
|
|
||||||
it 'returns false' do
|
|
||||||
configuration = described_class.new
|
|
||||||
configuration.basic_auth_enabled = false
|
|
||||||
basic_auth_enabled = configuration.basic_auth_enabled
|
|
||||||
|
|
||||||
expect(basic_auth_enabled).to be(false)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#basic_auth_credentials' do
|
|
||||||
it 'sets the username and password' do
|
|
||||||
configuration = described_class.new
|
|
||||||
configuration.basic_auth_credentials 'foo', 'bar'
|
|
||||||
credentials = configuration.config_object[:basic_auth]
|
|
||||||
|
|
||||||
expect(credentials).to eq(username: 'foo', password: 'bar')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#get_binding'
|
|
||||||
end
|
|
||||||
@ -1,100 +0,0 @@
|
|||||||
# This file was generated by the `rspec --init` command. Conventionally, all
|
|
||||||
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
|
||||||
# The generated `.rspec` file contains `--require spec_helper` which will cause
|
|
||||||
# this file to always be loaded, without a need to explicitly require it in any
|
|
||||||
# files.
|
|
||||||
#
|
|
||||||
# Given that it is always loaded, you are encouraged to keep this file as
|
|
||||||
# light-weight as possible. Requiring heavyweight dependencies from this file
|
|
||||||
# will add to the boot time of your test suite on EVERY test run, even for an
|
|
||||||
# individual file that may not need all of that loaded. Instead, consider making
|
|
||||||
# a separate helper file that requires the additional dependencies and performs
|
|
||||||
# the additional setup, and require it from the spec files that actually need
|
|
||||||
# it.
|
|
||||||
#
|
|
||||||
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
|
||||||
RSpec.configure do |config|
|
|
||||||
# rspec-expectations config goes here. You can use an alternate
|
|
||||||
# assertion/expectation library such as wrong or the stdlib/minitest
|
|
||||||
# assertions if you prefer.
|
|
||||||
config.expect_with :rspec do |expectations|
|
|
||||||
# This option will default to `true` in RSpec 4. It makes the `description`
|
|
||||||
# and `failure_message` of custom matchers include text for helper methods
|
|
||||||
# defined using `chain`, e.g.:
|
|
||||||
# be_bigger_than(2).and_smaller_than(4).description
|
|
||||||
# # => "be bigger than 2 and smaller than 4"
|
|
||||||
# ...rather than:
|
|
||||||
# # => "be bigger than 2"
|
|
||||||
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
|
||||||
end
|
|
||||||
|
|
||||||
# rspec-mocks config goes here. You can use an alternate test double
|
|
||||||
# library (such as bogus or mocha) by changing the `mock_with` option here.
|
|
||||||
config.mock_with :rspec do |mocks|
|
|
||||||
# Prevents you from mocking or stubbing a method that does not exist on
|
|
||||||
# a real object. This is generally recommended, and will default to
|
|
||||||
# `true` in RSpec 4.
|
|
||||||
mocks.verify_partial_doubles = true
|
|
||||||
end
|
|
||||||
|
|
||||||
# This option will default to `:apply_to_host_groups` in RSpec 4 (and will
|
|
||||||
# have no way to turn it off -- the option exists only for backwards
|
|
||||||
# compatibility in RSpec 3). It causes shared context metadata to be
|
|
||||||
# inherited by the metadata hash of host groups and examples, rather than
|
|
||||||
# triggering implicit auto-inclusion in groups with matching metadata.
|
|
||||||
config.shared_context_metadata_behavior = :apply_to_host_groups
|
|
||||||
|
|
||||||
# The settings below are suggested to provide a good initial experience
|
|
||||||
# with RSpec, but feel free to customize to your heart's content.
|
|
||||||
=begin
|
|
||||||
# This allows you to limit a spec run to individual examples or groups
|
|
||||||
# you care about by tagging them with `:focus` metadata. When nothing
|
|
||||||
# is tagged with `:focus`, all examples get run. RSpec also provides
|
|
||||||
# aliases for `it`, `describe`, and `context` that include `:focus`
|
|
||||||
# metadata: `fit`, `fdescribe` and `fcontext`, respectively.
|
|
||||||
config.filter_run_when_matching :focus
|
|
||||||
|
|
||||||
# Allows RSpec to persist some state between runs in order to support
|
|
||||||
# the `--only-failures` and `--next-failure` CLI options. We recommend
|
|
||||||
# you configure your source control system to ignore this file.
|
|
||||||
config.example_status_persistence_file_path = "spec/examples.txt"
|
|
||||||
|
|
||||||
# Limits the available syntax to the non-monkey patched syntax that is
|
|
||||||
# recommended. For more details, see:
|
|
||||||
# - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
|
|
||||||
# - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
|
||||||
# - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
|
|
||||||
config.disable_monkey_patching!
|
|
||||||
|
|
||||||
# This setting enables warnings. It's recommended, but in some cases may
|
|
||||||
# be too noisy due to issues in dependencies.
|
|
||||||
config.warnings = true
|
|
||||||
|
|
||||||
# Many RSpec users commonly either run the entire suite or an individual
|
|
||||||
# file, and it's useful to allow more verbose output when running an
|
|
||||||
# individual spec file.
|
|
||||||
if config.files_to_run.one?
|
|
||||||
# Use the documentation formatter for detailed output,
|
|
||||||
# unless a formatter has already been configured
|
|
||||||
# (e.g. via a command-line flag).
|
|
||||||
config.default_formatter = "doc"
|
|
||||||
end
|
|
||||||
|
|
||||||
# Print the 10 slowest examples and example groups at the
|
|
||||||
# end of the spec run, to help surface which specs are running
|
|
||||||
# particularly slow.
|
|
||||||
config.profile_examples = 10
|
|
||||||
|
|
||||||
# Run specs in random order to surface order dependencies. If you find an
|
|
||||||
# order dependency and want to debug it, you can fix the order by providing
|
|
||||||
# the seed, which is printed after each run.
|
|
||||||
# --seed 1234
|
|
||||||
config.order = :random
|
|
||||||
|
|
||||||
# Seed global randomization in this process using the `--seed` CLI option.
|
|
||||||
# Setting this allows you to use `--seed` to deterministically reproduce
|
|
||||||
# test failures related to randomization by passing the same `--seed` value
|
|
||||||
# as the one that triggered the failure.
|
|
||||||
Kernel.srand config.seed
|
|
||||||
=end
|
|
||||||
end
|
|
||||||
1367
rswag-ui/vendor/assets/components/swagger-ui/css/print.css.erb
vendored
Normal file
125
rswag-ui/vendor/assets/components/swagger-ui/css/reset.css
vendored
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/* http://meyerweb.com/eric/tools/css/reset/ v2.0 | 20110126 */
|
||||||
|
html,
|
||||||
|
body,
|
||||||
|
div,
|
||||||
|
span,
|
||||||
|
applet,
|
||||||
|
object,
|
||||||
|
iframe,
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6,
|
||||||
|
p,
|
||||||
|
blockquote,
|
||||||
|
pre,
|
||||||
|
a,
|
||||||
|
abbr,
|
||||||
|
acronym,
|
||||||
|
address,
|
||||||
|
big,
|
||||||
|
cite,
|
||||||
|
code,
|
||||||
|
del,
|
||||||
|
dfn,
|
||||||
|
em,
|
||||||
|
img,
|
||||||
|
ins,
|
||||||
|
kbd,
|
||||||
|
q,
|
||||||
|
s,
|
||||||
|
samp,
|
||||||
|
small,
|
||||||
|
strike,
|
||||||
|
strong,
|
||||||
|
sub,
|
||||||
|
sup,
|
||||||
|
tt,
|
||||||
|
var,
|
||||||
|
b,
|
||||||
|
u,
|
||||||
|
i,
|
||||||
|
center,
|
||||||
|
dl,
|
||||||
|
dt,
|
||||||
|
dd,
|
||||||
|
ol,
|
||||||
|
ul,
|
||||||
|
li,
|
||||||
|
fieldset,
|
||||||
|
form,
|
||||||
|
label,
|
||||||
|
legend,
|
||||||
|
table,
|
||||||
|
caption,
|
||||||
|
tbody,
|
||||||
|
tfoot,
|
||||||
|
thead,
|
||||||
|
tr,
|
||||||
|
th,
|
||||||
|
td,
|
||||||
|
article,
|
||||||
|
aside,
|
||||||
|
canvas,
|
||||||
|
details,
|
||||||
|
embed,
|
||||||
|
figure,
|
||||||
|
figcaption,
|
||||||
|
footer,
|
||||||
|
header,
|
||||||
|
hgroup,
|
||||||
|
menu,
|
||||||
|
nav,
|
||||||
|
output,
|
||||||
|
ruby,
|
||||||
|
section,
|
||||||
|
summary,
|
||||||
|
time,
|
||||||
|
mark,
|
||||||
|
audio,
|
||||||
|
video {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
font-size: 100%;
|
||||||
|
font: inherit;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
/* HTML5 display-role reset for older browsers */
|
||||||
|
article,
|
||||||
|
aside,
|
||||||
|
details,
|
||||||
|
figcaption,
|
||||||
|
figure,
|
||||||
|
footer,
|
||||||
|
header,
|
||||||
|
hgroup,
|
||||||
|
menu,
|
||||||
|
nav,
|
||||||
|
section {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
ol,
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
blockquote,
|
||||||
|
q {
|
||||||
|
quotes: none;
|
||||||
|
}
|
||||||
|
blockquote:before,
|
||||||
|
blockquote:after,
|
||||||
|
q:before,
|
||||||
|
q:after {
|
||||||
|
content: '';
|
||||||
|
content: none;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0;
|
||||||
|
}
|
||||||
1494
rswag-ui/vendor/assets/components/swagger-ui/css/screen.css.erb
vendored
Normal file
250
rswag-ui/vendor/assets/components/swagger-ui/css/style.css.erb
vendored
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
.swagger-section #header a#logo {
|
||||||
|
font-size: 1.5em;
|
||||||
|
font-weight: bold;
|
||||||
|
text-decoration: none;
|
||||||
|
background: transparent url(<%= asset_path('swagger-ui/images/logo.png') %>) no-repeat left center;
|
||||||
|
padding: 20px 0 20px 40px;
|
||||||
|
}
|
||||||
|
#text-head {
|
||||||
|
font-size: 80px;
|
||||||
|
font-family: 'Roboto', sans-serif;
|
||||||
|
color: #ffffff;
|
||||||
|
float: right;
|
||||||
|
margin-right: 20%;
|
||||||
|
}
|
||||||
|
.navbar-fixed-top .navbar-nav {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
.navbar-fixed-top .navbar-brand {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
.navbar-header {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
.navbar-inverse {
|
||||||
|
background-color: #000;
|
||||||
|
border-color: #000;
|
||||||
|
}
|
||||||
|
#navbar-brand {
|
||||||
|
margin-left: 20%;
|
||||||
|
}
|
||||||
|
.navtext {
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
.h1,
|
||||||
|
h1 {
|
||||||
|
font-size: 60px;
|
||||||
|
}
|
||||||
|
.navbar-default .navbar-header .navbar-brand {
|
||||||
|
color: #a2dfee;
|
||||||
|
}
|
||||||
|
/* tag titles */
|
||||||
|
.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a {
|
||||||
|
color: #393939;
|
||||||
|
font-family: 'Arvo', serif;
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a:hover {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 {
|
||||||
|
color: #525252;
|
||||||
|
padding-left: 0px;
|
||||||
|
display: block;
|
||||||
|
clear: none;
|
||||||
|
float: left;
|
||||||
|
font-family: 'Arvo', serif;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.navbar-default .navbar-collapse,
|
||||||
|
.navbar-default .navbar-form {
|
||||||
|
border-color: #0A0A0A;
|
||||||
|
}
|
||||||
|
.container1 {
|
||||||
|
width: 1500px;
|
||||||
|
margin: auto;
|
||||||
|
margin-top: 0;
|
||||||
|
background-image: url(<%= asset_path('swagger-ui/images/shield.png') %>);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: -40px -20px;
|
||||||
|
margin-bottom: 210px;
|
||||||
|
}
|
||||||
|
.container-inner {
|
||||||
|
width: 1200px;
|
||||||
|
margin: auto;
|
||||||
|
background-color: rgba(223, 227, 228, 0.75);
|
||||||
|
padding-bottom: 40px;
|
||||||
|
padding-top: 40px;
|
||||||
|
border-radius: 15px;
|
||||||
|
}
|
||||||
|
.header-content {
|
||||||
|
padding: 0;
|
||||||
|
width: 1000px;
|
||||||
|
}
|
||||||
|
.title1 {
|
||||||
|
font-size: 80px;
|
||||||
|
font-family: 'Vollkorn', serif;
|
||||||
|
color: #404040;
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 40px;
|
||||||
|
padding-bottom: 100px;
|
||||||
|
}
|
||||||
|
#icon {
|
||||||
|
margin-top: -18px;
|
||||||
|
}
|
||||||
|
.subtext {
|
||||||
|
font-size: 25px;
|
||||||
|
font-style: italic;
|
||||||
|
color: #08b;
|
||||||
|
text-align: right;
|
||||||
|
padding-right: 250px;
|
||||||
|
}
|
||||||
|
.bg-primary {
|
||||||
|
background-color: #00468b;
|
||||||
|
}
|
||||||
|
.navbar-default .nav > li > a,
|
||||||
|
.navbar-default .nav > li > a:focus {
|
||||||
|
color: #08b;
|
||||||
|
}
|
||||||
|
.navbar-default .nav > li > a,
|
||||||
|
.navbar-default .nav > li > a:hover {
|
||||||
|
color: #08b;
|
||||||
|
}
|
||||||
|
.navbar-default .nav > li > a,
|
||||||
|
.navbar-default .nav > li > a:focus:hover {
|
||||||
|
color: #08b;
|
||||||
|
}
|
||||||
|
.text-faded {
|
||||||
|
font-size: 25px;
|
||||||
|
font-family: 'Vollkorn', serif;
|
||||||
|
}
|
||||||
|
.section-heading {
|
||||||
|
font-family: 'Vollkorn', serif;
|
||||||
|
font-size: 45px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
hr {
|
||||||
|
border-color: #00468b;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
.description {
|
||||||
|
margin-top: 20px;
|
||||||
|
padding-bottom: 200px;
|
||||||
|
}
|
||||||
|
.description li {
|
||||||
|
font-family: 'Vollkorn', serif;
|
||||||
|
font-size: 25px;
|
||||||
|
color: #525252;
|
||||||
|
margin-left: 28%;
|
||||||
|
padding-top: 5px;
|
||||||
|
}
|
||||||
|
.gap {
|
||||||
|
margin-top: 200px;
|
||||||
|
}
|
||||||
|
.troubleshootingtext {
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
padding-left: 30%;
|
||||||
|
}
|
||||||
|
.troubleshootingtext li {
|
||||||
|
list-style-type: circle;
|
||||||
|
font-size: 25px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
}
|
||||||
|
.overlay {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
.block.response_body.json:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.backdrop {
|
||||||
|
color: blue;
|
||||||
|
}
|
||||||
|
#myModal {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.modal-backdrop {
|
||||||
|
bottom: 0;
|
||||||
|
position: fixed;
|
||||||
|
}
|
||||||
|
.curl {
|
||||||
|
padding: 10px;
|
||||||
|
font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace;
|
||||||
|
font-size: 0.9em;
|
||||||
|
max-height: 400px;
|
||||||
|
margin-top: 5px;
|
||||||
|
overflow-y: auto;
|
||||||
|
background-color: #fcf6db;
|
||||||
|
border: 1px solid #e5e0c6;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
.curl_title {
|
||||||
|
font-size: 1.1em;
|
||||||
|
margin: 0;
|
||||||
|
padding: 15px 0 5px;
|
||||||
|
font-family: 'Open Sans', 'Helvetica Neue', Arial, sans-serif;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
.footer {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.swagger-section .swagger-ui-wrap h2 {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
margin: 0;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
.markdown p {
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: 'Arvo', serif;
|
||||||
|
}
|
||||||
|
.swagger-section .swagger-ui-wrap .code {
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: 'Arvo', serif;
|
||||||
|
}
|
||||||
|
.swagger-section .swagger-ui-wrap b {
|
||||||
|
font-family: 'Arvo', serif;
|
||||||
|
}
|
||||||
|
#signin:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.dropdown-menu {
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
.navbar-right .dropdown-menu {
|
||||||
|
left: 0;
|
||||||
|
right: auto;
|
||||||
|
}
|
||||||
|
#signinbutton {
|
||||||
|
width: 100%;
|
||||||
|
height: 32px;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #08b;
|
||||||
|
}
|
||||||
|
.navbar-default .nav > li .details {
|
||||||
|
color: #000000;
|
||||||
|
text-transform: none;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: normal;
|
||||||
|
font-family: 'Open Sans', sans-serif;
|
||||||
|
font-style: italic;
|
||||||
|
line-height: 20px;
|
||||||
|
top: -2px;
|
||||||
|
}
|
||||||
|
.navbar-default .nav > li .details:hover {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
#signout {
|
||||||
|
width: 100%;
|
||||||
|
height: 32px;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #08b;
|
||||||
|
}
|
||||||
14
rswag-ui/vendor/assets/components/swagger-ui/css/typography.css.erb
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/* Google Font's Droid Sans */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Droid Sans';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Droid Sans'), local('DroidSans'), url(<%= asset_path('swagger-ui/fonts/DroidSans.ttf') %>), format('truetype');
|
||||||
|
}
|
||||||
|
/* Google Font's Droid Sans Bold */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Droid Sans';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
src: local('Droid Sans Bold'), local('DroidSans-Bold'), url(<%= asset_path('swagger-ui/fonts/DroidSans-Bold.ttf') %>), format('truetype');
|
||||||
|
}
|
||||||
BIN
rswag-ui/vendor/assets/components/swagger-ui/fonts/DroidSans-Bold.ttf
vendored
Normal file
BIN
rswag-ui/vendor/assets/components/swagger-ui/fonts/DroidSans.ttf
vendored
Normal file
BIN
rswag-ui/vendor/assets/components/swagger-ui/images/collapse.gif
vendored
Normal file
|
After Width: | Height: | Size: 69 B |
BIN
rswag-ui/vendor/assets/components/swagger-ui/images/expand.gif
vendored
Normal file
|
After Width: | Height: | Size: 73 B |
BIN
rswag-ui/vendor/assets/components/swagger-ui/images/explorer_icons.png
vendored
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
rswag-ui/vendor/assets/components/swagger-ui/images/favicon-16x16.png
vendored
Executable file
|
After Width: | Height: | Size: 445 B |
BIN
rswag-ui/vendor/assets/components/swagger-ui/images/favicon-32x32.png
vendored
Executable file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
rswag-ui/vendor/assets/components/swagger-ui/images/favicon.ico
vendored
Executable file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
rswag-ui/vendor/assets/components/swagger-ui/images/logo_small.png
vendored
Normal file
|
After Width: | Height: | Size: 455 B |
BIN
rswag-ui/vendor/assets/components/swagger-ui/images/pet_store_api.png
vendored
Normal file
|
After Width: | Height: | Size: 631 B |
BIN
rswag-ui/vendor/assets/components/swagger-ui/images/throbber.gif
vendored
Normal file
|
After Width: | Height: | Size: 9.0 KiB |
BIN
rswag-ui/vendor/assets/components/swagger-ui/images/wordnik_api.png
vendored
Normal file
|
After Width: | Height: | Size: 670 B |
53
rswag-ui/vendor/assets/components/swagger-ui/lang/ca.js
vendored
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/* jshint quotmark: double */
|
||||||
|
window.SwaggerTranslator.learn({
|
||||||
|
"Warning: Deprecated":"Advertència: Obsolet",
|
||||||
|
"Implementation Notes":"Notes d'implementació",
|
||||||
|
"Response Class":"Classe de la Resposta",
|
||||||
|
"Status":"Estatus",
|
||||||
|
"Parameters":"Paràmetres",
|
||||||
|
"Parameter":"Paràmetre",
|
||||||
|
"Value":"Valor",
|
||||||
|
"Description":"Descripció",
|
||||||
|
"Parameter Type":"Tipus del Paràmetre",
|
||||||
|
"Data Type":"Tipus de la Dada",
|
||||||
|
"Response Messages":"Missatges de la Resposta",
|
||||||
|
"HTTP Status Code":"Codi d'Estatus HTTP",
|
||||||
|
"Reason":"Raó",
|
||||||
|
"Response Model":"Model de la Resposta",
|
||||||
|
"Request URL":"URL de la Sol·licitud",
|
||||||
|
"Response Body":"Cos de la Resposta",
|
||||||
|
"Response Code":"Codi de la Resposta",
|
||||||
|
"Response Headers":"Capçaleres de la Resposta",
|
||||||
|
"Hide Response":"Amagar Resposta",
|
||||||
|
"Try it out!":"Prova-ho!",
|
||||||
|
"Show/Hide":"Mostrar/Amagar",
|
||||||
|
"List Operations":"Llista Operacions",
|
||||||
|
"Expand Operations":"Expandir Operacions",
|
||||||
|
"Raw":"Cru",
|
||||||
|
"can't parse JSON. Raw result":"no puc analitzar el JSON. Resultat cru",
|
||||||
|
"Example Value":"Valor d'Exemple",
|
||||||
|
"Model Schema":"Esquema del Model",
|
||||||
|
"Model":"Model",
|
||||||
|
"apply":"aplicar",
|
||||||
|
"Username":"Nom d'usuari",
|
||||||
|
"Password":"Contrasenya",
|
||||||
|
"Terms of service":"Termes del servei",
|
||||||
|
"Created by":"Creat per",
|
||||||
|
"See more at":"Veure més en",
|
||||||
|
"Contact the developer":"Contactar amb el desenvolupador",
|
||||||
|
"api version":"versió de la api",
|
||||||
|
"Response Content Type":"Tipus de Contingut de la Resposta",
|
||||||
|
"fetching resource":"recollint recurs",
|
||||||
|
"fetching resource list":"recollins llista de recursos",
|
||||||
|
"Explore":"Explorant",
|
||||||
|
"Show Swagger Petstore Example Apis":"Mostrar API d'Exemple Swagger Petstore",
|
||||||
|
"Can't read from server. It may not have the appropriate access-control-origin settings.":"No es pot llegir del servidor. Potser no teniu la configuració de control d'accés apropiada.",
|
||||||
|
"Please specify the protocol for":"Si us plau, especifiqueu el protocol per a",
|
||||||
|
"Can't read swagger JSON from":"No es pot llegir el JSON de swagger des de",
|
||||||
|
"Finished Loading Resource Information. Rendering Swagger UI":"Finalitzada la càrrega del recurs informatiu. Renderitzant Swagger UI",
|
||||||
|
"Unable to read api":"No es pot llegir l'api",
|
||||||
|
"from path":"des de la ruta",
|
||||||
|
"server returned":"el servidor ha retornat"
|
||||||
|
});
|
||||||
56
rswag-ui/vendor/assets/components/swagger-ui/lang/en.js
vendored
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/* jshint quotmark: double */
|
||||||
|
window.SwaggerTranslator.learn({
|
||||||
|
"Warning: Deprecated":"Warning: Deprecated",
|
||||||
|
"Implementation Notes":"Implementation Notes",
|
||||||
|
"Response Class":"Response Class",
|
||||||
|
"Status":"Status",
|
||||||
|
"Parameters":"Parameters",
|
||||||
|
"Parameter":"Parameter",
|
||||||
|
"Value":"Value",
|
||||||
|
"Description":"Description",
|
||||||
|
"Parameter Type":"Parameter Type",
|
||||||
|
"Data Type":"Data Type",
|
||||||
|
"Response Messages":"Response Messages",
|
||||||
|
"HTTP Status Code":"HTTP Status Code",
|
||||||
|
"Reason":"Reason",
|
||||||
|
"Response Model":"Response Model",
|
||||||
|
"Request URL":"Request URL",
|
||||||
|
"Response Body":"Response Body",
|
||||||
|
"Response Code":"Response Code",
|
||||||
|
"Response Headers":"Response Headers",
|
||||||
|
"Hide Response":"Hide Response",
|
||||||
|
"Headers":"Headers",
|
||||||
|
"Try it out!":"Try it out!",
|
||||||
|
"Show/Hide":"Show/Hide",
|
||||||
|
"List Operations":"List Operations",
|
||||||
|
"Expand Operations":"Expand Operations",
|
||||||
|
"Raw":"Raw",
|
||||||
|
"can't parse JSON. Raw result":"can't parse JSON. Raw result",
|
||||||
|
"Example Value":"Example Value",
|
||||||
|
"Model Schema":"Model Schema",
|
||||||
|
"Model":"Model",
|
||||||
|
"Click to set as parameter value":"Click to set as parameter value",
|
||||||
|
"apply":"apply",
|
||||||
|
"Username":"Username",
|
||||||
|
"Password":"Password",
|
||||||
|
"Terms of service":"Terms of service",
|
||||||
|
"Created by":"Created by",
|
||||||
|
"See more at":"See more at",
|
||||||
|
"Contact the developer":"Contact the developer",
|
||||||
|
"api version":"api version",
|
||||||
|
"Response Content Type":"Response Content Type",
|
||||||
|
"Parameter content type:":"Parameter content type:",
|
||||||
|
"fetching resource":"fetching resource",
|
||||||
|
"fetching resource list":"fetching resource list",
|
||||||
|
"Explore":"Explore",
|
||||||
|
"Show Swagger Petstore Example Apis":"Show Swagger Petstore Example Apis",
|
||||||
|
"Can't read from server. It may not have the appropriate access-control-origin settings.":"Can't read from server. It may not have the appropriate access-control-origin settings.",
|
||||||
|
"Please specify the protocol for":"Please specify the protocol for",
|
||||||
|
"Can't read swagger JSON from":"Can't read swagger JSON from",
|
||||||
|
"Finished Loading Resource Information. Rendering Swagger UI":"Finished Loading Resource Information. Rendering Swagger UI",
|
||||||
|
"Unable to read api":"Unable to read api",
|
||||||
|
"from path":"from path",
|
||||||
|
"server returned":"server returned"
|
||||||
|
});
|
||||||
53
rswag-ui/vendor/assets/components/swagger-ui/lang/es.js
vendored
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/* jshint quotmark: double */
|
||||||
|
window.SwaggerTranslator.learn({
|
||||||
|
"Warning: Deprecated":"Advertencia: Obsoleto",
|
||||||
|
"Implementation Notes":"Notas de implementación",
|
||||||
|
"Response Class":"Clase de la Respuesta",
|
||||||
|
"Status":"Status",
|
||||||
|
"Parameters":"Parámetros",
|
||||||
|
"Parameter":"Parámetro",
|
||||||
|
"Value":"Valor",
|
||||||
|
"Description":"Descripción",
|
||||||
|
"Parameter Type":"Tipo del Parámetro",
|
||||||
|
"Data Type":"Tipo del Dato",
|
||||||
|
"Response Messages":"Mensajes de la Respuesta",
|
||||||
|
"HTTP Status Code":"Código de Status HTTP",
|
||||||
|
"Reason":"Razón",
|
||||||
|
"Response Model":"Modelo de la Respuesta",
|
||||||
|
"Request URL":"URL de la Solicitud",
|
||||||
|
"Response Body":"Cuerpo de la Respuesta",
|
||||||
|
"Response Code":"Código de la Respuesta",
|
||||||
|
"Response Headers":"Encabezados de la Respuesta",
|
||||||
|
"Hide Response":"Ocultar Respuesta",
|
||||||
|
"Try it out!":"Pruébalo!",
|
||||||
|
"Show/Hide":"Mostrar/Ocultar",
|
||||||
|
"List Operations":"Listar Operaciones",
|
||||||
|
"Expand Operations":"Expandir Operaciones",
|
||||||
|
"Raw":"Crudo",
|
||||||
|
"can't parse JSON. Raw result":"no puede parsear el JSON. Resultado crudo",
|
||||||
|
"Example Value":"Valor de Ejemplo",
|
||||||
|
"Model Schema":"Esquema del Modelo",
|
||||||
|
"Model":"Modelo",
|
||||||
|
"apply":"aplicar",
|
||||||
|
"Username":"Nombre de usuario",
|
||||||
|
"Password":"Contraseña",
|
||||||
|
"Terms of service":"Términos de Servicio",
|
||||||
|
"Created by":"Creado por",
|
||||||
|
"See more at":"Ver más en",
|
||||||
|
"Contact the developer":"Contactar al desarrollador",
|
||||||
|
"api version":"versión de la api",
|
||||||
|
"Response Content Type":"Tipo de Contenido (Content Type) de la Respuesta",
|
||||||
|
"fetching resource":"buscando recurso",
|
||||||
|
"fetching resource list":"buscando lista del recurso",
|
||||||
|
"Explore":"Explorar",
|
||||||
|
"Show Swagger Petstore Example Apis":"Mostrar Api Ejemplo de Swagger Petstore",
|
||||||
|
"Can't read from server. It may not have the appropriate access-control-origin settings.":"No se puede leer del servidor. Tal vez no tiene la configuración de control de acceso de origen (access-control-origin) apropiado.",
|
||||||
|
"Please specify the protocol for":"Por favor, especificar el protocola para",
|
||||||
|
"Can't read swagger JSON from":"No se puede leer el JSON de swagger desde",
|
||||||
|
"Finished Loading Resource Information. Rendering Swagger UI":"Finalizada la carga del recurso de Información. Mostrando Swagger UI",
|
||||||
|
"Unable to read api":"No se puede leer la api",
|
||||||
|
"from path":"desde ruta",
|
||||||
|
"server returned":"el servidor retornó"
|
||||||
|
});
|
||||||
54
rswag-ui/vendor/assets/components/swagger-ui/lang/fr.js
vendored
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/* jshint quotmark: double */
|
||||||
|
window.SwaggerTranslator.learn({
|
||||||
|
"Warning: Deprecated":"Avertissement : Obsolète",
|
||||||
|
"Implementation Notes":"Notes d'implémentation",
|
||||||
|
"Response Class":"Classe de la réponse",
|
||||||
|
"Status":"Statut",
|
||||||
|
"Parameters":"Paramètres",
|
||||||
|
"Parameter":"Paramètre",
|
||||||
|
"Value":"Valeur",
|
||||||
|
"Description":"Description",
|
||||||
|
"Parameter Type":"Type du paramètre",
|
||||||
|
"Data Type":"Type de données",
|
||||||
|
"Response Messages":"Messages de la réponse",
|
||||||
|
"HTTP Status Code":"Code de statut HTTP",
|
||||||
|
"Reason":"Raison",
|
||||||
|
"Response Model":"Modèle de réponse",
|
||||||
|
"Request URL":"URL appelée",
|
||||||
|
"Response Body":"Corps de la réponse",
|
||||||
|
"Response Code":"Code de la réponse",
|
||||||
|
"Response Headers":"En-têtes de la réponse",
|
||||||
|
"Hide Response":"Cacher la réponse",
|
||||||
|
"Headers":"En-têtes",
|
||||||
|
"Try it out!":"Testez !",
|
||||||
|
"Show/Hide":"Afficher/Masquer",
|
||||||
|
"List Operations":"Liste des opérations",
|
||||||
|
"Expand Operations":"Développer les opérations",
|
||||||
|
"Raw":"Brut",
|
||||||
|
"can't parse JSON. Raw result":"impossible de décoder le JSON. Résultat brut",
|
||||||
|
"Example Value":"Exemple la valeur",
|
||||||
|
"Model Schema":"Définition du modèle",
|
||||||
|
"Model":"Modèle",
|
||||||
|
"apply":"appliquer",
|
||||||
|
"Username":"Nom d'utilisateur",
|
||||||
|
"Password":"Mot de passe",
|
||||||
|
"Terms of service":"Conditions de service",
|
||||||
|
"Created by":"Créé par",
|
||||||
|
"See more at":"Voir plus sur",
|
||||||
|
"Contact the developer":"Contacter le développeur",
|
||||||
|
"api version":"version de l'api",
|
||||||
|
"Response Content Type":"Content Type de la réponse",
|
||||||
|
"fetching resource":"récupération de la ressource",
|
||||||
|
"fetching resource list":"récupération de la liste de ressources",
|
||||||
|
"Explore":"Explorer",
|
||||||
|
"Show Swagger Petstore Example Apis":"Montrer les Apis de l'exemple Petstore de Swagger",
|
||||||
|
"Can't read from server. It may not have the appropriate access-control-origin settings.":"Impossible de lire à partir du serveur. Il se peut que les réglages access-control-origin ne soient pas appropriés.",
|
||||||
|
"Please specify the protocol for":"Veuillez spécifier un protocole pour",
|
||||||
|
"Can't read swagger JSON from":"Impossible de lire le JSON swagger à partir de",
|
||||||
|
"Finished Loading Resource Information. Rendering Swagger UI":"Chargement des informations terminé. Affichage de Swagger UI",
|
||||||
|
"Unable to read api":"Impossible de lire l'api",
|
||||||
|
"from path":"à partir du chemin",
|
||||||
|
"server returned":"réponse du serveur"
|
||||||
|
});
|
||||||
56
rswag-ui/vendor/assets/components/swagger-ui/lang/geo.js
vendored
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/* jshint quotmark: double */
|
||||||
|
window.SwaggerTranslator.learn({
|
||||||
|
"Warning: Deprecated":"ყურადღება: აღარ გამოიყენება",
|
||||||
|
"Implementation Notes":"იმპლემენტაციის აღწერა",
|
||||||
|
"Response Class":"რესპონს კლასი",
|
||||||
|
"Status":"სტატუსი",
|
||||||
|
"Parameters":"პარამეტრები",
|
||||||
|
"Parameter":"პარამეტრი",
|
||||||
|
"Value":"მნიშვნელობა",
|
||||||
|
"Description":"აღწერა",
|
||||||
|
"Parameter Type":"პარამეტრის ტიპი",
|
||||||
|
"Data Type":"მონაცემის ტიპი",
|
||||||
|
"Response Messages":"პასუხი",
|
||||||
|
"HTTP Status Code":"HTTP სტატუსი",
|
||||||
|
"Reason":"მიზეზი",
|
||||||
|
"Response Model":"რესპონს მოდელი",
|
||||||
|
"Request URL":"მოთხოვნის URL",
|
||||||
|
"Response Body":"პასუხის სხეული",
|
||||||
|
"Response Code":"პასუხის კოდი",
|
||||||
|
"Response Headers":"პასუხის ჰედერები",
|
||||||
|
"Hide Response":"დამალე პასუხი",
|
||||||
|
"Headers":"ჰედერები",
|
||||||
|
"Try it out!":"ცადე !",
|
||||||
|
"Show/Hide":"გამოჩენა/დამალვა",
|
||||||
|
"List Operations":"ოპერაციების სია",
|
||||||
|
"Expand Operations":"ოპერაციები ვრცლად",
|
||||||
|
"Raw":"ნედლი",
|
||||||
|
"can't parse JSON. Raw result":"JSON-ის დამუშავება ვერ მოხერხდა. ნედლი პასუხი",
|
||||||
|
"Example Value":"მაგალითი",
|
||||||
|
"Model Schema":"მოდელის სტრუქტურა",
|
||||||
|
"Model":"მოდელი",
|
||||||
|
"Click to set as parameter value":"პარამეტრისთვის მნიშვნელობის მისანიჭებლად, დააკლიკე",
|
||||||
|
"apply":"გამოყენება",
|
||||||
|
"Username":"მოხმარებელი",
|
||||||
|
"Password":"პაროლი",
|
||||||
|
"Terms of service":"მომსახურების პირობები",
|
||||||
|
"Created by":"შექმნა",
|
||||||
|
"See more at":"ნახე ვრცლად",
|
||||||
|
"Contact the developer":"დაუკავშირდი დეველოპერს",
|
||||||
|
"api version":"api ვერსია",
|
||||||
|
"Response Content Type":"პასუხის კონტენტის ტიპი",
|
||||||
|
"Parameter content type:":"პარამეტრის კონტენტის ტიპი:",
|
||||||
|
"fetching resource":"რესურსების მიღება",
|
||||||
|
"fetching resource list":"რესურსების სიის მიღება",
|
||||||
|
"Explore":"ნახვა",
|
||||||
|
"Show Swagger Petstore Example Apis":"ნახე Swagger Petstore სამაგალითო Api",
|
||||||
|
"Can't read from server. It may not have the appropriate access-control-origin settings.":"სერვერთან დაკავშირება ვერ ხერხდება. შეამოწმეთ access-control-origin.",
|
||||||
|
"Please specify the protocol for":"მიუთითეთ პროტოკოლი",
|
||||||
|
"Can't read swagger JSON from":"swagger JSON წაკითხვა ვერ მოხერხდა",
|
||||||
|
"Finished Loading Resource Information. Rendering Swagger UI":"რესურსების ჩატვირთვა სრულდება. Swagger UI რენდერდება",
|
||||||
|
"Unable to read api":"api წაკითხვა ვერ მოხერხდა",
|
||||||
|
"from path":"მისამართიდან",
|
||||||
|
"server returned":"სერვერმა დააბრუნა"
|
||||||
|
});
|
||||||
52
rswag-ui/vendor/assets/components/swagger-ui/lang/it.js
vendored
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/* jshint quotmark: double */
|
||||||
|
window.SwaggerTranslator.learn({
|
||||||
|
"Warning: Deprecated":"Attenzione: Deprecato",
|
||||||
|
"Implementation Notes":"Note di implementazione",
|
||||||
|
"Response Class":"Classe della risposta",
|
||||||
|
"Status":"Stato",
|
||||||
|
"Parameters":"Parametri",
|
||||||
|
"Parameter":"Parametro",
|
||||||
|
"Value":"Valore",
|
||||||
|
"Description":"Descrizione",
|
||||||
|
"Parameter Type":"Tipo di parametro",
|
||||||
|
"Data Type":"Tipo di dato",
|
||||||
|
"Response Messages":"Messaggi della risposta",
|
||||||
|
"HTTP Status Code":"Codice stato HTTP",
|
||||||
|
"Reason":"Motivo",
|
||||||
|
"Response Model":"Modello di risposta",
|
||||||
|
"Request URL":"URL della richiesta",
|
||||||
|
"Response Body":"Corpo della risposta",
|
||||||
|
"Response Code":"Oggetto della risposta",
|
||||||
|
"Response Headers":"Intestazioni della risposta",
|
||||||
|
"Hide Response":"Nascondi risposta",
|
||||||
|
"Try it out!":"Provalo!",
|
||||||
|
"Show/Hide":"Mostra/Nascondi",
|
||||||
|
"List Operations":"Mostra operazioni",
|
||||||
|
"Expand Operations":"Espandi operazioni",
|
||||||
|
"Raw":"Grezzo (raw)",
|
||||||
|
"can't parse JSON. Raw result":"non è possibile parsare il JSON. Risultato grezzo (raw).",
|
||||||
|
"Model Schema":"Schema del modello",
|
||||||
|
"Model":"Modello",
|
||||||
|
"apply":"applica",
|
||||||
|
"Username":"Nome utente",
|
||||||
|
"Password":"Password",
|
||||||
|
"Terms of service":"Condizioni del servizio",
|
||||||
|
"Created by":"Creato da",
|
||||||
|
"See more at":"Informazioni aggiuntive:",
|
||||||
|
"Contact the developer":"Contatta lo sviluppatore",
|
||||||
|
"api version":"versione api",
|
||||||
|
"Response Content Type":"Tipo di contenuto (content type) della risposta",
|
||||||
|
"fetching resource":"recuperando la risorsa",
|
||||||
|
"fetching resource list":"recuperando lista risorse",
|
||||||
|
"Explore":"Esplora",
|
||||||
|
"Show Swagger Petstore Example Apis":"Mostra le api di esempio di Swagger Petstore",
|
||||||
|
"Can't read from server. It may not have the appropriate access-control-origin settings.":"Non è possibile leggere dal server. Potrebbe non avere le impostazioni di controllo accesso origine (access-control-origin) appropriate.",
|
||||||
|
"Please specify the protocol for":"Si prega di specificare il protocollo per",
|
||||||
|
"Can't read swagger JSON from":"Impossibile leggere JSON swagger da:",
|
||||||
|
"Finished Loading Resource Information. Rendering Swagger UI":"Lettura informazioni risorse termianta. Swagger UI viene mostrata",
|
||||||
|
"Unable to read api":"Impossibile leggere la api",
|
||||||
|
"from path":"da cartella",
|
||||||
|
"server returned":"il server ha restituito"
|
||||||
|
});
|
||||||
53
rswag-ui/vendor/assets/components/swagger-ui/lang/ja.js
vendored
Executable file
@ -0,0 +1,53 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/* jshint quotmark: double */
|
||||||
|
window.SwaggerTranslator.learn({
|
||||||
|
"Warning: Deprecated":"警告: 廃止予定",
|
||||||
|
"Implementation Notes":"実装メモ",
|
||||||
|
"Response Class":"レスポンスクラス",
|
||||||
|
"Status":"ステータス",
|
||||||
|
"Parameters":"パラメータ群",
|
||||||
|
"Parameter":"パラメータ",
|
||||||
|
"Value":"値",
|
||||||
|
"Description":"説明",
|
||||||
|
"Parameter Type":"パラメータタイプ",
|
||||||
|
"Data Type":"データタイプ",
|
||||||
|
"Response Messages":"レスポンスメッセージ",
|
||||||
|
"HTTP Status Code":"HTTPステータスコード",
|
||||||
|
"Reason":"理由",
|
||||||
|
"Response Model":"レスポンスモデル",
|
||||||
|
"Request URL":"リクエストURL",
|
||||||
|
"Response Body":"レスポンスボディ",
|
||||||
|
"Response Code":"レスポンスコード",
|
||||||
|
"Response Headers":"レスポンスヘッダ",
|
||||||
|
"Hide Response":"レスポンスを隠す",
|
||||||
|
"Headers":"ヘッダ",
|
||||||
|
"Try it out!":"実際に実行!",
|
||||||
|
"Show/Hide":"表示/非表示",
|
||||||
|
"List Operations":"操作一覧",
|
||||||
|
"Expand Operations":"操作の展開",
|
||||||
|
"Raw":"Raw",
|
||||||
|
"can't parse JSON. Raw result":"JSONへ解釈できません. 未加工の結果",
|
||||||
|
"Model Schema":"モデルスキーマ",
|
||||||
|
"Model":"モデル",
|
||||||
|
"apply":"実行",
|
||||||
|
"Username":"ユーザ名",
|
||||||
|
"Password":"パスワード",
|
||||||
|
"Terms of service":"サービス利用規約",
|
||||||
|
"Created by":"Created by",
|
||||||
|
"See more at":"See more at",
|
||||||
|
"Contact the developer":"開発者に連絡",
|
||||||
|
"api version":"APIバージョン",
|
||||||
|
"Response Content Type":"レスポンス コンテンツタイプ",
|
||||||
|
"fetching resource":"リソースの取得",
|
||||||
|
"fetching resource list":"リソース一覧の取得",
|
||||||
|
"Explore":"Explore",
|
||||||
|
"Show Swagger Petstore Example Apis":"SwaggerペットストアAPIの表示",
|
||||||
|
"Can't read from server. It may not have the appropriate access-control-origin settings.":"サーバから読み込めません. 適切なaccess-control-origin設定を持っていない可能性があります.",
|
||||||
|
"Please specify the protocol for":"プロトコルを指定してください",
|
||||||
|
"Can't read swagger JSON from":"次からswagger JSONを読み込めません",
|
||||||
|
"Finished Loading Resource Information. Rendering Swagger UI":"リソース情報の読み込みが完了しました. Swagger UIを描画しています",
|
||||||
|
"Unable to read api":"APIを読み込めません",
|
||||||
|
"from path":"次のパスから",
|
||||||
|
"server returned":"サーバからの返答"
|
||||||
|
});
|
||||||
53
rswag-ui/vendor/assets/components/swagger-ui/lang/ko-kr.js
vendored
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/* jshint quotmark: double */
|
||||||
|
window.SwaggerTranslator.learn({
|
||||||
|
"Warning: Deprecated":"경고:폐기예정됨",
|
||||||
|
"Implementation Notes":"구현 노트",
|
||||||
|
"Response Class":"응답 클래스",
|
||||||
|
"Status":"상태",
|
||||||
|
"Parameters":"매개변수들",
|
||||||
|
"Parameter":"매개변수",
|
||||||
|
"Value":"값",
|
||||||
|
"Description":"설명",
|
||||||
|
"Parameter Type":"매개변수 타입",
|
||||||
|
"Data Type":"데이터 타입",
|
||||||
|
"Response Messages":"응답 메세지",
|
||||||
|
"HTTP Status Code":"HTTP 상태 코드",
|
||||||
|
"Reason":"원인",
|
||||||
|
"Response Model":"응답 모델",
|
||||||
|
"Request URL":"요청 URL",
|
||||||
|
"Response Body":"응답 본문",
|
||||||
|
"Response Code":"응답 코드",
|
||||||
|
"Response Headers":"응답 헤더",
|
||||||
|
"Hide Response":"응답 숨기기",
|
||||||
|
"Headers":"헤더",
|
||||||
|
"Try it out!":"써보기!",
|
||||||
|
"Show/Hide":"보이기/숨기기",
|
||||||
|
"List Operations":"목록 작업",
|
||||||
|
"Expand Operations":"전개 작업",
|
||||||
|
"Raw":"원본",
|
||||||
|
"can't parse JSON. Raw result":"JSON을 파싱할수 없음. 원본결과:",
|
||||||
|
"Model Schema":"모델 스키마",
|
||||||
|
"Model":"모델",
|
||||||
|
"apply":"적용",
|
||||||
|
"Username":"사용자 이름",
|
||||||
|
"Password":"암호",
|
||||||
|
"Terms of service":"이용약관",
|
||||||
|
"Created by":"작성자",
|
||||||
|
"See more at":"추가정보:",
|
||||||
|
"Contact the developer":"개발자에게 문의",
|
||||||
|
"api version":"api버전",
|
||||||
|
"Response Content Type":"응답Content Type",
|
||||||
|
"fetching resource":"리소스 가져오기",
|
||||||
|
"fetching resource list":"리소스 목록 가져오기",
|
||||||
|
"Explore":"탐색",
|
||||||
|
"Show Swagger Petstore Example Apis":"Swagger Petstore 예제 보기",
|
||||||
|
"Can't read from server. It may not have the appropriate access-control-origin settings.":"서버로부터 읽어들일수 없습니다. access-control-origin 설정이 올바르지 않을수 있습니다.",
|
||||||
|
"Please specify the protocol for":"다음을 위한 프로토콜을 정하세요",
|
||||||
|
"Can't read swagger JSON from":"swagger JSON 을 다음으로 부터 읽을수 없습니다",
|
||||||
|
"Finished Loading Resource Information. Rendering Swagger UI":"리소스 정보 불러오기 완료. Swagger UI 랜더링",
|
||||||
|
"Unable to read api":"api를 읽을 수 없습니다.",
|
||||||
|
"from path":"다음 경로로 부터",
|
||||||
|
"server returned":"서버 응답함."
|
||||||
|
});
|
||||||
53
rswag-ui/vendor/assets/components/swagger-ui/lang/pl.js
vendored
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/* jshint quotmark: double */
|
||||||
|
window.SwaggerTranslator.learn({
|
||||||
|
"Warning: Deprecated":"Uwaga: Wycofane",
|
||||||
|
"Implementation Notes":"Uwagi Implementacji",
|
||||||
|
"Response Class":"Klasa Odpowiedzi",
|
||||||
|
"Status":"Status",
|
||||||
|
"Parameters":"Parametry",
|
||||||
|
"Parameter":"Parametr",
|
||||||
|
"Value":"Wartość",
|
||||||
|
"Description":"Opis",
|
||||||
|
"Parameter Type":"Typ Parametru",
|
||||||
|
"Data Type":"Typ Danych",
|
||||||
|
"Response Messages":"Wiadomości Odpowiedzi",
|
||||||
|
"HTTP Status Code":"Kod Statusu HTTP",
|
||||||
|
"Reason":"Przyczyna",
|
||||||
|
"Response Model":"Model Odpowiedzi",
|
||||||
|
"Request URL":"URL Wywołania",
|
||||||
|
"Response Body":"Treść Odpowiedzi",
|
||||||
|
"Response Code":"Kod Odpowiedzi",
|
||||||
|
"Response Headers":"Nagłówki Odpowiedzi",
|
||||||
|
"Hide Response":"Ukryj Odpowiedź",
|
||||||
|
"Headers":"Nagłówki",
|
||||||
|
"Try it out!":"Wypróbuj!",
|
||||||
|
"Show/Hide":"Pokaż/Ukryj",
|
||||||
|
"List Operations":"Lista Operacji",
|
||||||
|
"Expand Operations":"Rozwiń Operacje",
|
||||||
|
"Raw":"Nieprzetworzone",
|
||||||
|
"can't parse JSON. Raw result":"nie można przetworzyć pliku JSON. Nieprzetworzone dane",
|
||||||
|
"Model Schema":"Schemat Modelu",
|
||||||
|
"Model":"Model",
|
||||||
|
"apply":"użyj",
|
||||||
|
"Username":"Nazwa użytkownika",
|
||||||
|
"Password":"Hasło",
|
||||||
|
"Terms of service":"Warunki używania",
|
||||||
|
"Created by":"Utworzone przez",
|
||||||
|
"See more at":"Zobacz więcej na",
|
||||||
|
"Contact the developer":"Kontakt z deweloperem",
|
||||||
|
"api version":"wersja api",
|
||||||
|
"Response Content Type":"Typ Zasobu Odpowiedzi",
|
||||||
|
"fetching resource":"ładowanie zasobu",
|
||||||
|
"fetching resource list":"ładowanie listy zasobów",
|
||||||
|
"Explore":"Eksploruj",
|
||||||
|
"Show Swagger Petstore Example Apis":"Pokaż Przykładowe Api Swagger Petstore",
|
||||||
|
"Can't read from server. It may not have the appropriate access-control-origin settings.":"Brak połączenia z serwerem. Może on nie mieć odpowiednich ustawień access-control-origin.",
|
||||||
|
"Please specify the protocol for":"Proszę podać protokół dla",
|
||||||
|
"Can't read swagger JSON from":"Nie można odczytać swagger JSON z",
|
||||||
|
"Finished Loading Resource Information. Rendering Swagger UI":"Ukończono Ładowanie Informacji o Zasobie. Renderowanie Swagger UI",
|
||||||
|
"Unable to read api":"Nie można odczytać api",
|
||||||
|
"from path":"ze ścieżki",
|
||||||
|
"server returned":"serwer zwrócił"
|
||||||
|
});
|
||||||
53
rswag-ui/vendor/assets/components/swagger-ui/lang/pt.js
vendored
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/* jshint quotmark: double */
|
||||||
|
window.SwaggerTranslator.learn({
|
||||||
|
"Warning: Deprecated":"Aviso: Depreciado",
|
||||||
|
"Implementation Notes":"Notas de Implementação",
|
||||||
|
"Response Class":"Classe de resposta",
|
||||||
|
"Status":"Status",
|
||||||
|
"Parameters":"Parâmetros",
|
||||||
|
"Parameter":"Parâmetro",
|
||||||
|
"Value":"Valor",
|
||||||
|
"Description":"Descrição",
|
||||||
|
"Parameter Type":"Tipo de parâmetro",
|
||||||
|
"Data Type":"Tipo de dados",
|
||||||
|
"Response Messages":"Mensagens de resposta",
|
||||||
|
"HTTP Status Code":"Código de status HTTP",
|
||||||
|
"Reason":"Razão",
|
||||||
|
"Response Model":"Modelo resposta",
|
||||||
|
"Request URL":"URL requisição",
|
||||||
|
"Response Body":"Corpo da resposta",
|
||||||
|
"Response Code":"Código da resposta",
|
||||||
|
"Response Headers":"Cabeçalho da resposta",
|
||||||
|
"Headers":"Cabeçalhos",
|
||||||
|
"Hide Response":"Esconder resposta",
|
||||||
|
"Try it out!":"Tente agora!",
|
||||||
|
"Show/Hide":"Mostrar/Esconder",
|
||||||
|
"List Operations":"Listar operações",
|
||||||
|
"Expand Operations":"Expandir operações",
|
||||||
|
"Raw":"Cru",
|
||||||
|
"can't parse JSON. Raw result":"Falha ao analisar JSON. Resulto cru",
|
||||||
|
"Model Schema":"Modelo esquema",
|
||||||
|
"Model":"Modelo",
|
||||||
|
"apply":"Aplicar",
|
||||||
|
"Username":"Usuário",
|
||||||
|
"Password":"Senha",
|
||||||
|
"Terms of service":"Termos do serviço",
|
||||||
|
"Created by":"Criado por",
|
||||||
|
"See more at":"Veja mais em",
|
||||||
|
"Contact the developer":"Contate o desenvolvedor",
|
||||||
|
"api version":"Versão api",
|
||||||
|
"Response Content Type":"Tipo de conteúdo da resposta",
|
||||||
|
"fetching resource":"busca recurso",
|
||||||
|
"fetching resource list":"buscando lista de recursos",
|
||||||
|
"Explore":"Explorar",
|
||||||
|
"Show Swagger Petstore Example Apis":"Show Swagger Petstore Example Apis",
|
||||||
|
"Can't read from server. It may not have the appropriate access-control-origin settings.":"Não é possível ler do servidor. Pode não ter as apropriadas configurações access-control-origin",
|
||||||
|
"Please specify the protocol for":"Por favor especifique o protocolo",
|
||||||
|
"Can't read swagger JSON from":"Não é possível ler o JSON Swagger de",
|
||||||
|
"Finished Loading Resource Information. Rendering Swagger UI":"Carregar informação de recurso finalizada. Renderizando Swagger UI",
|
||||||
|
"Unable to read api":"Não foi possível ler api",
|
||||||
|
"from path":"do caminho",
|
||||||
|
"server returned":"servidor retornou"
|
||||||
|
});
|
||||||
56
rswag-ui/vendor/assets/components/swagger-ui/lang/ru.js
vendored
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/* jshint quotmark: double */
|
||||||
|
window.SwaggerTranslator.learn({
|
||||||
|
"Warning: Deprecated":"Предупреждение: Устарело",
|
||||||
|
"Implementation Notes":"Заметки",
|
||||||
|
"Response Class":"Пример ответа",
|
||||||
|
"Status":"Статус",
|
||||||
|
"Parameters":"Параметры",
|
||||||
|
"Parameter":"Параметр",
|
||||||
|
"Value":"Значение",
|
||||||
|
"Description":"Описание",
|
||||||
|
"Parameter Type":"Тип параметра",
|
||||||
|
"Data Type":"Тип данных",
|
||||||
|
"HTTP Status Code":"HTTP код",
|
||||||
|
"Reason":"Причина",
|
||||||
|
"Response Model":"Структура ответа",
|
||||||
|
"Request URL":"URL запроса",
|
||||||
|
"Response Body":"Тело ответа",
|
||||||
|
"Response Code":"HTTP код ответа",
|
||||||
|
"Response Headers":"Заголовки ответа",
|
||||||
|
"Hide Response":"Спрятать ответ",
|
||||||
|
"Headers":"Заголовки",
|
||||||
|
"Response Messages":"Что может прийти в ответ",
|
||||||
|
"Try it out!":"Попробовать!",
|
||||||
|
"Show/Hide":"Показать/Скрыть",
|
||||||
|
"List Operations":"Операции кратко",
|
||||||
|
"Expand Operations":"Операции подробно",
|
||||||
|
"Raw":"В сыром виде",
|
||||||
|
"can't parse JSON. Raw result":"Не удается распарсить ответ:",
|
||||||
|
"Example Value":"Пример",
|
||||||
|
"Model Schema":"Структура",
|
||||||
|
"Model":"Описание",
|
||||||
|
"Click to set as parameter value":"Нажмите, чтобы испльзовать в качестве значения параметра",
|
||||||
|
"apply":"применить",
|
||||||
|
"Username":"Имя пользователя",
|
||||||
|
"Password":"Пароль",
|
||||||
|
"Terms of service":"Условия использования",
|
||||||
|
"Created by":"Разработано",
|
||||||
|
"See more at":"Еще тут",
|
||||||
|
"Contact the developer":"Связаться с разработчиком",
|
||||||
|
"api version":"Версия API",
|
||||||
|
"Response Content Type":"Content Type ответа",
|
||||||
|
"Parameter content type:":"Content Type параметра:",
|
||||||
|
"fetching resource":"Получение ресурса",
|
||||||
|
"fetching resource list":"Получение ресурсов",
|
||||||
|
"Explore":"Показать",
|
||||||
|
"Show Swagger Petstore Example Apis":"Показать примеры АПИ",
|
||||||
|
"Can't read from server. It may not have the appropriate access-control-origin settings.":"Не удается получить ответ от сервера. Возможно, проблема с настройками доступа",
|
||||||
|
"Please specify the protocol for":"Пожалуйста, укажите протокол для",
|
||||||
|
"Can't read swagger JSON from":"Не получается прочитать swagger json из",
|
||||||
|
"Finished Loading Resource Information. Rendering Swagger UI":"Загрузка информации о ресурсах завершена. Рендерим",
|
||||||
|
"Unable to read api":"Не удалось прочитать api",
|
||||||
|
"from path":"по адресу",
|
||||||
|
"server returned":"сервер сказал"
|
||||||
|
});
|
||||||
53
rswag-ui/vendor/assets/components/swagger-ui/lang/tr.js
vendored
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/* jshint quotmark: double */
|
||||||
|
window.SwaggerTranslator.learn({
|
||||||
|
"Warning: Deprecated":"Uyarı: Deprecated",
|
||||||
|
"Implementation Notes":"Gerçekleştirim Notları",
|
||||||
|
"Response Class":"Dönen Sınıf",
|
||||||
|
"Status":"Statü",
|
||||||
|
"Parameters":"Parametreler",
|
||||||
|
"Parameter":"Parametre",
|
||||||
|
"Value":"Değer",
|
||||||
|
"Description":"Açıklama",
|
||||||
|
"Parameter Type":"Parametre Tipi",
|
||||||
|
"Data Type":"Veri Tipi",
|
||||||
|
"Response Messages":"Dönüş Mesajı",
|
||||||
|
"HTTP Status Code":"HTTP Statü Kodu",
|
||||||
|
"Reason":"Gerekçe",
|
||||||
|
"Response Model":"Dönüş Modeli",
|
||||||
|
"Request URL":"İstek URL",
|
||||||
|
"Response Body":"Dönüş İçeriği",
|
||||||
|
"Response Code":"Dönüş Kodu",
|
||||||
|
"Response Headers":"Dönüş Üst Bilgileri",
|
||||||
|
"Hide Response":"Dönüşü Gizle",
|
||||||
|
"Headers":"Üst Bilgiler",
|
||||||
|
"Try it out!":"Dene!",
|
||||||
|
"Show/Hide":"Göster/Gizle",
|
||||||
|
"List Operations":"Operasyonları Listele",
|
||||||
|
"Expand Operations":"Operasyonları Aç",
|
||||||
|
"Raw":"Ham",
|
||||||
|
"can't parse JSON. Raw result":"JSON çözümlenemiyor. Ham sonuç",
|
||||||
|
"Model Schema":"Model Şema",
|
||||||
|
"Model":"Model",
|
||||||
|
"apply":"uygula",
|
||||||
|
"Username":"Kullanıcı Adı",
|
||||||
|
"Password":"Parola",
|
||||||
|
"Terms of service":"Servis şartları",
|
||||||
|
"Created by":"Oluşturan",
|
||||||
|
"See more at":"Daha fazlası için",
|
||||||
|
"Contact the developer":"Geliştirici ile İletişime Geçin",
|
||||||
|
"api version":"api versiyon",
|
||||||
|
"Response Content Type":"Dönüş İçerik Tipi",
|
||||||
|
"fetching resource":"kaynak getiriliyor",
|
||||||
|
"fetching resource list":"kaynak listesi getiriliyor",
|
||||||
|
"Explore":"Keşfet",
|
||||||
|
"Show Swagger Petstore Example Apis":"Swagger Petstore Örnek Api'yi Gör",
|
||||||
|
"Can't read from server. It may not have the appropriate access-control-origin settings.":"Sunucudan okuma yapılamıyor. Sunucu access-control-origin ayarlarınızı kontrol edin.",
|
||||||
|
"Please specify the protocol for":"Lütfen istenen adres için protokol belirtiniz",
|
||||||
|
"Can't read swagger JSON from":"Swagger JSON bu kaynaktan okunamıyor",
|
||||||
|
"Finished Loading Resource Information. Rendering Swagger UI":"Kaynak baglantısı tamamlandı. Swagger UI gösterime hazırlanıyor",
|
||||||
|
"Unable to read api":"api okunamadı",
|
||||||
|
"from path":"yoldan",
|
||||||
|
"server returned":"sunucuya dönüldü"
|
||||||
|
});
|
||||||
39
rswag-ui/vendor/assets/components/swagger-ui/lang/translator.js
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translator for documentation pages.
|
||||||
|
*
|
||||||
|
* To enable translation you should include one of language-files in your index.html
|
||||||
|
* after <script src='lang/translator.js' type='text/javascript'></script>.
|
||||||
|
* For example - <script src='lang/ru.js' type='text/javascript'></script>
|
||||||
|
*
|
||||||
|
* If you wish to translate some new texts you should do two things:
|
||||||
|
* 1. Add a new phrase pair ("New Phrase": "New Translation") into your language file (for example lang/ru.js). It will be great if you add it in other language files too.
|
||||||
|
* 2. Mark that text it templates this way <anyHtmlTag data-sw-translate>New Phrase</anyHtmlTag> or <anyHtmlTag data-sw-translate value='New Phrase'/>.
|
||||||
|
* The main thing here is attribute data-sw-translate. Only inner html, title-attribute and value-attribute are going to translate.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
window.SwaggerTranslator = {
|
||||||
|
|
||||||
|
_words:[],
|
||||||
|
|
||||||
|
translate: function(sel) {
|
||||||
|
var $this = this;
|
||||||
|
sel = sel || '[data-sw-translate]';
|
||||||
|
|
||||||
|
$(sel).each(function() {
|
||||||
|
$(this).html($this._tryTranslate($(this).html()));
|
||||||
|
|
||||||
|
$(this).val($this._tryTranslate($(this).val()));
|
||||||
|
$(this).attr('title', $this._tryTranslate($(this).attr('title')));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
_tryTranslate: function(word) {
|
||||||
|
return this._words[$.trim(word)] !== undefined ? this._words[$.trim(word)] : word;
|
||||||
|
},
|
||||||
|
|
||||||
|
learn: function(wordsMap) {
|
||||||
|
this._words = wordsMap;
|
||||||
|
}
|
||||||
|
};
|
||||||
53
rswag-ui/vendor/assets/components/swagger-ui/lang/zh-cn.js
vendored
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/* jshint quotmark: double */
|
||||||
|
window.SwaggerTranslator.learn({
|
||||||
|
"Warning: Deprecated":"警告:已过时",
|
||||||
|
"Implementation Notes":"实现备注",
|
||||||
|
"Response Class":"响应类",
|
||||||
|
"Status":"状态",
|
||||||
|
"Parameters":"参数",
|
||||||
|
"Parameter":"参数",
|
||||||
|
"Value":"值",
|
||||||
|
"Description":"描述",
|
||||||
|
"Parameter Type":"参数类型",
|
||||||
|
"Data Type":"数据类型",
|
||||||
|
"Response Messages":"响应消息",
|
||||||
|
"HTTP Status Code":"HTTP状态码",
|
||||||
|
"Reason":"原因",
|
||||||
|
"Response Model":"响应模型",
|
||||||
|
"Request URL":"请求URL",
|
||||||
|
"Response Body":"响应体",
|
||||||
|
"Response Code":"响应码",
|
||||||
|
"Response Headers":"响应头",
|
||||||
|
"Hide Response":"隐藏响应",
|
||||||
|
"Headers":"头",
|
||||||
|
"Try it out!":"试一下!",
|
||||||
|
"Show/Hide":"显示/隐藏",
|
||||||
|
"List Operations":"显示操作",
|
||||||
|
"Expand Operations":"展开操作",
|
||||||
|
"Raw":"原始",
|
||||||
|
"can't parse JSON. Raw result":"无法解析JSON. 原始结果",
|
||||||
|
"Model Schema":"模型架构",
|
||||||
|
"Model":"模型",
|
||||||
|
"apply":"应用",
|
||||||
|
"Username":"用户名",
|
||||||
|
"Password":"密码",
|
||||||
|
"Terms of service":"服务条款",
|
||||||
|
"Created by":"创建者",
|
||||||
|
"See more at":"查看更多:",
|
||||||
|
"Contact the developer":"联系开发者",
|
||||||
|
"api version":"api版本",
|
||||||
|
"Response Content Type":"响应Content Type",
|
||||||
|
"fetching resource":"正在获取资源",
|
||||||
|
"fetching resource list":"正在获取资源列表",
|
||||||
|
"Explore":"浏览",
|
||||||
|
"Show Swagger Petstore Example Apis":"显示 Swagger Petstore 示例 Apis",
|
||||||
|
"Can't read from server. It may not have the appropriate access-control-origin settings.":"无法从服务器读取。可能没有正确设置access-control-origin。",
|
||||||
|
"Please specify the protocol for":"请指定协议:",
|
||||||
|
"Can't read swagger JSON from":"无法读取swagger JSON于",
|
||||||
|
"Finished Loading Resource Information. Rendering Swagger UI":"已加载资源信息。正在渲染Swagger UI",
|
||||||
|
"Unable to read api":"无法读取api",
|
||||||
|
"from path":"从路径",
|
||||||
|
"server returned":"服务器返回"
|
||||||
|
});
|
||||||