Skip to content

Commit 58e4cb9

Browse files
committed
Merge branch '2.3-develop' of github.com:magento-engcom/magento2ce into adobe-stock-integration
2 parents d26f434 + 7324325 commit 58e4cb9

File tree

25 files changed

+783
-81
lines changed

25 files changed

+783
-81
lines changed

app/code/Magento/Bundle/Test/Mftf/ActionGroup/CreateBundleProductActionGroup.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,17 @@
146146
<fillField selector="{{AdminProductFormBundleSection.bundleOptionXProductYQuantity(x, '4')}}" userInput="2" stepKey="fillQuantity5" after="fillQuantity4"/>
147147
<fillField selector="{{AdminProductFormBundleSection.bundleOptionXProductYQuantity(x, '5')}}" userInput="2" stepKey="fillQuantity6" after="fillQuantity5"/>
148148
</actionGroup>
149+
150+
<actionGroup name="deleteBundleOptionByIndex">
151+
<annotations>
152+
<description>Requires Navigation to Product Creation page. Removes any Bundle Option by index specified in arguments. 'deleteIndex' refers to Bundle option number.</description>
153+
</annotations>
154+
<arguments>
155+
<argument name="deleteIndex" type="string"/>
156+
</arguments>
157+
158+
<conditionalClick selector="{{AdminProductFormBundleSection.bundleItemsToggle}}" dependentSelector="{{AdminProductFormBundleSection.bundleItemsToggle}}" visible="false" stepKey="conditionallyOpenSectionBundleItems"/>
159+
<scrollTo selector="{{AdminProductFormBundleSection.bundleItemsToggle}}" stepKey="scrollUpABit"/>
160+
<click selector="{{AdminProductFormBundleSection.deleteOption(deleteIndex)}}" stepKey="clickDeleteOption"/>
161+
</actionGroup>
149162
</actionGroups>

app/code/Magento/Bundle/Test/Mftf/Section/AdminProductFormBundleSection.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@
4646
<element name="currentBundleOption" type="text" selector="//div[@data-index='bundle-items']//div[contains(@class, 'admin__collapsible-title')]/span"/>
4747
<!--AddingAnOption-->
4848
<element name="addOptions" type="button" selector="//tr[@data-repeat-index='0']//td[4]" timeout="30"/>
49+
<!--DragAnOption -->
50+
<element name="dragOption" type="block" selector="//tr[{{dragIndex}}]//div[contains(@class, 'draggable-handle')]" timeout="30" parameterized="true"/>
51+
<!--DeleteAnOption -->
52+
<element name="deleteOption" type="button" selector="//tr[{{deleteIndex}}]//button[@data-index='delete_button']" timeout="30" parameterized="true"/>
4953
<!--SEODropdownTab-->
5054
<element name="seoDropdown" type="button" selector="//div[@data-index='search-engine-optimization']"/>
5155
<element name="seoDependent" type="button" selector="//div[@data-index='search-engine-optimization']//div[contains(@class, '_show')]"/>

