Skip to content

Commit 91aeb95

Browse files
committed
Merge remote-tracking branch 'upstream/2.4-develop' into catalog-mftf-cron-run-reliability
2 parents f79de3e + b98f4b5 commit 91aeb95

File tree

70 files changed

+1452
-223
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+1452
-223
lines changed

app/code/Magento/AsynchronousOperations/Model/ResourceModel/System/Message/Collection/Synchronized/Plugin.php

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
*/
1111
class Plugin
1212
{
13+
private const MESSAGES_LIMIT = 5;
1314
/**
1415
* @var \Magento\AdminNotification\Model\System\MessageFactory
1516
*/
@@ -95,27 +96,32 @@ public function afterToArray(
9596
$this->bulkNotificationManagement->getAcknowledgedBulksByUser($userId)
9697
);
9798
$bulkMessages = [];
99+
$messagesCount = 0;
100+
$data = [];
98101
foreach ($userBulks as $bulk) {
99102
$bulkUuid = $bulk->getBulkId();
100103
if (!in_array($bulkUuid, $acknowledgedBulks)) {
101-
$details = $this->operationDetails->getDetails($bulkUuid);
102-
$text = $this->getText($details);
103-
$bulkStatus = $this->statusMapper->operationStatusToBulkSummaryStatus($bulk->getStatus());
104-
if ($bulkStatus === \Magento\Framework\Bulk\BulkSummaryInterface::IN_PROGRESS) {
105-
$text = __('%1 item(s) are currently being updated.', $details['operations_total']) . $text;
104+
if ($messagesCount < self::MESSAGES_LIMIT) {
105+
$details = $this->operationDetails->getDetails($bulkUuid);
106+
$text = $this->getText($details);
107+
$bulkStatus = $this->statusMapper->operationStatusToBulkSummaryStatus($bulk->getStatus());
108+
if ($bulkStatus === \Magento\Framework\Bulk\BulkSummaryInterface::IN_PROGRESS) {
109+
$text = __('%1 item(s) are currently being updated.', $details['operations_total']) . $text;
110+
}
111+
$data = [
112+
'data' => [
113+
'text' => __('Task "%1": ', $bulk->getDescription()) . $text,
114+
'severity' => \Magento\Framework\Notification\MessageInterface::SEVERITY_MAJOR,
115+
// md5() here is not for cryptographic use.
116+
// phpcs:ignore Magento2.Security.InsecureFunction
117+
'identity' => md5('bulk' . $bulkUuid),
118+
'uuid' => $bulkUuid,
119+
'status' => $bulkStatus,
120+
'created_at' => $bulk->getStartTime()
121+
]
122+
];
123+
$messagesCount++;
106124
}
107-
$data = [
108-
'data' => [
109-
'text' => __('Task "%1": ', $bulk->getDescription()) . $text,
110-
'severity' => \Magento\Framework\Notification\MessageInterface::SEVERITY_MAJOR,
111-
// md5() here is not for cryptographic use.
112-
// phpcs:ignore Magento2.Security.InsecureFunction
113-
'identity' => md5('bulk' . $bulkUuid),
114-
'uuid' => $bulkUuid,
115-
'status' => $bulkStatus,
116-
'created_at' => $bulk->getStartTime()
117-
]
118-
];
119125
$bulkMessages[] = $this->messageFactory->create($data)->toArray();
120126
}
121127
}

app/code/Magento/AsynchronousOperations/Test/Unit/Model/ResourceModel/System/Message/Collection/Synchronized/PluginTest.php

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
*/
2828
class PluginTest extends TestCase
2929
{
30+
private const MESSAGES_LIMIT = 5;
3031
/**
3132
* @var Plugin
3233
*/
@@ -163,6 +164,60 @@ public function testAfterTo($operationDetails)
163164
$this->assertEquals(2, $result2['totalRecords']);
164165
}
165166

167+
/**
168+
* Tests that message building operations don't get called more than Plugin::MESSAGES_LIMIT times
169+
*
170+
* @return void
171+
*/
172+
public function testAfterToWithMessageLimit()
173+
{
174+
$result = ['items' =>[], 'totalRecords' => 1];
175+
$messagesCount = self::MESSAGES_LIMIT + 1;
176+
$userId = 1;
177+
$bulkUuid = 2;
178+
$bulkArray = [
179+
'status' => BulkSummaryInterface::NOT_STARTED
180+
];
181+
182+
$bulkMock = $this->getMockBuilder(BulkSummary::class)
183+
->addMethods(['getStatus'])
184+
->onlyMethods(['getBulkId', 'getDescription', 'getStartTime'])
185+
->disableOriginalConstructor()
186+
->getMock();
187+
$userBulks = array_fill(0, $messagesCount, $bulkMock);
188+
$bulkMock->expects($this->exactly($messagesCount))
189+
->method('getBulkId')->willReturn($bulkUuid);
190+
$this->operationsDetailsMock
191+
->expects($this->exactly(self::MESSAGES_LIMIT))
192+
->method('getDetails')
193+
->with($bulkUuid)
194+
->willReturn([
195+
'operations_successful' => 1,
196+
'operations_failed' => 0
197+
]);
198+
$bulkMock->expects($this->exactly(self::MESSAGES_LIMIT))
199+
->method('getDescription')->willReturn('Bulk Description');
200+
$this->messagefactoryMock->expects($this->exactly($messagesCount))
201+
->method('create')->willReturn($this->messageMock);
202+
$this->messageMock->expects($this->exactly($messagesCount))->method('toArray')->willReturn($bulkArray);
203+
$this->authorizationMock
204+
->expects($this->once())
205+
->method('isAllowed')
206+
->with($this->resourceName)
207+
->willReturn(true);
208+
$this->userContextMock->expects($this->once())->method('getUserId')->willReturn($userId);
209+
$this->bulkNotificationMock
210+
->expects($this->once())
211+
->method('getAcknowledgedBulksByUser')
212+
->with($userId)
213+
->willReturn([]);
214+
$this->statusMapper->expects($this->exactly(self::MESSAGES_LIMIT))
215+
->method('operationStatusToBulkSummaryStatus');
216+
$this->bulkStatusMock->expects($this->once())->method('getBulksByUser')->willReturn($userBulks);
217+
$result2 = $this->plugin->afterToArray($this->collectionMock, $result);
218+
$this->assertEquals($result['totalRecords'] + $messagesCount, $result2['totalRecords']);
219+
}
220+
166221
/**
167222
* @return array
168223
*/

app/code/Magento/Bundle/Pricing/Adjustment/DefaultSelectionPriceListProvider.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,10 @@ public function getPriceList(Product $bundleProduct, $searchMin, $useRegularPric
8585
[(int)$option->getOptionId()],
8686
$bundleProduct
8787
);
88-
$selectionsCollection->setFlag('has_stock_status_filter', true);
88+
89+
if ((int)$bundleProduct->getPriceType() !== Price::PRICE_TYPE_FIXED) {
90+
$selectionsCollection->setFlag('has_stock_status_filter', true);
91+
}
8992
$selectionsCollection->removeAttributeToSelect();
9093

9194
if (!$useRegularPrice) {

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
<!-- Save product and go to storefront -->
9595
<actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/>
9696

97+
<comment userInput="BIC workaround" stepKey="waitBeforeIndexerAfterBundle"/>
9798
<actionGroup ref="CliIndexerReindexActionGroup" stepKey="runCronIndexerAfterBundle">
9899
<argument name="indices" value=""/>
99100
</actionGroup>

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
<!-- Save product and go to storefront -->
7474
<actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/>
7575

76+
<comment userInput="BIC workaround" stepKey="waitBeforeIndexerAfterBundle"/>
7677
<actionGroup ref="CliIndexerReindexActionGroup" stepKey="runCronIndexerAfterBundle">
7778
<argument name="indices" value=""/>
7879
</actionGroup>

app/code/Magento/Bundle/Test/Unit/Pricing/Adjustment/DefaultSelectionPriceListProviderTest.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
namespace Magento\Bundle\Test\Unit\Pricing\Adjustment;
99

1010
use Magento\Bundle\Model\Option;
11+
use Magento\Bundle\Model\Product\Price;
1112
use Magento\Bundle\Model\Product\Type;
1213
use Magento\Bundle\Model\ResourceModel\Option\Collection;
1314
use Magento\Bundle\Model\ResourceModel\Selection\Collection as SelectionCollection;
@@ -109,6 +110,8 @@ protected function setUp(): void
109110

110111
$this->product = $this->getMockBuilder(Product::class)
111112
->disableOriginalConstructor()
113+
->addMethods(['getPriceType'])
114+
->onlyMethods(['getTypeInstance', 'isSalable'])
112115
->getMock();
113116
$this->optionsCollection = $this->getMockBuilder(Collection::class)
114117
->disableOriginalConstructor()
@@ -142,6 +145,54 @@ public function testGetPriceList(): void
142145
{
143146
$optionId = 1;
144147

148+
$this->typeInstance->expects($this->any())
149+
->method('getOptionsCollection')
150+
->with($this->product)
151+
->willReturn($this->optionsCollection);
152+
$this->product->expects($this->any())
153+
->method('getTypeInstance')
154+
->willReturn($this->typeInstance);
155+
$this->product->expects($this->once())
156+
->method('getPriceType')->willReturn(Price::PRICE_TYPE_FIXED);
157+
$this->optionsCollection->expects($this->once())
158+
->method('getIterator')
159+
->willReturn(new \ArrayIterator([$this->option]));
160+
$this->option->expects($this->once())
161+
->method('getOptionId')
162+
->willReturn($optionId);
163+
$this->typeInstance->expects($this->once())
164+
->method('getSelectionsCollection')
165+
->with([$optionId], $this->product)
166+
->willReturn($this->selectionCollection);
167+
$this->option->expects($this->once())
168+
->method('isMultiSelection')
169+
->willReturn(true);
170+
$this->storeManager->expects($this->once())
171+
->method('getStore')
172+
->willReturn($this->store);
173+
$this->store->expects($this->once())
174+
->method('getWebsiteId')
175+
->willReturn(0);
176+
$this->websiteRepository->expects($this->once())
177+
->method('getDefault')
178+
->willReturn($this->website);
179+
$this->website->expects($this->once())
180+
->method('getId')
181+
->willReturn(1);
182+
$this->selectionCollection->expects($this->once())
183+
->method('getIterator')
184+
->willReturn(new \ArrayIterator([]));
185+
$this->selectionCollection->expects($this->never())
186+
->method('setFlag')
187+
->with('has_stock_status_filter', true);
188+
189+
$this->model->getPriceList($this->product, false, false);
190+
}
191+
192+
public function testGetPriceListForFixedPriceType(): void
193+
{
194+
$optionId = 1;
195+
145196
$this->typeInstance->expects($this->any())
146197
->method('getOptionsCollection')
147198
->with($this->product)

app/code/Magento/Catalog/Block/Adminhtml/Category/Tab/Product.php

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,26 @@
1111
*/
1212
namespace Magento\Catalog\Block\Adminhtml\Category\Tab;
1313

14+
use Magento\Backend\Block\Template\Context;
1415
use Magento\Backend\Block\Widget\Grid;
1516
use Magento\Backend\Block\Widget\Grid\Column;
1617
use Magento\Backend\Block\Widget\Grid\Extended;
18+
use Magento\Backend\Helper\Data;
1719
use Magento\Catalog\Model\Product\Attribute\Source\Status;
1820
use Magento\Catalog\Model\Product\Visibility;
21+
use Magento\Catalog\Model\ProductFactory;
1922
use Magento\Framework\App\ObjectManager;
23+
use Magento\Framework\Registry;
2024

21-
class Product extends \Magento\Backend\Block\Widget\Grid\Extended
25+
class Product extends Extended
2226
{
2327
/**
24-
* Core registry
25-
*
26-
* @var \Magento\Framework\Registry
28+
* @var Registry
2729
*/
2830
protected $_coreRegistry = null;
2931

3032
/**
31-
* @var \Magento\Catalog\Model\ProductFactory
33+
* @var ProductFactory
3234
*/
3335
protected $_productFactory;
3436

@@ -43,19 +45,19 @@ class Product extends \Magento\Backend\Block\Widget\Grid\Extended
4345
private $visibility;
4446

4547
/**
46-
* @param \Magento\Backend\Block\Template\Context $context
47-
* @param \Magento\Backend\Helper\Data $backendHelper
48-
* @param \Magento\Catalog\Model\ProductFactory $productFactory
49-
* @param \Magento\Framework\Registry $coreRegistry
48+
* @param Context $context
49+
* @param Data $backendHelper
50+
* @param ProductFactory $productFactory
51+
* @param Registry $coreRegistry
5052
* @param array $data
5153
* @param Visibility|null $visibility
5254
* @param Status|null $status
5355
*/
5456
public function __construct(
55-
\Magento\Backend\Block\Template\Context $context,
56-
\Magento\Backend\Helper\Data $backendHelper,
57-
\Magento\Catalog\Model\ProductFactory $productFactory,
58-
\Magento\Framework\Registry $coreRegistry,
57+
Context $context,
58+
Data $backendHelper,
59+
ProductFactory $productFactory,
60+
Registry $coreRegistry,
5961
array $data = [],
6062
Visibility $visibility = null,
6163
Status $status = null
@@ -68,6 +70,8 @@ public function __construct(
6870
}
6971

7072
/**
73+
* Initialize object
74+
*
7175
* @return void
7276
*/
7377
protected function _construct()
@@ -79,6 +83,8 @@ protected function _construct()
7983
}
8084

8185
/**
86+
* Get current category
87+
*
8288
* @return array|null
8389
*/
8490
public function getCategory()
@@ -87,6 +93,8 @@ public function getCategory()
8793
}
8894

8995
/**
96+
* Add column filter to collection
97+
*
9098
* @param Column $column
9199
* @return $this
92100
*/
@@ -110,6 +118,8 @@ protected function _addColumnFilterToCollection($column)
110118
}
111119

112120
/**
121+
* Prepare collection.
122+
*
113123
* @return Grid
114124
*/
115125
protected function _prepareCollection()
@@ -136,6 +146,7 @@ protected function _prepareCollection()
136146
'left'
137147
);
138148
$storeId = (int)$this->getRequest()->getParam('store', 0);
149+
$collection->setStoreId($storeId);
139150
if ($storeId > 0) {
140151
$collection->addStoreFilter($storeId);
141152
}
@@ -153,6 +164,8 @@ protected function _prepareCollection()
153164
}
154165

155166
/**
167+
* Prepare columns.
168+
*
156169
* @return Extended
157170
*/
158171
protected function _prepareColumns()
@@ -230,6 +243,8 @@ protected function _prepareColumns()
230243
}
231244

