Skip to content

Commit 36e08c9

Browse files
authored
Added Symfony validator assertions (#189)
1 parent 3bbf45c commit 36e08c9

File tree

3 files changed

+109
-0
lines changed

3 files changed

+109
-0
lines changed

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"symfony/security-csrf": "^5.4 | ^6.4 | ^7.0",
5050
"symfony/security-http": "^5.4 | ^6.4 | ^7.0",
5151
"symfony/twig-bundle": "^5.4 | ^6.4 | ^7.0",
52+
"symfony/validator": "^5.4 | ^6.4 | ^7.0",
5253
"symfony/var-exporter": "^5.4 | ^6.4 | ^7.0",
5354
"vlucas/phpdotenv": "^4.2 | ^5.4"
5455
},

src/Codeception/Module/Symfony.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
use Codeception\Module\Symfony\SessionAssertionsTrait;
2525
use Codeception\Module\Symfony\TimeAssertionsTrait;
2626
use Codeception\Module\Symfony\TwigAssertionsTrait;
27+
use Codeception\Module\Symfony\ValidatorAssertionsTrait;
2728
use Codeception\TestInterface;
2829
use Doctrine\ORM\EntityManagerInterface;
2930
use Exception;
@@ -145,6 +146,7 @@ class Symfony extends Framework implements DoctrineProvider, PartedModule
145146
use SessionAssertionsTrait;
146147
use TimeAssertionsTrait;
147148
use TwigAssertionsTrait;
149+
use ValidatorAssertionsTrait;
148150

149151
public Kernel $kernel;
150152

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Codeception\Module\Symfony;
6+
7+
use Symfony\Component\Validator\ConstraintViolationInterface;
8+
use Symfony\Component\Validator\Validator\ValidatorInterface;
9+
10+
trait ValidatorAssertionsTrait
11+
{
12+
/**
13+
* Asserts that the given subject fails validation.
14+
* This assertion does not concern the exact number of violations.
15+
*
16+
* ```php
17+
* <?php
18+
* $I->dontSeeViolatedConstraint($subject);
19+
* $I->dontSeeViolatedConstraint($subject, 'propertyName');
20+
* $I->dontSeeViolatedConstraint($subject, 'propertyName', 'Symfony\Validator\ConstraintClass');
21+
* ```
22+
*/
23+
public function dontSeeViolatedConstraint(mixed $subject, ?string $propertyPath = null, ?string $constraint = null): void
24+
{
25+
$violations = $this->getViolationsForSubject($subject, $propertyPath, $constraint);
26+
$this->assertCount(0, $violations, 'Constraint violations found.');
27+
}
28+
29+
/**
30+
* Asserts that the given subject passes validation.
31+
* This assertion does not concern the exact number of violations.
32+
*
33+
* ```php
34+
* <?php
35+
* $I->seeViolatedConstraint($subject);
36+
* $I->seeViolatedConstraint($subject, 'propertyName');
37+
* $I->seeViolatedConstraint($subject, 'propertyName', 'Symfony\Validator\ConstraintClass');
38+
* ```
39+
*/
40+
public function seeViolatedConstraint(mixed $subject, ?string $propertyPath = null, ?string $constraint = null): void
41+
{
42+
$violations = $this->getViolationsForSubject($subject, $propertyPath, $constraint);
43+
$this->assertNotCount(0, $violations, 'No constraint violations found.');
44+
}
45+
46+
/**
47+
* Asserts the exact number of violations for the given subject.
48+
*
49+
* ```php
50+
* <?php
51+
* $I->seeViolatedConstraintsCount(3, $subject);
52+
* $I->seeViolatedConstraintsCount(2, $subject, 'propertyName');
53+
* ```
54+
*/
55+
public function seeViolatedConstraintsCount(int $expected, mixed $subject, ?string $propertyPath = null, ?string $constraint = null): void
56+
{
57+
$violations = $this->getViolationsForSubject($subject, $propertyPath, $constraint);
58+
$this->assertCount($expected, $violations);
59+
}
60+
61+
/**
62+
* Asserts that a constraint violation message or a part of it is present in the subject's violations.
63+
*
64+
* ```php
65+
* <?php
66+
* $I->seeViolatedConstraintMessage('too short', $user, 'address');
67+
* ```
68+
*/
69+
public function seeViolatedConstraintMessage(string $expected, mixed $subject, string $propertyPath): void
70+
{
71+
$violations = $this->getViolationsForSubject($subject, $propertyPath);
72+
$containsExpected = false;
73+
foreach ($violations as $violation) {
74+
if ($violation->getPropertyPath() === $propertyPath && str_contains($violation->getMessage(), $expected)) {
75+
$containsExpected = true;
76+
break;
77+
}
78+
}
79+
80+
$this->assertTrue($containsExpected, 'The violation messages do not contain: ' . $expected);
81+
}
82+
83+
/** @return ConstraintViolationInterface[] */
84+
protected function getViolationsForSubject(mixed $subject, ?string $propertyPath = null, ?string $constraint = null): array
85+
{
86+
$validator = $this->getValidatorService();
87+
$violations = $propertyPath ? $validator->validateProperty($subject, $propertyPath) : $validator->validate($subject);
88+
89+
$violations = iterator_to_array($violations);
90+
91+
if ($constraint !== null) {
92+
return array_filter(
93+
$violations,
94+
static fn($violation): bool => $violation->getConstraint()::class === $constraint &&
95+
($propertyPath === null || $violation->getPropertyPath() === $propertyPath)
96+
);
97+
}
98+
99+
return $violations;
100+
}
101+
102+
protected function getValidatorService(): ValidatorInterface
103+
{
104+
return $this->grabService(ValidatorInterface::class);
105+
}
106+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy