dropdownLink.spec.jsx 7.8 KB

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