@@ -589,6 +589,71 @@ export const isWprRelatedError = async(contents: string): Promise<boolean> => {
589589 return false ;
590590}
591591
592+
593+ /**
594+ * Checks if the mobile menu is currently open
595+ * This is useful for validating mobile menu state before attempting to open it
596+ *
597+ * @param {Page } page - The Playwright page instance to check
598+ * @returns {Promise<boolean> } - A Promise that resolves to true if menu is open, false otherwise
599+ *
600+ * @example
601+ * ```typescript
602+ * const isOpen = await isMobileMenuOpen(page);
603+ * if (isOpen) {
604+ * console.log('Menu is already open');
605+ * }
606+ * ```
607+ */
608+ export const isMobileMenuOpen = async ( page : Page ) : Promise < boolean > => {
609+ await page . waitForTimeout ( 5000 ) ;
610+ return await page . evaluate ( ( ) => {
611+ const candidates = Array . from ( document . querySelectorAll < HTMLElement > (
612+ 'nav, .mobile-menu, .mobile-navigation, #mobile-menu, .et_mobile_menu, [id*=mobile-menu]'
613+ ) ) ;
614+
615+ for ( const menu of candidates ) {
616+ const style = window . getComputedStyle ( menu ) ;
617+ const rect = menu . getBoundingClientRect ( ) ;
618+
619+ // Skip invisible elements
620+ if (
621+ style . display === 'none' ||
622+ style . visibility === 'hidden' ||
623+ Number ( style . opacity ) === 0
624+ ) continue ;
625+
626+ // Check if there is a transform
627+ const transform = style . transform ;
628+ if ( transform && transform !== 'none' ) {
629+ // Parse the matrix and check if it's fully translated offscreen
630+ const values = transform . match ( / m a t r i x .* \( ( .+ ) \) / ) ?. [ 1 ] . split ( ',' ) . map ( Number ) ;
631+ if ( values ) {
632+ const translateX = values . length === 6 ? values [ 4 ] : 0 ;
633+ const translateY = values . length === 6 ? values [ 5 ] : 0 ;
634+
635+ // If fully off-screen, menu is closed
636+ if ( translateX <= - window . innerWidth || translateY <= - window . innerHeight ) continue ;
637+ }
638+ }
639+
640+ // Check if element is large enough to be considered open
641+ const coversScreen = rect . width >= window . innerWidth * 0.3 && rect . height >= window . innerHeight * 0.3 ;
642+ if ( coversScreen ) return true ;
643+ }
644+
645+ // Fallback: toggle button aria-expanded
646+ const toggles = document . querySelectorAll < HTMLElement > (
647+ '.menu-toggle, .nav-toggle, .hamburger, .mobile_menu_bar, .et_mobile_menu'
648+ ) ;
649+ for ( const toggle of toggles ) {
650+ if ( toggle . getAttribute ( 'aria-expanded' ) === 'true' ) return true ;
651+ }
652+
653+ return false ;
654+ } ) ;
655+ } ;
656+
592657/**
593658 * Opens the mobile menu by finding and clicking toggle buttons
594659 * This is useful for testing mobile menu functionality
0 commit comments