Skip to content

Commit 2aeaf5b

Browse files
[Validator] Add CompoundConstraintTestCase to ease testing Compound Constraint
1 parent 3d380c9 commit 2aeaf5b

File tree

6 files changed

+263
-14
lines changed

6 files changed

+263
-14
lines changed

src/Symfony/Component/Validator/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ CHANGELOG
1010
* Add a `NoSuspiciousCharacters` constraint to validate a string is not a spoofing attempt
1111
* Add the `countUnit` option to the `Length` constraint to allow counting the string length either by code points (like before, now the default setting `Length::COUNT_CODEPOINTS`), bytes (`Length::COUNT_BYTES`) or graphemes (`Length::COUNT_GRAPHEMES`)
1212
* Add the `filenameMaxLength` option to the `File` constraint
13+
* Add `CompoundConstraintTestCase` to ease testing Compound Constraint
1314

1415
6.2
1516
---
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Validator\Test;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Validator\Constraints\Compound;
16+
use Symfony\Component\Validator\Constraints\GroupSequence;
17+
use Symfony\Component\Validator\ConstraintViolationInterface;
18+
use Symfony\Component\Validator\ConstraintViolationListInterface;
19+
use Symfony\Component\Validator\Validation;
20+
use Symfony\Component\Validator\Validator\ValidatorInterface;
21+
22+
/**
23+
* A test case to ease testing Compound Constraint.
24+
*
25+
* @author Alexandre Daubois <alex.daubois@gmail.com>
26+
*/
27+
abstract class CompoundConstraintTestCase extends TestCase
28+
{
29+
protected ValidatorInterface $validator;
30+
31+
protected ?ConstraintViolationListInterface $violationList = null;
32+
33+
protected function setUp(): void
34+
{
35+
$this->validator = Validation::createValidator();
36+
}
37+
38+
protected function validateValue(mixed $value, array|string|GroupSequence $groups = null): void
39+
{
40+
$this->violationList = $this->validator->validate($value, $this->createCompound(), $groups);
41+
}
42+
43+
protected function assertViolationIsRaisedByCompound(string $code): void
44+
{
45+
if (null === $this->violationList) {
46+
throw new \LogicException('Value must be validated with the "validateValue()" method before asserting on compound violations.');
47+
}
48+
49+
$this->assertTrue($this->isViolationRaised($code), sprintf('Expected violation with code "%s" to be raised.', $code));
50+
}
51+
52+
protected function assertViolationIsNotRaisedByCompound(string $code): void
53+
{
54+
if (null === $this->violationList) {
55+
throw new \LogicException('Value must be validated with the "validateValue()" method before asserting on compound violations.');
56+
}
57+
58+
$this->assertFalse($this->isViolationRaised($code), sprintf('Expected violation with code "%s" to be raised.', $code));
59+
}
60+
61+
protected function assertViolationsAreRaisedByCompound(array $codes): void
62+
{
63+
if (null === $this->violationList) {
64+
throw new \LogicException('Value must be validated with the "validateValue()" method before asserting on compound violations.');
65+
}
66+
67+
$violationCodes = array_map(static fn (ConstraintViolationInterface $violation): string => $violation->getCode(), iterator_to_array($this->violationList));
68+
69+
$violationCodes = array_filter($violationCodes, static fn (string $violationCode): bool => !\in_array($violationCode, $codes, true));
70+
71+
$this->assertEmpty($violationCodes, sprintf('Some violations code have not been raised: %s.', implode(', ', $violationCodes)));
72+
}
73+
74+
protected function assertViolationCountRaisedByCompound(int $count): void
75+
{
76+
if (null === $this->violationList) {
77+
throw new \LogicException('Value must be validated with the "validateValue()" method before asserting on compound violations.');
78+
}
79+
80+
$this->assertCount($count, $this->violationList, sprintf('Expected %d violation to be raised, got %d.', $count, \count($this->violationList)));
81+
}
82+
83+
protected function assertNoViolation(): void
84+
{
85+
if (null === $this->violationList) {
86+
throw new \LogicException('Value must be validated with the "validateValue()" method before asserting on compound violations.');
87+
}
88+
89+
$this->assertCount(0, $this->violationList, sprintf('Expected no violations to be raised, got %d.', \count($this->violationList)));
90+
}
91+
92+
private function isViolationRaised(string $code): bool
93+
{
94+
foreach ($this->violationList as $violation) {
95+
if ($violation->getCode() === $code) {
96+
return true;
97+
}
98+
}
99+
100+
return false;
101+
}
102+
103+
abstract public function createCompound(): Compound;
104+
}

src/Symfony/Component/Validator/Tests/Constraints/CompoundValidatorTest.php

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,9 @@
1111

1212
namespace Symfony\Component\Validator\Tests\Constraints;
1313

14-
use Symfony\Component\Validator\Constraints\Compound;
1514
use Symfony\Component\Validator\Constraints\CompoundValidator;
16-
use Symfony\Component\Validator\Constraints\Length;
17-
use Symfony\Component\Validator\Constraints\NotBlank;
1815
use Symfony\Component\Validator\Test\ConstraintValidatorTestCase;
16+
use Symfony\Component\Validator\Tests\Fixtures\DummyCompoundConstraint;
1917

