From 1a969c028cdf3ea1391f7607f8f09e4ae27a4ebf Mon Sep 17 00:00:00 2001
From: Roger <rogerdz88@hotmail.com>
Date: Fri, 5 Jan 2024 17:10:43 +0000
Subject: [PATCH 1/3] Columns functionality for
 \Magento\Theme\Block\Html\Topmenu seems broken

---
 app/code/Magento/Theme/Block/Html/Topmenu.php | 15 ++++-----------
 1 file changed, 4 insertions(+), 11 deletions(-)

diff --git a/app/code/Magento/Theme/Block/Html/Topmenu.php b/app/code/Magento/Theme/Block/Html/Topmenu.php
index f8460b43ba2ff..2ce3b54ffd7d0 100644
--- a/app/code/Magento/Theme/Block/Html/Topmenu.php
+++ b/app/code/Magento/Theme/Block/Html/Topmenu.php
@@ -141,7 +141,7 @@ protected function _columnBrake($items, $limit)
     {
         $total = $this->_countItems($items);
         if ($total <= $limit) {
-            return;
+            return [];
         }
 
         $result[] = ['total' => $total, 'max' => (int)ceil($total / ceil($total / $limit))];
@@ -151,12 +151,9 @@ protected function _columnBrake($items, $limit)
 
         foreach ($items as $item) {
             $place = $this->_countItems($item->getChildren()) + 1;
-            $count += $place;
+            $count++;
 
-            if ($place >= $limit) {
-                $colbrake = !$firstCol;
-                $count = 0;
-            } elseif ($count >= $limit) {
+            if ($count > $limit) {
                 $colbrake = !$firstCol;
                 $count = $place;
             } else {
@@ -242,7 +239,7 @@ protected function _getHtml(
             }
 
             if ($this->shouldAddNewColumn($colBrakes, $counter)) {
-                $html .= '</ul></li><li class="column"><ul>';
+                continue;
             }
 
             $html .= '<li ' . $this->_getRenderedMenuItemAttributes($child) . '>';
@@ -257,10 +254,6 @@ protected function _getHtml(
             $counter++;
         }
 
-        if (is_array($colBrakes) && !empty($colBrakes) && $limit) {
-            $html = '<li class="column"><ul>' . $html . '</ul></li>';
-        }
-
         return $html;
     }
 

From 85683bdf583a9f7f731dac1a278242cb8f3da45b Mon Sep 17 00:00:00 2001
From: engcom-Dash <grp-engcom-vendorworker-Dash@adobe.com>
Date: Mon, 9 Sep 2024 17:59:07 +0530
Subject: [PATCH 2/3] 38326: Add unit test and update return type of
 _columnBrake function

---
 app/code/Magento/Theme/Block/Html/Topmenu.php |   2 +-
 .../Test/Unit/Block/Html/TopmenuTest.php      | 216 ++++++++++++++++--
 2 files changed, 203 insertions(+), 15 deletions(-)
 mode change 100644 => 100755 app/code/Magento/Theme/Test/Unit/Block/Html/TopmenuTest.php

diff --git a/app/code/Magento/Theme/Block/Html/Topmenu.php b/app/code/Magento/Theme/Block/Html/Topmenu.php
index 7094a424dae6a..88ec35c552b44 100644
--- a/app/code/Magento/Theme/Block/Html/Topmenu.php
+++ b/app/code/Magento/Theme/Block/Html/Topmenu.php
@@ -133,7 +133,7 @@ protected function _countItems($items)
      *
      * @param Menu $items
      * @param int $limit
-     * @return array|void
+     * @return array
      *
      * @todo: Add Depth Level limit, and better logic for columns
      */
diff --git a/app/code/Magento/Theme/Test/Unit/Block/Html/TopmenuTest.php b/app/code/Magento/Theme/Test/Unit/Block/Html/TopmenuTest.php
old mode 100644
new mode 100755
index 5bc0f70dd7703..b2337e652b90f
--- a/app/code/Magento/Theme/Test/Unit/Block/Html/TopmenuTest.php
+++ b/app/code/Magento/Theme/Test/Unit/Block/Html/TopmenuTest.php
@@ -23,6 +23,8 @@
 use Magento\Framework\View\Element\Template\Context;
 use Magento\Store\Model\StoreManagerInterface;
 use Magento\Theme\Block\Html\Topmenu;
+use Magento\Backend\Model\Menu;
+use Magento\Backend\Model\Menu\Item as MenuItem;
 use PHPUnit\Framework\MockObject\MockObject;
 use PHPUnit\Framework\TestCase;
 
@@ -76,6 +78,21 @@ class TopmenuTest extends TestCase
      */
     private $requestMock;
 
+    /**
+     * @var Menu
+     */
+    private $menuMock;
+
+    /**
+     * @var MenuItem
+     */
+    private $menuItemMock;
+
+    /**
+     * @var Node
+     */
+    private $nodeMock;
+
     // @codingStandardsIgnoreStart
     /** @var string  */
     private $navigationMenuHtml = <<<HTML
@@ -107,6 +124,21 @@ protected function setUp(): void
             ->disableOriginalConstructor()
             ->getMock();
 
+        $this->menuMock = $this->getMockBuilder(Menu::class)
+            ->onlyMethods(['count', 'getIterator'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->menuItemMock = $this->getMockBuilder(MenuItem::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->nodeMock = $this->getMockBuilder(Node::class)
+            ->disableOriginalConstructor()
+            ->addMethods(['getClass'])
+            ->onlyMethods(['getChildren', 'hasChildren', '__call'])
+            ->getMock();
+
         $objectManager = new ObjectManager($this);
         $this->context = $objectManager->getObject(
             Context::class,
@@ -265,14 +297,10 @@ private function buildTree(bool $isCurrentItem): MockObject
 
         $children->expects($this->once())->method('count')->willReturn(10);
 
-        $nodeMock = $this->getMockBuilder(Node::class)
-            ->disableOriginalConstructor()
-            ->onlyMethods(['getChildren', '__call'])
-            ->getMock();
-        $nodeMock->expects($this->once())
+        $this->nodeMock->expects($this->once())
             ->method('getChildren')
             ->willReturn($children);
-        $nodeMock
+        $this->nodeMock
             ->method('__call')
             ->willReturnCallback(function ($arg1, $arg2) {
                 if ($arg1 == 'setOutermostClass') {
@@ -291,13 +319,13 @@ private function buildTree(bool $isCurrentItem): MockObject
         $this->nodeFactory->expects($this->any())
             ->method('create')
             ->with($nodeMockData)
-            ->willReturn($nodeMock);
+            ->willReturn($this->nodeMock);
 
         $this->treeFactory->expects($this->once())
             ->method('create')
             ->willReturn($treeMock);
 
-        return $nodeMock;
+        return $this->nodeMock;
     }
 
     /**
@@ -315,20 +343,180 @@ public function testGetMenu(): void
             'tree' => $treeMock
         ];
 
-        $nodeMock = $this->getMockBuilder(Node::class)
-            ->disableOriginalConstructor()
-            ->getMock();
-
         $this->nodeFactory->expects($this->any())
             ->method('create')
             ->with($nodeMockData)
-            ->willReturn($nodeMock);
+            ->willReturn($this->nodeMock);
 
         $this->treeFactory->expects($this->once())
             ->method('create')
             ->willReturn($treeMock);
 
         $topmenuBlock = $this->getTopmenu();
-        $this->assertEquals($nodeMock, $topmenuBlock->getMenu());
+        $this->assertEquals($this->nodeMock, $topmenuBlock->getMenu());
+    }
+
+    /**
+     * Test counting items when there are no children.
+     * @return void
+     */
+    public function testCountItemsNoChildren():void
+    {
+        $this->menuMock->expects($this->any())
+            ->method('count')
+            ->willReturn(5);
+        $this->menuMock->expects($this->any())
+            ->method('getIterator')
+            ->willReturn(new \ArrayIterator([$this->menuItemMock]));
+
+        $this->menuItemMock->expects($this->any())
+            ->method('hasChildren')
+            ->willReturn(false);
+
+        $method = new \ReflectionMethod(
+            Topmenu::class,
+            '_countItems'
+        );
+        $method->setAccessible(true);
+
+        $this->assertEquals(5, $method->invoke($this->getTopmenu(), $this->menuMock));
+    }
+
+    /**
+     * Test counting items when there are children.
+     * @return void
+     */
+    public function testCountItemsWithChildren(): void
+    {
+        // Setup child menu mock
+        $childMenuMock = $this->createMock(Menu::class);
+        $childMenuMock->expects($this->any())
+            ->method('count')
+            ->willReturn(3);
+        $childMenuMock->expects($this->any())
+            ->method('getIterator')
+            ->willReturn(new \ArrayIterator([]));
+
+        $this->menuItemMock->expects($this->any())
+            ->method('hasChildren')
+            ->willReturn(true);
+        $this->menuItemMock->expects($this->any())
+            ->method('getChildren')
+            ->willReturn($childMenuMock);
+
+        // Setup menu mock
+        $this->menuMock->expects($this->any())
+            ->method('count')
+            ->willReturn(2);
+        $this->menuMock->expects($this->any())
+            ->method('getIterator')
+            ->willReturn(new \ArrayIterator([$this->menuItemMock, $this->menuItemMock]));
+
+        $method = new \ReflectionMethod(
+            Topmenu::class,
+            '_countItems'
+        );
+        $method->setAccessible(true);
+
+        // Total should be 2 (top level) + 2 * 3 (children) = 8
+        $this->assertEquals(8, $method->invoke($this->getTopmenu(), $this->menuMock));
+    }
+
+    /**
+     * @return void
+     * @throws \ReflectionException
+     */
+    public function testColumnBrakeEmptyArray(): void
+    {
+        $this->testCountItemsNoChildren();
+
+        $method = new \ReflectionMethod(
+            Topmenu::class,
+            '_columnBrake'
+        );
+        $method->setAccessible(true);
+
+        $this->assertEquals([], $method->invoke($this->getTopmenu(), $this->menuMock, 5));
+    }
+
+    /**
+     * @return void
+     * @throws \ReflectionException
+     */
+    public function testColumnBrakeWithoutItem(): void
+    {
+        $result = [
+            [   'total' => 8,
+                'max' => 2
+            ],
+            [
+                'place' => 4,
+                'colbrake' => false
+            ],
+            [
+                'place' => 4,
+                'colbrake' => true
+            ]
+        ];
+
+        $this->testCountItemsWithChildren();
+
+        $method = new \ReflectionMethod(
+            Topmenu::class,
+            '_columnBrake'
+        );
+        $method->setAccessible(true);
+
+        $this->assertEquals($result, $method->invoke($this->getTopmenu(), $this->menuMock, 2));
+    }
+
+    /**
+     * @return void
+     */
+    public function testAddSubMenu(): void
+    {
+        $container = $this->createMock(CategoryTree::class);
+
+        $children = $this->getMockBuilder(Collection::class)
+            ->onlyMethods(['count'])
+            ->setConstructorArgs(['container' => $container])
+            ->getMock();
+
+        $this->nodeMock->expects($this->atLeastOnce())
+            ->method('hasChildren')
+            ->willReturn(true);
+
+        $this->nodeMock->expects($this->any())
+            ->method('getChildren')
+            ->willReturn($children);
+
+        $method = new \ReflectionMethod(
+            Topmenu::class,
+            '_addSubMenu'
+        );
+        $method->setAccessible(true);
+
+        $this->assertEquals(
+            '<ul class="level0 "></ul>',
+            $method->invoke($this->getTopmenu(), $this->nodeMock, 0, '', 2)
+        );
+    }
+
+    /**
+     * @return void
+     */
+    public function testSetCurrentClass(): void
+    {
+        $this->nodeMock->expects($this->once())
+            ->method('getClass')
+            ->willReturn(null);
+
+        $method = new \ReflectionMethod(
+            Topmenu::class,
+            'setCurrentClass'
+        );
+        $method->setAccessible(true);
+
+        $method->invoke($this->getTopmenu(), $this->nodeMock, '');
     }
 }

From 49a1dd7fa3b770b1d99b959a8e51d2a45b0a07a5 Mon Sep 17 00:00:00 2001
From: engcom-Dash <grp-engcom-vendorworker-Dash@adobe.com>
Date: Tue, 10 Sep 2024 11:25:02 +0530
Subject: [PATCH 3/3] 32386: Fix unit test failure for
 testColumnBrakeWithoutItem method

---
 app/code/Magento/Theme/Test/Unit/Block/Html/TopmenuTest.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/code/Magento/Theme/Test/Unit/Block/Html/TopmenuTest.php b/app/code/Magento/Theme/Test/Unit/Block/Html/TopmenuTest.php
index b2337e652b90f..53368d379d05f 100755
--- a/app/code/Magento/Theme/Test/Unit/Block/Html/TopmenuTest.php
+++ b/app/code/Magento/Theme/Test/Unit/Block/Html/TopmenuTest.php
@@ -455,7 +455,7 @@ public function testColumnBrakeWithoutItem(): void
             ],
             [
                 'place' => 4,
-                'colbrake' => true
+                'colbrake' => false
             ]
         ];