Skip to content

Commit bec9e5f

Browse files
[Validator] Add CompoundConstraintTestCase to ease testing Compound Constraints
1 parent dae3dfe commit bec9e5f

File tree

1 file changed

+74
-0
lines changed

1 file changed

+74
-0
lines changed

validation/custom_constraint.rst

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,9 @@ A class constraint validator must be applied to the class itself:
502502
Testing Custom Constraints
503503
--------------------------
504504

505+
Atomic Constraints
506+
~~~~~~~~~~~~~~~~~~
507+
505508
Use the :class:`Symfony\\Component\\Validator\\Test\\ConstraintValidatorTestCase`
506509
class to simplify writing unit tests for your custom constraints::
507510

@@ -545,3 +548,74 @@ class to simplify writing unit tests for your custom constraints::
545548
// ...
546549
}
547550
}
551+
552+
Compound Constraints
553+
~~~~~~~~~~~~~~~~~~~~
554+
555+
Let's say you create a compound constraint that checks if a string meets
556+
your minimum requirements for your password policy::
557+
558+
// src/Validator/PasswordRequirements.php
559+
namespace App\Validator;
560+
561+
use Symfony\Component\Validator\Constraints as Assert;
562+
563+
#[\Attribute]
564+
class PasswordRequirements extends Assert\Compound
565+
{
566+
protected function getConstraints(array $options): array
567+
{
568+
return [
569+
new Assert\NotBlank(allowNull: false),
570+
new Assert\Length(min: 8, max: 255),
571+
new Assert\NotCompromisedPassword(),
572+
new Assert\Type('string'),
573+
new Assert\Regex('/[A-Z]+/'),
574+
];
575+
}
576+
}
577+
578+
You can use the :class:`Symfony\\Component\\Validator\\Test\\CompoundConstraintTestCase`
579+
class to check precisely which of the constraints failed to pass::
580+
581+
// tests/Validator/PasswordRequirementsTest.php
582+
namespace App\Tests\Validator;
583+
584+
use App\Validator\PasswordRequirements;
585+
use Symfony\Component\Validator\Constraints as Assert;
586+
use Symfony\Component\Validator\Test\CompoundConstraintTestCase;
587+
588+
/**
589+
* @extends CompoundConstraintTestCase<PasswordRequirements>
590+
*/
591+
class PasswordRequirementsTest extends CompoundConstraintTestCase
592+
{
593+
public function createCompound(): Assert\Compound
594+
{
595+
return new PasswordRequirements();
596+
}
597+
598+
public function testInvalidPassword(): void
599+
{
600+
$this->validateValue('azerty123');
601+
602+
// check all constraints pass except for the
603+
// password leak and the uppercase letter checks
604+
$this->assertViolationsRaisedByCompound([
605+
new Assert\NotCompromisedPassword(),
606+
new Assert\Regex('/[A-Z]+/'),
607+
]);
608+
}
609+
610+
public function testValid(): void
611+
{
612+
$this->validateValue('VERYSTR0NGP4$$WORD#%!');
613+
614+
$this->assertNoViolation();
615+
}
616+
}
617+
618+
.. versionadded:: 7.2
619+
620+
The :class:`Symfony\\Component\\Validator\\Test\\CompoundConstraintTestCase`
621+
class was introduced in Symfony 7.2.

0 commit comments

Comments
 (0)