<?php
namespace Symfony\Component\Validator\Tests;
use Symfony\Component\Validator\Tests\Fixtures\FakeMetadataFactory;
use Symfony\Component\Validator\Constraints\Valid;
use Symfony\Component\Validator\Tests\Fixtures\Reference;
use Symfony\Component\Validator\DefaultTranslator;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\Tests\Fixtures\FailingConstraint;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintAValidator;
use Symfony\Component\Validator\Tests\Fixtures\Entity;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\ConstraintValidatorFactory;
use Symfony\Component\Validator\ValidationVisitor;
class ValidationVisitorTest extends \PHPUnit_Framework_TestCase {
const CLASS_NAME = 'Symfony\\Component\\Validator\\Tests\\Fixtures\\Entity';
private $visitor;
private $metadataFactory;
private $metadata;
protected function setUp() {
$this->metadataFactory = new FakeMetadataFactory();
$this->visitor = new ValidationVisitor('Root', $this->metadataFactory, new ConstraintValidatorFactory(), new DefaultTranslator());
$this->metadata = new ClassMetadata(self::CLASS_NAME);
$this->metadataFactory
->addMetadata($this->metadata);
}
protected function tearDown() {
$this->metadataFactory = null;
$this->visitor = null;
$this->metadata = null;
}
public function testValidatePassesCorrectClassAndProperty() {
$this->metadata
->addConstraint(new ConstraintA());
$entity = new Entity();
$this->visitor
->validate($entity, 'Default', '');
$context = ConstraintAValidator::$passedContext;
$this
->assertEquals('Symfony\\Component\\Validator\\Tests\\Fixtures\\Entity', $context
->getClassName());
$this
->assertNull($context
->getPropertyName());
}
public function testValidateConstraints() {
$this->metadata
->addConstraint(new ConstraintA());
$this->visitor
->validate(new Entity(), 'Default', '');
$this
->assertCount(1, $this->visitor
->getViolations());
}
public function testValidateTwiceValidatesConstraintsOnce() {
$this->metadata
->addConstraint(new ConstraintA());
$entity = new Entity();
$this->visitor
->validate($entity, 'Default', '');
$this->visitor
->validate($entity, 'Default', '');
$this
->assertCount(1, $this->visitor
->getViolations());
}
public function testValidateDifferentObjectsValidatesTwice() {
$this->metadata
->addConstraint(new ConstraintA());
$this->visitor
->validate(new Entity(), 'Default', '');
$this->visitor
->validate(new Entity(), 'Default', '');
$this
->assertCount(2, $this->visitor
->getViolations());
}
public function testValidateTwiceInDifferentGroupsValidatesTwice() {
$this->metadata
->addConstraint(new ConstraintA());
$this->metadata
->addConstraint(new ConstraintA(array(
'groups' => 'Custom',
)));
$entity = new Entity();
$this->visitor
->validate($entity, 'Default', '');
$this->visitor
->validate($entity, 'Custom', '');
$this
->assertCount(2, $this->visitor
->getViolations());
}
public function testValidatePropertyConstraints() {
$this->metadata
->addPropertyConstraint('firstName', new ConstraintA());
$this->visitor
->validate(new Entity(), 'Default', '');
$this
->assertCount(1, $this->visitor
->getViolations());
}
public function testValidateGetterConstraints() {
$this->metadata
->addGetterConstraint('lastName', new ConstraintA());
$this->visitor
->validate(new Entity(), 'Default', '');
$this
->assertCount(1, $this->visitor
->getViolations());
}
public function testValidateInDefaultGroupTraversesGroupSequence() {
$entity = new Entity();
$this->metadata
->addPropertyConstraint('firstName', new FailingConstraint(array(
'groups' => 'First',
)));
$this->metadata
->addGetterConstraint('lastName', new FailingConstraint(array(
'groups' => 'Default',
)));
$this->metadata
->setGroupSequence(array(
'First',
$this->metadata
->getDefaultGroup(),
));
$this->visitor
->validate($entity, 'Default', '');
$violations = new ConstraintViolationList(array(
new ConstraintViolation('Failed', 'Failed', array(), 'Root', 'firstName', ''),
));
$this
->assertEquals($violations, $this->visitor
->getViolations());
}
public function testValidateInGroupSequencePropagatesDefaultGroup() {
$entity = new Entity();
$entity->reference = new Reference();
$this->metadata
->addPropertyConstraint('reference', new Valid());
$this->metadata
->setGroupSequence(array(
$this->metadata
->getDefaultGroup(),
));
$referenceMetadata = new ClassMetadata(get_class($entity->reference));
$referenceMetadata
->addConstraint(new FailingConstraint(array(
'groups' => 'Default',
)));
$this->metadataFactory
->addMetadata($referenceMetadata);
$this->visitor
->validate($entity, 'Default', '');
$violations = new ConstraintViolationList(array(
new ConstraintViolation('Failed', 'Failed', array(), 'Root', 'reference', $entity->reference),
));
$this
->assertEquals($violations, $this->visitor
->getViolations());
}
public function testValidateInOtherGroupTraversesNoGroupSequence() {
$entity = new Entity();
$this->metadata
->addPropertyConstraint('firstName', new FailingConstraint(array(
'groups' => 'First',
)));
$this->metadata
->addGetterConstraint('lastName', new FailingConstraint(array(
'groups' => $this->metadata
->getDefaultGroup(),
)));
$this->metadata
->setGroupSequence(array(
'First',
$this->metadata
->getDefaultGroup(),
));
$this->visitor
->validate($entity, $this->metadata
->getDefaultGroup(), '');
$violations = new ConstraintViolationList(array(
new ConstraintViolation('Failed', 'Failed', array(), 'Root', 'lastName', ''),
));
$this
->assertEquals($violations, $this->visitor
->getViolations());
}
public function testValidateCascadedPropertyValidatesReferences() {
$entity = new Entity();
$entity->reference = new Entity();
$this->metadata
->addConstraint(new FailingConstraint());
$this->metadata
->addPropertyConstraint('reference', new Valid());
$this->visitor
->validate($entity, 'Default', '');
$violations = new ConstraintViolationList(array(
new ConstraintViolation('Failed', 'Failed', array(), 'Root', '', $entity),
new ConstraintViolation('Failed', 'Failed', array(), 'Root', 'reference', $entity->reference),
));
$this
->assertEquals($violations, $this->visitor
->getViolations());
}
public function testValidateCascadedPropertyValidatesArraysByDefault() {
$entity = new Entity();
$entity->reference = array(
'key' => new Entity(),
);
$this->metadata
->addConstraint(new FailingConstraint());
$this->metadata
->addPropertyConstraint('reference', new Valid());
$this->visitor
->validate($entity, 'Default', '');
$violations = new ConstraintViolationList(array(
new ConstraintViolation('Failed', 'Failed', array(), 'Root', '', $entity),
new ConstraintViolation('Failed', 'Failed', array(), 'Root', 'reference[key]', $entity->reference['key']),
));
$this
->assertEquals($violations, $this->visitor
->getViolations());
}
public function testValidateCascadedPropertyValidatesTraversableByDefault() {
$entity = new Entity();
$entity->reference = new \ArrayIterator(array(
'key' => new Entity(),
));
$this->metadata
->addConstraint(new FailingConstraint());
$this->metadata
->addPropertyConstraint('reference', new Valid());
$this->visitor
->validate($entity, 'Default', '');
$violations = new ConstraintViolationList(array(
new ConstraintViolation('Failed', 'Failed', array(), 'Root', '', $entity),
new ConstraintViolation('Failed', 'Failed', array(), 'Root', 'reference[key]', $entity->reference['key']),
));
$this
->assertEquals($violations, $this->visitor
->getViolations());
}
public function testValidateCascadedPropertyDoesNotValidateTraversableIfDisabled() {
$entity = new Entity();
$entity->reference = new \ArrayIterator(array(
'key' => new Entity(),
));
$this->metadataFactory
->addMetadata(new ClassMetadata('ArrayIterator'));
$this->metadata
->addConstraint(new FailingConstraint());
$this->metadata
->addPropertyConstraint('reference', new Valid(array(
'traverse' => false,
)));
$this->visitor
->validate($entity, 'Default', '');
$violations = new ConstraintViolationList(array(
new ConstraintViolation('Failed', 'Failed', array(), 'Root', '', $entity),
));
$this
->assertEquals($violations, $this->visitor
->getViolations());
}
public function testMetadataMayNotExistIfTraversalIsEnabled() {
$entity = new Entity();
$entity->reference = new \ArrayIterator();
$this->metadata
->addPropertyConstraint('reference', new Valid(array(
'traverse' => true,
)));
$this->visitor
->validate($entity, 'Default', '');
}
public function testMetadataMustExistIfTraversalIsDisabled() {
$entity = new Entity();
$entity->reference = new \ArrayIterator();
$this->metadata
->addPropertyConstraint('reference', new Valid(array(
'traverse' => false,
)));
$this->visitor
->validate($entity, 'Default', '');
}
public function testValidateCascadedPropertyDoesNotRecurseByDefault() {
$entity = new Entity();
$entity->reference = new \ArrayIterator(array(
'key' => new \ArrayIterator(array(
'nested' => new Entity(),
)),
));
$this->metadataFactory
->addMetadata(new ClassMetadata('ArrayIterator'));
$this->metadata
->addConstraint(new FailingConstraint());
$this->metadata
->addPropertyConstraint('reference', new Valid());
$this->visitor
->validate($entity, 'Default', '');
$violations = new ConstraintViolationList(array(
new ConstraintViolation('Failed', 'Failed', array(), 'Root', '', $entity),
));
$this
->assertEquals($violations, $this->visitor
->getViolations());
}
public function testValidateCascadedPropertyRecursesArraysByDefault() {
$entity = new Entity();
$entity->reference = array(
'key' => array(
'nested' => new Entity(),
),
);
$this->metadata
->addConstraint(new FailingConstraint());
$this->metadata
->addPropertyConstraint('reference', new Valid());
$this->visitor
->validate($entity, 'Default', '');
$violations = new ConstraintViolationList(array(
new ConstraintViolation('Failed', 'Failed', array(), 'Root', '', $entity),
new ConstraintViolation('Failed', 'Failed', array(), 'Root', 'reference[key][nested]', $entity->reference['key']['nested']),
));
$this
->assertEquals($violations, $this->visitor
->getViolations());
}
public function testValidateCascadedPropertyRecursesIfDeepIsSet() {
$entity = new Entity();
$entity->reference = new \ArrayIterator(array(
'key' => new \ArrayIterator(array(
'nested' => new Entity(),
)),
));
$this->metadata
->addConstraint(new FailingConstraint());
$this->metadata
->addPropertyConstraint('reference', new Valid(array(
'deep' => true,
)));
$this->visitor
->validate($entity, 'Default', '');
$violations = new ConstraintViolationList(array(
new ConstraintViolation('Failed', 'Failed', array(), 'Root', '', $entity),
new ConstraintViolation('Failed', 'Failed', array(), 'Root', 'reference[key][nested]', $entity->reference['key']['nested']),
));
$this
->assertEquals($violations, $this->visitor
->getViolations());
}
public function testValidateCascadedPropertyDoesNotValidateNestedScalarValues() {
$entity = new Entity();
$entity->reference = array(
'scalar',
'values',
);
$this->metadata
->addPropertyConstraint('reference', new Valid());
$this->visitor
->validate($entity, 'Default', '');
$this
->assertCount(0, $this->visitor
->getViolations());
}
public function testValidateCascadedPropertyDoesNotValidateNullValues() {
$entity = new Entity();
$entity->reference = null;
$this->metadata
->addPropertyConstraint('reference', new Valid());
$this->visitor
->validate($entity, 'Default', '');
$this
->assertCount(0, $this->visitor
->getViolations());
}
public function testValidateCascadedPropertyRequiresObjectOrArray() {
$entity = new Entity();
$entity->reference = 'no object';
$this->metadata
->addPropertyConstraint('reference', new Valid());
$this->visitor
->validate($entity, 'Default', '');
}
}