44 * Copyright © Magento, Inc. All rights reserved.
55 * See COPYING.txt for license details.
66 */
7+ declare (strict_types=1 );
8+
79namespace Magento \GroupedProduct \Api ;
810
9- use Magento \TestFramework \Helper \Bootstrap ;
10- use Magento \Indexer \Model \Config ;
11+ use Magento \Catalog \Api \ProductLinkManagementInterface ;
1112use Magento \Framework \Indexer \IndexerRegistry ;
1213use Magento \Framework \Webapi \Rest \Request ;
14+ use Magento \Indexer \Model \Config ;
15+ use Magento \TestFramework \Helper \Bootstrap ;
16+ use Magento \TestFramework \TestCase \WebapiAbstract ;
1317
14- class ProductLinkRepositoryTest extends \ Magento \ TestFramework \ TestCase \ WebapiAbstract
18+ class ProductLinkRepositoryTest extends WebapiAbstract
1519{
1620 const SERVICE_NAME = 'catalogProductLinkRepositoryV1 ' ;
1721 const SERVICE_VERSION = 'V1 ' ;
@@ -55,7 +59,7 @@ public function testSave(): void
5559 'linked_product_sku ' => 'simple-1 ' ,
5660 'position ' => 3 ,
5761 'extension_attributes ' => [
58- 'qty ' => (float ) 300.0000 ,
62+ 'qty ' => (float )300.0000 ,
5963 ],
6064 ];
6165
@@ -72,12 +76,15 @@ public function testSave(): void
7276 ];
7377 $ this ->_webApiCall ($ serviceInfo , ['entity ' => $ productData ]);
7478
75- /** @var \Magento\Catalog\Api\ ProductLinkManagementInterface $linkManagement */
76- $ linkManagement = $ this ->objectManager ->get (\ Magento \ Catalog \ Api \ ProductLinkManagementInterface::class);
79+ /** @var ProductLinkManagementInterface $linkManagement */
80+ $ linkManagement = $ this ->objectManager ->get (ProductLinkManagementInterface::class);
7781 $ actual = $ linkManagement ->getLinkedItemsByType ($ productSku , $ linkType );
78- array_walk ($ actual , function (&$ item ) {
79- $ item = $ item ->__toArray ();
80- });
82+ array_walk (
83+ $ actual ,
84+ function (&$ item ) {
85+ $ item = $ item ->__toArray ();
86+ }
87+ );
8188 $ this ->assertEquals ($ productData , $ actual [2 ]);
8289 }
8390
@@ -98,7 +105,7 @@ public function testLinkWithScheduledIndex(): void
98105 'linked_product_sku ' => $ productSimple ,
99106 'position ' => 3 ,
100107 'extension_attributes ' => [
101- 'qty ' => (float ) 300.0000 ,
108+ 'qty ' => (float )300.0000 ,
102109 ],
103110 ];
104111 $ serviceInfo = [
@@ -124,6 +131,101 @@ public function testLinkWithScheduledIndex(): void
124131 $ this ->restoreIndexMode ();
125132 }
126133
134+ /**
135+ * Verify empty out of stock grouped product is in stock after child has been added.
136+ *
137+ * @return void
138+ * @magentoApiDataFixture Magento/GroupedProduct/_files/empty_grouped_product.php
139+ * @magentoApiDataFixture Magento/Catalog/_files/product_virtual.php
140+ */
141+ public function testGroupedProductIsInStockAfterAddChild (): void
142+ {
143+ $ productSku = 'grouped-product ' ;
144+ self ::assertFalse ($ this ->isProductInStock ($ productSku ));
145+ $ items = [
146+ 'sku ' => $ productSku ,
147+ 'link_type ' => 'associated ' ,
148+ 'linked_product_type ' => 'virtual ' ,
149+ 'linked_product_sku ' => 'virtual-product ' ,
150+ 'position ' => 3 ,
151+ 'extension_attributes ' => [
152+ 'qty ' => 1 ,
153+ ],
154+ ];
155+ $ serviceInfo = [
156+ 'rest ' => [
157+ 'resourcePath ' => self ::RESOURCE_PATH . $ productSku . '/links ' ,
158+ 'httpMethod ' => Request::HTTP_METHOD_PUT ,
159+ ],
160+ 'soap ' => [
161+ 'service ' => self ::SERVICE_NAME ,
162+ 'serviceVersion ' => self ::SERVICE_VERSION ,
163+ 'operation ' => self ::SERVICE_NAME . 'Save ' ,
164+ ],
165+ ];
166+ $ this ->_webApiCall ($ serviceInfo , ['entity ' => $ items ]);
167+ self ::assertTrue ($ this ->isProductInStock ($ productSku ));
168+ }
169+
170+ /**
171+ * Verify in stock grouped product is out stock after children have been removed.
172+ *
173+ * @return void
174+ * @magentoApiDataFixture Magento/GroupedProduct/_files/product_grouped_with_simple.php
175+ */
176+ public function testGroupedProductIsOutOfStockAfterRemoveChild (): void
177+ {
178+ $ productSku = 'grouped ' ;
179+ $ childrenSkus = [
180+ 'simple_11 ' ,
181+ 'simple_22 ' ,
182+ ];
183+ self ::assertTrue ($ this ->isProductInStock ($ productSku ));
184+
185+ foreach ($ childrenSkus as $ childSku ) {
186+ $ serviceInfo = [
187+ 'rest ' => [
188+ 'resourcePath ' => self ::RESOURCE_PATH . $ productSku . '/links/associated/ ' . $ childSku ,
189+ 'httpMethod ' => Request::HTTP_METHOD_DELETE ,
190+ ],
191+ 'soap ' => [
192+ 'service ' => self ::SERVICE_NAME ,
193+ 'serviceVersion ' => self ::SERVICE_VERSION ,
194+ 'operation ' => self ::SERVICE_NAME . 'DeleteById ' ,
195+ ],
196+ ];
197+ $ requestData = ['sku ' => $ productSku , 'type ' => 'associated ' , 'linkedProductSku ' => $ childSku ];
198+ $ this ->_webApiCall ($ serviceInfo , $ requestData );
199+ }
200+
201+ self ::assertFalse ($ this ->isProductInStock ($ productSku ));
202+ }
203+
204+
205+ /**
206+ * Check product stock status.
207+ *
208+ * @param string $productSku
209+ * @return bool
210+ */
211+ private function isProductInStock (string $ productSku ): bool
212+ {
213+ $ serviceInfo = [
214+ 'rest ' => [
215+ 'resourcePath ' => '/V1/stockStatuses/ ' . $ productSku ,
216+ 'httpMethod ' => Request::HTTP_METHOD_GET ,
217+ ],
218+ 'soap ' => [
219+ 'service ' => 'catalogInventoryStockRegistryV1 ' ,
220+ 'serviceVersion ' => self ::SERVICE_VERSION ,
221+ 'operation ' => 'catalogInventoryStockRegistryV1getStockStatusBySku ' ,
222+ ],
223+ ];
224+ $ result = $ this ->_webApiCall ($ serviceInfo , ['productSku ' => $ productSku ]);
225+
226+ return (bool )$ result ['stock_status ' ];
227+ }
228+
127229 /**
128230 * @param string $productSku
129231 * @return array
@@ -139,11 +241,11 @@ private function buildSearchCriteria(string $productSku): array
139241 [
140242 'field ' => 'search_term ' ,
141243 'value ' => $ productSku ,
142- ]
143- ]
144- ]
145- ]
146- ]
244+ ],
245+ ],
246+ ],
247+ ],
248+ ],
147249 ];
148250 }
149251
@@ -156,13 +258,13 @@ private function buildSearchServiceInfo(array $searchCriteria): array
156258 return [
157259 'rest ' => [
158260 'resourcePath ' => self ::RESOURCE_PATH_SEARCH . '? ' . http_build_query ($ searchCriteria ),
159- 'httpMethod ' => Request::HTTP_METHOD_GET
261+ 'httpMethod ' => Request::HTTP_METHOD_GET ,
160262 ],
161263 'soap ' => [
162264 'service ' => self ::SERVICE_NAME_SEARCH ,
163265 'serviceVersion ' => self ::SERVICE_VERSION ,
164- 'operation ' => self ::SERVICE_NAME_SEARCH . 'Search '
165- ]
266+ 'operation ' => self ::SERVICE_NAME_SEARCH . 'Search ' ,
267+ ],
166268 ];
167269 }
168270
0 commit comments