StructureTest.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Config\Test\Unit\Model\Config;
  7. use Magento\Config\Model\Config\ScopeDefiner;
  8. use Magento\Config\Model\Config\Structure;
  9. use Magento\Config\Model\Config\Structure\Data;
  10. use Magento\Config\Model\Config\Structure\Element\FlyweightFactory;
  11. use Magento\Config\Model\Config\Structure\Element\Iterator\Tab as TabIterator;
  12. use PHPUnit_Framework_MockObject_MockObject as Mock;
  13. /**
  14. * Test for Structure.
  15. *
  16. * @see Structure
  17. */
  18. class StructureTest extends \PHPUnit\Framework\TestCase
  19. {
  20. /**
  21. * @var Structure|Mock
  22. */
  23. protected $_model;
  24. /**
  25. * @var FlyweightFactory|Mock
  26. */
  27. protected $_flyweightFactory;
  28. /**
  29. * @var TabIterator|Mock
  30. */
  31. protected $_tabIteratorMock;
  32. /**
  33. * @var Data|Mock
  34. */
  35. protected $_structureDataMock;
  36. /**
  37. * @var ScopeDefiner|Mock
  38. */
  39. protected $_scopeDefinerMock;
  40. /**
  41. * @var array
  42. */
  43. protected $_structureData;
  44. protected function setUp()
  45. {
  46. $this->_flyweightFactory = $this->getMockBuilder(FlyweightFactory::class)
  47. ->disableOriginalConstructor()
  48. ->getMock();
  49. $this->_tabIteratorMock = $this->getMockBuilder(TabIterator::class)
  50. ->disableOriginalConstructor()
  51. ->getMock();
  52. $this->_structureDataMock = $this->getMockBuilder(Data::class)
  53. ->disableOriginalConstructor()
  54. ->getMock();
  55. $this->_scopeDefinerMock = $this->getMockBuilder(ScopeDefiner::class)
  56. ->disableOriginalConstructor()
  57. ->getMock();
  58. $this->_structureData = require dirname(__DIR__) . '/_files/converted_config.php';
  59. $this->_scopeDefinerMock->expects($this->any())
  60. ->method('getScope')
  61. ->willReturn('scope');
  62. $this->_structureDataMock->expects($this->once())
  63. ->method('get')
  64. ->willReturn($this->_structureData['config']['system']);
  65. $this->_model = new Structure(
  66. $this->_structureDataMock,
  67. $this->_tabIteratorMock,
  68. $this->_flyweightFactory,
  69. $this->_scopeDefinerMock
  70. );
  71. }
  72. public function testGetTabsBuildsSectionTree()
  73. {
  74. $expected = ['tab1' => ['children' => ['section1' => ['tab' => 'tab1']]]];
  75. $this->_structureDataMock = $this->getMockBuilder(Data::class)
  76. ->disableOriginalConstructor()
  77. ->getMock();
  78. $this->_structureDataMock->expects($this->any())
  79. ->method('get')
  80. ->willReturn(
  81. ['sections' => ['section1' => ['tab' => 'tab1']], 'tabs' => ['tab1' => []]]
  82. );
  83. $this->_tabIteratorMock->expects($this->once())
  84. ->method('setElements')
  85. ->with($expected);
  86. $model = new \Magento\Config\Model\Config\Structure(
  87. $this->_structureDataMock,
  88. $this->_tabIteratorMock,
  89. $this->_flyweightFactory,
  90. $this->_scopeDefinerMock
  91. );
  92. $this->assertEquals($this->_tabIteratorMock, $model->getTabs());
  93. }
  94. public function testGetSectionList()
  95. {
  96. $expected = [
  97. 'section1_child_id_1' => true,
  98. 'section1_child_id_2' => true,
  99. 'section1_child_id_3' => true,
  100. 'section2_child_id_1' => true
  101. ];
  102. $this->_structureDataMock = $this->getMockBuilder(Data::class)
  103. ->disableOriginalConstructor()
  104. ->getMock();
  105. $this->_structureDataMock->expects($this->any())
  106. ->method('get')
  107. ->willReturn(
  108. [
  109. 'sections' => [
  110. 'section1' => [
  111. 'children' => [
  112. 'child_id_1' => 'child_data',
  113. 'child_id_2' => 'child_data',
  114. 'child_id_3' => 'child_data'
  115. ]
  116. ],
  117. 'section2' => [
  118. 'children' => [
  119. 'child_id_1' => 'child_data'
  120. ]
  121. ],
  122. ]
  123. ]
  124. );
  125. $model = new \Magento\Config\Model\Config\Structure(
  126. $this->_structureDataMock,
  127. $this->_tabIteratorMock,
  128. $this->_flyweightFactory,
  129. $this->_scopeDefinerMock
  130. );
  131. $this->assertEquals($expected, $model->getSectionList());
  132. }
  133. /**
  134. * @param string $path
  135. * @param string $expectedType
  136. * @param string $expectedId
  137. * @param string $expectedPath
  138. * @dataProvider emptyElementDataProvider
  139. */
  140. public function testGetElementReturnsEmptyElementIfNotExistingElementIsRequested(
  141. $path,
  142. $expectedType,
  143. $expectedId,
  144. $expectedPath
  145. ) {
  146. $elementMock = $this->getElementReturnsEmptyElementIfNotExistingElementIsRequested(
  147. $expectedType,
  148. $expectedId,
  149. $expectedPath
  150. );
  151. $this->assertEquals($elementMock, $this->_model->getElement($path));
  152. }
  153. /**
  154. * @param string $path
  155. * @param string $expectedType
  156. * @param string $expectedId
  157. * @param string $expectedPath
  158. * @dataProvider emptyElementDataProvider
  159. */
  160. public function testGetElementReturnsEmptyByConfigPathElementIfNotExistingElementIsRequested(
  161. $path,
  162. $expectedType,
  163. $expectedId,
  164. $expectedPath
  165. ) {
  166. $elementMock = $this->getElementReturnsEmptyElementIfNotExistingElementIsRequested(
  167. $expectedType,
  168. $expectedId,
  169. $expectedPath
  170. );
  171. $this->assertEquals($elementMock, $this->_model->getElementByConfigPath($path));
  172. }
  173. /**
  174. * @param string $expectedType
  175. * @param string $expectedId
  176. * @param string $expectedPath
  177. * @return Mock
  178. */
  179. private function getElementReturnsEmptyElementIfNotExistingElementIsRequested(
  180. $expectedType,
  181. $expectedId,
  182. $expectedPath
  183. ) {
  184. $expectedConfig = ['id' => $expectedId, 'path' => $expectedPath, '_elementType' => $expectedType];
  185. $elementMock = $this->getMockBuilder(Structure\ElementInterface::class)
  186. ->getMockForAbstractClass();
  187. $elementMock->expects($this->once())
  188. ->method('setData')
  189. ->with($expectedConfig);
  190. $this->_flyweightFactory->expects($this->once())
  191. ->method('create')
  192. ->with($expectedType)
  193. ->willReturn($elementMock);
  194. return $elementMock;
  195. }
  196. /**
  197. * @return array
  198. */
  199. public function emptyElementDataProvider()
  200. {
  201. return [
  202. ['someSection/group_1/nonexisting_field', 'field', 'nonexisting_field', 'someSection/group_1'],
  203. ['section_1/group_1/nonexisting_field', 'field', 'nonexisting_field', 'section_1/group_1'],
  204. ['section_1/nonexisting_group', 'group', 'nonexisting_group', 'section_1'],
  205. ['nonexisting_section', 'section', 'nonexisting_section', '']
  206. ];
  207. }
  208. public function testGetElementReturnsProperElementByPath()
  209. {
  210. $elementMock = $this->getElementPathReturnsProperElementByPath();
  211. $this->assertEquals($elementMock, $this->_model->getElement('section_1/group_level_1/field_3'));
  212. }
  213. public function testGetElementByConfigPathReturnsProperElementByPath()
  214. {
  215. $elementMock = $this->getElementPathReturnsProperElementByPath();
  216. $this->assertEquals($elementMock, $this->_model->getElementByConfigPath('section_1/group_level_1/field_3'));
  217. }
  218. /**
  219. * @return Mock
  220. */
  221. private function getElementPathReturnsProperElementByPath()
  222. {
  223. $section = $this->_structureData['config']['system']['sections']['section_1'];
  224. $fieldData = $section['children']['group_level_1']['children']['field_3'];
  225. $elementMock = $this->getMockBuilder(Structure\Element\Field::class)
  226. ->disableOriginalConstructor()
  227. ->getMock();
  228. $elementMock->expects($this->once())
  229. ->method('setData')
  230. ->with($fieldData, 'scope');
  231. $this->_flyweightFactory->expects($this->once())
  232. ->method('create')
  233. ->with('field')
  234. ->willReturn($elementMock);
  235. return $elementMock;
  236. }
  237. public function testGetElementByPathPartsIfSectionDataIsEmpty()
  238. {
  239. $fieldData = [
  240. 'id' => 'field_3',
  241. 'path' => 'section_1/group_level_1',
  242. '_elementType' => 'field',
  243. ];
  244. $pathParts = explode('/', 'section_1/group_level_1/field_3');
  245. $elementMock = $this->getMockBuilder(Structure\Element\Field::class)
  246. ->disableOriginalConstructor()
  247. ->getMock();
  248. $structureDataMock = $this->getMockBuilder(Data::class)
  249. ->disableOriginalConstructor()
  250. ->getMock();
  251. $elementMock->expects($this->once())
  252. ->method('setData')
  253. ->with($fieldData, 'scope');
  254. $this->_flyweightFactory->expects($this->once())
  255. ->method('create')
  256. ->with('field')
  257. ->willReturn($elementMock);
  258. $structureDataMock->expects($this->once())
  259. ->method('get')
  260. ->willReturn([]);
  261. $structureMock = new Structure(
  262. $structureDataMock,
  263. $this->_tabIteratorMock,
  264. $this->_flyweightFactory,
  265. $this->_scopeDefinerMock
  266. );
  267. $this->assertEquals($elementMock, $structureMock->getElementByPathParts($pathParts));
  268. }
  269. public function testGetFirstSectionReturnsFirstAllowedSection()
  270. {
  271. $tabMock = $this->getMockBuilder(Structure\Element\Tab::class)
  272. ->disableOriginalConstructor()
  273. ->setMethods(['current', 'getChildren', 'rewind'])
  274. ->getMock();
  275. $tabMock->expects($this->any())
  276. ->method('getChildren')
  277. ->willReturnSelf();
  278. $tabMock->expects($this->once())
  279. ->method('rewind');
  280. $section = $this->getMockBuilder(Structure\Element\Section::class)
  281. ->disableOriginalConstructor()
  282. ->setMethods(['isVisible', 'getData'])
  283. ->getMock();
  284. $section->expects($this->any())
  285. ->method('isVisible')
  286. ->willReturn(true);
  287. $section->expects($this->any())
  288. ->method('getData')
  289. ->willReturn('currentSection');
  290. $tabMock->expects($this->any())
  291. ->method('current')
  292. ->willReturn($section);
  293. $this->_tabIteratorMock->expects($this->once())
  294. ->method('rewind');
  295. $this->_tabIteratorMock->expects($this->once())
  296. ->method('current')
  297. ->willReturn($tabMock);
  298. $this->assertEquals('currentSection', $this->_model->getFirstSection()->getData());
  299. }
  300. public function testGetElementReturnsProperElementByPathCachesObject()
  301. {
  302. $elementMock = $this->getElementReturnsProperElementByPathCachesObject();
  303. $this->assertEquals($elementMock, $this->_model->getElement('section_1/group_level_1/field_3'));
  304. $this->assertEquals($elementMock, $this->_model->getElement('section_1/group_level_1/field_3'));
  305. }
  306. public function testGetElementByConfigPathReturnsProperElementByPathCachesObject()
  307. {
  308. $elementMock = $this->getElementReturnsProperElementByPathCachesObject();
  309. $this->assertEquals($elementMock, $this->_model->getElementByConfigPath('section_1/group_level_1/field_3'));
  310. $this->assertEquals($elementMock, $this->_model->getElementByConfigPath('section_1/group_level_1/field_3'));
  311. }
  312. /**
  313. * @return Mock
  314. */
  315. private function getElementReturnsProperElementByPathCachesObject()
  316. {
  317. $section = $this->_structureData['config']['system']['sections']['section_1'];
  318. $fieldData = $section['children']['group_level_1']['children']['field_3'];
  319. $elementMock = $this->getMockBuilder(Structure\Element\Field::class)
  320. ->disableOriginalConstructor()
  321. ->getMock();
  322. $elementMock->expects($this->once())
  323. ->method('setData')
  324. ->with($fieldData, 'scope');
  325. $this->_flyweightFactory->expects($this->once())
  326. ->method('create')
  327. ->with('field')
  328. ->willReturn($elementMock);
  329. return $elementMock;
  330. }
  331. /**
  332. * @param $attributeName
  333. * @param $attributeValue
  334. * @param $paths
  335. * @dataProvider getFieldPathsByAttributeDataProvider
  336. */
  337. public function testGetFieldPathsByAttribute($attributeName, $attributeValue, $paths)
  338. {
  339. $this->assertEquals($paths, $this->_model->getFieldPathsByAttribute($attributeName, $attributeValue));
  340. }
  341. /**
  342. * @return array
  343. */
  344. public function getFieldPathsByAttributeDataProvider()
  345. {
  346. return [
  347. [
  348. 'backend_model',
  349. \Magento\Config\Model\Config\Backend\Encrypted::class,
  350. [
  351. 'section_1/group_1/field_2',
  352. 'section_1/group_level_1/group_level_2/group_level_3/field_3_1_1',
  353. 'section_2/group_3/field_4',
  354. ]
  355. ],
  356. ['attribute_2', 'test_value_2', ['section_2/group_3/field_4']]
  357. ];
  358. }
  359. public function testGetFieldPaths()
  360. {
  361. $expected = [
  362. 'section/group/field2' => [
  363. 'field_2'
  364. ],
  365. 'field_3' => [
  366. 'field_3',
  367. 'field_3'
  368. ],
  369. 'field_3_1' => [
  370. 'field_3_1'
  371. ],
  372. 'field_3_1_1' => [
  373. 'field_3_1_1'
  374. ],
  375. 'section/group/field4' => [
  376. 'field_4',
  377. ],
  378. 'field_5' => [
  379. 'field_5',
  380. ],
  381. ];
  382. $this->assertSame(
  383. $expected,
  384. $this->_model->getFieldPaths()
  385. );
  386. }
  387. }