230 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			PHP
		
	
	
		
			Executable File
		
	
	
			
		
		
	
	
			230 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			PHP
		
	
	
		
			Executable File
		
	
	
<?php
 | 
						|
/**
 | 
						|
 * Copyright © Magento, Inc. All rights reserved.
 | 
						|
 * See COPYING.txt for license details.
 | 
						|
 */
 | 
						|
namespace Magento\SalesRule\Plugin;
 | 
						|
 | 
						|
use Magento\Framework\DataObject;
 | 
						|
use Magento\Framework\ObjectManagerInterface;
 | 
						|
use Magento\Quote\Model\Quote;
 | 
						|
use Magento\Quote\Model\QuoteManagement;
 | 
						|
use Magento\Quote\Model\SubmitQuoteValidator;
 | 
						|
use Magento\Sales\Api\OrderManagementInterface;
 | 
						|
use Magento\Sales\Model\Service\OrderService;
 | 
						|
use Magento\SalesRule\Model\Coupon;
 | 
						|
use Magento\SalesRule\Model\ResourceModel\Coupon\Usage;
 | 
						|
use Magento\TestFramework\Helper\Bootstrap;
 | 
						|
use Magento\TestFramework\MessageQueue\EnvironmentPreconditionException;
 | 
						|
use Magento\TestFramework\MessageQueue\PreconditionFailedException;
 | 
						|
use Magento\TestFramework\MessageQueue\PublisherConsumerController;
 | 
						|
use PHPUnit\Framework\MockObject\MockObject;
 | 
						|
use PHPUnit\Framework\TestCase;
 | 
						|
 | 
						|
/**
 | 
						|
 * Test increasing coupon usages after order placing and decreasing after order cancellation.
 | 
						|
 *
 | 
						|
 * @magentoAppArea frontend
 | 
						|
 * @magentoDbIsolation enabled
 | 
						|
 * @magentoAppIsolation enabled
 | 
						|
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 | 
						|
 */
 | 
						|
