dropdownMenuControl.spec.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary';
  2. import DropdownMenuControl from './dropdownMenuControl';
  3. describe('DropdownMenu', function () {
  4. it('renders a basic menu', function () {
  5. const onAction = jest.fn();
  6. render(
  7. <DropdownMenuControl
  8. items={[
  9. {
  10. key: 'item1',
  11. label: 'Item One',
  12. details: 'This is the first item',
  13. onAction,
  14. },
  15. {
  16. key: 'item2',
  17. label: 'Item Two',
  18. details: 'Another description here',
  19. },
  20. ]}
  21. triggerLabel="This is a Menu"
  22. />
  23. );
  24. // Open the mneu
  25. userEvent.click(screen.getByRole('button', {name: 'This is a Menu'}));
  26. // The mneu is open
  27. expect(screen.getByRole('menu')).toBeInTheDocument();
  28. // There are two menu items
  29. //
  30. // TODO(epurkhiser): These should really be menuitem roles NOT
  31. // menuitemradio's. But react-aria is setting this for us (probably because
  32. // the menu has submenus, so we need to be able to "select" them). We
  33. // should figure out how to tell it that this menu does not allow
  34. expect(screen.getAllByRole('menuitemradio')).toHaveLength(2);
  35. expect(
  36. screen.getByRole('menuitemradio', {name: 'Item One'})
  37. ).toHaveAccessibleDescription('This is the first item');
  38. expect(
  39. screen.getByRole('menuitemradio', {name: 'Item Two'})
  40. ).toHaveAccessibleDescription('Another description here');
  41. userEvent.click(screen.getByRole('menuitemradio', {name: 'Item One'}));
  42. expect(onAction).toHaveBeenCalled();
  43. });
  44. it('renders disabled items', function () {
  45. const onAction = jest.fn();
  46. render(
  47. <DropdownMenuControl
  48. items={[
  49. {
  50. key: 'item1',
  51. label: 'Item One',
  52. disabled: true,
  53. onAction,
  54. },
  55. ]}
  56. triggerLabel="Menu"
  57. />
  58. );
  59. userEvent.click(screen.getByRole('button', {name: 'Menu'}));
  60. const menuItem = screen.getByRole('menuitemradio', {name: 'Item One'});
  61. // RTL doesn't support toBeDisabled for aria-disabled
  62. //
  63. // See: https://github.com/testing-library/jest-dom/issues/144#issuecomment-577235097
  64. expect(menuItem).toHaveAttribute('aria-disabled', 'true');
  65. userEvent.click(menuItem);
  66. expect(onAction).not.toHaveBeenCalled();
  67. });
  68. it('renders submenues', function () {
  69. const onAction = jest.fn();
  70. render(
  71. <DropdownMenuControl
  72. items={[
  73. {
  74. key: 'item1',
  75. label: 'Item',
  76. isSubmenu: true,
  77. children: [
  78. {
  79. key: 'subitem',
  80. label: 'Sub Item',
  81. onAction,
  82. },
  83. ],
  84. },
  85. {
  86. key: 'item2',
  87. label: 'Item Two',
  88. },
  89. ]}
  90. triggerLabel="Menu"
  91. />
  92. );
  93. userEvent.click(screen.getByRole('button', {name: 'Menu'}));
  94. // Sub item won't be visible until we hover over it's parent
  95. expect(
  96. screen.queryByRole('menuitemradio', {name: 'Sub Item'})
  97. ).not.toBeInTheDocument();
  98. const parentItem = screen.getByRole('menuitemradio', {name: 'Item'});
  99. expect(parentItem).toHaveAttribute('aria-haspopup', 'true');
  100. expect(parentItem).toHaveAttribute('aria-expanded', 'false');
  101. userEvent.hover(parentItem);
  102. // The sub item is now visibile
  103. const subItem = screen.getByRole('menuitemradio', {name: 'Sub Item'});
  104. expect(subItem).toBeInTheDocument();
  105. // Menu does not close when hovering over it
  106. userEvent.unhover(parentItem);
  107. userEvent.hover(subItem);
  108. expect(subItem).toBeInTheDocument();
  109. // Menu is closed when hovering the other menu item
  110. userEvent.unhover(subItem);
  111. userEvent.hover(screen.getByRole('menuitemradio', {name: 'Item Two'}));
  112. expect(subItem).not.toBeInTheDocument();
  113. // Click the menu item
  114. userEvent.hover(parentItem);
  115. userEvent.click(screen.getByRole('menuitemradio', {name: 'Sub Item'}));
  116. expect(onAction).toHaveBeenCalled();
  117. });
  118. });