0
0
mirror of https://github.com/naturalcrit/homebrewery.git synced 2026-08-06 11:07:37 +00:00
Files
homebrewery/client/components/dropdown/dropdown.behavior.test.jsx
T
Gazook89 fa07af2d82 Add tests for the Dropdown structure and behavior
Largely this is written by an LLM after I provided the targets, and I've looked through the tests themselves to confirm they are accurate.  There may be improvements in how to actually *set up* the tests, though, as I am less familiar with those.

This has two test suites:  the first for html structure, the second for behavior.  Each of them calls another script that provides helper functions for setting things up and taking them down.  This keeps the test suites themselves fairly lean.
2026-05-29 11:08:05 -05:00

127 lines
4.1 KiB
React

import React from 'react';
import { Dropdown } from './dropdown.jsx';
import { createOpenMenu, renderDropdown, setupDropdownTestLifecycle } from './dropdown.testUtils.js';
setupDropdownTestLifecycle();
describe('Dropdown behavior', ()=>{
it('calls child click handlers when menu items are clicked', async ()=>{
const onClick = jest.fn();
const { host, cleanup } = await renderDropdown(
<Dropdown groupName='Events'>
<button className='menu-item' role='menuitem' onClick={onClick}>Click Me</button>
</Dropdown>
);
host.querySelector('.menu-list .menu-item').click();
expect(onClick).toHaveBeenCalledTimes(1);
await cleanup();
});
it('dismisses open menus when clicking a normal menu action', async ()=>{
const openMenu1 = createOpenMenu();
const openMenu2 = createOpenMenu();
const querySpy = jest.spyOn(document, 'querySelectorAll').mockImplementation((selector)=>{
if(selector === '.menu-list:popover-open') return [openMenu1, openMenu2];
return [];
});
const { host, cleanup } = await renderDropdown(
<Dropdown groupName='Dismiss'>
<button className='menu-item' role='menuitem'>Close</button>
</Dropdown>
);
host.querySelector('.menu-list .menu-item').click();
expect(querySpy).toHaveBeenCalledWith('.menu-list:popover-open');
expect(openMenu1.hidePopover).toHaveBeenCalledTimes(1);
expect(openMenu2.hidePopover).toHaveBeenCalledTimes(1);
await cleanup();
});
it('does not dismiss when no-dismiss is set to empty string or true', async ()=>{
for (const noDismissValue of ['', 'true']) {
const openMenu = createOpenMenu();
const querySpy = jest.spyOn(document, 'querySelectorAll').mockImplementation((selector)=>{
if(selector === '.menu-list:popover-open') return [openMenu];
return [];
});
const { host, cleanup } = await renderDropdown(
<Dropdown groupName={`No Dismiss ${noDismissValue || 'empty'}`}>
<button className='menu-item' role='menuitem' no-dismiss={noDismissValue}>Stay Open</button>
</Dropdown>
);
host.querySelector('.menu-list .menu-item').click();
expect(querySpy).not.toHaveBeenCalled();
expect(openMenu.hidePopover).not.toHaveBeenCalled();
await cleanup();
querySpy.mockRestore();
}
});
it('does dismiss when no-dismiss is explicitly false', async ()=>{
const openMenu = createOpenMenu();
const querySpy = jest.spyOn(document, 'querySelectorAll').mockImplementation((selector)=>{
if(selector === '.menu-list:popover-open') return [openMenu];
return [];
});
const { host, cleanup } = await renderDropdown(
<Dropdown groupName='No Dismiss False'>
<button className='menu-item' role='menuitem' no-dismiss='false'>Close</button>
</Dropdown>
);
host.querySelector('.menu-list .menu-item').click();
expect(querySpy).toHaveBeenCalledWith('.menu-list:popover-open');
expect(openMenu.hidePopover).toHaveBeenCalledTimes(1);
await cleanup();
});
it('does not dismiss when clicking submenu trigger actions', async ()=>{
const querySpy = jest.spyOn(document, 'querySelectorAll');
const { host, cleanup } = await renderDropdown(
<Dropdown groupName='Top'>
<Dropdown groupName='Child'>
<button className='menu-item' role='menuitem'>Leaf</button>
</Dropdown>
</Dropdown>
);
const submenuTrigger = host.querySelectorAll('.menu-wrapper > .menu-item')[1];
submenuTrigger.click();
expect(submenuTrigger.hasAttribute('popovertarget')).toBe(true);
expect(querySpy).not.toHaveBeenCalledWith('.menu-list:popover-open');
await cleanup();
});
it('handles iframe-click by hiding the open popover for this menu', async ()=>{
const { host, cleanup } = await renderDropdown(
<Dropdown groupName='Iframe Dismiss'>
<button className='menu-item' role='menuitem'>Item</button>
</Dropdown>
);
const menu = host.querySelector('.menu-list');
menu.matches = jest.fn((selector)=>selector === ':popover-open');
menu.hidePopover = jest.fn();
document.dispatchEvent(new Event('iframe-click'));
expect(menu.matches).toHaveBeenCalledWith(':popover-open');
expect(menu.hidePopover).toHaveBeenCalledTimes(1);
await cleanup();
});
});