55 */
66namespace Magento \GroupedProduct \Model \Product \Type ;
77
8+ use Magento \Catalog \Api \ProductRepositoryInterface ;
9+ use Magento \Catalog \Model \Product ;
10+ use Magento \CatalogInventory \Model \Configuration ;
11+ use Magento \Framework \App \Config \ReinitableConfigInterface ;
12+ use Magento \Framework \App \Config \Value ;
13+
814class GroupedTest extends \PHPUnit \Framework \TestCase
915{
16+ /**
17+ * @var ReinitableConfigInterface
18+ */
19+ private $ reinitableConfig ;
20+
1021 /**
1122 * @var \Magento\Framework\ObjectManagerInterface
1223 */
@@ -20,16 +31,21 @@ class GroupedTest extends \PHPUnit\Framework\TestCase
2031 protected function setUp ()
2132 {
2233 $ this ->objectManager = \Magento \TestFramework \Helper \Bootstrap::getObjectManager ();
23-
2434 $ this ->_productType = $ this ->objectManager ->get (\Magento \Catalog \Model \Product \Type::class);
35+ $ this ->reinitableConfig = $ this ->objectManager ->get (ReinitableConfigInterface::class);
36+ }
37+
38+ protected function tearDown ()
39+ {
40+ $ this ->dropConfigValue (Configuration::XML_PATH_SHOW_OUT_OF_STOCK );
2541 }
2642
2743 public function testFactory ()
2844 {
2945 $ product = new \Magento \Framework \DataObject ();
30- $ product ->setTypeId (\ Magento \ GroupedProduct \ Model \ Product \ Type \ Grouped::TYPE_CODE );
46+ $ product ->setTypeId (Grouped::TYPE_CODE );
3147 $ type = $ this ->_productType ->factory ($ product );
32- $ this ->assertInstanceOf (\ Magento \ GroupedProduct \ Model \ Product \ Type \ Grouped::class, $ type );
48+ $ this ->assertInstanceOf (Grouped::class, $ type );
3349 }
3450
3551 /**
@@ -38,12 +54,12 @@ public function testFactory()
3854 */
3955 public function testGetAssociatedProducts ()
4056 {
41- $ productRepository = $ this ->objectManager ->create (\ Magento \ Catalog \ Api \ ProductRepositoryInterface::class);
57+ $ productRepository = $ this ->objectManager ->create (ProductRepositoryInterface::class);
4258
43- /** @var \Magento\Catalog\Model\ Product $product */
59+ /** @var Product $product */
4460 $ product = $ productRepository ->get ('grouped-product ' );
4561 $ type = $ product ->getTypeInstance ();
46- $ this ->assertInstanceOf (\ Magento \ GroupedProduct \ Model \ Product \ Type \ Grouped::class, $ type );
62+ $ this ->assertInstanceOf (Grouped::class, $ type );
4763
4864 $ associatedProducts = $ type ->getAssociatedProducts ($ product );
4965 $ this ->assertCount (2 , $ associatedProducts );
@@ -53,7 +69,7 @@ public function testGetAssociatedProducts()
5369 }
5470
5571 /**
56- * @param \Magento\Catalog\Model\ Product $product
72+ * @param Product $product
5773 */
5874 private function assertProductInfo ($ product )
5975 {
@@ -92,25 +108,25 @@ public function testPrepareProduct()
92108 \Magento \Framework \DataObject::class,
93109 ['data ' => ['value ' => ['qty ' => 2 ]]]
94110 );
95- /** @var \Magento\Catalog\Api\ ProductRepositoryInterface $productRepository */
96- $ productRepository = $ this ->objectManager ->get (\ Magento \ Catalog \ Api \ ProductRepositoryInterface::class);
111+ /** @var ProductRepositoryInterface $productRepository */
112+ $ productRepository = $ this ->objectManager ->get (ProductRepositoryInterface::class);
97113 $ product = $ productRepository ->get ('grouped-product ' );
98114
99- /** @var \Magento\GroupedProduct\Model\Product\Type\ Grouped $type */
100- $ type = $ this ->objectManager ->get (\ Magento \ GroupedProduct \ Model \ Product \ Type \ Grouped::class);
115+ /** @var Grouped $type */
116+ $ type = $ this ->objectManager ->get (Grouped::class);
101117
102118 $ processModes = [
103- \ Magento \ GroupedProduct \ Model \ Product \ Type \ Grouped::PROCESS_MODE_FULL ,
104- \ Magento \ GroupedProduct \ Model \ Product \ Type \ Grouped::PROCESS_MODE_LITE
119+ Grouped::PROCESS_MODE_FULL ,
120+ Grouped::PROCESS_MODE_LITE
105121 ];
106122 $ expectedData = [
107- \ Magento \ GroupedProduct \ Model \ Product \ Type \ Grouped::PROCESS_MODE_FULL => [
123+ Grouped::PROCESS_MODE_FULL => [
108124 1 => '{"super_product_config":{"product_type":"grouped","product_id":" '
109125 . $ product ->getId () . '"}} ' ,
110126 21 => '{"super_product_config":{"product_type":"grouped","product_id":" '
111127 . $ product ->getId () . '"}} ' ,
112128 ],
113- \ Magento \ GroupedProduct \ Model \ Product \ Type \ Grouped::PROCESS_MODE_LITE => [
129+ Grouped::PROCESS_MODE_LITE => [
114130 $ product ->getId () => '{"value":{"qty":2}} ' ,
115131 ]
116132 ];
@@ -127,4 +143,172 @@ public function testPrepareProduct()
127143 }
128144 }
129145 }
146+
147+ /**
148+ * Test adding grouped product to cart then one of subproducts is out of stock.
149+ *
150+ * @magentoDataFixture Magento/GroupedProduct/_files/product_grouped_with_out_of_stock.php
151+ * @magentoAppArea frontend
152+ * @magentoAppIsolation enabled
153+ * @magentoDbIsolation disabled
154+ * @dataProvider outOfStockSubProductDataProvider
155+ * @param bool $outOfStockShown
156+ * @param array $data
157+ * @param array $expected
158+ */
159+ public function testOutOfStockSubProduct (bool $ outOfStockShown , array $ data , array $ expected )
160+ {
161+ $ this ->changeConfigValue (Configuration::XML_PATH_SHOW_OUT_OF_STOCK , $ outOfStockShown );
162+ $ buyRequest = new \Magento \Framework \DataObject ($ data );
163+ $ productRepository = $ this ->objectManager ->create (ProductRepositoryInterface::class);
164+ /** @var Product $product */
165+ $ product = $ productRepository ->get ('grouped-product ' );
166+ /** @var Grouped $groupedProduct */
167+ $ groupedProduct = $ this ->objectManager ->get (Grouped::class);
168+ $ actual = $ groupedProduct ->prepareForCartAdvanced ($ buyRequest , $ product , Grouped::PROCESS_MODE_FULL );
169+ self ::assertEquals (
170+ count ($ expected ),
171+ count ($ actual )
172+ );
173+ /** @var array $element */
174+ foreach ($ expected as $ number => $ element ) {
175+ foreach ($ element as $ key => $ value ) {
176+ self ::assertEquals (
177+ $ value ,
178+ $ actual [$ number ]->getData ($ key ),
179+ "Failed asserting that value $ key matches expected "
180+ );
181+ }
182+ }
183+
184+ }
185+
186+ /**
187+ * Data provider for testOutOfStockSubProduct.
188+ *
189+ * @return array
190+ */
191+ public function outOfStockSubProductDataProvider ()
192+ {
193+ return [
194+ 'Out of stock product are shown #1 ' => [
195+ true ,
196+ [
197+ 'product ' => 3 ,
198+ 'qty ' => 1 ,
199+ 'super_group ' => [
200+ 1 => 4 ,
201+ 21 => 5
202+ ],
203+ ],
204+ [
205+ [
206+ 'sku ' => 'virtual-product ' ,
207+ 'cart_qty ' => 5
208+ ],
209+ [
210+ 'sku ' => 'simple ' ,
211+ 'cart_qty ' => 4
212+ ],
213+ ]
214+ ],
215+ 'Out of stock product are shown #2 ' => [
216+ true ,
217+ [
218+ 'product ' => 3 ,
219+ 'qty ' => 1 ,
220+ 'super_group ' => [
221+ 1 => 0 ,
222+ ],
223+ ],
224+ [
225+ [
226+ 'sku ' => 'virtual-product ' ,
227+ 'cart_qty ' => 2 // This is a default quantity.
228+ ],
229+ ]
230+ ],
231+ 'Out of stock product are hidden #1 ' => [
232+ false ,
233+ [
234+ 'product ' => 3 ,
235+ 'qty ' => 1 ,
236+ 'super_group ' => [
237+ 1 => 4 ,
238+ 21 => 5
239+ ],
240+ ],
241+ [
242+ [
243+ 'sku ' => 'virtual-product ' ,
244+ 'cart_qty ' => 5
245+ ],
246+ [
247+ 'sku ' => 'simple ' ,
248+ 'cart_qty ' => 4
249+ ],
250+ ]
251+ ],
252+ 'Out of stock product are hidden #2 ' => [
253+ false ,
254+ [
255+ 'product ' => 3 ,
256+ 'qty ' => 1 ,
257+ 'super_group ' => [
258+ 1 => 0 ,
259+ ],
260+ ],
261+ [
262+ [
263+ 'sku ' => 'virtual-product ' ,
264+ 'cart_qty ' => 2 // This is a default quantity.
265+ ],
266+ ]
267+ ],
268+ ];
269+ }
270+
271+ /**
272+ * Write config value to database.
273+ *
274+ * @param string $path
275+ * @param string $value
276+ * @param string $scope
277+ * @param int $scopeId
278+ */
279+ private function changeConfigValue (string $ path , string $ value , string $ scope = 'default ' , int $ scopeId = 0 )
280+ {
281+ $ configValue = $ this ->objectManager ->create (Value::class);
282+ $ configValue ->setPath ($ path )
283+ ->setValue ($ value )
284+ ->setScope ($ scope )
285+ ->setScopeId ($ scopeId )
286+ ->save ();
287+ $ this ->reinitConfig ();
288+ }
289+
290+ /**
291+ * Delete config value from database.
292+ *
293+ * @param string $path
294+ */
295+ private function dropConfigValue (string $ path )
296+ {
297+ $ configValue = $ this ->objectManager ->create (Value::class);
298+ try {
299+ $ configValue ->load ($ path , 'path ' );
300+ $ configValue ->delete ();
301+ } catch (\Magento \Framework \Exception \NoSuchEntityException $ e ) {
302+ // do nothing
303+ }
304+ $ this ->reinitConfig ();
305+ }
306+
307+ /**
308+ * Reinit config.
309+ */
310+ private function reinitConfig ()
311+ {
312+ $ this ->reinitableConfig ->reinit ();
313+ }
130314}
0 commit comments