MenuTest.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Backend\Test\Unit\Model;
  7. use Magento\Backend\Model\Menu\Item;
  8. use Magento\Backend\Model\Menu\Item\Factory;
  9. use Magento\Framework\Serialize\SerializerInterface;
  10. class MenuTest extends \PHPUnit\Framework\TestCase
  11. {
  12. /**
  13. * @var \Magento\Backend\Model\Menu
  14. */
  15. protected $_model;
  16. /**
  17. * @var \Psr\Log\LoggerInterface
  18. */
  19. protected $_logger;
  20. /**
  21. * @var \Magento\Backend\Model\Menu\Item[]
  22. */
  23. protected $_items = [];
  24. /**
  25. * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager
  26. */
  27. private $objectManagerHelper;
  28. protected function setUp()
  29. {
  30. $this->objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
  31. $this->_items['item1'] = $this->createMock(\Magento\Backend\Model\Menu\Item::class);
  32. $this->_items['item1']->expects($this->any())->method('getId')->will($this->returnValue('item1'));
  33. $this->_items['item2'] = $this->createMock(\Magento\Backend\Model\Menu\Item::class);
  34. $this->_items['item2']->expects($this->any())->method('getId')->will($this->returnValue('item2'));
  35. $this->_items['item3'] = $this->createMock(\Magento\Backend\Model\Menu\Item::class);
  36. $this->_items['item3']->expects($this->any())->method('getId')->will($this->returnValue('item3'));
  37. $this->_logger = $this->createMock(\Psr\Log\LoggerInterface::class);
  38. $this->_model = $this->objectManagerHelper->getObject(
  39. \Magento\Backend\Model\Menu::class,
  40. [
  41. 'logger' => $this->_logger
  42. ]
  43. );
  44. }
  45. public function testAdd()
  46. {
  47. $item = $this->createMock(\Magento\Backend\Model\Menu\Item::class);
  48. $this->_model->add($item);
  49. $this->assertCount(1, $this->_model);
  50. $this->assertEquals($item, $this->_model[0]);
  51. }
  52. public function testAddDoLogAddAction()
  53. {
  54. $result = $this->_model->add($this->_items['item1']);
  55. $this->assertNull($result);
  56. }
  57. public function testAddToItem()
  58. {
  59. $subMenu = $this->getMockBuilder(\Magento\Backend\Model\Menu::class)->disableOriginalConstructor()->getMock();
  60. $subMenu->expects($this->once())->method("add")->with($this->_items['item2']);
  61. $this->_items['item1']->expects($this->once())->method("getChildren")->will($this->returnValue($subMenu));
  62. $this->_model->add($this->_items['item1']);
  63. $this->_model->add($this->_items['item2'], 'item1');
  64. }
  65. public function testAddWithSortIndexThatAlreadyExistsAddsItemOnNextAvailableIndex()
  66. {
  67. $this->_model->add($this->createMock(\Magento\Backend\Model\Menu\Item::class));
  68. $this->_model->add($this->createMock(\Magento\Backend\Model\Menu\Item::class));
  69. $this->_model->add($this->createMock(\Magento\Backend\Model\Menu\Item::class));
  70. $this->_model->add($this->_items['item1'], null, 2);
  71. $this->assertCount(4, $this->_model);
  72. $this->assertEquals($this->_items['item1'], $this->_model[3]);
  73. }
  74. public function testAddSortsItemsByTheirSortIndex()
  75. {
  76. $this->_model->add($this->_items['item1'], null, 10);
  77. $this->_model->add($this->_items['item2'], null, 20);
  78. $this->_model->add($this->_items['item3'], null, 15);
  79. $this->assertCount(3, $this->_model);
  80. $itemsOrdered = [];
  81. foreach ($this->_model as $item) {
  82. /** @var $item \Magento\Backend\Model\Menu\Item */
  83. $itemsOrdered[] = $item->getId();
  84. }
  85. $this->assertEquals(['item1', 'item3', 'item2'], $itemsOrdered);
  86. }
  87. public function testGet()
  88. {
  89. $this->_model->add($this->_items['item1']);
  90. $this->_model->add($this->_items['item2']);
  91. $this->assertEquals($this->_items['item1'], $this->_model[0]);
  92. $this->assertEquals($this->_items['item2'], $this->_model[1]);
  93. $this->assertEquals($this->_items['item1'], $this->_model->get(\item1::class));
  94. $this->assertEquals($this->_items['item2'], $this->_model->get(\item2::class));
  95. }
  96. public function testGetRecursive()
  97. {
  98. $menuOne = $this->objectManagerHelper->getObject(
  99. \Magento\Backend\Model\Menu::class,
  100. [
  101. 'logger' => $this->_logger
  102. ]
  103. );
  104. $menuTwo = $this->objectManagerHelper->getObject(
  105. \Magento\Backend\Model\Menu::class,
  106. [
  107. 'logger' => $this->_logger
  108. ]
  109. );
  110. $this->_items['item1']->expects($this->any())->method('hasChildren')->will($this->returnValue(true));
  111. $this->_items['item1']->expects($this->any())->method('getChildren')->will($this->returnValue($menuOne));
  112. $this->_model->add($this->_items['item1']);
  113. $this->_items['item2']->expects($this->any())->method('hasChildren')->will($this->returnValue(true));
  114. $this->_items['item2']->expects($this->any())->method('getChildren')->will($this->returnValue($menuTwo));
  115. $menuOne->add($this->_items['item2']);
  116. $this->_items['item3']->expects($this->any())->method('hasChildren')->will($this->returnValue(false));
  117. $menuTwo->add($this->_items['item3']);
  118. $this->assertEquals($this->_items['item1'], $this->_model->get('item1'));
  119. $this->assertEquals($this->_items['item2'], $this->_model->get('item2'));
  120. $this->assertEquals($this->_items['item3'], $this->_model->get('item3'));
  121. }
  122. public function testMove()
  123. {
  124. $this->_model->add($this->_items['item1']);
  125. $this->_model->add($this->_items['item2']);
  126. $this->_model->add($this->_items['item3']);
  127. $subMenu = $this->getMockBuilder(\Magento\Backend\Model\Menu::class)->disableOriginalConstructor()->getMock();
  128. $subMenu->expects($this->once())->method("add")->with($this->_items['item3']);
  129. $this->_items['item1']->expects($this->once())->method("getChildren")->will($this->returnValue($subMenu));
  130. $this->_model->move('item3', 'item1');
  131. $this->assertCount(2, $this->_model);
  132. $this->assertFalse(isset($this->_model[2]), "ttt");
  133. }
  134. /**
  135. * @expectedException \InvalidArgumentException
  136. */
  137. public function testMoveNonExistentItemThrowsException()
  138. {
  139. $this->_model->add($this->_items['item1']);
  140. $this->_model->add($this->_items['item2']);
  141. $this->_model->add($this->_items['item3']);
  142. $this->_model->move('item4', 'item1');
  143. }
  144. /**
  145. * @expectedException \InvalidArgumentException
  146. */
  147. public function testMoveToNonExistentItemThrowsException()
  148. {
  149. $this->_model->add($this->_items['item1']);
  150. $this->_model->add($this->_items['item2']);
  151. $this->_model->add($this->_items['item3']);
  152. $this->_model->move('item3', 'item4');
  153. }
  154. public function testRemoveRemovesMenuItem()
  155. {
  156. $this->_model->add($this->_items['item1']);
  157. $this->assertCount(1, $this->_model);
  158. $this->assertEquals($this->_items['item1'], $this->_model->get('item1'));
  159. $this->_model->remove('item1');
  160. $this->assertCount(0, $this->_model);
  161. $this->assertNull($this->_model->get('item1'));
  162. }
  163. public function testRemoveRemovesMenuItemRecursively()
  164. {
  165. $menuMock = $this->getMockBuilder(\Magento\Backend\Model\Menu::class)->disableOriginalConstructor()->getMock();
  166. $menuMock->expects($this->once())->method('remove')->with($this->equalTo('item2'));
  167. $this->_items['item1']->expects($this->any())->method('hasChildren')->will($this->returnValue(true));
  168. $this->_items['item1']->expects($this->any())->method('getChildren')->will($this->returnValue($menuMock));
  169. $this->_model->add($this->_items['item1']);
  170. $result = $this->_model->remove('item2');
  171. $this->assertNull($result);
  172. }
  173. public function testRemoveDoLogRemoveAction()
  174. {
  175. $this->_model->add($this->_items['item1']);
  176. $result = $this->_model->remove('item1');
  177. $this->assertTrue($result);
  178. }
  179. public function testReorderReordersItemOnTopLevel()
  180. {
  181. $this->_model->add($this->_items['item1'], null, 10);
  182. $this->_model->add($this->_items['item2'], null, 20);
  183. $this->assertEquals($this->_items['item2'], $this->_model[20]);
  184. $this->_model->reorder('item2', 5);
  185. $this->assertEquals($this->_items['item2'], $this->_model[5]);
  186. $this->assertFalse(isset($this->_model[20]));
  187. }
  188. public function testReorderReordersItemOnItsLevel()
  189. {
  190. $this->_logger->expects($this->any())->method('log');
  191. $subMenu = $this->objectManagerHelper->getObject(
  192. \Magento\Backend\Model\Menu::class,
  193. [
  194. 'logger' => $this->_logger
  195. ]
  196. );
  197. $this->_items['item1']->expects($this->any())->method("hasChildren")->will($this->returnValue(true));
  198. $this->_items['item1']->expects($this->any())->method("getChildren")->will($this->returnValue($subMenu));
  199. $this->_model->add($this->_items['item1']);
  200. $this->_model->add($this->_items['item2'], 'item1', 10);
  201. $this->_model->add($this->_items['item3'], 'item1', 20);
  202. $this->_model->reorder('item2', 25);
  203. $subMenu->reorder('item3', 30);
  204. $this->assertEquals($this->_items['item2'], $subMenu[25]);
  205. $this->assertEquals($this->_items['item3'], $subMenu[30]);
  206. }
  207. public function testIsLast()
  208. {
  209. $this->_model->add($this->_items['item1'], null, 10);
  210. $this->_model->add($this->_items['item2'], null, 16);
  211. $this->_model->add($this->_items['item3'], null, 15);
  212. $this->assertTrue($this->_model->isLast($this->_items['item2']));
  213. $this->assertFalse($this->_model->isLast($this->_items['item3']));
  214. }
  215. public function testGetFirstAvailableReturnsLeafNode()
  216. {
  217. $item = $this->createPartialMock(\Magento\Backend\Model\Menu\Item::class, ['getFirstAvailable', 'isAllowed']);
  218. $item->expects($this->never())->method('getFirstAvailable');
  219. $this->_model->add($item);
  220. $this->_items['item1']->expects($this->once())->method('isAllowed')->will($this->returnValue(true));
  221. $this->_items['item1']->expects($this->once())->method('isDisabled')->will($this->returnValue(false));
  222. $this->_items['item1']->expects($this->once())->method('hasChildren');
  223. $this->_model->add($this->_items['item1']);
  224. $this->assertEquals($this->_items['item1'], $this->_model->getFirstAvailable());
  225. }
  226. public function testGetFirstAvailableReturnsOnlyAllowedAndNotDisabledItem()
  227. {
  228. $this->_items['item1']->expects($this->exactly(1))->method('isAllowed')->will($this->returnValue(true));
  229. $this->_items['item1']->expects($this->exactly(1))->method('isDisabled')->will($this->returnValue(true));
  230. $this->_model->add($this->_items['item1']);
  231. $this->_items['item2']->expects($this->exactly(1))->method('isAllowed')->will($this->returnValue(false));
  232. $this->_model->add($this->_items['item2']);
  233. $this->_items['item3']->expects($this->exactly(1))->method('isAllowed')->will($this->returnValue(true));
  234. $this->_items['item3']->expects($this->exactly(1))->method('isDisabled')->will($this->returnValue(false));
  235. $this->_model->add($this->_items['item3']);
  236. $this->assertEquals($this->_items['item3'], $this->_model->getFirstAvailable());
  237. }
  238. public function testMultipleIterationsWorkProperly()
  239. {
  240. $this->_model->add($this->createMock(\Magento\Backend\Model\Menu\Item::class));
  241. $this->_model->add($this->createMock(\Magento\Backend\Model\Menu\Item::class));
  242. $this->_model->add($this->_items['item1']);
  243. $this->_model->add($this->_items['item2']);
  244. $items = [];
  245. /** @var $item \Magento\Backend\Model\Menu\Item */
  246. foreach ($this->_model as $item) {
  247. $items[] = $item->getId();
  248. }
  249. $itemsTwo = [];
  250. foreach ($this->_model as $item) {
  251. $itemsTwo[] = $item->getId();
  252. }
  253. $this->assertEquals($items, $itemsTwo);
  254. }
  255. /**
  256. * Test reset iterator to first element before each foreach
  257. */
  258. public function testNestedLoop()
  259. {
  260. $this->_model->add($this->_items['item1']);
  261. $this->_model->add($this->_items['item2']);
  262. $this->_model->add($this->_items['item3']);
  263. $expected = [
  264. 'item1' => ['item1', 'item2', 'item3'],
  265. 'item2' => ['item1', 'item2', 'item3'],
  266. 'item3' => ['item1', 'item2', 'item3'],
  267. ];
  268. $actual = [];
  269. foreach ($this->_model as $valLoopOne) {
  270. $keyLevelOne = $valLoopOne->getId();
  271. foreach ($this->_model as $valLoopTwo) {
  272. $actual[$keyLevelOne][] = $valLoopTwo->getId();
  273. }
  274. }
  275. $this->assertEquals($expected, $actual);
  276. }
  277. public function testSerialize()
  278. {
  279. $serializerMock = $this->createMock(SerializerInterface::class);
  280. $serializerMock->expects($this->once())
  281. ->method('serialize')
  282. ->with([['arrayData']])
  283. ->willReturn('serializedString');
  284. $menu = $this->objectManagerHelper->getObject(
  285. \Magento\Backend\Model\Menu::class,
  286. [
  287. 'logger' => $this->_logger,
  288. 'serializer' => $serializerMock,
  289. ]
  290. );
  291. $itemMock = $this->createMock(\Magento\Backend\Model\Menu\Item::class);
  292. $itemMock->expects($this->any())->method('getId')->will($this->returnValue('item1'));
  293. $itemMock->expects($this->once())
  294. ->method('toArray')
  295. ->willReturn(['arrayData']);
  296. $menu->add($itemMock);
  297. $this->assertEquals('serializedString', $menu->serialize());
  298. }
  299. public function testUnserialize()
  300. {
  301. $serializerMock = $this->createMock(SerializerInterface::class);
  302. $serializerMock->expects($this->once())
  303. ->method('unserialize')
  304. ->willReturn([['unserializedData']]);
  305. $menuItemFactoryMock = $this->createMock(Factory::class);
  306. $menuItemFactoryMock->expects($this->once())
  307. ->method('create')
  308. ->with(['unserializedData']);
  309. $menu = $this->objectManagerHelper->getObject(
  310. \Magento\Backend\Model\Menu::class,
  311. [
  312. 'logger' => $this->_logger,
  313. 'serializer' => $serializerMock,
  314. 'menuItemFactory' => $menuItemFactoryMock,
  315. ]
  316. );
  317. $menu->unserialize('serializedString');
  318. }
  319. }