From 8d467908da27a6e523af3bbfc5b6cb3bef6385a3 Mon Sep 17 00:00:00 2001 From: girishpanchal30 Date: Fri, 7 Aug 2026 13:11:58 +0530 Subject: [PATCH 1/7] fix: prevent duplicate footer menu IDs --- .../hfg/footer-menu-both-devices-setup.json | 4 ++ .../hfg/hfg-footer-menu-unique-id.spec.ts | 63 +++++++++++++++++++ .../Core/Components/NavFooter.php | 2 +- .../components/component-nav-footer.php | 9 ++- 4 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 e2e-tests/fixtures/customizer/hfg/footer-menu-both-devices-setup.json create mode 100644 e2e-tests/specs/customizer/hfg/hfg-footer-menu-unique-id.spec.ts diff --git a/e2e-tests/fixtures/customizer/hfg/footer-menu-both-devices-setup.json b/e2e-tests/fixtures/customizer/hfg/footer-menu-both-devices-setup.json new file mode 100644 index 0000000000..7845b249f7 --- /dev/null +++ b/e2e-tests/fixtures/customizer/hfg/footer-menu-both-devices-setup.json @@ -0,0 +1,4 @@ +{ + "hfg_footer_layout_v2": "{\"desktop\":{\"top\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]},\"main\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]},\"bottom\":{\"left\":[],\"c-left\":[],\"center\":[{\"id\":\"footer-menu\"}],\"c-right\":[],\"right\":[]}},\"mobile\":{\"top\":{\"left\":[],\"c-left\":[],\"center\":[{\"id\":\"footer-menu\"}],\"c-right\":[],\"right\":[]},\"main\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]},\"bottom\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]}}}", + "nav_menu_locations[footer]": 177 +} diff --git a/e2e-tests/specs/customizer/hfg/hfg-footer-menu-unique-id.spec.ts b/e2e-tests/specs/customizer/hfg/hfg-footer-menu-unique-id.spec.ts new file mode 100644 index 0000000000..cb35677d50 --- /dev/null +++ b/e2e-tests/specs/customizer/hfg/hfg-footer-menu-unique-id.spec.ts @@ -0,0 +1,63 @@ +import { test, expect } from '@playwright/test'; +import { setCustomizeSettings } from '../../../utils'; +import data from '../../../fixtures/customizer/hfg/footer-menu-both-devices-setup.json'; + +test.describe( + 'Footer Menu component in both desktop and mobile layouts', + function () { + test.beforeAll(async ({ request, baseURL }) => { + await setCustomizeSettings('hfgFooterMenuBothDevices', data, { + request, + baseURL, + }); + }); + + test('Both layout variants are rendered', async ({ page }) => { + await page.goto('/?test_name=hfgFooterMenuBothDevices'); + + await expect( + page.locator( + '.hfg_footer .footer--row[data-show-on="desktop"] .nav-menu-footer' + ) + ).toHaveCount(1); + + await expect( + page.locator( + '.hfg_footer .footer--row[data-show-on="mobile"] .nav-menu-footer' + ) + ).toHaveCount(1); + }); + + test('Menu IDs are unique across the whole document', async ({ + page, + }) => { + await page.goto('/?test_name=hfgFooterMenuBothDevices'); + + await expect(page.locator('ul#footer-menu')).toHaveCount(0); + await expect( + page.locator('ul#footer-menu-desktop-bottom') + ).toHaveCount(1); + await expect(page.locator('ul#footer-menu-mobile-top')).toHaveCount( + 1 + ); + + const duplicated = await page.evaluate(() => { + const ids = Array.from( + document.querySelectorAll('.hfg_footer [id]') + ).map((el) => el.id); + + return ids.filter((id, index) => ids.indexOf(id) !== index); + }); + + expect(duplicated).toEqual([]); + }); + + test('The footer-menu class is kept for styling', async ({ page }) => { + await page.goto('/?test_name=hfgFooterMenuBothDevices'); + + await expect( + page.locator('.hfg_footer ul.footer-menu') + ).toHaveCount(2); + }); + } +); diff --git a/header-footer-grid/Core/Components/NavFooter.php b/header-footer-grid/Core/Components/NavFooter.php index 927136b7c6..839eea3488 100644 --- a/header-footer-grid/Core/Components/NavFooter.php +++ b/header-footer-grid/Core/Components/NavFooter.php @@ -124,7 +124,7 @@ public function add_settings() { 'fallback' => 'inherit', ], [ - 'selector' => '.builder-item--' . $this->get_id() . ' .nav-menu-footer:not(.style-full-height) #footer-menu li:hover > a', + 'selector' => '.builder-item--' . $this->get_id() . ' .nav-menu-footer:not(.style-full-height) .footer-menu li:hover > a', 'prop' => 'color', 'fallback' => 'inherit', ], diff --git a/header-footer-grid/templates/components/component-nav-footer.php b/header-footer-grid/templates/components/component-nav-footer.php index 8e05102679..f9c40ae9a5 100644 --- a/header-footer-grid/templates/components/component-nav-footer.php +++ b/header-footer-grid/templates/components/component-nav-footer.php @@ -19,6 +19,13 @@ $container_classes[] = 'm-style'; } +$menu_id = NavFooter::COMPONENT_ID; +$device = current_device(); +$row = current_row(); +if ( ! empty( $device ) && ! empty( $row ) ) { + $menu_id .= '-' . $device . '-' . $row; +} + ?>