Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Forward Port PR-14344] Fix generating product URL rewrites for anchor categories #26784

Merged
merged 8 commits into from
Mar 17, 2020
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->

<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
<actionGroup name="AdminChangeSeoUrlKeyForSubCategoryWithoutRedirectActionGroup" extends="ChangeSeoUrlKeyForSubCategoryActionGroup">
<annotations>
<description>Requires navigation to subcategory creation/edit. Updates the Search Engine Optimization with uncheck Redirect Checkbox .</description>
</annotations>
<arguments>
<argument name="value" type="string"/>
</arguments>

<uncheckOption selector="{{AdminCategorySEOSection.UrlKeyRedirectCheckbox}}" stepKey="uncheckRedirectCheckbox" after="enterURLKey"/>
</actionGroup>
</actionGroups>
16 changes: 16 additions & 0 deletions app/code/Magento/Catalog/Test/Mftf/Data/CategoryData.xml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,22 @@
<data key="is_active">false</data>
<data key="include_in_menu">false</data>
</entity>
<entity name="_defaultCategoryDifferentUrlStore" type="category">
<data key="name" unique="suffix">SimpleCategory</data>
<data key="name_lwr" unique="suffix">simplecategory</data>
<data key="is_active">true</data>
<data key="url_key_default_store" unique="suffix">default-simplecategory</data>
<data key="url_key_custom_store" unique="suffix">custom-simplecategory</data>
</entity>
<entity name="SimpleSubCategoryDifferentUrlStore" type="category">
<data key="name" unique="suffix">SimpleSubCategory</data>
<data key="name_lwr" unique="suffix">simplesubcategory</data>
<data key="is_active">true</data>
<data key="url_key_default_store" unique="suffix">default-simplesubcategory</data>
<data key="url_key_custom_store" unique="suffix">custom-simplesubcategory</data>
<data key="include_in_menu">true</data>
<var key="parent_id" entityType="category" entityKey="id" />
</entity>
<!-- Category from file "prepared-for-sample-data.csv"-->
<entity name="Gear" type="category">
<data key="name">Gear</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public function generate($storeId, Product $product, ObjectRegistry $productCate
$anchorCategoryIds = $category->getAnchorsAbove();
if ($anchorCategoryIds) {
foreach ($anchorCategoryIds as $anchorCategoryId) {
$anchorCategory = $this->categoryRepository->get($anchorCategoryId);
$anchorCategory = $this->categoryRepository->get($anchorCategoryId, $storeId);
if ((int)$anchorCategory->getParentId() === Category::TREE_ROOT_ID) {
continue;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
<actionGroup name="AssertStorefrontProductRewriteUrlSubCategoryActionGroup">
<annotations>
<description>Validates that the provided Product Title is present on the Rewrite URL with a subcategory page.</description>
</annotations>
<arguments>
<argument name="category" type="string" defaultValue="simplecategory"/>
<argument name="product" defaultValue="SimpleProduct" />
</arguments>

<amOnPage url="{{category}}/{{product.urlKey}}2.html" stepKey="goToProductPage"/>
<see selector="{{StorefrontProductInfoMainSection.productName}}" userInput="{{product.name}}" stepKey="seeProductNameInStoreFront"/>
</actionGroup>
</actionGroups>
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,12 @@
<data key="label">No</data>
<data key="value">0</data>
</entity>
<entity name="EnableCategoriesPathProductUrls">
<data key="path">catalog/seo/product_use_categories</data>
<data key="value">1</data>
</entity>
<entity name="DisableCategoriesPathProductUrls">
<data key="path">catalog/seo/product_use_categories</data>
<data key="value">0</data>
</entity>
</entities>
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
<test name="AdminRewriteProductWithTwoStoreTest">
<annotations>
<title value="Rewriting URL of product"/>
<description value="Rewriting URL of product. Verify the full URL address"/>
<group value="CatalogUrlRewrite"/>
</annotations>

<before>
<magentoCLI command="config:set {{EnableCategoriesPathProductUrls.path}} {{EnableCategoriesPathProductUrls.value}}" stepKey="enableUseCategoriesPath"/>
<magentoCLI command="cache:flush" stepKey="flushCache"/>

<actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/>
<actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createStoreView" />
<createData entity="_defaultCategoryDifferentUrlStore" stepKey="defaultCategory"/>
<createData entity="SimpleSubCategoryDifferentUrlStore" stepKey="subCategory">
<requiredEntity createDataKey="defaultCategory"/>
</createData>
<createData entity="SimpleProduct" stepKey="simpleProduct">
<requiredEntity createDataKey="subCategory"/>
</createData>
</before>

<after>
<actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreView"/>
<actionGroup ref="logout" stepKey="logout"/>
<deleteData createDataKey="simpleProduct" stepKey="deleteSimpleProduct"/>
<deleteData createDataKey="defaultCategory" stepKey="deleteNewRootCategory"/>
<magentoCLI command="config:set {{DisableCategoriesPathProductUrls.path}} {{DisableCategoriesPathProductUrls.value}}" stepKey="disableUseCategoriesPath"/>
<magentoCLI command="cache:flush" stepKey="flushCache"/>
</after>

<actionGroup ref="NavigateToCreatedCategoryActionGroup" stepKey="navigateToCreatedDefaultCategory">
<argument name="Category" value="$$defaultCategory$$"/>
</actionGroup>
<actionGroup ref="AdminSwitchStoreViewActionGroup" stepKey="AdminSwitchDefaultStoreViewForDefaultCategory">
<argument name="storeView" value="_defaultStore.name"/>
</actionGroup>
<actionGroup ref="AdminChangeSeoUrlKeyForSubCategoryWithoutRedirectActionGroup" stepKey="changeSeoUrlKeyForDefaultCategoryDefaultStore">
<argument name="value" value="{{_defaultCategoryDifferentUrlStore.url_key_default_store}}"/>
</actionGroup>
<actionGroup ref="AdminSwitchStoreViewActionGroup" stepKey="AdminSwitchCustomStoreViewForDefaultCategory">
<argument name="storeView" value="customStore.name"/>
</actionGroup>
<actionGroup ref="AdminChangeSeoUrlKeyForSubCategoryWithoutRedirectActionGroup" stepKey="changeSeoUrlKeyForDefaultCategoryCustomStore">
<argument name="value" value="{{_defaultCategoryDifferentUrlStore.url_key_custom_store}}"/>
</actionGroup>

<actionGroup ref="NavigateToCreatedCategoryActionGroup" stepKey="navigateToCreatedSubCategory">
<argument name="Category" value="$$subCategory$$"/>
</actionGroup>
<actionGroup ref="AdminSwitchStoreViewActionGroup" stepKey="AdminSwitchDefaultStoreViewForSubCategory">
<argument name="storeView" value="_defaultStore.name"/>
</actionGroup>
<actionGroup ref="AdminChangeSeoUrlKeyForSubCategoryWithoutRedirectActionGroup" stepKey="changeSeoUrlKeyForSubCategoryDefaultStore">
<argument name="value" value="{{SimpleSubCategoryDifferentUrlStore.url_key_default_store}}"/>
</actionGroup>
<actionGroup ref="AdminSwitchStoreViewActionGroup" stepKey="AdminSwitchCustomStoreViewForSubCategory">
<argument name="storeView" value="customStore.name"/>
</actionGroup>

<actionGroup ref="AdminChangeSeoUrlKeyForSubCategoryWithoutRedirectActionGroup" stepKey="changeSeoUrlKeyForSubCategoryCustomStore">
<argument name="value" value="{{SimpleSubCategoryDifferentUrlStore.url_key_custom_store}}"/>
</actionGroup>
<actionGroup ref="AssertStorefrontProductRewriteUrlSubCategoryActionGroup" stepKey="validatesRewriteUrlDefaultStore">
<argument name="category" value="{{_defaultCategoryDifferentUrlStore.url_key_default_store}}"/>
<argument name="product" value="SimpleProduct" />
</actionGroup>

<actionGroup ref="StorefrontSwitchStoreViewActionGroup" stepKey="switchStore">
<argument name="storeView" value="customStore" />
</actionGroup>
<actionGroup ref="AssertStorefrontProductRewriteUrlSubCategoryActionGroup" stepKey="validatesRewriteUrlCustomStore">
<argument name="category" value="{{_defaultCategoryDifferentUrlStore.url_key_custom_store}}"/>
<argument name="product" value="SimpleProduct" />
</actionGroup>

</test>
</tests>
Original file line number Diff line number Diff line change
Expand Up @@ -3,53 +3,67 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\CatalogUrlRewrite\Test\Unit\Model\Product;

use Magento\Catalog\Api\CategoryRepositoryInterface;
use Magento\Catalog\Model\Product;
use Magento\CatalogUrlRewrite\Model\ObjectRegistry;
use Magento\CatalogUrlRewrite\Model\Product\AnchorUrlRewriteGenerator;
use Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator;
use Magento\CatalogUrlRewrite\Model\ProductUrlRewriteGenerator;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
use Magento\UrlRewrite\Service\V1\Data\UrlRewrite;
use Magento\UrlRewrite\Service\V1\Data\UrlRewriteFactory;
use PHPUnit\Framework\TestCase;
use PHPUnit_Framework_MockObject_MockObject as MockObject;

class AnchorUrlRewriteGeneratorTest extends \PHPUnit\Framework\TestCase
class AnchorUrlRewriteGeneratorTest extends TestCase
{
/** @var \Magento\CatalogUrlRewrite\Model\Product\AnchorUrlRewriteGenerator */
/** @var AnchorUrlRewriteGenerator */
protected $anchorUrlRewriteGenerator;

/** @var \Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator|\PHPUnit_Framework_MockObject_MockObject */
/** @var ProductUrlPathGenerator|MockObject */
protected $productUrlPathGenerator;

/** @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject */
/** @var Product|MockObject */
protected $product;

/** @var \Magento\Catalog\Api\CategoryRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject */
/** @var CategoryRepositoryInterface|MockObject */
private $categoryRepositoryInterface;

/** @var \Magento\CatalogUrlRewrite\Model\ObjectRegistry|\PHPUnit_Framework_MockObject_MockObject */
/** @var ObjectRegistry|MockObject */
protected $categoryRegistry;

/** @var \Magento\UrlRewrite\Service\V1\Data\UrlRewriteFactory|\PHPUnit_Framework_MockObject_MockObject */
/** @var UrlRewriteFactory|MockObject */
protected $urlRewriteFactory;

/** @var \Magento\UrlRewrite\Service\V1\Data\UrlRewrite|\PHPUnit_Framework_MockObject_MockObject */
/** @var UrlRewrite|MockObject */
protected $urlRewrite;

/**
* @inheritDoc
*/
protected function setUp()
{
$this->urlRewriteFactory = $this->getMockBuilder(\Magento\UrlRewrite\Service\V1\Data\UrlRewriteFactory::class)
$this->urlRewriteFactory = $this->getMockBuilder(UrlRewriteFactory::class)
->setMethods(['create'])
->disableOriginalConstructor()->getMock();
$this->urlRewrite = $this->getMockBuilder(\Magento\UrlRewrite\Service\V1\Data\UrlRewrite::class)
$this->urlRewrite = $this->getMockBuilder(UrlRewrite::class)
->disableOriginalConstructor()->getMock();
$this->product = $this->getMockBuilder(\Magento\Catalog\Model\Product::class)
$this->product = $this->getMockBuilder(Product::class)
->disableOriginalConstructor()->getMock();
$this->categoryRepositoryInterface = $this->getMockBuilder(
\Magento\Catalog\Api\CategoryRepositoryInterface::class
CategoryRepositoryInterface::class
)->disableOriginalConstructor()->getMock();
$this->categoryRegistry = $this->getMockBuilder(\Magento\CatalogUrlRewrite\Model\ObjectRegistry::class)
$this->categoryRegistry = $this->getMockBuilder(ObjectRegistry::class)
->disableOriginalConstructor()->getMock();
$this->productUrlPathGenerator = $this->getMockBuilder(
\Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator::class
ProductUrlPathGenerator::class
)->disableOriginalConstructor()->getMock();
$this->anchorUrlRewriteGenerator = (new ObjectManager($this))->getObject(
\Magento\CatalogUrlRewrite\Model\Product\AnchorUrlRewriteGenerator::class,
AnchorUrlRewriteGenerator::class,
[
'productUrlPathGenerator' => $this->productUrlPathGenerator,
'urlRewriteFactory' => $this->urlRewriteFactory,
Expand All @@ -58,7 +72,12 @@ protected function setUp()
);
}

public function testGenerateEmpty()
/**
* Verify generate if category registry list is empty.
*
* @return void
*/
public function testGenerateEmpty(): void
{
$this->categoryRegistry->expects($this->any())->method('getList')->will($this->returnValue([]));

Expand All @@ -68,7 +87,12 @@ public function testGenerateEmpty()
);
}

public function testGenerateCategories()
/**
* Verify generate product rewrites for anchor categories.
*
* @return void
*/
public function testGenerateCategories(): void
{
$urlPathWithCategory = 'category1/category2/category3/simple-product.html';
$storeId = 10;
Expand Down Expand Up @@ -100,9 +124,9 @@ public function testGenerateCategories()
->expects($this->any())
->method('get')
->withConsecutive(
[ 'category_id' => $categoryIds[0]],
[ 'category_id' => $categoryIds[1]],
[ 'category_id' => $categoryIds[2]]
[$categoryIds[0], $storeId],
[$categoryIds[1], $storeId],
[$categoryIds[2], $storeId]
)
->will($this->returnValue($category));
$this->categoryRegistry->expects($this->any())->method('getList')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\CatalogUrlRewrite\Model\Product;

use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\CatalogUrlRewrite\Model\ObjectRegistryFactory;
use Magento\Framework\ObjectManagerInterface;
use Magento\Store\Model\Store;
use Magento\TestFramework\Helper\Bootstrap;
use PHPUnit\Framework\TestCase;

/**
* Verify generate url rewrites for anchor categories.
*/
class AnchorUrlRewriteGeneratorTest extends TestCase
{

/**
* @var ObjectManagerInterface
*/
private $objectManager;

/**
* @var ProductRepositoryInterface
*/
private $productRepository;

/**
* @var ObjectRegistryFactory
*/
private $objectRegistryFactory;

/**
* @inheritDoc
*/
public function setUp()
{
parent::setUp(); // TODO: Change the autogenerated stub

$this->objectManager = Bootstrap::getObjectManager();
$this->productRepository = $this->objectManager->create(ProductRepositoryInterface::class);
$this->objectRegistryFactory = $this->objectManager->create(ObjectRegistryFactory::class);
}

/**
* Verify correct generate of the relative "StoreId"
*
* @param string $expect
* @return void
* @throws \Magento\Framework\Exception\LocalizedException
* @throws \Magento\Framework\Exception\NoSuchEntityException
* @magentoDataFixture Magento/CatalogUrlRewrite/_files/product_with_stores.php
* @magentoDbIsolation disabled
* @dataProvider getConfigGenerate
*/
public function testGenerate(string $expect): void
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For what input should the result change?
I see expectation attribute, but there's not context attribute.

{
$product = $this->productRepository->get('simple');
$categories = $product->getCategoryCollection();
$productCategories = $this->objectRegistryFactory->create(['entities' => $categories]);

/** @var AnchorUrlRewriteGenerator $generator */
$generator = $this->objectManager->get(AnchorUrlRewriteGenerator::class);

/** @var $store Store */
$store = Bootstrap::getObjectManager()->get(Store::class);
$store->load('fixture_second_store', 'code');

$urls = $generator->generate($store->getId(), $product, $productCategories);

$this->assertEquals($expect, $urls[0]->getRequestPath());
}

/**
* Data provider for testGenerate
*
* @return array
*/
public function getConfigGenerate(): array
{
return [
[
'expect' => 'category-1-custom/simple-product.html'
]
];
}
}
Loading