2018
class CompoundValidatorTest extends ConstraintValidatorTestCase
2119
{
@@ -43,14 +41,3 @@ public function testValidateWithConstraints()
4341
$this->assertNoViolation();
4442
}
4543
}
46-
47-
class DummyCompoundConstraint extends Compound
48-
{
49-
protected function getConstraints(array $options): array
50-
{
51-
return [
52-
new NotBlank(),
53-
new Length(['max' => 3]),
54-
];
55-
}
56-
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Validator\Tests\Fixtures;
13+
14+
use Symfony\Component\Validator\Constraints\Compound;
15+
use Symfony\Component\Validator\Constraints\Length;
16+
use Symfony\Component\Validator\Constraints\NotBlank;
17+
use Symfony\Component\Validator\Constraints\Regex;
18+
19+
class DummyCompoundConstraint extends Compound
20+
{
21+
protected function getConstraints(array $options): array
22+
{
23+
return [
24+
new NotBlank(),
25+
new Length(['max' => 3]),
26+
new Regex('/[a-z]+/'),
27+
];
28+
}
29+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Validator\Tests\Fixtures;
13+
14+
use Symfony\Component\Validator\Constraints\Compound;
15+
use Symfony\Component\Validator\Constraints\Length;
16+
use Symfony\Component\Validator\Constraints\NotBlank;
17+
use Symfony\Component\Validator\Constraints\Regex;
18+
19+
class DummyCompoundConstraintWithGroups extends Compound
20+
{
21+
protected function getConstraints(array $options): array
22+
{
23+
return [
24+
new NotBlank(groups: ['not_blank']),
25+
new Length(['max' => 3], groups: ['max_length']),
26+
];
27+
}
28+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Validator\Tests\Test;
13+
14+
use Symfony\Component\Validator\Constraints\Compound;
15+
use Symfony\Component\Validator\Constraints\Length;
16+
use Symfony\Component\Validator\Constraints\NotBlank;
17+
use Symfony\Component\Validator\Constraints\Regex;
18+
use Symfony\Component\Validator\Test\CompoundConstraintTestCase;
19+
use Symfony\Component\Validator\Tests\Fixtures\DummyCompoundConstraint;
20+
21+
class CompoundConstraintTestCaseTest extends CompoundConstraintTestCase
22+
{
23+
public function createCompound(): Compound
24+
{
25+
return new DummyCompoundConstraint();
26+
}
27+
28+
public function testAssertNoViolation()
29+
{
30+
$this->validateValue('abc');
31+
32+
$this->assertNoViolation();
33+
}
34+
35+
public function testAssertIsRaisedByCompound()
36+
{
37+
$this->validateValue('');
38+
39+
$this->assertViolationIsRaisedByCompound(NotBlank::IS_BLANK_ERROR);
40+
$this->assertViolationCountRaisedByCompound(1);
41+
}
42+
43+
public function testAssertIsNotRaisedByCompound()
44+
{
45+
$this->validateValue('abc');
46+
47+
$this->assertViolationIsNotRaisedByCompound(NotBlank::IS_BLANK_ERROR);
48+
}
49+
50+
public function testMultipleAssertAreRaisedByCompound()
51+
{
52+
$this->validateValue('1245');
53+
54+
$this->assertViolationsAreRaisedByCompound([
55+
Length::TOO_LONG_ERROR,
56+
Regex::REGEX_FAILED_ERROR,
57+
]);
58+
$this->assertViolationCountRaisedByCompound(2);
59+
}
60+
61+
public function testAssertIsRaisedByCompoundWithGroups()
62+
{
63+
$this->validateValue('', ['max_length']);
64+
65+
$this->assertViolationIsNotRaisedByCompound(NotBlank::IS_BLANK_ERROR);
66+
$this->assertViolationCountRaisedByCompound(0);
67+
}
68+
69+
public function testAssertViolationIsRaisedByCompoundWithoutValidate()
70+
{
71+
$this->expectException(\LogicException::class);
72+
$this->expectExceptionMessage('Value must be validated with the "validateValue()" method before asserting on compound violations.');
73+
74+
$this->assertViolationIsRaisedByCompound('code');
75+
}
76+
77+
public function testAssertViolationAreRaisedByCompoundWithoutValidate()
78+
{
79+
$this->expectException(\LogicException::class);
80+
$this->expectExceptionMessage('Value must be validated with the "validateValue()" method before asserting on compound violations.');
81+
82+
$this->assertViolationsAreRaisedByCompound(['code']);
83+
}
84+
85+
public function testAssertViolationCountRaisedByCompoundWithoutValidate()
86+
{
87+
$this->expectException(\LogicException::class);
88+
$this->expectExceptionMessage('Value must be validated with the "validateValue()" method before asserting on compound violations.');
89+
90+
$this->assertViolationCountRaisedByCompound(1);
91+
}
92+
93+
public function testAssertNoViolationWithoutValidate()
94+
{
95+
$this->expectException(\LogicException::class);
96+
$this->expectExceptionMessage('Value must be validated with the "validateValue()" method before asserting on compound violations.');
97+
98+
$this->assertNoViolation();
99+
}
100+
}

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