Skip to content

Commit 56a2280

Browse files
authored
Merge pull request #37 from drewish/support-yaml
Support YAML output
2 parents 89a8130 + 215f3b7 commit 56a2280

File tree

4 files changed

+121
-18
lines changed

4 files changed

+121
-18
lines changed

.travis.yml

+13-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
11
language: ruby
22
rvm:
3-
- 2.2.5
3+
- 2.2
4+
- 2.3
5+
- 2.4
6+
- 2.5
47
env:
5-
- "RAILS_VERSION=3.2.0"
6-
- "RAILS_VERSION=4.2.0"
7-
- "RAILS_VERSION=5.0.0"
8+
- RAILS_VERSION=3.2.0
9+
- RAILS_VERSION=4.2.0
10+
- RAILS_VERSION=5.1.0
811
cache: bundler
912
install: ./make_site.sh
1013
script: bundle exec rspec
14+
matrix:
15+
exclude:
16+
- rvm: 2.4
17+
env: RAILS_VERSION=3.2.0
18+
- rvm: 2.5
19+
env: RAILS_VERSION=3.2.0

lib/rspec/rails/swagger/formatter.rb

+25-5
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def example_finished(notification)
4444
end
4545

4646
def close(_notification)
47-
documents.each{|k, v| write_json(k, v)}
47+
documents.each{|k, v| write_file(k, v)}
4848

4949
self
5050
end
@@ -70,13 +70,33 @@ def example_output(notification)
7070
" #{notification.example.metadata[:swagger_response][:status_code]}"
7171
end
7272

73-
def write_json(name, document)
74-
root = ::RSpec.configuration.swagger_root
73+
def write_file(name, document)
74+
output =
75+
if %w(.yaml .yml).include? File.extname(name)
76+
YAML.dump(deep_stringify_keys(document))
77+
else
78+
JSON.pretty_generate(document) + "\n"
79+
end
80+
7581
# It would be good to at least warn if the name includes some '../' that
7682
# takes it out of root directory.
77-
target = Pathname(name).expand_path(root)
83+
target = Pathname(name).expand_path(::RSpec.configuration.swagger_root)
7884
target.dirname.mkpath
79-
target.write(JSON.pretty_generate(document))
85+
target.write(output)
86+
end
87+
88+
# Lifted from ActiveSupport's Hash _deep_transform_keys_in_object
89+
def deep_stringify_keys(object)
90+
case object
91+
when Hash
92+
object.each_with_object({}) do |(key, value), result|
93+
result[key.to_s] = deep_stringify_keys(value)
94+
end
95+
when Array
96+
object.map { |e| deep_stringify_keys(e) }
97+
else
98+
object
99+
end
80100
end
81101

82102
def document_for(doc_name = nil)

spec/rspec/rails/swagger/formatter_spec.rb

+73-6
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,8 @@ def minimal
9494
context "with a default formatter" do
9595
before(:example) do
9696
RSpec::Rails::Swagger::ResponseFormatters.register(
97-
'application/json',
98-
RSpec::Rails::Swagger::ResponseFormatters::JSON.new
97+
'application/json',
98+
RSpec::Rails::Swagger::ResponseFormatters::JSON.new
9999
)
100100
end
101101

@@ -119,7 +119,7 @@ def minimal
119119

120120
context "no relevant examples" do
121121
it "writes document with no changes" do
122-
expect(formatter).to receive(:write_json).with(documents.keys.first, documents.values.first)
122+
expect(formatter).to receive(:write_file).with(documents.keys.first, documents.values.first)
123123
formatter.close(blank_notification)
124124
end
125125
end
@@ -130,21 +130,22 @@ def minimal
130130
{
131131
swagger_object: :response,
132132
swagger_path_item: {path: "/ping"},
133-
swagger_operation: {method: :get},
133+
swagger_operation: {method: :get, produces: ["application/json"]},
134134
swagger_response: {status_code: 200, description: 'all good'},
135135
}
136136
end
137137

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

141-
expect(formatter).to receive(:write_json).with(
141+
expect(formatter).to receive(:write_file).with(
142142
documents.keys.first,
143143
documents.values.first.merge({
144144
paths: {
145145
'/ping' => {
146146
get: {
147-
responses: {200 => {description: 'all good'}}
147+
responses: {200 => {description: 'all good'}},
148+
produces: ["application/json"]
148149
}
149150
}
150151
}
@@ -153,6 +154,72 @@ def minimal
153154

154155
formatter.close(blank_notification)
155156
end
157+
158+
describe 'output formats' do
159+
let(:documents) { {file_name => minimal} }
160+
161+
subject do
162+
formatter.example_finished(example_notification)
163+
formatter.close(blank_notification)
164+
Pathname(file_name).expand_path(::RSpec.configuration.swagger_root).read
165+
end
166+
167+
%w(yaml yml).each do |extension|
168+
context "with a name that ends in .#{extension}" do
169+
let(:file_name) { "minimal.#{extension}" }
170+
171+
it 'outputs YAML' do
172+
expect(subject).to eq <<YAML
173+
---
174+
swagger: '2.0'
175+
info:
176+
version: 0.0.0
177+
title: Simple API
178+
paths:
179+
"/ping":
180+
get:
181+
responses:
182+
'200':
183+
description: all good
184+
produces:
185+
- application/json
186+
YAML
187+
end
188+
end
189+
end
190+
191+
%w(json txt).each do |extension|
192+
context "with a name that ends in .#{extension}" do
193+
let(:file_name) { "minimal.#{extension}" }
194+
195+
it 'outputs JSON' do
196+
expect(subject).to eq <<JSON
197+
{
198+
"swagger": "2.0",
199+
"info": {
200+
"version": "0.0.0",
201+
"title": "Simple API"
202+
},
203+
"paths": {
204+
"/ping": {
205+
"get": {
206+
"responses": {
207+
"200": {
208+
"description": "all good"
209+
}
210+
},
211+
"produces": [
212+
"application/json"
213+
]
214+
}
215+
}
216+
}
217+
}
218+
JSON
219+
end
220+
end
221+
end
222+
end
156223
end
157224
end
158225
end

spec/swagger_helper.rb

+10-3
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,18 @@
77

88
# Define one or more Swagger documents and global metadata for each.
99
#
10-
# When you run the "swaggerize" rake task, the complete Swagger will be
10+
# When you run the "swagger" rake task, the complete Swagger will be
1111
# generated at the provided relative path under `swagger_root`
12+
#
13+
# If the file name ends with .yml or .yaml the contents will be YAML,
14+
# otherwise the file will be JSON.
15+
#
1216
# By default, the operations defined in spec files are added to the first
13-
# document below. You can override this behavior by adding a swagger_doc tag to the
14-
# the root example_group in your specs, e.g. describe '...', swagger_doc: 'v2/swagger.json'
17+
# document below. You can override this behavior by adding a `swagger_doc` tag
18+
# to the the root example_group in your specs, e.g.
19+
#
20+
# describe '...', swagger_doc: 'v2/swagger.json'
21+
#
1522
config.swagger_docs = {
1623
'v1/swagger.json' => {
1724
swagger: '2.0',

0 commit comments

Comments
 (0)