Skip to content

Commit b411223

Browse files
committed
MC-25069: Quick/Advanced Search on storefront by product attributes
1 parent ad6c093 commit b411223

File tree

13 files changed

+888
-208
lines changed

13 files changed

+888
-208
lines changed
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\CatalogSearch\Controller\Advanced;
9+
10+
use Magento\Catalog\Api\ProductAttributeRepositoryInterface;
11+
use Magento\Catalog\Model\ResourceModel\Eav\Attribute;
12+
use Magento\TestFramework\TestCase\AbstractController;
13+
use Zend\Stdlib\Parameters;
14+
15+
/**
16+
* Test cases for catalog advanced search using mysql search engine.
17+
*
18+
* @magentoDbIsolation disabled
19+
* @magentoAppIsolation enabled
20+
*/
21+
class ResultTest extends AbstractController
22+
{
23+
/**
24+
* @var ProductAttributeRepositoryInterface
25+
*/
26+
private $productAttributeRepository;
27+
28+
/**
29+
* @inheritdoc
30+
*/
31+
protected function setUp()
32+
{
33+
parent::setUp();
34+
$this->productAttributeRepository = $this->_objectManager->create(ProductAttributeRepositoryInterface::class);
35+
}
36+
37+
/**
38+
* Advanced search test by difference product attributes.
39+
*
40+
* @magentoConfigFixture default/catalog/search/engine mysql
41+
* @magentoAppArea frontend
42+
* @magentoDataFixture Magento/CatalogSearch/_files/product_for_search.php
43+
* @magentoDataFixture Magento/CatalogSearch/_files/full_reindex.php
44+
* @dataProvider searchStringDataProvider
45+
*
46+
* @param array $searchParams
47+
* @return void
48+
*/
49+
public function testExecute(array $searchParams): void
50+
{
51+
if ('' !== $searchParams['test_searchable_attribute']) {
52+
$searchParams['test_searchable_attribute'] = $this->getAttributeOptionValueByOptionLabel(
53+
'test_searchable_attribute',
54+
$searchParams['test_searchable_attribute']
55+
);
56+
}
57+
58+
$this->getRequest()->setQuery(
59+
$this->_objectManager->create(
60+
Parameters::class,
61+
[
62+
'values' => $searchParams
63+
]
64+
)
65+
);
66+
$this->dispatch('catalogsearch/advanced/result');
67+
$responseBody = $this->getResponse()->getBody();
68+
$this->assertContains('Simple product name', $responseBody);
69+
}
70+
71+
/**
72+
* Data provider with strings for quick search.
73+
*
74+
* @return array
75+
*/
76+
public function searchStringDataProvider(): array
77+
{
78+
return [
79+
'search_product_by_name' => [
80+
[
81+
'name' => 'Simple product name',
82+
'sku' => '',
83+
'description' => '',
84+
'short_description' => '',
85+
'price' => [
86+
'from' => '',
87+
'to' => '',
88+
],
89+
'test_searchable_attribute' => '',
90+
],
91+
],
92+
'search_product_by_sku' => [
93+
[
94+
'name' => '',
95+
'sku' => 'simple_for_search',
96+
'description' => '',
97+
'short_description' => '',
98+
'price' => [
99+
'from' => '',
100+
'to' => '',
101+
],
102+
'test_searchable_attribute' => '',
103+
],
104+
],
105+
'search_product_by_description' => [
106+
[
107+
'name' => '',
108+
'sku' => '',
109+
'description' => 'Product description',
110+
'short_description' => '',
111+
'price' => [
112+
'from' => '',
113+
'to' => '',
114+
],
115+
'test_searchable_attribute' => '',
116+
],
117+
],
118+
'search_product_by_short_description' => [
119+
[
120+
'name' => '',
121+
'sku' => '',
122+
'description' => '',
123+
'short_description' => 'Product short description',
124+
'price' => [
125+
'from' => '',
126+
'to' => '',
127+
],
128+
'test_searchable_attribute' => '',
129+
],
130+
],
131+
'search_product_by_price_range' => [
132+
[
133+
'name' => '',
134+
'sku' => '',
135+
'description' => '',
136+
'short_description' => '',
137+
'price' => [
138+
'from' => '50',
139+
'to' => '150',
140+
],
141+
'test_searchable_attribute' => '',
142+
],
143+
],
144+
'search_product_by_custom_attribute' => [
145+
[
146+
'name' => '',
147+
'sku' => '',
148+
'description' => '',
149+
'short_description' => '',
150+
'price' => [
151+
'from' => '',
152+
'to' => '',
153+
],
154+
'test_searchable_attribute' => 'Option 1',
155+
],
156+
],
157+
];
158+
}
159+
160+
/**
161+
* Return attribute option value by option label.
162+
*
163+
* @param string $attributeCode
164+
* @param string $optionLabel
165+
* @return null|string
166+
*/
167+
private function getAttributeOptionValueByOptionLabel(string $attributeCode, string $optionLabel): ?string
168+
{
169+
/** @var Attribute $attribute */
170+
$attribute = $this->productAttributeRepository->get($attributeCode);
171+
172+
return $attribute->getSource()->getOptionId($optionLabel);
173+
}
174+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\CatalogSearch\Controller\Result;
9+
10+
use Magento\TestFramework\TestCase\AbstractController;
11+
12+
/**
13+
* Test cases for catalog quick search using mysql search engine.
14+
*
15+
* @magentoDbIsolation disabled
16+
* @magentoAppIsolation enabled
17+
*/
18+
class IndexTest extends AbstractController
19+
{
20+
/**
21+
* Quick search test by difference product attributes.
22+
*
23+
* @magentoConfigFixture default/catalog/search/engine mysql
24+
* @magentoAppArea frontend
25+
* @magentoDataFixture Magento/CatalogSearch/_files/product_for_search.php
26+
* @magentoDataFixture Magento/CatalogSearch/_files/full_reindex.php
27+
* @dataProvider searchStringDataProvider
28+
*
29+
* @param string $searchString
30+
* @return void
31+
*/
32+
public function testExecute(string $searchString): void
33+
{
34+
$this->getRequest()->setParam('q', $searchString);
35+
$this->dispatch('catalogsearch/result');
36+
$responseBody = $this->getResponse()->getBody();
37+
$this->assertContains('Simple product name', $responseBody);
38+
}
39+
40+
/**
41+
* Data provider with strings for quick search.
42+
*
43+
* @return array
44+
*/
45+
public function searchStringDataProvider(): array
46+
{
47+
return [
48+
'search_product_by_name' => ['Simple product name'],
49+
'search_product_by_sku' => ['simple_for_search'],
50+
'search_product_by_description' => ['Product description'],
51+
'search_product_by_short_description' => ['Product short description'],
52+
'search_product_by_custom_attribute' => ['Option 1'],
53+
];
54+
}
55+
}

dev/tests/integration/testsuite/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/DataProviderTest.php

Lines changed: 54 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -7,71 +7,84 @@
77

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

10-
use Magento\Catalog\Model\Product;
11-
use Magento\Catalog\Model\ProductRepository as ProductRepository;
12-
use Magento\CatalogSearch\Model\Indexer\Fulltext;
10+
use Magento\Catalog\Api\ProductRepositoryInterface;
1311
use Magento\Framework\Api\Search\Document as SearchDocument;
14-
use Magento\Framework\Indexer\IndexerRegistry;
15-
use Magento\Framework\Search\AdapterInterface as AdapterInterface;
1612
use Magento\Framework\Search\Request\Builder as SearchRequestBuilder;
1713
use Magento\Framework\Search\Request\Config as SearchRequestConfig;
1814
use Magento\Search\Model\AdapterFactory as AdapterFactory;
1915
use Magento\TestFramework\Helper\Bootstrap;
2016
use Magento\TestFramework\ObjectManager;
17+
use PHPUnit\Framework\TestCase;
2118

22-
class DataProviderTest extends \PHPUnit\Framework\TestCase
19+
/**
20+
* Search products by attribute value using mysql search engine.
21+
*/
22+
class DataProviderTest extends TestCase
2323
{
24+
/**
25+
* @var ObjectManager
26+
*/
27+
private $objectManager;
28+
29+
/**
30+
* @var SearchRequestConfig
31+
*/
32+
private $searchRequestConfig;
33+
34+
/**
35+
* @var SearchRequestBuilder
36+
*/
37+
private $requestBuilder;
38+
39+
/**
40+
* @var AdapterFactory
41+
*/
42+
private $adapterFactory;
43+
44+
/**
45+
* @var ProductRepositoryInterface
46+
*/
47+
private $productRepository;
48+
2449
/**
2550
* @inheritdoc
2651
*/
27-
public static function setUpBeforeClass()
52+
protected function setUp()
2853
{
29-
/*
30-
* Due to insufficient search engine isolation for Elasticsearch, this class must explicitly perform
31-
* a fulltext reindex prior to running its tests.
32-
*
33-
* This should be removed upon completing MC-19455.
34-
*/
35-
$indexRegistry = Bootstrap::getObjectManager()->get(IndexerRegistry::class);
36-
$fulltextIndexer = $indexRegistry->get(Fulltext::INDEXER_ID);
37-
$fulltextIndexer->reindexAll();
54+
$this->objectManager = Bootstrap::getObjectManager();
55+
$this->searchRequestConfig = $this->objectManager->create(SearchRequestConfig::class);
56+
$this->requestBuilder = $this->objectManager->create(
57+
SearchRequestBuilder::class,
58+
['config' => $this->searchRequestConfig]
59+
);
60+
$this->adapterFactory = $this->objectManager->get(AdapterFactory::class);
61+
$this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class);
62+
parent::setUp();
3863
}
3964

4065
/**
66+
* Search product by custom attribute value.
67+
*
68+
* @magentoConfigFixture default/catalog/search/engine mysql
4169
* @magentoDataFixture Magento/CatalogSearch/_files/product_for_search.php
70+
* @magentoDataFixture Magento/CatalogSearch/_files/full_reindex.php
4271
* @magentoDbIsolation disabled
72+
*
73+
* @return void
4374
*/
44-
public function testSearchProductByAttribute()
75+
public function testSearchProductByAttribute(): void
4576
{
46-
/** @var ObjectManager $objectManager */
47-
$objectManager = Bootstrap::getObjectManager();
48-
49-
/** @var SearchRequestConfig $config */
50-
$config = $objectManager->create(SearchRequestConfig::class);
51-
52-
/** @var SearchRequestBuilder $requestBuilder */
53-
$requestBuilder = $objectManager->create(
54-
SearchRequestBuilder::class,
55-
['config' => $config]
56-
);
57-
58-
$requestBuilder->bind('search_term', 'VALUE1');
59-
$requestBuilder->setRequestName('quick_search_container');
60-
$queryRequest = $requestBuilder->create();
61-
62-
/** @var AdapterInterface $adapter */
63-
$adapterFactory = $objectManager->create(AdapterFactory::class);
64-
$adapter = $adapterFactory->create();
77+
$this->requestBuilder->bind('search_term', 'Option 1');
78+
$this->requestBuilder->setRequestName('quick_search_container');
79+
$queryRequest = $this->requestBuilder->create();
80+
$adapter = $this->adapterFactory->create();
6581
$queryResponse = $adapter->query($queryRequest);
6682
$actualIds = [];
67-
83+
/** @var SearchDocument $document */
6884
foreach ($queryResponse as $document) {
69-
/** @var SearchDocument $document */
7085
$actualIds[] = $document->getId();
7186
}
72-
73-
/** @var Product $product */
74-
$product = $objectManager->create(ProductRepository::class)->get('simple');
87+
$product = $this->productRepository->get('simple_for_search');
7588
$this->assertContains($product->getId(), $actualIds, 'Product not found by searchable attribute.');
7689
}
7790
}

0 commit comments

Comments
 (0)