magento2-docker/dev/tests/integration/testsuite/Magento/Elasticsearch/Model/Indexer/IndexHandlerTest.php

298 lines
9.9 KiB
PHP
Executable File

<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Elasticsearch\Model\Indexer;
use Magento\AdvancedSearch\Model\Client\ClientInterface;
use Magento\Catalog\Model\Product\Action as ProductAction;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\CatalogInventory\Api\StockRegistryInterface;
use Magento\CatalogInventory\Api\StockItemRepositoryInterface;
use Magento\CatalogSearch\Model\Indexer\Fulltext as CatalogSearchFulltextIndexer;
use Magento\TestFramework\Helper\Bootstrap;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Elasticsearch\SearchAdapter\ConnectionManager;
use Magento\Elasticsearch\Model\Config;
use Magento\Elasticsearch\SearchAdapter\SearchIndexNameResolver;
use Magento\Indexer\Model\Indexer;
use Magento\Framework\Search\EngineResolverInterface;
use Magento\TestModuleCatalogSearch\Model\SearchEngineVersionReader;
use PHPUnit\Framework\TestCase;
/**
* Important: Please make sure that each integration test file works with unique search index. In order to
* achieve this, use @magentoConfigFixture to pass unique value for index_prefix for every test
* method. E.g. '@magentoConfigFixture current_store catalog/search/elasticsearch7_index_prefix indexerhandlertest'
*
* @magentoDbIsolation disabled
* @magentoDataFixture Magento/Elasticsearch/_files/indexer.php
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class IndexHandlerTest extends TestCase
{
/**
* @var ProductRepositoryInterface
*/
private $productRepository;
/**
* @var ClientInterface
*/
private $client;
/**
* @var StoreManagerInterface
*/
private $storeManager;
/**
* @var int[]
*/
private $storeIds;
/**
* @var string
*/
private $entityType;
/**
* @var Indexer
*/
private $indexer;
/**
* @var SearchIndexNameResolver
*/
private $searchIndexNameResolver;
/**
* {@inheritdoc}
*/
protected function setUp(): void
{
$connectionManager = Bootstrap::getObjectManager()->create(ConnectionManager::class);
$this->client = $connectionManager->getConnection();
$this->storeManager = Bootstrap::getObjectManager()->create(StoreManagerInterface::class);
$this->storeIds = array_keys($this->storeManager->getStores());
$clientConfig = Bootstrap::getObjectManager()->create(Config::class);
$this->entityType = $clientConfig->getEntityType();
$this->indexer = Bootstrap::getObjectManager()->create(Indexer::class);
$this->indexer->load(CatalogSearchFulltextIndexer::INDEXER_ID);
$this->indexer->reindexAll();
$this->searchIndexNameResolver = Bootstrap::getObjectManager()->create(SearchIndexNameResolver::class);
$this->productRepository = Bootstrap::getObjectManager()->create(ProductRepositoryInterface::class);
}
/**
* Make sure that correct engine is set
*/
protected function assertPreConditions(): void
{
$objectManager = Bootstrap::getObjectManager();
$currentEngine = $objectManager->get(EngineResolverInterface::class)->getCurrentSearchEngine();
$installedEngine = $objectManager->get(SearchEngineVersionReader::class)->getFullVersion();
$this->assertEquals(
$installedEngine,
$currentEngine,
sprintf(
'Search engine configuration "%s" is not compatible with the installed version',
$currentEngine
)
);
}
/**
* @return void
*/
public function testReindexAll(): void
{
$productApple = $this->productRepository->get('fulltext-1');
foreach ($this->storeIds as $storeId) {
$products = $this->searchByName('Apple', $storeId);
$this->assertCount(1, $products);
$this->assertEquals($productApple->getId(), $products[0]['_id']);
$products = $this->searchByName('Simple Product', $storeId);
$this->assertCount(5, $products);
$this->assertCount(2, $this->searchByBoolAttribute(0, $storeId));
$this->assertCount(3, $this->searchByBoolAttribute(1, $storeId));
}
}
/**
* @magentoAppIsolation enabled
* @return void
*/
public function testReindexRowAfterEdit(): void
{
$this->storeManager->setCurrentStore('admin');
$productApple = $this->productRepository->get('fulltext-1');
$productApple->setName('Simple Product Cucumber');
$this->productRepository->save($productApple);
foreach ($this->storeIds as $storeId) {
$products = $this->searchByName('Apple', $storeId);
$this->assertCount(0, $products);
$products = $this->searchByName('Cucumber', $storeId);
$this->assertCount(1, $products);
$this->assertEquals($productApple->getId(), $products[0]['_id']);
$products = $this->searchByName('Simple Product', $storeId);
$this->assertCount(5, $products);
}
}
/**
* @return void
*/
public function testReindexRowAfterMassAction(): void
{
$productApple = $this->productRepository->get('fulltext-1');
$productBanana = $this->productRepository->get('fulltext-2');
$productIds = [
$productApple->getId(),
$productBanana->getId(),
];
$attrData = [
'name' => 'Simple Product Common',
];
/** @var ProductAction $action */
$action = Bootstrap::getObjectManager()->get(ProductAction::class);
foreach ($this->storeIds as $storeId) {
$action->updateAttributes($productIds, $attrData, $storeId);
$products = $this->searchByName('Apple', $storeId);
$this->assertCount(0, $products);
$products = $this->searchByName('Banana', $storeId);
$this->assertCount(0, $products);
$products = $this->searchByName('Unknown', $storeId);
$this->assertCount(0, $products);
$products = $this->searchByName('Common', $storeId);
$this->assertCount(2, $products);
$products = $this->searchByName('Simple Product', $storeId);
$this->assertCount(5, $products);
}
}
/**
* @magentoAppArea adminhtml
* @return void
*/
public function testReindexRowAfterDelete(): void
{
$productBanana = $this->productRepository->get('fulltext-2');
$this->productRepository->delete($productBanana);
foreach ($this->storeIds as $storeId) {
$products = $this->searchByName('Banana', $storeId);
$this->assertEmpty($products);
$products = $this->searchByName('Simple Product', $storeId);
$this->assertCount(4, $products);
}
}
/**
* @magentoDbIsolation enabled
* @magentoAppArea adminhtml
* @magentoDataFixture Magento/Elasticsearch/_files/configurable_products.php
* @return void
*/
public function testReindexRowAfterUpdateStockStatus(): void
{
foreach ($this->storeIds as $storeId) {
$products = $this->searchByName('ProductOption1', $storeId);
$this->assertNotEmpty($products);
}
$product = $this->productRepository->get('simple_10');
/** @var StockRegistryInterface $stockRegistry */
$stockRegistry = Bootstrap::getObjectManager()->create(StockRegistryInterface::class);
$stockItem = $stockRegistry->getStockItem($product->getId());
$stockItem->setIsInStock(false);
/** @var StockItemRepositoryInterface $stockRepository */
$stockRepository = Bootstrap::getObjectManager()->create(StockItemRepositoryInterface::class);
$stockRepository->save($stockItem);
foreach ($this->storeIds as $storeId) {
$products = $this->searchByName('ProductOption1', $storeId);
$this->assertEmpty($products);
$products = $this->searchByName('Configurable', $storeId);
$this->assertNotEmpty($products);
}
}
/**
* Search docs in search engine by name.
*
* @param string $text
* @param int $storeId
* @return array
*/
private function searchByName(string $text, int $storeId): array
{
$index = $this->searchIndexNameResolver->getIndexName($storeId, $this->indexer->getId());
$searchQuery = [
'index' => $index,
'type' => $this->entityType,
'body' => [
'query' => [
'bool' => [
'minimum_should_match' => 1,
'should' => [
[
'match' => [
'name' => $text,
],
],
],
],
],
],
];
$queryResult = $this->client->query($searchQuery);
$products = isset($queryResult['hits']['hits']) ? $queryResult['hits']['hits'] : [];
return $products;
}
/**
* Search docs in search engine by boolean attribute.
*
* @param int $value
* @param int $storeId
* @return array
*/
private function searchByBoolAttribute(int $value, int $storeId): array
{
$index = $this->searchIndexNameResolver->getIndexName($storeId, $this->indexer->getId());
$searchQuery = [
'index' => $index,
'type' => $this->entityType,
'body' => [
'query' => [
'query_string' => [
'query' => $value,
'default_field' => 'boolean_attribute',
],
],
],
];
$queryResult = $this->client->query($searchQuery);
return isset($queryResult['hits']['hits']) ? $queryResult['hits']['hits'] : [];
}
}