813 lines
32 KiB
PHP
Executable File
813 lines
32 KiB
PHP
Executable File
<?php
|
|
/**
|
|
* Copyright © Magento, Inc. All rights reserved.
|
|
* See COPYING.txt for license details.
|
|
*/
|
|
declare(strict_types=1);
|
|
|
|
namespace Magento\Quote\Model;
|
|
|
|
use Magento\Catalog\Api\ProductRepositoryInterface;
|
|
use Magento\Checkout\Model\Session as CheckoutSession;
|
|
use Magento\Customer\Api\CustomerRepositoryInterface;
|
|
use Magento\Customer\Api\Data\CustomerInterface;
|
|
use Magento\Customer\Api\Data\CustomerInterfaceFactory;
|
|
use Magento\Customer\Model\CustomerFactory;
|
|
use Magento\Customer\Model\GroupFactory;
|
|
use Magento\Customer\Model\GroupManagement;
|
|
use Magento\Customer\Model\ResourceModel\Customer as CustomerResourceModel;
|
|
use Magento\Framework\Api\DataObjectHelper;
|
|
use Magento\Framework\Api\ExtensibleDataObjectConverter;
|
|
use Magento\Framework\Exception\LocalizedException;
|
|
use Magento\Framework\ObjectManagerInterface;
|
|
use Magento\Quote\Api\Data\AddressInterface;
|
|
use Magento\Quote\Api\Data\AddressInterfaceFactory;
|
|
use Magento\Quote\Api\Data\CartInterface;
|
|
use Magento\Quote\Api\Data\CartItemInterface;
|
|
use Magento\Quote\Api\Data\CartItemInterfaceFactory;
|
|
use Magento\TestFramework\Helper\Bootstrap;
|
|
use Magento\TestFramework\Quote\Model\GetQuoteByReservedOrderId;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
/**
|
|
* Tests for quote model.
|
|
*
|
|
* @see \Magento\Quote\Model\Quote
|
|
*
|
|
* @magentoDbIsolation enabled
|
|
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
|
*/
|
|
class QuoteTest extends TestCase
|
|
{
|
|
/** @var ObjectManagerInterface */
|
|
private $objectManager;
|
|
|
|
/** @var ProductRepositoryInterface */
|
|
private $productRepository;
|
|
|
|
/** @var GetQuoteByReservedOrderId */
|
|
private $getQuoteByReservedOrderId;
|
|
|
|
/** @var QuoteFactory */
|
|
private $quoteFactory;
|
|
|
|
/** @var DataObjectHelper */
|
|
private $dataObjectHelper;
|
|
|
|
/** @var CustomerRepositoryInterface */
|
|
private $customerRepository;
|
|
|
|
/** @var CustomerInterfaceFactory */
|
|
private $customerDataFactory;
|
|
|
|
/** @var CustomerFactory */
|
|
private $customerFactory;
|
|
|
|
/** @var AddressInterfaceFactory */
|
|
private $addressFactory;
|
|
|
|
/** @var CartItemInterfaceFactory */
|
|
private $itemFactory;
|
|
|
|
/** @var CustomerResourceModel */
|
|
private $customerResourceModel;
|
|
|
|
/** @var int */
|
|
private $customerIdToDelete;
|
|
|
|
/** @var GroupFactory */
|
|
private $groupFactory;
|
|
|
|
/** @var ExtensibleDataObjectConverter */
|
|
private $extensibleDataObjectConverter;
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
$this->objectManager = Bootstrap::getObjectManager();
|
|
$this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class);
|
|
$this->productRepository->cleanCache();
|
|
$this->getQuoteByReservedOrderId = $this->objectManager->get(GetQuoteByReservedOrderId::class);
|
|
$this->quoteFactory = $this->objectManager->get(QuoteFactory::class);
|
|
$this->dataObjectHelper = $this->objectManager->get(DataObjectHelper::class);
|
|
$this->customerRepository = $this->objectManager->get(CustomerRepositoryInterface::class);
|
|
$this->customerDataFactory = $this->objectManager->get(CustomerInterfaceFactory::class);
|
|
$this->customerFactory = $this->objectManager->get(CustomerFactory::class);
|
|
$this->addressFactory = $this->objectManager->get(AddressInterfaceFactory::class);
|
|
$this->itemFactory = $this->objectManager->get(CartItemInterfaceFactory::class);
|
|
$this->customerResourceModel = $this->objectManager->get(CustomerResourceModel::class);
|
|
$this->groupFactory = $this->objectManager->get(GroupFactory::class);
|
|
$this->extensibleDataObjectConverter = $this->objectManager->get(ExtensibleDataObjectConverter::class);
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
protected function tearDown(): void
|
|
{
|
|
if ($this->customerIdToDelete) {
|
|
$this->customerRepository->deleteById($this->customerIdToDelete);
|
|
}
|
|
|
|
parent::tearDown();
|
|
}
|
|
|
|
/**
|
|
* @magentoDataFixture Magento/Sales/_files/quote.php
|
|
* @magentoDataFixture Magento/Catalog/_files/product_virtual.php
|
|
* @return void
|
|
*/
|
|
public function testCollectTotalsWithVirtual(): void
|
|
{
|
|
$quote = $this->getQuoteByReservedOrderId->execute('test01');
|
|
$product = $this->productRepository->get('virtual-product', false, null, true);
|
|
$quote->addProduct($product);
|
|
$quote->collectTotals();
|
|
$this->assertEquals(2, $quote->getItemsQty());
|
|
$this->assertEquals(1, $quote->getVirtualItemsQty());
|
|
$this->assertEquals(20, $quote->getGrandTotal());
|
|
$this->assertEquals(20, $quote->getBaseGrandTotal());
|
|
}
|
|
|
|
/**
|
|
* @magentoDataFixture Magento/Catalog/_files/product_virtual.php
|
|
*
|
|
* @return void
|
|
*/
|
|
public function testGetAddressWithVirtualProduct(): void
|
|
{
|
|
$quote = $this->objectManager->create(Quote::class);
|
|
$billingAddress = $this->addressFactory->create();
|
|
$billingAddress->setFirstname('Joe')
|
|
->setLastname('Doe')
|
|
->setCountryId('US')
|
|
->setRegion('TX')
|
|
->setCity('Austin')
|
|
->setStreet('1000 West Parmer Line')
|
|
->setPostcode('11501')
|
|
->setTelephone('123456789');
|
|
$quote->setBillingAddress($billingAddress);
|
|
$shippingAddress = $this->addressFactory->create();
|
|
$shippingAddress->setFirstname('Joe')
|
|
->setLastname('Doe')
|
|
->setCountryId('US')
|
|
->setRegion('NJ')
|
|
->setCity('Newark')
|
|
->setStreet('2775 Granville Lane')
|
|
->setPostcode('07102')
|
|
->setTelephone('9734685221');
|
|
$quote->setShippingAddress($shippingAddress);
|
|
$product = $this->productRepository->get('virtual-product', false, null, true);
|
|
$quote->addProduct($product);
|
|
$quote->save();
|
|
$expectedAddress = $quote->getBillingAddress();
|
|
$this->assertEquals($expectedAddress, $quote->getAllItems()[0]->getAddress());
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
public function testSetCustomerData(): void
|
|
{
|
|
$quote = $this->quoteFactory->create();
|
|
$expected = $this->getCustomerDataArray();
|
|
$customer = $this->customerDataFactory->create();
|
|
$this->dataObjectHelper->populateWithArray($customer, $expected, CustomerInterfaceFactory::class);
|
|
$this->assertEquals($expected, $this->extensibleDataObjectConverter->toFlatArray($customer));
|
|
$quote->setCustomer($customer);
|
|
$customer = $quote->getCustomer();
|
|
$this->assertEquals($expected, $this->extensibleDataObjectConverter->toFlatArray($customer));
|
|
$this->assertEquals($expected[CustomerInterface::EMAIL], $quote->getCustomerEmail());
|
|
$this->assertEquals($expected[CustomerInterface::FIRSTNAME], $quote->getCustomerFirstname());
|
|
$this->assertEquals($expected[CustomerInterface::LASTNAME], $quote->getCustomerLastname());
|
|
$this->assertEquals($expected[CustomerInterface::MIDDLENAME], $quote->getCustomerMiddlename());
|
|
}
|
|
|
|
/**
|
|
* @magentoAppArea adminhtml
|
|
*
|
|
* @return void
|
|
*/
|
|
public function testUpdateCustomerData(): void
|
|
{
|
|
$quote = $this->quoteFactory->create();
|
|
$expected = $this->getCustomerDataArray();
|
|
unset($expected[CustomerInterface::ID]);
|
|
$customerDataSet = $this->customerDataFactory->create();
|
|
$this->dataObjectHelper->populateWithArray($customerDataSet, $expected, CustomerInterface::class);
|
|
$this->assertEquals($expected, $this->extensibleDataObjectConverter->toFlatArray($customerDataSet));
|
|
$customer = $this->customerRepository->save($customerDataSet);
|
|
$this->customerIdToDelete = $customer->getId();
|
|
$quote->setCustomer($customerDataSet);
|
|
$expected = $this->getCustomerDataArray();
|
|
$expected[CustomerInterface::EMAIL] = 'test@example.com';
|
|
$customerDataUpdated = $this->customerDataFactory->create();
|
|
$this->dataObjectHelper->populateWithArray($customerDataUpdated, $expected, CustomerInterface::class);
|
|
$quote->updateCustomerData($customerDataUpdated);
|
|
$customer = $quote->getCustomer();
|
|
$actual = $this->extensibleDataObjectConverter->toFlatArray($customer);
|
|
foreach ($expected as $item) {
|
|
$this->assertContains($item, $actual);
|
|
}
|
|
$this->assertEquals('test@example.com', $quote->getCustomerEmail());
|
|
}
|
|
|
|
/**
|
|
* Customer data is set to quote (which contains valid group ID).
|
|
*
|
|
* @return void
|
|
*/
|
|
public function testGetCustomerGroupFromCustomer(): void
|
|
{
|
|
$customerGroupId = 3;
|
|
$customerData = $this->customerDataFactory->create()->setId(1)->setGroupId($customerGroupId);
|
|
$quote = $this->quoteFactory->create();
|
|
$quote->setCustomer($customerData);
|
|
$quote->unsetData('customer_group_id');
|
|
$this->assertEquals($customerGroupId, $quote->getCustomerGroupId(), "Customer group ID is invalid");
|
|
}
|
|
|
|
/**
|
|
* @magentoDataFixture Magento/Customer/_files/customer_group.php
|
|
* @return void
|
|
*/
|
|
public function testGetCustomerTaxClassId(): void
|
|
{
|
|
$fixtureGroupCode = 'custom_group';
|
|
$fixtureTaxClassId = 3;
|
|
$fixtureGroupId = $this->groupFactory->create()->load($fixtureGroupCode, 'customer_group_code')->getId();
|
|
$quote = $this->quoteFactory->create();
|
|
$quote->setCustomerGroupId($fixtureGroupId);
|
|
$this->assertEquals($fixtureTaxClassId, $quote->getCustomerTaxClassId(), 'Customer tax class ID is invalid.');
|
|
}
|
|
|
|
/**
|
|
* Billing and shipping address arguments are not passed, customer has default billing and shipping addresses.
|
|
*
|
|
* @magentoDataFixture Magento/Customer/_files/customer.php
|
|
* @magentoDataFixture Magento/Customer/_files/customer_address.php
|
|
* @magentoDataFixture Magento/Customer/_files/customer_two_addresses.php
|
|
* @return void
|
|
*/
|
|
public function testAssignCustomerWithAddressChangeAddressesNotSpecified(): void
|
|
{
|
|
$quote = $this->quoteFactory->create();
|
|
$customerData = $this->prepareQuoteForTestAssignCustomerWithAddressChange($quote);
|
|
$quote->assignCustomerWithAddressChange($customerData);
|
|
$fixtureCustomerId = 1;
|
|
$this->assertEquals($fixtureCustomerId, $quote->getCustomerId(), 'Customer ID in quote is invalid.');
|
|
$expectedBillingAddressData = [
|
|
AddressInterface::KEY_STREET => 'Green str, 67',
|
|
AddressInterface::KEY_TELEPHONE => 3468676,
|
|
AddressInterface::KEY_POSTCODE => 75477,
|
|
AddressInterface::KEY_COUNTRY_ID => 'US',
|
|
AddressInterface::KEY_CITY => 'CityM',
|
|
AddressInterface::KEY_LASTNAME => 'Smith',
|
|
AddressInterface::KEY_FIRSTNAME => 'John',
|
|
AddressInterface::KEY_CUSTOMER_ID => 1,
|
|
AddressInterface::CUSTOMER_ADDRESS_ID => 1,
|
|
AddressInterface::KEY_REGION_ID => 1,
|
|
];
|
|
$this->assertQuoteAddress($expectedBillingAddressData, $quote->getBillingAddress());
|
|
$expectedShippingAddressData = [
|
|
AddressInterface::CUSTOMER_ADDRESS_ID => 2,
|
|
AddressInterface::KEY_TELEPHONE => 3234676,
|
|
AddressInterface::KEY_POSTCODE => 47676,
|
|
AddressInterface::KEY_COUNTRY_ID => 'US',
|
|
AddressInterface::KEY_CITY => 'CityX',
|
|
AddressInterface::KEY_STREET => 'Black str, 48',
|
|
AddressInterface::KEY_LASTNAME => 'Smith',
|
|
AddressInterface::KEY_FIRSTNAME => 'John',
|
|
AddressInterface::KEY_CUSTOMER_ID => 1,
|
|
AddressInterface::KEY_REGION_ID => 1,
|
|
];
|
|
$this->assertQuoteAddress($expectedShippingAddressData, $quote->getShippingAddress());
|
|
}
|
|
|
|
/**
|
|
* Billing and shipping address arguments are passed, customer has default billing and shipping addresses.
|
|
*
|
|
* @magentoDataFixture Magento/Customer/_files/customer.php
|
|
* @magentoDataFixture Magento/Customer/_files/customer_address.php
|
|
* @magentoDataFixture Magento/Customer/_files/customer_two_addresses.php
|
|
* @return void
|
|
*/
|
|
public function testAssignCustomerWithAddressChange(): void
|
|
{
|
|
$quote = $this->quoteFactory->create();
|
|
$customerData = $this->prepareQuoteForTestAssignCustomerWithAddressChange($quote);
|
|
$expectedBillingAddressData = [
|
|
AddressInterface::KEY_STREET => 'Billing str, 67',
|
|
AddressInterface::KEY_TELEPHONE => 16546757,
|
|
AddressInterface::KEY_POSTCODE => 2425457,
|
|
AddressInterface::KEY_COUNTRY_ID => 'US',
|
|
AddressInterface::KEY_CITY => 'CityBilling',
|
|
AddressInterface::KEY_LASTNAME => 'LastBilling',
|
|
AddressInterface::KEY_FIRSTNAME => 'FirstBilling',
|
|
AddressInterface::KEY_REGION_ID => 1,
|
|
];
|
|
$quoteBillingAddress = $this->addressFactory->create();
|
|
$quoteBillingAddress->setData($expectedBillingAddressData);
|
|
$expectedShippingAddressData = [
|
|
AddressInterface::KEY_TELEPHONE => 787878787,
|
|
AddressInterface::KEY_POSTCODE => 117785,
|
|
AddressInterface::KEY_COUNTRY_ID => 'US',
|
|
AddressInterface::KEY_CITY => 'CityShipping',
|
|
AddressInterface::KEY_STREET => 'Shipping str, 48',
|
|
AddressInterface::KEY_LASTNAME => 'LastShipping',
|
|
AddressInterface::KEY_FIRSTNAME => 'FirstShipping',
|
|
AddressInterface::KEY_REGION_ID => 1,
|
|
];
|
|
$quoteShippingAddress = $this->addressFactory->create();
|
|
$quoteShippingAddress->setData($expectedShippingAddressData);
|
|
$quote->assignCustomerWithAddressChange($customerData, $quoteBillingAddress, $quoteShippingAddress);
|
|
$fixtureCustomerId = 1;
|
|
$this->assertEquals($fixtureCustomerId, $quote->getCustomerId(), 'Customer ID in quote is invalid.');
|
|
$this->assertQuoteAddress($expectedBillingAddressData, $quote->getBillingAddress());
|
|
$this->assertQuoteAddress($expectedShippingAddressData, $quote->getShippingAddress());
|
|
}
|
|
|
|
/**
|
|
* Customer has address with country which not allowed in website
|
|
*
|
|
* @magentoDataFixture Magento/Customer/_files/customer.php
|
|
* @magentoDataFixture Magento/Customer/_files/customer_address.php
|
|
* @magentoDataFixture Magento/Backend/_files/allowed_countries_fr.php
|
|
* @return void
|
|
*/
|
|
public function testAssignCustomerWithAddressChangeWithNotAllowedCountry(): void
|
|
{
|
|
$quote = $this->quoteFactory->create();
|
|
$customerData = $this->prepareQuoteForTestAssignCustomerWithAddressChange($quote);
|
|
$quote->assignCustomerWithAddressChange($customerData);
|
|
$this->assertNull($quote->getBillingAddress()->getCountryId());
|
|
$this->assertNull($quote->getShippingAddress()->getCountryId());
|
|
}
|
|
|
|
/**
|
|
* @magentoDataFixture Magento/Catalog/_files/product_simple_duplicated.php
|
|
* @return void
|
|
*/
|
|
public function testAddProductUpdateItem(): void
|
|
{
|
|
$quote = $this->quoteFactory->create();
|
|
$productStockQty = 100;
|
|
$product = $this->productRepository->get('simple-1', false, null, true);
|
|
$quote->addProduct($product, 50);
|
|
$quote->setTotalsCollectedFlag(false)->collectTotals();
|
|
$this->assertEquals(50, $quote->getItemsQty());
|
|
$quote->addProduct($product, 50);
|
|
$quote->setTotalsCollectedFlag(false)->collectTotals();
|
|
$this->assertEquals(100, $quote->getItemsQty());
|
|
$params = [
|
|
'related_product' => '',
|
|
'product' => $product->getId(),
|
|
'qty' => 1,
|
|
'id' => 0,
|
|
];
|
|
$updateParams = new \Magento\Framework\DataObject($params);
|
|
$quote->updateItem($updateParams['id'], $updateParams);
|
|
$quote->setTotalsCollectedFlag(false)->collectTotals();
|
|
$this->assertEquals(1, $quote->getItemsQty());
|
|
$this->expectException(LocalizedException::class);
|
|
// TODO: fix test or implementation as described in https://github.com/magento-engcom/msi/issues/1037
|
|
// $this->expectExceptionMessage('The requested qty is not available');
|
|
$updateParams['qty'] = $productStockQty + 1;
|
|
$quote->updateItem($updateParams['id'], $updateParams);
|
|
}
|
|
|
|
/**
|
|
* Test to verify that reserved_order_id will be changed if it already in used
|
|
*
|
|
* @magentoDataFixture Magento/Sales/_files/order.php
|
|
* @magentoDataFixture Magento/Quote/_files/empty_quote.php
|
|
* @return void
|
|
*/
|
|
public function testReserveOrderId(): void
|
|
{
|
|
$quote = $this->getQuoteByReservedOrderId->execute('reserved_order_id');
|
|
$quote->reserveOrderId();
|
|
$this->assertEquals('reserved_order_id', $quote->getReservedOrderId());
|
|
$quote->setReservedOrderId('100000001');
|
|
$quote->reserveOrderId();
|
|
$this->assertNotEquals('100000001', $quote->getReservedOrderId());
|
|
}
|
|
|
|
/**
|
|
* Test to verify that disabled product cannot be added to cart
|
|
* @magentoDataFixture Magento/Quote/_files/is_not_salable_product.php
|
|
* @return void
|
|
*/
|
|
public function testAddedProductToQuoteIsSalable(): void
|
|
{
|
|
$product = $this->productRepository->getById(99, false, null, true);
|
|
$this->expectException(LocalizedException::class);
|
|
$this->expectExceptionMessage((string)__('Product that you are trying to add is not available.'));
|
|
$this->quoteFactory->create()->addProduct($product);
|
|
}
|
|
|
|
/**
|
|
* @magentoDataFixture Magento/Sales/_files/quote.php
|
|
* @magentoDataFixture Magento/Catalog/_files/product_simple.php
|
|
* @return void
|
|
*/
|
|
public function testGetItemById(): void
|
|
{
|
|
$quote = $this->getQuoteByReservedOrderId->execute('test01');
|
|
$quoteItem = $this->itemFactory->create();
|
|
$product = $this->productRepository->get('simple');
|
|
$quoteItem->setProduct($product);
|
|
$quote->addItem($quoteItem);
|
|
$quote->save();
|
|
$item = $quote->getItemById($quoteItem->getId());
|
|
$this->assertInstanceOf(CartItemInterface::class, $item);
|
|
$this->assertEquals($quoteItem->getId(), $item->getId());
|
|
}
|
|
|
|
/**
|
|
* Tests of quotes merging.
|
|
*
|
|
* @param int|null $guestItemGiftMessageId
|
|
* @param int|null $customerItemGiftMessageId
|
|
* @param int|null $guestOrderGiftMessageId
|
|
* @param int|null $customerOrderGiftMessageId
|
|
* @param int|null $expectedItemGiftMessageId
|
|
* @param int|null $expectedOrderGiftMessageId
|
|
*
|
|
* @magentoDataFixture Magento/Sales/_files/quote.php
|
|
* @dataProvider giftMessageDataProvider
|
|
* @return void
|
|
*/
|
|
public function testMerge(
|
|
?int $guestItemGiftMessageId,
|
|
?int $customerItemGiftMessageId,
|
|
?int $guestOrderGiftMessageId,
|
|
?int $customerOrderGiftMessageId,
|
|
?int $expectedItemGiftMessageId,
|
|
?int $expectedOrderGiftMessageId
|
|
): void {
|
|
$product = $this->productRepository->get('simple', false, null, true);
|
|
$guestQuote = $this->getQuoteByReservedOrderId->execute('test01');
|
|
$guestQuote->setGiftMessageId($guestOrderGiftMessageId);
|
|
$customerQuote = $this->quoteFactory->create();
|
|
$customerQuote->setReservedOrderId('test02')
|
|
->setStoreId($guestQuote->getStoreId())
|
|
->addProduct($product);
|
|
$customerQuote->setGiftMessageId($customerOrderGiftMessageId);
|
|
$guestItem = $guestQuote->getItemByProduct($product);
|
|
$guestItem->setGiftMessageId($guestItemGiftMessageId);
|
|
$customerItem = $customerQuote->getItemByProduct($product);
|
|
$customerItem->setGiftMessageId($customerItemGiftMessageId);
|
|
$customerQuote->merge($guestQuote);
|
|
$mergedItemItem = $customerQuote->getItemByProduct($product);
|
|
$this->assertEquals($expectedOrderGiftMessageId, $customerQuote->getGiftMessageId());
|
|
$this->assertEquals($expectedItemGiftMessageId, $mergedItemItem->getGiftMessageId());
|
|
}
|
|
|
|
/**
|
|
* Provides order- and item-level gift message Id.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function giftMessageDataProvider(): array
|
|
{
|
|
return [
|
|
[
|
|
'guestItemId' => null,
|
|
'customerItemId' => 1,
|
|
'guestOrderId' => null,
|
|
'customerOrderId' => 11,
|
|
'expectedItemId' => 1,
|
|
'expectedOrderId' => 11,
|
|
],
|
|
[
|
|
'guestItemId' => 1,
|
|
'customerItemId' => 2,
|
|
'guestOrderId' => 11,
|
|
'customerOrderId' => 22,
|
|
'expectedItemId' => 1,
|
|
'expectedOrderId' => 11,
|
|
],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @magentoDataFixture Magento/Catalog/_files/product_simple_with_custom_file_option.php
|
|
*
|
|
* @return void
|
|
*/
|
|
public function testAddProductWithoutChosenOptions(): void
|
|
{
|
|
$quote = $this->quoteFactory->create();
|
|
$product = $this->productRepository->get('simple_with_custom_file_option');
|
|
$result = $quote->addProduct($product);
|
|
$this->assertEquals(
|
|
(string)__(
|
|
'The product\'s required option(s) weren\'t entered. Make sure the options are entered and try again.'
|
|
),
|
|
$result
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @magentoDataFixture Magento/Catalog/_files/product_simple_duplicated.php
|
|
*
|
|
* @return void
|
|
*/
|
|
public function testAddProductWithInvalidRequestParams(): void
|
|
{
|
|
$quote = $this->quoteFactory->create();
|
|
$product = $this->productRepository->get('simple-1');
|
|
$this->expectExceptionObject(
|
|
new LocalizedException(__('We found an invalid request for adding product to quote.'))
|
|
);
|
|
$quote->addProduct($product, '');
|
|
}
|
|
|
|
/**
|
|
* @magentoDataFixture Magento/Catalog/_files/product_simple_out_of_stock.php
|
|
*
|
|
* @return void
|
|
*/
|
|
public function testAddProductOutOfStock(): void
|
|
{
|
|
$quote = $this->quoteFactory->create();
|
|
$product = $this->productRepository->get('simple-out-of-stock');
|
|
$this->expectExceptionObject(
|
|
new LocalizedException(__('Product that you are trying to add is not available.'))
|
|
);
|
|
$quote->addProduct($product, 1);
|
|
}
|
|
|
|
/**
|
|
* @magentoDataFixture Magento/Catalog/_files/product_simple_duplicated.php
|
|
*
|
|
* @return void
|
|
*/
|
|
public function testAddProductWithMoreQty(): void
|
|
{
|
|
$quote = $this->quoteFactory->create();
|
|
$product = $this->productRepository->get('simple-1');
|
|
$this->expectExceptionObject(new LocalizedException(__('The requested qty is not available')));
|
|
$quote->addProduct($product, 1500);
|
|
}
|
|
|
|
/**
|
|
* @magentoDataFixture Magento/Catalog/_files/simple_product_with_qty_increments.php
|
|
*
|
|
* @return void
|
|
*/
|
|
public function testAddProductWithQtyIncrements(): void
|
|
{
|
|
$quote = $this->quoteFactory->create();
|
|
$product = $this->productRepository->get('simple_product_with_qty_increments');
|
|
$this->expectExceptionObject(
|
|
new LocalizedException(__('You can buy this product only in quantities of %1 at a time.', 3))
|
|
);
|
|
$quote->addProduct($product, 1);
|
|
}
|
|
|
|
/**
|
|
* @magentoDataFixture Magento/Catalog/_files/simple_product_min_max_sale_qty.php
|
|
* @magentoAppIsolation enabled
|
|
*
|
|
* @return void
|
|
*/
|
|
public function testAddProductWithMinSaleQty(): void
|
|
{
|
|
$quote = $this->quoteFactory->create();
|
|
$product = $this->productRepository->get('simple_product_min_max_sale_qty');
|
|
$messages = [
|
|
(string)__('The fewest you may purchase is %1.', 5),
|
|
(string)__('The fewest you may purchase is %1', 5),
|
|
];
|
|
$this->expectException(LocalizedException::class);
|
|
$this->expectExceptionMessageMatches('/' . implode('|', $messages) . '/');
|
|
$quote->addProduct($product, 1);
|
|
}
|
|
|
|
/**
|
|
* @magentoDataFixture Magento/Catalog/_files/simple_product_min_max_sale_qty.php
|
|
*
|
|
* @return void
|
|
*/
|
|
public function testAddProductWithMaxSaleQty(): void
|
|
{
|
|
$quote = $this->quoteFactory->create();
|
|
$product = $this->productRepository->get('simple_product_min_max_sale_qty');
|
|
$messages = [
|
|
(string)__('The most you may purchase is %1.', 20),
|
|
(string)__('The requested qty exceeds the maximum qty allowed in shopping cart'),
|
|
];
|
|
$this->expectException(LocalizedException::class);
|
|
$this->expectExceptionMessageMatches('/' . implode('|', $messages) . '/');
|
|
$quote->addProduct($product, 25);
|
|
}
|
|
|
|
/**
|
|
* @magentoConfigFixture current_store cataloginventory/item_options/enable_qty_increments 1
|
|
* @magentoConfigFixture current_store cataloginventory/item_options/qty_increments 3
|
|
* @magentoDataFixture Magento/Catalog/_files/product_simple_duplicated.php
|
|
* @magentoAppIsolation enabled
|
|
*
|
|
* @return void
|
|
*/
|
|
public function testAddProductWithConfigQtyIncrements(): void
|
|
{
|
|
$quote = $this->quoteFactory->create();
|
|
$product = $this->productRepository->get('simple-1');
|
|
$this->expectExceptionObject(
|
|
new LocalizedException(__('You can buy this product only in quantities of %1 at a time.', 3))
|
|
);
|
|
$quote->addProduct($product, 1);
|
|
}
|
|
|
|
/**
|
|
* @magentoConfigFixture current_store cataloginventory/item_options/min_sale_qty 5
|
|
* @magentoDataFixture Magento/Catalog/_files/product_simple_duplicated.php
|
|
* @magentoAppIsolation enabled
|
|
*
|
|
* @return void
|
|
*/
|
|
public function testAddProductWithConfigMinSaleQty(): void
|
|
{
|
|
$quote = $this->quoteFactory->create();
|
|
$product = $this->productRepository->get('simple-1');
|
|
$messages = [
|
|
(string)__('The fewest you may purchase is %1.', 5),
|
|
(string)__('The fewest you may purchase is %1', 5),
|
|
];
|
|
$this->expectException(LocalizedException::class);
|
|
$this->expectExceptionMessageMatches('/' . implode('|', $messages) . '/');
|
|
$quote->addProduct($product, 1);
|
|
}
|
|
|
|
/**
|
|
* @magentoConfigFixture current_store cataloginventory/item_options/max_sale_qty 20
|
|
* @magentoDataFixture Magento/Catalog/_files/product_simple_duplicated.php
|
|
* @magentoAppIsolation enabled
|
|
*
|
|
* @return void
|
|
*/
|
|
public function testAddProductWithConfigMaxSaleQty(): void
|
|
{
|
|
$quote = $this->quoteFactory->create();
|
|
$product = $this->productRepository->get('simple-1');
|
|
$messages = [
|
|
(string)__('The most you may purchase is %1.', 20),
|
|
(string)__('The requested qty exceeds the maximum qty allowed in shopping cart'),
|
|
];
|
|
$this->expectException(LocalizedException::class);
|
|
$this->expectExceptionMessageMatches('/' . implode('|', $messages) . '/');
|
|
$quote->addProduct($product, 25);
|
|
}
|
|
|
|
/**
|
|
* Assert address in quote.
|
|
*
|
|
* @param array $expectedAddress
|
|
* @param AddressInterface $quoteAddress
|
|
* @return void
|
|
*/
|
|
private function assertQuoteAddress(array $expectedAddress, AddressInterface $quoteAddress): void
|
|
{
|
|
foreach ($expectedAddress as $field => $value) {
|
|
$this->assertEquals(
|
|
$value,
|
|
$quoteAddress->getData($field),
|
|
sprintf('"%s" value in quote %s address is invalid.', $field, $quoteAddress->getAddressType())
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Prepare quote for testing assignCustomerWithAddressChange method.
|
|
* Customer with two addresses created. First address is default billing, second is default shipping.
|
|
*
|
|
* @param CartInterface $quote
|
|
* @return CustomerInterface
|
|
*/
|
|
private function prepareQuoteForTestAssignCustomerWithAddressChange(CartInterface $quote): CustomerInterface
|
|
{
|
|
$fixtureCustomerId = 1;
|
|
$fixtureSecondAddressId = 2;
|
|
$customer = $this->customerFactory->create();
|
|
$this->customerResourceModel->load($customer, $fixtureCustomerId);
|
|
$customer->setDefaultShipping($fixtureSecondAddressId);
|
|
$this->customerResourceModel->save($customer);
|
|
$customerData = $customer->getDataModel();
|
|
$this->assertEmpty(
|
|
$quote->getBillingAddress()->getId(),
|
|
"Precondition failed: billing address should be empty."
|
|
);
|
|
$this->assertEmpty(
|
|
$quote->getShippingAddress()->getId(),
|
|
"Precondition failed: shipping address should be empty."
|
|
);
|
|
|
|
return $customerData;
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
private function getCustomerDataArray(): array
|
|
{
|
|
return [
|
|
CustomerInterface::CONFIRMATION => 'test',
|
|
CustomerInterface::CREATED_AT => '2/3/2014',
|
|
CustomerInterface::CREATED_IN => 'Default',
|
|
CustomerInterface::DEFAULT_BILLING => 'test',
|
|
CustomerInterface::DEFAULT_SHIPPING => 'test',
|
|
CustomerInterface::DOB => '2014-02-03 00:00:00',
|
|
CustomerInterface::EMAIL => 'qa@example.com',
|
|
CustomerInterface::FIRSTNAME => 'Joe',
|
|
CustomerInterface::GENDER => 0,
|
|
CustomerInterface::GROUP_ID => GroupManagement::NOT_LOGGED_IN_ID,
|
|
CustomerInterface::ID => 1,
|
|
CustomerInterface::LASTNAME => 'Dou',
|
|
CustomerInterface::MIDDLENAME => 'Ivan',
|
|
CustomerInterface::PREFIX => 'Dr.',
|
|
CustomerInterface::STORE_ID => 1,
|
|
CustomerInterface::SUFFIX => 'Jr.',
|
|
CustomerInterface::TAXVAT => 1,
|
|
CustomerInterface::WEBSITE_ID => 1,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @magentoConfigFixture current_store sales/minimum_order/active 1
|
|
* @magentoConfigFixture current_store sales/minimum_order/amount 5
|
|
* @magentoConfigFixture current_store sales/minimum_order/tax_including 1
|
|
* @magentoConfigFixture current_store sales/minimum_order/include_discount_amount 1
|
|
* @magentoConfigFixture current_store tax/calculation/price_includes_tax 1
|
|
* @magentoConfigFixture current_store tax/calculation/apply_after_discount 1
|
|
* @magentoConfigFixture current_store tax/calculation/cross_border_trade_enabled 1
|
|
* @magentoDataFixture Magento/SalesRule/_files/cart_rule_with_coupon_5_off_no_condition.php
|
|
* @magentoDataFixture Magento/Tax/_files/tax_rule_region_1_al.php
|
|
* @magentoDataFixture Magento/Checkout/_files/quote_with_taxable_product_and_customer.php
|
|
*/
|
|
public function testValidateMinimumAmountWithPriceInclTaxAndDiscount()
|
|
{
|
|
/** @var $quote \Magento\Quote\Model\Quote */
|
|
$quote = $this->getQuoteByReservedOrderId->execute('test_order_with_taxable_product');
|
|
$quote->setCouponCode('CART_FIXED_DISCOUNT_5');
|
|
$quote->collectTotals();
|
|
$this->assertEquals(-5, $quote->getShippingAddress()->getBaseDiscountAmount());
|
|
$this->assertEquals(9.3, $quote->getShippingAddress()->getBaseSubtotal());
|
|
$this->assertEquals(5, $quote->getShippingAddress()->getBaseGrandTotal());
|
|
$this->assertTrue($quote->validateMinimumAmount());
|
|
}
|
|
|
|
/**
|
|
* @magentoConfigFixture current_store multishipping/options/checkout_multiple 1
|
|
* @magentoAppIsolation enabled
|
|
* @magentoDbIsolation enabled
|
|
* @magentoDataFixture Magento/Multishipping/Fixtures/quote_with_split_items.php
|
|
* @return void
|
|
*/
|
|
public function testIsMultiShippingModeEnabledAfterQuoteItemRemoved(): void
|
|
{
|
|
$quote = $this->getQuoteByReservedOrderId->execute('multishipping_quote_id');
|
|
/** @var CheckoutSession $session */
|
|
$session = $this->objectManager->get(CheckoutSession::class);
|
|
$session->replaceQuote($quote);
|
|
$items = $quote->getAllItems();
|
|
$idToDelete = null;
|
|
foreach ($items as $item) {
|
|
if (!$item->getProduct()->isVirtual() && $item->getQty() == 1) {
|
|
$idToDelete = $item->getId();
|
|
}
|
|
}
|
|
|
|
if (!is_null($idToDelete)) {
|
|
$quoteShippingAddresses = $quote->getAllShippingAddresses();
|
|
foreach ($quoteShippingAddresses as $shippingAddress) {
|
|
if ($shippingAddress->getItemById($idToDelete)) {
|
|
$shippingAddress->removeItem($idToDelete);
|
|
$shippingAddress->setCollectShippingRates(true);
|
|
|
|
if (count($shippingAddress->getAllItems()) == 0) {
|
|
$shippingAddress->isDeleted(true);
|
|
}
|
|
}
|
|
}
|
|
$quote->removeItem($idToDelete);
|
|
$this->assertEquals(
|
|
1,
|
|
$quote->getIsMultiShipping(),
|
|
"Multi-shipping mode is disabled after quote item removal"
|
|
);
|
|
} else {
|
|
$this->assertTrue(
|
|
!is_null($idToDelete),
|
|
"No Simple Product item with qty 1 to delete exists"
|
|
);
|
|
}
|
|
}
|
|
}
|