Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added Symfony validator assertions (#189)
- Loading branch information
1 parent
3bbf45c
commit 36e08c9
Showing
3 changed files
with
109 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
106 changes: 106 additions & 0 deletions
106
src/Codeception/Module/Symfony/ValidatorAssertionsTrait.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Codeception\Module\Symfony; | ||
|
||
use Symfony\Component\Validator\ConstraintViolationInterface; | ||
use Symfony\Component\Validator\Validator\ValidatorInterface; | ||
|
||
trait ValidatorAssertionsTrait | ||
{ | ||
/** | ||
* Asserts that the given subject fails validation. | ||
* This assertion does not concern the exact number of violations. | ||
* | ||
* ```php | ||
* <?php | ||
* $I->dontSeeViolatedConstraint($subject); | ||
* $I->dontSeeViolatedConstraint($subject, 'propertyName'); | ||
* $I->dontSeeViolatedConstraint($subject, 'propertyName', 'Symfony\Validator\ConstraintClass'); | ||
* ``` | ||
*/ | ||
public function dontSeeViolatedConstraint(mixed $subject, ?string $propertyPath = null, ?string $constraint = null): void | ||
{ | ||
$violations = $this->getViolationsForSubject($subject, $propertyPath, $constraint); | ||
$this->assertCount(0, $violations, 'Constraint violations found.'); | ||
} | ||
|
||
/** | ||
* Asserts that the given subject passes validation. | ||
* This assertion does not concern the exact number of violations. | ||
* | ||
* ```php | ||
* <?php | ||
* $I->seeViolatedConstraint($subject); | ||
* $I->seeViolatedConstraint($subject, 'propertyName'); | ||
* $I->seeViolatedConstraint($subject, 'propertyName', 'Symfony\Validator\ConstraintClass'); | ||
* ``` | ||
*/ | ||
public function seeViolatedConstraint(mixed $subject, ?string $propertyPath = null, ?string $constraint = null): void | ||
{ | ||
$violations = $this->getViolationsForSubject($subject, $propertyPath, $constraint); | ||
$this->assertNotCount(0, $violations, 'No constraint violations found.'); | ||
} | ||
|
||
/** | ||
* Asserts the exact number of violations for the given subject. | ||
* | ||
* ```php | ||
* <?php | ||
* $I->seeViolatedConstraintsCount(3, $subject); | ||
* $I->seeViolatedConstraintsCount(2, $subject, 'propertyName'); | ||
* ``` | ||
*/ | ||
public function seeViolatedConstraintsCount(int $expected, mixed $subject, ?string $propertyPath = null, ?string $constraint = null): void | ||
{ | ||
$violations = $this->getViolationsForSubject($subject, $propertyPath, $constraint); | ||
$this->assertCount($expected, $violations); | ||
} | ||
|
||
/** | ||
* Asserts that a constraint violation message or a part of it is present in the subject's violations. | ||
* | ||
* ```php | ||
* <?php | ||
* $I->seeViolatedConstraintMessage('too short', $user, 'address'); | ||
* ``` | ||
*/ | ||
public function seeViolatedConstraintMessage(string $expected, mixed $subject, string $propertyPath): void | ||
{ | ||
$violations = $this->getViolationsForSubject($subject, $propertyPath); | ||
$containsExpected = false; | ||
foreach ($violations as $violation) { | ||
if ($violation->getPropertyPath() === $propertyPath && str_contains($violation->getMessage(), $expected)) { | ||
$containsExpected = true; | ||
break; | ||
} | ||
} | ||
|
||
$this->assertTrue($containsExpected, 'The violation messages do not contain: ' . $expected); | ||
} | ||
|
||
/** @return ConstraintViolationInterface[] */ | ||
protected function getViolationsForSubject(mixed $subject, ?string $propertyPath = null, ?string $constraint = null): array | ||
{ | ||
$validator = $this->getValidatorService(); | ||
$violations = $propertyPath ? $validator->validateProperty($subject, $propertyPath) : $validator->validate($subject); | ||
|
||
$violations = iterator_to_array($violations); | ||
|
||
if ($constraint !== null) { | ||
return array_filter( | ||
$violations, | ||
static fn($violation): bool => $violation->getConstraint()::class === $constraint && | ||
($propertyPath === null || $violation->getPropertyPath() === $propertyPath) | ||
); | ||
} | ||
|
||
return $violations; | ||
} | ||
|
||
protected function getValidatorService(): ValidatorInterface | ||
{ | ||
return $this->grabService(ValidatorInterface::class); | ||
} | ||
} |