metadata-based-explorer1
Version:
Box UI Elements
618 lines (536 loc) • 20.6 kB
JavaScript
/* eslint-disable jsx-a11y/anchor-is-valid */
import React from 'react';
import { mount } from 'enzyme';
import sinon from 'sinon';
import Menu from '../Menu';
const sandbox = sinon.sandbox.create();
describe('components/menu/Menu', () => {
afterEach(() => {
sandbox.verifyAndRestore();
});
describe('render()', () => {
test('should render a unordered list with correct props when called', () => {
const wrapper = mount(
<Menu className="awesome-menu">
<li />
<li />
</Menu>,
);
expect(wrapper.find('ul').length).toBe(1);
expect(wrapper.find('ul').prop('role')).toEqual('menu');
expect(wrapper.find('ul').prop('className')).toEqual('aria-menu awesome-menu');
expect(wrapper.find('ul').prop('tabIndex')).toEqual(-1);
});
});
describe('setInitialFocusIndex()', () => {
test('should set internal menuItemEls to valid items after mount', () => {
const wrapper = mount(
<Menu>
<li className="menu-item" role="menuitem" />
<li role="separator" />
<li className="menu-item" role="menuitem" />
<li aria-disabled="true" className="menu-item" role="menuitem" />
<li>
<a className="menu-item" role="menuitem">
Link
</a>
</li>
</Menu>,
);
const instance = wrapper.instance();
// Should have 3 items (li, li, a)
expect(instance.menuItemEls.length).toBe(3);
});
test('should call setFocus() asynchronously when initialFocusIndex is set to 0', () => {
const clock = sandbox.useFakeTimers();
const wrapper = shallow(
<Menu initialFocusIndex={0}>
<li role="menuitem" />
</Menu>,
{ disableLifecycleMethods: true },
);
const instance = wrapper.instance();
instance.setInitialFocusIndex();
sandbox
.mock(instance)
.expects('setFocus')
.withArgs(0);
clock.tick(100);
});
test('should call setFocus() asynchronously when initialFocusIndex is set to -1', () => {
const clock = sandbox.useFakeTimers();
const wrapper = shallow(
<Menu initialFocusIndex={-1}>
<li role="menuitem" />
</Menu>,
{ disableLifecycleMethods: true },
);
const instance = wrapper.instance();
instance.setInitialFocusIndex();
sandbox
.mock(instance)
.expects('setFocus')
.withArgs(-1);
clock.tick(100);
});
test('should not call setFocus() when no initialFocusIndex prop is passed', () => {
const clock = sandbox.useFakeTimers();
const wrapper = shallow(
<Menu>
<li role="menuitem" />
</Menu>,
{ disableLifecycleMethods: true },
);
const instance = wrapper.instance();
instance.setInitialFocusIndex();
sandbox
.mock(instance)
.expects('setFocus')
.never();
clock.tick(100);
});
});
describe('componentDidMount()', () => {
test('should call setInitialFocusIndex()', () => {
const wrapper = shallow(
<Menu className="awesome-menu">
<li />
</Menu>,
);
const instance = wrapper.instance();
instance.setInitialFocusIndex = sandbox.mock();
instance.componentDidMount();
});
});
describe('componentWillReceiveProps()', () => {
test('should call setInitialFocusIndex() when isSubmenu is true and isHidden changes from false to true', () => {
const wrapper = shallow(
<Menu className="awesome-menu" isHidden>
<li />
</Menu>,
);
const instance = wrapper.instance();
instance.setInitialFocusIndex = sandbox.mock();
instance.componentWillReceiveProps({
isHidden: false,
isSubmenu: true,
});
});
});
describe('componentDidUpdate()', () => {
test('should call setMenuItemEls() and setFocus() when the number of children changes', () => {
const clock = sandbox.useFakeTimers();
const wrapper = mount(
<Menu initialFocusIndex={1}>
<li key="1" className="menu-item" role="menuitem" />
<li key="2" role="separator" />
{false}
</Menu>,
);
clock.tick(0);
const instance = wrapper.instance();
const instanceMock = sandbox.mock(instance);
instanceMock.expects('setMenuItemEls');
instanceMock.expects('getMenuItemElFromEventTarget').returns({ menuIndex: 2 });
instanceMock.expects('setFocus').withExactArgs(2);
wrapper.setProps({
children: [
<li key="1" className="menu-item" role="menuitem" />,
<li key="2" role="separator" />,
<li key="3" className="menu-item" role="menuitem" />,
],
});
});
test('should not call setMenuItemEls() when the number of children stays the same', () => {
const wrapper = mount(
<Menu>
<li role="menuitem" />
</Menu>,
);
const instance = wrapper.instance();
sandbox
.mock(instance)
.expects('setMenuItemEls')
.never();
wrapper.setProps({ className: 'test' });
});
});
describe('handleClick()', () => {
test('should not call fireOnCloseHandler() when click did not occur on a valid menu item', () => {
const wrapper = mount(
<Menu>
<li role="menuitem" />
<li role="separator" />
</Menu>,
);
const listItems = wrapper.find('li');
const separatorEl = listItems.at(1).getDOMNode();
const instance = wrapper.instance();
sandbox
.mock(instance)
.expects('getMenuItemElFromEventTarget')
.withArgs(separatorEl)
.returns({ menuItemEl: null, menuIndex: -1 });
sandbox
.mock(instance)
.expects('fireOnCloseHandler')
.never();
wrapper.simulate('click', {
target: separatorEl,
preventDefault: sandbox.mock().never(),
stopPropagation: sandbox.mock().never(),
});
});
test('should call fireOnCloseHandler() when click occurred on a valid menu item', () => {
const wrapper = mount(
<Menu>
<li role="menuitem" />
<li role="separator" />
</Menu>,
);
const listItems = wrapper.find('li');
const menuItemEl = listItems.at(0).getDOMNode();
const instance = wrapper.instance();
sandbox
.mock(instance)
.expects('getMenuItemElFromEventTarget')
.withArgs(menuItemEl)
.returns({ menuItemEl });
sandbox.mock(instance).expects('fireOnCloseHandler');
wrapper.simulate('click', {
target: menuItemEl,
preventDefault: sandbox.mock().never(),
stopPropagation: sandbox.mock().never(),
});
});
});
describe('handleKeyDown()', () => {
test('should focusNextItem() when "down" key is pressed', () => {
const wrapper = mount(
<Menu>
<li role="menuitem" />
</Menu>,
);
const instance = wrapper.instance();
sandbox.mock(instance).expects('focusNextItem');
wrapper.simulate('keydown', {
key: 'ArrowDown',
preventDefault: sandbox.mock(),
stopPropagation: sandbox.mock(),
});
});
test('should focusPreviousItem() when "up" key is pressed', () => {
const wrapper = mount(
<Menu>
<li role="menuitem" />
</Menu>,
);
const instance = wrapper.instance();
sandbox.mock(instance).expects('focusPreviousItem');
wrapper.simulate('keydown', {
key: 'ArrowUp',
preventDefault: sandbox.mock(),
stopPropagation: sandbox.mock(),
});
});
test('should call fireOnCloseHandler() when "ArrowLeft" key is pressed and isSubmenu prop is true', () => {
const wrapper = mount(
<Menu isSubmenu>
<li role="menuitem" />
</Menu>,
);
const instance = wrapper.instance();
sandbox.mock(instance).expects('fireOnCloseHandler');
wrapper.simulate('keydown', {
key: 'ArrowLeft',
preventDefault: sandbox.mock(),
stopPropagation: sandbox.mock(),
});
});
test('should not call fireOnCloseHandler() when "ArrowLeft" key is pressed and isSubmenu prop is false', () => {
const wrapper = mount(
<Menu>
<li role="menuitem" />
</Menu>,
);
const instance = wrapper.instance();
sandbox
.mock(instance)
.expects('fireOnCloseHandler')
.never();
wrapper.simulate('keydown', {
key: 'ArrowLeft',
preventDefault: sandbox.mock().never(),
stopPropagation: sandbox.mock().never(),
});
});
[
{
key: 'Home',
},
{
key: 'PageUp',
},
].forEach(({ key }) => {
test('should focusFirstItem() when "home" or "pageup" key is pressed', () => {
const wrapper = mount(
<Menu>
<li role="menuitem" />
</Menu>,
);
const instance = wrapper.instance();
sandbox.mock(instance).expects('focusFirstItem');
wrapper.simulate('keydown', {
key,
preventDefault: sandbox.mock(),
stopPropagation: sandbox.mock(),
});
});
});
[
{
key: 'End',
},
{
key: 'PageDown',
},
].forEach(({ key }) => {
test('should focusLastItem() when "end" or "pagedown" key is pressed', () => {
const wrapper = mount(
<Menu>
<li role="menuitem" />
</Menu>,
);
const instance = wrapper.instance();
sandbox.mock(instance).expects('focusLastItem');
wrapper.simulate('keydown', {
key,
preventDefault: sandbox.mock(),
stopPropagation: sandbox.mock(),
});
});
});
test('should call fireOnCloseHandler() when "esc" key is pressed', () => {
const wrapper = mount(
<Menu>
<li role="menuitem" />
</Menu>,
);
const instance = wrapper.instance();
sandbox.mock(instance).expects('fireOnCloseHandler');
wrapper.simulate('keydown', {
key: 'Escape',
preventDefault: sandbox.mock(),
stopPropagation: sandbox.mock(),
});
});
test('should call fireOnCloseHandler() but NOT preventDefault() or stopPropagation() when "tab" key is pressed', () => {
const wrapper = mount(
<Menu>
<li role="menuitem" />
</Menu>,
);
const instance = wrapper.instance();
sandbox.mock(instance).expects('fireOnCloseHandler');
wrapper.simulate('keydown', {
key: 'Tab',
preventDefault: sandbox.mock().never(),
stopPropagation: sandbox.mock().never(),
});
});
[
{
key: ' ',
},
{
key: 'Enter',
},
].forEach(({ key }) => {
test('should trigger click event on event target when "space" or "enter" key is pressed', () => {
const wrapper = mount(
<Menu>
<li role="menuitem" />
</Menu>,
);
const menuItemEl = wrapper.find('li').getDOMNode();
sandbox.mock(menuItemEl).expects('click');
wrapper.simulate('keydown', {
target: menuItemEl,
key,
preventDefault: sandbox.mock(),
stopPropagation: sandbox.mock(),
});
});
});
});
describe('setFocus()', () => {
test('should not do anything when there are no valid menu items', () => {
const wrapper = mount(
<Menu>
<li role="separator" />
</Menu>,
);
const instance = wrapper.instance();
expect(instance.menuItemEls.length).toBe(0);
instance.setFocus(1);
expect(instance.focusIndex).toEqual(0);
});
test('should wrap to beginning when index is greater than number of items', () => {
const wrapper = mount(
<Menu>
<li className="menu-item" role="menuitem" />
<li className="menu-item" role="menuitem" />
</Menu>,
);
const instance = wrapper.instance();
const listItems = wrapper.find('li');
sandbox.mock(listItems.at(0).getDOMNode()).expects('focus');
instance.setFocus(2);
expect(instance.focusIndex).toEqual(0);
});
test('should wrap to end when index is less than 0', () => {
const wrapper = mount(
<Menu>
<li className="menu-item" role="menuitem" />
<li className="menu-item" role="menuitem" />
</Menu>,
);
const instance = wrapper.instance();
const listItems = wrapper.find('li');
sandbox.mock(listItems.at(1).getDOMNode()).expects('focus');
instance.setFocus(-2);
expect(instance.focusIndex).toEqual(1);
});
test('should move to specific index when index is in bounds', () => {
const wrapper = mount(
<Menu>
<li className="menu-item" role="menuitem" />
<li className="menu-item" role="menuitem" />
</Menu>,
);
const instance = wrapper.instance();
const listItems = wrapper.find('li');
sandbox.mock(listItems.at(1).getDOMNode()).expects('focus');
instance.setFocus(1);
expect(instance.focusIndex).toEqual(1);
});
});
describe('focusFirstItem()', () => {
test('should call setFocus(0) when called', () => {
const wrapper = mount(
<Menu>
<li role="menuitem" />
</Menu>,
);
const instance = wrapper.instance();
sandbox
.mock(instance)
.expects('setFocus')
.withArgs(0);
instance.focusFirstItem();
});
});
describe('focusLastItem()', () => {
test('should call setFocus(-1) when called', () => {
const wrapper = mount(
<Menu>
<li role="menuitem" />
<li role="menuitem" />
<li role="menuitem" />
</Menu>,
);
const instance = wrapper.instance();
sandbox
.mock(instance)
.expects('setFocus')
.withArgs(-1);
instance.focusLastItem();
});
});
describe('focusNextItem()', () => {
test('should call setFocus(current+1) when called', () => {
const wrapper = mount(
<Menu>
<li role="menuitem" />
<li role="menuitem" />
<li role="menuitem" />
</Menu>,
);
const instance = wrapper.instance();
instance.focusIndex = 1;
sandbox
.mock(instance)
.expects('setFocus')
.withArgs(2);
instance.focusNextItem();
});
});
describe('focusPreviousItem()', () => {
test('should call setFocus(current-1) when called', () => {
const wrapper = mount(
<Menu>
<li role="menuitem" />
<li role="menuitem" />
<li role="menuitem" />
</Menu>,
);
const instance = wrapper.instance();
instance.focusIndex = 2;
sandbox
.mock(instance)
.expects('setFocus')
.withArgs(1);
instance.focusPreviousItem();
});
});
describe('getMenuItemElFromEventTarget()', () => {
test('should return valid menu item when target is contained in a menu item', () => {
const wrapper = mount(
<Menu>
<li className="menu-item" role="menuitem" />
<li className="menu-item" role="menuitem">
<span>Awesome</span>
</li>
<li className="menu-item" role="menuitem" />
</Menu>,
);
const instance = wrapper.instance();
const listWrapper = wrapper.find('li');
const spanWrapper = wrapper.find('span');
const result = instance.getMenuItemElFromEventTarget(spanWrapper.at(0).getDOMNode());
const expectedResult = {
menuItemEl: listWrapper.at(1).getDOMNode(),
menuIndex: 1,
};
expect(result.menuItemEl).toEqual(expectedResult.menuItemEl);
expect(result.menuIndex).toEqual(expectedResult.menuIndex);
});
test('should return null when target is not in a valid menu item', () => {
const wrapper = mount(
<Menu>
<li role="menuitem" />
<li role="menuitem" />
<li role="menuitem" />
<li>
<span>Awesome</span>
</li>
</Menu>,
);
const instance = wrapper.instance();
const spanWrapper = wrapper.find('span');
const result = instance.getMenuItemElFromEventTarget(spanWrapper.at(0).getDOMNode());
expect(result.menuItemEl).toBeNull();
});
});
describe('fireOnCloseHandler()', () => {
test('should call onClose() when prop exists', () => {
const wrapper = mount(
<Menu onClose={sandbox.mock()}>
<li role="menuitem" />
</Menu>,
);
const instance = wrapper.instance();
instance.fireOnCloseHandler();
});
});
});