Skip to content

Commit

Permalink
Merge pull request #24 from drewish/allow-optional-params
Browse files Browse the repository at this point in the history
Don't require optional parameters to have value
  • Loading branch information
drewish authored Oct 5, 2016
2 parents 251f26f + 160af2e commit 7b91920
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 18 deletions.
2 changes: 2 additions & 0 deletions lib/rspec/rails/swagger/document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ def [](value)
data[value]
end

##
# Look up parameter or definition references.
def resolve_ref(ref)
unless %r{#/(?<location>parameters|definitions)/(?<name>.+)} =~ ref
raise ArgumentError, "Invalid reference: #{ref}"
Expand Down
20 changes: 14 additions & 6 deletions lib/rspec/rails/swagger/request_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,17 @@ module Swagger
class RequestBuilder
attr_reader :metadata, :instance

##
# Creates a new RequestBuilder from the Example class's +metadata+ hash
# and a test +instance+ that we can use to populate the parameter
# values.
def initialize(metadata, instance)
@metadata, @instance = metadata, instance
end

##
# Finds the Document associated with this request so things like schema
# and parameter references can be resolved.
def document
@document ||= begin
name = metadata[:swagger_document]
Expand All @@ -27,6 +34,9 @@ def consumes
Array(metadata[:swagger_operation][:consumes]).presence || Array(document[:consumes])
end

##
# Returns parameters defined in the operation and path item. Providing
# a +location+ will limit the parameters by their `in` value.
def parameters location = nil
path_item = metadata[:swagger_path_item] || {}
operation = metadata[:swagger_operation] || {}
Expand All @@ -39,12 +49,10 @@ def parameters location = nil
end

def parameter_values location
# Don't bother looking at the full parameter bodies since all we need
# are location and name which are in the key.
values = parameters(location)
.keys
.map{ |k| k.split('&').last }
.map{ |name| [name, instance.send(name)] }
values = parameters(location).
map{ |_, p| p['$ref'] ? document.resolve_ref(p['$ref']) : p }.
select{ |p| p[:required] || instance.respond_to?(p[:name]) }.
map{ |p| [p[:name], instance.send(p[:name])] }
Hash[values]
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.2'
STRING = '0.1.3'
end
end
end
Expand Down
76 changes: 65 additions & 11 deletions spec/rspec/rails/swagger/request_builder_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,15 +98,19 @@

describe '#parameters' do
subject { described_class.new(metadata, double('instance')) }
let(:metadata) { {
swagger_path_item: { parameters: {
'path&petId' => { name: 'petId', in: :path, description: 'path' },
'query&site' => { name: 'site', in: :query }
} },
swagger_operation: { parameters: {
'path&petId' => { name: 'petId', in: :path, description: 'op' }
} },
} }
let(:metadata) do
{
swagger_path_item: {
parameters: {
'path&petId' => { name: 'petId', in: :path, description: 'path' },
'query&site' => { name: 'site', in: :query }
}
},
swagger_operation: {
parameters: { 'path&petId' => { name: 'petId', in: :path, description: 'op' } }
}
}
end

it 'merges values from the path and operation' do
expect(subject.parameters).to eq({
Expand All @@ -116,6 +120,56 @@
end
end

describe '#parameter_values' do
subject { described_class.new(metadata, instance) }
let(:metadata) do
{
swagger_operation: {
parameters: {
"query&date" => { "$ref" => "#/parameters/filter_date" },
"query&subscriber" => { name: "subscriber", type: :string, in: :query, required: required }
}
}
}
end
let(:instance) { double('instance') }
before do
expect(subject).to receive_message_chain(:document, :resolve_ref) do
{ name: "date", type: :integer, in: :query, required: required }
end
end

context 'required parameters' do
let(:required) { true }

it 'includes defined values' do
allow(instance).to receive(:date) { 10 }
allow(instance).to receive(:subscriber) { false }

expect(subject.parameter_values(:query)).to eq({ 'date' => 10, 'subscriber' => false })
end

it 'undefined cause errors' do
expect{ subject.parameter_values(:query) }.to raise_exception(RSpec::Mocks::MockExpectationError)
end
end

context 'optional parameters' do
let(:required) { false }

it 'includes defined values' do
allow(instance).to receive(:date) { 27 }
allow(instance).to receive(:subscriber) { true }

expect(subject.parameter_values(:query)).to eq({ 'date' => 27, 'subscriber' => true })
end

it 'ommits undefined values' do
expect(subject.parameter_values(:query)).to eq({})
end
end
end

describe '#headers' do
subject { described_class.new(double('metadata'), instance) }
let(:instance) { double('instance') }
Expand Down Expand Up @@ -170,7 +224,7 @@
context 'with header params' do
it 'returns them in a string' do
expect(subject).to receive(:parameters).with(:header) { {
'header&X-Magic' => { same: :here }
'header&X-Magic' => { name: 'X-Magic', in: :header }
} }
expect(instance).to receive('X-Magic'.to_sym) { :pickles }

Expand Down Expand Up @@ -221,7 +275,7 @@
context 'with query params' do
it 'returns them in a string' do
expect(subject).to receive(:parameters).with(:query) { {
'query&site' => { same: :here }
'query&site' => { name: 'site', in: :query }
} }
expect(instance).to receive(:site) { :pickles }

Expand Down

0 comments on commit 7b91920

Please sign in to comment.