Skip to content

Commit

Permalink
increases code coverage (#570)
Browse files Browse the repository at this point in the history
- adds changelog entry
  • Loading branch information
peter scholz authored Jan 15, 2017
1 parent a7dc0e2 commit 8811dde
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 74 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

* [#567](https://github.com/ruby-grape/grape-swagger/pull/567): Issue#566: removes markdown - [@LeFnord](https://github.com/LeFnord).
* [#568](https://github.com/ruby-grape/grape-swagger/pull/568): Adds code coverage w/ coveralls - [@LeFnord](https://github.com/LeFnord).
* [#570](https://github.com/ruby-grape/grape-swagger/pull/570): Removes dead code -> increases code coverage - [@LeFnord](https://github.com/LeFnord).

* Your contribution here.

Expand Down
88 changes: 20 additions & 68 deletions lib/grape-swagger.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,8 @@ def combine_routes(app, doc_klass)

def combine_namespaces(app)
app.endpoints.each do |endpoint|
ns = if endpoint.respond_to?(:namespace_stackable)
endpoint.namespace_stackable(:namespace).last
else
endpoint.settings.stack.last[:namespace]
end
ns = endpoint.namespace_stackable(:namespace).last

# use the full namespace here (not the latest level only)
# and strip leading slash
mount_path = (endpoint.namespace_stackable(:mount_path) || []).join('/')
Expand All @@ -93,7 +90,7 @@ def combine_namespaces(app)

def combine_namespace_routes(namespaces)
# iterate over each single namespace
namespaces.each do |name, namespace|
namespaces.each do |name, _|
# get the parent route for the namespace
parent_route_name = extract_parent_route(name)
parent_route = @target_class.combined_routes[parent_route_name]
Expand All @@ -102,55 +99,28 @@ def combine_namespace_routes(namespaces)
!route_path_start_with?(route, name) || !route_instance_variable_equals?(route, name)
end

if namespace.options.key?(:swagger) && namespace.options[:swagger][:nested] == false
# Namespace shall appear as standalone resource, use specified name or use normalized path as name
identifier = if namespace.options[:swagger].key?(:name)
name.tr(' ', '-')
else
name.tr('_', '-').gsub(/\//, '_')
end
@target_class.combined_namespace_identifiers[identifier] = name
@target_class.combined_namespace_routes[identifier] = namespace_routes

# # get all nested namespaces below the current namespace
sub_namespaces = standalone_sub_namespaces(name, namespaces)
sub_routes = sub_routes_from(parent_route, sub_namespaces)
@target_class.combined_namespace_routes[identifier].push(*sub_routes)
else
# default case when not explicitly specified or nested == true
standalone_namespaces = namespaces.reject do |_, ns|
!ns.options.key?(:swagger) ||
!ns.options[:swagger].key?(:nested) ||
ns.options[:swagger][:nested] != false
end

parent_standalone_namespaces = standalone_namespaces.reject { |ns_name, _| !name.start_with?(ns_name) }
# add only to the main route
# if the namespace is not within any other namespace appearing as standalone resource
if parent_standalone_namespaces.empty?
# default option, append namespace methods to parent route
parent_route = @target_class.combined_namespace_routes.key?(parent_route_name)
@target_class.combined_namespace_routes[parent_route_name] = [] unless parent_route
@target_class.combined_namespace_routes[parent_route_name].push(*namespace_routes)
end
# default case when not explicitly specified or nested == true
standalone_namespaces = namespaces.reject do |_, ns|
!ns.options.key?(:swagger) ||
!ns.options[:swagger].key?(:nested) ||
ns.options[:swagger][:nested] != false
end

parent_standalone_namespaces = standalone_namespaces.reject { |ns_name, _| !name.start_with?(ns_name) }
# add only to the main route
# if the namespace is not within any other namespace appearing as standalone resource
# rubocop:disable Style/Next
if parent_standalone_namespaces.empty?
# default option, append namespace methods to parent route
parent_route = @target_class.combined_namespace_routes.key?(parent_route_name)
@target_class.combined_namespace_routes[parent_route_name] = [] unless parent_route
@target_class.combined_namespace_routes[parent_route_name].push(*namespace_routes)
end
end
end

def extract_parent_route(name)
route_name = name.match(%r{^/?([^/]*).*$})[1]
return route_name unless route_name.include? ':'
name.match(/\/[a-z]+/)[0].delete('/')
end

def sub_routes_from(parent_route, sub_namespaces)
sub_ns_paths = sub_namespaces.collect { |ns_name, _| ["/#{ns_name}", "/:version/#{ns_name}"] }
sub_routes = parent_route.reject do |route|
parent_namespace = route_instance_variable(route)
!sub_ns_paths.assoc(parent_namespace) && !sub_ns_paths.rassoc(parent_namespace)
end

sub_routes
name.match(%r{^/?([^/]*).*$})[1]
end

def route_instance_variable(route)
Expand All @@ -169,24 +139,6 @@ def route_path_start_with?(route, name)
route.path.start_with?(route_prefix, route_versioned_prefix)
end

def standalone_sub_namespaces(name, namespaces)
# assign all nested namespace routes to this resource, too
# (unless they are assigned to another standalone namespace themselves)
sub_namespaces = {}
# fetch all namespaces that are children of the current namespace
namespaces.each { |ns_name, ns| sub_namespaces[ns_name] = ns if ns_name.start_with?(name) && ns_name != name }
# remove the sub namespaces if they are assigned to another standalone namespace themselves
sub_namespaces.each do |sub_name, sub_ns|
# skip if sub_ns is standalone, too
next unless sub_ns.options.key?(:swagger) && sub_ns.options[:swagger][:nested] == false
# remove all namespaces that are nested below this standalone sub_ns
sub_namespaces.each do |sub_sub_name, _|
sub_namespaces.delete(sub_sub_name) if sub_sub_name.start_with?(sub_name)
end
end
sub_namespaces
end

def create_documentation_class
Class.new(Grape::API) do
extend GrapeSwagger::DocMethods
Expand Down
4 changes: 0 additions & 4 deletions lib/grape-swagger/doc_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@

module GrapeSwagger
module DocMethods
def name
@@class_name
end

def hide_documentation_path
@@hide_documentation_path
end
Expand Down
2 changes: 1 addition & 1 deletion lib/grape-swagger/endpoint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def content_types_for(target_class)

if content_types.empty?
formats = [target_class.format, target_class.default_format].compact.uniq
formats = Grape::Formatter::Base.formatters({}).keys if formats.empty?
formats = Grape::Formatter.formatters({}).keys if formats.empty?
content_types = Grape::ContentTypes::CONTENT_TYPES.select do |content_type, _mime_type|
formats.include? content_type
end.values
Expand Down
43 changes: 42 additions & 1 deletion spec/lib/endpoint_spec.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
require 'spec_helper'

describe Grape::Endpoint do
subject { described_class.new(Grape::Util::InheritableSetting.new, path: '/', method: :get) }
subject do
described_class.new(Grape::Util::InheritableSetting.new, path: '/', method: :get)
end

describe '#param_type_is_array?' do
it 'returns true if the value passed represents an array' do
Expand All @@ -15,4 +17,43 @@
expect(subject.send(:param_type_is_array?, '[String, Integer]')).to be_falsey
end
end

describe '.content_types_for' do
describe 'defined on target_class' do
let(:own_json) { 'text/own-json' }
let(:own_xml) { 'text/own-xml' }
let(:content_types) do
{
own_json: own_json,
own_xml: own_xml
}
end
let(:target_class) { OpenStruct.new(content_types: content_types) }

let(:object) { subject.content_types_for(target_class) }
specify do
expect(object).to eql [own_json, own_xml]
end
end

describe 'not defined' do
describe 'format given' do
let(:format) { :json }
let(:target_class) { OpenStruct.new(format: format) }
let(:object) { subject.content_types_for(target_class) }
specify do
expect(object).to eql ['application/json']
end

describe 'format not given' do
let(:target_class) { OpenStruct.new }
let(:object) { subject.content_types_for(target_class) }

specify do
expect(object).to eql %w(application/xml application/json text/plain)
end
end
end
end
end
end

0 comments on commit 8811dde

Please sign in to comment.