Skip to content

Commit c6aaabc

Browse files
committed
MC-38822: Attributes position doesn't affect the ranking in graphql response
1 parent 8c95f07 commit c6aaabc

File tree

4 files changed

+287
-0
lines changed

4 files changed

+287
-0
lines changed

app/code/Magento/CatalogGraphQl/Plugin/Search/Request/ConfigReader.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ private function getSearchableAttributes(): array
106106
$productAttributes->addFieldToFilter(
107107
['is_searchable', 'is_visible_in_advanced_search', 'is_filterable', 'is_filterable_in_search'],
108108
[1, 1, [1, 2], 1]
109+
)->setOrder(
110+
'position',
111+
'ASC'
109112
);
110113

111114
/** @var Attribute $attribute */
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
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\GraphQl\Catalog\CategoriesQuery;
9+
10+
use Magento\TestFramework\TestCase\GraphQlAbstract;
11+
12+
/**
13+
* Test to return category aggregations
14+
*/
15+
class CategoryAggregationsTest extends GraphQlAbstract
16+
{
17+
/**
18+
* Test to return category aggregations in sorting by position
19+
*
20+
* @magentoApiDataFixture Magento/Catalog/_files/products_with_layered_navigation_attributes.php
21+
*/
22+
public function testCategoryAggregationSorting(): void
23+
{
24+
$categoryId = 3334;
25+
$query = <<<QUERY
26+
{
27+
products(filter: {category_id: {eq: "{$categoryId}"}}) {
28+
aggregations{
29+
label
30+
attribute_code
31+
count
32+
options{
33+
label
34+
value
35+
count
36+
}
37+
}
38+
}
39+
}
40+
QUERY;
41+
$response = $this->graphQlQuery($query);
42+
$this->assertArrayNotHasKey('errors', $response);
43+
$this->assertArrayHasKey('products', $response);
44+
$this->assertArrayHasKey('aggregations', $response['products']);
45+
46+
$customAggregation = array_values(array_filter(
47+
$response['products']['aggregations'],
48+
function ($a) {
49+
return in_array($a['attribute_code'], ['test_attribute_1', 'test_attribute_2']);
50+
}
51+
));
52+
$this->assertCount(2, $customAggregation);
53+
$this->assertEquals('test_attribute_2', $customAggregation[0]['attribute_code']);
54+
$this->assertEquals('test_attribute_1', $customAggregation[1]['attribute_code']);
55+
}
56+
}
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
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+
use Magento\Catalog\Api\Data\CategoryInterfaceFactory;
9+
use Magento\Catalog\Api\Data\ProductAttributeInterfaceFactory;
10+
use Magento\Catalog\Api\Data\ProductInterfaceFactory;
11+
use Magento\Catalog\Api\ProductAttributeRepositoryInterface;
12+
use Magento\Catalog\Api\ProductRepositoryInterface;
13+
use Magento\Catalog\Model\Product;
14+
use Magento\Catalog\Model\Product\Attribute\Source\Status;
15+
use Magento\Catalog\Model\Product\Type;
16+
use Magento\Catalog\Model\Product\Visibility;
17+
use Magento\Eav\Model\Config;
18+
use Magento\Eav\Setup\EavSetup;
19+
use Magento\Indexer\Model\Indexer;
20+
use Magento\Indexer\Model\Indexer\Collection;
21+
use Magento\Msrp\Model\Product\Attribute\Source\Type as SourceType;
22+
use Magento\Store\Api\WebsiteRepositoryInterface;
23+
use Magento\TestFramework\Helper\Bootstrap;
24+
use Magento\TestFramework\Helper\CacheCleaner;
25+
26+
$objectManager = Bootstrap::getObjectManager();
27+
28+
/** @var Config $eavConfig */
29+
$eavConfig = $objectManager->get(Config::class);
30+
31+
/** @var ProductAttributeRepositoryInterface $attributeRepository */
32+
$attributeRepository = $objectManager->get(ProductAttributeRepositoryInterface::class);
33+
/** @var ProductAttributeInterfaceFactory $attributeFactory */
34+
$attributeFactory = $objectManager->get(ProductAttributeInterfaceFactory::class);
35+
36+
/** @var $installer EavSetup */
37+
$installer = $objectManager->get(EavSetup::class);
38+
$attributeSetId = $installer->getAttributeSetId(Product::ENTITY, 'Default');
39+
$groupId = $installer->getDefaultAttributeGroupId(Product::ENTITY, $attributeSetId);
40+
41+
/** @var WebsiteRepositoryInterface $websiteRepository */
42+
$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class);
43+
$baseWebsite = $websiteRepository->get('base');
44+
45+
for ($i = 1; $i <= 2; $i++) {
46+
$attributeModel = $attributeFactory->create();
47+
$attributeModel->setData(
48+
[
49+
'attribute_code' => 'test_attribute_' . $i,
50+
'entity_type_id' => $installer->getEntityTypeId(Product::ENTITY),
51+
'is_global' => 1,
52+
'is_user_defined' => 1,
53+
'frontend_input' => 'select',
54+
'is_unique' => 0,
55+
'is_required' => 0,
56+
'is_searchable' => 1,
57+
'is_visible_in_advanced_search' => 1,
58+
'is_comparable' => 1,
59+
'is_filterable' => 1,
60+
'is_filterable_in_search' => 1,
61+
'is_used_for_promo_rules' => 0,
62+
'is_html_allowed_on_front' => 1,
63+
'is_visible_on_front' => 1,
64+
'used_in_product_listing' => 1,
65+
'used_for_sort_by' => 1,
66+
'frontend_label' => ['Test Attribute ' . $i],
67+
'backend_type' => 'int',
68+
'option' => [
69+
'value' => ['option_0' => ['Option 1'], 'option_1' => ['Option 2']],
70+
'order' => ['option_0' => 1, 'option_1' => 2],
71+
],
72+
'default' => ['option_0'],
73+
'position' => 3 - $i
74+
]
75+
);
76+
$attribute = $attributeRepository->save($attributeModel);
77+
$installer->addAttributeToGroup(Product::ENTITY, $attributeSetId, $groupId, $attribute->getId());
78+
}
79+
80+
CacheCleaner::cleanAll();
81+
$eavConfig->clear();
82+
83+
/** @var ProductRepositoryInterface $productRepository */
84+
$productRepository = $objectManager->get(ProductRepositoryInterface::class);
85+
/** @var ProductInterfaceFactory $productInterfaceFactory */
86+
$productInterfaceFactory = $objectManager->get(ProductInterfaceFactory::class);
87+
88+
/** @var Product $product */
89+
$product = $productInterfaceFactory->create();
90+
$product->setTypeId(Type::TYPE_SIMPLE)
91+
->setAttributeSetId($product->getDefaultAttributeSetId())
92+
->setName('Simple Product1')
93+
->setSku('simple1')
94+
->setTaxClassId('none')
95+
->setDescription('description')
96+
->setShortDescription('short description')
97+
->setOptionsContainer('container1')
98+
->setMsrpDisplayActualPriceType(SourceType::TYPE_IN_CART)
99+
->setPrice(10)
100+
->setWeight(1)
101+
->setMetaTitle('meta title')
102+
->setMetaKeyword('meta keyword')
103+
->setMetaDescription('meta description')
104+
->setVisibility(Visibility::VISIBILITY_BOTH)
105+
->setStatus(Status::STATUS_ENABLED)
106+
->setWebsiteIds([$baseWebsite->getId()])
107+
->setCategoryIds([])
108+
->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1])
109+
->setSpecialPrice('5.99');
110+
$simple1 = $productRepository->save($product);
111+
112+
/** @var Product $product */
113+
$product = $productInterfaceFactory->create();
114+
$product->setTypeId(Type::TYPE_SIMPLE)
115+
->setAttributeSetId($product->getDefaultAttributeSetId())
116+
->setName('Simple Product2')
117+
->setSku('simple2')
118+
->setTaxClassId('none')
119+
->setDescription('description')
120+
->setShortDescription('short description')
121+
->setOptionsContainer('container1')
122+
->setMsrpDisplayActualPriceType(SourceType::TYPE_ON_GESTURE)
123+
->setPrice(20)
124+
->setWeight(1)
125+
->setMetaTitle('meta title')
126+
->setMetaKeyword('meta keyword')
127+
->setMetaDescription('meta description')
128+
->setVisibility(Visibility::VISIBILITY_BOTH)
129+
->setStatus(Status::STATUS_ENABLED)
130+
->setWebsiteIds([$baseWebsite->getId()])
131+
->setCategoryIds([])
132+
->setStockData(['use_config_manage_stock' => 1, 'qty' => 50, 'is_qty_decimal' => 0, 'is_in_stock' => 1])
133+
->setSpecialPrice('15.99');
134+
$simple2 = $productRepository->save($product);
135+
136+
/** @var CategoryInterfaceFactory $categoryInterfaceFactory */
137+
$categoryInterfaceFactory = $objectManager->get(CategoryInterfaceFactory::class);
138+
139+
$category = $categoryInterfaceFactory->create();
140+
$category->isObjectNew(true);
141+
$category->setId(3334)
142+
->setCreatedAt('2014-06-23 09:50:07')
143+
->setName('Category 1')
144+
->setParentId(2)
145+
->setPath('1/2/333')
146+
->setLevel(2)
147+
->setAvailableSortBy(['position', 'name'])
148+
->setDefaultSortBy('name')
149+
->setIsActive(true)
150+
->setPosition(1)
151+
->setPostedProducts(
152+
[
153+
$simple1->getId() => 10,
154+
$simple2->getId() => 11
155+
]
156+
);
157+
$category->save();
158+
159+
/** @var Collection $indexerCollection */
160+
$indexerCollection = $objectManager->get(Collection::class);
161+
$indexerCollection->load();
162+
/** @var Indexer $indexer */
163+
foreach ($indexerCollection->getItems() as $indexer) {
164+
$indexer->reindexAll();
165+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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+
use Magento\Catalog\Api\CategoryRepositoryInterface;
9+
use Magento\Catalog\Api\ProductAttributeRepositoryInterface;
10+
use Magento\Catalog\Api\ProductRepositoryInterface;
11+
use Magento\Eav\Model\Config;
12+
use Magento\Framework\Exception\NoSuchEntityException;
13+
use Magento\Framework\Registry;
14+
use Magento\TestFramework\Catalog\Model\GetCategoryByName;
15+
use Magento\TestFramework\Helper\Bootstrap;
16+
17+
$objectManager = Bootstrap::getObjectManager();
18+
/** @var Registry $registry */
19+
$registry = $objectManager->get(Registry::class);
20+
$registry->unregister('isSecureArea');
21+
$registry->register('isSecureArea', true);
22+
23+
/** @var ProductRepositoryInterface $productRepository */
24+
$productRepository = $objectManager->get(ProductRepositoryInterface::class);
25+
26+
foreach (['simple1', 'simple2'] as $sku) {
27+
try {
28+
$product = $productRepository->get($sku, false, null, true);
29+
$productRepository->delete($product);
30+
} catch (NoSuchEntityException $exception) {
31+
//Product already removed
32+
}
33+
}
34+
35+
/** @var CategoryRepositoryInterface $categoryRepository */
36+
$categoryRepository = $objectManager->get(CategoryRepositoryInterface::class);
37+
/** @var GetCategoryByName $getCategoryByName */
38+
$getCategoryByName = $objectManager->get(GetCategoryByName::class);
39+
$category = $getCategoryByName->execute('Category 1');
40+
try {
41+
if ($category->getId()) {
42+
$categoryRepository->delete($category);
43+
}
44+
} catch (NoSuchEntityException $exception) {
45+
//Category already removed
46+
}
47+
48+
$eavConfig = $objectManager->get(Config::class);
49+
/** @var ProductAttributeRepositoryInterface $attributeRepository */
50+
$attributeRepository = $objectManager->get(ProductAttributeRepositoryInterface::class);
51+
52+
try {
53+
for ($i = 1; $i <= 2; $i++) {
54+
$attribute = $attributeRepository->get('test_attribute_' . $i);
55+
$attributeRepository->delete($attribute);
56+
}
57+
} catch (NoSuchEntityException $exception) {
58+
//Attribute already removed
59+
}
60+
$eavConfig->clear();
61+
62+
$registry->unregister('isSecureArea');
63+
$registry->register('isSecureArea', false);

0 commit comments

Comments
 (0)