Api.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. <?php
  2. /**
  3. * Helper for API integration tests.
  4. *
  5. * Copyright © Magento, Inc. All rights reserved.
  6. * See COPYING.txt for license details.
  7. */
  8. namespace Magento\TestFramework\Helper;
  9. class Api
  10. {
  11. /**
  12. * Previous error handler
  13. *
  14. * @var mixed
  15. */
  16. protected static $_previousHandler = null;
  17. /**
  18. * Call API method via API handler.
  19. *
  20. * @param \PHPUnit\Framework\TestCase $testCase Active test case
  21. * @param string $path
  22. * @param array $params Order of items matters as they are passed to call_user_func_array
  23. * @return mixed
  24. */
  25. public static function call(\PHPUnit\Framework\TestCase $testCase, $path, $params = [])
  26. {
  27. $soapAdapterMock = $testCase->getMock(\stdClass::class, ['fault']);
  28. $soapAdapterMock->expects(
  29. $testCase->any()
  30. )->method(
  31. 'fault'
  32. )->will(
  33. $testCase->returnCallback([__CLASS__, 'soapAdapterFaultCallback'])
  34. );
  35. $serverMock = $testCase->getMock(\stdClass::class, ['getAdapter']);
  36. $serverMock->expects($testCase->any())->method('getAdapter')->will($testCase->returnValue($soapAdapterMock));
  37. $apiSessionMock = $testCase->createPartialMock(\stdClass::class, ['isAllowed', 'isLoggedIn']);
  38. $apiSessionMock->expects($testCase->any())->method('isAllowed')->will($testCase->returnValue(true));
  39. $apiSessionMock->expects($testCase->any())->method('isLoggedIn')->will($testCase->returnValue(true));
  40. $handlerMock = $testCase->createPartialMock(\stdClass::class, ['_getServer', '_getSession']);
  41. self::$_previousHandler = set_error_handler([$handlerMock, 'handlePhpError']);
  42. $handlerMock->expects($testCase->any())->method('_getServer')->will($testCase->returnValue($serverMock));
  43. $handlerMock->expects($testCase->any())->method('_getSession')->will($testCase->returnValue($apiSessionMock));
  44. array_unshift($params, 'sessionId');
  45. /** @var $objectManager \Magento\TestFramework\ObjectManager */
  46. $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
  47. $objectManager->get(\Magento\Framework\Registry::class)->unregister('isSecureArea');
  48. $objectManager->get(\Magento\Framework\Registry::class)->register('isSecureArea', true);
  49. $result = call_user_func_array([$handlerMock, $path], $params);
  50. $objectManager->get(\Magento\Framework\Registry::class)->unregister('isSecureArea');
  51. $objectManager->get(\Magento\Framework\Registry::class)->register('isSecureArea', false);
  52. self::restoreErrorHandler();
  53. return $result;
  54. }
  55. /**
  56. * Call API method via API handler that raises SoapFault exception
  57. *
  58. * @param \PHPUnit\Framework\TestCase $testCase Active test case
  59. * @param string $path
  60. * @param array $params Order of items matters as they are passed to call_user_func_array
  61. * @param string $expectedMessage exception message
  62. * @return \SoapFault
  63. */
  64. public static function callWithException(
  65. \PHPUnit\Framework\TestCase $testCase,
  66. $path,
  67. $params = [],
  68. $expectedMessage = ''
  69. ) {
  70. try {
  71. self::call($testCase, $path, $params);
  72. self::restoreErrorHandler();
  73. $testCase->fail('Expected error exception was not raised.');
  74. } catch (\SoapFault $exception) {
  75. self::restoreErrorHandler();
  76. if ($expectedMessage) {
  77. $testCase->assertEquals($expectedMessage, $exception->getMessage());
  78. }
  79. return $exception;
  80. }
  81. }
  82. /**
  83. * Restore previously used error handler
  84. */
  85. public static function restoreErrorHandler()
  86. {
  87. set_error_handler(self::$_previousHandler);
  88. }
  89. /**
  90. * Throw SoapFault exception. Callback for 'fault' method of API.
  91. *
  92. * @param string $exceptionCode
  93. * @param string $exceptionMessage
  94. * @throws \SoapFault
  95. */
  96. public static function soapAdapterFaultCallback($exceptionCode, $exceptionMessage)
  97. {
  98. throw new \SoapFault($exceptionCode, $exceptionMessage);
  99. }
  100. /**
  101. * Convert Simple XML to array
  102. *
  103. * @param \SimpleXMLObject $xml
  104. * @param String $keyTrimmer
  105. * @return object
  106. *
  107. * In XML notation we can't have nodes with digital names in other words fallowing XML will be not valid:
  108. * &lt;24&gt;
  109. * Default category
  110. * &lt;/24&gt;
  111. *
  112. * But this one will not cause any problems:
  113. * &lt;qwe_24&gt;
  114. * Default category
  115. * &lt;/qwe_24&gt;
  116. *
  117. * So when we want to obtain an array with key 24 we will pass the correct XML from above and $keyTrimmer = 'qwe_';
  118. * As a result we will obtain an array with digital key node.
  119. *
  120. * In the other case just don't pass the $keyTrimmer.
  121. */
  122. public static function simpleXmlToArray($xml, $keyTrimmer = null)
  123. {
  124. $result = [];
  125. $isTrimmed = false;
  126. if (null !== $keyTrimmer) {
  127. $isTrimmed = true;
  128. }
  129. if (is_object($xml)) {
  130. foreach (get_object_vars($xml->children()) as $key => $node) {
  131. $arrKey = $key;
  132. if ($isTrimmed) {
  133. $arrKey = str_replace($keyTrimmer, '', $key);
  134. }
  135. if (is_numeric($arrKey)) {
  136. $arrKey = 'Obj' . $arrKey;
  137. }
  138. if (is_object($node)) {
  139. $result[$arrKey] = self::simpleXmlToArray($node, $keyTrimmer);
  140. } elseif (is_array($node)) {
  141. $result[$arrKey] = [];
  142. foreach ($node as $nodeValue) {
  143. $result[$arrKey][] = self::simpleXmlToArray($nodeValue, $keyTrimmer);
  144. }
  145. } else {
  146. $result[$arrKey] = (string)$node;
  147. }
  148. }
  149. } else {
  150. $result = (string)$xml;
  151. }
  152. return $result;
  153. }
  154. /**
  155. * Check specific fields value in some entity data.
  156. *
  157. * @param \PHPUnit\Framework\TestCase $testCase
  158. * @param array $expectedData
  159. * @param array $actualData
  160. * @param array $fieldsToCompare To be able to compare fields from loaded model with fields from API response
  161. * this parameter provides fields mapping.
  162. * Array can store model field name $entityField mapped on field name in API response.
  163. * $fieldsToCompare format is:
  164. * $fieldsToCompare = array($modelFieldName => $apiResponseFieldName);
  165. * Example:
  166. * $fieldsToCompare = array(
  167. * 'entity_id' => 'product_id',
  168. * 'sku',
  169. * 'attribute_set_id' => 'set',
  170. * 'type_id' => 'type',
  171. * 'category_ids',
  172. * );
  173. */
  174. public static function checkEntityFields(
  175. \PHPUnit\Framework\TestCase $testCase,
  176. array $expectedData,
  177. array $actualData,
  178. array $fieldsToCompare = []
  179. ) {
  180. $fieldsToCompare = !empty($fieldsToCompare) ? $fieldsToCompare : array_keys($expectedData);
  181. foreach ($fieldsToCompare as $entityField => $field) {
  182. $testCase->assertEquals(
  183. $expectedData[is_numeric($entityField) ? $field : $entityField],
  184. $actualData[$field],
  185. sprintf('"%s" filed has invalid value.', $field)
  186. );
  187. }
  188. }
  189. }