Get optional props from validated object

This is much easier and safer than "guessing" the class name based on
the validator name. That can cause a problem when another class with the
same name is found. The "guessing" was only added because we used
OpenStruct in the tests, but we shouldn't change the code only to make
tests run. I changed the tests to use the real entities, with
auto-validation disabled in the constructor, so we can test the
validator manually.
This commit is contained in:
Benjamin Neff 2018-02-14 00:53:38 +01:00
parent 4a7a724118
commit 32a49cc549
No known key found for this signature in database
GPG key ID: 971464C3F1A90194
4 changed files with 20 additions and 21 deletions

View file

@ -41,7 +41,7 @@ module DiasporaFederation
Fabricator(:account_migration_entity, class_name: DiasporaFederation::Entities::AccountMigration) do Fabricator(:account_migration_entity, class_name: DiasporaFederation::Entities::AccountMigration) do
author { Fabricate.sequence(:diaspora_id) } author { Fabricate.sequence(:diaspora_id) }
profile { Fabricate(:profile_entity) } profile {|attrs| Fabricate(:profile_entity, author: attrs[:author]) }
old_identity { Fabricate.sequence(:diaspora_id) } old_identity { Fabricate.sequence(:diaspora_id) }
end end

View file

@ -13,10 +13,8 @@ module DiasporaFederation
private private
def optional_props def optional_props
entity_name = self.class.name.split("::").last.sub("Validator", "") return [] unless @obj.class.respond_to?(:optional_props)
return [] unless Entities.const_defined?(entity_name) @obj.class.optional_props
Entities.const_get(entity_name).optional_props
end end
end end
end end

View file

@ -1,47 +1,46 @@
module DiasporaFederation module DiasporaFederation
describe Validators::OptionalAwareValidator do describe Validators::OptionalAwareValidator do
let(:entity_data) { def entity_stub(additional_data={})
{test1: "abc", test2: true, test7: "abc", multi: []} allow_any_instance_of(Entities::TestComplexEntity).to receive(:freeze)
} allow_any_instance_of(Entities::TestComplexEntity).to receive(:validate)
entity_data = {test1: "abc", test2: true, test3: nil, test4: nil, test5: nil, test6: nil, test7: "abc", multi: []}
Entities::TestComplexEntity.new(entity_data.merge(additional_data))
end
it "validates a valid object" do it "validates a valid object" do
validator = Validators::TestComplexEntityValidator.new(OpenStruct.new(entity_data)) validator = Validators::TestComplexEntityValidator.new(entity_stub)
expect(validator).to be_valid expect(validator).to be_valid
expect(validator.errors).to be_empty expect(validator.errors).to be_empty
end end
it "fails when a mandatory property is invalid" do it "fails when a mandatory property is invalid" do
["ab", nil].each do |val| ["ab", nil].each do |val|
entity = OpenStruct.new(entity_data.merge(test1: val)) validator = Validators::TestComplexEntityValidator.new(entity_stub(test1: val))
validator = Validators::TestComplexEntityValidator.new(entity)
expect(validator).not_to be_valid expect(validator).not_to be_valid
expect(validator.errors).to include(:test1) expect(validator.errors).to include(:test1)
end end
end end
it "fails when an optional property is invalid" do it "fails when an optional property is invalid" do
entity = OpenStruct.new(entity_data.merge(test7: "ab")) validator = Validators::TestComplexEntityValidator.new(entity_stub(test7: "ab"))
validator = Validators::TestComplexEntityValidator.new(entity)
expect(validator).not_to be_valid expect(validator).not_to be_valid
expect(validator.errors).to include(:test7) expect(validator.errors).to include(:test7)
end end
it "allows an optional property to be nil" do it "allows an optional property to be nil" do
entity = OpenStruct.new(entity_data.merge(test7: nil)) validator = Validators::TestComplexEntityValidator.new(entity_stub(test7: nil))
validator = Validators::TestComplexEntityValidator.new(entity)
expect(validator).to be_valid expect(validator).to be_valid
expect(validator.errors).to be_empty expect(validator.errors).to be_empty
end end
it "doesn't ignore 'not_nil' rules for an optional property" do it "doesn't ignore 'not_nil' rules for an optional property" do
entity = OpenStruct.new(entity_data.merge(multi: nil)) validator = Validators::TestComplexEntityValidator.new(entity_stub(multi: nil))
validator = Validators::TestComplexEntityValidator.new(entity)
expect(validator).not_to be_valid expect(validator).not_to be_valid
expect(validator.errors).to include(:multi) expect(validator.errors).to include(:multi)
end end
it "doesn't fail when there is no entity for this validator" do it "doesn't fail when the entity doesn't have optional props" do
entity = OpenStruct.new(entity_data.merge(test1: nil)) entity = OpenStruct.new(test1: nil)
validator = Validators::TestUnknownEntityValidator.new(entity) validator = Validators::TestUnknownEntityValidator.new(entity)
expect(validator).not_to be_valid expect(validator).not_to be_valid
expect(validator.errors).to include(:test1) expect(validator.errors).to include(:test1)

View file

@ -1,6 +1,8 @@
def entity_stub(entity, data={}) def entity_stub(entity, data={})
OpenStruct.new(Fabricate.schematic(entity).options[:class_name].default_values entity_class = Fabricate.schematic(entity).options[:class_name]
.merge(Fabricate.attributes_for(entity)).merge(data)) allow_any_instance_of(entity_class).to receive(:freeze)
allow_any_instance_of(entity_class).to receive(:validate)
entity_class.new(Fabricate.attributes_for(entity).merge(data))
end end
ALPHANUMERIC_RANGE = [*"0".."9", *"A".."Z", *"a".."z"].freeze ALPHANUMERIC_RANGE = [*"0".."9", *"A".."Z", *"a".."z"].freeze