MassScheduleTest.php 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. <?php
  2. /**
  3. * Test services for name collisions.
  4. *
  5. * Let we have two service interfaces called Foo\Bar\Service\SomeBazV1Interface and Foo\Bar\Service\Some\BazV1Interface.
  6. * Given current name generation logic both are going to be translated to BarSomeBazV1. This test checks such things
  7. * are not going to happen.
  8. *
  9. * Copyright © Magento, Inc. All rights reserved.
  10. * See COPYING.txt for license details.
  11. */
  12. namespace Magento\AsynchronousOperations\Model;
  13. use Magento\Framework\Exception\BulkException;
  14. use Magento\Framework\Phrase;
  15. use Magento\Framework\Registry;
  16. use Magento\Framework\Webapi\Exception;
  17. use Magento\TestFramework\Helper\Bootstrap;
  18. use Magento\Catalog\Api\Data\ProductInterface;
  19. use Magento\TestFramework\MessageQueue\PublisherConsumerController;
  20. use Magento\TestFramework\MessageQueue\EnvironmentPreconditionException;
  21. use Magento\TestFramework\MessageQueue\PreconditionFailedException;
  22. use Magento\Catalog\Model\ResourceModel\Product\Collection;
  23. use Magento\Catalog\Api\ProductRepositoryInterface;
  24. use Magento\Framework\ObjectManagerInterface;
  25. /**
  26. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  27. */
  28. class MassScheduleTest extends \PHPUnit\Framework\TestCase
  29. {
  30. /**
  31. * @var string[]
  32. */
  33. protected $consumers = ['async.operations.all'];
  34. /**
  35. * @var ObjectManagerInterface
  36. */
  37. protected $objectManager;
  38. /**
  39. * @var MassSchedule
  40. */
  41. private $massSchedule;
  42. /**
  43. * @var Collection
  44. */
  45. private $collection;
  46. /**
  47. * @var ProductRepositoryInterface
  48. */
  49. private $productRepository;
  50. /**
  51. * @var PublisherConsumerController
  52. */
  53. private $publisherConsumerController;
  54. /**
  55. * @var array
  56. */
  57. private $skus = [];
  58. /**
  59. * @var Registry
  60. */
  61. private $registry;
  62. protected function setUp()
  63. {
  64. $this->objectManager = Bootstrap::getObjectManager();
  65. $this->registry = $this->objectManager->get(Registry::class);
  66. $this->massSchedule = $this->objectManager->create(MassSchedule::class);
  67. $this->logFilePath = TESTS_TEMP_DIR . "/MessageQueueTestLog.txt";
  68. $this->collection = $this->objectManager->create(Collection::class);
  69. $this->productRepository = $this->objectManager->create(ProductRepositoryInterface::class);
  70. /** @var PublisherConsumerController publisherConsumerController */
  71. $this->publisherConsumerController = $this->objectManager->create(PublisherConsumerController::class, [
  72. 'consumers' => $this->consumers,
  73. 'logFilePath' => $this->logFilePath,
  74. 'appInitParams' => \Magento\TestFramework\Helper\Bootstrap::getInstance()->getAppInitParams()
  75. ]);
  76. try {
  77. $this->publisherConsumerController->initialize();
  78. } catch (EnvironmentPreconditionException $e) {
  79. $this->markTestSkipped($e->getMessage());
  80. } catch (PreconditionFailedException $e) {
  81. $this->fail($e->getMessage());
  82. }
  83. parent::setUp();
  84. }
  85. /**
  86. * @dataProvider productDataProvider
  87. * @param ProductInterface[] $products
  88. */
  89. public function testScheduleMass($products)
  90. {
  91. try {
  92. $this->sendBulk($products);
  93. } catch (BulkException $bulkException) {
  94. $this->fail('Bulk was not accepted in full');
  95. }
  96. //assert all products are created
  97. try {
  98. $this->publisherConsumerController->waitForAsynchronousResult(
  99. [$this, 'assertProductExists'],
  100. [$this->skus, count($this->skus)]
  101. );
  102. } catch (PreconditionFailedException $e) {
  103. $this->fail("Not all products were created");
  104. }
  105. }
  106. public function sendBulk($products)
  107. {
  108. $this->skus = [];
  109. foreach ($products as $data) {
  110. if (isset($data['product'])) {
  111. $this->skus[] = $data['product']->getSku();
  112. }
  113. }
  114. $this->clearProducts();
  115. $result = $this->massSchedule->publishMass(
  116. 'async.magento.catalog.api.productrepositoryinterface.save.post',
  117. $products
  118. );
  119. //assert bulk accepted with no errors
  120. $this->assertFalse($result->isErrors());
  121. //assert number of products sent to queue
  122. $this->assertCount(count($this->skus), $result->getRequestItems());
  123. }
  124. public function tearDown()
  125. {
  126. $this->publisherConsumerController->stopConsumers();
  127. $this->clearProducts();
  128. parent::tearDown();
  129. }
  130. private function clearProducts()
  131. {
  132. $size = $this->objectManager->create(Collection::class)
  133. ->addAttributeToFilter('sku', ['in' => $this->skus])
  134. ->load()
  135. ->getSize();
  136. if ($size == 0) {
  137. return;
  138. }
  139. $this->registry->unregister('isSecureArea');
  140. $this->registry->register('isSecureArea', true);
  141. try {
  142. foreach ($this->skus as $sku) {
  143. $this->productRepository->deleteById($sku);
  144. }
  145. } catch (\Exception $e) {
  146. //nothing to delete
  147. }
  148. $this->registry->unregister('isSecureArea');
  149. $size = $this->objectManager->create(Collection::class)
  150. ->addAttributeToFilter('sku', ['in' => $this->skus])
  151. ->load()
  152. ->getSize();
  153. if ($size > 0) {
  154. throw new Exception(new Phrase("Collection size after clearing the products: %size", ['size' => $size]));
  155. }
  156. }
  157. public function assertProductExists($productsSkus, $count)
  158. {
  159. $collection = $this->objectManager->create(Collection::class)
  160. ->addAttributeToFilter('sku', ['in' => $productsSkus])
  161. ->load();
  162. $size = $collection->getSize();
  163. return $size == $count;
  164. }
  165. /**
  166. * @dataProvider productExceptionDataProvider
  167. * @param ProductInterface[] $products
  168. */
  169. public function testScheduleMassOneEntityFailure($products)
  170. {
  171. try {
  172. $this->sendBulk($products);
  173. } catch (BulkException $e) {
  174. $this->assertCount(1, $e->getErrors());
  175. $errors = $e->getErrors();
  176. $this->assertInstanceOf(\Magento\Framework\Exception\LocalizedException::class, $errors[0]);
  177. $this->assertEquals("Error processing 1 element of input data", $errors[0]->getMessage());
  178. $reasonException = $errors[0]->getPrevious();
  179. $expectedErrorMessage = "Data item corresponding to \"product\" " .
  180. "must be specified in the message with topic " .
  181. "\"async.magento.catalog.api.productrepositoryinterface.save.post\".";
  182. $this->assertEquals(
  183. $expectedErrorMessage,
  184. $reasonException->getMessage()
  185. );
  186. /** @var \Magento\WebapiAsync\Model\AsyncResponse $bulkStatus */
  187. $bulkStatus = $e->getData();
  188. $this->assertTrue($bulkStatus->isErrors());
  189. /** @var ItemStatus[] $items */
  190. $items = $bulkStatus->getRequestItems();
  191. $this->assertCount(2, $items);
  192. $this->assertEquals(ItemStatus::STATUS_ACCEPTED, $items[0]->getStatus());
  193. $this->assertEquals(0, $items[0]->getId());
  194. $this->assertEquals(ItemStatus::STATUS_REJECTED, $items[1]->getStatus());
  195. $this->assertEquals(1, $items[1]->getId());
  196. $this->assertEquals($expectedErrorMessage, $items[1]->getErrorMessage());
  197. }
  198. //assert one products is created
  199. try {
  200. $this->publisherConsumerController->waitForAsynchronousResult(
  201. [$this, 'assertProductExists'],
  202. [$this->skus, count($this->skus)]
  203. );
  204. } catch (PreconditionFailedException $e) {
  205. $this->fail("Not all products were created");
  206. }
  207. }
  208. private function getProduct()
  209. {
  210. /** @var $product \Magento\Catalog\Model\Product */
  211. $product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
  212. ->create(ProductInterface::class);
  213. $product
  214. ->setTypeId('simple')
  215. ->setAttributeSetId(4)
  216. ->setWebsiteIds([1])
  217. ->setName('Simple Product 1')
  218. ->setSku('unique-simple-product1')
  219. ->setPrice(10)
  220. ->setMetaTitle('meta title')
  221. ->setMetaKeyword('meta keyword')
  222. ->setMetaDescription('meta description')
  223. ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH)
  224. ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED)
  225. ->setStockData(['use_config_manage_stock' => 0]);
  226. return $product;
  227. }
  228. public function productDataProvider()
  229. {
  230. return [
  231. 'single_product' => [
  232. [['product' => $this->getProduct()]],
  233. ],
  234. 'multiple_products' => [
  235. [
  236. ['product' => $this->getProduct()
  237. ->setName('Simple Product 3')
  238. ->setSku('unique-simple-product3')
  239. ->setMetaTitle('meta title 3')
  240. ],
  241. ['product' => $this->getProduct()
  242. ->setName('Simple Product 2')
  243. ->setSku('unique-simple-product2')
  244. ->setMetaTitle('meta title 2')
  245. ]
  246. ]
  247. ],
  248. ];
  249. }
  250. public function productExceptionDataProvider()
  251. {
  252. return [
  253. 'single_product' => [
  254. [['product' => $this->getProduct()]],
  255. ],
  256. 'multiple_products' => [
  257. [
  258. ['product' => $this->getProduct()],
  259. ['customer' => $this->getProduct()]
  260. ]
  261. ],
  262. ];
  263. }
  264. }