713 lines
26 KiB
PHP
Executable File
713 lines
26 KiB
PHP
Executable File
<?php
|
|
/**
|
|
* Copyright © Magento, Inc. All rights reserved.
|
|
* See COPYING.txt for license details.
|
|
*/
|
|
namespace Magento\Elasticsearch\SearchAdapter;
|
|
|
|
use Magento\Catalog\Model\Product;
|
|
use Magento\Catalog\Model\ResourceModel\Eav\Attribute;
|
|
use Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\Collection;
|
|
use Magento\Framework\Search\EngineResolverInterface;
|
|
use Magento\TestFramework\Helper\Bootstrap;
|
|
use Magento\TestModuleCatalogSearch\Model\SearchEngineVersionReader;
|
|
|
|
/**
|
|
* Class AdapterTest
|
|
*
|
|
* @magentoDbIsolation disabled
|
|
* @magentoDataFixture Magento/Framework/Search/_files/products.php
|
|
*
|
|
* Important: Please make sure that each integration test file works with unique elastic 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 adaptertest'
|
|
*
|
|
* In ElasticSearch, a reindex is required if the test includes a new data fixture with new items to search, see
|
|
* testAdvancedSearchDateField().
|
|
* phpstan:ignore
|
|
*
|
|
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
|
*/
|
|
class AdapterTest extends \PHPUnit\Framework\TestCase
|
|
{
|
|
/**
|
|
* @var \Magento\Framework\Search\AdapterInterface
|
|
*/
|
|
private $adapter;
|
|
|
|
/**
|
|
* @var \Magento\Framework\Search\Request\Builder
|
|
*/
|
|
private $requestBuilder;
|
|
|
|
/**
|
|
* @var \Magento\Framework\ObjectManagerInterface
|
|
*/
|
|
private $objectManager;
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
protected function setUp(): void
|
|
{
|
|
$this->objectManager = Bootstrap::getObjectManager();
|
|
|
|
/** @var \Magento\Framework\Search\Request\Config\Converter $converter */
|
|
$converter = $this->objectManager->create(\Magento\Framework\Search\Request\Config\Converter::class);
|
|
|
|
$document = new \DOMDocument();
|
|
$document->load($this->getRequestConfigPath());
|
|
$requestConfig = $converter->convert($document);
|
|
|
|
/** @var \Magento\Framework\Search\Request\Config $config */
|
|
$config = $this->objectManager->create(\Magento\Framework\Search\Request\Config::class);
|
|
$config->merge($requestConfig);
|
|
|
|
$this->requestBuilder = $this->objectManager->create(
|
|
\Magento\Framework\Search\Request\Builder::class,
|
|
['config' => $config]
|
|
);
|
|
|
|
$this->adapter = $this->createAdapter();
|
|
|
|
$indexer = $this->objectManager->create(\Magento\Indexer\Model\Indexer::class);
|
|
$indexer->load('catalogsearch_fulltext');
|
|
$indexer->reindexAll();
|
|
}
|
|
|
|
/**
|
|
* Get request config path
|
|
*
|
|
* @return string
|
|
*/
|
|
protected function getRequestConfigPath()
|
|
{
|
|
return __DIR__ . '/../_files/requests.xml';
|
|
}
|
|
|
|
/**
|
|
* @return \Magento\Framework\Search\AdapterInterface
|
|
*/
|
|
protected function createAdapter()
|
|
{
|
|
return $this->objectManager->create(\Magento\Search\Model\AdapterFactory::class)->create();
|
|
}
|
|
|
|
/**
|
|
* Make sure that correct engine is set
|
|
*/
|
|
protected function assertPreConditions(): void
|
|
{
|
|
$currentEngine = $this->objectManager->get(EngineResolverInterface::class)->getCurrentSearchEngine();
|
|
$installedEngine = $this->objectManager->get(SearchEngineVersionReader::class)->getFullVersion();
|
|
$this->assertEquals(
|
|
$installedEngine,
|
|
$currentEngine,
|
|
sprintf(
|
|
'Search engine configuration "%s" is not compatible with the installed version',
|
|
$currentEngine
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @return \Magento\Framework\Search\Response\QueryResponse
|
|
*/
|
|
private function executeQuery()
|
|
{
|
|
/** @var \Magento\Framework\Search\RequestInterface $queryRequest */
|
|
$queryRequest = $this->requestBuilder->create();
|
|
|
|
$queryResponse = $this->adapter->query($queryRequest);
|
|
|
|
return $queryResponse;
|
|
}
|
|
|
|
/**
|
|
* @magentoAppIsolation enabled
|
|
* phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod
|
|
*/
|
|
public function testMatchQuery()
|
|
{
|
|
$this->requestBuilder->bind('fulltext_search_query', 'socks');
|
|
$this->requestBuilder->setRequestName('one_match');
|
|
|
|
$queryResponse = $this->executeQuery();
|
|
|
|
$this->assertEquals(1, $queryResponse->count());
|
|
}
|
|
|
|
/**
|
|
* @magentoAppIsolation enabled
|
|
*/
|
|
public function testMatchOrderedQuery()
|
|
{
|
|
$this->markTestSkipped(
|
|
'Elasticsearch not expected to order results by default. Test is skipped intentionally.'
|
|
);
|
|
$expectedIds = [8, 7, 6, 5, 2];
|
|
|
|
//Verify that MySql randomized result of equal-weighted results
|
|
//consistently ordered by entity_id after multiple calls
|
|
$this->requestBuilder->bind('fulltext_search_query', 'shorts');
|
|
$this->requestBuilder->setRequestName('one_match');
|
|
$queryResponse = $this->executeQuery();
|
|
|
|
$this->assertEquals(5, $queryResponse->count());
|
|
$this->assertOrderedProductIds($queryResponse, $expectedIds);
|
|
}
|
|
|
|
/**
|
|
* @param \Magento\Framework\Search\Response\QueryResponse $queryResponse
|
|
* @param array $expectedIds
|
|
*/
|
|
private function assertOrderedProductIds($queryResponse, $expectedIds)
|
|
{
|
|
$actualIds = [];
|
|
foreach ($queryResponse as $document) {
|
|
/** @var \Magento\Framework\Api\Search\Document $document */
|
|
$actualIds[] = $document->getId();
|
|
}
|
|
$this->assertEquals($expectedIds, $actualIds);
|
|
}
|
|
|
|
/**
|
|
* @magentoAppIsolation enabled
|
|
* phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod
|
|
*/
|
|
public function testMatchQueryFilters()
|
|
{
|
|
$this->requestBuilder->bind('fulltext_search_query', 'socks');
|
|
$this->requestBuilder->bind('pidm_from', 11);
|
|
$this->requestBuilder->bind('pidm_to', 17);
|
|
$this->requestBuilder->bind('pidsh', 18);
|
|
$this->requestBuilder->setRequestName('one_match_filters');
|
|
|
|
$queryResponse = $this->executeQuery();
|
|
$this->assertEquals(1, $queryResponse->count());
|
|
}
|
|
|
|
/**
|
|
* Range filter test with all fields filled
|
|
*
|
|
* @magentoAppIsolation enabled
|
|
* phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod
|
|
*/
|
|
public function testRangeFilterWithAllFields()
|
|
{
|
|
$this->requestBuilder->bind('range_filter_from', 11);
|
|
$this->requestBuilder->bind('range_filter_to', 17);
|
|
$this->requestBuilder->setRequestName('range_filter');
|
|
|
|
$queryResponse = $this->executeQuery();
|
|
$this->assertEquals(3, $queryResponse->count());
|
|
}
|
|
|
|
/**
|
|
* Range filter test with all fields filled
|
|
*
|
|
* @magentoAppIsolation enabled
|
|
* phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod
|
|
*/
|
|
public function testRangeFilterWithoutFromField()
|
|
{
|
|
$this->requestBuilder->bind('range_filter_to', 18);
|
|
$this->requestBuilder->setRequestName('range_filter_without_from_field');
|
|
|
|
$queryResponse = $this->executeQuery();
|
|
$this->assertEquals(4, $queryResponse->count());
|
|
}
|
|
|
|
/**
|
|
* Range filter test with all fields filled
|
|
*
|
|
* @magentoAppIsolation enabled
|
|
* phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod
|
|
*/
|
|
public function testRangeFilterWithoutToField()
|
|
{
|
|
$this->requestBuilder->bind('range_filter_from', 14);
|
|
$this->requestBuilder->setRequestName('range_filter_without_to_field');
|
|
|
|
$queryResponse = $this->executeQuery();
|
|
$this->assertEquals(4, $queryResponse->count());
|
|
}
|
|
|
|
/**
|
|
* Term filter test
|
|
*
|
|
* @magentoAppIsolation enabled
|
|
* phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod
|
|
*/
|
|
public function testTermFilter()
|
|
{
|
|
$this->requestBuilder->bind('request.price', 18);
|
|
$this->requestBuilder->setRequestName('term_filter');
|
|
|
|
$queryResponse = $this->executeQuery();
|
|
$this->assertEquals(1, $queryResponse->count());
|
|
$this->assertEquals(4, $queryResponse->getIterator()->offsetGet(0)->getId());
|
|
}
|
|
|
|
/**
|
|
* Term filter test
|
|
*
|
|
* @magentoAppIsolation enabled
|
|
* phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod
|
|
*/
|
|
public function testTermFilterArray()
|
|
{
|
|
$this->requestBuilder->bind('request.price', [17, 18]);
|
|
$this->requestBuilder->setRequestName('term_filter');
|
|
|
|
$queryResponse = $this->executeQuery();
|
|
$this->assertEquals(2, $queryResponse->count());
|
|
}
|
|
|
|
/**
|
|
* @param \Magento\Framework\Search\Response\QueryResponse $queryResponse
|
|
* @param array $expectedIds
|
|
*/
|
|
private function assertProductIds($queryResponse, $expectedIds)
|
|
{
|
|
$actualIds = [];
|
|
foreach ($queryResponse as $document) {
|
|
/** @var \Magento\Framework\Api\Search\Document $document */
|
|
$actualIds[] = $document->getId();
|
|
}
|
|
sort($actualIds);
|
|
sort($expectedIds);
|
|
$this->assertEquals($expectedIds, $actualIds);
|
|
}
|
|
|
|
/**
|
|
* Term filter test
|
|
*
|
|
* @magentoAppIsolation enabled
|
|
* phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod
|
|
*/
|
|
public function testWildcardFilter()
|
|
{
|
|
$expectedIds = [1, 3, 5];
|
|
$this->requestBuilder->bind('wildcard_filter', 're');
|
|
$this->requestBuilder->setRequestName('one_wildcard');
|
|
|
|
$queryResponse = $this->executeQuery();
|
|
$this->assertEquals(3, $queryResponse->count());
|
|
$this->assertProductIds($queryResponse, $expectedIds);
|
|
}
|
|
|
|
/**
|
|
* Request limits test
|
|
*
|
|
* @magentoAppIsolation enabled
|
|
* phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod
|
|
*/
|
|
public function testSearchLimit()
|
|
{
|
|
$this->requestBuilder->bind('wildcard_filter', 're');
|
|
$this->requestBuilder->setFrom(1);
|
|
$this->requestBuilder->setSize(2);
|
|
$this->requestBuilder->setRequestName('one_wildcard');
|
|
|
|
$queryResponse = $this->executeQuery();
|
|
$this->assertEquals(2, $queryResponse->count());
|
|
}
|
|
|
|
/**
|
|
* Bool filter test
|
|
*
|
|
* @magentoAppIsolation enabled
|
|
* phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod
|
|
*/
|
|
public function testBoolFilter()
|
|
{
|
|
$expectedIds = [2, 3];
|
|
$this->requestBuilder->bind('must_range_filter1_from', 13);
|
|
$this->requestBuilder->bind('must_range_filter1_to', 22);
|
|
$this->requestBuilder->bind('should_term_filter1', 13);
|
|
$this->requestBuilder->bind('should_term_filter2', 15);
|
|
$this->requestBuilder->bind('should_term_filter3', 17);
|
|
$this->requestBuilder->bind('should_term_filter4', 18);
|
|
$this->requestBuilder->bind('not_term_filter1', 13);
|
|
$this->requestBuilder->bind('not_term_filter2', 18);
|
|
$this->requestBuilder->setRequestName('bool_filter');
|
|
|
|
$queryResponse = $this->executeQuery();
|
|
$this->assertEquals(count($expectedIds), $queryResponse->count());
|
|
$this->assertProductIds($queryResponse, $expectedIds);
|
|
}
|
|
|
|
/**
|
|
* Test bool filter with nested negative bool filter
|
|
*
|
|
* @magentoAppIsolation enabled
|
|
* phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod
|
|
*/
|
|
public function testBoolFilterWithNestedNegativeBoolFilter()
|
|
{
|
|
$expectedIds = [1];
|
|
$this->requestBuilder->bind('not_range_filter_from', 14);
|
|
$this->requestBuilder->bind('not_range_filter_to', 20);
|
|
$this->requestBuilder->bind('nested_not_term_filter', 13);
|
|
$this->requestBuilder->setRequestName('bool_filter_with_nested_bool_filter');
|
|
|
|
$queryResponse = $this->executeQuery();
|
|
$this->assertEquals(count($expectedIds), $queryResponse->count());
|
|
$this->assertProductIds($queryResponse, $expectedIds);
|
|
}
|
|
|
|
/**
|
|
* Test range inside nested negative bool filter
|
|
*
|
|
* @magentoAppIsolation enabled
|
|
* phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod
|
|
*/
|
|
public function testBoolFilterWithNestedRangeInNegativeBoolFilter()
|
|
{
|
|
$expectedIds = [1, 5];
|
|
$this->requestBuilder->bind('nested_must_range_filter_from', 14);
|
|
$this->requestBuilder->bind('nested_must_range_filter_to', 18);
|
|
$this->requestBuilder->setRequestName('bool_filter_with_range_in_nested_negative_filter');
|
|
|
|
$queryResponse = $this->executeQuery();
|
|
$this->assertEquals(count($expectedIds), $queryResponse->count());
|
|
$this->assertProductIds($queryResponse, $expectedIds);
|
|
}
|
|
|
|
/**
|
|
* Sample Advanced search request test
|
|
*
|
|
* @dataProvider elasticSearchAdvancedSearchDataProvider
|
|
* @magentoAppIsolation enabled
|
|
* @param string $nameQuery
|
|
* @param string $descriptionQuery
|
|
* @param array $rangeFilter
|
|
* @param int $expectedRecordsCount
|
|
* phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod
|
|
*/
|
|
public function testSimpleAdvancedSearch(
|
|
$nameQuery,
|
|
$descriptionQuery,
|
|
$rangeFilter,
|
|
$expectedRecordsCount
|
|
) {
|
|
$this->requestBuilder->bind('name_query', $nameQuery);
|
|
$this->requestBuilder->bind('description_query', $descriptionQuery);
|
|
$this->requestBuilder->bind('request.from_price', $rangeFilter['from']);
|
|
$this->requestBuilder->bind('request.to_price', $rangeFilter['to']);
|
|
$this->requestBuilder->setRequestName('advanced_search_test');
|
|
|
|
$queryResponse = $this->executeQuery();
|
|
$this->assertEquals($expectedRecordsCount, $queryResponse->count());
|
|
}
|
|
|
|
/**
|
|
* Elastic Search specific data provider for advanced search test.
|
|
*
|
|
* The expected array is for Elastic Search is different that the one for MySQL
|
|
* because sometimes more matches are returned. For instance, 3rd index below
|
|
* will return 3 matches instead of 1 (which is what MySQL returns).
|
|
*
|
|
* @return array
|
|
*/
|
|
public function elasticSearchAdvancedSearchDataProvider()
|
|
{
|
|
return [
|
|
['white', 'shorts', ['from' => '16', 'to' => '18'], 0],
|
|
['white', 'shorts',['from' => '12', 'to' => '18'], 1],
|
|
['black', 'tshirts', ['from' => '12', 'to' => '20'], 0],
|
|
['shorts', 'green', ['from' => '12', 'to' => '22'], 3],
|
|
//Search with empty fields/values
|
|
['white', ' ', ['from' => '12', 'to' => '22'], 1],
|
|
[' ', 'green', ['from' => '12', 'to' => '22'], 2]
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @magentoAppIsolation enabled
|
|
* @magentoDataFixture Magento/Framework/Search/_files/filterable_attribute.php
|
|
*/
|
|
public function testCustomFilterableAttribute()
|
|
{
|
|
// Reindex Elastic Search since filterable_attribute data fixture added new fields to be indexed
|
|
$this->reindexAll();
|
|
/** @var Attribute $attribute */
|
|
$attribute = $this->objectManager->get(Attribute::class)
|
|
->loadByCode(Product::ENTITY, 'select_attribute');
|
|
/** @var Collection $selectOptions */
|
|
$selectOptions = $this->objectManager
|
|
->create(Collection::class)
|
|
->setAttributeFilter($attribute->getId());
|
|
|
|
$attribute->loadByCode(Product::ENTITY, 'multiselect_attribute');
|
|
/** @var Collection $multiselectOptions */
|
|
$multiselectOptions = $this->objectManager
|
|
->create(Collection::class)
|
|
->setAttributeFilter($attribute->getId());
|
|
|
|
$this->requestBuilder->bind('select_attribute', $selectOptions->getLastItem()->getId());
|
|
$this->requestBuilder->bind('multiselect_attribute', $multiselectOptions->getLastItem()->getId());
|
|
$this->requestBuilder->bind('price.from', 98);
|
|
$this->requestBuilder->bind('price.to', 100);
|
|
$this->requestBuilder->bind('category_ids', 2);
|
|
$this->requestBuilder->setRequestName('filterable_custom_attributes');
|
|
$queryResponse = $this->executeQuery();
|
|
$this->assertEquals(1, $queryResponse->count());
|
|
}
|
|
|
|
/**
|
|
* Test filtering by two attributes.
|
|
*
|
|
* @magentoAppIsolation enabled
|
|
* @magentoDataFixture Magento/Framework/Search/_files/filterable_attributes.php
|
|
* @dataProvider filterByAttributeValuesDataProvider
|
|
* @param string $requestName
|
|
* @param array $additionalData
|
|
* @return void
|
|
*/
|
|
public function testFilterByAttributeValues($requestName, $additionalData)
|
|
{
|
|
// Reindex Elastic Search since filterable_attribute data fixture added new fields to be indexed
|
|
$this->reindexAll();
|
|
/** @var Attribute $attribute */
|
|
$attribute = $this->objectManager->get(Attribute::class)
|
|
->loadByCode(Product::ENTITY, 'select_attribute_1');
|
|
/** @var Collection $selectOptions1 */
|
|
$selectOptions1 = $this->objectManager
|
|
->create(Collection::class)
|
|
->setAttributeFilter($attribute->getId());
|
|
$attribute->loadByCode(Product::ENTITY, 'select_attribute_2');
|
|
/** @var Collection $selectOptions2 */
|
|
$selectOptions2 = $this->objectManager
|
|
->create(Collection::class)
|
|
->setAttributeFilter($attribute->getId());
|
|
$this->requestBuilder->bind('select_attribute_1', $selectOptions1->getLastItem()->getId());
|
|
$this->requestBuilder->bind('select_attribute_2', $selectOptions2->getLastItem()->getId());
|
|
// Binds for specific containers.
|
|
foreach ($additionalData as $key => $value) {
|
|
$this->requestBuilder->bind($key, $value);
|
|
}
|
|
$this->requestBuilder->setRequestName($requestName);
|
|
$queryResponse = $this->executeQuery();
|
|
$this->assertEquals(1, $queryResponse->count());
|
|
}
|
|
|
|
/**
|
|
* Advanced search request using date product attribute
|
|
*
|
|
* @param $rangeFilter
|
|
* @param $expectedRecordsCount
|
|
* @magentoDataFixture Magento/Framework/Search/_files/date_attribute.php
|
|
* @magentoAppIsolation enabled
|
|
* @dataProvider dateDataProvider
|
|
*/
|
|
public function testAdvancedSearchDateField($rangeFilter, $expectedRecordsCount)
|
|
{
|
|
// Reindex Elastic Search since date_attribute data fixture added new fields to be indexed
|
|
$this->reindexAll();
|
|
$this->requestBuilder->bind('date.from', $rangeFilter['from']);
|
|
$this->requestBuilder->bind('date.to', $rangeFilter['to']);
|
|
$this->requestBuilder->setRequestName('advanced_search_date_field');
|
|
|
|
$queryResponse = $this->executeQuery();
|
|
$this->assertEquals($expectedRecordsCount, $queryResponse->count());
|
|
}
|
|
|
|
/**
|
|
* @magentoDataFixture Magento/Framework/Search/_files/product_configurable.php
|
|
* @magentoAppIsolation enabled
|
|
* phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod
|
|
*/
|
|
public function testAdvancedSearchCompositeProductWithOutOfStockOption()
|
|
{
|
|
/** @var Attribute $attribute */
|
|
$attribute = $this->objectManager->get(Attribute::class)
|
|
->loadByCode(Product::ENTITY, 'test_configurable');
|
|
/** @var Collection $selectOptions */
|
|
$selectOptions = $this->objectManager
|
|
->create(Collection::class)
|
|
->setAttributeFilter($attribute->getId());
|
|
|
|
$visibility = [
|
|
\Magento\Catalog\Model\Product\Visibility::VISIBILITY_IN_SEARCH,
|
|
\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH,
|
|
];
|
|
|
|
$firstOption = $selectOptions->getFirstItem();
|
|
$firstOptionId = $firstOption->getId();
|
|
$this->requestBuilder->bind('test_configurable', $firstOptionId);
|
|
$this->requestBuilder->bind('visibility', $visibility);
|
|
$this->requestBuilder->setRequestName('filter_out_of_stock_child');
|
|
|
|
$queryResponse = $this->executeQuery();
|
|
$this->assertEquals(0, $queryResponse->count());
|
|
|
|
$secondOption = $selectOptions->getLastItem();
|
|
$secondOptionId = $secondOption->getId();
|
|
$this->requestBuilder->bind('test_configurable', $secondOptionId);
|
|
$this->requestBuilder->bind('visibility', $visibility);
|
|
$this->requestBuilder->setRequestName('filter_out_of_stock_child');
|
|
|
|
$queryResponse = $this->executeQuery();
|
|
$this->assertEquals(1, $queryResponse->count());
|
|
}
|
|
|
|
/**
|
|
* @magentoDataFixture Magento/Framework/Search/_files/product_configurable_with_disabled_child.php
|
|
* @magentoAppIsolation enabled
|
|
*/
|
|
public function testAdvancedSearchCompositeProductWithDisabledChild()
|
|
{
|
|
// Reindex Elastic Search since date_attribute data fixture added new fields to be indexed
|
|
$this->reindexAll();
|
|
/** @var Attribute $attribute */
|
|
$attribute = $this->objectManager->get(Attribute::class)
|
|
->loadByCode(Product::ENTITY, 'test_configurable');
|
|
/** @var Collection $selectOptions */
|
|
$selectOptions = $this->objectManager
|
|
->create(Collection::class)
|
|
->setAttributeFilter($attribute->getId());
|
|
|
|
$firstOption = $selectOptions->getFirstItem();
|
|
$firstOptionId = $firstOption->getId();
|
|
$this->requestBuilder->bind('test_configurable', $firstOptionId);
|
|
$this->requestBuilder->setRequestName('filter_out_of_stock_child');
|
|
|
|
$queryResponse = $this->executeQuery();
|
|
$this->assertEquals(0, $queryResponse->count());
|
|
|
|
$secondOption = $selectOptions->getLastItem();
|
|
$secondOptionId = $secondOption->getId();
|
|
$this->requestBuilder->bind('test_configurable', $secondOptionId);
|
|
$this->requestBuilder->setRequestName('filter_out_of_stock_child');
|
|
|
|
$queryResponse = $this->executeQuery();
|
|
$this->assertEquals(0, $queryResponse->count());
|
|
}
|
|
|
|
/**
|
|
* @magentoDataFixture Magento/Framework/Search/_files/search_weight_products.php
|
|
* @magentoAppIsolation enabled
|
|
*/
|
|
public function testSearchQueryBoost()
|
|
{
|
|
// Reindex Elastic Search since date_attribute data fixture added new fields to be indexed
|
|
$this->reindexAll();
|
|
$this->requestBuilder->bind('query', 'antarctica');
|
|
$this->requestBuilder->setRequestName('search_boost');
|
|
$queryResponse = $this->executeQuery();
|
|
$this->assertEquals(2, $queryResponse->count());
|
|
|
|
/** @var \Magento\Framework\Api\Search\DocumentInterface $products */
|
|
$products = iterator_to_array($queryResponse);
|
|
/*
|
|
* Products now contain search query in two attributes which are boosted with the same value: 1
|
|
* The search keyword (antarctica) is mentioned twice only in one of the products.
|
|
* And, as both attributes have the same search weight and boost, we expect that
|
|
* the product with doubled keyword should be prioritized by a search engine as a most relevant
|
|
* and therefore will be first in the search result.
|
|
*/
|
|
$firstProduct = reset($products);
|
|
$this->assertEquals(1222, $firstProduct->getId());
|
|
$secondProduct = end($products);
|
|
$this->assertEquals(1221, $secondProduct->getId());
|
|
|
|
/** @var \Magento\Catalog\Api\ProductAttributeRepositoryInterface $productAttributeRepository */
|
|
$productAttributeRepository = $this->objectManager->get(
|
|
\Magento\Catalog\Api\ProductAttributeRepositoryInterface::class
|
|
);
|
|
|
|
/**
|
|
* Now we're going to change search weight of one of the attributes to ensure that it will affect
|
|
* how products are ordered in the search result
|
|
*/
|
|
/** @var Attribute $attribute */
|
|
$attribute = $productAttributeRepository->get('name');
|
|
$attribute->setSearchWeight(20);
|
|
$productAttributeRepository->save($attribute);
|
|
|
|
$this->requestBuilder->bind('query', 'antarctica');
|
|
$this->requestBuilder->setRequestName('search_boost_name');
|
|
$queryResponse = $this->executeQuery();
|
|
$this->assertEquals(2, $queryResponse->count());
|
|
|
|
/** @var \Magento\Framework\Api\Search\DocumentInterface $products */
|
|
$products = iterator_to_array($queryResponse);
|
|
/*
|
|
* As for the first case, we have two the same products.
|
|
* One of them has search keyword mentioned twice in the field which has search weight 1.
|
|
* However, we've changed the search weight of another attribute
|
|
* which has only one mention of the search keyword in another product.
|
|
*
|
|
* The case is mostly the same but search weight has been changed and we expect that
|
|
* less relevant (with only one mention) but more boosted (search weight = 20) product
|
|
* will be prioritized higher than more relevant, but less boosted product.
|
|
*/
|
|
$firstProduct = reset($products);
|
|
$this->assertEquals(1221, $firstProduct->getId());
|
|
//$firstProduct
|
|
$secondProduct = end($products);
|
|
$this->assertEquals(1222, $secondProduct->getId());
|
|
}
|
|
|
|
/**
|
|
* Perform full reindex
|
|
*
|
|
* @return void
|
|
*/
|
|
private function reindexAll()
|
|
{
|
|
$indexer = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
|
|
\Magento\Indexer\Model\Indexer::class
|
|
);
|
|
$indexer->load('catalogsearch_fulltext');
|
|
$indexer->reindexAll();
|
|
}
|
|
|
|
/**
|
|
* Date data provider
|
|
*
|
|
* @return array
|
|
*/
|
|
public function dateDataProvider()
|
|
{
|
|
return [
|
|
[['from' => '1999-12-31T00:00:00Z', 'to' => '2000-01-01T00:00:00Z'], 1],
|
|
[['from' => '2000-02-01T00:00:00Z', 'to' => ''], 0],
|
|
];
|
|
}
|
|
|
|
public function filterByAttributeValuesDataProvider()
|
|
{
|
|
return [
|
|
'quick_search_container' => [
|
|
'quick_search_container',
|
|
[
|
|
// Make sure search uses "should" cause.
|
|
'search_term' => 'Simple Product',
|
|
],
|
|
],
|
|
'advanced_search_container' => [
|
|
'advanced_search_container',
|
|
[
|
|
// Make sure "wildcard" feature works.
|
|
'sku' => 'simple_product',
|
|
]
|
|
],
|
|
'catalog_view_container' => [
|
|
'catalog_view_container',
|
|
[
|
|
'category_ids' => 2
|
|
]
|
|
],
|
|
'quick search by date' => [
|
|
'quick_search_container',
|
|
[
|
|
'search_term' => '2000-10-30',
|
|
],
|
|
],
|
|
];
|
|
}
|
|
}
|