magento2-docker/dev/tests/integration/testsuite/Magento/Checkout/Block/Cart/CrosssellTest.php

354 lines
12 KiB
PHP
Executable File

<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);
namespace Magento\Checkout\Block\Cart;
use Magento\Catalog\Block\Product\ProductList\AbstractLinksTest;
use Magento\Catalog\ViewModel\Product\Listing\PreparePostData;
use Magento\Checkout\Model\Session;
use Magento\TestFramework\Helper\Xpath;
use Magento\TestFramework\Quote\Model\GetQuoteByReservedOrderId;
use Magento\TestFramework\Store\ExecuteInStoreContext;
/**
* Check the correct behavior of cross-sell products in the shopping cart
*
* @see \Magento\Checkout\Block\Cart\Crosssell
* @magentoDbIsolation disabled
* @magentoAppIsolation enabled
* @magentoAppArea frontend
*/
class CrosssellTest extends AbstractLinksTest
{
private const MAX_ITEM_COUNT = 4;
/** @var Session */
private $checkoutSession;
/** @var string */
private $addToCartButtonXpath = "//div[contains(@class, 'actions-primary')]/button[@type='button']";
/** @var string */
private $addToCartSubmitXpath = "//div[contains(@class, 'actions-primary')]"
. "/form[@data-product-sku='%s']/button[@type='submit']";
/** @var string */
private $addToLinksXpath = "//div[contains(@class, 'actions-secondary')]";
/** @var ExecuteInStoreContext */
private $executeInStoreContext;
/**
* @inheritdoc
*/
protected function setUp(): void
{
parent::setUp();
$this->block = $this->layout->createBlock(Crosssell::class);
$this->linkType = 'crosssell';
$this->titleName = (string)__('More Choices:');
$this->checkoutSession = $this->objectManager->get(Session::class);
$this->executeInStoreContext = $this->objectManager->get(ExecuteInStoreContext::class);
}
/**
* Checks for a simple cross-sell product when block code is generated
*
* @magentoDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
* @magentoDataFixture Magento/Catalog/_files/product_simple_duplicated.php
* @return void
*/
public function testSimpleCrosssellProduct(): void
{
$relatedProduct = $this->productRepository->get('simple-1');
$this->linkProducts('simple', ['simple-1' => ['position' => 2]]);
$this->setCheckoutSessionQuote('test_order_with_simple_product_without_address');
$this->prepareBlock();
$html = $this->block->toHtml();
$this->assertNotEmpty($html);
$this->assertEquals(
1,
Xpath::getElementsCountForXpath(sprintf($this->titleXpath, $this->linkType, $this->titleName), $html),
'Expected title is incorrect or missing!'
);
$this->assertEquals(
1,
Xpath::getElementsCountForXpath(sprintf($this->addToCartSubmitXpath, $relatedProduct->getSku()), $html),
'Expected add to cart button is incorrect or missing!'
);
$this->assertEquals(
1,
Xpath::getElementsCountForXpath($this->addToLinksXpath, $html),
'Expected add to links is incorrect or missing!'
);
}
/**
* Checks for a cross-sell product with required option when block code is generated
*
* @magentoDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
* @magentoDataFixture Magento/Catalog/_files/product_virtual_with_options.php
* @return void
*/
public function testCrosssellProductWithRequiredOption(): void
{
$this->linkProducts('simple', ['virtual' => ['position' => 1]]);
$this->setCheckoutSessionQuote('test_order_with_simple_product_without_address');
$this->prepareBlock();
$html = $this->block->toHtml();
$this->assertEquals(
1,
Xpath::getElementsCountForXpath($this->addToCartButtonXpath, $html),
'Expected add to cart button is incorrect or missing!'
);
}
/**
* Test the display of cross-sell products in the block
*
* @dataProvider displayLinkedProductsProvider
* @magentoDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
* @magentoDataFixture Magento/Catalog/_files/products_list.php
* @param array $data
* @return void
*/
public function testDisplayCrosssellProducts(array $data): void
{
$this->updateProducts($data['updateProducts']);
$this->linkProducts('simple', $this->existingProducts);
$items = $this->getBlockItems('test_order_with_simple_product_without_address');
$this->assertEquals(
$data['expectedProductLinks'],
$this->getActualLinks($items),
'Expected cross-sell products do not match actual cross-sell products!'
);
}
/**
* Test the position and max count of cross-sell products in the block
*
* @magentoDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
* @magentoDataFixture Magento/Catalog/_files/products_list.php
* @magentoDataFixture Magento/Catalog/_files/product_simple_duplicated.php
* @magentoDataFixture Magento/Catalog/_files/second_product_simple.php
* @return void
*/
public function testPositionCrosssellProducts(): void
{
$positionData = array_merge_recursive(
$this->getPositionData(),
[
'productLinks' => [
'simple-1' => ['position' => 5],
'simple2' => ['position' => 4],
],
'expectedProductLinks' => [
'simple2',
],
]
);
$this->linkProducts('simple', $positionData['productLinks']);
$items = $this->getBlockItems('test_order_with_simple_product_without_address');
$this->assertCount(
self::MAX_ITEM_COUNT,
$items,
'Expected quantity of cross-sell products do not match the actual quantity!'
);
$this->assertEquals(
$positionData['expectedProductLinks'],
$this->getActualLinks($items),
'Expected cross-sell products do not match actual cross-sell products!'
);
}
/**
* Test the position and max count of cross-sell products in the block
* when set last added product in checkout session
*
* @dataProvider positionWithLastAddedProductProvider
* @magentoDataFixture Magento/Sales/_files/quote_with_multiple_products.php
* @magentoDataFixture Magento/Catalog/_files/products_list.php
* @magentoDataFixture Magento/Catalog/_files/product_simple_duplicated.php
* @magentoDataFixture Magento/Catalog/_files/second_product_simple.php
* @param array $positionData
* @param array $expectedProductLinks
* @return void
*/
public function testPositionCrosssellProductsWithLastAddedProduct(
array $positionData,
array $expectedProductLinks
): void {
foreach ($positionData as $sku => $productLinks) {
$this->linkProducts($sku, $productLinks);
}
$this->checkoutSession->setLastAddedProductId($this->productRepository->get('simple-tableRate-1')->getId());
$items = $this->getBlockItems('tableRate');
$this->assertCount(
self::MAX_ITEM_COUNT,
$items,
'Expected quantity of cross-sell products do not match the actual quantity!'
);
$this->assertEquals(
$expectedProductLinks,
$this->getActualLinks($items),
'Expected cross-sell products do not match actual cross-sell products!'
);
}
/**
* Provide test data to verify the position of linked products of the last added product.
*
* @return array
*/
public function positionWithLastAddedProductProvider(): array
{
return [
'less_four_linked_products_to_last_added_product' => [
'positionData' => [
'simple-tableRate-1' => [
'simple-249' => ['position' => 2],
'simple-156' => ['position' => 1],
],
'simple-tableRate-2' => [
'simple-1' => ['position' => 2],
'simple2' => ['position' => 1],
'wrong-simple' => ['position' => 3],
],
],
'expectedProductLinks' => [
'simple-156',
'simple-249',
'simple2',
'simple-1',
],
],
'four_linked_products_to_last_added_product' => [
'positionData' => [
'simple-tableRate-1' => [
'wrong-simple' => ['position' => 3],
'simple-249' => ['position' => 1],
'simple-156' => ['position' => 2],
'simple2' => ['position' => 4],
],
'simple-tableRate-2' => [
'simple-1' => ['position' => 1],
],
],
'expectedProductLinks' => [
'simple-249',
'simple-156',
'wrong-simple',
'simple2',
],
],
];
}
/**
* Test the display of cross-sell products in the block on different websites
*
* @dataProvider multipleWebsitesLinkedProductsProvider
* @magentoDataFixture Magento/Catalog/_files/products_with_websites_and_stores.php
* @magentoDataFixture Magento/Sales/_files/quote_with_multiple_products.php
* @magentoDataFixture Magento/Catalog/_files/products_list.php
* @param array $data
* @return void
*/
public function testMultipleWebsitesCrosssellProducts(array $data): void
{
$this->updateProducts($this->prepareProductsWebsiteIds());
$productLinks = array_merge($this->existingProducts, $data['productLinks']);
$this->linkProducts('simple-tableRate-1', $productLinks);
$items = $this->executeInStoreContext->execute($data['storeCode'], [$this, 'getBlockItems'], 'tableRate');
$this->assertEquals(
$data['expectedProductLinks'],
$this->getActualLinks($items),
'Expected cross-sell products do not match actual cross-sell products!'
);
}
/**
* Test the invisibility of cross-sell products in the block which added to cart
*
* @magentoDataFixture Magento/Sales/_files/quote_with_multiple_products.php
* @magentoDataFixture Magento/Catalog/_files/product_simple_duplicated.php
* @return void
*/
public function testInvisibilityCrosssellProductAddedToCart(): void
{
$productLinks = [
'simple-1' => ['position' => 1],
'simple-tableRate-2' => ['position' => 2],
];
$this->linkProducts('simple-tableRate-1', $productLinks);
$items = $this->getBlockItems('tableRate');
$this->assertEquals(
['simple-1'],
$this->getActualLinks($items),
'Expected cross-sell products do not match actual cross-sell products!'
);
}
/**
* Get products of block when quote in checkout session
*
* @param string $reservedOrderId
* @return array
*/
public function getBlockItems(string $reservedOrderId): array
{
$this->setCheckoutSessionQuote($reservedOrderId);
return $this->block->getItems();
}
/**
* @inheritdoc
*/
protected function prepareBlock(): void
{
parent::prepareBlock();
$this->block->setViewModel($this->objectManager->get(PreparePostData::class));
}
/**
* @inheritdoc
*/
protected function prepareProductsWebsiteIds(): array
{
$productsWebsiteIds = parent::prepareProductsWebsiteIds();
$simple = $productsWebsiteIds['simple-1'];
unset($productsWebsiteIds['simple-1']);
return array_merge($productsWebsiteIds, ['simple-tableRate-1' => $simple]);
}
/**
* Set quoteId in checkoutSession object.
*
* @param string $reservedOrderId
* @return void
*/
private function setCheckoutSessionQuote(string $reservedOrderId): void
{
$this->checkoutSession->clearQuote();
$quote = $this->objectManager->get(GetQuoteByReservedOrderId::class)->execute($reservedOrderId);
if ($quote !== null) {
$this->checkoutSession->setQuoteId($quote->getId());
}
}
}