JsonGenerationFromDataObjectTest.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Webapi;
  7. use Magento\TestFramework\Helper\Bootstrap;
  8. use Magento\Framework\App\ProductMetadataInterface;
  9. use Magento\Store\Model\StoreManagerInterface;
  10. /**
  11. * Test REST schema generation mechanisms.
  12. */
  13. class JsonGenerationFromDataObjectTest extends \Magento\TestFramework\TestCase\WebapiAbstract
  14. {
  15. /** @var string */
  16. protected $baseUrl = TESTS_BASE_URL;
  17. /** @var string */
  18. protected $storeCode;
  19. /** @var bool */
  20. protected $isSingleService;
  21. /**
  22. * @var ProductMetadataInterface
  23. */
  24. protected $productMetadata;
  25. protected function setUp()
  26. {
  27. $this->_markTestAsRestOnly("JSON generation tests are intended to be executed for REST adapter only.");
  28. $this->storeCode = Bootstrap::getObjectManager()->get(StoreManagerInterface::class)
  29. ->getStore()->getCode();
  30. $this->productMetadata = Bootstrap::getObjectManager()->get(ProductMetadataInterface::class);
  31. parent::setUp();
  32. }
  33. public function testMultiServiceRetrieval()
  34. {
  35. $this->isSingleService = false;
  36. $resourcePath = '/schema?services=testModule5AllSoapAndRestV1,testModule5AllSoapAndRestV2';
  37. $serviceInfo = [
  38. 'rest' => [
  39. 'resourcePath' => $resourcePath,
  40. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
  41. ],
  42. ];
  43. $schemaContent = $this->_webApiCall($serviceInfo);
  44. $this->checkActualData($this->getExpectedMultiServiceData(), $schemaContent);
  45. }
  46. public function testSingleServiceRetrieval()
  47. {
  48. $this->isSingleService = false;
  49. $resourcePath = '/schema?services=testModule5AllSoapAndRestV2';
  50. $serviceInfo = [
  51. 'rest' => [
  52. 'resourcePath' => $resourcePath,
  53. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
  54. ],
  55. ];
  56. $schemaContent = $this->_webApiCall($serviceInfo);
  57. $this->checkActualData($this->getExpectedSingleServiceData(), $schemaContent);
  58. }
  59. /**
  60. * @expectedException \Exception
  61. * @expectedExceptionMessage Specified request cannot be processed.
  62. */
  63. public function testInvalidRestUrlNoServices()
  64. {
  65. $resourcePath = '';
  66. $serviceInfo = [
  67. 'rest' => [
  68. 'resourcePath' => $resourcePath,
  69. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
  70. ],
  71. ];
  72. $this->_webApiCall($serviceInfo);
  73. }
  74. /**
  75. * @expectedException \Exception
  76. * @expectedExceptionMessage Incorrect format of request URI or Requested services are missing.
  77. */
  78. public function testInvalidRestUrlInvalidServiceName()
  79. {
  80. $this->isSingleService = false;
  81. $resourcePath = '/schema?services=invalidServiceName';
  82. $serviceInfo = [
  83. 'rest' => [
  84. 'resourcePath' => $resourcePath,
  85. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
  86. ],
  87. ];
  88. $this->_webApiCall($serviceInfo);
  89. }
  90. private function assertRecursiveArray($expected, $actual, $checkVal)
  91. {
  92. ksort($expected);
  93. ksort($actual);
  94. foreach ($expected as $expKey => $expVal) {
  95. $this->assertArrayHasKey($expKey, $actual, 'Schema does not contain \'' . $expKey . '\' section.');
  96. if (is_array($expVal)) {
  97. $this->assertTrue(is_array($actual[$expKey]));
  98. $this->assertRecursiveArray($expVal, $actual[$expKey], $checkVal);
  99. } elseif ($checkVal) {
  100. $this->assertEquals($expVal, $actual[$expKey], '\'' . $expKey . '\' section content is invalid.');
  101. }
  102. }
  103. }
  104. public function checkActualData($expected, $actual)
  105. {
  106. $this->assertRecursiveArray($expected, $actual, true);
  107. }
  108. public function getExpectedCommonData()
  109. {
  110. $versionParts = explode('.', $this->productMetadata->getVersion());
  111. if (!isset($versionParts[0]) || !isset($versionParts[1])) {
  112. return []; // Major and minor version are not set - return empty response
  113. }
  114. $majorMinorVersion = $versionParts[0] . '.' . $versionParts[1];
  115. $url = str_replace('://', '', strstr($this->baseUrl, '://'));
  116. $host = strpos($url, '/') ? strstr($url, '/', true) : $url;
  117. $basePath = strstr(rtrim($url, '/'), '/');
  118. $basePath = $basePath ? trim($basePath, '/') . '/' : '';
  119. $basePath = '/' . $basePath . 'rest/' . $this->storeCode;
  120. return [
  121. 'swagger' => '2.0',
  122. 'info' => [
  123. 'version' => $majorMinorVersion,
  124. 'title' => $this->productMetadata->getName() . ' ' .$this->productMetadata->getEdition(),
  125. ],
  126. 'host' => $host,
  127. 'basePath' => $basePath,
  128. ];
  129. }
  130. /**
  131. * @return array
  132. * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
  133. */
  134. public function getExpectedMultiServiceData()
  135. {
  136. $expected = [
  137. 'tags' => [
  138. [
  139. 'name' => 'testModule5AllSoapAndRestV1',
  140. 'description' => 'Both SOAP and REST Version ONE',
  141. ],
  142. [
  143. 'name' => 'testModule5AllSoapAndRestV2',
  144. 'description' => 'Both SOAP and REST Version TWO',
  145. ],
  146. ],
  147. 'paths' => [
  148. '/V1/TestModule5/{parentId}/nestedResource/{entityId}' => [
  149. 'put' => [
  150. 'tags' => [
  151. 'testModule5AllSoapAndRestV1',
  152. ],
  153. 'description' => 'Update existing item.',
  154. 'operationId' => 'testModule5AllSoapAndRestV1NestedUpdatePut',
  155. 'parameters' => [
  156. [
  157. 'name' => 'parentId',
  158. 'in' => 'path',
  159. 'type' => 'string',
  160. 'required' => true
  161. ],
  162. [
  163. 'name' => 'entityId',
  164. 'in' => 'path',
  165. 'type' => 'string',
  166. 'required' => true
  167. ],
  168. [
  169. 'name' => 'testModule5AllSoapAndRestV1NestedUpdatePutBody',
  170. 'in' => 'body',
  171. 'schema' => [
  172. 'required' => [
  173. 'entityItem',
  174. ],
  175. 'properties' => [
  176. 'entityItem' => [
  177. '$ref' => '#/definitions/test-module5-v1-entity-all-soap-and-rest',
  178. ],
  179. ],
  180. 'type' => 'object'
  181. ],
  182. ]
  183. ],
  184. 'responses' => [
  185. 200 => [
  186. 'description' => '200 Success.',
  187. 'schema' => [
  188. '$ref' => '#/definitions/test-module5-v1-entity-all-soap-and-rest',
  189. ],
  190. ],
  191. 401 => [
  192. 'description' => '401 Unauthorized',
  193. 'schema' => [
  194. '$ref' => '#/definitions/error-response',
  195. ],
  196. ],
  197. 'default' => [
  198. 'description' => 'Unexpected error',
  199. 'schema' => [
  200. '$ref' => '#/definitions/error-response',
  201. ],
  202. ],
  203. ],
  204. ],
  205. ],
  206. ],
  207. 'definitions' => [
  208. 'framework-attribute-interface' => [
  209. 'type' => 'object',
  210. 'description' => 'Interface for custom attribute value.',
  211. 'properties' => [
  212. 'attribute_code' => [
  213. 'type' => 'string',
  214. 'description' => 'Attribute code',
  215. ],
  216. 'value' => [
  217. 'type' => 'string',
  218. 'description' => 'Attribute value',
  219. ],
  220. ],
  221. 'required' => [
  222. 'attribute_code',
  223. 'value',
  224. ],
  225. ],
  226. 'test-module5-v1-entity-all-soap-and-rest' => [
  227. 'type' => 'object',
  228. 'description' => 'Some Data Object short description. Data Object long multi line description.',
  229. 'properties' => [
  230. 'entity_id' => [
  231. 'type' => 'integer',
  232. 'description' => 'Item ID',
  233. ],
  234. 'name' => [
  235. 'type' => 'string',
  236. 'description' => 'Item name',
  237. ],
  238. 'enabled' => [
  239. 'type' => 'boolean',
  240. 'description' => 'If entity is enabled',
  241. ],
  242. 'orders' => [
  243. 'type' => 'boolean',
  244. 'description' => 'If current entity has a property defined',
  245. ],
  246. 'custom_attributes' => [
  247. 'type' => 'array',
  248. 'description' => 'Custom attributes values.',
  249. 'items' => [
  250. '$ref' => '#/definitions/framework-attribute-interface',
  251. ],
  252. ],
  253. ],
  254. 'required' => [
  255. 'entity_id',
  256. 'enabled',
  257. 'orders',
  258. ],
  259. ],
  260. ],
  261. ];
  262. return array_merge_recursive($expected, $this->getExpectedCommonData());
  263. }
  264. /**
  265. * @return array
  266. * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
  267. */
  268. public function getExpectedSingleServiceData()
  269. {
  270. $expected = [
  271. 'tags' => [
  272. [
  273. 'name' => 'testModule5AllSoapAndRestV2',
  274. 'description' => 'Both SOAP and REST Version TWO',
  275. ],
  276. ],
  277. 'paths' => [
  278. '/V2/TestModule5/{id}' => [
  279. 'delete' => [
  280. 'tags' => [
  281. 'testModule5AllSoapAndRestV2',
  282. ],
  283. 'description' => 'Delete existing item.',
  284. 'operationId' => 'testModule5AllSoapAndRestV2DeleteDelete',
  285. 'parameters' => [
  286. [
  287. 'name' => 'id',
  288. 'in' => 'path',
  289. 'type' => 'string',
  290. 'required' => true
  291. ],
  292. ],
  293. 'responses' => [
  294. 200 => [
  295. 'description' => '200 Success.',
  296. 'schema' => [
  297. '$ref' => '#/definitions/test-module5-v2-entity-all-soap-and-rest',
  298. ],
  299. ],
  300. 401 => [
  301. 'description' => '401 Unauthorized',
  302. 'schema' => [
  303. '$ref' => '#/definitions/error-response',
  304. ],
  305. ],
  306. 'default' => [
  307. 'description' => 'Unexpected error',
  308. 'schema' => [
  309. '$ref' => '#/definitions/error-response',
  310. ],
  311. ],
  312. ],
  313. ],
  314. ],
  315. ],
  316. 'definitions' => [
  317. 'test-module5-v2-entity-all-soap-and-rest' => [
  318. 'type' => 'object',
  319. 'description' => 'Some Data Object short description. Data Object long multi line description.',
  320. 'properties' => [
  321. 'price' => [
  322. 'type' => 'integer',
  323. ],
  324. ],
  325. 'required' => [
  326. 'price',
  327. ],
  328. ],
  329. ],
  330. ];
  331. return array_merge($expected, $this->getExpectedCommonData());
  332. }
  333. }