@@ -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+
505508Use the :class: `Symfony\\ Component\\ Validator\\ Test\\ ConstraintValidatorTestCase `
506509class 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