From c752dc2c85fa31667d9c8b01afff796b28a0c17a Mon Sep 17 00:00:00 2001 From: Igor Zubkov Date: Mon, 27 Nov 2017 14:43:21 +0200 Subject: [PATCH] WIP #110 --- .gitignore | 2 + lib/swagger/blocks/internal_helpers.rb | 6 +- lib/swagger/blocks/node.rb | 9 ++- spec/lib/openapi_v3_api_declaration.json | 15 +++++ spec/lib/openapi_v3_blocks_spec.rb | 72 ++++++++++++++++++++++++ 5 files changed, 98 insertions(+), 6 deletions(-) create mode 100644 spec/lib/openapi_v3_api_declaration.json create mode 100644 spec/lib/openapi_v3_blocks_spec.rb diff --git a/.gitignore b/.gitignore index 31cafb5..ff3bd9e 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,5 @@ tmp *.o *.a mkmf.log +.idea/ + diff --git a/lib/swagger/blocks/internal_helpers.rb b/lib/swagger/blocks/internal_helpers.rb index a2f5aa7..ab1245d 100644 --- a/lib/swagger/blocks/internal_helpers.rb +++ b/lib/swagger/blocks/internal_helpers.rb @@ -39,11 +39,9 @@ def self.parse_swaggered_classes(swaggered_classes) # TODO should this merge the contents of the root nodes instead? def self.limit_root_node(root_nodes) if root_nodes.length == 0 - raise Swagger::Blocks::DeclarationError.new( - 'swagger_root must be declared') + raise Swagger::Blocks::DeclarationError.new('swagger_root must be declared') elsif root_nodes.length > 1 - raise Swagger::Blocks::DeclarationError.new( - 'Only one swagger_root declaration is allowed.') + raise Swagger::Blocks::DeclarationError.new('Only one swagger_root declaration is allowed.') end root_nodes.first end diff --git a/lib/swagger/blocks/node.rb b/lib/swagger/blocks/node.rb index da49e14..98e87cd 100644 --- a/lib/swagger/blocks/node.rb +++ b/lib/swagger/blocks/node.rb @@ -35,7 +35,7 @@ def as_json end return result if !name # If 'name' is given to this node, wrap the data with a root element with the given name. - {name => result} + { name => result } end def data @@ -53,12 +53,17 @@ def key(key, value) def version return @version if instance_variable_defined?('@version') && @version return '2.0' if data.has_key?(:swagger) && data[:swagger] == '2.0' - raise DeclarationError, "You must specify swagger '2.0'" + return '3.0' if data.has_key?(:openapi) && data[:openapi].start_with?('3.0') + raise DeclarationError, "You must specify swagger '2.0' or openapi '3.0.0'" end def is_swagger_2_0? version == '2.0' end + + def is_openapi_3? + version == '3.0' + end end end end diff --git a/spec/lib/openapi_v3_api_declaration.json b/spec/lib/openapi_v3_api_declaration.json new file mode 100644 index 0000000..bae8c7d --- /dev/null +++ b/spec/lib/openapi_v3_api_declaration.json @@ -0,0 +1,15 @@ +{ + "openapi": "3.0.0", + "info": { + "version": "1.0.0", + "title": "Swagger Petstore", + "description": "A sample API that uses a petstore as an example to demonstrate features in the openapi-3.0.0 specification", + "termsOfService": "http://helloreverb.com/terms/", + "contact": { + "name": "Wordnik API Team" + }, + "license": { + "name": "MIT" + } + } +} diff --git a/spec/lib/openapi_v3_blocks_spec.rb b/spec/lib/openapi_v3_blocks_spec.rb new file mode 100644 index 0000000..74b9d55 --- /dev/null +++ b/spec/lib/openapi_v3_blocks_spec.rb @@ -0,0 +1,72 @@ +require 'json' +require 'swagger/blocks' + +# TODO Test data originally based on the Swagger UI example data + +RESOURCE_LISTING_JSON_V3 = open(File.expand_path('../openapi_v3_api_declaration.json', __FILE__)).read + +class PetControllerV3 + include Swagger::Blocks + + swagger_root host: 'petstore.swagger.wordnik.com' do + key :openapi, '3.0.0' + info version: '1.0.0' do + key :title, 'Swagger Petstore' + key :description, 'A sample API that uses a petstore as an example to ' \ + 'demonstrate features in the openapi-3.0.0 specification' + key :termsOfService, 'http://helloreverb.com/terms/' + contact do + key :name, 'Wordnik API Team' + end + license do + key :name, 'MIT' + end + end + end +end + +describe 'Swagger::Blocks v3' do + describe 'build_json' do + it 'outputs the correct data' do + swaggered_classes = [ + PetControllerV3, + # PetV2, + # ErrorModelV2 + ] + actual = Swagger::Blocks.build_root_json(swaggered_classes) + actual = JSON.parse(actual.to_json) # For access consistency. + data = JSON.parse(RESOURCE_LISTING_JSON_V3) + + # Multiple expectations for better test diff output. + expect(actual['info']).to eq(data['info']) + expect(actual['paths']).to be + expect(actual['paths']['/pets']).to be + expect(actual['paths']['/pets']).to eq(data['paths']['/pets']) + expect(actual['paths']['/pets/{id}']).to be + expect(actual['paths']['/pets/{id}']['get']).to be + expect(actual['paths']['/pets/{id}']['get']).to eq(data['paths']['/pets/{id}']['get']) + expect(actual['paths']).to eq(data['paths']) + expect(actual['definitions']).to eq(data['definitions']) + expect(actual).to eq(data) + end + it 'is idempotent' do + # swaggered_classes = [PetControllerV2, PetV2, ErrorModelV2] + swaggered_classes = [PetControllerV3] + actual = JSON.parse(Swagger::Blocks.build_root_json(swaggered_classes).to_json) + data = JSON.parse(RESOURCE_LISTING_JSON_V3) + expect(actual).to eq(data) + end + + it 'errors if no swagger_root is declared' do + expect { + Swagger::Blocks.build_root_json([]) + }.to raise_error(Swagger::Blocks::DeclarationError) + end + + it 'errors if multiple swagger_roots are declared' do + expect { + Swagger::Blocks.build_root_json([PetControllerV3, PetControllerV3]) + }.to raise_error(Swagger::Blocks::DeclarationError) + end + end +end