BuilderTest.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\Validator\Test\Unit;
  7. /**
  8. * Class BuilderTest
  9. *
  10. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  11. */
  12. class BuilderTest extends \PHPUnit\Framework\TestCase
  13. {
  14. /**
  15. * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager
  16. */
  17. protected $_objectManager;
  18. /**
  19. * @var \Magento\Framework\ObjectManager\ObjectManager
  20. */
  21. protected $_realObjectManager;
  22. protected function setUp()
  23. {
  24. $this->_objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
  25. $config = new \Magento\Framework\ObjectManager\Config\Config(
  26. new \Magento\Framework\ObjectManager\Relations\Runtime()
  27. );
  28. $factory = new \Magento\Framework\ObjectManager\Factory\Dynamic\Developer($config);
  29. $this->_realObjectManager = new \Magento\Framework\ObjectManager\ObjectManager($factory, $config);
  30. $factory->setObjectManager($this->_realObjectManager);
  31. }
  32. /**
  33. * Test createValidator method
  34. *
  35. * @dataProvider createValidatorDataProvider
  36. *
  37. * @param array $constraints
  38. * @param \Magento\Framework\Validator\ValidatorInterface $expectedValidator
  39. */
  40. public function testCreateValidator(array $constraints, $expectedValidator)
  41. {
  42. /** @var $builder \Magento\Framework\Validator\Builder */
  43. $builder = $this->_objectManager->getObject(
  44. \Magento\Framework\Validator\Builder::class,
  45. [
  46. 'constraintFactory' => new \Magento\Framework\Validator\ConstraintFactory($this->_realObjectManager),
  47. 'validatorFactory' => new \Magento\Framework\ValidatorFactory($this->_realObjectManager),
  48. 'oneValidatorFactory' => new \Magento\Framework\Validator\UniversalFactory($this->_realObjectManager),
  49. 'constraints' => $constraints
  50. ]
  51. );
  52. $actualValidator = $builder->createValidator();
  53. $this->assertEquals($expectedValidator, $actualValidator);
  54. }
  55. /**
  56. * Data provider for
  57. *
  58. * @return array
  59. */
  60. public function createValidatorDataProvider()
  61. {
  62. $result = [];
  63. /** @var \Magento\Framework\Translate\AbstractAdapter $translator */
  64. $translator = $this->getMockBuilder(
  65. \Magento\Framework\Translate\AbstractAdapter::class
  66. )->getMockForAbstractClass();
  67. \Magento\Framework\Validator\AbstractValidator::setDefaultTranslator($translator);
  68. // Case 1. Check constructor with arguments
  69. $actualConstraints = [
  70. [
  71. 'alias' => 'name_alias',
  72. 'class' => \Magento\Framework\Validator\Test\Unit\Test\StringLength::class,
  73. 'options' => [
  74. 'arguments' => [
  75. 'options' => ['min' => 1, 'max' => new \Magento\Framework\Validator\Constraint\Option(20)],
  76. ],
  77. ],
  78. 'property' => 'name',
  79. 'type' => 'property',
  80. ],
  81. ];
  82. $expectedValidator = new \Magento\Framework\Validator();
  83. $expectedValidator->addValidator(
  84. new \Magento\Framework\Validator\Constraint\Property(
  85. new \Magento\Framework\Validator\Test\Unit\Test\StringLength(1, 20),
  86. 'name',
  87. 'name_alias'
  88. )
  89. );
  90. $result[] = [$actualConstraints, $expectedValidator];
  91. // Case 2. Check method calls
  92. $actualConstraints = [
  93. [
  94. 'alias' => 'description_alias',
  95. 'class' => \Magento\Framework\Validator\Test\Unit\Test\StringLength::class,
  96. 'options' => [
  97. 'methods' => [
  98. ['method' => 'setMin', 'arguments' => [10]],
  99. ['method' => 'setMax', 'arguments' => [1000]],
  100. ],
  101. ],
  102. 'property' => 'description',
  103. 'type' => 'property',
  104. ],
  105. ];
  106. $expectedValidator = new \Magento\Framework\Validator();
  107. $expectedValidator->addValidator(
  108. new \Magento\Framework\Validator\Constraint\Property(
  109. new \Magento\Framework\Validator\Test\Unit\Test\StringLength(10, 1000),
  110. 'description',
  111. 'description_alias'
  112. )
  113. );
  114. $result[] = [$actualConstraints, $expectedValidator];
  115. // Case 3. Check callback on validator
  116. $actualConstraints = [
  117. [
  118. 'alias' => 'sku_alias',
  119. 'class' => \Magento\Framework\Validator\Test\Unit\Test\StringLength::class,
  120. 'options' => [
  121. 'callback' => [
  122. new \Magento\Framework\Validator\Constraint\Option\Callback(
  123. function ($validator) {
  124. $validator->setMin(20);
  125. $validator->setMax(100);
  126. }
  127. ), ], ],'property' => 'sku', 'type' => 'property', ], ];
  128. $expectedValidator = new \Magento\Framework\Validator();
  129. $expectedValidator->addValidator(
  130. new \Magento\Framework\Validator\Constraint\Property(
  131. new \Magento\Framework\Validator\Test\Unit\Test\StringLength(20, 100),
  132. 'sku',
  133. 'sku_alias'
  134. )
  135. );
  136. $result[] = [$actualConstraints, $expectedValidator];
  137. return $result;
  138. }
  139. /**
  140. * Check addConfiguration logic
  141. *
  142. * @dataProvider configurationDataProvider
  143. *
  144. * @param array $constraints
  145. * @param string $alias
  146. * @param array $configuration
  147. * @param array $expected
  148. */
  149. public function testAddConfiguration($constraints, $alias, $configuration, $expected)
  150. {
  151. /** @var $builder \Magento\Framework\Validator\Builder */
  152. $builder = $this->_objectManager->getObject(
  153. \Magento\Framework\Validator\Builder::class,
  154. ['constraints' => $constraints]
  155. );
  156. $builder->addConfiguration($alias, $configuration);
  157. $this->assertAttributeEquals($expected, '_constraints', $builder);
  158. }
  159. /**
  160. * Check addConfigurations logic
  161. *
  162. * @dataProvider configurationDataProvider
  163. *
  164. * @param array $constraints
  165. * @param string $alias
  166. * @param array $configuration
  167. * @param array $expected
  168. */
  169. public function testAddConfigurations($constraints, $alias, $configuration, $expected)
  170. {
  171. /** @var $builder \Magento\Framework\Validator\Builder */
  172. $builder = $this->_objectManager->getObject(
  173. \Magento\Framework\Validator\Builder::class,
  174. ['constraints' => $constraints]
  175. );
  176. $configurations = [$alias => [$configuration]];
  177. $builder->addConfigurations($configurations);
  178. $this->assertAttributeEquals($expected, '_constraints', $builder);
  179. }
  180. /**
  181. * Builder configurations data provider
  182. *
  183. * @return array
  184. * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
  185. */
  186. public function configurationDataProvider()
  187. {
  188. $callback = new \Magento\Framework\Validator\Constraint\Option\Callback(
  189. [\Magento\Framework\Validator\Test\Unit\Test\Callback::class, 'getId']
  190. );
  191. $someMethod = ['method' => 'getMessages'];
  192. $methodWithArgs = ['method' => 'someMethod', 'arguments' => ['some_value_to_pass']];
  193. $callbackConfig = ['callback' => $callback];
  194. $configuredConstraint = [
  195. 'alias' => 'current_alias',
  196. 'class' => 'Some\Validator\Class',
  197. 'options' => [
  198. 'arguments' => ['some_argument' => 'some_value'],
  199. 'callback' => [$callback],
  200. 'methods' => [$someMethod],
  201. ],
  202. 'property' => 'int',
  203. 'type' => 'property',
  204. ];
  205. $emptyConstraint = [
  206. 'alias' => 'current_alias',
  207. 'class' => 'Some\Validator\Class',
  208. 'options' => null,
  209. 'property' => 'int',
  210. 'type' => 'property',
  211. ];
  212. $constraintWithArgs = [
  213. 'alias' => 'current_alias',
  214. 'class' => 'Some\Validator\Class',
  215. 'options' => ['arguments' => ['some_argument' => 'some_value']],
  216. 'property' => 'int',
  217. 'type' => 'property',
  218. ];
  219. return [
  220. 'constraint is unchanged when alias not found' => [
  221. [$emptyConstraint],
  222. 'some_alias',
  223. $someMethod,
  224. [$emptyConstraint],
  225. ],
  226. 'constraint options initialized with method' => [
  227. [$emptyConstraint],
  228. 'current_alias',
  229. $someMethod,
  230. [$this->_getExpectedConstraints($emptyConstraint, 'methods', [$someMethod])],
  231. ],
  232. 'constraint options initialized with callback' => [
  233. [$emptyConstraint],
  234. 'current_alias',
  235. $callbackConfig,
  236. [$this->_getExpectedConstraints($emptyConstraint, 'callback', [$callback])],
  237. ],
  238. 'constraint options initialized with arguments' => [
  239. [$emptyConstraint],
  240. 'current_alias',
  241. ['arguments' => ['some_argument' => 'some_value']],
  242. [
  243. $this->_getExpectedConstraints(
  244. $emptyConstraint,
  245. 'arguments',
  246. ['some_argument' => 'some_value']
  247. )
  248. ],
  249. ],
  250. 'constraint options arguments overwritten by newer arguments' => [
  251. [$configuredConstraint],
  252. 'current_alias',
  253. ['arguments' => ['some_argument' => 'some_value']],
  254. [
  255. $this->_getExpectedConstraints(
  256. $configuredConstraint,
  257. 'arguments',
  258. ['some_argument' => 'some_value']
  259. )
  260. ],
  261. ],
  262. 'methods initialized' => [
  263. [$constraintWithArgs],
  264. 'current_alias',
  265. $methodWithArgs,
  266. [$this->_getExpectedConstraints($constraintWithArgs, 'methods', [$methodWithArgs])],
  267. ],
  268. 'method added' => [
  269. [$configuredConstraint],
  270. 'current_alias',
  271. $methodWithArgs,
  272. [
  273. $this->_getExpectedConstraints(
  274. $configuredConstraint,
  275. 'methods',
  276. [$someMethod, $methodWithArgs]
  277. )
  278. ],
  279. ],
  280. 'callback initialized' => [
  281. [$constraintWithArgs],
  282. 'current_alias',
  283. $callbackConfig,
  284. [$this->_getExpectedConstraints($constraintWithArgs, 'callback', [$callback])],
  285. ],
  286. 'callback added' => [
  287. [$configuredConstraint],
  288. 'current_alias',
  289. $callbackConfig,
  290. [$this->_getExpectedConstraints($configuredConstraint, 'callback', [$callback, $callback])],
  291. ]
  292. ];
  293. }
  294. /**
  295. * Get expected constraint configuration by actual and changes
  296. *
  297. * @param array $constraint
  298. * @param string $optionKey
  299. * @param mixed $optionValue
  300. * @return array
  301. */
  302. protected function _getExpectedConstraints($constraint, $optionKey, $optionValue)
  303. {
  304. if (!is_array($constraint['options'])) {
  305. $constraint['options'] = [];
  306. }
  307. $constraint['options'][$optionKey] = $optionValue;
  308. return $constraint;
  309. }
  310. /**
  311. * Check arguments validation passed into constructor
  312. *
  313. * @dataProvider invalidArgumentsDataProvider
  314. *
  315. * @param array $options
  316. * @param string $exception
  317. * @param string $exceptionMessage
  318. */
  319. public function testConstructorConfigValidation(array $options, $exception, $exceptionMessage)
  320. {
  321. $this->expectException($exception);
  322. $this->expectExceptionMessage($exceptionMessage);
  323. if (array_key_exists('method', $options)) {
  324. $options = ['methods' => [$options]];
  325. }
  326. $constraints = [
  327. ['alias' => 'alias', 'class' => 'Some\Validator\Class', 'options' => $options, 'type' => 'entity'],
  328. ];
  329. $this->_objectManager->getObject(\Magento\Framework\Validator\Builder::class, ['constraints' => $constraints]);
  330. }
  331. /**
  332. * Check arguments validation passed into configuration
  333. *
  334. * @dataProvider invalidArgumentsDataProvider
  335. *
  336. * @param array $options
  337. * @param string $exception
  338. * @param string $exceptionMessage
  339. */
  340. public function testAddConfigurationConfigValidation(array $options, $exception, $exceptionMessage)
  341. {
  342. $this->expectException($exception);
  343. $this->expectExceptionMessage($exceptionMessage);
  344. $constraints = [
  345. ['alias' => 'alias', 'class' => 'Some\Validator\Class', 'options' => null, 'type' => 'entity'],
  346. ];
  347. /** @var $builder \Magento\Framework\Validator\Builder */
  348. $builder = $this->_objectManager->getObject(
  349. \Magento\Framework\Validator\Builder::class,
  350. ['constraints' => $constraints]
  351. );
  352. $builder->addConfiguration('alias', $options);
  353. }
  354. /**
  355. * Data provider for testing configuration validation
  356. *
  357. * @return array
  358. */
  359. public function invalidArgumentsDataProvider()
  360. {
  361. return [
  362. 'constructor invalid arguments' => [
  363. ['arguments' => 'invalid_argument'],
  364. 'InvalidArgumentException',
  365. 'Arguments must be an array',
  366. ],
  367. 'methods invalid arguments' => [
  368. ['method' => 'setValue', 'arguments' => 'invalid_argument'],
  369. 'InvalidArgumentException',
  370. 'Method arguments must be an array',
  371. ],
  372. 'methods invalid format' => [
  373. ['method' => ['name' => 'setValue']],
  374. 'InvalidArgumentException',
  375. 'Method has to be passed as string',
  376. ],
  377. 'constructor arguments invalid callback' => [
  378. ['callback' => ['invalid', 'callback']],
  379. 'InvalidArgumentException',
  380. 'Callback must be instance of \Magento\Framework\Validator\Constraint\Option\Callback',
  381. ]
  382. ];
  383. }
  384. /**
  385. * Check exception is thrown if validator is not an instance of \Magento\Framework\Validator\ValidatorInterface
  386. */
  387. public function testCreateValidatorInvalidInstance()
  388. {
  389. $this->expectException('InvalidArgumentException');
  390. $this->expectExceptionMessage(
  391. 'Constraint class "StdClass" must implement \Magento\Framework\Validator\ValidatorInterface'
  392. );
  393. $builder = $this->_objectManager->getObject(
  394. \Magento\Framework\Validator\Builder::class,
  395. [
  396. 'constraints' => [
  397. ['alias' => 'alias', 'class' => 'StdClass', 'options' => null, 'type' => 'entity'],
  398. ],
  399. 'validatorFactory' => new \Magento\Framework\ValidatorFactory($this->_realObjectManager)
  400. ]
  401. );
  402. $builder->createValidator();
  403. }
  404. /**
  405. * Test invalid configuration formats
  406. *
  407. * @dataProvider invalidConfigurationFormatDataProvider
  408. *
  409. * @expectedException \InvalidArgumentException
  410. * @expectedExceptionMessage Configuration has incorrect format
  411. *
  412. * @param mixed $configuration
  413. */
  414. public function testAddConfigurationInvalidFormat($configuration)
  415. {
  416. $constraints = [
  417. ['alias' => 'alias', 'class' => 'Some\Validator\Class', 'options' => null, 'type' => 'entity'],
  418. ];
  419. /** @var $builder \Magento\Framework\Validator\Builder */
  420. $builder = $this->_objectManager->getObject(
  421. \Magento\Framework\Validator\Builder::class,
  422. ['constraints' => $constraints]
  423. );
  424. $builder->addConfigurations($configuration);
  425. }
  426. /**
  427. * Data provider for incorrect configurations
  428. *
  429. * @return array
  430. */
  431. public function invalidConfigurationFormatDataProvider()
  432. {
  433. return [
  434. 'configuration incorrect method call' => [
  435. ['alias' => ['method' => ['name' => 'incorrectMethodCall']]],
  436. ],
  437. 'configuration incorrect configuration' => [
  438. ['alias' => [['data' => ['incorrectData']]]],
  439. ]
  440. ];
  441. }
  442. }