app/code/Magento/Bundle/Test/Mftf/Test/AdminCreateAndEditBundleProductSettingsTest.xml

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,5 +141,116 @@
141141
<argument name="websiteName" value="$createWebsite.website[name]$"/>
142142
</actionGroup>
143143
</test>
144+
<test name="AdminCreateAndEditBundleProductOptionsNegativeTest">
145+
<annotations>
146+
<features value="Bundle"/>
147+
<stories value="Modify bundle product in Admin"/>
148+
<title value="Admin should be able to remove any bundle option a bundle product"/>
149+
<description value="Admin should be able to set/edit other product information when creating/editing a bundle product"/>
150+
<severity value="MAJOR"/>
151+
<testCaseId value="MC-224"/>
152+
<skip>
153+
<issueId value="https://github.com/magento/magento2/issues/25468"/>
154+
</skip>
155+
<group value="Catalog"/>
156+
</annotations>
157+
<before>
158+
<!-- Create a Website -->
159+
<createData entity="customWebsite" stepKey="createWebsite"/>
160+
161+
<!-- Create first simple product for a bundle option -->
162+
<createData entity="SimpleProduct2" stepKey="createFirstSimpleProduct"/>
163+
164+
<!-- Create second simple product for a bundle option -->
165+
<createData entity="SimpleProduct2" stepKey="createSecondSimpleProduct"/>
166+
167+
<!-- Login as admin -->
168+
<actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/>
169+
</before>
170+
<after>
171+
<!-- Delete the simple product -->
172+
<deleteData createDataKey="createFirstSimpleProduct" stepKey="deleteFirstSimpleProduct"/>
173+
174+
<!-- Delete the simple product -->
175+
<deleteData createDataKey="createSecondSimpleProduct" stepKey="deleteSecondSimpleProduct"/>
176+
177+
<!-- Delete a Website -->
178+
<actionGroup ref="AdminDeleteWebsiteActionGroup" stepKey="deleteWebsite">
179+
<argument name="websiteName" value="Second Website"/>
180+
</actionGroup>
181+
182+
<!-- Log out -->
183+
<actionGroup ref="logout" stepKey="logout"/>
184+
</after>
185+
186+
<!-- Create new bundle product -->
187+
<actionGroup ref="GoToSpecifiedCreateProductPage" stepKey="createBundleProduct">
188+
<argument name="productType" value="bundle"/>
189+
</actionGroup>
190+
191+
<!-- Fill all main fields -->
192+
<actionGroup ref="fillMainBundleProductForm" stepKey="fillMainProductFields"/>
193+
194+
<!-- Add first bundle option to the product -->
195+
<actionGroup ref="addBundleOptionWithTwoProducts" stepKey="addFirstBundleOption">
196+
<argument name="x" value="0"/>
197+
<argument name="n" value="1"/>
198+
<argument name="prodOneSku" value="$$createFirstSimpleProduct.sku$$"/>
199+
<argument name="prodTwoSku" value="$$createSecondSimpleProduct.sku$$"/>
200+
<argument name="optionTitle" value="{{RadioButtonsOption.title}}"/>
201+
<argument name="inputType" value="{{RadioButtonsOption.type}}"/>
202+
</actionGroup>
203+
204+
<!-- Add second bundle option to the product -->
205+
<actionGroup ref="addBundleOptionWithTwoProducts" stepKey="addSecondBundleOption">
206+
<argument name="x" value="1"/>
207+
<argument name="n" value="2"/>
208+
<argument name="prodOneSku" value="$$createFirstSimpleProduct.sku$$"/>
209+
<argument name="prodTwoSku" value="$$createSecondSimpleProduct.sku$$"/>
210+
<argument name="optionTitle" value="{{CheckboxOption.title}}"/>
211+
<argument name="inputType" value="{{CheckboxOption.type}}"/>
212+
</actionGroup>
213+
214+
<!-- Add third bundle option to the product -->
215+
<actionGroup ref="addBundleOptionWithTwoProducts" stepKey="addThirdBundleOption">
216+
<argument name="x" value="2"/>
217+
<argument name="n" value="3"/>
218+
<argument name="prodOneSku" value="$$createFirstSimpleProduct.sku$$"/>
219+
<argument name="prodTwoSku" value="$$createSecondSimpleProduct.sku$$"/>
220+
<argument name="optionTitle" value="{{RadioButtonsOption.title}}"/>
221+
<argument name="inputType" value="{{RadioButtonsOption.type}}"/>
222+
</actionGroup>
223+
224+
<!-- Set product in created Website -->
225+
<actionGroup ref="AdminAssignProductInWebsiteActionGroup" stepKey="selectProductInWebsites">
226+
<argument name="website" value="$createWebsite.website[name]$"/>
227+
</actionGroup>
228+
229+
<!-- Save product form -->
230+
<actionGroup ref="saveProductForm" stepKey="saveWithThreeOptions"/>
231+
232+
<!-- Open created product -->
233+
<actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchForSimpleProduct">
234+
<argument name="product" value="BundleProduct"/>
235+
</actionGroup>
236+
<actionGroup ref="OpenEditProductOnBackendActionGroup" stepKey="openEditProduct">
237+
<argument name="product" value="BundleProduct"/>
238+
</actionGroup>
239+
240+
<!-- Remove second option -->
241+
<actionGroup ref="deleteBundleOptionByIndex" stepKey="deleteSecondOption">
242+
<argument name="deleteIndex" value="1"/>
243+
</actionGroup>
244+
245+
<!-- Save product form -->
246+
<actionGroup ref="saveProductForm" stepKey="clickSaveProduct"/>
247+
<click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="saveWithTwoOptions"/>
248+
<seeElement selector="{{AdminCategoryMessagesSection.SuccessMessage}}" stepKey="messageYouSavedTheProductIsShown"/>
249+
250+
<!-- Delete created bundle product -->
251+
<actionGroup ref="deleteProductUsingProductGrid" stepKey="deleteProduct">
252+
<argument name="product" value="BundleProduct"/>
253+
</actionGroup>
254+
</test>
144255
</tests>
145256

app/code/Magento/CatalogSearch/Setup/Patch/Data/SetInitialSearchWeightForAttributes.php

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,21 @@
66

77
namespace Magento\CatalogSearch\Setup\Patch\Data;
88

