magento2-docker/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteManagementTest.php

441 lines
17 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\Catalog\Model\Product\Type;
use Magento\Checkout\Api\PaymentInformationManagementInterface;
use Magento\Customer\Api\CustomerRepositoryInterface;
use Magento\Customer\Model\Vat;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\DataObject;
use Magento\Framework\Exception\CouldNotSaveException;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\StateException;
use Magento\Framework\ObjectManagerInterface;
use Magento\Quote\Api\CartManagementInterface;
use Magento\Quote\Api\Data\AddressInterface;
use Magento\Quote\Api\Data\PaymentInterface;
use Magento\Quote\Observer\Frontend\Quote\Address\CollectTotalsObserver;
use Magento\Quote\Observer\Frontend\Quote\Address\VatValidator;
use Magento\Sales\Api\OrderManagementInterface;
use Magento\Sales\Api\OrderRepositoryInterface;
use Magento\Store\Model\StoreManagerInterface;
use Magento\TestFramework\Helper\Bootstrap;
use Magento\TestFramework\Quote\Model\GetQuoteByReservedOrderId;
use PHPUnit\Framework\ExpectationFailedException;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
/**
* Class for testing QuoteManagement model
*
* @see \Magento\Quote\Model\QuoteManagement
* @magentoDbIsolation enabled
* @magentoAppIsolation enabled
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class QuoteManagementTest extends TestCase
{
/**
* @var ObjectManagerInterface
*/
private $objectManager;
/**
* @var CartManagementInterface
*/
private $cartManagement;
/**
* @var OrderRepositoryInterface
*/
private $orderRepository;
/**
* @var GetQuoteByReservedOrderId
*/
private $getQuoteByReservedOrderId;
/**
* @var ProductRepositoryInterface
*/
private $productRepository;
/**
* @var CustomerRepositoryInterface
*/
private $customerRepository;
/**
* @var StoreManagerInterface
*/
private $storeManager;
/**
* @var PaymentInformationManagementInterface
*/
private $paymentManagement;
/**
* @var PaymentInterface
*/
private $payment;
/**
* @var AddressInterface
*/
private $address;
/**
* @inheritdoc
*/
protected function setUp(): void
{
parent::setUp();
$this->objectManager = Bootstrap::getObjectManager();
$this->cartManagement = $this->objectManager->get(CartManagementInterface::class);
$this->orderRepository = $this->objectManager->get(OrderRepositoryInterface::class);
$this->getQuoteByReservedOrderId = $this->objectManager->get(GetQuoteByReservedOrderId::class);
$this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class);
$this->productRepository->cleanCache();
$this->customerRepository = $this->objectManager->get(CustomerRepositoryInterface::class);
$this->storeManager = $this->objectManager->get(StoreManagerInterface::class);
$this->paymentManagement = $this->objectManager->get(PaymentInformationManagementInterface::class);
$this->payment = $this->objectManager->get(PaymentInterface::class);
$this->address = $this->objectManager->get(AddressInterface::class);
}
/**
* Creates order with product that has child items.
*
* @magentoAppIsolation enabled
* @magentoDataFixture Magento/Sales/_files/quote_with_bundle.php
*
* @return void
*/
public function testSubmit(): void
{
$quote = $this->getQuoteByReservedOrderId->execute('test01');
$orderId = $this->cartManagement->placeOrder($quote->getId());
$order = $this->orderRepository->get($orderId);
$orderItems = $order->getItems();
$this->assertCount(3, $orderItems);
foreach ($orderItems as $orderItem) {
if ($orderItem->getProductType() == Type::TYPE_SIMPLE) {
$this->assertNotEmpty($orderItem->getParentItem(), 'Parent is not set for child product');
$this->assertNotEmpty($orderItem->getParentItemId(), 'Parent is not set for child product');
}
}
}
/**
* Verify guest customer place order with auto-group assigment.
*
* @magentoDataFixture Magento/Sales/_files/guest_quote_with_addresses.php
*
* @magentoConfigFixture default_store customer/create_account/auto_group_assign 1
* @magentoConfigFixture default_store customer/create_account/tax_calculation_address_type shipping
* @magentoConfigFixture default_store customer/create_account/viv_intra_union_group 2
* @magentoConfigFixture default_store customer/create_account/viv_on_each_transaction 1
*
* @return void
*/
public function testSubmitGuestCustomer(): void
{
$this->mockVatValidation();
$quote = $this->getQuoteByReservedOrderId->execute('guest_quote');
$this->cartManagement->placeOrder($quote->getId());
$quoteAfterOrderPlaced = $this->getQuoteByReservedOrderId->execute('guest_quote');
self::assertEquals(0, $quoteAfterOrderPlaced->getCustomerGroupId());
self::assertEquals(3, $quoteAfterOrderPlaced->getCustomerTaxClassId());
}
/**
* Creates order with purchase_order payment method
*
* @magentoAppIsolation enabled
* @magentoDataFixture Magento/Sales/_files/quote_with_purchase_order.php
*
* @return void
* @throws CouldNotSaveException
*/
public function testSubmitWithPurchaseOrder(): void
{
$paymentMethodName = 'purchaseorder';
$poNumber = '12345678';
$quote = $this->getQuoteByReservedOrderId->execute('test_order_1');
$quote->getPayment()->setPoNumber($poNumber);
$quote->collectTotals()->save();
$orderId = $this->cartManagement->placeOrder($quote->getId());
$order = $this->orderRepository->get($orderId);
$orderItems = $order->getItems();
$this->assertCount(1, $orderItems);
$payment = $order->getPayment();
$this->assertEquals($paymentMethodName, $payment->getMethod());
$this->assertEquals($poNumber, $payment->getPoNumber());
}
/**
* Creates order with purchase_order payment method without po_number
*
* @magentoAppIsolation enabled
* @magentoDataFixture Magento/Sales/_files/quote_with_purchase_order.php
*
* @return void
* @throws CouldNotSaveException
*/
public function testSubmitWithPurchaseOrderWithException(): void
{
$this->expectException(LocalizedException::class);
$this->expectExceptionMessage('Purchase order number is a required field.');
$quote = $this->getQuoteByReservedOrderId->execute('test_order_1');
$this->cartManagement->placeOrder($quote->getId());
}
/**
* Tries to create order with product that has child items and one of them was deleted.
*
* @magentoConfigFixture cataloginventory/options/enable_inventory_check 1
* @magentoAppArea adminhtml
* @magentoAppIsolation enabled
* @magentoDataFixture Magento/Sales/_files/quote_with_bundle.php
*/
public function testSubmitWithDeletedItem(): void
{
$this->productRepository->deleteById('simple-2');
$quote = $this->getQuoteByReservedOrderId->execute('test01');
$this->expectExceptionObject(
new LocalizedException(__('Some of the products below do not have all the required options.'))
);
$this->cartManagement->placeOrder($quote->getId());
}
/**
* Tries to create order with product that has child items and one of them
* was deleted when item data check is disabled on quote load.
* @magentoConfigFixture cataloginventory/options/enable_inventory_check 0
* @magentoAppArea adminhtml
* @magentoAppIsolation enabled
* @magentoDataFixture Magento/Sales/_files/quote_with_bundle.php
*/
public function testSubmitWithDeletedItemWithDisabledInventoryCheck(): void
{
$this->productRepository->deleteById('simple-2');
$quote = $this->getQuoteByReservedOrderId->execute('test01');
$this->cartManagement->placeOrder($quote->getId());
}
/**
* Tries to create order with item of stock during checkout.
* @magentoConfigFixture cataloginventory/options/enable_inventory_check 1
* @magentoDataFixture Magento/Sales/_files/quote.php
* @magentoDbIsolation enabled
*/
public function testSubmitWithItemOutOfStock(): void
{
$this->makeProductOutOfStock('simple');
$quote = $this->getQuoteByReservedOrderId->execute('test01');
$this->expectExceptionObject(new LocalizedException(__('Some of the products are out of stock.')));
$this->cartManagement->placeOrder($quote->getId());
}
/**
* Tries to create order with item of stock during checkout
* when item data check is disabled on quote load.
* @magentoConfigFixture cataloginventory/options/enable_inventory_check 0
* @magentoDataFixture Magento/Sales/_files/quote.php
* @magentoDbIsolation enabled
*/
public function testSubmitWithItemOutOfStockWithDisabledInventoryCheck(): void
{
$this->makeProductOutOfStock('simple');
$quote = $this->getQuoteByReservedOrderId->execute('test01');
$this->expectExceptionObject(
new LocalizedException(
__('The shipping method is missing. Select the shipping method and try again.')
)
);
$this->cartManagement->placeOrder($quote->getId());
}
/**
* Tries to create an order using quote with empty customer email.
*
* Order should not start placing if order validation is failed.
*
* @magentoDataFixture Magento/Quote/Fixtures/quote_without_customer_email.php
*
* @return void
*/
public function testSubmitWithEmptyCustomerEmail(): void
{
$quote = $this->getQuoteByReservedOrderId->execute('test01');
$orderManagement = $this->createMock(OrderManagementInterface::class);
$orderManagement->expects($this->never())
->method('place');
$cartManagement = $this->objectManager->create(
CartManagementInterface::class,
['orderManagement' => $orderManagement]
);
$this->expectExceptionObject(new LocalizedException(__('Email has a wrong format')));
try {
$cartManagement->placeOrder($quote->getId());
} catch (ExpectationFailedException $e) {
$this->fail('Place order method was not expected to be called if order validation is failed');
}
}
/**
* @magentoDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
* @magentoDataFixture Magento/Customer/_files/customer.php
*
* @return void
*/
public function testAssignCustomerToQuote(): void
{
$customer = $this->customerRepository->get('customer@example.com');
$quote = $this->getQuoteByReservedOrderId->execute('test_order_with_simple_product_without_address');
$result = $this->cartManagement->assignCustomer($quote->getId(), $customer->getId(), $customer->getStoreId());
$this->assertTrue($result);
$customerQuote = $this->cartManagement->getCartForCustomer($customer->getId());
$this->assertEquals($quote->getId(), $customerQuote->getId());
$this->assertEquals($customer->getId(), $customerQuote->getCustomerId());
$this->assertEquals($customer->getEmail(), $customerQuote->getCustomerEmail());
}
/**
* @magentoDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
* @magentoDataFixture Magento/Customer/_files/customer_for_second_website.php
*
* @return void
*/
public function testAssignCustomerFromAnotherWebsiteToQuote(): void
{
$websiteId = $this->storeManager->getWebsite('test')->getId();
$customer = $this->customerRepository->get('customer@example.com', $websiteId);
$quote = $this->getQuoteByReservedOrderId->execute('test_order_with_simple_product_without_address');
$this->expectExceptionObject(
new StateException(
__('The customer can\'t be assigned to the cart. The cart belongs to a different store.')
)
);
$this->cartManagement->assignCustomer($quote->getId(), $customer->getId(), $quote->getStoreId());
}
/**
* @magentoDataFixture Magento/Checkout/_files/quote_with_customer_without_address.php
* @magentoDataFixture Magento/Customer/_files/customer_with_uk_address.php
*
* @return void
*/
public function testAssignCustomerToQuoteAlreadyHaveCustomer(): void
{
$customer = $this->customerRepository->get('customer_uk_address@test.com');
$quote = $this->getQuoteByReservedOrderId->execute('test_order_with_customer_without_address');
$this->expectExceptionObject(
new StateException(__('The customer can\'t be assigned to the cart because the cart isn\'t anonymous.'))
);
$this->cartManagement->assignCustomer($quote->getId(), $customer->getId(), $quote->getStoreId());
}
/**
* Makes provided product as out of stock.
*
* @param string $sku
* @return void
*/
private function makeProductOutOfStock(string $sku): void
{
$product = $this->productRepository->get($sku);
$extensionAttributes = $product->getExtensionAttributes();
$stockItem = $extensionAttributes->getStockItem();
$stockItem->setIsInStock(false);
$this->productRepository->save($product);
}
/**
* Makes customer vat validator 'check vat number' response successful.
*
* @return void
*/
private function mockVatValidation(): void
{
$vatMock = $this->getMockBuilder(Vat::class)
->setConstructorArgs(
[
'scopeConfig' => $this->objectManager->get(ScopeConfigInterface::class),
'logger' => $this->objectManager->get(LoggerInterface::class),
]
)
->onlyMethods(['checkVatNumber'])
->getMock();
$gatewayResponse = new DataObject([
'is_valid' => true,
'request_date' => 'testData',
'request_identifier' => 'testRequestIdentifier',
'request_success' => true,
]);
$vatMock->method('checkVatNumber')->willReturn($gatewayResponse);
$this->objectManager->removeSharedInstance(CollectTotalsObserver::class);
$this->objectManager->removeSharedInstance(VatValidator::class);
$this->objectManager->removeSharedInstance(Vat::class);
$this->objectManager->addSharedInstance($vatMock, Vat::class);
}
/**
* Creates order with purchase_order payment method
*
* @magentoDataFixture Magento/Sales/_files/quote_with_customer.php
* @magentoDbIsolation disabled
* @return void
* @throws CouldNotSaveException
*/
public function testCustomerAddressIdAfterPlacingOrder(): void
{
$quote = $this->getQuoteByReservedOrderId->execute('test01');
$quote->getBillingAddress()->setSaveInAddressBook(null);
$quote->getBillingAddress()->setCustomerAddressId(null);
$this->address->setFirstname($quote->getBillingAddress()->getFirstname());
$this->address->setLastname($quote->getBillingAddress()->getLastname());
$this->address->setCity($quote->getBillingAddress()->getCity());
$this->address->setCompany($quote->getBillingAddress()->getCompany());
$this->address->setCountryId($quote->getBillingAddress()->getCountryId());
$this->address->setRegionId($quote->getBillingAddress()->getRegionId());
$this->address->setCustomerId($quote->getBillingAddress()->getCustomerId());
$this->address->setPostcode($quote->getBillingAddress()->getPostcode());
$this->address->setTelephone($quote->getBillingAddress()->getTelephone());
$this->address->setStreet($quote->getBillingAddress()->getStreet());
$this->address->setSameAsBilling($quote->getBillingAddress()->getSameAsBilling());
$this->address->setCustomerAddressId($quote->getBillingAddress()->getCustomerAddressId());
$this->address->setSaveInAddressBook($quote->getBillingAddress()->getSaveInAddressBook());
$quote->getShippingAddress()
->setShippingMethod('flatrate_flatrate')
->setCollectShippingRates(true);
$quote->getShippingAddress()->setSameAsBilling(1);
$quote->getShippingAddress()->setSaveInAddressBook(1);
$this->payment->setMethod('checkmo');
$quote->save();
$orderId = $this->paymentManagement->savePaymentInformationAndPlaceOrder(
$quote->getId(),
$this->payment,
$this->address
);
$order = $this->orderRepository->get($orderId);
$billingAddress = $order->getBillingAddress();
$shippingAddress = $order->getShippingAddress();
$this->assertNotNull($billingAddress->getCustomerAddressId());
$this->assertNotNull($shippingAddress->getCustomerAddressId());
$this->assertEquals($billingAddress->getCustomerAddressId(), $shippingAddress->getCustomerAddressId());
}
}