232245
/**
246+
* Retrieve grid reload url
247+
*
233248
* @return string
234249
*/
235250
public function getGridUrl()
@@ -238,6 +253,8 @@ public function getGridUrl()
238253
}
239254

240255
/**
256+
* Get selected products
257+
*
241258
* @return array
242259
*/
243260
protected function _getSelectedProducts()

app/code/Magento/Catalog/Test/Mftf/ActionGroup/AddCrossSellProductBySkuActionGroup.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,18 @@
1919
<!--Scroll up to avoid error-->
2020
<scrollTo selector="{{AdminProductFormRelatedUpSellCrossSellSection.relatedDropdown}}" x="0" y="-100" stepKey="scrollTo"/>
2121
<conditionalClick selector="{{AdminProductFormRelatedUpSellCrossSellSection.relatedDropdown}}" dependentSelector="{{AdminProductFormRelatedUpSellCrossSellSection.relatedDependent}}" visible="false" stepKey="openDropDownIfClosedRelatedUpSellCrossSell"/>
22+
<waitForElementClickable selector="{{AdminProductFormRelatedUpSellCrossSellSection.AddCrossSellProductsButton}}" stepKey="waitForAddCrossSellButtonClickable" />
2223
<click selector="{{AdminProductFormRelatedUpSellCrossSellSection.AddCrossSellProductsButton}}" stepKey="clickAddCrossSellButton"/>
2324
<conditionalClick selector="{{AdminProductCrossSellModalSection.Modal}} {{AdminProductGridFilterSection.clearFilters}}" dependentSelector="{{AdminProductCrossSellModalSection.Modal}} {{AdminProductGridFilterSection.clearFilters}}" visible="true" stepKey="clickClearFilters"/>
25+
<waitForElementClickable selector="{{AdminProductCrossSellModalSection.Modal}} {{AdminProductGridFilterSection.filters}}" stepKey="waitForProductFiltersClickable" />
2426
<click selector="{{AdminProductCrossSellModalSection.Modal}} {{AdminProductGridFilterSection.filters}}" stepKey="openProductFilters"/>
27+
<waitForElementVisible selector="{{AdminProductCrossSellModalSection.Modal}} {{AdminProductGridFilterSection.skuFilter}}" stepKey="waitForSkuFilterVisible" />
2528
<fillField selector="{{AdminProductCrossSellModalSection.Modal}} {{AdminProductGridFilterSection.skuFilter}}" userInput="{{sku}}" stepKey="fillProductSkuFilter"/>
2629
<click selector="{{AdminProductCrossSellModalSection.Modal}} {{AdminProductGridFilterSection.applyFilters}}" stepKey="clickApplyFilters"/>
2730
<waitForPageLoad stepKey="waitForPageToLoad"/>
31+
<waitForElementClickable selector="{{AdminProductCrossSellModalSection.Modal}}{{AdminProductModalSlideGridSection.productGridXRowYColumnButton('1', '1')}}" stepKey="waitForProductClickable" />
2832
<click selector="{{AdminProductCrossSellModalSection.Modal}}{{AdminProductModalSlideGridSection.productGridXRowYColumnButton('1', '1')}}" stepKey="selectProduct"/>
33+
<waitForElementClickable selector="{{AdminProductCrossSellModalSection.addSelectedProducts}}" stepKey="waitForAddRelatedProductClickable" />
2934
<click selector="{{AdminProductCrossSellModalSection.addSelectedProducts}}" stepKey="addRelatedProductSelected"/>
3035
<waitForPageLoad stepKey="waitForModalDisappear"/>
3136
</actionGroup>

