import {mountWithTheme} from 'sentry-test/enzyme'; import DropdownLink from 'sentry/components/dropdownLink'; import {MENU_CLOSE_DELAY} from 'sentry/constants'; jest.useFakeTimers(); describe('DropdownLink', function () { const INPUT_1 = { title: 'test', onOpen: () => {}, onClose: () => {}, topLevelClasses: 'top-level-class', alwaysRenderMenu: true, menuClasses: '', }; describe('renders', function () { it('and anchors to left by default', function () { const component = mountWithTheme(
1
2
); expect(component).toSnapshot(); }); it('and anchors to right', function () { const component = mountWithTheme(
1
2
); expect(component).toSnapshot(); }); }); describe('Uncontrolled', function () { let wrapper; beforeEach(function () { if (wrapper) { wrapper.unmount(); } wrapper = mountWithTheme(
  • hi
  • ); }); describe('While Closed', function () { it('displays dropdown menu when dropdown actor button clicked', function () { expect(wrapper.find('li')).toHaveLength(0); // open wrapper.find('a').simulate('click'); expect(wrapper.find('li')).toHaveLength(1); }); }); describe('While Opened', function () { beforeEach(function () { // Opens dropdown menu wrapper.find('a').simulate('click'); }); it('closes when clicked outside', async function () { const evt = document.createEvent('HTMLEvents'); evt.initEvent('click', false, true); document.body.dispatchEvent(evt); jest.runAllTimers(); await Promise.resolve(); wrapper.update(); expect(wrapper.find('li')).toHaveLength(0); }); it('closes when dropdown actor button is clicked', function () { wrapper.find('a').simulate('click'); expect(wrapper.find('li')).toHaveLength(0); }); it('closes when dropdown menu item is clicked', function () { wrapper.find('li').simulate('click'); expect(wrapper.find('li')).toHaveLength(0); }); it('does not close when menu is clicked and `keepMenuOpen` is on', function () { wrapper = mountWithTheme(
  • hi
  • ); wrapper.find('a').simulate('click'); wrapper.find('li').simulate('click'); expect(wrapper.find('li')).toHaveLength(1); wrapper.unmount(); }); }); }); describe('Controlled', function () { let wrapper; beforeEach(function () { if (wrapper) { wrapper.unmount(); } }); describe('Opened', function () { beforeEach(function () { wrapper = mountWithTheme(
  • hi
  • ); }); it('does not close when menu is clicked', function () { // open wrapper.find('li').simulate('click'); // State does not change expect(wrapper.find('.dropdown-menu')).toHaveLength(1); }); it('does not close when document is clicked', function () { const evt = document.createEvent('HTMLEvents'); evt.initEvent('click', false, true); document.body.dispatchEvent(evt); // State does not change expect(wrapper.find('.dropdown-menu')).toHaveLength(1); }); it('does not close when dropdown actor is clicked', function () { wrapper.find('a').simulate('click'); // State does not change expect(wrapper.find('.dropdown-menu')).toHaveLength(1); }); }); describe('Closed', function () { beforeEach(function () { wrapper = mountWithTheme(
  • hi
  • ); }); it('does not open when dropdown actor is clicked', function () { wrapper.find('a').simulate('click'); // State does not change expect(wrapper.find('.dropdown-menu')).toHaveLength(0); }); }); }); describe('Nested Dropdown', function () { let wrapper; beforeEach(function () { if (wrapper) { wrapper.unmount(); } wrapper = mountWithTheme(
  • Hello
  • Item 2
  • ); // Start when menu open wrapper.find('a').simulate('click'); }); it('closes when top-level actor is clicked', function () { wrapper.find('a').first().simulate('click'); expect(wrapper.find('.dropdown-menu')).toHaveLength(0); }); it('Opens / closes on mouse enter and leave', function () { // Nested menus have delay on open wrapper.find('.dropdown-menu a').simulate('mouseEnter'); jest.runAllTimers(); wrapper.update(); expect(wrapper.find('.dropdown-menu')).toHaveLength(2); // Leaving Nested Menu wrapper.find('a.nested-menu').simulate('mouseLeave'); // Nested menus have close delay expect(wrapper.find('.dropdown-menu')).toHaveLength(2); jest.advanceTimersByTime(MENU_CLOSE_DELAY - 1); wrapper.update(); // Re-entering nested menu will cancel close expect(wrapper.find('.dropdown-menu')).toHaveLength(2); wrapper.find('a.nested-menu').simulate('mouseEnter'); jest.advanceTimersByTime(2); wrapper.update(); expect(wrapper.find('.dropdown-menu')).toHaveLength(2); // Re-entering an actor will also cancel close expect(wrapper.find('.dropdown-menu')).toHaveLength(2); jest.advanceTimersByTime(MENU_CLOSE_DELAY - 1); wrapper.update(); wrapper.find('.dropdown-menu a').first().simulate('mouseEnter'); jest.advanceTimersByTime(2); wrapper.update(); expect(wrapper.find('.dropdown-menu')).toHaveLength(2); // Leave menu wrapper.find('a.nested-menu').simulate('mouseLeave'); jest.runAllTimers(); wrapper.update(); expect(wrapper.find('.dropdown-menu')).toHaveLength(1); }); it('closes when first level nested actor is clicked', function () { wrapper.find('#nested-actor').simulate('click'); expect(wrapper.find('.dropdown-menu')).toHaveLength(0); }); it('does not close when second level nested actor is clicked', function () { wrapper.find('a.nested-menu').simulate('mouseEnter'); jest.runAllTimers(); wrapper.update(); wrapper.find('a.nested-menu-2').simulate('click'); expect(wrapper.find('.dropdown-menu')).toHaveLength(2); }); it('closes when third level nested actor is clicked', function () { wrapper.find('a.nested-menu').simulate('mouseEnter'); jest.runAllTimers(); wrapper.update(); wrapper.find('a.nested-menu-2').simulate('mouseEnter'); jest.runAllTimers(); wrapper.update(); wrapper.find('#nested-actor-3').simulate('click'); expect(wrapper.find('.dropdown-menu')).toHaveLength(0); }); }); });