spec/grape/validations_spec.rb in grape-0.13.0 vs spec/grape/validations_spec.rb in grape-0.14.0

- old
+ new

@@ -316,10 +316,39 @@ end expect(subject.route_setting(:declared_params)).to eq([items: [:key]]) end end + context 'hash with a required param with validation' do + before do + subject.params do + requires :items, type: Hash do + requires :key, type: String, values: %w(a b) + end + end + subject.get '/required' do + 'required works' + end + end + + it 'errors when param is not a Hash' do + get '/required', items: 'not a hash' + expect(last_response.status).to eq(400) + expect(last_response.body).to eq('items is invalid, items[key] is missing, items[key] is invalid') + + get '/required', items: [{ key: 'hash in array' }] + expect(last_response.status).to eq(400) + expect(last_response.body).to eq('items is invalid, items[0][key] does not have a valid value') + end + + it 'works when all params match' do + get '/required', items: { key: 'a' } + expect(last_response.status).to eq(200) + expect(last_response.body).to eq('required works') + end + end + context 'group' do before do subject.params do group :items, type: Array do requires :key @@ -372,14 +401,15 @@ expect(last_response.status).to eq(400) end end context 'custom validator for a Hash' do - module DateRangeValidations - class DateRangeValidator < Grape::Validations::Base - def validate_param!(attr_name, params) - unless params[attr_name][:from] <= params[attr_name][:to] + module ValuesSpec + module DateRangeValidations + class DateRangeValidator < Grape::Validations::Base + def validate_param!(attr_name, params) + return if params[attr_name][:from] <= params[attr_name][:to] fail Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message: "'from' must be lower or equal to 'to'" end end end end @@ -460,22 +490,22 @@ { name: 'Job', parents: [{ name: 'Joy' }] } ] # NOTE: with body parameters in json or XML or similar this # should actually fail with: children[parents][name] is missing. expect(last_response.status).to eq(400) - expect(last_response.body).to eq('children[parents] is missing') + expect(last_response.body).to eq('children[0][parents] is missing') end it 'safely handles empty arrays and blank parameters' do # NOTE: with body parameters in json or XML or similar this # should actually return 200, since an empty array is valid. get '/within_array', children: [] expect(last_response.status).to eq(400) expect(last_response.body).to eq('children is missing') get '/within_array', children: [name: 'Jay'] expect(last_response.status).to eq(400) - expect(last_response.body).to eq('children[parents] is missing') + expect(last_response.body).to eq('children[0][parents] is missing') end it 'errors when param is not an Array' do # NOTE: would be nicer if these just returned 'children is invalid' get '/within_array', children: 'hello' @@ -486,11 +516,11 @@ expect(last_response.status).to eq(400) expect(last_response.body).to eq('children is invalid, children[parents] is missing') get '/within_array', children: [name: 'Jay', parents: { name: 'Fred' }] expect(last_response.status).to eq(400) - expect(last_response.body).to eq('children[parents] is invalid') + expect(last_response.body).to eq('children[0][parents] is invalid') end end context 'with block param' do before do @@ -612,19 +642,19 @@ put_with_json '/within_array', children: [ { name: 'Jim', parents: [{}] }, { name: 'Job', parents: [{ name: 'Joy' }] } ] expect(last_response.status).to eq(400) - expect(last_response.body).to eq('children[parents][name] is missing') + expect(last_response.body).to eq('children[0][parents][0][name] is missing') end it 'safely handles empty arrays and blank parameters' do put_with_json '/within_array', children: [] expect(last_response.status).to eq(200) put_with_json '/within_array', children: [name: 'Jay'] expect(last_response.status).to eq(400) - expect(last_response.body).to eq('children[parents] is missing') + expect(last_response.body).to eq('children[0][parents] is missing') end end context 'optional with an Array block' do before do @@ -651,11 +681,11 @@ end it 'errors when group is present, but required param is not' do get '/optional_group', items: [{ not_key: 'foo' }] expect(last_response.status).to eq(400) - expect(last_response.body).to eq('items[key] is missing') + expect(last_response.body).to eq('items[0][key] is missing') end it "errors when param is present but isn't an Array" do get '/optional_group', items: 'hello' expect(last_response.status).to eq(400) @@ -695,39 +725,39 @@ end it 'does internal validations if the outer group is present' do get '/nested_optional_group', items: [{ key: 'foo' }] expect(last_response.status).to eq(400) - expect(last_response.body).to eq('items[required_subitems] is missing') + expect(last_response.body).to eq('items[0][required_subitems] is missing') get '/nested_optional_group', items: [{ key: 'foo', required_subitems: [{ value: 'bar' }] }] expect(last_response.status).to eq(200) expect(last_response.body).to eq('nested optional group works') end it 'handles deep nesting' do get '/nested_optional_group', items: [{ key: 'foo', required_subitems: [{ value: 'bar' }], optional_subitems: [{ not_value: 'baz' }] }] expect(last_response.status).to eq(400) - expect(last_response.body).to eq('items[optional_subitems][value] is missing') + expect(last_response.body).to eq('items[0][optional_subitems][0][value] is missing') get '/nested_optional_group', items: [{ key: 'foo', required_subitems: [{ value: 'bar' }], optional_subitems: [{ value: 'baz' }] }] expect(last_response.status).to eq(200) expect(last_response.body).to eq('nested optional group works') end it 'handles validation within arrays' do get '/nested_optional_group', items: [{ key: 'foo' }] expect(last_response.status).to eq(400) - expect(last_response.body).to eq('items[required_subitems] is missing') + expect(last_response.body).to eq('items[0][required_subitems] is missing') get '/nested_optional_group', items: [{ key: 'foo', required_subitems: [{ value: 'bar' }] }] expect(last_response.status).to eq(200) expect(last_response.body).to eq('nested optional group works') get '/nested_optional_group', items: [{ key: 'foo', required_subitems: [{ value: 'bar' }], optional_subitems: [{ not_value: 'baz' }] }] expect(last_response.status).to eq(400) - expect(last_response.body).to eq('items[optional_subitems][value] is missing') + expect(last_response.body).to eq('items[0][optional_subitems][0][value] is missing') end it 'adds to declared parameters' do subject.params do optional :items, type: Array do @@ -761,13 +791,12 @@ context 'custom validation' do module CustomValidations class Customvalidator < Grape::Validations::Base def validate_param!(attr_name, params) - unless params[attr_name] == 'im custom' - fail Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message: 'is not custom!' - end + return if params[attr_name] == 'im custom' + fail Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message: 'is not custom!' end end end context 'when using optional with a custom validator' do @@ -910,13 +939,12 @@ context 'when using options on param' do module CustomValidations class CustomvalidatorWithOptions < Grape::Validations::Base def validate_param!(attr_name, params) - unless params[attr_name] == @option[:text] - fail Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message: @option[:error_message] - end + return if params[attr_name] == @option[:text] + fail Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message: @option[:error_message] end end end before do @@ -948,28 +976,29 @@ end end end it 'in helper module which kind of Grape::DSL::Helpers::BaseHelper' do - module SharedParams + shared_params = Module.new do extend Grape::DSL::Helpers::BaseHelper params :pagination do end end - subject.helpers SharedParams + subject.helpers shared_params end end context 'can be included in usual params' do before do - module SharedParams + shared_params = Module.new do extend Grape::DSL::Helpers::BaseHelper params :period do optional :start_date optional :end_date end end - subject.helpers SharedParams + + subject.helpers shared_params subject.helpers do params :pagination do optional :page, type: Integer optional :per_page, type: Integer