Skip to content

Commit

Permalink
Merge pull request #45 from drewish/overide-doc
Browse files Browse the repository at this point in the history
Standardize on swagger_doc naming
  • Loading branch information
drewish committed Apr 5, 2019
2 parents 672cdd4 + fd643be commit aba8588
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 67 deletions.
56 changes: 44 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ rails generate rspec:swagger_install
## Documenting Your API

Now you can edit `spec/swagger_helper.rb` and start filling in the top level
Swagger documention, e.g. basePath, [definitions](http://swagger.io/specification/#definitionsObject),
Swagger documentation, e.g. basePath, [definitions](http://swagger.io/specification/#definitionsObject),
[parameters](http://swagger.io/specification/#parametersDefinitionsObject),
[tags](http://swagger.io/specification/#tagObject), etc.

Expand Down Expand Up @@ -66,7 +66,7 @@ works pretty well and supports multiple documents.

## RSpec DSL

The DSL follows the hierachy of the Swagger Schema:
The DSL follows the hierarchy of the Swagger Schema:

- [Paths Object](http://swagger.io/specification/#paths-object-29)
- [Path Item Object](http://swagger.io/specification/#path-item-object-32)
Expand Down Expand Up @@ -98,7 +98,7 @@ RSpec.describe "Posts Controller", type: :request do
# Path Object
path '/posts/{post_id}' do
# Parameter Object
parameter "post_id", {in: :path, type: :integer}
parameter "post_id", { in: :path, type: :integer }
let(:post_id) { 1 }

# Operation Object
Expand All @@ -113,30 +113,30 @@ RSpec.describe "Posts Controller", type: :request do
# Parameter Object for content type could be defined like:
consumes 'application/json'
# or:
parameter 'Content-Type', {in: :header, type: :string}
parameter 'Content-Type', { in: :header, type: :string }
let(:'Content-Type') { 'application/json' }
# one of them would be considered

# authorization token in the header:
parameter 'Authorization', {in: :header, type: :string}
parameter 'Authorization', { in: :header, type: :string }
let(:'Authorization') { 'Bearer <token-here>' }

# Parameter Object
parameter "post_id", {in: :path, type: :integer}
parameter "post_id", { in: :path, type: :integer }
let(:post_id) { 1 }

# Parameter Object for Body
parameter "body", {in: :body, required: true, schema: {
parameter "body", { in: :body, required: true, schema: {
type: :object,
properties: {
title: { type: :string },
author_email: { type: :email }
}
}
let (:body) {
{ post:
{ title: 'my example',
author_email: '[email protected]' }
{ post:
{ title: 'my example',
author_email: '[email protected]' }
}
}
}
Expand All @@ -158,12 +158,44 @@ These methods are available inside of an RSpec contexts with the `type: :request
#### `path(template, attributes = {}, &block)`
Defines a new Path Item.

The `attributes` parameter accepts:
- `swagger_doc` a key in `RSpec.configuration.swagger_docs` that determines
which file the path belongs in.
- `tags` with an array of tags that will be applied to the child Operations.

You can also provide a default file and tags by setting them on a parent RSpec
context block:
```rb
RSpec.describe "Sample Requests", type: :request do
# The swagger_doc will be used as a default for the paths defined within the
# context block. Similarly, the tags will be merged with those set on paths
# defined within them.
context "setting defaults", swagger_doc: 'default_document.json', tags: [:context_tag] do
path '/posts', swagger_doc: 'overridden_document.yaml' tags: ['path_tag'] do
operation "GET", summary: "fetch list" do
produces 'application/json'
tags 'operation_tag'

response(200, { description: "successful" })
end
end
end
end
```
The `GET /posts` operation in this example will be saved in the `'overridden_document.yaml'`
file and tagged with `["context_tag", "path_tag", "operation_tag"]`.


### Path Item Object
These methods are available inside of blocks passed to the `path` method.

#### `operation(method, attributes = {}, &block)`
Defines a new Operation Object. The `method` is case insensitive.

The `attributes` parameter accepts:
- `tags` with an array of tags. These will be merged with tags passed to the
Path Item or `tags` method inside the Operation's block.

#### `delete(attributes = {}, &block)`
Alias for `operation(:delete, attributes, block)`.

Expand Down Expand Up @@ -203,7 +235,7 @@ parameter ref: "#/parameters/site_id"
Values for the parameters are set using `let`:
```rb
post summary: "create" do
parameter "body", in: :body, schema: { foo: :bar}
parameter "body", in: :body, schema: { foo: :bar }
let(:body) { { post: { title: 'asdf', body: "blah" } } }
# ...
end
Expand Down Expand Up @@ -245,7 +277,7 @@ RSpec.describe "Sample Requests", type: :request, tags: [:context_tag] do
produces 'application/json'
tags 'operation_tag'

response(200, {description: "successful"})
response(200, { description: "successful" })
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/rspec/rails/swagger/formatter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def example_finished(notification)
return unless metadata[:swagger_object] == :response

# Then add everything to the document
document = document_for(metadata[:swagger_document])
document = document_for(metadata[:swagger_doc])
path_item = path_item_for(document, metadata[:swagger_path_item])
operation = operation_for(path_item, metadata[:swagger_operation])
response = response_for(operation, metadata[:swagger_response])
Expand Down
10 changes: 8 additions & 2 deletions lib/rspec/rails/swagger/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def path template, attributes = {}, &block
#TODO template might be a $ref
meta = {
swagger_object: :path_item,
swagger_document: attributes[:swagger_document] || RSpec.configuration.swagger_docs.keys.first,
swagger_doc: attributes[:swagger_doc] || default_document,
swagger_path_item: {path: template},
}
# Merge tags passed into the path with those from parent contexts.
Expand All @@ -54,6 +54,12 @@ def path template, attributes = {}, &block
end
describe(template, meta, &block)
end

private

def default_document
metadata.try(:[], :swagger_doc) || RSpec.configuration.swagger_docs.keys.first
end
end

module PathItem
Expand Down Expand Up @@ -122,7 +128,7 @@ def parameter name, attributes = {}
def resolve_document metadata
# TODO: It's really inefficient to keep recreating this. It'd be nice
# if we could cache them some place.
name = metadata[:swagger_document]
name = metadata[:swagger_doc]
Document.new(RSpec.configuration.swagger_docs[name])
end

Expand Down
3 changes: 1 addition & 2 deletions lib/rspec/rails/swagger/request_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ def initialize(metadata, instance)
# and parameter references can be resolved.
def document
@document ||= begin
name = metadata[:swagger_document]
Document.new(RSpec.configuration.swagger_docs[name])
Document.new(RSpec.configuration.swagger_docs[metadata[:swagger_doc]])
end
end

Expand Down
2 changes: 1 addition & 1 deletion lib/rspec/rails/swagger/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module Rails
# Version information for RSpec Swagger.
module Swagger
module Version
STRING = '0.1.5'
STRING = '0.2.0'
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion spec/rspec/rails/swagger/formatter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def minimal
let(:metadata) do
{
swagger_object: :response,
swagger_document: 'doc2.json',
swagger_doc: 'doc2.json',
swagger_path_item: {path: "/ping"},
swagger_operation: {method: :put},
swagger_response: {status_code: 200, description: "OK"},
Expand Down
76 changes: 76 additions & 0 deletions spec/rspec/rails/swagger/helpers_paths_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
require 'swagger_helper'

RSpec.describe RSpec::Rails::Swagger::Helpers::Paths do
let(:klass) do
Class.new do
include RSpec::Rails::Swagger::Helpers::Paths
attr_accessor :metadata
def describe *args ; end
end
end
subject { klass.new }

it "requires the path start with a /" do
expect{ subject.path("foo") }.to raise_exception(ArgumentError)
expect{ subject.path("/foo") }.not_to raise_exception
end

describe 'swagger_doc' do
context 'with value specified in parent context' do
before { subject.metadata = {swagger_doc: 'default.json'} }

it "defaults to the parent value" do
expect(subject).to receive(:describe).with("/ping", {
swagger_object: :path_item,
swagger_doc: 'default.json',
swagger_path_item: {path: '/ping'}
})

subject.path('/ping')
end

it "uses the argument when provided" do
expect(subject).to receive(:describe).with("/ping", {
swagger_object: :path_item,
swagger_doc: 'overridden.json',
swagger_path_item: {path: '/ping'}
})

subject.path('/ping', swagger_doc: 'overridden.json')
end
end

context 'without a parent swagger_doc' do
it "defaults to the first swagger document" do
expect(subject).to receive(:describe).with("/ping", {
swagger_object: :path_item,
swagger_doc: RSpec.configuration.swagger_docs.keys.first,
swagger_path_item: {path: '/ping'}
})

subject.path('/ping')
end

it "uses the argument when provided" do
expect(subject).to receive(:describe).with("/ping", {
swagger_object: :path_item,
swagger_doc: 'overridden.json',
swagger_path_item: {path: '/ping'}
})

subject.path('/ping', swagger_doc: 'overridden.json')
end
end
end

it "passes tags through to the metadata" do
expect(subject).to receive(:describe).with("/ping", {
swagger_object: :path_item,
swagger_doc: RSpec.configuration.swagger_docs.keys.first,
swagger_path_item: {path: '/ping'},
tags: ['tag1']
})

subject.path('/ping', tags: ['tag1'])
end
end
47 changes: 0 additions & 47 deletions spec/rspec/rails/swagger/helpers_spec.rb
Original file line number Diff line number Diff line change
@@ -1,52 +1,5 @@
require 'swagger_helper'

RSpec.describe RSpec::Rails::Swagger::Helpers::Paths do
let(:klass) do
Class.new do
include RSpec::Rails::Swagger::Helpers::Paths
attr_accessor :metadata
def describe *args ; end
end
end
subject { klass.new }

it "requires the path start with a /" do
expect{ subject.path("foo") }.to raise_exception(ArgumentError)
expect{ subject.path("/foo") }.not_to raise_exception
end

it "defaults to the first swagger document if not specified" do
expect(subject).to receive(:describe).with("/ping", {
swagger_object: :path_item,
swagger_document: RSpec.configuration.swagger_docs.keys.first,
swagger_path_item: {path: '/ping'}
})

subject.path('/ping')
end

it "accepts specified swagger document name" do
expect(subject).to receive(:describe).with("/ping", {
swagger_object: :path_item,
swagger_document: 'hello_swagger.json',
swagger_path_item: {path: '/ping'}
})

subject.path('/ping', swagger_document: 'hello_swagger.json')
end

it "passes tags through to the metadata" do
expect(subject).to receive(:describe).with("/ping", {
swagger_object: :path_item,
swagger_document: RSpec.configuration.swagger_docs.keys.first,
swagger_path_item: {path: '/ping'},
tags: ['tag1']
})

subject.path('/ping', tags: ['tag1'])
end
end

RSpec.describe RSpec::Rails::Swagger::Helpers::PathItem do
let(:klass) do
Class.new do
Expand Down
2 changes: 1 addition & 1 deletion spec/rspec/rails/swagger/request_builder_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

describe '#document' do
subject { described_class.new(metadata, double('instance')) }
let(:metadata) { { swagger_document: 'example.json' } }
let(:metadata) { { swagger_doc: 'example.json' } }

it 'loads the document' do
allow(RSpec.configuration.swagger_docs).to receive(:[]).with('example.json').and_return({foo: :bar})
Expand Down

0 comments on commit aba8588

Please sign in to comment.