From 6fa07034152f98f53282a354087ad138d48184b4 Mon Sep 17 00:00:00 2001 From: Rumble Huang Date: Tue, 21 Apr 2020 23:27:15 +0800 Subject: [PATCH 1/2] Auto-detect parameters' types from example values --- .../views/api_blueprint_index.rb | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/lib/rspec_api_documentation/views/api_blueprint_index.rb b/lib/rspec_api_documentation/views/api_blueprint_index.rb index ef42c1fa..ca4e7abf 100644 --- a/lib/rspec_api_documentation/views/api_blueprint_index.rb +++ b/lib/rspec_api_documentation/views/api_blueprint_index.rb @@ -67,6 +67,11 @@ def format_route(example) # properties_description: "required, string" # } def fields(property_name, examples) + possible_parameters_values = examples.map do |example| + parameters = example.metadata[:extended_parameters] + next parameters.map { |parameter| [parameter[:name], parameter[:value]] }.to_h + end + examples .map { |example| example.metadata[property_name] } .flatten @@ -79,7 +84,19 @@ def fields(property_name, examples) else properties << 'optional' end - properties << property[:type] if property[:type] + + if property.key?(:type) + properties << property[:type] if property[:type] + else + possible_values = possible_parameters_values.map { |parameters| parameters[property[:name]] } + possible_types = possible_values.map { |value| guess_type(value) } + + possible_types.uniq! + possible_types.compact! + + properties.concat(possible_types) + end + if properties.count > 0 property[:properties_description] = properties.join(", ") else @@ -96,6 +113,21 @@ def fields(property_name, examples) end end + def guess_type(value) + case value + when TrueClass then :boolean + when FalseClass then :boolean + when Array then :array + when Integer then :integer + when Float then :number + when String then :string + when Rack::Test::UploadedFile then :file + when NilClass then nil + else + puts "Warning: unknown type of value #{value}" + end + end + # When no `description` was specified for a parameter, the DSL class # is making `description = "#{scope} #{name}"`, which is bad because it # assumes that all formats want this behavior. To avoid changing there From 1f9ad4b9cbe5efd4ca62afd810e1933e8c122777 Mon Sep 17 00:00:00 2001 From: khiav reoy Date: Fri, 11 Sep 2020 12:14:04 +0800 Subject: [PATCH 2/2] Fix test cases and add new test cases to test this feature --- .../views/api_blueprint_index.rb | 6 +-- spec/views/api_blueprint_index_spec.rb | 49 +++++++++++++++++++ 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/lib/rspec_api_documentation/views/api_blueprint_index.rb b/lib/rspec_api_documentation/views/api_blueprint_index.rb index ca4e7abf..a5b157d3 100644 --- a/lib/rspec_api_documentation/views/api_blueprint_index.rb +++ b/lib/rspec_api_documentation/views/api_blueprint_index.rb @@ -67,8 +67,8 @@ def format_route(example) # properties_description: "required, string" # } def fields(property_name, examples) - possible_parameters_values = examples.map do |example| - parameters = example.metadata[:extended_parameters] + possible_parameters_values = examples.map do |example| + parameters = example.metadata[:extended_parameters] || [] next parameters.map { |parameter| [parameter[:name], parameter[:value]] }.to_h end @@ -85,7 +85,7 @@ def fields(property_name, examples) properties << 'optional' end - if property.key?(:type) + if property.key?(:type) properties << property[:type] if property[:type] else possible_values = possible_parameters_values.map { |parameters| parameters[property[:name]] } diff --git a/spec/views/api_blueprint_index_spec.rb b/spec/views/api_blueprint_index_spec.rb index 1d526597..a1ce7c1e 100644 --- a/spec/views/api_blueprint_index_spec.rb +++ b/spec/views/api_blueprint_index_spec.rb @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- require 'spec_helper' +require 'rack/test' require 'rspec_api_documentation/dsl' describe RspecApiDocumentation::Views::ApiBlueprintIndex do @@ -164,4 +165,52 @@ end end end + + describe '#guess_type' do + let(:index) { RspecApiDocumentation::Index.new } + let(:order_route) { subject.sections[0][:routes][0] } + + resource "Order" do + route '/orders', 'Order' do + post "orders" do + parameter :desc, required: true + parameter :price, required: true + + let(:desc) { "A test order" } + let(:price) { 13 } + + let(:config) { RspecApiDocumentation::Configuration.new } + + before do + expect(client).to receive(:post) + do_request + + index.examples << RspecApiDocumentation::Example.new(client.example, config) + end + + it "should guess the parameter type" do + order_examples = order_route[:http_methods].map { |http_method| http_method[:examples] }.flatten + expect(order_examples.size).to eq 1 + expect(order_route[:route]).to eq "/orders" + expect(order_route[:route_name]).to eq "Order" + expect(order_route[:has_parameters?]).to eq true + expect(order_route[:parameters]).to eq [ + { + required: true, + name: "desc", + description: nil, + properties_description: "required, string" + }, + { + required: true, + name: "price", + description: nil, + properties_description: "required, integer" + } + ] + end + end + end + end + end end