LegacyExecutionContextTest.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Validator\Tests;
  11. use PHPUnit\Framework\TestCase;
  12. use Symfony\Component\Validator\Constraints\All;
  13. use Symfony\Component\Validator\Constraints\Collection;
  14. use Symfony\Component\Validator\ConstraintValidatorFactory;
  15. use Symfony\Component\Validator\ConstraintViolation;
  16. use Symfony\Component\Validator\ConstraintViolationList;
  17. use Symfony\Component\Validator\ExecutionContext;
  18. use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
  19. use Symfony\Component\Validator\ValidationVisitor;
  20. /**
  21. * @group legacy
  22. */
  23. class LegacyExecutionContextTest extends TestCase
  24. {
  25. const TRANS_DOMAIN = 'trans_domain';
  26. private $visitor;
  27. private $violations;
  28. private $metadata;
  29. private $metadataFactory;
  30. private $globalContext;
  31. private $translator;
  32. /**
  33. * @var ExecutionContext
  34. */
  35. private $context;
  36. protected function setUp()
  37. {
  38. $this->visitor = $this->getMockBuilder('Symfony\Component\Validator\ValidationVisitor')
  39. ->disableOriginalConstructor()
  40. ->getMock();
  41. $this->violations = new ConstraintViolationList();
  42. $this->metadata = $this->getMockBuilder('Symfony\Component\Validator\MetadataInterface')->getMock();
  43. $this->metadataFactory = $this->getMockBuilder('Symfony\Component\Validator\MetadataFactoryInterface')->getMock();
  44. $this->globalContext = $this->getMockBuilder('Symfony\Component\Validator\GlobalExecutionContextInterface')->getMock();
  45. $this->globalContext->expects($this->any())
  46. ->method('getRoot')
  47. ->will($this->returnValue('Root'));
  48. $this->globalContext->expects($this->any())
  49. ->method('getViolations')
  50. ->will($this->returnValue($this->violations));
  51. $this->globalContext->expects($this->any())
  52. ->method('getVisitor')
  53. ->will($this->returnValue($this->visitor));
  54. $this->globalContext->expects($this->any())
  55. ->method('getMetadataFactory')
  56. ->will($this->returnValue($this->metadataFactory));
  57. $this->translator = $this->getMockBuilder('Symfony\Component\Translation\TranslatorInterface')->getMock();
  58. $this->context = new ExecutionContext($this->globalContext, $this->translator, self::TRANS_DOMAIN, $this->metadata, 'currentValue', 'Group', 'foo.bar');
  59. }
  60. protected function tearDown()
  61. {
  62. $this->globalContext = null;
  63. $this->context = null;
  64. }
  65. public function testInit()
  66. {
  67. $this->assertCount(0, $this->context->getViolations());
  68. $this->assertSame('Root', $this->context->getRoot());
  69. $this->assertSame('foo.bar', $this->context->getPropertyPath());
  70. $this->assertSame('Group', $this->context->getGroup());
  71. }
  72. public function testClone()
  73. {
  74. $clone = clone $this->context;
  75. // Cloning the context keeps the reference to the original violation
  76. // list. This way we can efficiently duplicate context instances during
  77. // the validation run and only modify the properties that need to be
  78. // changed.
  79. $this->assertSame($this->context->getViolations(), $clone->getViolations());
  80. }
  81. public function testAddViolation()
  82. {
  83. $this->translator->expects($this->once())
  84. ->method('trans')
  85. ->with('Error', array('foo' => 'bar'))
  86. ->will($this->returnValue('Translated error'));
  87. $this->context->addViolation('Error', array('foo' => 'bar'), 'invalid');
  88. $this->assertEquals(new ConstraintViolationList(array(
  89. new ConstraintViolation(
  90. 'Translated error',
  91. 'Error',
  92. array('foo' => 'bar'),
  93. 'Root',
  94. 'foo.bar',
  95. 'invalid'
  96. ),
  97. )), $this->context->getViolations());
  98. }
  99. public function testAddViolationUsesPreconfiguredValueIfNotPassed()
  100. {
  101. $this->translator->expects($this->once())
  102. ->method('trans')
  103. ->with('Error', array())
  104. ->will($this->returnValue('Translated error'));
  105. $this->context->addViolation('Error');
  106. $this->assertEquals(new ConstraintViolationList(array(
  107. new ConstraintViolation(
  108. 'Translated error',
  109. 'Error',
  110. array(),
  111. 'Root',
  112. 'foo.bar',
  113. 'currentValue'
  114. ),
  115. )), $this->context->getViolations());
  116. }
  117. public function testAddViolationUsesPassedNullValue()
  118. {
  119. $this->translator->expects($this->once())
  120. ->method('trans')
  121. ->with('Error', array('foo1' => 'bar1'))
  122. ->will($this->returnValue('Translated error'));
  123. $this->translator->expects($this->once())
  124. ->method('transChoice')
  125. ->with('Choice error', 1, array('foo2' => 'bar2'))
  126. ->will($this->returnValue('Translated choice error'));
  127. // passed null value should override preconfigured value "invalid"
  128. $this->context->addViolation('Error', array('foo1' => 'bar1'), null);
  129. $this->context->addViolation('Choice error', array('foo2' => 'bar2'), null, 1);
  130. $this->assertEquals(new ConstraintViolationList(array(
  131. new ConstraintViolation(
  132. 'Translated error',
  133. 'Error',
  134. array('foo1' => 'bar1'),
  135. 'Root',
  136. 'foo.bar',
  137. null
  138. ),
  139. new ConstraintViolation(
  140. 'Translated choice error',
  141. 'Choice error',
  142. array('foo2' => 'bar2'),
  143. 'Root',
  144. 'foo.bar',
  145. null,
  146. 1
  147. ),
  148. )), $this->context->getViolations());
  149. }
  150. public function testAddViolationAt()
  151. {
  152. $this->translator->expects($this->once())
  153. ->method('trans')
  154. ->with('Error', array('foo' => 'bar'))
  155. ->will($this->returnValue('Translated error'));
  156. // override preconfigured property path
  157. $this->context->addViolationAt('bam.baz', 'Error', array('foo' => 'bar'), 'invalid');
  158. $this->assertEquals(new ConstraintViolationList(array(
  159. new ConstraintViolation(
  160. 'Translated error',
  161. 'Error',
  162. array('foo' => 'bar'),
  163. 'Root',
  164. 'foo.bar.bam.baz',
  165. 'invalid'
  166. ),
  167. )), $this->context->getViolations());
  168. }
  169. public function testAddViolationAtUsesPreconfiguredValueIfNotPassed()
  170. {
  171. $this->translator->expects($this->once())
  172. ->method('trans')
  173. ->with('Error', array())
  174. ->will($this->returnValue('Translated error'));
  175. $this->context->addViolationAt('bam.baz', 'Error');
  176. $this->assertEquals(new ConstraintViolationList(array(
  177. new ConstraintViolation(
  178. 'Translated error',
  179. 'Error',
  180. array(),
  181. 'Root',
  182. 'foo.bar.bam.baz',
  183. 'currentValue'
  184. ),
  185. )), $this->context->getViolations());
  186. }
  187. public function testAddViolationAtUsesPassedNullValue()
  188. {
  189. $this->translator->expects($this->once())
  190. ->method('trans')
  191. ->with('Error', array('foo' => 'bar'))
  192. ->will($this->returnValue('Translated error'));
  193. $this->translator->expects($this->once())
  194. ->method('transChoice')
  195. ->with('Choice error', 2, array('foo' => 'bar'))
  196. ->will($this->returnValue('Translated choice error'));
  197. // passed null value should override preconfigured value "invalid"
  198. $this->context->addViolationAt('bam.baz', 'Error', array('foo' => 'bar'), null);
  199. $this->context->addViolationAt('bam.baz', 'Choice error', array('foo' => 'bar'), null, 2);
  200. $this->assertEquals(new ConstraintViolationList(array(
  201. new ConstraintViolation(
  202. 'Translated error',
  203. 'Error',
  204. array('foo' => 'bar'),
  205. 'Root',
  206. 'foo.bar.bam.baz',
  207. null
  208. ),
  209. new ConstraintViolation(
  210. 'Translated choice error',
  211. 'Choice error',
  212. array('foo' => 'bar'),
  213. 'Root',
  214. 'foo.bar.bam.baz',
  215. null,
  216. 2
  217. ),
  218. )), $this->context->getViolations());
  219. }
  220. public function testAddViolationPluralTranslationError()
  221. {
  222. $this->translator->expects($this->once())
  223. ->method('transChoice')
  224. ->with('foo')
  225. ->will($this->throwException(new \InvalidArgumentException()));
  226. $this->translator->expects($this->once())
  227. ->method('trans')
  228. ->with('foo');
  229. $this->context->addViolation('foo', array(), null, 2);
  230. }
  231. public function testGetPropertyPath()
  232. {
  233. $this->assertEquals('foo.bar', $this->context->getPropertyPath());
  234. }
  235. public function testGetPropertyPathWithIndexPath()
  236. {
  237. $this->assertEquals('foo.bar[bam]', $this->context->getPropertyPath('[bam]'));
  238. }
  239. public function testGetPropertyPathWithEmptyPath()
  240. {
  241. $this->assertEquals('foo.bar', $this->context->getPropertyPath(''));
  242. }
  243. public function testGetPropertyPathWithEmptyCurrentPropertyPath()
  244. {
  245. $this->context = new ExecutionContext($this->globalContext, $this->translator, self::TRANS_DOMAIN, $this->metadata, 'currentValue', 'Group', '');
  246. $this->assertEquals('bam.baz', $this->context->getPropertyPath('bam.baz'));
  247. }
  248. public function testGetPropertyPathWithNestedCollectionsAndAllMixed()
  249. {
  250. $constraints = new Collection(array(
  251. 'shelves' => new All(array('constraints' => array(
  252. new Collection(array(
  253. 'name' => new ConstraintA(),
  254. 'books' => new All(array('constraints' => array(
  255. new ConstraintA(),
  256. ))),
  257. )),
  258. ))),
  259. 'name' => new ConstraintA(),
  260. ));
  261. $data = array(
  262. 'shelves' => array(
  263. array(
  264. 'name' => 'Research',
  265. 'books' => array('foo', 'bar'),
  266. ),
  267. array(
  268. 'name' => 'VALID',
  269. 'books' => array('foozy', 'VALID', 'bazzy'),
  270. ),
  271. ),
  272. 'name' => 'Library',
  273. );
  274. $expectedViolationPaths = array(
  275. '[shelves][0][name]',
  276. '[shelves][0][books][0]',
  277. '[shelves][0][books][1]',
  278. '[shelves][1][books][0]',
  279. '[shelves][1][books][2]',
  280. '[name]',
  281. );
  282. $visitor = new ValidationVisitor('Root', $this->metadataFactory, new ConstraintValidatorFactory(), $this->translator);
  283. $context = new ExecutionContext($visitor, $this->translator, self::TRANS_DOMAIN);
  284. $context->validateValue($data, $constraints);
  285. foreach ($context->getViolations() as $violation) {
  286. $violationPaths[] = $violation->getPropertyPath();
  287. }
  288. $this->assertEquals($expectedViolationPaths, $violationPaths);
  289. }
  290. }
  291. class ExecutionContextTest_TestClass
  292. {
  293. public $myProperty;
  294. }