diff --git a/README.md b/README.md index e2bb0ac..3bc9081 100644 --- a/README.md +++ b/README.md @@ -239,6 +239,45 @@ class MyCoolTest extends WebTestCase } ``` +## WithValidatorAssertionsTrait : Verify Validation Constraints after a request + +With this trait, you gain assertions methods which deal with Validation Constraints (requires WithClientTrait). + +```php +initializeClient(); + + // Don't forget to enable profiler before your request or none of this will work ! + $this->client->enableProfiler(); + + $this->post('/save', [ + 'firstName' => '', // It should create a violation + 'lastName' => 'Dupont', // It should not + 'age' => 2000 // It should create a violation + ]); + + // You can do some assertions about the validator's violations list + $this->assertNoValidatorErrors(); // Will fail + $this->assertValidatorErrorsCount(2); // Will succeed + $this->assertValidatorHasError('firstName'); // Will succeed + $this->assertValidatorHasErrors(['firstName', 'age']); // Will succeed + $this->assertValidatorHasErrors(['firstName', 'lastName']); // Will fail (since lastName did not violate a constraint) + } +} +``` + ## WithFakerTrait: Using faker made easy With this trait, you gain access to faker. diff --git a/src/Concerns/WithValidatorAssertionsTrait.php b/src/Concerns/WithValidatorAssertionsTrait.php new file mode 100644 index 0000000..28356a1 --- /dev/null +++ b/src/Concerns/WithValidatorAssertionsTrait.php @@ -0,0 +1,101 @@ +assertValidatorErrorsCount(0); + } + + /** + * Asserts that a specific number of errors occured in the validation process + */ + public function assertValidatorErrorsCount(int $count): self + { + $violations = $this->getViolationsCount($this->getProfile()); + + $this->assertEquals($count, $violations, sprintf('Failed asserting that validator had %s errors, %s found !', $count, $violations)); + + return $this; + } + + /** + * Asserts that the validator found an error for the specified propertyPath + */ + public function assertValidatorHasError(string $propertyPath): self + { + $violations = $this->createConstraintsViolationsArray($this->getProfile()); + + $this->assertArrayHasKey( + $propertyPath, + $violations, + sprintf('Failed asserting that "%s" has a validation error', $propertyPath) + ); + + return $this; + } + + /** + * Asserts that the validator found a set of errors for the specified properties + */ + public function assertValidatorHasErrors(array $properties): self + { + $violations = $this->createConstraintsViolationsArray($this->getProfile()); + + $notExistingProperties = []; + + foreach ($properties as $propertyPath) { + if (!array_key_exists($propertyPath, $violations)) { + $notExistingProperties[] = $propertyPath; + } + } + + $this->assertEquals( + 0, + count($notExistingProperties), + sprintf('Failed asserting that validator has these validation errors : %s', join(', ', $notExistingProperties)) + ); + + return $this; + } + + protected function getViolationsCount(Profile $profile): int + { + return $profile->getCollector('validator')->getViolationsCount(); + } + + protected function createConstraintsViolationsArray(Profile $profile): array + { + $calls = $profile->getCollector('validator')->getCalls(); + + $violations = []; + + foreach ($calls as $call) { + foreach ($call->violations as $violation) { + $propertyPath = str_replace('data.', '', $violation->propertyPath); + $violations[$propertyPath] = $violation->message; + } + } + + return $violations; + } + + protected function getProfile(): Profile + { + $profile = $this->client->getProfile(); + + if (!$profile) { + throw new ProfilerNotEnabledException(); + } + + return $profile; + } +} diff --git a/src/Exception/ProfilerNotEnabledException.php b/src/Exception/ProfilerNotEnabledException.php new file mode 100644 index 0000000..2aed5c1 --- /dev/null +++ b/src/Exception/ProfilerNotEnabledException.php @@ -0,0 +1,16 @@ +enableProfiler()' + )); + } +} diff --git a/src/WebTestCase.php b/src/WebTestCase.php index 7b03393..9e2a010 100644 --- a/src/WebTestCase.php +++ b/src/WebTestCase.php @@ -8,6 +8,7 @@ use Liior\SymfonyTestHelpers\Concerns\WithFakerTrait; use Liior\SymfonyTestHelpers\Concerns\WithClientTrait; use Liior\SymfonyTestHelpers\Concerns\WithContainerTrait; +use Liior\SymfonyTestHelpers\Concerns\WithValidatorAssertionsTrait; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase as BaseWebTestCase; class WebTestCase extends BaseWebTestCase @@ -18,4 +19,5 @@ class WebTestCase extends BaseWebTestCase use WithClientTrait; use WithDatabaseTrait; use WithFakerTrait; + use WithValidatorAssertionsTrait; }