dropdownLink.spec.jsx 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. import $ from 'jquery';
  2. import React from 'react';
  3. import {mount} from 'enzyme';
  4. import DropdownLink from 'app/components/dropdownLink';
  5. import {MENU_CLOSE_DELAY} from 'app/constants';
  6. jest.useFakeTimers();
  7. describe('DropdownLink', function() {
  8. const INPUT_1 = {
  9. title: 'test',
  10. onOpen: () => {},
  11. onClose: () => {},
  12. topLevelClasses: 'top-level-class',
  13. alwaysRenderMenu: true,
  14. menuClasses: '',
  15. };
  16. describe('renders', function() {
  17. it('and anchors to left by default', function() {
  18. const component = mount(
  19. <DropdownLink {...INPUT_1}>
  20. <div>1</div>
  21. <div>2</div>
  22. </DropdownLink>
  23. );
  24. expect(component).toMatchSnapshot();
  25. });
  26. it('and anchors to right', function() {
  27. const component = mount(
  28. <DropdownLink {...INPUT_1} anchorRight>
  29. <div>1</div>
  30. <div>2</div>
  31. </DropdownLink>
  32. );
  33. expect(component).toMatchSnapshot();
  34. });
  35. });
  36. describe('Uncontrolled', function() {
  37. let wrapper;
  38. beforeEach(function() {
  39. if (wrapper) {
  40. wrapper.unmount();
  41. }
  42. wrapper = mount(
  43. <DropdownLink alwaysRenderMenu={false} title="test">
  44. <li>hi</li>
  45. </DropdownLink>
  46. );
  47. });
  48. describe('While Closed', function() {
  49. it('displays dropdown menu when dropdown actor button clicked', function() {
  50. expect(wrapper.find('li')).toHaveLength(0);
  51. // open
  52. wrapper.find('a').simulate('click');
  53. expect(wrapper.find('li')).toHaveLength(1);
  54. });
  55. });
  56. describe('While Opened', function() {
  57. beforeEach(function() {
  58. // Opens dropdown menu
  59. wrapper.find('a').simulate('click');
  60. });
  61. it('closes when clicked outside', function() {
  62. const evt = document.createEvent('HTMLEvents');
  63. evt.initEvent('click', false, true);
  64. document.body.dispatchEvent(evt);
  65. wrapper.update();
  66. expect(wrapper.find('li')).toHaveLength(0);
  67. });
  68. it('closes when dropdown actor button is clicked', function() {
  69. wrapper.find('a').simulate('click');
  70. expect(wrapper.find('li')).toHaveLength(0);
  71. });
  72. it('closes when dropdown menu item is clicked', function() {
  73. wrapper.find('li').simulate('click');
  74. expect(wrapper.find('li')).toHaveLength(0);
  75. });
  76. it('does not close when menu is clicked and `keepMenuOpen` is on', function() {
  77. wrapper = mount(
  78. <DropdownLink title="test" alwaysRenderMenu={false} keepMenuOpen>
  79. <li>hi</li>
  80. </DropdownLink>
  81. );
  82. wrapper.find('a').simulate('click');
  83. wrapper.find('li').simulate('click');
  84. expect(wrapper.find('li')).toHaveLength(1);
  85. wrapper.unmount();
  86. });
  87. });
  88. });
  89. describe('Controlled', function() {
  90. let wrapper;
  91. beforeEach(function() {
  92. if (wrapper) {
  93. wrapper.unmount();
  94. }
  95. });
  96. describe('Opened', function() {
  97. beforeEach(function() {
  98. wrapper = mount(
  99. <DropdownLink isOpen={true} alwaysRenderMenu={false} title="test">
  100. <li>hi</li>
  101. </DropdownLink>
  102. );
  103. });
  104. it('does not close when menu is clicked', function() {
  105. // open
  106. wrapper.find('li').simulate('click');
  107. // State does not change
  108. expect(wrapper.find('.dropdown-menu')).toHaveLength(1);
  109. });
  110. it('does not close when document is clicked', function() {
  111. $(document).click();
  112. // State does not change
  113. expect(wrapper.find('.dropdown-menu')).toHaveLength(1);
  114. });
  115. it('does not close when dropdown actor is clicked', function() {
  116. wrapper.find('a').simulate('click');
  117. // State does not change
  118. expect(wrapper.find('.dropdown-menu')).toHaveLength(1);
  119. });
  120. });
  121. describe('Closed', function() {
  122. beforeEach(function() {
  123. wrapper = mount(
  124. <DropdownLink isOpen={false} alwaysRenderMenu={false} title="test">
  125. <li>hi</li>
  126. </DropdownLink>
  127. );
  128. });
  129. it('does not open when dropdown actor is clicked', function() {
  130. wrapper.find('a').simulate('click');
  131. // State does not change
  132. expect(wrapper.find('.dropdown-menu')).toHaveLength(0);
  133. });
  134. });
  135. });
  136. describe('Nested Dropdown', function() {
  137. let wrapper;
  138. beforeEach(function() {
  139. if (wrapper) {
  140. wrapper.unmount();
  141. }
  142. wrapper = mount(
  143. <DropdownLink title="parent" alwaysRenderMenu={false}>
  144. <li id="nested-actor">
  145. <DropdownLink
  146. className="nested-menu"
  147. alwaysRenderMenu={false}
  148. title="nested"
  149. isNestedDropdown={true}
  150. >
  151. <li id="nested-actor-2">
  152. <DropdownLink
  153. className="nested-menu-2"
  154. alwaysRenderMenu={false}
  155. title="nested #2"
  156. isNestedDropdown={true}
  157. >
  158. <li id="nested-actor-3">Hello</li>
  159. </DropdownLink>
  160. </li>
  161. </DropdownLink>
  162. </li>
  163. <li id="no-nest">Item 2</li>
  164. </DropdownLink>
  165. );
  166. // Start when menu open
  167. wrapper.find('a').simulate('click');
  168. });
  169. it('closes when top-level actor is clicked', function() {
  170. wrapper
  171. .find('a')
  172. .first()
  173. .simulate('click');
  174. expect(wrapper.find('.dropdown-menu')).toHaveLength(0);
  175. });
  176. it('Opens / closes on mouse enter and leave', function() {
  177. // Nested menus have delay on open
  178. wrapper.find('.dropdown-menu a').simulate('mouseEnter');
  179. jest.runAllTimers();
  180. wrapper.update();
  181. expect(wrapper.find('.dropdown-menu')).toHaveLength(2);
  182. // Leaving Nested Menu
  183. wrapper.find('a.nested-menu').simulate('mouseLeave');
  184. // Nested menus have close delay
  185. expect(wrapper.find('.dropdown-menu')).toHaveLength(2);
  186. jest.advanceTimersByTime(MENU_CLOSE_DELAY - 1);
  187. wrapper.update();
  188. // Re-entering nested menu will cancel close
  189. expect(wrapper.find('.dropdown-menu')).toHaveLength(2);
  190. wrapper.find('a.nested-menu').simulate('mouseEnter');
  191. jest.advanceTimersByTime(2);
  192. wrapper.update();
  193. expect(wrapper.find('.dropdown-menu')).toHaveLength(2);
  194. // Re-entering an actor will also cancel close
  195. expect(wrapper.find('.dropdown-menu')).toHaveLength(2);
  196. jest.advanceTimersByTime(MENU_CLOSE_DELAY - 1);
  197. wrapper.update();
  198. wrapper
  199. .find('.dropdown-menu a')
  200. .first()
  201. .simulate('mouseEnter');
  202. jest.advanceTimersByTime(2);
  203. wrapper.update();
  204. expect(wrapper.find('.dropdown-menu')).toHaveLength(2);
  205. // Leave menu
  206. wrapper.find('a.nested-menu').simulate('mouseLeave');
  207. jest.runAllTimers();
  208. wrapper.update();
  209. expect(wrapper.find('.dropdown-menu')).toHaveLength(1);
  210. });
  211. it('closes when first level nested actor is clicked', function() {
  212. wrapper.find('#nested-actor').simulate('click');
  213. expect(wrapper.find('.dropdown-menu')).toHaveLength(0);
  214. });
  215. it('closes when second level nested actor is clicked', function() {
  216. wrapper.find('a.nested-menu').simulate('mouseEnter');
  217. jest.runAllTimers();
  218. wrapper.update();
  219. wrapper.find('a.nested-menu-2 span').simulate('click');
  220. expect(wrapper.find('.dropdown-menu')).toHaveLength(0);
  221. });
  222. it('closes when third level nested actor is clicked', function() {
  223. wrapper.find('a.nested-menu').simulate('mouseEnter');
  224. jest.runAllTimers();
  225. wrapper.update();
  226. wrapper.find('a.nested-menu-2').simulate('mouseEnter');
  227. jest.runAllTimers();
  228. wrapper.update();
  229. wrapper.find('#nested-actor-3').simulate('click');
  230. expect(wrapper.find('.dropdown-menu')).toHaveLength(0);
  231. });
  232. });
  233. });