Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support YAML output #37

Merged
merged 2 commits into from
May 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
language: ruby
rvm:
- 2.2.5
- 2.2
- 2.3
- 2.4
- 2.5
env:
- "RAILS_VERSION=3.2.0"
- "RAILS_VERSION=4.2.0"
- "RAILS_VERSION=5.0.0"
- RAILS_VERSION=3.2.0
- RAILS_VERSION=4.2.0
- RAILS_VERSION=5.1.0
cache: bundler
install: ./make_site.sh
script: bundle exec rspec
matrix:
exclude:
- rvm: 2.4
env: RAILS_VERSION=3.2.0
- rvm: 2.5
env: RAILS_VERSION=3.2.0
30 changes: 25 additions & 5 deletions lib/rspec/rails/swagger/formatter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def example_finished(notification)
end

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

self
end
Expand All @@ -70,13 +70,33 @@ def example_output(notification)
" #{notification.example.metadata[:swagger_response][:status_code]}"
end

def write_json(name, document)
root = ::RSpec.configuration.swagger_root
def write_file(name, document)
output =
if %w(.yaml .yml).include? File.extname(name)
YAML.dump(deep_stringify_keys(document))
else
JSON.pretty_generate(document) + "\n"
end

# 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 = Pathname(name).expand_path(::RSpec.configuration.swagger_root)
target.dirname.mkpath
target.write(JSON.pretty_generate(document))
target.write(output)
end

# Lifted from ActiveSupport's Hash _deep_transform_keys_in_object
def deep_stringify_keys(object)
case object
when Hash
object.each_with_object({}) do |(key, value), result|
result[key.to_s] = deep_stringify_keys(value)
end
when Array
object.map { |e| deep_stringify_keys(e) }
else
object
end
end

def document_for(doc_name = nil)
Expand Down
79 changes: 73 additions & 6 deletions spec/rspec/rails/swagger/formatter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ def minimal
context "with a default formatter" do
before(:example) do
RSpec::Rails::Swagger::ResponseFormatters.register(
'application/json',
RSpec::Rails::Swagger::ResponseFormatters::JSON.new
'application/json',
RSpec::Rails::Swagger::ResponseFormatters::JSON.new
)
end

Expand All @@ -119,7 +119,7 @@ def minimal

context "no relevant examples" do
it "writes document with no changes" do
expect(formatter).to receive(:write_json).with(documents.keys.first, documents.values.first)
expect(formatter).to receive(:write_file).with(documents.keys.first, documents.values.first)
formatter.close(blank_notification)
end
end
Expand All @@ -130,21 +130,22 @@ def minimal
{
swagger_object: :response,
swagger_path_item: {path: "/ping"},
swagger_operation: {method: :get},
swagger_operation: {method: :get, produces: ["application/json"]},
swagger_response: {status_code: 200, description: 'all good'},
}
end

it "writes a document with the request" do
formatter.example_finished(example_notification)

expect(formatter).to receive(:write_json).with(
expect(formatter).to receive(:write_file).with(
documents.keys.first,
documents.values.first.merge({
paths: {
'/ping' => {
get: {
responses: {200 => {description: 'all good'}}
responses: {200 => {description: 'all good'}},
produces: ["application/json"]
}
}
}
Expand All @@ -153,6 +154,72 @@ def minimal

formatter.close(blank_notification)
end

describe 'output formats' do
let(:documents) { {file_name => minimal} }

subject do
formatter.example_finished(example_notification)
formatter.close(blank_notification)
Pathname(file_name).expand_path(::RSpec.configuration.swagger_root).read
end

%w(yaml yml).each do |extension|
context "with a name that ends in .#{extension}" do
let(:file_name) { "minimal.#{extension}" }

it 'outputs YAML' do
expect(subject).to eq <<YAML
---
swagger: '2.0'
info:
version: 0.0.0
title: Simple API
paths:
"/ping":
get:
responses:
'200':
description: all good
produces:
- application/json
YAML
end
end
end

%w(json txt).each do |extension|
context "with a name that ends in .#{extension}" do
let(:file_name) { "minimal.#{extension}" }

it 'outputs JSON' do
expect(subject).to eq <<JSON
{
"swagger": "2.0",
"info": {
"version": "0.0.0",
"title": "Simple API"
},
"paths": {
"/ping": {
"get": {
"responses": {
"200": {
"description": "all good"
}
},
"produces": [
"application/json"
]
}
}
}
}
JSON
end
end
end
end
end
end
end
13 changes: 10 additions & 3 deletions spec/swagger_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,18 @@

# Define one or more Swagger documents and global metadata for each.
#
# When you run the "swaggerize" rake task, the complete Swagger will be
# When you run the "swagger" rake task, the complete Swagger will be
# generated at the provided relative path under `swagger_root`
#
# If the file name ends with .yml or .yaml the contents will be YAML,
# otherwise the file will be JSON.
#
# 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
# the root example_group in your specs, e.g. describe '...', swagger_doc: 'v2/swagger.json'
# 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'
#
config.swagger_docs = {
'v1/swagger.json' => {
swagger: '2.0',
Expand Down