From 231898ab56c5aa8d322db8e076e45d17c0e32aa8 Mon Sep 17 00:00:00 2001 From: "s.humeau" Date: Sat, 12 Apr 2025 18:17:48 +0200 Subject: [PATCH 01/15] Fix Magento/Beckend/Block/Page/Footer integration test --- .../Magento/Backend/Block/Page/FooterTest.php | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Backend/Block/Page/FooterTest.php b/dev/tests/integration/testsuite/Magento/Backend/Block/Page/FooterTest.php index 81c1c5d13f31..1efa68787a04 100644 --- a/dev/tests/integration/testsuite/Magento/Backend/Block/Page/FooterTest.php +++ b/dev/tests/integration/testsuite/Magento/Backend/Block/Page/FooterTest.php @@ -6,6 +6,10 @@ namespace Magento\Backend\Block\Page; +use Magento\Framework\App\CacheInterface; +use Magento\Framework\App\ProductMetadata; +use Magento\TestFramework\Helper\Bootstrap; + /** * Test \Magento\Backend\Block\Page\Footer * @@ -16,7 +20,7 @@ class FooterTest extends \PHPUnit\Framework\TestCase /** * Test Product Version Value */ - const TEST_PRODUCT_VERSION = '222.333.444'; + private const TEST_PRODUCT_VERSION = '222.333.444'; /** * @var \Magento\Backend\Block\Page\Footer @@ -26,13 +30,14 @@ class FooterTest extends \PHPUnit\Framework\TestCase protected function setUp(): void { parent::setUp(); - $productMetadataMock = $this->getMockBuilder(\Magento\Framework\App\ProductMetadata::class) - ->onlyMethods(['getVersion']) + $productMetadataMock = $this->getMockBuilder(ProductMetadata::class) ->disableOriginalConstructor() ->getMock(); + $productMetadataMock->expects($this->once()) - ->method('getVersion') + ->method('getDistributionVersion') ->willReturn($this::TEST_PRODUCT_VERSION); + $this->block = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( \Magento\Framework\View\LayoutInterface::class )->createBlock( @@ -44,6 +49,8 @@ protected function setUp(): void public function testToHtml() { + /** @var \Magento\Framework\App\CacheInterface $cacheManager */ + Bootstrap::getObjectManager()->create(CacheInterface::class); $footerContent = $this->block->toHtml(); $this->assertStringContainsString( 'ver. ' . $this::TEST_PRODUCT_VERSION, From 91a818ceb14042e22fc1dda692f768fbc04b5b12 Mon Sep 17 00:00:00 2001 From: simsComputing Date: Sat, 12 Apr 2025 18:52:12 +0200 Subject: [PATCH 02/15] Fix Magento/Bundle/Model/Product/IsSaleableTest --- .../Option/AreBundleOptionsSalable.php | 26 +++- .../Bundle/Model/Product/IsSaleableTest.php | 23 +++- .../Bundle/_files/issaleable_product.php | 112 +++++++++++++----- 3 files changed, 126 insertions(+), 35 deletions(-) diff --git a/app/code/Magento/Bundle/Model/ResourceModel/Option/AreBundleOptionsSalable.php b/app/code/Magento/Bundle/Model/ResourceModel/Option/AreBundleOptionsSalable.php index bfea7dc1295c..1f62e3d8f0d3 100644 --- a/app/code/Magento/Bundle/Model/ResourceModel/Option/AreBundleOptionsSalable.php +++ b/app/code/Magento/Bundle/Model/ResourceModel/Option/AreBundleOptionsSalable.php @@ -72,6 +72,10 @@ public function execute(int $entityId, int $storeId): bool ['child_products' => $this->resourceConnection->getTableName('catalog_product_entity')], 'child_products.entity_id = bundle_selections.product_id', [] + )->joinInner( + ['child_stock_item' => $this->resourceConnection->getTableName('cataloginventory_stock_item')], + 'child_stock_item.product_id = child_products.entity_id', + [] )->group( ['bundle_options.parent_id', 'bundle_options.option_id'] )->where( @@ -103,18 +107,36 @@ public function execute(int $entityId, int $storeId): bool '1', '0' ); + + $hasMinRequiredQuantity = $connection->getCheckSql( + 'required = 1 AND manage_stock = 1 AND selection_can_change_qty = 0', + 'qty >= bundle_selections.selection_qty AND is_in_stock = 1', + '1' + ); + + $requiredInStock = $connection->getCheckSql( + 'required = 1 AND manage_stock = 1 AND selection_can_change_qty = 1', + 'qty >= 0 AND is_in_stock = 1', + '1' + ); + $optionsSaleabilitySelect->columns([ 'required' => 'bundle_options.required', 'is_salable' => $isOptionSalableExpr, 'is_required_and_unsalable' => $isRequiredOptionUnsalable, + 'has_min_required_quantity' => $hasMinRequiredQuantity, + 'required_in_stock' => $requiredInStock ]); $select = $connection->select()->from( $optionsSaleabilitySelect, - [new \Zend_Db_Expr('(MAX(is_salable) = 1 AND MAX(is_required_and_unsalable) = 0)')] + [new \Zend_Db_Expr( + '(MAX(is_salable) = 1 AND MAX(is_required_and_unsalable) = 0)' . + 'AND MIN(required_in_stock) = 1 AND MIN(has_min_required_quantity) = 1' + )] ); - $isSalable = $connection->fetchOne($select); + $isSalable = $connection->fetchOne($select); return (bool) $isSalable; } } diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/IsSaleableTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/IsSaleableTest.php index 8031e4e7a584..d62ec931c542 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/IsSaleableTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/IsSaleableTest.php @@ -6,6 +6,8 @@ namespace Magento\Bundle\Model\Product; +use Magento\Framework\Exception\NoSuchEntityException; + /** * Test class for \Magento\Bundle\Model\Product\Type (bundle product type) * @@ -216,6 +218,7 @@ public function testIsSaleableOnBundleWithoutSaleableSelectionsOnRequiredOption( /** * Check bundle product is NOT saleable if * there are not enough qty of selection on required option + * when user cannot define own quantities * * @magentoAppIsolation enabled * @covers \Magento\Bundle\Model\Product\Type::isSalable @@ -224,9 +227,7 @@ public function testIsSaleableOnBundleWithoutSaleableSelectionsOnRequiredOption( public function testIsSaleableOnBundleWithNotEnoughQtyOfSelection() { $this->setQtyForSelections(['simple1', 'simple2', 'simple3'], 1); - $bundleProduct = $this->productRepository->get('bundle-product'); - $this->assertFalse( $bundleProduct->isSalable(), 'Bundle product supposed to be non saleable' @@ -354,4 +355,22 @@ private function setQtyForSelections($productsSku, $qty) $this->productRepository->save($product); } } + + /** + * Check bundle product is not salable if required option where user can + * set own quantity is not in stock + * + * @return void + * @magentoAppIsolation enabled + * @throws NoSuchEntityException + */ + public function testIsSalableOnBundleWithRequiredOptionUserCanChangeQtyWithoutStock() + { + $product = $this->productRepository->get('bundle-product-checkbox-required-option'); + $this->setQtyForSelections(['simple1'], 0); + $this->assertFalse( + $product->isSalable(), + 'Bundle product with required option that has 0 stock should not be salable' + ); + } } diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/issaleable_product.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/issaleable_product.php index 960a0ac8c5bb..d5b3a9271c4b 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/issaleable_product.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/issaleable_product.php @@ -8,6 +8,49 @@ Resolver::getInstance()->requireDataFixture('Magento/Bundle/_files/multiple_products.php'); +if (!function_exists('prepareBundleOptions')) { + function prepareBundleOptions(Magento\Catalog\Model\Product $product) { + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + /** @var \Magento\Catalog\Model\ProductRepository $productRepository */ + $productRepository = $objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); + if ($product->getBundleOptionsData()) { + $options = []; + foreach ($product->getBundleOptionsData() as $key => $optionData) { + if (!(bool)$optionData['delete']) { + $option = $objectManager->create(\Magento\Bundle\Api\Data\OptionInterfaceFactory::class) + ->create(['data' => $optionData]); + $option->setSku($product->getSku()); + $option->setOptionId(null); + + $links = []; + $bundleLinks = $product->getBundleSelectionsData(); + if (!empty($bundleLinks[$key])) { + foreach ($bundleLinks[$key] as $linkData) { + if (!(bool)$linkData['delete']) { + $link = $objectManager->create(\Magento\Bundle\Api\Data\LinkInterfaceFactory::class) + ->create(['data' => $linkData]); + $linkProduct = $productRepository->getById($linkData['product_id']); + $link->setSku($linkProduct->getSku()); + $link->setQty($linkData['selection_qty']); + if (isset($linkData['selection_can_change_qty'])) { + $link->setCanChangeQuantity((bool)$linkData['selection_can_change_qty']); + } + $links[] = $link; + } + } + $option->setProductLinks($links); + $options[] = $option; + } + } + } + $extension = $product->getExtensionAttributes(); + $extension->setBundleProductOptions($options); + $product->setExtensionAttributes($extension); + } + $productRepository->save($product, true); + } +} + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); /** @var \Magento\Catalog\Model\ProductRepository $productRepository */ $productRepository = $objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); @@ -177,36 +220,43 @@ ] ); -if ($product->getBundleOptionsData()) { - $options = []; - foreach ($product->getBundleOptionsData() as $key => $optionData) { - if (!(bool)$optionData['delete']) { - $option = $objectManager->create(\Magento\Bundle\Api\Data\OptionInterfaceFactory::class) - ->create(['data' => $optionData]); - $option->setSku($product->getSku()); - $option->setOptionId(null); +$bundleProduct = $objectManager->create(\Magento\Catalog\Model\Product::class);; +$bundleProduct->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) + ->setId(4) + ->setAttributeSetId(4) + ->setWebsiteIds([1]) + ->setName('Bundle Product Checkbox Required Option') + ->setSku('bundle-product-checkbox-required-option') + ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) + ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setPriceView(0) + ->setSkuType(1) + ->setWeightType(1) + ->setPriceType(\Magento\Bundle\Model\Product\Price::PRICE_TYPE_DYNAMIC) + ->setPrice(10.0) + ->setShipmentType(Magento\Catalog\Model\Product\Type\AbstractType::SHIPMENT_TOGETHER) + ->setBundleOptionsData([ + [ + 'title' => 'Checkbox Options', + 'default_title' => 'Checkbox Options', + 'type' => 'checkbox', + 'required' => 1, + 'delete' => '', + ], + ]) + ->setBundleSelectionsData([ + [ + [ + 'product_id' => 10, + 'selection_qty' => 1, + 'selection_can_change_qty' => 1, + 'delete' => '', + 'option_id' => 6 + ], + ] + ]); - $links = []; - $bundleLinks = $product->getBundleSelectionsData(); - if (!empty($bundleLinks[$key])) { - foreach ($bundleLinks[$key] as $linkData) { - if (!(bool)$linkData['delete']) { - $link = $objectManager->create(\Magento\Bundle\Api\Data\LinkInterfaceFactory::class) - ->create(['data' => $linkData]); - $linkProduct = $productRepository->getById($linkData['product_id']); - $link->setSku($linkProduct->getSku()); - $link->setQty($linkData['selection_qty']); - $links[] = $link; - } - } - $option->setProductLinks($links); - $options[] = $option; - } - } - } - $extension = $product->getExtensionAttributes(); - $extension->setBundleProductOptions($options); - $product->setExtensionAttributes($extension); -} +prepareBundleOptions($product); +prepareBundleOptions($bundleProduct); -$productRepository->save($product, true); From 0a8014cd291c44aa81e28c2569388fa1f352821f Mon Sep 17 00:00:00 2001 From: simsComputing Date: Sun, 13 Apr 2025 19:40:18 +0200 Subject: [PATCH 03/15] Fix all other bundle test --- .../Model/ResourceModel/Option/AreBundleOptionsSalable.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Bundle/Model/ResourceModel/Option/AreBundleOptionsSalable.php b/app/code/Magento/Bundle/Model/ResourceModel/Option/AreBundleOptionsSalable.php index 1f62e3d8f0d3..d8a933d9f453 100644 --- a/app/code/Magento/Bundle/Model/ResourceModel/Option/AreBundleOptionsSalable.php +++ b/app/code/Magento/Bundle/Model/ResourceModel/Option/AreBundleOptionsSalable.php @@ -110,13 +110,13 @@ public function execute(int $entityId, int $storeId): bool $hasMinRequiredQuantity = $connection->getCheckSql( 'required = 1 AND manage_stock = 1 AND selection_can_change_qty = 0', - 'qty >= bundle_selections.selection_qty AND is_in_stock = 1', + '(qty >= bundle_selections.selection_qty OR backorders > 0) AND is_in_stock = 1', '1' ); $requiredInStock = $connection->getCheckSql( 'required = 1 AND manage_stock = 1 AND selection_can_change_qty = 1', - 'qty >= 0 AND is_in_stock = 1', + '(qty >= 0 OR backorders > 0) AND is_in_stock = 1', '1' ); From be8a2087e097cdc95245a155fcd1f4ca4b067a34 Mon Sep 17 00:00:00 2001 From: simsComputing Date: Mon, 21 Apr 2025 14:53:02 +0200 Subject: [PATCH 04/15] Integrate code review changes --- .../testsuite/Magento/Bundle/_files/issaleable_product.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/issaleable_product.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/issaleable_product.php index d5b3a9271c4b..3877157ee0d7 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/issaleable_product.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/issaleable_product.php @@ -8,7 +8,8 @@ Resolver::getInstance()->requireDataFixture('Magento/Bundle/_files/multiple_products.php'); -if (!function_exists('prepareBundleOptions')) { +if (!function_exists('prepareBundleOptions')) +{ function prepareBundleOptions(Magento\Catalog\Model\Product $product) { $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); /** @var \Magento\Catalog\Model\ProductRepository $productRepository */ @@ -220,7 +221,7 @@ function prepareBundleOptions(Magento\Catalog\Model\Product $product) { ] ); -$bundleProduct = $objectManager->create(\Magento\Catalog\Model\Product::class);; +$bundleProduct = $objectManager->create(\Magento\Catalog\Model\Product::class); $bundleProduct->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) ->setId(4) ->setAttributeSetId(4) @@ -259,4 +260,3 @@ function prepareBundleOptions(Magento\Catalog\Model\Product $product) { prepareBundleOptions($product); prepareBundleOptions($bundleProduct); - From 310d82c08bb541302eaad07c013064c66c9e81b1 Mon Sep 17 00:00:00 2001 From: simsComputing Date: Mon, 21 Apr 2025 15:04:39 +0200 Subject: [PATCH 05/15] Fix CatalogInventory test --- .../Inventory/ChangeParentStockStatus.php | 14 ++++++++- .../Model/Inventory/ParentItemProcessor.php | 29 ++++++------------- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/app/code/Magento/ConfigurableProduct/Model/Inventory/ChangeParentStockStatus.php b/app/code/Magento/ConfigurableProduct/Model/Inventory/ChangeParentStockStatus.php index 4ad15ea905f0..860e507fa6d6 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Inventory/ChangeParentStockStatus.php +++ b/app/code/Magento/ConfigurableProduct/Model/Inventory/ChangeParentStockStatus.php @@ -59,7 +59,7 @@ public function __construct( /** * Update stock status of configurable products based on children products stock status * - * @param array $childrenIds + * @param array $childrenIds * @return void */ public function execute(array $childrenIds): void @@ -70,6 +70,17 @@ public function execute(array $childrenIds): void } } + /** + * Updates the parent stock status based on children statuses + * + * @param int $parentId + * @return void + */ + public function executeFromParent(int $parentId): void + { + $this->processStockForParent($parentId); + } + /** * Update stock status of configurable product based on children products stock status * @@ -106,6 +117,7 @@ private function processStockForParent(int $productId): void if ($this->isNeedToUpdateParent($parentStockItem, $childrenIsInStock)) { $parentStockItem->setIsInStock($childrenIsInStock); $parentStockItem->setStockStatusChangedAuto(1); + // @phpstan-ignore method.notFound $parentStockItem->setStockStatusChangedAutomaticallyFlag(true); $this->stockItemRepository->save($parentStockItem); } diff --git a/app/code/Magento/ConfigurableProduct/Model/Inventory/ParentItemProcessor.php b/app/code/Magento/ConfigurableProduct/Model/Inventory/ParentItemProcessor.php index 4ae3efdd6aca..5f912155e7da 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Inventory/ParentItemProcessor.php +++ b/app/code/Magento/ConfigurableProduct/Model/Inventory/ParentItemProcessor.php @@ -7,6 +7,7 @@ namespace Magento\ConfigurableProduct\Model\Inventory; +use Magento\Catalog\Model\Product\Type; use Magento\ConfigurableProduct\Model\Product\Type\Configurable; use Magento\Catalog\Api\Data\ProductInterface as Product; use Magento\CatalogInventory\Api\StockItemCriteriaInterfaceFactory; @@ -21,27 +22,11 @@ class ParentItemProcessor implements ParentItemProcessorInterface { /** - * @var ChangeParentStockStatus - */ - private $changeParentStockStatus; - - /** - * @param Configurable $configurableType - * @param StockItemCriteriaInterfaceFactory $criteriaInterfaceFactory - * @param StockItemRepositoryInterface $stockItemRepository - * @param StockConfigurationInterface $stockConfiguration - * @param ChangeParentStockStatus|null $changeParentStockStatus - * @SuppressWarnings(PHPMD.UnusedFormalParameter) Deprecated dependencies + * @param ChangeParentStockStatus $changeParentStockStatus */ public function __construct( - Configurable $configurableType, - StockItemCriteriaInterfaceFactory $criteriaInterfaceFactory, - StockItemRepositoryInterface $stockItemRepository, - StockConfigurationInterface $stockConfiguration, - ?ChangeParentStockStatus $changeParentStockStatus = null + private readonly ChangeParentStockStatus $changeParentStockStatus ) { - $this->changeParentStockStatus = $changeParentStockStatus - ?? ObjectManager::getInstance()->get(ChangeParentStockStatus::class); } /** @@ -50,8 +35,12 @@ public function __construct( * @param Product $product * @return void */ - public function process(Product $product) + public function process(Product $product): void { - $this->changeParentStockStatus->execute([$product->getId()]); + if ($product->getTypeId() === Type::TYPE_SIMPLE) { + $this->changeParentStockStatus->execute([$product->getId()]); + } elseif ($product->getTypeId() === Configurable::TYPE_CODE) { + $this->changeParentStockStatus->executeFromParent((int)$product->getId()); + } } } From e60082750c754f6de3a0a359b643ff827677eb67 Mon Sep 17 00:00:00 2001 From: simsComputing Date: Sat, 26 Apr 2025 14:36:58 +0200 Subject: [PATCH 06/15] Fix stockitem criteria --- .../Model/ResourceModel/Stock/Item/StockItemCriteria.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Item/StockItemCriteria.php b/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Item/StockItemCriteria.php index 3d82ab247c4a..c65f031abaff 100644 --- a/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Item/StockItemCriteria.php +++ b/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Item/StockItemCriteria.php @@ -10,7 +10,7 @@ use Magento\CatalogInventory\Model\ResourceModel\Stock\Item\StockItemCriteriaMapper; /** - * Class StockItemCriteria + * Build criteria to filter products on catalog_stockinventory table */ class StockItemCriteria extends AbstractCriteria implements \Magento\CatalogInventory\Api\StockItemCriteriaInterface { @@ -55,7 +55,11 @@ public function setScopeFilter($scope) */ public function setProductsFilter($products) { - $this->data['products_filter'] = [$products]; + if (is_array($products)) { + $this->data['products_filter'] = $products; + } else { + $this->data['products_filter'] = [$products]; + } return true; } From 0c375c20ee5ca876aec7cfe53ef252f0542d7c87 Mon Sep 17 00:00:00 2001 From: simsComputing Date: Sun, 27 Apr 2025 17:27:23 +0200 Subject: [PATCH 07/15] Fix test on price indexing because of confiurable out of stock --- .../product_configurable_with_assigned_simples.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_with_assigned_simples.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_with_assigned_simples.php index 81a067195e90..d59bff310b51 100644 --- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_with_assigned_simples.php +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_with_assigned_simples.php @@ -37,8 +37,7 @@ ->setName('Configurable Product') ->setSku('configurable') ->setVisibility(Visibility::VISIBILITY_BOTH) - ->setStatus(Status::STATUS_ENABLED) - ->setStockData(['use_config_manage_stock' => 1, 'is_in_stock' => 1]); + ->setStatus(Status::STATUS_ENABLED); $productRepository = Bootstrap::getObjectManager()->get(ProductRepositoryInterface::class); $product = $productRepository->save($product); @@ -108,3 +107,10 @@ $indexerProcessor = Bootstrap::getObjectManager()->get(PriceIndexerProcessor::class); $indexerProcessor->reindexRow($product->getId()); + +/** @var Item $stockItem */ +$stockItem = Bootstrap::getObjectManager()->create(Item::class); +$stockItem->load($product->getId(), 'product_id'); + +$stockItem->setIsInStock(true); +$stockItem->save(); From ad8ac226855653e9c3b370c1176291bbaa4c2b6a Mon Sep 17 00:00:00 2001 From: simsComputing Date: Sun, 27 Apr 2025 20:39:09 +0200 Subject: [PATCH 08/15] Fix ButtonLock dependency --- .../testsuite/Magento/Customer/Block/Form/EditTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/Customer/Block/Form/EditTest.php b/dev/tests/integration/testsuite/Magento/Customer/Block/Form/EditTest.php index e62eb5a8ac3a..3b50155a15f0 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Block/Form/EditTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Block/Form/EditTest.php @@ -8,6 +8,7 @@ namespace Magento\Customer\Block\Form; use Magento\Customer\Model\Session; +use Magento\Framework\View\Element\ButtonLockInterface; use Magento\Framework\View\LayoutInterface; use Magento\Framework\View\Element\ButtonLockManager; use Magento\TestFramework\Helper\Bootstrap; @@ -60,7 +61,7 @@ protected function setUp(): void public function testCustomerEditButton(): void { $code = 'customer_edit'; - $buttonLock = $this->getMockBuilder(\Magento\ReCaptchaUi\Model\ButtonLock::class) + $buttonLock = $this->getMockBuilder(ButtonLockInterface::class) ->disableOriginalConstructor() ->disableAutoload() ->onlyMethods(['isDisabled', 'getCode']) From fca904d09a34d7734ca3ee432dfb00ddea7a5080 Mon Sep 17 00:00:00 2001 From: simsComputing Date: Sun, 27 Apr 2025 22:03:10 +0200 Subject: [PATCH 09/15] Fix tests for Magento_Customer --- .../Customer/Model/Metadata/Form/Multiline.php | 2 +- .../Magento/Customer/Api/AddressRepositoryTest.php | 6 +++--- .../Magento/Customer/Block/Form/LoginTest.php | 3 ++- .../Magento/Customer/Block/Form/RegisterTest.php | 3 ++- .../Address/FormPost/CreateAddressTest.php | 4 ++-- .../Address/FormPost/UpdateAddressTest.php | 4 ++-- .../Customer/Model/Address/CreateAddressTest.php | 4 ++-- .../Customer/Model/Address/UpdateAddressTest.php | 2 +- .../Model/ResourceModel/AddressRepositoryTest.php | 12 ++++++------ .../Model/ResourceModel/Grid/CollectionTest.php | 2 +- 10 files changed, 22 insertions(+), 20 deletions(-) diff --git a/app/code/Magento/Customer/Model/Metadata/Form/Multiline.php b/app/code/Magento/Customer/Model/Metadata/Form/Multiline.php index 6dcb4f53d366..8a37b2e2089c 100644 --- a/app/code/Magento/Customer/Model/Metadata/Form/Multiline.php +++ b/app/code/Magento/Customer/Model/Metadata/Form/Multiline.php @@ -116,7 +116,7 @@ public function outputValue($format = ElementFactory::OUTPUT_FORMAT_TEXT) $output = implode("
", $values); break; case ElementFactory::OUTPUT_FORMAT_ONELINE: - $output = implode(" ", $values); + $output = trim(implode(" ", $values), ' '); break; default: $output = implode("\n", $values); diff --git a/dev/tests/integration/testsuite/Magento/Customer/Api/AddressRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Customer/Api/AddressRepositoryTest.php index 2cb125baaeee..826dfdc0772b 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Api/AddressRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Api/AddressRepositoryTest.php @@ -65,15 +65,15 @@ protected function setUp(): void $address2 = $this->_addressFactory->create() ->setId('2') ->setCountryId('US') - ->setCustomerId(1) + ->setCustomerId('1') ->setPostcode('47676') ->setRegion($region) - ->setStreet(['Black str, 48']) + ->setStreet(['Black str, 48', '']) ->setCity('CityX') ->setTelephone('3234676') ->setFirstname('John') ->setLastname('Smith') - ->setRegionId(1); + ->setRegionId('1'); $this->_expectedAddresses = [$address, $address2]; } diff --git a/dev/tests/integration/testsuite/Magento/Customer/Block/Form/LoginTest.php b/dev/tests/integration/testsuite/Magento/Customer/Block/Form/LoginTest.php index 2d15819f0933..25c65ac5eec3 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Block/Form/LoginTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Block/Form/LoginTest.php @@ -8,6 +8,7 @@ namespace Magento\Customer\Block\Form; use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\View\Element\ButtonLockInterface; use Magento\Framework\View\LayoutInterface; use Magento\Framework\View\Element\ButtonLockManager; use Magento\TestFramework\Helper\Bootstrap; @@ -49,7 +50,7 @@ protected function setUp(): void $this->layout = $this->objectManager->get(LayoutInterface::class); $code = 'customer_login_form_submit'; - $buttonLock = $this->getMockBuilder(\Magento\ReCaptchaUi\Model\ButtonLock::class) + $buttonLock = $this->getMockBuilder(ButtonLockInterface::class) ->disableOriginalConstructor() ->disableAutoload() ->onlyMethods(['isDisabled', 'getCode']) diff --git a/dev/tests/integration/testsuite/Magento/Customer/Block/Form/RegisterTest.php b/dev/tests/integration/testsuite/Magento/Customer/Block/Form/RegisterTest.php index d1da64e0e9fe..24963e55d53f 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Block/Form/RegisterTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Block/Form/RegisterTest.php @@ -7,6 +7,7 @@ use Magento\Customer\Block\DataProviders\AddressAttributeData; use Magento\Customer\ViewModel\Address\RegionProvider; +use Magento\Framework\View\Element\ButtonLockInterface; use Magento\Framework\View\Element\Template; use Magento\Framework\View\Element\ButtonLockManager; use Magento\TestFramework\Helper\Bootstrap; @@ -207,7 +208,7 @@ private function setRegionProvider(Template $block): void private function setButtonLockManager(Template $block): void { $code = 'customer_create_form_submit'; - $buttonLock = $this->getMockBuilder(\Magento\ReCaptchaUi\Model\ButtonLock::class) + $buttonLock = $this->getMockBuilder(ButtonLockInterface::class) ->disableOriginalConstructor() ->disableAutoload() ->onlyMethods(['isDisabled', 'getCode']) diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Address/FormPost/CreateAddressTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Address/FormPost/CreateAddressTest.php index 559ccfcf9a13..d18a918b2f4e 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/Address/FormPost/CreateAddressTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Address/FormPost/CreateAddressTest.php @@ -220,7 +220,7 @@ public static function postDataForSuccessCreateAddressDataProvider(): array 'custom_region_name' => 'Alabama', AddressInterface::FIRSTNAME => 'John', AddressInterface::LASTNAME => 'Smith', - AddressInterface::STREET => ['Green str, 67'], + AddressInterface::STREET => ['Green str, 67', ''], AddressInterface::CITY => 'CityM', ], ], @@ -250,7 +250,7 @@ public static function postDataForSuccessCreateAddressDataProvider(): array ], 'required_field_street_as_array' => [ array_replace(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::STREET => ['', 'Green str, 67']]), - [AddressInterface::STREET => ['Green str, 67']], + [AddressInterface::STREET => ['Green str, 67', '']], ], 'field_company_name' => [ array_merge(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::COMPANY => 'My company']), diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Address/FormPost/UpdateAddressTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Address/FormPost/UpdateAddressTest.php index 9e91e8792236..0485d315a579 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/Address/FormPost/UpdateAddressTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Address/FormPost/UpdateAddressTest.php @@ -230,7 +230,7 @@ public static function postDataForSuccessUpdateAddressDataProvider(): array 'custom_region_name' => 'Arkansas', AddressInterface::FIRSTNAME => 'Foma', AddressInterface::LASTNAME => 'Kiniaev', - AddressInterface::STREET => ['Yellow str, 228'], + AddressInterface::STREET => ['Yellow str, 228', ''], AddressInterface::CITY => 'Mukachevo', ], ], @@ -260,7 +260,7 @@ public static function postDataForSuccessUpdateAddressDataProvider(): array ], 'required_field_street_as_array' => [ array_replace(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::STREET => ['', 'Green str, 67']]), - [AddressInterface::STREET => ['Green str, 67']], + [AddressInterface::STREET => ['Green str, 67', '']], ], 'field_company_name' => [ array_merge(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::COMPANY => 'My company']), diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/Address/CreateAddressTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/Address/CreateAddressTest.php index 67ffffb9e51c..be9572bcaf42 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/Address/CreateAddressTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/Address/CreateAddressTest.php @@ -220,7 +220,7 @@ public static function createAddressesDataProvider(): array 'custom_region_name' => 'Alabama', AddressInterface::FIRSTNAME => 'John', AddressInterface::LASTNAME => 'Smith', - AddressInterface::STREET => ['Green str, 67'], + AddressInterface::STREET => ['Green str, 67', ''], AddressInterface::CITY => 'CityM', ], ], @@ -250,7 +250,7 @@ public static function createAddressesDataProvider(): array ], 'required_field_street_as_array' => [ array_replace(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::STREET => ['', 'Green str, 67']]), - [AddressInterface::STREET => ['Green str, 67']], + [AddressInterface::STREET => ['Green str, 67', '']], ], 'field_name_prefix' => [ array_merge(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::PREFIX => 'My prefix']), diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/Address/UpdateAddressTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/Address/UpdateAddressTest.php index 2adf68d2cca4..7cde6370c50a 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/Address/UpdateAddressTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/Address/UpdateAddressTest.php @@ -195,7 +195,7 @@ public static function updateAddressesDataProvider(): array ], 'required_field_street_as_array' => [ [AddressInterface::STREET => ['', 'Test str, 55']], - [AddressInterface::STREET => ['Test str, 55']], + [AddressInterface::STREET => ['Test str, 55', '']], ], 'required_field_city' => [ [AddressInterface::CITY => 'Test city'], diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/AddressRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/AddressRepositoryTest.php index 87983dd0277f..f5eb7259d31d 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/AddressRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/AddressRepositoryTest.php @@ -81,15 +81,15 @@ protected function setUp(): void $region = $this->regionFactory->create() ->setRegionCode('AL') ->setRegion('Alabama') - ->setRegionId(1); + ->setRegionId('1'); $address = $this->addressFactory->create() ->setId('1') ->setCountryId('US') ->setCustomerId('1') ->setPostcode('75477') ->setRegion($region) - ->setRegionId(1) - ->setStreet(['Green str, 67']) + ->setRegionId('1') + ->setStreet(['Green str, 67', '']) ->setTelephone('3468676') ->setCity('CityM') ->setFirstname('John') @@ -101,8 +101,8 @@ protected function setUp(): void ->setCustomerId('1') ->setPostcode('47676') ->setRegion($region) - ->setRegionId(1) - ->setStreet(['Black str, 48']) + ->setRegionId('1') + ->setStreet(['Black str, 48', '']) ->setCity('CityX') ->setTelephone('3234676') ->setFirstname('John') @@ -647,7 +647,7 @@ public function testUpdateWithAlphanumericZipCode(): void AddressInterface::SUFFIX => '_Suffix', AddressInterface::PREFIX => 'Prefix', AddressInterface::COMPANY => 'Company', - AddressInterface::STREET => ['Northgate Street, 39'], + AddressInterface::STREET => ['Northgate Street, 39', ''], AddressInterface::CITY => 'BICKTON', AddressInterface::COUNTRY_ID => 'GB', AddressInterface::REGION => $region, diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/Grid/CollectionTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/Grid/CollectionTest.php index 07e38b1fd52f..167a9a1edef1 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/Grid/CollectionTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/Grid/CollectionTest.php @@ -54,7 +54,7 @@ public function testGetItemByIdForUpdateOnSchedule() $item = $this->targetObject->getItemById($newCustomer->getId()); $this->assertNotEmpty($item); $this->assertSame($newCustomer->getEmail(), $item->getEmail()); - $this->assertSame('test street test city Armed Forces Middle East 01001', $item->getBillingFull()); + $this->assertSame('test street' . PHP_EOL . ' test city Armed Forces Middle East 01001', $item->getBillingFull()); /** set customer grid indexer on schedule' mode */ $indexer->setScheduled(true); From 1997797af87d91b87c84d5f7645a825eed742477 Mon Sep 17 00:00:00 2001 From: simsComputing Date: Sat, 10 May 2025 14:32:09 +0200 Subject: [PATCH 10/15] Fix CustomerImportExport module test --- .../Model/Export/AddressTest.php | 47 ++++++++++--------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Export/AddressTest.php b/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Export/AddressTest.php index 20a757508c42..c215fd2aef0e 100644 --- a/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Export/AddressTest.php +++ b/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Export/AddressTest.php @@ -7,6 +7,8 @@ namespace Magento\CustomerImportExport\Model\Export; use Magento\CustomerImportExport\Model\Import\Address as ImportAddress; +use Magento\Store\Api\Data\WebsiteInterface; +use Magento\TestFramework\ObjectManager; /** * Test for customer address export model @@ -23,7 +25,7 @@ class AddressTest extends \PHPUnit\Framework\TestCase /** * List of existing websites * - * @var array + * @var WebsiteInterface[] */ protected $_websites = []; @@ -39,7 +41,7 @@ protected function setUp(): void )->getWebsites( true ); - /** @var $website \Magento\Store\Model\Website */ + /** @var WebsiteInterface $website */ foreach ($websites as $website) { $this->_websites[$website->getId()] = $website->getCode(); } @@ -48,18 +50,18 @@ protected function setUp(): void /** * Test export method */ - public function testExport() + public function testExport(): void { $websiteCode = Address::COLUMN_WEBSITE; $emailCode = Address::COLUMN_EMAIL; $entityIdCode = Address::COLUMN_ADDRESS_ID; $expectedAttributes = []; - /** @var $collection \Magento\Customer\Model\ResourceModel\Address\Attribute\Collection */ + /** @var \Magento\Customer\Model\ResourceModel\Address\Attribute\Collection $collection */ $collection = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( \Magento\Customer\Model\ResourceModel\Address\Attribute\Collection::class ); - /** @var $attribute \Magento\Customer\Model\Attribute */ + /** @var \Magento\Customer\Model\Attribute $attribute */ foreach ($collection as $attribute) { $expectedAttributes[] = $attribute->getAttributeCode(); } @@ -73,7 +75,6 @@ public function testExport() ) ); $this->_model->setParameters([]); - $data = $this->_csvToArray($this->_model->export(), $entityIdCode); $this->assertEquals( @@ -84,18 +85,18 @@ public function testExport() $this->assertNotEmpty($data['data'], 'No data was exported'); - /** @var $objectManager \Magento\TestFramework\ObjectManager */ + /** @var ObjectManager $objectManager */ $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); // Get addresses - /** @var $customers \Magento\Customer\Model\Customer[] */ + /** @var \Magento\Customer\Model\Customer[] $customers */ $customers = $objectManager->get( \Magento\Framework\Registry::class )->registry( '_fixture/Magento_ImportExport_Customers_Array' ); foreach ($customers as $customer) { - /** @var $address \Magento\Customer\Model\Address */ + /** @var \Magento\Customer\Model\Address $address */ foreach ($customer->getAddresses() as $address) { // Check unique key $data['data'][$address->getId()][$websiteCode] = $this->_websites[$customer->getWebsiteId()]; @@ -128,9 +129,9 @@ public function testExport() /** * Get possible gender values for filter * - * @return array + * @return array> */ - public static function getGenderFilterValueDataProvider() + public static function getGenderFilterValueDataProvider(): array { return ['male' => ['genderFilterValue' => 1], 'female' => ['genderFilterValue' => 2]]; } @@ -142,7 +143,7 @@ public static function getGenderFilterValueDataProvider() * * @param int $genderFilterValue */ - public function testExportWithFilter($genderFilterValue) + public function testExportWithFilter($genderFilterValue): void { $entityIdCode = Address::COLUMN_ADDRESS_ID; @@ -156,11 +157,11 @@ public function testExportWithFilter($genderFilterValue) $this->_model->setParameters($filterData); - /** @var $objectManager \Magento\TestFramework\ObjectManager */ + /** @var ObjectManager $objectManager */ $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); // Get expected address count - /** @var $customers \Magento\Customer\Model\Customer[] */ + /** @var \Magento\Customer\Model\Customer[] $customers */ $customers = $objectManager->get( \Magento\Framework\Registry::class )->registry( @@ -168,6 +169,7 @@ public function testExportWithFilter($genderFilterValue) ); $expectedCount = 0; foreach ($customers as $customer) { + // @phpstan-ignore method.notFound if ($customer->getGender() == $genderFilterValue) { $expectedCount += count($customer->getAddresses()); } @@ -181,7 +183,7 @@ public function testExportWithFilter($genderFilterValue) /** * Test entity type code value */ - public function testGetEntityTypeCode() + public function testGetEntityTypeCode(): void { $this->assertEquals('customer_address', $this->_model->getEntityTypeCode()); } @@ -189,7 +191,7 @@ public function testGetEntityTypeCode() /** * Test type of attribute collection */ - public function testGetAttributeCollection() + public function testGetAttributeCollection(): void { $this->assertInstanceOf( \Magento\Customer\Model\ResourceModel\Address\Attribute\Collection::class, @@ -202,13 +204,16 @@ public function testGetAttributeCollection() * * @param string $content * @param mixed $entityId - * @return array + * @return array> */ - protected function _csvToArray($content, $entityId = null) + protected function _csvToArray($content, $entityId = null): array { $data = ['header' => [], 'data' => []]; - - $lines = str_getcsv($content, "\n", '"', '\\'); + // Cannot use str_getcsv here because if native php bug. Needs to split lines + // the homemade way. + // Though this test is very fragile for now. This homemade way of splitting the CSV + // can break easily if something changes in the adress's street. + $lines = array_filter(preg_split('/\n(?!")/m', $content)); foreach ($lines as $index => $line) { if ($index == 0) { $data['header'] = str_getcsv($line, ',', '"', '\\'); @@ -228,7 +233,7 @@ protected function _csvToArray($content, $entityId = null) /** * Test filename getter. Filename must be set in constructor. */ - public function testGetFileName() + public function testGetFileName(): void { $this->assertEquals($this->_model->getEntityTypeCode(), $this->_model->getFileName()); } From 5782bb84428fc1c56a9aa8affc83716d5e86f837 Mon Sep 17 00:00:00 2001 From: simsComputing Date: Sat, 10 May 2025 18:35:32 +0200 Subject: [PATCH 11/15] Fix Mage-OS Product Name --- lib/internal/Magento/Framework/App/ProductMetadata.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/App/ProductMetadata.php b/lib/internal/Magento/Framework/App/ProductMetadata.php index 227f2c1fc311..53e1bb16fad7 100644 --- a/lib/internal/Magento/Framework/App/ProductMetadata.php +++ b/lib/internal/Magento/Framework/App/ProductMetadata.php @@ -25,7 +25,7 @@ class ProductMetadata implements ProductMetadataInterface, DistributionMetadataI /** * Magento product name */ - public const PRODUCT_NAME = 'Magento'; + public const PRODUCT_NAME = 'Mage-OS'; /** * Distribution product name From 18489c3e6d2f6625e8e71926ff42ed2ac733dfd0 Mon Sep 17 00:00:00 2001 From: simsComputing Date: Sun, 18 May 2025 21:08:50 +0200 Subject: [PATCH 12/15] Fix Magento_Downloadable integration tests --- .../Email/Items/Order/DownloadableTest.php | 8 +- ...with_configurable_downloadable_product.php | 87 ------------------- ...igurable_downloadable_product_rollback.php | 21 ----- .../quote_with_downloadable_product.php | 33 ++++++- 4 files changed, 35 insertions(+), 114 deletions(-) delete mode 100644 dev/tests/integration/testsuite/Magento/Downloadable/_files/quote_with_configurable_downloadable_product.php delete mode 100644 dev/tests/integration/testsuite/Magento/Downloadable/_files/quote_with_configurable_downloadable_product_rollback.php diff --git a/dev/tests/integration/testsuite/Magento/Downloadable/Block/Sales/Order/Email/Items/Order/DownloadableTest.php b/dev/tests/integration/testsuite/Magento/Downloadable/Block/Sales/Order/Email/Items/Order/DownloadableTest.php index 107d492068e4..a11c93d245b5 100644 --- a/dev/tests/integration/testsuite/Magento/Downloadable/Block/Sales/Order/Email/Items/Order/DownloadableTest.php +++ b/dev/tests/integration/testsuite/Magento/Downloadable/Block/Sales/Order/Email/Items/Order/DownloadableTest.php @@ -52,15 +52,15 @@ protected function setUp(): void } /** - * @magentoDataFixture Magento/Downloadable/_files/quote_with_configurable_downloadable_product.php + * @magentoDataFixture Magento/Downloadable/_files/quote_with_downloadable_product.php * @return void */ public function testShouldSendDownloadableLinksInTheEmail(): void { /** @var Quote $quote */ $quote = $this->objectManager->create(Quote::class); - $quote->load('reserved_order_configurable_downloadable', 'reserved_order_id'); - + // @phpstan-ignore argument.type + $quote->load('reserved_order_id_1', 'reserved_order_id'); $checkoutSession = $this->objectManager->get(CheckoutSession::class); $checkoutSession->setQuoteId($quote->getId()); @@ -74,7 +74,7 @@ public function testShouldSendDownloadableLinksInTheEmail(): void $cartManagement->placeOrder($cartId); $message = $this->transportBuilder->getSentMessage(); $rawMessage = quoted_printable_decode($message->getBody()->bodyToString()); - $this->assertStringContainsString('Configurable Downloadable Product', $rawMessage); + $this->assertStringContainsString('Downloadable Product', $rawMessage); $this->assertStringContainsString('SKU: downloadable-product', $rawMessage); $this->assertStringContainsString('Downloadable Product Link', $rawMessage); $this->assertStringContainsString('/downloadable/download/link/id/', $rawMessage); diff --git a/dev/tests/integration/testsuite/Magento/Downloadable/_files/quote_with_configurable_downloadable_product.php b/dev/tests/integration/testsuite/Magento/Downloadable/_files/quote_with_configurable_downloadable_product.php deleted file mode 100644 index bb17a119f0d6..000000000000 --- a/dev/tests/integration/testsuite/Magento/Downloadable/_files/quote_with_configurable_downloadable_product.php +++ /dev/null @@ -1,87 +0,0 @@ -requireDataFixture('Magento/Downloadable/_files/product_configurable_downloadable.php'); - -$objectManager = Bootstrap::getObjectManager(); -/** @var ProductRepositoryInterface $productRepository */ -$productRepository = $objectManager->create(ProductRepositoryInterface::class); -$downloadableProduct = $productRepository->get('downloadable-product'); -$configurableProduct = $productRepository->get('configurable_downloadable'); -/** @var $options Collection */ -$options = $objectManager->create(Collection::class); -/** @var Config $eavConfig */ -$eavConfig = $objectManager->get(Config::class); -$attribute = $eavConfig->getAttribute(Product::ENTITY, 'test_configurable'); -$option = $options->setAttributeFilter($attribute->getId())->getFirstItem(); -$requestInfo = new DataObject( - [ - 'product_id' => $configurableProduct->getId(), - 'selected_configurable_option' => $downloadableProduct->getId(), - 'qty' => 1, - 'super_attribute' => [ - $attribute->getId() => $option->getId() - ], - 'links' => array_keys($downloadableProduct->getDownloadableLinks()) - ] -); -$addressData = [ - 'telephone' => 3234676, - 'postcode' => 47676, - 'country_id' => 'DE', - 'city' => 'CityX', - 'street' => ['Black str, 48'], - 'lastname' => 'Smith', - 'firstname' => 'John', - 'vat_id' => 12345, - 'address_type' => 'shipping', - 'email' => 'some_email@mail.com', -]; - -$billingAddress = $objectManager->create( - Address::class, - ['data' => $addressData] -); -$billingAddress->setAddressType('billing'); -$shippingAddress = clone $billingAddress; -$shippingAddress->setId(null)->setAddressType('shipping'); - -/** @var Quote $quote */ -$quote = $objectManager->create(Quote::class); -$quote->setCustomerIsGuest(true) - ->setStoreId($objectManager->get(StoreManagerInterface::class)->getStore()->getId()) - ->setReservedOrderId('reserved_order_configurable_downloadable') - ->setIsMultiShipping(false) - ->setBillingAddress($billingAddress) - ->setShippingAddress($shippingAddress) - ->addProduct($configurableProduct, $requestInfo); - -$quote->getPayment()->setMethod('checkmo'); -$quote->getShippingAddress()->setShippingMethod('flatrate_flatrate')->setCollectShippingRates(true); -$quote->collectTotals(); -$quote->save(); - -/** @var QuoteIdMask $quoteIdMask */ -$quoteIdMask = $objectManager - ->create(QuoteIdMaskFactory::class) - ->create(); -$quoteIdMask->setQuoteId($quote->getId()); -$quoteIdMask->setDataChanges(true); -$quoteIdMask->save(); diff --git a/dev/tests/integration/testsuite/Magento/Downloadable/_files/quote_with_configurable_downloadable_product_rollback.php b/dev/tests/integration/testsuite/Magento/Downloadable/_files/quote_with_configurable_downloadable_product_rollback.php deleted file mode 100644 index 46fecf75bb58..000000000000 --- a/dev/tests/integration/testsuite/Magento/Downloadable/_files/quote_with_configurable_downloadable_product_rollback.php +++ /dev/null @@ -1,21 +0,0 @@ -create(\Magento\Quote\Model\Quote::class); -$quote->load('reserved_order_configurable_downloadable', 'reserved_order_id')->delete(); - -/** @var \Magento\Quote\Model\QuoteIdMask $quoteIdMask */ -$quoteIdMask = $objectManager->create(\Magento\Quote\Model\QuoteIdMask::class); -$quoteIdMask->delete($quote->getId()); - -Resolver::getInstance()->requireDataFixture( - 'Magento/Downloadable/_files/product_configurable_downloadable_rollback.php' -); diff --git a/dev/tests/integration/testsuite/Magento/Downloadable/_files/quote_with_downloadable_product.php b/dev/tests/integration/testsuite/Magento/Downloadable/_files/quote_with_downloadable_product.php index ecbba524ba82..576d5cfec634 100644 --- a/dev/tests/integration/testsuite/Magento/Downloadable/_files/quote_with_downloadable_product.php +++ b/dev/tests/integration/testsuite/Magento/Downloadable/_files/quote_with_downloadable_product.php @@ -6,6 +6,7 @@ use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\TestFramework\Workaround\Override\Fixture\Resolver; +use Magento\Quote\Model\Quote\Address; Resolver::getInstance()->requireDataFixture('Magento/Downloadable/_files/product_downloadable.php'); @@ -15,6 +16,27 @@ $productRepository = $objectManager->create(ProductRepositoryInterface::class); $product = $productRepository->get('downloadable-product'); +$addressData = [ + 'telephone' => 3234676, + 'postcode' => 47676, + 'country_id' => 'DE', + 'city' => 'CityX', + 'street' => ['Black str, 48'], + 'lastname' => 'Smith', + 'firstname' => 'John', + 'vat_id' => 12345, + 'address_type' => 'shipping', + 'email' => 'some_email@mail.com', +]; + +$billingAddress = $objectManager->create( + Address::class, + ['data' => $addressData] +); +$billingAddress->setAddressType('billing'); +$shippingAddress = clone $billingAddress; +$shippingAddress->setId(null)->setAddressType('shipping'); + /** @var \Magento\Quote\Model\Quote $quote */ $quote = $objectManager->create(\Magento\Quote\Model\Quote::class); $quote->setCustomerIsGuest( @@ -26,13 +48,19 @@ )->setReservedOrderId( 'reserved_order_id_1' )->setIsMultiShipping( - false -)->addProduct( + 0 +)->setBillingAddress($billingAddress) + ->setShippingAddress($shippingAddress) + ->addProduct( + // @phpstan-ignore argument.type $product, new \Magento\Framework\DataObject([ + // @phpstan-ignore method.notFound 'links' => array_keys($product->getDownloadableLinks()) ]) ); +$quote->getPayment()->setMethod('checkmo'); +$quote->getShippingAddress()->setShippingMethod('flatrate_flatrate')->setCollectShippingRates(true); $quote->collectTotals(); $quote->save(); @@ -40,6 +68,7 @@ $quoteIdMask = $objectManager ->create(\Magento\Quote\Model\QuoteIdMaskFactory::class) ->create(); +// @phpstan-ignore method.notFound $quoteIdMask->setQuoteId($quote->getId()); $quoteIdMask->setDataChanges(true); $quoteIdMask->save(); From ec24c0c6cd681b002a6f3f3fed21f7b42a1731d0 Mon Sep 17 00:00:00 2001 From: simsComputing Date: Sun, 15 Jun 2025 21:06:40 +0200 Subject: [PATCH 13/15] Backward compatibility --- .../Model/Inventory/ParentItemProcessor.php | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/ConfigurableProduct/Model/Inventory/ParentItemProcessor.php b/app/code/Magento/ConfigurableProduct/Model/Inventory/ParentItemProcessor.php index 5f912155e7da..243d57379a92 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Inventory/ParentItemProcessor.php +++ b/app/code/Magento/ConfigurableProduct/Model/Inventory/ParentItemProcessor.php @@ -21,12 +21,25 @@ */ class ParentItemProcessor implements ParentItemProcessorInterface { + private ChangeParentStockStatus $changeParentStockStatus; + /** - * @param ChangeParentStockStatus $changeParentStockStatus + * @param Configurable $configurableType + * @param StockItemCriteriaInterfaceFactory $criteriaInterfaceFactory + * @param StockItemRepositoryInterface $stockItemRepository + * @param StockConfigurationInterface $stockConfiguration + * @param ChangeParentStockStatus|null $changeParentStockStatus + * @SuppressWarnings(PHPMD.UnusedFormalParameter) Deprecated dependencies */ public function __construct( - private readonly ChangeParentStockStatus $changeParentStockStatus + Configurable $configurableType, + StockItemCriteriaInterfaceFactory $criteriaInterfaceFactory, + StockItemRepositoryInterface $stockItemRepository, + StockConfigurationInterface $stockConfiguration, + ?ChangeParentStockStatus $changeParentStockStatus = null ) { + $this->changeParentStockStatus = $changeParentStockStatus + ?? ObjectManager::getInstance()->get(ChangeParentStockStatus::class); } /** From 5701e29e707baacaf33b4da0d3c915e3ea76bea5 Mon Sep 17 00:00:00 2001 From: simsComputing Date: Tue, 24 Jun 2025 12:51:36 +0200 Subject: [PATCH 14/15] Fix customer adresses with empty line --- app/code/Magento/Customer/Helper/Address.php | 2 +- .../Customer/Model/ResourceModel/Grid/Collection.php | 1 - app/code/Magento/Customer/Test/Unit/Helper/AddressTest.php | 1 + .../Magento/Customer/Api/AddressRepositoryTest.php | 4 ++-- .../Controller/Address/FormPost/CreateAddressTest.php | 4 ++-- .../Controller/Address/FormPost/UpdateAddressTest.php | 4 ++-- .../Magento/Customer/Model/Address/CreateAddressTest.php | 4 ++-- .../Magento/Customer/Model/Address/UpdateAddressTest.php | 2 +- .../Customer/Model/ResourceModel/AddressRepositoryTest.php | 6 +++--- .../Customer/Model/ResourceModel/Grid/CollectionTest.php | 4 +--- 10 files changed, 15 insertions(+), 17 deletions(-) diff --git a/app/code/Magento/Customer/Helper/Address.php b/app/code/Magento/Customer/Helper/Address.php index 88f3024c2dc7..3e828560c1a1 100644 --- a/app/code/Magento/Customer/Helper/Address.php +++ b/app/code/Magento/Customer/Helper/Address.php @@ -330,7 +330,7 @@ public function convertStreetLines($origStreets, $toCount) } } - return $lines; + return array_filter($lines); } /** diff --git a/app/code/Magento/Customer/Model/ResourceModel/Grid/Collection.php b/app/code/Magento/Customer/Model/ResourceModel/Grid/Collection.php index 2c271f90bfa1..10a6e8d96812 100644 --- a/app/code/Magento/Customer/Model/ResourceModel/Grid/Collection.php +++ b/app/code/Magento/Customer/Model/ResourceModel/Grid/Collection.php @@ -74,7 +74,6 @@ protected function _initSelect() { parent::_initSelect(); $this->joinRegionNameTable(); - return $this; } diff --git a/app/code/Magento/Customer/Test/Unit/Helper/AddressTest.php b/app/code/Magento/Customer/Test/Unit/Helper/AddressTest.php index 47021100f7a8..2648b0d83359 100644 --- a/app/code/Magento/Customer/Test/Unit/Helper/AddressTest.php +++ b/app/code/Magento/Customer/Test/Unit/Helper/AddressTest.php @@ -242,6 +242,7 @@ public static function getConvertStreetLinesDataProvider() return [ [['street1', 'street2', 'street3', 'street4'], 3, ['street1 street2', 'street3', 'street4']], [['street1', 'street2', 'street3', 'street4'], 2, ['street1 street2', 'street3 street4']], + [['street1', ''], 2, ['street1']] ]; } diff --git a/dev/tests/integration/testsuite/Magento/Customer/Api/AddressRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Customer/Api/AddressRepositoryTest.php index 826dfdc0772b..cc54f0a6a0ac 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Api/AddressRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Api/AddressRepositoryTest.php @@ -68,12 +68,12 @@ protected function setUp(): void ->setCustomerId('1') ->setPostcode('47676') ->setRegion($region) - ->setStreet(['Black str, 48', '']) + ->setStreet(['Black str, 48']) ->setCity('CityX') ->setTelephone('3234676') ->setFirstname('John') ->setLastname('Smith') - ->setRegionId('1'); + ->setRegionId(1); $this->_expectedAddresses = [$address, $address2]; } diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Address/FormPost/CreateAddressTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Address/FormPost/CreateAddressTest.php index d18a918b2f4e..559ccfcf9a13 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/Address/FormPost/CreateAddressTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Address/FormPost/CreateAddressTest.php @@ -220,7 +220,7 @@ public static function postDataForSuccessCreateAddressDataProvider(): array 'custom_region_name' => 'Alabama', AddressInterface::FIRSTNAME => 'John', AddressInterface::LASTNAME => 'Smith', - AddressInterface::STREET => ['Green str, 67', ''], + AddressInterface::STREET => ['Green str, 67'], AddressInterface::CITY => 'CityM', ], ], @@ -250,7 +250,7 @@ public static function postDataForSuccessCreateAddressDataProvider(): array ], 'required_field_street_as_array' => [ array_replace(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::STREET => ['', 'Green str, 67']]), - [AddressInterface::STREET => ['Green str, 67', '']], + [AddressInterface::STREET => ['Green str, 67']], ], 'field_company_name' => [ array_merge(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::COMPANY => 'My company']), diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Address/FormPost/UpdateAddressTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Address/FormPost/UpdateAddressTest.php index 0485d315a579..9e91e8792236 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/Address/FormPost/UpdateAddressTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Address/FormPost/UpdateAddressTest.php @@ -230,7 +230,7 @@ public static function postDataForSuccessUpdateAddressDataProvider(): array 'custom_region_name' => 'Arkansas', AddressInterface::FIRSTNAME => 'Foma', AddressInterface::LASTNAME => 'Kiniaev', - AddressInterface::STREET => ['Yellow str, 228', ''], + AddressInterface::STREET => ['Yellow str, 228'], AddressInterface::CITY => 'Mukachevo', ], ], @@ -260,7 +260,7 @@ public static function postDataForSuccessUpdateAddressDataProvider(): array ], 'required_field_street_as_array' => [ array_replace(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::STREET => ['', 'Green str, 67']]), - [AddressInterface::STREET => ['Green str, 67', '']], + [AddressInterface::STREET => ['Green str, 67']], ], 'field_company_name' => [ array_merge(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::COMPANY => 'My company']), diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/Address/CreateAddressTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/Address/CreateAddressTest.php index be9572bcaf42..67ffffb9e51c 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/Address/CreateAddressTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/Address/CreateAddressTest.php @@ -220,7 +220,7 @@ public static function createAddressesDataProvider(): array 'custom_region_name' => 'Alabama', AddressInterface::FIRSTNAME => 'John', AddressInterface::LASTNAME => 'Smith', - AddressInterface::STREET => ['Green str, 67', ''], + AddressInterface::STREET => ['Green str, 67'], AddressInterface::CITY => 'CityM', ], ], @@ -250,7 +250,7 @@ public static function createAddressesDataProvider(): array ], 'required_field_street_as_array' => [ array_replace(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::STREET => ['', 'Green str, 67']]), - [AddressInterface::STREET => ['Green str, 67', '']], + [AddressInterface::STREET => ['Green str, 67']], ], 'field_name_prefix' => [ array_merge(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::PREFIX => 'My prefix']), diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/Address/UpdateAddressTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/Address/UpdateAddressTest.php index 7cde6370c50a..2adf68d2cca4 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/Address/UpdateAddressTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/Address/UpdateAddressTest.php @@ -195,7 +195,7 @@ public static function updateAddressesDataProvider(): array ], 'required_field_street_as_array' => [ [AddressInterface::STREET => ['', 'Test str, 55']], - [AddressInterface::STREET => ['Test str, 55', '']], + [AddressInterface::STREET => ['Test str, 55']], ], 'required_field_city' => [ [AddressInterface::CITY => 'Test city'], diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/AddressRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/AddressRepositoryTest.php index f5eb7259d31d..2557931918ad 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/AddressRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/AddressRepositoryTest.php @@ -101,8 +101,8 @@ protected function setUp(): void ->setCustomerId('1') ->setPostcode('47676') ->setRegion($region) - ->setRegionId('1') - ->setStreet(['Black str, 48', '']) + ->setRegionId(1) + ->setStreet(['Black str, 48']) ->setCity('CityX') ->setTelephone('3234676') ->setFirstname('John') @@ -647,7 +647,7 @@ public function testUpdateWithAlphanumericZipCode(): void AddressInterface::SUFFIX => '_Suffix', AddressInterface::PREFIX => 'Prefix', AddressInterface::COMPANY => 'Company', - AddressInterface::STREET => ['Northgate Street, 39', ''], + AddressInterface::STREET => ['Northgate Street, 39'], AddressInterface::CITY => 'BICKTON', AddressInterface::COUNTRY_ID => 'GB', AddressInterface::REGION => $region, diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/Grid/CollectionTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/Grid/CollectionTest.php index 167a9a1edef1..c9ec2d35aef9 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/Grid/CollectionTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/Grid/CollectionTest.php @@ -54,11 +54,9 @@ public function testGetItemByIdForUpdateOnSchedule() $item = $this->targetObject->getItemById($newCustomer->getId()); $this->assertNotEmpty($item); $this->assertSame($newCustomer->getEmail(), $item->getEmail()); - $this->assertSame('test street' . PHP_EOL . ' test city Armed Forces Middle East 01001', $item->getBillingFull()); - + $this->assertSame('test street test city Armed Forces Middle East 01001', $item->getBillingFull()); /** set customer grid indexer on schedule' mode */ $indexer->setScheduled(true); - /** Verify after update */ $newCustomer->setEmail('customer_updated@example.com'); $this->customerRepository->save($newCustomer); From 168c5d474f677de7849890945c03fc09b62d75f3 Mon Sep 17 00:00:00 2001 From: simsComputing Date: Tue, 24 Jun 2025 13:03:10 +0200 Subject: [PATCH 15/15] Code review --- .../Downloadable/_files/quote_with_downloadable_product.php | 4 ++-- lib/internal/Magento/Framework/App/ProductMetadata.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Downloadable/_files/quote_with_downloadable_product.php b/dev/tests/integration/testsuite/Magento/Downloadable/_files/quote_with_downloadable_product.php index 576d5cfec634..dd6f2bca76f1 100644 --- a/dev/tests/integration/testsuite/Magento/Downloadable/_files/quote_with_downloadable_product.php +++ b/dev/tests/integration/testsuite/Magento/Downloadable/_files/quote_with_downloadable_product.php @@ -50,8 +50,8 @@ )->setIsMultiShipping( 0 )->setBillingAddress($billingAddress) - ->setShippingAddress($shippingAddress) - ->addProduct( +->setShippingAddress($shippingAddress) +->addProduct( // @phpstan-ignore argument.type $product, new \Magento\Framework\DataObject([ diff --git a/lib/internal/Magento/Framework/App/ProductMetadata.php b/lib/internal/Magento/Framework/App/ProductMetadata.php index 53e1bb16fad7..227f2c1fc311 100644 --- a/lib/internal/Magento/Framework/App/ProductMetadata.php +++ b/lib/internal/Magento/Framework/App/ProductMetadata.php @@ -25,7 +25,7 @@ class ProductMetadata implements ProductMetadataInterface, DistributionMetadataI /** * Magento product name */ - public const PRODUCT_NAME = 'Mage-OS'; + public const PRODUCT_NAME = 'Magento'; /** * Distribution product name