import React from 'react'; import { describe, it, expect, vi } from 'vitest'; import { render, fireEvent } from '@testing-library/react'; import { PixelNavigationMenu, type PixelNavigationMenuItem } from '../../navigation/PixelNavigationMenu'; const baseItems: PixelNavigationMenuItem[] = [ { label: 'Home', href: '/' }, { label: 'Products', content:
Products mega panel
, }, { label: 'Resources', content:
Resources mega panel
, }, ]; describe('PixelNavigationMenu', () => { it('renders nav with items', () => { const { getAllByRole, getByText } = render( , ); expect(getByText('Home')).toBeTruthy(); expect(getByText('Products')).toBeTruthy(); expect(getByText('Resources')).toBeTruthy(); const menuitems = getAllByRole('menuitem'); expect(menuitems.length).toBe(3); }); it('hovering item with content shows panel', () => { const { getByText, queryByTestId, getByTestId } = render( , ); // Panel hidden initially. expect(queryByTestId('products-panel')).toBeNull(); fireEvent.mouseEnter(getByText('Products')); // Panel now visible. expect(getByTestId('products-panel')).toBeTruthy(); }); it('orientation=vertical applies vertical layout', () => { const { getByRole } = render( , ); // aria-orientation belongs on the menubar, not the nav landmark // (aria-allowed-attr: navigation does not support aria-orientation). const nav = getByRole('navigation'); expect(nav.getAttribute('aria-orientation')).toBeNull(); const menubar = getByRole('menubar'); expect(menubar.getAttribute('aria-orientation')).toBe('vertical'); }); it('navigation role applied', () => { const { getByRole } = render(); const nav = getByRole('navigation'); expect(nav).toBeTruthy(); expect(nav.tagName.toLowerCase()).toBe('nav'); }); it('keyboard tab navigates between items', () => { const onSelect = vi.fn(); const items: PixelNavigationMenuItem[] = [ { label: 'A', onSelect }, { label: 'B', onSelect: vi.fn() }, ]; const { getAllByRole } = render(); const menuitems = getAllByRole('menuitem'); // Both items reachable via tab order (tabIndex >= 0). menuitems.forEach((mi) => { const ti = mi.getAttribute('tabindex'); expect(ti === null || Number(ti) >= 0).toBe(true); }); // Pressing Enter on first activates onSelect. (menuitems[0] as HTMLElement).focus(); fireEvent.keyDown(menuitems[0], { key: 'Enter' }); expect(onSelect).toHaveBeenCalled(); }); it('items with content advertise aria-expanded', () => { const { getByText } = render(); const productsTrigger = getByText('Products').closest('[role="menuitem"]')!; expect(productsTrigger.getAttribute('aria-expanded')).toBe('false'); fireEvent.mouseEnter(getByText('Products')); expect(productsTrigger.getAttribute('aria-expanded')).toBe('true'); }); it('clicking item with href works as anchor', () => { const { getByText } = render(); const home = getByText('Home').closest('a, [role="menuitem"]'); expect(home).toBeTruthy(); // Home is rendered as anchor because it has href. expect((home as HTMLElement).tagName.toLowerCase()).toBe('a'); expect((home as HTMLAnchorElement).getAttribute('href')).toBe('/'); }); it('viewport=false renders panels inline (no shared viewport)', () => { const { getByText, getByTestId } = render( , ); fireEvent.mouseEnter(getByText('Products')); expect(getByTestId('products-panel')).toBeTruthy(); }); });