import {mountWithTheme} from 'sentry-test/enzyme'; import DeprecatedDropdownMenu from 'sentry/components/deprecatedDropdownMenu'; jest.useFakeTimers(); describe('dropdownMenuDeprecated', function () { let wrapper; beforeEach(function () { wrapper = mountWithTheme( <DeprecatedDropdownMenu> {({getRootProps, getActorProps, getMenuProps, isOpen}) => ( <span {...getRootProps({})}> <button {...getActorProps({})}>Open Dropdown</button> {isOpen && ( <ul {...getMenuProps({})}> <li>Dropdown Menu Item 1</li> </ul> )} </span> )} </DeprecatedDropdownMenu> ); }); it('renders', function () { expect(wrapper).toSnapshot(); }); it('can toggle dropdown menu with actor', function () { wrapper.find('button').simulate('click'); expect(wrapper.state('isOpen')).toBe(true); expect(wrapper.find('ul')).toHaveLength(1); wrapper.find('button').simulate('click'); expect(wrapper.state('isOpen')).toBe(false); expect(wrapper.find('ul')).toHaveLength(0); }); it('closes dropdown when clicking on anything in menu', function () { wrapper.find('button').simulate('click'); wrapper.find('li').simulate('click'); expect(wrapper.state('isOpen')).toBe(false); expect(wrapper.find('ul')).toHaveLength(0); }); it('closes dropdown when clicking outside of menu', async function () { wrapper.find('button').simulate('click'); // Simulate click on document const event = document.createEvent('HTMLEvents'); event.initEvent('click', false, true); document.body.dispatchEvent(event); jest.runAllTimers(); await Promise.resolve(); wrapper.update(); expect(wrapper.find('ul')).toHaveLength(0); }); it('closes dropdown when pressing escape', function () { wrapper.find('button').simulate('click'); expect(wrapper.state('isOpen')).toBe(true); wrapper.simulate('keyDown', {key: 'Escape'}); wrapper.find('button').simulate('keyDown', {key: 'Escape'}); expect(wrapper.state('isOpen')).toBe(false); expect(wrapper.find('ul')).toHaveLength(0); }); it('ignores "Escape" key if `closeOnEscape` is false', function () { wrapper = mountWithTheme( <DeprecatedDropdownMenu closeOnEscape={false}> {({getRootProps, getActorProps, getMenuProps, isOpen}) => ( <span {...getRootProps({})}> <button {...getActorProps({})}>Open Dropdown</button> {isOpen && ( <ul {...getMenuProps({})}> <li>Dropdown Menu Item 1</li> </ul> )} </span> )} </DeprecatedDropdownMenu> ); wrapper.find('button').simulate('click'); expect(wrapper.state('isOpen')).toBe(true); wrapper.find('button').simulate('keyDown', {key: 'Escape'}); expect(wrapper.find('ul')).toHaveLength(1); expect(wrapper.state('isOpen')).toBe(true); }); it('keeps dropdown open when clicking on anything in menu with `keepMenuOpen` prop', function () { wrapper = mountWithTheme( <DeprecatedDropdownMenu keepMenuOpen> {({getRootProps, getActorProps, getMenuProps, isOpen}) => ( <span {...getRootProps({})}> <button {...getActorProps({})}>Open Dropdown</button> {isOpen && ( <ul {...getMenuProps({})}> <li>Dropdown Menu Item 1</li> </ul> )} </span> )} </DeprecatedDropdownMenu> ); wrapper.find('button').simulate('click'); wrapper.find('li').simulate('click'); expect(wrapper.state('isOpen')).toBe(true); expect(wrapper.find('ul')).toHaveLength(1); }); it('render prop getters all extend props and call original onClick handlers', function () { const rootClick = jest.fn(); const actorClick = jest.fn(); const menuClick = jest.fn(); const addSpy = jest.spyOn(document, 'addEventListener'); const removeSpy = jest.spyOn(document, 'removeEventListener'); wrapper = mountWithTheme( <DeprecatedDropdownMenu keepMenuOpen> {({getRootProps, getActorProps, getMenuProps, isOpen}) => ( <span {...getRootProps({ className: 'root', onClick: rootClick, })} > <button {...getActorProps({ className: 'actor', onClick: actorClick, })} > Open Dropdown </button> {isOpen && ( <ul {...getMenuProps({ className: 'menu', onClick: menuClick, })} > <li>Dropdown Menu Item 1</li> </ul> )} </span> )} </DeprecatedDropdownMenu> ); expect(wrapper.find('ul')).toHaveLength(0); wrapper.find('span').simulate('click'); expect(rootClick).toHaveBeenCalled(); wrapper.find('button').simulate('click'); expect(actorClick).toHaveBeenCalled(); wrapper.find('li').simulate('click'); expect(menuClick).toHaveBeenCalled(); // breaks in jest22 // expect(wrapper).toSnapshot(); expect(wrapper.find('ul')).toHaveLength(1); expect(document.addEventListener).toHaveBeenCalled(); wrapper.unmount(); expect(document.removeEventListener).toHaveBeenCalled(); addSpy.mockRestore(); removeSpy.mockRestore(); }); it('always rendered menus should attach document event listeners only when opened', function () { const addSpy = jest.spyOn(document, 'addEventListener'); const removeSpy = jest.spyOn(document, 'removeEventListener'); wrapper = mountWithTheme( <DeprecatedDropdownMenu alwaysRenderMenu> {({getRootProps, getActorProps, getMenuProps}) => ( <span {...getRootProps({ className: 'root', })} > <button {...getActorProps({ className: 'actor', })} > Open Dropdown </button> <ul {...getMenuProps({ className: 'menu', })} > <li>Dropdown Menu Item 1</li> </ul> </span> )} </DeprecatedDropdownMenu> ); // Make sure this is only called when menu is open expect(document.addEventListener).not.toHaveBeenCalled(); wrapper.find('button').simulate('click'); expect(wrapper.state('isOpen')).toBe(true); expect(document.addEventListener).toHaveBeenCalled(); expect(document.removeEventListener).not.toHaveBeenCalled(); wrapper.find('button').simulate('click'); expect(wrapper.state('isOpen')).toBe(false); expect(document.removeEventListener).toHaveBeenCalled(); addSpy.mockRestore(); removeSpy.mockRestore(); }); it('does not close nested dropdown on actor clicks', function () { wrapper = mountWithTheme( <DeprecatedDropdownMenu isNestedDropdown> {({getRootProps, getActorProps, getMenuProps}) => ( <span {...getRootProps({})}> <button {...getActorProps({})}>Open Dropdown</button> { <ul {...getMenuProps({})}> <li data-test-id="menu-item">Dropdown Menu Item 1</li> </ul> } </span> )} </DeprecatedDropdownMenu> ); wrapper.find('button').simulate('mouseEnter'); expect(wrapper.find('[data-test-id="menu-item"]')).toHaveLength(1); wrapper.find('button').simulate('click'); // Should still be visible. expect(wrapper.find('[data-test-id="menu-item"]')).toHaveLength(1); }); });