diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/VerifyCategoryProductAndProductCategoryPartialReindexTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/VerifyCategoryProductAndProductCategoryPartialReindexTest.xml index e7ba97ad36785..ce04b377300f8 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/VerifyCategoryProductAndProductCategoryPartialReindexTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/VerifyCategoryProductAndProductCategoryPartialReindexTest.xml @@ -58,9 +58,9 @@ - + - + @@ -108,6 +108,8 @@ + + @@ -147,8 +149,9 @@ - + + @@ -213,8 +216,9 @@ - + + diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminCustomerFindWishlistItemActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminCustomerFindWishlistItemActionGroup.xml index bbdc4de330840..cd581ed1836dd 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminCustomerFindWishlistItemActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminCustomerFindWishlistItemActionGroup.xml @@ -14,6 +14,6 @@ - + diff --git a/app/code/Magento/Downloadable/Observer/SetLinkStatusObserver.php b/app/code/Magento/Downloadable/Observer/SetLinkStatusObserver.php index 971feafb857a9..2a07a3a49639f 100644 --- a/app/code/Magento/Downloadable/Observer/SetLinkStatusObserver.php +++ b/app/code/Magento/Downloadable/Observer/SetLinkStatusObserver.php @@ -61,6 +61,7 @@ public function execute(\Magento\Framework\Event\Observer $observer) 'payment_pending' => \Magento\Downloadable\Model\Link\Purchased\Item::LINK_STATUS_PENDING_PAYMENT, 'payment_review' => \Magento\Downloadable\Model\Link\Purchased\Item::LINK_STATUS_PAYMENT_REVIEW, ]; + $expiredOrderItemIds = []; $downloadableItemsStatuses = []; $orderItemStatusToEnable = $this->_scopeConfig->getValue( @@ -114,6 +115,10 @@ public function execute(\Magento\Framework\Event\Observer $observer) if (in_array($item->getStatusId(), $availableStatuses)) { $downloadableItemsStatuses[$item->getId()] = $linkStatuses['avail']; } + + if ($item->getQtyOrdered() - $item->getQtyRefunded() == 0) { + $expiredOrderItemIds[] = $item->getId(); + } } } } @@ -141,10 +146,22 @@ public function execute(\Magento\Framework\Event\Observer $observer) } } + if ($expiredOrderItemIds) { + $linkPurchased = $this->_createItemsCollection()->addFieldToFilter( + 'order_item_id', + ['in' => $expiredOrderItemIds] + ); + foreach ($linkPurchased as $link) { + $link->setStatus(\Magento\Downloadable\Model\Link\Purchased\Item::LINK_STATUS_EXPIRED)->save(); + } + } + return $this; } /** + * Returns purchased item collection + * * @return \Magento\Downloadable\Model\ResourceModel\Link\Purchased\Item\Collection */ protected function _createItemsCollection() diff --git a/app/code/Magento/Downloadable/Test/Mftf/ActionGroup/StorefrontNotAssertDownloadableProductLinkInCustomerAccountActionGroup.xml b/app/code/Magento/Downloadable/Test/Mftf/ActionGroup/StorefrontNotAssertDownloadableProductLinkInCustomerAccountActionGroup.xml new file mode 100644 index 0000000000000..ae288c7033e17 --- /dev/null +++ b/app/code/Magento/Downloadable/Test/Mftf/ActionGroup/StorefrontNotAssertDownloadableProductLinkInCustomerAccountActionGroup.xml @@ -0,0 +1,26 @@ + + + + + + + Goes to the Storefront Customer Dashboard page. Clicks on 'My Downloadable Products'. Validates that the provided Downloadable Product is present and Downloadable link not exist. + + + + + + + + + + + + + diff --git a/app/code/Magento/Downloadable/Test/Mftf/Section/StorefrontCustomerDownloadableProductsSection.xml b/app/code/Magento/Downloadable/Test/Mftf/Section/StorefrontCustomerDownloadableProductsSection.xml index d45a774077ba0..5d340e6c91060 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Section/StorefrontCustomerDownloadableProductsSection.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Section/StorefrontCustomerDownloadableProductsSection.xml @@ -10,5 +10,6 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
+
diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/StorefrontAccountDownloadableProductLinkAfterPartialRefundTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/StorefrontAccountDownloadableProductLinkAfterPartialRefundTest.xml new file mode 100644 index 0000000000000..d82cc25b0eccf --- /dev/null +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/StorefrontAccountDownloadableProductLinkAfterPartialRefundTest.xml @@ -0,0 +1,109 @@ + + + + + + + + + <description value="Verify that Downloadable product is not available in My Download Products tab after it has been partially refunded."/> + <severity value="CRITICAL"/> + <testCaseId value="MC-35198"/> + <group value="Downloadable"/> + </annotations> + + <before> + <magentoCLI stepKey="addDownloadableDomain" command="downloadable:domains:add example.com static.magento.com"/> + <magentoCLI command="config:set {{EnableFlatRateConfigData.path}} {{EnableFlatRateConfigData.value}}" stepKey="enableFlatRate"/> + + <createData entity="ApiCategory" stepKey="createCategory"/> + <createData entity="ApiSimpleProduct" stepKey="createSimpleProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="ApiDownloadableProduct" stepKey="createDownloadableProduct"/> + <createData entity="downloadableLink1" stepKey="addDownloadableLink1"> + <requiredEntity createDataKey="createDownloadableProduct"/> + </createData> + + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + + <createData entity="Simple_US_Customer_Multiple_Addresses" stepKey="createCustomer"/> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signIn"> + <argument name="Customer" value="$$createCustomer$$"/> + </actionGroup> + </before> + + <after> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> + <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogout"/> + + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> + <deleteData createDataKey="createDownloadableProduct" stepKey="deleteDownloadableProduct"/> + + <magentoCLI stepKey="removeDownloadableDomain" command="downloadable:domains:remove example.com static.magento.com"/> + <magentoCLI command="config:set {{EnableFlatRateConfigData.path}} {{EnableFlatRateConfigData.value}}" stepKey="enableFlatRate"/> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </after> + + <actionGroup ref="StorefrontAddSimpleProductToShoppingCartActionGroup" stepKey="addSimpleProductToCart"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> + + <amOnPage url="{{StorefrontProductPage.url($$createDownloadableProduct.custom_attributes[url_key]$$)}}" stepKey="OpenStoreFrontProductPage"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + + <actionGroup ref="StorefrontAddToCartCustomOptionsProductPageActionGroup" stepKey="addToTheCart"> + <argument name="productName" value="$$createDownloadableProduct.name$$"/> + </actionGroup> + + <actionGroup ref="ClickViewAndEditCartFromMiniCartActionGroup" stepKey="goToShoppingCartFromMinicart"/> + <click selector="{{CheckoutCartSummarySection.proceedToCheckout}}" stepKey="clickProceedToCheckout"/> + <waitForPageLoad stepKey="waitForProceedToCheckout"/> + <waitForElementVisible selector="{{CheckoutShippingSection.shipHereButton(UK_Not_Default_Address.street[0])}}" stepKey="waitForShipHereVisible"/> + <click selector="{{CheckoutShippingSection.shipHereButton(UK_Not_Default_Address.street[0])}}" stepKey="clickShipHere"/> + <click selector="{{CheckoutShippingGuestInfoSection.next}}" stepKey="clickNext"/> + <waitForPageLoad stepKey="waitForShipmentPageLoad"/> + <checkOption selector="{{CheckoutPaymentSection.billingAddressNotSameCheckbox}}" stepKey="selectPaymentSolution"/> + <waitForElement selector="{{CheckoutPaymentSection.paymentSectionTitle}}" stepKey="waitForPaymentSectionLoaded"/> + <click selector="{{CheckoutPaymentSection.placeOrder}}" stepKey="clickPlaceOrderButton"/> + <seeElement selector="{{CheckoutSuccessMainSection.success}}" stepKey="orderIsSuccessfullyPlaced"/> + <grabTextFrom selector="{{CheckoutSuccessMainSection.orderNumber22}}" stepKey="grabOrderNumber"/> + + <actionGroup ref="AdminLoginActionGroup" stepKey="LoginAsAdmin"/> + + <amOnPage url="{{AdminOrdersPage.url}}" stepKey="onOrdersPage"/> + <actionGroup ref="SearchAdminDataGridByKeywordActionGroup" stepKey="searchOrder"> + <argument name="keyword" value="$grabOrderNumber"/> + </actionGroup> + <actionGroup ref="AdminOrderGridClickFirstRowActionGroup" stepKey="clickOrderRow"/> + + <actionGroup ref="AdminCreateInvoiceActionGroup" stepKey="createCreditMemo"/> + + <actionGroup ref="OpenOrderByIdActionGroup" stepKey="openOrder"> + <argument name="orderId" value="{$grabOrderNumber}"/> + </actionGroup> + + <actionGroup ref="AdminOpenAndFillCreditMemoRefundActionGroup" stepKey="fillCreditMemoRefund"> + <argument name="itemQtyToRefund" value="0"/> + <argument name="rowNumber" value="1"/> + </actionGroup> + + <click selector="{{AdminCreditMemoTotalSection.submitRefundOffline}}" stepKey="clickRefundOffline"/> + <waitForPageLoad stepKey="waitForResultPage"/> + + <actionGroup ref="StorefrontNotAssertDownloadableProductLinkInCustomerAccountActionGroup" stepKey="dontSeeStorefrontMyAccountDownloadableProductsLink"> + <argument name="product" value="$$createDownloadableProduct$$"/> + </actionGroup> + + </test> +</tests> diff --git a/app/code/Magento/Downloadable/Test/Unit/Observer/SetLinkStatusObserverTest.php b/app/code/Magento/Downloadable/Test/Unit/Observer/SetLinkStatusObserverTest.php index 46a3ef6717582..b5be0309bb5be 100644 --- a/app/code/Magento/Downloadable/Test/Unit/Observer/SetLinkStatusObserverTest.php +++ b/app/code/Magento/Downloadable/Test/Unit/Observer/SetLinkStatusObserverTest.php @@ -189,7 +189,7 @@ public function testSetLinkStatusPending($orderState, array $orderStateMapping) ] ); - $this->itemsFactory->expects($this->once()) + $this->itemsFactory->expects($this->any()) ->method('create') ->willReturn( $this->createLinkItemCollection( @@ -243,7 +243,7 @@ public function testSetLinkStatusClosed() ] ); - $this->itemsFactory->expects($this->once()) + $this->itemsFactory->expects($this->any()) ->method('create') ->willReturn( $this->createLinkItemCollection( @@ -308,7 +308,7 @@ public function testSetLinkStatusInvoiced() ] ); - $this->itemsFactory->expects($this->once()) + $this->itemsFactory->expects($this->any()) ->method('create') ->willReturn( $this->createLinkItemCollection( @@ -344,6 +344,137 @@ public function testSetLinkStatusEmptyOrder() $this->assertInstanceOf(SetLinkStatusObserver::class, $result); } + public function testSetLinkStatusExpired() + { + $this->scopeConfig->expects($this->once()) + ->method('getValue') + ->with( + \Magento\Downloadable\Model\Link\Purchased\Item::XML_PATH_ORDER_ITEM_STATUS, + ScopeInterface::SCOPE_STORE, + 1 + ) + ->willReturn(Item::STATUS_PENDING); + + $this->observerMock->expects($this->once()) + ->method('getEvent') + ->willReturn($this->eventMock); + + $this->eventMock->expects($this->once()) + ->method('getOrder') + ->willReturn($this->orderMock); + + $this->orderMock->expects($this->once()) + ->method('getId') + ->willReturn(1); + + $this->orderMock->expects($this->once()) + ->method('getStoreId') + ->willReturn(1); + + $this->orderMock->expects($this->atLeastOnce()) + ->method('getState') + ->willReturn(Order::STATE_PROCESSING); + + $this->orderMock->expects($this->any()) + ->method('getAllItems') + ->willReturn( + [ + $this->createRefundOrderItem(2, 2, 2), + $this->createRefundOrderItem(3, 2, 1), + $this->createRefundOrderItem(4, 3, 3), + ] + ); + + $this->itemsFactory->expects($this->any()) + ->method('create') + ->willReturn( + $this->createLinkItemToExpireCollection( + [2, 4], + [ + $this->createLinkItem( + 'available', + 2, + true, + \Magento\Downloadable\Model\Link\Purchased\Item::LINK_STATUS_EXPIRED + ), + $this->createLinkItem( + 'pending_payment', + 4, + true, + \Magento\Downloadable\Model\Link\Purchased\Item::LINK_STATUS_EXPIRED + ), + ] + ) + ); + + $result = $this->setLinkStatusObserver->execute($this->observerMock); + $this->assertInstanceOf(SetLinkStatusObserver::class, $result); + } + + /** + * @param $id + * @param int $qtyOrdered + * @param int $qtyRefunded + * @param string $productType + * @param string $realProductType + * @return \Magento\Sales\Model\Order\Item|MockObject + */ + private function createRefundOrderItem( + $id, + $qtyOrdered, + $qtyRefunded, + $productType = DownloadableProductType::TYPE_DOWNLOADABLE, + $realProductType = DownloadableProductType::TYPE_DOWNLOADABLE + ) { + $item = $this->getMockBuilder(Item::class) + ->disableOriginalConstructor() + ->setMethods([ + 'getId', + 'getQtyOrdered', + 'getQtyRefunded', + 'getProductType', + 'getRealProductType' + ])->getMock(); + $item->expects($this->any()) + ->method('getId') + ->willReturn($id); + $item->expects($this->any()) + ->method('getQtyOrdered') + ->willReturn($qtyOrdered); + $item->expects($this->any()) + ->method('getQtyRefunded') + ->willReturn($qtyRefunded); + $item->expects($this->any()) + ->method('getProductType') + ->willReturn($productType); + $item->expects($this->any()) + ->method('getRealProductType') + ->willReturn($realProductType); + + return $item; + } + + /** + * @param array $expectedOrderItemIds + * @param array $items + * @return LinkItemCollection|MockObject + */ + private function createLinkItemToExpireCollection(array $expectedOrderItemIds, array $items) + { + $linkItemCollection = $this->getMockBuilder( + \Magento\Downloadable\Model\ResourceModel\Link\Purchased\Item\Collection::class + ) + ->disableOriginalConstructor() + ->setMethods(['addFieldToFilter']) + ->getMock(); + $linkItemCollection->expects($this->any()) + ->method('addFieldToFilter') + ->with('order_item_id', ['in' => $expectedOrderItemIds]) + ->willReturn($items); + + return $linkItemCollection; + } + /** * @param $id * @param int $statusId @@ -359,7 +490,7 @@ private function createOrderItem( ) { $item = $this->getMockBuilder(Item::class) ->disableOriginalConstructor() - ->setMethods(['getId', 'getProductType', 'getRealProductType', 'getStatusId']) + ->setMethods(['getId', 'getProductType', 'getRealProductType', 'getStatusId', 'getQtyOrdered']) ->getMock(); $item->expects($this->any()) ->method('getId') @@ -373,6 +504,9 @@ private function createOrderItem( $item->expects($this->any()) ->method('getStatusId') ->willReturn($statusId); + $item->expects($this->any()) + ->method('getQtyOrdered') + ->willReturn(1); return $item; } @@ -390,7 +524,7 @@ private function createLinkItemCollection(array $expectedOrderItemIds, array $it ->disableOriginalConstructor() ->setMethods(['addFieldToFilter']) ->getMock(); - $linkItemCollection->expects($this->once()) + $linkItemCollection->expects($this->any()) ->method('addFieldToFilter') ->with('order_item_id', ['in' => $expectedOrderItemIds]) ->willReturn($items); @@ -415,11 +549,11 @@ private function createLinkItem($status, $orderItemId, $isSaved = false, $expect ->method('getStatus') ->willReturn($status); if ($isSaved) { - $linkItem->expects($this->once()) + $linkItem->expects($this->any()) ->method('setStatus') ->with($expectedStatus) ->willReturnSelf(); - $linkItem->expects($this->once()) + $linkItem->expects($this->any()) ->method('save') ->willReturnSelf(); } diff --git a/app/code/Magento/Wishlist/Test/Mftf/Test/AdminDeleteCustomerWishListItemTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/AdminDeleteCustomerWishListItemTest.xml index 28a17d30aea2b..a2219d5145f17 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/Test/AdminDeleteCustomerWishListItemTest.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/Test/AdminDeleteCustomerWishListItemTest.xml @@ -23,7 +23,6 @@ <createData entity="SimpleProduct" stepKey="createProduct"> <requiredEntity createDataKey="createCategory"/> </createData> - <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> <createData entity="Simple_US_Customer" stepKey="createCustomer"/> </before> <after>