From f04a30ed62414023a5dbfcf2b8797ca82137e90a Mon Sep 17 00:00:00 2001 From: Abbey Hart Date: Wed, 27 Jul 2022 17:00:40 -0500 Subject: [PATCH 1/2] refactor(react): update menu tests to rtl --- .../react/src/components/Menu/Menu-test.js | 200 ++++++++---------- packages/react/src/components/Menu/Menu.js | 2 +- 2 files changed, 89 insertions(+), 113 deletions(-) diff --git a/packages/react/src/components/Menu/Menu-test.js b/packages/react/src/components/Menu/Menu-test.js index e7c6e6786567..43974f5e89d2 100644 --- a/packages/react/src/components/Menu/Menu-test.js +++ b/packages/react/src/components/Menu/Menu-test.js @@ -6,134 +6,110 @@ */ import React from 'react'; -import Menu, { - MenuItem, - MenuRadioGroup, - MenuSelectableItem, - MenuDivider, -} from '../Menu'; -import { mount } from 'enzyme'; - -const prefix = 'cds'; +import Menu, { MenuItem } from '../Menu'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; describe('Menu', () => { describe('renders as expected', () => { - describe('menu', () => { - it("isn't rendered when closed", () => { - const wrapper = mount(); - expect(wrapper.getDOMNode()).toBe(null); - }); - - it('receives the expected classes when opened', () => { - const wrapper = mount(); - const container = wrapper.getDOMNode(); - - expect(container.classList.contains(`${prefix}--menu`)).toBe(true); - expect(container.classList.contains(`${prefix}--menu--open`)).toBe( - true - ); - }); + it('should place a className on the outermost element', () => { + render(); + + expect(document.querySelector('.custom-class')).toBeDefined(); }); - describe('option', () => { - it('receives the expected classes', () => { - const wrapper = mount(); - const container = wrapper.childAt(0).childAt(0); - - expect(container.hasClass(`${prefix}--menu-option`)).toBe(true); - }); - - it('renders props.label', () => { - const wrapper = mount(); - - expect(wrapper.find(`span.${prefix}--menu-option__label`).text()).toBe( - 'Copy' - ); - expect( - wrapper.find(`span.${prefix}--menu-option__label`).prop('title') - ).toBe('Copy'); - }); - - it('renders props.shortcut when provided', () => { - const wrapper = mount(); - - expect( - wrapper.find(`div.${prefix}--menu-option__info`).length - ).toBeGreaterThan(0); - expect(wrapper.find(`div.${prefix}--menu-option__info`).text()).toBe( - '⌘C' - ); - }); - - it('respects props.disabled', () => { - const wrapper = mount(); - const content = wrapper.find(`div.${prefix}--menu-option__content`); - - expect( - content.hasClass(`${prefix}--menu-option__content--disabled`) - ).toBe(true); - expect( - wrapper.find(`li.${prefix}--menu-option`).prop('aria-disabled') - ).toBe(true); - }); - - it('supports danger kind', () => { - const wrapper = mount(); - const option = wrapper.find(`.${prefix}--menu-option`); - - expect(option.hasClass(`${prefix}--menu-option--danger`)).toBe(true); - }); - - it('renders props.children as submenu', () => { - const wrapper = mount( - - - - - - - ); - - const level1 = wrapper.find(`li.${prefix}--menu-option`).at(0); - - expect(level1.find(`ul.${prefix}--menu`).length).toBeGreaterThan(0); - }); + it('should spread props onto ul', () => { + render(); + + expect(screen.getByRole('menu')).toHaveAttribute( + 'data-testid', + 'test-id' + ); }); - describe('radiogroup', () => { - it('children have role "menuitemradio"', () => { - const wrapper = mount( - - ); - const options = wrapper.find(`li.${prefix}--menu-option`); + it('have an id when one is provided', () => { + render(); - expect(options.every('li[role="menuitemradio"]')).toBe(true); - }); + expect(screen.getByRole('menu')).toHaveAttribute('id', 'test-id'); }); - describe('selectable', () => { - it('has role "menuitemcheckbox"', () => { - const wrapper = mount(); - const container = wrapper.childAt(0); + it('should call onClose on key down', () => { + const onClose = jest.fn(); + render( + + + + ); + + userEvent.type(screen.getByRole('menuitem'), '{enter}'); - expect(container.prop('role')).toBe('menuitemcheckbox'); - }); + expect(onClose).toHaveBeenCalled(); }); - describe('divider', () => { - it('receives the expected classes', () => { - const wrapper = mount(); - const container = wrapper.childAt(0); + it('should call onClose on click', () => { + const onClose = jest.fn(); + render( + + + + ); + + userEvent.click(screen.getByRole('menuitem')); + + expect(onClose).toHaveBeenCalled(); + }); + + it('should be open if open is supplied', () => { + render(); + + expect(screen.getByRole('menu')).toBeInTheDocument(); + }); + + it('should change size based on size prop', () => { + render(); + + expect(screen.getByRole('menu')).toHaveClass('cds--menu--lg'); + }); - expect(container.hasClass(`${prefix}--menu-divider`)).toBe(true); - }); + it('should append to target element', () => { + const el = document.createElement('div'); + document.body.appendChild(el); + el.classList.add('custom-class'); + render(); + + expect(document.querySelector('.custom-class')).toBeInTheDocument(); + document.body.removeChild(el); + }); + }); +}); + +describe('MenuItem', () => { + describe('renders as expected', () => { + it('should be disabled', () => { + render(); + + expect(screen.getByRole('menuitem')).toHaveAttribute( + 'aria-disabled', + 'true' + ); + + expect(screen.getByRole('menuitem')).toHaveClass( + 'cds--menu-option--disabled' + ); + }); + + it('should change kind based on prop', () => { + render(); + + expect(screen.getByRole('menuitem')).toHaveClass( + 'cds--menu-option--danger' + ); + }); - it('has role "separator"', () => { - const wrapper = mount(); - const container = wrapper.childAt(0); + it('should render label', () => { + render(); - expect(container.prop('role')).toBe('separator'); - }); + expect(screen.getByText('item')).toBeInTheDocument(); }); }); }); diff --git a/packages/react/src/components/Menu/Menu.js b/packages/react/src/components/Menu/Menu.js index 0734b81dfdd5..d9f694007b20 100644 --- a/packages/react/src/components/Menu/Menu.js +++ b/packages/react/src/components/Menu/Menu.js @@ -351,7 +351,7 @@ Menu.propTypes = { /** * Optionally pass an element the Menu should be appended to as a child. Defaults to document.body. */ - target: PropTypes.element, + target: PropTypes.object, /** * Specify the x position where this menu is rendered From ff1919ab4ac586d97ab28244467e929c4619ef20 Mon Sep 17 00:00:00 2001 From: Abbey Hart Date: Wed, 27 Jul 2022 17:10:39 -0500 Subject: [PATCH 2/2] chore(react): update snapshots --- packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap index dc154b6235a1..910677d9c1d1 100644 --- a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap +++ b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap @@ -8465,7 +8465,7 @@ Map { "type": "oneOf", }, "target": Object { - "type": "element", + "type": "object", }, "x": Object { "args": Array [