rspec-api-docs
Generate API documentation using RSpec
rspec-api-docs provides a way to generate documentation from your request specs. It does this by providing a simple DSL and a custom formatter.
The default renderer produces a single JSON file which can be used by api-docs to display your documentation.
Installation
Add this line to your application's Gemfile:
gem 'rspec-api-docs'
And then execute:
$ bundle
Or install it yourself as:
$ gem install rspec-api-docs
Usage
rspec-api-docs works in two stages. The first stage introduces a new DSL
method, doc
, to include in your RSpec specs.
require 'rspec_api_docs/dsl'
RSpec.describe 'Characters' do
include RspecApiDocs::Dsl
# ...
end
The doc
method stores data in a hash on the RSpec example metadata.
The second stage is the formatter (RspecApiDocs::Formatter
). The formatter
parses the hash stored on each RSpec example and uses a
renderer to write out your
documentation.
$ rspec spec/requests/characters_spec.rb --formatter=RspecApiDocs::Formatter
DSL
First, require the DSL and include the DSL module.
You can do this in your spec_helper.rb
:
require 'rspec_api_docs/dsl'
RSpec.configure do |config|
config.include RspecApiDocs::Dsl, type: :request
# ...
end
Or in individual specs:
require 'rspec_api_docs/dsl'
RSpec.describe 'Characters' do
include RspecApiDocs::Dsl
# ...
end
You also need to require a lambda that runs after each expectation:
require 'rspec_api_docs/after'
RSpec.configure do |config|
config.after &RspecApiDocs::After::Hook
end
This automatically stores the last_request
and last_response
objects for
use by the formatter.
rspec-api-docs doesn't touch any of the built-in RSpec DSL methods.
Everything is contained in the doc
block.
You can use RSpec before
blocks to share setup between multiple examples.
require 'rspec_api_docs/dsl'
RSpec.describe 'Characters' do
include RspecApiDocs::Dsl
before do
doc do
resource_name 'Characters'
resource_description " Characters inhabit the Land of Ooo.\n EOF\n end\n end\n\n describe 'GET /characters/:id' do\n it 'returns a character' do\n doc do\n name 'Fetching a Character'\n description 'For getting information about a Character.'\n path '/characters/:id'\n\n field :id, 'The id of a character', scope: :character, type: 'integer'\n field :name, \"The character's name\", scope: :character, type: 'string'\n end\n\n get '/characters/1'\n\n # normal expectations ...\n end\n\n # ...\n end\nend\n"
resource_name
Accepts a string of the name of the resource.
Characters
resource_description
Accepts a string that describes the resource.
Characters inhabit the Land of Ooo.
resource_precedence
Accepts an optional integer.
Lower numbers are ordered first.
name
Accepts a string of the name of the resource.
Fetching a character
Note: This defaults to the "description" of the RSpec example.
it 'Fetching a character' do
# ...
end
description
Accepts a string that describes the example.
To find out information about a Character.
path
Accepts a string for the path requested in the example.
/characters/:id
Note: This defaults to the path of the first route requested in the example.
field
Accepts a name
, description
, and optionally a scope
, type
, and example
.
name
[Symbol
] the name of the response fielddescription
[String
] a description of the response fieldscope
[Symbol
,Array<Symbol>
] (optional) how the field is scopedtype
[String
] (optional) the type of the returned fieldexample
(optional) an example value
This can be called multiple times for each response field.
field :id, 'The id of a character', scope: :character, type: 'integer', example: 42
field :name, "The character's name", scope: :character, type: 'string'
The example
is useful if the data might change (i.e. a database ID column).
The value will be substituted in the resulting JSON.
param
Accepts a name
, description
, and optionally a scope
, type
, and required
flag.
name
[Symbol
] the name of the parameterdescription
[Symbol
] a description of the parameterscope
[Symbol
,Array<Symbol>
] (optional) how the parameter is scopedtype
[String
] (optional) the type of the parameterrequired
[Boolean
] (optional) if the parameter is required
This can be called multiple times for each parameter.
param :id, 'The id of a character', scope: :character, type: 'integer', required: true
param :name, "The character's name", scope: :character, type: 'string'
note
Accepts a note
and optional level
.
level
[Symbol
] one of:success
,:info
,:warning
, or:danger
. Defaults to:info
note
[String
] the note
note 'You need to supply an id!'
note :warning, "An error will be thrown if you don't supply an id!"
precedence
Accepts an optional integer.
Lower numbers are ordered first.
See the integration specs for more examples of the DSL in use.
Formatter
The formatter can be configured in your spec_helper.rb
:
# Defaults are shown
RspecApiDocs.configure do |config|
# The output directory for file(s) created by the renderer.
config.output_dir = 'docs'
# One of :json, :raddocs, or :slate.
# This can also be a class that quacks like a renderer.
# A renderer is initialized with an array of `Resource`s and a `#render`
# method is called.
config.renderer = :json
# Set to false if you don't want to validate params are documented and their
# types in the after block.
config.validate_params = true
end
See the documentation.
Rake tasks
require 'rspec_api_docs/rake_task'
RspecApiDocs::Rake.new do |task| # docs:generate
# Pattern for where to find the specs
task.pattern = 'spec/requests/**/*_spec.rb'
# Extra RSpec options
task.rspec_opts = ['--format progress']
end
RspecApiDocs::Rake.new do |task| # docs:ensure_updated
# Same as options above with some extras for when verify is true
# Raise an error if the generated docs don't match the existing docs
# The verify option only works with the :json renderer.
task.verify = true
# The existing (committed) output file
task.existing_file = 'docs/index.json'
end
# Non-verify task with custom name
RspecApiDocs::Rake.new :custom_task_name
Development
After checking out the repo, run bin/setup
to install dependencies. Then, run
rake
to run the tests.
To install this gem onto your local machine, run bundle exec rake install
. To
release a new version, update the version number in version.rb
, and then run
bundle exec rake release
, which will create a git tag for the version, push
git commits and tags, and push the .gem
file to rubygems.org.
Regenerate this project's integration spec docs locally:
$ ./bin/generate_integration_docs
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/twe4ked/rspec-api-docs. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
License
The gem is available as open source under the terms of the MIT License.