Skip to content

Commit

Permalink
Merge pull request #6 from drewish/rename-rspec-rails-swagger
Browse files Browse the repository at this point in the history
Rename to rspec-rails-swagger
  • Loading branch information
drewish authored Sep 26, 2016
2 parents c6b2d18 + 5e1f415 commit e1eb984
Show file tree
Hide file tree
Showing 25 changed files with 583 additions and 569 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# RSpec Swagger

[![Build Status](https://travis-ci.org/drewish/rspec-swagger.svg?branch=master)](https://travis-ci.org/drewish/rspec-swagger)
[![Code Climate](https://codeclimate.com/github/drewish/rspec-swagger/badges/gpa.svg)](https://codeclimate.com/github/drewish/rspec-swagger)
[![Build Status](https://travis-ci.org/drewish/rspec-rails-swagger.svg?branch=master)](https://travis-ci.org/drewish/rspec-rails-swagger)
[![Code Climate](https://codeclimate.com/github/drewish/rspec-rails-swagger/badges/gpa.svg)](https://codeclimate.com/github/drewish/rspec-rails-swagger)

This gem helps you generate Swagger docs by using RSpec to document the paths.
You execute a command to run the tests and generate the `.json` output. Running
Expand All @@ -15,15 +15,15 @@ The design of this was heavily influenced by the awesome [swagger_rails gem](htt
- Add the gem to your Rails app's `Gemfile`:
```rb
group :development, :test do
gem 'rspec-swagger'
gem 'rspec-rails-swagger'
end
```
- If you don't already have a `spec/rails_helper.rb` file run:
```shell
rails generate rspec:install
```
- Create `spec/swagger_helper.rb` file (eventually [this will become a
generator](https://github.com/drewish/rspec-swagger/issues/3)):
generator](https://github.com/drewish/rspec-rails-swagger/issues/3)):
```rb
require 'rspec/swagger'
require 'rails_helper'
Expand Down Expand Up @@ -55,7 +55,7 @@ end

## Generate the docs

Eventually [this will become a rake task](https://github.com/drewish/rspec-swagger/issues/2):
Eventually [this will become a rake task](https://github.com/drewish/rspec-rails-swagger/issues/2):
```
bundle exec rspec -f RSpec::Swagger::Formatter --order defined -t swagger_object
```
Expand Down
16 changes: 16 additions & 0 deletions lib/rspec/rails/swagger.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
require 'rspec/core'
require 'rspec/rails/swagger/configuration'
require 'rspec/rails/swagger/document'
require 'rspec/rails/swagger/formatter'
require 'rspec/rails/swagger/helpers'
require 'rspec/rails/swagger/request_builder'
require 'rspec/rails/swagger/version'

module RSpec
module Rails
module Swagger
initialize_configuration RSpec.configuration
end
end
end

16 changes: 16 additions & 0 deletions lib/rspec/rails/swagger/configuration.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module RSpec
module Rails
module Swagger
# Fake class to document RSpec Swagger configuration options.
class Configuration
end

def self.initialize_configuration(config)
config.add_setting :swagger_root
config.add_setting :swagger_docs, default: {}

Helpers.add_swagger_type_configurations(config)
end
end
end
end
32 changes: 32 additions & 0 deletions lib/rspec/rails/swagger/document.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
module RSpec
module Rails
module Swagger
class Document
attr_accessor :data

def initialize(data)
@data = data.deep_symbolize_keys
end

def [](value)
data[value]
end

def resolve_ref(ref)
unless %r{#/(?<location>parameters|definitions)/(?<name>.+)} =~ ref
raise ArgumentError, "Invalid reference: #{ref}"
end

result = data.fetch(location.to_sym, {})[name.to_sym]
raise ArgumentError, "Reference value does not exist: #{ref}" unless result

if location == 'parameters'
result.merge(name: name)
end

result
end
end
end
end
end
105 changes: 105 additions & 0 deletions lib/rspec/rails/swagger/formatter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
require 'rspec/core/formatters/base_text_formatter'

module RSpec
module Rails
module Swagger
class Formatter < RSpec::Core::Formatters::BaseTextFormatter
RSpec::Core::Formatters.register self, :example_finished, :close

def documents
# We don't try to load the docs in `initalize` because when running
# `rspec -f RSpec::Swagger::Formatter` RSpec initalized this class
# before `swagger_helper` has run.
@documents ||= ::RSpec.configuration.swagger_docs
end

def example_finished(notification)
metadata = notification.example.metadata
return unless metadata[:swagger_object] == :response

# metadata.each do |k, v|
# puts "#{k}\t#{v}" if k.to_s.starts_with?("swagger")
# end

document = document_for(metadata[:swagger_document])
path_item = path_item_for(document, metadata[:swagger_path_item])
operation = operation_for(path_item, metadata[:swagger_operation])
response_for(operation, metadata[:swagger_response])
end

def close(_notification)
documents.each{|k, v| write_json(k, v)}
end

def write_json(name, document)
root = ::RSpec.configuration.swagger_root
# It would be good to at least warn if the name includes some '../' that
# takes it out of root directory.
target = Pathname(name).expand_path(root)
target.dirname.mkpath
target.write(JSON.pretty_generate(document))
end

def document_for(doc_name = nil)
if doc_name
documents.fetch(doc_name)
else
documents.values.first
end
end

def path_item_for(document, swagger_path_item)
name = swagger_path_item[:path]

document[:paths] ||= {}
document[:paths][name] ||= {}
if swagger_path_item[:parameters]
document[:paths][name][:parameters] = prepare_parameters(swagger_path_item[:parameters])
end
document[:paths][name]
end

def operation_for(path, swagger_operation)
method = swagger_operation[:method]

path[method] ||= {responses: {}}
path[method].tap do |operation|
if swagger_operation[:parameters]
operation[:parameters] = prepare_parameters(swagger_operation[:parameters])
end
operation.merge!(swagger_operation.slice(
:summary, :description, :externalDocs, :operationId,
:consumes, :produces, :schemes, :deprecated, :security
))
end
end

def response_for(operation, swagger_response)
status = swagger_response[:status_code]

operation[:responses][status] ||= {}
operation[:responses][status].tap do |response|
if swagger_response[:examples]
response[:examples] = prepare_examples(swagger_response[:examples])
end
response.merge!(swagger_response.slice(:description, :schema, :headers))
end
end

def prepare_parameters(params)
params.values
end

def prepare_examples(examples)
if examples["application/json"].present?
begin
examples["application/json"] = JSON.parse(examples["application/json"])
rescue JSON::ParserError
end
end
examples
end
end
end
end
end
Loading

0 comments on commit e1eb984

Please sign in to comment.