app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductByIdOnProductGridActionGroup.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
</arguments>
1818

1919
<waitForElementClickable selector="{{AdminProductGridSection.productRowCheckboxById(productId)}}" stepKey="waitForElementClickable" />
20+
<scrollTo selector="{{AdminProductGridSection.productRowCheckboxById(productId)}}" x="-100" stepKey="scrollToProductCheckbox" />
21+
<moveMouseOver selector="{{AdminProductGridSection.productRowCheckboxById(productId)}}" x="-100" stepKey="moveMouseOverProductCheckbox" />
2022
<checkOption selector="{{AdminProductGridSection.productRowCheckboxById(productId)}}" stepKey="selectProduct"/>
23+
<waitForPageLoad stepKey="waitForBackgroundProcessesToFinish" />
2124
</actionGroup>
2225
</actionGroups>

app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminClickMassUpdateProductAttributesActionGroup.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
<annotations>
1313
<description>Clicks on 'Update attributes' from dropdown actions list on product grid page. Products should be selected via mass action before</description>
1414
</annotations>
15+
<waitForElementClickable selector="{{AdminProductGridSection.bulkActionDropdown}}" stepKey="waitForDropdownClickable" />
1516
<click selector="{{AdminProductGridSection.bulkActionDropdown}}" stepKey="clickDropdown"/>
17+
<waitForElementClickable selector="{{AdminProductGridSection.bulkActionOption('Update attributes')}}" stepKey="waitForOptionClickable" />
1618
<click selector="{{AdminProductGridSection.bulkActionOption('Update attributes')}}" stepKey="clickOption"/>
1719
<waitForPageLoad stepKey="waitForBulkUpdatePage"/>
1820
<seeInCurrentUrl url="{{ProductAttributesEditPage.url}}" stepKey="seeInUrl"/>

0 commit comments

Comments
 (0)