9+
use Magento\Catalog\Api\ProductAttributeRepositoryInterface;
910
use Magento\Framework\App\State;
11+
use Magento\Framework\Indexer\IndexerInterfaceFactory;
1012
use Magento\Framework\Setup\Patch\DataPatchInterface;
1113
use Magento\Framework\Setup\Patch\PatchVersionInterface;
12-
use Magento\Framework\Indexer\IndexerInterfaceFactory;
13-
use Magento\Catalog\Api\ProductAttributeRepositoryInterface;
1414

1515
/**
16+
* This patch sets up search weight for the product's system attributes, reindex required after patch applying.
17+
*
1618
* @deprecated
1719
* @see \Magento\ElasticSearch
1820
*/
1921
class SetInitialSearchWeightForAttributes implements DataPatchInterface, PatchVersionInterface
2022
{
23+
2124
/**
2225
* @var IndexerInterfaceFactory
2326
*/
@@ -50,7 +53,7 @@ public function __construct(
5053
}
5154

5255
/**
53-
* {@inheritdoc}
56+
* @inheritdoc
5457
*/
5558
public function apply()
5659
{
@@ -60,29 +63,31 @@ public function apply()
6063
$this->state->emulateAreaCode(
6164
\Magento\Framework\App\Area::AREA_CRONTAB,
6265
function () use ($indexer) {
63-
$indexer->reindexAll();
66+
$indexer->getState()
67+
->setStatus(\Magento\Framework\Indexer\StateInterface::STATUS_INVALID)
68+
->save();
6469
}
6570
);
6671
}
6772

6873
/**
69-
* {@inheritdoc}
74+
* @inheritdoc
7075
*/
7176
public static function getDependencies()
7277
{
7378
return [];
7479
}
7580

7681
/**
77-
* {@inheritdoc}
82+
* @inheritdoc
7883
*/
7984
public static function getVersion()
8085
{
8186
return '2.0.0';
8287
}
8388

8489
/**
85-
* {@inheritdoc}
90+
* @inheritdoc
8691
*/
8792
public function getAliases()
8893
{

app/code/Magento/Checkout/Model/DefaultConfigProvider.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,9 @@ private function getQuoteData()
397397
if ($this->checkoutSession->getQuote()->getId()) {
398398
$quote = $this->quoteRepository->get($this->checkoutSession->getQuote()->getId());
399399
$quoteData = $quote->toArray();
400+
if (null !== $quote->getExtensionAttributes()) {
401+
$quoteData['extension_attributes'] = $quote->getExtensionAttributes()->__toArray();
402+
}
400403
$quoteData['is_virtual'] = $quote->getIsVirtual();
401404

402405
if (!$quote->getCustomer()->getId()) {

app/code/Magento/Checkout/Model/Session.php

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
use Magento\Customer\Api\Data\CustomerInterface;
99
use Magento\Framework\App\ObjectManager;
10+
use Magento\Framework\Exception\NoSuchEntityException;
11+
use Magento\Quote\Api\Data\CartInterface;
1012
use Magento\Quote\Model\Quote;
1113
use Magento\Quote\Model\QuoteIdMaskFactory;
1214
use Psr\Log\LoggerInterface;
@@ -21,9 +23,6 @@
2123
*/
2224
class Session extends \Magento\Framework\Session\SessionManager
2325
{
24-
/**
25-
* Checkout state begin
26-
*/
2726
const CHECKOUT_STATE_BEGIN = 'begin';
2827

2928
/**
@@ -228,7 +227,7 @@ public function setLoadInactive($load = true)
228227
*
229228
* @return Quote
230229
* @throws \Magento\Framework\Exception\LocalizedException
231-
* @throws \Magento\Framework\Exception\NoSuchEntityException
230+
* @throws NoSuchEntityException
232231
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
233232
* @SuppressWarnings(PHPMD.NPathComplexity)
234233
*/
@@ -273,21 +272,17 @@ public function getQuote()
273272
*/
274273
$quote = $this->quoteRepository->get($this->getQuoteId());
275274
}
276-
} catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
275+
} catch (NoSuchEntityException $e) {
277276
$this->setQuoteId(null);
278277
}
279278
}
280279

281280
if (!$this->getQuoteId()) {
282281
if ($this->_customerSession->isLoggedIn() || $this->_customer) {
283-
$customerId = $this->_customer
284-
? $this->_customer->getId()
285-
: $this->_customerSession->getCustomerId();
286-
try {
287-
$quote = $this->quoteRepository->getActiveForCustomer($customerId);
288-
$this->setQuoteId($quote->getId());
289-
} catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
290-
$this->logger->critical($e);
282+
$quoteByCustomer = $this->getQuoteByCustomer();
283+
if ($quoteByCustomer !== null) {
284+
$this->setQuoteId($quoteByCustomer->getId());
285+
$quote = $quoteByCustomer;
291286
}
292287
} else {
293288
$quote->setIsCheckoutCart(true);
@@ -375,7 +370,7 @@ public function loadCustomerQuote()
375370

376371
try {
377372
$customerQuote = $this->quoteRepository->getForCustomer($this->_customerSession->getCustomerId());
378-
} catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
373+
} catch (NoSuchEntityException $e) {
379374
$customerQuote = $this->quoteFactory->create();
380375
}
381376
$customerQuote->setStoreId($this->_storeManager->getStore()->getId());
@@ -558,7 +553,7 @@ public function restoreQuote()
558553
$this->replaceQuote($quote)->unsLastRealOrderId();
559554
$this->_eventManager->dispatch('restore_quote', ['order' => $order, 'quote' => $quote]);
560555
return true;
561-
} catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
556+
} catch (NoSuchEntityException $e) {
562557
$this->logger->critical($e);
563558
}
564559
}
@@ -588,4 +583,22 @@ protected function isQuoteMasked()
588583
{
589584
return $this->isQuoteMasked;
590585
}
586+
587+
/**
588+
* Returns quote for customer if there is any
589+
*/
590+
private function getQuoteByCustomer(): ?CartInterface
591+
{
592+
$customerId = $this->_customer
593+
? $this->_customer->getId()
594+
: $this->_customerSession->getCustomerId();
595+
596+
try {
597+
$quote = $this->quoteRepository->getActiveForCustomer($customerId);
598+
} catch (NoSuchEntityException $e) {
599+
$quote = null;
600+
}
601+
602+
return $quote;
603+
}
591604
}

