diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontCategoryCurrentPageIsNthActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontCategoryCurrentPageIsNthActionGroup.xml
new file mode 100644
index 0000000000000..84e14269d24c2
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontCategoryCurrentPageIsNthActionGroup.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+ {{expectedPage}}
+ currentPageText
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontNavigateCategoryNextPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontNavigateCategoryNextPageActionGroup.xml
new file mode 100644
index 0000000000000..4776c9d32a34d
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontNavigateCategoryNextPageActionGroup.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+ Navigates storefront category next page from toolbar
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryBottomToolbarSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryBottomToolbarSection.xml
index 09eb4ad954274..c27a6107e5e35 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryBottomToolbarSection.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryBottomToolbarSection.xml
@@ -12,6 +12,6 @@
-
+
diff --git a/app/code/Magento/Swatches/Block/LayeredNavigation/RenderLayered.php b/app/code/Magento/Swatches/Block/LayeredNavigation/RenderLayered.php
index fc13372520945..9ba1083adab74 100644
--- a/app/code/Magento/Swatches/Block/LayeredNavigation/RenderLayered.php
+++ b/app/code/Magento/Swatches/Block/LayeredNavigation/RenderLayered.php
@@ -5,11 +5,17 @@
*/
namespace Magento\Swatches\Block\LayeredNavigation;
-use Magento\Eav\Model\Entity\Attribute;
+use Magento\Catalog\Model\Layer\Filter\AbstractFilter;
+use Magento\Catalog\Model\Layer\Filter\Item as FilterItem;
use Magento\Catalog\Model\ResourceModel\Layer\Filter\AttributeFactory;
-use Magento\Framework\View\Element\Template;
+use Magento\Eav\Model\Entity\Attribute;
use Magento\Eav\Model\Entity\Attribute\Option;
-use Magento\Catalog\Model\Layer\Filter\Item as FilterItem;
+use Magento\Framework\App\ObjectManager;
+use Magento\Framework\View\Element\Template;
+use Magento\Framework\View\Element\Template\Context;
+use Magento\Swatches\Helper\Data;
+use Magento\Swatches\Helper\Media;
+use Magento\Theme\Block\Html\Pager;
/**
* Class RenderLayered Render Swatches at Layered Navigation
@@ -37,7 +43,7 @@ class RenderLayered extends Template
protected $eavAttribute;
/**
- * @var \Magento\Catalog\Model\Layer\Filter\AbstractFilter
+ * @var AbstractFilter
*/
protected $filter;
@@ -47,41 +53,52 @@ class RenderLayered extends Template
protected $layerAttribute;
/**
- * @var \Magento\Swatches\Helper\Data
+ * @var Data
*/
protected $swatchHelper;
/**
- * @var \Magento\Swatches\Helper\Media
+ * @var Media
*/
protected $mediaHelper;
/**
- * @param Template\Context $context
+ * @var Pager
+ */
+ private $htmlPagerBlock;
+
+ /**
+ * @param Context $context
* @param Attribute $eavAttribute
* @param AttributeFactory $layerAttribute
- * @param \Magento\Swatches\Helper\Data $swatchHelper
- * @param \Magento\Swatches\Helper\Media $mediaHelper
+ * @param Data $swatchHelper
+ * @param Media $mediaHelper
* @param array $data
+ * @param Pager|null $htmlPagerBlock
*/
public function __construct(
- \Magento\Framework\View\Element\Template\Context $context,
+ Context $context,
Attribute $eavAttribute,
AttributeFactory $layerAttribute,
- \Magento\Swatches\Helper\Data $swatchHelper,
- \Magento\Swatches\Helper\Media $mediaHelper,
- array $data = []
+ Data $swatchHelper,
+ Media $mediaHelper,
+ array $data = [],
+ ?Pager $htmlPagerBlock = null
) {
$this->eavAttribute = $eavAttribute;
$this->layerAttribute = $layerAttribute;
$this->swatchHelper = $swatchHelper;
$this->mediaHelper = $mediaHelper;
+ $this->htmlPagerBlock = $htmlPagerBlock ?? ObjectManager::getInstance()->get(Pager::class);
parent::__construct($context, $data);
}
/**
+ * Set filter and attribute objects
+ *
* @param \Magento\Catalog\Model\Layer\Filter\AbstractFilter $filter
+ *
* @return $this
* @throws \Magento\Framework\Exception\LocalizedException
*/
@@ -94,6 +111,8 @@ public function setSwatchFilter(\Magento\Catalog\Model\Layer\Filter\AbstractFilt
}
/**
+ * Get attribute swatch data
+ *
* @return array
*/
public function getSwatchData()
@@ -114,30 +133,46 @@ public function getSwatchData()
$attributeOptionIds = array_keys($attributeOptions);
$swatches = $this->swatchHelper->getSwatchesByOptionsId($attributeOptionIds);
- $data = [
+ return [
'attribute_id' => $this->eavAttribute->getId(),
'attribute_code' => $this->eavAttribute->getAttributeCode(),
'attribute_label' => $this->eavAttribute->getStoreLabel(),
'options' => $attributeOptions,
'swatches' => $swatches,
];
-
- return $data;
}
/**
+ * Build filter option url
+ *
* @param string $attributeCode
* @param int $optionId
+ *
* @return string
*/
public function buildUrl($attributeCode, $optionId)
{
- $query = [$attributeCode => $optionId];
- return $this->_urlBuilder->getUrl('*/*/*', ['_current' => true, '_use_rewrite' => true, '_query' => $query]);
+ $query = [
+ $attributeCode => $optionId,
+ // exclude current page from urls
+ $this->htmlPagerBlock->getPageVarName() => null
+ ];
+
+ return $this->_urlBuilder->getUrl(
+ '*/*/*',
+ [
+ '_current' => true,
+ '_use_rewrite' => true,
+ '_query' => $query
+ ]
+ );
}
/**
+ * Get view data for option with no results
+ *
* @param Option $swatchOption
+ *
* @return array
*/
protected function getUnusedOption(Option $swatchOption)
@@ -150,8 +185,11 @@ protected function getUnusedOption(Option $swatchOption)
}
/**
+ * Get option data if visible
+ *
* @param FilterItem[] $filterItems
* @param Option $swatchOption
+ *
* @return array
*/
protected function getFilterOption(array $filterItems, Option $swatchOption)
@@ -166,8 +204,11 @@ protected function getFilterOption(array $filterItems, Option $swatchOption)
}
/**
+ * Get view data for option
+ *
* @param FilterItem $filterItem
* @param Option $swatchOption
+ *
* @return array
*/
protected function getOptionViewData(FilterItem $filterItem, Option $swatchOption)
@@ -187,15 +228,20 @@ protected function getOptionViewData(FilterItem $filterItem, Option $swatchOptio
}
/**
+ * Check if option should be visible
+ *
* @param FilterItem $filterItem
+ *
* @return bool
*/
protected function isOptionVisible(FilterItem $filterItem)
{
- return $this->isOptionDisabled($filterItem) && $this->isShowEmptyResults() ? false : true;
+ return !($this->isOptionDisabled($filterItem) && $this->isShowEmptyResults());
}
/**
+ * Check if attribute values should be visible with no results
+ *
* @return bool
*/
protected function isShowEmptyResults()
@@ -204,7 +250,10 @@ protected function isShowEmptyResults()
}
/**
+ * Check if option should be disabled
+ *
* @param FilterItem $filterItem
+ *
* @return bool
*/
protected function isOptionDisabled(FilterItem $filterItem)
@@ -213,8 +262,11 @@ protected function isOptionDisabled(FilterItem $filterItem)
}
/**
+ * Retrieve filter item by id
+ *
* @param FilterItem[] $filterItems
* @param integer $id
+ *
* @return bool|FilterItem
*/
protected function getFilterItemById(array $filterItems, $id)
@@ -228,14 +280,15 @@ protected function getFilterItemById(array $filterItems, $id)
}
/**
+ * Get swatch image path
+ *
* @param string $type
* @param string $filename
+ *
* @return string
*/
public function getSwatchPath($type, $filename)
{
- $imagePath = $this->mediaHelper->getSwatchAttributeImage($type, $filename);
-
- return $imagePath;
+ return $this->mediaHelper->getSwatchAttributeImage($type, $filename);
}
}
diff --git a/app/code/Magento/Swatches/Test/Mftf/ActionGroup/AddTextSwatchToProductActionGroup.xml b/app/code/Magento/Swatches/Test/Mftf/ActionGroup/AddTextSwatchToProductActionGroup.xml
index 97a391137d8e3..5f3ec07bd4983 100644
--- a/app/code/Magento/Swatches/Test/Mftf/ActionGroup/AddTextSwatchToProductActionGroup.xml
+++ b/app/code/Magento/Swatches/Test/Mftf/ActionGroup/AddTextSwatchToProductActionGroup.xml
@@ -19,6 +19,7 @@
+
@@ -41,6 +42,7 @@
+
diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontRedirectToFirstPageOnFilteringBySwatchTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontRedirectToFirstPageOnFilteringBySwatchTest.xml
new file mode 100644
index 0000000000000..c6266e034bffc
--- /dev/null
+++ b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontRedirectToFirstPageOnFilteringBySwatchTest.xml
@@ -0,0 +1,103 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Swatches/Test/Unit/Block/LayeredNavigation/RenderLayeredTest.php b/app/code/Magento/Swatches/Test/Unit/Block/LayeredNavigation/RenderLayeredTest.php
index 4056bf27f571e..06960c409b476 100644
--- a/app/code/Magento/Swatches/Test/Unit/Block/LayeredNavigation/RenderLayeredTest.php
+++ b/app/code/Magento/Swatches/Test/Unit/Block/LayeredNavigation/RenderLayeredTest.php
@@ -18,6 +18,7 @@
use Magento\Swatches\Block\LayeredNavigation\RenderLayered;
use Magento\Swatches\Helper\Data;
use Magento\Swatches\Helper\Media;
+use Magento\Theme\Block\Html\Pager;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
@@ -28,35 +29,60 @@
*/
class RenderLayeredTest extends TestCase
{
- /** @var MockObject */
- protected $contextMock;
-
- /** @var MockObject */
- protected $requestMock;
-
- /** @var MockObject */
- protected $urlBuilder;
-
- /** @var MockObject */
- protected $eavAttributeMock;
-
- /** @var MockObject */
- protected $layerAttributeFactoryMock;
-
- /** @var MockObject */
- protected $layerAttributeMock;
-
- /** @var MockObject */
- protected $swatchHelperMock;
-
- /** @var MockObject */
- protected $mediaHelperMock;
-
- /** @var MockObject */
- protected $filterMock;
-
- /** @var MockObject */
- protected $block;
+ /**
+ * @var RenderLayered|MockObject
+ */
+ private $block;
+
+ /**
+ * @var Context|MockObject
+ */
+ private $contextMock;
+
+ /**
+ * @var RequestInterface|MockObject
+ */
+ private $requestMock;
+
+ /**
+ * @var Url|MockObject
+ */
+ private $urlBuilder;
+
+ /**
+ * @var Attribute|MockObject
+ */
+ private $eavAttributeMock;
+
+ /**
+ * @var AttributeFactory|MockObject
+ */
+ private $layerAttributeFactoryMock;
+
+ /**
+ * @var \Magento\Catalog\Model\ResourceModel\Layer\Filter\Attribute|MockObject
+ */
+ private $layerAttributeMock;
+
+ /**
+ * @var Data|MockObject
+ */
+ private $swatchHelperMock;
+
+ /**
+ * @var Media|MockObject
+ */
+ private $mediaHelperMock;
+
+ /**
+ * @var AbstractFilter|MockObject
+ */
+ private $filterMock;
+
+ /**
+ * @var Pager|MockObject
+ */
+ private $htmlBlockPagerMock;
protected function setUp(): void
{
@@ -66,8 +92,8 @@ protected function setUp(): void
Url::class,
['getCurrentUrl', 'getRedirectUrl', 'getUrl']
);
- $this->contextMock->expects($this->any())->method('getRequest')->willReturn($this->requestMock);
- $this->contextMock->expects($this->any())->method('getUrlBuilder')->willReturn($this->urlBuilder);
+ $this->contextMock->method('getRequest')->willReturn($this->requestMock);
+ $this->contextMock->method('getUrlBuilder')->willReturn($this->urlBuilder);
$this->eavAttributeMock = $this->createMock(Attribute::class);
$this->layerAttributeFactoryMock = $this->createPartialMock(
AttributeFactory::class,
@@ -80,6 +106,7 @@ protected function setUp(): void
$this->swatchHelperMock = $this->createMock(Data::class);
$this->mediaHelperMock = $this->createMock(Media::class);
$this->filterMock = $this->createMock(AbstractFilter::class);
+ $this->htmlBlockPagerMock = $this->createMock(Pager::class);
$this->block = $this->getMockBuilder(RenderLayered::class)
->setMethods(['filter', 'eavAttribute'])
@@ -91,6 +118,7 @@ protected function setUp(): void
$this->swatchHelperMock,
$this->mediaHelperMock,
[],
+ $this->htmlBlockPagerMock
]
)
->getMock();
@@ -114,7 +142,7 @@ public function testGetSwatchData()
$item3 = $this->createMock(Item::class);
$item4 = $this->createMock(Item::class);
- $item1->expects($this->any())->method('__call')->withConsecutive(
+ $item1->method('__call')->withConsecutive(
['getValue'],
['getCount'],
['getValue'],
@@ -128,9 +156,9 @@ public function testGetSwatchData()
'Yellow'
);
- $item2->expects($this->any())->method('__call')->with('getValue')->willReturn('blue');
+ $item2->method('__call')->with('getValue')->willReturn('blue');
- $item3->expects($this->any())->method('__call')->withConsecutive(
+ $item3->method('__call')->withConsecutive(
['getValue'],
['getCount']
)->willReturnOnConsecutiveCalls(
@@ -138,7 +166,7 @@ public function testGetSwatchData()
0
);
- $item4->expects($this->any())->method('__call')->withConsecutive(
+ $item4->method('__call')->withConsecutive(
['getValue'],
['getCount'],
['getValue'],
@@ -162,22 +190,22 @@ public function testGetSwatchData()
$this->block->method('filter')->willReturn($this->filterMock);
$option1 = $this->createMock(Option::class);
- $option1->expects($this->any())->method('getValue')->willReturn('yellow');
+ $option1->method('getValue')->willReturn('yellow');
$option2 = $this->createMock(Option::class);
- $option2->expects($this->any())->method('getValue')->willReturn(null);
+ $option2->method('getValue')->willReturn(null);
$option3 = $this->createMock(Option::class);
- $option3->expects($this->any())->method('getValue')->willReturn('red');
+ $option3->method('getValue')->willReturn('red');
$option4 = $this->createMock(Option::class);
- $option4->expects($this->any())->method('getValue')->willReturn('green');
+ $option4->method('getValue')->willReturn('green');
$eavAttribute = $this->createMock(\Magento\Catalog\Model\ResourceModel\Eav\Attribute::class);
$eavAttribute->expects($this->once())
->method('getOptions')
->willReturn([$option1, $option2, $option3, $option4]);
- $eavAttribute->expects($this->any())->method('getIsFilterable')->willReturn(0);
+ $eavAttribute->method('getIsFilterable')->willReturn(0);
$this->filterMock->expects($this->once())->method('getAttributeModel')->willReturn($eavAttribute);
$this->block->method('eavAttribute')->willReturn($eavAttribute);
@@ -200,7 +228,7 @@ public function testGetSwatchDataException()
{
$this->block->method('filter')->willReturn($this->filterMock);
$this->block->setSwatchFilter($this->filterMock);
- $this->expectException('\RuntimeException');
+ $this->expectException(\RuntimeException::class);
$this->block->getSwatchData();
}