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.
293 lines
8.5 KiB
Ruby
293 lines
8.5 KiB
Ruby
def entity_stub(entity, data={})
|
|
entity_class = Fabricate.schematic(entity).options[:class_name]
|
|
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
|
|
|
|
ALPHANUMERIC_RANGE = [*"0".."9", *"A".."Z", *"a".."z"].freeze
|
|
|
|
def alphanumeric_string(length)
|
|
Array.new(length) { ALPHANUMERIC_RANGE.sample }.join
|
|
end
|
|
|
|
shared_examples "a common validator" do
|
|
it "validates a well-formed instance" do
|
|
validator = described_class.new(entity_stub(entity))
|
|
expect(validator).to be_valid
|
|
expect(validator.errors).to be_empty
|
|
end
|
|
end
|
|
|
|
shared_examples "a relayable validator" do
|
|
it_behaves_like "a diaspora* ID validator" do
|
|
let(:property) { :author }
|
|
end
|
|
|
|
describe "#guid" do
|
|
it_behaves_like "a guid validator" do
|
|
let(:property) { :guid }
|
|
end
|
|
end
|
|
|
|
describe "#parent_guid" do
|
|
it_behaves_like "a guid validator" do
|
|
let(:property) { :parent_guid }
|
|
end
|
|
end
|
|
|
|
describe "#parent" do
|
|
it_behaves_like "a property with a value validation/restriction" do
|
|
let(:property) { :parent }
|
|
let(:wrong_values) { [nil] }
|
|
let(:correct_values) { [Fabricate(:related_entity)] }
|
|
end
|
|
end
|
|
end
|
|
|
|
shared_examples "a property with a value validation/restriction" do
|
|
it "fails if a wrong value is supplied" do
|
|
wrong_values.each do |val|
|
|
validator = described_class.new(entity_stub(entity, property => val))
|
|
expect(validator).not_to be_valid
|
|
expect(validator.errors).to include(property)
|
|
end
|
|
end
|
|
|
|
it "validates if a correct value is supplied" do
|
|
correct_values.each do |val|
|
|
validator = described_class.new(entity_stub(entity, property => val))
|
|
expect(validator).to be_valid
|
|
expect(validator.errors).to be_empty
|
|
end
|
|
end
|
|
end
|
|
|
|
shared_examples "a property that mustn't be empty" do
|
|
it_behaves_like "a property with a value validation/restriction" do
|
|
let(:wrong_values) { ["", nil] }
|
|
let(:correct_values) { [] }
|
|
end
|
|
end
|
|
|
|
shared_examples "a diaspora* ID validator" do
|
|
it "must not be nil or empty if mandatory" do
|
|
[nil, ""].each do |val|
|
|
validator = described_class.new(entity_stub(entity, property => val))
|
|
|
|
expect(validator).not_to be_valid
|
|
expect(validator.errors).to include(property)
|
|
end
|
|
end
|
|
|
|
it "validates a well-formed diaspora* ID" do
|
|
validator = described_class.new(entity_stub(entity, property => "alice@example.org"))
|
|
|
|
expect(validator).to be_valid
|
|
expect(validator.errors).to be_empty
|
|
end
|
|
|
|
it "must be a valid diaspora* ID" do
|
|
validator = described_class.new(entity_stub(entity, property => "i am a weird diaspora* ID @@@ ### 12345"))
|
|
|
|
expect(validator).not_to be_valid
|
|
expect(validator.errors).to include(property)
|
|
end
|
|
end
|
|
|
|
shared_examples "common guid validator" do
|
|
it "validates a well-formed guid from redmatrix" do
|
|
validator = described_class.new(entity_stub(entity, property => "1234567890ABCDefgh_ijkl-mnopQR@example.com:3000"))
|
|
|
|
expect(validator).to be_valid
|
|
expect(validator.errors).to be_empty
|
|
end
|
|
|
|
it "must be at least 16 chars" do
|
|
validator = described_class.new(entity_stub(entity, property => "aaaaaa"))
|
|
|
|
expect(validator).not_to be_valid
|
|
expect(validator.errors).to include(property)
|
|
end
|
|
|
|
it "must only contain [0-9a-z-_@.:]" do
|
|
validator = described_class.new(entity_stub(entity, property => "zzz+-#*$$"))
|
|
|
|
expect(validator).not_to be_valid
|
|
expect(validator.errors).to include(property)
|
|
end
|
|
end
|
|
|
|
shared_examples "a guid validator" do
|
|
include_examples "common guid validator"
|
|
|
|
it "must not be nil or empty" do
|
|
[nil, ""].each do |val|
|
|
validator = described_class.new(entity_stub(entity, property => val))
|
|
|
|
expect(validator).not_to be_valid
|
|
expect(validator.errors).to include(property)
|
|
end
|
|
end
|
|
end
|
|
|
|
shared_examples "a nilable guid validator" do
|
|
include_examples "common guid validator"
|
|
|
|
it "can be nil" do
|
|
validator = described_class.new(entity_stub(entity, property => nil))
|
|
|
|
expect(validator).to be_valid
|
|
expect(validator.errors).to be_empty
|
|
end
|
|
end
|
|
|
|
shared_examples "a boolean validator" do
|
|
it "validates a well-formed boolean" do
|
|
[true, "true", false, "false"].each do |val|
|
|
validator = described_class.new(entity_stub(entity, property => val))
|
|
|
|
expect(validator).to be_valid
|
|
expect(validator.errors).to be_empty
|
|
end
|
|
end
|
|
|
|
it "must not be an arbitrary string or other object" do
|
|
["asdf", Date.today, 1234].each do |val|
|
|
validator = described_class.new(entity_stub(entity, property => val))
|
|
|
|
expect(validator).not_to be_valid
|
|
expect(validator.errors).to include(property)
|
|
end
|
|
end
|
|
end
|
|
|
|
shared_examples "a public key validator" do
|
|
it "fails for malformed rsa key" do
|
|
validator = described_class.new(entity_stub(entity, property => "ASDF"))
|
|
|
|
expect(validator).not_to be_valid
|
|
expect(validator.errors).to include(property)
|
|
end
|
|
|
|
it "must not be nil or empty" do
|
|
[nil, ""].each do |val|
|
|
validator = described_class.new(entity_stub(entity, property => val))
|
|
|
|
expect(validator).not_to be_valid
|
|
expect(validator.errors).to include(property)
|
|
end
|
|
end
|
|
end
|
|
|
|
shared_examples "a name validator" do
|
|
it "is allowed to be nil or empty" do
|
|
[nil, ""].each do |val|
|
|
validator = described_class.new(entity_stub(entity, property => val))
|
|
|
|
expect(validator).to be_valid
|
|
expect(validator.errors).to be_empty
|
|
end
|
|
end
|
|
|
|
it "is allowed to contain special chars" do
|
|
validator = described_class.new(entity_stub(entity, property => "cool name ©"))
|
|
|
|
expect(validator).to be_valid
|
|
expect(validator.errors).to be_empty
|
|
end
|
|
|
|
it "validates the maximum number of chars" do
|
|
validator = described_class.new(entity_stub(entity, property => alphanumeric_string(length)))
|
|
|
|
expect(validator).to be_valid
|
|
expect(validator.errors).to be_empty
|
|
end
|
|
|
|
it "must not exceed the maximum number of chars" do
|
|
validator = described_class.new(entity_stub(entity, property => alphanumeric_string(length + 1)))
|
|
|
|
expect(validator).not_to be_valid
|
|
expect(validator.errors).to include(property)
|
|
end
|
|
|
|
it "must not contain semicolons" do
|
|
validator = described_class.new(entity_stub(entity, property => "asdf;qwer;yxcv"))
|
|
|
|
expect(validator).not_to be_valid
|
|
expect(validator.errors).to include(property)
|
|
end
|
|
end
|
|
|
|
shared_examples "a length validator" do
|
|
it "is allowed to be nil or empty" do
|
|
[nil, ""].each do |val|
|
|
validator = described_class.new(entity_stub(entity, property => val))
|
|
|
|
expect(validator).to be_valid
|
|
expect(validator.errors).to be_empty
|
|
end
|
|
end
|
|
|
|
it "is allowed to contain special chars" do
|
|
validator = described_class.new(entity_stub(entity, property => "cool name ©;:#%"))
|
|
|
|
expect(validator).to be_valid
|
|
expect(validator.errors).to be_empty
|
|
end
|
|
|
|
it "validates the maximum number of chars" do
|
|
validator = described_class.new(entity_stub(entity, property => alphanumeric_string(length)))
|
|
|
|
expect(validator).to be_valid
|
|
expect(validator.errors).to be_empty
|
|
end
|
|
|
|
it "must not exceed the maximum number of chars" do
|
|
validator = described_class.new(entity_stub(entity, property => alphanumeric_string(length + 1)))
|
|
|
|
expect(validator).not_to be_valid
|
|
expect(validator.errors).to include(property)
|
|
end
|
|
end
|
|
|
|
shared_examples "a url validator without path" do
|
|
it "must not be nil or empty" do
|
|
[nil, ""].each do |val|
|
|
validator = described_class.new(entity_stub(entity, property => val))
|
|
|
|
expect(validator).not_to be_valid
|
|
expect(validator.errors).to include(property)
|
|
end
|
|
end
|
|
|
|
it "fails for url with special chars" do
|
|
validator = described_class.new(entity_stub(entity, property => "https://asdf$%.com"))
|
|
|
|
expect(validator).not_to be_valid
|
|
expect(validator.errors).to include(property)
|
|
end
|
|
|
|
it "fails for url without scheme" do
|
|
validator = described_class.new(entity_stub(entity, property => "example.com"))
|
|
|
|
expect(validator).not_to be_valid
|
|
expect(validator.errors).to include(property)
|
|
end
|
|
end
|
|
|
|
shared_examples "a url path validator" do
|
|
it "fails for url with special chars" do
|
|
validator = described_class.new(entity_stub(entity, property => "https://asdf$%.com/some/path"))
|
|
|
|
expect(validator).not_to be_valid
|
|
expect(validator.errors).to include(property)
|
|
end
|
|
|
|
it "fails for url without path" do
|
|
validator = described_class.new(entity_stub(entity, property => "https://example.com"))
|
|
|
|
expect(validator).not_to be_valid
|
|
expect(validator.errors).to include(property)
|
|
end
|
|
end
|