DomTest.php 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\Config\Test\Unit;
  7. class DomTest extends \PHPUnit\Framework\TestCase
  8. {
  9. /**
  10. * @var \Magento\Framework\Config\ValidationStateInterface|\PHPUnit_Framework_MockObject_MockObject
  11. */
  12. protected $validationStateMock;
  13. protected function setUp()
  14. {
  15. $this->validationStateMock = $this->getMockForAbstractClass(
  16. \Magento\Framework\Config\ValidationStateInterface::class
  17. );
  18. $this->validationStateMock->method('isValidationRequired')
  19. ->willReturn(true);
  20. }
  21. /**
  22. * @param string $xmlFile
  23. * @param string $newXmlFile
  24. * @param array $ids
  25. * @param string|null $typeAttributeName
  26. * @param string $expectedXmlFile
  27. * @dataProvider mergeDataProvider
  28. */
  29. public function testMerge($xmlFile, $newXmlFile, $ids, $typeAttributeName, $expectedXmlFile)
  30. {
  31. $xml = file_get_contents(__DIR__ . "/_files/dom/{$xmlFile}");
  32. $newXml = file_get_contents(__DIR__ . "/_files/dom/{$newXmlFile}");
  33. $config = new \Magento\Framework\Config\Dom($xml, $this->validationStateMock, $ids, $typeAttributeName);
  34. $config->merge($newXml);
  35. $this->assertXmlStringEqualsXmlFile(__DIR__ . "/_files/dom/{$expectedXmlFile}", $config->getDom()->saveXML());
  36. }
  37. /**
  38. * @return array
  39. */
  40. public function mergeDataProvider()
  41. {
  42. // note differences of XML declaration in fixture files: sometimes encoding is specified, sometimes isn't
  43. return [
  44. [
  45. 'ids.xml',
  46. 'ids_new.xml',
  47. [
  48. '/root/node/subnode' => 'id',
  49. '/root/other_node' => 'id',
  50. '/root/other_node/child' => 'identifier',
  51. ],
  52. null,
  53. 'ids_merged.xml',
  54. ],
  55. ['no_ids.xml', 'no_ids_new.xml', [], null, 'no_ids_merged.xml'],
  56. ['ambiguous_one.xml', 'ambiguous_new_two.xml', [], null, 'ambiguous_merged.xml'],
  57. ['namespaced.xml', 'namespaced_new.xml', ['/root/node' => 'id'], null, 'namespaced_merged.xml'],
  58. ['override_node.xml', 'override_node_new.xml', [], null, 'override_node_merged.xml'],
  59. ['override_node_new.xml', 'override_node.xml', [], null, 'override_node_merged.xml'],
  60. ['text_node.xml', 'text_node_new.xml', [], null, 'text_node_merged.xml'],
  61. [
  62. 'recursive.xml',
  63. 'recursive_new.xml',
  64. ['/root/(node|another_node)(/param)?' => 'name', '/root/node/param(/complex/item)+' => 'key'],
  65. null,
  66. 'recursive_merged.xml',
  67. ],
  68. [
  69. 'recursive_deep.xml',
  70. 'recursive_deep_new.xml',
  71. ['/root(/node)+' => 'name'],
  72. null,
  73. 'recursive_deep_merged.xml',
  74. ],
  75. [
  76. 'types.xml',
  77. 'types_new.xml',
  78. ['/root/item' => 'id', '/root/item/subitem' => 'id'],
  79. 'xsi:type',
  80. 'types_merged.xml',
  81. ],
  82. [
  83. 'attributes.xml',
  84. 'attributes_new.xml',
  85. ['/root/item' => 'id', '/root/item/subitem' => 'id'],
  86. 'xsi:type',
  87. 'attributes_merged.xml',
  88. ],
  89. ];
  90. }
  91. /**
  92. * @expectedException \Magento\Framework\Exception\LocalizedException
  93. * @expectedExceptionMessage More than one node matching the query: /root/node/subnode
  94. */
  95. public function testMergeException()
  96. {
  97. $xml = file_get_contents(__DIR__ . "/_files/dom/ambiguous_two.xml");
  98. $newXml = file_get_contents(__DIR__ . "/_files/dom/ambiguous_new_one.xml");
  99. $config = new \Magento\Framework\Config\Dom($xml, $this->validationStateMock);
  100. $config->merge($newXml);
  101. }
  102. /**
  103. * @param string $xml
  104. * @param array $expectedErrors
  105. * @dataProvider validateDataProvider
  106. */
  107. public function testValidate($xml, array $expectedErrors)
  108. {
  109. if (!function_exists('libxml_set_external_entity_loader')) {
  110. $this->markTestSkipped('Skipped on HHVM. Will be fixed in MAGETWO-45033');
  111. }
  112. $dom = new \Magento\Framework\Config\Dom($xml, $this->validationStateMock);
  113. $actualResult = $dom->validate(__DIR__ . '/_files/sample.xsd', $actualErrors);
  114. $this->assertEquals(empty($expectedErrors), $actualResult);
  115. $this->assertEquals($expectedErrors, $actualErrors);
  116. }
  117. /**
  118. * @return array
  119. */
  120. public function validateDataProvider()
  121. {
  122. return [
  123. 'valid' => ['<root><node id="id1"/><node id="id2"/></root>', []],
  124. 'invalid' => [
  125. '<root><node id="id1"/><unknown_node/></root>',
  126. ["Element 'unknown_node': This element is not expected. Expected is ( node ).\nLine: 1\n"],
  127. ],
  128. ];
  129. }
  130. public function testValidateCustomErrorFormat()
  131. {
  132. $xml = '<root><unknown_node/></root>';
  133. $errorFormat = 'Error: `%message%`';
  134. $expectedErrors = [
  135. "Error: `Element 'unknown_node': This element is not expected. Expected is ( node ).`",
  136. ];
  137. $dom = new \Magento\Framework\Config\Dom($xml, $this->validationStateMock, [], null, null, $errorFormat);
  138. $actualResult = $dom->validate(__DIR__ . '/_files/sample.xsd', $actualErrors);
  139. $this->assertFalse($actualResult);
  140. $this->assertEquals($expectedErrors, $actualErrors);
  141. }
  142. /**
  143. * @expectedException \InvalidArgumentException
  144. * @expectedExceptionMessage Error format '%message%,%unknown%' contains unsupported placeholders
  145. */
  146. public function testValidateCustomErrorFormatInvalid()
  147. {
  148. $xml = '<root><unknown_node/></root>';
  149. $errorFormat = '%message%,%unknown%';
  150. $dom = new \Magento\Framework\Config\Dom($xml, $this->validationStateMock, [], null, null, $errorFormat);
  151. $dom->validate(__DIR__ . '/_files/sample.xsd');
  152. }
  153. public function testValidateUnknownError()
  154. {
  155. if (!function_exists('libxml_set_external_entity_loader')) {
  156. $this->markTestSkipped('Skipped on HHVM. Will be fixed in MAGETWO-45033');
  157. }
  158. $xml = '<root><node id="id1"/><node id="id2"/></root>';
  159. $schemaFile = __DIR__ . '/_files/sample.xsd';
  160. $dom = new \Magento\Framework\Config\Dom($xml, $this->validationStateMock);
  161. $domMock = $this->createPartialMock(\DOMDocument::class, ['schemaValidate']);
  162. $domMock->expects($this->once())
  163. ->method('schemaValidate')
  164. ->with($schemaFile)
  165. ->willReturn(false);
  166. $this->assertEquals(
  167. ["Element 'unknown_node': This element is not expected. Expected is ( node ).\nLine: 1\n"],
  168. $dom->validateDomDocument($domMock, $schemaFile)
  169. );
  170. }
  171. /**
  172. * @expectedException \Magento\Framework\Config\Dom\ValidationSchemaException
  173. */
  174. public function testValidateDomDocumentThrowsException()
  175. {
  176. if (!function_exists('libxml_set_external_entity_loader')) {
  177. $this->markTestSkipped('Skipped on HHVM. Will be fixed in MAGETWO-45033');
  178. }
  179. $xml = '<root><node id="id1"/><node id="id2"/></root>';
  180. $schemaFile = __DIR__ . '/_files/sample.xsd';
  181. $dom = new \Magento\Framework\Config\Dom($xml, $this->validationStateMock);
  182. $domMock = $this->createPartialMock(\DOMDocument::class, ['schemaValidate']);
  183. $domMock->expects($this->once())
  184. ->method('schemaValidate')
  185. ->with($schemaFile)
  186. ->willThrowException(new \Exception());
  187. $dom->validateDomDocument($domMock, $schemaFile);
  188. }
  189. }