Version 1
[yaffs-website] / vendor / symfony / validator / Tests / Constraints / AbstractConstraintValidatorTest.php
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\Constraints;
13
14 use PHPUnit\Framework\Assert;
15 use PHPUnit\Framework\TestCase;
16 use Symfony\Component\Validator\Constraint;
17 use Symfony\Component\Validator\Constraints\NotNull;
18 use Symfony\Component\Validator\ConstraintValidatorInterface;
19 use Symfony\Component\Validator\ConstraintViolation;
20 use Symfony\Component\Validator\Context\ExecutionContext;
21 use Symfony\Component\Validator\Context\ExecutionContextInterface;
22 use Symfony\Component\Validator\Context\LegacyExecutionContext;
23 use Symfony\Component\Validator\ExecutionContextInterface as LegacyExecutionContextInterface;
24 use Symfony\Component\Validator\Mapping\ClassMetadata;
25 use Symfony\Component\Validator\Mapping\PropertyMetadata;
26 use Symfony\Component\Validator\Validation;
27
28 /**
29  * @author Bernhard Schussek <bschussek@gmail.com>
30  */
31 abstract class AbstractConstraintValidatorTest extends TestCase
32 {
33     /**
34      * @var ExecutionContextInterface
35      */
36     protected $context;
37
38     /**
39      * @var ConstraintValidatorInterface
40      */
41     protected $validator;
42
43     protected $group;
44     protected $metadata;
45     protected $object;
46     protected $value;
47     protected $root;
48     protected $propertyPath;
49     protected $constraint;
50     protected $defaultTimezone;
51
52     protected function setUp()
53     {
54         $this->group = 'MyGroup';
55         $this->metadata = null;
56         $this->object = null;
57         $this->value = 'InvalidValue';
58         $this->root = 'root';
59         $this->propertyPath = 'property.path';
60
61         // Initialize the context with some constraint so that we can
62         // successfully build a violation.
63         $this->constraint = new NotNull();
64
65         $this->context = $this->createContext();
66         $this->validator = $this->createValidator();
67         $this->validator->initialize($this->context);
68
69         \Locale::setDefault('en');
70
71         $this->setDefaultTimezone('UTC');
72     }
73
74     protected function tearDown()
75     {
76         $this->restoreDefaultTimezone();
77     }
78
79     protected function setDefaultTimezone($defaultTimezone)
80     {
81         // Make sure this method can not be called twice before calling
82         // also restoreDefaultTimezone()
83         if (null === $this->defaultTimezone) {
84             $this->defaultTimezone = date_default_timezone_get();
85             date_default_timezone_set($defaultTimezone);
86         }
87     }
88
89     protected function restoreDefaultTimezone()
90     {
91         if (null !== $this->defaultTimezone) {
92             date_default_timezone_set($this->defaultTimezone);
93             $this->defaultTimezone = null;
94         }
95     }
96
97     protected function createContext()
98     {
99         $translator = $this->getMockBuilder('Symfony\Component\Translation\TranslatorInterface')->getMock();
100         $validator = $this->getMockBuilder('Symfony\Component\Validator\Validator\ValidatorInterface')->getMock();
101         $contextualValidator = $this->getMockBuilder('Symfony\Component\Validator\Validator\ContextualValidatorInterface')->getMock();
102
103         switch ($this->getApiVersion()) {
104             case Validation::API_VERSION_2_5:
105                 $context = new ExecutionContext(
106                     $validator,
107                     $this->root,
108                     $translator
109                 );
110                 break;
111             case Validation::API_VERSION_2_4:
112             case Validation::API_VERSION_2_5_BC:
113                 $context = new LegacyExecutionContext(
114                     $validator,
115                     $this->root,
116                     $this->getMockBuilder('Symfony\Component\Validator\MetadataFactoryInterface')->getMock(),
117                     $translator
118                 );
119                 break;
120             default:
121                 throw new \RuntimeException('Invalid API version');
122         }
123
124         $context->setGroup($this->group);
125         $context->setNode($this->value, $this->object, $this->metadata, $this->propertyPath);
126         $context->setConstraint($this->constraint);
127
128         $validator->expects($this->any())
129             ->method('inContext')
130             ->with($context)
131             ->will($this->returnValue($contextualValidator));
132
133         return $context;
134     }
135
136     /**
137      * @param mixed  $message
138      * @param array  $parameters
139      * @param string $propertyPath
140      * @param string $invalidValue
141      * @param null   $plural
142      * @param null   $code
143      *
144      * @return ConstraintViolation
145      *
146      * @deprecated to be removed in Symfony 3.0. Use {@link buildViolation()} instead.
147      */
148     protected function createViolation($message, array $parameters = array(), $propertyPath = 'property.path', $invalidValue = 'InvalidValue', $plural = null, $code = null)
149     {
150         return new ConstraintViolation(
151             null,
152             $message,
153             $parameters,
154             $this->root,
155             $propertyPath,
156             $invalidValue,
157             $plural,
158             $code,
159             $this->constraint
160         );
161     }
162
163     protected function setGroup($group)
164     {
165         $this->group = $group;
166         $this->context->setGroup($group);
167     }
168
169     protected function setObject($object)
170     {
171         $this->object = $object;
172         $this->metadata = is_object($object)
173             ? new ClassMetadata(get_class($object))
174             : null;
175
176         $this->context->setNode($this->value, $this->object, $this->metadata, $this->propertyPath);
177     }
178
179     protected function setProperty($object, $property)
180     {
181         $this->object = $object;
182         $this->metadata = is_object($object)
183             ? new PropertyMetadata(get_class($object), $property)
184             : null;
185
186         $this->context->setNode($this->value, $this->object, $this->metadata, $this->propertyPath);
187     }
188
189     protected function setValue($value)
190     {
191         $this->value = $value;
192         $this->context->setNode($this->value, $this->object, $this->metadata, $this->propertyPath);
193     }
194
195     protected function setRoot($root)
196     {
197         $this->root = $root;
198         $this->context = $this->createContext();
199         $this->validator->initialize($this->context);
200     }
201
202     protected function setPropertyPath($propertyPath)
203     {
204         $this->propertyPath = $propertyPath;
205         $this->context->setNode($this->value, $this->object, $this->metadata, $this->propertyPath);
206     }
207
208     protected function expectNoValidate()
209     {
210         $validator = $this->context->getValidator()->inContext($this->context);
211         $validator->expects($this->never())
212             ->method('atPath');
213         $validator->expects($this->never())
214             ->method('validate');
215     }
216
217     protected function expectValidateAt($i, $propertyPath, $value, $group)
218     {
219         $validator = $this->context->getValidator()->inContext($this->context);
220         $validator->expects($this->at(2 * $i))
221             ->method('atPath')
222             ->with($propertyPath)
223             ->will($this->returnValue($validator));
224         $validator->expects($this->at(2 * $i + 1))
225             ->method('validate')
226             ->with($value, $this->logicalOr(null, array(), $this->isInstanceOf('\Symfony\Component\Validator\Constraints\Valid')), $group);
227     }
228
229     protected function expectValidateValueAt($i, $propertyPath, $value, $constraints, $group = null)
230     {
231         $contextualValidator = $this->context->getValidator()->inContext($this->context);
232         $contextualValidator->expects($this->at(2 * $i))
233             ->method('atPath')
234             ->with($propertyPath)
235             ->will($this->returnValue($contextualValidator));
236         $contextualValidator->expects($this->at(2 * $i + 1))
237             ->method('validate')
238             ->with($value, $constraints, $group);
239     }
240
241     protected function assertNoViolation()
242     {
243         $this->assertSame(0, $violationsCount = count($this->context->getViolations()), sprintf('0 violation expected. Got %u.', $violationsCount));
244     }
245
246     /**
247      * @param mixed  $message
248      * @param array  $parameters
249      * @param string $propertyPath
250      * @param string $invalidValue
251      * @param null   $plural
252      * @param null   $code
253      *
254      * @deprecated To be removed in Symfony 3.0. Use
255      *             {@link buildViolation()} instead.
256      */
257     protected function assertViolation($message, array $parameters = array(), $propertyPath = 'property.path', $invalidValue = 'InvalidValue', $plural = null, $code = null)
258     {
259         @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0. Use the buildViolation() method instead.', E_USER_DEPRECATED);
260
261         $this->buildViolation($message)
262             ->setParameters($parameters)
263             ->atPath($propertyPath)
264             ->setInvalidValue($invalidValue)
265             ->setCode($code)
266             ->setPlural($plural)
267             ->assertRaised();
268     }
269
270     /**
271      * @param array $expected
272      *
273      * @deprecated To be removed in Symfony 3.0. Use
274      *             {@link buildViolation()} instead.
275      */
276     protected function assertViolations(array $expected)
277     {
278         @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0. Use the buildViolation() method instead.', E_USER_DEPRECATED);
279
280         $violations = $this->context->getViolations();
281
282         $this->assertCount(count($expected), $violations);
283
284         $i = 0;
285
286         foreach ($expected as $violation) {
287             $this->assertEquals($violation, $violations[$i++]);
288         }
289     }
290
291     /**
292      * @param $message
293      *
294      * @return ConstraintViolationAssertion
295      */
296     protected function buildViolation($message)
297     {
298         return new ConstraintViolationAssertion($this->context, $message, $this->constraint);
299     }
300
301     protected function getApiVersion()
302     {
303         return Validation::API_VERSION_2_5;
304     }
305
306     abstract protected function createValidator();
307 }
308
309 /**
310  * @internal
311  */
312 class ConstraintViolationAssertion
313 {
314     /**
315      * @var LegacyExecutionContextInterface
316      */
317     private $context;
318
319     /**
320      * @var ConstraintViolationAssertion[]
321      */
322     private $assertions;
323
324     private $message;
325     private $parameters = array();
326     private $invalidValue = 'InvalidValue';
327     private $propertyPath = 'property.path';
328     private $translationDomain;
329     private $plural;
330     private $code;
331     private $constraint;
332     private $cause;
333
334     public function __construct(LegacyExecutionContextInterface $context, $message, Constraint $constraint = null, array $assertions = array())
335     {
336         $this->context = $context;
337         $this->message = $message;
338         $this->constraint = $constraint;
339         $this->assertions = $assertions;
340     }
341
342     public function atPath($path)
343     {
344         $this->propertyPath = $path;
345
346         return $this;
347     }
348
349     public function setParameter($key, $value)
350     {
351         $this->parameters[$key] = $value;
352
353         return $this;
354     }
355
356     public function setParameters(array $parameters)
357     {
358         $this->parameters = $parameters;
359
360         return $this;
361     }
362
363     public function setTranslationDomain($translationDomain)
364     {
365         $this->translationDomain = $translationDomain;
366
367         return $this;
368     }
369
370     public function setInvalidValue($invalidValue)
371     {
372         $this->invalidValue = $invalidValue;
373
374         return $this;
375     }
376
377     public function setPlural($number)
378     {
379         $this->plural = $number;
380
381         return $this;
382     }
383
384     public function setCode($code)
385     {
386         $this->code = $code;
387
388         return $this;
389     }
390
391     public function setCause($cause)
392     {
393         $this->cause = $cause;
394
395         return $this;
396     }
397
398     public function buildNextViolation($message)
399     {
400         $assertions = $this->assertions;
401         $assertions[] = $this;
402
403         return new self($this->context, $message, $this->constraint, $assertions);
404     }
405
406     public function assertRaised()
407     {
408         $expected = array();
409         foreach ($this->assertions as $assertion) {
410             $expected[] = $assertion->getViolation();
411         }
412         $expected[] = $this->getViolation();
413
414         $violations = iterator_to_array($this->context->getViolations());
415
416         Assert::assertSame($expectedCount = count($expected), $violationsCount = count($violations), sprintf('%u violation(s) expected. Got %u.', $expectedCount, $violationsCount));
417
418         reset($violations);
419
420         foreach ($expected as $violation) {
421             Assert::assertEquals($violation, current($violations));
422             next($violations);
423         }
424     }
425
426     private function getViolation()
427     {
428         return new ConstraintViolation(
429             null,
430             $this->message,
431             $this->parameters,
432             $this->context->getRoot(),
433             $this->propertyPath,
434             $this->invalidValue,
435             $this->plural,
436             $this->code,
437             $this->constraint,
438             $this->cause
439         );
440     }
441 }