Merge branch '3.4' into 4.3
* 3.4: [Validator] Add ConstraintValidator::formatValue() tests [Validator] Sync string to date behavior and throw a better exception Check phpunit configuration for listeners
This commit is contained in:
commit
200281db40
@ -23,8 +23,6 @@ class CommandForV5 extends \PHPUnit_TextUI_Command
|
|||||||
*/
|
*/
|
||||||
protected function createRunner()
|
protected function createRunner()
|
||||||
{
|
{
|
||||||
$listener = new SymfonyTestsListenerForV5();
|
|
||||||
|
|
||||||
$this->arguments['listeners'] = isset($this->arguments['listeners']) ? $this->arguments['listeners'] : array();
|
$this->arguments['listeners'] = isset($this->arguments['listeners']) ? $this->arguments['listeners'] : array();
|
||||||
|
|
||||||
$registeredLocally = false;
|
$registeredLocally = false;
|
||||||
@ -37,8 +35,21 @@ class CommandForV5 extends \PHPUnit_TextUI_Command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($this->arguments['configuration'])) {
|
||||||
|
$configuration = $this->arguments['configuration'];
|
||||||
|
if (!$configuration instanceof \PHPUnit_Util_Configuration) {
|
||||||
|
$configuration = \PHPUnit_Util_Configuration::getInstance($this->arguments['configuration']);
|
||||||
|
}
|
||||||
|
foreach ($configuration->getListenerConfiguration() as $registeredListener) {
|
||||||
|
if ('Symfony\Bridge\PhpUnit\SymfonyTestsListener' === ltrim($registeredListener['class'], '\\')) {
|
||||||
|
$registeredLocally = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!$registeredLocally) {
|
if (!$registeredLocally) {
|
||||||
$this->arguments['listeners'][] = $listener;
|
$this->arguments['listeners'][] = new SymfonyTestsListenerForV5();
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::createRunner();
|
return parent::createRunner();
|
||||||
|
@ -13,6 +13,7 @@ namespace Symfony\Bridge\PhpUnit\Legacy;
|
|||||||
|
|
||||||
use PHPUnit\TextUI\Command as BaseCommand;
|
use PHPUnit\TextUI\Command as BaseCommand;
|
||||||
use PHPUnit\TextUI\TestRunner as BaseRunner;
|
use PHPUnit\TextUI\TestRunner as BaseRunner;
|
||||||
|
use PHPUnit\Util\Configuration;
|
||||||
use Symfony\Bridge\PhpUnit\SymfonyTestsListener;
|
use Symfony\Bridge\PhpUnit\SymfonyTestsListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -27,8 +28,6 @@ class CommandForV6 extends BaseCommand
|
|||||||
*/
|
*/
|
||||||
protected function createRunner(): BaseRunner
|
protected function createRunner(): BaseRunner
|
||||||
{
|
{
|
||||||
$listener = new SymfonyTestsListener();
|
|
||||||
|
|
||||||
$this->arguments['listeners'] = isset($this->arguments['listeners']) ? $this->arguments['listeners'] : [];
|
$this->arguments['listeners'] = isset($this->arguments['listeners']) ? $this->arguments['listeners'] : [];
|
||||||
|
|
||||||
$registeredLocally = false;
|
$registeredLocally = false;
|
||||||
@ -41,8 +40,21 @@ class CommandForV6 extends BaseCommand
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($this->arguments['configuration'])) {
|
||||||
|
$configuration = $this->arguments['configuration'];
|
||||||
|
if (!$configuration instanceof Configuration) {
|
||||||
|
$configuration = Configuration::getInstance($this->arguments['configuration']);
|
||||||
|
}
|
||||||
|
foreach ($configuration->getListenerConfiguration() as $registeredListener) {
|
||||||
|
if ('Symfony\Bridge\PhpUnit\SymfonyTestsListener' === ltrim($registeredListener['class'], '\\')) {
|
||||||
|
$registeredLocally = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!$registeredLocally) {
|
if (!$registeredLocally) {
|
||||||
$this->arguments['listeners'][] = $listener;
|
$this->arguments['listeners'][] = new SymfonyTestsListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::createRunner();
|
return parent::createRunner();
|
||||||
|
@ -85,12 +85,10 @@ abstract class ConstraintValidator implements ConstraintValidatorInterface
|
|||||||
*/
|
*/
|
||||||
protected function formatValue($value, $format = 0)
|
protected function formatValue($value, $format = 0)
|
||||||
{
|
{
|
||||||
$isDateTime = $value instanceof \DateTimeInterface;
|
if (($format & self::PRETTY_DATE) && $value instanceof \DateTimeInterface) {
|
||||||
|
|
||||||
if (($format & self::PRETTY_DATE) && $isDateTime) {
|
|
||||||
if (class_exists('IntlDateFormatter')) {
|
if (class_exists('IntlDateFormatter')) {
|
||||||
$locale = \Locale::getDefault();
|
$locale = \Locale::getDefault();
|
||||||
$formatter = new \IntlDateFormatter($locale, \IntlDateFormatter::MEDIUM, \IntlDateFormatter::SHORT);
|
$formatter = new \IntlDateFormatter($locale, \IntlDateFormatter::MEDIUM, \IntlDateFormatter::SHORT, $value->getTimezone());
|
||||||
|
|
||||||
// neither the native nor the stub IntlDateFormatter support
|
// neither the native nor the stub IntlDateFormatter support
|
||||||
// DateTimeImmutable as of yet
|
// DateTimeImmutable as of yet
|
||||||
|
@ -65,14 +65,14 @@ abstract class AbstractComparisonValidator extends ConstraintValidator
|
|||||||
// This allows to compare with any date/time value supported by
|
// This allows to compare with any date/time value supported by
|
||||||
// the DateTime constructor:
|
// the DateTime constructor:
|
||||||
// https://php.net/datetime.formats
|
// https://php.net/datetime.formats
|
||||||
if (\is_string($comparedValue)) {
|
if (\is_string($comparedValue) && $value instanceof \DateTimeInterface) {
|
||||||
if ($value instanceof \DateTimeImmutable) {
|
// If $value is immutable, convert the compared value to a DateTimeImmutable too, otherwise use DateTime
|
||||||
// If $value is immutable, convert the compared value to a
|
$dateTimeClass = $value instanceof \DateTimeImmutable ? \DateTimeImmutable::class : \DateTime::class;
|
||||||
// DateTimeImmutable too
|
|
||||||
$comparedValue = new \DateTimeImmutable($comparedValue);
|
try {
|
||||||
} elseif ($value instanceof \DateTimeInterface) {
|
$comparedValue = new $dateTimeClass($comparedValue);
|
||||||
// Otherwise use DateTime
|
} catch (\Exception $e) {
|
||||||
$comparedValue = new \DateTime($comparedValue);
|
throw new ConstraintDefinitionException(sprintf('The compared value "%s" could not be converted to a "%s" instance in the "%s" constraint.', $comparedValue, $dateTimeClass, \get_class($constraint)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ namespace Symfony\Component\Validator\Constraints;
|
|||||||
|
|
||||||
use Symfony\Component\Validator\Constraint;
|
use Symfony\Component\Validator\Constraint;
|
||||||
use Symfony\Component\Validator\ConstraintValidator;
|
use Symfony\Component\Validator\ConstraintValidator;
|
||||||
|
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
|
||||||
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
|
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,12 +51,26 @@ class RangeValidator extends ConstraintValidator
|
|||||||
// the DateTime constructor:
|
// the DateTime constructor:
|
||||||
// https://php.net/datetime.formats
|
// https://php.net/datetime.formats
|
||||||
if ($value instanceof \DateTimeInterface) {
|
if ($value instanceof \DateTimeInterface) {
|
||||||
|
$dateTimeClass = null;
|
||||||
|
|
||||||
if (\is_string($min)) {
|
if (\is_string($min)) {
|
||||||
$min = new \DateTime($min);
|
$dateTimeClass = $value instanceof \DateTimeImmutable ? \DateTimeImmutable::class : \DateTime::class;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$min = new $dateTimeClass($min);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
throw new ConstraintDefinitionException(sprintf('The min value "%s" could not be converted to a "%s" instance in the "%s" constraint.', $min, $dateTimeClass, \get_class($constraint)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (\is_string($max)) {
|
if (\is_string($max)) {
|
||||||
$max = new \DateTime($max);
|
$dateTimeClass = $dateTimeClass ?: ($value instanceof \DateTimeImmutable ? \DateTimeImmutable::class : \DateTime::class);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$max = new $dateTimeClass($max);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
throw new ConstraintDefinitionException(sprintf('The max value "%s" could not be converted to a "%s" instance in the "%s" constraint.', $max, $dateTimeClass, \get_class($constraint)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Validator\Tests;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Symfony\Component\Validator\Constraint;
|
||||||
|
use Symfony\Component\Validator\ConstraintValidator;
|
||||||
|
|
||||||
|
final class ConstraintValidatorTest extends TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @dataProvider formatValueProvider
|
||||||
|
*/
|
||||||
|
public function testFormatValue($expected, $value, $format = 0)
|
||||||
|
{
|
||||||
|
$this->assertSame($expected, (new TestFormatValueConstraintValidator())->formatValueProxy($value, $format));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function formatValueProvider()
|
||||||
|
{
|
||||||
|
$data = [
|
||||||
|
['true', true],
|
||||||
|
['false', false],
|
||||||
|
['null', null],
|
||||||
|
['resource', fopen('php://memory', 'r')],
|
||||||
|
['"foo"', 'foo'],
|
||||||
|
['array', []],
|
||||||
|
['object', $toString = new TestToStringObject()],
|
||||||
|
['ccc', $toString, ConstraintValidator::OBJECT_TO_STRING],
|
||||||
|
['object', $dateTime = (new \DateTimeImmutable('@0'))->setTimezone(new \DateTimeZone('UTC'))],
|
||||||
|
[class_exists(\IntlDateFormatter::class) ? 'Jan 1, 1970, 12:00 AM' : '1970-01-01 00:00:00', $dateTime, ConstraintValidator::PRETTY_DATE],
|
||||||
|
];
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class TestFormatValueConstraintValidator extends ConstraintValidator
|
||||||
|
{
|
||||||
|
public function validate($value, Constraint $constraint)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function formatValueProxy($value, $format)
|
||||||
|
{
|
||||||
|
return $this->formatValue($value, $format);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class TestToStringObject
|
||||||
|
{
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return 'ccc';
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,7 @@ namespace Symfony\Component\Validator\Tests\Constraints;
|
|||||||
|
|
||||||
use Symfony\Component\Intl\Util\IntlTestHelper;
|
use Symfony\Component\Intl\Util\IntlTestHelper;
|
||||||
use Symfony\Component\Validator\Constraint;
|
use Symfony\Component\Validator\Constraint;
|
||||||
|
use Symfony\Component\Validator\Constraints\AbstractComparison;
|
||||||
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
|
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
|
||||||
use Symfony\Component\Validator\Test\ConstraintValidatorTestCase;
|
use Symfony\Component\Validator\Test\ConstraintValidatorTestCase;
|
||||||
|
|
||||||
@ -211,6 +212,31 @@ abstract class AbstractComparisonValidatorTestCase extends ConstraintValidatorTe
|
|||||||
->assertRaised();
|
->assertRaised();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider throwsOnInvalidStringDatesProvider
|
||||||
|
*/
|
||||||
|
public function testThrowsOnInvalidStringDates(AbstractComparison $constraint, $expectedMessage, $value)
|
||||||
|
{
|
||||||
|
$this->expectException(ConstraintDefinitionException::class);
|
||||||
|
$this->expectExceptionMessage($expectedMessage);
|
||||||
|
|
||||||
|
$this->validator->validate($value, $constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function throwsOnInvalidStringDatesProvider()
|
||||||
|
{
|
||||||
|
$constraint = $this->createConstraint([
|
||||||
|
'value' => 'foo',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$constraintClass = \get_class($constraint);
|
||||||
|
|
||||||
|
return [
|
||||||
|
[$constraint, sprintf('The compared value "foo" could not be converted to a "DateTimeImmutable" instance in the "%s" constraint.', $constraintClass), new \DateTimeImmutable()],
|
||||||
|
[$constraint, sprintf('The compared value "foo" could not be converted to a "DateTime" instance in the "%s" constraint.', $constraintClass), new \DateTime()],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Validator\Tests\Constraints;
|
namespace Symfony\Component\Validator\Tests\Constraints;
|
||||||
|
|
||||||
|
use Symfony\Component\Validator\Constraints\AbstractComparison;
|
||||||
use Symfony\Component\Validator\Constraints\PositiveOrZero;
|
use Symfony\Component\Validator\Constraints\PositiveOrZero;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -98,10 +99,10 @@ class GreaterThanOrEqualValidatorWithPositiveOrZeroConstraintTest extends Greate
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider provideValidComparisonsToPropertyPath
|
* @dataProvider throwsOnInvalidStringDatesProvider
|
||||||
*/
|
*/
|
||||||
public function testValidComparisonToPropertyPathOnArray($comparedValue)
|
public function testThrowsOnInvalidStringDates(AbstractComparison $constraint, $expectedMessage, $value)
|
||||||
{
|
{
|
||||||
$this->markTestSkipped('PropertyPath option is not used in Positive constraint');
|
$this->markTestSkipped('The compared value cannot be an invalid string date because it is hardcoded to 0.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Validator\Tests\Constraints;
|
namespace Symfony\Component\Validator\Tests\Constraints;
|
||||||
|
|
||||||
|
use Symfony\Component\Validator\Constraints\AbstractComparison;
|
||||||
use Symfony\Component\Validator\Constraints\Positive;
|
use Symfony\Component\Validator\Constraints\Positive;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -101,10 +102,10 @@ class GreaterThanValidatorWithPositiveConstraintTest extends GreaterThanValidato
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider provideValidComparisonsToPropertyPath
|
* @dataProvider throwsOnInvalidStringDatesProvider
|
||||||
*/
|
*/
|
||||||
public function testValidComparisonToPropertyPathOnArray($comparedValue)
|
public function testThrowsOnInvalidStringDates(AbstractComparison $constraint, $expectedMessage, $value)
|
||||||
{
|
{
|
||||||
$this->markTestSkipped('PropertyPath option is not used in Positive constraint');
|
$this->markTestSkipped('The compared value cannot be an invalid string date because it is hardcoded to 0.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Validator\Tests\Constraints;
|
namespace Symfony\Component\Validator\Tests\Constraints;
|
||||||
|
|
||||||
|
use Symfony\Component\Validator\Constraints\AbstractComparison;
|
||||||
use Symfony\Component\Validator\Constraints\NegativeOrZero;
|
use Symfony\Component\Validator\Constraints\NegativeOrZero;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -101,10 +102,10 @@ class LessThanOrEqualValidatorWithNegativeOrZeroConstraintTest extends LessThanO
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider provideValidComparisonsToPropertyPath
|
* @dataProvider throwsOnInvalidStringDatesProvider
|
||||||
*/
|
*/
|
||||||
public function testValidComparisonToPropertyPathOnArray($comparedValue)
|
public function testThrowsOnInvalidStringDates(AbstractComparison $constraint, $expectedMessage, $value)
|
||||||
{
|
{
|
||||||
$this->markTestSkipped('PropertyPath option is not used in NegativeOrZero constraint');
|
$this->markTestSkipped('The compared value cannot be an invalid string date because it is hardcoded to 0.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Validator\Tests\Constraints;
|
namespace Symfony\Component\Validator\Tests\Constraints;
|
||||||
|
|
||||||
|
use Symfony\Component\Validator\Constraints\AbstractComparison;
|
||||||
use Symfony\Component\Validator\Constraints\Negative;
|
use Symfony\Component\Validator\Constraints\Negative;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -101,10 +102,10 @@ class LessThanValidatorWithNegativeConstraintTest extends LessThanValidatorTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider provideValidComparisonsToPropertyPath
|
* @dataProvider throwsOnInvalidStringDatesProvider
|
||||||
*/
|
*/
|
||||||
public function testValidComparisonToPropertyPathOnArray($comparedValue)
|
public function testThrowsOnInvalidStringDates(AbstractComparison $constraint, $expectedMessage, $value)
|
||||||
{
|
{
|
||||||
$this->markTestSkipped('PropertyPath option is not used in Positive constraint');
|
$this->markTestSkipped('The compared value cannot be an invalid string date because it is hardcoded to 0.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ namespace Symfony\Component\Validator\Tests\Constraints;
|
|||||||
use Symfony\Component\Intl\Util\IntlTestHelper;
|
use Symfony\Component\Intl\Util\IntlTestHelper;
|
||||||
use Symfony\Component\Validator\Constraints\Range;
|
use Symfony\Component\Validator\Constraints\Range;
|
||||||
use Symfony\Component\Validator\Constraints\RangeValidator;
|
use Symfony\Component\Validator\Constraints\RangeValidator;
|
||||||
|
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
|
||||||
use Symfony\Component\Validator\Test\ConstraintValidatorTestCase;
|
use Symfony\Component\Validator\Test\ConstraintValidatorTestCase;
|
||||||
|
|
||||||
class RangeValidatorTest extends ConstraintValidatorTestCase
|
class RangeValidatorTest extends ConstraintValidatorTestCase
|
||||||
@ -389,4 +390,29 @@ class RangeValidatorTest extends ConstraintValidatorTestCase
|
|||||||
->setCode(Range::INVALID_CHARACTERS_ERROR)
|
->setCode(Range::INVALID_CHARACTERS_ERROR)
|
||||||
->assertRaised();
|
->assertRaised();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider throwsOnInvalidStringDatesProvider
|
||||||
|
*/
|
||||||
|
public function testThrowsOnInvalidStringDates($expectedMessage, $value, $min, $max)
|
||||||
|
{
|
||||||
|
$this->expectException(ConstraintDefinitionException::class);
|
||||||
|
$this->expectExceptionMessage($expectedMessage);
|
||||||
|
|
||||||
|
$this->validator->validate($value, new Range([
|
||||||
|
'min' => $min,
|
||||||
|
'max' => $max,
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function throwsOnInvalidStringDatesProvider()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['The min value "foo" could not be converted to a "DateTimeImmutable" instance in the "Symfony\Component\Validator\Constraints\Range" constraint.', new \DateTimeImmutable(), 'foo', null],
|
||||||
|
['The min value "foo" could not be converted to a "DateTime" instance in the "Symfony\Component\Validator\Constraints\Range" constraint.', new \DateTime(), 'foo', null],
|
||||||
|
['The max value "foo" could not be converted to a "DateTimeImmutable" instance in the "Symfony\Component\Validator\Constraints\Range" constraint.', new \DateTimeImmutable(), null, 'foo'],
|
||||||
|
['The max value "foo" could not be converted to a "DateTime" instance in the "Symfony\Component\Validator\Constraints\Range" constraint.', new \DateTime(), null, 'foo'],
|
||||||
|
['The min value "bar" could not be converted to a "DateTimeImmutable" instance in the "Symfony\Component\Validator\Constraints\Range" constraint.', new \DateTimeImmutable(), 'bar', 'ccc'],
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user