Skip to content

Commit 3d3e19c

Browse files
committed
Add Integration tests to cover url_key and url_path management
1 parent 315691d commit 3d3e19c

File tree

2 files changed

+177
-45
lines changed

2 files changed

+177
-45
lines changed

dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/Save/AbstractSaveCategoryTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ protected function setUp()
3939
protected function performSaveCategoryRequest(array $data): array
4040
{
4141
$data['return_session_messages_only'] = true;
42+
$this->getRequest()->setDispatched(false);
4243
$this->getRequest()->setMethod(HttpRequest::METHOD_POST);
4344
$this->getRequest()->setPostValue($data);
4445
$this->dispatch('backend/catalog/category/save');

dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/Save/SaveCategoryDifferentScopesTest.php

Lines changed: 176 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,18 @@
1010
use Magento\Catalog\Api\CategoryRepositoryInterface;
1111
use Magento\Catalog\Api\Data\CategoryInterface;
1212
use Magento\Catalog\Model\Category;
13+
use Magento\Framework\App\ResourceConnection;
14+
use Magento\Framework\DB\Adapter\AdapterInterface;
15+
use Magento\Framework\Exception\NoSuchEntityException;
1316
use Magento\Store\Model\StoreManagerInterface;
1417

1518
/**
1619
* @magentoAppArea adminhtml
1720
*/
1821
class SaveCategoryDifferentScopesTest extends AbstractSaveCategoryTest
1922
{
20-
private const DEFAULT_STORE_ID = 1;
21-
private const FIXTURE_CATEGORY_ID = 333;
2223
private const GLOBAL_SCOPE_ID = 0;
23-
24-
private const FIXTURE_URL_KEY = 'category-1';
24+
private const DEFAULT_STORE_ID = 1;
2525

2626
private const FIXTURE_CATEGORY_ROOT = 400;
2727
private const FIXTURE_CATEGORY_CHILD = 401;
@@ -35,6 +35,9 @@ class SaveCategoryDifferentScopesTest extends AbstractSaveCategoryTest
3535
/** @var StoreManagerInterface */
3636
private $storeManager;
3737

38+
/** @var AdapterInterface */
39+
private $dbConnection;
40+
3841
/**
3942
* @inheritDoc
4043
*/
@@ -43,6 +46,8 @@ protected function setUp()
4346
parent::setUp();
4447
$this->categoryRepository = $this->_objectManager->get(CategoryRepositoryInterface::class);
4548
$this->storeManager = $this->_objectManager->get(StoreManagerInterface::class);
49+
50+
4651
}
4752

4853
/**
@@ -55,53 +60,117 @@ protected function tearDown()
5560
parent::tearDown();
5661
}
5762

63+
/**
64+
* For Test purposes you may need FRESH Category repository without internal cache
65+
*
66+
* @return CategoryRepositoryInterface
67+
*/
68+
private function createCategoryRepository(): CategoryRepositoryInterface
69+
{
70+
return $this->_objectManager->create(CategoryRepositoryInterface::class);
71+
}
72+
5873
/**
5974
* Change of `url_key` for specific store should not affect global value of `url_path`
6075
*
6176
* @magentoDbIsolation enabled
62-
* @magentoDataFixture Magento/Catalog/_files/category.php
77+
* @magentoDataFixture Magento/Catalog/_files/category_tree.php
78+
* @magentoDataFixture Magento/Store/_files/core_fixturestore.php
6379
*/
64-
public function testChangeUrlKeyForSpecificStoreShouldNotChangeGlobalUrlPath()
80+
public function testUrlKeyUpdateInCustomStoreDoesNotChangeGlobalUrlPath()
6581
{
66-
$expectedStoreScopeUrlKey = 'url-key-store-1';
67-
$expectedGlobalScopeUrlKey = self::FIXTURE_URL_KEY;
82+
$secondStoreId = $this->getStoreId(self::FIXTURE_SECOND_STORE_CODE);
83+
84+
$storeScopeUrlKey = 'url-key-store-1';
6885

69-
$postData = [
70-
'entity_id' => self::FIXTURE_CATEGORY_ID,
71-
'store_id' => self::DEFAULT_STORE_ID,
72-
'url_key' => $expectedStoreScopeUrlKey
86+
$updateCategoryStoreScope = [
87+
'entity_id' => self::FIXTURE_CATEGORY_LEAF,
88+
'store_id' => $secondStoreId,
89+
'url_key' => $storeScopeUrlKey,
90+
'use_config' => [
91+
'available_sort_by' => 1,
92+
]
7393
];
74-
$responseData = $this->performSaveCategoryRequest($postData);
94+
$responseData = $this->performSaveCategoryRequest($updateCategoryStoreScope);
7595
$this->assertRequestIsSuccessfullyPerformed($responseData);
7696

77-
/** @var CategoryInterface|Category $storeScopeCategory */
78-
$storeScopeCategory = $this->categoryRepository->get(self::FIXTURE_CATEGORY_ID, self::DEFAULT_STORE_ID);
79-
$this->assertSame($expectedStoreScopeUrlKey, $storeScopeCategory->getData('url_path'));
97+
$this->assertCategoryUrlPathForStore(
98+
self::FIXTURE_CATEGORY_LEAF,
99+
$secondStoreId,
100+
$this->getExpectedUrlPath([2 => $storeScopeUrlKey])
101+
);
80102

81-
$globalScopeCategory = $this->categoryRepository->get(self::FIXTURE_CATEGORY_ID, self::GLOBAL_SCOPE_ID);
82-
$this->assertSame($expectedGlobalScopeUrlKey, $globalScopeCategory->getData('url_path'));
103+
$this->assertCategoryUrlPathForStore(
104+
self::FIXTURE_CATEGORY_LEAF,
105+
self::GLOBAL_SCOPE_ID,
106+
$this->getExpectedUrlPath()
107+
);
83108
}
84109

85110
/**
86-
* Change of `url_key` for root category in specific store should change all the children `url_path`
111+
* Magento EAV should not create entries for Default store (1) when Custom Store values are saved
87112
*
88113
* @magentoDbIsolation enabled
89114
* @magentoDataFixture Magento/Catalog/_files/category_tree.php
90115
* @magentoDataFixture Magento/Store/_files/core_fixturestore.php
91116
*/
92-
public function testChangeUrlKeyAffectsAllChildrenUrlPath()
117+
public function testUrlKeyUpdateInCustomStoreDoesNotCreateEntriesForDefaultStore()
93118
{
94119
$secondStoreId = $this->getStoreId(self::FIXTURE_SECOND_STORE_CODE);
120+
$storeScopeUrlKey = 'url-key-store-1';
95121

96-
$urlKeys = [
97-
1 => 'category-1',
98-
2 => 'category-1-1',
99-
3 => 'category-1-1-1'
122+
$updateCategoryStoreScope = [
123+
'entity_id' => self::FIXTURE_CATEGORY_LEAF,
124+
'store_id' => $secondStoreId,
125+
'url_key' => $storeScopeUrlKey,
126+
'use_config' => [
127+
'available_sort_by' => 1,
128+
]
100129
];
130+
$responseData = $this->performSaveCategoryRequest($updateCategoryStoreScope);
131+
$this->assertRequestIsSuccessfullyPerformed($responseData);
132+
133+
$attributeValues = $this->getCategoryVarcharAttributeValuesPerScope(self::FIXTURE_CATEGORY_LEAF, 'url_path');
134+
$this->assertArrayNotHasKey(self::DEFAULT_STORE_ID, $attributeValues);
135+
}
101136

102-
/** @var CategoryInterface|Category $leafOriginal */
103-
$leafOriginal = $this->categoryRepository->get(self::FIXTURE_CATEGORY_LEAF);
104-
$this->assertSame(implode('/', $urlKeys), $leafOriginal->getData('url_path'));
137+
/**
138+
* Magento EAV should not create entries for Default store (1) when Global scope (0) values are saved
139+
*
140+
* @magentoDbIsolation enabled
141+
* @magentoDataFixture Magento/Catalog/_files/category_tree.php
142+
* @magentoDataFixture Magento/Store/_files/core_fixturestore.php
143+
*/
144+
public function testUrlKeyUpdateInGlobalScopeDoesNotCreateEntriesForDefaultStore()
145+
{
146+
$storeScopeUrlKey = 'url-key-store-1';
147+
148+
$updateCategoryStoreScope = [
149+
'entity_id' => self::FIXTURE_CATEGORY_LEAF,
150+
'url_key' => $storeScopeUrlKey,
151+
'use_config' => [
152+
'available_sort_by' => 1,
153+
]
154+
];
155+
$responseData = $this->performSaveCategoryRequest($updateCategoryStoreScope);
156+
$this->assertRequestIsSuccessfullyPerformed($responseData);
157+
158+
$attributeValues = $this->getCategoryVarcharAttributeValuesPerScope(self::FIXTURE_CATEGORY_LEAF, 'url_path');
159+
$this->assertArrayNotHasKey(self::DEFAULT_STORE_ID, $attributeValues);
160+
}
161+
162+
/**
163+
* Change of `url_key` for root category in specific store should change all the children `url_path`
164+
*
165+
* @magentoDbIsolation enabled
166+
* @magentoDataFixture Magento/Catalog/_files/category_tree.php
167+
* @magentoDataFixture Magento/Store/_files/core_fixturestore.php
168+
*/
169+
public function testUpdateRootUrlKeyAffectsAllChildrenUrlPath()
170+
{
171+
$secondStoreId = $this->getStoreId(self::FIXTURE_SECOND_STORE_CODE);
172+
173+
$this->assertCategoryUrlPathForStore(self::FIXTURE_CATEGORY_LEAF, $secondStoreId, $this->getExpectedUrlPath());
105174

106175
$updateRootData = [
107176
'entity_id' => self::FIXTURE_CATEGORY_ROOT,
@@ -114,16 +183,13 @@ public function testChangeUrlKeyAffectsAllChildrenUrlPath()
114183
$responseData = $this->performSaveCategoryRequest($updateRootData);
115184
$this->assertRequestIsSuccessfullyPerformed($responseData);
116185

117-
$newUrlKeys = $urlKeys;
118-
$newUrlKeys[1] = 'store-root';
119-
120-
/** @var CategoryInterface|Category $leafStoreScope */
121-
$leafStoreScope = $this->categoryRepository->get(self::FIXTURE_CATEGORY_LEAF, $secondStoreId);
122-
$this->assertSame(implode('/', $newUrlKeys), $leafStoreScope->getData('url_path'));
186+
$this->categoryRepository = $this->createCategoryRepository();
187+
$this->assertCategoryUrlPathForStore(self::FIXTURE_CATEGORY_LEAF, $secondStoreId,
188+
$this->getExpectedUrlPath([0 => 'store-root']));
123189

124-
/** @var CategoryInterface|Category $leafGlobalScope */
125-
$leafGlobalScope = $this->categoryRepository->get(self::FIXTURE_CATEGORY_LEAF);
126-
$this->assertSame(implode('/', $urlKeys), $leafGlobalScope->getData('url_path'));
190+
// Verify the potential side effects to Global Scope
191+
$this->assertCategoryUrlPathForStore(self::FIXTURE_CATEGORY_LEAF, self::DEFAULT_STORE_ID,
192+
$this->getExpectedUrlPath());
127193
}
128194

129195
/**
@@ -133,24 +199,27 @@ public function testChangeUrlKeyAffectsAllChildrenUrlPath()
133199
* @magentoDataFixture Magento/Store/_files/core_fixturestore.php
134200
* @magentoDataFixture Magento/Catalog/_files/category_tree.php
135201
*/
136-
public function testCategoryUrlPathUsesGlobalUrlKey()
202+
public function testStoreScopeCategoryUrlPathUsesGlobalScopeUrlKey()
137203
{
204+
$this->markTestIncomplete('Still in Magento');
138205
$secondStoreId = $this->getStoreId(self::FIXTURE_SECOND_STORE_CODE);
139206

140-
$setSecondStoreCategoryUrlKey = [
207+
$updateSecondStoreCategoryUrlKey = [
141208
'entity_id' => self::FIXTURE_CATEGORY_CHILD,
142209
'url_key' => 'second-store-child',
143210
'store_id' => $secondStoreId,
144211
'use_config' => [
145212
'available_sort_by' => 1,
146213
]
147214
];
148-
$responseData = $this->performSaveCategoryRequest($setSecondStoreCategoryUrlKey);
215+
$responseData = $this->performSaveCategoryRequest($updateSecondStoreCategoryUrlKey);
149216
$this->assertRequestIsSuccessfullyPerformed($responseData);
150217

151-
/** @var CategoryInterface|Category $categoryWithCustomUrlKey */
152-
$categoryWithCustomUrlKey = $this->categoryRepository->get(self::FIXTURE_CATEGORY_CHILD, $secondStoreId);
153-
$this->assertSame('category-1/second-store-child', $categoryWithCustomUrlKey->getData('url_path'));
218+
// Temporary solution to reset Request object.
219+
$this->getRequest()->setDispatched(false);
220+
221+
$this->assertCategoryUrlPathForStore(self::FIXTURE_CATEGORY_LEAF, $secondStoreId,
222+
$this->getExpectedUrlPath([1 => 'second-store-child']));
154223

155224
$useDefaultUrlKey = [
156225
'entity_id' => self::FIXTURE_CATEGORY_CHILD,
@@ -165,19 +234,81 @@ public function testCategoryUrlPathUsesGlobalUrlKey()
165234
$responseData = $this->performSaveCategoryRequest($useDefaultUrlKey);
166235
$this->assertRequestIsSuccessfullyPerformed($responseData);
167236

168-
$categoryWithDefaultUrlKey = $this->categoryRepository->get(self::FIXTURE_CATEGORY_LEAF, $secondStoreId);
169-
$this->assertSame('category-1/category-1-1/category-1-1-1', $categoryWithDefaultUrlKey->getData('url_path'));
237+
$this->assertCategoryUrlPathForStore(self::FIXTURE_CATEGORY_LEAF, $secondStoreId, $this->getExpectedUrlPath());
170238
}
171239

172240
/**
173241
* Returns StoreID by Code
174242
*
175243
* @param string $code
176244
* @return int
177-
* @throws \Magento\Framework\Exception\NoSuchEntityException
245+
* @throws NoSuchEntityException
178246
*/
179247
private function getStoreId(string $code): int
180248
{
181249
return (int)$this->storeManager->getStore($code)->getId();
182250
}
251+
252+
/**
253+
* Returns
254+
* @param array $replacements
255+
* @return string
256+
*/
257+
private function getExpectedUrlPath(array $replacements = []): string
258+
{
259+
$basicUrlPath = ['category-1', 'category-1-1', 'category-1-1-1'];
260+
261+
return implode('/', array_replace($basicUrlPath, $replacements));
262+
}
263+
264+
/**
265+
* Returns array of attribute values per scope
266+
*
267+
* @param int $categoryId
268+
* @param string $attributeCode
269+
*/
270+
private function getCategoryVarcharAttributeValuesPerScope(int $categoryId, string $attributeCode)
271+
{
272+
$selectValues = $this->getConnection()->select()
273+
->from(
274+
['ccev' => $this->getConnection()->getTableName('catalog_category_entity_varchar')],
275+
['store_id', 'value']
276+
)
277+
->join(
278+
['ea' => $this->getConnection()->getTableName('eav_attribute')],
279+
'ccev.attribute_id = ea.attribute_id',
280+
[]
281+
)
282+
->where('entity_id = ?', $categoryId)
283+
->where('ea.attribute_code = ?', $attributeCode);
284+
285+
return $this->getConnection()->fetchPairs($selectValues);
286+
}
287+
288+
/**
289+
* Asserts the URL path for the Category in specified Store scope
290+
*
291+
* @param int $categoryId
292+
* @param int $storeId
293+
* @param string $expectedPath
294+
* @throws NoSuchEntityException
295+
*/
296+
private function assertCategoryUrlPathForStore(int $categoryId, int $storeId, string $expectedPath)
297+
{
298+
/** @var CategoryInterface|Category $storeScopeCategory */
299+
$storeScopeCategory = $this->categoryRepository->get($categoryId, $storeId);
300+
$this->assertSame($storeId, $storeScopeCategory->getStoreId());
301+
$this->assertSame($expectedPath, $storeScopeCategory->getData('url_path'));
302+
}
303+
304+
private function getConnection(): AdapterInterface
305+
{
306+
if (null === $this->dbConnection) {
307+
/** @var ResourceConnection $resourceConnection */
308+
$resourceConnection = $this->_objectManager->create(ResourceConnection::class);
309+
$this->dbConnection = $resourceConnection->getConnection();
310+
}
311+
312+
return $this->dbConnection;
313+
}
183314
}

0 commit comments

Comments
 (0)