|
15 | 15 | use Magento\Catalog\Model\Indexer\Product\Eav\Processor; |
16 | 16 | use Magento\Catalog\Model\ResourceModel\Category\Collection as CategoryCollection; |
17 | 17 | use Magento\Catalog\Model\ResourceModel\Eav\Attribute; |
| 18 | +use Magento\Framework\Exception\LocalizedException; |
18 | 19 | use Magento\Framework\ObjectManagerInterface; |
19 | 20 | use Magento\TestFramework\Fixture\DataFixture; |
20 | 21 | use Magento\TestFramework\Fixture\DataFixtureStorage; |
@@ -235,44 +236,95 @@ public function testProductListWithDateAttribute() |
235 | 236 | /** |
236 | 237 | * Make sure CatalogWidget would display anchor category products recursively from children categories. |
237 | 238 | * |
238 | | - * 1. Create an anchor root category and a sub category inside it |
239 | | - * 2. Create 2 new products and assign them to the sub categories |
240 | | - * 3. Create product list widget condition to display products from the anchor root category |
241 | | - * 4. Load collection for product list widget and make sure that number of loaded products is correct |
| 239 | + * @param string $operator |
| 240 | + * @param string $value |
| 241 | + * @param array $expectedProducts |
| 242 | + * @throws LocalizedException |
242 | 243 | */ |
243 | 244 | #[ |
244 | | - DataFixture('Magento/Catalog/_files/product_in_nested_anchor_categories.php'), |
| 245 | + DataProvider('createAnchorCollectionDataProvider'), |
| 246 | + // level 1 categories |
| 247 | + DataFixture(CategoryFixture::class, ['is_anchor' => 1], 'category1'), |
| 248 | + DataFixture(CategoryFixture::class, ['is_anchor' => 1], 'category2'), |
| 249 | + DataFixture(CategoryFixture::class, ['is_anchor' => 0], 'category3'), |
| 250 | + // level 2 categories |
| 251 | + DataFixture(CategoryFixture::class, ['parent_id' => '$category1.id$'], 'category11'), |
| 252 | + DataFixture(CategoryFixture::class, ['parent_id' => '$category2.id$'], 'category21'), |
| 253 | + DataFixture(CategoryFixture::class, ['parent_id' => '$category3.id$'], 'category31'), |
| 254 | + // level 3 categories |
| 255 | + DataFixture(CategoryFixture::class, ['parent_id' => '$category11.id$'], 'category111'), |
| 256 | + // products assigned to level 1 categories |
| 257 | + DataFixture(ProductFixture::class, ['category_ids' => ['$category1.id$']], as: 'product1'), |
| 258 | + DataFixture(ProductFixture::class, ['category_ids' => ['$category2.id$']], as: 'product2'), |
| 259 | + DataFixture(ProductFixture::class, ['category_ids' => ['$category3.id$']], as: 'product3'), |
| 260 | + // unassigned product |
| 261 | + DataFixture(ProductFixture::class, as: 'product4'), |
| 262 | + // products assigned to level 2 categories |
| 263 | + DataFixture(ProductFixture::class, ['category_ids' => ['$category11.id$']], as: 'product11'), |
| 264 | + DataFixture(ProductFixture::class, ['category_ids' => ['$category21.id$']], as: 'product21'), |
| 265 | + DataFixture(ProductFixture::class, ['category_ids' => ['$category31.id$']], as: 'product31'), |
| 266 | + // products assigned to level 3 categories |
| 267 | + DataFixture(ProductFixture::class, ['category_ids' => ['$category111.id$']], as: 'product111'), |
245 | 268 | ] |
246 | | - public function testCreateAnchorCollection() |
247 | | - { |
| 269 | + public function testCreateAnchorCollection( |
| 270 | + string $operator, |
| 271 | + string $value, |
| 272 | + array $expectedProducts |
| 273 | + ): void { |
248 | 274 | // Reindex EAV attributes to enable products filtration by created multiselect attribute |
249 | 275 | /** @var Processor $eavIndexerProcessor */ |
250 | 276 | $eavIndexerProcessor = $this->objectManager->get( |
251 | 277 | Processor::class |
252 | 278 | ); |
253 | 279 | $eavIndexerProcessor->reindexAll(); |
| 280 | + $fixtures = DataFixtureStorageManager::getStorage(); |
254 | 281 |
|
255 | 282 | $this->categoryCollection->addNameToResult()->load(); |
256 | | - $rootCategoryId = $this |
257 | | - ->categoryCollection |
258 | | - ->getItemByColumnValue('name', 'Default Category') |
259 | | - ->getId(); |
| 283 | + $value = preg_replace_callback( |
| 284 | + '/(category\d+)/', |
| 285 | + function ($matches) use ($fixtures) { |
| 286 | + return $fixtures->get($matches[1])->getId(); |
| 287 | + }, |
| 288 | + $value |
| 289 | + ); |
260 | 290 |
|
261 | 291 | $encodedConditions = '^[`1`:^[`type`:`Magento||CatalogWidget||Model||Rule||Condition||Combine`, |
262 | 292 | `aggregator`:`all`,`value`:`1`,`new_child`:``^], |
263 | 293 | `1--1`:^[`type`:`Magento||CatalogWidget||Model||Rule||Condition||Product`, |
264 | 294 | `attribute`:`category_ids`, |
265 | | - `operator`:`==`,`value`:`' . $rootCategoryId . '`^]^]'; |
| 295 | + `operator`:`' . $operator . '`,`value`:`' . $value . '`^]^]'; |
266 | 296 |
|
267 | 297 | $this->block->setData('conditions_encoded', $encodedConditions); |
268 | 298 |
|
269 | 299 | $productCollection = $this->block->createCollection(); |
270 | 300 | $productCollection->load(); |
271 | 301 |
|
272 | | - $this->assertEquals( |
273 | | - 2, |
274 | | - $productCollection->count(), |
275 | | - "Anchor root category does not contain products of it's children." |
| 302 | + $allProducts = [ |
| 303 | + 'product1', |
| 304 | + 'product2', |
| 305 | + 'product3', |
| 306 | + 'product4', |
| 307 | + 'product11', |
| 308 | + 'product21', |
| 309 | + 'product31', |
| 310 | + 'product111', |
| 311 | + ]; |
| 312 | + $allProducts = array_combine( |
| 313 | + array_map(fn ($productKey) => $fixtures->get($productKey)->getSku(), $allProducts), |
| 314 | + $allProducts, |
| 315 | + ); |
| 316 | + |
| 317 | + $actualProducts = $productCollection->getColumnValues('sku'); |
| 318 | + |
| 319 | + $this->assertEqualsCanonicalizing( |
| 320 | + $expectedProducts, |
| 321 | + array_map( |
| 322 | + fn ($sku) => $allProducts[$sku], |
| 323 | + array_intersect( |
| 324 | + $actualProducts, |
| 325 | + array_keys($allProducts) |
| 326 | + ) |
| 327 | + ) |
276 | 328 | ); |
277 | 329 | } |
278 | 330 |
|
@@ -534,4 +586,78 @@ public static function collectionResultWithMultiselectAttributeDataProvider(): a |
534 | 586 | ] |
535 | 587 | ]; |
536 | 588 | } |
| 589 | + |
| 590 | + /** |
| 591 | + * @return array[] |
| 592 | + */ |
| 593 | + public static function createAnchorCollectionDataProvider(): array |
| 594 | + { |
| 595 | + return [ |
| 596 | + 'is - category1,category2' => [ |
| 597 | + '==', |
| 598 | + 'category1,category2', |
| 599 | + ['product111', 'product21', 'product11', 'product2', 'product1'] |
| 600 | + ], |
| 601 | + 'is not - category1,category2' => [ |
| 602 | + '!=', |
| 603 | + 'category1,category2', |
| 604 | + ['product31', 'product4', 'product3'] |
| 605 | + ], |
| 606 | + 'contains - category1,category2' => [ |
| 607 | + '{}', |
| 608 | + 'category1,category2', |
| 609 | + ['product111', 'product21', 'product11', 'product2', 'product1'] |
| 610 | + ], |
| 611 | + 'does not contain - category1,category2' => [ |
| 612 | + '!{}', |
| 613 | + 'category1,category2', |
| 614 | + ['product31', 'product4', 'product3'] |
| 615 | + ], |
| 616 | + 'is one of - category1,category2' => [ |
| 617 | + '()', |
| 618 | + 'category1,category2', |
| 619 | + ['product111', 'product21', 'product11', 'product2', 'product1'] |
| 620 | + ], |
| 621 | + 'is not one of - category1,category2' => [ |
| 622 | + '!()', |
| 623 | + 'category1,category2', |
| 624 | + ['product31', 'product4', 'product3'] |
| 625 | + ], |
| 626 | + // single anchor category |
| 627 | + 'is - category1' => [ |
| 628 | + '==', |
| 629 | + 'category1', |
| 630 | + ['product111', 'product11', 'product1'] |
| 631 | + ], |
| 632 | + 'is not - category1' => [ |
| 633 | + '!=', |
| 634 | + 'category1', |
| 635 | + ['product31', 'product21', 'product4', 'product3', 'product2'] |
| 636 | + ], |
| 637 | + // single non-anchor category |
| 638 | + 'is - category3' => [ |
| 639 | + '==', |
| 640 | + 'category3', |
| 641 | + ['product3'] |
| 642 | + ], |
| 643 | + 'is not - category3' => [ |
| 644 | + '!=', |
| 645 | + 'category3', |
| 646 | + ['product111', 'product31', 'product21', 'product11', 'product4', 'product2', 'product1'] |
| 647 | + ], |
| 648 | + // anchor and non-anchor category |
| 649 | + 'is - category1,category3' => [ |
| 650 | + '==', |
| 651 | + // spaces are intentional to check trimming functionality |
| 652 | + 'category1 , category3', |
| 653 | + ['product111', 'product11', 'product3', 'product1'] |
| 654 | + ], |
| 655 | + 'is not - category1,category3' => [ |
| 656 | + '!=', |
| 657 | + // spaces are intentional to check trimming functionality |
| 658 | + 'category1 , category3', |
| 659 | + ['product31', 'product21', 'product4', 'product2'] |
| 660 | + ], |
| 661 | + ]; |
| 662 | + } |
537 | 663 | } |
0 commit comments