AttributeTest.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Eav\Test\Unit\Model\ResourceModel\Entity;
  7. use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
  8. /**
  9. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  10. */
  11. class AttributeTest extends \PHPUnit\Framework\TestCase
  12. {
  13. /**
  14. * @var \PHPUnit_Framework_MockObject_MockObject
  15. */
  16. protected $selectMock;
  17. /**
  18. * @var \PHPUnit_Framework_MockObject_MockObject
  19. */
  20. protected $contextMock;
  21. protected function setUp()
  22. {
  23. $this->contextMock = $this->createMock(\Magento\Framework\Model\Context::class);
  24. $eventManagerMock = $this->createMock(\Magento\Framework\Event\ManagerInterface::class);
  25. $eventManagerMock->expects($this->any())->method('dispatch');
  26. $this->contextMock->expects($this->any())->method('getEventDispatcher')->willReturn($eventManagerMock);
  27. }
  28. /**
  29. * @covers \Magento\Eav\Model\ResourceModel\Entity\Attribute::_saveOption
  30. */
  31. public function testSaveOptionSystemAttribute()
  32. {
  33. /** @var $connectionMock \PHPUnit_Framework_MockObject_MockObject */
  34. /** @var $resourceModel \Magento\Eav\Model\ResourceModel\Entity\Attribute */
  35. list($connectionMock, $resourceModel) = $this->_prepareResourceModel();
  36. $attributeData = [
  37. 'attribute_id' => '123',
  38. 'entity_type_id' => 4,
  39. 'attribute_code' => 'status',
  40. 'backend_model' => null,
  41. 'backend_type' => 'int',
  42. 'frontend_input' => 'select',
  43. 'frontend_label' => 'Status',
  44. 'frontend_class' => null,
  45. 'source_model' => \Magento\Catalog\Model\Product\Attribute\Source\Status::class,
  46. 'is_required' => 1,
  47. 'is_user_defined' => 0,
  48. 'is_unique' => 0
  49. ];
  50. $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
  51. /** @var $model \Magento\Framework\Model\AbstractModel */
  52. $arguments = $objectManagerHelper->getConstructArguments(\Magento\Framework\Model\AbstractModel::class);
  53. $arguments['data'] = $attributeData;
  54. $arguments['context'] = $this->contextMock;
  55. $model = $this->getMockBuilder(\Magento\Framework\Model\AbstractModel::class)
  56. ->setMethods(['hasDataChanges'])
  57. ->setConstructorArgs($arguments)
  58. ->getMock();
  59. $model->setDefault(['2']);
  60. $model->setOption(['delete' => [1 => '', 2 => '']]);
  61. $model->expects($this->any())->method('hasDataChanges')->willReturn(true);
  62. $connectionMock->expects(
  63. $this->once()
  64. )->method(
  65. 'insert'
  66. )->will(
  67. $this->returnValueMap([['eav_attribute', $attributeData, 1]])
  68. );
  69. $connectionMock->expects(
  70. $this->once()
  71. )->method(
  72. 'fetchRow'
  73. )->will(
  74. $this->returnValueMap(
  75. [
  76. [
  77. 'SELECT `eav_attribute`.* FROM `eav_attribute` ' .
  78. 'WHERE (attribute_code="status") AND (entity_type_id="4")',
  79. $attributeData,
  80. ],
  81. ]
  82. )
  83. );
  84. $connectionMock->expects(
  85. $this->once()
  86. )->method(
  87. 'update'
  88. )->with(
  89. 'eav_attribute',
  90. ['default_value' => 2],
  91. ['attribute_id = ?' => null]
  92. );
  93. $connectionMock->expects($this->never())->method('delete');
  94. $resourceModel->save($model);
  95. }
  96. /**
  97. * @covers \Magento\Eav\Model\ResourceModel\Entity\Attribute::_saveOption
  98. */
  99. public function testSaveOptionNewUserDefinedAttribute()
  100. {
  101. /** @var $connectionMock \PHPUnit_Framework_MockObject_MockObject */
  102. /** @var $resourceModel \Magento\Eav\Model\ResourceModel\Entity\Attribute */
  103. list($connectionMock, $resourceModel) = $this->_prepareResourceModel();
  104. $attributeData = [
  105. 'entity_type_id' => 4,
  106. 'attribute_code' => 'a_dropdown',
  107. 'backend_model' => null,
  108. 'backend_type' => 'int',
  109. 'frontend_input' => 'select',
  110. 'frontend_label' => 'A Dropdown',
  111. 'frontend_class' => null,
  112. 'source_model' => \Magento\Eav\Model\Entity\Attribute\Source\Table::class,
  113. 'is_required' => 0,
  114. 'is_user_defined' => 1,
  115. 'is_unique' => 0,
  116. ];
  117. $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
  118. /** @var $model \Magento\Framework\Model\AbstractModel */
  119. $arguments = $objectManagerHelper->getConstructArguments(\Magento\Framework\Model\AbstractModel::class);
  120. $arguments['data'] = $attributeData;
  121. $arguments['context'] = $this->contextMock;
  122. $model = $this->getMockBuilder(\Magento\Framework\Model\AbstractModel::class)
  123. ->setMethods(['hasDataChanges'])
  124. ->setConstructorArgs($arguments)
  125. ->getMock();
  126. $model->expects($this->any())->method('hasDataChanges')->willReturn(true);
  127. $model->setOption(['value' => ['option_1' => ['Backend Label', 'Frontend Label']]]);
  128. $connectionMock->expects(
  129. $this->any()
  130. )->method(
  131. 'lastInsertId'
  132. )->will(
  133. $this->returnValueMap([['eav_attribute', 123], ['eav_attribute_option_value', 321]])
  134. );
  135. $connectionMock->expects(
  136. $this->once()
  137. )->method(
  138. 'update'
  139. )->will(
  140. $this->returnValueMap(
  141. [['eav_attribute', ['default_value' => ''], ['attribute_id = ?' => 123], 1]]
  142. )
  143. );
  144. $connectionMock->expects(
  145. $this->once()
  146. )->method(
  147. 'fetchRow'
  148. )->will(
  149. $this->returnValueMap(
  150. [
  151. [
  152. 'SELECT `eav_attribute`.* FROM `eav_attribute` ' .
  153. 'WHERE (attribute_code="a_dropdown") AND (entity_type_id="4")',
  154. false,
  155. ],
  156. ]
  157. )
  158. );
  159. $connectionMock->expects(
  160. $this->once()
  161. )->method(
  162. 'delete'
  163. )->will(
  164. $this->returnValueMap([['eav_attribute_option_value', ['option_id = ?' => ''], 0]])
  165. );
  166. $connectionMock->expects(
  167. $this->exactly(4)
  168. )->method(
  169. 'insert'
  170. )->will(
  171. $this->returnValueMap(
  172. [
  173. ['eav_attribute', $attributeData, 1],
  174. ['eav_attribute_option', ['attribute_id' => 123, 'sort_order' => 0], 1],
  175. [
  176. 'eav_attribute_option_value',
  177. ['option_id' => 123, 'store_id' => 0, 'value' => 'Backend Label'],
  178. 1
  179. ],
  180. [
  181. 'eav_attribute_option_value',
  182. ['option_id' => 123, 'store_id' => 1, 'value' => 'Frontend Label'],
  183. 1
  184. ],
  185. ]
  186. )
  187. );
  188. $connectionMock->expects($this->any())->method('getTransactionLevel')->willReturn(1);
  189. $resourceModel->save($model);
  190. }
  191. /**
  192. * @covers \Magento\Eav\Model\ResourceModel\Entity\Attribute::_saveOption
  193. */
  194. public function testSaveOptionNoValue()
  195. {
  196. /** @var $connectionMock \PHPUnit_Framework_MockObject_MockObject */
  197. /** @var $resourceModel \Magento\Eav\Model\ResourceModel\Entity\Attribute */
  198. list($connectionMock, $resourceModel) = $this->_prepareResourceModel();
  199. $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
  200. /** @var $model \Magento\Framework\Model\AbstractModel */
  201. $arguments = $objectManagerHelper->getConstructArguments(\Magento\Framework\Model\AbstractModel::class);
  202. $arguments['context'] = $this->contextMock;
  203. $model = $this->getMockBuilder(\Magento\Framework\Model\AbstractModel::class)
  204. ->setMethods(['hasDataChanges'])
  205. ->setConstructorArgs($arguments)
  206. ->getMock();
  207. $model->expects($this->any())->method('hasDataChanges')->willReturn(true);
  208. $model->setOption('not-an-array');
  209. $connectionMock->expects($this->once())->method('insert')->with('eav_attribute');
  210. $connectionMock->expects($this->never())->method('delete');
  211. $connectionMock->expects($this->never())->method('update');
  212. $resourceModel->save($model);
  213. }
  214. /**
  215. * Retrieve resource model mock instance and its adapter
  216. *
  217. * @return array
  218. * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
  219. */
  220. protected function _prepareResourceModel()
  221. {
  222. $connectionMock = $this->createPartialMock(\Magento\Framework\DB\Adapter\Pdo\Mysql::class, [
  223. '_connect',
  224. 'delete',
  225. 'describeTable',
  226. 'fetchRow',
  227. 'insert',
  228. 'lastInsertId',
  229. 'quote',
  230. 'update',
  231. 'beginTransaction',
  232. 'commit',
  233. 'rollback',
  234. 'select',
  235. 'getTransactionLevel'
  236. ]);
  237. $connectionMock->expects(
  238. $this->any()
  239. )->method(
  240. 'describeTable'
  241. )->with(
  242. 'eav_attribute'
  243. )->will(
  244. $this->returnValue($this->_describeEavAttribute())
  245. );
  246. $connectionMock->expects(
  247. $this->any()
  248. )->method(
  249. 'quote'
  250. )->will(
  251. $this->returnValueMap(
  252. [
  253. [123, 123],
  254. ['4', '"4"'],
  255. ['a_dropdown', '"a_dropdown"'],
  256. ['status', '"status"'],
  257. ]
  258. )
  259. );
  260. $this->selectMock = $this->createMock(\Magento\Framework\DB\Select::class);
  261. $connectionMock->expects(
  262. $this->any()
  263. )->method(
  264. 'select'
  265. )->willReturn(
  266. $this->selectMock
  267. );
  268. $this->selectMock->expects($this->any())->method('from')->willReturnSelf();
  269. $this->selectMock->expects($this->any())->method('where')->willReturnSelf();
  270. $storeManager = $this->createPartialMock(\Magento\Store\Model\StoreManager::class, ['getStores']);
  271. $storeManager->expects(
  272. $this->any()
  273. )->method(
  274. 'getStores'
  275. )->with(
  276. true
  277. )->will(
  278. $this->returnValue(
  279. [
  280. new \Magento\Framework\DataObject(['id' => 0]),
  281. new \Magento\Framework\DataObject(['id' => 1])
  282. ]
  283. )
  284. );
  285. /** @var $resource \Magento\Framework\App\ResourceConnection */
  286. $resource = $this->createMock(\Magento\Framework\App\ResourceConnection::class);
  287. $resource->expects($this->any())->method('getTableName')->will($this->returnArgument(0));
  288. $resource->expects($this->any())->method('getConnection')->with()->will($this->returnValue($connectionMock));
  289. $eavEntityType = $this->createMock(\Magento\Eav\Model\ResourceModel\Entity\Type::class);
  290. $relationProcessorMock = $this->createMock(
  291. \Magento\Framework\Model\ResourceModel\Db\ObjectRelationProcessor::class
  292. );
  293. $contextMock = $this->createMock(\Magento\Framework\Model\ResourceModel\Db\Context::class);
  294. $contextMock->expects($this->once())->method('getResources')->willReturn($resource);
  295. $contextMock->expects($this->once())->method('getObjectRelationProcessor')->willReturn($relationProcessorMock);
  296. $configMock = $this->getMockBuilder(\Magento\Eav\Model\Config::class)->disableOriginalConstructor()->getMock();
  297. $arguments = [
  298. 'context' => $contextMock,
  299. 'storeManager' => $storeManager,
  300. 'eavEntityType' => $eavEntityType,
  301. ];
  302. $helper = new ObjectManager($this);
  303. $resourceModel = $helper->getObject(\Magento\Eav\Model\ResourceModel\Entity\Attribute::class, $arguments);
  304. $helper->setBackwardCompatibleProperty(
  305. $resourceModel,
  306. 'config',
  307. $configMock
  308. );
  309. return [$connectionMock, $resourceModel];
  310. }
  311. /**
  312. * Retrieve eav_attribute table structure
  313. *
  314. * @return array
  315. */
  316. protected function _describeEavAttribute()
  317. {
  318. return require __DIR__ . '/../../../_files/describe_table_eav_attribute.php';
  319. }
  320. }