class CouponUsagesTest extends TestCase
 | 
						|
{
 | 
						|
    /**
 | 
						|
     * @var PublisherConsumerController
 | 
						|
     */
 | 
						|
    private $publisherConsumerController;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var array
 | 
						|
     */
 | 
						|
    private $consumers = ['sales.rule.update.coupon.usage'];
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var ObjectManagerInterface
 | 
						|
     */
 | 
						|
    private $objectManager;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var Usage
 | 
						|
     */
 | 
						|
    private $usage;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var DataObject
 | 
						|
     */
 | 
						|
    private $couponUsage;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var QuoteManagement
 | 
						|
     */
 | 
						|
    private $quoteManagement;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var OrderService
 | 
						|
     */
 | 
						|
    private $orderService;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @inheritdoc
 | 
						|
     */
 | 
						|
    protected function setUp(): void
 | 
						|
    {
 | 
						|
        $this->objectManager = Bootstrap::getObjectManager();
 | 
						|
        $this->usage = $this->objectManager->get(Usage::class);
 | 
						|
        $this->couponUsage = $this->objectManager->create(DataObject::class);
 | 
						|
        $this->quoteManagement = $this->objectManager->get(QuoteManagement::class);
 | 
						|
        $this->orderService = $this->objectManager->get(OrderService::class);
 | 
						|
 | 
						|
        $this->publisherConsumerController = Bootstrap::getObjectManager()->create(
 | 
						|
            PublisherConsumerController::class,
 | 
						|
            [
 | 
						|
                'consumers' => $this->consumers,
 | 
						|
                'logFilePath' => TESTS_TEMP_DIR . "/MessageQueueTestLog.txt",
 | 
						|
                'maxMessages' => 100,
 | 
						|
                'appInitParams' => Bootstrap::getInstance()->getAppInitParams()
 | 
						|
            ]
 | 
						|
        );
 | 
						|
        try {
 | 
						|
            $this->publisherConsumerController->startConsumers();
 | 
						|
        } catch (EnvironmentPreconditionException $e) {
 | 
						|
            $this->markTestSkipped($e->getMessage());
 | 
						|
        } catch (PreconditionFailedException $e) {
 | 
						|
            $this->fail(
 | 
						|
                $e->getMessage()
 | 
						|
            );
 | 
						|
        }
 | 
						|
        parent::setUp();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @inheritdoc
 | 
						|
     */
 | 
						|
    protected function tearDown(): void
 | 
						|
    {
 | 
						|
        $this->publisherConsumerController->stopConsumers();
 | 
						|
        parent::tearDown();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Test increasing coupon usages after after order placing and decreasing after order cancellation.
 | 
						|
     *
 | 
						|
     * @magentoDataFixture Magento/SalesRule/_files/coupons_limited_order.php
 | 
						|
     * @magentoDbIsolation disabled
 | 
						|
     */
 | 
						|
    public function testSubmitQuoteAndCancelOrder()
 | 
						|
    {
 | 
						|
        $customerId = 1;
 | 
						|
        $couponCode = 'one_usage';
 | 
						|
        $reservedOrderId = 'test01';
 | 
						|
 | 
						|
        /** @var Coupon $coupon */
 | 
						|
        $coupon = $this->objectManager->create(Coupon::class);
 | 
						|
        $coupon->loadByCode($couponCode);
 | 
						|
        /** @var Quote $quote */
 | 
						|
        $quote = $this->objectManager->create(Quote::class);
 | 
						|
        $quote->load($reservedOrderId, 'reserved_order_id');
 | 
						|
 | 
						|
        // Make sure coupon usages value is incremented then order is placed.
 | 
						|
        $order = $this->quoteManagement->submit($quote);
 | 
						|
        sleep(10); // timeout to processing Magento queue
 | 
						|
        $this->usage->loadByCustomerCoupon($this->couponUsage, $customerId, $coupon->getId());
 | 
						|
        $coupon->loadByCode($couponCode);
 | 
						|
 | 
						|
        self::assertEquals(
 | 
						|
            1,
 | 
						|
            $coupon->getTimesUsed()
 | 
						|
        );
 | 
						|
        self::assertEquals(
 | 
						|
            1,
 | 
						|
            $this->couponUsage->getTimesUsed()
 | 
						|
        );
 | 
						|
 | 
						|
        // Make sure order coupon usages value is decremented then order is cancelled.
 | 
						|
        $this->orderService->cancel($order->getId());
 | 
						|
        $this->usage->loadByCustomerCoupon($this->couponUsage, $customerId, $coupon->getId());
 | 
						|
        $coupon->loadByCode($couponCode);
 | 
						|
 | 
						|
        self::assertEquals(
 | 
						|
            0,
 | 
						|
            $coupon->getTimesUsed()
 | 
						|
        );
 | 
						|
        self::assertEquals(
 | 
						|
            0,
 | 
						|
            $this->couponUsage->getTimesUsed()
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Test to decrement coupon usages after exception on order placing
 | 
						|
     *
 | 
						|
     * @param array $mockObjects
 | 
						|
     * @magentoDataFixture Magento/SalesRule/_files/coupons_limited_order.php
 | 
						|
     * @magentoDbIsolation disabled
 | 
						|
     * @dataProvider quoteSubmitFailureDataProvider
 | 
						|
     */
 | 
						|
    public function testQuoteSubmitFailure(array $mockObjects)
 | 
						|
    {
 | 
						|
        $customerId = 1;
 | 
						|
        $couponCode = 'one_usage';
 | 
						|
        $reservedOrderId = 'test01';
 | 
						|
 | 
						|
        /** @var Coupon $coupon */
 | 
						|
        $coupon = $this->objectManager->get(Coupon::class);
 | 
						|
        $coupon->loadByCode($couponCode);
 | 
						|
        /** @var Quote $quote */
 | 
						|
        $quote = $this->objectManager->get(Quote::class);
 | 
						|
        $quote->load($reservedOrderId, 'reserved_order_id');
 | 
						|
 | 
						|
        /** @var QuoteManagement $quoteManagement */
 | 
						|
        $quoteManagement = $this->objectManager->create(
 | 
						|
            QuoteManagement::class,
 | 
						|
            $mockObjects
 | 
						|
        );
 | 
						|
 | 
						|
        try {
 | 
						|
            $quoteManagement->submit($quote);
 | 
						|
        } catch (\Exception $exception) {
 | 
						|
            sleep(10); // timeout to processing queue
 | 
						|
            $this->usage->loadByCustomerCoupon($this->couponUsage, $customerId, $coupon->getId());
 | 
						|
            $coupon->loadByCode($couponCode);
 | 
						|
            self::assertEquals(
 | 
						|
                0,
 | 
						|
                $coupon->getTimesUsed()
 | 
						|
            );
 | 
						|
            self::assertEquals(
 | 
						|
                0,
 | 
						|
                $this->couponUsage->getTimesUsed()
 | 
						|
            );
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return array
 | 
						|
     */
 | 
						|
    public function quoteSubmitFailureDataProvider(): array
 | 
						|
    {
 | 
						|
        /** @var OrderManagementInterface|MockObject $orderManagement */
 | 
						|
        $orderManagement = $this->createMock(OrderManagementInterface::class);
 | 
						|
        $orderManagement->expects($this->once())
 | 
						|
            ->method('place')
 | 
						|
            ->willThrowException(new \Exception());
 | 
						|
 | 
						|
        /** @var OrderManagementInterface|MockObject $orderManagement */
 | 
						|
        $submitQuoteValidator = $this->createMock(SubmitQuoteValidator::class);
 | 
						|
        $submitQuoteValidator->expects($this->once())
 | 
						|
            ->method('validateQuote')
 | 
						|
            ->willThrowException(new \Exception());
 | 
						|
 | 
						|
        return [
 | 
						|
            'order placing failure' => [
 | 
						|
                ['orderManagement' => $orderManagement]
 | 
						|
            ],
 | 
						|
            'quote validation failure' => [
 | 
						|
                ['submitQuoteValidator' => $submitQuoteValidator]
 | 
						|
            ],
 | 
						|
        ];
 | 
						|
    }
 | 
						|
}
 |