|
6 | 6 | */ |
7 | 7 |
|
8 | 8 | import React from 'react'; |
9 | | -import Menu, { |
10 | | - MenuItem, |
11 | | - MenuRadioGroup, |
12 | | - MenuSelectableItem, |
13 | | - MenuDivider, |
14 | | -} from '../Menu'; |
15 | | -import { mount } from 'enzyme'; |
16 | | - |
17 | | -const prefix = 'cds'; |
| 9 | +import Menu, { MenuItem } from '../Menu'; |
| 10 | +import { render, screen } from '@testing-library/react'; |
| 11 | +import userEvent from '@testing-library/user-event'; |
18 | 12 |
|
19 | 13 | describe('Menu', () => { |
20 | 14 | describe('renders as expected', () => { |
21 | | - describe('menu', () => { |
22 | | - it("isn't rendered when closed", () => { |
23 | | - const wrapper = mount(<Menu />); |
24 | | - expect(wrapper.getDOMNode()).toBe(null); |
25 | | - }); |
26 | | - |
27 | | - it('receives the expected classes when opened', () => { |
28 | | - const wrapper = mount(<Menu open />); |
29 | | - const container = wrapper.getDOMNode(); |
30 | | - |
31 | | - expect(container.classList.contains(`${prefix}--menu`)).toBe(true); |
32 | | - expect(container.classList.contains(`${prefix}--menu--open`)).toBe( |
33 | | - true |
34 | | - ); |
35 | | - }); |
| 15 | + it('should place a className on the outermost element', () => { |
| 16 | + render(<Menu className="custom-class" open />); |
| 17 | + |
| 18 | + expect(document.querySelector('.custom-class')).toBeDefined(); |
36 | 19 | }); |
37 | 20 |
|
38 | | - describe('option', () => { |
39 | | - it('receives the expected classes', () => { |
40 | | - const wrapper = mount(<MenuItem label="Copy" />); |
41 | | - const container = wrapper.childAt(0).childAt(0); |
42 | | - |
43 | | - expect(container.hasClass(`${prefix}--menu-option`)).toBe(true); |
44 | | - }); |
45 | | - |
46 | | - it('renders props.label', () => { |
47 | | - const wrapper = mount(<MenuItem label="Copy" />); |
48 | | - |
49 | | - expect(wrapper.find(`span.${prefix}--menu-option__label`).text()).toBe( |
50 | | - 'Copy' |
51 | | - ); |
52 | | - expect( |
53 | | - wrapper.find(`span.${prefix}--menu-option__label`).prop('title') |
54 | | - ).toBe('Copy'); |
55 | | - }); |
56 | | - |
57 | | - it('renders props.shortcut when provided', () => { |
58 | | - const wrapper = mount(<MenuItem label="Copy" shortcut="⌘C" />); |
59 | | - |
60 | | - expect( |
61 | | - wrapper.find(`div.${prefix}--menu-option__info`).length |
62 | | - ).toBeGreaterThan(0); |
63 | | - expect(wrapper.find(`div.${prefix}--menu-option__info`).text()).toBe( |
64 | | - '⌘C' |
65 | | - ); |
66 | | - }); |
67 | | - |
68 | | - it('respects props.disabled', () => { |
69 | | - const wrapper = mount(<MenuItem label="Copy" disabled />); |
70 | | - const content = wrapper.find(`div.${prefix}--menu-option__content`); |
71 | | - |
72 | | - expect( |
73 | | - content.hasClass(`${prefix}--menu-option__content--disabled`) |
74 | | - ).toBe(true); |
75 | | - expect( |
76 | | - wrapper.find(`li.${prefix}--menu-option`).prop('aria-disabled') |
77 | | - ).toBe(true); |
78 | | - }); |
79 | | - |
80 | | - it('supports danger kind', () => { |
81 | | - const wrapper = mount(<MenuItem label="Delete" kind="danger" />); |
82 | | - const option = wrapper.find(`.${prefix}--menu-option`); |
83 | | - |
84 | | - expect(option.hasClass(`${prefix}--menu-option--danger`)).toBe(true); |
85 | | - }); |
86 | | - |
87 | | - it('renders props.children as submenu', () => { |
88 | | - const wrapper = mount( |
89 | | - <Menu open> |
90 | | - <MenuItem label="Format"> |
91 | | - <MenuItem label="Bold" /> |
92 | | - <MenuItem label="Italic" /> |
93 | | - </MenuItem> |
94 | | - </Menu> |
95 | | - ); |
96 | | - |
97 | | - const level1 = wrapper.find(`li.${prefix}--menu-option`).at(0); |
98 | | - |
99 | | - expect(level1.find(`ul.${prefix}--menu`).length).toBeGreaterThan(0); |
100 | | - }); |
| 21 | + it('should spread props onto ul', () => { |
| 22 | + render(<Menu data-testid="test-id" open />); |
| 23 | + |
| 24 | + expect(screen.getByRole('menu')).toHaveAttribute( |
| 25 | + 'data-testid', |
| 26 | + 'test-id' |
| 27 | + ); |
101 | 28 | }); |
102 | 29 |
|
103 | | - describe('radiogroup', () => { |
104 | | - it('children have role "menuitemradio"', () => { |
105 | | - const wrapper = mount( |
106 | | - <MenuRadioGroup label="Share with" items={['None', 'All']} /> |
107 | | - ); |
108 | | - const options = wrapper.find(`li.${prefix}--menu-option`); |
| 30 | + it('have an id when one is provided', () => { |
| 31 | + render(<Menu id="test-id" open />); |
109 | 32 |
|
110 | | - expect(options.every('li[role="menuitemradio"]')).toBe(true); |
111 | | - }); |
| 33 | + expect(screen.getByRole('menu')).toHaveAttribute('id', 'test-id'); |
112 | 34 | }); |
113 | 35 |
|
114 | | - describe('selectable', () => { |
115 | | - it('has role "menuitemcheckbox"', () => { |
116 | | - const wrapper = mount(<MenuSelectableItem label="Publish" />); |
117 | | - const container = wrapper.childAt(0); |
| 36 | + it('should call onClose on key down', () => { |
| 37 | + const onClose = jest.fn(); |
| 38 | + render( |
| 39 | + <Menu open onClose={onClose}> |
| 40 | + <MenuItem label="item" /> |
| 41 | + </Menu> |
| 42 | + ); |
| 43 | + |
| 44 | + userEvent.type(screen.getByRole('menuitem'), '{enter}'); |
118 | 45 |
|
119 | | - expect(container.prop('role')).toBe('menuitemcheckbox'); |
120 | | - }); |
| 46 | + expect(onClose).toHaveBeenCalled(); |
121 | 47 | }); |
122 | 48 |
|
123 | | - describe('divider', () => { |
124 | | - it('receives the expected classes', () => { |
125 | | - const wrapper = mount(<MenuDivider />); |
126 | | - const container = wrapper.childAt(0); |
| 49 | + it('should call onClose on click', () => { |
| 50 | + const onClose = jest.fn(); |
| 51 | + render( |
| 52 | + <Menu open onClose={onClose}> |
| 53 | + <MenuItem label="item" /> |
| 54 | + </Menu> |
| 55 | + ); |
| 56 | + |
| 57 | + userEvent.click(screen.getByRole('menuitem')); |
| 58 | + |
| 59 | + expect(onClose).toHaveBeenCalled(); |
| 60 | + }); |
| 61 | + |
| 62 | + it('should be open if open is supplied', () => { |
| 63 | + render(<Menu open />); |
| 64 | + |
| 65 | + expect(screen.getByRole('menu')).toBeInTheDocument(); |
| 66 | + }); |
| 67 | + |
| 68 | + it('should change size based on size prop', () => { |
| 69 | + render(<Menu open size="lg" />); |
| 70 | + |
| 71 | + expect(screen.getByRole('menu')).toHaveClass('cds--menu--lg'); |
| 72 | + }); |
127 | 73 |
|
128 | | - expect(container.hasClass(`${prefix}--menu-divider`)).toBe(true); |
129 | | - }); |
| 74 | + it('should append to target element', () => { |
| 75 | + const el = document.createElement('div'); |
| 76 | + document.body.appendChild(el); |
| 77 | + el.classList.add('custom-class'); |
| 78 | + render(<Menu open target={el} />); |
| 79 | + |
| 80 | + expect(document.querySelector('.custom-class')).toBeInTheDocument(); |
| 81 | + document.body.removeChild(el); |
| 82 | + }); |
| 83 | + }); |
| 84 | +}); |
| 85 | + |
| 86 | +describe('MenuItem', () => { |
| 87 | + describe('renders as expected', () => { |
| 88 | + it('should be disabled', () => { |
| 89 | + render(<MenuItem label="item" disabled />); |
| 90 | + |
| 91 | + expect(screen.getByRole('menuitem')).toHaveAttribute( |
| 92 | + 'aria-disabled', |
| 93 | + 'true' |
| 94 | + ); |
| 95 | + |
| 96 | + expect(screen.getByRole('menuitem')).toHaveClass( |
| 97 | + 'cds--menu-option--disabled' |
| 98 | + ); |
| 99 | + }); |
| 100 | + |
| 101 | + it('should change kind based on prop', () => { |
| 102 | + render(<MenuItem label="item" kind="danger" />); |
| 103 | + |
| 104 | + expect(screen.getByRole('menuitem')).toHaveClass( |
| 105 | + 'cds--menu-option--danger' |
| 106 | + ); |
| 107 | + }); |
130 | 108 |
|
131 | | - it('has role "separator"', () => { |
132 | | - const wrapper = mount(<MenuDivider />); |
133 | | - const container = wrapper.childAt(0); |
| 109 | + it('should render label', () => { |
| 110 | + render(<MenuItem label="item" />); |
134 | 111 |
|
135 | | - expect(container.prop('role')).toBe('separator'); |
136 | | - }); |
| 112 | + expect(screen.getByText('item')).toBeInTheDocument(); |
137 | 113 | }); |
138 | 114 | }); |
139 | 115 | }); |
0 commit comments