From cfcf77db921376b4a59ef532c9c19b971c322c18 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi Date: Sat, 3 Jan 2026 16:13:01 -0600 Subject: [PATCH 01/83] ACP2E-4349: [B2B] Purchase orders not auto-converting to sales order with ActiveMQ --- InventoryCatalog/Test/Api/DeleteProductTest.php | 3 --- InventoryCatalog/Test/Api/UpdateProductSkuTest.php | 3 --- InventoryCatalog/Test/Api/UpdateProductTypeTest.php | 3 --- .../Test/Api/DeleteProductTest.php | 3 --- .../Test/Api/UpdateProductSkuTest.php | 3 --- 5 files changed, 15 deletions(-) diff --git a/InventoryCatalog/Test/Api/DeleteProductTest.php b/InventoryCatalog/Test/Api/DeleteProductTest.php index 5ccbcd9e56e0..7b72b970b351 100644 --- a/InventoryCatalog/Test/Api/DeleteProductTest.php +++ b/InventoryCatalog/Test/Api/DeleteProductTest.php @@ -102,9 +102,6 @@ private function rejectMessages() 'inventory.source.items.cleanup', $this->defaultValueProvider->getConnection() ); - if ($this->defaultValueProvider->getConnection() === 'stomp') { - $queue->subscribeQueue(); - } while ($envelope = $queue->dequeue()) { $queue->reject($envelope, false); } diff --git a/InventoryCatalog/Test/Api/UpdateProductSkuTest.php b/InventoryCatalog/Test/Api/UpdateProductSkuTest.php index c518124c89f2..a9f9169fee04 100644 --- a/InventoryCatalog/Test/Api/UpdateProductSkuTest.php +++ b/InventoryCatalog/Test/Api/UpdateProductSkuTest.php @@ -123,9 +123,6 @@ private function rejectMessages() 'inventory.source.items.cleanup', $this->defaultValueProvider->getConnection() ); - if ($this->defaultValueProvider->getConnection() === 'stomp') { - $queue->subscribeQueue(); - } while ($envelope = $queue->dequeue()) { $queue->reject($envelope, false); } diff --git a/InventoryCatalog/Test/Api/UpdateProductTypeTest.php b/InventoryCatalog/Test/Api/UpdateProductTypeTest.php index 8a83308e270d..e932174d0b7d 100644 --- a/InventoryCatalog/Test/Api/UpdateProductTypeTest.php +++ b/InventoryCatalog/Test/Api/UpdateProductTypeTest.php @@ -104,9 +104,6 @@ private function rejectMessages() 'inventory.source.items.cleanup', $this->defaultValueProvider->getConnection() ); - if ($this->defaultValueProvider->getConnection() === 'stomp') { - $queue->subscribeQueue(); - } while ($envelope = $queue->dequeue()) { $queue->reject($envelope, false); } diff --git a/InventoryLowQuantityNotification/Test/Api/DeleteProductTest.php b/InventoryLowQuantityNotification/Test/Api/DeleteProductTest.php index b353dcfc059c..3a819c86110c 100644 --- a/InventoryLowQuantityNotification/Test/Api/DeleteProductTest.php +++ b/InventoryLowQuantityNotification/Test/Api/DeleteProductTest.php @@ -103,9 +103,6 @@ private function rejectMessages() 'inventory.source.items.cleanup', $this->defaultValueProvider->getConnection() ); - if ($this->defaultValueProvider->getConnection() === 'stomp') { - $queue->subscribeQueue(); - } while ($envelope = $queue->dequeue()) { $queue->reject($envelope, false); } diff --git a/InventoryLowQuantityNotification/Test/Api/UpdateProductSkuTest.php b/InventoryLowQuantityNotification/Test/Api/UpdateProductSkuTest.php index 8722a48ccb43..22c7deff84d8 100644 --- a/InventoryLowQuantityNotification/Test/Api/UpdateProductSkuTest.php +++ b/InventoryLowQuantityNotification/Test/Api/UpdateProductSkuTest.php @@ -124,9 +124,6 @@ private function rejectMessages() 'inventory.source.items.cleanup', $this->defaultValueProvider->getConnection() ); - if ($this->defaultValueProvider->getConnection() === 'stomp') { - $queue->subscribeQueue(); - } while ($envelope = $queue->dequeue()) { $queue->reject($envelope, false); } From db6842d1b3642b1ddc03a4ce6213406e6b50dda4 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi Date: Tue, 10 Mar 2026 13:46:46 -0500 Subject: [PATCH 02/83] ACP2E-4349: [B2B] Purchase orders not auto-converting to sales order with ActiveMQ --- InventoryCatalog/etc/queue_publisher.xml | 10 +++++----- InventoryIndexer/etc/queue_publisher.xml | 6 +++--- InventorySales/etc/queue_publisher.xml | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/InventoryCatalog/etc/queue_publisher.xml b/InventoryCatalog/etc/queue_publisher.xml index 745e96ad2b3b..9fd8b24d0e0a 100644 --- a/InventoryCatalog/etc/queue_publisher.xml +++ b/InventoryCatalog/etc/queue_publisher.xml @@ -6,9 +6,9 @@ */ --> - - - - - + + + + + diff --git a/InventoryIndexer/etc/queue_publisher.xml b/InventoryIndexer/etc/queue_publisher.xml index 77b3cae270f7..91b62731608e 100644 --- a/InventoryIndexer/etc/queue_publisher.xml +++ b/InventoryIndexer/etc/queue_publisher.xml @@ -6,7 +6,7 @@ */ --> - - - + + + diff --git a/InventorySales/etc/queue_publisher.xml b/InventorySales/etc/queue_publisher.xml index 23f92078b65e..6b90a78774c6 100644 --- a/InventorySales/etc/queue_publisher.xml +++ b/InventorySales/etc/queue_publisher.xml @@ -6,6 +6,6 @@ */ --> - - + + From e6031c0b121e8b5f2dc5cd109565f4d54d7dae84 Mon Sep 17 00:00:00 2001 From: flowers Date: Thu, 26 Mar 2026 13:06:40 -0500 Subject: [PATCH 03/83] ACP2E-4765: In-store pickup order placement fails after Directory subdivision name is updated via data patch --- .../ExtractPickupLocationAddressData.php | 18 +++- .../ExtractPickupLocationAddressDataTest.php | 92 ++++++++++++++++++- 2 files changed, 107 insertions(+), 3 deletions(-) diff --git a/InventoryInStorePickup/Model/ExtractPickupLocationAddressData.php b/InventoryInStorePickup/Model/ExtractPickupLocationAddressData.php index 95e15d3d96d4..2e30203abc34 100644 --- a/InventoryInStorePickup/Model/ExtractPickupLocationAddressData.php +++ b/InventoryInStorePickup/Model/ExtractPickupLocationAddressData.php @@ -8,6 +8,7 @@ namespace Magento\InventoryInStorePickup\Model; use Magento\Directory\Model\RegionFactory; +use Magento\Directory\Model\ResourceModel\Region as RegionResource; use Magento\Framework\App\ObjectManager; use Magento\Framework\DataObject\Copy; use Magento\InventoryApi\Api\Data\SourceInterface; @@ -28,6 +29,11 @@ class ExtractPickupLocationAddressData */ private $regionFactory; + /** + * @var RegionResource + */ + private $regionResource; + /** * @var array */ @@ -36,14 +42,18 @@ class ExtractPickupLocationAddressData /** * @param Copy $copyService * @param RegionFactory|null $regionFactory + * @param RegionResource|null $regionResource */ public function __construct( Copy $copyService, - ?RegionFactory $regionFactory = null + ?RegionFactory $regionFactory = null, + ?RegionResource $regionResource = null ) { $this->objectCopyService = $copyService; $this->regionFactory = $regionFactory ?: ObjectManager::getInstance()->get(RegionFactory::class); + $this->regionResource = $regionResource ?: + ObjectManager::getInstance()->get(RegionResource::class); } /** @@ -78,7 +88,11 @@ private function retrieveRegion(PickupLocationInterface $pickupLocation, array $ if (!isset($this->regions[$cacheKey])) { $region = $this->regionFactory->create(); - $region->loadByName($pickupLocation->getRegion(), $pickupLocation->getCountryId()); + if ($pickupLocation->getRegionId()) { + $this->regionResource->load($region, $pickupLocation->getRegionId()); + } else { + $region->loadByName($pickupLocation->getRegion(), $pickupLocation->getCountryId()); + } $this->regions[$cacheKey] = $region->getName() ?: $pickupLocation->getRegion(); } diff --git a/InventoryInStorePickup/Test/Unit/Model/ExtractPickupLocationAddressDataTest.php b/InventoryInStorePickup/Test/Unit/Model/ExtractPickupLocationAddressDataTest.php index 50a37b56b2c5..f47c48ac9ca8 100644 --- a/InventoryInStorePickup/Test/Unit/Model/ExtractPickupLocationAddressDataTest.php +++ b/InventoryInStorePickup/Test/Unit/Model/ExtractPickupLocationAddressDataTest.php @@ -9,6 +9,7 @@ use Magento\Directory\Model\Region; use Magento\Directory\Model\RegionFactory; +use Magento\Directory\Model\ResourceModel\Region as RegionResource; use Magento\Framework\DataObject\Copy; use Magento\Framework\TestFramework\Unit\Helper\MockCreationTrait; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; @@ -40,6 +41,11 @@ class ExtractPickupLocationAddressDataTest extends TestCase */ private $regionMock; + /** + * @var RegionResource|MockObject + */ + private $regionResourceMock; + /** * @inheritDoc */ @@ -49,10 +55,16 @@ protected function setUp(): void $this->regionMock = $this->createPartialMockWithReflection( Region::class, - ['getCode', 'load', 'getName', 'loadByName'] + ['getCode', 'getName', 'loadByName'] ); $this->regionMock->method('loadByName')->willReturnSelf(); + $this->regionResourceMock = $this->getMockBuilder(RegionResource::class) + ->disableOriginalConstructor() + ->onlyMethods(['load']) + ->getMock(); + $this->regionResourceMock->method('load')->willReturnSelf(); + $this->objectCopyServiceMock = $this->getMockBuilder(Copy::class) ->disableOriginalConstructor() ->onlyMethods(['getDataFromFieldset']) @@ -71,6 +83,7 @@ protected function setUp(): void [ 'objectCopyService' => $this->objectCopyServiceMock, 'regionFactory' => $regionFactoryMock, + 'regionResource' => $this->regionResourceMock, ] ); } @@ -120,4 +133,81 @@ public static function executeDataProvider(): array ], ]; } + + /** + * When region_id is set, region is loaded via ResourceModel by ID and loadByName is not called. + */ + public function testExecuteLoadsRegionByIdWhenRegionIdIsSet(): void + { + $this->objectCopyServiceMock->method('getDataFromFieldset') + ->willReturn(['region' => 'stale_name']); + $this->regionMock->method('getName')->willReturn('current_name'); + + $pickupLocation = $this->createMock(PickupLocation::class); + $pickupLocation->method('getCountryId')->willReturn('CH'); + $pickupLocation->method('getRegionId')->willReturn(42); + $pickupLocation->method('getRegion')->willReturn('stale_name'); + + $this->regionResourceMock->expects($this->once()) + ->method('load') + ->with($this->regionMock, 42); + $this->regionMock->expects($this->never())->method('loadByName'); + + $result = $this->model->execute($pickupLocation); + + $this->assertEquals(['region' => 'current_name'], $result); + } + + /** + * When region_id is null, region is resolved via loadByName and ResourceModel load is not called. + */ + public function testExecuteFallsBackToLoadByNameWhenRegionIdIsNull(): void + { + $this->objectCopyServiceMock->method('getDataFromFieldset') + ->willReturn(['region' => 'some_region']); + $this->regionMock->method('getName')->willReturn('some_region'); + + $pickupLocation = $this->createMock(PickupLocation::class); + $pickupLocation->method('getCountryId')->willReturn('US'); + $pickupLocation->method('getRegionId')->willReturn(null); + $pickupLocation->method('getRegion')->willReturn('some_region'); + + $this->regionResourceMock->expects($this->never())->method('load'); + $this->regionMock->expects($this->once()) + ->method('loadByName') + ->with('some_region', 'US') + ->willReturnSelf(); + + $result = $this->model->execute($pickupLocation); + + $this->assertEquals(['region' => 'some_region'], $result); + } + + /** + * After a Directory data patch renames a subdivision, the current name is resolved + * live from Directory by region_id, not from the stale string in inventory_source.region. + */ + public function testExecuteReturnsCurrentRegionNameAfterDirectoryRename(): void + { + // inventory_source.region still holds the old name from before the data patch + $this->objectCopyServiceMock->method('getDataFromFieldset') + ->willReturn(['region' => 'Friburg']); + + // ResourceModel returns the updated name after the rename + $this->regionMock->method('getName')->willReturn('Renamed Friburg'); + + $pickupLocation = $this->createMock(PickupLocation::class); + $pickupLocation->method('getCountryId')->willReturn('CH'); + $pickupLocation->method('getRegionId')->willReturn(42); + $pickupLocation->method('getRegion')->willReturn('Friburg'); + + $this->regionResourceMock->expects($this->once()) + ->method('load') + ->with($this->regionMock, 42); + + $result = $this->model->execute($pickupLocation); + + // Must reflect the live Directory name, not the stale inventory_source value + $this->assertEquals(['region' => 'Renamed Friburg'], $result); + } } From 578b097ba9d37e25c874b59f6972d84e591b107c Mon Sep 17 00:00:00 2001 From: Olga Moyseyenko Date: Mon, 30 Mar 2026 23:27:46 -0500 Subject: [PATCH 04/83] ACP2E-4741: [CLOUD] Gift card and related not sellable WF-1688 --- .../Indexer/SiblingProductsProvider.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/InventoryGroupedProductIndexer/Indexer/SiblingProductsProvider.php b/InventoryGroupedProductIndexer/Indexer/SiblingProductsProvider.php index f88abb479d93..06c8aae21b7c 100644 --- a/InventoryGroupedProductIndexer/Indexer/SiblingProductsProvider.php +++ b/InventoryGroupedProductIndexer/Indexer/SiblingProductsProvider.php @@ -40,6 +40,11 @@ public function getSkus(array $skus): array ['sibling_link' => $this->resourceConnection->getTableName('catalog_product_link')], 'sibling_link.linked_product_id = child_product_entity.' . $metadata->getIdentifierField(), [] + )->joinInner( + ['link_type' => $this->resourceConnection->getTableName('catalog_product_link_type')], + 'link_type.link_type_id = sibling_link.link_type_id' + . ' AND link_type.code = ' . $connection->quote('super'), + [] )->joinInner( ['sibling_product_entity' => $this->resourceConnection->getTableName('catalog_product_entity')], 'sibling_product_entity.' . $metadata->getLinkField() . ' = sibling_link.product_id', From 10bb41b5b27756c923d3c4ea76d7ddb6f526a299 Mon Sep 17 00:00:00 2001 From: Olga Moyseyenko Date: Fri, 3 Apr 2026 12:32:51 -0500 Subject: [PATCH 05/83] ACP2E-4741: [CLOUD] Gift card and related not sellable WF-1688 --- .../Indexer/SiblingProductsProvider.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/InventoryGroupedProductIndexer/Indexer/SiblingProductsProvider.php b/InventoryGroupedProductIndexer/Indexer/SiblingProductsProvider.php index 06c8aae21b7c..378c1d03f93f 100644 --- a/InventoryGroupedProductIndexer/Indexer/SiblingProductsProvider.php +++ b/InventoryGroupedProductIndexer/Indexer/SiblingProductsProvider.php @@ -8,6 +8,7 @@ namespace Magento\InventoryGroupedProductIndexer\Indexer; use Magento\Catalog\Api\Data\ProductInterface; +use Magento\GroupedProduct\Model\ResourceModel\Product\Link; use Magento\Framework\App\ResourceConnection; use Magento\Framework\EntityManager\MetadataPool; use Magento\InventoryIndexer\Indexer\SiblingProductsProviderInterface; @@ -29,6 +30,7 @@ public function __construct( */ public function getSkus(array $skus): array { + $linkTypeId = Link::LINK_TYPE_GROUPED; $metadata = $this->metadataPool->getMetadata(ProductInterface::class); $connection = $this->resourceConnection->getConnection(); @@ -38,12 +40,8 @@ public function getSkus(array $skus): array [] )->joinInner( ['sibling_link' => $this->resourceConnection->getTableName('catalog_product_link')], - 'sibling_link.linked_product_id = child_product_entity.' . $metadata->getIdentifierField(), - [] - )->joinInner( - ['link_type' => $this->resourceConnection->getTableName('catalog_product_link_type')], - 'link_type.link_type_id = sibling_link.link_type_id' - . ' AND link_type.code = ' . $connection->quote('super'), + 'sibling_link.linked_product_id = child_product_entity.' . $metadata->getIdentifierField() + . ' AND sibling_link.link_type_id = ' . $linkTypeId, [] )->joinInner( ['sibling_product_entity' => $this->resourceConnection->getTableName('catalog_product_entity')], From 4483a0674b75fe14a62dbb94660f5ffcacc925fb Mon Sep 17 00:00:00 2001 From: Alexandra Zota Date: Mon, 6 Apr 2026 16:23:39 +0300 Subject: [PATCH 06/83] ACP2E-4805: Configurable Product's performance impact on checkout (totals-information, estimate-shipping-modules) --- .../IsConfigurableProductChildrenSalable.php | 83 +++++- ...ConfigurableProductChildrenSalableTest.php | 260 ++++++++++++++++++ 2 files changed, 332 insertions(+), 11 deletions(-) create mode 100644 InventoryConfigurableProduct/Test/Unit/Model/IsProductSalableCondition/IsConfigurableProductChildrenSalableTest.php diff --git a/InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductChildrenSalable.php b/InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductChildrenSalable.php index 5d08fdd76927..b2c6f557a64e 100644 --- a/InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductChildrenSalable.php +++ b/InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductChildrenSalable.php @@ -8,8 +8,12 @@ namespace Magento\InventoryConfigurableProduct\Model\IsProductSalableCondition; use Magento\ConfigurableProduct\Model\Product\Type\Configurable; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\App\ResourceConnection; use Magento\InventoryCatalogApi\Model\GetProductIdsBySkusInterface; use Magento\InventoryCatalogApi\Model\GetSkusByProductIdsInterface; +use Magento\InventoryIndexer\Indexer\IndexStructure; +use Magento\InventoryIndexer\Model\StockIndexTableNameResolverInterface; use Magento\InventorySalesApi\Api\AreProductsSalableInterface; /** @@ -37,22 +41,40 @@ class IsConfigurableProductChildrenSalable */ private $getSkusByProductIds; + /** + * @var ResourceConnection + */ + private $resource; + + /** + * @var StockIndexTableNameResolverInterface + */ + private $stockIndexTableNameResolver; + /** * @param Configurable $configurable * @param AreProductsSalableInterface $areProductsSalable * @param GetProductIdsBySkusInterface $getProductIdsBySkus * @param GetSkusByProductIdsInterface $getSkusByProductIds + * @param ResourceConnection|null $resource + * @param StockIndexTableNameResolverInterface|null $stockIndexTableNameResolver */ public function __construct( Configurable $configurable, AreProductsSalableInterface $areProductsSalable, GetProductIdsBySkusInterface $getProductIdsBySkus, - GetSkusByProductIdsInterface $getSkusByProductIds + GetSkusByProductIdsInterface $getSkusByProductIds, + ?ResourceConnection $resource = null, + ?StockIndexTableNameResolverInterface $stockIndexTableNameResolver = null ) { $this->configurable = $configurable; $this->areProductsSalable = $areProductsSalable; $this->getProductIdsBySkus = $getProductIdsBySkus; $this->getSkusByProductIds = $getSkusByProductIds; + $this->resource = $resource + ?: ObjectManager::getInstance()->get(ResourceConnection::class); + $this->stockIndexTableNameResolver = $stockIndexTableNameResolver + ?: ObjectManager::getInstance()->get(StockIndexTableNameResolverInterface::class); } /** @@ -69,20 +91,59 @@ public function __construct( */ public function execute(string $sku, int $stockId): bool { - $isSalable = false; $productId = $this->getProductIdsBySkus->execute([$sku])[$sku]; $ids = $this->configurable->getChildrenIds($productId); - $childrenSkus = $this->getSkusByProductIds->execute($ids[0]); - // check associated products salability one by one rather in batch for performance reason - foreach ($childrenSkus as $childSku) { - $results = $this->areProductsSalable->execute([$childSku], $stockId); - $result = reset($results); - if ($result && $result->isSalable()) { - $isSalable = true; - break; + $childrenIds = $ids[0] ?? []; + + if (empty($childrenIds)) { + return false; + } + + $childrenSkus = $this->getSkusByProductIds->execute($childrenIds); + + if (empty($childrenSkus)) { + return false; + } + + $candidateSkus = $this->getSalableCandidatesFromIndex($childrenSkus, $stockId); + + if (empty($candidateSkus)) { + return false; + } + + $results = $this->areProductsSalable->execute($candidateSkus, $stockId); + foreach ($results as $result) { + if ($result->isSalable()) { + return true; } } - return $isSalable; + return false; + } + + /** + * Pre-filter children using the stock index to find candidates marked as salable. + * + * The stock index table (inventory_stock_{id}) aggregates source item data per stock, + * accounting for multi-source inventory assignments. This single query eliminates + * iterating through all children individually. The returned candidates are then + * validated through the full salability condition chain via areProductsSalable. + * + * @param array $skus + * @param int $stockId + * @return array + */ + private function getSalableCandidatesFromIndex(array $skus, int $stockId): array + { + $connection = $this->resource->getConnection(); + $select = $connection->select() + ->from( + $this->stockIndexTableNameResolver->execute($stockId), + [IndexStructure::SKU] + ) + ->where(IndexStructure::SKU . ' IN (?)', array_values($skus)) + ->where(IndexStructure::IS_SALABLE . ' = ?', 1); + + return $connection->fetchCol($select); } } diff --git a/InventoryConfigurableProduct/Test/Unit/Model/IsProductSalableCondition/IsConfigurableProductChildrenSalableTest.php b/InventoryConfigurableProduct/Test/Unit/Model/IsProductSalableCondition/IsConfigurableProductChildrenSalableTest.php new file mode 100644 index 000000000000..da7e143c8067 --- /dev/null +++ b/InventoryConfigurableProduct/Test/Unit/Model/IsProductSalableCondition/IsConfigurableProductChildrenSalableTest.php @@ -0,0 +1,260 @@ +configurableMock = $this->createMock(Configurable::class); + $this->areProductsSalableMock = $this->createMock(AreProductsSalableInterface::class); + $this->getProductIdsBySkusMock = $this->createMock(GetProductIdsBySkusInterface::class); + $this->getSkusByProductIdsMock = $this->createMock(GetSkusByProductIdsInterface::class); + $this->resourceMock = $this->createMock(ResourceConnection::class); + $this->stockIndexTableNameResolverMock = $this->createMock(StockIndexTableNameResolverInterface::class); + $this->connectionMock = $this->createMock(AdapterInterface::class); + $this->selectMock = $this->createMock(Select::class); + + $this->resourceMock->method('getConnection')->willReturn($this->connectionMock); + $this->connectionMock->method('select')->willReturn($this->selectMock); + $this->selectMock->method('from')->willReturnSelf(); + $this->selectMock->method('where')->willReturnSelf(); + + $this->model = new IsConfigurableProductChildrenSalable( + $this->configurableMock, + $this->areProductsSalableMock, + $this->getProductIdsBySkusMock, + $this->getSkusByProductIdsMock, + $this->resourceMock, + $this->stockIndexTableNameResolverMock + ); + } + + public function testReturnsFalseWhenNoChildren(): void + { + $this->setupConfigurableProduct('configurable-sku', 100, []); + + $result = $this->model->execute('configurable-sku', 1); + + self::assertFalse($result); + } + + public function testReturnsFalseWhenNoChildrenSkus(): void + { + $this->setupConfigurableProduct('configurable-sku', 100, [10 => 10, 20 => 20]); + $this->getSkusByProductIdsMock->method('execute') + ->with([10 => 10, 20 => 20]) + ->willReturn([]); + + $result = $this->model->execute('configurable-sku', 1); + + self::assertFalse($result); + } + + public function testReturnsFalseWhenNoSalableCandidatesInIndex(): void + { + $this->setupConfigurableProduct('configurable-sku', 100, [10 => 10, 20 => 20]); + $this->getSkusByProductIdsMock->method('execute') + ->willReturn([10 => 'simple_10', 20 => 'simple_20']); + + $this->stockIndexTableNameResolverMock->method('execute') + ->with(1) + ->willReturn('inventory_stock_1'); + $this->connectionMock->method('fetchCol') + ->willReturn([]); + + $this->areProductsSalableMock->expects($this->never())->method('execute'); + + $result = $this->model->execute('configurable-sku', 1); + + self::assertFalse($result); + } + + public function testReturnsTrueWhenCandidateConfirmedSalable(): void + { + $this->setupConfigurableProduct('configurable-sku', 100, [10 => 10, 20 => 20]); + $this->getSkusByProductIdsMock->method('execute') + ->willReturn([10 => 'simple_10', 20 => 'simple_20']); + + $this->stockIndexTableNameResolverMock->method('execute') + ->with(5) + ->willReturn('inventory_stock_5'); + $this->connectionMock->method('fetchCol') + ->willReturn(['simple_20']); + + $salableResult = $this->createSalableResult('simple_20', true); + $this->areProductsSalableMock->expects($this->once()) + ->method('execute') + ->with(['simple_20'], 5) + ->willReturn([$salableResult]); + + $result = $this->model->execute('configurable-sku', 5); + + self::assertTrue($result); + } + + public function testReturnsFalseWhenCandidateNotConfirmedSalable(): void + { + $this->setupConfigurableProduct('configurable-sku', 100, [10 => 10, 20 => 20]); + $this->getSkusByProductIdsMock->method('execute') + ->willReturn([10 => 'simple_10', 20 => 'simple_20']); + + $this->stockIndexTableNameResolverMock->method('execute') + ->willReturn('inventory_stock_1'); + $this->connectionMock->method('fetchCol') + ->willReturn(['simple_10', 'simple_20']); + + $result1 = $this->createSalableResult('simple_10', false); + $result2 = $this->createSalableResult('simple_20', false); + $this->areProductsSalableMock->expects($this->once()) + ->method('execute') + ->with(['simple_10', 'simple_20'], 1) + ->willReturn([$result1, $result2]); + + $result = $this->model->execute('configurable-sku', 1); + + self::assertFalse($result); + } + + public function testOnlySalableCandidatesPassedToAreProductsSalable(): void + { + $childIds = []; + $childSkus = []; + for ($i = 1; $i <= 100; $i++) { + $childIds[$i] = $i; + $childSkus[$i] = 'child_' . $i; + } + + $this->setupConfigurableProduct('configurable-sku', 500, $childIds); + $this->getSkusByProductIdsMock->method('execute') + ->willReturn($childSkus); + + $this->stockIndexTableNameResolverMock->method('execute') + ->willReturn('inventory_stock_1'); + // Only 2 out of 100 are salable in the index + $this->connectionMock->method('fetchCol') + ->willReturn(['child_50', 'child_75']); + + $result1 = $this->createSalableResult('child_50', true); + $result2 = $this->createSalableResult('child_75', true); + $this->areProductsSalableMock->expects($this->once()) + ->method('execute') + ->with(['child_50', 'child_75'], 1) + ->willReturn([$result1, $result2]); + + $result = $this->model->execute('configurable-sku', 1); + + self::assertTrue($result); + } + + public function testWorksWithNonDefaultStock(): void + { + $this->setupConfigurableProduct('configurable-sku', 100, [10 => 10]); + $this->getSkusByProductIdsMock->method('execute') + ->willReturn([10 => 'simple_10']); + + $this->stockIndexTableNameResolverMock->expects($this->once()) + ->method('execute') + ->with(20) + ->willReturn('inventory_stock_20'); + $this->connectionMock->method('fetchCol') + ->willReturn(['simple_10']); + + $salableResult = $this->createSalableResult('simple_10', true); + $this->areProductsSalableMock->expects($this->once()) + ->method('execute') + ->with(['simple_10'], 20) + ->willReturn([$salableResult]); + + $result = $this->model->execute('configurable-sku', 20); + + self::assertTrue($result); + } + + /** + * Set up common mocks for configurable product resolution + */ + private function setupConfigurableProduct(string $sku, int $productId, array $childrenIds): void + { + $this->getProductIdsBySkusMock->method('execute') + ->with([$sku]) + ->willReturn([$sku => $productId]); + $this->configurableMock->method('getChildrenIds') + ->with($productId) + ->willReturn([0 => $childrenIds]); + } + + /** + * Create a mock salable result + */ + private function createSalableResult(string $sku, bool $isSalable): IsProductSalableResultInterface + { + $mock = $this->createMock(IsProductSalableResultInterface::class); + $mock->method('getSku')->willReturn($sku); + $mock->method('isSalable')->willReturn($isSalable); + return $mock; + } +} From 67e429143dfdb6d4b2247584e407a5a9531d7138 Mon Sep 17 00:00:00 2001 From: Alexandra Zota Date: Mon, 6 Apr 2026 16:57:48 +0300 Subject: [PATCH 07/83] ACP2E-4805: Configurable Product's performance impact on checkout (totals-information, estimate-shipping-modules) --- .../IsConfigurableProductChildrenSalable.php | 35 +++++++----- ...ConfigurableProductChildrenSalableTest.php | 57 ++++++++++++++++--- 2 files changed, 70 insertions(+), 22 deletions(-) diff --git a/InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductChildrenSalable.php b/InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductChildrenSalable.php index b2c6f557a64e..4116a6db5215 100644 --- a/InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductChildrenSalable.php +++ b/InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductChildrenSalable.php @@ -111,9 +111,10 @@ public function execute(string $sku, int $stockId): bool return false; } - $results = $this->areProductsSalable->execute($candidateSkus, $stockId); - foreach ($results as $result) { - if ($result->isSalable()) { + foreach ($candidateSkus as $candidateSku) { + $results = $this->areProductsSalable->execute([$candidateSku], $stockId); + $result = reset($results); + if ($result && $result->isSalable()) { return true; } } @@ -129,21 +130,25 @@ public function execute(string $sku, int $stockId): bool * iterating through all children individually. The returned candidates are then * validated through the full salability condition chain via areProductsSalable. * - * @param array $skus + * @param string[] $skus * @param int $stockId - * @return array + * @return string[] */ private function getSalableCandidatesFromIndex(array $skus, int $stockId): array { - $connection = $this->resource->getConnection(); - $select = $connection->select() - ->from( - $this->stockIndexTableNameResolver->execute($stockId), - [IndexStructure::SKU] - ) - ->where(IndexStructure::SKU . ' IN (?)', array_values($skus)) - ->where(IndexStructure::IS_SALABLE . ' = ?', 1); - - return $connection->fetchCol($select); + try { + $connection = $this->resource->getConnection(); + $select = $connection->select() + ->from( + $this->stockIndexTableNameResolver->execute($stockId), + [IndexStructure::SKU] + ) + ->where(IndexStructure::SKU . ' IN (?)', array_values($skus)) + ->where(IndexStructure::IS_SALABLE . ' = ?', 1); + + return $connection->fetchCol($select); + } catch (\Exception $e) { + return []; + } } } diff --git a/InventoryConfigurableProduct/Test/Unit/Model/IsProductSalableCondition/IsConfigurableProductChildrenSalableTest.php b/InventoryConfigurableProduct/Test/Unit/Model/IsProductSalableCondition/IsConfigurableProductChildrenSalableTest.php index da7e143c8067..880e1c775ce0 100644 --- a/InventoryConfigurableProduct/Test/Unit/Model/IsProductSalableCondition/IsConfigurableProductChildrenSalableTest.php +++ b/InventoryConfigurableProduct/Test/Unit/Model/IsProductSalableCondition/IsConfigurableProductChildrenSalableTest.php @@ -169,16 +169,41 @@ public function testReturnsFalseWhenCandidateNotConfirmedSalable(): void $result1 = $this->createSalableResult('simple_10', false); $result2 = $this->createSalableResult('simple_20', false); - $this->areProductsSalableMock->expects($this->once()) + $this->areProductsSalableMock->expects($this->exactly(2)) ->method('execute') - ->with(['simple_10', 'simple_20'], 1) - ->willReturn([$result1, $result2]); + ->willReturnMap([ + [['simple_10'], 1, [$result1]], + [['simple_20'], 1, [$result2]], + ]); $result = $this->model->execute('configurable-sku', 1); self::assertFalse($result); } + public function testEarlyExitOnFirstConfirmedSalable(): void + { + $this->setupConfigurableProduct('configurable-sku', 100, [10 => 10, 20 => 20]); + $this->getSkusByProductIdsMock->method('execute') + ->willReturn([10 => 'simple_10', 20 => 'simple_20']); + + $this->stockIndexTableNameResolverMock->method('execute') + ->willReturn('inventory_stock_1'); + $this->connectionMock->method('fetchCol') + ->willReturn(['simple_10', 'simple_20']); + + $salableResult = $this->createSalableResult('simple_10', true); + // Only called once — early exit after first salable candidate confirmed + $this->areProductsSalableMock->expects($this->once()) + ->method('execute') + ->with(['simple_10'], 1) + ->willReturn([$salableResult]); + + $result = $this->model->execute('configurable-sku', 1); + + self::assertTrue($result); + } + public function testOnlySalableCandidatesPassedToAreProductsSalable(): void { $childIds = []; @@ -198,12 +223,12 @@ public function testOnlySalableCandidatesPassedToAreProductsSalable(): void $this->connectionMock->method('fetchCol') ->willReturn(['child_50', 'child_75']); - $result1 = $this->createSalableResult('child_50', true); - $result2 = $this->createSalableResult('child_75', true); + $salableResult = $this->createSalableResult('child_50', true); + // Early exit: only first candidate checked, second never reached $this->areProductsSalableMock->expects($this->once()) ->method('execute') - ->with(['child_50', 'child_75'], 1) - ->willReturn([$result1, $result2]); + ->with(['child_50'], 1) + ->willReturn([$salableResult]); $result = $this->model->execute('configurable-sku', 1); @@ -234,6 +259,24 @@ public function testWorksWithNonDefaultStock(): void self::assertTrue($result); } + public function testGracefulDegradationOnIndexQueryFailure(): void + { + $this->setupConfigurableProduct('configurable-sku', 100, [10 => 10]); + $this->getSkusByProductIdsMock->method('execute') + ->willReturn([10 => 'simple_10']); + + $this->stockIndexTableNameResolverMock->method('execute') + ->willReturn('inventory_stock_1'); + $this->connectionMock->method('fetchCol') + ->willThrowException(new \Exception('Table does not exist')); + + $this->areProductsSalableMock->expects($this->never())->method('execute'); + + $result = $this->model->execute('configurable-sku', 1); + + self::assertFalse($result); + } + /** * Set up common mocks for configurable product resolution */ From 0dbdd64c6a1a3a3fc93fb6d0c51c664e48fdf07b Mon Sep 17 00:00:00 2001 From: Alexandra Zota Date: Tue, 7 Apr 2026 11:01:38 +0300 Subject: [PATCH 08/83] ACP2E-4805: Configurable Product's performance impact on checkout (totals-information, estimate-shipping-modules) --- ...ConfigurableProductChildrenSalableTest.php | 303 ------------------ InventoryConfigurableProduct/etc/di.xml | 3 +- 2 files changed, 1 insertion(+), 305 deletions(-) delete mode 100644 InventoryConfigurableProduct/Test/Unit/Model/IsProductSalableCondition/IsConfigurableProductChildrenSalableTest.php diff --git a/InventoryConfigurableProduct/Test/Unit/Model/IsProductSalableCondition/IsConfigurableProductChildrenSalableTest.php b/InventoryConfigurableProduct/Test/Unit/Model/IsProductSalableCondition/IsConfigurableProductChildrenSalableTest.php deleted file mode 100644 index 880e1c775ce0..000000000000 --- a/InventoryConfigurableProduct/Test/Unit/Model/IsProductSalableCondition/IsConfigurableProductChildrenSalableTest.php +++ /dev/null @@ -1,303 +0,0 @@ -configurableMock = $this->createMock(Configurable::class); - $this->areProductsSalableMock = $this->createMock(AreProductsSalableInterface::class); - $this->getProductIdsBySkusMock = $this->createMock(GetProductIdsBySkusInterface::class); - $this->getSkusByProductIdsMock = $this->createMock(GetSkusByProductIdsInterface::class); - $this->resourceMock = $this->createMock(ResourceConnection::class); - $this->stockIndexTableNameResolverMock = $this->createMock(StockIndexTableNameResolverInterface::class); - $this->connectionMock = $this->createMock(AdapterInterface::class); - $this->selectMock = $this->createMock(Select::class); - - $this->resourceMock->method('getConnection')->willReturn($this->connectionMock); - $this->connectionMock->method('select')->willReturn($this->selectMock); - $this->selectMock->method('from')->willReturnSelf(); - $this->selectMock->method('where')->willReturnSelf(); - - $this->model = new IsConfigurableProductChildrenSalable( - $this->configurableMock, - $this->areProductsSalableMock, - $this->getProductIdsBySkusMock, - $this->getSkusByProductIdsMock, - $this->resourceMock, - $this->stockIndexTableNameResolverMock - ); - } - - public function testReturnsFalseWhenNoChildren(): void - { - $this->setupConfigurableProduct('configurable-sku', 100, []); - - $result = $this->model->execute('configurable-sku', 1); - - self::assertFalse($result); - } - - public function testReturnsFalseWhenNoChildrenSkus(): void - { - $this->setupConfigurableProduct('configurable-sku', 100, [10 => 10, 20 => 20]); - $this->getSkusByProductIdsMock->method('execute') - ->with([10 => 10, 20 => 20]) - ->willReturn([]); - - $result = $this->model->execute('configurable-sku', 1); - - self::assertFalse($result); - } - - public function testReturnsFalseWhenNoSalableCandidatesInIndex(): void - { - $this->setupConfigurableProduct('configurable-sku', 100, [10 => 10, 20 => 20]); - $this->getSkusByProductIdsMock->method('execute') - ->willReturn([10 => 'simple_10', 20 => 'simple_20']); - - $this->stockIndexTableNameResolverMock->method('execute') - ->with(1) - ->willReturn('inventory_stock_1'); - $this->connectionMock->method('fetchCol') - ->willReturn([]); - - $this->areProductsSalableMock->expects($this->never())->method('execute'); - - $result = $this->model->execute('configurable-sku', 1); - - self::assertFalse($result); - } - - public function testReturnsTrueWhenCandidateConfirmedSalable(): void - { - $this->setupConfigurableProduct('configurable-sku', 100, [10 => 10, 20 => 20]); - $this->getSkusByProductIdsMock->method('execute') - ->willReturn([10 => 'simple_10', 20 => 'simple_20']); - - $this->stockIndexTableNameResolverMock->method('execute') - ->with(5) - ->willReturn('inventory_stock_5'); - $this->connectionMock->method('fetchCol') - ->willReturn(['simple_20']); - - $salableResult = $this->createSalableResult('simple_20', true); - $this->areProductsSalableMock->expects($this->once()) - ->method('execute') - ->with(['simple_20'], 5) - ->willReturn([$salableResult]); - - $result = $this->model->execute('configurable-sku', 5); - - self::assertTrue($result); - } - - public function testReturnsFalseWhenCandidateNotConfirmedSalable(): void - { - $this->setupConfigurableProduct('configurable-sku', 100, [10 => 10, 20 => 20]); - $this->getSkusByProductIdsMock->method('execute') - ->willReturn([10 => 'simple_10', 20 => 'simple_20']); - - $this->stockIndexTableNameResolverMock->method('execute') - ->willReturn('inventory_stock_1'); - $this->connectionMock->method('fetchCol') - ->willReturn(['simple_10', 'simple_20']); - - $result1 = $this->createSalableResult('simple_10', false); - $result2 = $this->createSalableResult('simple_20', false); - $this->areProductsSalableMock->expects($this->exactly(2)) - ->method('execute') - ->willReturnMap([ - [['simple_10'], 1, [$result1]], - [['simple_20'], 1, [$result2]], - ]); - - $result = $this->model->execute('configurable-sku', 1); - - self::assertFalse($result); - } - - public function testEarlyExitOnFirstConfirmedSalable(): void - { - $this->setupConfigurableProduct('configurable-sku', 100, [10 => 10, 20 => 20]); - $this->getSkusByProductIdsMock->method('execute') - ->willReturn([10 => 'simple_10', 20 => 'simple_20']); - - $this->stockIndexTableNameResolverMock->method('execute') - ->willReturn('inventory_stock_1'); - $this->connectionMock->method('fetchCol') - ->willReturn(['simple_10', 'simple_20']); - - $salableResult = $this->createSalableResult('simple_10', true); - // Only called once — early exit after first salable candidate confirmed - $this->areProductsSalableMock->expects($this->once()) - ->method('execute') - ->with(['simple_10'], 1) - ->willReturn([$salableResult]); - - $result = $this->model->execute('configurable-sku', 1); - - self::assertTrue($result); - } - - public function testOnlySalableCandidatesPassedToAreProductsSalable(): void - { - $childIds = []; - $childSkus = []; - for ($i = 1; $i <= 100; $i++) { - $childIds[$i] = $i; - $childSkus[$i] = 'child_' . $i; - } - - $this->setupConfigurableProduct('configurable-sku', 500, $childIds); - $this->getSkusByProductIdsMock->method('execute') - ->willReturn($childSkus); - - $this->stockIndexTableNameResolverMock->method('execute') - ->willReturn('inventory_stock_1'); - // Only 2 out of 100 are salable in the index - $this->connectionMock->method('fetchCol') - ->willReturn(['child_50', 'child_75']); - - $salableResult = $this->createSalableResult('child_50', true); - // Early exit: only first candidate checked, second never reached - $this->areProductsSalableMock->expects($this->once()) - ->method('execute') - ->with(['child_50'], 1) - ->willReturn([$salableResult]); - - $result = $this->model->execute('configurable-sku', 1); - - self::assertTrue($result); - } - - public function testWorksWithNonDefaultStock(): void - { - $this->setupConfigurableProduct('configurable-sku', 100, [10 => 10]); - $this->getSkusByProductIdsMock->method('execute') - ->willReturn([10 => 'simple_10']); - - $this->stockIndexTableNameResolverMock->expects($this->once()) - ->method('execute') - ->with(20) - ->willReturn('inventory_stock_20'); - $this->connectionMock->method('fetchCol') - ->willReturn(['simple_10']); - - $salableResult = $this->createSalableResult('simple_10', true); - $this->areProductsSalableMock->expects($this->once()) - ->method('execute') - ->with(['simple_10'], 20) - ->willReturn([$salableResult]); - - $result = $this->model->execute('configurable-sku', 20); - - self::assertTrue($result); - } - - public function testGracefulDegradationOnIndexQueryFailure(): void - { - $this->setupConfigurableProduct('configurable-sku', 100, [10 => 10]); - $this->getSkusByProductIdsMock->method('execute') - ->willReturn([10 => 'simple_10']); - - $this->stockIndexTableNameResolverMock->method('execute') - ->willReturn('inventory_stock_1'); - $this->connectionMock->method('fetchCol') - ->willThrowException(new \Exception('Table does not exist')); - - $this->areProductsSalableMock->expects($this->never())->method('execute'); - - $result = $this->model->execute('configurable-sku', 1); - - self::assertFalse($result); - } - - /** - * Set up common mocks for configurable product resolution - */ - private function setupConfigurableProduct(string $sku, int $productId, array $childrenIds): void - { - $this->getProductIdsBySkusMock->method('execute') - ->with([$sku]) - ->willReturn([$sku => $productId]); - $this->configurableMock->method('getChildrenIds') - ->with($productId) - ->willReturn([0 => $childrenIds]); - } - - /** - * Create a mock salable result - */ - private function createSalableResult(string $sku, bool $isSalable): IsProductSalableResultInterface - { - $mock = $this->createMock(IsProductSalableResultInterface::class); - $mock->method('getSku')->willReturn($sku); - $mock->method('isSalable')->willReturn($isSalable); - return $mock; - } -} diff --git a/InventoryConfigurableProduct/etc/di.xml b/InventoryConfigurableProduct/etc/di.xml index 76b50c219971..39d2a91f825f 100644 --- a/InventoryConfigurableProduct/etc/di.xml +++ b/InventoryConfigurableProduct/etc/di.xml @@ -47,8 +47,7 @@ - + From 1bc671453f3d87308f71bdc7a593dda4dc660d6a Mon Sep 17 00:00:00 2001 From: Alexandra Zota Date: Tue, 7 Apr 2026 12:07:58 +0300 Subject: [PATCH 09/83] ACP2E-4805: Configurable Product's performance impact on checkout (totals-information, estimate-shipping-modules) --- ...bleProductSalableOnNonDefaultStockTest.php | 196 ++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 InventoryConfigurableProduct/Test/Integration/IsProductSalable/IsConfigurableProductSalableOnNonDefaultStockTest.php diff --git a/InventoryConfigurableProduct/Test/Integration/IsProductSalable/IsConfigurableProductSalableOnNonDefaultStockTest.php b/InventoryConfigurableProduct/Test/Integration/IsProductSalable/IsConfigurableProductSalableOnNonDefaultStockTest.php new file mode 100644 index 000000000000..743892c86f7f --- /dev/null +++ b/InventoryConfigurableProduct/Test/Integration/IsProductSalable/IsConfigurableProductSalableOnNonDefaultStockTest.php @@ -0,0 +1,196 @@ +areProductsSalable = Bootstrap::getObjectManager()->get(AreProductsSalableInterface::class); + $this->fixtures = DataFixtureStorageManager::getStorage(); + } + + #[ + DbIsolation(false), + DataFixture(SourceFixture::class, ['source_code' => 'source_1'], 'source1'), + DataFixture(StockFixture::class, as: 'stock'), + DataFixture( + StockSourceLinksFixture::class, + [['stock_id' => '$stock.stock_id$', 'source_code' => '$source1.source_code$']] + ), + DataFixture( + StockSalesChannelsFixture::class, + ['stock_id' => '$stock.stock_id$', 'sales_channels' => ['base']] + ), + DataFixture(Indexer::class, ['indexer_id' => 'inventory']), + DataFixture(ProductFixture::class, ['sku' => 'child-1'], 'child1'), + DataFixture(ProductFixture::class, ['sku' => 'child-2'], 'child2'), + DataFixture(AttributeFixture::class, as: 'attr'), + DataFixture( + ConfigurableProductFixture::class, + ['_options' => ['$attr$'], '_links' => ['$child1$', '$child2$']], + 'configurable' + ), + DataFixture( + SourceItemsFixture::class, + [ + ['sku' => '$child1.sku$', 'source_code' => '$source1.source_code$', 'quantity' => 100, 'status' => 1], + ['sku' => '$child2.sku$', 'source_code' => '$source1.source_code$', 'quantity' => 100, 'status' => 1], + ] + ), + DataFixture(Indexer::class, ['indexer_id' => 'inventory']), + ] + public function testConfigurableIsSalableWhenChildrenAreInStock(): void + { + $stockId = (int) $this->fixtures->get('stock')->getStockId(); + $sku = $this->fixtures->get('configurable')->getSku(); + + $results = $this->areProductsSalable->execute([$sku], $stockId); + $result = current($results); + + self::assertTrue($result->isSalable(), 'Configurable should be salable when children are in stock'); + } + + #[ + DbIsolation(false), + DataFixture(SourceFixture::class, ['source_code' => 'source_1'], 'source1'), + DataFixture(StockFixture::class, as: 'stock'), + DataFixture( + StockSourceLinksFixture::class, + [['stock_id' => '$stock.stock_id$', 'source_code' => '$source1.source_code$']] + ), + DataFixture( + StockSalesChannelsFixture::class, + ['stock_id' => '$stock.stock_id$', 'sales_channels' => ['base']] + ), + DataFixture(Indexer::class, ['indexer_id' => 'inventory']), + DataFixture(ProductFixture::class, ['sku' => 'child-1'], 'child1'), + DataFixture(ProductFixture::class, ['sku' => 'child-2'], 'child2'), + DataFixture(AttributeFixture::class, as: 'attr'), + DataFixture( + ConfigurableProductFixture::class, + ['_options' => ['$attr$'], '_links' => ['$child1$', '$child2$']], + 'configurable' + ), + DataFixture( + SourceItemsFixture::class, + [ + ['sku' => '$child1.sku$', 'source_code' => '$source1.source_code$', 'quantity' => 0, 'status' => 0], + ['sku' => '$child2.sku$', 'source_code' => '$source1.source_code$', 'quantity' => 0, 'status' => 0], + ] + ), + DataFixture(Indexer::class, ['indexer_id' => 'inventory']), + ] + public function testConfigurableIsNotSalableWhenAllChildrenOutOfStock(): void + { + $stockId = (int) $this->fixtures->get('stock')->getStockId(); + $sku = $this->fixtures->get('configurable')->getSku(); + + $results = $this->areProductsSalable->execute([$sku], $stockId); + $result = current($results); + + self::assertFalse( + $result->isSalable(), + 'Configurable should not be salable when all children are out of stock' + ); + } + + #[ + DbIsolation(false), + DataFixture(SourceFixture::class, ['source_code' => 'source_us'], 'sourceUs'), + DataFixture(SourceFixture::class, ['source_code' => 'source_eu'], 'sourceEu'), + DataFixture(StockFixture::class, as: 'stockUs'), + DataFixture(StockFixture::class, as: 'stockEu'), + DataFixture( + StockSourceLinksFixture::class, + [ + ['stock_id' => '$stockUs.stock_id$', 'source_code' => '$sourceUs.source_code$'], + ['stock_id' => '$stockEu.stock_id$', 'source_code' => '$sourceEu.source_code$'], + ] + ), + DataFixture( + StockSalesChannelsFixture::class, + ['stock_id' => '$stockUs.stock_id$', 'sales_channels' => ['base']] + ), + DataFixture(Indexer::class, ['indexer_id' => 'inventory']), + DataFixture(ProductFixture::class, ['sku' => 'child-1'], 'child1'), + DataFixture(ProductFixture::class, ['sku' => 'child-2'], 'child2'), + DataFixture(AttributeFixture::class, as: 'attr'), + DataFixture( + ConfigurableProductFixture::class, + ['_options' => ['$attr$'], '_links' => ['$child1$', '$child2$']], + 'configurable' + ), + DataFixture( + SourceItemsFixture::class, + [ + ['sku' => '$child1.sku$', 'source_code' => '$sourceUs.source_code$', 'quantity' => 100, 'status' => 1], + ['sku' => '$child2.sku$', 'source_code' => '$sourceUs.source_code$', 'quantity' => 100, 'status' => 1], + ['sku' => '$child1.sku$', 'source_code' => '$sourceEu.source_code$', 'quantity' => 0, 'status' => 0], + ['sku' => '$child2.sku$', 'source_code' => '$sourceEu.source_code$', 'quantity' => 0, 'status' => 0], + ] + ), + DataFixture(Indexer::class, ['indexer_id' => 'inventory']), + ] + public function testConfigurableSalabilityReflectsPerStockSourceAssignments(): void + { + $sku = $this->fixtures->get('configurable')->getSku(); + + $stockUsId = (int) $this->fixtures->get('stockUs')->getStockId(); + $results = $this->areProductsSalable->execute([$sku], $stockUsId); + $result = current($results); + self::assertTrue( + $result->isSalable(), + 'Configurable should be salable on US stock where children have stock' + ); + + $stockEuId = (int) $this->fixtures->get('stockEu')->getStockId(); + $results = $this->areProductsSalable->execute([$sku], $stockEuId); + $result = current($results); + self::assertFalse( + $result->isSalable(), + 'Configurable should not be salable on EU stock where children are out of stock' + ); + } +} From dac77c80328e12d48bc4f0cfa4395a9f17789a5d Mon Sep 17 00:00:00 2001 From: Alexandra Zota Date: Tue, 7 Apr 2026 12:10:25 +0300 Subject: [PATCH 10/83] ACP2E-4805: Configurable Product's performance impact on checkout (totals-information, estimate-shipping-modules) --- .../IsConfigurableProductChildrenSalable.php | 84 ++----------------- 1 file changed, 9 insertions(+), 75 deletions(-) diff --git a/InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductChildrenSalable.php b/InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductChildrenSalable.php index 4116a6db5215..5d08fdd76927 100644 --- a/InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductChildrenSalable.php +++ b/InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductChildrenSalable.php @@ -8,12 +8,8 @@ namespace Magento\InventoryConfigurableProduct\Model\IsProductSalableCondition; use Magento\ConfigurableProduct\Model\Product\Type\Configurable; -use Magento\Framework\App\ObjectManager; -use Magento\Framework\App\ResourceConnection; use Magento\InventoryCatalogApi\Model\GetProductIdsBySkusInterface; use Magento\InventoryCatalogApi\Model\GetSkusByProductIdsInterface; -use Magento\InventoryIndexer\Indexer\IndexStructure; -use Magento\InventoryIndexer\Model\StockIndexTableNameResolverInterface; use Magento\InventorySalesApi\Api\AreProductsSalableInterface; /** @@ -41,40 +37,22 @@ class IsConfigurableProductChildrenSalable */ private $getSkusByProductIds; - /** - * @var ResourceConnection - */ - private $resource; - - /** - * @var StockIndexTableNameResolverInterface - */ - private $stockIndexTableNameResolver; - /** * @param Configurable $configurable * @param AreProductsSalableInterface $areProductsSalable * @param GetProductIdsBySkusInterface $getProductIdsBySkus * @param GetSkusByProductIdsInterface $getSkusByProductIds - * @param ResourceConnection|null $resource - * @param StockIndexTableNameResolverInterface|null $stockIndexTableNameResolver */ public function __construct( Configurable $configurable, AreProductsSalableInterface $areProductsSalable, GetProductIdsBySkusInterface $getProductIdsBySkus, - GetSkusByProductIdsInterface $getSkusByProductIds, - ?ResourceConnection $resource = null, - ?StockIndexTableNameResolverInterface $stockIndexTableNameResolver = null + GetSkusByProductIdsInterface $getSkusByProductIds ) { $this->configurable = $configurable; $this->areProductsSalable = $areProductsSalable; $this->getProductIdsBySkus = $getProductIdsBySkus; $this->getSkusByProductIds = $getSkusByProductIds; - $this->resource = $resource - ?: ObjectManager::getInstance()->get(ResourceConnection::class); - $this->stockIndexTableNameResolver = $stockIndexTableNameResolver - ?: ObjectManager::getInstance()->get(StockIndexTableNameResolverInterface::class); } /** @@ -91,64 +69,20 @@ public function __construct( */ public function execute(string $sku, int $stockId): bool { + $isSalable = false; $productId = $this->getProductIdsBySkus->execute([$sku])[$sku]; $ids = $this->configurable->getChildrenIds($productId); - $childrenIds = $ids[0] ?? []; - - if (empty($childrenIds)) { - return false; - } - - $childrenSkus = $this->getSkusByProductIds->execute($childrenIds); - - if (empty($childrenSkus)) { - return false; - } - - $candidateSkus = $this->getSalableCandidatesFromIndex($childrenSkus, $stockId); - - if (empty($candidateSkus)) { - return false; - } - - foreach ($candidateSkus as $candidateSku) { - $results = $this->areProductsSalable->execute([$candidateSku], $stockId); + $childrenSkus = $this->getSkusByProductIds->execute($ids[0]); + // check associated products salability one by one rather in batch for performance reason + foreach ($childrenSkus as $childSku) { + $results = $this->areProductsSalable->execute([$childSku], $stockId); $result = reset($results); if ($result && $result->isSalable()) { - return true; + $isSalable = true; + break; } } - return false; - } - - /** - * Pre-filter children using the stock index to find candidates marked as salable. - * - * The stock index table (inventory_stock_{id}) aggregates source item data per stock, - * accounting for multi-source inventory assignments. This single query eliminates - * iterating through all children individually. The returned candidates are then - * validated through the full salability condition chain via areProductsSalable. - * - * @param string[] $skus - * @param int $stockId - * @return string[] - */ - private function getSalableCandidatesFromIndex(array $skus, int $stockId): array - { - try { - $connection = $this->resource->getConnection(); - $select = $connection->select() - ->from( - $this->stockIndexTableNameResolver->execute($stockId), - [IndexStructure::SKU] - ) - ->where(IndexStructure::SKU . ' IN (?)', array_values($skus)) - ->where(IndexStructure::IS_SALABLE . ' = ?', 1); - - return $connection->fetchCol($select); - } catch (\Exception $e) { - return []; - } + return $isSalable; } } From 6f454a7e5e71fe6028b57ee8854ece8c8aad7fc8 Mon Sep 17 00:00:00 2001 From: Olga Moyseyenko Date: Mon, 13 Apr 2026 20:38:52 -0500 Subject: [PATCH 11/83] ACP2E-4741: [CLOUD] Gift card and related not sellable WF-1688 --- .../Indexer/Stock/SkuListsProcessorTest.php | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 InventoryIndexer/Test/Integration/Indexer/Stock/SkuListsProcessorTest.php diff --git a/InventoryIndexer/Test/Integration/Indexer/Stock/SkuListsProcessorTest.php b/InventoryIndexer/Test/Integration/Indexer/Stock/SkuListsProcessorTest.php new file mode 100644 index 000000000000..4b271b75e8aa --- /dev/null +++ b/InventoryIndexer/Test/Integration/Indexer/Stock/SkuListsProcessorTest.php @@ -0,0 +1,133 @@ +sourceItemIndexer = Bootstrap::getObjectManager()->get(SourceItemIndexer::class); + $this->getStockItemData = Bootstrap::getObjectManager()->get(GetStockItemData::class); + $this->getSourceItemIds = Bootstrap::getObjectManager()->get(GetSourceItemIds::class); + $this->sourceItemRepository = Bootstrap::getObjectManager()->get(SourceItemRepositoryInterface::class); + $this->searchCriteriaBuilder = Bootstrap::getObjectManager()->get(SearchCriteriaBuilder::class); + $this->removeIndexData = Bootstrap::getObjectManager()->get(RemoveIndexData::class); + $this->resource = Bootstrap::getObjectManager()->get(ResourceConnection::class); + } + + /** + * We broke transaction during indexation so we need to clean db state manually + */ + protected function tearDown(): void + { + $this->removeIndexData->execute([2]); + } + + /** + * Product should stay in inventory stock if related product is updated and reindex is run. + * + */ + #[ + DbIsolation(false), + AppIsolation(true), + DataFixture(SourceFixture::class, as: 'source2'), + DataFixture(StockFixture::class, as: 'stock2'), + DataFixture( + StockSourceLinksFixture::class, + [['stock_id' => '$stock2.stock_id$', 'source_code' => '$source2.source_code$'],] + ), + DataFixture( + StockSalesChannelsFixture::class, + ['stock_id' => '$stock2.stock_id$', 'sales_channels' => ['base']] + ), + DataFixture(ProductFixture::class, as: 'p1'), + DataFixture(ProductFixture::class, ['product_links' => [['sku' => '$p1.sku$', 'type' => 'related']]], 'p2'), + DataFixture(ProductFixture::class, ['product_links' => [['sku' => '$p1.sku$', 'type' => 'upsell']]], 'p3'), + DataFixture(ProductFixture::class, ['product_links' => [['sku' => '$p1.sku$', 'type' => 'crosssell']]], 'p4'), + DataFixture( + SourceItemsFixture::class, + [ + ['sku' => '$p1.sku$', 'source_code' => '$source2.source_code$', 'quantity' => 100], + ['sku' => '$p2.sku$', 'source_code' => '$source2.source_code$', 'quantity' => 200], + ['sku' => '$p3.sku$', 'source_code' => '$source2.source_code$', 'quantity' => 300], + ['sku' => '$p4.sku$', 'source_code' => '$source2.source_code$', 'quantity' => 400], + ] + ), + ] + public function testReindexListForRelatedProducts() + { + $connection = $this->resource->getConnection(); + $select = $connection->select() + ->from($this->resource->getTableName('inventory_stock_2')) + ->order('sku ASC'); + $inventoryData = $connection->fetchAll($select); + + // All products should be in inventory_stock_2 table, none should be deleted at reindex. + // Reindex is triggered when source is assigned to products + assertCount(4, $inventoryData, 'All 4 products should be present in inventory_stock_2 table'); + } +} + From a04c7583742142e70304b711df5eced1ac851d5f Mon Sep 17 00:00:00 2001 From: Dnyaneshwar S Jambhulkar Date: Tue, 14 Apr 2026 23:35:22 +0530 Subject: [PATCH 12/83] AC-16487::Fake Modules Require dev/ Directory in Extension Repositories --- .../GetNonCachedStockItemPlugin.php | 5 +- .../TestModuleInventoryStateCache/etc/di.xml | 0 .../etc/events.xml | 0 .../etc/frontend/di.xml | 0 .../etc/module.xml | 0 .../registration.php | 0 .../BundleProductOnlyXLeftInStockTest.php | 7 +- .../GraphQl}/BundleProductStockStatusTest.php | 4 +- .../SimpleProductWithOptionsCartTest.php | 4 +- .../PickupLocationForShippingTest.php | 4 +- .../Test/Api/GraphQl}/MergeCartsTest.php | 2 +- .../GetNonCachedStockItemPlugin.php | 82 ------------------- .../TestModuleInventoryStateCache/etc/di.xml | 11 --- .../etc/frontend/di.xml | 14 ---- .../etc/events.xml | 12 --- .../etc/module.xml | 18 ---- .../registration.php | 13 --- 17 files changed, 14 insertions(+), 162 deletions(-) rename {dev/tests/integration => InventoryCache/Test}/_files/Magento/TestModuleInventoryStateCache/Plugin/CatalogInventory/Model/StockRegistryProvider/GetNonCachedStockItemPlugin.php (97%) rename {dev/tests/integration => InventoryCache/Test}/_files/Magento/TestModuleInventoryStateCache/etc/di.xml (100%) rename {dev/tests/api-functional => InventoryCache/Test}/_files/Magento/TestModuleInventoryStateCache/etc/events.xml (100%) rename {dev/tests/integration => InventoryCache/Test}/_files/Magento/TestModuleInventoryStateCache/etc/frontend/di.xml (100%) rename {dev/tests/api-functional => InventoryCache/Test}/_files/Magento/TestModuleInventoryStateCache/etc/module.xml (100%) rename {dev/tests/api-functional => InventoryCache/Test}/_files/Magento/TestModuleInventoryStateCache/registration.php (100%) rename {dev/tests/api-functional/testsuite/Magento/GraphQl/Inventory => InventoryGraphQl/Test/Api/GraphQl}/BundleProductOnlyXLeftInStockTest.php (97%) rename {dev/tests/api-functional/testsuite/Magento/GraphQl/Inventory => InventoryGraphQl/Test/Api/GraphQl}/BundleProductStockStatusTest.php (98%) rename {dev/tests/api-functional/testsuite/Magento/GraphQl/Inventory => InventoryGraphQl/Test/Api/GraphQl}/SimpleProductWithOptionsCartTest.php (99%) rename {dev/tests/api-functional/testsuite/Magento/GraphQl/InventoryInStorePickupQuote => InventoryInStorePickupQuoteGraphQl/Test/Api/GraphQl}/PickupLocationForShippingTest.php (99%) rename {dev/tests/api-functional/testsuite/Magento/GraphQl/InventoryQuote => InventoryQuoteGraphQl/Test/Api/GraphQl}/MergeCartsTest.php (98%) delete mode 100644 dev/tests/api-functional/_files/Magento/TestModuleInventoryStateCache/Plugin/CatalogInventory/Model/StockRegistryProvider/GetNonCachedStockItemPlugin.php delete mode 100644 dev/tests/api-functional/_files/Magento/TestModuleInventoryStateCache/etc/di.xml delete mode 100644 dev/tests/api-functional/_files/Magento/TestModuleInventoryStateCache/etc/frontend/di.xml delete mode 100644 dev/tests/integration/_files/Magento/TestModuleInventoryStateCache/etc/events.xml delete mode 100644 dev/tests/integration/_files/Magento/TestModuleInventoryStateCache/etc/module.xml delete mode 100644 dev/tests/integration/_files/Magento/TestModuleInventoryStateCache/registration.php diff --git a/dev/tests/integration/_files/Magento/TestModuleInventoryStateCache/Plugin/CatalogInventory/Model/StockRegistryProvider/GetNonCachedStockItemPlugin.php b/InventoryCache/Test/_files/Magento/TestModuleInventoryStateCache/Plugin/CatalogInventory/Model/StockRegistryProvider/GetNonCachedStockItemPlugin.php similarity index 97% rename from dev/tests/integration/_files/Magento/TestModuleInventoryStateCache/Plugin/CatalogInventory/Model/StockRegistryProvider/GetNonCachedStockItemPlugin.php rename to InventoryCache/Test/_files/Magento/TestModuleInventoryStateCache/Plugin/CatalogInventory/Model/StockRegistryProvider/GetNonCachedStockItemPlugin.php index ecfc6e7673dc..bbc1f296cbc6 100644 --- a/dev/tests/integration/_files/Magento/TestModuleInventoryStateCache/Plugin/CatalogInventory/Model/StockRegistryProvider/GetNonCachedStockItemPlugin.php +++ b/InventoryCache/Test/_files/Magento/TestModuleInventoryStateCache/Plugin/CatalogInventory/Model/StockRegistryProvider/GetNonCachedStockItemPlugin.php @@ -7,6 +7,7 @@ namespace Magento\TestModuleInventoryStateCache\Plugin\CatalogInventory\Model\StockRegistryProvider; +use Closure; use Magento\CatalogInventory\Api\Data\StockItemInterface; use Magento\CatalogInventory\Api\Data\StockItemInterfaceFactory; use Magento\CatalogInventory\Api\StockItemCriteriaInterfaceFactory; @@ -57,7 +58,7 @@ public function __construct( * Get non cached stock items for product. * * @param StockRegistryProviderInterface $subject - * @param \Closure $proceed + * @param Closure $proceed * @param int|null $productId * @param int|null $stockId * @return StockItemInterface @@ -65,7 +66,7 @@ public function __construct( */ public function aroundGetStockItem( StockRegistryProviderInterface $subject, - \Closure $proceed, + Closure $proceed, ?int $productId, ?int $stockId ): StockItemInterface { diff --git a/dev/tests/integration/_files/Magento/TestModuleInventoryStateCache/etc/di.xml b/InventoryCache/Test/_files/Magento/TestModuleInventoryStateCache/etc/di.xml similarity index 100% rename from dev/tests/integration/_files/Magento/TestModuleInventoryStateCache/etc/di.xml rename to InventoryCache/Test/_files/Magento/TestModuleInventoryStateCache/etc/di.xml diff --git a/dev/tests/api-functional/_files/Magento/TestModuleInventoryStateCache/etc/events.xml b/InventoryCache/Test/_files/Magento/TestModuleInventoryStateCache/etc/events.xml similarity index 100% rename from dev/tests/api-functional/_files/Magento/TestModuleInventoryStateCache/etc/events.xml rename to InventoryCache/Test/_files/Magento/TestModuleInventoryStateCache/etc/events.xml diff --git a/dev/tests/integration/_files/Magento/TestModuleInventoryStateCache/etc/frontend/di.xml b/InventoryCache/Test/_files/Magento/TestModuleInventoryStateCache/etc/frontend/di.xml similarity index 100% rename from dev/tests/integration/_files/Magento/TestModuleInventoryStateCache/etc/frontend/di.xml rename to InventoryCache/Test/_files/Magento/TestModuleInventoryStateCache/etc/frontend/di.xml diff --git a/dev/tests/api-functional/_files/Magento/TestModuleInventoryStateCache/etc/module.xml b/InventoryCache/Test/_files/Magento/TestModuleInventoryStateCache/etc/module.xml similarity index 100% rename from dev/tests/api-functional/_files/Magento/TestModuleInventoryStateCache/etc/module.xml rename to InventoryCache/Test/_files/Magento/TestModuleInventoryStateCache/etc/module.xml diff --git a/dev/tests/api-functional/_files/Magento/TestModuleInventoryStateCache/registration.php b/InventoryCache/Test/_files/Magento/TestModuleInventoryStateCache/registration.php similarity index 100% rename from dev/tests/api-functional/_files/Magento/TestModuleInventoryStateCache/registration.php rename to InventoryCache/Test/_files/Magento/TestModuleInventoryStateCache/registration.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Inventory/BundleProductOnlyXLeftInStockTest.php b/InventoryGraphQl/Test/Api/GraphQl/BundleProductOnlyXLeftInStockTest.php similarity index 97% rename from dev/tests/api-functional/testsuite/Magento/GraphQl/Inventory/BundleProductOnlyXLeftInStockTest.php rename to InventoryGraphQl/Test/Api/GraphQl/BundleProductOnlyXLeftInStockTest.php index 7c0dbe4456d3..4417cad39fcc 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Inventory/BundleProductOnlyXLeftInStockTest.php +++ b/InventoryGraphQl/Test/Api/GraphQl/BundleProductOnlyXLeftInStockTest.php @@ -5,8 +5,9 @@ */ declare(strict_types=1); -namespace Magento\GraphQl\Inventory; +namespace Magento\InventoryGraphQl\Test\Api\GraphQl; +use Exception; use Magento\Bundle\Test\Fixture\AddProductToCart as AddBundleProductToCart; use Magento\Bundle\Test\Fixture\Link as BundleSelectionFixture; use Magento\Bundle\Test\Fixture\Option as BundleOptionFixture; @@ -39,7 +40,7 @@ class BundleProductOnlyXLeftInStockTest extends GraphQlAbstract private $fixtures; /** - * @inheritdoc + * @inheritDoc */ protected function setUp(): void { @@ -80,7 +81,7 @@ protected function setUp(): void * @param string $stockThresholdQty * @return void * - * @throws \Exception + * @throws Exception */ #[DataProvider('stockThresholdQtyProvider')] public function testOnlyXLeftInStockBundleProduct(string $stockThresholdQty): void diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Inventory/BundleProductStockStatusTest.php b/InventoryGraphQl/Test/Api/GraphQl/BundleProductStockStatusTest.php similarity index 98% rename from dev/tests/api-functional/testsuite/Magento/GraphQl/Inventory/BundleProductStockStatusTest.php rename to InventoryGraphQl/Test/Api/GraphQl/BundleProductStockStatusTest.php index a1da356e6196..ce78384a191a 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Inventory/BundleProductStockStatusTest.php +++ b/InventoryGraphQl/Test/Api/GraphQl/BundleProductStockStatusTest.php @@ -5,7 +5,7 @@ */ declare(strict_types=1); -namespace Magento\GraphQl\Inventory; +namespace Magento\InventoryGraphQl\Test\Api\GraphQl; use Magento\Bundle\Test\Fixture\AddProductToCart as AddBundleProductToCart; use Magento\Bundle\Test\Fixture\Link as BundleSelectionFixture; @@ -47,7 +47,7 @@ class BundleProductStockStatusTest extends GraphQlAbstract private $fixtures; /** - * @inheritdoc + * @inheritDoc */ protected function setUp(): void { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Inventory/SimpleProductWithOptionsCartTest.php b/InventoryGraphQl/Test/Api/GraphQl/SimpleProductWithOptionsCartTest.php similarity index 99% rename from dev/tests/api-functional/testsuite/Magento/GraphQl/Inventory/SimpleProductWithOptionsCartTest.php rename to InventoryGraphQl/Test/Api/GraphQl/SimpleProductWithOptionsCartTest.php index dbc903b4ab28..5bdb3b894ec4 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Inventory/SimpleProductWithOptionsCartTest.php +++ b/InventoryGraphQl/Test/Api/GraphQl/SimpleProductWithOptionsCartTest.php @@ -5,11 +5,12 @@ */ declare(strict_types=1); -namespace Magento\GraphQl\Inventory; +namespace Magento\InventoryGraphQl\Test\Api\GraphQl; use Exception; use Magento\Catalog\Api\Data\ProductCustomOptionInterface; use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Catalog\Test\Fixture\Product; use Magento\CatalogInventory\Api\Data\StockItemInterface; use Magento\Framework\DataObject; @@ -21,7 +22,6 @@ use Magento\TestFramework\Fixture\DataFixtureStorageManager; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; -use Magento\Catalog\Api\ProductRepositoryInterface; /** * Product stock_status test diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/InventoryInStorePickupQuote/PickupLocationForShippingTest.php b/InventoryInStorePickupQuoteGraphQl/Test/Api/GraphQl/PickupLocationForShippingTest.php similarity index 99% rename from dev/tests/api-functional/testsuite/Magento/GraphQl/InventoryInStorePickupQuote/PickupLocationForShippingTest.php rename to InventoryInStorePickupQuoteGraphQl/Test/Api/GraphQl/PickupLocationForShippingTest.php index f91b16919e90..1212b2ea92d8 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/InventoryInStorePickupQuote/PickupLocationForShippingTest.php +++ b/InventoryInStorePickupQuoteGraphQl/Test/Api/GraphQl/PickupLocationForShippingTest.php @@ -5,7 +5,7 @@ */ declare(strict_types=1); -namespace Magento\GraphQl\InventoryInStorePickupQuote; +namespace Magento\InventoryInStorePickupQuoteGraphQl\Test\Api\GraphQl; use Magento\Catalog\Test\Fixture\Product as ProductFixture; use Magento\Framework\Exception\CouldNotSaveException; @@ -13,6 +13,7 @@ use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Validation\ValidationException; use Magento\InventoryApi\Api\SourceRepositoryInterface; +use Magento\InventoryApi\Test\Fixture\Source as SourceFixture; use Magento\InventoryApi\Test\Fixture\SourceItems as SourceItemsFixture; use Magento\InventoryApi\Test\Fixture\Stock as StockFixture; use Magento\InventoryApi\Test\Fixture\StockSourceLinks as StockSourceLinksFixture; @@ -20,7 +21,6 @@ use Magento\InventorySalesApi\Api\Data\SalesChannelInterface; use Magento\InventorySalesApi\Test\Fixture\StockSalesChannels as StockSalesChannelsFixture; use Magento\Quote\Test\Fixture\AddProductToCart as AddProductToCartFixture; -use Magento\InventoryApi\Test\Fixture\Source as SourceFixture; use Magento\Quote\Test\Fixture\GuestCart as GuestCartFixture; use Magento\Quote\Test\Fixture\QuoteIdMask as QuoteMaskFixture; use Magento\Store\Model\StoreManagerInterface; diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/InventoryQuote/MergeCartsTest.php b/InventoryQuoteGraphQl/Test/Api/GraphQl/MergeCartsTest.php similarity index 98% rename from dev/tests/api-functional/testsuite/Magento/GraphQl/InventoryQuote/MergeCartsTest.php rename to InventoryQuoteGraphQl/Test/Api/GraphQl/MergeCartsTest.php index c372494c2137..974e1079e175 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/InventoryQuote/MergeCartsTest.php +++ b/InventoryQuoteGraphQl/Test/Api/GraphQl/MergeCartsTest.php @@ -5,7 +5,7 @@ */ declare(strict_types=1); -namespace Magento\GraphQl\InventoryQuote; +namespace Magento\InventoryQuoteGraphQl\Test\Api\GraphQl; use Magento\Catalog\Test\Fixture\Product as ProductFixture; use Magento\Customer\Test\Fixture\Customer as CustomerFixture; diff --git a/dev/tests/api-functional/_files/Magento/TestModuleInventoryStateCache/Plugin/CatalogInventory/Model/StockRegistryProvider/GetNonCachedStockItemPlugin.php b/dev/tests/api-functional/_files/Magento/TestModuleInventoryStateCache/Plugin/CatalogInventory/Model/StockRegistryProvider/GetNonCachedStockItemPlugin.php deleted file mode 100644 index f0562b5fc2ee..000000000000 --- a/dev/tests/api-functional/_files/Magento/TestModuleInventoryStateCache/Plugin/CatalogInventory/Model/StockRegistryProvider/GetNonCachedStockItemPlugin.php +++ /dev/null @@ -1,82 +0,0 @@ -stockItemCriteriaFactory = $stockItemCriteriaFactory; - $this->stockItemRepository = $stockItemRepository; - $this->stockItemFactory = $stockItemFactory; - } - - /** - * Get non cached stock items for product. - * - * @param StockRegistryProviderInterface $subject - * @param \Closure $proceed - * @param int|null $productId - * @param int|null $stockId - * @return StockItemInterface - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public function aroundGetStockItem( - StockRegistryProviderInterface $subject, - \Closure $proceed, - ?int $productId, - ?int $stockId - ): StockItemInterface { - $criteria = $this->stockItemCriteriaFactory->create(); - $criteria->setProductsFilter($productId); - $collection = $this->stockItemRepository->getList($criteria); - $stockItem = current($collection->getItems()); - if (!$stockItem || !$stockItem->getItemId()) { - $stockItem = $this->stockItemFactory->create(); - } - - return $stockItem; - } -} diff --git a/dev/tests/api-functional/_files/Magento/TestModuleInventoryStateCache/etc/di.xml b/dev/tests/api-functional/_files/Magento/TestModuleInventoryStateCache/etc/di.xml deleted file mode 100644 index 4c1b4c242e47..000000000000 --- a/dev/tests/api-functional/_files/Magento/TestModuleInventoryStateCache/etc/di.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/dev/tests/api-functional/_files/Magento/TestModuleInventoryStateCache/etc/frontend/di.xml b/dev/tests/api-functional/_files/Magento/TestModuleInventoryStateCache/etc/frontend/di.xml deleted file mode 100644 index d80e6b7d3a20..000000000000 --- a/dev/tests/api-functional/_files/Magento/TestModuleInventoryStateCache/etc/frontend/di.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - diff --git a/dev/tests/integration/_files/Magento/TestModuleInventoryStateCache/etc/events.xml b/dev/tests/integration/_files/Magento/TestModuleInventoryStateCache/etc/events.xml deleted file mode 100644 index c6fbdeda3344..000000000000 --- a/dev/tests/integration/_files/Magento/TestModuleInventoryStateCache/etc/events.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - diff --git a/dev/tests/integration/_files/Magento/TestModuleInventoryStateCache/etc/module.xml b/dev/tests/integration/_files/Magento/TestModuleInventoryStateCache/etc/module.xml deleted file mode 100644 index 15ecb879bc0e..000000000000 --- a/dev/tests/integration/_files/Magento/TestModuleInventoryStateCache/etc/module.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - diff --git a/dev/tests/integration/_files/Magento/TestModuleInventoryStateCache/registration.php b/dev/tests/integration/_files/Magento/TestModuleInventoryStateCache/registration.php deleted file mode 100644 index 52748b494de3..000000000000 --- a/dev/tests/integration/_files/Magento/TestModuleInventoryStateCache/registration.php +++ /dev/null @@ -1,13 +0,0 @@ -getPath(ComponentRegistrar::MODULE, 'Magento_TestModuleInventoryStateCache') === null) { - ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Magento_TestModuleInventoryStateCache', __DIR__); -} From 32f5a77bf966a50246c7e4b8cdcb7172f78b70c8 Mon Sep 17 00:00:00 2001 From: Olga Moyseyenko Date: Tue, 14 Apr 2026 15:34:34 -0500 Subject: [PATCH 13/83] ACP2E-4741: [CLOUD] Gift card and related not sellable WF-1688 --- .../Indexer/Stock/SkuListsProcessorTest.php | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/InventoryIndexer/Test/Integration/Indexer/Stock/SkuListsProcessorTest.php b/InventoryIndexer/Test/Integration/Indexer/Stock/SkuListsProcessorTest.php index 4b271b75e8aa..82d1e56db9f2 100644 --- a/InventoryIndexer/Test/Integration/Indexer/Stock/SkuListsProcessorTest.php +++ b/InventoryIndexer/Test/Integration/Indexer/Stock/SkuListsProcessorTest.php @@ -22,6 +22,7 @@ use Magento\InventorySalesApi\Test\Fixture\StockSalesChannels as StockSalesChannelsFixture; use Magento\TestFramework\Fixture\AppIsolation; use Magento\TestFramework\Fixture\DataFixture; +use Magento\TestFramework\Fixture\DataFixtureStorageManager as DataFixtureStorageManager; use Magento\TestFramework\Fixture\DbIsolation; use Magento\TestFramework\Helper\Bootstrap; use PHPUnit\Framework\TestCase; @@ -67,6 +68,11 @@ class SkuListsProcessorTest extends TestCase */ private $resource; + /** + * @var int + */ + private $stockId; + protected function setUp(): void { $this->sourceItemIndexer = Bootstrap::getObjectManager()->get(SourceItemIndexer::class); @@ -79,11 +85,13 @@ protected function setUp(): void } /** - * We broke transaction during indexation so we need to clean db state manually + * @inheritdoc */ protected function tearDown(): void { - $this->removeIndexData->execute([2]); + $this->removeIndexData->execute([$this->stockId]); + + parent::tearDown(); } /** @@ -119,15 +127,20 @@ protected function tearDown(): void ] public function testReindexListForRelatedProducts() { + $fixtures = DataFixtureStorageManager::getStorage(); + + $stock = $fixtures->get('stock2'); + $this->stockId = $stock->getStockID(); + $tableName = 'inventory_stock_' . $this->stockId; + $connection = $this->resource->getConnection(); $select = $connection->select() - ->from($this->resource->getTableName('inventory_stock_2')) + ->from($this->resource->getTableName($tableName)) ->order('sku ASC'); $inventoryData = $connection->fetchAll($select); // All products should be in inventory_stock_2 table, none should be deleted at reindex. // Reindex is triggered when source is assigned to products - assertCount(4, $inventoryData, 'All 4 products should be present in inventory_stock_2 table'); + assertCount(4, $inventoryData, 'All 4 products should be present in' . $tableName . ' table'); } } - From 8035dafd8a56dbc3e84914b306e756405374c0ee Mon Sep 17 00:00:00 2001 From: Alexandra Zota Date: Wed, 15 Apr 2026 14:34:02 +0300 Subject: [PATCH 14/83] ACP2E-4805: Configurable Product's performance impact on checkout (totals-information, estimate-shipping-modules) --- .../IsConfigurableProductChildrenSalable.php | 88 ------------------- .../GetIsQtySalableForConfigurableProduct.php | 60 ------------- InventoryConfigurableProduct/etc/di.xml | 3 - 3 files changed, 151 deletions(-) delete mode 100644 InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductChildrenSalable.php delete mode 100644 InventoryConfigurableProduct/Plugin/InventorySales/Model/IsProductSalableCondition/GetIsQtySalableForConfigurableProduct.php diff --git a/InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductChildrenSalable.php b/InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductChildrenSalable.php deleted file mode 100644 index 5d08fdd76927..000000000000 --- a/InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductChildrenSalable.php +++ /dev/null @@ -1,88 +0,0 @@ -configurable = $configurable; - $this->areProductsSalable = $areProductsSalable; - $this->getProductIdsBySkus = $getProductIdsBySkus; - $this->getSkusByProductIds = $getSkusByProductIds; - } - - /** - * Get configurable product salable status based on children products salable status - * - * Returns TRUE if: - * - * - at least one child is salable - * - * @param string $sku - * @param int $stockId - * @return bool - * @throws \Magento\Framework\Exception\NoSuchEntityException - */ - public function execute(string $sku, int $stockId): bool - { - $isSalable = false; - $productId = $this->getProductIdsBySkus->execute([$sku])[$sku]; - $ids = $this->configurable->getChildrenIds($productId); - $childrenSkus = $this->getSkusByProductIds->execute($ids[0]); - // check associated products salability one by one rather in batch for performance reason - foreach ($childrenSkus as $childSku) { - $results = $this->areProductsSalable->execute([$childSku], $stockId); - $result = reset($results); - if ($result && $result->isSalable()) { - $isSalable = true; - break; - } - } - - return $isSalable; - } -} diff --git a/InventoryConfigurableProduct/Plugin/InventorySales/Model/IsProductSalableCondition/GetIsQtySalableForConfigurableProduct.php b/InventoryConfigurableProduct/Plugin/InventorySales/Model/IsProductSalableCondition/GetIsQtySalableForConfigurableProduct.php deleted file mode 100644 index a4578cad6a74..000000000000 --- a/InventoryConfigurableProduct/Plugin/InventorySales/Model/IsProductSalableCondition/GetIsQtySalableForConfigurableProduct.php +++ /dev/null @@ -1,60 +0,0 @@ -getProductTypesBySkus = $getProductTypesBySkus; - $this->isConfigurableProductChildrenSalable = $isConfigurableProductChildrenSalable; - } - - /** - * Check configurable product salable status based on selections salable status - * - * @param GetIsQtySalableInterface $getIsQtySalable - * @param bool $isSalable - * @param string $sku - * @param int $stockId - * @return bool - * @throws \Magento\Framework\Exception\NoSuchEntityException - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public function afterExecute( - GetIsQtySalableInterface $getIsQtySalable, - bool $isSalable, - string $sku, - int $stockId - ): bool { - return $this->getProductTypesBySkus->execute([$sku])[$sku] === Configurable::TYPE_CODE - ? $this->isConfigurableProductChildrenSalable->execute($sku, $stockId) - : $isSalable; - } -} diff --git a/InventoryConfigurableProduct/etc/di.xml b/InventoryConfigurableProduct/etc/di.xml index 39d2a91f825f..1670a7107c7a 100644 --- a/InventoryConfigurableProduct/etc/di.xml +++ b/InventoryConfigurableProduct/etc/di.xml @@ -46,9 +46,6 @@ - - - From 35d48e7c3e26f65565dd37268b92dc4fc811d757 Mon Sep 17 00:00:00 2001 From: Olga Moyseyenko Date: Thu, 16 Apr 2026 17:45:07 -0500 Subject: [PATCH 15/83] ACP2E-4741: [CLOUD] Gift card and related not sellable WF-1688 --- InventoryApi/Test/Fixture/Stock.php | 18 +++- .../Indexer/Stock/SkuListsProcessorTest.php | 93 ++++++------------- 2 files changed, 42 insertions(+), 69 deletions(-) diff --git a/InventoryApi/Test/Fixture/Stock.php b/InventoryApi/Test/Fixture/Stock.php index e5af48dc95ac..b854822e35df 100644 --- a/InventoryApi/Test/Fixture/Stock.php +++ b/InventoryApi/Test/Fixture/Stock.php @@ -7,6 +7,7 @@ namespace Magento\InventoryApi\Test\Fixture; +use Magento\Framework\App\ResourceConnection; use Magento\Framework\DataObject; use Magento\InventoryApi\Api\Data\StockInterface; use Magento\InventoryApi\Api\StockRepositoryInterface; @@ -30,16 +31,23 @@ class Stock implements RevertibleDataFixtureInterface */ private ProcessorInterface $dataProcessor; + /** + * @var ResourceConnection $resourceConnection + */ + private $resourceConnection; + /** * @param ServiceFactory $serviceFactory * @param ProcessorInterface $dataProcessor */ public function __construct( ServiceFactory $serviceFactory, - ProcessorInterface $dataProcessor + ProcessorInterface $dataProcessor, + ResourceConnection $resourceConnection ) { $this->serviceFactory = $serviceFactory; $this->dataProcessor = $dataProcessor; + $this->resourceConnection = $resourceConnection; } /** @@ -62,8 +70,14 @@ public function apply(array $data = []): ?DataObject */ public function revert(DataObject $data): void { + $stockId = $data['stock_id']; + $service = $this->serviceFactory->create(StockRepositoryInterface::class, 'deleteById'); - $service->execute(['stockId' => $data['stock_id']]); + $service->execute(['stockId' => $stockId]); + + $connection = $this->resourceConnection->getConnection(); + $tableName = 'inventory_stock_' . $stockId; + $connection -> dropTable($tableName); } /** diff --git a/InventoryIndexer/Test/Integration/Indexer/Stock/SkuListsProcessorTest.php b/InventoryIndexer/Test/Integration/Indexer/Stock/SkuListsProcessorTest.php index 82d1e56db9f2..fed799a905d9 100644 --- a/InventoryIndexer/Test/Integration/Indexer/Stock/SkuListsProcessorTest.php +++ b/InventoryIndexer/Test/Integration/Indexer/Stock/SkuListsProcessorTest.php @@ -8,17 +8,12 @@ namespace Magento\InventoryIndexer\Test\Integration\Indexer\Stock; use Magento\Catalog\Test\Fixture\Product as ProductFixture; -use Magento\Framework\Api\SearchCriteriaBuilder; -use Magento\Framework\App\ResourceConnection; -use Magento\InventoryApi\Api\SourceItemRepositoryInterface; use Magento\InventoryApi\Test\Fixture\Source as SourceFixture; use Magento\InventoryApi\Test\Fixture\SourceItems as SourceItemsFixture; use Magento\InventoryApi\Test\Fixture\Stock as StockFixture; use Magento\InventoryApi\Test\Fixture\StockSourceLinks as StockSourceLinksFixture; -use Magento\InventoryIndexer\Indexer\SourceItem\GetSourceItemIds; -use Magento\InventoryIndexer\Indexer\SourceItem\SourceItemIndexer; -use Magento\InventoryIndexer\Test\Integration\Indexer\RemoveIndexData as RemoveIndexData; use Magento\InventoryIndexer\Model\ResourceModel\GetStockItemData; +use Magento\InventorySalesApi\Model\GetStockItemDataInterface; use Magento\InventorySalesApi\Test\Fixture\StockSalesChannels as StockSalesChannelsFixture; use Magento\TestFramework\Fixture\AppIsolation; use Magento\TestFramework\Fixture\DataFixture; @@ -26,77 +21,24 @@ use Magento\TestFramework\Fixture\DbIsolation; use Magento\TestFramework\Helper\Bootstrap; use PHPUnit\Framework\TestCase; -use function PHPUnit\Framework\assertCount; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class SkuListsProcessorTest extends TestCase { - /** - * @var SourceItemIndexer - */ - private $sourceItemIndexer; - /** * @var GetStockItemData */ private $getStockItemData; - /** - * @var GetSourceItemIds - */ - private $getSourceItemIds; - - /** - * @var RemoveIndexData - */ - private $removeIndexData; - - /** - * @var SourceItemRepositoryInterface - */ - private $sourceItemRepository; - - /** - * @var SearchCriteriaBuilder - */ - private $searchCriteriaBuilder; - - /** - * @var ResourceConnection - */ - private $resource; - - /** - * @var int - */ - private $stockId; - protected function setUp(): void { - $this->sourceItemIndexer = Bootstrap::getObjectManager()->get(SourceItemIndexer::class); $this->getStockItemData = Bootstrap::getObjectManager()->get(GetStockItemData::class); - $this->getSourceItemIds = Bootstrap::getObjectManager()->get(GetSourceItemIds::class); - $this->sourceItemRepository = Bootstrap::getObjectManager()->get(SourceItemRepositoryInterface::class); - $this->searchCriteriaBuilder = Bootstrap::getObjectManager()->get(SearchCriteriaBuilder::class); - $this->removeIndexData = Bootstrap::getObjectManager()->get(RemoveIndexData::class); - $this->resource = Bootstrap::getObjectManager()->get(ResourceConnection::class); - } - - /** - * @inheritdoc - */ - protected function tearDown(): void - { - $this->removeIndexData->execute([$this->stockId]); - - parent::tearDown(); } /** * Product should stay in inventory stock if related product is updated and reindex is run. - * */ #[ DbIsolation(false), @@ -130,17 +72,34 @@ public function testReindexListForRelatedProducts() $fixtures = DataFixtureStorageManager::getStorage(); $stock = $fixtures->get('stock2'); - $this->stockId = $stock->getStockID(); - $tableName = 'inventory_stock_' . $this->stockId; + $stockId = $stock->getStockId(); - $connection = $this->resource->getConnection(); - $select = $connection->select() - ->from($this->resource->getTableName($tableName)) - ->order('sku ASC'); - $inventoryData = $connection->fetchAll($select); + $sku1 = $fixtures->get('p1')->getSku(); + $sku2 = $fixtures->get('p2')->getSku(); + $sku3 = $fixtures->get('p3')->getSku(); + $sku4 = $fixtures->get('p4')->getSku(); // All products should be in inventory_stock_2 table, none should be deleted at reindex. // Reindex is triggered when source is assigned to products - assertCount(4, $inventoryData, 'All 4 products should be present in' . $tableName . ' table'); + self::assertEquals( + [GetStockItemDataInterface::QUANTITY => 100, GetStockItemDataInterface::IS_SALABLE => 1], + $this->getStockItemData->execute($sku1, $stockId), + "First product should be present in inventory_stock_" . $stockId + ); + self::assertEquals( + [GetStockItemDataInterface::QUANTITY => 200, GetStockItemDataInterface::IS_SALABLE => 1], + $this->getStockItemData->execute($sku2, $stockId), + "Second product should be present in inventory_stock_" . $stockId + ); + self::assertEquals( + [GetStockItemDataInterface::QUANTITY => 300, GetStockItemDataInterface::IS_SALABLE => 1], + $this->getStockItemData->execute($sku3, $stockId), + "Third product should be present in inventory_stock_" . $stockId + ); + self::assertEquals( + [GetStockItemDataInterface::QUANTITY => 400, GetStockItemDataInterface::IS_SALABLE => 1], + $this->getStockItemData->execute($sku4, $stockId), + "Fourth product should be present in inventory_stock_" . $stockId + ); } } From c61a326441f4b7cdccbd1952d204b0d80ce49474 Mon Sep 17 00:00:00 2001 From: Olga Moyseyenko Date: Fri, 17 Apr 2026 12:51:29 -0500 Subject: [PATCH 16/83] ACP2E-4741: [CLOUD] Gift card and related not sellable WF-1688 --- InventoryApi/Test/Fixture/Stock.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InventoryApi/Test/Fixture/Stock.php b/InventoryApi/Test/Fixture/Stock.php index b854822e35df..2d00dd4e46b9 100644 --- a/InventoryApi/Test/Fixture/Stock.php +++ b/InventoryApi/Test/Fixture/Stock.php @@ -77,7 +77,7 @@ public function revert(DataObject $data): void $connection = $this->resourceConnection->getConnection(); $tableName = 'inventory_stock_' . $stockId; - $connection -> dropTable($tableName); + $connection->dropTable($tableName); } /** From 4ce41b7913efa53a592b859407979f35df8389ea Mon Sep 17 00:00:00 2001 From: Alexandra Zota Date: Wed, 29 Apr 2026 16:28:48 +0300 Subject: [PATCH 17/83] ACP2E-4880: Add PR Quality Gates github workflow --- .github/scripts/.gitignore | 3 + .github/scripts/check_copyright.py | 766 +++++++++++ .github/scripts/copyright-template.txt | 4 + .github/scripts/filter-blacklist.sh | 37 + .github/scripts/generate-stubs.sh | 102 ++ .github/scripts/phpcs-noise-filter.txt | 15 + .github/scripts/phpmd-ruleset.xml | 59 + .github/scripts/phpstan-extensions.neon | 17 + .../scripts/phpstan-framework-autoload.php | 39 + .github/scripts/phpstan.neon | 58 + .github/scripts/read-pkg-constraint.sh | 20 + .github/scripts/rector-compat.php | 48 + .../resolve_magento_tool_constraints.py | 323 +++++ .github/scripts/run-phpcs.sh | 33 + .../templates/copyright-private-repo.txt | 15 + .../templates/copyright-public-repo.txt | 4 + .github/workflows/pr-quality-gates.yml | 1170 +++++++++++++++++ 17 files changed, 2713 insertions(+) create mode 100644 .github/scripts/.gitignore create mode 100644 .github/scripts/check_copyright.py create mode 100644 .github/scripts/copyright-template.txt create mode 100755 .github/scripts/filter-blacklist.sh create mode 100755 .github/scripts/generate-stubs.sh create mode 100644 .github/scripts/phpcs-noise-filter.txt create mode 100644 .github/scripts/phpmd-ruleset.xml create mode 100644 .github/scripts/phpstan-extensions.neon create mode 100644 .github/scripts/phpstan-framework-autoload.php create mode 100644 .github/scripts/phpstan.neon create mode 100755 .github/scripts/read-pkg-constraint.sh create mode 100644 .github/scripts/rector-compat.php create mode 100755 .github/scripts/resolve_magento_tool_constraints.py create mode 100755 .github/scripts/run-phpcs.sh create mode 100644 .github/scripts/templates/copyright-private-repo.txt create mode 100644 .github/scripts/templates/copyright-public-repo.txt create mode 100644 .github/workflows/pr-quality-gates.yml diff --git a/.github/scripts/.gitignore b/.github/scripts/.gitignore new file mode 100644 index 000000000000..b908d4cbe37c --- /dev/null +++ b/.github/scripts/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +*.pyc +.DS_Store diff --git a/.github/scripts/check_copyright.py b/.github/scripts/check_copyright.py new file mode 100644 index 000000000000..32189451e14d --- /dev/null +++ b/.github/scripts/check_copyright.py @@ -0,0 +1,766 @@ +#!/usr/bin/env python3 +# +# Copyright 2026 Adobe +# All Rights Reserved. +# +# .github/scripts/check_copyright.py - Magento Copyright Header Checker + +import os +import sys +import re +import click +from pathlib import Path +from typing import List, Tuple +from datetime import datetime +import subprocess + +def _resolve_git_root() -> str: + result = subprocess.run( + ['git', 'rev-parse', '--show-toplevel'], + capture_output=True, text=True, check=False + ) + return result.stdout.strip() if result.returncode == 0 else '.' + +_GIT_ROOT = _resolve_git_root() + +# File extensions and their comment styles. +# Aligned with the PHP update_copyrights.php updater which supports: +# PHP, PHTML, HTML, JS, XML, XSD, CSS, LESS +COMMENT_STYLES = { + # PHP files + '.php': ('\n'), + + # Frontend files + '.js': ('/**\n * ', ' * ', ' */\n'), + '.css': ('/**\n * ', ' * ', ' */\n'), + '.less': ('/**\n * ', ' * ', ' */\n'), + '.scss': ('/**\n * ', ' * ', ' */\n'), + + # Configuration files + '.xml': ('\n\n'), + '.xsd': ('\n\n'), + + # GraphQL schema files + '.graphqls': ('# ', '# ', '\n'), + + # Markup files + '.html': (''), +} + +# Magento-specific exclusion patterns +MAGENTO_EXCLUSIONS = { + 'vendor', # Composer dependencies + 'var', # Cache and temporary files + 'generated', # Auto-generated code + 'pub/static', # Generated static files + 'pub/media', # Media files + # dev/tests is intentionally NOT excluded — Magento test files under + # dev/tests/*/testsuite/ do need copyright headers. + 'lib/web', # Third-party web libraries + 'app/etc', # Configuration files + 'setup/src/Magento/Setup/Fixtures', # Setup fixtures + 'node_modules', # Node.js dependencies + '.git', # Git files + 'phpserver', # PHP server files + 'grunt', # Grunt files + 'dev/tools', # Development tools + 'dev/build', # Build files + 'update', # Update files + 'bin', # Binary files +} + +# Magento module structure patterns +MAGENTO_MODULE_PATTERNS = [ + r'app/code/[^/]+/[^/]+/', # app/code/Vendor/Module/ + r'app/design/[^/]+/[^/]+/[^/]+/', # app/design/area/vendor/theme/ +] + + +def _normalize_copyright(text: str) -> str: + """Normalize copyright text for flexible comparison. + + Strips all comment markers, whitespace and punctuation that varies + between file types, matching the approach used by the Jenkins + SanityCopyrightChecker. + """ + return re.sub(r'[\s#/\*\-<>!?\[\]]+', '', text).lower() + + + +def _is_third_party_file(file_path: str, content: str) -> bool: + """Detect third-party files that should skip copyright validation. + + Matches the Jenkins SanityCopyrightChecker logic: if neither the file + path nor its content mentions 'Magento' or 'Adobe', it is assumed to be + a third-party library file. Checking the path ensures that files inside + Magento module directories (app/code/Magento/...) are never skipped even + when the file content itself contains no such references. + """ + return ('Magento' not in file_path and 'Adobe' not in file_path + and 'Magento' not in content and 'Adobe' not in content) + + +def get_git_creation_year(file_path: str, debug: bool = False, use_current_year: bool = False, + base_sha: str = '') -> int: + """Get the year when file was first added to git.""" + + # In PR mode, check whether the file existed in the base commit. + # git cat-file -e is a single object lookup — no history traversal. + # git status --porcelain only catches unstaged/untracked files, which is + # never the case on CI where the PR branch is already checked out clean. + if use_current_year and base_sha: + try: + result = subprocess.run( + ['git', 'cat-file', '-e', f'{base_sha}:{file_path}'], + capture_output=True, cwd=_GIT_ROOT + ) + if result.returncode != 0: + # File did not exist in base — it is new in this PR. + current_year = datetime.now().year + if debug: + click.echo(f" New file (not in base {base_sha[:8]}): using year {current_year}") + return current_year + if debug: + click.echo(f" File exists in base {base_sha[:8]}: finding original creation year") + except Exception: + pass + + if debug: + click.echo(f" Finding git creation year for: {file_path}") + + # Try multiple git commands to find the creation year + git_commands = [ + ['git', 'log', '--follow', '--format=%ad', '--date=format:%Y', '--reverse', '--', file_path], + ['git', 'log', '--format=%ad', '--date=format:%Y', '--reverse', '--', file_path], + ['git', 'log', '--diff-filter=A', '--format=%ad', '--date=format:%Y', '--', file_path], + ] + + for i, cmd in enumerate(git_commands): + try: + if debug: + click.echo(f" Trying command {i+1}: {' '.join(cmd)}") + + result = subprocess.run(cmd, capture_output=True, text=True, cwd=_GIT_ROOT) + + if result.returncode == 0 and result.stdout.strip(): + years = result.stdout.strip().split('\n') + if years and years[0]: + first_year = int(years[0]) + if debug: + click.echo(f" Found git creation year: {first_year}") + return first_year + except (subprocess.CalledProcessError, ValueError, IndexError) as e: + if debug: + click.echo(f" Command {i+1} failed: {e}") + continue + + # Fallback to file modification time + try: + stat = os.stat(file_path) + fallback_year = datetime.fromtimestamp(stat.st_mtime).year + if debug: + click.echo(f" Using file modification time fallback: {fallback_year}") + return fallback_year + except Exception: + pass + + current_year = datetime.now().year + if debug: + click.echo(f" Using current year fallback: {current_year}") + return current_year + + +def load_template(template_path: str) -> str: + """Load the copyright template.""" + try: + with open(template_path, 'r', encoding='utf-8') as f: + return f.read().strip() + except FileNotFoundError: + click.echo(f"Template file not found: {template_path}", err=True) + sys.exit(1) + + +def format_copyright_header(template: str, file_path: str, comment_style: Tuple[str, str, str], + year: str, debug: bool = False) -> str: + """Format copyright header for specific file type using the given year.""" + start_comment, line_comment, end_comment = comment_style + + formatted_template = template.replace('{{YEAR}}', year) + + if debug: + click.echo(f" File: {file_path} -> Year: {year}") + + file_ext = Path(file_path).suffix.lower() + + # If template already contains proper comment format (like Adobe templates), use as-is + if formatted_template.strip().startswith('/**') and formatted_template.strip().endswith('*/'): + if file_ext == '.php': + return f"\n" + elif file_ext in ['.xml', '.xsd']: + content = formatted_template.strip()[3:-2].strip() + lines = content.split('\n') + result = ['', '') + return '\n'.join(result) + '\n' + elif file_ext == '.graphqls': + content = formatted_template.strip()[3:-2].strip() + lines = content.split('\n') + result = [] + for line in lines: + line = line.strip() + if line.startswith('*'): + line = line[1:].strip() + if line: + result.append(f'# {line}') + else: + result.append('#') + return '\n'.join(result) + '\n' + elif file_ext == '.html': + content = formatted_template.strip()[3:-2].strip() + lines = content.split('\n') + result = ['') + return '\n'.join(result) + '\n' + else: + return f"{formatted_template}\n" + + # Format according to file type + if file_ext in ['.php', '.phtml']: + lines = formatted_template.split('\n') + result = ['') + return '\n'.join(result) + '\n' + + elif file_ext in ['.xml', '.xsd']: + lines = formatted_template.split('\n') + result = ['', '') + return '\n'.join(result) + '\n' + + elif file_ext in ['.js', '.css', '.less', '.scss']: + lines = formatted_template.split('\n') + result = ['/**'] + for line in lines: + if line.strip(): + result.append(f' * {line}') + else: + result.append(' *') + result.append(' */') + return '\n'.join(result) + '\n' + + elif file_ext == '.graphqls': + lines = formatted_template.split('\n') + result = [] + for line in lines: + if line.strip(): + result.append(f'# {line}') + else: + result.append('#') + return '\n'.join(result) + '\n' + + elif file_ext in ['.html', '.md']: + lines = formatted_template.split('\n') + result = ['') + return '\n'.join(result) + '\n' + + return formatted_template + '\n' + + +def extract_existing_copyright(content: str, comment_style: Tuple[str, str, str]) -> Tuple[str, int]: + """Extract existing copyright header and return it with the number of lines. + + Uses a state machine with explicit block types so that the end-of-block + detection is never applied to the wrong comment style. Three block types: + C_STYLE — /* ... */ or /** ... */ + HTML — (including nested /** */ used in XML files) + HASH — consecutive # lines (Python, shell, YAML) + """ + lines = content.split('\n') + + copyright_patterns = [ + r'\bcopyright\b', + r'\blicensed?\s+under\b', + r'\bspdx-license\b', + r'\ball rights reserved\b', + r'@copyright', + r'@license', + r'\badobe\s+confidential\b', + r'\bcopyright\s+\d{4}\s+(?:adobe|magento)', + r'see\s+copying\.txt', + r'see\s+license', + ] + + def _has_copyright(text: str) -> bool: + return any(re.search(p, text.lower()) for p in copyright_patterns) + + C_STYLE = 'c_style' + HTML = 'html' + HASH = 'hash' + + header_lines: list = [] + line_count = 0 + block_type = None + found_copyright = False + + for i, line in enumerate(lines): + stripped = line.strip() + + # Always skip the PHP opening tag and XML declaration on line 0. + if i == 0 and (stripped.startswith(' 2: + if _has_copyright(stripped): + found_copyright = True + line_count = i + 1 + else: + header_lines = [] + break + continue + + if stripped.startswith(' block. + if stripped.endswith('-->') and len(stripped) > 4: + if _has_copyright(stripped): + found_copyright = True + line_count = i + 1 + else: + header_lines = [] + break + continue + + if stripped.startswith('#'): + block_type = HASH + if _has_copyright(stripped): + found_copyright = True + header_lines.append(line) + line_count = i + 1 + continue + + if stripped == '' and not header_lines: + continue + + # Non-comment content — nothing more to find. + break + + # ── Inside a C-style block /* ... */ ──────────────────────────── + elif block_type == C_STYLE: + header_lines.append(line) + line_count = i + 1 + if _has_copyright(stripped): + found_copyright = True + if stripped.endswith('*/'): + if found_copyright: + break + # Non-copyright C-style block; reset and keep looking. + header_lines = [] + line_count = 0 + block_type = None + + # ── Inside an HTML comment block ──────────────────── + # Lines inside can be free-form text, star-prefixed, or nested /** */. + # We consume everything until --> regardless of line content. + elif block_type == HTML: + header_lines.append(line) + line_count = i + 1 + if _has_copyright(stripped): + found_copyright = True + if stripped.endswith('-->'): + if found_copyright: + break + # Non-copyright HTML block; reset and keep looking. + header_lines = [] + line_count = 0 + block_type = None + + # ── Inside a hash-comment block # lines ───────────────────────── + elif block_type == HASH: + if not stripped.startswith('#'): + # Hash block ended. + if found_copyright: + # The current line is not part of the header. + line_count = i + break + if _has_copyright(stripped): + found_copyright = True + header_lines.append(line) + line_count = i + 1 + + if not found_copyright: + return '', 0 + + return '\n'.join(header_lines), line_count + + +def is_magento_file(file_path: str) -> bool: + """Check if file is part of Magento core or a Magento module.""" + for pattern in MAGENTO_MODULE_PATTERNS: + if re.search(pattern, file_path): + return True + + magento_files = [ + 'registration.php', + 'module.xml', + 'composer.json', + 'requirejs-config.js', + 'web.xml', + ] + + filename = os.path.basename(file_path) + return filename in magento_files + + +def _matches_path_segment(exclusion: str, file_path: str) -> bool: + """Check if exclusion matches as a path segment (not arbitrary substring).""" + normalized = f'/{file_path}' + return f'/{exclusion}/' in normalized or normalized.endswith(f'/{exclusion}') + + +def should_exclude_file(file_path: str, exclude_list: List[str]) -> bool: + """Check if file should be excluded from copyright checking.""" + for excl in exclude_list: + if _matches_path_segment(excl, file_path): + return True + + for excl in MAGENTO_EXCLUSIONS: + if _matches_path_segment(excl, file_path): + return True + + # Exclude test directories outside app/code, but allow dev/tests/*/testsuite/ + # which contains standard Magento test suites that require copyright headers. + if '/tests/' in file_path.lower() and '/app/code/' not in file_path.lower(): + if not re.search(r'dev/tests/[^/]+/testsuite/', file_path.lower()): + return True + + filename = os.path.basename(file_path) + + if any(lib in file_path.lower() for lib in ['jquery', 'prototype', 'scriptaculous', 'mage/lib']): + return True + + if filename.endswith('.min.js') or filename.endswith('.min.css'): + return True + + return False + + +def check_file(file_path: str, template: str, fix: bool = False, dry_run: bool = False, + debug: bool = False, pr_mode: bool = False, base_sha: str = '') -> bool: + """Check and optionally fix copyright header in a file.""" + ext = Path(file_path).suffix.lower() + + if ext not in COMMENT_STYLES: + return True + + try: + with open(file_path, 'r', encoding='utf-8') as f: + content = f.read() + except (UnicodeDecodeError, PermissionError): + return True + + # Skip third-party files that don't reference Magento/Adobe at all, + # matching the Jenkins SanityCopyrightChecker behaviour. + if _is_third_party_file(file_path, content): + if debug: + click.echo(f" Skipping 3rd-party file (no Magento/Adobe reference): {file_path}") + return True + + comment_style = COMMENT_STYLES[ext] + existing_header, header_line_count = extract_existing_copyright(content, comment_style) + + # ── Determine the year to validate against ──────────────────────── + # On GitHub Actions we have full git history, so always use the + # authoritative git creation year. The Jenkins checker trusts the + # year in the file because git is not available there, but here we + # can and should verify it. + year = str(get_git_creation_year(file_path, debug, use_current_year=pr_mode, base_sha=base_sha)) + + expected_header = format_copyright_header(template, file_path, comment_style, year, debug) + + if debug: + click.echo(f" Expected header preview:") + click.echo(f" {expected_header[:100]}...") + click.echo(f" Existing header preview:") + click.echo(f" {existing_header[:100]}...") + click.echo(f" Year used for comparison: {year}") + + # ── Comparison ──────────────────────────────────────────────────── + # Use normalized comparison (strip all comment markers / whitespace) + # so minor formatting differences do not cause failures, matching the + # flexible approach of the Jenkins SanityCopyrightChecker. + expected_norm = _normalize_copyright(expected_header) + existing_norm = _normalize_copyright(existing_header) + + # The expected template must appear within the existing header. + # (Not the reverse -- a nearly-empty header like "php" must not match.) + if ext in ['.xml', '.xsd']: + if '/**' in existing_header or '*/' in existing_header: + if debug: + click.echo(f" XML file has incorrect comment style: {file_path}") + # Fall through to fix / report + elif expected_norm and expected_norm in existing_norm: + return True + else: + if expected_norm and expected_norm in existing_norm: + return True + + # ── No match ────────────────────────────────────────────────────── + + if dry_run: + click.echo(f" Would fix: {file_path}") + return False + + if fix: + lines = content.split('\n') + + preserved_lines = [] + if lines and (lines[0].startswith('#!') or 'coding:' in lines[0] or 'encoding:' in lines[0]): + preserved_lines.append(lines[0]) + + # When there is no existing copyright (header_line_count == 0) but the + # file already has a [label] +# Reads file paths from , removes entries matching any pattern in +# /*.txt, and writes surviving paths to stdout one per line. +# Skipped files are reported to stderr as " + + + + resourceConnection = $resourceConnection + ?? ObjectManager::getInstance()->get(ResourceConnection::class); + // Sort processors by sort order uasort( $this->saleabilityChangesProcessorsPool, @@ -51,6 +63,7 @@ public function __construct( * * @param SkuListInStock[] $skuListInStockList * @return void + * @throws StateException */ public function reindexList(array $skuListInStockList): void { @@ -68,6 +81,9 @@ public function reindexList(array $skuListInStockList): void ->setAlias(IndexAlias::MAIN->value) ->build(); if (!$this->indexStructure->isExist($mainIndexName, $this->connectionName)) { + if ($this->resourceConnection->getConnection($this->connectionName)->getTransactionLevel() > 0) { + continue; + } $this->indexStructure->create($mainIndexName, $this->connectionName); } $this->indexDataFiller->fillIndex($mainIndexName, $skuListInStock, $this->connectionName); From 6d7fafd6ba4c0073dcc292082d831004559119f2 Mon Sep 17 00:00:00 2001 From: arnsaha Date: Mon, 4 May 2026 10:45:48 -0500 Subject: [PATCH 20/83] ACP2E-4866 : Add ReindexCompositeProductsOnLegacyStockItemSavePlugin class Co-Authored-By: Claude Sonnet 4.6 --- ...iteProductsOnLegacyStockItemSavePlugin.php | 63 +++++++++ ...roductsOnLegacyStockItemSavePluginTest.php | 131 ++++++++++++++++++ 2 files changed, 194 insertions(+) create mode 100644 InventoryCatalog/Plugin/CatalogInventory/Model/Stock/StockItemRepository/ReindexCompositeProductsOnLegacyStockItemSavePlugin.php create mode 100644 InventoryCatalog/Test/Unit/Plugin/CatalogInventory/Model/Stock/StockItemRepository/ReindexCompositeProductsOnLegacyStockItemSavePluginTest.php diff --git a/InventoryCatalog/Plugin/CatalogInventory/Model/Stock/StockItemRepository/ReindexCompositeProductsOnLegacyStockItemSavePlugin.php b/InventoryCatalog/Plugin/CatalogInventory/Model/Stock/StockItemRepository/ReindexCompositeProductsOnLegacyStockItemSavePlugin.php new file mode 100644 index 000000000000..c25b1556d58f --- /dev/null +++ b/InventoryCatalog/Plugin/CatalogInventory/Model/Stock/StockItemRepository/ReindexCompositeProductsOnLegacyStockItemSavePlugin.php @@ -0,0 +1,63 @@ +getProductId(); + $skusByIds = $this->getSkusByProductIds->execute([$productId]); + if (!isset($skusByIds[$productId])) { + return $stockItem; + } + $productSku = $skusByIds[$productId]; + + if ($this->getSourceItemsBySku->execute($productSku) === []) { + $this->compositeProductsIndexer->reindexList([$productSku]); + } + + return $stockItem; + } +} diff --git a/InventoryCatalog/Test/Unit/Plugin/CatalogInventory/Model/Stock/StockItemRepository/ReindexCompositeProductsOnLegacyStockItemSavePluginTest.php b/InventoryCatalog/Test/Unit/Plugin/CatalogInventory/Model/Stock/StockItemRepository/ReindexCompositeProductsOnLegacyStockItemSavePluginTest.php new file mode 100644 index 000000000000..106640967577 --- /dev/null +++ b/InventoryCatalog/Test/Unit/Plugin/CatalogInventory/Model/Stock/StockItemRepository/ReindexCompositeProductsOnLegacyStockItemSavePluginTest.php @@ -0,0 +1,131 @@ +getSkusByProductIds = $this->createMock(GetSkusByProductIdsInterface::class); + $this->getSourceItemsBySku = $this->createMock(GetSourceItemsBySku::class); + $this->compositeProductsIndexer = $this->createMock(CompositeProductsIndexer::class); + + $this->plugin = new ReindexCompositeProductsOnLegacyStockItemSavePlugin( + $this->getSkusByProductIds, + $this->getSourceItemsBySku, + $this->compositeProductsIndexer + ); + } + + public function testReindexIsTriggeredWhenProductHasNoSourceItems(): void + { + $productId = 123; + $sku = 'bundle-sku'; + + $stockItem = $this->createMock(StockItemInterface::class); + $stockItem->method('getProductId')->willReturn($productId); + + $this->getSkusByProductIds->expects($this->once()) + ->method('execute') + ->with([$productId]) + ->willReturn([$productId => $sku]); + + $this->getSourceItemsBySku->expects($this->once()) + ->method('execute') + ->with($sku) + ->willReturn([]); + + $this->compositeProductsIndexer->expects($this->once()) + ->method('reindexList') + ->with([$sku]); + + $result = $this->plugin->afterSave( + $this->createMock(StockItemRepository::class), + $stockItem + ); + + $this->assertSame($stockItem, $result); + } + + public function testReindexIsSkippedWhenProductHasSourceItems(): void + { + $productId = 123; + $sku = 'simple-sku'; + + $stockItem = $this->createMock(StockItemInterface::class); + $stockItem->method('getProductId')->willReturn($productId); + + $this->getSkusByProductIds->expects($this->once()) + ->method('execute') + ->with([$productId]) + ->willReturn([$productId => $sku]); + + $sourceItem = $this->createMock(SourceItem::class); + $this->getSourceItemsBySku->expects($this->once()) + ->method('execute') + ->with($sku) + ->willReturn([$sourceItem]); + + $this->compositeProductsIndexer->expects($this->never()) + ->method('reindexList'); + + $result = $this->plugin->afterSave( + $this->createMock(StockItemRepository::class), + $stockItem + ); + + $this->assertSame($stockItem, $result); + } + + public function testReindexIsSkippedWhenProductSkuIsNotFound(): void + { + $productId = 123; + + $stockItem = $this->createMock(StockItemInterface::class); + $stockItem->method('getProductId')->willReturn($productId); + + $this->getSkusByProductIds->expects($this->once()) + ->method('execute') + ->with([$productId]) + ->willReturn([]); + + $this->getSourceItemsBySku->expects($this->never()) + ->method('execute'); + $this->compositeProductsIndexer->expects($this->never()) + ->method('reindexList'); + + $result = $this->plugin->afterSave( + $this->createMock(StockItemRepository::class), + $stockItem + ); + + $this->assertSame($stockItem, $result); + } +} From ee77f97cb1eed9d61b83a3ae283f408f7afd0404 Mon Sep 17 00:00:00 2001 From: Sandesh S Date: Wed, 6 May 2026 18:14:23 +0530 Subject: [PATCH 21/83] ACQE-9572: OfflineDistanceBasedSelectionAlgorithmCustomStockTestTwoItemsDeductionTest - Fixed deprecated assertions, missing waits, config revert, and removed CI reindex/cache operations. --- ...hmCustomStockTestTwoItemsDeductionTest.xml | 115 +++++++----------- 1 file changed, 46 insertions(+), 69 deletions(-) diff --git a/InventoryAdminUi/Test/Mftf/Test/OfflineDistanceBasedSelectionAlgorithmCustomStockTestTwoItemsDeductionTest.xml b/InventoryAdminUi/Test/Mftf/Test/OfflineDistanceBasedSelectionAlgorithmCustomStockTestTwoItemsDeductionTest.xml index f1bb2f26e5f4..35f81d6f2419 100644 --- a/InventoryAdminUi/Test/Mftf/Test/OfflineDistanceBasedSelectionAlgorithmCustomStockTestTwoItemsDeductionTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/OfflineDistanceBasedSelectionAlgorithmCustomStockTestTwoItemsDeductionTest.xml @@ -10,6 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <description value="Check, 'Offline Distance Based Source Selection Algorithm' select corrects source for simple product on custom stock with two items to deduct."/> @@ -17,12 +18,8 @@ <severity value="CRITICAL"/> <group value="msi"/> <group value="multi_mode"/> - <skip> - <issueId value="https://github.com/magento/inventory/issues/2690"/> - </skip> <group value="pr_exclude"/> </annotations> - <before> <!--Enable "Manage Stock", set distance based algorithm to offline and download tables.--> <magentoCLI command="config:set {{TurnOnManageStockConfig.path}} {{TurnOnManageStockConfig.value}}" stepKey="enableManageStock"/> @@ -58,59 +55,32 @@ <actionGroup ref="AssignSourceToProductActionGroup" stepKey="assignUSSource1ToCreatedProduct"> <argument name="sourceCode" value="$$USSource1.source[source_code]$$"/> </actionGroup> + <waitForElementVisible selector="{{AdminProductSourcesGrid.rowQty('1')}}" stepKey="waitForUSSource1QtyField"/> <fillField selector="{{AdminProductSourcesGrid.rowQty('1')}}" userInput="5" stepKey="setUSSource1Quantity"/> <actionGroup ref="AssignSourceToProductActionGroup" stepKey="assignUSSource2ToCreatedProduct"> <argument name="sourceCode" value="$$USSource2.source[source_code]$$"/> </actionGroup> + <waitForElementVisible selector="{{AdminProductSourcesGrid.rowQty('2')}}" stepKey="waitForUSSource2QtyField"/> <fillField selector="{{AdminProductSourcesGrid.rowQty('2')}}" userInput="5" stepKey="setUSSource2Quantity"/> <actionGroup ref="AssignSourceToProductActionGroup" stepKey="assignUASource1ToCreatedProduct"> <argument name="sourceCode" value="$$UASource1.source[source_code]$$"/> </actionGroup> + <waitForElementVisible selector="{{AdminProductSourcesGrid.rowQty('3')}}" stepKey="waitForUASource1QtyField"/> <fillField selector="{{AdminProductSourcesGrid.rowQty('3')}}" userInput="5" stepKey="setUASource1Quantity"/> + <waitForElementClickable selector="{{AdminProductFormActionSection.saveButton}}" stepKey="waitForSaveButton"/> <click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="saveEditedSimpleProduct"/> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> - <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> - <argument name="tags" value=""/> - </actionGroup> </before> <after> + <!--Revert config changes.--> + <magentoCLI command="config:set {{TurnOnManageStockConfig.path}} {{TurnOnManageStockConfig.value}}" stepKey="revertManageStock"/> + <magentoCLI command="config:set cataloginventory/source_selection_distance_based/provider offline" stepKey="revertSelectionAlgorithm"/> <!--Disable created sources.--> <actionGroup ref="DisableAllSourcesActionGroup" stepKey="disableAllSources"/> - <comment userInput="BIC workaround" stepKey="navigateToSourceList"/> - <comment userInput="BIC workaround" stepKey="clearSourcesFilter"/> - <comment userInput="BIC workaround" stepKey="filterUSSource1BySourceCode"/> - <comment userInput="BIC workaround" stepKey="clickEditUSSource1"/> - <comment userInput="BIC workaround" stepKey="waitForUSSource1EditPageLoad"/> - <comment userInput="BIC workaround" stepKey="disableUSSource1"/> - <comment userInput="BIC workaround" stepKey="saveAndCloseUSSource1"/> - - <comment userInput="BIC workaround" stepKey="filterUSSource2BySourceCode"/> - <comment userInput="BIC workaround" stepKey="clickEditUSSource2"/> - <comment userInput="BIC workaround" stepKey="waitForUSSource2EditPageLoad"/> - <comment userInput="BIC workaround" stepKey="disableUSSource2"/> - <comment userInput="BIC workaround" stepKey="saveAndCloseUSSource2"/> - - <comment userInput="BIC workaround" stepKey="filterUASource1BySourceCode"/> - <comment userInput="BIC workaround" stepKey="clickEditUASource1"/> - <comment userInput="BIC workaround" stepKey="waitForUASource1EditPageLoad"/> - <comment userInput="BIC workaround" stepKey="disableUASource1"/> - <comment userInput="BIC workaround" stepKey="saveAndCloseUASource1"/> - <!--Assign Main Website to Default Stock.--> <actionGroup ref="AssignWebsiteToStockActionGroup" stepKey="assignMainWebsiteToDefaultStock"> <argument name="stockName" value="{{_defaultStock.name}}"/> <argument name="websiteName" value="{{_defaultWebsite.name}}"/> </actionGroup> - <comment userInput="BIC workaround" stepKey="navigateToStockListPage"/> - <comment userInput="BIC workaround" stepKey="waitForStockListPageLoad"/> - <comment userInput="BIC workaround" stepKey="searchDefaultStockByName"/> - <comment userInput="BIC workaround" stepKey="clickEditDefaultStock"/> - <comment userInput="BIC workaround" stepKey="waitFroDefaultStockEditPageLoad"/> - <comment userInput="BIC workaround" stepKey="selectDefaultWebsiteAsSalesChannelForDefaultStock"/> - <comment userInput="BIC workaround" stepKey="saveDefaultStock"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <!--Remove category, product, customer and additional stock.--> <deleteData createDataKey="category" stepKey="deleteCategory"/> @@ -118,9 +88,6 @@ <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> <deleteData createDataKey="additionalStock" stepKey="deleteAdditionalStock"/> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> </after> <!--Login Customer.--> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefront"> @@ -134,46 +101,49 @@ <argument name="checkQuantity" value="1"/> </actionGroup> <!--Place Order.--> + <waitForElementClickable selector="{{StorefrontMinicartSection.goToCheckout}}" stepKey="waitForGoToCheckoutClickable"/> <click selector="{{StorefrontMinicartSection.goToCheckout}}" stepKey="goToCheckout"/> - <waitForPageLoad time="30" stepKey="waitForPageLoad1"/> + <waitForPageLoad stepKey="waitForPageLoad1"/> <waitForElementClickable selector="{{CheckoutShippingMethodsSection.firstShippingMethod}}" stepKey="waitForFirstShippingMethodClickable" /> <click selector="{{CheckoutShippingMethodsSection.firstShippingMethod}}" stepKey="selectShippingMethod"/> - <waitForPageLoad time="30" stepKey="waitForPageLoad2"/> + <waitForPageLoad stepKey="waitForPageLoad2"/> <actionGroup ref="StorefrontCheckoutClickNextButtonActionGroup" stepKey="navigateToSecondCheckoutStep"/> - <comment userInput="BIC workaround" stepKey="waitForPageLoad3"/> <actionGroup ref="CheckoutSelectCheckMoneyOrderPaymentActionGroup" stepKey="selectCheckMoneyOrderPayment"/> - <comment userInput="BIC workaround" stepKey="waitForPageLoad4"/> - <see selector="{{CheckoutPaymentSection.billingAddress}}" userInput="{{US_Address_TX.street[0]}}" stepKey="chooseBillingAddress"/> + <waitForText userInput="{{US_Address_TX.street[0]}}" selector="{{CheckoutPaymentSection.billingAddress}}" stepKey="chooseBillingAddress"/> <actionGroup ref="ClickPlaceOrderActionGroup" stepKey="placeOrder"/> - <comment userInput="BIC workaround" stepKey="waitForPageLoad5"/> <grabTextFrom selector="{{CheckoutSuccessMainSection.orderNumber22}}" stepKey="grabOrderNumber"/> - <see selector="{{CheckoutSuccessMainSection.success}}" userInput="Your order number is:" stepKey="checkOrderPlaceSuccessMessage"/> + <waitForText userInput="Your order number is:" selector="{{CheckoutSuccessMainSection.success}}" stepKey="checkOrderPlaceSuccessMessage"/> <!--Create Shipment--> <actionGroup ref="OpenOrderByIdActionGroup" stepKey="openOrder"> <argument name="orderId" value="{$grabOrderNumber}"/> </actionGroup> + <waitForElementClickable selector="{{AdminOrderDetailsMainActionsSection.ship}}" stepKey="waitForShipClickable"/> <click selector="{{AdminOrderDetailsMainActionsSection.ship}}" stepKey="clickShip"/> <!--Verify Distance Based Source Selection Algorithm.--> + <waitForElementClickable selector="{{AdminSourceSelectionFormSection.sourceSelectionAlgorithmToggle}}" stepKey="waitForAlgorithmToggleClickable"/> <click selector="{{AdminSourceSelectionFormSection.sourceSelectionAlgorithmToggle}}" stepKey="openSourceSelectionAlgorithmList"/> + <waitForElementClickable selector="{{AdminSourceSelectionFormSection.selectDistancePriority}}" stepKey="waitForDistancePriorityClickable"/> <click selector="{{AdminSourceSelectionFormSection.selectDistancePriority}}" stepKey="selectDistancePriorityAlgorithm"/> <waitForLoadingMaskToDisappear stepKey="waitForAreaApplied"/> <!--Verify Distance Based Algorithm applied correctly.--> - <see selector="{{AdminSourceSelectionOrderedItemsGrid.rowProductSku('0')}}" userInput="$$simpleProduct.sku$$" stepKey="checkProductSku"/> - <see selector="{{AdminSourceSelectionOrderedItemsGrid.rowQtyToShip('0')}}" userInput="10" stepKey="checkQtyToShip"/> - <see selector="{{AdminSourceSelectionOrderedItemsGrid.rowAvailableSourcesName('0','0')}}" userInput="$$USSource2.source[name]$$" stepKey="checkUSSource2Name"/> + <waitForText userInput="$$simpleProduct.sku$$" selector="{{AdminSourceSelectionOrderedItemsGrid.rowProductSku('0')}}" stepKey="checkProductSku"/> + <waitForText userInput="10" selector="{{AdminSourceSelectionOrderedItemsGrid.rowQtyToShip('0')}}" stepKey="checkQtyToShip"/> + <waitForText userInput="$$USSource2.source[name]$$" selector="{{AdminSourceSelectionOrderedItemsGrid.rowAvailableSourcesName('0','0')}}" stepKey="checkUSSource2Name"/> <seeInField selector="{{AdminSourceSelectionOrderedItemsGrid.rowAvailableSourcesQtyToDeduct('0','0')}}" userInput="5" stepKey="checkUSSource2Qty"/> - <see selector="{{AdminSourceSelectionOrderedItemsGrid.rowAvailableSourcesName('0','1')}}" userInput="$$USSource1.source[name]$$" stepKey="checkUSSource1Name"/> + <waitForText userInput="$$USSource1.source[name]$$" selector="{{AdminSourceSelectionOrderedItemsGrid.rowAvailableSourcesName('0','1')}}" stepKey="checkUSSource1Name"/> <seeInField selector="{{AdminSourceSelectionOrderedItemsGrid.rowAvailableSourcesQtyToDeduct('0','1')}}" userInput="5" stepKey="checkUSSource1Qty"/> - <see selector="{{AdminSourceSelectionOrderedItemsGrid.rowAvailableSourcesName('0','2')}}" userInput="$$UASource1.source[name]$$" stepKey="checkSourceName"/> + <waitForText userInput="$$UASource1.source[name]$$" selector="{{AdminSourceSelectionOrderedItemsGrid.rowAvailableSourcesName('0','2')}}" stepKey="checkSourceName"/> <seeInField selector="{{AdminSourceSelectionOrderedItemsGrid.rowAvailableSourcesQtyToDeduct('0','2')}}" userInput="0" stepKey="checkUASource1Qty"/> <!--Select first source and proceed to shipment.--> + <waitForElementVisible selector="{{AdminSourceSelectionFormSection.sourceSelection}}" stepKey="waitForSourceSelectionForUSSource2"/> <selectOption selector="{{AdminSourceSelectionFormSection.sourceSelection}}" userInput="$$USSource2.source[name]$$" stepKey="selectUSSource2ToCreateShipment"/> + <waitForElementClickable selector="{{AdminSourceSelectionFormSection.proceedToShipment}}" stepKey="waitForProceedToShipmentClickable"/> <click selector="{{AdminSourceSelectionFormSection.proceedToShipment}}" stepKey="createShipment"/> - <waitForPageLoad time="30" stepKey="waitForPageLoad9"/> - <see selector="{{AdminShipmentOrderInformationSection.orderStatus}}" userInput="Pending" stepKey="seeShipmentOrderStatusForUSSource2"/> + <waitForPageLoad stepKey="waitForShipmentPageUSSource2"/> + <waitForText userInput="Pending" selector="{{AdminShipmentOrderInformationSection.orderStatus}}" stepKey="seeShipmentOrderStatusForUSSource2"/> <actionGroup ref="VerifyBasicShipmentInformationActionGroup" stepKey="checkBasicShipmentOrderInfoForUSSource2"> <argument name="customer" value="$$customer$$"/> <argument name="shippingAddress" value="US_Address_TX"/> @@ -182,19 +152,24 @@ <actionGroup ref="SeeProductInShipmentItemsActionGroup" stepKey="checkProductInShipmentForUSSource2"> <argument name="product" value="$$simpleProduct$$"/> </actionGroup> - <see selector="{{AdminShipmentInventorySection.sourceList}}" userInput="$$USSource2.source[name]$$" stepKey="checkSourceNameOnShipmentPageForUSSource2"/> + <waitForText userInput="$$USSource2.source[name]$$" selector="{{AdminShipmentInventorySection.sourceList}}" stepKey="checkSourceNameOnShipmentPageForUSSource2"/> <!--Submit and verify shipment.--> + <waitForElementClickable selector="{{AdminShipmentMainActionsSection.submitShipment}}" stepKey="waitForSubmitShipmentForUSSource2"/> <click selector="{{AdminShipmentMainActionsSection.submitShipment}}" stepKey="clickSubmitShipmentForUSSource2"/> + <waitForPageLoad stepKey="waitForOrderPageAfterUSSource2Shipment"/> <seeInCurrentUrl url="{{AdminOrderDetailsPage.url}}" stepKey="seeViewOrderPageShippingForUSSource2"/> - <see selector="{{AdminOrderDetailsMessagesSection.successMessage}}" userInput="The shipment has been created." stepKey="checkShipmentCreateSuccessMessageForUSSource2"/> - <see selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="Processing" stepKey="checkOrderStatusForUSSource2"/> - <see selector="{{AdminOrderItemsOrderedSection.itemQty('1')}}" userInput="Shipped 5" stepKey="checkShippedQuantityForUSSource2"/> + <waitForText userInput="The shipment has been created." selector="{{AdminOrderDetailsMessagesSection.successMessage}}" stepKey="checkShipmentCreateSuccessMessageForUSSource2"/> + <waitForText userInput="Processing" selector="{{AdminOrderDetailsInformationSection.orderStatus}}" stepKey="checkOrderStatusForUSSource2"/> + <waitForText userInput="Shipped 5" selector="{{AdminOrderItemsOrderedSection.itemQty('1')}}" stepKey="checkShippedQuantityForUSSource2"/> <!--Select second source and proceed to shipment.--> + <waitForElementClickable selector="{{AdminOrderDetailsMainActionsSection.ship}}" stepKey="waitForShipForUSSource1Clickable"/> <click selector="{{AdminOrderDetailsMainActionsSection.ship}}" stepKey="clickShipForUSSource1"/> + <waitForElementVisible selector="{{AdminSourceSelectionFormSection.sourceSelection}}" stepKey="waitForSourceSelectionForUSSource1"/> <selectOption selector="{{AdminSourceSelectionFormSection.sourceSelection}}" userInput="$$USSource1.source[name]$$" stepKey="selectUSSource1ToCreateShipment"/> + <waitForElementClickable selector="{{AdminSourceSelectionFormSection.proceedToShipment}}" stepKey="waitForProceedToShipmentForUSSource1Clickable"/> <click selector="{{AdminSourceSelectionFormSection.proceedToShipment}}" stepKey="createShipmentForUSSource1"/> - <waitForPageLoad time="30" stepKey="waitForPageLoadForUSSource1"/> - <see selector="{{AdminShipmentOrderInformationSection.orderStatus}}" userInput="Processing" stepKey="seeShipmentOrderStatusForUSSource1"/> + <waitForPageLoad stepKey="waitForPageLoadForUSSource1"/> + <waitForText userInput="Processing" selector="{{AdminShipmentOrderInformationSection.orderStatus}}" stepKey="seeShipmentOrderStatusForUSSource1"/> <actionGroup ref="VerifyBasicShipmentInformationActionGroup" stepKey="checkBasicShipmentOrderInfoForUSSource1"> <argument name="customer" value="$$customer$$"/> <argument name="shippingAddress" value="US_Address_TX"/> @@ -203,22 +178,24 @@ <actionGroup ref="SeeProductInShipmentItemsActionGroup" stepKey="checkProductInShipmentForUSSource1"> <argument name="product" value="$$simpleProduct$$"/> </actionGroup> - <see selector="{{AdminShipmentInventorySection.sourceList}}" userInput="$$USSource1.source[name]$$" stepKey="checkSourceNameOnShipmentPageForUSSource1"/> + <waitForText userInput="$$USSource1.source[name]$$" selector="{{AdminShipmentInventorySection.sourceList}}" stepKey="checkSourceNameOnShipmentPageForUSSource1"/> <!--Submit and verify shipment.--> + <waitForElementClickable selector="{{AdminShipmentMainActionsSection.submitShipment}}" stepKey="waitForSubmitShipmentForUSSource1"/> <click selector="{{AdminShipmentMainActionsSection.submitShipment}}" stepKey="clickSubmitShipmentForUSSource1"/> + <waitForPageLoad stepKey="waitForOrderPageAfterUSSource1Shipment"/> <seeInCurrentUrl url="{{AdminOrderDetailsPage.url}}" stepKey="seeViewOrderPageShippingForUSSource1"/> - <see selector="{{AdminOrderDetailsMessagesSection.successMessage}}" userInput="The shipment has been created." stepKey="checkShipmentCreateSuccessMessageForUSSource1"/> - <see selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="Processing" stepKey="checkOrderStatusForUSSource1"/> - <see selector="{{AdminOrderItemsOrderedSection.itemQty('1')}}" userInput="Shipped 10" stepKey="checkShippedQuantityForUSSource1"/> + <waitForText userInput="The shipment has been created." selector="{{AdminOrderDetailsMessagesSection.successMessage}}" stepKey="checkShipmentCreateSuccessMessageForUSSource1"/> + <waitForText userInput="Processing" selector="{{AdminOrderDetailsInformationSection.orderStatus}}" stepKey="checkOrderStatusForUSSource1"/> + <waitForText userInput="Shipped 10" selector="{{AdminOrderItemsOrderedSection.itemQty('1')}}" stepKey="checkShippedQuantityForUSSource1"/> <!--Verify product quantity.--> <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndexPageForCheckProductQtyAfterCreateShipment"/> <actionGroup ref="AdminGridFilterSearchResultsByInput" stepKey="findSimpleProductBySkuToCheckQtyAfterCreateShipment"> <argument name="selector" value="AdminProductGridFilterSection.skuFilter"/> <argument name="value" value="$$simpleProduct.sku$$"/> </actionGroup> - <see selector="{{AdminProductGridSection.productQtyPerSource('1',$$USSource2.source[name]$$)}}" userInput="0" stepKey="checkUSSource2QtyAfterCreateShipment"/> - <see selector="{{AdminProductGridSection.productQtyPerSource('1',$$USSource1.source[name]$$)}}" userInput="0" stepKey="checkUSSource1QtyAfterCreateShipment"/> - <see selector="{{AdminProductGridSection.productQtyPerSource('1',$$UASource1.source[name]$$)}}" userInput="5" stepKey="checkUASource1QtyAfterCreateShipment"/> - <see selector="{{AdminProductGridSection.productSalableQty('1',$$additionalStock.stock[name]$$)}}" userInput="5" stepKey="checkSalableQtyAfterCreateShipment"/> + <waitForText userInput="0" selector="{{AdminProductGridSection.productQtyPerSource('1',$$USSource2.source[name]$$)}}" stepKey="checkUSSource2QtyAfterCreateShipment"/> + <waitForText userInput="0" selector="{{AdminProductGridSection.productQtyPerSource('1',$$USSource1.source[name]$$)}}" stepKey="checkUSSource1QtyAfterCreateShipment"/> + <waitForText userInput="5" selector="{{AdminProductGridSection.productQtyPerSource('1',$$UASource1.source[name]$$)}}" stepKey="checkUASource1QtyAfterCreateShipment"/> + <waitForText userInput="5" selector="{{AdminProductGridSection.productSalableQty('1',$$additionalStock.stock[name]$$)}}" stepKey="checkSalableQtyAfterCreateShipment"/> </test> </tests> From bc83fc35ae6217c319d86da4eb540dae2dcb49fc Mon Sep 17 00:00:00 2001 From: del72683 <del72683@adobe.com> Date: Thu, 7 May 2026 11:45:35 +0530 Subject: [PATCH 22/83] AC-16488::Hardcoded Fixture Paths Fail in Composer Builds [test suite] --- .../Integration/Indexer/PriceIndexerTest.php | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/InventoryBundleProductIndexer/Test/Integration/Indexer/PriceIndexerTest.php b/InventoryBundleProductIndexer/Test/Integration/Indexer/PriceIndexerTest.php index 10f29d22607a..4a973aa6a58d 100644 --- a/InventoryBundleProductIndexer/Test/Integration/Indexer/PriceIndexerTest.php +++ b/InventoryBundleProductIndexer/Test/Integration/Indexer/PriceIndexerTest.php @@ -39,6 +39,16 @@ DataFixture(StoreFixture::class, ['store_group_id' => '$group2.id$'], 'store2'), DataFixture(SourceFixture::class, as: 'source2'), DataFixture(StockFixture::class, as: 'stock2'), + DataFixture( + StockSourceLinksFixture::class, + [ + ['stock_id' => '$stock2.stock_id$', 'source_code' => '$source2.source_code$'], + ] + ), + DataFixture( + StockSalesChannelsFixture::class, + ['stock_id' => '$stock2.stock_id$', 'sales_channels' => ['$website2.code$']] + ), DataFixture(ProductFixture::class, ['website_ids' => ['1', '$website2.id$'], 'price' => 10], 'product1'), DataFixture(ProductFixture::class, ['website_ids' => ['1', '$website2.id$'], 'price' => 20], 'product2'), DataFixture(ProductFixture::class, ['website_ids' => ['1', '$website2.id$'], 'price' => 5], 'product3'), @@ -52,16 +62,6 @@ ['website_ids' => ['1', '$website2.id$'], 'price' => 8, 'status' => 2], 'product9' ), - DataFixture( - StockSourceLinksFixture::class, - [ - ['stock_id' => '$stock2.stock_id$', 'source_code' => '$source2.source_code$'], - ] - ), - DataFixture( - StockSalesChannelsFixture::class, - ['stock_id' => '$stock2.stock_id$', 'sales_channels' => ['$website2.code$']] - ), DataFixture( SourceItemsFixture::class, [ From 28309a1a2f9cdfd889cf6ad07b740037bd2eb2b9 Mon Sep 17 00:00:00 2001 From: Karishma Thakare <del57145@adobe.com> Date: Thu, 7 May 2026 19:54:33 +0530 Subject: [PATCH 23/83] ACQE-9836: Filter - Sales Order Grid - Added filter clearance code --- ...AdminCancelOrderDownloadableProductCustomStockTest.xml | 3 ++- ...MemoAutoReturnToStockVirtualProductCustomStockTest.xml | 3 ++- ...llInvoiceFullShipmentGroupedProductCustomStockTest.xml | 3 ++- ...tialRefundFullInvoiceVirtualProductCustomStockTest.xml | 3 ++- ...lRefundPartialInvoiceVirtualProductCustomStockTest.xml | 3 ++- ...llInvoiceFullShipmentSimpleProductsCustomStockTest.xml | 4 +++- ...CreditMemoTotalRefundBundleProductDefaultStockTest.xml | 3 ++- ...lInvoiceFullShipmentGroupedProductDefaultStockTest.xml | 3 ++- ...otalRefundFullInvoiceGroupedProductCustomStockTest.xml | 3 ++- ...nvoicePartialShipmentGroupedProductCustomStockTest.xml | 3 ++- ...otalRefundFullInvoiceVirtualProductCustomStockTest.xml | 3 ++- ...talRefundVirtualProductCustomOptionCustomStockTest.xml | 3 ++- ...pmentSimpleProductWithCustomOptionDefaultStockTest.xml | 3 ++- ...reateInvoiceForVirtualProductInSingleStockModeTest.xml | 4 +++- ...orOrderWithConfigurableProductFromCustomSourceTest.xml | 8 +++++++- ...pmentForOrderWithSimpleProductFromCustomSourceTest.xml | 3 ++- ...ForWholeOrderWithSimpleProductFromCustomSourceTest.xml | 8 +++++++- ...oupedProductWithChildsProductOnNonDefaultStockTest.xml | 4 +++- ...DeductItemsInShipmentForOrderWithSimpleProductTest.xml | 8 +++++++- ...AdminCreateInvoiceWithSimpleProductCustomStockTest.xml | 4 +++- ...dminCreateShipmentWithSimpleProductCustomStockTest.xml | 4 +++- 21 files changed, 62 insertions(+), 21 deletions(-) diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCancelOrderDownloadableProductCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCancelOrderDownloadableProductCustomStockTest.xml index 4305b35186b2..643b6893a186 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCancelOrderDownloadableProductCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCancelOrderDownloadableProductCustomStockTest.xml @@ -25,7 +25,8 @@ <after> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> <deleteData createDataKey="customer" stepKey="deleteCustomer" after="deleteCustomStock"/> - </after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> +</after> <!-- Login as customer --> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefront"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoAutoReturnToStockVirtualProductCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoAutoReturnToStockVirtualProductCustomStockTest.xml index 57c4e2b35d57..3e9addf87a09 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoAutoReturnToStockVirtualProductCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoAutoReturnToStockVirtualProductCustomStockTest.xml @@ -55,7 +55,8 @@ <comment userInput="BIC workaround" stepKey="revertAutoReturnItems" after="deleteProduct"/> <comment userInput="BIC workaround" stepKey="reindex" after="revertAutoReturnItems"/> <comment userInput="BIC workaround" stepKey="flushCache" after="reindex"/> - </after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> +</after> <!--Assign virtual product to additional source.--> <actionGroup ref="AssignSourceToProductActionGroup" stepKey="assignTestSourceToCreatedProduct" after="openProductEditPage"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundFullInvoiceFullShipmentGroupedProductCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundFullInvoiceFullShipmentGroupedProductCustomStockTest.xml index ee88ae0f1cbb..bd2693ec26dd 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundFullInvoiceFullShipmentGroupedProductCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundFullInvoiceFullShipmentGroupedProductCustomStockTest.xml @@ -35,7 +35,8 @@ <argument name="websiteName" value="{{_defaultWebsite.name}}"/> </actionGroup> <deleteData createDataKey="additionalStock" after="logoutOfAdmin" stepKey="deleteStock"/> - </after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> +</after> <!--Assign simple product to additional source.--> <actionGroup ref="AssignSourceToProductActionGroup" stepKey="assignTestSourceToCreatedProduct" after="openSimpleProductPage"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundFullInvoiceVirtualProductCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundFullInvoiceVirtualProductCustomStockTest.xml index 6a790684c30f..86e97f880dd5 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundFullInvoiceVirtualProductCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundFullInvoiceVirtualProductCustomStockTest.xml @@ -35,7 +35,8 @@ <argument name="websiteName" value="{{_defaultWebsite.name}}"/> </actionGroup> <deleteData createDataKey="additionalStock" after="logoutOfAdmin" stepKey="deleteStock"/> - </after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> +</after> <!--Assign virtual product to additional source.--> <actionGroup ref="AssignSourceToProductActionGroup" stepKey="assignTestSourceToCreatedProduct" after="openProductEditPage"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundPartialInvoiceVirtualProductCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundPartialInvoiceVirtualProductCustomStockTest.xml index a2096d7b1ebe..392d18285877 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundPartialInvoiceVirtualProductCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundPartialInvoiceVirtualProductCustomStockTest.xml @@ -51,7 +51,8 @@ <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> </actionGroup> - </after> + <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> +</after> <!--Login To storefront as Customer--> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefront"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialReturnToStockAfterFullInvoiceFullShipmentSimpleProductsCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialReturnToStockAfterFullInvoiceFullShipmentSimpleProductsCustomStockTest.xml index 1be33679ac78..64ce0a3f94a3 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialReturnToStockAfterFullInvoiceFullShipmentSimpleProductsCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialReturnToStockAfterFullInvoiceFullShipmentSimpleProductsCustomStockTest.xml @@ -72,7 +72,9 @@ <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> </actionGroup> - </after> + <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> +</after> <!--Login on storefront--> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefront"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundBundleProductDefaultStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundBundleProductDefaultStockTest.xml index 6a510d87f1bc..a7114053721b 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundBundleProductDefaultStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundBundleProductDefaultStockTest.xml @@ -32,7 +32,8 @@ <after> <remove keyForRemoval="assignMainWebsiteToDefaultStock"/> <remove keyForRemoval="deleteStock"/> - </after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> +</after> <!--Set 'Default' Source quantity.--> <remove keyForRemoval="assignTestSourceToCreatedProduct"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoiceFullShipmentGroupedProductDefaultStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoiceFullShipmentGroupedProductDefaultStockTest.xml index edfa75374cb8..83b7e6c932be 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoiceFullShipmentGroupedProductDefaultStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoiceFullShipmentGroupedProductDefaultStockTest.xml @@ -50,7 +50,8 @@ <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> </actionGroup> - </after> + <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> +</after> <!--Set default source product quantity.--> <amOnPage url="{{AdminProductEditPage.url($$product.id$$)}}" stepKey="openSimpleProductPage"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoiceGroupedProductCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoiceGroupedProductCustomStockTest.xml index ca646ba8a3d2..633a99987633 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoiceGroupedProductCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoiceGroupedProductCustomStockTest.xml @@ -35,7 +35,8 @@ <argument name="websiteName" value="{{_defaultWebsite.name}}"/> </actionGroup> <deleteData createDataKey="additionalStock" after="logoutOfAdmin" stepKey="deleteStock"/> - </after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> +</after> <!--Assign virtual product to additional source.--> <actionGroup ref="AssignSourceToProductActionGroup" stepKey="assignTestSourceToCreatedProduct" after="openVirtualProductPage"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoicePartialShipmentGroupedProductCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoicePartialShipmentGroupedProductCustomStockTest.xml index b3c5a50166bb..2b06ab5f800c 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoicePartialShipmentGroupedProductCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoicePartialShipmentGroupedProductCustomStockTest.xml @@ -35,7 +35,8 @@ <argument name="websiteName" value="{{_defaultWebsite.name}}"/> </actionGroup> <deleteData createDataKey="additionalStock" after="logoutOfAdmin" stepKey="deleteStock"/> - </after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> +</after> <!--Assign simple product to additional source.--> <actionGroup ref="AssignSourceToProductActionGroup" stepKey="assignTestSourceToCreatedProduct" after="openSimpleProductPage"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoiceVirtualProductCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoiceVirtualProductCustomStockTest.xml index f3740f714075..7d9ee97b0b80 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoiceVirtualProductCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoiceVirtualProductCustomStockTest.xml @@ -35,7 +35,8 @@ <argument name="websiteName" value="{{_defaultWebsite.name}}"/> </actionGroup> <deleteData createDataKey="additionalStock" after="logoutOfAdmin" stepKey="deleteStock"/> - </after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> +</after> <!--Assign virtual product to additional source.--> <actionGroup ref="AssignSourceToProductActionGroup" stepKey="assignTestSourceToCreatedProduct" after="openProductEditPage"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundVirtualProductCustomOptionCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundVirtualProductCustomOptionCustomStockTest.xml index daed3c5e145c..236af10cb73f 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundVirtualProductCustomOptionCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundVirtualProductCustomOptionCustomStockTest.xml @@ -35,7 +35,8 @@ <argument name="websiteName" value="{{_defaultWebsite.name}}"/> </actionGroup> <deleteData createDataKey="additionalStock" after="logoutOfAdmin" stepKey="deleteStock"/> - </after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> +</after> <!--Assign virtual product to additional source.--> <actionGroup ref="AssignSourceToProductActionGroup" stepKey="assignTestSourceToCreatedProduct" after="openProductEditPage"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateFullShipmentSimpleProductWithCustomOptionDefaultStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateFullShipmentSimpleProductWithCustomOptionDefaultStockTest.xml index c213c50749cd..82c9fe22081e 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateFullShipmentSimpleProductWithCustomOptionDefaultStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateFullShipmentSimpleProductWithCustomOptionDefaultStockTest.xml @@ -49,7 +49,8 @@ <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> </actionGroup> - </after> + <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> +</after> <!--Add custom option to product.--> <amOnPage url="{{AdminProductEditPage.url($$product.id$$)}}" stepKey="openProductEditPage"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateInvoiceForVirtualProductInSingleStockModeTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateInvoiceForVirtualProductInSingleStockModeTest.xml index 4aae6d687b6e..e1d60edc05dd 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateInvoiceForVirtualProductInSingleStockModeTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateInvoiceForVirtualProductInSingleStockModeTest.xml @@ -34,7 +34,9 @@ <deleteData createDataKey="product" stepKey="deleteProduct"/> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> - </after> + <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> +</after> <comment userInput="Assign category to created virtual product." stepKey="assignCategoryToProductComment"/> <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndexPageForEditProduct"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialShipmentForOrderWithConfigurableProductFromCustomSourceTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialShipmentForOrderWithConfigurableProductFromCustomSourceTest.xml index f02b76e9b3db..8c3a9b5e0083 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialShipmentForOrderWithConfigurableProductFromCustomSourceTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialShipmentForOrderWithConfigurableProductFromCustomSourceTest.xml @@ -156,7 +156,13 @@ <actionGroup ref="CliCacheCleanActionGroup" stepKey="cleanCache"> <argument name="tags" value="full_page"/> </actionGroup> - </after> + <amOnPage url="{{AdminManageStockPage.url}}" stepKey="goToInventoryStockGridToClearFilters"/> + <waitForPageLoad stepKey="waitForInventoryStockGridToLoad"/> + <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clearInventoryStockGridFilters"/> + <waitForPageLoad stepKey="waitAfterClearInventoryStockFilters"/> + <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> +</after> <!-- Login as Customer and add Product to Cart--> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="customerLogin"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialShipmentForOrderWithSimpleProductFromCustomSourceTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialShipmentForOrderWithSimpleProductFromCustomSourceTest.xml index d4b162c960cf..fdb92e527b86 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialShipmentForOrderWithSimpleProductFromCustomSourceTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialShipmentForOrderWithSimpleProductFromCustomSourceTest.xml @@ -86,7 +86,8 @@ <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <!-- Delete all products via API --> <helper class="Magento\Catalog\Test\Mftf\Helper\ProductApiHelper" method="deleteAllProductsApi" stepKey="deleteAllProductsViaApi"/> - </after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> +</after> <!-- Login as Customer and add Product to Cart--> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="customerLogin"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateShipmentForWholeOrderWithSimpleProductFromCustomSourceTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateShipmentForWholeOrderWithSimpleProductFromCustomSourceTest.xml index c2f640de4780..c2cb8e4be050 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateShipmentForWholeOrderWithSimpleProductFromCustomSourceTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateShipmentForWholeOrderWithSimpleProductFromCustomSourceTest.xml @@ -102,7 +102,13 @@ <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - </after> + <amOnPage url="{{AdminManageStockPage.url}}" stepKey="goToInventoryStockGridToClearFilters"/> + <waitForPageLoad stepKey="waitForInventoryStockGridToLoad"/> + <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clearInventoryStockGridFilters"/> + <waitForPageLoad stepKey="waitAfterClearInventoryStockFilters"/> + <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> +</after> <!-- Login as Customer and add Product to Cart--> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="customerLogin"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminInvoiceCreatedForWholeOrderWithGroupedProductWithChildsProductOnNonDefaultStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminInvoiceCreatedForWholeOrderWithGroupedProductWithChildsProductOnNonDefaultStockTest.xml index 855687331df1..187e01d64f22 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminInvoiceCreatedForWholeOrderWithGroupedProductWithChildsProductOnNonDefaultStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminInvoiceCreatedForWholeOrderWithGroupedProductWithChildsProductOnNonDefaultStockTest.xml @@ -54,7 +54,9 @@ <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> </actionGroup> - </after> + <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> +</after> <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="openProductGrid1"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminManualSelectingOfSourcesToDeductItemsInShipmentForOrderWithSimpleProductTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminManualSelectingOfSourcesToDeductItemsInShipmentForOrderWithSimpleProductTest.xml index cfa0eed59c29..a056430ab3ad 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminManualSelectingOfSourcesToDeductItemsInShipmentForOrderWithSimpleProductTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminManualSelectingOfSourcesToDeductItemsInShipmentForOrderWithSimpleProductTest.xml @@ -104,7 +104,13 @@ <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - </after> + <amOnPage url="{{AdminManageStockPage.url}}" stepKey="goToInventoryStockGridToClearFilters"/> + <waitForPageLoad stepKey="waitForInventoryStockGridToLoad"/> + <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clearInventoryStockGridFilters"/> + <waitForPageLoad stepKey="waitAfterClearInventoryStockFilters"/> + <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> +</after> <!-- Login as Customer and add Product to Cart--> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="customerLogin"> diff --git a/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminCreateInvoiceWithSimpleProductCustomStockTest.xml b/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminCreateInvoiceWithSimpleProductCustomStockTest.xml index 0d5946c89345..8e9e164856f6 100644 --- a/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminCreateInvoiceWithSimpleProductCustomStockTest.xml +++ b/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminCreateInvoiceWithSimpleProductCustomStockTest.xml @@ -83,7 +83,9 @@ <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> </actionGroup> - </after> + <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> +</after> <!--Add product to cart.--> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefront"> diff --git a/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminCreateShipmentWithSimpleProductCustomStockTest.xml b/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminCreateShipmentWithSimpleProductCustomStockTest.xml index 281b0810f8d8..271c20c8ed19 100644 --- a/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminCreateShipmentWithSimpleProductCustomStockTest.xml +++ b/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminCreateShipmentWithSimpleProductCustomStockTest.xml @@ -83,7 +83,9 @@ <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> </actionGroup> - </after> + <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> +</after> <!--Add product to cart.--> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefront"> From d3525a0d838565ffff30e4ae95dc4c794b522855 Mon Sep 17 00:00:00 2001 From: soumah <soumah@adobe.com> Date: Thu, 7 May 2026 12:35:19 -0500 Subject: [PATCH 24/83] ACP2E-4866: Bundle Product stock status inconsistency - Fix CR comments and build failures --- .../Indexer/SelectBuilder.php | 14 +- ...iteProductsOnLegacyStockItemSavePlugin.php | 80 ++++++++++ ...iteProductsOnLegacyStockItemSavePlugin.php | 63 -------- ...teProductReindexOnNonDefaultStockTest.php} | 149 +++++++++--------- ...LegacyStockAfterSourceItemsDeleteTest.php} | 45 +++++- ...LegacyStockItemAtSourceItemsDeleteTest.php | 114 -------------- ...roductsOnLegacyStockItemSavePluginTest.php | 131 --------------- InventoryCatalog/etc/di.xml | 7 +- .../Indexer/SelectBuilder.php | 14 +- .../composer.json | 3 +- .../Indexer/SelectBuilder.php | 13 +- InventoryGroupedProductIndexer/composer.json | 3 +- .../Indexer/Stock/SkuListsProcessor.php | 16 -- 13 files changed, 242 insertions(+), 410 deletions(-) create mode 100644 InventoryCatalog/Plugin/CatalogInventory/Model/ResourceModel/Stock/Item/ReindexCompositeProductsOnLegacyStockItemSavePlugin.php delete mode 100644 InventoryCatalog/Plugin/CatalogInventory/Model/Stock/StockItemRepository/ReindexCompositeProductsOnLegacyStockItemSavePlugin.php rename InventoryCatalog/Test/Integration/{ReindexBundleOnNonDefaultStockAfterLegacyStockItemSaveTest.php => CompositeProductReindexOnNonDefaultStockTest.php} (52%) rename InventoryCatalog/Test/Integration/{SetOutOfStockToLegacyStockStatusAtSourceItemsDeleteTest.php => LegacyStockAfterSourceItemsDeleteTest.php} (67%) delete mode 100644 InventoryCatalog/Test/Integration/SetToZeroLegacyStockItemAtSourceItemsDeleteTest.php delete mode 100644 InventoryCatalog/Test/Unit/Plugin/CatalogInventory/Model/Stock/StockItemRepository/ReindexCompositeProductsOnLegacyStockItemSavePluginTest.php diff --git a/InventoryBundleProductIndexer/Indexer/SelectBuilder.php b/InventoryBundleProductIndexer/Indexer/SelectBuilder.php index 539b4f15a001..8c48ae8cb020 100644 --- a/InventoryBundleProductIndexer/Indexer/SelectBuilder.php +++ b/InventoryBundleProductIndexer/Indexer/SelectBuilder.php @@ -8,6 +8,7 @@ namespace Magento\InventoryBundleProductIndexer\Indexer; use Magento\Bundle\Model\Product\Type as BundleProductType; +use Magento\CatalogInventory\Api\StockConfigurationInterface; use Magento\Framework\App\ResourceConnection; use Magento\Framework\DB\Select; use Magento\InventoryCatalogApi\Api\DefaultStockProviderInterface; @@ -39,11 +40,13 @@ class SelectBuilder implements SiblingSelectBuilderInterface * @param ResourceConnection $resourceConnection * @param DefaultStockProviderInterface $defaultStockProvider * @param OptionsStatusSelectBuilder $optionsStatusSelectBuilder + * @param StockConfigurationInterface $configuration */ public function __construct( ResourceConnection $resourceConnection, DefaultStockProviderInterface $defaultStockProvider, - OptionsStatusSelectBuilder $optionsStatusSelectBuilder + OptionsStatusSelectBuilder $optionsStatusSelectBuilder, + private readonly StockConfigurationInterface $configuration ) { $this->resourceConnection = $resourceConnection; $this->defaultStockProvider = $defaultStockProvider; @@ -63,6 +66,13 @@ public function getSelect(int $stockId, array $skuList = [], IndexAlias $indexAl '1', '0' ); + + $manageStock = '(legacy_stock_item.use_config_manage_stock = 0 AND legacy_stock_item.manage_stock = 1)'; + if (((int)$this->configuration->getManageStock()) === 1) { + $manageStock .= ' OR legacy_stock_item.use_config_manage_stock = 1'; + $manageStock = "($manageStock)"; + } + $select = $connection->select() ->from( ['product_entity' => $this->resourceConnection->getTableName('catalog_product_entity')], @@ -85,7 +95,7 @@ public function getSelect(int $stockId, array $skuList = [], IndexAlias $indexAl IndexStructure::SKU => 'product_entity.sku', IndexStructure::QUANTITY => $connection->getIfNullSql('SUM(options.quantity)', '0'), IndexStructure::IS_SALABLE => $connection->getCheckSql( - 'legacy_stock_item.is_in_stock = 0 OR options.sku IS NULL', + "(legacy_stock_item.is_in_stock = 0 AND $manageStock) OR options.sku IS NULL", '0', 'MAX(' . $isRequiredOptionUnavailable . ') = 0 AND MAX(options.stock_status) = 1' ), diff --git a/InventoryCatalog/Plugin/CatalogInventory/Model/ResourceModel/Stock/Item/ReindexCompositeProductsOnLegacyStockItemSavePlugin.php b/InventoryCatalog/Plugin/CatalogInventory/Model/ResourceModel/Stock/Item/ReindexCompositeProductsOnLegacyStockItemSavePlugin.php new file mode 100644 index 000000000000..3284a0533424 --- /dev/null +++ b/InventoryCatalog/Plugin/CatalogInventory/Model/ResourceModel/Stock/Item/ReindexCompositeProductsOnLegacyStockItemSavePlugin.php @@ -0,0 +1,80 @@ +<?php +/** + * Copyright 2026 Adobe + * All Rights Reserved. + */ +declare(strict_types=1); + +namespace Magento\InventoryCatalog\Plugin\CatalogInventory\Model\ResourceModel\Stock\Item; + +use Magento\CatalogInventory\Model\ResourceModel\Stock\Item as ItemResourceModel; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Model\AbstractModel; +use Magento\InventoryCatalogApi\Model\GetSkusByProductIdsInterface; +use Magento\InventoryCatalogApi\Model\IsSingleSourceModeInterface; +use Magento\InventoryIndexer\Indexer\CompositeProductsIndexer; +use Throwable; + +/** + * Reindexes non-default stocks for composite products that have no source items + * (e.g. bundles) when the legacy stock item is saved. + * + * Without this plugin, admin-side toggles of bundle Stock Status only update + * inventory_stock_1 (a VIEW over cataloginventory_stock_status) but leave + * inventory_stock_N out of sync because no source-item indexer is triggered. + */ +class ReindexCompositeProductsOnLegacyStockItemSavePlugin +{ + /** + * @param GetSkusByProductIdsInterface $getSkusByProductIds + * @param CompositeProductsIndexer $compositeProductsIndexer + * @param IsSingleSourceModeInterface $isSingleSourceMode + */ + public function __construct( + private readonly GetSkusByProductIdsInterface $getSkusByProductIds, + private readonly CompositeProductsIndexer $compositeProductsIndexer, + private readonly IsSingleSourceModeInterface $isSingleSourceMode + ) { + } + + /** + * Trigger composite reindex on non-default stocks for products without source items. + * + * @param ItemResourceModel $subject + * @param mixed $result + * @param AbstractModel $stockItem + * @return ItemResourceModel + * @throws NoSuchEntityException + * @throws Throwable + */ + public function afterSave( + ItemResourceModel $subject, + ItemResourceModel $result, + AbstractModel $stockItem + ): ItemResourceModel { + if (!$this->isSingleSourceMode->execute()) { + $productId = (int) $stockItem->getProductId(); + try { + $sku = $this->getSkusByProductIds->execute([$productId])[$productId]; + } catch (NoSuchEntityException $e) { + $sku = null; + } + if ($sku !== null) { + $subject->getConnection()->beginTransaction(); + try { + // Makes sure if this save is part of a larger transaction, + // the reindex will be deferred until after commit. + $subject->addCommitCallback(function () use ($sku) { + $this->compositeProductsIndexer->reindexList([$sku]); + }); + $subject->getConnection()->commit(); + } catch (Throwable $e) { + $subject->getConnection()->rollBack(); + throw $e; + } + } + } + + return $result; + } +} diff --git a/InventoryCatalog/Plugin/CatalogInventory/Model/Stock/StockItemRepository/ReindexCompositeProductsOnLegacyStockItemSavePlugin.php b/InventoryCatalog/Plugin/CatalogInventory/Model/Stock/StockItemRepository/ReindexCompositeProductsOnLegacyStockItemSavePlugin.php deleted file mode 100644 index c25b1556d58f..000000000000 --- a/InventoryCatalog/Plugin/CatalogInventory/Model/Stock/StockItemRepository/ReindexCompositeProductsOnLegacyStockItemSavePlugin.php +++ /dev/null @@ -1,63 +0,0 @@ -<?php -/** - * Copyright 2026 Adobe - * All Rights Reserved. - */ -declare(strict_types=1); - -namespace Magento\InventoryCatalog\Plugin\CatalogInventory\Model\Stock\StockItemRepository; - -use Magento\CatalogInventory\Api\Data\StockItemInterface; -use Magento\CatalogInventory\Model\Stock\StockItemRepository; -use Magento\Framework\Exception\NoSuchEntityException; -use Magento\Inventory\Model\SourceItem\Command\GetSourceItemsBySku; -use Magento\InventoryCatalogApi\Model\GetSkusByProductIdsInterface; -use Magento\InventoryIndexer\Indexer\CompositeProductsIndexer; - -/** - * Reindexes non-default stocks for composite products that have no source items - * (e.g. bundles) when the legacy stock item is saved. - * - * Without this plugin, admin-side toggles of bundle Stock Status only update - * inventory_stock_1 (a VIEW over cataloginventory_stock_status) but leave - * inventory_stock_N out of sync because no source-item indexer is triggered. - */ -class ReindexCompositeProductsOnLegacyStockItemSavePlugin -{ - /** - * @param GetSkusByProductIdsInterface $getSkusByProductIds - * @param GetSourceItemsBySku $getSourceItemsBySku - * @param CompositeProductsIndexer $compositeProductsIndexer - */ - public function __construct( - private readonly GetSkusByProductIdsInterface $getSkusByProductIds, - private readonly GetSourceItemsBySku $getSourceItemsBySku, - private readonly CompositeProductsIndexer $compositeProductsIndexer - ) { - } - - /** - * Trigger composite reindex on non-default stocks for products without source items. - * - * @param StockItemRepository $subject - * @param StockItemInterface $stockItem - * @return StockItemInterface - * @throws NoSuchEntityException - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public function afterSave(StockItemRepository $subject, StockItemInterface $stockItem): StockItemInterface - { - $productId = (int) $stockItem->getProductId(); - $skusByIds = $this->getSkusByProductIds->execute([$productId]); - if (!isset($skusByIds[$productId])) { - return $stockItem; - } - $productSku = $skusByIds[$productId]; - - if ($this->getSourceItemsBySku->execute($productSku) === []) { - $this->compositeProductsIndexer->reindexList([$productSku]); - } - - return $stockItem; - } -} diff --git a/InventoryCatalog/Test/Integration/ReindexBundleOnNonDefaultStockAfterLegacyStockItemSaveTest.php b/InventoryCatalog/Test/Integration/CompositeProductReindexOnNonDefaultStockTest.php similarity index 52% rename from InventoryCatalog/Test/Integration/ReindexBundleOnNonDefaultStockAfterLegacyStockItemSaveTest.php rename to InventoryCatalog/Test/Integration/CompositeProductReindexOnNonDefaultStockTest.php index 4958a99301bc..4c8141073fe0 100644 --- a/InventoryCatalog/Test/Integration/ReindexBundleOnNonDefaultStockAfterLegacyStockItemSaveTest.php +++ b/InventoryCatalog/Test/Integration/CompositeProductReindexOnNonDefaultStockTest.php @@ -12,8 +12,9 @@ use Magento\Bundle\Test\Fixture\Product as BundleProductFixture; use Magento\Catalog\Test\Fixture\Product as ProductFixture; use Magento\CatalogInventory\Api\StockRegistryInterface; -use Magento\Framework\Exception\LocalizedException; -use Magento\Framework\Exception\NoSuchEntityException; +use Magento\ConfigurableProduct\Test\Fixture\Attribute as AttributeFixture; +use Magento\ConfigurableProduct\Test\Fixture\Product as ConfigurableProductFixture; +use Magento\GroupedProduct\Test\Fixture\Product as GroupedProductFixture; use Magento\InventoryApi\Test\Fixture\Source as SourceFixture; use Magento\InventoryApi\Test\Fixture\SourceItems as SourceItemsFixture; use Magento\InventoryApi\Test\Fixture\Stock as StockFixture; @@ -28,12 +29,12 @@ use PHPUnit\Framework\TestCase; /** - * Verifies that bundle product salability on non-default stocks is + * Verifies that composite product salability on non-default stocks is * updated when stock status is changed via StockItemRepository. * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class ReindexBundleOnNonDefaultStockAfterLegacyStockItemSaveTest extends TestCase +class CompositeProductReindexOnNonDefaultStockTest extends TestCase { /** * @var StockRegistryInterface @@ -55,7 +56,7 @@ protected function setUp(): void #[ DbIsolation(false), - DataFixture(SourceFixture::class, ['source_code' => 'eu-1'], 'source'), + DataFixture(SourceFixture::class, as: 'source'), DataFixture(StockFixture::class, as: 'stock'), DataFixture( StockSourceLinksFixture::class, @@ -65,7 +66,7 @@ protected function setUp(): void StockSalesChannelsFixture::class, ['stock_id' => '$stock.stock_id$', 'sales_channels' => ['base']] ), - DataFixture(ProductFixture::class, ['sku' => 'bundle-child-simple'], 'child'), + DataFixture(ProductFixture::class, as: 'child'), DataFixture( SourceItemsFixture::class, [['sku' => '$child.sku$', 'source_code' => '$source.source_code$', 'quantity' => 10, 'status' => 1]] @@ -74,55 +75,46 @@ protected function setUp(): void DataFixture(BundleOptionFixture::class, ['product_links' => ['$link$'], 'required' => true], 'opt'), DataFixture( BundleProductFixture::class, - ['sku' => 'bundle-parent', '_options' => ['$opt$'], 'shipment_type' => 1], - 'bundle' + ['_options' => ['$opt$'], 'shipment_type' => 1], + 'parent_product' ), ] - /** - * Asserts that setting is_in_stock=false marks the bundle as not salable on a non-default stock. - * - * @return void - * @throws NoSuchEntityException - * @throws LocalizedException - */ - public function testBundleIsMarkedNotSalableOnNonDefaultStockAfterLegacyStockItemSave(): void + public function testShouldReindexBundleProductStockStatusAfterSave(): void { - $fixtures = DataFixtureStorageManager::getStorage(); - $stock = $fixtures->get('stock'); - $this->assertNotNull($stock, 'Non-default stock fixture must be created'); - - $stockId = (int) $stock->getStockId(); - - $stockItemDataBefore = $this->getStockItemData->execute('bundle-parent', $stockId); - $this->assertNotNull( - $stockItemDataBefore, - 'Bundle must be indexed on the non-default stock before the legacy stock item save' - ); - $this->assertEquals( - 1, - (int) $stockItemDataBefore[GetStockItemDataInterface::IS_SALABLE], - 'Bundle must be salable on non-default stock before setting is_in_stock = false' - ); - - $stockItem = $this->stockRegistry->getStockItemBySku('bundle-parent'); - $stockItem->setIsInStock(false); - $this->stockRegistry->updateStockItemBySku('bundle-parent', $stockItem); + $this->performAssertions(); + } - $stockItemDataAfter = $this->getStockItemData->execute('bundle-parent', $stockId); - $this->assertNotNull( - $stockItemDataAfter, - 'Bundle stock data on the non-default stock must exist after the legacy stock item save' - ); - $this->assertEquals( - 0, - (int) $stockItemDataAfter[GetStockItemDataInterface::IS_SALABLE], - 'Bundle must be marked not salable on non-default stock after admin sets is_in_stock = false' - ); + #[ + DbIsolation(false), + DataFixture(SourceFixture::class, as: 'source'), + DataFixture(StockFixture::class, as: 'stock'), + DataFixture( + StockSourceLinksFixture::class, + [['stock_id' => '$stock.stock_id$', 'source_code' => '$source.source_code$']] + ), + DataFixture( + StockSalesChannelsFixture::class, + ['stock_id' => '$stock.stock_id$', 'sales_channels' => ['base']] + ), + DataFixture(ProductFixture::class, as: 'child'), + DataFixture( + SourceItemsFixture::class, + [['sku' => '$child.sku$', 'source_code' => '$source.source_code$', 'quantity' => 10, 'status' => 1]] + ), + DataFixture( + GroupedProductFixture::class, + ['product_links' => ['$child.sku$']], + 'parent_product' + ), + ] + public function testShouldReindexGroupedProductStockStatusAfterSave(): void + { + $this->performAssertions(); } #[ DbIsolation(false), - DataFixture(SourceFixture::class, ['source_code' => 'eu-2'], 'source'), + DataFixture(SourceFixture::class, as: 'source'), DataFixture(StockFixture::class, as: 'stock'), DataFixture( StockSourceLinksFixture::class, @@ -132,58 +124,71 @@ public function testBundleIsMarkedNotSalableOnNonDefaultStockAfterLegacyStockIte StockSalesChannelsFixture::class, ['stock_id' => '$stock.stock_id$', 'sales_channels' => ['base']] ), - DataFixture(ProductFixture::class, ['sku' => 'bundle-child-simple-2'], 'child'), + DataFixture(ProductFixture::class, as: 'child'), DataFixture( SourceItemsFixture::class, [['sku' => '$child.sku$', 'source_code' => '$source.source_code$', 'quantity' => 10, 'status' => 1]] ), - DataFixture(BundleSelectionFixture::class, ['sku' => '$child.sku$', 'qty' => 1], 'link'), - DataFixture(BundleOptionFixture::class, ['product_links' => ['$link$'], 'required' => true], 'opt'), + DataFixture(AttributeFixture::class, as: 'attr'), DataFixture( - BundleProductFixture::class, - ['sku' => 'bundle-parent-2', '_options' => ['$opt$'], 'shipment_type' => 1], - 'bundle' + ConfigurableProductFixture::class, + ['_options' => ['$attr$'],'_links' => ['$child$']], + 'parent_product' ), ] - /** - * Asserts that restoring is_in_stock=true marks the bundle as salable again on a non-default stock. - * - * @return void - * @throws NoSuchEntityException - * @throws LocalizedException - */ - public function testBundleIsMarkedSalableOnNonDefaultStockAfterLegacyStockItemRestored(): void + public function testShouldReindexConfigurableProductStockStatusAfterSave(): void + { + $this->performAssertions(); + } + + private function performAssertions(): void { $fixtures = DataFixtureStorageManager::getStorage(); $stock = $fixtures->get('stock'); $this->assertNotNull($stock, 'Non-default stock fixture must be created'); + $sku = $fixtures->get('parent_product')->getSku(); $stockId = (int) $stock->getStockId(); - $stockItem = $this->stockRegistry->getStockItemBySku('bundle-parent-2'); + $stockItemDataBefore = $this->getStockItemData->execute($sku, $stockId); + $this->assertNotNull( + $stockItemDataBefore, + $sku . ' must be indexed on the non-default stock before the legacy stock item save' + ); + $this->assertEquals( + 1, + (int)$stockItemDataBefore[GetStockItemDataInterface::IS_SALABLE], + $sku . ' must be salable on non-default stock before setting is_in_stock = false' + ); + + $stockItem = $this->stockRegistry->getStockItemBySku($sku); $stockItem->setIsInStock(false); - $this->stockRegistry->updateStockItemBySku('bundle-parent-2', $stockItem); + $this->stockRegistry->updateStockItemBySku($sku, $stockItem); - $stockItemDataOos = $this->getStockItemData->execute('bundle-parent-2', $stockId); + $stockItemDataAfter = $this->getStockItemData->execute($sku, $stockId); + $this->assertNotNull( + $stockItemDataAfter, + $sku . ' stock data on the non-default stock must exist after the legacy stock item save' + ); $this->assertEquals( 0, - (int) ($stockItemDataOos[GetStockItemDataInterface::IS_SALABLE] ?? 1), - 'Bundle must be not salable after setting is_in_stock = false' + (int)$stockItemDataAfter[GetStockItemDataInterface::IS_SALABLE], + $sku . ' must be marked not salable on non-default stock after admin sets is_in_stock = false' ); - $stockItem = $this->stockRegistry->getStockItemBySku('bundle-parent-2'); + $stockItem = $this->stockRegistry->getStockItemBySku($sku); $stockItem->setIsInStock(true); - $this->stockRegistry->updateStockItemBySku('bundle-parent-2', $stockItem); + $this->stockRegistry->updateStockItemBySku($sku, $stockItem); - $stockItemDataBack = $this->getStockItemData->execute('bundle-parent-2', $stockId); + $stockItemDataBack = $this->getStockItemData->execute($sku, $stockId); $this->assertNotNull( $stockItemDataBack, - 'Bundle stock data on the non-default stock must exist after restoring is_in_stock = true' + $sku . ' stock data on the non-default stock must exist after restoring is_in_stock = true' ); $this->assertEquals( 1, - (int) $stockItemDataBack[GetStockItemDataInterface::IS_SALABLE], - 'Bundle must be salable again on non-default stock after admin sets is_in_stock = true' + (int)$stockItemDataBack[GetStockItemDataInterface::IS_SALABLE], + $sku . ' must be salable again on non-default stock after admin sets is_in_stock = true' ); } } diff --git a/InventoryCatalog/Test/Integration/SetOutOfStockToLegacyStockStatusAtSourceItemsDeleteTest.php b/InventoryCatalog/Test/Integration/LegacyStockAfterSourceItemsDeleteTest.php similarity index 67% rename from InventoryCatalog/Test/Integration/SetOutOfStockToLegacyStockStatusAtSourceItemsDeleteTest.php rename to InventoryCatalog/Test/Integration/LegacyStockAfterSourceItemsDeleteTest.php index 2e43eb6d87f5..bf5dc7efad34 100644 --- a/InventoryCatalog/Test/Integration/SetOutOfStockToLegacyStockStatusAtSourceItemsDeleteTest.php +++ b/InventoryCatalog/Test/Integration/LegacyStockAfterSourceItemsDeleteTest.php @@ -8,6 +8,9 @@ namespace Magento\InventoryCatalog\Test\Integration; use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\CatalogInventory\Api\StockItemCriteriaInterface; +use Magento\CatalogInventory\Api\StockItemCriteriaInterfaceFactory; +use Magento\CatalogInventory\Api\StockItemRepositoryInterface; use Magento\CatalogInventory\Api\StockStatusCriteriaInterface; use Magento\CatalogInventory\Api\StockStatusCriteriaInterfaceFactory; use Magento\CatalogInventory\Api\StockStatusRepositoryInterface; @@ -20,7 +23,7 @@ use PHPUnit\Framework\TestCase; use Magento\TestFramework\Helper\Bootstrap; -class SetOutOfStockToLegacyStockStatusAtSourceItemsDeleteTest extends TestCase +class LegacyStockAfterSourceItemsDeleteTest extends TestCase { /** * @var ProductRepositoryInterface @@ -57,6 +60,16 @@ class SetOutOfStockToLegacyStockStatusAtSourceItemsDeleteTest extends TestCase */ private $defaultSourceProvider; + /** + * @var StockItemCriteriaInterfaceFactory + */ + private $legacyStockItemCriteriaFactory; + + /** + * @var StockItemRepositoryInterface + */ + private $legacyStockItemRepository; + protected function setUp(): void { $this->productRepository = Bootstrap::getObjectManager()->get(ProductRepositoryInterface::class); @@ -71,6 +84,11 @@ protected function setUp(): void $this->sourceItemsDelete = Bootstrap::getObjectManager()->get(SourceItemsDeleteInterface::class); $this->defaultSourceProvider = Bootstrap::getObjectManager()->get(DefaultSourceProviderInterface::class); + + $this->legacyStockItemCriteriaFactory = Bootstrap::getObjectManager()->get( + StockItemCriteriaInterfaceFactory::class + ); + $this->legacyStockItemRepository = Bootstrap::getObjectManager()->get(StockItemRepositoryInterface::class); } /** @@ -85,6 +103,24 @@ public function testSetOutOfStock() $productId = $product->getId(); $websiteId = 0; + /** @var StockItemCriteriaInterface $legacyStockItemCriteria */ + $legacyStockItemCriteria = $this->legacyStockItemCriteriaFactory->create(); + $legacyStockItemCriteria->setProductsFilter($productId); + $legacyStockItemCriteria->setScopeFilter($websiteId); + $legacyStockItems = $this->legacyStockItemRepository->getList($legacyStockItemCriteria)->getItems(); + self::assertCount(1, $legacyStockItems); + + $legacyStockItem = reset($legacyStockItems); + self::assertTrue($legacyStockItem->getIsInStock()); + self::assertEquals(5.5, $legacyStockItem->getQty()); + + $searchCriteria = $this->searchCriteriaBuilder + ->addFilter(SourceItemInterface::SKU, $productSku) + ->addFilter(SourceItemInterface::SOURCE_CODE, $this->defaultSourceProvider->getCode()) + ->create(); + $sourceItems = $this->sourceItemRepository->getList($searchCriteria)->getItems(); + self::assertCount(1, $sourceItems); + /** @var StockStatusCriteriaInterface $legacyStockStatusCriteria */ $legacyStockStatusCriteria = $this->legacyStockStatusCriteriaFactory->create(); $legacyStockStatusCriteria->setProductsFilter($productId); @@ -105,6 +141,13 @@ public function testSetOutOfStock() $this->sourceItemsDelete->execute($sourceItems); + $legacyStockItems = $this->legacyStockItemRepository->getList($legacyStockItemCriteria)->getItems(); + self::assertCount(1, $legacyStockItems); + + $legacyStockItem = reset($legacyStockItems); + self::assertFalse($legacyStockItem->getIsInStock()); + self::assertEquals(0, $legacyStockItem->getQty()); + $legacyStockStatuses = $this->legacyStockStatusRepository->getList($legacyStockStatusCriteria)->getItems(); self::assertCount(1, $legacyStockStatuses); diff --git a/InventoryCatalog/Test/Integration/SetToZeroLegacyStockItemAtSourceItemsDeleteTest.php b/InventoryCatalog/Test/Integration/SetToZeroLegacyStockItemAtSourceItemsDeleteTest.php deleted file mode 100644 index 3b184ab013ae..000000000000 --- a/InventoryCatalog/Test/Integration/SetToZeroLegacyStockItemAtSourceItemsDeleteTest.php +++ /dev/null @@ -1,114 +0,0 @@ -<?php -/** - * Copyright 2017 Adobe - * All Rights Reserved. - */ -declare(strict_types=1); - -namespace Magento\InventoryCatalog\Test\Integration; - -use Magento\Catalog\Api\ProductRepositoryInterface; -use Magento\Framework\Api\SearchCriteriaBuilder; -use Magento\InventoryApi\Api\Data\SourceItemInterface; -use Magento\InventoryApi\Api\SourceItemRepositoryInterface; -use Magento\InventoryApi\Api\SourceItemsDeleteInterface; -use Magento\InventoryCatalogApi\Api\DefaultSourceProviderInterface; -use PHPUnit\Framework\TestCase; -use Magento\TestFramework\Helper\Bootstrap; -use Magento\CatalogInventory\Api\StockItemRepositoryInterface; -use Magento\CatalogInventory\Api\StockItemCriteriaInterface; -use Magento\CatalogInventory\Api\StockItemCriteriaInterfaceFactory; - -class SetToZeroLegacyStockItemAtSourceItemsDeleteTest extends TestCase -{ - /** - * @var ProductRepositoryInterface - */ - private $productRepository; - - /** - * @var StockItemCriteriaInterfaceFactory - */ - private $legacyStockItemCriteriaFactory; - - /** - * @var StockItemRepositoryInterface - */ - private $legacyStockItemRepository; - - /** - * @var SearchCriteriaBuilder - */ - private $searchCriteriaBuilder; - - /** - * @var SourceItemRepositoryInterface - */ - private $sourceItemRepository; - - /** - * @var SourceItemsDeleteInterface - */ - private $sourceItemsDelete; - - /** - * @var DefaultSourceProviderInterface - */ - private $defaultSourceProvider; - - protected function setUp(): void - { - $this->productRepository = Bootstrap::getObjectManager()->get(ProductRepositoryInterface::class); - - $this->legacyStockItemCriteriaFactory = Bootstrap::getObjectManager()->get( - StockItemCriteriaInterfaceFactory::class - ); - $this->legacyStockItemRepository = Bootstrap::getObjectManager()->get(StockItemRepositoryInterface::class); - - $this->searchCriteriaBuilder = Bootstrap::getObjectManager()->get(SearchCriteriaBuilder::class); - $this->sourceItemRepository = Bootstrap::getObjectManager()->get(SourceItemRepositoryInterface::class); - - $this->sourceItemsDelete = Bootstrap::getObjectManager()->get(SourceItemsDeleteInterface::class); - $this->defaultSourceProvider = Bootstrap::getObjectManager()->get(DefaultSourceProviderInterface::class); - } - - /** - * @magentoDataFixture Magento_InventoryApi::Test/_files/products.php - * @magentoDataFixture Magento_InventoryCatalog::Test/_files/source_items_on_default_source.php - * @magentoDataFixture Magento_InventoryIndexer::Test/_files/reindex_inventory.php - */ - public function testSetToZero() - { - $productSku = 'SKU-1'; - $product = $this->productRepository->get($productSku); - $productId = $product->getId(); - $websiteId = 0; - - /** @var StockItemCriteriaInterface $legacyStockItemCriteria */ - $legacyStockItemCriteria = $this->legacyStockItemCriteriaFactory->create(); - $legacyStockItemCriteria->setProductsFilter($productId); - $legacyStockItemCriteria->setScopeFilter($websiteId); - $legacyStockItems = $this->legacyStockItemRepository->getList($legacyStockItemCriteria)->getItems(); - self::assertCount(1, $legacyStockItems); - - $legacyStockItem = reset($legacyStockItems); - self::assertTrue($legacyStockItem->getIsInStock()); - self::assertEquals(5.5, $legacyStockItem->getQty()); - - $searchCriteria = $this->searchCriteriaBuilder - ->addFilter(SourceItemInterface::SKU, $productSku) - ->addFilter(SourceItemInterface::SOURCE_CODE, $this->defaultSourceProvider->getCode()) - ->create(); - $sourceItems = $this->sourceItemRepository->getList($searchCriteria)->getItems(); - self::assertCount(1, $sourceItems); - - $this->sourceItemsDelete->execute($sourceItems); - - $legacyStockItems = $this->legacyStockItemRepository->getList($legacyStockItemCriteria)->getItems(); - self::assertCount(1, $legacyStockItems); - - $legacyStockItem = reset($legacyStockItems); - self::assertFalse($legacyStockItem->getIsInStock()); - self::assertEquals(0, $legacyStockItem->getQty()); - } -} diff --git a/InventoryCatalog/Test/Unit/Plugin/CatalogInventory/Model/Stock/StockItemRepository/ReindexCompositeProductsOnLegacyStockItemSavePluginTest.php b/InventoryCatalog/Test/Unit/Plugin/CatalogInventory/Model/Stock/StockItemRepository/ReindexCompositeProductsOnLegacyStockItemSavePluginTest.php deleted file mode 100644 index 106640967577..000000000000 --- a/InventoryCatalog/Test/Unit/Plugin/CatalogInventory/Model/Stock/StockItemRepository/ReindexCompositeProductsOnLegacyStockItemSavePluginTest.php +++ /dev/null @@ -1,131 +0,0 @@ -<?php -/** - * Copyright 2026 Adobe - * All Rights Reserved. - */ -declare(strict_types=1); - -namespace Magento\InventoryCatalog\Test\Unit\Plugin\CatalogInventory\Model\Stock\StockItemRepository; - -use Magento\CatalogInventory\Api\Data\StockItemInterface; -use Magento\CatalogInventory\Model\Stock\StockItemRepository; -use Magento\Inventory\Model\SourceItem; -use Magento\Inventory\Model\SourceItem\Command\GetSourceItemsBySku; -use Magento\InventoryCatalog\Plugin\CatalogInventory\Model\Stock\StockItemRepository\ReindexCompositeProductsOnLegacyStockItemSavePlugin; // phpcs:ignore Generic.Files.LineLength.TooLong -use Magento\InventoryCatalogApi\Model\GetSkusByProductIdsInterface; -use Magento\InventoryIndexer\Indexer\CompositeProductsIndexer; -use PHPUnit\Framework\MockObject\MockObject; -use PHPUnit\Framework\TestCase; - -class ReindexCompositeProductsOnLegacyStockItemSavePluginTest extends TestCase -{ - /** @var GetSkusByProductIdsInterface|MockObject */ - private $getSkusByProductIds; - - /** @var GetSourceItemsBySku|MockObject */ - private $getSourceItemsBySku; - - /** @var CompositeProductsIndexer|MockObject */ - private $compositeProductsIndexer; - - /** @var ReindexCompositeProductsOnLegacyStockItemSavePlugin */ - private $plugin; - - protected function setUp(): void - { - $this->getSkusByProductIds = $this->createMock(GetSkusByProductIdsInterface::class); - $this->getSourceItemsBySku = $this->createMock(GetSourceItemsBySku::class); - $this->compositeProductsIndexer = $this->createMock(CompositeProductsIndexer::class); - - $this->plugin = new ReindexCompositeProductsOnLegacyStockItemSavePlugin( - $this->getSkusByProductIds, - $this->getSourceItemsBySku, - $this->compositeProductsIndexer - ); - } - - public function testReindexIsTriggeredWhenProductHasNoSourceItems(): void - { - $productId = 123; - $sku = 'bundle-sku'; - - $stockItem = $this->createMock(StockItemInterface::class); - $stockItem->method('getProductId')->willReturn($productId); - - $this->getSkusByProductIds->expects($this->once()) - ->method('execute') - ->with([$productId]) - ->willReturn([$productId => $sku]); - - $this->getSourceItemsBySku->expects($this->once()) - ->method('execute') - ->with($sku) - ->willReturn([]); - - $this->compositeProductsIndexer->expects($this->once()) - ->method('reindexList') - ->with([$sku]); - - $result = $this->plugin->afterSave( - $this->createMock(StockItemRepository::class), - $stockItem - ); - - $this->assertSame($stockItem, $result); - } - - public function testReindexIsSkippedWhenProductHasSourceItems(): void - { - $productId = 123; - $sku = 'simple-sku'; - - $stockItem = $this->createMock(StockItemInterface::class); - $stockItem->method('getProductId')->willReturn($productId); - - $this->getSkusByProductIds->expects($this->once()) - ->method('execute') - ->with([$productId]) - ->willReturn([$productId => $sku]); - - $sourceItem = $this->createMock(SourceItem::class); - $this->getSourceItemsBySku->expects($this->once()) - ->method('execute') - ->with($sku) - ->willReturn([$sourceItem]); - - $this->compositeProductsIndexer->expects($this->never()) - ->method('reindexList'); - - $result = $this->plugin->afterSave( - $this->createMock(StockItemRepository::class), - $stockItem - ); - - $this->assertSame($stockItem, $result); - } - - public function testReindexIsSkippedWhenProductSkuIsNotFound(): void - { - $productId = 123; - - $stockItem = $this->createMock(StockItemInterface::class); - $stockItem->method('getProductId')->willReturn($productId); - - $this->getSkusByProductIds->expects($this->once()) - ->method('execute') - ->with([$productId]) - ->willReturn([]); - - $this->getSourceItemsBySku->expects($this->never()) - ->method('execute'); - $this->compositeProductsIndexer->expects($this->never()) - ->method('reindexList'); - - $result = $this->plugin->afterSave( - $this->createMock(StockItemRepository::class), - $stockItem - ); - - $this->assertSame($stockItem, $result); - } -} diff --git a/InventoryCatalog/etc/di.xml b/InventoryCatalog/etc/di.xml index 8c9ae1780a56..09228da300a3 100644 --- a/InventoryCatalog/etc/di.xml +++ b/InventoryCatalog/etc/di.xml @@ -49,6 +49,8 @@ <plugin name="update_source_item_at_legacy_qty_counter" type="Magento\InventoryCatalog\Plugin\CatalogInventory\UpdateSourceItemAtLegacyQtyCounterPlugin"/> </type> <type name="Magento\CatalogInventory\Model\ResourceModel\Stock\Item"> + <plugin name="reindex_composite_products_on_legacy_stock_item_save" + type="Magento\InventoryCatalog\Plugin\CatalogInventory\Model\ResourceModel\Stock\Item\ReindexCompositeProductsOnLegacyStockItemSavePlugin"/> <plugin name="update_source_item_at_legacy_stock_item_save" type="Magento\InventoryCatalog\Plugin\CatalogInventory\UpdateSourceItemAtLegacyStockItemSavePlugin"/> </type> @@ -157,11 +159,6 @@ </arguments> </type> - <type name="Magento\CatalogInventory\Model\Stock\StockItemRepository"> - <plugin name="reindex_composite_products_after_save_product_stock_item" - type="Magento\InventoryCatalog\Plugin\CatalogInventory\Model\Stock\StockItemRepository\ReindexCompositeProductsOnLegacyStockItemSavePlugin"/> - </type> - <!-- Negative Min Quantity Threshold for Backorders --> <type name="Magento\Catalog\Controller\Adminhtml\Product\Initialization\StockDataFilter"> <plugin name="allow_negative_min_qty" diff --git a/InventoryConfigurableProductIndexer/Indexer/SelectBuilder.php b/InventoryConfigurableProductIndexer/Indexer/SelectBuilder.php index bfff352d0369..698c24de5006 100644 --- a/InventoryConfigurableProductIndexer/Indexer/SelectBuilder.php +++ b/InventoryConfigurableProductIndexer/Indexer/SelectBuilder.php @@ -8,6 +8,7 @@ namespace Magento\InventoryConfigurableProductIndexer\Indexer; use Magento\Catalog\Api\Data\ProductInterface; +use Magento\CatalogInventory\Api\StockConfigurationInterface; use Magento\Framework\App\ResourceConnection; use Magento\Framework\DB\Select; use Magento\Framework\EntityManager\MetadataPool; @@ -27,13 +28,15 @@ class SelectBuilder implements SiblingSelectBuilderInterface * @param IndexNameResolverInterface $indexNameResolver * @param MetadataPool $metadataPool * @param DefaultStockProviderInterface $defaultStockProvider + * @param StockConfigurationInterface $configuration */ public function __construct( private readonly ResourceConnection $resourceConnection, private readonly IndexNameBuilder $indexNameBuilder, private readonly IndexNameResolverInterface $indexNameResolver, private readonly MetadataPool $metadataPool, - private readonly DefaultStockProviderInterface $defaultStockProvider + private readonly DefaultStockProviderInterface $defaultStockProvider, + private readonly StockConfigurationInterface $configuration ) { } @@ -51,13 +54,20 @@ public function getSelect(int $stockId, array $skuList = [], IndexAlias $indexAl $metadata = $this->metadataPool->getMetadata(ProductInterface::class); $linkField = $metadata->getLinkField(); + $manageStock = '(inventory_stock_item.use_config_manage_stock = 0 AND inventory_stock_item.manage_stock = 1)'; + if (((int)$this->configuration->getManageStock()) === 1) { + $manageStock .= ' OR inventory_stock_item.use_config_manage_stock = 1'; + $manageStock = "($manageStock)"; + } + $select = $connection->select() ->from( ['stock' => $indexTableName], [ IndexStructure::SKU => 'parent_product_entity.sku', IndexStructure::QUANTITY => 'SUM(stock.quantity)', - IndexStructure::IS_SALABLE => 'IF(inventory_stock_item.is_in_stock = 0, 0, MAX(stock.is_salable))', + IndexStructure::IS_SALABLE => + "IF(inventory_stock_item.is_in_stock = 0 AND $manageStock, 0, MAX(stock.is_salable))", ] )->joinInner( ['product_entity' => $this->resourceConnection->getTableName('catalog_product_entity')], diff --git a/InventoryConfigurableProductIndexer/composer.json b/InventoryConfigurableProductIndexer/composer.json index 980f7a811e24..3b9269ffb335 100644 --- a/InventoryConfigurableProductIndexer/composer.json +++ b/InventoryConfigurableProductIndexer/composer.json @@ -9,7 +9,8 @@ "magento/module-inventory-catalog-api": "*", "magento/module-inventory-indexer": "*", "magento/module-inventory-multi-dimensional-indexer-api": "*", - "magento/module-configurable-product": "*" + "magento/module-configurable-product": "*", + "magento/module-catalog-inventory": "*" }, "suggest": { "magento/module-inventory": "*" diff --git a/InventoryGroupedProductIndexer/Indexer/SelectBuilder.php b/InventoryGroupedProductIndexer/Indexer/SelectBuilder.php index 307e3e0dcdb3..1ebaf717ca85 100644 --- a/InventoryGroupedProductIndexer/Indexer/SelectBuilder.php +++ b/InventoryGroupedProductIndexer/Indexer/SelectBuilder.php @@ -8,6 +8,7 @@ namespace Magento\InventoryGroupedProductIndexer\Indexer; use Magento\Catalog\Api\Data\ProductInterface; +use Magento\CatalogInventory\Api\StockConfigurationInterface; use Magento\Framework\App\ResourceConnection; use Magento\Framework\DB\Select; use Magento\Framework\EntityManager\MetadataPool; @@ -29,12 +30,14 @@ class SelectBuilder implements SiblingSelectBuilderInterface * @param IndexNameBuilder $indexNameBuilder * @param IndexNameResolverInterface $indexNameResolver * @param MetadataPool $metadataPool + * @param StockConfigurationInterface $configuration */ public function __construct( private readonly ResourceConnection $resourceConnection, private readonly IndexNameBuilder $indexNameBuilder, private readonly IndexNameResolverInterface $indexNameResolver, private readonly MetadataPool $metadataPool, + private readonly StockConfigurationInterface $configuration ) { } @@ -52,6 +55,12 @@ public function getSelect(int $stockId, array $skuList = [], IndexAlias $indexAl $metadata = $this->metadataPool->getMetadata(ProductInterface::class); $linkField = $metadata->getLinkField(); + $manageStock = '(inventory_stock_item.use_config_manage_stock = 0 AND inventory_stock_item.manage_stock = 1)'; + if (((int)$this->configuration->getManageStock()) === 1) { + $manageStock .= ' OR inventory_stock_item.use_config_manage_stock = 1'; + $manageStock = "($manageStock)"; + } + $select = $connection->select(); $select->from( ['parent_link' => $this->resourceConnection->getTableName('catalog_product_link')], @@ -75,8 +84,8 @@ public function getSelect(int $stockId, array $skuList = [], IndexAlias $indexAl 'child_stock.sku = child_product_entity.sku', [ IndexStructure::QUANTITY => 'SUM(child_stock.quantity)', - IndexStructure::IS_SALABLE => 'IF(inventory_stock_item.is_in_stock = 0, 0, - MAX(child_stock.is_salable))', + IndexStructure::IS_SALABLE => + "IF(inventory_stock_item.is_in_stock = 0 AND $manageStock, 0, MAX(child_stock.is_salable))", ] )->joinInner( ['child_filter_product_entity' => $this->resourceConnection->getTableName('catalog_product_entity')], diff --git a/InventoryGroupedProductIndexer/composer.json b/InventoryGroupedProductIndexer/composer.json index dac91c5c4531..63d4d2202212 100644 --- a/InventoryGroupedProductIndexer/composer.json +++ b/InventoryGroupedProductIndexer/composer.json @@ -7,7 +7,8 @@ "magento/module-catalog": "*", "magento/module-inventory-indexer": "*", "magento/module-inventory-multi-dimensional-indexer-api": "*", - "magento/module-grouped-product": "*" + "magento/module-grouped-product": "*", + "magento/module-catalog-inventory": "*" }, "suggest": { "magento/module-inventory": "*" diff --git a/InventoryIndexer/Indexer/Stock/SkuListsProcessor.php b/InventoryIndexer/Indexer/Stock/SkuListsProcessor.php index 1141e5e274af..cf99fc6eb408 100644 --- a/InventoryIndexer/Indexer/Stock/SkuListsProcessor.php +++ b/InventoryIndexer/Indexer/Stock/SkuListsProcessor.php @@ -7,9 +7,7 @@ namespace Magento\InventoryIndexer\Indexer\Stock; -use Magento\Framework\App\ObjectManager; use Magento\Framework\App\ResourceConnection; -use Magento\Framework\Exception\StateException; use Magento\InventoryCatalogApi\Api\DefaultStockProviderInterface; use Magento\InventoryIndexer\Indexer\InventoryIndexer; use Magento\InventoryIndexer\Indexer\SourceItem\CompositeProductProcessorInterface as ProductProcessor; @@ -25,11 +23,6 @@ class SkuListsProcessor */ private string $connectionName = ResourceConnection::DEFAULT_CONNECTION; - /** - * @var ResourceConnection - */ - private ResourceConnection $resourceConnection; - /** * @param GetSalableStatuses $getSalableStatuses * @param DefaultStockProviderInterface $defaultStockProvider @@ -37,7 +30,6 @@ class SkuListsProcessor * @param IndexStructureInterface $indexStructure * @param IndexDataFiller $indexDataFiller * @param ProductProcessor[] $saleabilityChangesProcessorsPool - * @param ResourceConnection|null $resourceConnection */ public function __construct( private readonly GetSalableStatuses $getSalableStatuses, @@ -46,11 +38,7 @@ public function __construct( private readonly IndexStructureInterface $indexStructure, private readonly IndexDataFiller $indexDataFiller, private array $saleabilityChangesProcessorsPool = [], - ?ResourceConnection $resourceConnection = null ) { - $this->resourceConnection = $resourceConnection - ?? ObjectManager::getInstance()->get(ResourceConnection::class); - // Sort processors by sort order uasort( $this->saleabilityChangesProcessorsPool, @@ -63,7 +51,6 @@ public function __construct( * * @param SkuListInStock[] $skuListInStockList * @return void - * @throws StateException */ public function reindexList(array $skuListInStockList): void { @@ -81,9 +68,6 @@ public function reindexList(array $skuListInStockList): void ->setAlias(IndexAlias::MAIN->value) ->build(); if (!$this->indexStructure->isExist($mainIndexName, $this->connectionName)) { - if ($this->resourceConnection->getConnection($this->connectionName)->getTransactionLevel() > 0) { - continue; - } $this->indexStructure->create($mainIndexName, $this->connectionName); } $this->indexDataFiller->fillIndex($mainIndexName, $skuListInStock, $this->connectionName); From 361481b203106778982824920e2eccd07691f52b Mon Sep 17 00:00:00 2001 From: Karishma Thakare <del57145@adobe.com> Date: Thu, 7 May 2026 23:55:18 +0530 Subject: [PATCH 25/83] ACQE-9836: Filter - Sales Order Grid - Added filter clearance code --- ...ceFullShipmentGroupedProductCustomStockTest.xml | 4 ++-- ...PartialInvoiceVirtualProductCustomStockTest.xml | 4 ++-- ...ceFullShipmentSimpleProductsCustomStockTest.xml | 6 +++--- ...eFullShipmentGroupedProductDefaultStockTest.xml | 4 ++-- ...artialShipmentGroupedProductCustomStockTest.xml | 4 ++-- ...mpleProductWithCustomOptionDefaultStockTest.xml | 4 ++-- ...voiceForVirtualProductInSingleStockModeTest.xml | 6 +++--- ...WithConfigurableProductFromCustomSourceTest.xml | 14 +++++++------- ...oductWithChildsProductOnNonDefaultStockTest.xml | 6 +++--- ...temsInShipmentForOrderWithSimpleProductTest.xml | 14 +++++++------- ...eateInvoiceWithSimpleProductCustomStockTest.xml | 6 +++--- ...ateShipmentWithSimpleProductCustomStockTest.xml | 6 +++--- 12 files changed, 39 insertions(+), 39 deletions(-) diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundFullInvoiceFullShipmentGroupedProductCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundFullInvoiceFullShipmentGroupedProductCustomStockTest.xml index bd2693ec26dd..74a2bf144a0f 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundFullInvoiceFullShipmentGroupedProductCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundFullInvoiceFullShipmentGroupedProductCustomStockTest.xml @@ -35,8 +35,8 @@ <argument name="websiteName" value="{{_defaultWebsite.name}}"/> </actionGroup> <deleteData createDataKey="additionalStock" after="logoutOfAdmin" stepKey="deleteStock"/> - <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> -</after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters" after="clearOrdersFilters"/> + </after> <!--Assign simple product to additional source.--> <actionGroup ref="AssignSourceToProductActionGroup" stepKey="assignTestSourceToCreatedProduct" after="openSimpleProductPage"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundPartialInvoiceVirtualProductCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundPartialInvoiceVirtualProductCustomStockTest.xml index 392d18285877..a34b3e555851 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundPartialInvoiceVirtualProductCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundPartialInvoiceVirtualProductCustomStockTest.xml @@ -47,12 +47,12 @@ </actionGroup> <deleteData createDataKey="stock" stepKey="deleteStock"/> <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersFilters"/> + <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> </actionGroup> - <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> -</after> + </after> <!--Login To storefront as Customer--> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefront"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialReturnToStockAfterFullInvoiceFullShipmentSimpleProductsCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialReturnToStockAfterFullInvoiceFullShipmentSimpleProductsCustomStockTest.xml index 64ce0a3f94a3..bc2edd19a845 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialReturnToStockAfterFullInvoiceFullShipmentSimpleProductsCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialReturnToStockAfterFullInvoiceFullShipmentSimpleProductsCustomStockTest.xml @@ -68,13 +68,13 @@ <argument name="websiteName" value="{{_defaultWebsite.name}}"/> </actionGroup> <deleteData createDataKey="stock" stepKey="deleteStock"/> + <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> </actionGroup> - <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> -</after> + </after> <!--Login on storefront--> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefront"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoiceFullShipmentGroupedProductDefaultStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoiceFullShipmentGroupedProductDefaultStockTest.xml index 83b7e6c932be..5eb747b61ba1 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoiceFullShipmentGroupedProductDefaultStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoiceFullShipmentGroupedProductDefaultStockTest.xml @@ -41,6 +41,7 @@ </actionGroup> <!--Clear Filters--> <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersFilters"/> + <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> @@ -50,8 +51,7 @@ <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> </actionGroup> - <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> -</after> + </after> <!--Set default source product quantity.--> <amOnPage url="{{AdminProductEditPage.url($$product.id$$)}}" stepKey="openSimpleProductPage"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoicePartialShipmentGroupedProductCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoicePartialShipmentGroupedProductCustomStockTest.xml index 2b06ab5f800c..67ae2deeeb7d 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoicePartialShipmentGroupedProductCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoicePartialShipmentGroupedProductCustomStockTest.xml @@ -35,8 +35,8 @@ <argument name="websiteName" value="{{_defaultWebsite.name}}"/> </actionGroup> <deleteData createDataKey="additionalStock" after="logoutOfAdmin" stepKey="deleteStock"/> - <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> -</after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters" after="clearOrdersFilters"/> + </after> <!--Assign simple product to additional source.--> <actionGroup ref="AssignSourceToProductActionGroup" stepKey="assignTestSourceToCreatedProduct" after="openSimpleProductPage"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateFullShipmentSimpleProductWithCustomOptionDefaultStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateFullShipmentSimpleProductWithCustomOptionDefaultStockTest.xml index 82c9fe22081e..01070ef0b241 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateFullShipmentSimpleProductWithCustomOptionDefaultStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateFullShipmentSimpleProductWithCustomOptionDefaultStockTest.xml @@ -45,12 +45,12 @@ <!--Clear Filters--> <deleteData createDataKey="category" stepKey="deletecategory"/> <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersFilters"/> + <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> </actionGroup> - <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> -</after> + </after> <!--Add custom option to product.--> <amOnPage url="{{AdminProductEditPage.url($$product.id$$)}}" stepKey="openProductEditPage"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateInvoiceForVirtualProductInSingleStockModeTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateInvoiceForVirtualProductInSingleStockModeTest.xml index e1d60edc05dd..8bf3ba679170 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateInvoiceForVirtualProductInSingleStockModeTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateInvoiceForVirtualProductInSingleStockModeTest.xml @@ -29,14 +29,14 @@ </before> <after> <actionGroup ref="AdminClearFiltersActionGroup" stepKey="clearProductsGridFilters"/> + <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <deleteData createDataKey="category" stepKey="deleteCategory"/> <deleteData createDataKey="product" stepKey="deleteProduct"/> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> - <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> -</after> + </after> <comment userInput="Assign category to created virtual product." stepKey="assignCategoryToProductComment"/> <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndexPageForEditProduct"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialShipmentForOrderWithConfigurableProductFromCustomSourceTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialShipmentForOrderWithConfigurableProductFromCustomSourceTest.xml index 8c3a9b5e0083..80bd7038f172 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialShipmentForOrderWithConfigurableProductFromCustomSourceTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialShipmentForOrderWithConfigurableProductFromCustomSourceTest.xml @@ -146,6 +146,12 @@ <click selector="{{AdminGridMainControls.saveAndContinue}}" stepKey="saveDefaultStock"/> <!-- Delete configurable product created via UI --> <helper class="Magento\Catalog\Test\Mftf\Helper\ProductApiHelper" method="deleteAllProductsApi" stepKey="deleteAllProductsViaApi"/> + <amOnPage url="{{AdminManageStockPage.url}}" stepKey="goToInventoryStockGridToClearFilters"/> + <waitForPageLoad stepKey="waitForInventoryStockGridToLoad"/> + <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clearInventoryStockGridFilters"/> + <waitForPageLoad stepKey="waitAfterClearInventoryStockFilters"/> + <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> @@ -156,13 +162,7 @@ <actionGroup ref="CliCacheCleanActionGroup" stepKey="cleanCache"> <argument name="tags" value="full_page"/> </actionGroup> - <amOnPage url="{{AdminManageStockPage.url}}" stepKey="goToInventoryStockGridToClearFilters"/> - <waitForPageLoad stepKey="waitForInventoryStockGridToLoad"/> - <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clearInventoryStockGridFilters"/> - <waitForPageLoad stepKey="waitAfterClearInventoryStockFilters"/> - <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> -</after> + </after> <!-- Login as Customer and add Product to Cart--> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="customerLogin"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminInvoiceCreatedForWholeOrderWithGroupedProductWithChildsProductOnNonDefaultStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminInvoiceCreatedForWholeOrderWithGroupedProductWithChildsProductOnNonDefaultStockTest.xml index 187e01d64f22..b24c408615e6 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminInvoiceCreatedForWholeOrderWithGroupedProductWithChildsProductOnNonDefaultStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminInvoiceCreatedForWholeOrderWithGroupedProductWithChildsProductOnNonDefaultStockTest.xml @@ -44,6 +44,8 @@ <actionGroup ref="DisableSourceActionGroup" stepKey="disableCreatedCustomSource"> <argument name="sourceCode" value="$$additionalSource.source[source_code]$$"/> </actionGroup> + <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> @@ -54,9 +56,7 @@ <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> </actionGroup> - <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> -</after> + </after> <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="openProductGrid1"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminManualSelectingOfSourcesToDeductItemsInShipmentForOrderWithSimpleProductTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminManualSelectingOfSourcesToDeductItemsInShipmentForOrderWithSimpleProductTest.xml index a056430ab3ad..4015cddd39b8 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminManualSelectingOfSourcesToDeductItemsInShipmentForOrderWithSimpleProductTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminManualSelectingOfSourcesToDeductItemsInShipmentForOrderWithSimpleProductTest.xml @@ -100,17 +100,17 @@ <after> <!-- Delete all products via API using ProductApiHelper --> <helper class="Magento\Catalog\Test\Mftf\Helper\ProductApiHelper" method="deleteAllProductsApi" stepKey="deleteAllProductsViaApi"/> + <amOnPage url="{{AdminManageStockPage.url}}" stepKey="goToInventoryStockGridToClearFilters"/> + <waitForPageLoad stepKey="waitForInventoryStockGridToLoad"/> + <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clearInventoryStockGridFilters"/> + <waitForPageLoad stepKey="waitAfterClearInventoryStockFilters"/> + <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <amOnPage url="{{AdminManageStockPage.url}}" stepKey="goToInventoryStockGridToClearFilters"/> - <waitForPageLoad stepKey="waitForInventoryStockGridToLoad"/> - <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clearInventoryStockGridFilters"/> - <waitForPageLoad stepKey="waitAfterClearInventoryStockFilters"/> - <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> -</after> + </after> <!-- Login as Customer and add Product to Cart--> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="customerLogin"> diff --git a/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminCreateInvoiceWithSimpleProductCustomStockTest.xml b/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminCreateInvoiceWithSimpleProductCustomStockTest.xml index 8e9e164856f6..41e8eb7ed38f 100644 --- a/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminCreateInvoiceWithSimpleProductCustomStockTest.xml +++ b/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminCreateInvoiceWithSimpleProductCustomStockTest.xml @@ -79,13 +79,13 @@ </actionGroup> <deleteData createDataKey="stock" stepKey="deleteStock"/> <actionGroup ref="DisableAllSourcesActionGroup" stepKey="disableAllSources"/> + <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> </actionGroup> - <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> -</after> + </after> <!--Add product to cart.--> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefront"> diff --git a/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminCreateShipmentWithSimpleProductCustomStockTest.xml b/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminCreateShipmentWithSimpleProductCustomStockTest.xml index 271c20c8ed19..e7eb4bbf49b6 100644 --- a/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminCreateShipmentWithSimpleProductCustomStockTest.xml +++ b/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminCreateShipmentWithSimpleProductCustomStockTest.xml @@ -79,13 +79,13 @@ </actionGroup> <deleteData createDataKey="stock" stepKey="deleteStock"/> <actionGroup ref="DisableAllSourcesActionGroup" stepKey="disableAllSources"/> + <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> </actionGroup> - <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> -</after> + </after> <!--Add product to cart.--> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefront"> From 3ce68a4891be6d9721d458c7deea9df3031b1946 Mon Sep 17 00:00:00 2001 From: Karishma Thakare <del57145@adobe.com> Date: Fri, 8 May 2026 08:46:01 +0530 Subject: [PATCH 26/83] ACQE-9836: Filter - Sales Order Grid - Added filter clearance code --- ...eOrderWithSimpleProductFromCustomSourceTest.xml | 14 +++++++------- .../Test/Mftf/test-dependency-allowlist | 1 + .../Test/Mftf/test-dependency-allowlist | 3 ++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateShipmentForWholeOrderWithSimpleProductFromCustomSourceTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateShipmentForWholeOrderWithSimpleProductFromCustomSourceTest.xml index c2cb8e4be050..3a05516d5596 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateShipmentForWholeOrderWithSimpleProductFromCustomSourceTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateShipmentForWholeOrderWithSimpleProductFromCustomSourceTest.xml @@ -98,17 +98,17 @@ <after> <!-- Delete simple product created via UI --> <helper class="Magento\Catalog\Test\Mftf\Helper\ProductApiHelper" method="deleteAllProductsApi" stepKey="deleteAllProductsViaApi"/> + <amOnPage url="{{AdminManageStockPage.url}}" stepKey="goToInventoryStockGridToClearFilters"/> + <waitForPageLoad stepKey="waitForInventoryStockGridToLoad"/> + <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clearInventoryStockGridFilters"/> + <waitForPageLoad stepKey="waitAfterClearInventoryStockFilters"/> + <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <amOnPage url="{{AdminManageStockPage.url}}" stepKey="goToInventoryStockGridToClearFilters"/> - <waitForPageLoad stepKey="waitForInventoryStockGridToLoad"/> - <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clearInventoryStockGridFilters"/> - <waitForPageLoad stepKey="waitAfterClearInventoryStockFilters"/> - <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> -</after> + </after> <!-- Login as Customer and add Product to Cart--> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="customerLogin"> diff --git a/InventoryAdminUi/Test/Mftf/test-dependency-allowlist b/InventoryAdminUi/Test/Mftf/test-dependency-allowlist index 0b7b951dff6f..ea1793e464f2 100644 --- a/InventoryAdminUi/Test/Mftf/test-dependency-allowlist +++ b/InventoryAdminUi/Test/Mftf/test-dependency-allowlist @@ -61,4 +61,5 @@ SingleShippingSection BillingAgreement AdminLeftNavigationMenuSubTitlesVisibleTest AdminMenuSection +AdminOrdersGridClearFiltersActionGroup NewProduct diff --git a/InventoryInStorePickupAdminUi/Test/Mftf/test-dependency-allowlist b/InventoryInStorePickupAdminUi/Test/Mftf/test-dependency-allowlist index d5706583d157..44a15c4de182 100644 --- a/InventoryInStorePickupAdminUi/Test/Mftf/test-dependency-allowlist +++ b/InventoryInStorePickupAdminUi/Test/Mftf/test-dependency-allowlist @@ -8,4 +8,5 @@ StorefrontAddConfigurableProductToTheCartActionGroup AdminProductFormGroupedProductsSection AdminAddProductsToGroupPanel FillDefaultQuantityForLinkedToGroupProductInGridActionGroup -AdminSelectInStorePickupShippingMethodActionGroup \ No newline at end of file +AdminSelectInStorePickupShippingMethodActionGroup +AdminOrdersGridClearFiltersActionGroup \ No newline at end of file From cd03090306054badda48765a0ef467e752537ac0 Mon Sep 17 00:00:00 2001 From: Sandesh S <tec47624@adobe.com> Date: Fri, 8 May 2026 09:41:09 +0530 Subject: [PATCH 27/83] ACQE-9572: OfflineDistanceBasedSelectionAlgorithmCustomStockTestTwoItemsDeductionTest - Add two magentoCron runs before product quantity verification to trigger reindex after shipment creation. --- ...edSelectionAlgorithmCustomStockTestTwoItemsDeductionTest.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/InventoryAdminUi/Test/Mftf/Test/OfflineDistanceBasedSelectionAlgorithmCustomStockTestTwoItemsDeductionTest.xml b/InventoryAdminUi/Test/Mftf/Test/OfflineDistanceBasedSelectionAlgorithmCustomStockTestTwoItemsDeductionTest.xml index 35f81d6f2419..faca131767f4 100644 --- a/InventoryAdminUi/Test/Mftf/Test/OfflineDistanceBasedSelectionAlgorithmCustomStockTestTwoItemsDeductionTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/OfflineDistanceBasedSelectionAlgorithmCustomStockTestTwoItemsDeductionTest.xml @@ -188,6 +188,8 @@ <waitForText userInput="Processing" selector="{{AdminOrderDetailsInformationSection.orderStatus}}" stepKey="checkOrderStatusForUSSource1"/> <waitForText userInput="Shipped 10" selector="{{AdminOrderItemsOrderedSection.itemQty('1')}}" stepKey="checkShippedQuantityForUSSource1"/> <!--Verify product quantity.--> + <magentoCron stepKey="runCron"/> + <magentoCron stepKey="runCronAgain"/> <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndexPageForCheckProductQtyAfterCreateShipment"/> <actionGroup ref="AdminGridFilterSearchResultsByInput" stepKey="findSimpleProductBySkuToCheckQtyAfterCreateShipment"> <argument name="selector" value="AdminProductGridFilterSection.skuFilter"/> From 6b5188e927a4404397f01630070f39c533550be3 Mon Sep 17 00:00:00 2001 From: chandrakalahanchinal <del66267@adobe.com> Date: Fri, 8 May 2026 16:23:46 +0530 Subject: [PATCH 28/83] ACQE-9501: [MFTF TESTS] StorefrontBundleProductChangeStockStatusCustomStockTest - Added reindex steps. --- ...roductChangeStockStatusCustomStockCustomWebsiteTest.xml | 7 +++---- ...efrontBundleProductChangeStockStatusCustomStockTest.xml | 6 +++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/InventoryAdminUi/Test/Mftf/Test/StorefrontBundleProductChangeStockStatusCustomStockCustomWebsiteTest.xml b/InventoryAdminUi/Test/Mftf/Test/StorefrontBundleProductChangeStockStatusCustomStockCustomWebsiteTest.xml index 7aa3bbbab7e1..7dcffa4c8d6b 100644 --- a/InventoryAdminUi/Test/Mftf/Test/StorefrontBundleProductChangeStockStatusCustomStockCustomWebsiteTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StorefrontBundleProductChangeStockStatusCustomStockCustomWebsiteTest.xml @@ -16,10 +16,6 @@ <severity value="CRITICAL"/> <group value="msi"/> <group value="multi_mode"/> - <skip> - <issueId value="https://github.com/magento/inventory/issues/1821"/> - </skip> - <group value="pr_exclude"/> </annotations> <before> @@ -124,6 +120,9 @@ <amOnPage url="{{AdminProductEditPage.url($$bundleProduct.id$$)}}" stepKey="openBundleProductEditPage"/> <selectOption selector="{{AdminProductFormSection.productStockStatus}}" userInput="{{SourceStatusInStock.value}}" stepKey="selectOutOfStock"/> <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/> + <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> + <argument name="indices" value=""/> + </actionGroup> <!-- Check product is visible on Storefront--> <actionGroup ref="StorefrontAssertProductOnCategoryPageAdditionalWebsiteActionGroup" stepKey="verifyProductOnCategoryPage"> <argument name="categoryName" value="$category.name$"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/StorefrontBundleProductChangeStockStatusCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/StorefrontBundleProductChangeStockStatusCustomStockTest.xml index 39d4fd28793b..96feaeef37bd 100644 --- a/InventoryAdminUi/Test/Mftf/Test/StorefrontBundleProductChangeStockStatusCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StorefrontBundleProductChangeStockStatusCustomStockTest.xml @@ -16,9 +16,6 @@ <severity value="CRITICAL"/> <group value="msi"/> <group value="multi_mode"/> - <skip> - <issueId value="https://github.com/magento/inventory/issues/1821"/> - </skip> </annotations> <before> @@ -87,6 +84,9 @@ <amOnPage url="{{AdminProductEditPage.url($$bundleProduct.id$$)}}" stepKey="openBundleProductEditPage"/> <selectOption selector="{{AdminProductFormSection.productStockStatus}}" userInput="{{SourceStatusInStock.value}}" stepKey="selectOutOfStock"/> <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/> + <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> + <argument name="indices" value=""/> + </actionGroup> <!-- Check product is visible on Storefront--> <actionGroup ref="AssertProductInStorefrontCategoryPage" stepKey="verifyProductVisibleOnStorefront"> <argument name="category" value="$category$"/> From a28facb1d4888bb0e41c8a08315525adaba2e9b1 Mon Sep 17 00:00:00 2001 From: Karishma Thakare <del57145@adobe.com> Date: Fri, 8 May 2026 19:07:34 +0530 Subject: [PATCH 29/83] ACQE-9836: Filter - Sales Order Grid - Added filter clearance code --- ...AdminCancelOrderDownloadableProductCustomStockTest.xml | 4 ++-- ...MemoAutoReturnToStockVirtualProductCustomStockTest.xml | 4 ++-- ...tialRefundFullInvoiceVirtualProductCustomStockTest.xml | 4 ++-- ...CreditMemoTotalRefundBundleProductDefaultStockTest.xml | 4 ++-- ...otalRefundFullInvoiceGroupedProductCustomStockTest.xml | 4 ++-- ...otalRefundFullInvoiceVirtualProductCustomStockTest.xml | 4 ++-- ...talRefundVirtualProductCustomOptionCustomStockTest.xml | 4 ++-- ...pmentForOrderWithSimpleProductFromCustomSourceTest.xml | 8 ++++---- 8 files changed, 18 insertions(+), 18 deletions(-) diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCancelOrderDownloadableProductCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCancelOrderDownloadableProductCustomStockTest.xml index 643b6893a186..4f98f1298c5b 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCancelOrderDownloadableProductCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCancelOrderDownloadableProductCustomStockTest.xml @@ -25,8 +25,8 @@ <after> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> <deleteData createDataKey="customer" stepKey="deleteCustomer" after="deleteCustomStock"/> - <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> -</after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> + </after> <!-- Login as customer --> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefront"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoAutoReturnToStockVirtualProductCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoAutoReturnToStockVirtualProductCustomStockTest.xml index 3e9addf87a09..177ff0f46671 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoAutoReturnToStockVirtualProductCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoAutoReturnToStockVirtualProductCustomStockTest.xml @@ -55,8 +55,8 @@ <comment userInput="BIC workaround" stepKey="revertAutoReturnItems" after="deleteProduct"/> <comment userInput="BIC workaround" stepKey="reindex" after="revertAutoReturnItems"/> <comment userInput="BIC workaround" stepKey="flushCache" after="reindex"/> - <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> -</after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> + </after> <!--Assign virtual product to additional source.--> <actionGroup ref="AssignSourceToProductActionGroup" stepKey="assignTestSourceToCreatedProduct" after="openProductEditPage"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundFullInvoiceVirtualProductCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundFullInvoiceVirtualProductCustomStockTest.xml index 86e97f880dd5..6ba0d5d2d6cc 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundFullInvoiceVirtualProductCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundFullInvoiceVirtualProductCustomStockTest.xml @@ -35,8 +35,8 @@ <argument name="websiteName" value="{{_defaultWebsite.name}}"/> </actionGroup> <deleteData createDataKey="additionalStock" after="logoutOfAdmin" stepKey="deleteStock"/> - <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> -</after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> + </after> <!--Assign virtual product to additional source.--> <actionGroup ref="AssignSourceToProductActionGroup" stepKey="assignTestSourceToCreatedProduct" after="openProductEditPage"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundBundleProductDefaultStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundBundleProductDefaultStockTest.xml index a7114053721b..33935f436218 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundBundleProductDefaultStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundBundleProductDefaultStockTest.xml @@ -32,8 +32,8 @@ <after> <remove keyForRemoval="assignMainWebsiteToDefaultStock"/> <remove keyForRemoval="deleteStock"/> - <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> -</after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> + </after> <!--Set 'Default' Source quantity.--> <remove keyForRemoval="assignTestSourceToCreatedProduct"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoiceGroupedProductCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoiceGroupedProductCustomStockTest.xml index 633a99987633..4c6d9928acc1 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoiceGroupedProductCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoiceGroupedProductCustomStockTest.xml @@ -35,8 +35,8 @@ <argument name="websiteName" value="{{_defaultWebsite.name}}"/> </actionGroup> <deleteData createDataKey="additionalStock" after="logoutOfAdmin" stepKey="deleteStock"/> - <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> -</after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> + </after> <!--Assign virtual product to additional source.--> <actionGroup ref="AssignSourceToProductActionGroup" stepKey="assignTestSourceToCreatedProduct" after="openVirtualProductPage"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoiceVirtualProductCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoiceVirtualProductCustomStockTest.xml index 7d9ee97b0b80..4c82f6d99348 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoiceVirtualProductCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundFullInvoiceVirtualProductCustomStockTest.xml @@ -35,8 +35,8 @@ <argument name="websiteName" value="{{_defaultWebsite.name}}"/> </actionGroup> <deleteData createDataKey="additionalStock" after="logoutOfAdmin" stepKey="deleteStock"/> - <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> -</after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> + </after> <!--Assign virtual product to additional source.--> <actionGroup ref="AssignSourceToProductActionGroup" stepKey="assignTestSourceToCreatedProduct" after="openProductEditPage"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundVirtualProductCustomOptionCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundVirtualProductCustomOptionCustomStockTest.xml index 236af10cb73f..a773af65f9cc 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundVirtualProductCustomOptionCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundVirtualProductCustomOptionCustomStockTest.xml @@ -35,8 +35,8 @@ <argument name="websiteName" value="{{_defaultWebsite.name}}"/> </actionGroup> <deleteData createDataKey="additionalStock" after="logoutOfAdmin" stepKey="deleteStock"/> - <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> -</after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> + </after> <!--Assign virtual product to additional source.--> <actionGroup ref="AssignSourceToProductActionGroup" stepKey="assignTestSourceToCreatedProduct" after="openProductEditPage"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialShipmentForOrderWithSimpleProductFromCustomSourceTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialShipmentForOrderWithSimpleProductFromCustomSourceTest.xml index fdb92e527b86..1b64a326dec8 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialShipmentForOrderWithSimpleProductFromCustomSourceTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialShipmentForOrderWithSimpleProductFromCustomSourceTest.xml @@ -80,14 +80,14 @@ </actionGroup> </before> <after> + <!-- Delete all products via API --> + <helper class="Magento\Catalog\Test\Mftf\Helper\ProductApiHelper" method="deleteAllProductsApi" stepKey="deleteAllProductsViaApi"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <!-- Delete all products via API --> - <helper class="Magento\Catalog\Test\Mftf\Helper\ProductApiHelper" method="deleteAllProductsApi" stepKey="deleteAllProductsViaApi"/> - <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> -</after> + </after> <!-- Login as Customer and add Product to Cart--> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="customerLogin"> From bf8c344d51edb1909bdb37c79d4c77e88a075906 Mon Sep 17 00:00:00 2001 From: soumah <soumah@adobe.com> Date: Fri, 8 May 2026 09:32:27 -0500 Subject: [PATCH 30/83] ACP2E-4866: Bundle Product stock status inconsistency - Fix CR comments --- InventoryBundleProductIndexer/Indexer/SelectBuilder.php | 6 +++--- .../Indexer/SelectBuilder.php | 6 +++--- InventoryConfigurableProductIndexer/composer.json | 2 +- InventoryGroupedProductIndexer/Indexer/SelectBuilder.php | 6 +++--- InventoryGroupedProductIndexer/composer.json | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/InventoryBundleProductIndexer/Indexer/SelectBuilder.php b/InventoryBundleProductIndexer/Indexer/SelectBuilder.php index 8c48ae8cb020..40dc98e0a145 100644 --- a/InventoryBundleProductIndexer/Indexer/SelectBuilder.php +++ b/InventoryBundleProductIndexer/Indexer/SelectBuilder.php @@ -8,10 +8,10 @@ namespace Magento\InventoryBundleProductIndexer\Indexer; use Magento\Bundle\Model\Product\Type as BundleProductType; -use Magento\CatalogInventory\Api\StockConfigurationInterface; use Magento\Framework\App\ResourceConnection; use Magento\Framework\DB\Select; use Magento\InventoryCatalogApi\Api\DefaultStockProviderInterface; +use Magento\InventoryConfigurationApi\Model\InventoryConfigurationInterface; use Magento\InventoryIndexer\Indexer\IndexStructure; use Magento\InventoryIndexer\Indexer\SiblingSelectBuilderInterface; use Magento\InventoryMultiDimensionalIndexerApi\Model\IndexAlias; @@ -40,13 +40,13 @@ class SelectBuilder implements SiblingSelectBuilderInterface * @param ResourceConnection $resourceConnection * @param DefaultStockProviderInterface $defaultStockProvider * @param OptionsStatusSelectBuilder $optionsStatusSelectBuilder - * @param StockConfigurationInterface $configuration + * @param InventoryConfigurationInterface $configuration */ public function __construct( ResourceConnection $resourceConnection, DefaultStockProviderInterface $defaultStockProvider, OptionsStatusSelectBuilder $optionsStatusSelectBuilder, - private readonly StockConfigurationInterface $configuration + private readonly InventoryConfigurationInterface $configuration ) { $this->resourceConnection = $resourceConnection; $this->defaultStockProvider = $defaultStockProvider; diff --git a/InventoryConfigurableProductIndexer/Indexer/SelectBuilder.php b/InventoryConfigurableProductIndexer/Indexer/SelectBuilder.php index 698c24de5006..ebc6ac10a504 100644 --- a/InventoryConfigurableProductIndexer/Indexer/SelectBuilder.php +++ b/InventoryConfigurableProductIndexer/Indexer/SelectBuilder.php @@ -8,11 +8,11 @@ namespace Magento\InventoryConfigurableProductIndexer\Indexer; use Magento\Catalog\Api\Data\ProductInterface; -use Magento\CatalogInventory\Api\StockConfigurationInterface; use Magento\Framework\App\ResourceConnection; use Magento\Framework\DB\Select; use Magento\Framework\EntityManager\MetadataPool; use Magento\InventoryCatalogApi\Api\DefaultStockProviderInterface; +use Magento\InventoryConfigurationApi\Model\InventoryConfigurationInterface; use Magento\InventoryIndexer\Indexer\IndexStructure; use Magento\InventoryIndexer\Indexer\InventoryIndexer; use Magento\InventoryIndexer\Indexer\SiblingSelectBuilderInterface; @@ -28,7 +28,7 @@ class SelectBuilder implements SiblingSelectBuilderInterface * @param IndexNameResolverInterface $indexNameResolver * @param MetadataPool $metadataPool * @param DefaultStockProviderInterface $defaultStockProvider - * @param StockConfigurationInterface $configuration + * @param InventoryConfigurationInterface $configuration */ public function __construct( private readonly ResourceConnection $resourceConnection, @@ -36,7 +36,7 @@ public function __construct( private readonly IndexNameResolverInterface $indexNameResolver, private readonly MetadataPool $metadataPool, private readonly DefaultStockProviderInterface $defaultStockProvider, - private readonly StockConfigurationInterface $configuration + private readonly InventoryConfigurationInterface $configuration ) { } diff --git a/InventoryConfigurableProductIndexer/composer.json b/InventoryConfigurableProductIndexer/composer.json index 3b9269ffb335..bdbc140d94e3 100644 --- a/InventoryConfigurableProductIndexer/composer.json +++ b/InventoryConfigurableProductIndexer/composer.json @@ -10,7 +10,7 @@ "magento/module-inventory-indexer": "*", "magento/module-inventory-multi-dimensional-indexer-api": "*", "magento/module-configurable-product": "*", - "magento/module-catalog-inventory": "*" + "magento/module-inventory-configuration-api": "*" }, "suggest": { "magento/module-inventory": "*" diff --git a/InventoryGroupedProductIndexer/Indexer/SelectBuilder.php b/InventoryGroupedProductIndexer/Indexer/SelectBuilder.php index 1ebaf717ca85..e6a586cce7ef 100644 --- a/InventoryGroupedProductIndexer/Indexer/SelectBuilder.php +++ b/InventoryGroupedProductIndexer/Indexer/SelectBuilder.php @@ -8,11 +8,11 @@ namespace Magento\InventoryGroupedProductIndexer\Indexer; use Magento\Catalog\Api\Data\ProductInterface; -use Magento\CatalogInventory\Api\StockConfigurationInterface; use Magento\Framework\App\ResourceConnection; use Magento\Framework\DB\Select; use Magento\Framework\EntityManager\MetadataPool; use Magento\GroupedProduct\Model\ResourceModel\Product\Link; +use Magento\InventoryConfigurationApi\Model\InventoryConfigurationInterface; use Magento\InventoryIndexer\Indexer\IndexStructure; use Magento\InventoryIndexer\Indexer\InventoryIndexer; use Magento\InventoryIndexer\Indexer\SiblingSelectBuilderInterface; @@ -30,14 +30,14 @@ class SelectBuilder implements SiblingSelectBuilderInterface * @param IndexNameBuilder $indexNameBuilder * @param IndexNameResolverInterface $indexNameResolver * @param MetadataPool $metadataPool - * @param StockConfigurationInterface $configuration + * @param InventoryConfigurationInterface $configuration */ public function __construct( private readonly ResourceConnection $resourceConnection, private readonly IndexNameBuilder $indexNameBuilder, private readonly IndexNameResolverInterface $indexNameResolver, private readonly MetadataPool $metadataPool, - private readonly StockConfigurationInterface $configuration + private readonly InventoryConfigurationInterface $configuration ) { } diff --git a/InventoryGroupedProductIndexer/composer.json b/InventoryGroupedProductIndexer/composer.json index 63d4d2202212..e6d06da9c438 100644 --- a/InventoryGroupedProductIndexer/composer.json +++ b/InventoryGroupedProductIndexer/composer.json @@ -8,7 +8,7 @@ "magento/module-inventory-indexer": "*", "magento/module-inventory-multi-dimensional-indexer-api": "*", "magento/module-grouped-product": "*", - "magento/module-catalog-inventory": "*" + "magento/module-inventory-configuration-api": "*" }, "suggest": { "magento/module-inventory": "*" From 47dba755e82fbf779fe51f6d749e9220a1aa96d5 Mon Sep 17 00:00:00 2001 From: Karishma Thakare <del57145@adobe.com> Date: Mon, 11 May 2026 15:10:57 +0530 Subject: [PATCH 31/83] ACQE-9845: Filter - Sales Order Grid - Added filter clearance code --- .../Mftf/Test/AdminReorderBundleProductOnCustomStockTest.xml | 1 + .../Mftf/Test/AdminReorderSimpleProductDefaultStockTest.xml | 1 + ...PrioritySelectionAlgorithmSimpleProductCustomStockTest.xml | 1 + ...AlgorithmSourcePriorityWithSimpleProductOutOfStockTest.xml | 1 + ...StockStatusChangedForMixedProductTypesOnTestSourceTest.xml | 1 + ...thSimpleProductFromTestSourceWithNumericSourceCodeTest.xml | 1 + ...lableQuantityOfSourceAndStockForProductAfterRefundTest.xml | 1 + .../CustomerReorderDownloadableProductCustomStockTest.xml | 1 + ...tCustomerCreateOrderWithSimpleProductOnCustomStockTest.xml | 1 + ...erOrderedVirtualProductOnDefaultSourceFromHomepageTest.xml | 1 + ...rderWithSimpleProductOnDefaultStockFromMainWebsiteTest.xml | 1 + ...eatedOrderWithSimpleProductOnTestStockFromHomepageTest.xml | 1 + .../LoggedInCustomerOrderGroupedProductCustomStockTest.xml | 1 + ...ithChildProductsAssignedToDefaultStockFromHomepageTest.xml | 4 ++++ ...romTestSourceUsingMultiShipmentsToSeveralAddressesTest.xml | 4 ++++ ...LoggedInCustomerReorderSimpleProductOnDefaultStockTest.xml | 1 + .../LoggedInCustomerReorderSimpleProductOnTestStockTest.xml | 1 + ...oggedInCustomerReorderVirtualProductOnDefaultStockTest.xml | 1 + .../LoggedInCustomerReorderVirtualProductOnTestStockTest.xml | 1 + ...gorithmSimpleProductCustomStockNotSupportedCountryTest.xml | 1 + ...nceBasedSelectionAlgorithmSimpleProductCustomStockTest.xml | 1 + ...RegisteredCustomerReorderGroupedProductCustomStockTest.xml | 1 + ...egisteredCustomerReorderGroupedProductDefaultStockTest.xml | 1 + .../Mftf/Test/ReorderButtonBundleProductDefaultStockTest.xml | 1 + .../Test/ReorderButtonDownlodableProductDefaultSourceTest.xml | 1 + .../Mftf/Test/ReorderButtonGroupedProductOnTestStockTest.xml | 1 + .../Test/ReorderButtonSimpleProductOnDefaultStockTest.xml | 1 + .../Test/ReorderButtonVirtualProductOnDefaultStockTest.xml | 1 + ...derOfTheOrderWithSimpleProductOnTestStockFromAdminTest.xml | 1 + .../AdminNotifyCustomerForPickupOrderBundleProductTest.xml | 1 + ...minNotifyCustomerForPickupOrderConfigurableProductTest.xml | 1 + .../AdminNotifyCustomerForPickupOrderGroupedProductTest.xml | 1 + ...rIsReadyForPickupTwiceWithSimpleProductCustomStockTest.xml | 1 + ...yOrderIsReadyForPickupWithSimpleProductCustomStockTest.xml | 1 + ...ceOrderWithPickupInStoreMethodWithGoogleAPIEnabledTest.xml | 1 + ...ceOrderWithPickupInStoreMethodWithGoogleAPIEnabledTest.xml | 1 + ...ourcesColumnTnTheSalesOrderGridInMagentoAdminPanelTest.xml | 1 + ...tyCheckShipmentForMultiProductOrderWithMultiSourceTest.xml | 1 + .../Test/Mftf/Test/SourcesPagerForOrderShipmentTest.xml | 1 + 39 files changed, 45 insertions(+) diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminReorderBundleProductOnCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminReorderBundleProductOnCustomStockTest.xml index 389e31bac384..f064f8001fe8 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminReorderBundleProductOnCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminReorderBundleProductOnCustomStockTest.xml @@ -84,6 +84,7 @@ <argument name="websiteName" value="{{_defaultWebsite.name}}"/> </actionGroup> <deleteData createDataKey="stock" stepKey="deleteStock"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminReorderSimpleProductDefaultStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminReorderSimpleProductDefaultStockTest.xml index 5e6f6d1ba216..8c34068ff80b 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminReorderSimpleProductDefaultStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminReorderSimpleProductDefaultStockTest.xml @@ -42,6 +42,7 @@ <deleteData createDataKey="simpleCategory" stepKey="deleteCategory"/> <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> <actionGroup ref="DisableAllSourcesActionGroup" stepKey="disableAllSources"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminSourcePrioritySelectionAlgorithmSimpleProductCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminSourcePrioritySelectionAlgorithmSimpleProductCustomStockTest.xml index 2b9d9931cfe3..9092862a5003 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminSourcePrioritySelectionAlgorithmSimpleProductCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminSourcePrioritySelectionAlgorithmSimpleProductCustomStockTest.xml @@ -100,6 +100,7 @@ <waitForPageLoad time="30" stepKey="waitFroDefaultStockEditPageLoad"/> <selectOption selector="{{AdminEditStockSalesChannelsSection.websites}}" userInput="Main Website" stepKey="selectDefaultWebsiteAsSalesChannelForDefaultStock"/> <click selector="{{AdminGridMainControls.saveAndContinue}}" stepKey="saveDefaultStock"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <deleteData createDataKey="category" stepKey="deleteCategory"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminSourceSelectionAlgorithmSourcePriorityWithSimpleProductOutOfStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminSourceSelectionAlgorithmSourcePriorityWithSimpleProductOutOfStockTest.xml index daaf676363f9..0054629a8456 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminSourceSelectionAlgorithmSourcePriorityWithSimpleProductOutOfStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminSourceSelectionAlgorithmSourcePriorityWithSimpleProductOutOfStockTest.xml @@ -93,6 +93,7 @@ <comment userInput="BIC workaround" stepKey="selectDefaultWebsiteAsSalesChannelForDefaultStock"/> <comment userInput="BIC workaround" stepKey="saveDefaultStock"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <!--Remove category, product, customer and additional stock.--> <deleteData createDataKey="simpleCategory" stepKey="deleteCategory"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminStockStatusChangedForMixedProductTypesOnTestSourceTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminStockStatusChangedForMixedProductTypesOnTestSourceTest.xml index 3778b72f4b6e..c2f077f34309 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminStockStatusChangedForMixedProductTypesOnTestSourceTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminStockStatusChangedForMixedProductTypesOnTestSourceTest.xml @@ -84,6 +84,7 @@ <!--Disable all sources.--> <actionGroup ref="DisableAllSourcesActionGroup" stepKey="deleteSource"/> <!--Admin logout--> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Login as customer --> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminUserCreatedShipmentForWholeOrderWithSimpleProductFromTestSourceWithNumericSourceCodeTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminUserCreatedShipmentForWholeOrderWithSimpleProductFromTestSourceWithNumericSourceCodeTest.xml index 6e92f6b7f382..79c18a0ab256 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminUserCreatedShipmentForWholeOrderWithSimpleProductFromTestSourceWithNumericSourceCodeTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminUserCreatedShipmentForWholeOrderWithSimpleProductFromTestSourceWithNumericSourceCodeTest.xml @@ -52,6 +52,7 @@ </before> <after> <!--Assign Default Stock to Default Website.--> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AssignWebsiteToStockActionGroup" stepKey="assignMainWebsiteToDefaultStock"> <argument name="stockName" value="{{_defaultStock.name}}"/> <argument name="websiteName" value="{{_defaultWebsite.name}}"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminVerifySalableQuantityOfSourceAndStockForProductAfterRefundTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminVerifySalableQuantityOfSourceAndStockForProductAfterRefundTest.xml index ad6fe55a2abb..34d200bfcbec 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminVerifySalableQuantityOfSourceAndStockForProductAfterRefundTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminVerifySalableQuantityOfSourceAndStockForProductAfterRefundTest.xml @@ -31,6 +31,7 @@ <argument name="websiteName" value="{{_defaultWebsite.name}}"/> </actionGroup> <!--Admin Logout--> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <!-- Logout from Storefront--> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/CustomerReorderDownloadableProductCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/CustomerReorderDownloadableProductCustomStockTest.xml index b2cd262eca42..b81367c6727b 100644 --- a/InventoryAdminUi/Test/Mftf/Test/CustomerReorderDownloadableProductCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/CustomerReorderDownloadableProductCustomStockTest.xml @@ -23,6 +23,7 @@ <createData entity="MsiCustomer1" stepKey="customer" after="linkSourceStock1"/> </before> <after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter" before="logoutFromAdminArea"/> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> <deleteData createDataKey="customer" stepKey="deleteCustomer" after="deleteCustomStock"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/GuestCustomerCreateOrderWithSimpleProductOnCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/GuestCustomerCreateOrderWithSimpleProductOnCustomStockTest.xml index 8824dc75e8a3..15af4d4d31f8 100644 --- a/InventoryAdminUi/Test/Mftf/Test/GuestCustomerCreateOrderWithSimpleProductOnCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/GuestCustomerCreateOrderWithSimpleProductOnCustomStockTest.xml @@ -75,6 +75,7 @@ <actionGroup ref="CliCacheFlushActionGroup" stepKey="cleanCache"> <argument name="tags" value=""/> </actionGroup> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/GuestCustomerOrderedVirtualProductOnDefaultSourceFromHomepageTest.xml b/InventoryAdminUi/Test/Mftf/Test/GuestCustomerOrderedVirtualProductOnDefaultSourceFromHomepageTest.xml index 8b77c3b0643a..4c8ee59c7925 100644 --- a/InventoryAdminUi/Test/Mftf/Test/GuestCustomerOrderedVirtualProductOnDefaultSourceFromHomepageTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/GuestCustomerOrderedVirtualProductOnDefaultSourceFromHomepageTest.xml @@ -56,6 +56,7 @@ <comment userInput="BIC workaround" stepKey="disableCustomSource"/> <comment userInput="BIC workaround" stepKey="saveAndCloseCustomSource"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <deleteData createDataKey="category" stepKey="deleteCategory"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerCreateOrderWithSimpleProductOnDefaultStockFromMainWebsiteTest.xml b/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerCreateOrderWithSimpleProductOnDefaultStockFromMainWebsiteTest.xml index bead16f8390d..6c9419830b6a 100644 --- a/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerCreateOrderWithSimpleProductOnDefaultStockFromMainWebsiteTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerCreateOrderWithSimpleProductOnDefaultStockFromMainWebsiteTest.xml @@ -63,6 +63,7 @@ <actionGroup ref="DisableSourceActionGroup" stepKey="disableCreatedCustomSource"> <argument name="sourceCode" value="$$customSource.source[source_code]$$"/> </actionGroup> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <deleteData createDataKey="category" stepKey="deleteCategory"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerCreatedOrderWithSimpleProductOnTestStockFromHomepageTest.xml b/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerCreatedOrderWithSimpleProductOnTestStockFromHomepageTest.xml index 027bb29fef4e..539af07bf14e 100644 --- a/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerCreatedOrderWithSimpleProductOnTestStockFromHomepageTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerCreatedOrderWithSimpleProductOnTestStockFromHomepageTest.xml @@ -45,6 +45,7 @@ <actionGroup ref="DisableSourceActionGroup" stepKey="disableThirdCreatedSource"> <argument name="sourceCode" value="$$createSource.source[source_code]$$"/> </actionGroup> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerOrderGroupedProductCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerOrderGroupedProductCustomStockTest.xml index edb943383dd0..65446e1350e8 100644 --- a/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerOrderGroupedProductCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerOrderGroupedProductCustomStockTest.xml @@ -44,6 +44,7 @@ <actionGroup ref="DisableSourceActionGroup" stepKey="disableCreatedCustomSource"> <argument name="sourceCode" value="$$additionalSource.source[source_code]$$"/> </actionGroup> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <!--Remove test data.--> <deleteData createDataKey="product" stepKey="deleteProduct"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerOrderedGroupedProductWithChildProductsAssignedToDefaultStockFromHomepageTest.xml b/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerOrderedGroupedProductWithChildProductsAssignedToDefaultStockFromHomepageTest.xml index e8ea3b40c888..a9c10b82eadf 100644 --- a/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerOrderedGroupedProductWithChildProductsAssignedToDefaultStockFromHomepageTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerOrderedGroupedProductWithChildProductsAssignedToDefaultStockFromHomepageTest.xml @@ -20,6 +20,7 @@ <group value="multi_mode"/> <group value="pr_exclude"/> </annotations> + <before> <remove keyForRemoval="navigateToStockListPage"/> <remove keyForRemoval="waitForStockListPageLoad"/> @@ -29,6 +30,9 @@ <remove keyForRemoval="selectDefaultWebsiteAsSalesChannelForDefaultStock"/> <remove keyForRemoval="saveDefaultStock"/> </before> + <after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter" before="logoutFromAdminArea"/> + </after> <remove keyForRemoval="createNewOrderForCustomer"/> <remove keyForRemoval="clickOnDefaultStoreViewIfPresent1"/> <remove keyForRemoval="waitForPageLoad3"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerOrderedSimpleProductFromTestSourceUsingMultiShipmentsToSeveralAddressesTest.xml b/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerOrderedSimpleProductFromTestSourceUsingMultiShipmentsToSeveralAddressesTest.xml index 3f0e39846664..4555e21a7469 100644 --- a/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerOrderedSimpleProductFromTestSourceUsingMultiShipmentsToSeveralAddressesTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerOrderedSimpleProductFromTestSourceUsingMultiShipmentsToSeveralAddressesTest.xml @@ -21,9 +21,13 @@ <group value="multi_mode"/> <group value="pr_exclude"/> </annotations> + <before> <remove keyForRemoval="assignStockToAdditionalWebsite"/> </before> + <after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter" before="deleteSimpleProduct"/> + </after> <remove keyForRemoval="assignTestSourceToCreatedProduct"/> <remove keyForRemoval="setProductQuantity"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerReorderSimpleProductOnDefaultStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerReorderSimpleProductOnDefaultStockTest.xml index ad3d49bb1ab6..650b7a27bed8 100644 --- a/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerReorderSimpleProductOnDefaultStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerReorderSimpleProductOnDefaultStockTest.xml @@ -46,6 +46,7 @@ <deleteData createDataKey="product" stepKey="deleteProduct"/> <!--Disable additional source.--> <actionGroup ref="DisableAllSourcesActionGroup" stepKey="disableAllSources"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerReorderSimpleProductOnTestStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerReorderSimpleProductOnTestStockTest.xml index 1b5d5e46c307..e56084adfe7f 100644 --- a/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerReorderSimpleProductOnTestStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerReorderSimpleProductOnTestStockTest.xml @@ -58,6 +58,7 @@ </actionGroup> <deleteData createDataKey="additionalStock" stepKey="deleteStock"/> <actionGroup ref="DisableAllSourcesActionGroup" stepKey="disableAllSources"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerReorderVirtualProductOnDefaultStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerReorderVirtualProductOnDefaultStockTest.xml index f4392e4d9ce6..ce1c56239fd3 100644 --- a/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerReorderVirtualProductOnDefaultStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerReorderVirtualProductOnDefaultStockTest.xml @@ -36,6 +36,7 @@ <actionGroup ref="DisableSourceActionGroup" stepKey="disableAdditionalSource"> <argument name="sourceCode" value="$$additionalSource.source[source_code]$$"/> </actionGroup> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <!--Clean up created data.--> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> diff --git a/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerReorderVirtualProductOnTestStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerReorderVirtualProductOnTestStockTest.xml index 6d981a88b9a9..f91ef3259644 100644 --- a/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerReorderVirtualProductOnTestStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/LoggedInCustomerReorderVirtualProductOnTestStockTest.xml @@ -59,6 +59,7 @@ <argument name="websiteName" value="{{_defaultWebsite.name}}"/> </actionGroup> <deleteData createDataKey="additionalStock" stepKey="deleteStock"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryAdminUi/Test/Mftf/Test/OfflineDistanceBasedSelectionAlgorithmSimpleProductCustomStockNotSupportedCountryTest.xml b/InventoryAdminUi/Test/Mftf/Test/OfflineDistanceBasedSelectionAlgorithmSimpleProductCustomStockNotSupportedCountryTest.xml index f2c724ce74bc..e950726dc38a 100644 --- a/InventoryAdminUi/Test/Mftf/Test/OfflineDistanceBasedSelectionAlgorithmSimpleProductCustomStockNotSupportedCountryTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/OfflineDistanceBasedSelectionAlgorithmSimpleProductCustomStockNotSupportedCountryTest.xml @@ -101,6 +101,7 @@ <comment userInput="BIC workaround" stepKey="selectDefaultWebsiteAsSalesChannelForDefaultStock"/> <comment userInput="BIC workaround" stepKey="saveDefaultStock"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <!--Remove category, product, customer and additional stock.--> <deleteData createDataKey="category" stepKey="deleteCategory"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/OfflineDistanceBasedSelectionAlgorithmSimpleProductCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/OfflineDistanceBasedSelectionAlgorithmSimpleProductCustomStockTest.xml index e05fcc32ea24..96751cd7c5d0 100644 --- a/InventoryAdminUi/Test/Mftf/Test/OfflineDistanceBasedSelectionAlgorithmSimpleProductCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/OfflineDistanceBasedSelectionAlgorithmSimpleProductCustomStockTest.xml @@ -102,6 +102,7 @@ <comment userInput="BIC workaround" stepKey="selectDefaultWebsiteAsSalesChannelForDefaultStock"/> <comment userInput="BIC workaround" stepKey="saveDefaultStock"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <!--Remove category, product, customer and additional stock.--> <deleteData createDataKey="category" stepKey="deleteCategory"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/RegisteredCustomerReorderGroupedProductCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/RegisteredCustomerReorderGroupedProductCustomStockTest.xml index ee0b15bd312e..f7b18d4e7c49 100644 --- a/InventoryAdminUi/Test/Mftf/Test/RegisteredCustomerReorderGroupedProductCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/RegisteredCustomerReorderGroupedProductCustomStockTest.xml @@ -79,6 +79,7 @@ </actionGroup> <deleteData createDataKey="additionalStock" stepKey="deleteStock"/> <deleteData createDataKey="category" stepKey="deletecategory"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryAdminUi/Test/Mftf/Test/RegisteredCustomerReorderGroupedProductDefaultStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/RegisteredCustomerReorderGroupedProductDefaultStockTest.xml index 133c5a9a63e3..0729c64a4f2a 100644 --- a/InventoryAdminUi/Test/Mftf/Test/RegisteredCustomerReorderGroupedProductDefaultStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/RegisteredCustomerReorderGroupedProductDefaultStockTest.xml @@ -69,6 +69,7 @@ <!--Disable additional source.--> <actionGroup ref="DisableAllSourcesActionGroup" stepKey="disableAllSources"/> <deleteData createDataKey="category" stepKey="deletecategory"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryAdminUi/Test/Mftf/Test/ReorderButtonBundleProductDefaultStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/ReorderButtonBundleProductDefaultStockTest.xml index ae2b0229720d..a79d7f3f4959 100644 --- a/InventoryAdminUi/Test/Mftf/Test/ReorderButtonBundleProductDefaultStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/ReorderButtonBundleProductDefaultStockTest.xml @@ -75,6 +75,7 @@ <actionGroup ref="DisableSourceActionGroup" stepKey="disableAdditionalSource"> <argument name="sourceCode" value="$$additionalSource.source[source_code]$$"/> </actionGroup> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <!--Clean up created data.--> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> diff --git a/InventoryAdminUi/Test/Mftf/Test/ReorderButtonDownlodableProductDefaultSourceTest.xml b/InventoryAdminUi/Test/Mftf/Test/ReorderButtonDownlodableProductDefaultSourceTest.xml index 70cb4b9dec28..08fe4a71e1e6 100644 --- a/InventoryAdminUi/Test/Mftf/Test/ReorderButtonDownlodableProductDefaultSourceTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/ReorderButtonDownlodableProductDefaultSourceTest.xml @@ -45,6 +45,7 @@ <actionGroup ref="DisableSourceActionGroup" stepKey="disableAdditionalSource"> <argument name="sourceCode" value="$$additionalSource.source[source_code]$$"/> </actionGroup> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <!--Clean up created data.--> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> diff --git a/InventoryAdminUi/Test/Mftf/Test/ReorderButtonGroupedProductOnTestStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/ReorderButtonGroupedProductOnTestStockTest.xml index 08128b820035..456eb7d2483d 100644 --- a/InventoryAdminUi/Test/Mftf/Test/ReorderButtonGroupedProductOnTestStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/ReorderButtonGroupedProductOnTestStockTest.xml @@ -39,6 +39,7 @@ <!--Disable additional source.--> <actionGroup ref="DisableAllSourcesActionGroup" stepKey="disableCustomSource"/> <deleteData createDataKey="category" stepKey="deletecategory"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <!--Clean up created data.--> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> diff --git a/InventoryAdminUi/Test/Mftf/Test/ReorderButtonSimpleProductOnDefaultStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/ReorderButtonSimpleProductOnDefaultStockTest.xml index 740183a28fb5..d6aaef2ed873 100644 --- a/InventoryAdminUi/Test/Mftf/Test/ReorderButtonSimpleProductOnDefaultStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/ReorderButtonSimpleProductOnDefaultStockTest.xml @@ -35,6 +35,7 @@ <actionGroup ref="DisableSourceActionGroup" stepKey="disableThirdCreatedSource"> <argument name="sourceCode" value="$$additionalSource.source[source_code]$$"/> </actionGroup> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <!--Clean up created data.--> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> diff --git a/InventoryAdminUi/Test/Mftf/Test/ReorderButtonVirtualProductOnDefaultStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/ReorderButtonVirtualProductOnDefaultStockTest.xml index 3eb10bcd15e7..2ed0a7f617db 100644 --- a/InventoryAdminUi/Test/Mftf/Test/ReorderButtonVirtualProductOnDefaultStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/ReorderButtonVirtualProductOnDefaultStockTest.xml @@ -38,6 +38,7 @@ <actionGroup ref="DisableSourceActionGroup" stepKey="disableAdditionalSource"> <argument name="sourceCode" value="$$additionalSource.source[source_code]$$"/> </actionGroup> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <!--Clean up created data.--> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> diff --git a/InventoryAdminUi/Test/Mftf/Test/ReorderOfTheOrderWithSimpleProductOnTestStockFromAdminTest.xml b/InventoryAdminUi/Test/Mftf/Test/ReorderOfTheOrderWithSimpleProductOnTestStockFromAdminTest.xml index 15ffe6aaf3f5..c0b8d0bc0e2d 100644 --- a/InventoryAdminUi/Test/Mftf/Test/ReorderOfTheOrderWithSimpleProductOnTestStockFromAdminTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/ReorderOfTheOrderWithSimpleProductOnTestStockFromAdminTest.xml @@ -49,6 +49,7 @@ <argument name="websiteName" value="{{_defaultWebsite.name}}"/> </actionGroup> <deleteData createDataKey="createStock" stepKey="deleteStock"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminNotifyCustomerForPickupOrderBundleProductTest.xml b/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminNotifyCustomerForPickupOrderBundleProductTest.xml index 69c922467964..f2c50dedfeb4 100644 --- a/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminNotifyCustomerForPickupOrderBundleProductTest.xml +++ b/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminNotifyCustomerForPickupOrderBundleProductTest.xml @@ -97,6 +97,7 @@ <actionGroup ref="CliCacheCleanActionGroup" stepKey="cleanCache"> <argument name="tags" value=""/> </actionGroup> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> <!--Add bundle product to cart.--> diff --git a/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminNotifyCustomerForPickupOrderConfigurableProductTest.xml b/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminNotifyCustomerForPickupOrderConfigurableProductTest.xml index 8c31fdf01e7a..89ba91cd5c81 100644 --- a/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminNotifyCustomerForPickupOrderConfigurableProductTest.xml +++ b/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminNotifyCustomerForPickupOrderConfigurableProductTest.xml @@ -95,6 +95,7 @@ <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> </actionGroup> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> <!--Add configurable product to cart.--> diff --git a/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminNotifyCustomerForPickupOrderGroupedProductTest.xml b/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminNotifyCustomerForPickupOrderGroupedProductTest.xml index 8348cbdfd63e..8eac4c666a46 100644 --- a/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminNotifyCustomerForPickupOrderGroupedProductTest.xml +++ b/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminNotifyCustomerForPickupOrderGroupedProductTest.xml @@ -78,6 +78,7 @@ </actionGroup> <actionGroup ref="DisableAllSourcesActionGroup" stepKey="disableAllSources"/> <deleteData createDataKey="stock" stepKey="deleteStock"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminNotifyOrderIsReadyForPickupTwiceWithSimpleProductCustomStockTest.xml b/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminNotifyOrderIsReadyForPickupTwiceWithSimpleProductCustomStockTest.xml index ec43b505b382..7f40ba74339f 100644 --- a/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminNotifyOrderIsReadyForPickupTwiceWithSimpleProductCustomStockTest.xml +++ b/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminNotifyOrderIsReadyForPickupTwiceWithSimpleProductCustomStockTest.xml @@ -69,6 +69,7 @@ </actionGroup> <deleteData createDataKey="stock" stepKey="deleteStock"/> <actionGroup ref="DisableAllSourcesActionGroup" stepKey="disableAllSources"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminVerifyNotifyOrderIsReadyForPickupWithSimpleProductCustomStockTest.xml b/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminVerifyNotifyOrderIsReadyForPickupWithSimpleProductCustomStockTest.xml index f69300bc8f86..a0393c8ac5fd 100644 --- a/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminVerifyNotifyOrderIsReadyForPickupWithSimpleProductCustomStockTest.xml +++ b/InventoryInStorePickupAdminUi/Test/Mftf/Test/AdminVerifyNotifyOrderIsReadyForPickupWithSimpleProductCustomStockTest.xml @@ -71,6 +71,7 @@ </actionGroup> <deleteData createDataKey="stock" stepKey="deleteStock"/> <actionGroup ref="DisableAllSourcesActionGroup" stepKey="disableAllSources"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryInStorePickupFrontend/Test/Mftf/Test/GuestCustomerPlaceOrderWithPickupInStoreMethodWithGoogleAPIEnabledTest.xml b/InventoryInStorePickupFrontend/Test/Mftf/Test/GuestCustomerPlaceOrderWithPickupInStoreMethodWithGoogleAPIEnabledTest.xml index d3905ebbf0b8..0a99d2123adf 100644 --- a/InventoryInStorePickupFrontend/Test/Mftf/Test/GuestCustomerPlaceOrderWithPickupInStoreMethodWithGoogleAPIEnabledTest.xml +++ b/InventoryInStorePickupFrontend/Test/Mftf/Test/GuestCustomerPlaceOrderWithPickupInStoreMethodWithGoogleAPIEnabledTest.xml @@ -92,6 +92,7 @@ </actionGroup> <deleteData createDataKey="category" stepKey="deleteCategory"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> <!--Go to storefront --> diff --git a/InventoryInStorePickupFrontend/Test/Mftf/Test/LoggedInCustomerPlaceOrderWithPickupInStoreMethodWithGoogleAPIEnabledTest.xml b/InventoryInStorePickupFrontend/Test/Mftf/Test/LoggedInCustomerPlaceOrderWithPickupInStoreMethodWithGoogleAPIEnabledTest.xml index dd787eac294b..31acffd3eebe 100644 --- a/InventoryInStorePickupFrontend/Test/Mftf/Test/LoggedInCustomerPlaceOrderWithPickupInStoreMethodWithGoogleAPIEnabledTest.xml +++ b/InventoryInStorePickupFrontend/Test/Mftf/Test/LoggedInCustomerPlaceOrderWithPickupInStoreMethodWithGoogleAPIEnabledTest.xml @@ -61,6 +61,7 @@ <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutStorefront"/> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/InventorySalesAdminUi/Test/Mftf/Test/SourcesColumnTnTheSalesOrderGridInMagentoAdminPanelTest.xml b/InventorySalesAdminUi/Test/Mftf/Test/SourcesColumnTnTheSalesOrderGridInMagentoAdminPanelTest.xml index 3b39aea64356..d9d348363809 100644 --- a/InventorySalesAdminUi/Test/Mftf/Test/SourcesColumnTnTheSalesOrderGridInMagentoAdminPanelTest.xml +++ b/InventorySalesAdminUi/Test/Mftf/Test/SourcesColumnTnTheSalesOrderGridInMagentoAdminPanelTest.xml @@ -60,6 +60,7 @@ <argument name="tags" value=""/> </actionGroup> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> diff --git a/InventoryShippingAdminUi/Test/Mftf/Test/QtyCheckShipmentForMultiProductOrderWithMultiSourceTest.xml b/InventoryShippingAdminUi/Test/Mftf/Test/QtyCheckShipmentForMultiProductOrderWithMultiSourceTest.xml index 213c7e9f89c9..952a0ca465a6 100644 --- a/InventoryShippingAdminUi/Test/Mftf/Test/QtyCheckShipmentForMultiProductOrderWithMultiSourceTest.xml +++ b/InventoryShippingAdminUi/Test/Mftf/Test/QtyCheckShipmentForMultiProductOrderWithMultiSourceTest.xml @@ -97,6 +97,7 @@ <argument name="stockName" value="{{_defaultStock.name}}"/> <argument name="websiteName" value="{{_defaultWebsite.name}}"/> </actionGroup> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <!--Remove category, product, customer and additional stock.--> <deleteData createDataKey="category" stepKey="deleteCategory"/> diff --git a/InventoryShippingAdminUi/Test/Mftf/Test/SourcesPagerForOrderShipmentTest.xml b/InventoryShippingAdminUi/Test/Mftf/Test/SourcesPagerForOrderShipmentTest.xml index 5da7fbfa0c16..3f408a09074a 100644 --- a/InventoryShippingAdminUi/Test/Mftf/Test/SourcesPagerForOrderShipmentTest.xml +++ b/InventoryShippingAdminUi/Test/Mftf/Test/SourcesPagerForOrderShipmentTest.xml @@ -213,6 +213,7 @@ <argument name="stockName" value="{{_defaultStock.name}}"/> <argument name="websiteName" value="{{_defaultWebsite.name}}"/> </actionGroup> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <!--Remove category, product, customer and additional stock.--> <deleteData createDataKey="category" stepKey="deleteCategory"/> From 42258896bbb235f712726c27752105df95df62b7 Mon Sep 17 00:00:00 2001 From: chandrakalahanchinal <del66267@adobe.com> Date: Mon, 11 May 2026 19:08:15 +0530 Subject: [PATCH 32/83] ACQE-9557: Update test steps - Updated test steps bases on current flow. --- ...DisabledManageStockOnConfigurationPageCustomStockTest.xml | 5 +---- ...roductDisabledManageStockOnProductPageCustomStockTest.xml | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminBundleProductDisabledManageStockOnConfigurationPageCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminBundleProductDisabledManageStockOnConfigurationPageCustomStockTest.xml index fd6555facc42..c8a40fc994e3 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminBundleProductDisabledManageStockOnConfigurationPageCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminBundleProductDisabledManageStockOnConfigurationPageCustomStockTest.xml @@ -17,9 +17,6 @@ <severity value="CRITICAL"/> <group value="msi"/> <group value="multi_mode"/> - <skip> - <issueId value="https://github.com/magento/inventory/issues/1821"/> - </skip> <group value="pr_exclude"/> </annotations> @@ -106,7 +103,7 @@ <!--Verify product is not visible storefront.--> <amOnPage url="{{StorefrontCategoryPage.url($$category.custom_attributes[url_key]$$)}}" stepKey="navigateToCategoryPage"/> <waitForPageLoad stepKey="waitForCategoryPageLoad"/> - <dontSee userInput="$bundleProduct.name$" stepKey="assertProductIsNotPresent"/> + <see userInput="$bundleProduct.name$" stepKey="assertProductIsPresent1"/> <!--Disable "Manage Stock" in configuration.--> <magentoCLI command="config:set {{TurnOffManageStockConfig.path}} {{TurnOffManageStockConfig.value}}" stepKey="disableManageStock"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminBundleProductDisabledManageStockOnProductPageCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminBundleProductDisabledManageStockOnProductPageCustomStockTest.xml index 35634dd1682d..c7ee98819491 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminBundleProductDisabledManageStockOnProductPageCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminBundleProductDisabledManageStockOnProductPageCustomStockTest.xml @@ -17,9 +17,6 @@ <severity value="CRITICAL"/> <group value="msi"/> <group value="multi_mode"/> - <skip> - <issueId value="https://github.com/magento/inventory/issues/1821"/> - </skip> <group value="pr_exclude"/> </annotations> @@ -92,7 +89,7 @@ <!--Verify product is not visible storefront.--> <amOnPage url="{{StorefrontCategoryPage.url($$category.custom_attributes[url_key]$$)}}" stepKey="navigateToCategoryPage"/> <waitForPageLoad stepKey="waitForCategoryPageLoad"/> - <dontSee userInput="$bundleProduct.name$" stepKey="assertProductIsNotPresent"/> + <see userInput="$bundleProduct.name$" stepKey="assertProductIsPresent1"/> <!--Disable "Manage Stock" On Product Page.--> <amOnPage url="{{AdminProductEditPage.url($$bundleProduct.id$$)}}" stepKey="openProductEditPageToSetStockStatus"/> <click selector="{{AdminProductFormSection.advancedInventoryLink}}" stepKey="clickOnAdvancedInventoryLink"/> From 689b4e2f5c9d9228bb2157ba22ab573b1d23bc34 Mon Sep 17 00:00:00 2001 From: Karishma Thakare <del57145@adobe.com> Date: Tue, 12 May 2026 17:14:09 +0530 Subject: [PATCH 33/83] ACQE-9836: Filter - Sales Order Grid - Added filter clearance code --- ...ntForOrderWithConfigurableProductFromCustomSourceTest.xml | 5 +---- ...entForWholeOrderWithSimpleProductFromCustomSourceTest.xml | 5 +---- ...sToDeductItemsInShipmentForOrderWithSimpleProductTest.xml | 5 +---- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialShipmentForOrderWithConfigurableProductFromCustomSourceTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialShipmentForOrderWithConfigurableProductFromCustomSourceTest.xml index 80bd7038f172..ea84936e518c 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialShipmentForOrderWithConfigurableProductFromCustomSourceTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialShipmentForOrderWithConfigurableProductFromCustomSourceTest.xml @@ -146,10 +146,7 @@ <click selector="{{AdminGridMainControls.saveAndContinue}}" stepKey="saveDefaultStock"/> <!-- Delete configurable product created via UI --> <helper class="Magento\Catalog\Test\Mftf\Helper\ProductApiHelper" method="deleteAllProductsApi" stepKey="deleteAllProductsViaApi"/> - <amOnPage url="{{AdminManageStockPage.url}}" stepKey="goToInventoryStockGridToClearFilters"/> - <waitForPageLoad stepKey="waitForInventoryStockGridToLoad"/> - <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clearInventoryStockGridFilters"/> - <waitForPageLoad stepKey="waitAfterClearInventoryStockFilters"/> + <actionGroup ref="AdminManageStockGridClearFiltersActionGroup" stepKey="clearManageStockGridFiltersAfter"/> <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateShipmentForWholeOrderWithSimpleProductFromCustomSourceTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateShipmentForWholeOrderWithSimpleProductFromCustomSourceTest.xml index 3a05516d5596..f8beb58c4902 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateShipmentForWholeOrderWithSimpleProductFromCustomSourceTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateShipmentForWholeOrderWithSimpleProductFromCustomSourceTest.xml @@ -98,10 +98,7 @@ <after> <!-- Delete simple product created via UI --> <helper class="Magento\Catalog\Test\Mftf\Helper\ProductApiHelper" method="deleteAllProductsApi" stepKey="deleteAllProductsViaApi"/> - <amOnPage url="{{AdminManageStockPage.url}}" stepKey="goToInventoryStockGridToClearFilters"/> - <waitForPageLoad stepKey="waitForInventoryStockGridToLoad"/> - <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clearInventoryStockGridFilters"/> - <waitForPageLoad stepKey="waitAfterClearInventoryStockFilters"/> + <actionGroup ref="AdminManageStockGridClearFiltersActionGroup" stepKey="clearManageStockGridFiltersAfter"/> <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminManualSelectingOfSourcesToDeductItemsInShipmentForOrderWithSimpleProductTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminManualSelectingOfSourcesToDeductItemsInShipmentForOrderWithSimpleProductTest.xml index 4015cddd39b8..308efdf5c68e 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminManualSelectingOfSourcesToDeductItemsInShipmentForOrderWithSimpleProductTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminManualSelectingOfSourcesToDeductItemsInShipmentForOrderWithSimpleProductTest.xml @@ -100,10 +100,7 @@ <after> <!-- Delete all products via API using ProductApiHelper --> <helper class="Magento\Catalog\Test\Mftf\Helper\ProductApiHelper" method="deleteAllProductsApi" stepKey="deleteAllProductsViaApi"/> - <amOnPage url="{{AdminManageStockPage.url}}" stepKey="goToInventoryStockGridToClearFilters"/> - <waitForPageLoad stepKey="waitForInventoryStockGridToLoad"/> - <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clearInventoryStockGridFilters"/> - <waitForPageLoad stepKey="waitAfterClearInventoryStockFilters"/> + <actionGroup ref="AdminManageStockGridClearFiltersActionGroup" stepKey="clearManageStockGridFiltersAfter"/> <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="clearProductGridFilters"/> <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> From 5e0535ed67310956b3f666233c4592e61932a3cf Mon Sep 17 00:00:00 2001 From: Karishma Thakare <del57145@adobe.com> Date: Tue, 12 May 2026 17:17:54 +0530 Subject: [PATCH 34/83] ACQE-9836: Filter - Sales Order Grid - Added filter clearance code --- ...ManageStockGridClearFiltersActionGroup.xml | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 InventoryAdminUi/Test/Mftf/ActionGroup/AdminManageStockGridClearFiltersActionGroup.xml diff --git a/InventoryAdminUi/Test/Mftf/ActionGroup/AdminManageStockGridClearFiltersActionGroup.xml b/InventoryAdminUi/Test/Mftf/ActionGroup/AdminManageStockGridClearFiltersActionGroup.xml new file mode 100644 index 000000000000..43e65165c179 --- /dev/null +++ b/InventoryAdminUi/Test/Mftf/ActionGroup/AdminManageStockGridClearFiltersActionGroup.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright 2024 Adobe + * All Rights Reserved. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminManageStockGridClearFiltersActionGroup"> + <annotations> + <description>Opens the Admin Manage Stock grid and clicks Clear Filters when that control is visible.</description> + </annotations> + <amOnPage url="{{AdminManageStockPage.url}}" stepKey="goToManageStockGridPage"/> + <waitForPageLoad stepKey="waitForManageStockGridPageLoad"/> + <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" + dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" + visible="true" + stepKey="clickClearStockGridFiltersIfPresent"/> + <waitForLoadingMaskToDisappear stepKey="waitAfterClearStockGridFilters"/> + </actionGroup> +</actionGroups> From 07510a2f40b46c6e9614e32cbdc59d808d317221 Mon Sep 17 00:00:00 2001 From: Karishma Thakare <del57145@adobe.com> Date: Tue, 12 May 2026 18:38:53 +0530 Subject: [PATCH 35/83] ACQE-9836: Filter - Sales Order Grid - Added filter clearance code --- .../ActionGroup/AdminManageStockGridClearFiltersActionGroup.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InventoryAdminUi/Test/Mftf/ActionGroup/AdminManageStockGridClearFiltersActionGroup.xml b/InventoryAdminUi/Test/Mftf/ActionGroup/AdminManageStockGridClearFiltersActionGroup.xml index 43e65165c179..3ea5c4865c2e 100644 --- a/InventoryAdminUi/Test/Mftf/ActionGroup/AdminManageStockGridClearFiltersActionGroup.xml +++ b/InventoryAdminUi/Test/Mftf/ActionGroup/AdminManageStockGridClearFiltersActionGroup.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- /** - * Copyright 2024 Adobe + * Copyright 2026 Adobe * All Rights Reserved. */ --> From 7bc848e7013ae7d8d703a14e54d18cc5f4d38e47 Mon Sep 17 00:00:00 2001 From: Alexandra Zota <zota@adobe.com> Date: Wed, 13 May 2026 16:49:43 +0300 Subject: [PATCH 36/83] ACP2E-4933: PR Quality Gates bugfixes and improvements --- .github/scripts/check_copyright.py | 62 ++- .github/scripts/generate-stubs.sh | 17 +- .github/scripts/phpstan.neon | 15 +- .../templates/copyright-public-repo.txt | 4 - .github/workflows/pr-quality-gates.yml | 469 ++++++------------ 5 files changed, 246 insertions(+), 321 deletions(-) delete mode 100644 .github/scripts/templates/copyright-public-repo.txt diff --git a/.github/scripts/check_copyright.py b/.github/scripts/check_copyright.py index 32189451e14d..69a0e1131fc0 100644 --- a/.github/scripts/check_copyright.py +++ b/.github/scripts/check_copyright.py @@ -84,6 +84,9 @@ def _normalize_copyright(text: str) -> str: between file types, matching the approach used by the Jenkins SanityCopyrightChecker. """ + # Remove PHP inline declarations so that '<?php declare(strict_types=1)' + # and '<?php' normalize identically and the copyright substring check passes. + text = re.sub(r'\bdeclare\s*\([^)]*\)\s*;?', '', text) return re.sub(r'[\s#/\*\-<>!?\[\]]+', '', text).lower() @@ -129,11 +132,10 @@ def get_git_creation_year(file_path: str, debug: bool = False, use_current_year: if debug: click.echo(f" Finding git creation year for: {file_path}") - # Try multiple git commands to find the creation year + # Primary: follow renames; fallback: without --follow if rename chain fails git_commands = [ ['git', 'log', '--follow', '--format=%ad', '--date=format:%Y', '--reverse', '--', file_path], - ['git', 'log', '--format=%ad', '--date=format:%Y', '--reverse', '--', file_path], - ['git', 'log', '--diff-filter=A', '--format=%ad', '--date=format:%Y', '--', file_path], + ['git', 'log', '--format=%ad', '--date=format:%Y', '--reverse', '--', file_path], ] for i, cmd in enumerate(git_commands): @@ -551,6 +553,27 @@ def check_file(file_path: str, template: str, fix: bool = False, dry_run: bool = # ── No match ────────────────────────────────────────────────────── + # For existing files in PR mode: if the copyright year already in the file + # is earlier than what git log reports, accept it. This handles files that + # predate the repository's available git history (e.g. Copyright 2011 when + # git log only goes back to 2015 due to history truncation or rebase). + # New files are excluded — they must carry the current year. + if pr_mode and base_sha and existing_header: + try: + cat_result = subprocess.run( + ['git', 'cat-file', '-e', f'{base_sha}:{file_path}'], + capture_output=True, cwd=_GIT_ROOT + ) + if cat_result.returncode == 0: + existing_year_match = re.search(r'[Cc]opyright\s+(\d{4})', existing_header) + if existing_year_match and int(existing_year_match.group(1)) < int(year): + if debug: + click.echo(f' Accepting copyright year {existing_year_match.group(1)}: ' + f'predates git history (git reports {year})') + return True + except Exception: + pass + if dry_run: click.echo(f" Would fix: {file_path}") return False @@ -605,11 +628,12 @@ def check_file(file_path: str, template: str, fix: bool = False, dry_run: bool = @click.option('--stats', is_flag=True, help='Show detailed statistics') @click.option('--debug', is_flag=True, help='Show detailed git debugging information') @click.option('--path', default='.', help='Path to check - can be a file or directory (default: current directory)') +@click.option('--file-list', default='', help='File containing paths to check, one per line (faster than looping --path calls)') @click.option('--verbose', is_flag=True, help='Show verbose output with detailed information') @click.option('--pr-mode', is_flag=True, help='PR mode: trust existing year for modified files, current year for new files') @click.option('--base-sha', default='', help='Base commit SHA for PR mode: used to detect new vs modified files without git log') def main(template: str, fix: bool, dry_run: bool, extensions: str, exclude: str, - magento_only: bool, stats: bool, debug: bool, path: str, verbose: bool, pr_mode: bool, base_sha: str): + magento_only: bool, stats: bool, debug: bool, path: str, file_list: str, verbose: bool, pr_mode: bool, base_sha: str): """Check copyright headers against a template file (Magento-optimized). Template should contain {{YEAR}} placeholder which will be replaced with @@ -636,14 +660,36 @@ def main(template: str, fix: bool, dry_run: bool, extensions: str, exclude: str, click.echo("Cannot use --dry-run and --fix together", err=True) sys.exit(1) - if not os.path.exists(path): - click.echo(f"Path does not exist: {path}", err=True) - sys.exit(1) - template_content = load_template(template) extensions_list = [ext.strip() for ext in extensions.split(',')] exclude_list = [entry.strip() for entry in exclude.split(',') if entry.strip()] + if file_list: + if not os.path.exists(file_list): + click.echo(f"File list not found: {file_list}", err=True) + sys.exit(1) + with open(file_list) as fh: + paths = [line.strip() for line in fh if line.strip()] + issues_found = [] + for file_path in paths: + if not os.path.isfile(file_path): + continue + if should_exclude_file(file_path, exclude_list): + continue + if not any(file_path.endswith(ext) for ext in extensions_list): + continue + if not check_file(file_path, template_content, fix, dry_run, debug, pr_mode, base_sha): + issues_found.append(file_path) + if issues_found: + click.echo(f"\n{len(issues_found)} file(s) have copyright issues") + sys.exit(1) + click.echo("All relevant PR files have correct copyright headers") + return + + if not os.path.exists(path): + click.echo(f"Path does not exist: {path}", err=True) + sys.exit(1) + issues_found = [] files_checked = 0 files_skipped = 0 diff --git a/.github/scripts/generate-stubs.sh b/.github/scripts/generate-stubs.sh index 087b4410f185..02a90fee4032 100755 --- a/.github/scripts/generate-stubs.sh +++ b/.github/scripts/generate-stubs.sh @@ -22,10 +22,25 @@ if [ ! -f "$FILE_LIST" ]; then fi # Extract all 'use Magento\...' from the changed files only, strip aliases -classes=$(cat "$FILE_LIST" | while IFS= read -r f; do +use_classes=$(cat "$FILE_LIST" | while IFS= read -r f; do [ -n "$f" ] && [ -f "$f" ] && grep -h '^use Magento\\' "$f" 2>/dev/null || true done | sed -E 's/^use[[:space:]]+//;s/[[:space:]]+as[[:space:]].*//;s/[[:space:]]*;[[:space:]]*$//' | sort -u) +# Also extract fully-qualified parent classes from 'extends' clauses. +# Catches cases like: class Foo extends \Magento\Catalog\...\Bar +# where no matching 'use' statement exists in the changed file. +extends_classes=$(cat "$FILE_LIST" | while IFS= read -r f; do + [ -n "$f" ] && [ -f "$f" ] && grep -hE '\bextends\b' "$f" 2>/dev/null | grep -oE '\\?Magento(\\[A-Za-z0-9_]+)+' | sed 's/^\\//' || true +done | sort -u) + +# Also extract Magento interfaces from 'implements' clauses — stubs for these +# prevent "implements unknown interface Magento\..." errors in sparse clone. +implements_classes=$(cat "$FILE_LIST" | while IFS= read -r f; do + [ -n "$f" ] && [ -f "$f" ] && grep -hE '\bimplements\b' "$f" 2>/dev/null | grep -oE '\\?Magento(\\[A-Za-z0-9_]+)+' | sed 's/^\\//' || true +done | sort -u) + +classes=$(printf '%s\n%s\n%s\n' "$use_classes" "$extends_classes" "$implements_classes" | grep -v '^$' | sort -u) + if [ -z "$classes" ]; then echo "No Magento class references found in changed files." echo "<?php" > "$STUB_FILE" diff --git a/.github/scripts/phpstan.neon b/.github/scripts/phpstan.neon index c93ee36bf071..8e1d9ecf302b 100644 --- a/.github/scripts/phpstan.neon +++ b/.github/scripts/phpstan.neon @@ -5,7 +5,7 @@ parameters: # Level 1 catches undefined variables, wrong argument counts, - # basic type issues. Same level Jenkins uses. + # basic type issues. level: 1 checkExplicitMixedMissingReturn: true checkPhpDocMissingReturn: true @@ -28,6 +28,7 @@ parameters: - */Test/Mftf/* - */Test/Performance/* - */testsuite/* + - */dev/tests/* ignoreErrors: # Constructor unused parameters (common in Magento DI) - '#Constructor of class [a-zA-Z0-9\\_]+ has an unused parameter#' @@ -51,8 +52,16 @@ parameters: # Note: "extends unknown class" cannot be suppressed via ignoreErrors # (PHPStan hard-rejects it) — those are handled via excludePaths or the # lib/internal autoloader. - - '#has invalid type#' + - '#has invalid.*type#' - '#Class [a-zA-Z0-9\\_\\\\]+ not found\.#' + - '#Instantiated class [a-zA-Z0-9\\_\\\\]+ not found\.#' - '#is not an Attribute class#' - '#has unknown class [a-zA-Z0-9\\_\\\\]+ as its type#' - - '#calls parent::__construct\(\) but [a-zA-Z0-9\\_\\\\]+ does not extend any class#' + - '#calls parent::[a-zA-Z0-9_]+\(\) but [a-zA-Z0-9\\_\\\\]+ does not extend any class#' + # Stub-generated classes have no constructor; sparse-clone cannot include + # the real implementation (e.g. Magento\\Framework\\DataObject). + - '#does not have a constructor and must be instantiated without any parameters#' + # Laminas static method calls when Laminas is not installed in sparse-clone + - '#Call to static method [a-zA-Z0-9_]+\(\) on an unknown class#' + # Undefined variables: GHA scope is changed files only, parity with Static Tests + - '#Undefined variable:#' diff --git a/.github/scripts/templates/copyright-public-repo.txt b/.github/scripts/templates/copyright-public-repo.txt deleted file mode 100644 index 74dfda828bcf..000000000000 --- a/.github/scripts/templates/copyright-public-repo.txt +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Copyright {{YEAR}} Adobe - * All Rights Reserved. - */ diff --git a/.github/workflows/pr-quality-gates.yml b/.github/workflows/pr-quality-gates.yml index 8d4731bb512d..d329e7b6d4bd 100644 --- a/.github/workflows/pr-quality-gates.yml +++ b/.github/workflows/pr-quality-gates.yml @@ -43,115 +43,83 @@ jobs: has_js: ${{ steps.check.outputs.has_js }} has_static: ${{ steps.check.outputs.has_static }} has_new_files: ${{ steps.check.outputs.has_new_files }} + has_copyright_files: ${{ steps.check.outputs.has_copyright_files }} copyright_files: ${{ steps.check.outputs.copyright_files }} steps: - - uses: actions/checkout@v6 - with: - fetch-depth: 0 - # Blobless partial clone: downloads commit/tree objects only. - # File blobs are fetched on demand — only .github/ files are - # written to disk (needed for the CI file presence check). - # git diff --name-only only needs tree objects, so it works here. - filter: blob:none - sparse-checkout: | - .github - - - name: Debug PR gating context - run: | - set -euo pipefail - echo "event_name=${{ github.event_name }}" - echo "event_action=${{ github.event.action }}" - echo "base_owner=${{ github.event.pull_request.base.repo.owner.login }}" - echo "base_repo=${{ github.event.pull_request.base.repo.name }}" - echo "head_owner=${{ github.event.pull_request.head.repo.owner.login }}" - echo "head_repo=${{ github.event.pull_request.head.repo.name }}" - echo "PR_QA_ENABLED_JOBS='${{ vars.PR_QA_ENABLED_JOBS }}'" - - - name: Verify CI files are not removed - run: | - set -euo pipefail - missing=false - for f in \ - .github/workflows/pr-quality-gates.yml \ - .github/scripts/check_copyright.py \ - .github/scripts/copyright-template.txt \ - .github/scripts/rector-compat.php \ - .github/scripts/phpmd-ruleset.xml \ - .github/scripts/phpstan.neon \ - .github/scripts/phpstan-framework-autoload.php \ - .github/scripts/phpstan-extensions.neon \ - .github/scripts/filter-blacklist.sh; do - if [ ! -f "$f" ]; then - echo "::error::Required CI file missing: $f" - missing=true - fi - done - if [ "$missing" = "true" ]; then - echo "::error::CI files must not be removed. Restore them before merging." - exit 1 - fi - echo "All required CI files present." - - - name: Detect changed file types + - name: Detect changed files and verify CI integrity id: check + env: + GH_TOKEN: ${{ github.token }} run: | set -euo pipefail - base_ref="${{ github.event.pull_request.base.ref }}" - base_sha="${{ github.event.pull_request.base.sha }}" - head_sha="${{ github.event.pull_request.head.sha }}" - pr_number="${{ github.event.pull_request.number }}" - - if ! git cat-file -e "${base_sha}^{commit}" 2>/dev/null; then - git fetch origin "$base_ref" || true - base_sha="origin/$base_ref" - fi - - if ! git cat-file -e "${head_sha}^{commit}" 2>/dev/null; then - git fetch origin "pull/${pr_number}/head:pr-${pr_number}-head" || true - if git rev-parse --verify -q "pr-${pr_number}-head" >/dev/null; then - head_sha="pr-${pr_number}-head" + pr="${{ github.event.pull_request.number }}" + repo="${{ github.repository }}" + echo "PR #${pr} ${{ github.event.pull_request.head.repo.full_name }} → ${{ github.event.pull_request.base.repo.full_name }}" + echo "PR_QA_ENABLED_JOBS: ${{ vars.PR_QA_ENABLED_JOBS }}" + + # Fetch all changed files as "filename TAB status" pairs (paginated) + files=$(gh api "repos/${repo}/pulls/${pr}/files" --paginate \ + --jq '.[] | [.filename, .status] | @tsv') + + # Verify required CI files are not removed in this PR + required=( + .github/workflows/pr-quality-gates.yml + .github/scripts/check_copyright.py + .github/scripts/copyright-template.txt + .github/scripts/rector-compat.php + .github/scripts/phpmd-ruleset.xml + .github/scripts/phpstan.neon + .github/scripts/phpstan-framework-autoload.php + .github/scripts/phpstan-extensions.neon + .github/scripts/filter-blacklist.sh + ) + missing=false + while IFS=$'\t' read -r filename status; do + [[ "$status" != "removed" ]] && continue + for req in "${required[@]}"; do + if [[ "$filename" == "$req" ]]; then + echo "::error::Required CI file removed: $filename" + missing=true + fi + done + done <<< "$files" + if $missing; then echo "::error::Restore removed CI files before merging."; exit 1; fi + + # Categorize files (exclude .github/, vendor/, lib/web/) + has_php=false; has_js=false; has_static=false + has_new_files=false; has_copyright_files=false + copyright_files="" + copyright_exts='\.(php|phtml|js|css|scss|less|xml|xsd|html|graphqls)$' + + while IFS=$'\t' read -r filename status; do + [[ -z "$filename" ]] && continue + [[ "$filename" =~ ^(\.github|vendor|lib/web)/ ]] && continue + [[ "$filename" =~ \.(php|phtml)$ ]] && has_php=true + [[ "$filename" =~ \.js$ && ! "$filename" =~ \.min\.js$ ]] && has_js=true + [[ "$filename" =~ \.(xml|xsd|html|graphqls|less)$ ]] && has_static=true + if [[ "$filename" =~ $copyright_exts && "$status" =~ ^(added|modified|renamed|copied)$ ]]; then + has_copyright_files=true + copyright_files+="${filename}"$'\n' + [[ "$status" == "added" ]] && has_new_files=true fi - fi - - changed=$(git diff --name-only --diff-filter=ACMR "$base_sha...$head_sha" \ - | grep -vE '^(\.github|vendor|lib/web)/' || true) - - has_php=false - has_js=false - has_static=false - has_new_files=false - - if echo "$changed" | grep -qE '\.(php|phtml)$'; then - has_php=true - fi - if echo "$changed" | grep -E '\.js$' | grep -qv '\.min\.js$'; then - has_js=true - fi - if echo "$changed" | grep -qE '\.(xml|xsd|html|graphqls|less)$'; then - has_static=true - fi - - added=$(git diff --name-only --diff-filter=A "$base_sha...$head_sha" \ - | grep -vE '^(\.github|vendor|lib/web)/' \ - | grep -qE '\.(php|phtml|js|css|scss|less|xml|xsd|html|graphqls)$' && echo true || echo false) - has_new_files=$added - - copyright_files=$(git diff --name-only --diff-filter=ACMRT "$base_sha...$head_sha" \ - | grep -vE '^(\.github|vendor|lib/web)/' \ - | grep -E '\.(php|phtml|js|css|scss|less|xml|xsd|html|graphqls)$' || true) - - echo "has_php=$has_php" >> "$GITHUB_OUTPUT" - echo "has_js=$has_js" >> "$GITHUB_OUTPUT" - echo "has_static=$has_static" >> "$GITHUB_OUTPUT" - echo "has_new_files=$has_new_files" >> "$GITHUB_OUTPUT" + done <<< "$files" + copyright_files="${copyright_files%$'\n'}" + + echo "has_php=$has_php" >> "$GITHUB_OUTPUT" + echo "has_js=$has_js" >> "$GITHUB_OUTPUT" + echo "has_static=$has_static" >> "$GITHUB_OUTPUT" + echo "has_new_files=$has_new_files" >> "$GITHUB_OUTPUT" + echo "has_copyright_files=$has_copyright_files" >> "$GITHUB_OUTPUT" { echo "copyright_files<<EOF" echo "$copyright_files" echo "EOF" } >> "$GITHUB_OUTPUT" + echo "PHP files changed: $has_php" echo "JS files changed: $has_js" echo "Static files changed: $has_static" + echo "Copyright-eligible files changed: $has_copyright_files" # ────────────────────────────────────────────────────────────────────── # Job 2: Mainline Alignment (Branch Freshness + PR Gate) @@ -173,188 +141,81 @@ jobs: env: CROSS_REPO_READ_TOKEN: ${{ secrets.CROSS_REPO_READ_TOKEN }} steps: - - uses: actions/checkout@v6 - with: - fetch-depth: 0 - filter: blob:none - sparse-checkout: | - .github - - name: Check branch alignment with upstream mainline - uses: actions/github-script@v9 env: - GIT_CONFIG_NOSYSTEM: '1' - GITHUB_TOKEN: ${{ github.token }} - with: - script: | - const { execFileSync } = require('child_process'); - const git = (...args) => execFileSync('git', args, { encoding: 'utf-8' }); - - const baseBranch = context.payload.pull_request.base.ref; - const headSha = context.payload.pull_request.head.sha; - const repoOwner = context.repo.owner; - const repoName = context.repo.repo; - - core.info(`Fork repo : ${repoOwner}/${repoName}`); - core.info(`Base branch : ${baseBranch}`); - core.info(`Head SHA : ${headSha}`); - - // ── Resolve the upstream (parent) repo ─────────────────── - // If this repo is a fork, compare against the parent's - // mainline. Otherwise fall back to origin. - let upstreamUrl = ''; - let upstreamLabel = ''; - - try { - const { data: repo } = await github.rest.repos.get({ - owner: repoOwner, - repo: repoName, - }); - - if (repo.fork && repo.parent) { - upstreamUrl = repo.parent.clone_url; - upstreamLabel = repo.parent.full_name; - core.info(`Upstream : ${upstreamLabel} (detected as parent fork)`); - } - } catch (e) { - core.warning(`Could not query repo metadata: ${e.message}. Falling back to origin.`); - } - - // If not a fork (or API call failed), compare against origin. - let canUseUpstream = !!upstreamUrl; - - const setGitAuth = (token) => { - // actions/checkout v6 injects credentials via includeIf.gitdir entries pointing - // to a temporary config file — not via http.extraheader — so unset-all on - // extraheader alone leaves a second Authorization header on the wire. - // Mirror what checkout's post-run cleanup does: remove those includeIf entries first. - try { - const keys = git('config', '--local', '--name-only', '--get-regexp', '^includeIf\\.gitdir:') - .trim().split('\n').filter(Boolean); - for (const key of keys) { - try { git('config', '--local', '--unset-all', key); } catch(e) {} - } - } catch(e) {} // no includeIf entries is normal outside of checkout-managed repos - // Clear http.extraheader from local and global (system excluded via GIT_CONFIG_NOSYSTEM=1). - // Also disable the credential helper so only our one token reaches the wire. - for (const scope of ['--local', '--global']) { - try { git('config', scope, '--unset-all', 'http.https://github.com/.extraheader'); } catch(e) {} - } - git('config', '--local', 'credential.https://github.com.helper', ''); - if (token) { - const encoded = Buffer.from(`x-access-token:${token}`).toString('base64'); - git('config', '--local', 'http.https://github.com/.extraheader', `AUTHORIZATION: basic ${encoded}`); - } - }; - - const crossRepoToken = process.env.CROSS_REPO_READ_TOKEN || ''; - if (canUseUpstream) { - // Authenticate upstream fetch with CROSS_REPO_READ_TOKEN if available. - if (crossRepoToken) { - setGitAuth(crossRepoToken); - core.info(`Upstream fetch: using CROSS_REPO_READ_TOKEN for authentication`); - } else { - core.info(`Upstream fetch: no CROSS_REPO_READ_TOKEN, attempting anonymous`); - } - - // Add the upstream remote and fetch the mainline branch. - // If the upstream is private and inaccessible, fall back to origin. - try { - git('remote', 'add', 'upstream', upstreamUrl); - } catch (e) { - // Remote may already exist from a previous step. - if (!/already exists/.test(e.stderr || '')) throw e; - } - try { - git('fetch', 'upstream', baseBranch); - } catch (e) { - core.warning( - `Cannot fetch from upstream ${upstreamLabel}. ` + - `Falling back to origin/${baseBranch}.` - ); - canUseUpstream = false; - } - } - - if (!canUseUpstream) { - // Only restore credentials if they were replaced for the upstream fetch. - // When no crossRepoToken was supplied, setGitAuth was never called and - // the checkout's includeIf credentials are still intact — calling - // setGitAuth here would strip them and leave git unauthenticated. - if (crossRepoToken) { - setGitAuth(process.env.GITHUB_TOKEN || ''); - } - upstreamLabel = `${repoOwner}/${repoName}`; - git('fetch', 'origin', baseBranch); - } - - const remoteName = canUseUpstream ? 'upstream' : 'origin'; - - const mainlineRef = `${remoteName}/${baseBranch}`; - const baseHeadSha = git('rev-parse', mainlineRef).trim(); - core.info(`Mainline HEAD (${upstreamLabel} ${baseBranch}): ${baseHeadSha}`); - - // ── 1. Merge-base check ────────────────────────────────── - // The merge-base between the PR head and mainline must equal - // mainline HEAD. If it does not, the branch is behind. - const mergeBase = git('merge-base', headSha, mainlineRef).trim(); - - core.info(`Merge base : ${mergeBase}`); - - if (mergeBase !== baseHeadSha) { - const behind = git('rev-list', '--count', `${mergeBase}..${mainlineRef}`).trim(); - - const fetchCmd = canUseUpstream - ? `git fetch upstream ${baseBranch} && git merge upstream/${baseBranch}` - : `git fetch origin ${baseBranch} && git merge origin/${baseBranch}`; - - core.setFailed( - `Branch is ${behind} commit(s) behind ${upstreamLabel} ${baseBranch}.\n\n` + - `Merge the latest mainline into the PR branch before CI builds ` + - `(PAT, MFTF, integration tests) will run.\n\n` + - `To fix:\n` + - ` ${fetchCmd}\n` + - ` git push\n` - ); - return; - } - - // ── 2. Conflict check ──────────────────────────────────── - // Attempt a tree-only merge to detect conflicts without - // actually creating a merge commit. - try { - execFileSync('git', ['merge-tree', mergeBase, mainlineRef, headSha], - { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }); - } catch (e) { - const output = (e.stdout || '') + (e.stderr || ''); - if (/conflict/i.test(output) || /CONFLICT/i.test(output)) { - core.setFailed( - `Merge conflicts detected between this branch and ${upstreamLabel} ${baseBranch}.\n` + - `Merge mainline and resolve conflicts before CI can proceed.` - ); - return; - } - } + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + base_branch="${{ github.event.pull_request.base.ref }}" + head_sha="${{ github.event.pull_request.head.sha }}" + repo="${{ github.repository }}" + owner="${repo%%/*}" + echo "Base branch : ${base_branch}" + echo "Head SHA : ${head_sha}" + + # Resolve upstream (parent) repo; fall back to origin if not a fork + upstream_owner="$owner" + upstream_repo="${repo##*/}" + upstream_label="$repo" + meta=$(gh api "repos/${repo}" \ + --jq '[.fork, (.parent.owner.login // ""), (.parent.name // ""), (.parent.full_name // "")] | @tsv' \ + 2>/dev/null || echo "false ") + IFS=$'\t' read -r is_fork p_owner p_repo p_label <<< "$meta" + if [[ "$is_fork" == "true" && -n "$p_owner" ]]; then + upstream_owner="$p_owner" + upstream_repo="$p_repo" + upstream_label="$p_label" + echo "Upstream : ${upstream_label} (parent fork)" + fi - // ── 3. Staleness warning ───────────────────────────────── - // If the branch diverged more than 7 days ago, warn (but - // do not fail) -- the developer may want to refresh. - const mergeBaseDate = git('log', '-1', '--format=%ci', mergeBase).trim(); + # Get upstream mainline HEAD SHA; fall back to origin on error + if ! mainline_sha=$(gh api "repos/${upstream_owner}/${upstream_repo}/branches/${base_branch}" \ + --jq '.commit.sha' 2>/dev/null); then + echo "::warning::Cannot reach ${upstream_label}/${base_branch}. Falling back to origin." + upstream_owner="$owner" + upstream_repo="${repo##*/}" + upstream_label="$repo" + mainline_sha=$(gh api "repos/${repo}/branches/${base_branch}" --jq '.commit.sha') + fi + echo "Mainline HEAD (${upstream_label} ${base_branch}): ${mainline_sha}" - const ageMs = Date.now() - new Date(mergeBaseDate).getTime(); - const ageDays = Math.floor(ageMs / (1000 * 60 * 60 * 24)); + # ── 1. Freshness check ────────────────────────────────────────── + cmp=$(gh api "repos/${repo}/compare/${mainline_sha}...${head_sha}" \ + --jq '[.behind_by, .ahead_by, .status, (.merge_base_commit.commit.committer.date // "")] | @tsv') + IFS=$'\t' read -r behind ahead cmp_status merge_base_date <<< "$cmp" + echo "Status: ${cmp_status}, behind_by: ${behind}, ahead_by: ${ahead}" - if (ageDays > 7) { - core.warning( - `Branch diverged from ${upstreamLabel} ${baseBranch} ${ageDays} days ago. ` + - `Consider rebasing to pick up recent mainline changes.` - ); - } + if [[ "$behind" -gt 0 ]]; then + if [[ "$upstream_owner" != "$owner" ]]; then + fetch_cmd="git fetch upstream ${base_branch} && git merge upstream/${base_branch}" + else + fetch_cmd="git fetch origin ${base_branch} && git merge origin/${base_branch}" + fi + echo "::error::Branch is ${behind} commit(s) behind ${upstream_label} ${base_branch}.%0A%0AMerge the latest mainline before CI builds (PAT, MFTF, integration tests) will run.%0A%0ATo fix:%0A ${fetch_cmd}%0A git push" + exit 1 + fi - core.info( - `Branch is up to date with ${upstreamLabel} ${baseBranch} ` + - `(diverged ${ageDays} day(s) ago). All good.` - ); + # ── 2. Conflict check ─────────────────────────────────────────── + mergeable=$(gh api "repos/${repo}/pulls/${{ github.event.pull_request.number }}" \ + --jq '.mergeable') + if [[ "$mergeable" == "false" ]]; then + echo "::error::Merge conflicts detected between this branch and ${upstream_label} ${base_branch}. Merge mainline and resolve conflicts before CI can proceed." + exit 1 + fi + [[ "$mergeable" == "null" ]] && echo "::warning::GitHub has not yet computed mergeability. Conflict check skipped." + + # ── 3. Staleness warning ──────────────────────────────────────── + if [[ -n "$merge_base_date" && "$merge_base_date" != "null" ]]; then + now=$(date +%s) + base_epoch=$(date -d "$merge_base_date" +%s 2>/dev/null || echo "") + if [[ -n "$base_epoch" ]]; then + age_days=$(( (now - base_epoch) / 86400 )) + [[ "$age_days" -gt 7 ]] && echo "::warning::Branch diverged from ${upstream_label} ${base_branch} ${age_days} days ago. Consider rebasing." + echo "Branch is up to date with ${upstream_label} ${base_branch} (diverged ${age_days} day(s) ago). All good." + fi + else + echo "Branch is up to date with ${upstream_label} ${base_branch}. All good." + fi # ────────────────────────────────────────────────────────────────────── # Job 4: Copyright Header Check @@ -368,13 +229,11 @@ jobs: - detect-changes if: >- always() && - contains(format(',{0},', vars.PR_QA_ENABLED_JOBS), ',copyright-check,') && ( - github.event_name == 'workflow_dispatch' || - (github.event_name == 'pull_request' && - needs.mainline-alignment.result == 'success' && - needs.detect-changes.result == 'success' && - needs.detect-changes.outputs.has_new_files == 'true') - ) + contains(format(',{0},', vars.PR_QA_ENABLED_JOBS), ',copyright-check,') && + github.event_name == 'pull_request' && + needs.mainline-alignment.result == 'success' && + needs.detect-changes.result == 'success' && + needs.detect-changes.outputs.has_copyright_files == 'true' runs-on: ubuntu-latest timeout-minutes: 5 permissions: @@ -417,35 +276,16 @@ jobs: exit 0 fi - exit_code=0 - while IFS= read -r file; do - if [ -n "$file" ] && [ -f "$file" ]; then - if ! python3 .github/scripts/check_copyright.py \ - --template "${GITHUB_WORKSPACE}/.github/scripts/copyright-template.txt" \ - --path "$file" \ - --pr-mode \ - --base-sha "${{ github.event.pull_request.base.sha }}"; then - exit_code=1 - fi - fi - done <<< "$pr_code_files" - - if [ $exit_code -ne 0 ]; then + printf '%s\n' "$pr_code_files" | grep -v '^$' > /tmp/copyright_files.txt + if ! python3 .github/scripts/check_copyright.py \ + --template "${GITHUB_WORKSPACE}/.github/scripts/copyright-template.txt" \ + --file-list /tmp/copyright_files.txt \ + --pr-mode \ + --base-sha "${{ github.event.pull_request.base.sha }}"; then echo "::error::Some PR files have copyright issues" exit 1 fi - echo "All relevant PR files have correct copyright headers" - - name: Check copyright headers (Manual) - if: github.event_name == 'workflow_dispatch' - run: | - set -euo pipefail - echo "Running copyright check in manual mode..." - python3 .github/scripts/check_copyright.py \ - --template "${GITHUB_WORKSPACE}/.github/scripts/copyright-template.txt" \ - --magento-only \ - --stats \ - --verbose # ────────────────────────────────────────────────────────────────────── # Job 5: Magento Coding Standard (PHPCS + Rector + ESLint) @@ -714,6 +554,25 @@ jobs: if [ ! -f "$ruleset" ]; then echo "Magento ruleset not available, falling back to local standalone ruleset." ruleset="${GITHUB_WORKSPACE}/.github/scripts/phpmd-ruleset.xml" + else + else + # Wrap the primary ruleset to exclude rules that require the full + # vendor tree (Laminas etc.) and crash in the sparse-clone environment. + wrapper="/tmp/phpmd-ruleset-ci.xml" + cat > "$wrapper" <<XML + <?xml version="1.0" encoding="UTF-8"?> + <ruleset name="Magento PHPMD (CI)" xmlns="http://pmd.sf.net/ruleset/1.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"> + <description>Magento PHPMD rules, excluding rules that require the full vendor tree.</description> + <rule ref="${ruleset}"> + <exclude name="CookieAndSessionMisuse"/> + <exclude name="AllPurposeAction"/> + </rule> + </ruleset> + XML + ruleset="$wrapper" + fi fi cat > "$prepend_file" <<'PHP' <?php @@ -990,8 +849,8 @@ jobs: github.event_name == 'pull_request' && contains(fromJSON('["success","failure"]'), needs.detect-changes.result) && contains(fromJSON('["success","failure"]'), needs.mainline-alignment.result) && - contains(fromJSON('["success","failure"]'), needs.copyright-check.result) && - contains(fromJSON('["success","failure"]'), needs.coding-standard.result) && + contains(fromJSON('["success","failure","skipped"]'), needs.copyright-check.result) && + contains(fromJSON('["success","failure","skipped"]'), needs.coding-standard.result) && vars.PR_QA_ENABLED_JOBS != '' runs-on: ubuntu-latest timeout-minutes: 5 From 6ac2d0a929407b027d961a05d56727d625d181c9 Mon Sep 17 00:00:00 2001 From: Alexandra Zota <zota@adobe.com> Date: Wed, 13 May 2026 17:01:58 +0300 Subject: [PATCH 37/83] ACP2E-4933: PR Quality Gates bugfixes and improvements --- .github/workflows/pr-quality-gates.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pr-quality-gates.yml b/.github/workflows/pr-quality-gates.yml index d329e7b6d4bd..89bbe0af598e 100644 --- a/.github/workflows/pr-quality-gates.yml +++ b/.github/workflows/pr-quality-gates.yml @@ -138,6 +138,7 @@ jobs: timeout-minutes: 10 permissions: contents: read + pull-requests: read env: CROSS_REPO_READ_TOKEN: ${{ secrets.CROSS_REPO_READ_TOKEN }} steps: From 012226b81c85c57979fdf57dde4f764045a6d299 Mon Sep 17 00:00:00 2001 From: Alexandra Zota <zota@adobe.com> Date: Wed, 13 May 2026 17:05:33 +0300 Subject: [PATCH 38/83] ACP2E-4933: PR Quality Gates bugfixes and improvements --- .github/workflows/pr-quality-gates.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pr-quality-gates.yml b/.github/workflows/pr-quality-gates.yml index 89bbe0af598e..f8a5e72cac4c 100644 --- a/.github/workflows/pr-quality-gates.yml +++ b/.github/workflows/pr-quality-gates.yml @@ -38,6 +38,7 @@ jobs: timeout-minutes: 5 permissions: contents: read + pull-requests: read outputs: has_php: ${{ steps.check.outputs.has_php }} has_js: ${{ steps.check.outputs.has_js }} From 2c8b39d240cef644d01af8060a3af7e16731c641 Mon Sep 17 00:00:00 2001 From: Karishma Thakare <del57145@adobe.com> Date: Thu, 14 May 2026 00:06:28 +0530 Subject: [PATCH 39/83] ACQE-9850: Filter - Sales Order Grid - Added filter clearance code --- ...CustomerCabinetOnHomepageIsNotPresentIfProductSoldOutTest.xml | 1 + ...ValidationConfigurableProductSoldOutInSingleStockModeTest.xml | 1 + ...tCacheValidationSimpleProductSoldOutInSingleStockModeTest.xml | 1 + ...rontCacheValidationSimpleProductSoldOutOnDefaultStockTest.xml | 1 + ...rderConfigurableProductTextSwatchAttributeCustomStockTest.xml | 1 + ...nfigurableProductWithDropDownAttributeAndCustomSourceTest.xml | 1 + ...figurableProductWithDropDownAttributeAndDefaultSourceTest.xml | 1 + ...tLoggedInCustomerOrderDownloadableProductDefaultStockTest.xml | 1 + ...rontLoggedInCustomerReorderBundleProductOnCustomStockTest.xml | 1 + .../StorefrontQuickOrderConfigurableProductsCustomStockTest.xml | 1 + .../Test/StorefrontQuickOrderSimpleProductCustomStockTest.xml | 1 + .../Test/StorefrontQuickOrderSimpleProductsCustomStockTest.xml | 1 + ...roductWithDropDownAttributeOnDefaultStockFromHomepageTest.xml | 1 + ...leProductWithDropDownAttributeOnTestStockFromHomepageTest.xml | 1 + ...irtualProductAfterCancellationOfOrderCountedCorrectlyTest.xml | 1 + ...torefrontGuestCreateOrderWithBundleProductCustomStockTest.xml | 1 + ...ontGuestCreateOrderWithConfigurableProductCustomStockTest.xml | 1 + ...orefrontGuestCreateOrderWithGroupedProductCustomStockTest.xml | 1 + ...tCreateOrderWithSimpleProductCustomStockCustomWebsiteTest.xml | 1 + ...torefrontGuestCreateOrderWithSimpleProductCustomStockTest.xml | 1 + ...refrontGuestCreateOrderWithSimpleProductNumericSourceTest.xml | 1 + ...rCreateOrderWithSimpleProductCustomStockCustomWebsiteTest.xml | 1 + ...ggedInCustomerCreateOrderWithSimpleProductCustomStockTest.xml | 1 + 23 files changed, 23 insertions(+) diff --git a/InventoryAdminUi/Test/Mftf/Test/StorefrontButtonReorderForTheOrderWithConfigurableProductOnTestStockInCustomerCabinetOnHomepageIsNotPresentIfProductSoldOutTest.xml b/InventoryAdminUi/Test/Mftf/Test/StorefrontButtonReorderForTheOrderWithConfigurableProductOnTestStockInCustomerCabinetOnHomepageIsNotPresentIfProductSoldOutTest.xml index f8bd07218094..8a6ac45387f3 100644 --- a/InventoryAdminUi/Test/Mftf/Test/StorefrontButtonReorderForTheOrderWithConfigurableProductOnTestStockInCustomerCabinetOnHomepageIsNotPresentIfProductSoldOutTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StorefrontButtonReorderForTheOrderWithConfigurableProductOnTestStockInCustomerCabinetOnHomepageIsNotPresentIfProductSoldOutTest.xml @@ -28,6 +28,7 @@ <remove keyForRemoval="assignMainWebsiteToDefaultStock"/> </before> <after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter"/> <!--Assign Default Stock to Default Website.--> <actionGroup ref="AssignWebsiteToStockActionGroup" stepKey="assignMainWebsiteToDefaultStock" before="logoutOfAdmin1"> <argument name="stockName" value="{{_defaultStock.name}}"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/StorefrontCacheValidationConfigurableProductSoldOutInSingleStockModeTest.xml b/InventoryAdminUi/Test/Mftf/Test/StorefrontCacheValidationConfigurableProductSoldOutInSingleStockModeTest.xml index c519e96dffa8..a2c08d06c7f1 100644 --- a/InventoryAdminUi/Test/Mftf/Test/StorefrontCacheValidationConfigurableProductSoldOutInSingleStockModeTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StorefrontCacheValidationConfigurableProductSoldOutInSingleStockModeTest.xml @@ -52,6 +52,7 @@ <createData entity="Simple_US_Customer" stepKey="customer"/> </before> <after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter" before="logoutFromAdminArea"/> <deleteData createDataKey="configurableProduct" stepKey="deleteConfigurableProduct"/> <deleteData createDataKey="configurableChildProduct" stepKey="deleteConfigurableProductVariation"/> <deleteData createDataKey="configurableProductAttribute" stepKey="deleteConfigurableProductAttribute"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/StorefrontCacheValidationSimpleProductSoldOutInSingleStockModeTest.xml b/InventoryAdminUi/Test/Mftf/Test/StorefrontCacheValidationSimpleProductSoldOutInSingleStockModeTest.xml index 53246f499f7b..ad021fe96a26 100644 --- a/InventoryAdminUi/Test/Mftf/Test/StorefrontCacheValidationSimpleProductSoldOutInSingleStockModeTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StorefrontCacheValidationSimpleProductSoldOutInSingleStockModeTest.xml @@ -30,6 +30,7 @@ </createData> </before> <after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter" before="logoutOfAdmin"/> <!--Clean up created data.--> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/StorefrontCacheValidationSimpleProductSoldOutOnDefaultStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/StorefrontCacheValidationSimpleProductSoldOutOnDefaultStockTest.xml index e2079cf36296..28f1ee95b4b5 100644 --- a/InventoryAdminUi/Test/Mftf/Test/StorefrontCacheValidationSimpleProductSoldOutOnDefaultStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StorefrontCacheValidationSimpleProductSoldOutOnDefaultStockTest.xml @@ -30,6 +30,7 @@ <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> </before> <after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter" before="logoutOfAdmin"/> <!--Disable additional source.--> <actionGroup ref="DisableSourceActionGroup" stepKey="disableThirdCreatedSource"> <argument name="sourceCode" value="$$additionalSource.source[source_code]$$"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerOrderConfigurableProductTextSwatchAttributeCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerOrderConfigurableProductTextSwatchAttributeCustomStockTest.xml index 9e31775af648..24e489c991e0 100644 --- a/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerOrderConfigurableProductTextSwatchAttributeCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerOrderConfigurableProductTextSwatchAttributeCustomStockTest.xml @@ -67,6 +67,7 @@ </actionGroup> </before> <after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter" before="logoutOfAdmin"/> <!-- Delete configurable product and variants via API using ProductApiHelper --> <helper class="Magento\Catalog\Test\Mftf\Helper\ProductApiHelper" method="deleteAllProductsApi" stepKey="deleteAllProductsViaApi"/> <!--Assign Default Stock to Main Website.--> diff --git a/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerOrderConfigurableProductWithDropDownAttributeAndCustomSourceTest.xml b/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerOrderConfigurableProductWithDropDownAttributeAndCustomSourceTest.xml index f70ad56dc743..257f24fd62a6 100644 --- a/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerOrderConfigurableProductWithDropDownAttributeAndCustomSourceTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerOrderConfigurableProductWithDropDownAttributeAndCustomSourceTest.xml @@ -66,6 +66,7 @@ <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/> </before> <after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter" before="logoutFromAdminArea"/> <deleteData createDataKey="configurableProduct" stepKey="deleteConfigurableProduct"/> <deleteData createDataKey="configurableChildProduct" stepKey="deleteConfigurableProductVariation"/> <deleteData createDataKey="configurableProductAttribute" stepKey="deleteConfigurableProductAttribute"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerOrderConfigurableProductWithDropDownAttributeAndDefaultSourceTest.xml b/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerOrderConfigurableProductWithDropDownAttributeAndDefaultSourceTest.xml index 5a4acb4e16ca..62a0fa12a842 100644 --- a/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerOrderConfigurableProductWithDropDownAttributeAndDefaultSourceTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerOrderConfigurableProductWithDropDownAttributeAndDefaultSourceTest.xml @@ -61,6 +61,7 @@ <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/> </before> <after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter" before="logoutFromAdminArea"/> <deleteData createDataKey="configurableProduct" stepKey="deleteConfigurableProduct"/> <deleteData createDataKey="configurableChildProduct" stepKey="deleteConfigurableProductVariation"/> <deleteData createDataKey="configurableProductAttribute" stepKey="deleteConfigurableProductAttribute"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerOrderDownloadableProductDefaultStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerOrderDownloadableProductDefaultStockTest.xml index 34722d35ee5f..be307f63cbc1 100644 --- a/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerOrderDownloadableProductDefaultStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerOrderDownloadableProductDefaultStockTest.xml @@ -43,6 +43,7 @@ </actionGroup> </before> <after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter" before="logoutOfAdmin"/> <!--Delete test data.--> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerReorderBundleProductOnCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerReorderBundleProductOnCustomStockTest.xml index 6d9a49df8504..2eee6c166d7e 100644 --- a/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerReorderBundleProductOnCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerReorderBundleProductOnCustomStockTest.xml @@ -71,6 +71,7 @@ </createData> </before> <after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter" before="logoutOfAdmin"/> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> <deleteData createDataKey="category" stepKey="deleteCategory"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/StorefrontQuickOrderConfigurableProductsCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/StorefrontQuickOrderConfigurableProductsCustomStockTest.xml index 8ca8173fd19e..1bd101085f91 100644 --- a/InventoryAdminUi/Test/Mftf/Test/StorefrontQuickOrderConfigurableProductsCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StorefrontQuickOrderConfigurableProductsCustomStockTest.xml @@ -101,6 +101,7 @@ <actionGroup ref="SaveProductFormActionGroup" stepKey="saveConfigurableVariation2"/> </before> <after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter" before="logout"/> <remove keyForRemoval="deleteProduct"/> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/StorefrontQuickOrderSimpleProductCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/StorefrontQuickOrderSimpleProductCustomStockTest.xml index 1d637ecec798..d9c84e5c5f91 100644 --- a/InventoryAdminUi/Test/Mftf/Test/StorefrontQuickOrderSimpleProductCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StorefrontQuickOrderSimpleProductCustomStockTest.xml @@ -41,6 +41,7 @@ <actionGroup ref="AdminFormSaveAndCloseActionGroup" stepKey="saveAndCloseSimpleProduct"/> </before> <after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter" before="logout"/> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> <!--Assign Default Stock to Default Website.--> diff --git a/InventoryAdminUi/Test/Mftf/Test/StorefrontQuickOrderSimpleProductsCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/StorefrontQuickOrderSimpleProductsCustomStockTest.xml index acdd0eb90089..4a4f2d47672a 100644 --- a/InventoryAdminUi/Test/Mftf/Test/StorefrontQuickOrderSimpleProductsCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StorefrontQuickOrderSimpleProductsCustomStockTest.xml @@ -56,6 +56,7 @@ <actionGroup ref="AdminFormSaveAndCloseActionGroup" stepKey="saveAndCloseSimpleProduct2"/> </before> <after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter" before="logout"/> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> <deleteData createDataKey="product" stepKey="deleteSimpleProduct2"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/StorefrontReorderOfTheOrderWithConfigurableProductWithDropDownAttributeOnDefaultStockFromHomepageTest.xml b/InventoryAdminUi/Test/Mftf/Test/StorefrontReorderOfTheOrderWithConfigurableProductWithDropDownAttributeOnDefaultStockFromHomepageTest.xml index e7ad2742f154..6c62f3b124a8 100644 --- a/InventoryAdminUi/Test/Mftf/Test/StorefrontReorderOfTheOrderWithConfigurableProductWithDropDownAttributeOnDefaultStockFromHomepageTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StorefrontReorderOfTheOrderWithConfigurableProductWithDropDownAttributeOnDefaultStockFromHomepageTest.xml @@ -61,6 +61,7 @@ </actionGroup> </before> <after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter" before="logoutFromAdminArea"/> <deleteData createDataKey="configurableProduct" stepKey="deleteConfigurableProduct"/> <deleteData createDataKey="product" stepKey="deleteConfigurableProductVariation"/> <deleteData createDataKey="configurableProductAttribute" stepKey="deleteConfigurableProductAttribute"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/StorefrontReorderOfTheOrderWithConfigurableProductWithDropDownAttributeOnTestStockFromHomepageTest.xml b/InventoryAdminUi/Test/Mftf/Test/StorefrontReorderOfTheOrderWithConfigurableProductWithDropDownAttributeOnTestStockFromHomepageTest.xml index ee8f30903c92..545856f99098 100644 --- a/InventoryAdminUi/Test/Mftf/Test/StorefrontReorderOfTheOrderWithConfigurableProductWithDropDownAttributeOnTestStockFromHomepageTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StorefrontReorderOfTheOrderWithConfigurableProductWithDropDownAttributeOnTestStockFromHomepageTest.xml @@ -66,6 +66,7 @@ <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/> </before> <after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter" before="logoutFromAdminArea"/> <deleteData createDataKey="configurableProduct" stepKey="deleteConfigurableProduct"/> <deleteData createDataKey="product" stepKey="deleteConfigurableProductVariation"/> <deleteData createDataKey="configurableProductAttribute" stepKey="deleteConfigurableProductAttribute"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/StorefrontSalableQuantityOnNonDefaultStockForVirtualProductAfterCancellationOfOrderCountedCorrectlyTest.xml b/InventoryAdminUi/Test/Mftf/Test/StorefrontSalableQuantityOnNonDefaultStockForVirtualProductAfterCancellationOfOrderCountedCorrectlyTest.xml index 9648a9a272a5..8ea517fd3c9b 100644 --- a/InventoryAdminUi/Test/Mftf/Test/StorefrontSalableQuantityOnNonDefaultStockForVirtualProductAfterCancellationOfOrderCountedCorrectlyTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StorefrontSalableQuantityOnNonDefaultStockForVirtualProductAfterCancellationOfOrderCountedCorrectlyTest.xml @@ -40,6 +40,7 @@ <actionGroup ref="AdminLoginActionGroup" stepKey="loginToAdminArea"/> </before> <after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter" before="logoutFromAdminArea"/> <!--Assign Default Stock to Main Website.--> <actionGroup ref="AssignWebsiteToStockActionGroup" stepKey="assignMainWebsiteToDefaultStock"> <argument name="stockName" value="{{_defaultStock.name}}"/> diff --git a/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontGuestCreateOrderWithBundleProductCustomStockTest.xml b/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontGuestCreateOrderWithBundleProductCustomStockTest.xml index 21f02afbcc8c..3b48d0335de7 100644 --- a/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontGuestCreateOrderWithBundleProductCustomStockTest.xml +++ b/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontGuestCreateOrderWithBundleProductCustomStockTest.xml @@ -77,6 +77,7 @@ </actionGroup> </before> <after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter" before="logoutOfAdmin"/> <!--Revert Distance Provider for Distance Based SSA to online.--> <magentoCLI command="config:set {{OnlineDistanceProviderForDistanceBasedSSA.path}} {{OnlineDistanceProviderForDistanceBasedSSA.value}}" stepKey="setDistanceProviderToOffline"/> <!--Disable 'In Store Pickup' shipping method.--> diff --git a/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontGuestCreateOrderWithConfigurableProductCustomStockTest.xml b/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontGuestCreateOrderWithConfigurableProductCustomStockTest.xml index 8c87018012b4..34ce4a76b589 100644 --- a/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontGuestCreateOrderWithConfigurableProductCustomStockTest.xml +++ b/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontGuestCreateOrderWithConfigurableProductCustomStockTest.xml @@ -78,6 +78,7 @@ <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/> </before> <after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter" before="logoutOfAdmin"/> <!--Revert Distance Provider for Distance Based SSA to online.--> <magentoCLI command="config:set {{OnlineDistanceProviderForDistanceBasedSSA.path}} {{OnlineDistanceProviderForDistanceBasedSSA.value}}" stepKey="setDistanceProviderToOffline"/> <!--Disable 'In Store Pickup' shipping method.--> diff --git a/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontGuestCreateOrderWithGroupedProductCustomStockTest.xml b/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontGuestCreateOrderWithGroupedProductCustomStockTest.xml index 561527af12c7..dd6083692856 100644 --- a/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontGuestCreateOrderWithGroupedProductCustomStockTest.xml +++ b/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontGuestCreateOrderWithGroupedProductCustomStockTest.xml @@ -65,6 +65,7 @@ </before> <after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter" before="logoutOfAdmin"/> <!--Revert Distance Provider for Distance Based SSA to online.--> <magentoCLI command="config:set {{OnlineDistanceProviderForDistanceBasedSSA.path}} {{OnlineDistanceProviderForDistanceBasedSSA.value}}" stepKey="setDistanceProviderToOffline"/> <!--Disable 'In Store Pickup' shipping method.--> diff --git a/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontGuestCreateOrderWithSimpleProductCustomStockCustomWebsiteTest.xml b/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontGuestCreateOrderWithSimpleProductCustomStockCustomWebsiteTest.xml index d094d2d028d5..464f4b8e1898 100644 --- a/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontGuestCreateOrderWithSimpleProductCustomStockCustomWebsiteTest.xml +++ b/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontGuestCreateOrderWithSimpleProductCustomStockCustomWebsiteTest.xml @@ -92,6 +92,7 @@ <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/> </before> <after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter" before="logoutOfAdmin"/> <!--Disable 'add store code to url'--> <magentoCLI command="config:set {{StorefrontDisableAddStoreCodeToUrls.path}} {{StorefrontDisableAddStoreCodeToUrls.value}}" stepKey="addStoreCodeToUrlDisable"/> <!--Revert Distance Provider for Distance Based SSA to online.--> diff --git a/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontGuestCreateOrderWithSimpleProductCustomStockTest.xml b/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontGuestCreateOrderWithSimpleProductCustomStockTest.xml index a4ea4aabe383..967a0c165a6c 100644 --- a/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontGuestCreateOrderWithSimpleProductCustomStockTest.xml +++ b/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontGuestCreateOrderWithSimpleProductCustomStockTest.xml @@ -64,6 +64,7 @@ <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/> </before> <after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter" before="logoutOfAdmin"/> <!--Revert Distance Provider for Distance Based SSA to online.--> <magentoCLI command="config:set {{OnlineDistanceProviderForDistanceBasedSSA.path}} {{OnlineDistanceProviderForDistanceBasedSSA.value}}" stepKey="setDistanceProviderToOffline"/> <!--Disable 'In Store Pickup' shipping method.--> diff --git a/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontGuestCreateOrderWithSimpleProductNumericSourceTest.xml b/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontGuestCreateOrderWithSimpleProductNumericSourceTest.xml index 7876826c4bd7..0dd152aca3b0 100644 --- a/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontGuestCreateOrderWithSimpleProductNumericSourceTest.xml +++ b/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontGuestCreateOrderWithSimpleProductNumericSourceTest.xml @@ -56,6 +56,7 @@ <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/> </before> <after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter" before="logoutOfAdmin"/> <!--Revert Distance Provider for Distance Based SSA to online.--> <magentoCLI command="config:set {{OnlineDistanceProviderForDistanceBasedSSA.path}} {{OnlineDistanceProviderForDistanceBasedSSA.value}}" stepKey="setDistanceProviderToOffline"/> <!--Disable 'In Store Pickup' shipping method.--> diff --git a/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontLoggedInCustomerCreateOrderWithSimpleProductCustomStockCustomWebsiteTest.xml b/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontLoggedInCustomerCreateOrderWithSimpleProductCustomStockCustomWebsiteTest.xml index 056d0034be53..40bf01973cae 100644 --- a/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontLoggedInCustomerCreateOrderWithSimpleProductCustomStockCustomWebsiteTest.xml +++ b/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontLoggedInCustomerCreateOrderWithSimpleProductCustomStockCustomWebsiteTest.xml @@ -89,6 +89,7 @@ <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/> </before> <after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter" before="logoutOfAdmin"/> <!--Disable 'add store code to url'--> <magentoCLI command="config:set {{StorefrontDisableAddStoreCodeToUrls.path}} {{StorefrontDisableAddStoreCodeToUrls.value}}" stepKey="addStoreCodeToUrlDisable"/> <!--Revert Distance Provider for Distance Based SSA to online.--> diff --git a/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontLoggedInCustomerCreateOrderWithSimpleProductCustomStockTest.xml b/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontLoggedInCustomerCreateOrderWithSimpleProductCustomStockTest.xml index 246256aa0a12..d9b25595c386 100644 --- a/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontLoggedInCustomerCreateOrderWithSimpleProductCustomStockTest.xml +++ b/InventoryInStorePickupFrontend/Test/Mftf/Test/StorefrontLoggedInCustomerCreateOrderWithSimpleProductCustomStockTest.xml @@ -64,6 +64,7 @@ <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/> </before> <after> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrdersGridFiltersAfter" before="logoutOfAdmin"/> <!--Revert Distance Provider for Distance Based SSA to online.--> <magentoCLI command="config:set {{OnlineDistanceProviderForDistanceBasedSSA.path}} {{OnlineDistanceProviderForDistanceBasedSSA.value}}" stepKey="setDistanceProviderToOffline"/> <!--Disable 'In Store Pickup' shipping method.--> From 10c710a6a5990dc1fb39ceda184629ca015d8922 Mon Sep 17 00:00:00 2001 From: "sandesh.as" <cod48668@adobe.com> Date: Fri, 15 May 2026 14:08:15 +0530 Subject: [PATCH 40/83] AC-16487::Fake Modules Require dev/ Directory in Extension Repositories --- .../Test/Api/GraphQl/BundleProductOnlyXLeftInStockTest.php | 2 ++ .../Test/Api/GraphQl/BundleProductStockStatusTest.php | 2 ++ .../Test/Api/GraphQl/PickupLocationForShippingTest.php | 2 ++ 3 files changed, 6 insertions(+) diff --git a/InventoryGraphQl/Test/Api/GraphQl/BundleProductOnlyXLeftInStockTest.php b/InventoryGraphQl/Test/Api/GraphQl/BundleProductOnlyXLeftInStockTest.php index 4417cad39fcc..27f5d92b4795 100644 --- a/InventoryGraphQl/Test/Api/GraphQl/BundleProductOnlyXLeftInStockTest.php +++ b/InventoryGraphQl/Test/Api/GraphQl/BundleProductOnlyXLeftInStockTest.php @@ -26,6 +26,8 @@ /** * Test for bundle product only x left in stock + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class BundleProductOnlyXLeftInStockTest extends GraphQlAbstract { diff --git a/InventoryGraphQl/Test/Api/GraphQl/BundleProductStockStatusTest.php b/InventoryGraphQl/Test/Api/GraphQl/BundleProductStockStatusTest.php index ce78384a191a..1708ad70c660 100644 --- a/InventoryGraphQl/Test/Api/GraphQl/BundleProductStockStatusTest.php +++ b/InventoryGraphQl/Test/Api/GraphQl/BundleProductStockStatusTest.php @@ -33,6 +33,8 @@ /** * Test for bundle product stock_status + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class BundleProductStockStatusTest extends GraphQlAbstract { diff --git a/InventoryInStorePickupQuoteGraphQl/Test/Api/GraphQl/PickupLocationForShippingTest.php b/InventoryInStorePickupQuoteGraphQl/Test/Api/GraphQl/PickupLocationForShippingTest.php index 1212b2ea92d8..456562c46277 100644 --- a/InventoryInStorePickupQuoteGraphQl/Test/Api/GraphQl/PickupLocationForShippingTest.php +++ b/InventoryInStorePickupQuoteGraphQl/Test/Api/GraphQl/PickupLocationForShippingTest.php @@ -35,6 +35,8 @@ /** * Test coverage of extension of Quote Graph Ql. * Test possibility to pass Pickup Location Code to Shipping Address. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class PickupLocationForShippingTest extends GraphQlAbstract { From a4fe7ec63dc6199b628730a88ef8729452599c54 Mon Sep 17 00:00:00 2001 From: Shweta Tripathi <shwetatripat@adobe.com> Date: Mon, 18 May 2026 13:48:33 +0530 Subject: [PATCH 41/83] ACQE-9696: [ATLH] Filters - Round 3 - Inventory Source Grid - Added cleanup code for Inventory Source Grid --- ...extSwatchAttributeAndDefaultSourceTest.xml | 1 + ...oldForVirtualProductWithTestSourceTest.xml | 1 + ...geStockForVirtualProductIsDisabledTest.xml | 1 + ...nUseDecimalQuantityOnSimpleProductTest.xml | 1 + ...UseDecimalQuantityOnVirtualProductTest.xml | 1 + ...etFilterInManageSourcesGridActionGroup.xml | 28 +++++++++++++++++++ ...WithDropDownAttributeWithNewSourceTest.xml | 1 + .../AdminAddStockToVirtualProductTest.xml | 1 + .../AdminAssignMultipleSourcesToStockTest.xml | 1 + ...minCanDeleteSourcesAssignedToStockTest.xml | 1 + ...OrderWithGroupedProductCustomStockTest.xml | 1 + ...hForConfigurableProductOnTestStockTest.xml | 1 + ...SearchForVirtualProductOnTestStockTest.xml | 1 + ...ctDisabledManageStockOnCustomStockTest.xml | 1 + ...anageStockOnProductPageCustomStockTest.xml | 1 + ...OrderWithGroupedProductCustomStockTest.xml | 1 + .../AdminEachSourceQuantityCanBeSetTest.xml | 1 + ...dminManageSourceGridColumnsSortingTest.xml | 2 +- ...ctWithDropDownAttributeViaTheAdminTest.xml | 1 + ...ductWithSwatchAttributeViaTheAdminTest.xml | 1 + ...roductWithTextAttributeViaTheAdminTest.xml | 1 + ...ductWithSwatchAttributeViaTheAdminTest.xml | 2 +- ...roductWithTextAttributeViaTheAdminTest.xml | 2 +- ...aginationWorkedInManageSourcesGridTest.xml | 1 + ...orityOfSourcesChangedByDragAndDropTest.xml | 1 + ...dminRemoveSourcesAssignedToProductTest.xml | 1 + ...eDuringCreatingConfigurableProductTest.xml | 2 +- ...urceForEachQuantityCanBeSetByAdminTest.xml | 1 + .../Mftf/Test/AdminUpdateSourceDataTest.xml | 1 + ...tsGridToUnAssignAllAssignedSourcesTest.xml | 1 + ...dminUserSetStatusForEachSourceItemTest.xml | 1 + ...FromHomepageWithFreeShippingMethodTest.xml | 1 + ...rderedVirtualProductOnDefaultStockTest.xml | 1 + ...urableProductWithDropDownAttributeTest.xml | 1 + ...igurableProductWithSwatchAttributeTest.xml | 1 + ...dWithVirtualProductByGuestCustomerTest.xml | 1 + ...NonDefaultSourceCreatedByAdminUserTest.xml | 1 + ...fStockWhenChildProductIsOutOfStockTest.xml | 1 + 38 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 InventoryAdminUi/Test/Mftf/ActionGroup/AdminResetFilterInManageSourcesGridActionGroup.xml diff --git a/Inventory/Test/Mftf/Test/AdminAddConfigurableProductWithTextSwatchAttributeAndDefaultSourceTest.xml b/Inventory/Test/Mftf/Test/AdminAddConfigurableProductWithTextSwatchAttributeAndDefaultSourceTest.xml index b23f6618c4ac..898a56e628bb 100644 --- a/Inventory/Test/Mftf/Test/AdminAddConfigurableProductWithTextSwatchAttributeAndDefaultSourceTest.xml +++ b/Inventory/Test/Mftf/Test/AdminAddConfigurableProductWithTextSwatchAttributeAndDefaultSourceTest.xml @@ -40,6 +40,7 @@ <argument name="stockName" value="{{_defaultStock.name}}"/> <argument name="websiteName" value="{{_defaultWebsite.name}}"/> </actionGroup> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> <deleteData createDataKey="createPreReqCategory1" stepKey="deletePreReqCategory1"/> </after> diff --git a/Inventory/Test/Mftf/Test/AdminCanSetOnlyXLeftThresholdForVirtualProductWithTestSourceTest.xml b/Inventory/Test/Mftf/Test/AdminCanSetOnlyXLeftThresholdForVirtualProductWithTestSourceTest.xml index 995ee9d4479e..ade71ade3a1e 100644 --- a/Inventory/Test/Mftf/Test/AdminCanSetOnlyXLeftThresholdForVirtualProductWithTestSourceTest.xml +++ b/Inventory/Test/Mftf/Test/AdminCanSetOnlyXLeftThresholdForVirtualProductWithTestSourceTest.xml @@ -42,6 +42,7 @@ </actionGroup> <deleteData createDataKey="createCategory1" stepKey="deletecreateCategory1"/> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> </after> <actionGroup ref="AdminGoToProductGridFilterResultsByInputEditProduct" stepKey="goToProductGridFilterResultsByInputEditProduct1"> diff --git a/Inventory/Test/Mftf/Test/AdminManageStockForVirtualProductIsDisabledTest.xml b/Inventory/Test/Mftf/Test/AdminManageStockForVirtualProductIsDisabledTest.xml index e6809cb3cbc4..67e212857716 100644 --- a/Inventory/Test/Mftf/Test/AdminManageStockForVirtualProductIsDisabledTest.xml +++ b/Inventory/Test/Mftf/Test/AdminManageStockForVirtualProductIsDisabledTest.xml @@ -69,6 +69,7 @@ </actionGroup> <deleteData createDataKey="simpleVirtualMsiProduct1" stepKey="deleteVirtualProduct"/> <deleteData createDataKey="simpleCategory1" stepKey="deletesimpleCategory1"/> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> </after> diff --git a/Inventory/Test/Mftf/Test/AdminUseDecimalQuantityOnSimpleProductTest.xml b/Inventory/Test/Mftf/Test/AdminUseDecimalQuantityOnSimpleProductTest.xml index 9fdefc32e07e..429a77334740 100644 --- a/Inventory/Test/Mftf/Test/AdminUseDecimalQuantityOnSimpleProductTest.xml +++ b/Inventory/Test/Mftf/Test/AdminUseDecimalQuantityOnSimpleProductTest.xml @@ -46,6 +46,7 @@ </actionGroup> <deleteData createDataKey="simpleProduct1" stepKey="deleteProduct"/> <deleteData createDataKey="simpleCategory1" stepKey="deletesimpleCategory1"/> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> </after> diff --git a/Inventory/Test/Mftf/Test/AdminUseDecimalQuantityOnVirtualProductTest.xml b/Inventory/Test/Mftf/Test/AdminUseDecimalQuantityOnVirtualProductTest.xml index c232c083a8d6..10988f2d7730 100644 --- a/Inventory/Test/Mftf/Test/AdminUseDecimalQuantityOnVirtualProductTest.xml +++ b/Inventory/Test/Mftf/Test/AdminUseDecimalQuantityOnVirtualProductTest.xml @@ -46,6 +46,7 @@ </actionGroup> <deleteData createDataKey="simpleCategory1" stepKey="deletesimpleCategory1"/> <deleteData createDataKey="simpleProduct1" stepKey="deleteProduct"/> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/ActionGroup/AdminResetFilterInManageSourcesGridActionGroup.xml b/InventoryAdminUi/Test/Mftf/ActionGroup/AdminResetFilterInManageSourcesGridActionGroup.xml new file mode 100644 index 000000000000..6226228a7e55 --- /dev/null +++ b/InventoryAdminUi/Test/Mftf/ActionGroup/AdminResetFilterInManageSourcesGridActionGroup.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright 2026 Adobe + * All Rights Reserved. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminResetFilterInManageSourcesGridActionGroup"> + <annotations> + <description>Navigates to the Admin Manage Sources grid and clears keyword search and column filters.</description> + </annotations> + <amOnPage url="{{AdminManageSourcePage.url}}" stepKey="amOnManageSourcesGridForFilterReset"/> + <waitForPageLoad stepKey="waitForManageSourcesGridForFilterReset"/> + <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" + dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" + stepKey="clearManageSourcesGridKeywordFilters"/> + <conditionalClick selector="{{AdminGridFilterControls.clearAll}}" + dependentSelector=".admin__data-grid-header[data-bind='afterRender: \$data.setToolbarNode'] .admin__data-grid-filters-current._show" + visible="true" stepKey="clearManageSourcesGridAppliedFilters"/> + <conditionalClick selector="{{AdminGridFilterControls.clearAll}}" + dependentSelector="{{AdminManageSourcesGridFilterControls.dropDown}}" visible="true" + stepKey="clearManageSourcesGridFiltersDropdown"/> + <waitForPageLoad stepKey="waitForManageSourcesGridAfterFilterReset"/> + </actionGroup> +</actionGroups> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminAddConfigurableProductWithDropDownAttributeWithNewSourceTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminAddConfigurableProductWithDropDownAttributeWithNewSourceTest.xml index 71be37c4427a..8817ec2ab0cb 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminAddConfigurableProductWithDropDownAttributeWithNewSourceTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminAddConfigurableProductWithDropDownAttributeWithNewSourceTest.xml @@ -39,6 +39,7 @@ <argument name="stockName" value="{{_defaultStock.name}}"/> <argument name="websiteName" value="{{_defaultWebsite.name}}"/> </actionGroup> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> <deleteData createDataKey="createPreReqCategory1" stepKey="deletePreReqCategory1"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminAddStockToVirtualProductTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminAddStockToVirtualProductTest.xml index fcfdcd304481..fda2e287ef80 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminAddStockToVirtualProductTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminAddStockToVirtualProductTest.xml @@ -38,6 +38,7 @@ </actionGroup> <!-- Delete all products via API using ProductApiHelper --> <helper class="Magento\Catalog\Test\Mftf\Helper\ProductApiHelper" method="deleteAllProductsApi" stepKey="deleteAllProductsViaApi"/> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> <deleteData createDataKey="createPreReqCategory1" stepKey="deletePreReqCategory1"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminAssignMultipleSourcesToStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminAssignMultipleSourcesToStockTest.xml index 03cc1d2942b9..6f9428dbcd57 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminAssignMultipleSourcesToStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminAssignMultipleSourcesToStockTest.xml @@ -45,6 +45,7 @@ <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin1"/> </before> <after> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCanDeleteSourcesAssignedToStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCanDeleteSourcesAssignedToStockTest.xml index c114bfdaf288..c7bfb46c4939 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCanDeleteSourcesAssignedToStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCanDeleteSourcesAssignedToStockTest.xml @@ -29,6 +29,7 @@ <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin1"/> </before> <after> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCancelOrderWithGroupedProductCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCancelOrderWithGroupedProductCustomStockTest.xml index 2bfd47a761d6..69f3b16c476e 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCancelOrderWithGroupedProductCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCancelOrderWithGroupedProductCustomStockTest.xml @@ -38,6 +38,7 @@ <argument name="stockName" value="{{_defaultStock.name}}"/> <argument name="websiteName" value="{{_defaultWebsite.name}}"/> </actionGroup> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <!--Delete created test data.--> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCatalogQuickSearchForConfigurableProductOnTestStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCatalogQuickSearchForConfigurableProductOnTestStockTest.xml index 06616bf320b6..7dfa2d634caa 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCatalogQuickSearchForConfigurableProductOnTestStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCatalogQuickSearchForConfigurableProductOnTestStockTest.xml @@ -40,6 +40,7 @@ <!-- Delete all products via API using ProductApiHelper --> <helper class="Magento\Catalog\Test\Mftf\Helper\ProductApiHelper" method="deleteAllProductsApi" stepKey="deleteAllProductsViaApi"/> <deleteData createDataKey="createCategory1" stepKey="deleteCategory"/> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCatalogQuickSearchForVirtualProductOnTestStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCatalogQuickSearchForVirtualProductOnTestStockTest.xml index 9111c5d917a1..8a2129e530cb 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCatalogQuickSearchForVirtualProductOnTestStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCatalogQuickSearchForVirtualProductOnTestStockTest.xml @@ -42,6 +42,7 @@ </actionGroup> <deleteData createDataKey="virtualProduct1" stepKey="deleteVirtualProduct"/> <deleteData createDataKey="createCategory1" stepKey="deletecreateCategory1"/> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminConfigurableProductDisabledManageStockOnCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminConfigurableProductDisabledManageStockOnCustomStockTest.xml index 5e9d6ff2b5b8..ff15ea767bac 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminConfigurableProductDisabledManageStockOnCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminConfigurableProductDisabledManageStockOnCustomStockTest.xml @@ -49,6 +49,7 @@ <deleteData createDataKey="category" stepKey="deleteCategory"/> <!-- Delete all products via API using ProductApiHelper --> <helper class="Magento\Catalog\Test\Mftf\Helper\ProductApiHelper" method="deleteAllProductsApi" stepKey="deleteAllProductsViaApi"/> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <magentoCLI command="config:set {{MediaGalleryConfigDataEnabled.path}} {{MediaGalleryConfigDataEnabled.value}}" stepKey="disabledOldMediaGallery"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminConfigurableProductDisabledManageStockOnProductPageCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminConfigurableProductDisabledManageStockOnProductPageCustomStockTest.xml index aa47de2692cb..94d175b4ba1b 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminConfigurableProductDisabledManageStockOnProductPageCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminConfigurableProductDisabledManageStockOnProductPageCustomStockTest.xml @@ -43,6 +43,7 @@ <deleteData createDataKey="category" stepKey="deleteCategory"/> <!-- Delete all products via API using ProductApiHelper --> <helper class="Magento\Catalog\Test\Mftf\Helper\ProductApiHelper" method="deleteAllProductsApi" stepKey="deleteAllProductsViaApi"/> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateOrderWithGroupedProductCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateOrderWithGroupedProductCustomStockTest.xml index 7d5d12b48a45..9d277bb3e0d7 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateOrderWithGroupedProductCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateOrderWithGroupedProductCustomStockTest.xml @@ -29,6 +29,7 @@ <argument name="stockName" value="{{_defaultStock.name}}"/> <argument name="websiteName" value="{{_defaultWebsite.name}}"/> </actionGroup> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> </after> <!--Assign simple product to additional source.--> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminEachSourceQuantityCanBeSetTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminEachSourceQuantityCanBeSetTest.xml index f385dfd71e72..6dd1c3579c52 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminEachSourceQuantityCanBeSetTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminEachSourceQuantityCanBeSetTest.xml @@ -35,6 +35,7 @@ </actionGroup> </before> <after> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> <deleteData createDataKey="simpleCategory1" stepKey="deleteCategory1"/> <deleteData createDataKey="simpleProduct1" stepKey="deleteProduct1"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminManageSourceGridColumnsSortingTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminManageSourceGridColumnsSortingTest.xml index 4ccb205c1624..0aaba97a33b8 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminManageSourceGridColumnsSortingTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminManageSourceGridColumnsSortingTest.xml @@ -68,7 +68,7 @@ <waitForPageLoad time="30" stepKey="waitForSourceEditPageLoadToDisableCustomSource4"/> <click selector="{{AdminEditSourceGeneralSection.isEnabledLabel}}" stepKey="clickIsEnabledToDisableCustomSource4"/> <actionGroup ref="AdminFormSaveAndCloseActionGroup" stepKey="saveAndCloseCustomSourceToDisableCustomSource4"/> - + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminOrderCreatedForGuestCustomerWithConfigurableProductWithDropDownAttributeViaTheAdminTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminOrderCreatedForGuestCustomerWithConfigurableProductWithDropDownAttributeViaTheAdminTest.xml index e37fb450d138..a2b4c0841d39 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminOrderCreatedForGuestCustomerWithConfigurableProductWithDropDownAttributeViaTheAdminTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminOrderCreatedForGuestCustomerWithConfigurableProductWithDropDownAttributeViaTheAdminTest.xml @@ -56,6 +56,7 @@ <amOnPage url="{{AdminManageStockPage.url}}" stepKey="navigateToStockIndexPage"/> <actionGroup ref="AdminGridFilterResetActionGroup" stepKey="resetStocksGridFilter"/> <actionGroup ref="AdminClearFiltersActionGroup" stepKey="clearProductsGridFilters"/> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> <deleteData createDataKey="simpleCategory1" stepKey="deleteCategory1"/> <deleteData createDataKey="createCustomer1" stepKey="deleteCustomer"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminOrderCreatedForGuestCustomerWithConfigurableProductWithSwatchAttributeViaTheAdminTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminOrderCreatedForGuestCustomerWithConfigurableProductWithSwatchAttributeViaTheAdminTest.xml index 27b4eafec125..5654a62e0a7b 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminOrderCreatedForGuestCustomerWithConfigurableProductWithSwatchAttributeViaTheAdminTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminOrderCreatedForGuestCustomerWithConfigurableProductWithSwatchAttributeViaTheAdminTest.xml @@ -59,6 +59,7 @@ </actionGroup> <!-- Delete all products via API --> <helper class="Magento\Catalog\Test\Mftf\Helper\ProductApiHelper" method="deleteAllProductsApi" stepKey="deleteAllProductsViaApi"/> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> <deleteData createDataKey="simpleCategory1" stepKey="deleteCategory1"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminOrderCreatedForGuestCustomerWithConfigurableProductWithTextAttributeViaTheAdminTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminOrderCreatedForGuestCustomerWithConfigurableProductWithTextAttributeViaTheAdminTest.xml index ff2ae913b6b6..fc1b6de91d22 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminOrderCreatedForGuestCustomerWithConfigurableProductWithTextAttributeViaTheAdminTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminOrderCreatedForGuestCustomerWithConfigurableProductWithTextAttributeViaTheAdminTest.xml @@ -45,6 +45,7 @@ <actionGroup ref="AdminDeleteCustomerActionGroup" stepKey="deleteCustomerFromGrid"> <argument name="customerEmail" value="MsiCustomer1.email"/> </actionGroup> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> <deleteData createDataKey="simpleCategory1" stepKey="deleteCategory1"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminOrderCreatedWithConfigurableProductWithSwatchAttributeViaTheAdminTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminOrderCreatedWithConfigurableProductWithSwatchAttributeViaTheAdminTest.xml index 7196cec9052a..3c5082d44105 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminOrderCreatedWithConfigurableProductWithSwatchAttributeViaTheAdminTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminOrderCreatedWithConfigurableProductWithSwatchAttributeViaTheAdminTest.xml @@ -54,7 +54,7 @@ </actionGroup> <!-- Delete all products via API --> <helper class="Magento\Catalog\Test\Mftf\Helper\ProductApiHelper" method="deleteAllProductsApi" stepKey="deleteAllProductsViaApi"/> - + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> <deleteData createDataKey="simpleCategory1" stepKey="deleteCategory1"/> <deleteData createDataKey="createCustomer1" stepKey="deleteCustomer"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminOrderCreatedWithConfigurableProductWithTextAttributeViaTheAdminTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminOrderCreatedWithConfigurableProductWithTextAttributeViaTheAdminTest.xml index 058082c2c8e7..80113e5996da 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminOrderCreatedWithConfigurableProductWithTextAttributeViaTheAdminTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminOrderCreatedWithConfigurableProductWithTextAttributeViaTheAdminTest.xml @@ -54,7 +54,7 @@ </actionGroup> <!-- Delete all products via API --> <helper class="Magento\Catalog\Test\Mftf\Helper\ProductApiHelper" method="deleteAllProductsApi" stepKey="deleteAllProductsViaApi"/> - + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> <deleteData createDataKey="simpleCategory1" stepKey="deleteCategory1"/> <deleteData createDataKey="createCustomer1" stepKey="deleteCustomer"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminPaginationWorkedInManageSourcesGridTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminPaginationWorkedInManageSourcesGridTest.xml index 537c30469c43..bdd2c7e86e4c 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminPaginationWorkedInManageSourcesGridTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminPaginationWorkedInManageSourcesGridTest.xml @@ -47,6 +47,7 @@ <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin1"/> </before> <after> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminPriorityOfSourcesChangedByDragAndDropTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminPriorityOfSourcesChangedByDragAndDropTest.xml index 6bbc8ff5b127..91d8b2209951 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminPriorityOfSourcesChangedByDragAndDropTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminPriorityOfSourcesChangedByDragAndDropTest.xml @@ -28,6 +28,7 @@ <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> </before> <after> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminRemoveSourcesAssignedToProductTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminRemoveSourcesAssignedToProductTest.xml index 100029329db3..1dbcdcc057d6 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminRemoveSourcesAssignedToProductTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminRemoveSourcesAssignedToProductTest.xml @@ -31,6 +31,7 @@ <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin1"/> </before> <after> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> <deleteData createDataKey="simpleProduct1" stepKey="deleteProduct1"/> <deleteData createDataKey="simpleCategory1" stepKey="deleteCategory1"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminSaveTwiceDuringCreatingConfigurableProductTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminSaveTwiceDuringCreatingConfigurableProductTest.xml index 464eff76ea17..b81711ad9727 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminSaveTwiceDuringCreatingConfigurableProductTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminSaveTwiceDuringCreatingConfigurableProductTest.xml @@ -41,7 +41,7 @@ <deleteData createDataKey="category" stepKey="deleteCategory"/> <!-- Delete all products via API --> <helper class="Magento\Catalog\Test\Mftf\Helper\ProductApiHelper" method="deleteAllProductsApi" stepKey="deleteAllProductsViaApi"/> - + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> </after> <comment userInput="Create Configurable product with two options 'In Stock' on 'Default' stock" diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminSourceForEachQuantityCanBeSetByAdminTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminSourceForEachQuantityCanBeSetByAdminTest.xml index e9e52e3fbf45..288ac007e3ab 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminSourceForEachQuantityCanBeSetByAdminTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminSourceForEachQuantityCanBeSetByAdminTest.xml @@ -31,6 +31,7 @@ <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin1"/> </before> <after> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> <deleteData createDataKey="simpleCategory1" stepKey="deleteCategory1"/> <deleteData createDataKey="simpleProduct1" stepKey="deleteProduct1"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminUpdateSourceDataTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminUpdateSourceDataTest.xml index 4cefdde84e11..6bf3385d1689 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminUpdateSourceDataTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminUpdateSourceDataTest.xml @@ -25,6 +25,7 @@ <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin1"/> </before> <after> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminUserApplyToSeveralSimpleProductsMassActionUnAssignProductSourcesOnProductsGridToUnAssignAllAssignedSourcesTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminUserApplyToSeveralSimpleProductsMassActionUnAssignProductSourcesOnProductsGridToUnAssignAllAssignedSourcesTest.xml index 1a50a23c4ffd..8e364e65a929 100755 --- a/InventoryAdminUi/Test/Mftf/Test/AdminUserApplyToSeveralSimpleProductsMassActionUnAssignProductSourcesOnProductsGridToUnAssignAllAssignedSourcesTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminUserApplyToSeveralSimpleProductsMassActionUnAssignProductSourcesOnProductsGridToUnAssignAllAssignedSourcesTest.xml @@ -31,6 +31,7 @@ <deleteData createDataKey="createSubCategory" stepKey="deleteSubCategory"/> <deleteData createDataKey="createStock" stepKey="deleteStock"/> <actionGroup ref="DisableAllSourcesActionGroup" stepKey="disableAllSources"/> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminUserSetStatusForEachSourceItemTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminUserSetStatusForEachSourceItemTest.xml index 31aae213438d..f0a69e20808a 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminUserSetStatusForEachSourceItemTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminUserSetStatusForEachSourceItemTest.xml @@ -56,6 +56,7 @@ <argument name="stockName" value="{{_defaultStock.name}}"/> <argument name="websiteName" value="{{_defaultWebsite.name}}"/> </actionGroup> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <deleteData createDataKey="simpleProduct1" stepKey="deleteProduct"/> <deleteData createDataKey="simpleCategory1" stepKey="deleteCategory1"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/GuestCustomerCreatedOrderWithSimpleProductFromHomepageWithFreeShippingMethodTest.xml b/InventoryAdminUi/Test/Mftf/Test/GuestCustomerCreatedOrderWithSimpleProductFromHomepageWithFreeShippingMethodTest.xml index 828bdac1e2bc..324b5e8131ac 100644 --- a/InventoryAdminUi/Test/Mftf/Test/GuestCustomerCreatedOrderWithSimpleProductFromHomepageWithFreeShippingMethodTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/GuestCustomerCreatedOrderWithSimpleProductFromHomepageWithFreeShippingMethodTest.xml @@ -47,6 +47,7 @@ <argument name="stockName" value="{{_defaultStock.name}}"/> <argument name="websiteName" value="{{_defaultWebsite.name}}"/> </actionGroup> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> </after> <!-- Assign product to custom source --> <amOnPage url="{{AdminProductEditPage.url($$simpleProduct.id$$)}}" stepKey="openProductEditPage"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerOrderedVirtualProductOnDefaultStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerOrderedVirtualProductOnDefaultStockTest.xml index 4cd398e60f98..ebb6e16ee927 100644 --- a/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerOrderedVirtualProductOnDefaultStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerOrderedVirtualProductOnDefaultStockTest.xml @@ -53,6 +53,7 @@ <createData entity="VirtualProduct" stepKey="product"/> </before> <after> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <deleteData createDataKey="category" stepKey="deleteCategory"/> <deleteData createDataKey="product" stepKey="deleteProduct"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/StorefrontOrderCreatedWithConfigurableProductWithDropDownAttributeTest.xml b/InventoryAdminUi/Test/Mftf/Test/StorefrontOrderCreatedWithConfigurableProductWithDropDownAttributeTest.xml index 375b7292a5f5..cc27f23abe87 100644 --- a/InventoryAdminUi/Test/Mftf/Test/StorefrontOrderCreatedWithConfigurableProductWithDropDownAttributeTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StorefrontOrderCreatedWithConfigurableProductWithDropDownAttributeTest.xml @@ -40,6 +40,7 @@ </actionGroup> <!-- Delete all products via API using ProductApiHelper --> <helper class="Magento\Catalog\Test\Mftf\Helper\ProductApiHelper" method="deleteAllProductsApi" stepKey="deleteAllProductsViaApi"/> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> <deleteData createDataKey="simpleCategory1" stepKey="deleteCategory1"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/StorefrontOrderCreatedWithConfigurableProductWithSwatchAttributeTest.xml b/InventoryAdminUi/Test/Mftf/Test/StorefrontOrderCreatedWithConfigurableProductWithSwatchAttributeTest.xml index b721810670ee..f77abb68fa40 100644 --- a/InventoryAdminUi/Test/Mftf/Test/StorefrontOrderCreatedWithConfigurableProductWithSwatchAttributeTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StorefrontOrderCreatedWithConfigurableProductWithSwatchAttributeTest.xml @@ -41,6 +41,7 @@ </actionGroup> <!-- Delete all products via API using ProductApiHelper --> <helper class="Magento\Catalog\Test\Mftf\Helper\ProductApiHelper" method="deleteAllProductsApi" stepKey="deleteAllProductsViaApi"/> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> <deleteData createDataKey="simpleCategory1" stepKey="deleteCategory1"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/StorefrontOrderCreatedWithVirtualProductByGuestCustomerTest.xml b/InventoryAdminUi/Test/Mftf/Test/StorefrontOrderCreatedWithVirtualProductByGuestCustomerTest.xml index 5fb9df2bb7b6..b3918ead0f8b 100644 --- a/InventoryAdminUi/Test/Mftf/Test/StorefrontOrderCreatedWithVirtualProductByGuestCustomerTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StorefrontOrderCreatedWithVirtualProductByGuestCustomerTest.xml @@ -42,6 +42,7 @@ <deleteData createDataKey="simpleCategory1" stepKey="deletesimpleCategory1"/> <!-- Delete virtual product created via UI --> <helper class="Magento\Catalog\Test\Mftf\Helper\ProductApiHelper" method="deleteAllProductsApi" stepKey="deleteAllProductsViaApi"/> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/StorefrontSimpleProductAssignedToNonDefaultSourceCreatedByAdminUserTest.xml b/InventoryAdminUi/Test/Mftf/Test/StorefrontSimpleProductAssignedToNonDefaultSourceCreatedByAdminUserTest.xml index c256db582531..7552b7395269 100644 --- a/InventoryAdminUi/Test/Mftf/Test/StorefrontSimpleProductAssignedToNonDefaultSourceCreatedByAdminUserTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StorefrontSimpleProductAssignedToNonDefaultSourceCreatedByAdminUserTest.xml @@ -44,6 +44,7 @@ <argument name="stockName" value="{{_defaultStock.name}}"/> <argument name="websiteName" value="{{_defaultWebsite.name}}"/> </actionGroup> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/InventoryBundleProduct/Test/Mftf/Test/StorefrontBundleProductOutOfStockWhenChildProductIsOutOfStockTest.xml b/InventoryBundleProduct/Test/Mftf/Test/StorefrontBundleProductOutOfStockWhenChildProductIsOutOfStockTest.xml index cdfbcb41292f..01f0f7f95e07 100644 --- a/InventoryBundleProduct/Test/Mftf/Test/StorefrontBundleProductOutOfStockWhenChildProductIsOutOfStockTest.xml +++ b/InventoryBundleProduct/Test/Mftf/Test/StorefrontBundleProductOutOfStockWhenChildProductIsOutOfStockTest.xml @@ -223,6 +223,7 @@ <actionGroup ref="CliCacheCleanActionGroup" stepKey="cleanCache"> <argument name="tags" value=""/> </actionGroup> + <actionGroup ref="AdminResetFilterInManageSourcesGridActionGroup" stepKey="resetManageSourcesGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> </after> <!--Verify simple product1, simple product 2 and simple product 3 is visible in category front page --> From 8c6548d47256ef0d5a16bb6f75cfa254d8bc3855 Mon Sep 17 00:00:00 2001 From: chandrakalahanchinal <del66267@adobe.com> Date: Mon, 18 May 2026 14:11:23 +0530 Subject: [PATCH 42/83] ACQE-9557: Update test steps - Updated steps based on current flow. --- ...uctDisabledManageStockOnConfigurationPageCustomStockTest.xml | 2 +- ...leProductDisabledManageStockOnProductPageCustomStockTest.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminBundleProductDisabledManageStockOnConfigurationPageCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminBundleProductDisabledManageStockOnConfigurationPageCustomStockTest.xml index c8a40fc994e3..c7adc4ba9e73 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminBundleProductDisabledManageStockOnConfigurationPageCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminBundleProductDisabledManageStockOnConfigurationPageCustomStockTest.xml @@ -115,7 +115,7 @@ <!--Verify product is visible storefront.--> <amOnPage url="{{StorefrontCategoryPage.url($$category.custom_attributes[url_key]$$)}}" stepKey="navigateToCategoryPageToVerifyBundleProduct"/> <waitForPageLoad stepKey="waitForCategoryPageLoadToVerifyBundleProduct"/> - <see userInput="$bundleProduct.name$" stepKey="assertProductIsPresent"/> + <dontSee userInput="$bundleProduct.name$" stepKey="assertProductIsPresent"/> <see userInput="$$simpleProduct.price$$" stepKey="assertProductPriceIsPresent"/> </test> </tests> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminBundleProductDisabledManageStockOnProductPageCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminBundleProductDisabledManageStockOnProductPageCustomStockTest.xml index c7ee98819491..334128e7cd3a 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminBundleProductDisabledManageStockOnProductPageCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminBundleProductDisabledManageStockOnProductPageCustomStockTest.xml @@ -101,7 +101,7 @@ <!--Verify product is visible storefront.--> <amOnPage url="{{StorefrontCategoryPage.url($$category.custom_attributes[url_key]$$)}}" stepKey="navigateToCategoryPageToVerifyBundleProduct"/> <waitForPageLoad stepKey="waitForCategoryPageLoadToVerifyBundleProduct"/> - <see userInput="$bundleProduct.name$" stepKey="assertProductIsPresent"/> + <dontSee userInput="$bundleProduct.name$" stepKey="assertProductIsPresent"/> <see userInput="$$simpleProduct.price$$" stepKey="assertProductPriceIsPresent"/> </test> </tests> From b64033c97d0983be8d16f3909841515986f3ebc3 Mon Sep 17 00:00:00 2001 From: Shweta Tripathi <shwetatripat@adobe.com> Date: Mon, 18 May 2026 15:56:57 +0530 Subject: [PATCH 43/83] ACQE-9696: [ATLH] Filters - Round 3 - Inventory Source Grid - Fixed dependency errors --- Inventory/Test/Mftf/test-dependency-allowlist | 1 + Inventory/Test/Mftf/test-dependency-errors-detailed | 5 +++++ InventoryBundleProduct/Test/Mftf/test-dependency-allowlist | 1 + .../Test/Mftf/test-dependency-errors-detailed | 1 + 4 files changed, 8 insertions(+) diff --git a/Inventory/Test/Mftf/test-dependency-allowlist b/Inventory/Test/Mftf/test-dependency-allowlist index 2837dd88a132..5c57919e16ec 100644 --- a/Inventory/Test/Mftf/test-dependency-allowlist +++ b/Inventory/Test/Mftf/test-dependency-allowlist @@ -49,6 +49,7 @@ AdminProductEditPage StorefrontProductPage AdminAssignCategoryToProductAndSaveActionGroup DisableAllSourcesActionGroup +AdminResetFilterInManageSourcesGridActionGroup StorefrontAssertProductNameOnProductPageActionGroup StorefrontAssertProductPriceOnProductPageActionGroup AdminProductSEOSection diff --git a/Inventory/Test/Mftf/test-dependency-errors-detailed b/Inventory/Test/Mftf/test-dependency-errors-detailed index 933208c8bca6..190cd5c25e5b 100644 --- a/Inventory/Test/Mftf/test-dependency-errors-detailed +++ b/Inventory/Test/Mftf/test-dependency-errors-detailed @@ -26,6 +26,7 @@ contains entity references that violate dependency constraints: CliIndexerReindexActionGroup from module(s): magento/module-indexer AdminLoginActionGroup from module(s): magento/module-admin-analytics, magento/module-backend, magento/module-two-factor-auth AssignWebsiteToStockActionGroup from module(s): magento/module-inventory-admin-ui + AdminResetFilterInManageSourcesGridActionGroup from module(s): magento/module-inventory-admin-ui AdminLogoutActionGroup from module(s): magento/module-backend AssertProductInStorefrontCategoryPage from module(s): magento/module-catalog AssertProductNameAndSkuInStorefrontProductPageActionGroup from module(s): magento/module-catalog @@ -44,6 +45,7 @@ contains entity references that violate dependency constraints: AdminOrderDetailsPage from module(s): magento/module-gift-wrapping, magento/module-reward, magento/module-rma, magento/module-sales AdminLoginActionGroup from module(s): magento/module-admin-analytics, magento/module-backend, magento/module-two-factor-auth AssignWebsiteToStockActionGroup from module(s): magento/module-inventory-admin-ui + AdminResetFilterInManageSourcesGridActionGroup from module(s): magento/module-inventory-admin-ui AdminLogoutActionGroup from module(s): magento/module-backend AdminGoToProductGridFilterResultsByInputEditProduct from module(s): magento/module-inventory-admin-ui AdminOnProductEditPageAssignSourceToProduct from module(s): magento/module-inventory-admin-ui @@ -128,6 +130,7 @@ contains entity references that violate dependency constraints: AdminGoToProductGridFilterResultsByInputEditProduct from module(s): magento/module-inventory-admin-ui AdminOnProductEditPageAssignSourceToProduct from module(s): magento/module-inventory-admin-ui AssignWebsiteToStockActionGroup from module(s): magento/module-inventory-admin-ui + AdminResetFilterInManageSourcesGridActionGroup from module(s): magento/module-inventory-admin-ui AdminLogoutActionGroup from module(s): magento/module-backend AssertProductInStorefrontCategoryPage from module(s): magento/module-catalog AssertProductInStorefrontProductPageActionGroup from module(s): magento/module-catalog @@ -172,6 +175,7 @@ contains entity references that violate dependency constraints: CheckoutSuccessMainSection from module(s): magento/module-b2b, magento/module-checkout AdminLoginActionGroup from module(s): magento/module-admin-analytics, magento/module-backend, magento/module-two-factor-auth AssignWebsiteToStockActionGroup from module(s): magento/module-inventory-admin-ui + AdminResetFilterInManageSourcesGridActionGroup from module(s): magento/module-inventory-admin-ui AdminLogoutActionGroup from module(s): magento/module-backend AdminGoToProductGridFilterResultsByInputEditProduct from module(s): magento/module-inventory-admin-ui AdminOnProductEditPageAssignSourceToProduct from module(s): magento/module-inventory-admin-ui @@ -199,6 +203,7 @@ contains entity references that violate dependency constraints: CheckoutSuccessMainSection from module(s): magento/module-b2b, magento/module-checkout AdminLoginActionGroup from module(s): magento/module-admin-analytics, magento/module-backend, magento/module-two-factor-auth AssignWebsiteToStockActionGroup from module(s): magento/module-inventory-admin-ui + AdminResetFilterInManageSourcesGridActionGroup from module(s): magento/module-inventory-admin-ui AdminLogoutActionGroup from module(s): magento/module-backend AdminGoToProductGridFilterResultsByInputEditProduct from module(s): magento/module-inventory-admin-ui AdminOnProductEditPageAssignSourceToProduct from module(s): magento/module-inventory-admin-ui diff --git a/InventoryBundleProduct/Test/Mftf/test-dependency-allowlist b/InventoryBundleProduct/Test/Mftf/test-dependency-allowlist index 864f4354d3d7..b60735443666 100644 --- a/InventoryBundleProduct/Test/Mftf/test-dependency-allowlist +++ b/InventoryBundleProduct/Test/Mftf/test-dependency-allowlist @@ -5,4 +5,5 @@ AssignWebsiteToStockActionGroup AssignSourceToProductActionGroup AdminFillSourceQtyOnProductEditPageActionGroup AdminChangeSourceStockStatusActionGroup +AdminResetFilterInManageSourcesGridActionGroup AdminApplyMinAndMaxQtyOnProductEditPageActionGroup diff --git a/InventoryBundleProduct/Test/Mftf/test-dependency-errors-detailed b/InventoryBundleProduct/Test/Mftf/test-dependency-errors-detailed index ab1348be8eb5..2224500d3892 100644 --- a/InventoryBundleProduct/Test/Mftf/test-dependency-errors-detailed +++ b/InventoryBundleProduct/Test/Mftf/test-dependency-errors-detailed @@ -9,3 +9,4 @@ contains entity references that violate dependency constraints: AssignSourceToProductActionGroup from module(s): magento/module-inventory-admin-ui AdminFillSourceQtyOnProductEditPageActionGroup from module(s): magento/module-inventory-admin-ui AdminChangeSourceStockStatusActionGroup from module(s): magento/module-inventory-admin-ui + AdminResetFilterInManageSourcesGridActionGroup from module(s): magento/module-inventory-admin-ui From 65cc35cb8bd56f039ec8ae47adb4214fe97e86de Mon Sep 17 00:00:00 2001 From: Alexandra Zota <zota@adobe.com> Date: Thu, 21 May 2026 16:25:38 +0300 Subject: [PATCH 44/83] ACP2E-4947: PR Quality Gates bugfixes and improvements 2 --- .github/scripts/check_copyright.py | 176 +++-- .github/scripts/check_copyright_pr.php | 354 ++++++++++ .github/scripts/phpstan.neon | 2 + .github/scripts/tslint.json | 12 + .github/workflows/pr-quality-gates.yml | 865 +++++++++++-------------- 5 files changed, 860 insertions(+), 549 deletions(-) create mode 100644 .github/scripts/check_copyright_pr.php create mode 100644 .github/scripts/tslint.json diff --git a/.github/scripts/check_copyright.py b/.github/scripts/check_copyright.py index 69a0e1131fc0..d75d936792a2 100644 --- a/.github/scripts/check_copyright.py +++ b/.github/scripts/check_copyright.py @@ -84,8 +84,11 @@ def _normalize_copyright(text: str) -> str: between file types, matching the approach used by the Jenkins SanityCopyrightChecker. """ - # Remove PHP inline declarations so that '<?php declare(strict_types=1)' - # and '<?php' normalize identically and the copyright substring check passes. + # Strip XML processing instructions entirely so encoding/version attribute + # differences (e.g. encoding="UTF-8" vs absent) do not affect comparison. + text = re.sub(r'<\?xml[^?]*\?>', '', text) + # Strip PHP declare() so '<?php declare(strict_types=1)' and '<?php' + # normalize identically. text = re.sub(r'\bdeclare\s*\([^)]*\)\s*;?', '', text) return re.sub(r'[\s#/\*\-<>!?\[\]]+', '', text).lower() @@ -492,7 +495,8 @@ def should_exclude_file(file_path: str, exclude_list: List[str]) -> bool: def check_file(file_path: str, template: str, fix: bool = False, dry_run: bool = False, - debug: bool = False, pr_mode: bool = False, base_sha: str = '') -> bool: + debug: bool = False, pr_mode: bool = False, base_sha: str = '', + is_private: bool = False, requires_notice: bool = False) -> bool: """Check and optionally fix copyright header in a file.""" ext = Path(file_path).suffix.lower() @@ -512,70 +516,97 @@ def check_file(file_path: str, template: str, fix: bool = False, dry_run: bool = click.echo(f" Skipping 3rd-party file (no Magento/Adobe reference): {file_path}") return True + # ── Confidentiality format check (derived from template) ───────── + has_confidential = 'ADOBE CONFIDENTIAL' in content + has_notice = 'NOTICE:' in content + if is_private and not has_confidential: + click.echo(f" ERROR: Private repo: missing ADOBE CONFIDENTIAL header: {file_path}") + return False + if is_private and requires_notice and not has_notice: + click.echo(f" ERROR: Private repo: missing NOTICE block in copyright header: {file_path}") + return False + if not is_private and has_confidential: + click.echo(f" ERROR: Public repo: file must not contain ADOBE CONFIDENTIAL: {file_path}") + return False + comment_style = COMMENT_STYLES[ext] existing_header, header_line_count = extract_existing_copyright(content, comment_style) - # ── Determine the year to validate against ──────────────────────── - # On GitHub Actions we have full git history, so always use the - # authoritative git creation year. The Jenkins checker trusts the - # year in the file because git is not available there, but here we - # can and should verify it. - year = str(get_git_creation_year(file_path, debug, use_current_year=pr_mode, base_sha=base_sha)) - - expected_header = format_copyright_header(template, file_path, comment_style, year, debug) - - if debug: - click.echo(f" Expected header preview:") - click.echo(f" {expected_header[:100]}...") - click.echo(f" Existing header preview:") - click.echo(f" {existing_header[:100]}...") - click.echo(f" Year used for comparison: {year}") - # ── Comparison ──────────────────────────────────────────────────── - # Use normalized comparison (strip all comment markers / whitespace) - # so minor formatting differences do not cause failures, matching the - # flexible approach of the Jenkins SanityCopyrightChecker. - expected_norm = _normalize_copyright(expected_header) existing_norm = _normalize_copyright(existing_header) + year = str(datetime.now().year) # default; overridden in non-PR mode + expected_header = '' # set for new files and non-PR mode + base_header_for_fix = None # set for existing files whose copyright changed - # The expected template must appear within the existing header. - # (Not the reverse -- a nearly-empty header like "php" must not match.) - if ext in ['.xml', '.xsd']: - if '/**' in existing_header or '*/' in existing_header: - if debug: - click.echo(f" XML file has incorrect comment style: {file_path}") - # Fall through to fix / report - elif expected_norm and expected_norm in existing_norm: - return True - else: - if expected_norm and expected_norm in existing_norm: - return True - - # ── No match ────────────────────────────────────────────────────── - - # For existing files in PR mode: if the copyright year already in the file - # is earlier than what git log reports, accept it. This handles files that - # predate the repository's available git history (e.g. Copyright 2011 when - # git log only goes back to 2015 due to history truncation or rebase). - # New files are excluded — they must carry the current year. - if pr_mode and base_sha and existing_header: + if pr_mode and base_sha: try: - cat_result = subprocess.run( - ['git', 'cat-file', '-e', f'{base_sha}:{file_path}'], - capture_output=True, cwd=_GIT_ROOT + base_result = subprocess.run( + ['git', 'show', f'{base_sha}:{file_path}'], + capture_output=True, text=True, cwd=_GIT_ROOT ) - if cat_result.returncode == 0: - existing_year_match = re.search(r'[Cc]opyright\s+(\d{4})', existing_header) - if existing_year_match and int(existing_year_match.group(1)) < int(year): + except Exception: + base_result = None + + if base_result is not None and base_result.returncode == 0: + # Existing file: compare copyright directly against the base branch. + # No template involved — we only check that the developer did not + # modify the copyright header. If the base had no copyright, skip: + # migrating existing files to the Adobe format is a separate task. + base_header, _ = extract_existing_copyright(base_result.stdout, comment_style) + if not base_header: + if debug: + click.echo(f" Existing file has no copyright in base — skipping") + return True + base_norm = _normalize_copyright(base_header) + if base_norm == existing_norm: + return True + # Copyright was changed in this PR — fall through to report/fix. + base_header_for_fix = base_header + else: + # New file: must carry the current year and correct format. + expected_header = format_copyright_header(template, file_path, comment_style, year, debug) + expected_norm = _normalize_copyright(expected_header) + if debug: + click.echo(f" New file: year {year}") + click.echo(f" Expected: {expected_header[:80]}...") + if ext in ['.xml', '.xsd']: + if '/**' in existing_header or '*/' in existing_header: if debug: - click.echo(f' Accepting copyright year {existing_year_match.group(1)}: ' - f'predates git history (git reports {year})') + click.echo(f" XML file has incorrect comment style: {file_path}") + elif expected_norm and expected_norm in existing_norm: return True - except Exception: - pass + else: + if expected_norm and expected_norm in existing_norm: + return True + + else: + # Non-PR mode (local scan / --fix): use git creation year. + year = str(get_git_creation_year(file_path, debug, use_current_year=pr_mode, base_sha=base_sha)) + expected_header = format_copyright_header(template, file_path, comment_style, year, debug) + expected_norm = _normalize_copyright(expected_header) + if debug: + click.echo(f" Expected header preview:") + click.echo(f" {expected_header[:100]}...") + click.echo(f" Existing header preview:") + click.echo(f" {existing_header[:100]}...") + click.echo(f" Year used for comparison: {year}") + if ext in ['.xml', '.xsd']: + if '/**' in existing_header or '*/' in existing_header: + if debug: + click.echo(f" XML file has incorrect comment style: {file_path}") + elif expected_norm and expected_norm in existing_norm: + return True + else: + if expected_norm and expected_norm in existing_norm: + return True + + # ── No match ────────────────────────────────────────────────────── if dry_run: - click.echo(f" Would fix: {file_path}") + if base_header_for_fix is not None: + click.echo(f" Would restore: {file_path} (copyright was modified in this PR)") + else: + click.echo(f" Would fix: {file_path}") return False if fix: @@ -597,7 +628,16 @@ def check_file(file_path: str, template: str, fix: bool = False, dry_run: bool = new_content = '\n'.join(preserved_lines) if preserved_lines: new_content += '\n' - new_content += expected_header + + if base_header_for_fix is not None: + # Existing file: restore the copyright to what it was in the base branch. + new_content += base_header_for_fix + fix_msg = f" Fixed: {file_path} (restored base copyright)" + else: + # New file or non-PR mode: write the template-generated header. + new_content += expected_header + fix_msg = f" Fixed: {file_path} (year: {year})" + if not remaining_content.startswith('\n'): new_content += '\n' new_content += remaining_content.lstrip('\n') @@ -605,13 +645,19 @@ def check_file(file_path: str, template: str, fix: bool = False, dry_run: bool = with open(file_path, 'w', encoding='utf-8') as f: f.write(new_content) - click.echo(f" Fixed: {file_path} (year: {year})") + click.echo(fix_msg) return True else: - click.echo(f" Missing/incorrect copyright: {file_path} (expected year: {year})") - click.echo(f" To fix: python3 .github/scripts/check_copyright.py " - f"--template .github/scripts/copyright-template.txt " - f"--path '{file_path}' --pr-mode --fix") + if base_header_for_fix is not None: + click.echo(f" Copyright was modified in this PR: {file_path}") + click.echo(f" To fix: python3 .github/scripts/check_copyright.py " + f"--template .github/scripts/copyright-template.txt " + f"--path '{file_path}' --pr-mode --base-sha $BASE_SHA --fix") + else: + click.echo(f" Missing/incorrect copyright: {file_path} (expected year: {year})") + click.echo(f" To fix: python3 .github/scripts/check_copyright.py " + f"--template .github/scripts/copyright-template.txt " + f"--path '{file_path}' --pr-mode --fix") return False @@ -661,6 +707,8 @@ def main(template: str, fix: bool, dry_run: bool, extensions: str, exclude: str, sys.exit(1) template_content = load_template(template) + is_private = 'ADOBE CONFIDENTIAL' in template_content + requires_notice = 'NOTICE:' in template_content extensions_list = [ext.strip() for ext in extensions.split(',')] exclude_list = [entry.strip() for entry in exclude.split(',') if entry.strip()] @@ -678,7 +726,7 @@ def main(template: str, fix: bool, dry_run: bool, extensions: str, exclude: str, continue if not any(file_path.endswith(ext) for ext in extensions_list): continue - if not check_file(file_path, template_content, fix, dry_run, debug, pr_mode, base_sha): + if not check_file(file_path, template_content, fix, dry_run, debug, pr_mode, base_sha, is_private, requires_notice): issues_found.append(file_path) if issues_found: click.echo(f"\n{len(issues_found)} file(s) have copyright issues") @@ -741,7 +789,7 @@ def main(template: str, fix: bool, dry_run: bool, extensions: str, exclude: str, if verbose or debug: click.echo(f"Checking: {path}") - if not check_file(path, template_content, fix, dry_run, debug, pr_mode, base_sha): + if not check_file(path, template_content, fix, dry_run, debug, pr_mode, base_sha, is_private, requires_notice): issues_found.append(path) else: if debug: @@ -774,7 +822,7 @@ def main(template: str, fix: bool, dry_run: bool, extensions: str, exclude: str, if verbose or debug: click.echo(f"Checking: {file_path}") - if not check_file(file_path, template_content, fix, dry_run, debug, pr_mode, base_sha): + if not check_file(file_path, template_content, fix, dry_run, debug, pr_mode, base_sha, is_private, requires_notice): issues_found.append(file_path) if debug: diff --git a/.github/scripts/check_copyright_pr.php b/.github/scripts/check_copyright_pr.php new file mode 100644 index 000000000000..3ec5ec3a545d --- /dev/null +++ b/.github/scripts/check_copyright_pr.php @@ -0,0 +1,354 @@ +<?php +/** + * Copyright 2026 Adobe + * All Rights Reserved. + */ +declare(strict_types=1); + +/** + * PR copyright header checker. + * + * New files — must carry the current year in the correct format for the repo edition. + * Existing files — the normalized copyright header must be identical to the base branch; + * the year must not be changed. + * + * Usage: + * php check_copyright_pr.php \ + * --files /tmp/copyright_changed.txt \ + * --added /tmp/copyright_added.txt \ + * --base-dir <dir> \ + * --template .github/scripts/copyright-template.txt + */ + +// ── Argument parsing ────────────────────────────────────────────────────────── + +$opts = getopt('', ['files:', 'added:', 'base-dir:', 'template:']); + +$missing = []; +foreach (['files', 'base-dir', 'template'] as $req) { + if (empty($opts[$req])) $missing[] = "--$req"; +} +if ($missing) { + fwrite(STDERR, "Error: missing required arguments: " . implode(', ', $missing) . "\n"); + fwrite(STDERR, "Usage: php check_copyright_pr.php --files <list> --added <list> --base-dir <dir> --template <path>\n"); + exit(1); +} + +$filesPath = $opts['files']; +$addedPath = $opts['added'] ?? ''; +$baseDir = rtrim((string) $opts['base-dir'], '/'); +$templatePath = $opts['template']; + +if (!file_exists($filesPath)) { + echo "No copyright-eligible changed files found — skipping.\n"; + exit(0); +} + +$template = trim((string) file_get_contents($templatePath)); +$isPrivate = str_contains($template, 'ADOBE CONFIDENTIAL'); +$requiresNotice = str_contains($template, 'NOTICE:'); +$changedFiles = array_filter(array_map('trim', file($filesPath))); +$addedFiles = ($addedPath && file_exists($addedPath)) + ? array_flip(array_filter(array_map('trim', file($addedPath)))) + : []; + +$currentYear = (int) date('Y'); +$issues = []; +$checked = 0; +$skipped = 0; + +// ── Helpers ─────────────────────────────────────────────────────────────────── + +/** + * Normalize a copyright block for comparison: strip XML declarations, PHP + * declare(), comment markers, whitespace and punctuation — mirrors the Python + * _normalize_copyright() function. + */ +function normalizeHeader(string $text): string +{ + $text = preg_replace('/<\?xml[^?]*\?>/', '', $text); // strip XML PI + $text = preg_replace('/\bdeclare\s*\([^)]*\)\s*;?/', '', $text); // strip declare() + return strtolower((string) preg_replace('/[\s#\/\*\-<>!?\[\]]+/', '', $text)); +} + +/** + * Returns true when the file should be skipped entirely. + */ +function shouldExclude(string $filePath): bool +{ + static $allowedExts = ['php','phtml','html','js','xml','xsd','less','css','scss','graphqls']; + + $ext = strtolower(pathinfo($filePath, PATHINFO_EXTENSION)); + if (!in_array($ext, $allowedExts, true)) return true; + + // .github/ and vendor/ are always excluded + if (preg_match('#^(\.github|vendor)/#', $filePath)) return true; + + // lib/web/ is excluded except lib/web/mage/ (Adobe-authored JS) + if (preg_match('#^lib/web/#', $filePath) && !preg_match('#^lib/web/mage/#', $filePath)) return true; + + return false; +} + +/** + * Extract the first copyright block from file content. + * Handles C-style (/** ... *\/), HTML (<!-- ... -->), and hash (# ...) blocks. + * Returns the raw header text, or '' if no copyright found. + */ +function extractCopyrightBlock(string $content): string +{ + $lines = explode("\n", $content); + $blockType = null; // 'c', 'html', 'hash' + $collected = []; + $foundCopyright = false; + + foreach ($lines as $i => $line) { + $s = trim($line); + + // Line 0: skip PHP/XML opening tag but collect it + if ($i === 0 && (str_starts_with($s, '<?php') || str_starts_with($s, '<?xml'))) { + $collected[] = $line; + continue; + } + + if ($blockType === null) { + if (str_starts_with($s, '/**') || str_starts_with($s, '/*')) { + $blockType = 'c'; + $collected[] = $line; + if (strlen($s) > 2 && str_ends_with($s, '*/')) { + $foundCopyright = stripos($s, 'copyright') !== false; + break; + } + continue; + } + if (str_starts_with($s, '<!--')) { + $blockType = 'html'; + $collected[] = $line; + if (strlen($s) > 4 && str_ends_with($s, '-->')) { + $foundCopyright = stripos($s, 'copyright') !== false; + break; + } + continue; + } + if (str_starts_with($s, '#')) { + $blockType = 'hash'; + $collected[] = $line; + if (stripos($s, 'copyright') !== false) $foundCopyright = true; + continue; + } + // Empty lines and declare() before the copyright block are allowed + if ($s === '') continue; + if (preg_match('/^declare\s*\([^)]*\)\s*;?$/', $s)) continue; + break; + } + + if ($blockType === 'c') { + $collected[] = $line; + if (stripos($s, 'copyright') !== false) $foundCopyright = true; + if (str_ends_with($s, '*/')) { + if ($foundCopyright) break; + $collected = []; $foundCopyright = false; $blockType = null; // non-copyright block, reset + } + continue; + } + + if ($blockType === 'html') { + $collected[] = $line; + if (stripos($s, 'copyright') !== false) $foundCopyright = true; + if (str_ends_with($s, '-->')) { + if ($foundCopyright) break; + $collected = []; $foundCopyright = false; $blockType = null; + } + continue; + } + + if ($blockType === 'hash') { + if (!str_starts_with($s, '#')) break; // end of hash block + if (stripos($s, 'copyright') !== false) $foundCopyright = true; + $collected[] = $line; + continue; + } + } + + return $foundCopyright ? implode("\n", $collected) : ''; +} + +/** + * Fetch the base-branch content of a file from the pre-fetched directory. + * Returns null when the file did not exist in the base branch. + */ +function getBaseContent(string $filePath, string $baseDir): ?string +{ + $path = $baseDir . '/' . $filePath; + return file_exists($path) ? (string) file_get_contents($path) : null; +} + +/** + * Build the expected copyright header for a given file type using the template. + * The template is in /** ... *\/ block format. + */ +function buildExpectedHeader(string $template, string $filePath, int $year): string +{ + $tpl = str_replace('{{YEAR}}', (string) $year, $template); + $ext = strtolower(pathinfo($filePath, PATHINFO_EXTENSION)); + + // Template is already in /** */ form; adapt wrapping for the file type. + // Strip outer /** and */ to get the inner lines. + $inner = trim((string) preg_replace('/^\/\*\*\s*|\s*\*\/$/', '', $tpl)); + $innerLines = explode("\n", $inner); + $bodyLines = array_map(static fn(string $l): string => ltrim($l, ' *'), $innerLines); + + switch ($ext) { + case 'php': + return "<?php\n" . $tpl . "\n"; + case 'phtml': + return "<?php\n" . $tpl . "\n?>\n"; + case 'xml': + case 'xsd': + $out = ['<?xml version="1.0"?>', '<!--']; + foreach ($bodyLines as $l) $out[] = $l !== '' ? " * {$l}" : ' *'; + $out[] = ' -->'; + return implode("\n", $out) . "\n"; + case 'graphqls': + $out = []; + foreach ($bodyLines as $l) $out[] = $l !== '' ? "# {$l}" : '#'; + return implode("\n", $out) . "\n"; + case 'html': + $out = ['<!--']; + foreach ($bodyLines as $l) $out[] = $l !== '' ? " * {$l}" : ' *'; + $out[] = ' -->'; + return implode("\n", $out) . "\n"; + default: + return $tpl . "\n"; + } +} + +// ── Main loop ───────────────────────────────────────────────────────────────── + +foreach ($changedFiles as $filePath) { + if (shouldExclude($filePath)) { + $skipped++; + continue; + } + + if (!is_file($filePath)) { + $skipped++; + continue; + } + + $content = (string) file_get_contents($filePath); + + // Skip third-party files that contain no Magento/Adobe reference + if (strpos($content, 'Magento') === false && strpos($content, 'Adobe') === false + && strpos($filePath, 'Magento') === false && strpos($filePath, 'Adobe') === false + ) { + $skipped++; + continue; + } + + $checked++; + $isNew = isset($addedFiles[$filePath]); + $currentHeader = extractCopyrightBlock($content); + + // ── Confidentiality format check (derived from template) ───────────────── + $hasConfidential = str_contains($content, 'ADOBE CONFIDENTIAL'); + $hasNotice = str_contains($content, 'NOTICE:'); + if ($isPrivate && !$hasConfidential) { + $issues[] = [ + 'file' => $filePath, + 'reason' => 'Private repo: missing ADOBE CONFIDENTIAL header', + 'new' => $isNew, + ]; + continue; + } + if ($isPrivate && $requiresNotice && !$hasNotice) { + $issues[] = [ + 'file' => $filePath, + 'reason' => 'Private repo: missing NOTICE block in copyright header', + 'new' => $isNew, + ]; + continue; + } + if (!$isPrivate && $hasConfidential) { + $issues[] = [ + 'file' => $filePath, + 'reason' => 'Public repo: file must not contain ADOBE CONFIDENTIAL', + 'new' => $isNew, + ]; + continue; + } + + // ── Missing copyright entirely ──────────────────────────────────────────── + if ($currentHeader === '') { + $issues[] = [ + 'file' => $filePath, + 'reason' => 'Missing copyright header', + 'new' => $isNew, + ]; + continue; + } + + $currentNorm = normalizeHeader($currentHeader); + + if ($isNew) { + // ── New file: must match the template with the current year ─────────── + $expected = buildExpectedHeader($template, $filePath, $currentYear); + $expectedNorm = normalizeHeader($expected); + if ($expectedNorm !== '' && strpos($currentNorm, $expectedNorm) === false) { + $issues[] = [ + 'file' => $filePath, + 'reason' => "New file: copyright header must use year {$currentYear} in the correct format", + 'new' => true, + ]; + } + } else { + // ── Existing file: copyright must not have changed ──────────────────── + $baseContent = getBaseContent($filePath, $baseDir); + + if ($baseContent === null) { + // File not found in base — treat as new + $expected = buildExpectedHeader($template, $filePath, $currentYear); + $expectedNorm = normalizeHeader($expected); + if ($expectedNorm !== '' && strpos($currentNorm, $expectedNorm) === false) { + $issues[] = [ + 'file' => $filePath, + 'reason' => "New file (not in base branch): copyright header must use year {$currentYear}", + 'new' => true, + ]; + } + continue; + } + + $baseHeader = extractCopyrightBlock($baseContent); + if ($baseHeader === '') { + // No copyright in base — skip (migrating old files is a separate task) + continue; + } + + $baseNorm = normalizeHeader($baseHeader); + if ($baseNorm !== $currentNorm) { + $issues[] = [ + 'file' => $filePath, + 'reason' => 'Copyright header was modified in this PR (year or content changed)', + 'new' => false, + ]; + } + } +} + +// ── Report ──────────────────────────────────────────────────────────────────── + +echo "Copyright check: {$checked} file(s) checked, {$skipped} skipped\n"; + +if (empty($issues)) { + echo "All files have correct copyright headers\n"; + exit(0); +} + +echo count($issues) . " file(s) have copyright issues:\n"; +foreach ($issues as $issue) { + $tag = $issue['new'] ? '[NEW] ' : '[EXISTING]'; + echo " {$tag} {$issue['file']}\n"; + echo " {$issue['reason']}\n"; +} +exit(1); diff --git a/.github/scripts/phpstan.neon b/.github/scripts/phpstan.neon index 8e1d9ecf302b..e60582b11c46 100644 --- a/.github/scripts/phpstan.neon +++ b/.github/scripts/phpstan.neon @@ -42,6 +42,8 @@ parameters: - '#Call to an undefined static method#' # Constants defined in interfaces (stubs have no constants) - '#Access to undefined constant#' + # Constants on classes not present in the sparse-clone + - '#Access to constant [a-zA-Z0-9_]+ on an unknown class#' # Variable defined in phtml template context - '#Variable \$block might not be defined#' - '#Variable \$escaper might not be defined#' diff --git a/.github/scripts/tslint.json b/.github/scripts/tslint.json new file mode 100644 index 000000000000..1b99ba7d68dd --- /dev/null +++ b/.github/scripts/tslint.json @@ -0,0 +1,12 @@ +{ + "rules": { + "no-var-keyword": true, + "no-any": true, + "triple-equals": true, + "semicolon": [true, "always"], + "prefer-const": true, + "no-console": false, + "eofline": true, + "trailing-comma": [true, {"multiline": "never", "singleline": "never"}] + } +} diff --git a/.github/workflows/pr-quality-gates.yml b/.github/workflows/pr-quality-gates.yml index f8a5e72cac4c..9cc7b7541c5e 100644 --- a/.github/workflows/pr-quality-gates.yml +++ b/.github/workflows/pr-quality-gates.yml @@ -13,137 +13,38 @@ on: workflow_dispatch: # Repository variables used by this workflow: -# - PR_QA_ENABLED_JOBS: CSV list of optional jobs to run. +# - PR_QA_ENABLED_JOBS: CSV list of checks to run. # Supported values: -# copyright-check,coding-standard,aggregate-linked-pr-checks -# Note: mainline-alignment and detect-changes always run on pull_request. +# coding-standard,aggregate-linked-pr-checks # - PR_QA_CODING_STANDARD_ENABLED_CHECKS: CSV list of coding-standard sub-checks. # Empty or includes "all" => run all coding-standard sub-checks. # Supported values: -# all,phpcs,phpcs-xml,phpcs-html,phpcs-graphql,phpcs-less,phpmd,phpstan, -# phpcpd,strict-types,fixture-reuse,rector,eslint +# all,phpcs,phpcs-xml,phpcs-html,phpcs-graphql,phpcs-less,phpmd, +# strict-types,fixture-reuse,eslint,typescript jobs: # ────────────────────────────────────────────────────────────────────── - # Pre-check: Detect which file types are present in the PR so that - # language-specific jobs (PHPCS, ESLint, Rector) can skip entirely - # when no relevant files were changed. + # Single job: mainline alignment + change detection + coding standard + # + linked-PR aggregate gate, run sequentially so the PR shows one check. # ────────────────────────────────────────────────────────────────────── - detect-changes: - needs: mainline-alignment + pr-quality-gates: if: >- github.event_name == 'pull_request' && vars.PR_QA_ENABLED_JOBS != '' runs-on: ubuntu-latest - timeout-minutes: 5 - permissions: - contents: read - pull-requests: read - outputs: - has_php: ${{ steps.check.outputs.has_php }} - has_js: ${{ steps.check.outputs.has_js }} - has_static: ${{ steps.check.outputs.has_static }} - has_new_files: ${{ steps.check.outputs.has_new_files }} - has_copyright_files: ${{ steps.check.outputs.has_copyright_files }} - copyright_files: ${{ steps.check.outputs.copyright_files }} - steps: - - name: Detect changed files and verify CI integrity - id: check - env: - GH_TOKEN: ${{ github.token }} - run: | - set -euo pipefail - pr="${{ github.event.pull_request.number }}" - repo="${{ github.repository }}" - echo "PR #${pr} ${{ github.event.pull_request.head.repo.full_name }} → ${{ github.event.pull_request.base.repo.full_name }}" - echo "PR_QA_ENABLED_JOBS: ${{ vars.PR_QA_ENABLED_JOBS }}" - - # Fetch all changed files as "filename TAB status" pairs (paginated) - files=$(gh api "repos/${repo}/pulls/${pr}/files" --paginate \ - --jq '.[] | [.filename, .status] | @tsv') - - # Verify required CI files are not removed in this PR - required=( - .github/workflows/pr-quality-gates.yml - .github/scripts/check_copyright.py - .github/scripts/copyright-template.txt - .github/scripts/rector-compat.php - .github/scripts/phpmd-ruleset.xml - .github/scripts/phpstan.neon - .github/scripts/phpstan-framework-autoload.php - .github/scripts/phpstan-extensions.neon - .github/scripts/filter-blacklist.sh - ) - missing=false - while IFS=$'\t' read -r filename status; do - [[ "$status" != "removed" ]] && continue - for req in "${required[@]}"; do - if [[ "$filename" == "$req" ]]; then - echo "::error::Required CI file removed: $filename" - missing=true - fi - done - done <<< "$files" - if $missing; then echo "::error::Restore removed CI files before merging."; exit 1; fi - - # Categorize files (exclude .github/, vendor/, lib/web/) - has_php=false; has_js=false; has_static=false - has_new_files=false; has_copyright_files=false - copyright_files="" - copyright_exts='\.(php|phtml|js|css|scss|less|xml|xsd|html|graphqls)$' - - while IFS=$'\t' read -r filename status; do - [[ -z "$filename" ]] && continue - [[ "$filename" =~ ^(\.github|vendor|lib/web)/ ]] && continue - [[ "$filename" =~ \.(php|phtml)$ ]] && has_php=true - [[ "$filename" =~ \.js$ && ! "$filename" =~ \.min\.js$ ]] && has_js=true - [[ "$filename" =~ \.(xml|xsd|html|graphqls|less)$ ]] && has_static=true - if [[ "$filename" =~ $copyright_exts && "$status" =~ ^(added|modified|renamed|copied)$ ]]; then - has_copyright_files=true - copyright_files+="${filename}"$'\n' - [[ "$status" == "added" ]] && has_new_files=true - fi - done <<< "$files" - copyright_files="${copyright_files%$'\n'}" - - echo "has_php=$has_php" >> "$GITHUB_OUTPUT" - echo "has_js=$has_js" >> "$GITHUB_OUTPUT" - echo "has_static=$has_static" >> "$GITHUB_OUTPUT" - echo "has_new_files=$has_new_files" >> "$GITHUB_OUTPUT" - echo "has_copyright_files=$has_copyright_files" >> "$GITHUB_OUTPUT" - { - echo "copyright_files<<EOF" - echo "$copyright_files" - echo "EOF" - } >> "$GITHUB_OUTPUT" - - echo "PHP files changed: $has_php" - echo "JS files changed: $has_js" - echo "Static files changed: $has_static" - echo "Copyright-eligible files changed: $has_copyright_files" - - # ────────────────────────────────────────────────────────────────────── - # Job 2: Mainline Alignment (Branch Freshness + PR Gate) - # - # PRs live on a fork (e.g. adobe-commerce-tier-4/<repo>), but the - # mainline lives on the upstream repo (magento-commerce/<repo>). - # This job fetches the upstream mainline branch and verifies the PR - # branch is rebased on its HEAD -- catching stale branches and merge - # conflicts before expensive CI builds waste cycles. - # ────────────────────────────────────────────────────────────────────── - mainline-alignment: - if: >- - github.event_name == 'pull_request' && - vars.PR_QA_ENABLED_JOBS != '' - runs-on: ubuntu-latest - timeout-minutes: 10 + timeout-minutes: 25 permissions: contents: read pull-requests: read + checks: read + statuses: read env: CROSS_REPO_READ_TOKEN: ${{ secrets.CROSS_REPO_READ_TOKEN }} steps: + + # ── Mainline alignment ────────────────────────────────────────── - name: Check branch alignment with upstream mainline + id: mainline env: GH_TOKEN: ${{ github.token }} run: | @@ -219,109 +120,151 @@ jobs: echo "Branch is up to date with ${upstream_label} ${base_branch}. All good." fi - # ────────────────────────────────────────────────────────────────────── - # Job 4: Copyright Header Check - # - # Validates that changed files carry the correct Adobe copyright header - # with the proper year (based on git creation date). - # ────────────────────────────────────────────────────────────────────── - copyright-check: - needs: - - mainline-alignment - - detect-changes - if: >- - always() && - contains(format(',{0},', vars.PR_QA_ENABLED_JOBS), ',copyright-check,') && - github.event_name == 'pull_request' && - needs.mainline-alignment.result == 'success' && - needs.detect-changes.result == 'success' && - needs.detect-changes.outputs.has_copyright_files == 'true' - runs-on: ubuntu-latest - timeout-minutes: 5 - permissions: - contents: read - steps: - - uses: actions/checkout@v6 - with: - fetch-depth: 0 - filter: blob:none - sparse-checkout-cone-mode: false - sparse-checkout: | - /.github/ - ${{ needs.detect-changes.outputs.copyright_files }} - - - name: Setup Python - uses: actions/setup-python@v6 - with: - python-version: '3.11' - - - name: Install dependencies - run: pip install click==8.2.1 - - - name: Check copyright headers (PR) - if: github.event_name == 'pull_request' + # ── Detect changed files ──────────────────────────────────────── + - name: Detect changed files and verify CI integrity + id: check env: - PR_CODE_FILES: ${{ needs.detect-changes.outputs.copyright_files }} + GH_TOKEN: ${{ github.token }} run: | set -euo pipefail - echo "Running copyright check in PR mode..." - echo "Base SHA: ${{ github.event.pull_request.base.sha }}" - echo "Head SHA: ${{ github.event.pull_request.head.sha }}" + pr="${{ github.event.pull_request.number }}" + repo="${{ github.repository }}" + echo "PR #${pr} ${{ github.event.pull_request.head.repo.full_name }} → ${{ github.event.pull_request.base.repo.full_name }}" + echo "PR_QA_ENABLED_JOBS: ${{ vars.PR_QA_ENABLED_JOBS }}" - pr_code_files="$PR_CODE_FILES" + # Fetch all changed files as "filename TAB status" pairs (paginated) + files=$(gh api "repos/${repo}/pulls/${pr}/files" --paginate \ + --jq '.[] | [.filename, .status] | @tsv') - echo "Relevant files in PR:" - echo "$pr_code_files" + # Verify required CI files are not removed in this PR + required=( + .github/workflows/pr-quality-gates.yml + .github/scripts/check_copyright.py + .github/scripts/copyright-template.txt + .github/scripts/phpmd-ruleset.xml + .github/scripts/tslint.json + .github/scripts/filter-blacklist.sh + ) + missing=false + while IFS=$'\t' read -r filename status; do + [[ "$status" != "removed" ]] && continue + for req in "${required[@]}"; do + if [[ "$filename" == "$req" ]]; then + echo "::error::Required CI file removed: $filename" + missing=true + fi + done + done <<< "$files" + if $missing; then echo "::error::Restore removed CI files before merging."; exit 1; fi - if [ -z "$pr_code_files" ]; then - echo "No code files changed in this PR" - exit 0 - fi + # Categorize files (exclude .github/, vendor/, lib/web/ except lib/web/mage/) + # lib/web/ contains vendored third-party JS/CSS (jQuery, RequireJS, etc.) + # lib/web/mage/ is Adobe-authored JS and is included. + has_php=false; has_js=false; has_static=false; has_ts=false + has_new_files=false; has_copyright_files=false + copyright_files="" + copyright_exts='\.(php|phtml|js|css|scss|less|xml|xsd|html|graphqls)$' + count_new=0; count_modified=0; count_removed=0 + php_list=""; js_list=""; xml_list=""; html_list="" + graphql_list=""; less_list=""; new_php_list=""; copyright_added_list="" + ts_list="" - printf '%s\n' "$pr_code_files" | grep -v '^$' > /tmp/copyright_files.txt - if ! python3 .github/scripts/check_copyright.py \ - --template "${GITHUB_WORKSPACE}/.github/scripts/copyright-template.txt" \ - --file-list /tmp/copyright_files.txt \ - --pr-mode \ - --base-sha "${{ github.event.pull_request.base.sha }}"; then - echo "::error::Some PR files have copyright issues" - exit 1 - fi + while IFS=$'\t' read -r filename status; do + [[ -z "$filename" ]] && continue + [[ "$filename" =~ ^(\.github|vendor)/ ]] && continue + [[ "$filename" =~ ^lib/web/ && ! "$filename" =~ ^lib/web/mage/ ]] && continue + case "$status" in + added) count_new=$((count_new + 1)) ;; + modified|renamed|copied) count_modified=$((count_modified + 1)) ;; + removed) count_removed=$((count_removed + 1)) ;; + esac + [[ "$filename" =~ \.(php|phtml)$ ]] && has_php=true + [[ "$filename" =~ \.js$ && ! "$filename" =~ \.min\.js$ ]] && has_js=true + [[ "$filename" =~ \.(xml|xsd|html|graphqls|less)$ ]] && has_static=true + [[ "$filename" =~ \.ts$ && ! "$filename" =~ \.d\.ts$ ]] && has_ts=true + if [[ "$status" =~ ^(added|modified|renamed|copied)$ ]]; then + [[ "$filename" =~ \.(php|phtml)$ ]] && php_list+="${filename}"$'\n' + [[ "$filename" =~ \.js$ && ! "$filename" =~ \.min\.js$ ]] && js_list+="${filename}"$'\n' + [[ "$filename" =~ \.(xml|xsd)$ ]] && xml_list+="${filename}"$'\n' + [[ "$filename" =~ \.html$ ]] && html_list+="${filename}"$'\n' + [[ "$filename" =~ \.graphqls$ ]] && graphql_list+="${filename}"$'\n' + [[ "$filename" =~ \.less$ ]] && less_list+="${filename}"$'\n' + [[ "$filename" =~ \.php$ && "$status" == "added" ]] && new_php_list+="${filename}"$'\n' + [[ "$filename" =~ \.ts$ && ! "$filename" =~ \.d\.ts$ ]] && ts_list+="${filename}"$'\n' + fi + if [[ "$filename" =~ $copyright_exts && "$status" =~ ^(added|modified|renamed|copied)$ ]]; then + has_copyright_files=true + copyright_files+="${filename}"$'\n' + if [[ "$status" == "added" ]]; then + has_new_files=true + copyright_added_list+="${filename}"$'\n' + fi + fi + done <<< "$files" + copyright_files="${copyright_files%$'\n'}" + # Write file lists for coding-standard checks (avoids git diff in later steps) + [ -n "$php_list" ] && printf '%s' "${php_list%$'\n'}" > /tmp/changed_php.txt + [ -n "$js_list" ] && printf '%s' "${js_list%$'\n'}" > /tmp/changed_js.txt + [ -n "$xml_list" ] && printf '%s' "${xml_list%$'\n'}" > /tmp/changed_xml.txt + [ -n "$html_list" ] && printf '%s' "${html_list%$'\n'}" > /tmp/changed_html.txt + [ -n "$graphql_list" ] && printf '%s' "${graphql_list%$'\n'}" > /tmp/changed_graphqls.txt + [ -n "$less_list" ] && printf '%s' "${less_list%$'\n'}" > /tmp/changed_less.txt + [ -n "$new_php_list" ] && printf '%s' "${new_php_list%$'\n'}" > /tmp/new_php.txt + [ -n "$copyright_files" ] && printf '%s' "$copyright_files" > /tmp/copyright_changed.txt + [ -n "$copyright_added_list" ] && printf '%s' "${copyright_added_list%$'\n'}" > /tmp/copyright_added.txt + [ -n "$ts_list" ] && printf '%s' "${ts_list%$'\n'}" > /tmp/changed_ts.txt - # ────────────────────────────────────────────────────────────────────── - # Job 5: Magento Coding Standard (PHPCS + Rector + ESLint) - # - # Clones magento/magento-coding-standard once and runs all three - # tools from it, matching how the repo's own CI invokes them. - # ────────────────────────────────────────────────────────────────────── - coding-standard: - needs: detect-changes - if: >- - contains(format(',{0},', vars.PR_QA_ENABLED_JOBS), ',coding-standard,') && - github.event_name == 'pull_request' && - ( - needs.detect-changes.outputs.has_php == 'true' || - needs.detect-changes.outputs.has_js == 'true' || - needs.detect-changes.outputs.has_static == 'true' - ) - runs-on: ubuntu-latest - timeout-minutes: 10 - permissions: - contents: read - steps: + echo "has_php=$has_php" >> "$GITHUB_OUTPUT" + echo "has_js=$has_js" >> "$GITHUB_OUTPUT" + echo "has_static=$has_static" >> "$GITHUB_OUTPUT" + echo "has_ts=$has_ts" >> "$GITHUB_OUTPUT" + echo "has_new_files=$has_new_files" >> "$GITHUB_OUTPUT" + echo "has_copyright_files=$has_copyright_files" >> "$GITHUB_OUTPUT" + { + echo "copyright_files<<EOF" + echo "$copyright_files" + echo "EOF" + } >> "$GITHUB_OUTPUT" + + count_total=$((count_new + count_modified + count_removed)) + echo "PHP files changed: $has_php" + echo "JS files changed: $has_js" + echo "Static files changed: $has_static" + echo "TS files changed: $has_ts" + echo "Copyright-eligible files changed: $has_copyright_files" + echo "Files: ${count_total} total | ${count_new} new | ${count_modified} modified | ${count_removed} deleted" + + - name: Set file type env vars + run: | + echo "HAS_PHP=${{ steps.check.outputs.has_php }}" >> "$GITHUB_ENV" + echo "HAS_JS=${{ steps.check.outputs.has_js }}" >> "$GITHUB_ENV" + echo "HAS_STATIC=${{ steps.check.outputs.has_static }}" >> "$GITHUB_ENV" + echo "HAS_TS=${{ steps.check.outputs.has_ts }}" >> "$GITHUB_ENV" + echo "HAS_COPYRIGHT_FILES=${{ steps.check.outputs.has_copyright_files }}" >> "$GITHUB_ENV" + echo "HAS_PHP_OR_STATIC=${{ steps.check.outputs.has_php == 'true' || steps.check.outputs.has_static == 'true' }}" >> "$GITHUB_ENV" + + # ── Coding standard ───────────────────────────────────────────── - uses: actions/checkout@v6 + if: >- + contains(format(',{0},', vars.PR_QA_ENABLED_JOBS), ',coding-standard,') && + (env.HAS_PHP == 'true' || env.HAS_JS == 'true' || env.HAS_STATIC == 'true' || env.HAS_TS == 'true') with: - fetch-depth: 0 + fetch-depth: 1 + filter: blob:none + sparse-checkout: .github + sparse-checkout-cone-mode: true - name: Resolve PHP version from repository composer.json id: php-version + if: env.HAS_PHP_OR_STATIC == 'true' env: REPO_NAME: ${{ github.event.repository.name }} BASE_REF: ${{ github.event.pull_request.base.ref }} run: python3 .github/scripts/resolve_magento_tool_constraints.py - name: Setup PHP + if: env.HAS_PHP_OR_STATIC == 'true' uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # 2.37.0 with: php-version: ${{ steps.php-version.outputs.php_version }} @@ -329,60 +272,62 @@ jobs: extensions: simplexml, dom - name: Setup Node.js - if: needs.detect-changes.outputs.has_js == 'true' + if: env.HAS_JS == 'true' uses: actions/setup-node@v6 with: node-version: '21' - name: Install Magento Coding Standard id: install-mcs + if: >- + contains(format(',{0},', vars.PR_QA_ENABLED_JOBS), ',coding-standard,') && + (env.HAS_PHP == 'true' || env.HAS_JS == 'true' || env.HAS_STATIC == 'true' || env.HAS_TS == 'true') run: | set -euo pipefail - composer create-project --no-interaction --no-progress --stability=dev --remove-vcs magento/magento-coding-standard:dev-develop mcs - cd mcs - - # PHPMD/PHPStan versions: same magento/magento2 composer.json as PHP version - # resolution (quality-patches release → magento2 refs), written by the - # "Resolve PHP version" step to /tmp/magento2-composer.json. - if [ ! -f /tmp/magento2-composer.json ]; then - echo "::error::Missing /tmp/magento2-composer.json — the Resolve PHP version step must run first." - exit 1 - fi - echo "Magento CE composer.json for tool pins (ref: ${{ steps.php-version.outputs.magento_composer_ref }})" - - phpmd_constraint="" - phpstan_constraint="" - for src in \ - "${GITHUB_WORKSPACE}/mcs/composer.json" \ - "/tmp/magento2-composer.json"; do - [ -f "$src" ] || continue - [ -z "$phpmd_constraint" ] && phpmd_constraint="$("${GITHUB_WORKSPACE}/.github/scripts/read-pkg-constraint.sh" "$src" "phpmd/phpmd" || true)" - [ -z "$phpstan_constraint" ] && phpstan_constraint="$("${GITHUB_WORKSPACE}/.github/scripts/read-pkg-constraint.sh" "$src" "phpstan/phpstan" || true)" - [ -n "$phpmd_constraint" ] && [ -n "$phpstan_constraint" ] && break - done - if [ -z "$phpmd_constraint" ] || [ -z "$phpstan_constraint" ]; then - echo "::error::Could not resolve phpmd/phpmd or phpstan/phpstan from mcs/composer.json or /tmp/magento2-composer.json." - exit 1 + if [ "$HAS_PHP_OR_STATIC" = "true" ]; then + composer create-project --no-interaction --no-progress --stability=dev --remove-vcs magento/magento-coding-standard:dev-develop mcs + cd mcs && npm install && cd "${GITHUB_WORKSPACE}" + + echo "PHPCS installed standards:" + mcs/vendor/bin/phpcs -i + + # PHPMD version: same magento/magento2 composer.json as PHP version + # resolution (quality-patches release → magento2 refs), written by the + # "Resolve PHP version" step to /tmp/magento2-composer.json. + if [ ! -f /tmp/magento2-composer.json ]; then + echo "::error::Missing /tmp/magento2-composer.json — the Resolve PHP version step must run first." + exit 1 + fi + echo "Magento CE composer.json for tool pins (ref: ${{ steps.php-version.outputs.magento_composer_ref }})" + + phpmd_constraint="" + for src in \ + "${GITHUB_WORKSPACE}/mcs/composer.json" \ + "/tmp/magento2-composer.json"; do + [ -f "$src" ] || continue + [ -z "$phpmd_constraint" ] && phpmd_constraint="$("${GITHUB_WORKSPACE}/.github/scripts/read-pkg-constraint.sh" "$src" "phpmd/phpmd" || true)" + [ -n "$phpmd_constraint" ] && break + done + + if [ -z "$phpmd_constraint" ]; then + echo "::error::Could not resolve phpmd/phpmd from mcs/composer.json or /tmp/magento2-composer.json." + exit 1 + fi + echo "Resolved phpmd/phpmd constraint: $phpmd_constraint" + + mkdir -p qa-tools + cd qa-tools + composer init --name=local/qa-tools --no-interaction + composer config minimum-stability dev + composer config prefer-stable true + composer require --dev --no-interaction --no-progress --with-all-dependencies \ + "phpmd/phpmd:${phpmd_constraint}" + elif [ "$HAS_JS" = "true" ]; then + git clone --depth 1 --no-tags \ + https://github.com/magento/magento-coding-standard.git mcs + cd mcs && npm install && cd "${GITHUB_WORKSPACE}" fi - echo "Resolved phpmd/phpmd constraint: $phpmd_constraint" - echo "Resolved phpstan/phpstan constraint: $phpstan_constraint" - - npm install - echo "" - echo "PHPCS installed standards:" - vendor/bin/phpcs -i - - cd .. - mkdir -p qa-tools - cd qa-tools - composer init --name=local/qa-tools --no-interaction - composer config minimum-stability dev - composer config prefer-stable true - composer require --dev --no-interaction --no-progress --with-all-dependencies \ - "phpmd/phpmd:${phpmd_constraint}" \ - "phpstan/phpstan:${phpstan_constraint}" \ - sebastian/phpcpd echo "ready=true" >> "$GITHUB_OUTPUT" - name: Resolve enabled checks @@ -398,18 +343,17 @@ jobs: echo ",$ENABLED," | grep -qF ",$check," && echo "true" && return echo "false" } - for check in phpcs phpcs-xml phpcs-html phpcs-graphql phpcs-less phpmd phpstan phpcpd strict-types fixture-reuse rector eslint; do + for check in php-lint phpcs phpcs-xml xml-lint phpcs-html phpcs-graphql phpcs-less phpmd strict-types fixture-reuse eslint typescript; do key="${check//-/_}" echo "${key}=$(is_enabled "$check")" >> "$GITHUB_OUTPUT" done - name: Print resolved tool version map + if: env.HAS_PHP_OR_STATIC == 'true' run: | set -euo pipefail phpmd_mcs="$(.github/scripts/read-pkg-constraint.sh "${GITHUB_WORKSPACE}/mcs/composer.json" "phpmd/phpmd" || true)" - phpstan_mcs="$(.github/scripts/read-pkg-constraint.sh "${GITHUB_WORKSPACE}/mcs/composer.json" "phpstan/phpstan" || true)" phpmd_m2="$(.github/scripts/read-pkg-constraint.sh "/tmp/magento2-composer.json" "phpmd/phpmd" || true)" - phpstan_m2="$(.github/scripts/read-pkg-constraint.sh "/tmp/magento2-composer.json" "phpstan/phpstan" || true)" echo "=== Resolved Tool Version Map ===" echo "repo_name=${{ github.event.repository.name }}" @@ -418,17 +362,15 @@ jobs: echo "php_version=${{ steps.php-version.outputs.php_version }}" echo "phpmd_constraint_from_mcs=${phpmd_mcs:-<missing>}" echo "phpmd_constraint_from_magento2=${phpmd_m2:-<missing>}" - echo "phpstan_constraint_from_mcs=${phpstan_mcs:-<missing>}" - echo "phpstan_constraint_from_magento2=${phpstan_m2:-<missing>}" - name: Fetch Magento static PHPMD framework + if: env.HAS_PHP_OR_STATIC == 'true' run: | set -euo pipefail ref="${{ steps.php-version.outputs.magento_composer_ref }}" if [ -z "$ref" ]; then ref="2.4-develop" fi - target="/tmp/magento2-static" rm -rf "$target" git clone --depth 1 --filter=blob:none --sparse \ @@ -439,66 +381,71 @@ jobs: git sparse-checkout set \ dev/tests/static/framework \ dev/tests/static/testsuite/Magento/Test/Php/_files/phpmd \ - dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist \ - dev/tests/static/testsuite/Magento/Test/Php/_files/phpstan/blacklist \ lib/internal/Magento/Framework echo "Fetched Magento static PHPMD framework from ref: $ref" - - name: Get changed files + - name: Checkout changed files and fetch base commit id: files + if: steps.install-mcs.outputs.ready == 'true' run: | set -euo pipefail - base_ref="${{ github.event.pull_request.base.ref }}" base_sha="${{ github.event.pull_request.base.sha }}" - head_sha="${{ github.event.pull_request.head.sha }}" - pr_number="${{ github.event.pull_request.number }}" + echo "base_sha=$base_sha" >> "$GITHUB_ENV" + git fetch --filter=blob:none --depth=1 origin "$base_sha" 2>/dev/null || true + + # Deduplicate across all file lists so each blob is fetched exactly once. + # Use `cat "$f"; echo` to ensure a newline after each file's content — + # without it, the last entry of one list concatenates with the first of the next. + all_files=$(mktemp) + for f in /tmp/changed_php.txt /tmp/changed_js.txt /tmp/changed_xml.txt \ + /tmp/changed_html.txt /tmp/changed_graphqls.txt /tmp/changed_less.txt \ + /tmp/changed_ts.txt /tmp/copyright_changed.txt; do + [ -f "$f" ] || continue + cat "$f"; echo + done | sort -u | grep -v '^$' > "$all_files" + + checked_out=0 + while IFS= read -r file; do + [ -n "$file" ] || continue + tmp=$(mktemp) + if git show "HEAD:${file}" > "$tmp" 2>/dev/null; then + mkdir -p "$(dirname "$file")" + mv "$tmp" "$file" + checked_out=$((checked_out + 1)) + else + rm -f "$tmp" + echo "::warning::Could not fetch $file from HEAD (not at HEAD — removed in PR?)" + fi + done < "$all_files" + rm -f "$all_files" + echo "Checked out ${checked_out} changed file(s)." - if ! git cat-file -e "${base_sha}^{commit}" 2>/dev/null; then - git fetch origin "$base_ref" || true - base_sha="origin/$base_ref" - fi + # ── PHP syntax lint ─────────────────────────────────────────── - if ! git cat-file -e "${head_sha}^{commit}" 2>/dev/null; then - git fetch origin "pull/${pr_number}/head:pr-${pr_number}-head" || true - if git rev-parse --verify -q "pr-${pr_number}-head" >/dev/null; then - head_sha="pr-${pr_number}-head" + - name: PHP syntax lint + id: php-lint + if: always() && steps.gate.outputs.php_lint == 'true' && env.HAS_PHP == 'true' + run: | + set -euo pipefail + errors=0 + while IFS= read -r file; do + [ -n "$file" ] || continue + if ! php -l "$file" 2>&1; then + errors=$((errors + 1)) fi + done < /tmp/changed_php.txt + if [ "$errors" -gt 0 ]; then + echo "::error::${errors} file(s) have PHP parse errors" + exit 1 fi - - changed=$(git diff --name-only --diff-filter=ACMRT "$base_sha...$head_sha" \ - | grep -vE '^(\.github|vendor|lib/web)/' || true) - added=$(git diff --name-only --diff-filter=A "$base_sha...$head_sha" \ - | grep -vE '^(\.github|vendor|lib/web)/' || true) - - php_files=$(echo "$changed" | grep -E '\.(php|phtml)$' || true) - js_files=$(echo "$changed" | grep -E '\.js$' | grep -v '\.min\.js$' || true) - xml_files=$(echo "$changed" | grep -E '\.(xml|xsd)$' || true) - html_files=$(echo "$changed" | grep -E '\.html$' || true) - graphql_files=$(echo "$changed" | grep -E '\.graphqls$' || true) - less_files=$(echo "$changed" | grep -E '\.less$' || true) - new_php=$(echo "$added" | grep -E '\.php$' || true) - - [ -n "$php_files" ] && echo "$php_files" > /tmp/changed_php.txt - [ -n "$js_files" ] && echo "$js_files" > /tmp/changed_js.txt - [ -n "$xml_files" ] && echo "$xml_files" > /tmp/changed_xml.txt - [ -n "$html_files" ] && echo "$html_files" > /tmp/changed_html.txt - [ -n "$graphql_files" ] && echo "$graphql_files" > /tmp/changed_graphqls.txt - [ -n "$less_files" ] && echo "$less_files" > /tmp/changed_less.txt - [ -n "$new_php" ] && echo "$new_php" > /tmp/new_php.txt - - echo "PHP files: $(echo "$php_files" | grep -c . || echo 0)" - echo "JS files: $(echo "$js_files" | grep -c . || echo 0)" - echo "XML/XSD files: $(echo "$xml_files" | grep -c . || echo 0)" - echo "HTML files: $(echo "$html_files" | grep -c . || echo 0)" - echo "GraphQL schema files: $(echo "$graphql_files" | grep -c . || echo 0)" - echo "LESS files: $(echo "$less_files" | grep -c . || echo 0)" - echo "New PHP files: $(echo "$new_php" | grep -c . || echo 0)" + echo "All PHP files passed syntax check." # ── PHPCS ───────────────────────────────────────────────────── - name: Run PHPCS - if: always() && steps.gate.outputs.phpcs == 'true' && needs.detect-changes.outputs.has_php == 'true' + id: phpcs + if: always() && steps.gate.outputs.phpcs == 'true' && env.HAS_PHP == 'true' run: | set -euo pipefail # Exclude Legacy sniffs that parse XML or load external data @@ -514,36 +461,58 @@ jobs: EXCLUDE="$EXCLUDE,Magento2.Legacy.RestrictedCode" .github/scripts/run-phpcs.sh "PHP" /tmp/changed_php.txt "--exclude=$EXCLUDE" + - name: XML well-formedness lint + id: xml-lint + if: always() && steps.gate.outputs.xml_lint == 'true' && env.HAS_STATIC == 'true' + run: | + set -euo pipefail + sudo apt-get install -y -q libxml2-utils 2>/dev/null + errors=0 + while IFS= read -r file; do + [ -n "$file" ] || continue + if ! xmllint --noout "$file" 2>&1; then + errors=$((errors + 1)) + fi + done < /tmp/changed_xml.txt + if [ "$errors" -gt 0 ]; then + echo "::error::${errors} XML/XSD file(s) are not well-formed" + exit 1 + fi + echo "All XML/XSD files are well-formed." + - name: Run PHPCS for XML/XSD - if: always() && steps.gate.outputs.phpcs_xml == 'true' && needs.detect-changes.outputs.has_static == 'true' + id: phpcs-xml + if: always() && steps.gate.outputs.phpcs_xml == 'true' && env.HAS_STATIC == 'true' run: | set -euo pipefail .github/scripts/run-phpcs.sh "XML/XSD" /tmp/changed_xml.txt "--extensions=xml,xsd" - name: Run PHPCS for HTML - if: always() && steps.gate.outputs.phpcs_html == 'true' && needs.detect-changes.outputs.has_static == 'true' + id: phpcs-html + if: always() && steps.gate.outputs.phpcs_html == 'true' && env.HAS_STATIC == 'true' run: | set -euo pipefail .github/scripts/run-phpcs.sh "HTML" /tmp/changed_html.txt - name: Run PHPCS for GraphQL - if: always() && steps.gate.outputs.phpcs_graphql == 'true' && needs.detect-changes.outputs.has_static == 'true' + id: phpcs-graphql + if: always() && steps.gate.outputs.phpcs_graphql == 'true' && env.HAS_STATIC == 'true' run: | set -euo pipefail .github/scripts/run-phpcs.sh "GraphQL schema" /tmp/changed_graphqls.txt - name: Run PHPCS for LESS - if: always() && steps.gate.outputs.phpcs_less == 'true' && needs.detect-changes.outputs.has_static == 'true' + id: phpcs-less + if: always() && steps.gate.outputs.phpcs_less == 'true' && env.HAS_STATIC == 'true' run: | set -euo pipefail .github/scripts/run-phpcs.sh "LESS" /tmp/changed_less.txt - # ── Rector ──────────────────────────────────────────────────── - # ── PHPMD ──────────────────────────────────────────────────── - name: Run PHPMD - if: always() && steps.gate.outputs.phpmd == 'true' && needs.detect-changes.outputs.has_php == 'true' + id: phpmd + if: always() && steps.gate.outputs.phpmd == 'true' && env.HAS_PHP == 'true' run: | set -euo pipefail if [ ! -f /tmp/changed_php.txt ] || [ ! -s /tmp/changed_php.txt ]; then @@ -551,31 +520,23 @@ jobs: exit 0 fi phpmd_bin="${GITHUB_WORKSPACE}/qa-tools/vendor/bin/phpmd" - ruleset="/tmp/magento2-static/dev/tests/static/testsuite/Magento/Test/Php/_files/phpmd/ruleset.xml" + magento_ruleset="/tmp/magento2-static/dev/tests/static/testsuite/Magento/Test/Php/_files/phpmd/ruleset.xml" prepend_file="/tmp/magento2-static/phpmd-prepend.php" - if [ ! -f "$ruleset" ]; then - echo "Magento ruleset not available, falling back to local standalone ruleset." - ruleset="${GITHUB_WORKSPACE}/.github/scripts/phpmd-ruleset.xml" - else - else - # Wrap the primary ruleset to exclude rules that require the full - # vendor tree (Laminas etc.) and crash in the sparse-clone environment. - wrapper="/tmp/phpmd-ruleset-ci.xml" - cat > "$wrapper" <<XML - <?xml version="1.0" encoding="UTF-8"?> - <ruleset name="Magento PHPMD (CI)" xmlns="http://pmd.sf.net/ruleset/1.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"> - <description>Magento PHPMD rules, excluding rules that require the full vendor tree.</description> - <rule ref="${ruleset}"> - <exclude name="CookieAndSessionMisuse"/> - <exclude name="AllPurposeAction"/> - </rule> - </ruleset> - XML - ruleset="$wrapper" - fi - fi + # Wrap the Magento ruleset to exclude rules that require the full + # vendor tree (Laminas etc.) and crash in the sparse-clone environment. + ruleset="/tmp/phpmd-ruleset-ci.xml" + { + printf '<?xml version="1.0" encoding="UTF-8"?>\n' + printf '<ruleset name="Magento PHPMD (CI)" xmlns="http://pmd.sf.net/ruleset/1.0.0"\n' + printf ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n' + printf ' xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd">\n' + printf ' <description>Magento PHPMD rules, excluding rules that require the full vendor tree.</description>\n' + printf ' <rule ref="%s">\n' "$magento_ruleset" + printf ' <exclude name="CookieAndSessionMisuse"/>\n' + printf ' <exclude name="AllPurposeAction"/>\n' + printf ' </rule>\n' + printf '</ruleset>\n' + } > "$ruleset" cat > "$prepend_file" <<'PHP' <?php $root = '/tmp/magento2-static'; @@ -606,105 +567,43 @@ jobs: phpmd_symfony=true fi + phpmd_exit=0 batch_size=20 for ((i=0; i<${#files[@]}; i+=batch_size)); do batch_files=("${files[@]:i:batch_size}") batch_list=$(printf "%s," "${batch_files[@]}" | sed 's/,*$//') if [ "$phpmd_symfony" = true ]; then - php -d auto_prepend_file="$prepend_file" "$phpmd_bin" analyze "${batch_files[@]}" \ + timeout 120 php -d auto_prepend_file="$prepend_file" -d memory_limit=512M \ + "$phpmd_bin" analyze "${batch_files[@]}" \ --format=text \ --ruleset="$ruleset" \ --suffixes=php --suffixes=phtml \ - --no-progress || exit $? + --no-progress 2>/dev/null || phpmd_exit=$? else - php -d auto_prepend_file="$prepend_file" "$phpmd_bin" \ + timeout 120 php -d auto_prepend_file="$prepend_file" -d memory_limit=512M \ + "$phpmd_bin" \ "$batch_list" \ text \ "$ruleset" \ - --suffixes=php,phtml || exit $? + --suffixes=php,phtml 2>/dev/null || phpmd_exit=$? fi + [ "$phpmd_exit" -ne 0 ] && break done - - # ── PHPStan ────────────────────────────────────────────────── - - - name: Generate Magento stubs for PHPStan - if: always() && steps.gate.outputs.phpstan == 'true' && needs.detect-changes.outputs.has_php == 'true' - run: | - set -euo pipefail - if [ ! -f /tmp/changed_php.txt ] || [ ! -s /tmp/changed_php.txt ]; then - echo "No PHP files to check, skipping phpstan." - exit 0 - fi - bash .github/scripts/generate-stubs.sh /tmp/changed_php.txt - - - name: Run PHPStan - if: always() && steps.gate.outputs.phpstan == 'true' && needs.detect-changes.outputs.has_php == 'true' - run: | - set -euo pipefail - if [ ! -f /tmp/changed_php.txt ] || [ ! -s /tmp/changed_php.txt ]; then - echo "No PHP files to check, skipping phpstan." - exit 0 - fi - - blacklist_dir="/tmp/magento2-static/dev/tests/static/testsuite/Magento/Test/Php/_files/phpstan/blacklist" - mapfile -t files_to_scan < <(.github/scripts/filter-blacklist.sh "$blacklist_dir" /tmp/changed_php.txt "PHPStan") - - if [ "${#files_to_scan[@]}" -eq 0 ]; then - echo "No PHP files to analyze after blacklist filtering." - exit 0 - fi - - # When the CE sparse clone is present, use phpstan-extensions.neon which - # extends the base config with DataObjectClassReflectionExtension and - # FilteredErrorFormatter. The extension classes are loaded via - # --autoload-file, which PHPStan processes before building its DI - # container (unlike bootstrapFiles, which run after container build). - # When the sparse clone is absent, fall back to the base neon and the - # plain table formatter — extensions are simply not registered. - ext_class="/tmp/magento2-static/dev/tests/static/framework/Magento/PhpStan/Reflection/Php/DataObjectClassReflectionExtension.php" - fmt_class="/tmp/magento2-static/dev/tests/static/framework/Magento/PhpStan/Formatters/FilteredErrorFormatter.php" - - if [ -f "$ext_class" ] && [ -f "$fmt_class" ]; then - phpstan_neon="${GITHUB_WORKSPACE}/.github/scripts/phpstan-extensions.neon" - autoload_flag="--autoload-file=${GITHUB_WORKSPACE}/.github/scripts/phpstan-framework-autoload.php" - error_format="filtered" - else - phpstan_neon="${GITHUB_WORKSPACE}/.github/scripts/phpstan.neon" - autoload_flag="" - error_format="table" - fi - - "${GITHUB_WORKSPACE}/qa-tools/vendor/bin/phpstan" analyse \ - $autoload_flag \ - --configuration="$phpstan_neon" \ - --no-progress \ - --error-format="$error_format" \ - "${files_to_scan[@]}" - - # ── PHPCPD ──────────────────────────────────────────────────── - - - name: Run PHPCPD (Copy/Paste Detector) - if: always() && steps.gate.outputs.phpcpd == 'true' && needs.detect-changes.outputs.has_php == 'true' - run: | - set -euo pipefail - if [ ! -f /tmp/changed_php.txt ] || [ ! -s /tmp/changed_php.txt ]; then - echo "No PHP files to check, skipping phpcpd." - exit 0 + if [ "$phpmd_exit" -eq 124 ]; then + echo "::error::PHPMD batch timed out (120 s). The PR may have too many complex files for a single batch. Consider splitting the PR." + exit 1 fi - blacklist_dir="/tmp/magento2-static/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist" - mapfile -t files_to_scan < <(.github/scripts/filter-blacklist.sh "$blacklist_dir" /tmp/changed_php.txt "PHPCPD") - - if [ "${#files_to_scan[@]}" -eq 0 ]; then - echo "No PHP files left for PHPCPD after blacklist filtering." - exit 0 + if [ "$phpmd_exit" -eq 143 ]; then + echo "::error::PHPMD was terminated by SIGTERM (exit 143). Possible cause: OOM or job timeout on a large PR." + exit 1 fi - - "${GITHUB_WORKSPACE}/qa-tools/vendor/bin/phpcpd" "${files_to_scan[@]}" + exit "$phpmd_exit" # ── strict_types ────────────────────────────────────────────── - name: Check strict_types declaration - if: always() && steps.gate.outputs.strict_types == 'true' && needs.detect-changes.outputs.has_php == 'true' + id: strict-types + if: always() && steps.gate.outputs.strict_types == 'true' && env.HAS_PHP == 'true' run: | set -euo pipefail if [ ! -s /tmp/new_php.txt ]; then @@ -729,7 +628,8 @@ jobs: echo "All new PHP files have strict_types declaration." - name: Check fixture reuse (static parity) - if: always() && steps.gate.outputs.fixture_reuse == 'true' && needs.detect-changes.outputs.has_php == 'true' + id: fixture-reuse + if: always() && steps.gate.outputs.fixture_reuse == 'true' && env.HAS_PHP == 'true' run: | set -euo pipefail if [ ! -f /tmp/changed_php.txt ] || [ ! -s /tmp/changed_php.txt ]; then @@ -757,41 +657,40 @@ jobs: fi echo "Fixture reuse check passed." - # ── Rector ──────────────────────────────────────────────────── + # ── Copyright headers ───────────────────────────────────────── - - name: Run Rector - if: always() && steps.gate.outputs.rector == 'true' && needs.detect-changes.outputs.has_php == 'true' - env: - RECTOR_PHP_VERSION: ${{ steps.php-version.outputs.php_version }} + - name: Check copyright headers + id: copyright + if: always() && steps.install-mcs.outputs.ready == 'true' && env.HAS_COPYRIGHT_FILES == 'true' run: | set -euo pipefail - if [ ! -f /tmp/changed_php.txt ] || [ ! -s /tmp/changed_php.txt ]; then - echo "No PHP files to check, skipping rector." + if [ ! -f /tmp/copyright_changed.txt ] || [ ! -s /tmp/copyright_changed.txt ]; then + echo "No copyright-eligible files — skipping." exit 0 fi - file_args=() - while IFS= read -r file; do - [ -n "$file" ] && [ -f "$file" ] && file_args+=("$GITHUB_WORKSPACE/$file") - done < /tmp/changed_php.txt + # Pre-fetch base versions so the PHP script needs no shell execution + mkdir -p /tmp/copyright_base + while IFS= read -r f; do + [ -z "$f" ] && continue + mkdir -p "/tmp/copyright_base/$(dirname "$f")" + git show "${base_sha}:${f}" > "/tmp/copyright_base/${f}" 2>/dev/null || true + done < /tmp/copyright_changed.txt - if [ ${#file_args[@]} -eq 0 ]; then - echo "No PHP files to check." - exit 0 - fi + added_flag="" + [ -f /tmp/copyright_added.txt ] && added_flag="--added /tmp/copyright_added.txt" - cd mcs - vendor/bin/rector process \ - --config "$GITHUB_WORKSPACE/.github/scripts/rector-compat.php" \ - --dry-run \ - --autoload-file vendor/squizlabs/php_codesniffer/autoload.php \ - --autoload-file vendor/magento/php-compatibility-fork/PHPCSAliases.php \ - "${file_args[@]}" + php .github/scripts/check_copyright_pr.php \ + --files /tmp/copyright_changed.txt \ + $added_flag \ + --base-dir /tmp/copyright_base \ + --template "${GITHUB_WORKSPACE}/.github/scripts/copyright-template.txt" # ── ESLint ──────────────────────────────────────────────────── - name: Run ESLint - if: always() && steps.gate.outputs.eslint == 'true' && needs.detect-changes.outputs.has_js == 'true' + id: eslint + if: always() && steps.gate.outputs.eslint == 'true' && env.HAS_JS == 'true' run: | set -euo pipefail mapfile -t js_args < /tmp/changed_js.txt @@ -800,77 +699,73 @@ jobs: -c mcs/eslint/eslint.config.mjs \ "${js_args[@]}" - - name: Validate generated XML test reports are non-empty - if: always() + # ── TypeScript ──────────────────────────────────────────────── + + - name: Run TypeScript checks + id: typescript + if: always() && steps.gate.outputs.typescript == 'true' && env.HAS_TS == 'true' run: | set -euo pipefail - report_dir="${GITHUB_WORKSPACE}/build/test-reports" - if [ ! -d "$report_dir" ]; then - echo "No build/test-reports directory found; skipping XML report size check." - exit 0 + npm install --prefix /tmp/ts-tools typescript tslint 2>/dev/null + TSC=/tmp/ts-tools/node_modules/.bin/tsc + TSLINT=/tmp/ts-tools/node_modules/.bin/tslint + + mapfile -t ts_files < /tmp/changed_ts.txt + + # Fetch tslint.json from HEAD if present (compiler options only — do not use + # tsconfig.json include paths, which would try to compile the full project tree) + _tmp=$(mktemp) + if git show "HEAD:tslint.json" > "$_tmp" 2>/dev/null && [ -s "$_tmp" ]; then + mv "$_tmp" tslint.json + echo "Using repo tslint.json" + else + rm -f "$_tmp" + cp .github/scripts/tslint.json tslint.json + echo "Using bundled .github/scripts/tslint.json (repo has no tslint.json)" fi - shopt -s nullglob - xml_reports=("$report_dir"/*.xml) - shopt -u nullglob + tslint_exit=0 + tsc_exit=0 - if [ "${#xml_reports[@]}" -eq 0 ]; then - echo "No XML reports found in $report_dir; skipping XML report size check." - exit 0 - fi + # tslint — mirrors npm run test:static:log + "$TSLINT" --format stylish "${ts_files[@]}" || tslint_exit=$? - has_empty=0 - for report in "${xml_reports[@]}"; do - if [ ! -s "$report" ]; then - echo "::error::Test report file is empty: $report" - has_empty=1 - fi - done + # tsc --noEmit --noResolve — mirrors npm run test:errors:log + # --noResolve skips import resolution so only the changed files are needed + "$TSC" --noEmit --noResolve --allowSyntheticDefaultImports \ + --esModuleInterop --strict --target ES2020 \ + "${ts_files[@]}" || tsc_exit=$? - if [ "$has_empty" -ne 0 ]; then - echo "::error::One or more XML test report files are empty. This often means tests failed before writing JUnit output." - exit 1 - fi - echo "All discovered XML test reports are non-empty." + [ "$tslint_exit" -gt 0 ] || [ "$tsc_exit" -gt 0 ] && exit 1 || true + + - name: Coding standard results summary + if: always() && steps.install-mcs.outputs.ready == 'true' + run: | + { + echo "## Coding Standard Results" + echo "| Check | Status |" + echo "|-------|--------|" + echo "| PHP syntax lint | ${{ steps.php-lint.outcome == 'success' && '✅' || steps.php-lint.outcome == 'skipped' && '⏭️' || '❌' }} |" + echo "| PHPCS PHP | ${{ steps.phpcs.outcome == 'success' && '✅' || steps.phpcs.outcome == 'skipped' && '⏭️' || '❌' }} |" + echo "| XML lint | ${{ steps.xml-lint.outcome == 'success' && '✅' || steps.xml-lint.outcome == 'skipped' && '⏭️' || '❌' }} |" + echo "| PHPCS XML/XSD | ${{ steps.phpcs-xml.outcome == 'success' && '✅' || steps.phpcs-xml.outcome == 'skipped' && '⏭️' || '❌' }} |" + echo "| PHPCS HTML | ${{ steps.phpcs-html.outcome == 'success' && '✅' || steps.phpcs-html.outcome == 'skipped' && '⏭️' || '❌' }} |" + echo "| PHPCS GraphQL | ${{ steps.phpcs-graphql.outcome == 'success' && '✅' || steps.phpcs-graphql.outcome == 'skipped' && '⏭️' || '❌' }} |" + echo "| PHPCS LESS | ${{ steps.phpcs-less.outcome == 'success' && '✅' || steps.phpcs-less.outcome == 'skipped' && '⏭️' || '❌' }} |" + echo "| PHPMD | ${{ steps.phpmd.outcome == 'success' && '✅' || steps.phpmd.outcome == 'skipped' && '⏭️' || '❌' }} |" + echo "| Strict types | ${{ steps.strict-types.outcome == 'success' && '✅' || steps.strict-types.outcome == 'skipped' && '⏭️' || '❌' }} |" + echo "| Fixture reuse | ${{ steps.fixture-reuse.outcome == 'success' && '✅' || steps.fixture-reuse.outcome == 'skipped' && '⏭️' || '❌' }} |" + echo "| Copyright | ${{ steps.copyright.outcome == 'success' && '✅' || steps.copyright.outcome == 'skipped' && '⏭️' || '❌' }} |" + echo "| ESLint | ${{ steps.eslint.outcome == 'success' && '✅' || steps.eslint.outcome == 'skipped' && '⏭️' || '❌' }} |" + echo "| TypeScript | ${{ steps.typescript.outcome == 'success' && '✅' || steps.typescript.outcome == 'skipped' && '⏭️' || '❌' }} |" + } >> "$GITHUB_STEP_SUMMARY" + + # ── Linked PR aggregate gate ──────────────────────────────────── - # ────────────────────────────────────────────────────────────────────── - # Final Job: Linked PR Aggregate Gate - # - # Runs after all PR quality jobs finish and validates linked PRs listed - # in the PR description (Related PRs area). - # ────────────────────────────────────────────────────────────────────── - aggregate-linked-pr-checks: - needs: - - detect-changes - - mainline-alignment - - copyright-check - - coding-standard - if: >- - contains(format(',{0},', vars.PR_QA_ENABLED_JOBS), ',aggregate-linked-pr-checks,') && - always() && - github.event_name == 'pull_request' && - contains(fromJSON('["success","failure"]'), needs.detect-changes.result) && - contains(fromJSON('["success","failure"]'), needs.mainline-alignment.result) && - contains(fromJSON('["success","failure","skipped"]'), needs.copyright-check.result) && - contains(fromJSON('["success","failure","skipped"]'), needs.coding-standard.result) && - vars.PR_QA_ENABLED_JOBS != '' - runs-on: ubuntu-latest - timeout-minutes: 5 - env: - CROSS_REPO_READ_TOKEN: ${{ secrets.CROSS_REPO_READ_TOKEN }} - permissions: - contents: read - pull-requests: read - checks: read - statuses: read - steps: - name: Debug aggregate gate context + if: always() && contains(format(',{0},', vars.PR_QA_ENABLED_JOBS), ',aggregate-linked-pr-checks,') run: | set -euo pipefail - echo "detect-changes=${{ needs.detect-changes.result }}" - echo "mainline-alignment=${{ needs.mainline-alignment.result }}" - echo "copyright-check=${{ needs.copyright-check.result }}" - echo "coding-standard=${{ needs.coding-standard.result }}" echo "PR_QA_ENABLED_JOBS='${{ vars.PR_QA_ENABLED_JOBS }}'" if [ -n "${CROSS_REPO_READ_TOKEN}" ]; then echo "CROSS_REPO_READ_TOKEN=present" @@ -879,14 +774,14 @@ jobs: fi - name: Skip if cross-repo token is missing - if: ${{ env.CROSS_REPO_READ_TOKEN == '' }} + if: always() && contains(format(',{0},', vars.PR_QA_ENABLED_JOBS), ',aggregate-linked-pr-checks,') && env.CROSS_REPO_READ_TOKEN == '' run: | set -euo pipefail echo "CROSS_REPO_READ_TOKEN is not set. Skipping aggregate-linked-pr-checks." exit 0 - name: Validate linked PR checks - if: ${{ env.CROSS_REPO_READ_TOKEN != '' }} + if: always() && contains(format(',{0},', vars.PR_QA_ENABLED_JOBS), ',aggregate-linked-pr-checks,') && env.CROSS_REPO_READ_TOKEN != '' uses: actions/github-script@v9 with: github-token: ${{ env.CROSS_REPO_READ_TOKEN }} From 6204230efc7b09a27eaa7e87723c7eea0ef4a2c1 Mon Sep 17 00:00:00 2001 From: Alexandra Zota <zota@adobe.com> Date: Thu, 21 May 2026 16:41:54 +0300 Subject: [PATCH 45/83] ACP2E-4947: PR Quality Gates bugfixes and improvements 2 --- .github/scripts/check_copyright.py | 860 ------------------ .github/scripts/generate-stubs.sh | 117 --- .github/scripts/phpstan-extensions.neon | 17 - .../scripts/phpstan-framework-autoload.php | 39 - .github/scripts/phpstan.neon | 69 -- .github/scripts/rector-compat.php | 48 - .github/workflows/pr-quality-gates.yml | 1 - 7 files changed, 1151 deletions(-) delete mode 100644 .github/scripts/check_copyright.py delete mode 100755 .github/scripts/generate-stubs.sh delete mode 100644 .github/scripts/phpstan-extensions.neon delete mode 100644 .github/scripts/phpstan-framework-autoload.php delete mode 100644 .github/scripts/phpstan.neon delete mode 100644 .github/scripts/rector-compat.php diff --git a/.github/scripts/check_copyright.py b/.github/scripts/check_copyright.py deleted file mode 100644 index d75d936792a2..000000000000 --- a/.github/scripts/check_copyright.py +++ /dev/null @@ -1,860 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright 2026 Adobe -# All Rights Reserved. -# -# .github/scripts/check_copyright.py - Magento Copyright Header Checker - -import os -import sys -import re -import click -from pathlib import Path -from typing import List, Tuple -from datetime import datetime -import subprocess - -def _resolve_git_root() -> str: - result = subprocess.run( - ['git', 'rev-parse', '--show-toplevel'], - capture_output=True, text=True, check=False - ) - return result.stdout.strip() if result.returncode == 0 else '.' - -_GIT_ROOT = _resolve_git_root() - -# File extensions and their comment styles. -# Aligned with the PHP update_copyrights.php updater which supports: -# PHP, PHTML, HTML, JS, XML, XSD, CSS, LESS -COMMENT_STYLES = { - # PHP files - '.php': ('<?php\n/**\n * ', ' * ', ' */\n'), - '.phtml': ('<?php\n/**\n * ', ' * ', ' */\n?>\n'), - - # Frontend files - '.js': ('/**\n * ', ' * ', ' */\n'), - '.css': ('/**\n * ', ' * ', ' */\n'), - '.less': ('/**\n * ', ' * ', ' */\n'), - '.scss': ('/**\n * ', ' * ', ' */\n'), - - # Configuration files - '.xml': ('<?xml version="1.0"?>\n<!--\n', ' * ', '\n-->\n'), - '.xsd': ('<?xml version="1.0"?>\n<!--\n', ' * ', '\n-->\n'), - - # GraphQL schema files - '.graphqls': ('# ', '# ', '\n'), - - # Markup files - '.html': ('<!--\n', ' * ', '\n-->'), -} - -# Magento-specific exclusion patterns -MAGENTO_EXCLUSIONS = { - 'vendor', # Composer dependencies - 'var', # Cache and temporary files - 'generated', # Auto-generated code - 'pub/static', # Generated static files - 'pub/media', # Media files - # dev/tests is intentionally NOT excluded — Magento test files under - # dev/tests/*/testsuite/ do need copyright headers. - 'lib/web', # Third-party web libraries - 'app/etc', # Configuration files - 'setup/src/Magento/Setup/Fixtures', # Setup fixtures - 'node_modules', # Node.js dependencies - '.git', # Git files - 'phpserver', # PHP server files - 'grunt', # Grunt files - 'dev/tools', # Development tools - 'dev/build', # Build files - 'update', # Update files - 'bin', # Binary files -} - -# Magento module structure patterns -MAGENTO_MODULE_PATTERNS = [ - r'app/code/[^/]+/[^/]+/', # app/code/Vendor/Module/ - r'app/design/[^/]+/[^/]+/[^/]+/', # app/design/area/vendor/theme/ -] - - -def _normalize_copyright(text: str) -> str: - """Normalize copyright text for flexible comparison. - - Strips all comment markers, whitespace and punctuation that varies - between file types, matching the approach used by the Jenkins - SanityCopyrightChecker. - """ - # Strip XML processing instructions entirely so encoding/version attribute - # differences (e.g. encoding="UTF-8" vs absent) do not affect comparison. - text = re.sub(r'<\?xml[^?]*\?>', '', text) - # Strip PHP declare() so '<?php declare(strict_types=1)' and '<?php' - # normalize identically. - text = re.sub(r'\bdeclare\s*\([^)]*\)\s*;?', '', text) - return re.sub(r'[\s#/\*\-<>!?\[\]]+', '', text).lower() - - - -def _is_third_party_file(file_path: str, content: str) -> bool: - """Detect third-party files that should skip copyright validation. - - Matches the Jenkins SanityCopyrightChecker logic: if neither the file - path nor its content mentions 'Magento' or 'Adobe', it is assumed to be - a third-party library file. Checking the path ensures that files inside - Magento module directories (app/code/Magento/...) are never skipped even - when the file content itself contains no such references. - """ - return ('Magento' not in file_path and 'Adobe' not in file_path - and 'Magento' not in content and 'Adobe' not in content) - - -def get_git_creation_year(file_path: str, debug: bool = False, use_current_year: bool = False, - base_sha: str = '') -> int: - """Get the year when file was first added to git.""" - - # In PR mode, check whether the file existed in the base commit. - # git cat-file -e is a single object lookup — no history traversal. - # git status --porcelain only catches unstaged/untracked files, which is - # never the case on CI where the PR branch is already checked out clean. - if use_current_year and base_sha: - try: - result = subprocess.run( - ['git', 'cat-file', '-e', f'{base_sha}:{file_path}'], - capture_output=True, cwd=_GIT_ROOT - ) - if result.returncode != 0: - # File did not exist in base — it is new in this PR. - current_year = datetime.now().year - if debug: - click.echo(f" New file (not in base {base_sha[:8]}): using year {current_year}") - return current_year - if debug: - click.echo(f" File exists in base {base_sha[:8]}: finding original creation year") - except Exception: - pass - - if debug: - click.echo(f" Finding git creation year for: {file_path}") - - # Primary: follow renames; fallback: without --follow if rename chain fails - git_commands = [ - ['git', 'log', '--follow', '--format=%ad', '--date=format:%Y', '--reverse', '--', file_path], - ['git', 'log', '--format=%ad', '--date=format:%Y', '--reverse', '--', file_path], - ] - - for i, cmd in enumerate(git_commands): - try: - if debug: - click.echo(f" Trying command {i+1}: {' '.join(cmd)}") - - result = subprocess.run(cmd, capture_output=True, text=True, cwd=_GIT_ROOT) - - if result.returncode == 0 and result.stdout.strip(): - years = result.stdout.strip().split('\n') - if years and years[0]: - first_year = int(years[0]) - if debug: - click.echo(f" Found git creation year: {first_year}") - return first_year - except (subprocess.CalledProcessError, ValueError, IndexError) as e: - if debug: - click.echo(f" Command {i+1} failed: {e}") - continue - - # Fallback to file modification time - try: - stat = os.stat(file_path) - fallback_year = datetime.fromtimestamp(stat.st_mtime).year - if debug: - click.echo(f" Using file modification time fallback: {fallback_year}") - return fallback_year - except Exception: - pass - - current_year = datetime.now().year - if debug: - click.echo(f" Using current year fallback: {current_year}") - return current_year - - -def load_template(template_path: str) -> str: - """Load the copyright template.""" - try: - with open(template_path, 'r', encoding='utf-8') as f: - return f.read().strip() - except FileNotFoundError: - click.echo(f"Template file not found: {template_path}", err=True) - sys.exit(1) - - -def format_copyright_header(template: str, file_path: str, comment_style: Tuple[str, str, str], - year: str, debug: bool = False) -> str: - """Format copyright header for specific file type using the given year.""" - start_comment, line_comment, end_comment = comment_style - - formatted_template = template.replace('{{YEAR}}', year) - - if debug: - click.echo(f" File: {file_path} -> Year: {year}") - - file_ext = Path(file_path).suffix.lower() - - # If template already contains proper comment format (like Adobe templates), use as-is - if formatted_template.strip().startswith('/**') and formatted_template.strip().endswith('*/'): - if file_ext == '.php': - return f"<?php\n{formatted_template}\n" - elif file_ext == '.phtml': - return f"<?php\n{formatted_template}\n?>\n" - elif file_ext in ['.xml', '.xsd']: - content = formatted_template.strip()[3:-2].strip() - lines = content.split('\n') - result = ['<?xml version="1.0"?>', '<!--'] - for line in lines: - line = line.strip() - if line.startswith('*'): - line = line[1:].strip() - if line: - result.append(f' * {line}') - else: - result.append(' *') - result.append(' -->') - return '\n'.join(result) + '\n' - elif file_ext == '.graphqls': - content = formatted_template.strip()[3:-2].strip() - lines = content.split('\n') - result = [] - for line in lines: - line = line.strip() - if line.startswith('*'): - line = line[1:].strip() - if line: - result.append(f'# {line}') - else: - result.append('#') - return '\n'.join(result) + '\n' - elif file_ext == '.html': - content = formatted_template.strip()[3:-2].strip() - lines = content.split('\n') - result = ['<!--'] - for line in lines: - line = line.strip() - if line.startswith('*'): - line = line[1:].strip() - if line: - result.append(f' * {line}') - else: - result.append(' *') - result.append(' -->') - return '\n'.join(result) + '\n' - else: - return f"{formatted_template}\n" - - # Format according to file type - if file_ext in ['.php', '.phtml']: - lines = formatted_template.split('\n') - result = ['<?php', '/**'] - for line in lines: - if line.strip(): - result.append(f' * {line}') - else: - result.append(' *') - result.append(' */') - if file_ext == '.phtml': - result.append('?>') - return '\n'.join(result) + '\n' - - elif file_ext in ['.xml', '.xsd']: - lines = formatted_template.split('\n') - result = ['<?xml version="1.0"?>', '<!--'] - for line in lines: - if line.strip(): - result.append(f' * {line}') - else: - result.append(' *') - result.append(' -->') - return '\n'.join(result) + '\n' - - elif file_ext in ['.js', '.css', '.less', '.scss']: - lines = formatted_template.split('\n') - result = ['/**'] - for line in lines: - if line.strip(): - result.append(f' * {line}') - else: - result.append(' *') - result.append(' */') - return '\n'.join(result) + '\n' - - elif file_ext == '.graphqls': - lines = formatted_template.split('\n') - result = [] - for line in lines: - if line.strip(): - result.append(f'# {line}') - else: - result.append('#') - return '\n'.join(result) + '\n' - - elif file_ext in ['.html', '.md']: - lines = formatted_template.split('\n') - result = ['<!--'] - for line in lines: - if line.strip(): - result.append(f' * {line}') - else: - result.append(' *') - result.append(' -->') - return '\n'.join(result) + '\n' - - return formatted_template + '\n' - - -def extract_existing_copyright(content: str, comment_style: Tuple[str, str, str]) -> Tuple[str, int]: - """Extract existing copyright header and return it with the number of lines. - - Uses a state machine with explicit block types so that the end-of-block - detection is never applied to the wrong comment style. Three block types: - C_STYLE — /* ... */ or /** ... */ - HTML — <!-- ... --> (including nested /** */ used in XML files) - HASH — consecutive # lines (Python, shell, YAML) - """ - lines = content.split('\n') - - copyright_patterns = [ - r'\bcopyright\b', - r'\blicensed?\s+under\b', - r'\bspdx-license\b', - r'\ball rights reserved\b', - r'@copyright', - r'@license', - r'\badobe\s+confidential\b', - r'\bcopyright\s+\d{4}\s+(?:adobe|magento)', - r'see\s+copying\.txt', - r'see\s+license', - ] - - def _has_copyright(text: str) -> bool: - return any(re.search(p, text.lower()) for p in copyright_patterns) - - C_STYLE = 'c_style' - HTML = 'html' - HASH = 'hash' - - header_lines: list = [] - line_count = 0 - block_type = None - found_copyright = False - - for i, line in enumerate(lines): - stripped = line.strip() - - # Always skip the PHP opening tag and XML declaration on line 0. - if i == 0 and (stripped.startswith('<?php') or stripped.startswith('<?xml')): - header_lines.append(line) - continue - - # ── Not yet inside a block ──────────────────────────────────────── - if block_type is None: - if stripped.startswith('/**') or stripped.startswith('/*'): - block_type = C_STYLE - header_lines.append(line) - # Handle single-line /* ... */ block. - if stripped.endswith('*/') and len(stripped) > 2: - if _has_copyright(stripped): - found_copyright = True - line_count = i + 1 - else: - header_lines = [] - break - continue - - if stripped.startswith('<!--'): - block_type = HTML - header_lines.append(line) - # Handle single-line <!-- ... --> block. - if stripped.endswith('-->') and len(stripped) > 4: - if _has_copyright(stripped): - found_copyright = True - line_count = i + 1 - else: - header_lines = [] - break - continue - - if stripped.startswith('#'): - block_type = HASH - if _has_copyright(stripped): - found_copyright = True - header_lines.append(line) - line_count = i + 1 - continue - - if stripped == '' and not header_lines: - continue - - # Non-comment content — nothing more to find. - break - - # ── Inside a C-style block /* ... */ ──────────────────────────── - elif block_type == C_STYLE: - header_lines.append(line) - line_count = i + 1 - if _has_copyright(stripped): - found_copyright = True - if stripped.endswith('*/'): - if found_copyright: - break - # Non-copyright C-style block; reset and keep looking. - header_lines = [] - line_count = 0 - block_type = None - - # ── Inside an HTML comment block <!-- ... --> ──────────────────── - # Lines inside can be free-form text, star-prefixed, or nested /** */. - # We consume everything until --> regardless of line content. - elif block_type == HTML: - header_lines.append(line) - line_count = i + 1 - if _has_copyright(stripped): - found_copyright = True - if stripped.endswith('-->'): - if found_copyright: - break - # Non-copyright HTML block; reset and keep looking. - header_lines = [] - line_count = 0 - block_type = None - - # ── Inside a hash-comment block # lines ───────────────────────── - elif block_type == HASH: - if not stripped.startswith('#'): - # Hash block ended. - if found_copyright: - # The current line is not part of the header. - line_count = i - break - if _has_copyright(stripped): - found_copyright = True - header_lines.append(line) - line_count = i + 1 - - if not found_copyright: - return '', 0 - - return '\n'.join(header_lines), line_count - - -def is_magento_file(file_path: str) -> bool: - """Check if file is part of Magento core or a Magento module.""" - for pattern in MAGENTO_MODULE_PATTERNS: - if re.search(pattern, file_path): - return True - - magento_files = [ - 'registration.php', - 'module.xml', - 'composer.json', - 'requirejs-config.js', - 'web.xml', - ] - - filename = os.path.basename(file_path) - return filename in magento_files - - -def _matches_path_segment(exclusion: str, file_path: str) -> bool: - """Check if exclusion matches as a path segment (not arbitrary substring).""" - normalized = f'/{file_path}' - return f'/{exclusion}/' in normalized or normalized.endswith(f'/{exclusion}') - - -def should_exclude_file(file_path: str, exclude_list: List[str]) -> bool: - """Check if file should be excluded from copyright checking.""" - for excl in exclude_list: - if _matches_path_segment(excl, file_path): - return True - - for excl in MAGENTO_EXCLUSIONS: - if _matches_path_segment(excl, file_path): - return True - - # Exclude test directories outside app/code, but allow dev/tests/*/testsuite/ - # which contains standard Magento test suites that require copyright headers. - if '/tests/' in file_path.lower() and '/app/code/' not in file_path.lower(): - if not re.search(r'dev/tests/[^/]+/testsuite/', file_path.lower()): - return True - - filename = os.path.basename(file_path) - - if any(lib in file_path.lower() for lib in ['jquery', 'prototype', 'scriptaculous', 'mage/lib']): - return True - - if filename.endswith('.min.js') or filename.endswith('.min.css'): - return True - - return False - - -def check_file(file_path: str, template: str, fix: bool = False, dry_run: bool = False, - debug: bool = False, pr_mode: bool = False, base_sha: str = '', - is_private: bool = False, requires_notice: bool = False) -> bool: - """Check and optionally fix copyright header in a file.""" - ext = Path(file_path).suffix.lower() - - if ext not in COMMENT_STYLES: - return True - - try: - with open(file_path, 'r', encoding='utf-8') as f: - content = f.read() - except (UnicodeDecodeError, PermissionError): - return True - - # Skip third-party files that don't reference Magento/Adobe at all, - # matching the Jenkins SanityCopyrightChecker behaviour. - if _is_third_party_file(file_path, content): - if debug: - click.echo(f" Skipping 3rd-party file (no Magento/Adobe reference): {file_path}") - return True - - # ── Confidentiality format check (derived from template) ───────── - has_confidential = 'ADOBE CONFIDENTIAL' in content - has_notice = 'NOTICE:' in content - if is_private and not has_confidential: - click.echo(f" ERROR: Private repo: missing ADOBE CONFIDENTIAL header: {file_path}") - return False - if is_private and requires_notice and not has_notice: - click.echo(f" ERROR: Private repo: missing NOTICE block in copyright header: {file_path}") - return False - if not is_private and has_confidential: - click.echo(f" ERROR: Public repo: file must not contain ADOBE CONFIDENTIAL: {file_path}") - return False - - comment_style = COMMENT_STYLES[ext] - existing_header, header_line_count = extract_existing_copyright(content, comment_style) - - # ── Comparison ──────────────────────────────────────────────────── - existing_norm = _normalize_copyright(existing_header) - year = str(datetime.now().year) # default; overridden in non-PR mode - expected_header = '' # set for new files and non-PR mode - base_header_for_fix = None # set for existing files whose copyright changed - - if pr_mode and base_sha: - try: - base_result = subprocess.run( - ['git', 'show', f'{base_sha}:{file_path}'], - capture_output=True, text=True, cwd=_GIT_ROOT - ) - except Exception: - base_result = None - - if base_result is not None and base_result.returncode == 0: - # Existing file: compare copyright directly against the base branch. - # No template involved — we only check that the developer did not - # modify the copyright header. If the base had no copyright, skip: - # migrating existing files to the Adobe format is a separate task. - base_header, _ = extract_existing_copyright(base_result.stdout, comment_style) - if not base_header: - if debug: - click.echo(f" Existing file has no copyright in base — skipping") - return True - base_norm = _normalize_copyright(base_header) - if base_norm == existing_norm: - return True - # Copyright was changed in this PR — fall through to report/fix. - base_header_for_fix = base_header - else: - # New file: must carry the current year and correct format. - expected_header = format_copyright_header(template, file_path, comment_style, year, debug) - expected_norm = _normalize_copyright(expected_header) - if debug: - click.echo(f" New file: year {year}") - click.echo(f" Expected: {expected_header[:80]}...") - if ext in ['.xml', '.xsd']: - if '/**' in existing_header or '*/' in existing_header: - if debug: - click.echo(f" XML file has incorrect comment style: {file_path}") - elif expected_norm and expected_norm in existing_norm: - return True - else: - if expected_norm and expected_norm in existing_norm: - return True - - else: - # Non-PR mode (local scan / --fix): use git creation year. - year = str(get_git_creation_year(file_path, debug, use_current_year=pr_mode, base_sha=base_sha)) - expected_header = format_copyright_header(template, file_path, comment_style, year, debug) - expected_norm = _normalize_copyright(expected_header) - if debug: - click.echo(f" Expected header preview:") - click.echo(f" {expected_header[:100]}...") - click.echo(f" Existing header preview:") - click.echo(f" {existing_header[:100]}...") - click.echo(f" Year used for comparison: {year}") - if ext in ['.xml', '.xsd']: - if '/**' in existing_header or '*/' in existing_header: - if debug: - click.echo(f" XML file has incorrect comment style: {file_path}") - elif expected_norm and expected_norm in existing_norm: - return True - else: - if expected_norm and expected_norm in existing_norm: - return True - - # ── No match ────────────────────────────────────────────────────── - - if dry_run: - if base_header_for_fix is not None: - click.echo(f" Would restore: {file_path} (copyright was modified in this PR)") - else: - click.echo(f" Would fix: {file_path}") - return False - - if fix: - lines = content.split('\n') - - preserved_lines = [] - if lines and (lines[0].startswith('#!') or 'coding:' in lines[0] or 'encoding:' in lines[0]): - preserved_lines.append(lines[0]) - - # When there is no existing copyright (header_line_count == 0) but the - # file already has a <?php or <?xml opening tag on line 0, skip that line - # so the generated header (which includes the opening tag) does not - # produce a duplicate. - skip = header_line_count - if skip == 0 and lines and re.match(r'<\?(?:php|xml)\b', lines[0].strip()): - skip = 1 - remaining_content = '\n'.join(lines[skip:]) - - new_content = '\n'.join(preserved_lines) - if preserved_lines: - new_content += '\n' - - if base_header_for_fix is not None: - # Existing file: restore the copyright to what it was in the base branch. - new_content += base_header_for_fix - fix_msg = f" Fixed: {file_path} (restored base copyright)" - else: - # New file or non-PR mode: write the template-generated header. - new_content += expected_header - fix_msg = f" Fixed: {file_path} (year: {year})" - - if not remaining_content.startswith('\n'): - new_content += '\n' - new_content += remaining_content.lstrip('\n') - - with open(file_path, 'w', encoding='utf-8') as f: - f.write(new_content) - - click.echo(fix_msg) - return True - else: - if base_header_for_fix is not None: - click.echo(f" Copyright was modified in this PR: {file_path}") - click.echo(f" To fix: python3 .github/scripts/check_copyright.py " - f"--template .github/scripts/copyright-template.txt " - f"--path '{file_path}' --pr-mode --base-sha $BASE_SHA --fix") - else: - click.echo(f" Missing/incorrect copyright: {file_path} (expected year: {year})") - click.echo(f" To fix: python3 .github/scripts/check_copyright.py " - f"--template .github/scripts/copyright-template.txt " - f"--path '{file_path}' --pr-mode --fix") - return False - - -@click.command() -@click.option('--template', required=True, help='Path to copyright template file') -@click.option('--fix', is_flag=True, help='Fix copyright headers automatically') -@click.option('--dry-run', is_flag=True, help='Show what would be fixed without making changes') -@click.option('--extensions', default='.php,.phtml,.js,.css,.scss,.less,.xml,.xsd,.html,.graphqls', - help='Comma-separated list of file extensions to check') -@click.option('--exclude', default='', - help='Additional comma-separated list of directories to exclude') -@click.option('--magento-only', is_flag=True, - help='Only check files that are part of Magento modules') -@click.option('--stats', is_flag=True, help='Show detailed statistics') -@click.option('--debug', is_flag=True, help='Show detailed git debugging information') -@click.option('--path', default='.', help='Path to check - can be a file or directory (default: current directory)') -@click.option('--file-list', default='', help='File containing paths to check, one per line (faster than looping --path calls)') -@click.option('--verbose', is_flag=True, help='Show verbose output with detailed information') -@click.option('--pr-mode', is_flag=True, help='PR mode: trust existing year for modified files, current year for new files') -@click.option('--base-sha', default='', help='Base commit SHA for PR mode: used to detect new vs modified files without git log') -def main(template: str, fix: bool, dry_run: bool, extensions: str, exclude: str, - magento_only: bool, stats: bool, debug: bool, path: str, file_list: str, verbose: bool, pr_mode: bool, base_sha: str): - """Check copyright headers against a template file (Magento-optimized). - - Template should contain {{YEAR}} placeholder which will be replaced with - the appropriate year for each file. - - In PR mode (--pr-mode), new files use the current year and existing - files use their git creation year. Unlike the Jenkins checker (which - trusts the year already in the file because git is unavailable there), - this script verifies the year against git history. - - Examples: - - Check a single file: - python3 .github/scripts/check_copyright.py --template .github/scripts/copyright-template.txt --path app/code/Magento/MysqlMq/registration.php --dry-run - - Check a directory: - python3 .github/scripts/check_copyright.py --template .github/scripts/copyright-template.txt --path app/code/Magento/MysqlMq/ --fix - - Check entire project: - python3 .github/scripts/check_copyright.py --template .github/scripts/copyright-template.txt --magento-only --stats - """ - - if dry_run and fix: - click.echo("Cannot use --dry-run and --fix together", err=True) - sys.exit(1) - - template_content = load_template(template) - is_private = 'ADOBE CONFIDENTIAL' in template_content - requires_notice = 'NOTICE:' in template_content - extensions_list = [ext.strip() for ext in extensions.split(',')] - exclude_list = [entry.strip() for entry in exclude.split(',') if entry.strip()] - - if file_list: - if not os.path.exists(file_list): - click.echo(f"File list not found: {file_list}", err=True) - sys.exit(1) - with open(file_list) as fh: - paths = [line.strip() for line in fh if line.strip()] - issues_found = [] - for file_path in paths: - if not os.path.isfile(file_path): - continue - if should_exclude_file(file_path, exclude_list): - continue - if not any(file_path.endswith(ext) for ext in extensions_list): - continue - if not check_file(file_path, template_content, fix, dry_run, debug, pr_mode, base_sha, is_private, requires_notice): - issues_found.append(file_path) - if issues_found: - click.echo(f"\n{len(issues_found)} file(s) have copyright issues") - sys.exit(1) - click.echo("All relevant PR files have correct copyright headers") - return - - if not os.path.exists(path): - click.echo(f"Path does not exist: {path}", err=True) - sys.exit(1) - - issues_found = [] - files_checked = 0 - files_skipped = 0 - magento_files = 0 - ext_stats = {} - - is_single_file = os.path.isfile(path) - show_header = verbose or not is_single_file - - if show_header: - click.echo(f"Checking copyright headers in: {path}") - if is_single_file: - click.echo(f" Mode: Single file") - else: - click.echo(f" Mode: Directory traversal") - click.echo(f" Extensions: {', '.join(extensions_list)}") - if magento_only: - click.echo(" Checking Magento modules only") - if pr_mode: - click.echo(" PR mode: trusting existing year for modified files") - - if debug: - click.echo(f" Debug: Path={path}, is_single_file={is_single_file}") - click.echo(f" Debug: magento_only={magento_only}, pr_mode={pr_mode}") - click.echo(f" Debug: exclude_list={exclude_list}") - - if is_single_file: - files_skipped = 0 - - if should_exclude_file(path, exclude_list): - if verbose: - click.echo(f" File excluded: {path}") - files_skipped = 1 - elif magento_only and not is_magento_file(path): - if verbose: - click.echo(f" Not a Magento file: {path}") - files_skipped = 1 - else: - file_ext = Path(path).suffix.lower() - if not any(path.endswith(ext) for ext in extensions_list): - if verbose: - click.echo(f" Unsupported extension {file_ext}: {path}") - files_skipped = 1 - else: - files_checked = 1 - ext_stats[file_ext] = 1 - magento_files = 1 if is_magento_file(path) else 0 - - if verbose or debug: - click.echo(f"Checking: {path}") - - if not check_file(path, template_content, fix, dry_run, debug, pr_mode, base_sha, is_private, requires_notice): - issues_found.append(path) - else: - if debug: - click.echo(f" Debug: Processing directory: {path}") - - total_files_found = 0 - for root, dirs, files in os.walk(path): - dirs[:] = [d for d in dirs if not should_exclude_file(os.path.join(root, d), exclude_list)] - - for file in files: - total_files_found += 1 - file_path = os.path.join(root, file) - - if should_exclude_file(file_path, exclude_list): - files_skipped += 1 - continue - - if magento_only and not is_magento_file(file_path): - files_skipped += 1 - continue - - if any(file.endswith(ext) for ext in extensions_list): - ext = Path(file).suffix.lower() - ext_stats[ext] = ext_stats.get(ext, 0) + 1 - - if is_magento_file(file_path): - magento_files += 1 - - files_checked += 1 - if verbose or debug: - click.echo(f"Checking: {file_path}") - - if not check_file(file_path, template_content, fix, dry_run, debug, pr_mode, base_sha, is_private, requires_notice): - issues_found.append(file_path) - - if debug: - click.echo(f" Debug: Directory walk completed. Total files found: {total_files_found}") - click.echo(f" Debug: Files checked: {files_checked}, Files skipped: {files_skipped}") - - if not is_single_file or verbose: - click.echo(f"\nResults:") - click.echo(f" Files checked: {files_checked}") - click.echo(f" Files skipped: {files_skipped}") - click.echo(f" Magento files: {magento_files}") - - if stats: - click.echo(f"\nStatistics by extension:") - for ext, count in sorted(ext_stats.items()): - click.echo(f" {ext}: {count} files") - - if issues_found: - click.echo(f"\n{len(issues_found)} files have copyright issues") - if dry_run: - click.echo("Run with --fix to automatically correct them") - elif not fix: - click.echo("Run with --fix to automatically correct them") - click.echo("Run with --dry-run to see what would be changed") - else: - if dry_run: - click.echo("\nAll files would have correct copyright headers") - else: - click.echo("\nAll files have correct copyright headers") - - if issues_found: - sys.exit(1) - -if __name__ == "__main__": - main() diff --git a/.github/scripts/generate-stubs.sh b/.github/scripts/generate-stubs.sh deleted file mode 100755 index 02a90fee4032..000000000000 --- a/.github/scripts/generate-stubs.sh +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright 2026 Adobe -# All Rights Reserved. -# -# Generates PHPStan stub files from use statements in the given files. -# Called by the CI workflow with the list of changed PHP files. -# -# Usage: .github/scripts/generate-stubs.sh <file-list> -# <file-list>: path to a text file with one PHP file path per line -# -# Output: /tmp/magento-stubs.php - -set -euo pipefail - -FILE_LIST="${1:?Usage: generate-stubs.sh <file-list>}" -STUB_FILE="/tmp/magento-stubs.php" - -if [ ! -f "$FILE_LIST" ]; then - echo "File list not found: $FILE_LIST" - exit 1 -fi - -# Extract all 'use Magento\...' from the changed files only, strip aliases -use_classes=$(cat "$FILE_LIST" | while IFS= read -r f; do - [ -n "$f" ] && [ -f "$f" ] && grep -h '^use Magento\\' "$f" 2>/dev/null || true -done | sed -E 's/^use[[:space:]]+//;s/[[:space:]]+as[[:space:]].*//;s/[[:space:]]*;[[:space:]]*$//' | sort -u) - -# Also extract fully-qualified parent classes from 'extends' clauses. -# Catches cases like: class Foo extends \Magento\Catalog\...\Bar -# where no matching 'use' statement exists in the changed file. -extends_classes=$(cat "$FILE_LIST" | while IFS= read -r f; do - [ -n "$f" ] && [ -f "$f" ] && grep -hE '\bextends\b' "$f" 2>/dev/null | grep -oE '\\?Magento(\\[A-Za-z0-9_]+)+' | sed 's/^\\//' || true -done | sort -u) - -# Also extract Magento interfaces from 'implements' clauses — stubs for these -# prevent "implements unknown interface Magento\..." errors in sparse clone. -implements_classes=$(cat "$FILE_LIST" | while IFS= read -r f; do - [ -n "$f" ] && [ -f "$f" ] && grep -hE '\bimplements\b' "$f" 2>/dev/null | grep -oE '\\?Magento(\\[A-Za-z0-9_]+)+' | sed 's/^\\//' || true -done | sort -u) - -classes=$(printf '%s\n%s\n%s\n' "$use_classes" "$extends_classes" "$implements_classes" | grep -v '^$' | sort -u) - -if [ -z "$classes" ]; then - echo "No Magento class references found in changed files." - echo "<?php" > "$STUB_FILE" - exit 0 -fi - -cat > "$STUB_FILE" << 'HEADER' -<?php -/** - * Auto-generated Magento class stubs for PHPStan. - * Contains minimal declarations so PHPStan can resolve - * Magento framework classes without the full vendor/ tree. - */ -HEADER - -# Phrase class must come first (used by __ function) -cat >> "$STUB_FILE" << 'PHRASE' - -namespace Magento\Framework { - class Phrase { public function __construct(string $text, array $args = []) {} public function __toString(): string { return ''; } } -} - -namespace { - if (!function_exists('__')) { - function __($text, ...$args): \Magento\Framework\Phrase { return new \Magento\Framework\Phrase($text, $args); } - } -} - -PHRASE - -# Track already declared FQCNs to avoid duplicate class/interface declarations -# (e.g. predeclared stubs or repeated use statements). -declare -A declared_fqcns -declared_fqcns["Magento\\Framework\\Phrase"]=1 - -current_ns="" -while IFS= read -r fqcn; do - [ -z "$fqcn" ] && continue - - if [ -n "${declared_fqcns[$fqcn]:-}" ]; then - continue - fi - declared_fqcns["$fqcn"]=1 - - # Extract namespace and short class name - short="${fqcn##*\\}" - ns="${fqcn%\\$short}" - - # Start new namespace block if changed - if [ "$ns" != "$current_ns" ]; then - [ -n "$current_ns" ] && echo "}" >> "$STUB_FILE" && echo "" >> "$STUB_FILE" - echo "namespace $ns {" >> "$STUB_FILE" - current_ns="$ns" - fi - - # Determine type by naming convention - if echo "$short" | grep -qE 'Interface$'; then - echo " interface $short {}" >> "$STUB_FILE" - elif echo "$short" | grep -qE 'Exception$'; then - echo " class $short extends \\Exception {}" >> "$STUB_FILE" - elif echo "$short" | grep -qE 'Factory$'; then - echo " class $short { public function create(array \$data = []) {} }" >> "$STUB_FILE" - else - echo " class $short {}" >> "$STUB_FILE" - fi - -done <<< "$classes" - -# Close last namespace -[ -n "$current_ns" ] && echo "}" >> "$STUB_FILE" - - -count=$(grep -cE '^\s+(class|interface|abstract)' "$STUB_FILE") -echo "Generated $STUB_FILE with $count stub(s) from changed files." diff --git a/.github/scripts/phpstan-extensions.neon b/.github/scripts/phpstan-extensions.neon deleted file mode 100644 index 34fd92715770..000000000000 --- a/.github/scripts/phpstan-extensions.neon +++ /dev/null @@ -1,17 +0,0 @@ -# -# Copyright 2026 Adobe -# All Rights Reserved. -# - -includes: - - %currentWorkingDirectory%/.github/scripts/phpstan.neon - -services: - - - class: Magento\PhpStan\Reflection\Php\DataObjectClassReflectionExtension - tags: {phpstan.broker.methodsClassReflectionExtension: {priority: 100}} - - errorFormatter.filtered: - class: Magento\PhpStan\Formatters\FilteredErrorFormatter - arguments: - tableErrorFormatter: @errorFormatter.table diff --git a/.github/scripts/phpstan-framework-autoload.php b/.github/scripts/phpstan-framework-autoload.php deleted file mode 100644 index 34fff1c6db31..000000000000 --- a/.github/scripts/phpstan-framework-autoload.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php -/** - * Copyright 2026 Adobe - * All Rights Reserved. - */ -declare(strict_types=1); - -// Registers autoloaders for the CE sparse clone at /tmp/magento2-static/: -// -// dev/tests/static/framework/ — Magento\PhpStan\* and Magento\CodeMessDetector\* -// lib/internal/ — Magento\Framework\* (resolves parent classes and -// parameter types not captured by the use-statement -// stub generator, e.g. FQN in extends clauses) -// -// Loaded via --autoload-file (before PHPStan builds its DI container) only when -// the CE sparse clone is present. When it is absent this file is never referenced. - -$bases = [ - '/tmp/magento2-static/dev/tests/static/framework/', - '/tmp/magento2-static/lib/internal/', -]; - -$anyPresent = false; -foreach ($bases as $base) { - if (!is_dir($base)) { - continue; - } - $anyPresent = true; - spl_autoload_register(static function (string $class) use ($base): void { - $file = $base . str_replace('\\', '/', $class) . '.php'; - if (is_file($file)) { - require_once $file; - } - }); -} - -if (!$anyPresent) { - return; -} diff --git a/.github/scripts/phpstan.neon b/.github/scripts/phpstan.neon deleted file mode 100644 index e60582b11c46..000000000000 --- a/.github/scripts/phpstan.neon +++ /dev/null @@ -1,69 +0,0 @@ -# -# Copyright 2026 Adobe -# All Rights Reserved. -# - -parameters: - # Level 1 catches undefined variables, wrong argument counts, - # basic type issues. - level: 1 - checkExplicitMixedMissingReturn: true - checkPhpDocMissingReturn: true - reportUnmatchedIgnoredErrors: false - bootstrapFiles: - - /tmp/magento-stubs.php - excludePaths: - - */_files/* - - */Fixtures/* - - */tmp/* - - .github/* - # Test directories: PHPUnit and Magento test framework are not available - # in the GHA sparse-clone environment. Jenkins has the full codebase so - # it can analyze test files without unknown-class errors; we cannot. - # Covers both app/code/*/Test/Unit|Integration paths and - # dev/tests/*/testsuite/ paths used by integration/API-functional tests. - - */Test/Unit/* - - */Test/Integration/* - - */Test/Functional/* - - */Test/Mftf/* - - */Test/Performance/* - - */testsuite/* - - */dev/tests/* - ignoreErrors: - # Constructor unused parameters (common in Magento DI) - - '#Constructor of class [a-zA-Z0-9\\_]+ has an unused parameter#' - # Void return type with missing return - - '#Method (?:.*?) should return (?:.*?)void(?:.*?) but return statement is missing.#' - # Parent class methods accessed via inheritance (stubs are empty) - - '#Call to an undefined method#' - # Properties defined in parent class (stubs are empty) - - '#Access to an undefined property#' - # Parent constructors / static methods in stubs (empty classes) - - '#Call to an undefined static method#' - # Constants defined in interfaces (stubs have no constants) - - '#Access to undefined constant#' - # Constants on classes not present in the sparse-clone - - '#Access to constant [a-zA-Z0-9_]+ on an unknown class#' - # Variable defined in phtml template context - - '#Variable \$block might not be defined#' - - '#Variable \$escaper might not be defined#' - # Incomplete-stub errors: GHA analyzes changed files only; non-framework - # classes and parameter types not in the changed files' use statements may - # be stubs with no type info. Magento\Framework\* is resolved via the - # lib/internal autoloader; broader unknown-type errors are suppressed here. - # Note: "extends unknown class" cannot be suppressed via ignoreErrors - # (PHPStan hard-rejects it) — those are handled via excludePaths or the - # lib/internal autoloader. - - '#has invalid.*type#' - - '#Class [a-zA-Z0-9\\_\\\\]+ not found\.#' - - '#Instantiated class [a-zA-Z0-9\\_\\\\]+ not found\.#' - - '#is not an Attribute class#' - - '#has unknown class [a-zA-Z0-9\\_\\\\]+ as its type#' - - '#calls parent::[a-zA-Z0-9_]+\(\) but [a-zA-Z0-9\\_\\\\]+ does not extend any class#' - # Stub-generated classes have no constructor; sparse-clone cannot include - # the real implementation (e.g. Magento\\Framework\\DataObject). - - '#does not have a constructor and must be instantiated without any parameters#' - # Laminas static method calls when Laminas is not installed in sparse-clone - - '#Call to static method [a-zA-Z0-9_]+\(\) on an unknown class#' - # Undefined variables: GHA scope is changed files only, parity with Static Tests - - '#Undefined variable:#' diff --git a/.github/scripts/rector-compat.php b/.github/scripts/rector-compat.php deleted file mode 100644 index fca2164384ef..000000000000 --- a/.github/scripts/rector-compat.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php -/** - * Copyright 2026 Adobe - * All Rights Reserved. - */ - -/** - * Rector configuration compatible with both Rector 1.x and 2.x. - * - * The upstream magento-coding-standard rector.php uses singleton() which - * does not register rules in Rector 2.x. This wrapper uses rule() instead. - */ -declare(strict_types=1); - -use Magento2\Rector\Src\ReplaceMbStrposNullLimit; -use Magento2\Rector\Src\ReplaceNewDateTimeNull; -use Magento2\Rector\Src\ReplacePregSplitNullLimit; -use Rector\Config\RectorConfig; -use Rector\ValueObject\PhpVersion; -use Rector\Php80\Rector\Class_\StringableForToStringRector; -use Rector\Php80\Rector\ClassMethod\FinalPrivateToPrivateVisibilityRector; -use Rector\CodeQuality\Rector\ClassMethod\OptionalParametersAfterRequiredRector; -use Rector\Php80\Rector\ClassMethod\SetStateToStaticRector; - -return static function (RectorConfig $rectorConfig): void { - $envVersion = getenv('RECTOR_PHP_VERSION') ?: '8.3'; - $constantName = 'PHP_' . str_replace('.', '', $envVersion); - $phpVersion = defined(PhpVersion::class . '::' . $constantName) - ? constant(PhpVersion::class . '::' . $constantName) - : PhpVersion::PHP_83; - $rectorConfig->phpVersion($phpVersion); - - $rules = [ - FinalPrivateToPrivateVisibilityRector::class, - OptionalParametersAfterRequiredRector::class, - SetStateToStaticRector::class, - StringableForToStringRector::class, - // Php81ResourceReturnToObjectRector was removed in Rector 2.x - ReplacePregSplitNullLimit::class, - ReplaceMbStrposNullLimit::class, - ReplaceNewDateTimeNull::class, - ]; - - // rule() works in both Rector 1.x and 2.x - foreach ($rules as $rule) { - $rectorConfig->rule($rule); - } -}; diff --git a/.github/workflows/pr-quality-gates.yml b/.github/workflows/pr-quality-gates.yml index 9cc7b7541c5e..d698b7007523 100644 --- a/.github/workflows/pr-quality-gates.yml +++ b/.github/workflows/pr-quality-gates.yml @@ -139,7 +139,6 @@ jobs: # Verify required CI files are not removed in this PR required=( .github/workflows/pr-quality-gates.yml - .github/scripts/check_copyright.py .github/scripts/copyright-template.txt .github/scripts/phpmd-ruleset.xml .github/scripts/tslint.json From d76b77b3f8d7d68d3f9c9eaeddcf2f0067609aeb Mon Sep 17 00:00:00 2001 From: chandrakalahanchinal <del66267@adobe.com> Date: Fri, 22 May 2026 13:18:19 +0530 Subject: [PATCH 46/83] ACQE-9557: Update test steps - Updated test steps with standards. --- ...uctDisabledManageStockOnConfigurationPageCustomStockTest.xml | 2 +- ...leProductDisabledManageStockOnProductPageCustomStockTest.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminBundleProductDisabledManageStockOnConfigurationPageCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminBundleProductDisabledManageStockOnConfigurationPageCustomStockTest.xml index c7adc4ba9e73..518df2094bbd 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminBundleProductDisabledManageStockOnConfigurationPageCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminBundleProductDisabledManageStockOnConfigurationPageCustomStockTest.xml @@ -103,7 +103,7 @@ <!--Verify product is not visible storefront.--> <amOnPage url="{{StorefrontCategoryPage.url($$category.custom_attributes[url_key]$$)}}" stepKey="navigateToCategoryPage"/> <waitForPageLoad stepKey="waitForCategoryPageLoad"/> - <see userInput="$bundleProduct.name$" stepKey="assertProductIsPresent1"/> + <waitForText userInput="$bundleProduct.name$" stepKey="assertProductIsPresent1"/> <!--Disable "Manage Stock" in configuration.--> <magentoCLI command="config:set {{TurnOffManageStockConfig.path}} {{TurnOffManageStockConfig.value}}" stepKey="disableManageStock"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminBundleProductDisabledManageStockOnProductPageCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminBundleProductDisabledManageStockOnProductPageCustomStockTest.xml index 334128e7cd3a..2464693a1286 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminBundleProductDisabledManageStockOnProductPageCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminBundleProductDisabledManageStockOnProductPageCustomStockTest.xml @@ -89,7 +89,7 @@ <!--Verify product is not visible storefront.--> <amOnPage url="{{StorefrontCategoryPage.url($$category.custom_attributes[url_key]$$)}}" stepKey="navigateToCategoryPage"/> <waitForPageLoad stepKey="waitForCategoryPageLoad"/> - <see userInput="$bundleProduct.name$" stepKey="assertProductIsPresent1"/> + <waitForText userInput="$bundleProduct.name$" stepKey="assertProductIsPresent1"/> <!--Disable "Manage Stock" On Product Page.--> <amOnPage url="{{AdminProductEditPage.url($$bundleProduct.id$$)}}" stepKey="openProductEditPageToSetStockStatus"/> <click selector="{{AdminProductFormSection.advancedInventoryLink}}" stepKey="clickOnAdvancedInventoryLink"/> From 33e201145b14689ac12e2f92b7d1c7db3ed6a19d Mon Sep 17 00:00:00 2001 From: Alexandra Zota <zota@adobe.com> Date: Fri, 22 May 2026 13:27:37 +0300 Subject: [PATCH 47/83] ACP2E-4972: PR Quality Gates bugfixes and improvements 3 --- .github/workflows/pr-quality-gates.yml | 28 ++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-quality-gates.yml b/.github/workflows/pr-quality-gates.yml index d698b7007523..b888bf4792af 100644 --- a/.github/workflows/pr-quality-gates.yml +++ b/.github/workflows/pr-quality-gates.yml @@ -363,7 +363,7 @@ jobs: echo "phpmd_constraint_from_magento2=${phpmd_m2:-<missing>}" - name: Fetch Magento static PHPMD framework - if: env.HAS_PHP_OR_STATIC == 'true' + if: env.HAS_PHP_OR_STATIC == 'true' || env.HAS_JS == 'true' run: | set -euo pipefail ref="${{ steps.php-version.outputs.magento_composer_ref }}" @@ -692,7 +692,31 @@ jobs: if: always() && steps.gate.outputs.eslint == 'true' && env.HAS_JS == 'true' run: | set -euo pipefail - mapfile -t js_args < /tmp/changed_js.txt + + # Filter against Jenkins ESLint blacklist (blacklist files live in CE repo, + # fetched via the PHPMD sparse-checkout above) + bl="/tmp/magento2-static/dev/tests/static/testsuite/Magento/Test/Js/_files/blacklist" + { + cat "$bl/magento.txt" 2>/dev/null || true + cat "$bl/ee.txt" 2>/dev/null || true + cat "$bl/b2b.txt" 2>/dev/null || true + } > /tmp/eslint_blacklist.txt + + mapfile -t js_args < <(python3 - /tmp/changed_js.txt /tmp/eslint_blacklist.txt <<'PYEOF' + import fnmatch, sys + with open(sys.argv[2]) as f: + patterns = [l.strip() for l in f if l.strip() and not l.strip().startswith('//')] + with open(sys.argv[1]) as f: + files = [l.strip() for l in f if l.strip()] + filtered = [fp for fp in files if not any(fnmatch.fnmatch(fp, p) for p in patterns)] + print('\n'.join(filtered)) + PYEOF + ) + + if [ ${#js_args[@]} -eq 0 ]; then + echo "All changed JS files are blacklisted — skipping ESLint." + exit 0 + fi mcs/node_modules/.bin/eslint \ -c mcs/eslint/eslint.config.mjs \ From b6f5a7d90e0a43501c2377b872b0934910fb86cd Mon Sep 17 00:00:00 2001 From: Alexandra Zota <zota@adobe.com> Date: Fri, 22 May 2026 18:13:31 +0300 Subject: [PATCH 48/83] ACP2E-4972: PR Quality Gates bugfixes and improvements 3 --- .github/workflows/pr-quality-gates.yml | 101 +++++++++++++++++++++---- 1 file changed, 87 insertions(+), 14 deletions(-) diff --git a/.github/workflows/pr-quality-gates.yml b/.github/workflows/pr-quality-gates.yml index b888bf4792af..0f4bfd74517b 100644 --- a/.github/workflows/pr-quality-gates.yml +++ b/.github/workflows/pr-quality-gates.yml @@ -380,6 +380,9 @@ jobs: git sparse-checkout set \ dev/tests/static/framework \ dev/tests/static/testsuite/Magento/Test/Php/_files/phpmd \ + dev/tests/static/testsuite/Magento/Test/Js/_files/blacklist \ + dev/tests/static/testsuite/Magento/Test/Js/_files/whitelist \ + dev/tests/static/testsuite/Magento/Test/Less/_files/blacklist \ lib/internal/Magento/Framework echo "Fetched Magento static PHPMD framework from ref: $ref" @@ -505,7 +508,32 @@ jobs: if: always() && steps.gate.outputs.phpcs_less == 'true' && env.HAS_STATIC == 'true' run: | set -euo pipefail - .github/scripts/run-phpcs.sh "LESS" /tmp/changed_less.txt + + # Filter against Jenkins LESS blacklist (legacy files with known violations) + bl="/tmp/magento2-static/dev/tests/static/testsuite/Magento/Test/Less/_files/blacklist" + { + cat "$bl/old.txt" 2>/dev/null || true + cat "$bl/ee.txt" 2>/dev/null || true + } > /tmp/less_blacklist.txt + + filtered_less=$(mktemp) + python3 - /tmp/changed_less.txt /tmp/less_blacklist.txt "$filtered_less" <<'PYEOF' + import fnmatch, sys + with open(sys.argv[2]) as f: + patterns = [l.strip() for l in f if l.strip() and not l.strip().startswith('//')] + with open(sys.argv[1]) as f: + files = [l.strip() for l in f if l.strip()] + filtered = [fp for fp in files if not any(fnmatch.fnmatch(fp, p) for p in patterns)] + with open(sys.argv[3], 'w') as out: + out.write('\n'.join(filtered) + ('\n' if filtered else '')) + PYEOF + + if [ ! -s "$filtered_less" ]; then + echo "All changed LESS files are blacklisted — skipping PHPCS LESS." + exit 0 + fi + + .github/scripts/run-phpcs.sh "LESS" "$filtered_less" # ── PHPMD ──────────────────────────────────────────────────── @@ -693,28 +721,73 @@ jobs: run: | set -euo pipefail - # Filter against Jenkins ESLint blacklist (blacklist files live in CE repo, - # fetched via the PHPMD sparse-checkout above) - bl="/tmp/magento2-static/dev/tests/static/testsuite/Magento/Test/Js/_files/blacklist" + # Apply Jenkins whitelist then blacklist — both live in CE repo sparse clone. + # Whitelist defines which files are expected to comply (app/code, app/design, + # lib/web/mage, etc.). Files outside it (grunt tasks, setup scripts) are not + # subject to ESLint in Jenkins and must be excluded here too. + jsd="/tmp/magento2-static/dev/tests/static/testsuite/Magento/Test/Js/_files" + { + cat "$jsd/whitelist/magento.txt" 2>/dev/null || true + cat "$jsd/whitelist/ee.txt" 2>/dev/null || true + cat "$jsd/whitelist/b2b.txt" 2>/dev/null || true + } > /tmp/eslint_whitelist.txt { - cat "$bl/magento.txt" 2>/dev/null || true - cat "$bl/ee.txt" 2>/dev/null || true - cat "$bl/b2b.txt" 2>/dev/null || true + cat "$jsd/blacklist/magento.txt" 2>/dev/null || true + cat "$jsd/blacklist/ee.txt" 2>/dev/null || true + cat "$jsd/blacklist/b2b.txt" 2>/dev/null || true } > /tmp/eslint_blacklist.txt - mapfile -t js_args < <(python3 - /tmp/changed_js.txt /tmp/eslint_blacklist.txt <<'PYEOF' - import fnmatch, sys - with open(sys.argv[2]) as f: - patterns = [l.strip() for l in f if l.strip() and not l.strip().startswith('//')] + mapfile -t js_args < <(python3 - /tmp/changed_js.txt /tmp/eslint_whitelist.txt /tmp/eslint_blacklist.txt <<'PYEOF' + import re, sys + + def glob_to_regex(pattern): + result = '' + i = 0 + while i < len(pattern): + if pattern[i:i+3] == '**/': + result += '(?:.+/)?' + i += 3 + elif pattern[i:i+2] == '**': + result += '.*' + i += 2 + elif pattern[i] == '*': + result += '[^/]*' + i += 1 + elif pattern[i] == '?': + result += '[^/]' + i += 1 + else: + result += re.escape(pattern[i]) + i += 1 + return re.compile('^' + result + '$') + + def load(path): + try: + with open(path) as f: + return [glob_to_regex(l.strip()) for l in f + if l.strip() and not l.strip().startswith('#') + and not l.strip().startswith('//')] + except FileNotFoundError: + return [] + with open(sys.argv[1]) as f: files = [l.strip() for l in f if l.strip()] - filtered = [fp for fp in files if not any(fnmatch.fnmatch(fp, p) for p in patterns)] - print('\n'.join(filtered)) + whitelist = load(sys.argv[2]) + blacklist = load(sys.argv[3]) + + result = [] + for fp in files: + if whitelist and not any(r.match(fp) for r in whitelist): + continue + if any(r.match(fp) for r in blacklist): + continue + result.append(fp) + print('\n'.join(result)) PYEOF ) if [ ${#js_args[@]} -eq 0 ]; then - echo "All changed JS files are blacklisted — skipping ESLint." + echo "All changed JS files are outside whitelist scope or blacklisted — skipping ESLint." exit 0 fi From 0a169a4d23021a210986630e39adfb3d8653e6d5 Mon Sep 17 00:00:00 2001 From: Karishma Thakare <del57145@adobe.com> Date: Wed, 27 May 2026 22:10:23 +0530 Subject: [PATCH 49/83] ACQE-9701: [ATLH] Filters - Round 3 - Inventory Stocks Grid - Added filter clearance code --- .../Test/AdminAssignSourcesSelectedOnTwoPagesToStockTest.xml | 5 +++-- ...ntForOrderWithConfigurableProductFromCustomSourceTest.xml | 2 ++ ...fferentTypeOfProductsWithOutOfStockStatusOnSourceTest.xml | 4 ++++ .../Test/AdminPaginationWorkedInManageStocksGridTest.xml | 3 +++ .../Test/AdminStockCanBeDeletedFromEditStockPageTest.xml | 3 +++ ...minStockCannotBeDeletedWhenSalesChannelIsAssignedTest.xml | 4 ++++ ...inStockDeletedFromGridWhenNoSalesChannelsAssignedTest.xml | 3 +++ ...InvoiceForWholeOrderWithVirtualProductOnTestStockTest.xml | 3 +++ ...iewScopeInVisualMerchandiserOnCategoryPageInAdminTest.xml | 2 ++ .../TwentyTwoSourcesAssignedToTheStockByAdminUserTest.xml | 3 +++ ...yZeroLeftNotAppearedOnSimpleProductPageOnFrontendTest.xml | 3 +++ 11 files changed, 33 insertions(+), 2 deletions(-) diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminAssignSourcesSelectedOnTwoPagesToStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminAssignSourcesSelectedOnTwoPagesToStockTest.xml index a3e70337bdce..6ba6b16ff4f3 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminAssignSourcesSelectedOnTwoPagesToStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminAssignSourcesSelectedOnTwoPagesToStockTest.xml @@ -47,8 +47,9 @@ </before> <after> <deleteData createDataKey="createStock" stepKey="deleteStock"/> - <amOnPage url="{{AdminManageStockPage.url}}" stepKey="amOnStockListPage"/> - <actionGroup ref="AdminGridFilterResetActionGroup" stepKey="clearSourceFilters"/> + <amOnPage url="{{AdminManageStockPage.url}}" stepKey="goToStockGridBeforeClearFilters"/> + <waitForPageLoad stepKey="waitForStockGridLoad"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearInventoryStockListingFiltersAfter"/> <actionGroup ref="DisableAllSourcesActionGroup" stepKey="disableAllSources"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialShipmentForOrderWithConfigurableProductFromCustomSourceTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialShipmentForOrderWithConfigurableProductFromCustomSourceTest.xml index f02b76e9b3db..88ac98552f3e 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialShipmentForOrderWithConfigurableProductFromCustomSourceTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialShipmentForOrderWithConfigurableProductFromCustomSourceTest.xml @@ -144,6 +144,8 @@ <selectOption selector="{{AdminEditStockSalesChannelsSection.websites}}" userInput="Main Website" stepKey="selectDefaultWebsiteAsSalesChannelForDefaultStock"/> <click selector="{{AdminGridMainControls.saveAndContinue}}" stepKey="saveDefaultStock"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearInventoryStockListingFiltersAfter"/> + <actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="resetInventoryStockListingToDefaultView"/> <!-- Delete configurable product created via UI --> <helper class="Magento\Catalog\Test\Mftf\Helper\ProductApiHelper" method="deleteAllProductsApi" stepKey="deleteAllProductsViaApi"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminMassActionTransferInventoryToSourceForDifferentTypeOfProductsWithOutOfStockStatusOnSourceTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminMassActionTransferInventoryToSourceForDifferentTypeOfProductsWithOutOfStockStatusOnSourceTest.xml index c5252d70f448..e3120e655150 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminMassActionTransferInventoryToSourceForDifferentTypeOfProductsWithOutOfStockStatusOnSourceTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminMassActionTransferInventoryToSourceForDifferentTypeOfProductsWithOutOfStockStatusOnSourceTest.xml @@ -120,6 +120,10 @@ <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> </actionGroup> + <amOnPage url="{{AdminManageStockPage.url}}" stepKey="goToStockGridBeforeClearFilters"/> + <waitForPageLoad stepKey="waitForStockGridLoad"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearInventoryStockListingFiltersAfter"/> + <actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="resetInventoryStockListingToDefaultView"/> </after> <comment userInput="Set to all products status 'Out of stock' on default source." stepKey="setOutOfStockToAllProductsComment"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminPaginationWorkedInManageStocksGridTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminPaginationWorkedInManageStocksGridTest.xml index a22a83429336..5adac42b7cf4 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminPaginationWorkedInManageStocksGridTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminPaginationWorkedInManageStocksGridTest.xml @@ -46,6 +46,9 @@ <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> </before> <after> + <amOnPage url="{{AdminManageStockPage.url}}" stepKey="goToStockGridBeforeClearFilters"/> + <waitForPageLoad stepKey="waitForStockGridLoad"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearInventoryStockListingFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminStockCanBeDeletedFromEditStockPageTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminStockCanBeDeletedFromEditStockPageTest.xml index d99fbcf3cab2..8954c5244128 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminStockCanBeDeletedFromEditStockPageTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminStockCanBeDeletedFromEditStockPageTest.xml @@ -24,6 +24,9 @@ <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin1"/> </before> <after> + <amOnPage url="{{AdminManageStockPage.url}}" stepKey="goToStockGridBeforeClearFilters"/> + <waitForPageLoad stepKey="waitForStockGridLoad"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearInventoryStockListingFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminStockCannotBeDeletedWhenSalesChannelIsAssignedTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminStockCannotBeDeletedWhenSalesChannelIsAssignedTest.xml index 63bb7f2afd13..6340a23ceb4c 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminStockCannotBeDeletedWhenSalesChannelIsAssignedTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminStockCannotBeDeletedWhenSalesChannelIsAssignedTest.xml @@ -30,6 +30,10 @@ <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> </actionGroup> + <amOnPage url="{{AdminManageStockPage.url}}" stepKey="goToStockGridBeforeClearFilters"/> + <waitForPageLoad stepKey="waitForStockGridLoad"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearInventoryStockListingFiltersAfter"/> + <actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="resetInventoryStockListingToDefaultView"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminStockDeletedFromGridWhenNoSalesChannelsAssignedTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminStockDeletedFromGridWhenNoSalesChannelsAssignedTest.xml index 3f4235971fd9..5cf5fafd7bd8 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminStockDeletedFromGridWhenNoSalesChannelsAssignedTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminStockDeletedFromGridWhenNoSalesChannelsAssignedTest.xml @@ -25,6 +25,9 @@ <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin1"/> </before> <after> + <amOnPage url="{{AdminManageStockPage.url}}" stepKey="goToStockGridBeforeClearFilters"/> + <waitForPageLoad stepKey="waitForStockGridLoad"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearInventoryStockListingFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminUserCreatedInvoiceForWholeOrderWithVirtualProductOnTestStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminUserCreatedInvoiceForWholeOrderWithVirtualProductOnTestStockTest.xml index 218f45fdfa54..08e78675fbc5 100755 --- a/InventoryAdminUi/Test/Mftf/Test/AdminUserCreatedInvoiceForWholeOrderWithVirtualProductOnTestStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminUserCreatedInvoiceForWholeOrderWithVirtualProductOnTestStockTest.xml @@ -39,6 +39,9 @@ <deleteData createDataKey="createCustomer1" stepKey="deleteCustomer"/> <actionGroup ref="DisableAllSourcesActionGroup" stepKey="disableAllSources"/> <magentoCLI command="config:set {{DisableCashOnDeliveryPaymentMethod.path}} {{DisableCashOnDeliveryPaymentMethod.value}}" stepKey="disableCashOnDeliveryPaymentMethod"/> + <amOnPage url="{{AdminManageStockPage.url}}" stepKey="goToStockGridBeforeClearFilters"/> + <waitForPageLoad stepKey="waitForStockGridLoad"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearInventoryStockListingFiltersAfter"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/ProductsSortingInStoreviewScopeInVisualMerchandiserOnCategoryPageInAdminTest.xml b/InventoryAdminUi/Test/Mftf/Test/ProductsSortingInStoreviewScopeInVisualMerchandiserOnCategoryPageInAdminTest.xml index 1744e267d8b7..b2303893c1f3 100644 --- a/InventoryAdminUi/Test/Mftf/Test/ProductsSortingInStoreviewScopeInVisualMerchandiserOnCategoryPageInAdminTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/ProductsSortingInStoreviewScopeInVisualMerchandiserOnCategoryPageInAdminTest.xml @@ -63,6 +63,8 @@ <actionGroup ref="AdminDeleteWebsiteActionGroup" stepKey="deleteWebsite"> <argument name="websiteName" value="{{customWebsite.name}}"/> </actionGroup> + <amOnPage url="{{AdminManageStockPage.url}}" stepKey="goToStockGridBeforeClearFilters"/> + <waitForPageLoad stepKey="waitForStockGridLoad"/> <!--Clear Filter--> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearGridFilters"/> <!--Delete Stock--> diff --git a/InventoryAdminUi/Test/Mftf/Test/TwentyTwoSourcesAssignedToTheStockByAdminUserTest.xml b/InventoryAdminUi/Test/Mftf/Test/TwentyTwoSourcesAssignedToTheStockByAdminUserTest.xml index 33d840a3b2ed..3eb193289ee6 100755 --- a/InventoryAdminUi/Test/Mftf/Test/TwentyTwoSourcesAssignedToTheStockByAdminUserTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/TwentyTwoSourcesAssignedToTheStockByAdminUserTest.xml @@ -49,6 +49,9 @@ <argument name="sourceName21" value="$$createTestSource21.source[name]$$" /> <argument name="sourceName22" value="$$createTestSource22.source[name]$$" /> </actionGroup> + <amOnPage url="{{AdminManageStockPage.url}}" stepKey="goToStockGridBeforeClearFilters"/> + <waitForPageLoad stepKey="waitForStockGridLoad"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearInventoryStockListingFiltersAfter"/> <actionGroup ref="DisableAllSourcesActionGroup" stepKey="disableAllSources"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/VerifyThatMessageOnlyZeroLeftNotAppearedOnSimpleProductPageOnFrontendTest.xml b/InventoryAdminUi/Test/Mftf/Test/VerifyThatMessageOnlyZeroLeftNotAppearedOnSimpleProductPageOnFrontendTest.xml index 322877d2e4d7..ae33fb078a66 100644 --- a/InventoryAdminUi/Test/Mftf/Test/VerifyThatMessageOnlyZeroLeftNotAppearedOnSimpleProductPageOnFrontendTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/VerifyThatMessageOnlyZeroLeftNotAppearedOnSimpleProductPageOnFrontendTest.xml @@ -64,6 +64,9 @@ <actionGroup ref="CliCacheCleanActionGroup" stepKey="cleanCache"> <argument name="tags" value="full_page"/> </actionGroup> + <amOnPage url="{{AdminManageStockPage.url}}" stepKey="goToStockGridBeforeClearFilters"/> + <waitForPageLoad stepKey="waitForStockGridLoad"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearInventoryStockListingFiltersAfter"/> </after> <actionGroup ref="AdminProductPageOpenByIdActionGroup" stepKey="goToProduct1"> From 4ca648daa79113c1cee9c47d933bf2fa4186a63d Mon Sep 17 00:00:00 2001 From: Karishma Thakare <del57145@adobe.com> Date: Thu, 28 May 2026 12:21:52 +0530 Subject: [PATCH 50/83] ACQE-9701: [ATLH] Filters - Round 3 - Inventory Stocks Grid - Added filter clearance code --- ...entForOrderWithConfigurableProductFromCustomSourceTest.xml | 4 ++++ ...ifferentTypeOfProductsWithOutOfStockStatusOnSourceTest.xml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialShipmentForOrderWithConfigurableProductFromCustomSourceTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialShipmentForOrderWithConfigurableProductFromCustomSourceTest.xml index 88ac98552f3e..9fe53d7d235e 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialShipmentForOrderWithConfigurableProductFromCustomSourceTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialShipmentForOrderWithConfigurableProductFromCustomSourceTest.xml @@ -144,6 +144,10 @@ <selectOption selector="{{AdminEditStockSalesChannelsSection.websites}}" userInput="Main Website" stepKey="selectDefaultWebsiteAsSalesChannelForDefaultStock"/> <click selector="{{AdminGridMainControls.saveAndContinue}}" stepKey="saveDefaultStock"/> + <waitForPageLoad time="30" stepKey="waitAfterDefaultStockSave"/> + + <amOnPage url="{{AdminManageStockPage.url}}" stepKey="goToStockGridBeforeClearFilters"/> + <waitForPageLoad time="30" stepKey="waitForStockGridLoad"/> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearInventoryStockListingFiltersAfter"/> <actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="resetInventoryStockListingToDefaultView"/> <!-- Delete configurable product created via UI --> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminMassActionTransferInventoryToSourceForDifferentTypeOfProductsWithOutOfStockStatusOnSourceTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminMassActionTransferInventoryToSourceForDifferentTypeOfProductsWithOutOfStockStatusOnSourceTest.xml index e3120e655150..260504e64441 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminMassActionTransferInventoryToSourceForDifferentTypeOfProductsWithOutOfStockStatusOnSourceTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminMassActionTransferInventoryToSourceForDifferentTypeOfProductsWithOutOfStockStatusOnSourceTest.xml @@ -114,16 +114,16 @@ <actionGroup ref="DisableSourceActionGroup" stepKey="disableFirstCreatedSource"> <argument name="sourceCode" value="$$createSource.source[source_code]$$"/> </actionGroup> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <deleteData createDataKey="createCategory" stepKey="deleteCreatedCategory"/> <deleteData createDataKey="createStock" stepKey="deleteCreatedStock"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> </actionGroup> <amOnPage url="{{AdminManageStockPage.url}}" stepKey="goToStockGridBeforeClearFilters"/> - <waitForPageLoad stepKey="waitForStockGridLoad"/> + <waitForPageLoad time="30" stepKey="waitForStockGridLoad"/> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearInventoryStockListingFiltersAfter"/> <actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="resetInventoryStockListingToDefaultView"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> </after> <comment userInput="Set to all products status 'Out of stock' on default source." stepKey="setOutOfStockToAllProductsComment"/> From 17c0b5887c49f137637a446278ad05b70346cd46 Mon Sep 17 00:00:00 2001 From: Alexandra Zota <zota@adobe.com> Date: Thu, 28 May 2026 15:56:06 +0300 Subject: [PATCH 51/83] ACP2E-4972: PR Quality Gates bugfixes and improvements 3 --- .github/workflows/pr-quality-gates.yml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/pr-quality-gates.yml b/.github/workflows/pr-quality-gates.yml index 0f4bfd74517b..b7f1c7ddf3eb 100644 --- a/.github/workflows/pr-quality-gates.yml +++ b/.github/workflows/pr-quality-gates.yml @@ -203,16 +203,16 @@ jobs: copyright_files="${copyright_files%$'\n'}" # Write file lists for coding-standard checks (avoids git diff in later steps) - [ -n "$php_list" ] && printf '%s' "${php_list%$'\n'}" > /tmp/changed_php.txt - [ -n "$js_list" ] && printf '%s' "${js_list%$'\n'}" > /tmp/changed_js.txt - [ -n "$xml_list" ] && printf '%s' "${xml_list%$'\n'}" > /tmp/changed_xml.txt - [ -n "$html_list" ] && printf '%s' "${html_list%$'\n'}" > /tmp/changed_html.txt - [ -n "$graphql_list" ] && printf '%s' "${graphql_list%$'\n'}" > /tmp/changed_graphqls.txt - [ -n "$less_list" ] && printf '%s' "${less_list%$'\n'}" > /tmp/changed_less.txt - [ -n "$new_php_list" ] && printf '%s' "${new_php_list%$'\n'}" > /tmp/new_php.txt - [ -n "$copyright_files" ] && printf '%s' "$copyright_files" > /tmp/copyright_changed.txt - [ -n "$copyright_added_list" ] && printf '%s' "${copyright_added_list%$'\n'}" > /tmp/copyright_added.txt - [ -n "$ts_list" ] && printf '%s' "${ts_list%$'\n'}" > /tmp/changed_ts.txt + [ -n "$php_list" ] && printf '%s\n' "${php_list%$'\n'}" > /tmp/changed_php.txt + [ -n "$js_list" ] && printf '%s\n' "${js_list%$'\n'}" > /tmp/changed_js.txt + [ -n "$xml_list" ] && printf '%s\n' "${xml_list%$'\n'}" > /tmp/changed_xml.txt + [ -n "$html_list" ] && printf '%s\n' "${html_list%$'\n'}" > /tmp/changed_html.txt + [ -n "$graphql_list" ] && printf '%s\n' "${graphql_list%$'\n'}" > /tmp/changed_graphqls.txt + [ -n "$less_list" ] && printf '%s\n' "${less_list%$'\n'}" > /tmp/changed_less.txt + [ -n "$new_php_list" ] && printf '%s\n' "${new_php_list%$'\n'}" > /tmp/new_php.txt + [ -n "$copyright_files" ] && printf '%s\n' "$copyright_files" > /tmp/copyright_changed.txt + [ -n "$copyright_added_list" ] && printf '%s\n' "${copyright_added_list%$'\n'}" > /tmp/copyright_added.txt + [ -n "$ts_list" ] && printf '%s\n' "${ts_list%$'\n'}" > /tmp/changed_ts.txt echo "has_php=$has_php" >> "$GITHUB_OUTPUT" echo "has_js=$has_js" >> "$GITHUB_OUTPUT" @@ -614,7 +614,7 @@ jobs: "$ruleset" \ --suffixes=php,phtml 2>/dev/null || phpmd_exit=$? fi - [ "$phpmd_exit" -ne 0 ] && break + [ "$phpmd_exit" -ne 0 ] && [ "$phpmd_exit" -ne 2 ] && break done if [ "$phpmd_exit" -eq 124 ]; then echo "::error::PHPMD batch timed out (120 s). The PR may have too many complex files for a single batch. Consider splitting the PR." From f2565e402b3f9f07c4642bcb064a5f0aa93da299 Mon Sep 17 00:00:00 2001 From: Alexandra Zota <zota@adobe.com> Date: Thu, 28 May 2026 16:31:35 +0300 Subject: [PATCH 52/83] ACP2E-4972: PR Quality Gates bugfixes and improvements 3 --- .github/workflows/pr-quality-gates.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr-quality-gates.yml b/.github/workflows/pr-quality-gates.yml index b7f1c7ddf3eb..aa16b04614d8 100644 --- a/.github/workflows/pr-quality-gates.yml +++ b/.github/workflows/pr-quality-gates.yml @@ -72,13 +72,13 @@ jobs: fi # Get upstream mainline HEAD SHA; fall back to origin on error - if ! mainline_sha=$(gh api "repos/${upstream_owner}/${upstream_repo}/branches/${base_branch}" \ - --jq '.commit.sha' 2>/dev/null); then + if ! mainline_sha=$(gh api "repos/${upstream_owner}/${upstream_repo}/git/ref/heads/${base_branch}" \ + --jq '.object.sha' 2>/dev/null); then echo "::warning::Cannot reach ${upstream_label}/${base_branch}. Falling back to origin." upstream_owner="$owner" upstream_repo="${repo##*/}" upstream_label="$repo" - mainline_sha=$(gh api "repos/${repo}/branches/${base_branch}" --jq '.commit.sha') + mainline_sha=$(gh api "repos/${repo}/git/ref/heads/${base_branch}" --jq '.object.sha') fi echo "Mainline HEAD (${upstream_label} ${base_branch}): ${mainline_sha}" From a8584d1e92cafe8dfd9d8a4af97c81eb27610a6a Mon Sep 17 00:00:00 2001 From: Alexandra Zota <zota@adobe.com> Date: Fri, 29 May 2026 18:19:23 +0300 Subject: [PATCH 53/83] ACP2E-4995: PR Quality Gates bugfixes and improvements 4 --- .github/scripts/check_copyright_pr.php | 52 ++++---- .github/scripts/run-phpcs.sh | 2 +- .github/workflows/pr-quality-gates.yml | 174 ++++++++++++++----------- 3 files changed, 124 insertions(+), 104 deletions(-) diff --git a/.github/scripts/check_copyright_pr.php b/.github/scripts/check_copyright_pr.php index 3ec5ec3a545d..e78f308b22ea 100644 --- a/.github/scripts/check_copyright_pr.php +++ b/.github/scripts/check_copyright_pr.php @@ -278,20 +278,17 @@ function buildExpectedHeader(string $template, string $filePath, int $year): str continue; } - // ── Missing copyright entirely ──────────────────────────────────────────── - if ($currentHeader === '') { - $issues[] = [ - 'file' => $filePath, - 'reason' => 'Missing copyright header', - 'new' => $isNew, - ]; - continue; - } - - $currentNorm = normalizeHeader($currentHeader); - if ($isNew) { - // ── New file: must match the template with the current year ─────────── + // ── New file: must have a copyright header in current-year format ───── + if ($currentHeader === '') { + $issues[] = [ + 'file' => $filePath, + 'reason' => 'Missing copyright header', + 'new' => true, + ]; + continue; + } + $currentNorm = normalizeHeader($currentHeader); $expected = buildExpectedHeader($template, $filePath, $currentYear); $expectedNorm = normalizeHeader($expected); if ($expectedNorm !== '' && strpos($currentNorm, $expectedNorm) === false) { @@ -302,30 +299,33 @@ function buildExpectedHeader(string $template, string $filePath, int $year): str ]; } } else { - // ── Existing file: copyright must not have changed ──────────────────── + // ── Existing file: compare against base; skip if base had no copyright ─ $baseContent = getBaseContent($filePath, $baseDir); if ($baseContent === null) { - // File not found in base — treat as new - $expected = buildExpectedHeader($template, $filePath, $currentYear); - $expectedNorm = normalizeHeader($expected); - if ($expectedNorm !== '' && strpos($currentNorm, $expectedNorm) === false) { - $issues[] = [ - 'file' => $filePath, - 'reason' => "New file (not in base branch): copyright header must use year {$currentYear}", - 'new' => true, - ]; - } + // Modified file but base blob unavailable (partial clone fetch failure). + // Skip rather than emit a false positive. + echo " [SKIP] {$filePath} — base content unavailable (partial clone fetch failure)\n"; + $skipped++; continue; } $baseHeader = extractCopyrightBlock($baseContent); if ($baseHeader === '') { - // No copyright in base — skip (migrating old files is a separate task) continue; } - $baseNorm = normalizeHeader($baseHeader); + if ($currentHeader === '') { + $issues[] = [ + 'file' => $filePath, + 'reason' => 'Copyright header was removed in this PR', + 'new' => false, + ]; + continue; + } + + $baseNorm = normalizeHeader($baseHeader); + $currentNorm = normalizeHeader($currentHeader); if ($baseNorm !== $currentNorm) { $issues[] = [ 'file' => $filePath, diff --git a/.github/scripts/run-phpcs.sh b/.github/scripts/run-phpcs.sh index 826c8d66b49c..570c8ad3315f 100755 --- a/.github/scripts/run-phpcs.sh +++ b/.github/scripts/run-phpcs.sh @@ -21,7 +21,7 @@ fi phpcs_tmp=$(mktemp) phpcs_exit=0 mcs/vendor/bin/phpcs \ - --standard=Magento2 \ + --standard="${PHPCS_STANDARD:-Magento2}" \ "$@" \ --report=full \ --no-colors \ diff --git a/.github/workflows/pr-quality-gates.yml b/.github/workflows/pr-quality-gates.yml index aa16b04614d8..614d55754eb8 100644 --- a/.github/workflows/pr-quality-gates.yml +++ b/.github/workflows/pr-quality-gates.yml @@ -13,14 +13,13 @@ on: workflow_dispatch: # Repository variables used by this workflow: -# - PR_QA_ENABLED_JOBS: CSV list of checks to run. -# Supported values: -# coding-standard,aggregate-linked-pr-checks +# - PR_QA_ENABLED_JOBS: CSV list of top-level jobs to run. +# Supported values: coding-standard,aggregate-linked-pr-checks # - PR_QA_CODING_STANDARD_ENABLED_CHECKS: CSV list of coding-standard sub-checks. -# Empty or includes "all" => run all coding-standard sub-checks. +# Empty or includes "all" => run all sub-checks. # Supported values: -# all,phpcs,phpcs-xml,phpcs-html,phpcs-graphql,phpcs-less,phpmd, -# strict-types,fixture-reuse,eslint,typescript +# all,php-lint,phpcs,phpcs-xml,xml-lint,phpcs-html,phpcs-graphql,phpcs-less, +# phpmd,strict-types,fixture-reuse,eslint jobs: # ────────────────────────────────────────────────────────────────────── @@ -141,7 +140,6 @@ jobs: .github/workflows/pr-quality-gates.yml .github/scripts/copyright-template.txt .github/scripts/phpmd-ruleset.xml - .github/scripts/tslint.json .github/scripts/filter-blacklist.sh ) missing=false @@ -159,14 +157,13 @@ jobs: # Categorize files (exclude .github/, vendor/, lib/web/ except lib/web/mage/) # lib/web/ contains vendored third-party JS/CSS (jQuery, RequireJS, etc.) # lib/web/mage/ is Adobe-authored JS and is included. - has_php=false; has_js=false; has_static=false; has_ts=false + has_php=false; has_js=false; has_static=false has_new_files=false; has_copyright_files=false copyright_files="" copyright_exts='\.(php|phtml|js|css|scss|less|xml|xsd|html|graphqls)$' count_new=0; count_modified=0; count_removed=0 php_list=""; js_list=""; xml_list=""; html_list="" graphql_list=""; less_list=""; new_php_list=""; copyright_added_list="" - ts_list="" while IFS=$'\t' read -r filename status; do [[ -z "$filename" ]] && continue @@ -180,7 +177,6 @@ jobs: [[ "$filename" =~ \.(php|phtml)$ ]] && has_php=true [[ "$filename" =~ \.js$ && ! "$filename" =~ \.min\.js$ ]] && has_js=true [[ "$filename" =~ \.(xml|xsd|html|graphqls|less)$ ]] && has_static=true - [[ "$filename" =~ \.ts$ && ! "$filename" =~ \.d\.ts$ ]] && has_ts=true if [[ "$status" =~ ^(added|modified|renamed|copied)$ ]]; then [[ "$filename" =~ \.(php|phtml)$ ]] && php_list+="${filename}"$'\n' [[ "$filename" =~ \.js$ && ! "$filename" =~ \.min\.js$ ]] && js_list+="${filename}"$'\n' @@ -189,12 +185,11 @@ jobs: [[ "$filename" =~ \.graphqls$ ]] && graphql_list+="${filename}"$'\n' [[ "$filename" =~ \.less$ ]] && less_list+="${filename}"$'\n' [[ "$filename" =~ \.php$ && "$status" == "added" ]] && new_php_list+="${filename}"$'\n' - [[ "$filename" =~ \.ts$ && ! "$filename" =~ \.d\.ts$ ]] && ts_list+="${filename}"$'\n' fi if [[ "$filename" =~ $copyright_exts && "$status" =~ ^(added|modified|renamed|copied)$ ]]; then has_copyright_files=true copyright_files+="${filename}"$'\n' - if [[ "$status" == "added" ]]; then + if [[ "$status" =~ ^(added|renamed|copied)$ ]]; then has_new_files=true copyright_added_list+="${filename}"$'\n' fi @@ -212,12 +207,10 @@ jobs: [ -n "$new_php_list" ] && printf '%s\n' "${new_php_list%$'\n'}" > /tmp/new_php.txt [ -n "$copyright_files" ] && printf '%s\n' "$copyright_files" > /tmp/copyright_changed.txt [ -n "$copyright_added_list" ] && printf '%s\n' "${copyright_added_list%$'\n'}" > /tmp/copyright_added.txt - [ -n "$ts_list" ] && printf '%s\n' "${ts_list%$'\n'}" > /tmp/changed_ts.txt echo "has_php=$has_php" >> "$GITHUB_OUTPUT" echo "has_js=$has_js" >> "$GITHUB_OUTPUT" echo "has_static=$has_static" >> "$GITHUB_OUTPUT" - echo "has_ts=$has_ts" >> "$GITHUB_OUTPUT" echo "has_new_files=$has_new_files" >> "$GITHUB_OUTPUT" echo "has_copyright_files=$has_copyright_files" >> "$GITHUB_OUTPUT" { @@ -230,7 +223,6 @@ jobs: echo "PHP files changed: $has_php" echo "JS files changed: $has_js" echo "Static files changed: $has_static" - echo "TS files changed: $has_ts" echo "Copyright-eligible files changed: $has_copyright_files" echo "Files: ${count_total} total | ${count_new} new | ${count_modified} modified | ${count_removed} deleted" @@ -239,7 +231,6 @@ jobs: echo "HAS_PHP=${{ steps.check.outputs.has_php }}" >> "$GITHUB_ENV" echo "HAS_JS=${{ steps.check.outputs.has_js }}" >> "$GITHUB_ENV" echo "HAS_STATIC=${{ steps.check.outputs.has_static }}" >> "$GITHUB_ENV" - echo "HAS_TS=${{ steps.check.outputs.has_ts }}" >> "$GITHUB_ENV" echo "HAS_COPYRIGHT_FILES=${{ steps.check.outputs.has_copyright_files }}" >> "$GITHUB_ENV" echo "HAS_PHP_OR_STATIC=${{ steps.check.outputs.has_php == 'true' || steps.check.outputs.has_static == 'true' }}" >> "$GITHUB_ENV" @@ -247,7 +238,7 @@ jobs: - uses: actions/checkout@v6 if: >- contains(format(',{0},', vars.PR_QA_ENABLED_JOBS), ',coding-standard,') && - (env.HAS_PHP == 'true' || env.HAS_JS == 'true' || env.HAS_STATIC == 'true' || env.HAS_TS == 'true') + (env.HAS_PHP == 'true' || env.HAS_JS == 'true' || env.HAS_STATIC == 'true') with: fetch-depth: 1 filter: blob:none @@ -280,7 +271,7 @@ jobs: id: install-mcs if: >- contains(format(',{0},', vars.PR_QA_ENABLED_JOBS), ',coding-standard,') && - (env.HAS_PHP == 'true' || env.HAS_JS == 'true' || env.HAS_STATIC == 'true' || env.HAS_TS == 'true') + (env.HAS_PHP == 'true' || env.HAS_JS == 'true' || env.HAS_STATIC == 'true') run: | set -euo pipefail @@ -342,7 +333,7 @@ jobs: echo ",$ENABLED," | grep -qF ",$check," && echo "true" && return echo "false" } - for check in php-lint phpcs phpcs-xml xml-lint phpcs-html phpcs-graphql phpcs-less phpmd strict-types fixture-reuse eslint typescript; do + for check in php-lint phpcs phpcs-xml xml-lint phpcs-html phpcs-graphql phpcs-less phpmd strict-types fixture-reuse eslint; do key="${check//-/_}" echo "${key}=$(is_enabled "$check")" >> "$GITHUB_OUTPUT" done @@ -402,7 +393,7 @@ jobs: all_files=$(mktemp) for f in /tmp/changed_php.txt /tmp/changed_js.txt /tmp/changed_xml.txt \ /tmp/changed_html.txt /tmp/changed_graphqls.txt /tmp/changed_less.txt \ - /tmp/changed_ts.txt /tmp/copyright_changed.txt; do + /tmp/copyright_changed.txt; do [ -f "$f" ] || continue cat "$f"; echo done | sort -u | grep -v '^$' > "$all_files" @@ -430,6 +421,10 @@ jobs: if: always() && steps.gate.outputs.php_lint == 'true' && env.HAS_PHP == 'true' run: | set -euo pipefail + if [ ! -f /tmp/changed_php.txt ] || [ ! -s /tmp/changed_php.txt ]; then + echo "No PHP files to check — skipping." + exit 0 + fi errors=0 while IFS= read -r file; do [ -n "$file" ] || continue @@ -450,17 +445,22 @@ jobs: if: always() && steps.gate.outputs.phpcs == 'true' && env.HAS_PHP == 'true' run: | set -euo pipefail - # Exclude Legacy sniffs that parse XML or load external data - # files from the Magento project tree (not available on forks). - EXCLUDE="Magento2.Legacy.ObsoleteConfigNodes" - EXCLUDE="$EXCLUDE,Magento2.Legacy.Layout" - EXCLUDE="$EXCLUDE,Magento2.Legacy.ObsoleteSystemConfiguration" - EXCLUDE="$EXCLUDE,Magento2.Legacy.ObsoleteAcl" - EXCLUDE="$EXCLUDE,Magento2.Legacy.ObsoleteMenu" - EXCLUDE="$EXCLUDE,Magento2.Legacy.ClassReferencesInConfigurationFiles" - EXCLUDE="$EXCLUDE,Magento2.Legacy.ModuleXML" - EXCLUDE="$EXCLUDE,Magento2.Legacy.WidgetXML" - EXCLUDE="$EXCLUDE,Magento2.Legacy.RestrictedCode" + EXCLUDE=$(python3 - <<'PY' + import os + sniff_dir = 'mcs/Magento2/Sniffs/Legacy' + exclude_names = { + 'Layout', 'ObsoleteConfigNodes', 'ObsoleteSystemConfiguration', + 'ObsoleteAcl', 'ObsoleteMenu', 'ClassReferencesInConfigurationFiles', + 'ModuleXML', 'WidgetXML', 'RestrictedCode', + } + sniffs = sorted([ + 'Magento2.Legacy.' + name + for name in exclude_names + if os.path.exists(f'{sniff_dir}/{name}Sniff.php') + ]) + print(','.join(sniffs)) + PY + ) .github/scripts/run-phpcs.sh "PHP" /tmp/changed_php.txt "--exclude=$EXCLUDE" - name: XML well-formedness lint @@ -468,6 +468,10 @@ jobs: if: always() && steps.gate.outputs.xml_lint == 'true' && env.HAS_STATIC == 'true' run: | set -euo pipefail + if [ ! -f /tmp/changed_xml.txt ] || [ ! -s /tmp/changed_xml.txt ]; then + echo "No XML/XSD files to check — skipping." + exit 0 + fi sudo apt-get install -y -q libxml2-utils 2>/dev/null errors=0 while IFS= read -r file; do @@ -487,7 +491,26 @@ jobs: if: always() && steps.gate.outputs.phpcs_xml == 'true' && env.HAS_STATIC == 'true' run: | set -euo pipefail - .github/scripts/run-phpcs.sh "XML/XSD" /tmp/changed_xml.txt "--extensions=xml,xsd" + grep -E '^(app/code/|lib/internal/|app/design/|dev/tests/|pub/|setup/|phpserver/)' /tmp/changed_xml.txt 2>/dev/null > /tmp/changed_xml_phpcs.txt || true + python3 - <<'PY' + import xml.etree.ElementTree as ET, sys + src = 'mcs/Magento2/ruleset.xml' + try: + root = ET.parse(src).getroot() + except Exception as e: + print(f"Could not parse {src}: {e}", file=sys.stderr) + sys.exit(1) + rules = [r.get('ref') for r in root.findall('rule') + if any(p.text and r'\.xml$' in p.text for p in r.findall('exclude-pattern'))] + lines = ['<?xml version="1.0"?>', '<ruleset name="Magento2-XML-XSD">', ' <rule ref="Magento2"/>'] + for ref in rules: + lines += [f' <rule ref="{ref}">', r' <exclude-pattern>*\.xsd$</exclude-pattern>', ' </rule>'] + lines.append('</ruleset>') + open('/tmp/phpcs-xml-ruleset.xml', 'w').write('\n'.join(lines)) + print(f"Generated /tmp/phpcs-xml-ruleset.xml with XSD exclusions for: {', '.join(rules) or 'none'}") + PY + PHPCS_STANDARD=/tmp/phpcs-xml-ruleset.xml \ + .github/scripts/run-phpcs.sh "XML/XSD" /tmp/changed_xml_phpcs.txt "--extensions=xml,xsd" - name: Run PHPCS for HTML id: phpcs-html @@ -508,6 +531,10 @@ jobs: if: always() && steps.gate.outputs.phpcs_less == 'true' && env.HAS_STATIC == 'true' run: | set -euo pipefail + if [ ! -f /tmp/changed_less.txt ] || [ ! -s /tmp/changed_less.txt ]; then + echo "No LESS files to check — skipping PHPCS LESS." + exit 0 + fi # Filter against Jenkins LESS blacklist (legacy files with known violations) bl="/tmp/magento2-static/dev/tests/static/testsuite/Magento/Test/Less/_files/blacklist" @@ -595,6 +622,7 @@ jobs: fi phpmd_exit=0 + phpmd_stderr=$(mktemp) batch_size=20 for ((i=0; i<${#files[@]}; i+=batch_size)); do batch_files=("${files[@]:i:batch_size}") @@ -605,17 +633,27 @@ jobs: --format=text \ --ruleset="$ruleset" \ --suffixes=php --suffixes=phtml \ - --no-progress 2>/dev/null || phpmd_exit=$? + --no-progress 2>>"$phpmd_stderr" || phpmd_exit=$? else timeout 120 php -d auto_prepend_file="$prepend_file" -d memory_limit=512M \ "$phpmd_bin" \ "$batch_list" \ text \ "$ruleset" \ - --suffixes=php,phtml 2>/dev/null || phpmd_exit=$? + --suffixes=php,phtml 2>>"$phpmd_stderr" || phpmd_exit=$? fi [ "$phpmd_exit" -ne 0 ] && [ "$phpmd_exit" -ne 2 ] && break done + # If PHPMD exited cleanly (no violations, exit 0) but produced stderr, it likely + # means pdepend failed to parse some files without signalling an error — silent + # coverage gap. PHPMD 3.x also writes GitHub annotation lines (::warning::) to + # stderr on top of the text violations on stdout; those are normal and appear only + # when violations are found (exit 2), so we only inspect stderr on exit 0. + if [ "$phpmd_exit" -eq 0 ] && [ -s "$phpmd_stderr" ]; then + echo "::warning::PHPMD produced error output — some files may not have been analysed (pdepend parse failure?):" + while IFS= read -r line; do echo "::warning::$line"; done < "$phpmd_stderr" + fi + rm -f "$phpmd_stderr" if [ "$phpmd_exit" -eq 124 ]; then echo "::error::PHPMD batch timed out (120 s). The PR may have too many complex files for a single batch. Consider splitting the PR." exit 1 @@ -689,6 +727,8 @@ jobs: - name: Check copyright headers id: copyright if: always() && steps.install-mcs.outputs.ready == 'true' && env.HAS_COPYRIGHT_FILES == 'true' + env: + GH_TOKEN: ${{ github.token }} run: | set -euo pipefail if [ ! -f /tmp/copyright_changed.txt ] || [ ! -s /tmp/copyright_changed.txt ]; then @@ -696,12 +736,28 @@ jobs: exit 0 fi - # Pre-fetch base versions so the PHP script needs no shell execution + # Pre-fetch base versions for copyright comparison. + # Primary: git ls-tree (tree objects from the earlier --filter=blob:none fetch) to + # get the blob SHA, then git cat-file to fetch the blob content via lazy partial-clone. + # Fallback: GitHub API for files whose subtree objects are missing from the local + # partial clone (known limitation with recently-added directories on shallow fetches). mkdir -p /tmp/copyright_base while IFS= read -r f; do [ -z "$f" ] && continue - mkdir -p "/tmp/copyright_base/$(dirname "$f")" - git show "${base_sha}:${f}" > "/tmp/copyright_base/${f}" 2>/dev/null || true + mkdir -p "/tmp/copyright_base/$(dirname "$f")" 2>/dev/null || continue + blob=$(git ls-tree "$base_sha" -- "$f" 2>/dev/null | awk 'NR==1{print $3}') + if [ -n "$blob" ]; then + git cat-file blob "$blob" > "/tmp/copyright_base/${f}" 2>/dev/null || true + else + # Tree object not in local partial clone (subtree may not have been fetched). + # Fetch base file content via GitHub API so the copyright check can run. + # For files that genuinely do not exist in base, the API returns 404 and the + # output file is empty — PHP treats that as "no base copyright" and skips. + gh api \ + --header "Accept: application/vnd.github.raw" \ + "repos/${{ github.repository }}/contents/${f}?ref=${base_sha}" \ + > "/tmp/copyright_base/${f}" 2>/dev/null || true + fi done < /tmp/copyright_changed.txt added_flag="" @@ -720,6 +776,10 @@ jobs: if: always() && steps.gate.outputs.eslint == 'true' && env.HAS_JS == 'true' run: | set -euo pipefail + if [ ! -f /tmp/changed_js.txt ] || [ ! -s /tmp/changed_js.txt ]; then + echo "No JS files to check — skipping ESLint." + exit 0 + fi # Apply Jenkins whitelist then blacklist — both live in CE repo sparse clone. # Whitelist defines which files are expected to comply (app/code, app/design, @@ -795,45 +855,6 @@ jobs: -c mcs/eslint/eslint.config.mjs \ "${js_args[@]}" - # ── TypeScript ──────────────────────────────────────────────── - - - name: Run TypeScript checks - id: typescript - if: always() && steps.gate.outputs.typescript == 'true' && env.HAS_TS == 'true' - run: | - set -euo pipefail - npm install --prefix /tmp/ts-tools typescript tslint 2>/dev/null - TSC=/tmp/ts-tools/node_modules/.bin/tsc - TSLINT=/tmp/ts-tools/node_modules/.bin/tslint - - mapfile -t ts_files < /tmp/changed_ts.txt - - # Fetch tslint.json from HEAD if present (compiler options only — do not use - # tsconfig.json include paths, which would try to compile the full project tree) - _tmp=$(mktemp) - if git show "HEAD:tslint.json" > "$_tmp" 2>/dev/null && [ -s "$_tmp" ]; then - mv "$_tmp" tslint.json - echo "Using repo tslint.json" - else - rm -f "$_tmp" - cp .github/scripts/tslint.json tslint.json - echo "Using bundled .github/scripts/tslint.json (repo has no tslint.json)" - fi - - tslint_exit=0 - tsc_exit=0 - - # tslint — mirrors npm run test:static:log - "$TSLINT" --format stylish "${ts_files[@]}" || tslint_exit=$? - - # tsc --noEmit --noResolve — mirrors npm run test:errors:log - # --noResolve skips import resolution so only the changed files are needed - "$TSC" --noEmit --noResolve --allowSyntheticDefaultImports \ - --esModuleInterop --strict --target ES2020 \ - "${ts_files[@]}" || tsc_exit=$? - - [ "$tslint_exit" -gt 0 ] || [ "$tsc_exit" -gt 0 ] && exit 1 || true - - name: Coding standard results summary if: always() && steps.install-mcs.outputs.ready == 'true' run: | @@ -853,7 +874,6 @@ jobs: echo "| Fixture reuse | ${{ steps.fixture-reuse.outcome == 'success' && '✅' || steps.fixture-reuse.outcome == 'skipped' && '⏭️' || '❌' }} |" echo "| Copyright | ${{ steps.copyright.outcome == 'success' && '✅' || steps.copyright.outcome == 'skipped' && '⏭️' || '❌' }} |" echo "| ESLint | ${{ steps.eslint.outcome == 'success' && '✅' || steps.eslint.outcome == 'skipped' && '⏭️' || '❌' }} |" - echo "| TypeScript | ${{ steps.typescript.outcome == 'success' && '✅' || steps.typescript.outcome == 'skipped' && '⏭️' || '❌' }} |" } >> "$GITHUB_STEP_SUMMARY" # ── Linked PR aggregate gate ──────────────────────────────────── From 148d7081395e1a791d2334e33c4119f03aa866d2 Mon Sep 17 00:00:00 2001 From: Karishma Thakare <del57145@adobe.com> Date: Tue, 2 Jun 2026 23:28:26 +0530 Subject: [PATCH 54/83] ACQE-9694: [ATLH] Filters - Round 3 - Products Grid - Fixed indentation issue --- ...yXLeftThresholdForVirtualProductWithDefaultSourceTest.xml | 4 ++++ .../Test/AdminCreateVirtualProductOnSingleStockModeTest.xml | 4 ++++ .../AdminOutOfStockThresholdOnVirtualProductPageTest.xml | 4 ++++ ...gurationPageAndAppliedToSimpleProductOnTestSourceTest.xml | 4 ++++ ...ithVirtualProductDefaultSourceAfterPartialInvoiceTest.xml | 4 ++++ ...FullShipmentBundleProductCustomStockCustomWebsiteTest.xml | 4 ++++ ...reateCreditMemoTotalRefundSimpleProductNumericSkuTest.xml | 4 ++++ .../AdminCreateOrderWithGroupedProductDefaultStockTest.xml | 4 ++++ ...editMemoFullInvoiceConfigurableProductCustomStockTest.xml | 5 ++++- .../Test/Mftf/Test/AdminMSICreditMemoReturnToStockTest.xml | 4 ++++ ...ationPageTurnedOffForGroupedProductOnDefaultStockTest.xml | 4 ++++ ...StockOnConfigurationPageTurnedOffForSimpleProductTest.xml | 4 ++++ ...ockOnProductPageTurnedOffForDownloadableProductInTest.xml | 4 ++++ ...urceForSimpleProductsWithOutOfStockStatusOnSourceTest.xml | 4 ++++ ...ultAppliedToSimpleProductOnConfigurationAdminPageTest.xml | 4 ++++ ...rWithSimpleProductOnDefaultStockCanceledFromAdminTest.xml | 4 ++++ ...wnloadableProductInAdvancedInventoryOnProductPageTest.xml | 4 ++++ ...AdminReorderBundleProductCustomStockCustomWebsiteTest.xml | 4 ++++ ...SimpleProductQuantityInSingleStockModeViaTheAdminTest.xml | 4 ++++ ...plyOnlyXLeftThresholdForSimpleProductOnTestSourceTest.xml | 4 ++++ ...ationWithNegativeOutOfStockThresholdAndBackordersTest.xml | 4 ++++ ...geStockNoInAdvancedInventorySettingsOnProductPageTest.xml | 5 ++++- ...thSimpleProductWithInventoryOnDefaultAndTestStockTest.xml | 5 ++++- ...rderWithSimpleProductOnTestStockFromCustomWebsiteTest.xml | 4 ++++ ...oductPageAndAppliedToSimpleProductOnDefaultSourceTest.xml | 4 ++++ ...uctPageAndAppliedToSimpleProductOnSingleStockModeTest.xml | 4 ++++ ...figurableProductWhenAllChildProductsAreOutOfStockTest.xml | 4 ++++ ...ockWhenAllItsChildProductsGetOutOfStockOrDisabledTest.xml | 4 ++++ ...tOnDefaultStockAfterFullInvoiceAndPartialShipmentTest.xml | 4 ++++ ...CreatedWithChildProductsOnDefaultStockByAdminUserTest.xml | 4 ++++ ...deredDownloadableProductOnCustomStockFromHomepageTest.xml | 4 ++++ ...eredDownloadableProductOnDefaultStockFromHomepageTest.xml | 4 ++++ ...onPageTurnedOffForBundleProductOnTestStockInAdminTest.xml | 4 ++++ ...ctPageTurnedOffForBundleProductOnTestStockInAdminTest.xml | 4 ++++ ...ebsiteButNotAssignedToAnySourceCreatedByAdminUserTest.xml | 4 ++++ ...sChangedForBundleProductOnTestStockAndTestWebsiteTest.xml | 4 ++++ .../StockStatusChangedForBundleProductOnTestStockTest.xml | 4 ++++ ...StatusChangedForConfigurableProductOnDefaultStockTest.xml | 4 ++++ ...edForConfigurableProductOnTestStockAndTestWebsiteTest.xml | 4 ++++ ...ockStatusChangedForConfigurableProductOnTestStockTest.xml | 4 ++++ ...rderWithSimpleProductOnTestStockFromCustomWebsiteTest.xml | 4 ++++ ...orGroupedProductAfterPlacingOrderCountedCorrectlyTest.xml | 4 ++++ ...roStatusAsOrderedPartialAndBackOrderedAccordinglyTest.xml | 4 ++++ ...tCustomStockCustomWebsiteBySkuFromCustomerAccountTest.xml | 4 ++++ ...WithVirtualProductInSingleStockModeWithBackordersTest.xml | 4 ++++ ...oductWithMangeStockAsNoOnTestStockAndMainWebsitesTest.xml | 5 ++++- .../StockStatusChangedForGroupedProductOnTestStockTest.xml | 4 ++++ .../Mftf/Test/AsyncOrderStockReservationRollbackTest.xml | 4 ++++ .../Mftf/Test/AsyncOrderWithAsyncStockReservationTest.xml | 4 ++++ ...isualSwatchAbsenceOfAttributeWhenProductStocksOutTest.xml | 4 ++++ 50 files changed, 200 insertions(+), 4 deletions(-) diff --git a/Inventory/Test/Mftf/Test/AdminCanSetOnlyXLeftThresholdForVirtualProductWithDefaultSourceTest.xml b/Inventory/Test/Mftf/Test/AdminCanSetOnlyXLeftThresholdForVirtualProductWithDefaultSourceTest.xml index 9213ec3ea0df..45b576b4277b 100644 --- a/Inventory/Test/Mftf/Test/AdminCanSetOnlyXLeftThresholdForVirtualProductWithDefaultSourceTest.xml +++ b/Inventory/Test/Mftf/Test/AdminCanSetOnlyXLeftThresholdForVirtualProductWithDefaultSourceTest.xml @@ -66,6 +66,10 @@ </actionGroup> <deleteData createDataKey="createCategory1" stepKey="deletecreateCategory1"/> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> </after> <actionGroup ref="AdminGoToProductGridFilterResultsByInputEditProduct" stepKey="goToProductGridFilterResultsByInputEditProduct1"> diff --git a/Inventory/Test/Mftf/Test/AdminCreateVirtualProductOnSingleStockModeTest.xml b/Inventory/Test/Mftf/Test/AdminCreateVirtualProductOnSingleStockModeTest.xml index 6ca0af2936cc..9b9a668c3bcb 100644 --- a/Inventory/Test/Mftf/Test/AdminCreateVirtualProductOnSingleStockModeTest.xml +++ b/Inventory/Test/Mftf/Test/AdminCreateVirtualProductOnSingleStockModeTest.xml @@ -32,6 +32,10 @@ <after> <deleteData createDataKey="createCategory1" stepKey="deletecreateCategory1"/> <deleteData createDataKey="virtualProduct1" stepKey="deleteVirtualProduct"/> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> </after> diff --git a/Inventory/Test/Mftf/Test/AdminOutOfStockThresholdOnVirtualProductPageTest.xml b/Inventory/Test/Mftf/Test/AdminOutOfStockThresholdOnVirtualProductPageTest.xml index 0e49100c13e9..07f264e60e17 100644 --- a/Inventory/Test/Mftf/Test/AdminOutOfStockThresholdOnVirtualProductPageTest.xml +++ b/Inventory/Test/Mftf/Test/AdminOutOfStockThresholdOnVirtualProductPageTest.xml @@ -28,6 +28,10 @@ <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin1"/> </before> <after> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> <deleteData createDataKey="createProduct1" stepKey="deleteProduct1"/> <deleteData createDataKey="createCategory1" stepKey="deleteCategory1"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminBackordersEnabledOnConfigurationPageAndAppliedToSimpleProductOnTestSourceTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminBackordersEnabledOnConfigurationPageAndAppliedToSimpleProductOnTestSourceTest.xml index 2747209d92c4..bcf81b0226b1 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminBackordersEnabledOnConfigurationPageAndAppliedToSimpleProductOnTestSourceTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminBackordersEnabledOnConfigurationPageAndAppliedToSimpleProductOnTestSourceTest.xml @@ -106,6 +106,10 @@ <waitForPageLoad time="30" stepKey="waitForDefaultStockPageLoaded"/> <selectOption selector="{{AdminEditStockSalesChannelsSection.websites}}" userInput="Main Website" stepKey="selectDefaultWebsiteAsSalesChannelForDefaultStock"/> <click selector="{{AdminGridMainControls.saveAndContinue}}" stepKey="saveDefaultStock"/> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCancelOrderWithVirtualProductDefaultSourceAfterPartialInvoiceTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCancelOrderWithVirtualProductDefaultSourceAfterPartialInvoiceTest.xml index bb7abee91147..112d29c82089 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCancelOrderWithVirtualProductDefaultSourceAfterPartialInvoiceTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCancelOrderWithVirtualProductDefaultSourceAfterPartialInvoiceTest.xml @@ -62,6 +62,10 @@ <actionGroup ref="DisableSourceActionGroup" stepKey="disableCreatedCustomSource"> <argument name="sourceCode" value="$$customSource.source[source_code]$$"/> </actionGroup> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <deleteData createDataKey="category" stepKey="deleteCategory"/> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoAfterFullInvoiceFullShipmentBundleProductCustomStockCustomWebsiteTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoAfterFullInvoiceFullShipmentBundleProductCustomStockCustomWebsiteTest.xml index 357c6fac2f72..3259b3dbdba8 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoAfterFullInvoiceFullShipmentBundleProductCustomStockCustomWebsiteTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoAfterFullInvoiceFullShipmentBundleProductCustomStockCustomWebsiteTest.xml @@ -113,6 +113,10 @@ <deleteData createDataKey="stock" stepKey="deleteStock"/> <!--Delete all customers via API--> <helper class="Magento\Customer\Test\Mftf\Helper\CustomerApiHelper" method="deleteAllCustomersApi" stepKey="deleteAllCustomersViaApi"/> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundSimpleProductNumericSkuTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundSimpleProductNumericSkuTest.xml index b91b2beb7527..15763be63292 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundSimpleProductNumericSkuTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundSimpleProductNumericSkuTest.xml @@ -48,6 +48,10 @@ <actionGroup ref="DisableSourceActionGroup" stepKey="disableSource"> <argument name="sourceCode" value="$source.source[source_code]$"/> </actionGroup> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateOrderWithGroupedProductDefaultStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateOrderWithGroupedProductDefaultStockTest.xml index 67256610166d..9a6faa6ef0a2 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateOrderWithGroupedProductDefaultStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateOrderWithGroupedProductDefaultStockTest.xml @@ -52,6 +52,10 @@ </actionGroup> </before> <after> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <deleteData createDataKey="category" stepKey="deleteCategory"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialCreditMemoFullInvoiceConfigurableProductCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialCreditMemoFullInvoiceConfigurableProductCustomStockTest.xml index ec1475a997f5..8f13f9469087 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialCreditMemoFullInvoiceConfigurableProductCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialCreditMemoFullInvoiceConfigurableProductCustomStockTest.xml @@ -70,7 +70,10 @@ <argument name="websiteName" value="{{_defaultWebsite.name}}"/> </actionGroup> <actionGroup ref="AdminOrdersPageOpenActionGroup" stepKey="navigateToSalesOrderPage"/> - <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clickOnButtonToRemoveFiltersIfPresent"/> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminMSICreditMemoReturnToStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminMSICreditMemoReturnToStockTest.xml index d6f7df1e3394..92fef94c2dc2 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminMSICreditMemoReturnToStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminMSICreditMemoReturnToStockTest.xml @@ -41,6 +41,10 @@ <deleteData createDataKey="createMSISimpleProduct1" stepKey="deleteProduct"/> <deleteData createDataKey="createMSISimpleProduct2" stepKey="deleteProduct2"/> <!--Admin Logout--> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> <!-- Step 1: Create New Category --> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminManageStockOnConfigurationPageTurnedOffForGroupedProductOnDefaultStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminManageStockOnConfigurationPageTurnedOffForGroupedProductOnDefaultStockTest.xml index dda3a77485ea..4a6acad71339 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminManageStockOnConfigurationPageTurnedOffForGroupedProductOnDefaultStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminManageStockOnConfigurationPageTurnedOffForGroupedProductOnDefaultStockTest.xml @@ -56,6 +56,10 @@ <actionGroup ref="DisableSourceActionGroup" stepKey="disableAdditionalSource"> <argument name="sourceCode" value="$additionalSource.source[source_code]$"/> </actionGroup> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <!--Clean up created data.--> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminManageStockOnConfigurationPageTurnedOffForSimpleProductTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminManageStockOnConfigurationPageTurnedOffForSimpleProductTest.xml index d9dbb62f90ee..69be0dec9f3a 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminManageStockOnConfigurationPageTurnedOffForSimpleProductTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminManageStockOnConfigurationPageTurnedOffForSimpleProductTest.xml @@ -71,6 +71,10 @@ <actionGroup ref="CliCacheCleanActionGroup" stepKey="cleanCache"> <argument name="tags" value="full_page"/> </actionGroup> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminManageStockOnProductPageTurnedOffForDownloadableProductInTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminManageStockOnProductPageTurnedOffForDownloadableProductInTest.xml index 7307fad954e3..e401747b75cf 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminManageStockOnProductPageTurnedOffForDownloadableProductInTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminManageStockOnProductPageTurnedOffForDownloadableProductInTest.xml @@ -51,6 +51,10 @@ <actionGroup ref="DisableSourceActionGroup" stepKey="disableAdditionalSource"> <argument name="sourceCode" value="$$additionalSource.source[source_code]$$"/> </actionGroup> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <!--Clean up created data.--> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminMassActionTransferInventoryToSourceForSimpleProductsWithOutOfStockStatusOnSourceTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminMassActionTransferInventoryToSourceForSimpleProductsWithOutOfStockStatusOnSourceTest.xml index 3e5e46288c38..554ec8e08e73 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminMassActionTransferInventoryToSourceForSimpleProductsWithOutOfStockStatusOnSourceTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminMassActionTransferInventoryToSourceForSimpleProductsWithOutOfStockStatusOnSourceTest.xml @@ -89,6 +89,10 @@ <actionGroup ref="DisableSourceActionGroup" stepKey="disableFirstCreatedSource"> <argument name="sourceCode" value="$$createSource.source[source_code]$$"/> </actionGroup> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <deleteData createDataKey="createCategory" stepKey="deleteCreatedCategory"/> <deleteData createDataKey="createStock" stepKey="deleteCreatedStock"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminNotifyQuantityUseDefaultAppliedToSimpleProductOnConfigurationAdminPageTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminNotifyQuantityUseDefaultAppliedToSimpleProductOnConfigurationAdminPageTest.xml index d3a8bf2b6c0b..95350072b6a0 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminNotifyQuantityUseDefaultAppliedToSimpleProductOnConfigurationAdminPageTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminNotifyQuantityUseDefaultAppliedToSimpleProductOnConfigurationAdminPageTest.xml @@ -76,6 +76,10 @@ <comment userInput="Set 'Notify for Quantity Below' to '1' by default" stepKey="revertNotifyQtyBelowComment"/> <magentoCLI command="config:set cataloginventory/item_options/notify_stock_qty 1" stepKey="setNotifyForQuantityBelowToOne"/> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logOutFromAdminArea"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminOrderWithSimpleProductOnDefaultStockCanceledFromAdminTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminOrderWithSimpleProductOnDefaultStockCanceledFromAdminTest.xml index 328584111031..437c7304bc84 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminOrderWithSimpleProductOnDefaultStockCanceledFromAdminTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminOrderWithSimpleProductOnDefaultStockCanceledFromAdminTest.xml @@ -57,6 +57,10 @@ <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> <deleteData createDataKey="simpleCategory" stepKey="deleteCategory"/> <deleteData createDataKey="additionalStock" stepKey="deleteCustomStock"/> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminOutOfStockThresholdAppliedToDownloadableProductInAdvancedInventoryOnProductPageTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminOutOfStockThresholdAppliedToDownloadableProductInAdvancedInventoryOnProductPageTest.xml index 5a866f27cfe5..991ba3743f9d 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminOutOfStockThresholdAppliedToDownloadableProductInAdvancedInventoryOnProductPageTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminOutOfStockThresholdAppliedToDownloadableProductInAdvancedInventoryOnProductPageTest.xml @@ -48,6 +48,10 @@ <actionGroup ref="DisableSourceActionGroup" stepKey="disableAdditionalSource"> <argument name="sourceCode" value="$$additionalSource.source[source_code]$$"/> </actionGroup> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <!--Clean up created data.--> <deleteData createDataKey="category" stepKey="deleteCategory"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminReorderBundleProductCustomStockCustomWebsiteTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminReorderBundleProductCustomStockCustomWebsiteTest.xml index b46b0ebbd458..01282260483a 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminReorderBundleProductCustomStockCustomWebsiteTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminReorderBundleProductCustomStockCustomWebsiteTest.xml @@ -113,6 +113,10 @@ <deleteData createDataKey="stock" stepKey="deleteStock"/> <!--Delete all customers via API--> <helper class="Magento\Customer\Test\Mftf\Helper\CustomerApiHelper" method="deleteAllCustomersApi" stepKey="deleteAllCustomersViaApi"/> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminUpdateSimpleProductQuantityInSingleStockModeViaTheAdminTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminUpdateSimpleProductQuantityInSingleStockModeViaTheAdminTest.xml index b78676bf2963..d230aac0cfce 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminUpdateSimpleProductQuantityInSingleStockModeViaTheAdminTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminUpdateSimpleProductQuantityInSingleStockModeViaTheAdminTest.xml @@ -31,6 +31,10 @@ <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin1"/> </before> <after> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> <deleteData createDataKey="simpleCategory1" stepKey="deleteCategory1"/> <deleteData createDataKey="simpleProduct1" stepKey="deleteProduct1"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminUserApplyOnlyXLeftThresholdForSimpleProductOnTestSourceTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminUserApplyOnlyXLeftThresholdForSimpleProductOnTestSourceTest.xml index 66ca1fba38b4..503144f6bc26 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminUserApplyOnlyXLeftThresholdForSimpleProductOnTestSourceTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminUserApplyOnlyXLeftThresholdForSimpleProductOnTestSourceTest.xml @@ -104,6 +104,10 @@ <actionGroup ref="DisableSourceActionGroup" stepKey="disableCreatedSource"> <argument name="sourceCode" value="$$createSource.source[source_code]$$"/> </actionGroup> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminUserApplyOnlyXLeftTreshholdForSimpleProductOnTestSourceInCombinationWithNegativeOutOfStockThresholdAndBackordersTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminUserApplyOnlyXLeftTreshholdForSimpleProductOnTestSourceInCombinationWithNegativeOutOfStockThresholdAndBackordersTest.xml index 40062a34a301..0c48646b58b7 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminUserApplyOnlyXLeftTreshholdForSimpleProductOnTestSourceInCombinationWithNegativeOutOfStockThresholdAndBackordersTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminUserApplyOnlyXLeftTreshholdForSimpleProductOnTestSourceInCombinationWithNegativeOutOfStockThresholdAndBackordersTest.xml @@ -49,6 +49,10 @@ <actionGroup ref="DisableSourceActionGroup" stepKey="disableAdditionalSource"> <argument name="sourceCode" value="$$additionalSource.source[source_code]$$"/> </actionGroup> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <!--Clean up created data.--> <comment userInput="BIC workaround" stepKey="displayOutOfStockNo"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminUserCreateOrderFromCustomWebsiteWithSimpleProductWithManageStockNoInAdvancedInventorySettingsOnProductPageTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminUserCreateOrderFromCustomWebsiteWithSimpleProductWithManageStockNoInAdvancedInventorySettingsOnProductPageTest.xml index 33200a0f9ed8..228f2cca5841 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminUserCreateOrderFromCustomWebsiteWithSimpleProductWithManageStockNoInAdvancedInventorySettingsOnProductPageTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminUserCreateOrderFromCustomWebsiteWithSimpleProductWithManageStockNoInAdvancedInventorySettingsOnProductPageTest.xml @@ -81,7 +81,10 @@ <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> </actionGroup> - </after> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> +</after> <!-- Assign product to custom website --> <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="openProductGrid"/> <actionGroup ref="FilterProductGridBySkuActionGroup" stepKey="filterProduct1"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminUserCreateOrderFromTestWebsiteWithSimpleProductWithInventoryOnDefaultAndTestStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminUserCreateOrderFromTestWebsiteWithSimpleProductWithInventoryOnDefaultAndTestStockTest.xml index 82390a340e17..e06014164522 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminUserCreateOrderFromTestWebsiteWithSimpleProductWithInventoryOnDefaultAndTestStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminUserCreateOrderFromTestWebsiteWithSimpleProductWithInventoryOnDefaultAndTestStockTest.xml @@ -88,7 +88,10 @@ <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> </actionGroup> - </after> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> +</after> <actionGroup ref="AdminProductPageOpenByIdActionGroup" stepKey="goToProduct1"> <argument name="productId" value="$createProduct1.id$"/> </actionGroup> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminUserCreateOrderWithSimpleProductOnTestStockFromCustomWebsiteTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminUserCreateOrderWithSimpleProductOnTestStockFromCustomWebsiteTest.xml index 36862854c091..2511f2f298f5 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminUserCreateOrderWithSimpleProductOnTestStockFromCustomWebsiteTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminUserCreateOrderWithSimpleProductOnTestStockFromCustomWebsiteTest.xml @@ -85,6 +85,10 @@ </actionGroup> <deleteData createDataKey="stock" stepKey="deleteStock"/> <actionGroup ref="DisableAllSourcesActionGroup" stepKey="disableAllSources"/> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryAdminUi/Test/Mftf/Test/BackordersEnabledOnProductPageAndAppliedToSimpleProductOnDefaultSourceTest.xml b/InventoryAdminUi/Test/Mftf/Test/BackordersEnabledOnProductPageAndAppliedToSimpleProductOnDefaultSourceTest.xml index c95684952664..2972e388f04b 100644 --- a/InventoryAdminUi/Test/Mftf/Test/BackordersEnabledOnProductPageAndAppliedToSimpleProductOnDefaultSourceTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/BackordersEnabledOnProductPageAndAppliedToSimpleProductOnDefaultSourceTest.xml @@ -93,6 +93,10 @@ <actionGroup ref="DisableSourceActionGroup" stepKey="disableCreatedSource"> <argument name="sourceCode" value="$$createSource.source[source_code]$$"/> </actionGroup> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/BackordersEnabledOnProductPageAndAppliedToSimpleProductOnSingleStockModeTest.xml b/InventoryAdminUi/Test/Mftf/Test/BackordersEnabledOnProductPageAndAppliedToSimpleProductOnSingleStockModeTest.xml index 81d85f4e7fcb..695c1f1228b8 100644 --- a/InventoryAdminUi/Test/Mftf/Test/BackordersEnabledOnProductPageAndAppliedToSimpleProductOnSingleStockModeTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/BackordersEnabledOnProductPageAndAppliedToSimpleProductOnSingleStockModeTest.xml @@ -54,6 +54,10 @@ <waitForPageLoad time="30" stepKey="waitForPageLoad5"/> </before> <after> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/ConfigurableProductWhenAllChildProductsAreOutOfStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/ConfigurableProductWhenAllChildProductsAreOutOfStockTest.xml index b84aa4a62944..3ce48db01791 100755 --- a/InventoryAdminUi/Test/Mftf/Test/ConfigurableProductWhenAllChildProductsAreOutOfStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/ConfigurableProductWhenAllChildProductsAreOutOfStockTest.xml @@ -47,6 +47,10 @@ <actionGroup ref="AdminDeleteCreatedColorAttributeActionGroup" stepKey="deleteBlueColorAttribute"> <argument name="Color" value="{{colorProductAttribute3.name}}"/> </actionGroup> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/ConfigurableProductWithDropDownAttributeOnTestStockGetOutOfStockWhenAllItsChildProductsGetOutOfStockOrDisabledTest.xml b/InventoryAdminUi/Test/Mftf/Test/ConfigurableProductWithDropDownAttributeOnTestStockGetOutOfStockWhenAllItsChildProductsGetOutOfStockOrDisabledTest.xml index 62c551ecd5c8..6d85f45ddfe0 100755 --- a/InventoryAdminUi/Test/Mftf/Test/ConfigurableProductWithDropDownAttributeOnTestStockGetOutOfStockWhenAllItsChildProductsGetOutOfStockOrDisabledTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/ConfigurableProductWithDropDownAttributeOnTestStockGetOutOfStockWhenAllItsChildProductsGetOutOfStockOrDisabledTest.xml @@ -48,6 +48,10 @@ <argument name="Color" value="{{colorProductAttribute1.name}}"/> </actionGroup> <actionGroup ref="DisableAllSourcesActionGroup" stepKey="disableAllSources"/> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/CreditMemoCreatedWithPartialRefundWithSimpleProductOnDefaultStockAfterFullInvoiceAndPartialShipmentTest.xml b/InventoryAdminUi/Test/Mftf/Test/CreditMemoCreatedWithPartialRefundWithSimpleProductOnDefaultStockAfterFullInvoiceAndPartialShipmentTest.xml index 4243655ccf6d..a680d7a33a37 100644 --- a/InventoryAdminUi/Test/Mftf/Test/CreditMemoCreatedWithPartialRefundWithSimpleProductOnDefaultStockAfterFullInvoiceAndPartialShipmentTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/CreditMemoCreatedWithPartialRefundWithSimpleProductOnDefaultStockAfterFullInvoiceAndPartialShipmentTest.xml @@ -40,6 +40,10 @@ <deleteData createDataKey="simpleCategory" stepKey="deleteCategory"/> <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> <actionGroup ref="DisableAllSourcesActionGroup" stepKey="disableSources"/> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryAdminUi/Test/Mftf/Test/GroupedProductCreatedWithChildProductsOnDefaultStockByAdminUserTest.xml b/InventoryAdminUi/Test/Mftf/Test/GroupedProductCreatedWithChildProductsOnDefaultStockByAdminUserTest.xml index 04583476fcc3..fe3d21f79bba 100644 --- a/InventoryAdminUi/Test/Mftf/Test/GroupedProductCreatedWithChildProductsOnDefaultStockByAdminUserTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/GroupedProductCreatedWithChildProductsOnDefaultStockByAdminUserTest.xml @@ -120,6 +120,10 @@ <!--Disable all sources.--> <actionGroup ref="DisableAllSourcesActionGroup" stepKey="deleteSource"/> <!--Admin logout--> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Find the product that we just created using the product grid --> diff --git a/InventoryAdminUi/Test/Mftf/Test/GuestCustomerOrderedDownloadableProductOnCustomStockFromHomepageTest.xml b/InventoryAdminUi/Test/Mftf/Test/GuestCustomerOrderedDownloadableProductOnCustomStockFromHomepageTest.xml index 122ba8fc76a7..31653265b407 100644 --- a/InventoryAdminUi/Test/Mftf/Test/GuestCustomerOrderedDownloadableProductOnCustomStockFromHomepageTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/GuestCustomerOrderedDownloadableProductOnCustomStockFromHomepageTest.xml @@ -70,6 +70,10 @@ <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createStock" stepKey="deleteStock"/> <deleteData createDataKey="downloadableProduct" stepKey="deleteProduct"/> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryAdminUi/Test/Mftf/Test/GuestCustomerOrderedDownloadableProductOnDefaultStockFromHomepageTest.xml b/InventoryAdminUi/Test/Mftf/Test/GuestCustomerOrderedDownloadableProductOnDefaultStockFromHomepageTest.xml index 6d26dd2c8293..444521020503 100644 --- a/InventoryAdminUi/Test/Mftf/Test/GuestCustomerOrderedDownloadableProductOnDefaultStockFromHomepageTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/GuestCustomerOrderedDownloadableProductOnDefaultStockFromHomepageTest.xml @@ -49,6 +49,10 @@ <magentoCLI stepKey="disableGuestCheckoutForDownloadable" command="config:set catalog/downloadable/disable_guest_checkout 1" /> <magentoCLI stepKey="disableShareableDownloadableItems" command="config:set catalog/downloadable/shareable 0" /> <actionGroup ref="DisableAllSourcesActionGroup" stepKey="disableSources"/> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryAdminUi/Test/Mftf/Test/ManageStockOnConfigurationPageTurnedOffForBundleProductOnTestStockInAdminTest.xml b/InventoryAdminUi/Test/Mftf/Test/ManageStockOnConfigurationPageTurnedOffForBundleProductOnTestStockInAdminTest.xml index e053db779a53..d46e5e8f7e72 100644 --- a/InventoryAdminUi/Test/Mftf/Test/ManageStockOnConfigurationPageTurnedOffForBundleProductOnTestStockInAdminTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/ManageStockOnConfigurationPageTurnedOffForBundleProductOnTestStockInAdminTest.xml @@ -37,6 +37,10 @@ <deleteData createDataKey="createBundleProduct" stepKey="deleteBundleProduct"/> <deleteData createDataKey="createSubCategory" stepKey="deleteSubCategory"/> <actionGroup ref="DisableAllSourcesActionGroup" stepKey="disableAllSources"/> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/ManageStockOnProductPageTurnedOffForBundleProductOnTestStockInAdminTest.xml b/InventoryAdminUi/Test/Mftf/Test/ManageStockOnProductPageTurnedOffForBundleProductOnTestStockInAdminTest.xml index 5a8c8767b668..707fa0d91f34 100644 --- a/InventoryAdminUi/Test/Mftf/Test/ManageStockOnProductPageTurnedOffForBundleProductOnTestStockInAdminTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/ManageStockOnProductPageTurnedOffForBundleProductOnTestStockInAdminTest.xml @@ -34,6 +34,10 @@ <deleteData createDataKey="createBundleProduct" stepKey="deleteBundleProduct"/> <deleteData createDataKey="createSubCategory" stepKey="deleteSubCategory"/> <actionGroup ref="DisableAllSourcesActionGroup" stepKey="disableAllSources"/> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/SimpleProductAssignedToTestWebsiteButNotAssignedToAnySourceCreatedByAdminUserTest.xml b/InventoryAdminUi/Test/Mftf/Test/SimpleProductAssignedToTestWebsiteButNotAssignedToAnySourceCreatedByAdminUserTest.xml index 8b43d0a3ec29..c934b44aa9f1 100755 --- a/InventoryAdminUi/Test/Mftf/Test/SimpleProductAssignedToTestWebsiteButNotAssignedToAnySourceCreatedByAdminUserTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/SimpleProductAssignedToTestWebsiteButNotAssignedToAnySourceCreatedByAdminUserTest.xml @@ -53,6 +53,10 @@ <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> </actionGroup> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForBundleProductOnTestStockAndTestWebsiteTest.xml b/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForBundleProductOnTestStockAndTestWebsiteTest.xml index 3048cc6828a2..056b8bc7ab5a 100755 --- a/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForBundleProductOnTestStockAndTestWebsiteTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForBundleProductOnTestStockAndTestWebsiteTest.xml @@ -55,6 +55,10 @@ <argument name="indices" value=""/> </actionGroup> <actionGroup ref="DisableAllSourcesActionGroup" stepKey="disableAllSources"/> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForBundleProductOnTestStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForBundleProductOnTestStockTest.xml index 9e2592920f5a..cce099296f39 100755 --- a/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForBundleProductOnTestStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForBundleProductOnTestStockTest.xml @@ -37,6 +37,10 @@ <deleteData createDataKey="createBundleProduct" stepKey="deleteBundleProduct"/> <deleteData createDataKey="createSubCategory" stepKey="deleteSubCategory"/> <actionGroup ref="DisableAllSourcesActionGroup" stepKey="disableAllSources"/> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForConfigurableProductOnDefaultStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForConfigurableProductOnDefaultStockTest.xml index 9494361a6241..39a34a20a6b6 100755 --- a/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForConfigurableProductOnDefaultStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForConfigurableProductOnDefaultStockTest.xml @@ -50,6 +50,10 @@ <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> </actionGroup> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForConfigurableProductOnTestStockAndTestWebsiteTest.xml b/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForConfigurableProductOnTestStockAndTestWebsiteTest.xml index 674b4f3cee99..818f9cd83d23 100755 --- a/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForConfigurableProductOnTestStockAndTestWebsiteTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForConfigurableProductOnTestStockAndTestWebsiteTest.xml @@ -54,6 +54,10 @@ <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> </actionGroup> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForConfigurableProductOnTestStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForConfigurableProductOnTestStockTest.xml index b6686924d4c9..cb57301aca0e 100755 --- a/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForConfigurableProductOnTestStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForConfigurableProductOnTestStockTest.xml @@ -43,6 +43,10 @@ <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> </actionGroup> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerCreateOrderWithSimpleProductOnTestStockFromCustomWebsiteTest.xml b/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerCreateOrderWithSimpleProductOnTestStockFromCustomWebsiteTest.xml index 7dd94e1d76a5..f858e43af98a 100644 --- a/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerCreateOrderWithSimpleProductOnTestStockFromCustomWebsiteTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerCreateOrderWithSimpleProductOnTestStockFromCustomWebsiteTest.xml @@ -80,6 +80,10 @@ </actionGroup> <!--Delete all customers via API--> <helper class="Magento\Customer\Test\Mftf\Helper\CustomerApiHelper" method="deleteAllCustomersApi" stepKey="deleteAllCustomersViaApi"/> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> <magentoCLI command="config:set {{StorefrontDisableAddStoreCodeToUrls.path}} {{StorefrontDisableAddStoreCodeToUrls.value}}" diff --git a/InventoryAdminUi/Test/Mftf/Test/StorefrontSalableQuantityOnNonDefaultStockForGroupedProductAfterPlacingOrderCountedCorrectlyTest.xml b/InventoryAdminUi/Test/Mftf/Test/StorefrontSalableQuantityOnNonDefaultStockForGroupedProductAfterPlacingOrderCountedCorrectlyTest.xml index eba49b235439..de98b2802ef8 100644 --- a/InventoryAdminUi/Test/Mftf/Test/StorefrontSalableQuantityOnNonDefaultStockForGroupedProductAfterPlacingOrderCountedCorrectlyTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StorefrontSalableQuantityOnNonDefaultStockForGroupedProductAfterPlacingOrderCountedCorrectlyTest.xml @@ -44,6 +44,10 @@ <actionGroup ref="DisableSourceActionGroup" stepKey="disableCreatedCustomSource"> <argument name="sourceCode" value="$$additionalSource.source[source_code]$$"/> </actionGroup> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/ValidateAfterPlacingAnOrderWithZeroStatusAsOrderedPartialAndBackOrderedAccordinglyTest.xml b/InventoryAdminUi/Test/Mftf/Test/ValidateAfterPlacingAnOrderWithZeroStatusAsOrderedPartialAndBackOrderedAccordinglyTest.xml index d56caf73fa54..bad2a5ccfcf2 100644 --- a/InventoryAdminUi/Test/Mftf/Test/ValidateAfterPlacingAnOrderWithZeroStatusAsOrderedPartialAndBackOrderedAccordinglyTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/ValidateAfterPlacingAnOrderWithZeroStatusAsOrderedPartialAndBackOrderedAccordinglyTest.xml @@ -197,6 +197,10 @@ <actionGroup ref="DisableSourceActionGroup" stepKey="deleteSource"> <argument name="sourceCode" value="$source.source[source_code]$"/> </actionGroup> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryAdvancedCheckout/Test/Mftf/Test/CreateOrderWithConfigurableProductCustomStockCustomWebsiteBySkuFromCustomerAccountTest.xml b/InventoryAdvancedCheckout/Test/Mftf/Test/CreateOrderWithConfigurableProductCustomStockCustomWebsiteBySkuFromCustomerAccountTest.xml index 169b12e2eed5..41a656418233 100644 --- a/InventoryAdvancedCheckout/Test/Mftf/Test/CreateOrderWithConfigurableProductCustomStockCustomWebsiteBySkuFromCustomerAccountTest.xml +++ b/InventoryAdvancedCheckout/Test/Mftf/Test/CreateOrderWithConfigurableProductCustomStockCustomWebsiteBySkuFromCustomerAccountTest.xml @@ -95,6 +95,10 @@ </actionGroup> <!--Delete all customers via API--> <helper class="Magento\Customer\Test\Mftf\Helper\CustomerApiHelper" method="deleteAllCustomersApi" stepKey="deleteAllCustomersViaApi"/> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout" before="deleteStock"/> <deleteData createDataKey="additionalStock" stepKey="deleteStock" before="deleteConfigChildProductOne"/> <!--Revert "Add Store Code To URL" configuration.--> diff --git a/InventoryCatalogAdminUi/Test/Mftf/Test/AdminCreateOrderWithVirtualProductInSingleStockModeWithBackordersTest.xml b/InventoryCatalogAdminUi/Test/Mftf/Test/AdminCreateOrderWithVirtualProductInSingleStockModeWithBackordersTest.xml index 2c4407237187..e13d58a873e1 100644 --- a/InventoryCatalogAdminUi/Test/Mftf/Test/AdminCreateOrderWithVirtualProductInSingleStockModeWithBackordersTest.xml +++ b/InventoryCatalogAdminUi/Test/Mftf/Test/AdminCreateOrderWithVirtualProductInSingleStockModeWithBackordersTest.xml @@ -60,6 +60,10 @@ <actionGroup ref="AdminFormSaveAndCloseActionGroup" stepKey="saveAndClose"/> </before> <after> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createVirtualProduct" stepKey="deleteProduct"/> diff --git a/InventoryCatalogAdminUi/Test/Mftf/Test/OnlyXleftNotDisplayedForSimpleProductWithMangeStockAsNoOnTestStockAndMainWebsitesTest.xml b/InventoryCatalogAdminUi/Test/Mftf/Test/OnlyXleftNotDisplayedForSimpleProductWithMangeStockAsNoOnTestStockAndMainWebsitesTest.xml index e7646854c187..84fba404d0c8 100644 --- a/InventoryCatalogAdminUi/Test/Mftf/Test/OnlyXleftNotDisplayedForSimpleProductWithMangeStockAsNoOnTestStockAndMainWebsitesTest.xml +++ b/InventoryCatalogAdminUi/Test/Mftf/Test/OnlyXleftNotDisplayedForSimpleProductWithMangeStockAsNoOnTestStockAndMainWebsitesTest.xml @@ -52,7 +52,10 @@ <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCacheAfterDeletingTheStock"> <argument name="tags" value=""/> </actionGroup> - </after> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> +</after> <!-- Step2: Create the Subcategory --> <createData entity="_defaultCategory" stepKey="createCategory"/> diff --git a/InventoryGroupedProduct/Test/Mftf/Test/StockStatusChangedForGroupedProductOnTestStockTest.xml b/InventoryGroupedProduct/Test/Mftf/Test/StockStatusChangedForGroupedProductOnTestStockTest.xml index 22c92db4b742..73ed13ab94bf 100644 --- a/InventoryGroupedProduct/Test/Mftf/Test/StockStatusChangedForGroupedProductOnTestStockTest.xml +++ b/InventoryGroupedProduct/Test/Mftf/Test/StockStatusChangedForGroupedProductOnTestStockTest.xml @@ -58,6 +58,10 @@ <!--Disable all sources.--> <actionGroup ref="DisableAllSourcesActionGroup" stepKey="deleteSource"/> <!--Admin logout--> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Assign Test source to simple and virtual products --> diff --git a/InventorySalesAsyncOrder/Test/Mftf/Test/AsyncOrderStockReservationRollbackTest.xml b/InventorySalesAsyncOrder/Test/Mftf/Test/AsyncOrderStockReservationRollbackTest.xml index 8a28efd089c8..93089ab0c7df 100644 --- a/InventorySalesAsyncOrder/Test/Mftf/Test/AsyncOrderStockReservationRollbackTest.xml +++ b/InventorySalesAsyncOrder/Test/Mftf/Test/AsyncOrderStockReservationRollbackTest.xml @@ -39,6 +39,10 @@ <argument name="email" value="{{CustomerEntityOne.email}}"/> </actionGroup> <actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="resetGrid"/> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventorySalesAsyncOrder/Test/Mftf/Test/AsyncOrderWithAsyncStockReservationTest.xml b/InventorySalesAsyncOrder/Test/Mftf/Test/AsyncOrderWithAsyncStockReservationTest.xml index d1358789a051..611ffd14a483 100644 --- a/InventorySalesAsyncOrder/Test/Mftf/Test/AsyncOrderWithAsyncStockReservationTest.xml +++ b/InventorySalesAsyncOrder/Test/Mftf/Test/AsyncOrderWithAsyncStockReservationTest.xml @@ -45,6 +45,10 @@ <argument name="email" value="{{CustomerEntityOne.email}}"/> </actionGroup> <actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="resetGrid"/> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> diff --git a/InventorySwatchesFrontendUi/Test/Mftf/Test/StorefrontValidateVisualSwatchAbsenceOfAttributeWhenProductStocksOutTest.xml b/InventorySwatchesFrontendUi/Test/Mftf/Test/StorefrontValidateVisualSwatchAbsenceOfAttributeWhenProductStocksOutTest.xml index 97c54c35682c..cd9552992809 100644 --- a/InventorySwatchesFrontendUi/Test/Mftf/Test/StorefrontValidateVisualSwatchAbsenceOfAttributeWhenProductStocksOutTest.xml +++ b/InventorySwatchesFrontendUi/Test/Mftf/Test/StorefrontValidateVisualSwatchAbsenceOfAttributeWhenProductStocksOutTest.xml @@ -62,6 +62,10 @@ <actionGroup ref="DeleteCategoryActionGroup" stepKey="deleteCategory"> <argument name="categoryEntity" value="SimpleSubCategory"/> </actionGroup> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> From de5628446423afc22a877ad9fc093d6f78efa123 Mon Sep 17 00:00:00 2001 From: Karishma Thakare <del57145@adobe.com> Date: Tue, 2 Jun 2026 23:32:42 +0530 Subject: [PATCH 55/83] ACQE-9694: [ATLH] Filters - Round 3 - Products Grid - Fixed indentation issue --- ...ockNoInAdvancedInventorySettingsOnProductPageTest.xml | 3 ++- ...mpleProductWithInventoryOnDefaultAndTestStockTest.xml | 3 ++- ...tWithMangeStockAsNoOnTestStockAndMainWebsitesTest.xml | 9 +++++---- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminUserCreateOrderFromCustomWebsiteWithSimpleProductWithManageStockNoInAdvancedInventorySettingsOnProductPageTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminUserCreateOrderFromCustomWebsiteWithSimpleProductWithManageStockNoInAdvancedInventorySettingsOnProductPageTest.xml index 228f2cca5841..1ec3b0c769b5 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminUserCreateOrderFromCustomWebsiteWithSimpleProductWithManageStockNoInAdvancedInventorySettingsOnProductPageTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminUserCreateOrderFromCustomWebsiteWithSimpleProductWithManageStockNoInAdvancedInventorySettingsOnProductPageTest.xml @@ -84,7 +84,8 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> -</after> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> + </after> <!-- Assign product to custom website --> <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="openProductGrid"/> <actionGroup ref="FilterProductGridBySkuActionGroup" stepKey="filterProduct1"> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminUserCreateOrderFromTestWebsiteWithSimpleProductWithInventoryOnDefaultAndTestStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminUserCreateOrderFromTestWebsiteWithSimpleProductWithInventoryOnDefaultAndTestStockTest.xml index e06014164522..a2c60b96df3f 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminUserCreateOrderFromTestWebsiteWithSimpleProductWithInventoryOnDefaultAndTestStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminUserCreateOrderFromTestWebsiteWithSimpleProductWithInventoryOnDefaultAndTestStockTest.xml @@ -91,7 +91,8 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> -</after> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> + </after> <actionGroup ref="AdminProductPageOpenByIdActionGroup" stepKey="goToProduct1"> <argument name="productId" value="$createProduct1.id$"/> </actionGroup> diff --git a/InventoryCatalogAdminUi/Test/Mftf/Test/OnlyXleftNotDisplayedForSimpleProductWithMangeStockAsNoOnTestStockAndMainWebsitesTest.xml b/InventoryCatalogAdminUi/Test/Mftf/Test/OnlyXleftNotDisplayedForSimpleProductWithMangeStockAsNoOnTestStockAndMainWebsitesTest.xml index 84fba404d0c8..64bbfd44eb5e 100644 --- a/InventoryCatalogAdminUi/Test/Mftf/Test/OnlyXleftNotDisplayedForSimpleProductWithMangeStockAsNoOnTestStockAndMainWebsitesTest.xml +++ b/InventoryCatalogAdminUi/Test/Mftf/Test/OnlyXleftNotDisplayedForSimpleProductWithMangeStockAsNoOnTestStockAndMainWebsitesTest.xml @@ -52,10 +52,11 @@ <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCacheAfterDeletingTheStock"> <argument name="tags" value=""/> </actionGroup> - <!--Clear filter product listing grid--> - <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> - <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> -</after> + <!--Clear filter product listing grid--> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> + </after> <!-- Step2: Create the Subcategory --> <createData entity="_defaultCategory" stepKey="createCategory"/> From 226aa72c41017268442d755c32321cdb926c1c4e Mon Sep 17 00:00:00 2001 From: Karishma Thakare <del57145@adobe.com> Date: Wed, 3 Jun 2026 09:57:43 +0530 Subject: [PATCH 56/83] ACQE-9694: [ATLH] Filters - Round 3 - Products Grid - Fixed dependency issue --- Inventory/Test/Mftf/test-dependency-allowlist | 3 +++ InventoryAdminUi/Test/Mftf/test-dependency-allowlist | 3 +++ InventoryAdvancedCheckout/Test/Mftf/test-dependency-allowlist | 3 +++ InventoryGroupedProduct/Test/Mftf/test-dependency-allowlist | 3 +++ InventorySalesAsyncOrder/Test/Mftf/test-dependency-allowlist | 3 +++ .../Test/Mftf/test-dependency-allowlist | 3 +++ 6 files changed, 18 insertions(+) diff --git a/Inventory/Test/Mftf/test-dependency-allowlist b/Inventory/Test/Mftf/test-dependency-allowlist index 2837dd88a132..a073d0f1ceca 100644 --- a/Inventory/Test/Mftf/test-dependency-allowlist +++ b/Inventory/Test/Mftf/test-dependency-allowlist @@ -67,3 +67,6 @@ CheckoutSuccessMainSection ClickPlaceOrderActionGroup CheckoutPaymentSection TurnOffManageStockConfig + +AdminOpenCatalogProductPageActionGroup +ClearFiltersAdminProductGridActionGroup diff --git a/InventoryAdminUi/Test/Mftf/test-dependency-allowlist b/InventoryAdminUi/Test/Mftf/test-dependency-allowlist index ea1793e464f2..3c252eb95f74 100644 --- a/InventoryAdminUi/Test/Mftf/test-dependency-allowlist +++ b/InventoryAdminUi/Test/Mftf/test-dependency-allowlist @@ -63,3 +63,6 @@ AdminLeftNavigationMenuSubTitlesVisibleTest AdminMenuSection AdminOrdersGridClearFiltersActionGroup NewProduct + +AdminOpenCatalogProductPageActionGroup +ClearFiltersAdminProductGridActionGroup diff --git a/InventoryAdvancedCheckout/Test/Mftf/test-dependency-allowlist b/InventoryAdvancedCheckout/Test/Mftf/test-dependency-allowlist index 8474a0ea6c25..6e165c3af411 100644 --- a/InventoryAdvancedCheckout/Test/Mftf/test-dependency-allowlist +++ b/InventoryAdvancedCheckout/Test/Mftf/test-dependency-allowlist @@ -8,3 +8,6 @@ AddConfigurableProductBySkuFromCustomerAccountTest AddSimpleProductBySkuFromCustomerAccountTest AddSimpleOutOfStockProductBySkuFromCustomerAccountTest RegisterCustomOnStorefrontActionGroup + +AdminOpenCatalogProductPageActionGroup +ClearFiltersAdminProductGridActionGroup diff --git a/InventoryGroupedProduct/Test/Mftf/test-dependency-allowlist b/InventoryGroupedProduct/Test/Mftf/test-dependency-allowlist index f747a64e61f2..70439b938373 100644 --- a/InventoryGroupedProduct/Test/Mftf/test-dependency-allowlist +++ b/InventoryGroupedProduct/Test/Mftf/test-dependency-allowlist @@ -7,3 +7,6 @@ _defaultSource AdminProductSourcesGrid UnassignSourceFromProductActionGroup CliConsumerStartActionGroup + +AdminOpenCatalogProductPageActionGroup +ClearFiltersAdminProductGridActionGroup diff --git a/InventorySalesAsyncOrder/Test/Mftf/test-dependency-allowlist b/InventorySalesAsyncOrder/Test/Mftf/test-dependency-allowlist index 56fa7f3b11d9..98f96489fcb1 100644 --- a/InventorySalesAsyncOrder/Test/Mftf/test-dependency-allowlist +++ b/InventorySalesAsyncOrder/Test/Mftf/test-dependency-allowlist @@ -5,3 +5,6 @@ CliConsumerStartActionGroup AssertRejectedOrderInGridActionGroup AsyncOrderStockReservationTest AssertProcessedOrderInGridActionGroup + +AdminOpenCatalogProductPageActionGroup +ClearFiltersAdminProductGridActionGroup diff --git a/InventorySwatchesFrontendUi/Test/Mftf/test-dependency-allowlist b/InventorySwatchesFrontendUi/Test/Mftf/test-dependency-allowlist index a0f1db1b3e56..8d0db800efa5 100644 --- a/InventorySwatchesFrontendUi/Test/Mftf/test-dependency-allowlist +++ b/InventorySwatchesFrontendUi/Test/Mftf/test-dependency-allowlist @@ -41,3 +41,6 @@ StorefrontAddProductToCartWithQtyActionGroup StorefrontOpenCartFromMinicartActionGroup StorefrontClickProceedToCheckoutActionGroup ClickPlaceOrderActionGroup + +AdminOpenCatalogProductPageActionGroup +ClearFiltersAdminProductGridActionGroup From ecac3f79110184dfe3aff9c53e113a648e27e177 Mon Sep 17 00:00:00 2001 From: del72683 <del72683@adobe.com> Date: Wed, 3 Jun 2026 14:56:16 +0530 Subject: [PATCH 57/83] AC-17305::Addressing Integration Test Failures in 2.4.9-dev Composer package --- .../Indexer/SkuListsProcessorTest.php | 33 ++++++--- ...iteProductReindexOnNonDefaultStockTest.php | 40 +++++++++-- ...bleProductSalableOnNonDefaultStockTest.php | 70 +++++++++++++------ 3 files changed, 108 insertions(+), 35 deletions(-) diff --git a/InventoryBundleProductIndexer/Test/Integration/Indexer/SkuListsProcessorTest.php b/InventoryBundleProductIndexer/Test/Integration/Indexer/SkuListsProcessorTest.php index 7d01de27b514..d5604b4b8983 100644 --- a/InventoryBundleProductIndexer/Test/Integration/Indexer/SkuListsProcessorTest.php +++ b/InventoryBundleProductIndexer/Test/Integration/Indexer/SkuListsProcessorTest.php @@ -13,6 +13,7 @@ use Magento\Bundle\Test\Fixture\Option as BundleOptionFixture; use Magento\Bundle\Test\Fixture\Product as BundleProductFixture; use Magento\Catalog\Test\Fixture\Product as ProductFixture; +use Magento\Indexer\Test\Fixture\Indexer as IndexerFixture; use Magento\InventoryApi\Api\Data\StockInterface; use Magento\InventoryApi\Api\GetSourceItemsBySkuInterface; use Magento\InventoryApi\Api\SourceItemsSaveInterface; @@ -27,10 +28,14 @@ use Magento\InventoryReservations\Test\Fixture\Reservation as ReservationFixture; use Magento\InventorySalesApi\Model\GetStockItemDataInterface; use Magento\InventorySalesApi\Test\Fixture\StockSalesChannels as StockSalesChannelsFixture; +use Magento\Store\Test\Fixture\Group as StoreGroupFixture; +use Magento\Store\Test\Fixture\Store as StoreFixture; +use Magento\Store\Test\Fixture\Website as WebsiteFixture; use Magento\TestFramework\Fixture\DataFixture; use Magento\TestFramework\Fixture\DataFixtureStorage; use Magento\TestFramework\Fixture\DataFixtureStorageManager; use Magento\TestFramework\Fixture\DbIsolation; +use Magento\TestFramework\Fixture\ScopeFixture; use Magento\TestFramework\Helper\Bootstrap; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\DataProvider; @@ -86,6 +91,10 @@ protected function setUp(): void #[ DbIsolation(false), + DataFixture(ScopeFixture::class, ['type' => 'website', 'code' => 'base'], as: 'website1'), + DataFixture(WebsiteFixture::class, as: 'website2'), + DataFixture(StoreGroupFixture::class, ['website_id' => '$website2.id$'], 'group2'), + DataFixture(StoreFixture::class, ['store_group_id' => '$group2.id$'], 'store2'), DataFixture(SourceFixture::class, ['source_code' => 's2'], 'source2'), DataFixture(SourceFixture::class, ['source_code' => 's3'], 'source3'), DataFixture(StockFixture::class, as: 'stock2'), @@ -98,17 +107,20 @@ protected function setUp(): void ), DataFixture( StockSalesChannelsFixture::class, - ['stock_id' => '$stock2.stock_id$', 'sales_channels' => ['base']] + ['stock_id' => '$stock2.stock_id$', 'sales_channels' => ['$website2.code$']] ), - DataFixture( ProductFixture::class, - ['sku' => 'simple1', 'stock_item' => ['use_config_min_qty' => 0, 'min_qty' => 2]], + [ + 'sku' => 'simple1', + 'website_ids' => ['1', '$website2.id$'], + 'stock_item' => ['use_config_min_qty' => 0, 'min_qty' => 2], + ], 's1' ), - DataFixture(ProductFixture::class, ['sku' => 'simple2'], 's2'), - DataFixture(ProductFixture::class, ['sku' => 'simple3'], 's3'), - DataFixture(ProductFixture::class, ['sku' => 'simple4'], 's4'), + DataFixture(ProductFixture::class, ['sku' => 'simple2', 'website_ids' => ['1', '$website2.id$']], 's2'), + DataFixture(ProductFixture::class, ['sku' => 'simple3', 'website_ids' => ['1', '$website2.id$']], 's3'), + DataFixture(ProductFixture::class, ['sku' => 'simple4', 'website_ids' => ['1', '$website2.id$']], 's4'), DataFixture( SourceItemsFixture::class, [ @@ -136,7 +148,6 @@ protected function setUp(): void ], ] ), - DataFixture( BundleSelectionFixture::class, ['sku' => '$s1.sku$', 'qty' => 3, 'can_change_quantity' => 0], @@ -162,8 +173,14 @@ protected function setUp(): void DataFixture(BundleOptionFixture::class, ['product_links' => ['$link4$'], 'required' => false], 'opt3'), DataFixture( BundleProductFixture::class, - ['sku' => 'bundle1', '_options' => ['$opt1$', '$opt2$', '$opt3$'], 'shipment_type' => 1] + [ + 'sku' => 'bundle1', + 'website_ids' => ['1', '$website2.id$'], + '_options' => ['$opt1$', '$opt2$', '$opt3$'], + 'shipment_type' => 1, + ] ), + DataFixture(IndexerFixture::class), DataProvider('executeListDataProvider') ] /** diff --git a/InventoryCatalog/Test/Integration/CompositeProductReindexOnNonDefaultStockTest.php b/InventoryCatalog/Test/Integration/CompositeProductReindexOnNonDefaultStockTest.php index 4c8141073fe0..f118dee3c045 100644 --- a/InventoryCatalog/Test/Integration/CompositeProductReindexOnNonDefaultStockTest.php +++ b/InventoryCatalog/Test/Integration/CompositeProductReindexOnNonDefaultStockTest.php @@ -15,6 +15,7 @@ use Magento\ConfigurableProduct\Test\Fixture\Attribute as AttributeFixture; use Magento\ConfigurableProduct\Test\Fixture\Product as ConfigurableProductFixture; use Magento\GroupedProduct\Test\Fixture\Product as GroupedProductFixture; +use Magento\Indexer\Test\Fixture\Indexer as IndexerFixture; use Magento\InventoryApi\Test\Fixture\Source as SourceFixture; use Magento\InventoryApi\Test\Fixture\SourceItems as SourceItemsFixture; use Magento\InventoryApi\Test\Fixture\Stock as StockFixture; @@ -22,9 +23,13 @@ use Magento\InventoryIndexer\Model\ResourceModel\GetStockItemData; use Magento\InventorySalesApi\Model\GetStockItemDataInterface; use Magento\InventorySalesApi\Test\Fixture\StockSalesChannels as StockSalesChannelsFixture; +use Magento\Store\Test\Fixture\Group as StoreGroupFixture; +use Magento\Store\Test\Fixture\Store as StoreFixture; +use Magento\Store\Test\Fixture\Website as WebsiteFixture; use Magento\TestFramework\Fixture\DataFixture; use Magento\TestFramework\Fixture\DataFixtureStorageManager; use Magento\TestFramework\Fixture\DbIsolation; +use Magento\TestFramework\Fixture\ScopeFixture; use Magento\TestFramework\Helper\Bootstrap; use PHPUnit\Framework\TestCase; @@ -56,7 +61,11 @@ protected function setUp(): void #[ DbIsolation(false), - DataFixture(SourceFixture::class, as: 'source'), + DataFixture(ScopeFixture::class, ['type' => 'website', 'code' => 'base'], as: 'website1'), + DataFixture(WebsiteFixture::class, as: 'website2'), + DataFixture(StoreGroupFixture::class, ['website_id' => '$website2.id$'], 'group2'), + DataFixture(StoreFixture::class, ['store_group_id' => '$group2.id$'], 'store2'), + DataFixture(SourceFixture::class, ['source_code' => 'source_bundle'], 'source'), DataFixture(StockFixture::class, as: 'stock'), DataFixture( StockSourceLinksFixture::class, @@ -64,9 +73,13 @@ protected function setUp(): void ), DataFixture( StockSalesChannelsFixture::class, - ['stock_id' => '$stock.stock_id$', 'sales_channels' => ['base']] + ['stock_id' => '$stock.stock_id$', 'sales_channels' => ['$website2.code$']] + ), + DataFixture( + ProductFixture::class, + ['sku' => 'child-bundle', 'website_ids' => ['1', '$website2.id$']], + 'child' ), - DataFixture(ProductFixture::class, as: 'child'), DataFixture( SourceItemsFixture::class, [['sku' => '$child.sku$', 'source_code' => '$source.source_code$', 'quantity' => 10, 'status' => 1]] @@ -75,7 +88,12 @@ protected function setUp(): void DataFixture(BundleOptionFixture::class, ['product_links' => ['$link$'], 'required' => true], 'opt'), DataFixture( BundleProductFixture::class, - ['_options' => ['$opt$'], 'shipment_type' => 1], + [ + 'sku' => 'bundle-parent', + 'website_ids' => ['1', '$website2.id$'], + '_options' => ['$opt$'], + 'shipment_type' => 1, + ], 'parent_product' ), ] @@ -86,7 +104,11 @@ public function testShouldReindexBundleProductStockStatusAfterSave(): void #[ DbIsolation(false), - DataFixture(SourceFixture::class, as: 'source'), + DataFixture(ScopeFixture::class, ['type' => 'website', 'code' => 'base'], as: 'website1'), + DataFixture(WebsiteFixture::class, as: 'website2'), + DataFixture(StoreGroupFixture::class, ['website_id' => '$website2.id$'], 'group2'), + DataFixture(StoreFixture::class, ['store_group_id' => '$group2.id$'], 'store2'), + DataFixture(SourceFixture::class, ['source_code' => 'source_grouped'], 'source'), DataFixture(StockFixture::class, as: 'stock'), DataFixture( StockSourceLinksFixture::class, @@ -106,6 +128,7 @@ public function testShouldReindexBundleProductStockStatusAfterSave(): void ['product_links' => ['$child.sku$']], 'parent_product' ), + DataFixture(IndexerFixture::class), ] public function testShouldReindexGroupedProductStockStatusAfterSave(): void { @@ -114,7 +137,11 @@ public function testShouldReindexGroupedProductStockStatusAfterSave(): void #[ DbIsolation(false), - DataFixture(SourceFixture::class, as: 'source'), + DataFixture(ScopeFixture::class, ['type' => 'website', 'code' => 'base'], as: 'website1'), + DataFixture(WebsiteFixture::class, as: 'website2'), + DataFixture(StoreGroupFixture::class, ['website_id' => '$website2.id$'], 'group2'), + DataFixture(StoreFixture::class, ['store_group_id' => '$group2.id$'], 'store2'), + DataFixture(SourceFixture::class, ['source_code' => 'source_configurable'], 'source'), DataFixture(StockFixture::class, as: 'stock'), DataFixture( StockSourceLinksFixture::class, @@ -135,6 +162,7 @@ public function testShouldReindexGroupedProductStockStatusAfterSave(): void ['_options' => ['$attr$'],'_links' => ['$child$']], 'parent_product' ), + DataFixture(IndexerFixture::class), ] public function testShouldReindexConfigurableProductStockStatusAfterSave(): void { diff --git a/InventoryConfigurableProduct/Test/Integration/IsProductSalable/IsConfigurableProductSalableOnNonDefaultStockTest.php b/InventoryConfigurableProduct/Test/Integration/IsProductSalable/IsConfigurableProductSalableOnNonDefaultStockTest.php index 743892c86f7f..f8e602a37c68 100644 --- a/InventoryConfigurableProduct/Test/Integration/IsProductSalable/IsConfigurableProductSalableOnNonDefaultStockTest.php +++ b/InventoryConfigurableProduct/Test/Integration/IsProductSalable/IsConfigurableProductSalableOnNonDefaultStockTest.php @@ -10,17 +10,21 @@ use Magento\Catalog\Test\Fixture\Product as ProductFixture; use Magento\ConfigurableProduct\Test\Fixture\Attribute as AttributeFixture; use Magento\ConfigurableProduct\Test\Fixture\Product as ConfigurableProductFixture; -use Magento\Indexer\Test\Fixture\Indexer; +use Magento\Indexer\Test\Fixture\Indexer as IndexerFixture; use Magento\InventoryApi\Test\Fixture\Source as SourceFixture; use Magento\InventoryApi\Test\Fixture\SourceItems as SourceItemsFixture; use Magento\InventoryApi\Test\Fixture\Stock as StockFixture; use Magento\InventoryApi\Test\Fixture\StockSourceLinks as StockSourceLinksFixture; use Magento\InventorySalesApi\Api\AreProductsSalableInterface; use Magento\InventorySalesApi\Test\Fixture\StockSalesChannels as StockSalesChannelsFixture; +use Magento\Store\Test\Fixture\Group as StoreGroupFixture; +use Magento\Store\Test\Fixture\Store as StoreFixture; +use Magento\Store\Test\Fixture\Website as WebsiteFixture; use Magento\TestFramework\Fixture\DataFixture; use Magento\TestFramework\Fixture\DataFixtureStorage; use Magento\TestFramework\Fixture\DataFixtureStorageManager; use Magento\TestFramework\Fixture\DbIsolation; +use Magento\TestFramework\Fixture\ScopeFixture; use Magento\TestFramework\Helper\Bootstrap; use PHPUnit\Framework\TestCase; @@ -53,7 +57,11 @@ protected function setUp(): void #[ DbIsolation(false), - DataFixture(SourceFixture::class, ['source_code' => 'source_1'], 'source1'), + DataFixture(ScopeFixture::class, ['type' => 'website', 'code' => 'base'], as: 'website1'), + DataFixture(WebsiteFixture::class, as: 'website2'), + DataFixture(StoreGroupFixture::class, ['website_id' => '$website2.id$'], 'group2'), + DataFixture(StoreFixture::class, ['store_group_id' => '$group2.id$'], 'store2'), + DataFixture(SourceFixture::class, ['source_code' => 'source_salable'], 'source1'), DataFixture(StockFixture::class, as: 'stock'), DataFixture( StockSourceLinksFixture::class, @@ -61,15 +69,19 @@ protected function setUp(): void ), DataFixture( StockSalesChannelsFixture::class, - ['stock_id' => '$stock.stock_id$', 'sales_channels' => ['base']] + ['stock_id' => '$stock.stock_id$', 'sales_channels' => ['$website2.code$']] ), - DataFixture(Indexer::class, ['indexer_id' => 'inventory']), - DataFixture(ProductFixture::class, ['sku' => 'child-1'], 'child1'), - DataFixture(ProductFixture::class, ['sku' => 'child-2'], 'child2'), + DataFixture(ProductFixture::class, ['sku' => 'child-salable-1', 'website_ids' => ['1', '$website2.id$']], 'child1'), + DataFixture(ProductFixture::class, ['sku' => 'child-salable-2', 'website_ids' => ['1', '$website2.id$']], 'child2'), DataFixture(AttributeFixture::class, as: 'attr'), DataFixture( ConfigurableProductFixture::class, - ['_options' => ['$attr$'], '_links' => ['$child1$', '$child2$']], + [ + 'sku' => 'configurable-salable', + 'website_ids' => ['1', '$website2.id$'], + '_options' => ['$attr$'], + '_links' => ['$child1$', '$child2$'], + ], 'configurable' ), DataFixture( @@ -79,7 +91,7 @@ protected function setUp(): void ['sku' => '$child2.sku$', 'source_code' => '$source1.source_code$', 'quantity' => 100, 'status' => 1], ] ), - DataFixture(Indexer::class, ['indexer_id' => 'inventory']), + DataFixture(IndexerFixture::class), ] public function testConfigurableIsSalableWhenChildrenAreInStock(): void { @@ -94,7 +106,11 @@ public function testConfigurableIsSalableWhenChildrenAreInStock(): void #[ DbIsolation(false), - DataFixture(SourceFixture::class, ['source_code' => 'source_1'], 'source1'), + DataFixture(ScopeFixture::class, ['type' => 'website', 'code' => 'base'], as: 'website1'), + DataFixture(WebsiteFixture::class, as: 'website2'), + DataFixture(StoreGroupFixture::class, ['website_id' => '$website2.id$'], 'group2'), + DataFixture(StoreFixture::class, ['store_group_id' => '$group2.id$'], 'store2'), + DataFixture(SourceFixture::class, ['source_code' => 'source_oos'], 'source1'), DataFixture(StockFixture::class, as: 'stock'), DataFixture( StockSourceLinksFixture::class, @@ -102,15 +118,19 @@ public function testConfigurableIsSalableWhenChildrenAreInStock(): void ), DataFixture( StockSalesChannelsFixture::class, - ['stock_id' => '$stock.stock_id$', 'sales_channels' => ['base']] + ['stock_id' => '$stock.stock_id$', 'sales_channels' => ['$website2.code$']] ), - DataFixture(Indexer::class, ['indexer_id' => 'inventory']), - DataFixture(ProductFixture::class, ['sku' => 'child-1'], 'child1'), - DataFixture(ProductFixture::class, ['sku' => 'child-2'], 'child2'), + DataFixture(ProductFixture::class, ['sku' => 'child-oos-1', 'website_ids' => ['1', '$website2.id$']], 'child1'), + DataFixture(ProductFixture::class, ['sku' => 'child-oos-2', 'website_ids' => ['1', '$website2.id$']], 'child2'), DataFixture(AttributeFixture::class, as: 'attr'), DataFixture( ConfigurableProductFixture::class, - ['_options' => ['$attr$'], '_links' => ['$child1$', '$child2$']], + [ + 'sku' => 'configurable-oos', + 'website_ids' => ['1', '$website2.id$'], + '_options' => ['$attr$'], + '_links' => ['$child1$', '$child2$'], + ], 'configurable' ), DataFixture( @@ -120,7 +140,7 @@ public function testConfigurableIsSalableWhenChildrenAreInStock(): void ['sku' => '$child2.sku$', 'source_code' => '$source1.source_code$', 'quantity' => 0, 'status' => 0], ] ), - DataFixture(Indexer::class, ['indexer_id' => 'inventory']), + DataFixture(IndexerFixture::class), ] public function testConfigurableIsNotSalableWhenAllChildrenOutOfStock(): void { @@ -138,6 +158,10 @@ public function testConfigurableIsNotSalableWhenAllChildrenOutOfStock(): void #[ DbIsolation(false), + DataFixture(ScopeFixture::class, ['type' => 'website', 'code' => 'base'], as: 'website1'), + DataFixture(WebsiteFixture::class, as: 'website2'), + DataFixture(StoreGroupFixture::class, ['website_id' => '$website2.id$'], 'group2'), + DataFixture(StoreFixture::class, ['store_group_id' => '$group2.id$'], 'store2'), DataFixture(SourceFixture::class, ['source_code' => 'source_us'], 'sourceUs'), DataFixture(SourceFixture::class, ['source_code' => 'source_eu'], 'sourceEu'), DataFixture(StockFixture::class, as: 'stockUs'), @@ -151,15 +175,19 @@ public function testConfigurableIsNotSalableWhenAllChildrenOutOfStock(): void ), DataFixture( StockSalesChannelsFixture::class, - ['stock_id' => '$stockUs.stock_id$', 'sales_channels' => ['base']] + ['stock_id' => '$stockUs.stock_id$', 'sales_channels' => ['$website2.code$']] ), - DataFixture(Indexer::class, ['indexer_id' => 'inventory']), - DataFixture(ProductFixture::class, ['sku' => 'child-1'], 'child1'), - DataFixture(ProductFixture::class, ['sku' => 'child-2'], 'child2'), + DataFixture(ProductFixture::class, ['sku' => 'child-per-stock-1', 'website_ids' => ['1', '$website2.id$']], 'child1'), + DataFixture(ProductFixture::class, ['sku' => 'child-per-stock-2', 'website_ids' => ['1', '$website2.id$']], 'child2'), DataFixture(AttributeFixture::class, as: 'attr'), DataFixture( ConfigurableProductFixture::class, - ['_options' => ['$attr$'], '_links' => ['$child1$', '$child2$']], + [ + 'sku' => 'configurable-per-stock', + 'website_ids' => ['1', '$website2.id$'], + '_options' => ['$attr$'], + '_links' => ['$child1$', '$child2$'], + ], 'configurable' ), DataFixture( @@ -171,7 +199,7 @@ public function testConfigurableIsNotSalableWhenAllChildrenOutOfStock(): void ['sku' => '$child2.sku$', 'source_code' => '$sourceEu.source_code$', 'quantity' => 0, 'status' => 0], ] ), - DataFixture(Indexer::class, ['indexer_id' => 'inventory']), + DataFixture(IndexerFixture::class), ] public function testConfigurableSalabilityReflectsPerStockSourceAssignments(): void { From 3e607f35bd5c1c61bae0c486e7f758b415729d15 Mon Sep 17 00:00:00 2001 From: Karishma Thakare <del57145@adobe.com> Date: Wed, 3 Jun 2026 22:37:42 +0530 Subject: [PATCH 58/83] ACQE-9694: [ATLH] Filters - Round 3 - Products Grid - Fixed build failure --- ...OnlyXLeftThresholdForVirtualProductWithDefaultSourceTest.xml | 1 - .../Test/AdminCreateVirtualProductOnSingleStockModeTest.xml | 1 - .../Test/AdminOutOfStockThresholdOnVirtualProductPageTest.xml | 1 - Inventory/Test/Mftf/test-dependency-allowlist | 1 - ...nfigurationPageAndAppliedToSimpleProductOnTestSourceTest.xml | 2 -- ...erWithVirtualProductDefaultSourceAfterPartialInvoiceTest.xml | 1 - ...iceFullShipmentBundleProductCustomStockCustomWebsiteTest.xml | 1 - ...inCreateCreditMemoTotalRefundSimpleProductNumericSkuTest.xml | 1 - .../Test/AdminCreateOrderWithGroupedProductDefaultStockTest.xml | 1 - ...lCreditMemoFullInvoiceConfigurableProductCustomStockTest.xml | 1 - .../Test/Mftf/Test/AdminMSICreditMemoReturnToStockTest.xml | 1 - ...gurationPageTurnedOffForGroupedProductOnDefaultStockTest.xml | 1 - ...ageStockOnConfigurationPageTurnedOffForSimpleProductTest.xml | 1 - ...eStockOnProductPageTurnedOffForDownloadableProductInTest.xml | 1 - ...oSourceForSimpleProductsWithOutOfStockStatusOnSourceTest.xml | 1 - ...efaultAppliedToSimpleProductOnConfigurationAdminPageTest.xml | 2 -- ...rderWithSimpleProductOnDefaultStockCanceledFromAdminTest.xml | 1 - ...oDownloadableProductInAdvancedInventoryOnProductPageTest.xml | 1 - .../AdminReorderBundleProductCustomStockCustomWebsiteTest.xml | 1 - ...ateSimpleProductQuantityInSingleStockModeViaTheAdminTest.xml | 1 - ...rApplyOnlyXLeftThresholdForSimpleProductOnTestSourceTest.xml | 2 -- ...binationWithNegativeOutOfStockThresholdAndBackordersTest.xml | 1 - ...teOrderWithSimpleProductOnTestStockFromCustomWebsiteTest.xml | 1 - ...nProductPageAndAppliedToSimpleProductOnDefaultSourceTest.xml | 2 -- ...roductPageAndAppliedToSimpleProductOnSingleStockModeTest.xml | 1 - ...ConfigurableProductWhenAllChildProductsAreOutOfStockTest.xml | 1 - ...fStockWhenAllItsChildProductsGetOutOfStockOrDisabledTest.xml | 1 - ...ductOnDefaultStockAfterFullInvoiceAndPartialShipmentTest.xml | 1 - ...uctCreatedWithChildProductsOnDefaultStockByAdminUserTest.xml | 1 - ...rOrderedDownloadableProductOnCustomStockFromHomepageTest.xml | 1 - ...OrderedDownloadableProductOnDefaultStockFromHomepageTest.xml | 1 - ...ationPageTurnedOffForBundleProductOnTestStockInAdminTest.xml | 1 - ...oductPageTurnedOffForBundleProductOnTestStockInAdminTest.xml | 1 - ...stWebsiteButNotAssignedToAnySourceCreatedByAdminUserTest.xml | 1 - ...atusChangedForBundleProductOnTestStockAndTestWebsiteTest.xml | 1 - .../Test/StockStatusChangedForBundleProductOnTestStockTest.xml | 1 - ...ockStatusChangedForConfigurableProductOnDefaultStockTest.xml | 1 - ...angedForConfigurableProductOnTestStockAndTestWebsiteTest.xml | 1 - .../StockStatusChangedForConfigurableProductOnTestStockTest.xml | 1 - ...teOrderWithSimpleProductOnTestStockFromCustomWebsiteTest.xml | 1 - ...ckForGroupedProductAfterPlacingOrderCountedCorrectlyTest.xml | 1 - ...hZeroStatusAsOrderedPartialAndBackOrderedAccordinglyTest.xml | 1 - InventoryAdminUi/Test/Mftf/test-dependency-allowlist | 1 - ...ductCustomStockCustomWebsiteBySkuFromCustomerAccountTest.xml | 1 - InventoryAdvancedCheckout/Test/Mftf/test-dependency-allowlist | 1 - ...derWithVirtualProductInSingleStockModeWithBackordersTest.xml | 1 - .../Test/StockStatusChangedForGroupedProductOnTestStockTest.xml | 1 - InventoryGroupedProduct/Test/Mftf/test-dependency-allowlist | 1 - .../Test/Mftf/Test/AsyncOrderStockReservationRollbackTest.xml | 1 - .../Test/Mftf/Test/AsyncOrderWithAsyncStockReservationTest.xml | 1 - InventorySalesAsyncOrder/Test/Mftf/test-dependency-allowlist | 1 - ...teVisualSwatchAbsenceOfAttributeWhenProductStocksOutTest.xml | 1 - InventorySwatchesFrontendUi/Test/Mftf/test-dependency-allowlist | 1 - 53 files changed, 57 deletions(-) diff --git a/Inventory/Test/Mftf/Test/AdminCanSetOnlyXLeftThresholdForVirtualProductWithDefaultSourceTest.xml b/Inventory/Test/Mftf/Test/AdminCanSetOnlyXLeftThresholdForVirtualProductWithDefaultSourceTest.xml index 45b576b4277b..ffd7304ebe74 100644 --- a/Inventory/Test/Mftf/Test/AdminCanSetOnlyXLeftThresholdForVirtualProductWithDefaultSourceTest.xml +++ b/Inventory/Test/Mftf/Test/AdminCanSetOnlyXLeftThresholdForVirtualProductWithDefaultSourceTest.xml @@ -69,7 +69,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> </after> <actionGroup ref="AdminGoToProductGridFilterResultsByInputEditProduct" stepKey="goToProductGridFilterResultsByInputEditProduct1"> diff --git a/Inventory/Test/Mftf/Test/AdminCreateVirtualProductOnSingleStockModeTest.xml b/Inventory/Test/Mftf/Test/AdminCreateVirtualProductOnSingleStockModeTest.xml index 9b9a668c3bcb..4930fb77f34e 100644 --- a/Inventory/Test/Mftf/Test/AdminCreateVirtualProductOnSingleStockModeTest.xml +++ b/Inventory/Test/Mftf/Test/AdminCreateVirtualProductOnSingleStockModeTest.xml @@ -35,7 +35,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> </after> diff --git a/Inventory/Test/Mftf/Test/AdminOutOfStockThresholdOnVirtualProductPageTest.xml b/Inventory/Test/Mftf/Test/AdminOutOfStockThresholdOnVirtualProductPageTest.xml index 07f264e60e17..e059207ef5ca 100644 --- a/Inventory/Test/Mftf/Test/AdminOutOfStockThresholdOnVirtualProductPageTest.xml +++ b/Inventory/Test/Mftf/Test/AdminOutOfStockThresholdOnVirtualProductPageTest.xml @@ -31,7 +31,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> <deleteData createDataKey="createProduct1" stepKey="deleteProduct1"/> <deleteData createDataKey="createCategory1" stepKey="deleteCategory1"/> diff --git a/Inventory/Test/Mftf/test-dependency-allowlist b/Inventory/Test/Mftf/test-dependency-allowlist index a073d0f1ceca..61d27d6a0785 100644 --- a/Inventory/Test/Mftf/test-dependency-allowlist +++ b/Inventory/Test/Mftf/test-dependency-allowlist @@ -67,6 +67,5 @@ CheckoutSuccessMainSection ClickPlaceOrderActionGroup CheckoutPaymentSection TurnOffManageStockConfig - AdminOpenCatalogProductPageActionGroup ClearFiltersAdminProductGridActionGroup diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminBackordersEnabledOnConfigurationPageAndAppliedToSimpleProductOnTestSourceTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminBackordersEnabledOnConfigurationPageAndAppliedToSimpleProductOnTestSourceTest.xml index bcf81b0226b1..074e76820be5 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminBackordersEnabledOnConfigurationPageAndAppliedToSimpleProductOnTestSourceTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminBackordersEnabledOnConfigurationPageAndAppliedToSimpleProductOnTestSourceTest.xml @@ -109,8 +109,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCancelOrderWithVirtualProductDefaultSourceAfterPartialInvoiceTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCancelOrderWithVirtualProductDefaultSourceAfterPartialInvoiceTest.xml index 112d29c82089..e6eec0a61e54 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCancelOrderWithVirtualProductDefaultSourceAfterPartialInvoiceTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCancelOrderWithVirtualProductDefaultSourceAfterPartialInvoiceTest.xml @@ -65,7 +65,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <deleteData createDataKey="category" stepKey="deleteCategory"/> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoAfterFullInvoiceFullShipmentBundleProductCustomStockCustomWebsiteTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoAfterFullInvoiceFullShipmentBundleProductCustomStockCustomWebsiteTest.xml index 3259b3dbdba8..8eb1497f1e2c 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoAfterFullInvoiceFullShipmentBundleProductCustomStockCustomWebsiteTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoAfterFullInvoiceFullShipmentBundleProductCustomStockCustomWebsiteTest.xml @@ -116,7 +116,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundSimpleProductNumericSkuTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundSimpleProductNumericSkuTest.xml index 15763be63292..e4b0e3c3c868 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundSimpleProductNumericSkuTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateCreditMemoTotalRefundSimpleProductNumericSkuTest.xml @@ -51,7 +51,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreateOrderWithGroupedProductDefaultStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreateOrderWithGroupedProductDefaultStockTest.xml index 9a6faa6ef0a2..6f43d06b08e9 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreateOrderWithGroupedProductDefaultStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreateOrderWithGroupedProductDefaultStockTest.xml @@ -55,7 +55,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <deleteData createDataKey="category" stepKey="deleteCategory"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialCreditMemoFullInvoiceConfigurableProductCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialCreditMemoFullInvoiceConfigurableProductCustomStockTest.xml index 8f13f9469087..43c12e6d16a1 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialCreditMemoFullInvoiceConfigurableProductCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminCreatePartialCreditMemoFullInvoiceConfigurableProductCustomStockTest.xml @@ -73,7 +73,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminMSICreditMemoReturnToStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminMSICreditMemoReturnToStockTest.xml index 92fef94c2dc2..b9fcd577c6d1 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminMSICreditMemoReturnToStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminMSICreditMemoReturnToStockTest.xml @@ -44,7 +44,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> <!-- Step 1: Create New Category --> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminManageStockOnConfigurationPageTurnedOffForGroupedProductOnDefaultStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminManageStockOnConfigurationPageTurnedOffForGroupedProductOnDefaultStockTest.xml index 4a6acad71339..9d6be17ec674 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminManageStockOnConfigurationPageTurnedOffForGroupedProductOnDefaultStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminManageStockOnConfigurationPageTurnedOffForGroupedProductOnDefaultStockTest.xml @@ -59,7 +59,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <!--Clean up created data.--> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminManageStockOnConfigurationPageTurnedOffForSimpleProductTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminManageStockOnConfigurationPageTurnedOffForSimpleProductTest.xml index 69be0dec9f3a..68427ece0ca3 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminManageStockOnConfigurationPageTurnedOffForSimpleProductTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminManageStockOnConfigurationPageTurnedOffForSimpleProductTest.xml @@ -74,7 +74,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminManageStockOnProductPageTurnedOffForDownloadableProductInTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminManageStockOnProductPageTurnedOffForDownloadableProductInTest.xml index e401747b75cf..6a767f9cf27a 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminManageStockOnProductPageTurnedOffForDownloadableProductInTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminManageStockOnProductPageTurnedOffForDownloadableProductInTest.xml @@ -54,7 +54,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <!--Clean up created data.--> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminMassActionTransferInventoryToSourceForSimpleProductsWithOutOfStockStatusOnSourceTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminMassActionTransferInventoryToSourceForSimpleProductsWithOutOfStockStatusOnSourceTest.xml index 554ec8e08e73..0e8a59e09876 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminMassActionTransferInventoryToSourceForSimpleProductsWithOutOfStockStatusOnSourceTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminMassActionTransferInventoryToSourceForSimpleProductsWithOutOfStockStatusOnSourceTest.xml @@ -92,7 +92,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <deleteData createDataKey="createCategory" stepKey="deleteCreatedCategory"/> <deleteData createDataKey="createStock" stepKey="deleteCreatedStock"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminNotifyQuantityUseDefaultAppliedToSimpleProductOnConfigurationAdminPageTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminNotifyQuantityUseDefaultAppliedToSimpleProductOnConfigurationAdminPageTest.xml index 95350072b6a0..1113b96ec8d7 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminNotifyQuantityUseDefaultAppliedToSimpleProductOnConfigurationAdminPageTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminNotifyQuantityUseDefaultAppliedToSimpleProductOnConfigurationAdminPageTest.xml @@ -79,8 +79,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - - <actionGroup ref="AdminLogoutActionGroup" stepKey="logOutFromAdminArea"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminOrderWithSimpleProductOnDefaultStockCanceledFromAdminTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminOrderWithSimpleProductOnDefaultStockCanceledFromAdminTest.xml index 437c7304bc84..3bba0e45acaa 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminOrderWithSimpleProductOnDefaultStockCanceledFromAdminTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminOrderWithSimpleProductOnDefaultStockCanceledFromAdminTest.xml @@ -60,7 +60,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminOutOfStockThresholdAppliedToDownloadableProductInAdvancedInventoryOnProductPageTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminOutOfStockThresholdAppliedToDownloadableProductInAdvancedInventoryOnProductPageTest.xml index 991ba3743f9d..54aab1fbd398 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminOutOfStockThresholdAppliedToDownloadableProductInAdvancedInventoryOnProductPageTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminOutOfStockThresholdAppliedToDownloadableProductInAdvancedInventoryOnProductPageTest.xml @@ -51,7 +51,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <!--Clean up created data.--> <deleteData createDataKey="category" stepKey="deleteCategory"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminReorderBundleProductCustomStockCustomWebsiteTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminReorderBundleProductCustomStockCustomWebsiteTest.xml index 01282260483a..cfdb04e91525 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminReorderBundleProductCustomStockCustomWebsiteTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminReorderBundleProductCustomStockCustomWebsiteTest.xml @@ -116,7 +116,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminUpdateSimpleProductQuantityInSingleStockModeViaTheAdminTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminUpdateSimpleProductQuantityInSingleStockModeViaTheAdminTest.xml index d230aac0cfce..178861cd0ba2 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminUpdateSimpleProductQuantityInSingleStockModeViaTheAdminTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminUpdateSimpleProductQuantityInSingleStockModeViaTheAdminTest.xml @@ -34,7 +34,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> <deleteData createDataKey="simpleCategory1" stepKey="deleteCategory1"/> <deleteData createDataKey="simpleProduct1" stepKey="deleteProduct1"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminUserApplyOnlyXLeftThresholdForSimpleProductOnTestSourceTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminUserApplyOnlyXLeftThresholdForSimpleProductOnTestSourceTest.xml index 503144f6bc26..6b658fef5640 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminUserApplyOnlyXLeftThresholdForSimpleProductOnTestSourceTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminUserApplyOnlyXLeftThresholdForSimpleProductOnTestSourceTest.xml @@ -107,8 +107,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminUserApplyOnlyXLeftTreshholdForSimpleProductOnTestSourceInCombinationWithNegativeOutOfStockThresholdAndBackordersTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminUserApplyOnlyXLeftTreshholdForSimpleProductOnTestSourceInCombinationWithNegativeOutOfStockThresholdAndBackordersTest.xml index 0c48646b58b7..50bf00799029 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminUserApplyOnlyXLeftTreshholdForSimpleProductOnTestSourceInCombinationWithNegativeOutOfStockThresholdAndBackordersTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminUserApplyOnlyXLeftTreshholdForSimpleProductOnTestSourceInCombinationWithNegativeOutOfStockThresholdAndBackordersTest.xml @@ -52,7 +52,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <!--Clean up created data.--> <comment userInput="BIC workaround" stepKey="displayOutOfStockNo"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminUserCreateOrderWithSimpleProductOnTestStockFromCustomWebsiteTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminUserCreateOrderWithSimpleProductOnTestStockFromCustomWebsiteTest.xml index 2511f2f298f5..e6becdac1ec5 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminUserCreateOrderWithSimpleProductOnTestStockFromCustomWebsiteTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminUserCreateOrderWithSimpleProductOnTestStockFromCustomWebsiteTest.xml @@ -88,7 +88,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryAdminUi/Test/Mftf/Test/BackordersEnabledOnProductPageAndAppliedToSimpleProductOnDefaultSourceTest.xml b/InventoryAdminUi/Test/Mftf/Test/BackordersEnabledOnProductPageAndAppliedToSimpleProductOnDefaultSourceTest.xml index 2972e388f04b..03b2b461d5a8 100644 --- a/InventoryAdminUi/Test/Mftf/Test/BackordersEnabledOnProductPageAndAppliedToSimpleProductOnDefaultSourceTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/BackordersEnabledOnProductPageAndAppliedToSimpleProductOnDefaultSourceTest.xml @@ -96,8 +96,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/BackordersEnabledOnProductPageAndAppliedToSimpleProductOnSingleStockModeTest.xml b/InventoryAdminUi/Test/Mftf/Test/BackordersEnabledOnProductPageAndAppliedToSimpleProductOnSingleStockModeTest.xml index 695c1f1228b8..0f92fb5da1fc 100644 --- a/InventoryAdminUi/Test/Mftf/Test/BackordersEnabledOnProductPageAndAppliedToSimpleProductOnSingleStockModeTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/BackordersEnabledOnProductPageAndAppliedToSimpleProductOnSingleStockModeTest.xml @@ -57,7 +57,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/ConfigurableProductWhenAllChildProductsAreOutOfStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/ConfigurableProductWhenAllChildProductsAreOutOfStockTest.xml index 3ce48db01791..df2847e4f08f 100755 --- a/InventoryAdminUi/Test/Mftf/Test/ConfigurableProductWhenAllChildProductsAreOutOfStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/ConfigurableProductWhenAllChildProductsAreOutOfStockTest.xml @@ -50,7 +50,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/ConfigurableProductWithDropDownAttributeOnTestStockGetOutOfStockWhenAllItsChildProductsGetOutOfStockOrDisabledTest.xml b/InventoryAdminUi/Test/Mftf/Test/ConfigurableProductWithDropDownAttributeOnTestStockGetOutOfStockWhenAllItsChildProductsGetOutOfStockOrDisabledTest.xml index 6d85f45ddfe0..34053ff417cb 100755 --- a/InventoryAdminUi/Test/Mftf/Test/ConfigurableProductWithDropDownAttributeOnTestStockGetOutOfStockWhenAllItsChildProductsGetOutOfStockOrDisabledTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/ConfigurableProductWithDropDownAttributeOnTestStockGetOutOfStockWhenAllItsChildProductsGetOutOfStockOrDisabledTest.xml @@ -51,7 +51,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/CreditMemoCreatedWithPartialRefundWithSimpleProductOnDefaultStockAfterFullInvoiceAndPartialShipmentTest.xml b/InventoryAdminUi/Test/Mftf/Test/CreditMemoCreatedWithPartialRefundWithSimpleProductOnDefaultStockAfterFullInvoiceAndPartialShipmentTest.xml index a680d7a33a37..70aa1f2e4e16 100644 --- a/InventoryAdminUi/Test/Mftf/Test/CreditMemoCreatedWithPartialRefundWithSimpleProductOnDefaultStockAfterFullInvoiceAndPartialShipmentTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/CreditMemoCreatedWithPartialRefundWithSimpleProductOnDefaultStockAfterFullInvoiceAndPartialShipmentTest.xml @@ -43,7 +43,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryAdminUi/Test/Mftf/Test/GroupedProductCreatedWithChildProductsOnDefaultStockByAdminUserTest.xml b/InventoryAdminUi/Test/Mftf/Test/GroupedProductCreatedWithChildProductsOnDefaultStockByAdminUserTest.xml index fe3d21f79bba..3798cf5400e6 100644 --- a/InventoryAdminUi/Test/Mftf/Test/GroupedProductCreatedWithChildProductsOnDefaultStockByAdminUserTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/GroupedProductCreatedWithChildProductsOnDefaultStockByAdminUserTest.xml @@ -123,7 +123,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Find the product that we just created using the product grid --> diff --git a/InventoryAdminUi/Test/Mftf/Test/GuestCustomerOrderedDownloadableProductOnCustomStockFromHomepageTest.xml b/InventoryAdminUi/Test/Mftf/Test/GuestCustomerOrderedDownloadableProductOnCustomStockFromHomepageTest.xml index 31653265b407..06491baabc96 100644 --- a/InventoryAdminUi/Test/Mftf/Test/GuestCustomerOrderedDownloadableProductOnCustomStockFromHomepageTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/GuestCustomerOrderedDownloadableProductOnCustomStockFromHomepageTest.xml @@ -73,7 +73,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryAdminUi/Test/Mftf/Test/GuestCustomerOrderedDownloadableProductOnDefaultStockFromHomepageTest.xml b/InventoryAdminUi/Test/Mftf/Test/GuestCustomerOrderedDownloadableProductOnDefaultStockFromHomepageTest.xml index 444521020503..7d7dccf15a27 100644 --- a/InventoryAdminUi/Test/Mftf/Test/GuestCustomerOrderedDownloadableProductOnDefaultStockFromHomepageTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/GuestCustomerOrderedDownloadableProductOnDefaultStockFromHomepageTest.xml @@ -52,7 +52,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryAdminUi/Test/Mftf/Test/ManageStockOnConfigurationPageTurnedOffForBundleProductOnTestStockInAdminTest.xml b/InventoryAdminUi/Test/Mftf/Test/ManageStockOnConfigurationPageTurnedOffForBundleProductOnTestStockInAdminTest.xml index d46e5e8f7e72..084b425cc518 100644 --- a/InventoryAdminUi/Test/Mftf/Test/ManageStockOnConfigurationPageTurnedOffForBundleProductOnTestStockInAdminTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/ManageStockOnConfigurationPageTurnedOffForBundleProductOnTestStockInAdminTest.xml @@ -40,7 +40,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/ManageStockOnProductPageTurnedOffForBundleProductOnTestStockInAdminTest.xml b/InventoryAdminUi/Test/Mftf/Test/ManageStockOnProductPageTurnedOffForBundleProductOnTestStockInAdminTest.xml index 707fa0d91f34..f2f7274deac6 100644 --- a/InventoryAdminUi/Test/Mftf/Test/ManageStockOnProductPageTurnedOffForBundleProductOnTestStockInAdminTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/ManageStockOnProductPageTurnedOffForBundleProductOnTestStockInAdminTest.xml @@ -37,7 +37,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/SimpleProductAssignedToTestWebsiteButNotAssignedToAnySourceCreatedByAdminUserTest.xml b/InventoryAdminUi/Test/Mftf/Test/SimpleProductAssignedToTestWebsiteButNotAssignedToAnySourceCreatedByAdminUserTest.xml index c934b44aa9f1..65f72b1fdc9c 100755 --- a/InventoryAdminUi/Test/Mftf/Test/SimpleProductAssignedToTestWebsiteButNotAssignedToAnySourceCreatedByAdminUserTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/SimpleProductAssignedToTestWebsiteButNotAssignedToAnySourceCreatedByAdminUserTest.xml @@ -56,7 +56,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForBundleProductOnTestStockAndTestWebsiteTest.xml b/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForBundleProductOnTestStockAndTestWebsiteTest.xml index 056b8bc7ab5a..5b27c6db510f 100755 --- a/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForBundleProductOnTestStockAndTestWebsiteTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForBundleProductOnTestStockAndTestWebsiteTest.xml @@ -58,7 +58,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForBundleProductOnTestStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForBundleProductOnTestStockTest.xml index cce099296f39..0775cf7ac695 100755 --- a/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForBundleProductOnTestStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForBundleProductOnTestStockTest.xml @@ -40,7 +40,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForConfigurableProductOnDefaultStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForConfigurableProductOnDefaultStockTest.xml index 39a34a20a6b6..b9fe0fbc6457 100755 --- a/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForConfigurableProductOnDefaultStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForConfigurableProductOnDefaultStockTest.xml @@ -53,7 +53,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForConfigurableProductOnTestStockAndTestWebsiteTest.xml b/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForConfigurableProductOnTestStockAndTestWebsiteTest.xml index 818f9cd83d23..3adcb7f2b4e5 100755 --- a/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForConfigurableProductOnTestStockAndTestWebsiteTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForConfigurableProductOnTestStockAndTestWebsiteTest.xml @@ -57,7 +57,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForConfigurableProductOnTestStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForConfigurableProductOnTestStockTest.xml index cb57301aca0e..1a292dc0f450 100755 --- a/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForConfigurableProductOnTestStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StockStatusChangedForConfigurableProductOnTestStockTest.xml @@ -46,7 +46,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerCreateOrderWithSimpleProductOnTestStockFromCustomWebsiteTest.xml b/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerCreateOrderWithSimpleProductOnTestStockFromCustomWebsiteTest.xml index f858e43af98a..2b331ef2b030 100644 --- a/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerCreateOrderWithSimpleProductOnTestStockFromCustomWebsiteTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StorefrontLoggedInCustomerCreateOrderWithSimpleProductOnTestStockFromCustomWebsiteTest.xml @@ -83,7 +83,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> <magentoCLI command="config:set {{StorefrontDisableAddStoreCodeToUrls.path}} {{StorefrontDisableAddStoreCodeToUrls.value}}" diff --git a/InventoryAdminUi/Test/Mftf/Test/StorefrontSalableQuantityOnNonDefaultStockForGroupedProductAfterPlacingOrderCountedCorrectlyTest.xml b/InventoryAdminUi/Test/Mftf/Test/StorefrontSalableQuantityOnNonDefaultStockForGroupedProductAfterPlacingOrderCountedCorrectlyTest.xml index de98b2802ef8..5a85f67fa0b1 100644 --- a/InventoryAdminUi/Test/Mftf/Test/StorefrontSalableQuantityOnNonDefaultStockForGroupedProductAfterPlacingOrderCountedCorrectlyTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/StorefrontSalableQuantityOnNonDefaultStockForGroupedProductAfterPlacingOrderCountedCorrectlyTest.xml @@ -47,7 +47,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" /> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> diff --git a/InventoryAdminUi/Test/Mftf/Test/ValidateAfterPlacingAnOrderWithZeroStatusAsOrderedPartialAndBackOrderedAccordinglyTest.xml b/InventoryAdminUi/Test/Mftf/Test/ValidateAfterPlacingAnOrderWithZeroStatusAsOrderedPartialAndBackOrderedAccordinglyTest.xml index bad2a5ccfcf2..5c223c44ba90 100644 --- a/InventoryAdminUi/Test/Mftf/Test/ValidateAfterPlacingAnOrderWithZeroStatusAsOrderedPartialAndBackOrderedAccordinglyTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/ValidateAfterPlacingAnOrderWithZeroStatusAsOrderedPartialAndBackOrderedAccordinglyTest.xml @@ -200,7 +200,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventoryAdminUi/Test/Mftf/test-dependency-allowlist b/InventoryAdminUi/Test/Mftf/test-dependency-allowlist index 3c252eb95f74..00c446c832fd 100644 --- a/InventoryAdminUi/Test/Mftf/test-dependency-allowlist +++ b/InventoryAdminUi/Test/Mftf/test-dependency-allowlist @@ -63,6 +63,5 @@ AdminLeftNavigationMenuSubTitlesVisibleTest AdminMenuSection AdminOrdersGridClearFiltersActionGroup NewProduct - AdminOpenCatalogProductPageActionGroup ClearFiltersAdminProductGridActionGroup diff --git a/InventoryAdvancedCheckout/Test/Mftf/Test/CreateOrderWithConfigurableProductCustomStockCustomWebsiteBySkuFromCustomerAccountTest.xml b/InventoryAdvancedCheckout/Test/Mftf/Test/CreateOrderWithConfigurableProductCustomStockCustomWebsiteBySkuFromCustomerAccountTest.xml index 41a656418233..9623e01e29ce 100644 --- a/InventoryAdvancedCheckout/Test/Mftf/Test/CreateOrderWithConfigurableProductCustomStockCustomWebsiteBySkuFromCustomerAccountTest.xml +++ b/InventoryAdvancedCheckout/Test/Mftf/Test/CreateOrderWithConfigurableProductCustomStockCustomWebsiteBySkuFromCustomerAccountTest.xml @@ -98,7 +98,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logout" before="deleteStock"/> <deleteData createDataKey="additionalStock" stepKey="deleteStock" before="deleteConfigChildProductOne"/> <!--Revert "Add Store Code To URL" configuration.--> diff --git a/InventoryAdvancedCheckout/Test/Mftf/test-dependency-allowlist b/InventoryAdvancedCheckout/Test/Mftf/test-dependency-allowlist index 6e165c3af411..565627478cd7 100644 --- a/InventoryAdvancedCheckout/Test/Mftf/test-dependency-allowlist +++ b/InventoryAdvancedCheckout/Test/Mftf/test-dependency-allowlist @@ -8,6 +8,5 @@ AddConfigurableProductBySkuFromCustomerAccountTest AddSimpleProductBySkuFromCustomerAccountTest AddSimpleOutOfStockProductBySkuFromCustomerAccountTest RegisterCustomOnStorefrontActionGroup - AdminOpenCatalogProductPageActionGroup ClearFiltersAdminProductGridActionGroup diff --git a/InventoryCatalogAdminUi/Test/Mftf/Test/AdminCreateOrderWithVirtualProductInSingleStockModeWithBackordersTest.xml b/InventoryCatalogAdminUi/Test/Mftf/Test/AdminCreateOrderWithVirtualProductInSingleStockModeWithBackordersTest.xml index e13d58a873e1..fee15e89c647 100644 --- a/InventoryCatalogAdminUi/Test/Mftf/Test/AdminCreateOrderWithVirtualProductInSingleStockModeWithBackordersTest.xml +++ b/InventoryCatalogAdminUi/Test/Mftf/Test/AdminCreateOrderWithVirtualProductInSingleStockModeWithBackordersTest.xml @@ -63,7 +63,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminArea"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createVirtualProduct" stepKey="deleteProduct"/> diff --git a/InventoryGroupedProduct/Test/Mftf/Test/StockStatusChangedForGroupedProductOnTestStockTest.xml b/InventoryGroupedProduct/Test/Mftf/Test/StockStatusChangedForGroupedProductOnTestStockTest.xml index 73ed13ab94bf..274a0b935ca6 100644 --- a/InventoryGroupedProduct/Test/Mftf/Test/StockStatusChangedForGroupedProductOnTestStockTest.xml +++ b/InventoryGroupedProduct/Test/Mftf/Test/StockStatusChangedForGroupedProductOnTestStockTest.xml @@ -61,7 +61,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Assign Test source to simple and virtual products --> diff --git a/InventoryGroupedProduct/Test/Mftf/test-dependency-allowlist b/InventoryGroupedProduct/Test/Mftf/test-dependency-allowlist index 70439b938373..984359560d33 100644 --- a/InventoryGroupedProduct/Test/Mftf/test-dependency-allowlist +++ b/InventoryGroupedProduct/Test/Mftf/test-dependency-allowlist @@ -7,6 +7,5 @@ _defaultSource AdminProductSourcesGrid UnassignSourceFromProductActionGroup CliConsumerStartActionGroup - AdminOpenCatalogProductPageActionGroup ClearFiltersAdminProductGridActionGroup diff --git a/InventorySalesAsyncOrder/Test/Mftf/Test/AsyncOrderStockReservationRollbackTest.xml b/InventorySalesAsyncOrder/Test/Mftf/Test/AsyncOrderStockReservationRollbackTest.xml index 93089ab0c7df..59225db6081e 100644 --- a/InventorySalesAsyncOrder/Test/Mftf/Test/AsyncOrderStockReservationRollbackTest.xml +++ b/InventorySalesAsyncOrder/Test/Mftf/Test/AsyncOrderStockReservationRollbackTest.xml @@ -42,7 +42,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> diff --git a/InventorySalesAsyncOrder/Test/Mftf/Test/AsyncOrderWithAsyncStockReservationTest.xml b/InventorySalesAsyncOrder/Test/Mftf/Test/AsyncOrderWithAsyncStockReservationTest.xml index 611ffd14a483..675858aaa47c 100644 --- a/InventorySalesAsyncOrder/Test/Mftf/Test/AsyncOrderWithAsyncStockReservationTest.xml +++ b/InventorySalesAsyncOrder/Test/Mftf/Test/AsyncOrderWithAsyncStockReservationTest.xml @@ -48,7 +48,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> diff --git a/InventorySalesAsyncOrder/Test/Mftf/test-dependency-allowlist b/InventorySalesAsyncOrder/Test/Mftf/test-dependency-allowlist index 98f96489fcb1..ed685a651b1b 100644 --- a/InventorySalesAsyncOrder/Test/Mftf/test-dependency-allowlist +++ b/InventorySalesAsyncOrder/Test/Mftf/test-dependency-allowlist @@ -5,6 +5,5 @@ CliConsumerStartActionGroup AssertRejectedOrderInGridActionGroup AsyncOrderStockReservationTest AssertProcessedOrderInGridActionGroup - AdminOpenCatalogProductPageActionGroup ClearFiltersAdminProductGridActionGroup diff --git a/InventorySwatchesFrontendUi/Test/Mftf/Test/StorefrontValidateVisualSwatchAbsenceOfAttributeWhenProductStocksOutTest.xml b/InventorySwatchesFrontendUi/Test/Mftf/Test/StorefrontValidateVisualSwatchAbsenceOfAttributeWhenProductStocksOutTest.xml index cd9552992809..e85f5e73c28a 100644 --- a/InventorySwatchesFrontendUi/Test/Mftf/Test/StorefrontValidateVisualSwatchAbsenceOfAttributeWhenProductStocksOutTest.xml +++ b/InventorySwatchesFrontendUi/Test/Mftf/Test/StorefrontValidateVisualSwatchAbsenceOfAttributeWhenProductStocksOutTest.xml @@ -65,7 +65,6 @@ <!--Clear filter product listing grid--> <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPageBeforeClearFilters"/> <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearProductGridFilters"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> diff --git a/InventorySwatchesFrontendUi/Test/Mftf/test-dependency-allowlist b/InventorySwatchesFrontendUi/Test/Mftf/test-dependency-allowlist index 8d0db800efa5..3f909f3eb951 100644 --- a/InventorySwatchesFrontendUi/Test/Mftf/test-dependency-allowlist +++ b/InventorySwatchesFrontendUi/Test/Mftf/test-dependency-allowlist @@ -41,6 +41,5 @@ StorefrontAddProductToCartWithQtyActionGroup StorefrontOpenCartFromMinicartActionGroup StorefrontClickProceedToCheckoutActionGroup ClickPlaceOrderActionGroup - AdminOpenCatalogProductPageActionGroup ClearFiltersAdminProductGridActionGroup From 000e2960ce802a01b1eb498e18c7891f52357b8c Mon Sep 17 00:00:00 2001 From: del72683 <del72683@adobe.com> Date: Thu, 4 Jun 2026 12:59:51 +0530 Subject: [PATCH 59/83] AC-17305::Addressing Integration Test Failures in 2.4.9-dev Composer package --- ...urableProductSalableOnNonDefaultStockTest.php | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/InventoryConfigurableProduct/Test/Integration/IsProductSalable/IsConfigurableProductSalableOnNonDefaultStockTest.php b/InventoryConfigurableProduct/Test/Integration/IsProductSalable/IsConfigurableProductSalableOnNonDefaultStockTest.php index f8e602a37c68..a8c6e2b53fbd 100644 --- a/InventoryConfigurableProduct/Test/Integration/IsProductSalable/IsConfigurableProductSalableOnNonDefaultStockTest.php +++ b/InventoryConfigurableProduct/Test/Integration/IsProductSalable/IsConfigurableProductSalableOnNonDefaultStockTest.php @@ -71,8 +71,12 @@ protected function setUp(): void StockSalesChannelsFixture::class, ['stock_id' => '$stock.stock_id$', 'sales_channels' => ['$website2.code$']] ), - DataFixture(ProductFixture::class, ['sku' => 'child-salable-1', 'website_ids' => ['1', '$website2.id$']], 'child1'), - DataFixture(ProductFixture::class, ['sku' => 'child-salable-2', 'website_ids' => ['1', '$website2.id$']], 'child2'), + DataFixture( + ProductFixture::class, + ['sku' => 'child-salable-1', 'website_ids' => ['1', '$website2.id$']], 'child1'), + DataFixture( + ProductFixture::class, + ['sku' => 'child-salable-2', 'website_ids' => ['1', '$website2.id$']], 'child2'), DataFixture(AttributeFixture::class, as: 'attr'), DataFixture( ConfigurableProductFixture::class, @@ -177,8 +181,12 @@ public function testConfigurableIsNotSalableWhenAllChildrenOutOfStock(): void StockSalesChannelsFixture::class, ['stock_id' => '$stockUs.stock_id$', 'sales_channels' => ['$website2.code$']] ), - DataFixture(ProductFixture::class, ['sku' => 'child-per-stock-1', 'website_ids' => ['1', '$website2.id$']], 'child1'), - DataFixture(ProductFixture::class, ['sku' => 'child-per-stock-2', 'website_ids' => ['1', '$website2.id$']], 'child2'), + DataFixture( + ProductFixture::class, + ['sku' => 'child-per-stock-1', 'website_ids' => ['1', '$website2.id$']], 'child1'), + DataFixture( + ProductFixture::class, + ['sku' => 'child-per-stock-2', 'website_ids' => ['1', '$website2.id$']], 'child2'), DataFixture(AttributeFixture::class, as: 'attr'), DataFixture( ConfigurableProductFixture::class, From c766a90cfaf37c2fba4d573def40ea744e2ca475 Mon Sep 17 00:00:00 2001 From: del72683 <del72683@adobe.com> Date: Thu, 4 Jun 2026 17:38:33 +0530 Subject: [PATCH 60/83] AC-17305::Addressing Integration Test Failures in 2.4.9-dev Composer package --- ...urableProductSalableOnNonDefaultStockTest.php | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/InventoryConfigurableProduct/Test/Integration/IsProductSalable/IsConfigurableProductSalableOnNonDefaultStockTest.php b/InventoryConfigurableProduct/Test/Integration/IsProductSalable/IsConfigurableProductSalableOnNonDefaultStockTest.php index a8c6e2b53fbd..ccf0959b2a88 100644 --- a/InventoryConfigurableProduct/Test/Integration/IsProductSalable/IsConfigurableProductSalableOnNonDefaultStockTest.php +++ b/InventoryConfigurableProduct/Test/Integration/IsProductSalable/IsConfigurableProductSalableOnNonDefaultStockTest.php @@ -73,10 +73,14 @@ protected function setUp(): void ), DataFixture( ProductFixture::class, - ['sku' => 'child-salable-1', 'website_ids' => ['1', '$website2.id$']], 'child1'), + ['sku' => 'child-salable-1', 'website_ids' => ['1', '$website2.id$']], + 'child1' + ), DataFixture( ProductFixture::class, - ['sku' => 'child-salable-2', 'website_ids' => ['1', '$website2.id$']], 'child2'), + ['sku' => 'child-salable-2', 'website_ids' => ['1', '$website2.id$']], + 'child2' + ), DataFixture(AttributeFixture::class, as: 'attr'), DataFixture( ConfigurableProductFixture::class, @@ -183,10 +187,14 @@ public function testConfigurableIsNotSalableWhenAllChildrenOutOfStock(): void ), DataFixture( ProductFixture::class, - ['sku' => 'child-per-stock-1', 'website_ids' => ['1', '$website2.id$']], 'child1'), + ['sku' => 'child-per-stock-1', 'website_ids' => ['1', '$website2.id$']], + 'child1' + ), DataFixture( ProductFixture::class, - ['sku' => 'child-per-stock-2', 'website_ids' => ['1', '$website2.id$']], 'child2'), + ['sku' => 'child-per-stock-2', 'website_ids' => ['1', '$website2.id$']], + 'child2' + ), DataFixture(AttributeFixture::class, as: 'attr'), DataFixture( ConfigurableProductFixture::class, From 0bdbba8c3ddf57e12a21fe01a1dcbf69524f7cad Mon Sep 17 00:00:00 2001 From: Mohit Sharma <glo87054@adobe.com> Date: Fri, 5 Jun 2026 15:17:28 +0530 Subject: [PATCH 61/83] ACQE-9640: [MFTF TESTS] StockStatusChangedForConfigurableProductOnTestStockAndTestWebsiteTest - Fix outdated admin grid search selectors in stock MFTF action groups. --- .../ActionGroup/AdminCreateNewStockActionGroup.xml | 3 ++- .../Mftf/ActionGroup/AdminDeleteStockActionGroup.xml | 4 ++++ .../AdminEditStockSourcesSection.xml | 10 +++++----- .../AdminManageStockGridBodySection.xml | 4 ++-- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/InventoryAdminUi/Test/Mftf/ActionGroup/AdminCreateNewStockActionGroup.xml b/InventoryAdminUi/Test/Mftf/ActionGroup/AdminCreateNewStockActionGroup.xml index cd11c03e70a1..d0c210900739 100644 --- a/InventoryAdminUi/Test/Mftf/ActionGroup/AdminCreateNewStockActionGroup.xml +++ b/InventoryAdminUi/Test/Mftf/ActionGroup/AdminCreateNewStockActionGroup.xml @@ -22,11 +22,12 @@ <selectOption selector="{{AdminEditStockGeneralSection.websites}}" userInput="{{websiteName}}" stepKey="selectWebsite" /> <click selector="{{AdminEditStockGeneralSection.assignSources}}" stepKey="clickAssignSourceButton" /> <waitForPageLoad stepKey="waitForStoreGroupPageLoad" /> + <waitForElementVisible selector="{{AdminEditStockSourcesSection.searchSourceText}}" stepKey="waitForAssignSourcesModalSearchField" /> <conditionalClick selector="{{AdminEditStockSourcesSection.clearAll}}" dependentSelector="{{AdminEditStockSourcesSection.clearAll}}" visible="true" stepKey="clearAllPreviouslySearchedSources" /> <fillField selector="{{AdminEditStockSourcesSection.searchSourceText}}" userInput="{{assignSource}}" stepKey="enterSourceName" /> <click selector="{{AdminEditStockSourcesSection.clickSearchSource}}" stepKey="clickSearchSourceButton" /> <waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskToDisappear"/> - <checkOption selector="{{AdminEditStockSourcesSection.selectSource(assignSource)}}" stepKey="selectTheSource"/> + <click selector="{{AdminEditStockSourcesSection.selectSource(assignSource)}}" stepKey="selectTheSource"/> <click selector="{{AdminEditStockSourcesSection.doneButton}}" stepKey="clickDoneButton" /> <click selector="{{AdminEditStockGeneralSection.saveAndContinueDropdown}}" stepKey="clickSaveAndContinueDropdown" /> <click selector="{{AdminEditStockGeneralSection.saveAndCloseButton}}" stepKey="clickSaveAndClose" /> diff --git a/InventoryAdminUi/Test/Mftf/ActionGroup/AdminDeleteStockActionGroup.xml b/InventoryAdminUi/Test/Mftf/ActionGroup/AdminDeleteStockActionGroup.xml index 51f0c1355fb4..3e72956149d9 100644 --- a/InventoryAdminUi/Test/Mftf/ActionGroup/AdminDeleteStockActionGroup.xml +++ b/InventoryAdminUi/Test/Mftf/ActionGroup/AdminDeleteStockActionGroup.xml @@ -16,7 +16,10 @@ <argument name="websiteName" defaultValue="Main Website" type="string"/> </arguments> <amOnPage url="{{AdminStockPage.url}}" stepKey="navigateToManageStockPage"/> + <waitForPageLoad stepKey="waitForManageStockPageLoad"/> <conditionalClick selector="{{AdminProductGridFilterSection.clearFilters}}" dependentSelector="{{AdminProductGridFilterSection.clearFilters}}" visible="true" stepKey="clickClearFilters"/> + <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clickClearKeywordFilters"/> + <waitForElementVisible selector="{{AdminManageStockGridBody.searchStockText}}" stepKey="waitForStockGridSearchField"/> <fillField selector="{{AdminManageStockGridBody.searchStockText}}" userInput="{{stockName}}" stepKey="enterStockName" /> <click selector="{{AdminManageStockGridBody.clickSearchStock}}" stepKey="clickSearchStockButton" /> <waitForPageLoad stepKey="waitForStoreGroupPageLoad" /> @@ -29,6 +32,7 @@ <waitForPageLoad stepKey="waitForStoreGroupPageLoadPostEditingTheSources" /> <waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskToDisappear"/> <seeElement selector="{{AdminManageStockGridBody.stockSavedSuccessfulMessage}}" stepKey="verifyTheStockSavedSuccessfully"/> + <waitForElementVisible selector="{{AdminManageStockGridBody.searchStockText}}" stepKey="waitForStockGridSearchFieldForDelete"/> <fillField selector="{{AdminManageStockGridBody.searchStockText}}" userInput="{{stockName}}" stepKey="enterStockNameForDelete" /> <click selector="{{AdminManageStockGridBody.clickSearchStock}}" stepKey="clickSearchStockButtonForDelete" /> <waitForPageLoad stepKey="waitForStoreGroupPageLoadForDelete" /> diff --git a/InventoryAdminUi/Test/Mftf/Section/AdminManageStockFormSection/AdminEditStockSourcesSection.xml b/InventoryAdminUi/Test/Mftf/Section/AdminManageStockFormSection/AdminEditStockSourcesSection.xml index c274d5260552..84cd39d1aa7b 100644 --- a/InventoryAdminUi/Test/Mftf/Section/AdminManageStockFormSection/AdminEditStockSourcesSection.xml +++ b/InventoryAdminUi/Test/Mftf/Section/AdminManageStockFormSection/AdminEditStockSourcesSection.xml @@ -14,11 +14,11 @@ <element name="rowSourceName" type="text" selector=".data-row[data-repeat-index='{{arg1}}'] span[data-index='name']" parameterized="true"/> <element name="rowSourceDelete" type="button" selector=".data-row[data-repeat-index='{{arg1}}'] .action-delete" parameterized="true"/> <element name="tableRow" type="block" selector=".admin__dynamic-rows[data-index='assigned_sources'] tbody > tr.data-row"/> - <element name="clearAll" type="button" selector="//div[contains(@data-bind,'data.setToolbarNode')]//button[@class='action-tertiary action-clear']" /> - <element name="searchSourceText" type="input" selector="//div[contains(@data-bind,'data.setToolbarNode')]//input[@placeholder='Search by keyword']"/> - <element name="clickSearchSource" type="button" selector="//div[contains(@data-bind,'data.setToolbarNode')]//div[@class='data-grid-search-control-wrap']//button[@class='action-submit']"/> - <element name="selectSource" type="select" selector="//tr[@class='data-row']//div[contains(text(),'{{test_source_code}}')]/../..//input[@class='admin__control-checkbox']" parameterized="true"/> - <element name="doneButton" type="button" selector="//button[@class='action-primary']//span[contains(text(),'Done')]" /> + <element name="clearAll" type="button" selector=".inventory_stock_form_inventory_stock_form_sources_assign_sources_modal .admin__data-grid-header [data-action='grid-filter-reset']" /> + <element name="searchSourceText" type="input" selector=".inventory_stock_form_inventory_stock_form_sources_assign_sources_modal .admin__data-grid-header[data-bind='afterRender: \$data.setToolbarNode'] input[placeholder='Search by keyword']"/> + <element name="clickSearchSource" type="button" selector=".inventory_stock_form_inventory_stock_form_sources_assign_sources_modal .data-grid-search-control-wrap > button.action-submit"/> + <element name="selectSource" type="select" selector="//input[ancestor::tr[contains(., '{{test_source_code}}')]]" parameterized="true"/> + <element name="doneButton" type="button" selector=".inventory_stock_form_inventory_stock_form_sources_assign_sources_modal button.action-primary" /> <element name="deleteAssignedSources" type="button" selector="//tr[@class='data-row']//button[@class='action-delete']"/> <element name="deleteSpecificAssignedSources" type="button" selector="//tr[@class='data-row']//td//span[text()='{{var1}}']/../../../../..//button[@class='action-delete']" parameterized="true"/> <element name="deleteStock" type="button" selector="//div[@class='page-actions-buttons']//button[@data-ui-id='delete-button']"/> diff --git a/InventoryAdminUi/Test/Mftf/Section/AdminManageStockGridSection/AdminManageStockGridBodySection.xml b/InventoryAdminUi/Test/Mftf/Section/AdminManageStockGridSection/AdminManageStockGridBodySection.xml index 0b47f94a5679..8dffc1f4ff00 100644 --- a/InventoryAdminUi/Test/Mftf/Section/AdminManageStockGridSection/AdminManageStockGridBodySection.xml +++ b/InventoryAdminUi/Test/Mftf/Section/AdminManageStockGridSection/AdminManageStockGridBodySection.xml @@ -12,8 +12,8 @@ <element name="stockSelectedCheckbox" type="checkbox" selector="#idscheck{{id}}" parameterized="true"/> <element name="assignedSourceContent" type="text" selector="table[data-role='grid'] ul[data-bind*='assignedSource']"/> <element name="tooltipAssignedSource" type="text" selector="//div[contains(@class, 'data-tooltip-title') and contains(text(), 'Assigned Sources:')]/..//span[text()='{{source_code}}']" parameterized="true"/> - <element name="searchStockText" type="input" selector="//input[@placeholder='Search by keyword'][1]"/> - <element name="clickSearchStock" type="button" selector="//div[@class='data-grid-search-control-wrap']//button[@class='action-submit']"/> + <element name="searchStockText" type="input" selector=".admin__data-grid-header[data-bind='afterRender: \$data.setToolbarNode'] input[placeholder='Search by keyword']"/> + <element name="clickSearchStock" type="button" selector=".admin__data-grid-header[data-bind='afterRender: \$data.setToolbarNode'] .data-grid-search-control-wrap > button.action-submit"/> <element name="editStock" type="button" selector="//tr[@class='data-row']//div[contains(text(),'{{test_source_code}}')]/../..//a[@class='action-menu-item' and contains(text(),'Edit')]" parameterized="true"/> <element name="selectStock" type="select" selector="//tr[@class='data-row']//div[contains(text(),'{{test_stock_code}}')]/../..//input[@class='admin__control-checkbox']" parameterized="true"/> <element name="stockSavedSuccessfulMessage" type="text" selector="//div[@class='message message-success success']//div[contains(text(),'The Stock has been saved.')]"/> From c1c4cc37c82592b007f48e6949e342428b8600d6 Mon Sep 17 00:00:00 2001 From: Alexandra Zota <zota@adobe.com> Date: Fri, 5 Jun 2026 17:56:44 +0300 Subject: [PATCH 62/83] ACP2E-5003: Handle invalid store code gracefully in GetStockIdForCurrentWebsite --- .../Model/GetStockIdForCurrentWebsite.php | 9 +++- .../Model/GetStockIdForCurrentWebsiteTest.php | 49 +++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/InventoryCatalog/Model/GetStockIdForCurrentWebsite.php b/InventoryCatalog/Model/GetStockIdForCurrentWebsite.php index afb9ae2f6aef..46acfa4c39b3 100644 --- a/InventoryCatalog/Model/GetStockIdForCurrentWebsite.php +++ b/InventoryCatalog/Model/GetStockIdForCurrentWebsite.php @@ -8,10 +8,11 @@ namespace Magento\InventoryCatalog\Model; use Magento\Framework\App\ObjectManager; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\HTTP\PhpEnvironment\Request; use Magento\InventorySalesApi\Api\Data\SalesChannelInterface; use Magento\InventorySalesApi\Api\StockResolverInterface; use Magento\Store\Model\StoreManagerInterface; -use Magento\Framework\HTTP\PhpEnvironment\Request; /** * Service for get stock id for current website. @@ -56,7 +57,11 @@ public function __construct( public function execute(): int { $storeId = $this->request->getParam('store'); - $websiteId = $this->storeManager->getStore($storeId)->getWebsiteId(); + try { + $websiteId = $this->storeManager->getStore($storeId)->getWebsiteId(); + } catch (NoSuchEntityException $e) { + $websiteId = $this->storeManager->getStore()->getWebsiteId(); + } $websiteCode = $this->storeManager->getWebsite($websiteId)->getCode(); $stock = $this->stockResolver->execute(SalesChannelInterface::TYPE_WEBSITE, $websiteCode); diff --git a/InventoryCatalog/Test/Unit/Model/GetStockIdForCurrentWebsiteTest.php b/InventoryCatalog/Test/Unit/Model/GetStockIdForCurrentWebsiteTest.php index 35f4c0496453..d5b2b5d4ea95 100644 --- a/InventoryCatalog/Test/Unit/Model/GetStockIdForCurrentWebsiteTest.php +++ b/InventoryCatalog/Test/Unit/Model/GetStockIdForCurrentWebsiteTest.php @@ -7,6 +7,7 @@ namespace Magento\InventoryCatalog\Test\Unit\Model; +use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\HTTP\PhpEnvironment\Request; use Magento\InventoryApi\Api\Data\StockInterface; use Magento\InventoryCatalog\Model\GetStockIdForCurrentWebsite; @@ -95,4 +96,52 @@ public function testExecute(): void $this->assertSame($stockId, $this->model->execute()); } + + /** + * @return void + */ + public function testExecuteWithInvalidStoreFallsBackToCurrentStore(): void + { + $invalidStoreCode = 'noneExistent'; + $websiteId = 1; + $websiteCode = 'base'; + $stockId = 1; + + $this->request->expects($this->once())->method('getParam') + ->with('store') + ->willReturn($invalidStoreCode); + + $currentStore = $this->createMock(StoreInterface::class); + $currentStore->expects($this->once()) + ->method('getWebsiteId') + ->willReturn($websiteId); + + $this->storeManager->expects($this->exactly(2)) + ->method('getStore') + ->willReturnCallback(function ($storeId = null) use ($invalidStoreCode, $currentStore) { + if ($storeId === $invalidStoreCode) { + throw new NoSuchEntityException(__('The store that was requested wasn\'t found.')); + } + return $currentStore; + }); + + $website = $this->createMock(WebsiteInterface::class); + $website->expects($this->once()) + ->method('getCode') + ->willReturn($websiteCode); + $this->storeManager->expects($this->once()) + ->method('getWebsite') + ->with($websiteId) + ->willReturn($website); + + $stock = $this->createMock(StockInterface::class); + $stock->expects($this->once())->method('getStockId') + ->willReturn($stockId); + $this->stockResolver->expects($this->once()) + ->method('execute') + ->with(SalesChannelInterface::TYPE_WEBSITE, $websiteCode) + ->willReturn($stock); + + $this->assertSame($stockId, $this->model->execute()); + } } From af9698a3122935d36bb16e1ab35ffa33ba2c7ae5 Mon Sep 17 00:00:00 2001 From: Mohit Sharma <glo87054@adobe.com> Date: Thu, 11 Jun 2026 11:29:11 +0530 Subject: [PATCH 63/83] ACQE-9629: [MFTF TESTS] AdminUserSetStatusForEachSourceItemTest - Click product name instead of Edit link to avoid tooltip intercept. --- .../Mftf/Test/AdminUserSetStatusForEachSourceItemTest.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminUserSetStatusForEachSourceItemTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminUserSetStatusForEachSourceItemTest.xml index f0a69e20808a..1e1bad549745 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminUserSetStatusForEachSourceItemTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminUserSetStatusForEachSourceItemTest.xml @@ -121,8 +121,8 @@ <waitForText selector="{{AdminProductGridSection.productGridCell('1', 'Websites')}}" userInput="Main Website" stepKey="seeSimpleProductWebsiteInFirstRow"/> <waitForElementClickable selector="{{AdminGridColumnsControls.cancel}}" stepKey="waitForCancelToHideColumnsBlock"/> <click selector="{{AdminGridColumnsControls.cancel}}" stepKey="clickOnCancelToHideColumnsBlock"/> - <waitForElementClickable selector="{{AdminGridRow.editByValue(SimpleMsiProduct.sku)}}" stepKey="waitForEditSimpleMsiProduct"/> - <click selector="{{AdminGridRow.editByValue(SimpleMsiProduct.sku)}}" stepKey="clickOnEditSimpleMsiProduct"/> + <waitForElementClickable selector="{{AdminProductGridSection.productGridNameProduct(SimpleMsiProduct.name)}}" stepKey="waitForEditSimpleMsiProduct"/> + <click selector="{{AdminProductGridSection.productGridNameProduct(SimpleMsiProduct.name)}}" stepKey="clickOnEditSimpleMsiProduct"/> <waitForPageLoad stepKey="waitForSimpleProductPageLoad"/> From 79b7d9694b226eee72204b327f5d6be368bb4bdd Mon Sep 17 00:00:00 2001 From: Mohit Sharma <glo87054@adobe.com> Date: Tue, 16 Jun 2026 09:59:50 +0530 Subject: [PATCH 64/83] ACQE-10343: [MFTF TESTS] AdminBundleProductDisabledManageStockOnProductPageCustomStockTest - Fix inverted storefront assertions. --- ...ProductDisabledManageStockOnProductPageCustomStockTest.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminBundleProductDisabledManageStockOnProductPageCustomStockTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminBundleProductDisabledManageStockOnProductPageCustomStockTest.xml index 2464693a1286..0d955fe77fd6 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminBundleProductDisabledManageStockOnProductPageCustomStockTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminBundleProductDisabledManageStockOnProductPageCustomStockTest.xml @@ -89,7 +89,7 @@ <!--Verify product is not visible storefront.--> <amOnPage url="{{StorefrontCategoryPage.url($$category.custom_attributes[url_key]$$)}}" stepKey="navigateToCategoryPage"/> <waitForPageLoad stepKey="waitForCategoryPageLoad"/> - <waitForText userInput="$bundleProduct.name$" stepKey="assertProductIsPresent1"/> + <dontSee userInput="$$bundleProduct.name$$" stepKey="assertProductIsNotPresent"/> <!--Disable "Manage Stock" On Product Page.--> <amOnPage url="{{AdminProductEditPage.url($$bundleProduct.id$$)}}" stepKey="openProductEditPageToSetStockStatus"/> <click selector="{{AdminProductFormSection.advancedInventoryLink}}" stepKey="clickOnAdvancedInventoryLink"/> @@ -101,7 +101,7 @@ <!--Verify product is visible storefront.--> <amOnPage url="{{StorefrontCategoryPage.url($$category.custom_attributes[url_key]$$)}}" stepKey="navigateToCategoryPageToVerifyBundleProduct"/> <waitForPageLoad stepKey="waitForCategoryPageLoadToVerifyBundleProduct"/> - <dontSee userInput="$bundleProduct.name$" stepKey="assertProductIsPresent"/> + <see userInput="$$bundleProduct.name$$" stepKey="assertProductIsPresent"/> <see userInput="$$simpleProduct.price$$" stepKey="assertProductPriceIsPresent"/> </test> </tests> From 1b0abb8283d4728687477c6b7deafeaaae681788 Mon Sep 17 00:00:00 2001 From: Karishma Thakare <del57145@adobe.com> Date: Mon, 22 Jun 2026 21:35:02 +0530 Subject: [PATCH 65/83] ACQE-10614: [Unskip] Analysis- Run mentioned tests on local and check which skipped for same reason - Removed skip tag --- ...lectionAlgorithmSourcePriorityWithSimpleMsiProductTest.xml | 4 ++-- .../Test/Mftf/Test/SkippedTest/EndToEndB2CGuestUserTest.xml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Inventory/Test/Mftf/Test/SkippedTest/AdminSourceSelectionAlgorithmSourcePriorityWithSimpleMsiProductTest.xml b/Inventory/Test/Mftf/Test/SkippedTest/AdminSourceSelectionAlgorithmSourcePriorityWithSimpleMsiProductTest.xml index 2eb8cde293a6..5c419609e165 100644 --- a/Inventory/Test/Mftf/Test/SkippedTest/AdminSourceSelectionAlgorithmSourcePriorityWithSimpleMsiProductTest.xml +++ b/Inventory/Test/Mftf/Test/SkippedTest/AdminSourceSelectionAlgorithmSourcePriorityWithSimpleMsiProductTest.xml @@ -9,9 +9,9 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AdminSourceSelectionAlgorithmSourcePriorityWithSimpleMsiProductTest"> <annotations> - <skip> + <!--<skip> <issueId value="MSI-1631"/> - </skip> + </skip>--> <group value="pr_exclude"/> </annotations> </test> diff --git a/Inventory/Test/Mftf/Test/SkippedTest/EndToEndB2CGuestUserTest.xml b/Inventory/Test/Mftf/Test/SkippedTest/EndToEndB2CGuestUserTest.xml index 7a67d5d09e78..e946f63d02df 100644 --- a/Inventory/Test/Mftf/Test/SkippedTest/EndToEndB2CGuestUserTest.xml +++ b/Inventory/Test/Mftf/Test/SkippedTest/EndToEndB2CGuestUserTest.xml @@ -9,9 +9,9 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="EndToEndB2CGuestUserTest"> <annotations> - <skip> + <!-- <skip> <issueId value="MSI-1631"/> - </skip> + </skip>--> <group value="pr_exclude"/> </annotations> </test> From 2764fb5dfa119e12ee30c00266b601367a3400a4 Mon Sep 17 00:00:00 2001 From: Karishma Thakare <del57145@adobe.com> Date: Mon, 22 Jun 2026 22:43:49 +0530 Subject: [PATCH 66/83] ACQE-10614: [Unskip] Analysis- Run mentioned tests on local and check which skipped for same reason - Refactorfed the test --- ...SourcePriorityWithSimpleMsiProductTest.xml | 4 ++-- .../Test/Mftf/Data/StockSourceLinksData.xml | 24 +++++++++++++++++++ ...SourcePriorityWithSimpleMsiProductTest.xml | 23 +++++------------- 3 files changed, 32 insertions(+), 19 deletions(-) diff --git a/Inventory/Test/Mftf/Test/SkippedTest/AdminSourceSelectionAlgorithmSourcePriorityWithSimpleMsiProductTest.xml b/Inventory/Test/Mftf/Test/SkippedTest/AdminSourceSelectionAlgorithmSourcePriorityWithSimpleMsiProductTest.xml index 2eb8cde293a6..350002c72a76 100644 --- a/Inventory/Test/Mftf/Test/SkippedTest/AdminSourceSelectionAlgorithmSourcePriorityWithSimpleMsiProductTest.xml +++ b/Inventory/Test/Mftf/Test/SkippedTest/AdminSourceSelectionAlgorithmSourcePriorityWithSimpleMsiProductTest.xml @@ -9,9 +9,9 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AdminSourceSelectionAlgorithmSourcePriorityWithSimpleMsiProductTest"> <annotations> - <skip> + <!-- <skip> <issueId value="MSI-1631"/> - </skip> + </skip>--> <group value="pr_exclude"/> </annotations> </test> diff --git a/InventoryAdminUi/Test/Mftf/Data/StockSourceLinksData.xml b/InventoryAdminUi/Test/Mftf/Data/StockSourceLinksData.xml index fbada7868d43..a6300eb38d4b 100644 --- a/InventoryAdminUi/Test/Mftf/Data/StockSourceLinksData.xml +++ b/InventoryAdminUi/Test/Mftf/Data/StockSourceLinksData.xml @@ -16,4 +16,28 @@ <var key="stock_id" entityKey="return" entityType="stock"/> <var key="source_code" entityKey="source[source_code]" entityType="source"/> </entity> + <entity name="SourceStockLinked2" type="source-stock-links"> + <requiredEntity type="source-stock-link">Link2</requiredEntity> + </entity> + <entity name="Link2" type="source-stock-link"> + <data key="priority">2</data> + <var key="stock_id" entityKey="return" entityType="stock"/> + <var key="source_code" entityKey="source[source_code]" entityType="source"/> + </entity> + <entity name="SourceStockLinked3" type="source-stock-links"> + <requiredEntity type="source-stock-link">Link3</requiredEntity> + </entity> + <entity name="Link3" type="source-stock-link"> + <data key="priority">3</data> + <var key="stock_id" entityKey="return" entityType="stock"/> + <var key="source_code" entityKey="source[source_code]" entityType="source"/> + </entity> + <entity name="SourceStockLinked4" type="source-stock-links"> + <requiredEntity type="source-stock-link">Link4</requiredEntity> + </entity> + <entity name="Link4" type="source-stock-link"> + <data key="priority">4</data> + <var key="stock_id" entityKey="return" entityType="stock"/> + <var key="source_code" entityKey="source[source_code]" entityType="source"/> + </entity> </entities> diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminSourceSelectionAlgorithmSourcePriorityWithSimpleMsiProductTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminSourceSelectionAlgorithmSourcePriorityWithSimpleMsiProductTest.xml index edddf989cbd5..7c0f28b1df09 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminSourceSelectionAlgorithmSourcePriorityWithSimpleMsiProductTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminSourceSelectionAlgorithmSourcePriorityWithSimpleMsiProductTest.xml @@ -33,36 +33,25 @@ <createData entity="Simple_US_Customer" stepKey="createCustomer"/> <createData entity="SourceStockLinked1" stepKey="linkSourceStock1"> + <requiredEntity createDataKey="createStock1"/> + <requiredEntity createDataKey="createSource4"/> + </createData> + <createData entity="SourceStockLinked2" stepKey="linkSourceStock2"> <requiredEntity createDataKey="createStock1"/> <requiredEntity createDataKey="createSource1"/> </createData> - <createData entity="SourceStockLinked1" stepKey="linkSourceStock2"> + <createData entity="SourceStockLinked3" stepKey="linkSourceStock3"> <requiredEntity createDataKey="createStock1"/> <requiredEntity createDataKey="createSource2"/> </createData> - <createData entity="SourceStockLinked1" stepKey="linkSourceStock3"> + <createData entity="SourceStockLinked4" stepKey="linkSourceStock4"> <requiredEntity createDataKey="createStock1"/> <requiredEntity createDataKey="createSource3"/> </createData> - <createData entity="SourceStockLinked1" stepKey="linkSourceStock4"> - <requiredEntity createDataKey="createStock1"/> - <requiredEntity createDataKey="createSource4"/> - </createData> <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> <waitForPageLoad stepKey="waitForPageLoadAfterLogin"/> - <actionGroup ref="AdminGoToStockGridFilterResultsByInputEditStock" stepKey="goToStockGridFilterResultsByInputEditStock1"> - <argument name="filter_selector" value="AdminManageStockGridFilterControls.name"/> - <argument name="filter_value" value="$$createStock1.stock[name]$$"/> - </actionGroup> - - <dragAndDrop selector1="{{AdminEditStockSourcesSection.rowSourceDrag('3')}}" selector2="{{AdminEditStockSourcesSection.rowSourceDrag('1')}}" stepKey="dragAndDropNameSource4ToSecondPriority"/> - <waitForPageLoad stepKey="waitForPageLoad1"/> - <dragAndDrop selector1="{{AdminEditStockSourcesSection.rowSourceDrag('0')}}" selector2="{{AdminEditStockSourcesSection.rowSourceDrag('1')}}" stepKey="dragAndDropNameSource4ToHighestPriority"/> - <waitForPageLoad stepKey="waitForPageLoad2"/> - <click selector="{{AdminGridMainControls.saveAndContinue}}" stepKey="saveCustomStock"/> - <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductGrid"/> <waitForPageLoad time="30" stepKey="waitForProductGridPageLoad"/> </before> From a812d2676f29672d47c64f5e9645ae2a3ade5a42 Mon Sep 17 00:00:00 2001 From: Karishma Thakare <del57145@adobe.com> Date: Tue, 23 Jun 2026 00:46:49 +0530 Subject: [PATCH 67/83] ACQE-10614: [Unskip] Analysis- Run mentioned tests on local and check which skipped for same reason - Refactorfed the test --- ...SourcePriorityWithSimpleMsiProductTest.xml | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminSourceSelectionAlgorithmSourcePriorityWithSimpleMsiProductTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminSourceSelectionAlgorithmSourcePriorityWithSimpleMsiProductTest.xml index 7c0f28b1df09..eb7852772efc 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminSourceSelectionAlgorithmSourcePriorityWithSimpleMsiProductTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminSourceSelectionAlgorithmSourcePriorityWithSimpleMsiProductTest.xml @@ -95,11 +95,11 @@ <scrollToTopOfPage stepKey="scrollToTopOfPage1"/> <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$simpleCategory1.name$$]" requiredAction="true" stepKey="searchAndSelectCategory1"/> - <fillField selector="{{AdminProductSourcesGrid.rowQty('0')}}" userInput="{{SimpleMsiProduct.quantity}}" stepKey="fillCustomSource1QtyField"/> - <fillField selector="{{AdminProductSourcesGrid.rowQty('1')}}" userInput="{{SimpleMsiProduct.quantity}}" stepKey="fillCustomSource2QtyField"/> - <fillField selector="{{AdminProductSourcesGrid.rowQty('2')}}" userInput="{{SimpleMsiProduct.quantity}}" stepKey="fillCustomSource3QtyField"/> - <fillField selector="{{AdminProductSourcesGrid.rowQty('3')}}" userInput="{{SimpleMsiProduct.quantity}}" stepKey="fillCustomSource4QtyField"/> - <fillField selector="{{AdminProductSourcesGrid.rowQty('4')}}" userInput="{{SimpleMsiProduct.quantity}}" stepKey="fillCustomSource5QtyField"/> + <fillField selector="{{AdminProductSourcesGrid.rowQty('0')}}" userInput="1000" stepKey="fillCustomSource1QtyField"/> + <fillField selector="{{AdminProductSourcesGrid.rowQty('1')}}" userInput="1000" stepKey="fillCustomSource2QtyField"/> + <fillField selector="{{AdminProductSourcesGrid.rowQty('2')}}" userInput="1000" stepKey="fillCustomSource3QtyField"/> + <fillField selector="{{AdminProductSourcesGrid.rowQty('3')}}" userInput="1000" stepKey="fillCustomSource4QtyField"/> + <fillField selector="{{AdminProductSourcesGrid.rowQty('4')}}" userInput="1000" stepKey="fillCustomSource5QtyField"/> <actionGroup ref="AdminFormSaveAndCloseActionGroup" stepKey="saveAndCloseSimpleMsiProduct"/> <waitForPageLoad stepKey="waitForSimpleMsiProductGidPageLoad"/> @@ -168,12 +168,14 @@ <click selector="{{AdminSourceSelectionFormSection.proceedToShipment}}" stepKey="createShipment"/> <waitForPageLoad stepKey="waitForPageLoad11"/> - <see selector="{{AdminShipmentOrderInformationSection.orderStatus}}" userInput="Pending" stepKey="seeOrderStatus"/> + <waitForText selector="{{AdminShipmentOrderInformationSection.orderStatus}}" userInput="Pending" stepKey="seeOrderStatus"/> - <actionGroup ref="SeeProductInShipmentItemsActionGroup" stepKey="checkProductInShipment"> - <argument name="product" value="SimpleMsiProduct"/> - </actionGroup> + <scrollTo selector="{{AdminShipmentItemsSection.skuColumn}}" stepKey="scrollToShipmentItemsTable"/> + <waitForElementVisible selector="{{AdminShipmentItemsSection.skuColumn}}" time="30" stepKey="waitForShipmentItemsVisible"/> + <wait time="60" stepKey="waitForSku"/> + <see selector=".order-shipment-table .col-product" userInput="$$simpleMsiProduct1.product[name]$$" stepKey="checkProductInShipment"/> + <waitForText selector="{{AdminShipmentInventorySection.sourceList}}" userInput="$$createSource4.source[name]$$" stepKey="checkSourceNameOnShipmentPage"/> <see selector="{{AdminShipmentInventorySection.sourceList}}" userInput="$$createSource4.source[name]$$" stepKey="checkSourceNameOnShipmentPage"/> <click selector="{{AdminShipmentMainActionsSection.submitShipment}}" stepKey="clickSubmitShipment"/> From f0a29930f60a7e6aed7354a477e08ba8694d5bf4 Mon Sep 17 00:00:00 2001 From: Karishma Thakare <del57145@adobe.com> Date: Tue, 23 Jun 2026 01:21:03 +0530 Subject: [PATCH 68/83] ACQE-10614: [Unskip] Analysis- Run mentioned tests on local and check which skipped for same reason - Refactored the test --- ...ectionAlgorithmSourcePriorityWithSimpleMsiProductTest.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/InventoryAdminUi/Test/Mftf/Test/AdminSourceSelectionAlgorithmSourcePriorityWithSimpleMsiProductTest.xml b/InventoryAdminUi/Test/Mftf/Test/AdminSourceSelectionAlgorithmSourcePriorityWithSimpleMsiProductTest.xml index eb7852772efc..d0634c1faca1 100644 --- a/InventoryAdminUi/Test/Mftf/Test/AdminSourceSelectionAlgorithmSourcePriorityWithSimpleMsiProductTest.xml +++ b/InventoryAdminUi/Test/Mftf/Test/AdminSourceSelectionAlgorithmSourcePriorityWithSimpleMsiProductTest.xml @@ -114,7 +114,9 @@ <see selector="{{AdminProductGridSection.productGridCell('1', 'Price')}}" userInput="{{SimpleMsiProduct.price}}" stepKey="seeSimpleMsiProductPriceInFirstRow"/> <see selector="{{AdminProductGridSection.productGridCell('1', 'Status')}}" userInput="Enabled" stepKey="seeSimpleMsiProductStatusInFirstRow"/> <see selector="{{AdminProductGridSection.productGridCell('1', 'Websites')}}" userInput="Main Website" stepKey="seeSimpleMsiProductWebsiteInFirstRow"/> - + <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> + <argument name="indices" value=""/> + </actionGroup> <comment userInput="Login as Customer and add Product to Cart" stepKey="loginCustomerComment"/> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="customerLogin"> <argument name="Customer" value="$$createCustomer$$"/> @@ -176,7 +178,6 @@ <see selector=".order-shipment-table .col-product" userInput="$$simpleMsiProduct1.product[name]$$" stepKey="checkProductInShipment"/> <waitForText selector="{{AdminShipmentInventorySection.sourceList}}" userInput="$$createSource4.source[name]$$" stepKey="checkSourceNameOnShipmentPage"/> - <see selector="{{AdminShipmentInventorySection.sourceList}}" userInput="$$createSource4.source[name]$$" stepKey="checkSourceNameOnShipmentPage"/> <click selector="{{AdminShipmentMainActionsSection.submitShipment}}" stepKey="clickSubmitShipment"/> <seeInCurrentUrl url="{{AdminOrderDetailsPage.url}}" stepKey="seeViewOrderPageShipping"/> From 230e26a68f62063f692189dbcd1096b5c90a08ca Mon Sep 17 00:00:00 2001 From: Karishma Thakare <del57145@adobe.com> Date: Tue, 23 Jun 2026 10:13:33 +0530 Subject: [PATCH 69/83] ACQE-10614: [Unskip] Analysis- Run mentioned tests on local and check which skipped for same reason - Removed skipped tests --- ...mSourcePriorityWithSimpleMsiProductTest.xml | 18 ------------------ .../SkippedTest/EndToEndB2CGuestUserTest.xml | 18 ------------------ 2 files changed, 36 deletions(-) delete mode 100644 Inventory/Test/Mftf/Test/SkippedTest/AdminSourceSelectionAlgorithmSourcePriorityWithSimpleMsiProductTest.xml delete mode 100644 Inventory/Test/Mftf/Test/SkippedTest/EndToEndB2CGuestUserTest.xml diff --git a/Inventory/Test/Mftf/Test/SkippedTest/AdminSourceSelectionAlgorithmSourcePriorityWithSimpleMsiProductTest.xml b/Inventory/Test/Mftf/Test/SkippedTest/AdminSourceSelectionAlgorithmSourcePriorityWithSimpleMsiProductTest.xml deleted file mode 100644 index 5c419609e165..000000000000 --- a/Inventory/Test/Mftf/Test/SkippedTest/AdminSourceSelectionAlgorithmSourcePriorityWithSimpleMsiProductTest.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright 2020 Adobe - * All Rights Reserved. - */ ---> -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="AdminSourceSelectionAlgorithmSourcePriorityWithSimpleMsiProductTest"> - <annotations> - <!--<skip> - <issueId value="MSI-1631"/> - </skip>--> - <group value="pr_exclude"/> - </annotations> - </test> -</tests> diff --git a/Inventory/Test/Mftf/Test/SkippedTest/EndToEndB2CGuestUserTest.xml b/Inventory/Test/Mftf/Test/SkippedTest/EndToEndB2CGuestUserTest.xml deleted file mode 100644 index e946f63d02df..000000000000 --- a/Inventory/Test/Mftf/Test/SkippedTest/EndToEndB2CGuestUserTest.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright 2020 Adobe - * All Rights Reserved. - */ ---> -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="EndToEndB2CGuestUserTest"> - <annotations> - <!-- <skip> - <issueId value="MSI-1631"/> - </skip>--> - <group value="pr_exclude"/> - </annotations> - </test> -</tests> From 81d63968a4e7ceb55acba5c53c48964e799cc1b5 Mon Sep 17 00:00:00 2001 From: Alexandra Zota <zota@adobe.com> Date: Wed, 24 Jun 2026 18:30:24 +0300 Subject: [PATCH 70/83] ACP2E-5049: PR Quality Gates: delivery to PB and Security Repos --- .github/scripts/filter-blacklist.sh | 37 ---- .github/scripts/phpcs-noise-filter.txt | 15 -- .github/scripts/phpmd-ruleset.xml | 59 ------ .github/scripts/run-phpcs.sh | 8 +- .github/scripts/tslint.json | 12 -- .github/workflows/pr-quality-gates.yml | 240 ++++++++++++++++--------- 6 files changed, 160 insertions(+), 211 deletions(-) delete mode 100755 .github/scripts/filter-blacklist.sh delete mode 100644 .github/scripts/phpcs-noise-filter.txt delete mode 100644 .github/scripts/phpmd-ruleset.xml delete mode 100644 .github/scripts/tslint.json diff --git a/.github/scripts/filter-blacklist.sh b/.github/scripts/filter-blacklist.sh deleted file mode 100755 index 9a845aa4fd7a..000000000000 --- a/.github/scripts/filter-blacklist.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright 2026 Adobe -# All Rights Reserved. -# -# Usage: filter-blacklist.sh <blacklist_dir> <file_list> [label] -# Reads file paths from <file_list>, removes entries matching any pattern in -# <blacklist_dir>/*.txt, and writes surviving paths to stdout one per line. -# Skipped files are reported to stderr as "<label> skip (blacklist): <file>". -set -euo pipefail - -BLACKLIST_DIR="$1" -FILE_LIST="$2" -LABEL="${3:-skip}" - -mapfile -t patterns < <( - [ -d "$BLACKLIST_DIR" ] || exit 0 - cat "$BLACKLIST_DIR"/*.txt 2>/dev/null \ - | sed 's/[[:space:]]*$//' \ - | grep -vE '^[[:space:]]*$|^[[:space:]]*#' || true -) - -while IFS= read -r f; do - [ -n "$f" ] && [ -f "$f" ] || continue - skip=false - for p in "${patterns[@]+"${patterns[@]}"}"; do - if [[ "$f" == $p ]] || [[ "$f" == *"$p"* ]]; then - skip=true - break - fi - done - if [ "$skip" = true ]; then - echo "$LABEL skip (blacklist): $f" >&2 - else - echo "$f" - fi -done < "$FILE_LIST" diff --git a/.github/scripts/phpcs-noise-filter.txt b/.github/scripts/phpcs-noise-filter.txt deleted file mode 100644 index c37a25ea3383..000000000000 --- a/.github/scripts/phpcs-noise-filter.txt +++ /dev/null @@ -1,15 +0,0 @@ -# -# Copyright 2026 Adobe -# All Rights Reserved. -# -# Lines matching any of these patterns are stripped from PHPCS output. -# Used by run-phpcs.sh via: grep -vEf phpcs-noise-filter.txt -^DEPRECATED: -^WARNING: The Magento2 standard -has been deprecated since -^Deprecated sniffs are still -^ +Squiz\. -^The Magento2\. -Support for scanning -^future\.$ -^- Squiz\. diff --git a/.github/scripts/phpmd-ruleset.xml b/.github/scripts/phpmd-ruleset.xml deleted file mode 100644 index 05e325644267..000000000000 --- a/.github/scripts/phpmd-ruleset.xml +++ /dev/null @@ -1,59 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright 2026 Adobe - * All Rights Reserved. - */ ---> -<!-- - PHPMD fallback ruleset for GitHub Actions PR checks. - - Used only when the CE sparse clone at /tmp/magento2-static is unavailable. - The primary ruleset is: - dev/tests/static/testsuite/Magento/Test/Php/_files/phpmd/ruleset.xml - fetched from the CE repo by the "Fetch Magento static PHPMD framework" step. - - Magento-specific rules (AllPurposeAction, CookieAndSessionMisuse, - custom UnusedFormalParameter) are omitted here because their rule classes - live in dev/tests/static/framework/Magento/CodeMessDetector/ which is only - available via the CE sparse clone. The primary ruleset includes them with - the php-includepath pointing to that framework directory. ---> -<ruleset name="Magento PHPMD rule set" xmlns="http://pmd.sf.net/ruleset/1.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd" - xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd"> - <description>Magento Code Check Rules (standalone)</description> - - <!-- Code Size Rules --> - <rule ref="rulesets/codesize.xml/CyclomaticComplexity" /> - <rule ref="rulesets/codesize.xml/NPathComplexity" /> - <rule ref="rulesets/codesize.xml/ExcessiveMethodLength" /> - <rule ref="rulesets/codesize.xml/ExcessiveParameterList" /> - <rule ref="rulesets/codesize.xml/ExcessivePublicCount" /> - <rule ref="rulesets/codesize.xml/TooManyFields" /> - <rule ref="rulesets/codesize.xml/ExcessiveClassComplexity"> - <properties> - <property name="maximum" value="100" /> - </properties> - </rule> - - <!-- Unused code rules --> - <rule ref="rulesets/unusedcode.xml"> - <exclude name="UnusedFormalParameter"/> - </rule> - - <!-- Code design rules --> - <rule ref="rulesets/design.xml/NumberOfChildren" /> - <rule ref="rulesets/design.xml/DepthOfInheritance"> - <properties> - <property name="minimum" value="8" /> - </properties> - </rule> - <rule ref="rulesets/design.xml/CouplingBetweenObjects" /> - - <!-- Naming Rules --> - <rule ref="rulesets/naming.xml/ShortMethodName" /> - <rule ref="rulesets/naming.xml/ConstantNamingConventions" /> - <rule ref="rulesets/naming.xml/BooleanGetMethodName" /> -</ruleset> diff --git a/.github/scripts/run-phpcs.sh b/.github/scripts/run-phpcs.sh index 570c8ad3315f..61c2ea8ce2ee 100755 --- a/.github/scripts/run-phpcs.sh +++ b/.github/scripts/run-phpcs.sh @@ -11,7 +11,6 @@ FILE_LIST="$2" shift 2 SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -NOISE_FILTER_FILE="$SCRIPT_DIR/phpcs-noise-filter.txt" if [ ! -s "$FILE_LIST" ]; then echo "No $LABEL files to check, skipping phpcs." @@ -25,9 +24,12 @@ mcs/vendor/bin/phpcs \ "$@" \ --report=full \ --no-colors \ - --file-list="$FILE_LIST" > "$phpcs_tmp" 2>&1 || phpcs_exit=$? + --report-width=200 \ + --file-list="$FILE_LIST" > "$phpcs_tmp" 2>/dev/null || phpcs_exit=$? if [ $phpcs_exit -eq 0 ] && grep -qE "^FOUND [0-9]+ (ERROR|WARNING)" "$phpcs_tmp"; then phpcs_exit=1; fi -grep -vEf "$NOISE_FILTER_FILE" "$phpcs_tmp" || true +grep -vE \ + '^DEPRECATED: |sniff is listening for |^WARNING: The Magento2 standard uses [0-9]+ deprecated|^- [A-Za-z]|^ This sniff has been deprecated|^ Support for scanning|^Deprecated sniffs are still run|^future\.$' \ + "$phpcs_tmp" || true rm -f "$phpcs_tmp" exit $phpcs_exit diff --git a/.github/scripts/tslint.json b/.github/scripts/tslint.json deleted file mode 100644 index 1b99ba7d68dd..000000000000 --- a/.github/scripts/tslint.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "rules": { - "no-var-keyword": true, - "no-any": true, - "triple-equals": true, - "semicolon": [true, "always"], - "prefer-const": true, - "no-console": false, - "eofline": true, - "trailing-comma": [true, {"multiline": "never", "singleline": "never"}] - } -} diff --git a/.github/workflows/pr-quality-gates.yml b/.github/workflows/pr-quality-gates.yml index 614d55754eb8..563f44e66755 100644 --- a/.github/workflows/pr-quality-gates.yml +++ b/.github/workflows/pr-quality-gates.yml @@ -10,7 +10,6 @@ on: types: [opened, synchronize, reopened, ready_for_review] branches: - "*" - workflow_dispatch: # Repository variables used by this workflow: # - PR_QA_ENABLED_JOBS: CSV list of top-level jobs to run. @@ -38,7 +37,7 @@ jobs: checks: read statuses: read env: - CROSS_REPO_READ_TOKEN: ${{ secrets.CROSS_REPO_READ_TOKEN }} + HAS_CROSS_REPO_TOKEN: ${{ secrets.CROSS_REPO_READ_TOKEN != '' }} steps: # ── Mainline alignment ────────────────────────────────────────── @@ -46,10 +45,13 @@ jobs: id: mainline env: GH_TOKEN: ${{ github.token }} + BASE_REF: ${{ github.event.pull_request.base.ref }} + HEAD_SHA: ${{ github.event.pull_request.head.sha }} + PR_NUMBER: ${{ github.event.pull_request.number }} run: | set -euo pipefail - base_branch="${{ github.event.pull_request.base.ref }}" - head_sha="${{ github.event.pull_request.head.sha }}" + base_branch="$BASE_REF" + head_sha="$HEAD_SHA" repo="${{ github.repository }}" owner="${repo%%/*}" echo "Base branch : ${base_branch}" @@ -98,7 +100,7 @@ jobs: fi # ── 2. Conflict check ─────────────────────────────────────────── - mergeable=$(gh api "repos/${repo}/pulls/${{ github.event.pull_request.number }}" \ + mergeable=$(gh api "repos/${repo}/pulls/${PR_NUMBER}" \ --jq '.mergeable') if [[ "$mergeable" == "false" ]]; then echo "::error::Merge conflicts detected between this branch and ${upstream_label} ${base_branch}. Merge mainline and resolve conflicts before CI can proceed." @@ -124,11 +126,14 @@ jobs: id: check env: GH_TOKEN: ${{ github.token }} + PR_NUMBER: ${{ github.event.pull_request.number }} + HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }} + BASE_REPO: ${{ github.event.pull_request.base.repo.full_name }} run: | set -euo pipefail - pr="${{ github.event.pull_request.number }}" + pr="$PR_NUMBER" repo="${{ github.repository }}" - echo "PR #${pr} ${{ github.event.pull_request.head.repo.full_name }} → ${{ github.event.pull_request.base.repo.full_name }}" + echo "PR #${pr} ${HEAD_REPO} → ${BASE_REPO}" echo "PR_QA_ENABLED_JOBS: ${{ vars.PR_QA_ENABLED_JOBS }}" # Fetch all changed files as "filename TAB status" pairs (paginated) @@ -139,8 +144,6 @@ jobs: required=( .github/workflows/pr-quality-gates.yml .github/scripts/copyright-template.txt - .github/scripts/phpmd-ruleset.xml - .github/scripts/filter-blacklist.sh ) missing=false while IFS=$'\t' read -r filename status; do @@ -265,7 +268,7 @@ jobs: if: env.HAS_JS == 'true' uses: actions/setup-node@v6 with: - node-version: '21' + node-version: '22' - name: Install Magento Coding Standard id: install-mcs @@ -340,24 +343,33 @@ jobs: - name: Print resolved tool version map if: env.HAS_PHP_OR_STATIC == 'true' + env: + REPO_NAME: ${{ github.event.repository.name }} + BASE_REF: ${{ github.event.pull_request.base.ref }} + MAGENTO_COMPOSER_REF: ${{ steps.php-version.outputs.magento_composer_ref }} + PHP_VERSION_OUT: ${{ steps.php-version.outputs.php_version }} run: | set -euo pipefail phpmd_mcs="$(.github/scripts/read-pkg-constraint.sh "${GITHUB_WORKSPACE}/mcs/composer.json" "phpmd/phpmd" || true)" phpmd_m2="$(.github/scripts/read-pkg-constraint.sh "/tmp/magento2-composer.json" "phpmd/phpmd" || true)" echo "=== Resolved Tool Version Map ===" - echo "repo_name=${{ github.event.repository.name }}" - echo "base_ref=${{ github.event.pull_request.base.ref }}" - echo "magento_composer_ref=${{ steps.php-version.outputs.magento_composer_ref }}" - echo "php_version=${{ steps.php-version.outputs.php_version }}" + echo "repo_name=${REPO_NAME}" + echo "base_ref=${BASE_REF}" + echo "magento_composer_ref=${MAGENTO_COMPOSER_REF}" + echo "php_version=${PHP_VERSION_OUT}" echo "phpmd_constraint_from_mcs=${phpmd_mcs:-<missing>}" echo "phpmd_constraint_from_magento2=${phpmd_m2:-<missing>}" - name: Fetch Magento static PHPMD framework + id: fetch-static + continue-on-error: true if: env.HAS_PHP_OR_STATIC == 'true' || env.HAS_JS == 'true' + env: + MAGENTO_COMPOSER_REF: ${{ steps.php-version.outputs.magento_composer_ref }} run: | set -euo pipefail - ref="${{ steps.php-version.outputs.magento_composer_ref }}" + ref="${MAGENTO_COMPOSER_REF}" if [ -z "$ref" ]; then ref="2.4-develop" fi @@ -377,13 +389,16 @@ jobs: lib/internal/Magento/Framework echo "Fetched Magento static PHPMD framework from ref: $ref" + echo "ready=true" >> "$GITHUB_OUTPUT" - name: Checkout changed files and fetch base commit id: files if: steps.install-mcs.outputs.ready == 'true' + env: + BASE_SHA: ${{ github.event.pull_request.base.sha }} run: | set -euo pipefail - base_sha="${{ github.event.pull_request.base.sha }}" + base_sha="$BASE_SHA" echo "base_sha=$base_sha" >> "$GITHUB_ENV" git fetch --filter=blob:none --depth=1 origin "$base_sha" 2>/dev/null || true @@ -472,11 +487,10 @@ jobs: echo "No XML/XSD files to check — skipping." exit 0 fi - sudo apt-get install -y -q libxml2-utils 2>/dev/null errors=0 while IFS= read -r file; do [ -n "$file" ] || continue - if ! xmllint --noout "$file" 2>&1; then + if ! python3 -c "import sys,xml.etree.ElementTree as ET; ET.parse(sys.argv[1])" "$file" 2>&1; then errors=$((errors + 1)) fi done < /tmp/changed_xml.txt @@ -491,7 +505,7 @@ jobs: if: always() && steps.gate.outputs.phpcs_xml == 'true' && env.HAS_STATIC == 'true' run: | set -euo pipefail - grep -E '^(app/code/|lib/internal/|app/design/|dev/tests/|pub/|setup/|phpserver/)' /tmp/changed_xml.txt 2>/dev/null > /tmp/changed_xml_phpcs.txt || true + grep -vE '^(\.github/|node_modules/|vendor/)' /tmp/changed_xml.txt 2>/dev/null > /tmp/changed_xml_phpcs.txt || true python3 - <<'PY' import xml.etree.ElementTree as ET, sys src = 'mcs/Magento2/ruleset.xml' @@ -574,24 +588,21 @@ jobs: exit 0 fi phpmd_bin="${GITHUB_WORKSPACE}/qa-tools/vendor/bin/phpmd" - magento_ruleset="/tmp/magento2-static/dev/tests/static/testsuite/Magento/Test/Php/_files/phpmd/ruleset.xml" - prepend_file="/tmp/magento2-static/phpmd-prepend.php" - # Wrap the Magento ruleset to exclude rules that require the full - # vendor tree (Laminas etc.) and crash in the sparse-clone environment. - ruleset="/tmp/phpmd-ruleset-ci.xml" - { - printf '<?xml version="1.0" encoding="UTF-8"?>\n' - printf '<ruleset name="Magento PHPMD (CI)" xmlns="http://pmd.sf.net/ruleset/1.0.0"\n' - printf ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n' - printf ' xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd">\n' - printf ' <description>Magento PHPMD rules, excluding rules that require the full vendor tree.</description>\n' - printf ' <rule ref="%s">\n' "$magento_ruleset" - printf ' <exclude name="CookieAndSessionMisuse"/>\n' - printf ' <exclude name="AllPurposeAction"/>\n' - printf ' </rule>\n' - printf '</ruleset>\n' - } > "$ruleset" - cat > "$prepend_file" <<'PHP' + prepend_file=$(mktemp) + if [ "${{ steps.fetch-static.outputs.ready }}" != "true" ]; then + ref="${{ steps.php-version.outputs.magento_composer_ref }}" + [ -z "$ref" ] && ref="2.4-develop" + echo "::warning::Magento static framework unavailable — fetching PHPMD ruleset directly from magento/magento2@${ref}." + magento_ruleset=$(mktemp /tmp/phpmd-ruleset-raw-XXXXXX.xml) + if ! curl -fsSL "https://raw.githubusercontent.com/magento/magento2/${ref}/dev/tests/static/testsuite/Magento/Test/Php/_files/phpmd/ruleset.xml" \ + -o "$magento_ruleset" 2>/dev/null; then + echo "::error::Failed to fetch PHPMD ruleset — skipping PHPMD." + exit 0 + fi + else + magento_ruleset="/tmp/magento2-static/dev/tests/static/testsuite/Magento/Test/Php/_files/phpmd/ruleset.xml" + prepend_file="/tmp/magento2-static/phpmd-prepend.php" + cat > "$prepend_file" <<'PHP' <?php $root = '/tmp/magento2-static'; $traitFile = $root . '/lib/internal/Magento/Framework/GetParameterClassTrait.php'; @@ -612,6 +623,22 @@ jobs: } }); PHP + fi + # Wrap the Magento ruleset to exclude rules that require the full + # vendor tree (Laminas etc.) and crash in the sparse-clone environment. + ruleset="/tmp/phpmd-ruleset-ci.xml" + { + printf '<?xml version="1.0" encoding="UTF-8"?>\n' + printf '<ruleset name="Magento PHPMD (CI)" xmlns="http://pmd.sf.net/ruleset/1.0.0"\n' + printf ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n' + printf ' xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd">\n' + printf ' <description>Magento PHPMD rules, excluding rules that require the full vendor tree.</description>\n' + printf ' <rule ref="%s">\n' "$magento_ruleset" + printf ' <exclude name="CookieAndSessionMisuse"/>\n' + printf ' <exclude name="AllPurposeAction"/>\n' + printf ' </rule>\n' + printf '</ruleset>\n' + } > "$ruleset" mapfile -t files < <(while IFS= read -r f; do [ -f "$f" ] && printf '%s\n' "$f"; done < /tmp/changed_php.txt) @@ -781,6 +808,10 @@ jobs: exit 0 fi + if [ "${{ steps.fetch-static.outputs.ready }}" != "true" ]; then + echo "::warning::Magento static framework unavailable — ESLint whitelist/blacklist filtering skipped. All changed JS files will be linted." + fi + # Apply Jenkins whitelist then blacklist — both live in CE repo sparse clone. # Whitelist defines which files are expected to comply (app/code, app/design, # lib/web/mage, etc.). Files outside it (grunt tasks, setup scripts) are not @@ -830,6 +861,21 @@ jobs: except FileNotFoundError: return [] + # Known top-level dirs that are not root-level Magento modules. + NON_MODULE_DIRS = { + 'app', 'lib', 'dev', 'pub', 'setup', 'vendor', '.github', + 'bin', 'generated', 'var', 'build', 'node_modules', + } + + def whitelist_path(fp): + # Root-level module repos use PascalCase top-level dirs instead + # of app/code/Magento/. Remap for whitelist matching only; + # pass the original path to ESLint. + first = fp.split('/')[0] + if first and first[0].isupper() and first not in NON_MODULE_DIRS: + return 'app/code/Magento/' + fp + return fp + with open(sys.argv[1]) as f: files = [l.strip() for l in f if l.strip()] whitelist = load(sys.argv[2]) @@ -837,16 +883,17 @@ jobs: result = [] for fp in files: - if whitelist and not any(r.match(fp) for r in whitelist): + match_fp = whitelist_path(fp) + if whitelist and not any(r.match(match_fp) for r in whitelist): continue - if any(r.match(fp) for r in blacklist): + if any(r.match(match_fp) for r in blacklist): continue result.append(fp) print('\n'.join(result)) PYEOF ) - if [ ${#js_args[@]} -eq 0 ]; then + if [ ${#js_args[@]} -eq 0 ] || [ -z "${js_args[*]}" ]; then echo "All changed JS files are outside whitelist scope or blacklisted — skipping ESLint." exit 0 fi @@ -883,29 +930,34 @@ jobs: run: | set -euo pipefail echo "PR_QA_ENABLED_JOBS='${{ vars.PR_QA_ENABLED_JOBS }}'" - if [ -n "${CROSS_REPO_READ_TOKEN}" ]; then + if [ "${HAS_CROSS_REPO_TOKEN}" = "true" ]; then echo "CROSS_REPO_READ_TOKEN=present" else echo "CROSS_REPO_READ_TOKEN=missing" fi - name: Skip if cross-repo token is missing - if: always() && contains(format(',{0},', vars.PR_QA_ENABLED_JOBS), ',aggregate-linked-pr-checks,') && env.CROSS_REPO_READ_TOKEN == '' + if: always() && contains(format(',{0},', vars.PR_QA_ENABLED_JOBS), ',aggregate-linked-pr-checks,') && env.HAS_CROSS_REPO_TOKEN == 'false' run: | set -euo pipefail echo "CROSS_REPO_READ_TOKEN is not set. Skipping aggregate-linked-pr-checks." exit 0 - name: Validate linked PR checks - if: always() && contains(format(',{0},', vars.PR_QA_ENABLED_JOBS), ',aggregate-linked-pr-checks,') && env.CROSS_REPO_READ_TOKEN != '' + if: always() && contains(format(',{0},', vars.PR_QA_ENABLED_JOBS), ',aggregate-linked-pr-checks,') && env.HAS_CROSS_REPO_TOKEN == 'true' uses: actions/github-script@v9 with: - github-token: ${{ env.CROSS_REPO_READ_TOKEN }} + github-token: ${{ secrets.CROSS_REPO_READ_TOKEN }} script: | const owner = context.repo.owner; const repo = context.repo.repo; - const pr = context.payload.pull_request; - const prNumber = pr.number; + const prNumber = context.payload.pull_request.number; + // Fetch the current PR body via REST API — the webhook payload snapshot + // (context.payload.pull_request.body) is frozen at trigger time and misses + // description edits made after the last push. + const { data: pr } = await github.rest.pulls.get({ + owner, repo, pull_number: prNumber, + }); const body = pr.body || ''; // Only scan the "Related Pull Requests" section, up to the placeholder comment. const sectionMatch = body.match( @@ -938,12 +990,12 @@ jobs: return; } - const okConclusions = new Set(['success', 'neutral', 'skipped']); const rows = []; let hasFailures = false; for (const link of links) { const label = `${link.owner}/${link.repo}#${link.number}`; + const url = `https://github.com/${link.owner}/${link.repo}/pull/${link.number}`; try { const { data: linked } = await github.rest.pulls.get({ owner: link.owner, @@ -954,83 +1006,101 @@ jobs: const sha = linked.head.sha; const prState = linked.state; - const statusesResp = await github.rest.repos.listCommitStatusesForRef({ - owner: link.owner, - repo: link.repo, - ref: sha, - per_page: 100, - }); - const statuses = statusesResp.data || []; - const badStatuses = statuses.filter(s => s.state !== 'success'); - + // Only look at the pr-quality-gates check run; ignore unrelated checks (Kodiak, etc.) const checksResp = await github.rest.checks.listForRef({ owner: link.owner, repo: link.repo, ref: sha, + check_name: 'pr-quality-gates', per_page: 100, }); - const checkRuns = checksResp.data.check_runs || []; - const badChecks = checkRuns.filter(c => c.status !== 'completed' || !okConclusions.has(c.conclusion || '')); + // GitHub returns most recent run first + const gateRun = (checksResp.data.check_runs || [])[0] || null; + + let gateStatus = 'no run'; + let failedSteps = []; + if (gateRun) { + if (gateRun.status !== 'completed') { + gateStatus = gateRun.status; + } else { + gateStatus = gateRun.conclusion; + if (gateRun.conclusion === 'failure') { + const jobIdMatch = (gateRun.details_url || gateRun.html_url || '').match(/\/job\/(\d+)/); + if (jobIdMatch) { + try { + const { data: jobData } = await github.rest.actions.getJobForWorkflowRun({ + owner: link.owner, + repo: link.repo, + job_id: parseInt(jobIdMatch[1]), + }); + failedSteps = (jobData.steps || []) + .filter(s => s.conclusion === 'failure') + .map(s => s.name); + } catch (_) { /* step detail unavailable */ } + } + } + } + } - const hasAnySignals = statuses.length > 0 || checkRuns.length > 0; - const pass = prState === 'open' && hasAnySignals && badStatuses.length === 0 && badChecks.length === 0; + // Only confirmed bad conclusions count as failures; in_progress/queued is not a failure + const badConclusions = new Set(['failure', 'cancelled', 'timed_out', 'action_required', 'stale']); + const isPending = !gateRun || gateRun.status !== 'completed'; + const isFailed = !isPending && badConclusions.has(gateRun.conclusion); - if (!pass) hasFailures = true; + if (isFailed) hasFailures = true; rows.push({ pr: label, + url, state: prState, - totalStatuses: statuses.length, - failingStatuses: badStatuses.length, - totalChecks: checkRuns.length, - failingChecks: badChecks.length, - result: pass ? 'PASS' : 'FAIL', + gateStatus, + failedSteps, + result: isFailed ? 'FAIL' : isPending ? 'PENDING' : 'PASS', error: null, }); } catch (e) { - hasFailures = true; + const httpStatus = e.status || (e.response && e.response.status) || 0; + const isTransient = httpStatus >= 500 || httpStatus === 408 || httpStatus === 429; + const shortMsg = (e.message || String(e)).split('\n')[0].slice(0, 120); + if (!isTransient) hasFailures = true; rows.push({ pr: label, + url, state: 'unknown', - totalStatuses: 0, - failingStatuses: 0, - totalChecks: 0, - failingChecks: 0, - result: 'FAIL', - error: e.message, + gateStatus: isTransient ? `api unavailable (${httpStatus})` : 'error', + failedSteps: [], + result: isTransient ? 'PENDING' : 'FAIL', + error: isTransient ? null : shortMsg, }); } } const ciCell = r => { if (r.error) return `error: ${r.error}`; - const parts = []; - if (r.totalChecks > 0) - parts.push(`${r.totalChecks} check run${r.totalChecks !== 1 ? 's' : ''}` + - (r.failingChecks > 0 ? `, ${r.failingChecks} failing` : ', all green')); - if (r.totalStatuses > 0) - parts.push(`${r.totalStatuses} status${r.totalStatuses !== 1 ? 'es' : ''}` + - (r.failingStatuses > 0 ? `, ${r.failingStatuses} failing` : ', all green')); - return parts.length > 0 ? parts.join(' / ') : 'no signals'; + if (r.gateStatus === 'no run') return 'no run yet'; + if (r.gateStatus === 'success') return 'passing'; + if (r.gateStatus === 'failure' && r.failedSteps.length > 0) + return r.failedSteps.join(', '); + return r.gateStatus; }; // GitHub Actions summary: rendered as an HTML table await core.summary .addHeading('Linked PR Aggregate Report', 3) .addTable([ - ['Linked PR', 'State', 'CI', 'Result'].map(h => ({ data: h, header: true })), + ['Linked PR', 'State', 'Quality Gate', 'Result'].map(h => ({ data: h, header: true })), ...rows.map(r => [ - r.pr, + `<a href="${r.url}">${r.pr}</a>`, r.state, ciCell(r), - r.result === 'PASS' ? '✅ PASS' : '❌ FAIL', + r.result === 'PASS' ? '✅ PASS' : r.result === 'PENDING' ? '⏳ PENDING' : '❌ FAIL', ]), ]) .write(); // Step log: plain text const logLines = rows.map(r => - ` ${r.result === 'PASS' ? '✅' : '❌'} ${r.pr} [${r.state}] ${ciCell(r)}` + ` ${r.result === 'PASS' ? '✅' : r.result === 'PENDING' ? '⏳' : '❌'} ${r.pr} [${r.state}] ${ciCell(r)} ${r.url}` ); const logReport = logLines.join('\n'); From 84d43f76fff4b95cc245ee2ca78f5b4bc5dfb49e Mon Sep 17 00:00:00 2001 From: Alexandra Zota <zota@adobe.com> Date: Thu, 25 Jun 2026 11:57:08 +0300 Subject: [PATCH 71/83] ACP2E-5049: PR Quality Gates: delivery to PB and Security Repos --- .github/scripts/check_copyright_pr.php | 29 ------------------- .../resolve_magento_tool_constraints.py | 8 ++--- 2 files changed, 2 insertions(+), 35 deletions(-) diff --git a/.github/scripts/check_copyright_pr.php b/.github/scripts/check_copyright_pr.php index e78f308b22ea..4b05ea8f6270 100644 --- a/.github/scripts/check_copyright_pr.php +++ b/.github/scripts/check_copyright_pr.php @@ -45,8 +45,6 @@ } $template = trim((string) file_get_contents($templatePath)); -$isPrivate = str_contains($template, 'ADOBE CONFIDENTIAL'); -$requiresNotice = str_contains($template, 'NOTICE:'); $changedFiles = array_filter(array_map('trim', file($filesPath))); $addedFiles = ($addedPath && file_exists($addedPath)) ? array_flip(array_filter(array_map('trim', file($addedPath)))) @@ -250,33 +248,6 @@ function buildExpectedHeader(string $template, string $filePath, int $year): str $isNew = isset($addedFiles[$filePath]); $currentHeader = extractCopyrightBlock($content); - // ── Confidentiality format check (derived from template) ───────────────── - $hasConfidential = str_contains($content, 'ADOBE CONFIDENTIAL'); - $hasNotice = str_contains($content, 'NOTICE:'); - if ($isPrivate && !$hasConfidential) { - $issues[] = [ - 'file' => $filePath, - 'reason' => 'Private repo: missing ADOBE CONFIDENTIAL header', - 'new' => $isNew, - ]; - continue; - } - if ($isPrivate && $requiresNotice && !$hasNotice) { - $issues[] = [ - 'file' => $filePath, - 'reason' => 'Private repo: missing NOTICE block in copyright header', - 'new' => $isNew, - ]; - continue; - } - if (!$isPrivate && $hasConfidential) { - $issues[] = [ - 'file' => $filePath, - 'reason' => 'Public repo: file must not contain ADOBE CONFIDENTIAL', - 'new' => $isNew, - ]; - continue; - } if ($isNew) { // ── New file: must have a copyright header in current-year format ───── diff --git a/.github/scripts/resolve_magento_tool_constraints.py b/.github/scripts/resolve_magento_tool_constraints.py index a9f2ec51d9be..c7eed385744b 100755 --- a/.github/scripts/resolve_magento_tool_constraints.py +++ b/.github/scripts/resolve_magento_tool_constraints.py @@ -8,7 +8,7 @@ Used in GitHub Actions (writes GITHUB_OUTPUT and /tmp/magento2-composer.json) and locally: - REPO_NAME=magento2b2b BASE_REF=2.4.8-p3 \\ + REPO_NAME=magento2ce BASE_REF=2.4-develop \\ python3 .github/scripts/resolve_magento_tool_constraints.py --print-summary See emulate_ci_tools_locally.sh for a full local QA-tools install. @@ -62,13 +62,9 @@ def resolve( repo_package_map = { "magento2ce": "magento/magento2-base", - "magento2ee": "magento/magento2-ee-base", - "magento2b2b": "magento/magento2-b2b-base", "inventory": "magento/inventory-metapackage", "magento2-page-builder": "magento/module-page-builder", - "magento2-page-builder-ee": "magento/page-builder-commerce", "security-package": "magento/security-package", - "security-package-ee": "magento/security-package-ee", } selected_release = "" @@ -246,7 +242,7 @@ def main() -> int: p.add_argument( "--repo-name", default=os.environ.get("REPO_NAME", ""), - help="GitHub repository name (e.g. magento2b2b). Env: REPO_NAME", + help="GitHub repository name (e.g. magento2ce). Env: REPO_NAME", ) p.add_argument( "--base-ref", From bfa1c6f40249f722575053df051394238b7cf60c Mon Sep 17 00:00:00 2001 From: Alexandra Zota <zota@adobe.com> Date: Thu, 25 Jun 2026 12:45:40 +0300 Subject: [PATCH 72/83] ACP2E-5049: PR Quality Gates: delivery to PB and Security Repos --- .../scripts/resolve_magento_tool_constraints.py | 15 +-------------- .github/workflows/pr-quality-gates.yml | 1 + 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/.github/scripts/resolve_magento_tool_constraints.py b/.github/scripts/resolve_magento_tool_constraints.py index c7eed385744b..36704ded58e0 100755 --- a/.github/scripts/resolve_magento_tool_constraints.py +++ b/.github/scripts/resolve_magento_tool_constraints.py @@ -54,21 +54,8 @@ def resolve( """ Returns (php_version, source_ref, composer_json_data, raw_php_constraint_or_empty). """ - # Normalize known repo-name aliases used across forks/exceptions. - repo_alias_map = { - "magento2inventory": "inventory", - } - normalized_repo_name = repo_alias_map.get(repo_name, repo_name) - - repo_package_map = { - "magento2ce": "magento/magento2-base", - "inventory": "magento/inventory-metapackage", - "magento2-page-builder": "magento/module-page-builder", - "security-package": "magento/security-package", - } - selected_release = "" - package_key = repo_package_map.get(normalized_repo_name, "") + package_key = os.environ.get("REPO_PACKAGE_KEY", "") base_ref = (base_ref or "").strip() def base_ref_candidates(ref: str) -> list[str]: diff --git a/.github/workflows/pr-quality-gates.yml b/.github/workflows/pr-quality-gates.yml index 563f44e66755..1f4357507549 100644 --- a/.github/workflows/pr-quality-gates.yml +++ b/.github/workflows/pr-quality-gates.yml @@ -254,6 +254,7 @@ jobs: env: REPO_NAME: ${{ github.event.repository.name }} BASE_REF: ${{ github.event.pull_request.base.ref }} + REPO_PACKAGE_KEY: magento/inventory-metapackage run: python3 .github/scripts/resolve_magento_tool_constraints.py - name: Setup PHP From 9a41469c4013a5a352fb2a142e1fc61b0d0f4d48 Mon Sep 17 00:00:00 2001 From: Sokly Meach <meach@adobe.com> Date: Fri, 3 Jul 2026 15:34:44 -0500 Subject: [PATCH 73/83] ACP2E-4973: [Feature Request] Clear redundant in store pickup data when changing shipping carrier --- ...ocationOnNonPickupShippingMethodPlugin.php | 150 +++++++++ .../ShippingInformationManagementPlugin.php | 23 +- ...ionOnNonPickupShippingMethodPluginTest.php | 289 ++++++++++++++++++ ...hippingInformationManagementPluginTest.php | 79 +++-- InventoryInStorePickupQuote/etc/di.xml | 1 + 5 files changed, 513 insertions(+), 29 deletions(-) create mode 100644 InventoryInStorePickupQuote/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPlugin.php create mode 100644 InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php diff --git a/InventoryInStorePickupQuote/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPlugin.php b/InventoryInStorePickupQuote/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPlugin.php new file mode 100644 index 000000000000..d57677cacb22 --- /dev/null +++ b/InventoryInStorePickupQuote/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPlugin.php @@ -0,0 +1,150 @@ +<?php +/** + * Copyright 2026 Adobe + * All Rights Reserved. + */ +declare(strict_types=1); + +namespace Magento\InventoryInStorePickupQuote\Plugin\Checkout; + +use Magento\Checkout\Api\Data\ShippingInformationInterface; +use Magento\Checkout\Model\ShippingInformationManagement; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\InventoryInStorePickupShippingApi\Model\Carrier\InStorePickup; +use Magento\Quote\Api\CartRepositoryInterface; +use Magento\Quote\Api\Data\AddressExtensionFactory; +use Magento\Quote\Api\Data\AddressInterface; + +/** + * Clear pickup location data from quote shipping address when switching to a non-pickup delivery method. + */ +class ClearPickupLocationOnNonPickupShippingMethodPlugin +{ + /** + * @param AddressExtensionFactory $addressExtensionFactory + * @param CartRepositoryInterface $cartRepository + */ + public function __construct( + private readonly AddressExtensionFactory $addressExtensionFactory, + private readonly CartRepositoryInterface $cartRepository + ) { + } + + /** + * Remove pickup location association before shipping information is saved for a delivery method. + * + * @param ShippingInformationManagement $subject + * @param int $cartId + * @param ShippingInformationInterface $addressInformation + * @return array + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * @throws NoSuchEntityException + */ + public function beforeSaveAddressInformation( + ShippingInformationManagement $subject, + int $cartId, + ShippingInformationInterface $addressInformation + ): array { + $carrierCode = $addressInformation->getShippingCarrierCode(); + $methodCode = $addressInformation->getShippingMethodCode(); + if ($carrierCode === null || $methodCode === null) { + return [$cartId, $addressInformation]; + } + if ($carrierCode . '_' . $methodCode === InStorePickup::DELIVERY_METHOD) { + return [$cartId, $addressInformation]; + } + $quote = $this->cartRepository->getActive($cartId); + $quoteShippingAddress = $quote->getShippingAddress(); + $shippingAddress = $addressInformation->getShippingAddress(); + $shouldResetPickupAddress = $this->shouldResetInStorePickupAddress($shippingAddress, $quoteShippingAddress); + $this->clearPickupLocationFromAddress($shippingAddress); + if ($quoteShippingAddress !== null && $quoteShippingAddress !== $shippingAddress) { + $this->clearPickupLocationFromAddress($quoteShippingAddress); + } + if ($shouldResetPickupAddress) { + $this->resetInStorePickupAddress($shippingAddress); + if ($quoteShippingAddress !== null && $quoteShippingAddress !== $shippingAddress) { + $this->resetInStorePickupAddress($quoteShippingAddress); + } + } + return [$cartId, $addressInformation]; + } + + /** + * Check if the in-store pickup address should be clear or not + * + * @param AddressInterface|null $shippingAddress + * @param AddressInterface|null $quoteShippingAddress + * @return bool + */ + private function shouldResetInStorePickupAddress( + ?AddressInterface $shippingAddress, + ?AddressInterface $quoteShippingAddress + ): bool { + if ($this->hasPickupLocationCode($shippingAddress)) { + return true; + } + if ($this->hasPickupLocationCode($quoteShippingAddress)) { + return true; + } + return $quoteShippingAddress?->getShippingMethod() === InStorePickup::DELIVERY_METHOD; + } + + /** + * Check the given address is an in-store pickup address + * + * @param AddressInterface|null $address + * @return bool + */ + private function hasPickupLocationCode(?AddressInterface $address): bool + { + $pickupLocationCode = $address?->getExtensionAttributes()?->getPickupLocationCode(); + + return $pickupLocationCode !== null && $pickupLocationCode !== ''; + } + + /** + * Clear in-store pickup address fields + * + * @param AddressInterface|null $address + * @return void + */ + private function resetInStorePickupAddress(?AddressInterface $address): void + { + if ($address === null) { + return; + } + $address->setFirstname(null); + $address->setLastname(null); + $address->setCompany(null); + $address->setStreet([]); + $address->setCity(null); + $address->setRegion(null); + $address->setRegionId(null); + $address->setRegionCode(null); + $address->setPostcode(null); + $address->setTelephone(null); + $address->setCustomerAddressId(null); + $address->setSaveInAddressBook(false); + $address->setSameAsBilling(false); + } + + /** + * Ensure extension attributes exist and clear pickup location code. + * + * @param AddressInterface|null $address + * @return void + */ + private function clearPickupLocationFromAddress(?AddressInterface $address): void + { + if ($address === null) { + return; + } + $extension = $address->getExtensionAttributes(); + if ($extension === null) { + $extension = $this->addressExtensionFactory->create(); + $address->setExtensionAttributes($extension); + } + $extension->setPickupLocationCode(null); + } +} diff --git a/InventoryInStorePickupQuote/Plugin/Checkout/ShippingInformationManagementPlugin.php b/InventoryInStorePickupQuote/Plugin/Checkout/ShippingInformationManagementPlugin.php index 50ed793153e1..1d9f06729006 100644 --- a/InventoryInStorePickupQuote/Plugin/Checkout/ShippingInformationManagementPlugin.php +++ b/InventoryInStorePickupQuote/Plugin/Checkout/ShippingInformationManagementPlugin.php @@ -33,7 +33,10 @@ public function beforeSaveAddressInformation( $address = $addressInformation->getShippingAddress(); $billingAddress = $addressInformation->getBillingAddress(); - if (!$this->isPickupStoreShipping($address) && $this->isBillingAddressCompletelyNull($billingAddress)) { + if (!$this->isPickupStoreShipping($address) + && $this->isBillingAddressCompletelyNull($billingAddress) + && $this->hasCompleteShippingAddress($address) + ) { $addressInformation->setBillingAddress($address); } @@ -58,6 +61,24 @@ private function isPickupStoreShipping(?AddressInterface $shippingAddress): bool return false; } + /** + * Check if shipping address has enough data to be copied to billing. + * + * @param AddressInterface|null $shippingAddress + * @return bool + */ + private function hasCompleteShippingAddress(?AddressInterface $shippingAddress): bool + { + if (!$shippingAddress) { + return false; + } + $street = $shippingAddress->getStreet(); + if (is_array($street)) { + $street = implode('', $street); + } + return $street && $shippingAddress->getCity(); + } + /** * Check if billing address is completely null (not set at all) * diff --git a/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php b/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php new file mode 100644 index 000000000000..0394e6a7ff98 --- /dev/null +++ b/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php @@ -0,0 +1,289 @@ +<?php +/** + * Copyright 2026 Adobe + * All Rights Reserved. + */ +declare(strict_types=1); + +namespace Magento\InventoryInStorePickupQuote\Test\Unit\Plugin\Checkout; + +use Magento\Checkout\Api\Data\ShippingInformationInterface; +use Magento\Checkout\Model\ShippingInformationManagement; +use Magento\InventoryInStorePickupQuote\Plugin\Checkout\ClearPickupLocationOnNonPickupShippingMethodPlugin; +use Magento\InventoryInStorePickupShippingApi\Model\Carrier\InStorePickup; +use Magento\Quote\Api\CartRepositoryInterface; +use Magento\Quote\Api\Data\AddressExtensionFactory; +use Magento\Quote\Api\Data\AddressExtensionInterface; +use Magento\Quote\Model\Quote; +use Magento\Quote\Model\Quote\Address; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Unit test for ClearPickupLocationOnNonPickupShippingMethodPlugin. + */ +class ClearPickupLocationOnNonPickupShippingMethodPluginTest extends TestCase +{ + private ClearPickupLocationOnNonPickupShippingMethodPlugin $plugin; + + /** @var ShippingInformationManagement&MockObject */ + private MockObject $subject; + + /** @var ShippingInformationInterface&MockObject */ + private MockObject $addressInformation; + + /** @var CartRepositoryInterface&MockObject */ + private MockObject $cartRepository; + + /** @var AddressExtensionFactory&MockObject */ + private MockObject $addressExtensionFactory; + + /** + * @inheritDoc + */ + protected function setUp(): void + { + $this->subject = $this->createMock(ShippingInformationManagement::class); + $this->addressInformation = $this->createMock(ShippingInformationInterface::class); + $this->cartRepository = $this->createMock(CartRepositoryInterface::class); + $this->addressExtensionFactory = $this->createMock(AddressExtensionFactory::class); + $this->plugin = new ClearPickupLocationOnNonPickupShippingMethodPlugin( + $this->addressExtensionFactory, + $this->cartRepository + ); + } + + /** + * @return void + */ + public function testDoesNothingWhenMethodIsInStorePickup(): void + { + $cartId = 42; + $this->addressInformation->method('getShippingCarrierCode')->willReturn('instore'); + $this->addressInformation->method('getShippingMethodCode')->willReturn('pickup'); + $this->cartRepository->expects($this->never())->method('getActive'); + + $result = $this->plugin->beforeSaveAddressInformation( + $this->subject, + $cartId, + $this->addressInformation + ); + + $this->assertSame([$cartId, $this->addressInformation], $result); + } + + /** + * @return void + */ + public function testDoesNothingWhenCarrierCodeIsNull(): void + { + $cartId = 42; + $this->addressInformation->method('getShippingCarrierCode')->willReturn(null); + $this->addressInformation->method('getShippingMethodCode')->willReturn('flatrate'); + $this->cartRepository->expects($this->never())->method('getActive'); + + $result = $this->plugin->beforeSaveAddressInformation( + $this->subject, + $cartId, + $this->addressInformation + ); + + $this->assertSame([$cartId, $this->addressInformation], $result); + } + + /** + * @return void + */ + public function testClearsPickupCodeAndResetsAddressWhenSwitchingToFlatrate(): void + { + $cartId = 42; + $extension = $this->createExtensionMock('apple-store'); + $shippingAddress = $this->createAddressMock($extension); + + $extension->expects($this->once())->method('setPickupLocationCode')->with(null); + $this->expectAddressReset($shippingAddress); + + $this->configureFlatrateMethod(); + $this->configureQuoteWithShippingAddress($cartId, $shippingAddress); + + $this->plugin->beforeSaveAddressInformation( + $this->subject, + $cartId, + $this->addressInformation + ); + } + + /** + * @return void + */ + public function testDoesNotResetAddressForNormalDeliveryCheckout(): void + { + $cartId = 42; + $shippingExtension = $this->createExtensionMock(null); + $quoteExtension = $this->createExtensionMock(null); + $shippingAddress = $this->createAddressMock($shippingExtension); + $quoteShippingAddress = $this->createAddressMock($quoteExtension); + $quoteShippingAddress->method('getShippingMethod')->willReturn('flatrate_flatrate'); + + $shippingExtension->expects($this->once())->method('setPickupLocationCode')->with(null); + $quoteExtension->expects($this->once())->method('setPickupLocationCode')->with(null); + $shippingAddress->expects($this->never())->method('setFirstname'); + $shippingAddress->expects($this->never())->method('setStreet'); + $shippingAddress->expects($this->never())->method('setCity'); + + $this->configureFlatrateMethod(); + $quote = $this->createMock(Quote::class); + $quote->method('getShippingAddress')->willReturn($quoteShippingAddress); + $this->cartRepository->method('getActive')->with($cartId)->willReturn($quote); + $this->addressInformation->method('getShippingAddress')->willReturn($shippingAddress); + + $this->plugin->beforeSaveAddressInformation( + $this->subject, + $cartId, + $this->addressInformation + ); + } + + /** + * @return void + */ + public function testClearsPickupCodeOnBothAddressesWhenDifferentFromIncoming(): void + { + $cartId = 42; + $incomingExtension = $this->createExtensionMock(null); + $quoteExtension = $this->createExtensionMock('apple-store'); + $incomingAddress = $this->createAddressMock($incomingExtension); + $quoteShippingAddress = $this->createAddressMock($quoteExtension); + + $incomingExtension->expects($this->once())->method('setPickupLocationCode')->with(null); + $quoteExtension->expects($this->once())->method('setPickupLocationCode')->with(null); + $this->expectAddressReset($incomingAddress); + $this->expectAddressReset($quoteShippingAddress); + + $this->configureFlatrateMethod(); + $quote = $this->createMock(Quote::class); + $quote->method('getShippingAddress')->willReturn($quoteShippingAddress); + $this->cartRepository->method('getActive')->with($cartId)->willReturn($quote); + $this->addressInformation->method('getShippingAddress')->willReturn($incomingAddress); + + $this->plugin->beforeSaveAddressInformation( + $this->subject, + $cartId, + $this->addressInformation + ); + } + + /** + * @return void + */ + public function testInitializesExtensionAttributesWhenMissing(): void + { + $cartId = 42; + $extension = $this->createExtensionMock(null); + $shippingAddress = $this->createAddressMock(null); + + $this->addressExtensionFactory->expects($this->once())->method('create')->willReturn($extension); + $extension->expects($this->once())->method('setPickupLocationCode')->with(null); + $shippingAddress->expects($this->once())->method('setExtensionAttributes')->with($extension); + $shippingAddress->expects($this->never())->method('setStreet'); + + $this->configureFlatrateMethod(); + $this->configureQuoteWithShippingAddress($cartId, $shippingAddress); + + $this->plugin->beforeSaveAddressInformation( + $this->subject, + $cartId, + $this->addressInformation + ); + } + + /** + * @return void + */ + public function testResetsAddressWhenQuoteShippingMethodIsStillInStorePickup(): void + { + $cartId = 42; + $extension = $this->createExtensionMock(null); + $shippingAddress = $this->createAddressMock($extension); + $quoteShippingAddress = $this->createAddressMock($extension); + $quoteShippingAddress->method('getShippingMethod')->willReturn(InStorePickup::DELIVERY_METHOD); + + $extension->expects($this->exactly(2))->method('setPickupLocationCode')->with(null); + $this->expectAddressReset($shippingAddress); + $this->expectAddressReset($quoteShippingAddress); + + $this->configureFlatrateMethod(); + $quote = $this->createMock(Quote::class); + $quote->method('getShippingAddress')->willReturn($quoteShippingAddress); + $this->cartRepository->method('getActive')->with($cartId)->willReturn($quote); + $this->addressInformation->method('getShippingAddress')->willReturn($shippingAddress); + + $this->plugin->beforeSaveAddressInformation( + $this->subject, + $cartId, + $this->addressInformation + ); + } + + /** + * @param Address&MockObject $address + * @return void + */ + private function expectAddressReset(MockObject $address): void + { + $address->expects($this->once())->method('setFirstname')->with(null); + $address->expects($this->once())->method('setLastname')->with(null); + $address->expects($this->once())->method('setCompany')->with(null); + $address->expects($this->once())->method('setStreet')->with([]); + $address->expects($this->once())->method('setCity')->with(null); + $address->expects($this->once())->method('setPostcode')->with(null); + } + + /** + * @param int $cartId + * @param Address&MockObject $shippingAddress + * @return void + */ + private function configureQuoteWithShippingAddress(int $cartId, MockObject $shippingAddress): void + { + $quote = $this->createMock(Quote::class); + $quote->method('getShippingAddress')->willReturn($shippingAddress); + $this->cartRepository->method('getActive')->with($cartId)->willReturn($quote); + $this->addressInformation->method('getShippingAddress')->willReturn($shippingAddress); + } + + /** + * @return void + */ + private function configureFlatrateMethod(): void + { + $this->addressInformation->method('getShippingCarrierCode')->willReturn('flatrate'); + $this->addressInformation->method('getShippingMethodCode')->willReturn('flatrate'); + } + + /** + * @param AddressExtensionInterface&MockObject|null $extension + * @return Address&MockObject + */ + private function createAddressMock(?MockObject $extension): MockObject + { + $address = $this->getMockBuilder(Address::class) + ->disableOriginalConstructor() + ->getMock(); + $address->method('getExtensionAttributes')->willReturn($extension); + + return $address; + } + + /** + * @param string|null $pickupLocationCode + * @return AddressExtensionInterface&MockObject + */ + private function createExtensionMock(?string $pickupLocationCode): MockObject + { + $extension = $this->createMock(AddressExtensionInterface::class); + $extension->method('getPickupLocationCode')->willReturn($pickupLocationCode); + + return $extension; + } +} diff --git a/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ShippingInformationManagementPluginTest.php b/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ShippingInformationManagementPluginTest.php index 91721d1d491a..de56763f7aa4 100644 --- a/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ShippingInformationManagementPluginTest.php +++ b/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ShippingInformationManagementPluginTest.php @@ -9,20 +9,17 @@ use Magento\Checkout\Api\Data\ShippingInformationInterface; use Magento\Checkout\Model\ShippingInformationManagement; -use Magento\Framework\TestFramework\Unit\Helper\MockCreationTrait; use Magento\InventoryInStorePickupQuote\Plugin\Checkout\ShippingInformationManagementPlugin; -use Magento\Quote\Api\Data\AddressInterface; use Magento\Quote\Api\Data\AddressExtensionInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; +use Magento\Quote\Api\Data\AddressInterface; /** * Unit test for ShippingInformationManagementPlugin. */ class ShippingInformationManagementPluginTest extends TestCase { - use MockCreationTrait; - /** * Test subject. * @@ -30,30 +27,20 @@ class ShippingInformationManagementPluginTest extends TestCase */ private $plugin; - /** - * @var ShippingInformationManagement|MockObject - */ - private $subject; + /** @var ShippingInformationManagement&MockObject */ + private MockObject $subject; - /** - * @var ShippingInformationInterface|MockObject - */ - private $addressInformation; + /** @var ShippingInformationInterface&MockObject */ + private MockObject $addressInformation; - /** - * @var AddressInterface|MockObject - */ - private $shippingAddress; + /** @var AddressInterface&MockObject */ + private MockObject $shippingAddress; - /** - * @var AddressInterface|MockObject - */ - private $billingAddress; + /** @var AddressInterface&MockObject */ + private MockObject $billingAddress; - /** - * @var AddressInterface|MockObject - */ - private $extensionAttributes; + /** @var AddressExtensionInterface&MockObject */ + private MockObject $extensionAttributes; /** * @inheritDoc @@ -64,10 +51,7 @@ protected function setUp(): void $this->addressInformation = $this->createMock(ShippingInformationInterface::class); $this->shippingAddress = $this->createMock(AddressInterface::class); $this->billingAddress = $this->createMock(AddressInterface::class); - $this->extensionAttributes = $this->createPartialMockWithReflection( - AddressExtensionInterface::class, - ['getPickupLocationCode'] - ); + $this->extensionAttributes = $this->createMock(AddressExtensionInterface::class); $this->plugin = new ShippingInformationManagementPlugin(); } @@ -145,6 +129,12 @@ public function testBeforeSaveAddressInformationNotPickupStore(): void $this->extensionAttributes->expects($this->once()) ->method('getPickupLocationCode') ->willReturn(null); + $this->shippingAddress->expects($this->once()) + ->method('getStreet') + ->willReturn(['123 Main St']); + $this->shippingAddress->expects($this->once()) + ->method('getCity') + ->willReturn('Austin'); $this->addressInformation->expects($this->once()) ->method('getShippingAddress') ->willReturn($this->shippingAddress); @@ -161,4 +151,37 @@ public function testBeforeSaveAddressInformationNotPickupStore(): void ); $this->assertEquals([$cartId, $this->addressInformation], $result); } + + /** + * Test billing is not copied when shipping address was cleared after pickup reset + * + * @return void + */ + public function testBeforeSaveAddressInformationDoesNotCopyIncompleteShippingAddressToBilling(): void + { + $cartId = 123; + $this->shippingAddress->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn($this->extensionAttributes); + $this->extensionAttributes->expects($this->once()) + ->method('getPickupLocationCode') + ->willReturn(null); + $this->shippingAddress->expects($this->once()) + ->method('getStreet') + ->willReturn([]); + $this->shippingAddress->expects($this->never())->method('getCity'); + $this->addressInformation->expects($this->once()) + ->method('getShippingAddress') + ->willReturn($this->shippingAddress); + $this->addressInformation->expects($this->once()) + ->method('getBillingAddress') + ->willReturn(null); + $this->addressInformation->expects($this->never())->method('setBillingAddress'); + $result = $this->plugin->beforeSaveAddressInformation( + $this->subject, + $cartId, + $this->addressInformation + ); + $this->assertEquals([$cartId, $this->addressInformation], $result); + } } diff --git a/InventoryInStorePickupQuote/etc/di.xml b/InventoryInStorePickupQuote/etc/di.xml index 50336d6ab905..c43ba5a62e41 100644 --- a/InventoryInStorePickupQuote/etc/di.xml +++ b/InventoryInStorePickupQuote/etc/di.xml @@ -38,6 +38,7 @@ <plugin name="inventory_in_store_pickup_quote_replace_shipping_address_on_assign_customer" sortOrder="20" type="Magento\InventoryInStorePickupQuote\Plugin\Quote\ReplaceShippingAddressWithPickupLocationAddressOnAssignCustomer" /> </type> <type name="Magento\Checkout\Model\ShippingInformationManagement"> + <plugin name="inventory_in_store_pickup_quote_clear_pickup_on_non_pickup_shipping_method" sortOrder="10" type="Magento\InventoryInStorePickupQuote\Plugin\Checkout\ClearPickupLocationOnNonPickupShippingMethodPlugin" /> <plugin name="inventory_in_store_pickup_quote_shipping_information_management" sortOrder="20" type="Magento\InventoryInStorePickupQuote\Plugin\Checkout\ShippingInformationManagementPlugin" /> </type> </config> From 22a62d8fa6231406e11d9979b7e7f259a20af15e Mon Sep 17 00:00:00 2001 From: Sokly Meach <meach@adobe.com> Date: Fri, 3 Jul 2026 20:41:13 -0500 Subject: [PATCH 74/83] ACP2E-4973: [Feature Request] Clear redundant in store pickup data when changing shipping carrier --- .../ClearPickupLocationOnNonPickupShippingMethodPluginTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php b/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php index 0394e6a7ff98..da99053e5a81 100644 --- a/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php +++ b/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php @@ -24,6 +24,9 @@ */ class ClearPickupLocationOnNonPickupShippingMethodPluginTest extends TestCase { + /** + * Test subject + */ private ClearPickupLocationOnNonPickupShippingMethodPlugin $plugin; /** @var ShippingInformationManagement&MockObject */ From 0e03fd4c053045a875d6670b47024016b105008d Mon Sep 17 00:00:00 2001 From: Sokly Meach <meach@adobe.com> Date: Fri, 3 Jul 2026 20:43:24 -0500 Subject: [PATCH 75/83] ACP2E-4973: [Feature Request] Clear redundant in store pickup data when changing shipping carrier --- .../ClearPickupLocationOnNonPickupShippingMethodPluginTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php b/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php index da99053e5a81..fb8210c1a2e3 100644 --- a/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php +++ b/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php @@ -26,6 +26,8 @@ class ClearPickupLocationOnNonPickupShippingMethodPluginTest extends TestCase { /** * Test subject + * + * @var ClearPickupLocationOnNonPickupShippingMethodPlugin */ private ClearPickupLocationOnNonPickupShippingMethodPlugin $plugin; From f2435f35157632f5dc1ce29da48fe6251ec138cf Mon Sep 17 00:00:00 2001 From: Sokly Meach <meach@adobe.com> Date: Mon, 6 Jul 2026 16:45:06 -0500 Subject: [PATCH 76/83] ACP2E-4973: [Feature Request] Clear redundant in store pickup data when changing shipping carrier --- ...ocationOnNonPickupShippingMethodPlugin.php | 22 +++++----- ...ionOnNonPickupShippingMethodPluginTest.php | 40 ++++++++++++++++++- 2 files changed, 51 insertions(+), 11 deletions(-) diff --git a/InventoryInStorePickupQuote/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPlugin.php b/InventoryInStorePickupQuote/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPlugin.php index d57677cacb22..a69db9683fbb 100644 --- a/InventoryInStorePickupQuote/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPlugin.php +++ b/InventoryInStorePickupQuote/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPlugin.php @@ -53,15 +53,22 @@ public function beforeSaveAddressInformation( if ($carrierCode . '_' . $methodCode === InStorePickup::DELIVERY_METHOD) { return [$cartId, $addressInformation]; } + $shippingAddress = $addressInformation->getShippingAddress(); $quote = $this->cartRepository->getActive($cartId); $quoteShippingAddress = $quote->getShippingAddress(); - $shippingAddress = $addressInformation->getShippingAddress(); - $shouldResetPickupAddress = $this->shouldResetInStorePickupAddress($shippingAddress, $quoteShippingAddress); + $quoteIsInStorePickup = $this->isQuoteInStorePickupOrder($quoteShippingAddress); + + // The request is establishing in-store pickup (it carries a pickup location) on a cart that is + // not yet a pickup order, so honor it instead of treating it as a switch to home delivery. + if (!$quoteIsInStorePickup && $this->hasPickupLocationCode($shippingAddress)) { + return [$cartId, $addressInformation]; + } + $this->clearPickupLocationFromAddress($shippingAddress); if ($quoteShippingAddress !== null && $quoteShippingAddress !== $shippingAddress) { $this->clearPickupLocationFromAddress($quoteShippingAddress); } - if ($shouldResetPickupAddress) { + if ($quoteIsInStorePickup) { $this->resetInStorePickupAddress($shippingAddress); if ($quoteShippingAddress !== null && $quoteShippingAddress !== $shippingAddress) { $this->resetInStorePickupAddress($quoteShippingAddress); @@ -71,19 +78,14 @@ public function beforeSaveAddressInformation( } /** - * Check if the in-store pickup address should be clear or not + * Check whether the cart is currently an in-store pickup order. * - * @param AddressInterface|null $shippingAddress * @param AddressInterface|null $quoteShippingAddress * @return bool */ - private function shouldResetInStorePickupAddress( - ?AddressInterface $shippingAddress, + private function isQuoteInStorePickupOrder( ?AddressInterface $quoteShippingAddress ): bool { - if ($this->hasPickupLocationCode($shippingAddress)) { - return true; - } if ($this->hasPickupLocationCode($quoteShippingAddress)) { return true; } diff --git a/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php b/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php index fb8210c1a2e3..fa5ec84bedda 100644 --- a/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php +++ b/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php @@ -97,9 +97,47 @@ public function testDoesNothingWhenCarrierCodeIsNull(): void } /** + * The request is establishing in-store pickup (it carries a pickup location) on a cart that is + * not yet a pickup order, so the plugin must keep the address even with a placeholder carrier. + * + * @return void + */ + public function testKeepsPickupStateWhenRequestEstablishesPickupOnNonPickupQuote(): void + { + $cartId = 42; + $incomingExtension = $this->createExtensionMock('apple-store'); + $incomingAddress = $this->createAddressMock($incomingExtension); + $quoteExtension = $this->createExtensionMock(null); + $quoteShippingAddress = $this->createAddressMock($quoteExtension); + $quoteShippingAddress->method('getShippingMethod')->willReturn(null); + + $incomingExtension->expects($this->never())->method('setPickupLocationCode'); + $incomingAddress->expects($this->never())->method('setFirstname'); + $incomingAddress->expects($this->never())->method('setStreet'); + $incomingAddress->expects($this->never())->method('setCity'); + + $this->configureFlatrateMethod(); + $quote = $this->createMock(Quote::class); + $quote->method('getShippingAddress')->willReturn($quoteShippingAddress); + $this->cartRepository->method('getActive')->with($cartId)->willReturn($quote); + $this->addressInformation->method('getShippingAddress')->willReturn($incomingAddress); + + $result = $this->plugin->beforeSaveAddressInformation( + $this->subject, + $cartId, + $this->addressInformation + ); + + $this->assertSame([$cartId, $this->addressInformation], $result); + } + + /** + * Switching an existing in-store pickup order to home delivery must clear the pickup location and + * reset the store address even though the reused quote address still carries the pickup code. + * * @return void */ - public function testClearsPickupCodeAndResetsAddressWhenSwitchingToFlatrate(): void + public function testClearsPickupWhenSwitchingExistingPickupOrderToDelivery(): void { $cartId = 42; $extension = $this->createExtensionMock('apple-store'); From 9176b81a7664d90d3807e35c7f0a35207730b111 Mon Sep 17 00:00:00 2001 From: Sokly Meach <meach@adobe.com> Date: Mon, 6 Jul 2026 21:50:08 -0500 Subject: [PATCH 77/83] ACP2E-4973: [Feature Request] Clear redundant in store pickup data when changing shipping carrier --- ...ocationOnNonPickupShippingMethodPlugin.php | 91 +++++++++++++++---- ...ionOnNonPickupShippingMethodPluginTest.php | 6 +- 2 files changed, 77 insertions(+), 20 deletions(-) diff --git a/InventoryInStorePickupQuote/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPlugin.php b/InventoryInStorePickupQuote/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPlugin.php index a69db9683fbb..ffc178330898 100644 --- a/InventoryInStorePickupQuote/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPlugin.php +++ b/InventoryInStorePickupQuote/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPlugin.php @@ -45,36 +45,89 @@ public function beforeSaveAddressInformation( int $cartId, ShippingInformationInterface $addressInformation ): array { - $carrierCode = $addressInformation->getShippingCarrierCode(); - $methodCode = $addressInformation->getShippingMethodCode(); - if ($carrierCode === null || $methodCode === null) { - return [$cartId, $addressInformation]; - } - if ($carrierCode . '_' . $methodCode === InStorePickup::DELIVERY_METHOD) { + if ($this->shouldSkipForShippingMethod($addressInformation)) { return [$cartId, $addressInformation]; } $shippingAddress = $addressInformation->getShippingAddress(); - $quote = $this->cartRepository->getActive($cartId); - $quoteShippingAddress = $quote->getShippingAddress(); + $quoteShippingAddress = $this->cartRepository->getActive($cartId)->getShippingAddress(); $quoteIsInStorePickup = $this->isQuoteInStorePickupOrder($quoteShippingAddress); - - // The request is establishing in-store pickup (it carries a pickup location) on a cart that is - // not yet a pickup order, so honor it instead of treating it as a switch to home delivery. - if (!$quoteIsInStorePickup && $this->hasPickupLocationCode($shippingAddress)) { + if ($this->shouldPreservePickupAssignment($quoteIsInStorePickup, $shippingAddress)) { return [$cartId, $addressInformation]; } + $this->cleanupPickupFromAddresses($shippingAddress, $quoteShippingAddress, $quoteIsInStorePickup); + return [$cartId, $addressInformation]; + } + + /** + * Skip cleanup when shipping method is missing or already in-store pickup. + * + * @param ShippingInformationInterface $addressInformation + * @return bool + */ + private function shouldSkipForShippingMethod(ShippingInformationInterface $addressInformation): bool + { + $carrierCode = $addressInformation->getShippingCarrierCode(); + $methodCode = $addressInformation->getShippingMethodCode(); + if ($carrierCode === null || $methodCode === null) { + return true; + } + return $carrierCode . '_' . $methodCode === InStorePickup::DELIVERY_METHOD; + } + + /** + * Skip cleanup when the request is establishing pickup on a non-pickup quote. + * + * @param bool $quoteIsInStorePickup + * @param AddressInterface|null $shippingAddress + * @return bool + */ + private function shouldPreservePickupAssignment( + bool $quoteIsInStorePickup, + ?AddressInterface $shippingAddress + ): bool { + return !$quoteIsInStorePickup && $this->hasPickupLocationCode($shippingAddress); + } + /** + * Clear pickup association and optionally reset store address fields. + * + * @param AddressInterface|null $shippingAddress + * @param AddressInterface|null $quoteShippingAddress + * @param bool $quoteIsInStorePickup + * @return void + */ + private function cleanupPickupFromAddresses( + ?AddressInterface $shippingAddress, + ?AddressInterface $quoteShippingAddress, + bool $quoteIsInStorePickup + ): void { $this->clearPickupLocationFromAddress($shippingAddress); - if ($quoteShippingAddress !== null && $quoteShippingAddress !== $shippingAddress) { + if ($this->isDistinctQuoteAddress($quoteShippingAddress, $shippingAddress)) { $this->clearPickupLocationFromAddress($quoteShippingAddress); } - if ($quoteIsInStorePickup) { - $this->resetInStorePickupAddress($shippingAddress); - if ($quoteShippingAddress !== null && $quoteShippingAddress !== $shippingAddress) { - $this->resetInStorePickupAddress($quoteShippingAddress); - } + + if (!$quoteIsInStorePickup) { + return; } - return [$cartId, $addressInformation]; + + $this->resetInStorePickupAddress($shippingAddress); + if ($this->isDistinctQuoteAddress($quoteShippingAddress, $shippingAddress)) { + $this->resetInStorePickupAddress($quoteShippingAddress); + } + } + + /** + * Check whether quote shipping address is a different object from the incoming address. + * + * @param AddressInterface|null $quoteShippingAddress + * @param AddressInterface|null $shippingAddress + * @return bool + */ + private function isDistinctQuoteAddress( + ?AddressInterface $quoteShippingAddress, + ?AddressInterface $shippingAddress + ): bool { + return $quoteShippingAddress !== null && $quoteShippingAddress !== $shippingAddress; } /** diff --git a/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php b/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php index fa5ec84bedda..0c18c13305b5 100644 --- a/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php +++ b/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php @@ -324,7 +324,11 @@ private function createAddressMock(?MockObject $extension): MockObject */ private function createExtensionMock(?string $pickupLocationCode): MockObject { - $extension = $this->createMock(AddressExtensionInterface::class); + $builder = $this->getMockBuilder(AddressExtensionInterface::class); + if (!method_exists(AddressExtensionInterface::class, 'getPickupLocationCode')) { + $builder->addMethods(['getPickupLocationCode', 'setPickupLocationCode']); + } + $extension = $builder->getMock(); $extension->method('getPickupLocationCode')->willReturn($pickupLocationCode); return $extension; From 6631de47980627359b469941192af152a1e94b11 Mon Sep 17 00:00:00 2001 From: Sokly Meach <meach@adobe.com> Date: Tue, 7 Jul 2026 12:31:22 -0500 Subject: [PATCH 78/83] ACP2E-4973: [Feature Request] Clear redundant in store pickup data when changing shipping carrier --- InventoryInStorePickupQuote/etc/di.xml | 1 - ...ocationOnNonPickupShippingMethodPlugin.php | 2 +- .../AddressExtensionStubInterface.php | 35 +++++++++++++++++++ ...ionOnNonPickupShippingMethodPluginTest.php | 10 ++---- .../composer.json | 5 ++- .../etc/graphql/di.xml | 5 +++ .../etc/module.xml | 2 ++ 7 files changed, 50 insertions(+), 10 deletions(-) rename {InventoryInStorePickupQuote => InventoryInStorePickupQuoteGraphQl}/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPlugin.php (99%) create mode 100644 InventoryInStorePickupQuoteGraphQl/Test/Unit/Plugin/Checkout/AddressExtensionStubInterface.php rename {InventoryInStorePickupQuote => InventoryInStorePickupQuoteGraphQl}/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php (96%) diff --git a/InventoryInStorePickupQuote/etc/di.xml b/InventoryInStorePickupQuote/etc/di.xml index c43ba5a62e41..50336d6ab905 100644 --- a/InventoryInStorePickupQuote/etc/di.xml +++ b/InventoryInStorePickupQuote/etc/di.xml @@ -38,7 +38,6 @@ <plugin name="inventory_in_store_pickup_quote_replace_shipping_address_on_assign_customer" sortOrder="20" type="Magento\InventoryInStorePickupQuote\Plugin\Quote\ReplaceShippingAddressWithPickupLocationAddressOnAssignCustomer" /> </type> <type name="Magento\Checkout\Model\ShippingInformationManagement"> - <plugin name="inventory_in_store_pickup_quote_clear_pickup_on_non_pickup_shipping_method" sortOrder="10" type="Magento\InventoryInStorePickupQuote\Plugin\Checkout\ClearPickupLocationOnNonPickupShippingMethodPlugin" /> <plugin name="inventory_in_store_pickup_quote_shipping_information_management" sortOrder="20" type="Magento\InventoryInStorePickupQuote\Plugin\Checkout\ShippingInformationManagementPlugin" /> </type> </config> diff --git a/InventoryInStorePickupQuote/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPlugin.php b/InventoryInStorePickupQuoteGraphQl/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPlugin.php similarity index 99% rename from InventoryInStorePickupQuote/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPlugin.php rename to InventoryInStorePickupQuoteGraphQl/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPlugin.php index ffc178330898..d7c6010a7266 100644 --- a/InventoryInStorePickupQuote/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPlugin.php +++ b/InventoryInStorePickupQuoteGraphQl/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPlugin.php @@ -5,7 +5,7 @@ */ declare(strict_types=1); -namespace Magento\InventoryInStorePickupQuote\Plugin\Checkout; +namespace Magento\InventoryInStorePickupQuoteGraphQl\Plugin\Checkout; use Magento\Checkout\Api\Data\ShippingInformationInterface; use Magento\Checkout\Model\ShippingInformationManagement; diff --git a/InventoryInStorePickupQuoteGraphQl/Test/Unit/Plugin/Checkout/AddressExtensionStubInterface.php b/InventoryInStorePickupQuoteGraphQl/Test/Unit/Plugin/Checkout/AddressExtensionStubInterface.php new file mode 100644 index 000000000000..9859fb10a725 --- /dev/null +++ b/InventoryInStorePickupQuoteGraphQl/Test/Unit/Plugin/Checkout/AddressExtensionStubInterface.php @@ -0,0 +1,35 @@ +<?php +/** + * Copyright 2026 Adobe + * All Rights Reserved. + */ +declare(strict_types=1); + +namespace Magento\InventoryInStorePickupQuoteGraphQl\Test\Unit\Plugin\Checkout; + +use Magento\Quote\Api\Data\AddressExtensionInterface; + +/** + * Test stub that declares the pickup location extension attribute methods. + * + * The source AddressExtensionInterface is an empty marker; getPickupLocationCode()/ + * setPickupLocationCode() only exist on the generated interface. Mocking this stub keeps + * the unit test independent of generated code and PHPUnit version. + */ +interface AddressExtensionStubInterface extends AddressExtensionInterface +{ + /** + * Get pickup location code. + * + * @return string|null + */ + public function getPickupLocationCode(); + + /** + * Set pickup location code. + * + * @param string|null $pickupLocationCode + * @return $this + */ + public function setPickupLocationCode($pickupLocationCode); +} diff --git a/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php b/InventoryInStorePickupQuoteGraphQl/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php similarity index 96% rename from InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php rename to InventoryInStorePickupQuoteGraphQl/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php index 0c18c13305b5..d09f5a788830 100644 --- a/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php +++ b/InventoryInStorePickupQuoteGraphQl/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php @@ -5,11 +5,11 @@ */ declare(strict_types=1); -namespace Magento\InventoryInStorePickupQuote\Test\Unit\Plugin\Checkout; +namespace Magento\InventoryInStorePickupQuoteGraphQl\Test\Unit\Plugin\Checkout; use Magento\Checkout\Api\Data\ShippingInformationInterface; use Magento\Checkout\Model\ShippingInformationManagement; -use Magento\InventoryInStorePickupQuote\Plugin\Checkout\ClearPickupLocationOnNonPickupShippingMethodPlugin; +use Magento\InventoryInStorePickupQuoteGraphQl\Plugin\Checkout\ClearPickupLocationOnNonPickupShippingMethodPlugin; use Magento\InventoryInStorePickupShippingApi\Model\Carrier\InStorePickup; use Magento\Quote\Api\CartRepositoryInterface; use Magento\Quote\Api\Data\AddressExtensionFactory; @@ -324,11 +324,7 @@ private function createAddressMock(?MockObject $extension): MockObject */ private function createExtensionMock(?string $pickupLocationCode): MockObject { - $builder = $this->getMockBuilder(AddressExtensionInterface::class); - if (!method_exists(AddressExtensionInterface::class, 'getPickupLocationCode')) { - $builder->addMethods(['getPickupLocationCode', 'setPickupLocationCode']); - } - $extension = $builder->getMock(); + $extension = $this->createMock(AddressExtensionStubInterface::class); $extension->method('getPickupLocationCode')->willReturn($pickupLocationCode); return $extension; diff --git a/InventoryInStorePickupQuoteGraphQl/composer.json b/InventoryInStorePickupQuoteGraphQl/composer.json index 0dcab444ee2b..df6adfd2ecb0 100644 --- a/InventoryInStorePickupQuoteGraphQl/composer.json +++ b/InventoryInStorePickupQuoteGraphQl/composer.json @@ -7,7 +7,10 @@ "magento/module-quote-graph-ql": "*", "magento/module-quote": "*", "magento/module-graph-ql": "*", - "magento/module-inventory": "*" + "magento/module-checkout": "*", + "magento/module-inventory": "*", + "magento/module-inventory-in-store-pickup-quote": "*", + "magento/module-inventory-in-store-pickup-shipping-api": "*" }, "type": "magento2-module", "license": [ diff --git a/InventoryInStorePickupQuoteGraphQl/etc/graphql/di.xml b/InventoryInStorePickupQuoteGraphQl/etc/graphql/di.xml index 7eba43545a4b..a53b8f4c91cb 100644 --- a/InventoryInStorePickupQuoteGraphQl/etc/graphql/di.xml +++ b/InventoryInStorePickupQuoteGraphQl/etc/graphql/di.xml @@ -9,4 +9,9 @@ <type name="Magento\QuoteGraphQl\Model\Cart\GetShippingAddress"> <plugin name="adapt_set_shipping_address_on_cart_for_store_pickup_plugin" type="Magento\InventoryInStorePickupQuoteGraphQl\Model\Cart\GetShippingAddress\AdaptGetShippingAddressPlugin"/> </type> + <type name="Magento\Checkout\Model\ShippingInformationManagement"> + <plugin name="inventory_in_store_pickup_quote_graphql_clear_pickup_on_non_pickup_shipping_method" + type="Magento\InventoryInStorePickupQuoteGraphQl\Plugin\Checkout\ClearPickupLocationOnNonPickupShippingMethodPlugin" + sortOrder="10"/> + </type> </config> diff --git a/InventoryInStorePickupQuoteGraphQl/etc/module.xml b/InventoryInStorePickupQuoteGraphQl/etc/module.xml index cd56efd72cbe..4848ee21638a 100644 --- a/InventoryInStorePickupQuoteGraphQl/etc/module.xml +++ b/InventoryInStorePickupQuoteGraphQl/etc/module.xml @@ -11,6 +11,8 @@ <module name="Magento_QuoteGraphQl" /> <module name="Magento_Quote" /> <module name="Magento_GraphQl" /> + <module name="Magento_Checkout" /> + <module name="Magento_InventoryInStorePickupQuote" /> </sequence> </module> </config> From 812a94e65d1fd1613758fb65b624bc786a2cd029 Mon Sep 17 00:00:00 2001 From: Sokly Meach <meach@adobe.com> Date: Tue, 7 Jul 2026 13:26:23 -0500 Subject: [PATCH 79/83] ACP2E-4973: [Feature Request] Clear redundant in store pickup data when changing shipping carrier --- InventoryInStorePickupQuoteGraphQl/composer.json | 1 - InventoryInStorePickupQuoteGraphQl/etc/module.xml | 1 - 2 files changed, 2 deletions(-) diff --git a/InventoryInStorePickupQuoteGraphQl/composer.json b/InventoryInStorePickupQuoteGraphQl/composer.json index df6adfd2ecb0..6e58a32bb7bb 100644 --- a/InventoryInStorePickupQuoteGraphQl/composer.json +++ b/InventoryInStorePickupQuoteGraphQl/composer.json @@ -9,7 +9,6 @@ "magento/module-graph-ql": "*", "magento/module-checkout": "*", "magento/module-inventory": "*", - "magento/module-inventory-in-store-pickup-quote": "*", "magento/module-inventory-in-store-pickup-shipping-api": "*" }, "type": "magento2-module", diff --git a/InventoryInStorePickupQuoteGraphQl/etc/module.xml b/InventoryInStorePickupQuoteGraphQl/etc/module.xml index 4848ee21638a..08dd28aad981 100644 --- a/InventoryInStorePickupQuoteGraphQl/etc/module.xml +++ b/InventoryInStorePickupQuoteGraphQl/etc/module.xml @@ -12,7 +12,6 @@ <module name="Magento_Quote" /> <module name="Magento_GraphQl" /> <module name="Magento_Checkout" /> - <module name="Magento_InventoryInStorePickupQuote" /> </sequence> </module> </config> From 28e850b037c7665b11ad3b095fb09ff80e33d1b8 Mon Sep 17 00:00:00 2001 From: Sokly Meach <meach@adobe.com> Date: Tue, 7 Jul 2026 15:22:19 -0500 Subject: [PATCH 80/83] ACP2E-4973: [Feature Request] Clear redundant in store pickup data when changing shipping carrier --- ...hippingInformationManagementPluginTest.php | 30 ++++++++++++---- .../AddressExtensionStubInterface.php | 35 ------------------- ...ionOnNonPickupShippingMethodPluginTest.php | 8 ++++- 3 files changed, 30 insertions(+), 43 deletions(-) delete mode 100644 InventoryInStorePickupQuoteGraphQl/Test/Unit/Plugin/Checkout/AddressExtensionStubInterface.php diff --git a/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ShippingInformationManagementPluginTest.php b/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ShippingInformationManagementPluginTest.php index de56763f7aa4..114f763652a2 100644 --- a/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ShippingInformationManagementPluginTest.php +++ b/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ShippingInformationManagementPluginTest.php @@ -9,17 +9,20 @@ use Magento\Checkout\Api\Data\ShippingInformationInterface; use Magento\Checkout\Model\ShippingInformationManagement; +use Magento\Framework\TestFramework\Unit\Helper\MockCreationTrait; use Magento\InventoryInStorePickupQuote\Plugin\Checkout\ShippingInformationManagementPlugin; use Magento\Quote\Api\Data\AddressExtensionInterface; +use Magento\Quote\Api\Data\AddressInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Magento\Quote\Api\Data\AddressInterface; /** * Unit test for ShippingInformationManagementPlugin. */ class ShippingInformationManagementPluginTest extends TestCase { + use MockCreationTrait; + /** * Test subject. * @@ -27,19 +30,29 @@ class ShippingInformationManagementPluginTest extends TestCase */ private $plugin; - /** @var ShippingInformationManagement&MockObject */ + /** + * @var ShippingInformationManagement&MockObject + */ private MockObject $subject; - /** @var ShippingInformationInterface&MockObject */ + /** + * @var ShippingInformationInterface&MockObject + */ private MockObject $addressInformation; - /** @var AddressInterface&MockObject */ + /** + * @var AddressInterface&MockObject + */ private MockObject $shippingAddress; - /** @var AddressInterface&MockObject */ + /** + * @var AddressInterface&MockObject + */ private MockObject $billingAddress; - /** @var AddressExtensionInterface&MockObject */ + /** + * @var AddressExtensionInterface&MockObject + */ private MockObject $extensionAttributes; /** @@ -51,7 +64,10 @@ protected function setUp(): void $this->addressInformation = $this->createMock(ShippingInformationInterface::class); $this->shippingAddress = $this->createMock(AddressInterface::class); $this->billingAddress = $this->createMock(AddressInterface::class); - $this->extensionAttributes = $this->createMock(AddressExtensionInterface::class); + $this->extensionAttributes = $this->createPartialMockWithReflection( + AddressExtensionInterface::class, + ['getPickupLocationCode'] + ); $this->plugin = new ShippingInformationManagementPlugin(); } diff --git a/InventoryInStorePickupQuoteGraphQl/Test/Unit/Plugin/Checkout/AddressExtensionStubInterface.php b/InventoryInStorePickupQuoteGraphQl/Test/Unit/Plugin/Checkout/AddressExtensionStubInterface.php deleted file mode 100644 index 9859fb10a725..000000000000 --- a/InventoryInStorePickupQuoteGraphQl/Test/Unit/Plugin/Checkout/AddressExtensionStubInterface.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php -/** - * Copyright 2026 Adobe - * All Rights Reserved. - */ -declare(strict_types=1); - -namespace Magento\InventoryInStorePickupQuoteGraphQl\Test\Unit\Plugin\Checkout; - -use Magento\Quote\Api\Data\AddressExtensionInterface; - -/** - * Test stub that declares the pickup location extension attribute methods. - * - * The source AddressExtensionInterface is an empty marker; getPickupLocationCode()/ - * setPickupLocationCode() only exist on the generated interface. Mocking this stub keeps - * the unit test independent of generated code and PHPUnit version. - */ -interface AddressExtensionStubInterface extends AddressExtensionInterface -{ - /** - * Get pickup location code. - * - * @return string|null - */ - public function getPickupLocationCode(); - - /** - * Set pickup location code. - * - * @param string|null $pickupLocationCode - * @return $this - */ - public function setPickupLocationCode($pickupLocationCode); -} diff --git a/InventoryInStorePickupQuoteGraphQl/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php b/InventoryInStorePickupQuoteGraphQl/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php index d09f5a788830..5c219f14ee3f 100644 --- a/InventoryInStorePickupQuoteGraphQl/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php +++ b/InventoryInStorePickupQuoteGraphQl/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php @@ -9,6 +9,7 @@ use Magento\Checkout\Api\Data\ShippingInformationInterface; use Magento\Checkout\Model\ShippingInformationManagement; +use Magento\Framework\TestFramework\Unit\Helper\MockCreationTrait; use Magento\InventoryInStorePickupQuoteGraphQl\Plugin\Checkout\ClearPickupLocationOnNonPickupShippingMethodPlugin; use Magento\InventoryInStorePickupShippingApi\Model\Carrier\InStorePickup; use Magento\Quote\Api\CartRepositoryInterface; @@ -24,6 +25,8 @@ */ class ClearPickupLocationOnNonPickupShippingMethodPluginTest extends TestCase { + use MockCreationTrait; + /** * Test subject * @@ -324,7 +327,10 @@ private function createAddressMock(?MockObject $extension): MockObject */ private function createExtensionMock(?string $pickupLocationCode): MockObject { - $extension = $this->createMock(AddressExtensionStubInterface::class); + $extension = $this->createPartialMockWithReflection( + AddressExtensionInterface::class, + ['getPickupLocationCode', 'setPickupLocationCode'] + ); $extension->method('getPickupLocationCode')->willReturn($pickupLocationCode); return $extension; From 7d4352c533f782e85e7bbe3acf28b94b4170dcff Mon Sep 17 00:00:00 2001 From: Sokly Meach <meach@adobe.com> Date: Tue, 7 Jul 2026 16:47:54 -0500 Subject: [PATCH 81/83] ACP2E-4973: [Feature Request] Clear redundant in store pickup data when changing shipping carrier --- ...hippingInformationManagementPluginTest.php | 20 +++++++------- ...ionOnNonPickupShippingMethodPluginTest.php | 26 +++++++++---------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ShippingInformationManagementPluginTest.php b/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ShippingInformationManagementPluginTest.php index 114f763652a2..6c356108ff9c 100644 --- a/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ShippingInformationManagementPluginTest.php +++ b/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ShippingInformationManagementPluginTest.php @@ -31,29 +31,29 @@ class ShippingInformationManagementPluginTest extends TestCase private $plugin; /** - * @var ShippingInformationManagement&MockObject + * @var ShippingInformationManagement|MockObject */ - private MockObject $subject; + private $subject; /** - * @var ShippingInformationInterface&MockObject + * @var ShippingInformationInterface|MockObject */ - private MockObject $addressInformation; + private $addressInformation; /** - * @var AddressInterface&MockObject + * @var AddressInterface|MockObject */ - private MockObject $shippingAddress; + private $shippingAddress; /** - * @var AddressInterface&MockObject + * @var AddressInterface|MockObject */ - private MockObject $billingAddress; + private $billingAddress; /** - * @var AddressExtensionInterface&MockObject + * @var AddressExtensionInterface|MockObject */ - private MockObject $extensionAttributes; + private $extensionAttributes; /** * @inheritDoc diff --git a/InventoryInStorePickupQuoteGraphQl/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php b/InventoryInStorePickupQuoteGraphQl/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php index 5c219f14ee3f..1189f7e9d9a3 100644 --- a/InventoryInStorePickupQuoteGraphQl/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php +++ b/InventoryInStorePickupQuoteGraphQl/Test/Unit/Plugin/Checkout/ClearPickupLocationOnNonPickupShippingMethodPluginTest.php @@ -34,17 +34,17 @@ class ClearPickupLocationOnNonPickupShippingMethodPluginTest extends TestCase */ private ClearPickupLocationOnNonPickupShippingMethodPlugin $plugin; - /** @var ShippingInformationManagement&MockObject */ - private MockObject $subject; + /** @var ShippingInformationManagement|MockObject */ + private $subject; - /** @var ShippingInformationInterface&MockObject */ - private MockObject $addressInformation; + /** @var ShippingInformationInterface|MockObject */ + private $addressInformation; - /** @var CartRepositoryInterface&MockObject */ - private MockObject $cartRepository; + /** @var CartRepositoryInterface|MockObject */ + private $cartRepository; - /** @var AddressExtensionFactory&MockObject */ - private MockObject $addressExtensionFactory; + /** @var AddressExtensionFactory|MockObject */ + private $addressExtensionFactory; /** * @inheritDoc @@ -272,7 +272,7 @@ public function testResetsAddressWhenQuoteShippingMethodIsStillInStorePickup(): } /** - * @param Address&MockObject $address + * @param Address|MockObject $address * @return void */ private function expectAddressReset(MockObject $address): void @@ -287,7 +287,7 @@ private function expectAddressReset(MockObject $address): void /** * @param int $cartId - * @param Address&MockObject $shippingAddress + * @param Address|MockObject $shippingAddress * @return void */ private function configureQuoteWithShippingAddress(int $cartId, MockObject $shippingAddress): void @@ -308,8 +308,8 @@ private function configureFlatrateMethod(): void } /** - * @param AddressExtensionInterface&MockObject|null $extension - * @return Address&MockObject + * @param AddressExtensionInterface|MockObject|null $extension + * @return Address|MockObject */ private function createAddressMock(?MockObject $extension): MockObject { @@ -323,7 +323,7 @@ private function createAddressMock(?MockObject $extension): MockObject /** * @param string|null $pickupLocationCode - * @return AddressExtensionInterface&MockObject + * @return AddressExtensionInterface|MockObject */ private function createExtensionMock(?string $pickupLocationCode): MockObject { From 852240e1a5c29a928e1837cab19e997887509d2e Mon Sep 17 00:00:00 2001 From: Sokly Meach <meach@adobe.com> Date: Tue, 7 Jul 2026 17:00:34 -0500 Subject: [PATCH 82/83] ACP2E-4973: [Feature Request] Clear redundant in store pickup data when changing shipping carrier --- .../ShippingInformationManagementPluginTest.php | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ShippingInformationManagementPluginTest.php b/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ShippingInformationManagementPluginTest.php index 6c356108ff9c..a2aee9fb548c 100644 --- a/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ShippingInformationManagementPluginTest.php +++ b/InventoryInStorePickupQuote/Test/Unit/Plugin/Checkout/ShippingInformationManagementPluginTest.php @@ -11,8 +11,8 @@ use Magento\Checkout\Model\ShippingInformationManagement; use Magento\Framework\TestFramework\Unit\Helper\MockCreationTrait; use Magento\InventoryInStorePickupQuote\Plugin\Checkout\ShippingInformationManagementPlugin; -use Magento\Quote\Api\Data\AddressExtensionInterface; use Magento\Quote\Api\Data\AddressInterface; +use Magento\Quote\Api\Data\AddressExtensionInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -51,7 +51,7 @@ class ShippingInformationManagementPluginTest extends TestCase private $billingAddress; /** - * @var AddressExtensionInterface|MockObject + * @var AddressInterface|MockObject */ private $extensionAttributes; @@ -145,12 +145,8 @@ public function testBeforeSaveAddressInformationNotPickupStore(): void $this->extensionAttributes->expects($this->once()) ->method('getPickupLocationCode') ->willReturn(null); - $this->shippingAddress->expects($this->once()) - ->method('getStreet') - ->willReturn(['123 Main St']); - $this->shippingAddress->expects($this->once()) - ->method('getCity') - ->willReturn('Austin'); + $this->shippingAddress->expects($this->once())->method('getStreet')->willReturn(['123 Main St']); + $this->shippingAddress->expects($this->once())->method('getCity')->willReturn('Austin'); $this->addressInformation->expects($this->once()) ->method('getShippingAddress') ->willReturn($this->shippingAddress); @@ -182,9 +178,7 @@ public function testBeforeSaveAddressInformationDoesNotCopyIncompleteShippingAdd $this->extensionAttributes->expects($this->once()) ->method('getPickupLocationCode') ->willReturn(null); - $this->shippingAddress->expects($this->once()) - ->method('getStreet') - ->willReturn([]); + $this->shippingAddress->expects($this->once())->method('getStreet')->willReturn([]); $this->shippingAddress->expects($this->never())->method('getCity'); $this->addressInformation->expects($this->once()) ->method('getShippingAddress') From 50cffaa4c3ea6e82d65701c02aa9c96deb27860e Mon Sep 17 00:00:00 2001 From: Jeanmarcos Juarez <janmarcoj@gmail.com> Date: Mon, 3 Aug 2026 16:24:54 -0400 Subject: [PATCH 83/83] ci(dist): exclude the .github tooling inherited from upstream from the QA file scan --- .github/scripts/dist-qa-local.sh | 11 +++++++---- .github/workflows/dist-qa.yml | 4 +++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/scripts/dist-qa-local.sh b/.github/scripts/dist-qa-local.sh index e5999f99588a..2056a66fda7e 100755 --- a/.github/scripts/dist-qa-local.sh +++ b/.github/scripts/dist-qa-local.sh @@ -28,12 +28,15 @@ fi echo "Base ref: $BASE" +# .github/ is excluded: it carries CI tooling inherited from upstream (CLI scripts that +# legitimately use echo/exit), which the Magento2 standard rejects and which is not part +# of the distributed code. CHANGED=$( { - git diff --name-only --diff-filter=ACMR "$BASE"...HEAD -- '*.php' - git diff --name-only --diff-filter=ACMR -- '*.php' - git diff --name-only --diff-filter=ACMR --cached -- '*.php' - git ls-files --others --exclude-standard -- '*.php' + git diff --name-only --diff-filter=ACMR "$BASE"...HEAD -- '*.php' ':(exclude).github/' + git diff --name-only --diff-filter=ACMR -- '*.php' ':(exclude).github/' + git diff --name-only --diff-filter=ACMR --cached -- '*.php' ':(exclude).github/' + git ls-files --others --exclude-standard -- '*.php' ':(exclude).github/' } 2>/dev/null | sort -u | grep -v '^$' || true ) diff --git a/.github/workflows/dist-qa.yml b/.github/workflows/dist-qa.yml index eba29c18e6dd..d39c02296761 100644 --- a/.github/workflows/dist-qa.yml +++ b/.github/workflows/dist-qa.yml @@ -40,7 +40,9 @@ jobs: id: changed run: | git fetch --no-tags --depth=1 origin "${{ github.base_ref }}" - git diff --name-only --diff-filter=ACMR "origin/${{ github.base_ref }}...HEAD" -- '*.php' > changed.txt || true + # .github/ is excluded: it carries CI tooling inherited from upstream (CLI scripts + # that legitimately use echo/exit) and is not part of the distributed code. + git diff --name-only --diff-filter=ACMR "origin/${{ github.base_ref }}...HEAD" -- '*.php' ':(exclude).github/' > changed.txt || true echo "Changed PHP files:" cat changed.txt || true echo "count=$(grep -c . changed.txt || echo 0)" >> "$GITHUB_OUTPUT"