Skip to content

Commit 06ba316

Browse files
committed
ACP2E-3898: Page Builder Product Widget ordering not being applied in GraphQL
1 parent 48f5f04 commit 06ba316

File tree

1 file changed

+141
-0
lines changed

1 file changed

+141
-0
lines changed
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
<?php
2+
/**
3+
* Copyright 2025 Adobe
4+
* All Rights Reserved.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\PageBuilder\Api;
10+
11+
use Magento\Catalog\Model\ResourceModel\Category\Collection;
12+
use Magento\Cms\Api\Data\PageInterface;
13+
use Magento\Cms\Model\PageRepository;
14+
use Magento\Framework\Api\SearchCriteriaBuilder;
15+
use Magento\Framework\Exception\CouldNotSaveException;
16+
use Magento\Framework\ObjectManagerInterface;
17+
use Magento\GraphQl\Service\GraphQlRequest;
18+
use Magento\TestFramework\Helper\Bootstrap;
19+
use Magento\TestFramework\TestCase\GraphQlAbstract;
20+
21+
class CMSContentProductListing extends GraphQlAbstract
22+
{
23+
/**
24+
* @var ObjectManagerInterface
25+
*/
26+
private ObjectManagerInterface $objectManager;
27+
28+
/**
29+
* @var SearchCriteriaBuilder
30+
*/
31+
private SearchCriteriaBuilder $searchCriteriaBuilder;
32+
33+
/**
34+
* @var PageRepository
35+
*/
36+
private PageRepository $pageRepository;
37+
38+
/**
39+
* @var Collection
40+
*/
41+
private Collection $categoryCollection;
42+
43+
/**
44+
* @inheritDoc
45+
*/
46+
protected function setUp(): void
47+
{
48+
$this->objectManager = $objectManager = Bootstrap::getObjectManager();
49+
$this->searchCriteriaBuilder = $objectManager->get(SearchCriteriaBuilder::class);
50+
$this->pageRepository = $objectManager->get(PageRepository::class);
51+
$this->categoryCollection = $this->objectManager->get(Collection::class);
52+
}
53+
54+
/**
55+
* @magentoDataFixture Magento/Cms/Fixtures/page_list.php
56+
* @magentoApiDataFixture Magento/Catalog/_files/category_with_three_products.php
57+
* @return void
58+
* @throws CouldNotSaveException
59+
*/
60+
public function testCMSContentProductListing(): void
61+
{
62+
$category = $this->categoryCollection->addFieldToFilter(
63+
'name',
64+
'Category 999'
65+
)->getFirstItem();
66+
$categoryId = $category->getId();
67+
$content = '<style>#html-body [data-pb-style=E4B30DS]{justify-content:flex-start;display:flex;' .
68+
'flex-direction:column;background-position:left top;background-size:cover;background-repeat:no-repeat;' .
69+
'background-attachment:scroll}</style><div data-content-type="row" data-appearance="contained" ' .
70+
'data-element="main"><div data-enable-parallax="0" data-parallax-speed="0.5" data-background-images="{}" ' .
71+
'data-background-type="image" data-video-loop="true" data-video-play-only-visible="true" ' .
72+
'data-video-lazy-load="true" data-video-fallback-src="" data-element="inner" ' .
73+
'data-pb-style="E4B30DS"><div data-content-type="products" data-appearance="grid" ' .
74+
'data-element="main">{{widget type="Magento\CatalogWidget\Block\Product\ProductsList" ' .
75+
'template="Magento_CatalogWidget::product/widget/content/grid.phtml" anchor_text="" id_path="" ' .
76+
'show_pager="0" products_count="5" condition_option="category_ids" condition_option_value="' .$categoryId
77+
.'"type_name="Catalog Products List" conditions_encoded="^[`1`:^[`aggregator`:`all`,`new_child`:``,' .
78+
'`type`:`Magento||CatalogWidget||Model||Rule||Condition||Combine`,`value`:`1`^],`1--1`:^[`operator`:`==`,' .
79+
'`type`:`Magento||CatalogWidget||Model||Rule||Condition||Product`,`attribute`:`category_ids`,' .
80+
'`value`:`' . $categoryId . '`^]^]" sort_order="position"}}</div></div></div>';
81+
$page = $this->getPageByTitle('Page with 1column layout');
82+
$page->setContent($content);
83+
$this->pageRepository->save($page);
84+
85+
$productPositions = $category->getProductsPosition();
86+
$count = 3;
87+
foreach ($productPositions as $productId => $position) {
88+
$productPositions[$productId] = $count;
89+
$count--;
90+
}
91+
ksort($productPositions);
92+
93+
$category->setPostedProducts($productPositions);
94+
$category->save();
95+
96+
$query = $this->getQuery($page->getIdentifier(), ['title', 'content']);
97+
$response = $this->graphQlQueryWithResponseHeaders($query);
98+
$position1 = strpos($response['body']['cmsPage']['content'], '/simple-product-with-price-10.html');
99+
$position2 = strpos($response['body']['cmsPage']['content'], '/simple-product2.html');
100+
$position3 = strpos($response['body']['cmsPage']['content'], '/simple-product-with-price-20.html');
101+
$this->assertTrue($position1 < $position2 && $position2 < $position3);
102+
}
103+
104+
/**
105+
* Retrieve a page by its title
106+
*
107+
* @param string $title
108+
* @return PageInterface
109+
*/
110+
private function getPageByTitle(string $title): PageInterface
111+
{
112+
$searchCriteria = $this->searchCriteriaBuilder
113+
->addFilter('title', $title)
114+
->create();
115+
116+
$pages = $this->pageRepository->getList($searchCriteria)->getItems();
117+
118+
/** @var PageInterface $page */
119+
$page = reset($pages);
120+
121+
return $page;
122+
}
123+
124+
/**
125+
* @param string $identifier
126+
* @param array $fields
127+
* @return string
128+
*/
129+
private function getQuery(string $identifier, array $fields = ['title']): string
130+
{
131+
$fields = implode(PHP_EOL, $fields);
132+
133+
return <<<QUERY
134+
{
135+
cmsPage(identifier: "$identifier") {
136+
$fields
137+
}
138+
}
139+
QUERY;
140+
}
141+
}

0 commit comments

Comments
 (0)