diff --git a/lib/apipie/generator/swagger/type_extractor.rb b/lib/apipie/generator/swagger/type_extractor.rb index f3ded1c3..b14c21dd 100644 --- a/lib/apipie/generator/swagger/type_extractor.rb +++ b/lib/apipie/generator/swagger/type_extractor.rb @@ -25,21 +25,10 @@ def initialize(validator) @validator = validator end - # @param [Hash] warnings - def extract_with_warnings(warnings = {}) - if boolean? && warnings[:boolean].present? - Apipie::Generator::Swagger::WarningWriter.instance.warn(warnings[:boolean]) - end - - extract - end - def extract expected_type = if string? :string - elsif boolean? - :boolean elsif enum? :enum else @@ -59,12 +48,4 @@ def enum? @validator.is_a?(Apipie::Validator::EnumValidator) || (@validator.respond_to?(:is_enum?) && @validator.is_enum?) end - - def boolean? - @_boolean ||= enum? && boolean_values? - end - - def boolean_values? - @validator.values.to_set == Set.new([true, false]) - end end diff --git a/lib/apipie/generator/swagger/warning.rb b/lib/apipie/generator/swagger/warning.rb index 41d202d5..0d3aa5f7 100644 --- a/lib/apipie/generator/swagger/warning.rb +++ b/lib/apipie/generator/swagger/warning.rb @@ -7,7 +7,6 @@ class Apipie::Generator::Swagger::Warning OPTIONAL_WITHOUT_DEFAULT_VALUE_CODE = 105 PARAM_IGNORED_IN_FORM_DATA_CODE = 106 PATH_PARAM_NOT_DESCRIBED_CODE = 107 - INFERRING_BOOLEAN_CODE = 108 CODES = { missing_method_summary: MISSING_METHOD_SUMMARY_CODE, @@ -17,8 +16,7 @@ class Apipie::Generator::Swagger::Warning optional_param_in_path: OPTIONAL_PARAM_IN_PATH_CODE, optional_without_default_value: OPTIONAL_WITHOUT_DEFAULT_VALUE_CODE, param_ignored_in_form_data: PARAM_IGNORED_IN_FORM_DATA_CODE, - path_param_not_described_code: PATH_PARAM_NOT_DESCRIBED_CODE, - inferring_boolean: INFERRING_BOOLEAN_CODE + path_param_not_described_code: PATH_PARAM_NOT_DESCRIBED_CODE } MESSAGES = { @@ -29,8 +27,7 @@ class Apipie::Generator::Swagger::Warning OPTIONAL_PARAM_IN_PATH_CODE => "The parameter :%{parameter} is 'in-path'. Ignoring 'not required' in DSL", OPTIONAL_WITHOUT_DEFAULT_VALUE_CODE => "The parameter :%{parameter} is optional but default value is not specified (use :default_value => ...)", PARAM_IGNORED_IN_FORM_DATA_CODE => "Ignoring param :%{parameter} -- cannot include Hash without fields in a formData specification", - PATH_PARAM_NOT_DESCRIBED_CODE => "The parameter :%{name} appears in the path %{path} but is not described", - INFERRING_BOOLEAN_CODE => "The parameter [%{parameter}] is Enum with [true, false] values. Inferring 'boolean'" + PATH_PARAM_NOT_DESCRIBED_CODE => "The parameter :%{name} appears in the path %{path} but is not described" } attr_reader :code diff --git a/lib/apipie/validator.rb b/lib/apipie/validator.rb index 34fb229c..8615d2b8 100644 --- a/lib/apipie/validator.rb +++ b/lib/apipie/validator.rb @@ -472,13 +472,13 @@ def validate(value) end def self.build(param_description, argument, options, block) - if argument == :bool || argument == :boolean + if argument == :bool || argument == :boolean || boolean_array?(argument) self.new(param_description) end end - def expected_type - 'boolean' + private_class_method def self.boolean_array?(argument) + argument.is_a?(Array) && (argument - [true, false]) == [] end def description @@ -489,6 +489,10 @@ def description def ignore_allow_blank? true end + + def expected_type + 'boolean' + end end class NestedValidator < BaseValidator diff --git a/spec/lib/apipie/generator/swagger/type_extractor_spec.rb b/spec/lib/apipie/generator/swagger/type_extractor_spec.rb index 8f572785..b74eb2cc 100644 --- a/spec/lib/apipie/generator/swagger/type_extractor_spec.rb +++ b/spec/lib/apipie/generator/swagger/type_extractor_spec.rb @@ -26,15 +26,6 @@ it 'returns an enum type' do expect(subject).to eq(Apipie::Generator::Swagger::TypeExtractor::TYPES[:enum]) end - - context 'and has `true`, `false` as values' do - let(:param_description_name) { :visible } - let(:enum_values) { [true, false] } - - it 'returns a boolean type' do - expect(subject).to eq(Apipie::Generator::Swagger::TypeExtractor::TYPES[:boolean]) - end - end end end end @@ -44,38 +35,4 @@ it_behaves_like 'extractable method' end - - describe '#extarct_with_warnings' do - before { Apipie.configuration.generator.swagger.suppress_warnings = false } - - subject { extractor.extract_with_warnings(warnings) } - - it_behaves_like 'extractable method' - - context "when enum validator is used" do - context "and has `true`, `false` as values" do - let(:enum_values) { [true, false] } - - let(:validator) do - Apipie::ResponseDescriptionAdapter::PropDesc::Validator.new('some-type', enum_values) - end - - context 'and a boolean warning is passed' do - let(:boolean_warning) do - Apipie::Generator::Swagger::Warning.for_code( - Apipie::Generator::Swagger::Warning::INFERRING_BOOLEAN_CODE, - 'SampleController#action', - { parameter: 'some-param' } - ) - end - - let(:warnings) { { boolean: boolean_warning } } - - it 'outputs the warning' do - expect { subject }.to output(boolean_warning.warning_message).to_stderr - end - end - end - end - end end diff --git a/spec/lib/apipie/generator/swagger/warning_writer_spec.rb b/spec/lib/apipie/generator/swagger/warning_writer_spec.rb index 7e5cebd5..c55af271 100644 --- a/spec/lib/apipie/generator/swagger/warning_writer_spec.rb +++ b/spec/lib/apipie/generator/swagger/warning_writer_spec.rb @@ -5,7 +5,7 @@ let(:warning) do Apipie::Generator::Swagger::Warning.for_code( - Apipie::Generator::Swagger::Warning::INFERRING_BOOLEAN_CODE, + Apipie::Generator::Swagger::Warning::PARAM_IGNORED_IN_FORM_DATA_CODE, 'SampleController#action', { parameter: 'some-param' } ) @@ -32,7 +32,7 @@ context 'when Apipie.configuration.generator.swagger.suppress_warnings includes warning code' do before do Apipie.configuration.generator.swagger.suppress_warnings = - Array(Apipie::Generator::Swagger::Warning::INFERRING_BOOLEAN_CODE) + Array(Apipie::Generator::Swagger::Warning::PARAM_IGNORED_IN_FORM_DATA_CODE) end it { is_expected.to be_falsey } diff --git a/spec/lib/apipie/param_description_spec.rb b/spec/lib/apipie/param_description_spec.rb index 3b7dc5cc..f9aef925 100644 --- a/spec/lib/apipie/param_description_spec.rb +++ b/spec/lib/apipie/param_description_spec.rb @@ -114,88 +114,210 @@ end describe 'validate' do + subject { param_description.validate(validation_value) } + + let(:allow_blank) { nil } + + let(:param_description) do + Apipie::ParamDescription.new( + method_desc, + :param, + validation_type, + allow_blank: allow_blank + ) + end + context 'when allow_blank is ignored, as it was before 0.7.0' do - before do - Apipie.configuration.ignore_allow_blank_false = true - end + before { Apipie.configuration.ignore_allow_blank_false = true } + after { Apipie.configuration.ignore_allow_blank_false = false } + + context 'when validation type is :boolean' do + let(:validation_type) { :boolean } - context 'when the parameter is a boolean' do - it "should not throw an exception when passed false" do - expect { Apipie::ParamDescription.new(method_desc, :param, :boolean).validate(false) }.to_not raise_error + context 'when validation value is false' do + let(:validation_value) { false } + + it 'should not raise an error' do + expect { subject }.not_to raise_error + end end - it "should throw an exception when passed an empty value" do - expect { Apipie::ParamDescription.new(method_desc, :param, :boolean).validate('') }.to raise_error(Apipie::ParamInvalid) + context 'when validation value is an empty string' do + let(:validation_value) { '' } + + it 'should raise an error' do + expect { subject }.to raise_error(Apipie::ParamInvalid) + end end end - context 'when the parameter is a string' do - context 'when allow_blank is specified as true' do - it "should throw an exception when passed an empty value" do - expect { Apipie::ParamDescription.new(method_desc, :param, String, allow_blank: true).validate('') }.to_not raise_error + context 'when validation type is a boolean array' do + let(:validation_type) { [true, false] } + + context 'when validation value is false' do + let(:validation_value) { false } + + it 'should not raise an error' do + expect { subject }.not_to raise_error end end - context 'when allow_blank is specified as false' do - it "should throw an exception when passed an empty value" do - expect { Apipie::ParamDescription.new(method_desc, :param, String, allow_blank: false).validate('') }.to_not raise_error + + context 'when validation value is true' do + let(:validation_value) { true } + + it 'should not raise an error' do + expect { subject }.not_to raise_error end end - context 'when allow_blank is not specified' do - it "should throw an exception when passed an empty value" do - expect { Apipie::ParamDescription.new(method_desc, :param, String).validate('') }.to_not raise_error + + context 'when validation value is an empty string' do + let(:validation_value) { '' } + + it 'should raise an error' do + expect { subject }.to raise_error(Apipie::ParamInvalid) end end end - after do - Apipie.configuration.ignore_allow_blank_false = false + context 'when validation type is String' do + let(:validation_type) { String } + + context 'when validation value is empty string' do + let(:validation_value) { '' } + + it 'should not raise an error' do + expect { subject }.not_to raise_error + end + + context 'when allow_blank is specified as true' do + let(:allow_blank) { true } + + it 'should not raise an error' do + expect { subject }.not_to raise_error + end + end + end end end - context 'when the parameter is a boolean' do - it "should not throw an exception when passed false" do - expect { Apipie::ParamDescription.new(method_desc, :param, :boolean).validate(false) }.to_not raise_error - end + context 'when the validation type is :boolean' do + let(:validation_type) { :boolean } + + context 'when validation value' do + let(:validation_value) { false } + + it 'should not raise an error' do + expect { subject }.not_to raise_error + end + + context 'when allow_blank is false' do + let(:allow_blank) { false } + + it 'should not raise an error' do + expect { subject }.not_to raise_error + end + end + + context 'when allow_blank is true' do + let(:allow_blank) { true } - it "should still not throw an exception when passed false with explicit allow_blank: false" do - expect { Apipie::ParamDescription.new(method_desc, :param, :boolean, allow_blank: false).validate(false) }.to_not raise_error + it 'should not raise an error' do + expect { subject }.not_to raise_error + end + end end - it "should throw an exception when passed an empty value" do - expect { Apipie::ParamDescription.new(method_desc, :param, :boolean).validate('') }.to raise_error(Apipie::ParamInvalid) + context 'when validation value is empty string' do + let(:validation_value) { '' } + + it 'should raise an error' do + expect { subject }.to raise_error(Apipie::ParamInvalid) + end end end - context "when the parameter is a custom type with ignore_allow_blank? returning true" do - it "should not throw an exception when passed a blank but valid value" do - expect { Apipie::ParamDescription.new(method_desc, :param, :custom_bool).validate(false) }.to_not raise_error + context 'when validation type is a boolean array' do + let(:validation_type) { [true, false] } + + context 'when validation value is false' do + let(:validation_value) { false } + + it 'should not raise an error' do + expect { subject }.not_to raise_error + end end - it "should still not throw an exception when passed false with explicit allow_blank: false" do - expect { Apipie::ParamDescription.new(method_desc, :param, :custom_bool, allow_blank: false).validate(false) }.to_not raise_error + context 'when validation value is true' do + let(:validation_value) { true } + + it 'should not raise an error' do + expect { subject }.not_to raise_error + end end - it "should throw an exception when passed an invalid but blank value" do - expect { Apipie::ParamDescription.new(method_desc, :param, :custom_bool).validate("") }.to raise_error(Apipie::ParamInvalid) + context 'when validation value is an empty string' do + let(:validation_value) { '' } + + it 'should raise an error' do + expect { subject }.to raise_error(Apipie::ParamInvalid) + end end end - context 'when the parameter is a string' do - context 'when allow_blank is specified as true' do - it "should throw an exception when passed an empty value" do - expect { Apipie::ParamDescription.new(method_desc, :param, String, allow_blank: true).validate('') }.to_not raise_error + context 'when the validation type is a custom one' do + let(:validation_type) { :custom_bool } + + context 'when ignore_allow_blank? returning true' do + before do + allow(CustomBoolValidator).to receive(:ignore_allow_blank?).and_return(true) + end + + context 'when a blank but valid value is passed' do + let(:validation_value) { false } + + it 'should not raise an error' do + expect { subject }.not_to raise_error + end + + context 'when allow_blank is false' do + let(:allow_blank) { false } + + it 'should not raise an error' do + expect { subject }.not_to raise_error + end + end + end + + context 'when a blank but invalid value is passed' do + let(:validation_value) { '' } + + it 'should raise an error' do + expect { subject }.to raise_error(Apipie::ParamInvalid) + end end end - context 'when allow_blank is specified as false' do - it "should throw an exception when passed an empty value" do - expect do - Apipie::ParamDescription.new(method_desc, :param, String, allow_blank: false).validate('') - end.to raise_error(Apipie::ParamInvalid) + end + + context 'when validation type is String' do + let(:validation_type) { String } + + context 'when a blank but invalid value is passed' do + let(:validation_value) { '' } + + it 'should raise an error' do + expect { subject }.to raise_error(Apipie::ParamInvalid) end end - context 'when allow_blank is not specified' do - it "should throw an exception when passed an empty value" do - expect { Apipie::ParamDescription.new(method_desc, :param, String).validate('') }.to raise_error(Apipie::ParamInvalid) + + context 'when allow_blank is specified as true' do + let(:allow_blank) { true } + + context 'when and empty string is given' do + let(:validation_value) { '' } + + it 'should not raise an error' do + expect { subject }.not_to raise_error + end end end end diff --git a/spec/lib/apipie/validator_spec.rb b/spec/lib/apipie/validator_spec.rb index e7436df3..831daba0 100644 --- a/spec/lib/apipie/validator_spec.rb +++ b/spec/lib/apipie/validator_spec.rb @@ -51,19 +51,55 @@ end describe 'BooleanValidator' do - it "should validate by object class" do - validator = Apipie::Validator::BooleanValidator.new(params_desc) - expect(validator.validate("1")).to be_truthy - expect(validator.validate(1)).to be_truthy - expect(validator.validate(true)).to be_truthy - expect(validator.validate(0)).to be_truthy - expect(validator.validate(false)).to be_truthy - expect(validator.validate({ 1 => 1 })).to be_falsey + let(:validator) do + Apipie::Validator::BooleanValidator end - it "should have a valid description" do - validator = Apipie::Validator::BooleanValidator.new(params_desc) - expect(validator.description).to eq('Must be one of: true, false, 1, 0.') + let(:validator_instance) { validator.new(params_desc) } + + describe '.build' do + subject { validator.build(params_desc, argument, nil, nil) } + + context 'when argument is [true, false]' do + let(:argument) { [true, false] } + + it { is_expected.to be_an_instance_of(Apipie::Validator::BooleanValidator) } + end + + context 'when argument is :bool' do + let(:argument) { :bool } + + it { is_expected.to be_an_instance_of(Apipie::Validator::BooleanValidator) } + end + + context 'when argument :boolean' do + let(:argument) { :boolean } + + it { is_expected.to be_an_instance_of(Apipie::Validator::BooleanValidator) } + end + + context 'when argument :booooooooolean' do + let(:argument) { :booooooooolean } + + it { is_expected.to be_nil } + end + end + + describe '#validate' do + it "should validate by object class" do + expect(validator_instance.validate("1")).to be_truthy + expect(validator_instance.validate(1)).to be_truthy + expect(validator_instance.validate(true)).to be_truthy + expect(validator_instance.validate(0)).to be_truthy + expect(validator_instance.validate(false)).to be_truthy + expect(validator_instance.validate({ 1 => 1 })).to be_falsey + end + end + + describe '#description' do + subject { validator_instance.description } + + it { is_expected.to eq('Must be one of: true, false, 1, 0.') } end end