Skip to content

Commit

Permalink
MC-25069: Quick/Advanced Search on storefront by product attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
IvanPletnyov committed Dec 16, 2019
1 parent ad6c093 commit b411223
Show file tree
Hide file tree
Showing 13 changed files with 888 additions and 208 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\CatalogSearch\Controller\Advanced;

use Magento\Catalog\Api\ProductAttributeRepositoryInterface;
use Magento\Catalog\Model\ResourceModel\Eav\Attribute;
use Magento\TestFramework\TestCase\AbstractController;
use Zend\Stdlib\Parameters;

/**
* Test cases for catalog advanced search using mysql search engine.
*
* @magentoDbIsolation disabled
* @magentoAppIsolation enabled
*/
class ResultTest extends AbstractController
{
/**
* @var ProductAttributeRepositoryInterface
*/
private $productAttributeRepository;

/**
* @inheritdoc
*/
protected function setUp()
{
parent::setUp();
$this->productAttributeRepository = $this->_objectManager->create(ProductAttributeRepositoryInterface::class);
}

/**
* Advanced search test by difference product attributes.
*
* @magentoConfigFixture default/catalog/search/engine mysql
* @magentoAppArea frontend
* @magentoDataFixture Magento/CatalogSearch/_files/product_for_search.php
* @magentoDataFixture Magento/CatalogSearch/_files/full_reindex.php
* @dataProvider searchStringDataProvider
*
* @param array $searchParams
* @return void
*/
public function testExecute(array $searchParams): void
{
if ('' !== $searchParams['test_searchable_attribute']) {
$searchParams['test_searchable_attribute'] = $this->getAttributeOptionValueByOptionLabel(
'test_searchable_attribute',
$searchParams['test_searchable_attribute']
);
}

$this->getRequest()->setQuery(
$this->_objectManager->create(
Parameters::class,
[
'values' => $searchParams
]
)
);
$this->dispatch('catalogsearch/advanced/result');
$responseBody = $this->getResponse()->getBody();
$this->assertContains('Simple product name', $responseBody);
}

/**
* Data provider with strings for quick search.
*
* @return array
*/
public function searchStringDataProvider(): array
{
return [
'search_product_by_name' => [
[
'name' => 'Simple product name',
'sku' => '',
'description' => '',
'short_description' => '',
'price' => [
'from' => '',
'to' => '',
],
'test_searchable_attribute' => '',
],
],
'search_product_by_sku' => [
[
'name' => '',
'sku' => 'simple_for_search',
'description' => '',
'short_description' => '',
'price' => [
'from' => '',
'to' => '',
],
'test_searchable_attribute' => '',
],
],
'search_product_by_description' => [
[
'name' => '',
'sku' => '',
'description' => 'Product description',
'short_description' => '',
'price' => [
'from' => '',
'to' => '',
],
'test_searchable_attribute' => '',
],
],
'search_product_by_short_description' => [
[
'name' => '',
'sku' => '',
'description' => '',
'short_description' => 'Product short description',
'price' => [
'from' => '',
'to' => '',
],
'test_searchable_attribute' => '',
],
],
'search_product_by_price_range' => [
[
'name' => '',
'sku' => '',
'description' => '',
'short_description' => '',
'price' => [
'from' => '50',
'to' => '150',
],
'test_searchable_attribute' => '',
],
],
'search_product_by_custom_attribute' => [
[
'name' => '',
'sku' => '',
'description' => '',
'short_description' => '',
'price' => [
'from' => '',
'to' => '',
],
'test_searchable_attribute' => 'Option 1',
],
],
];
}

/**
* Return attribute option value by option label.
*
* @param string $attributeCode
* @param string $optionLabel
* @return null|string
*/
private function getAttributeOptionValueByOptionLabel(string $attributeCode, string $optionLabel): ?string
{
/** @var Attribute $attribute */
$attribute = $this->productAttributeRepository->get($attributeCode);

return $attribute->getSource()->getOptionId($optionLabel);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\CatalogSearch\Controller\Result;

use Magento\TestFramework\TestCase\AbstractController;

/**
* Test cases for catalog quick search using mysql search engine.
*
* @magentoDbIsolation disabled
* @magentoAppIsolation enabled
*/
class IndexTest extends AbstractController
{
/**
* Quick search test by difference product attributes.
*
* @magentoConfigFixture default/catalog/search/engine mysql
* @magentoAppArea frontend
* @magentoDataFixture Magento/CatalogSearch/_files/product_for_search.php
* @magentoDataFixture Magento/CatalogSearch/_files/full_reindex.php
* @dataProvider searchStringDataProvider
*
* @param string $searchString
* @return void
*/
public function testExecute(string $searchString): void
{
$this->getRequest()->setParam('q', $searchString);
$this->dispatch('catalogsearch/result');
$responseBody = $this->getResponse()->getBody();
$this->assertContains('Simple product name', $responseBody);
}

/**
* Data provider with strings for quick search.
*
* @return array
*/
public function searchStringDataProvider(): array
{
return [
'search_product_by_name' => ['Simple product name'],
'search_product_by_sku' => ['simple_for_search'],
'search_product_by_description' => ['Product description'],
'search_product_by_short_description' => ['Product short description'],
'search_product_by_custom_attribute' => ['Option 1'],
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,71 +7,84 @@

namespace Magento\CatalogSearch\Model\Indexer\Fulltext\Action;

use Magento\Catalog\Model\Product;
use Magento\Catalog\Model\ProductRepository as ProductRepository;
use Magento\CatalogSearch\Model\Indexer\Fulltext;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Framework\Api\Search\Document as SearchDocument;
use Magento\Framework\Indexer\IndexerRegistry;
use Magento\Framework\Search\AdapterInterface as AdapterInterface;
use Magento\Framework\Search\Request\Builder as SearchRequestBuilder;
use Magento\Framework\Search\Request\Config as SearchRequestConfig;
use Magento\Search\Model\AdapterFactory as AdapterFactory;
use Magento\TestFramework\Helper\Bootstrap;
use Magento\TestFramework\ObjectManager;
use PHPUnit\Framework\TestCase;

class DataProviderTest extends \PHPUnit\Framework\TestCase
/**
* Search products by attribute value using mysql search engine.
*/
class DataProviderTest extends TestCase
{
/**
* @var ObjectManager
*/
private $objectManager;

/**
* @var SearchRequestConfig
*/
private $searchRequestConfig;

/**
* @var SearchRequestBuilder
*/
private $requestBuilder;

/**
* @var AdapterFactory
*/
private $adapterFactory;

/**
* @var ProductRepositoryInterface
*/
private $productRepository;

/**
* @inheritdoc
*/
public static function setUpBeforeClass()
protected function setUp()
{
/*
* Due to insufficient search engine isolation for Elasticsearch, this class must explicitly perform
* a fulltext reindex prior to running its tests.
*
* This should be removed upon completing MC-19455.
*/
$indexRegistry = Bootstrap::getObjectManager()->get(IndexerRegistry::class);
$fulltextIndexer = $indexRegistry->get(Fulltext::INDEXER_ID);
$fulltextIndexer->reindexAll();
$this->objectManager = Bootstrap::getObjectManager();
$this->searchRequestConfig = $this->objectManager->create(SearchRequestConfig::class);
$this->requestBuilder = $this->objectManager->create(
SearchRequestBuilder::class,
['config' => $this->searchRequestConfig]
);
$this->adapterFactory = $this->objectManager->get(AdapterFactory::class);
$this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class);
parent::setUp();
}

/**
* Search product by custom attribute value.
*
* @magentoConfigFixture default/catalog/search/engine mysql
* @magentoDataFixture Magento/CatalogSearch/_files/product_for_search.php
* @magentoDataFixture Magento/CatalogSearch/_files/full_reindex.php
* @magentoDbIsolation disabled
*
* @return void
*/
public function testSearchProductByAttribute()
public function testSearchProductByAttribute(): void
{
/** @var ObjectManager $objectManager */
$objectManager = Bootstrap::getObjectManager();

/** @var SearchRequestConfig $config */
$config = $objectManager->create(SearchRequestConfig::class);

/** @var SearchRequestBuilder $requestBuilder */
$requestBuilder = $objectManager->create(
SearchRequestBuilder::class,
['config' => $config]
);

$requestBuilder->bind('search_term', 'VALUE1');
$requestBuilder->setRequestName('quick_search_container');
$queryRequest = $requestBuilder->create();

/** @var AdapterInterface $adapter */
$adapterFactory = $objectManager->create(AdapterFactory::class);
$adapter = $adapterFactory->create();
$this->requestBuilder->bind('search_term', 'Option 1');
$this->requestBuilder->setRequestName('quick_search_container');
$queryRequest = $this->requestBuilder->create();
$adapter = $this->adapterFactory->create();
$queryResponse = $adapter->query($queryRequest);
$actualIds = [];

/** @var SearchDocument $document */
foreach ($queryResponse as $document) {
/** @var SearchDocument $document */
$actualIds[] = $document->getId();
}

/** @var Product $product */
$product = $objectManager->create(ProductRepository::class)->get('simple');
$product = $this->productRepository->get('simple_for_search');
$this->assertContains($product->getId(), $actualIds, 'Product not found by searchable attribute.');
}
}
Loading

0 comments on commit b411223

Please sign in to comment.