app/code/Magento/Checkout/Test/Unit/Model/SessionTest.php

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
*/
1010
namespace Magento\Checkout\Test\Unit\Model;
1111

12-
use \Magento\Checkout\Model\Session;
12+
use Magento\Checkout\Model\Session;
13+
use Magento\Framework\Exception\NoSuchEntityException;
1314

1415
/**
1516
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
@@ -374,6 +375,68 @@ public function testGetStepData()
374375
$this->assertEquals($stepData['complex']['key'], $session->getStepData('complex', 'key'));
375376
}
376377

378+
/**
379+
* Ensure that if quote not exist for customer quote will be null
380+
*
381+
* @return void
382+
*/
383+
public function testGetQuote(): void
384+
{
385+
$storeManager = $this->getMockForAbstractClass(\Magento\Store\Model\StoreManagerInterface::class);
386+
$customerSession = $this->createMock(\Magento\Customer\Model\Session::class);
387+
$quoteRepository = $this->createMock(\Magento\Quote\Api\CartRepositoryInterface::class);
388+
$quoteFactory = $this->createMock(\Magento\Quote\Model\QuoteFactory::class);
389+
$quote = $this->createMock(\Magento\Quote\Model\Quote::class);
390+
$logger = $this->createMock(\Psr\Log\LoggerInterface::class);
391+
$loggerMethods = get_class_methods(\Psr\Log\LoggerInterface::class);
392+
393+
$quoteFactory->expects($this->once())
394+
->method('create')
395+
->willReturn($quote);
396+
$customerSession->expects($this->exactly(3))
397+
->method('isLoggedIn')
398+
->willReturn(true);
399+
$store = $this->getMockBuilder(\Magento\Store\Model\Store::class)
400+
->disableOriginalConstructor()
401+
->setMethods(['getWebsiteId', '__wakeup'])
402+
->getMock();
403+
$storeManager->expects($this->any())
404+
->method('getStore')
405+
->will($this->returnValue($store));
406+
$storage = $this->getMockBuilder(\Magento\Framework\Session\Storage::class)
407+
->disableOriginalConstructor()
408+
->setMethods(['setData', 'getData'])
409+
->getMock();
410+
$storage->expects($this->at(0))
411+
->method('getData')
412+
->willReturn(1);
413+
$quoteRepository->expects($this->once())
414+
->method('getActiveForCustomer')
415+
->willThrowException(new NoSuchEntityException());
416+
417+
foreach ($loggerMethods as $method) {
418+
$logger->expects($this->never())->method($method);
419+
}
420+
421+
$quote->expects($this->once())
422+
->method('setCustomer')
423+
->with(null);
424+
425+
$constructArguments = $this->_helper->getConstructArguments(
426+
\Magento\Checkout\Model\Session::class,
427+
[
428+
'storeManager' => $storeManager,
429+
'quoteRepository' => $quoteRepository,
430+
'customerSession' => $customerSession,
431+
'storage' => $storage,
432+
'quoteFactory' => $quoteFactory,
433+
'logger' => $logger
434+
]
435+
);
436+
$this->_session = $this->_helper->getObject(\Magento\Checkout\Model\Session::class, $constructArguments);
437+
$this->_session->getQuote();
438+
}
439+
377440
public function testSetStepData()
378441
{
379442
$stepData = [

0 commit comments

Comments
 (0)