UNPKG

materialuiupgraded

Version:

Material-UI's workspace package

514 lines (439 loc) 19.6 kB
import React from 'react'; import keycode from 'keycode'; import { assert } from 'chai'; import { spy } from 'sinon'; import CheckBox from '../internal/svg-icons/CheckBox'; import CancelIcon from '../internal/svg-icons/Cancel'; import { createShallow, createMount, getClasses, unwrap } from '../test-utils'; import Avatar from '../Avatar'; import Chip from './Chip'; describe('<Chip />', () => { let shallow; let classes; let mount; before(() => { shallow = createShallow({ dive: true }); classes = getClasses(<Chip />); mount = createMount(); }); after(() => { mount.cleanUp(); }); describe('text only', () => { it('should render a div containing a span', () => { const wrapper = shallow(<Chip className="my-Chip" data-my-prop="woofChip" />); assert.strictEqual(wrapper.name(), 'div'); assert.strictEqual(wrapper.childAt(0).name(), 'span'); assert.strictEqual(wrapper.hasClass(classes.root), true); assert.strictEqual(wrapper.hasClass('my-Chip'), true); assert.strictEqual(wrapper.props()['data-my-prop'], 'woofChip'); assert.strictEqual(wrapper.props().tabIndex, -1); assert.strictEqual(wrapper.hasClass(classes.root), true); assert.strictEqual(wrapper.hasClass(classes.colorPrimary), false); assert.strictEqual(wrapper.hasClass(classes.colorSecondary), false); assert.strictEqual(wrapper.hasClass(classes.clickable), false); assert.strictEqual(wrapper.hasClass(classes.clickableColorPrimary), false); assert.strictEqual(wrapper.hasClass(classes.clickableColorSecondary), false); assert.strictEqual(wrapper.hasClass(classes.deletable), false); assert.strictEqual(wrapper.hasClass(classes.deletableColorPrimary), false); assert.strictEqual(wrapper.hasClass(classes.deletableColorSecondary), false); }); it('should render with the root and the primary class', () => { const wrapper = shallow(<Chip className="my-Chip" data-my-prop="woofChip" color="primary" />); assert.strictEqual(wrapper.hasClass(classes.root), true); assert.strictEqual(wrapper.hasClass(classes.colorPrimary), true); }); it('should render with the root and the secondary class', () => { const wrapper = shallow( <Chip className="my-Chip" data-my-prop="woofChip" color="secondary" />, ); assert.strictEqual(wrapper.hasClass(classes.root), true); assert.strictEqual(wrapper.hasClass(classes.colorSecondary), true); }); }); describe('clickable text chip', () => { let wrapper; let handleClick; before(() => { handleClick = () => {}; wrapper = shallow(<Chip className="my-Chip" data-my-prop="woofChip" onClick={handleClick} />); }); it('should render a div containing a span', () => { assert.strictEqual(wrapper.name(), 'div'); assert.strictEqual(wrapper.childAt(0).name(), 'span'); }); it('should merge user classes & spread custom props to the root node', () => { assert.strictEqual(wrapper.hasClass(classes.root), true); assert.strictEqual(wrapper.hasClass('my-Chip'), true); assert.strictEqual(wrapper.props()['data-my-prop'], 'woofChip'); assert.strictEqual(wrapper.props().onClick, handleClick); }); it('should have a tabIndex prop', () => { assert.strictEqual(wrapper.props().tabIndex, 0); }); it('should apply user value of tabIndex', () => { wrapper = shallow( // eslint-disable-next-line jsx-a11y/tabindex-no-positive <Chip onClick={() => {}} tabIndex={5} />, ); assert.strictEqual(wrapper.props().tabIndex, 5); }); it('should render with the root and clickable class', () => { assert.strictEqual(wrapper.hasClass(classes.root), true); assert.strictEqual(wrapper.hasClass(classes.clickable), true); }); it('should render with the root and clickable primary class', () => { wrapper = shallow( <Chip className="my-Chip" data-my-prop="woofChip" onClick={handleClick} color="primary" />, ); assert.strictEqual(wrapper.hasClass(classes.root), true); assert.strictEqual(wrapper.hasClass(classes.colorPrimary), true); assert.strictEqual(wrapper.hasClass(classes.clickable), true); assert.strictEqual(wrapper.hasClass(classes.clickableColorPrimary), true); }); it('should render with the root and outlined clickable primary class', () => { wrapper = shallow( <Chip className="my-Chip" data-my-prop="woofChip" onClick={handleClick} color="primary" variant="outlined" />, ); assert.strictEqual(wrapper.hasClass(classes.root), true); assert.strictEqual(wrapper.hasClass(classes.colorPrimary), true); assert.strictEqual(wrapper.hasClass(classes.clickable), true); assert.strictEqual(wrapper.hasClass(classes.clickableColorPrimary), true); assert.strictEqual(wrapper.hasClass(classes.outlined), true); assert.strictEqual(wrapper.hasClass(classes.outlinedPrimary), true); }); it('should render with the root and clickable secondary class', () => { wrapper = shallow( <Chip className="my-Chip" data-my-prop="woofChip" onClick={handleClick} color="secondary" />, ); assert.strictEqual(wrapper.hasClass(classes.root), true); assert.strictEqual(wrapper.hasClass(classes.colorSecondary), true); assert.strictEqual(wrapper.hasClass(classes.clickable), true); assert.strictEqual(wrapper.hasClass(classes.clickableColorSecondary), true); }); }); describe('deletable Avatar chip', () => { let wrapper; before(() => { wrapper = shallow( <Chip avatar={ <Avatar className="my-Avatar" data-my-prop="woofChip"> MB </Avatar> } label="Text Avatar Chip" onDelete={() => {}} className="my-Chip" data-my-prop="woofChip" />, ); }); it('should render a div containing an Avatar, span and svg', () => { assert.strictEqual(wrapper.name(), 'div'); assert.strictEqual(wrapper.childAt(0).type(), Avatar); assert.strictEqual(wrapper.childAt(1).name(), 'span'); assert.strictEqual(wrapper.childAt(2).name(), 'pure(Cancel)'); }); it('should merge user classes & spread custom props to the root node', () => { assert.strictEqual(wrapper.hasClass(classes.root), true); assert.strictEqual(wrapper.hasClass('my-Chip'), true); assert.strictEqual(wrapper.props()['data-my-prop'], 'woofChip'); }); it('should merge user classes & spread custom props to the Avatar node', () => { assert.strictEqual(wrapper.childAt(0).hasClass(classes.avatar), true); assert.strictEqual(wrapper.childAt(0).hasClass('my-Avatar'), true); assert.strictEqual(wrapper.childAt(0).props()['data-my-prop'], 'woofChip'); }); it('should have a tabIndex prop', () => { assert.strictEqual(wrapper.props().tabIndex, 0); }); it('should fire the function given in onDeleteRequest', () => { const onDeleteSpy = spy(); wrapper.setProps({ onDelete: onDeleteSpy }); wrapper.find('pure(Cancel)').simulate('click', { stopPropagation: () => {} }); assert.strictEqual(onDeleteSpy.callCount, 1); }); it('should stop propagation in onDeleteRequest', () => { const onDeleteSpy = spy(); const stopPropagationSpy = spy(); wrapper.setProps({ onDelete: onDeleteSpy }); wrapper.find('pure(Cancel)').simulate('click', { stopPropagation: stopPropagationSpy }); assert.strictEqual(stopPropagationSpy.callCount, 1); }); it('should render with the root, deletable classes', () => { assert.strictEqual(wrapper.hasClass(classes.root), true); assert.strictEqual(wrapper.hasClass(classes.deletable), true); const avatarWrapper = wrapper.childAt(0); assert.strictEqual(avatarWrapper.hasClass(classes.avatar), true); }); it('should render with the root, deletable and avatar primary classes', () => { wrapper = shallow( <Chip avatar={ <Avatar className="my-Avatar" data-my-prop="woofChip"> MB </Avatar> } label="Text Avatar Chip" onDelete={() => {}} className="my-Chip" data-my-prop="woofChip" color="primary" />, ); assert.strictEqual(wrapper.hasClass(classes.root), true); assert.strictEqual(wrapper.hasClass(classes.colorPrimary), true); assert.strictEqual(wrapper.hasClass(classes.deletable), true); assert.strictEqual(wrapper.hasClass(classes.deletableColorPrimary), true); const avatarWrapper = wrapper.childAt(0); assert.strictEqual(avatarWrapper.hasClass(classes.avatar), true); assert.strictEqual(avatarWrapper.hasClass(classes.avatarColorPrimary), true); }); it('should render with the root, deletable and avatar secondary classes', () => { wrapper = shallow( <Chip avatar={ <Avatar className="my-Avatar" data-my-prop="woofChip"> MB </Avatar> } label="Text Avatar Chip" onDelete={() => {}} className="my-Chip" data-my-prop="woofChip" color="secondary" />, ); assert.strictEqual(wrapper.hasClass(classes.root), true); assert.strictEqual(wrapper.hasClass(classes.colorSecondary), true); assert.strictEqual(wrapper.hasClass(classes.deletable), true); assert.strictEqual(wrapper.hasClass(classes.deletableColorSecondary), true); const avatarWrapper = wrapper.childAt(0); assert.strictEqual(avatarWrapper.hasClass(classes.avatar), true); assert.strictEqual(avatarWrapper.hasClass(classes.avatarColorSecondary), true); }); }); describe('prop: deleteIcon', () => { it('should fire the function given in onDeleteRequest', () => { const wrapper = shallow( <Chip label="Custom delete icon Chip" onDelete={() => {}} deleteIcon={<CheckBox />} />, ); const onDeleteSpy = spy(); wrapper.setProps({ onDelete: onDeleteSpy }); wrapper.find(CheckBox).simulate('click', { stopPropagation: () => {} }); assert.strictEqual(onDeleteSpy.callCount, 1, 'should have called the onDelete handler'); }); it('should render a default icon', () => { const wrapper = mount(<Chip label="Custom delete icon Chip" onDelete={() => {}} />); assert.strictEqual(wrapper.find(CancelIcon).length, 1); }); it( 'should render a default icon with the root, deletable, deleteIcon' + ' and deleteIconOutlinedColorSecondary classes', () => { const wrapper = shallow( <Chip label="Custom delete icon Chip" onDelete={() => {}} variant="outlined" color="secondary" />, ); assert.strictEqual(wrapper.hasClass(classes.root), true); assert.strictEqual(wrapper.hasClass(classes.deletable), true); const iconWrapper = wrapper.find(CancelIcon); assert.strictEqual(iconWrapper.hasClass(classes.deleteIcon), true); assert.strictEqual(iconWrapper.hasClass(classes.deleteIconOutlinedColorSecondary), true); }, ); it('should render a default icon with the root, deletable and deleteIcon classes', () => { const wrapper = shallow(<Chip label="Custom delete icon Chip" onDelete={() => {}} />); assert.strictEqual(wrapper.hasClass(classes.root), true); assert.strictEqual(wrapper.hasClass(classes.deletable), true); const iconWrapper = wrapper.find(CancelIcon); assert.strictEqual(iconWrapper.hasClass(classes.deleteIcon), true); }); it('should render default icon with the root, deletable and deleteIcon primary class', () => { const wrapper = shallow( <Chip label="Custom delete icon Chip" onDelete={() => {}} color="primary" />, ); assert.strictEqual(wrapper.hasClass(classes.root), true); assert.strictEqual(wrapper.hasClass(classes.colorPrimary), true); assert.strictEqual(wrapper.hasClass(classes.deletable), true); assert.strictEqual(wrapper.hasClass(classes.deletableColorPrimary), true); const iconWrapper = wrapper.find(CancelIcon); assert.strictEqual(iconWrapper.hasClass(classes.deleteIcon), true); assert.strictEqual(iconWrapper.hasClass(classes.deleteIconColorPrimary), true); }); it('should render a default icon with the root, deletable, deleteIcon secondary class', () => { const wrapper = shallow( <Chip label="Custom delete icon Chip" onDelete={() => {}} color="secondary" />, ); assert.strictEqual(wrapper.hasClass(classes.root), true); assert.strictEqual(wrapper.hasClass(classes.colorSecondary), true); assert.strictEqual(wrapper.hasClass(classes.deletable), true); assert.strictEqual(wrapper.hasClass(classes.deletableColorSecondary), true); const iconWrapper = wrapper.find(CancelIcon); assert.strictEqual(iconWrapper.hasClass(classes.deleteIcon), true); assert.strictEqual(iconWrapper.hasClass(classes.deleteIconColorSecondary), true); }); }); describe('reacts to keyboard chip', () => { const ChipNaked = unwrap(Chip); let wrapper; describe('onKeyDown is defined', () => { it('should call onKeyDown when a key is pressed', () => { const anyKeydownEvent = { keycode: keycode('p') }; const onKeyDownSpy = spy(); wrapper = mount(<Chip classes={{}} onKeyDown={onKeyDownSpy} />); wrapper.find('div').simulate('keyDown', anyKeydownEvent); assert.strictEqual(onKeyDownSpy.callCount, 1); assert.strictEqual(onKeyDownSpy.args[0][0].keyCode, anyKeydownEvent.keyCode); }); }); describe('escape', () => { it('should unfocus when a esc key is pressed', () => { const wrapper2 = mount(<ChipNaked classes={{}} />); const handleBlur = spy(); wrapper2.instance().chipRef.blur = handleBlur; wrapper2.find('div').simulate('keyUp', { preventDefault: () => {}, keyCode: keycode('esc'), }); assert.strictEqual(handleBlur.callCount, 1); }); }); describe('onClick is defined', () => { let onClickSpy; before(() => { onClickSpy = spy(); wrapper = mount(<ChipNaked classes={{}} onClick={onClickSpy} />); }); afterEach(() => { onClickSpy.resetHistory(); }); it('should call onClick when `space` is pressed ', () => { const preventDefaultSpy = spy(); const spaceKeyDown = { preventDefault: preventDefaultSpy, keyCode: keycode('space'), }; wrapper.find('div').simulate('keyDown', spaceKeyDown); assert.strictEqual(preventDefaultSpy.callCount, 1); assert.strictEqual(onClickSpy.callCount, 0); const spaceKeyUp = { keyCode: keycode('space'), }; wrapper.find('div').simulate('keyUp', spaceKeyUp); assert.strictEqual(onClickSpy.callCount, 1); assert.strictEqual(onClickSpy.args[0][0].keyCode, spaceKeyUp.keyCode); }); it('should call onClick when `enter` is pressed ', () => { const preventDefaultSpy = spy(); const enterKeyDown = { preventDefault: preventDefaultSpy, keyCode: keycode('enter'), }; wrapper.find('div').simulate('keyDown', enterKeyDown); assert.strictEqual(preventDefaultSpy.callCount, 1); assert.strictEqual(onClickSpy.callCount, 0); const enterKeyUp = { keyCode: keycode('enter'), }; wrapper.find('div').simulate('keyUp', enterKeyUp); assert.strictEqual(onClickSpy.callCount, 1); assert.strictEqual(onClickSpy.args[0][0].keyCode, enterKeyUp.keyCode); }); }); describe('onDelete is defined and `backspace` is pressed', () => { it('should call onDelete', () => { const preventDefaultSpy = spy(); const onDeleteSpy = spy(); const wrapper2 = mount(<ChipNaked classes={{}} onDelete={onDeleteSpy} />); const backspaceKeyDown = { preventDefault: preventDefaultSpy, keyCode: keycode('backspace'), }; wrapper2.find('div').simulate('keyDown', backspaceKeyDown); assert.strictEqual(preventDefaultSpy.callCount, 1); assert.strictEqual(onDeleteSpy.callCount, 0); const backspaceKeyUp = { keyCode: keycode('backspace'), }; wrapper2.find('div').simulate('keyUp', backspaceKeyUp); assert.strictEqual(onDeleteSpy.callCount, 1); assert.strictEqual(onDeleteSpy.args[0][0].keyCode, backspaceKeyUp.keyCode); }); }); describe('has children that generate events', () => { let onClickSpy; let onDeleteSpy; let onKeyDownSpy; let onKeyUpSpy; before(() => { onClickSpy = spy(); onDeleteSpy = spy(); onKeyDownSpy = spy(); onKeyUpSpy = spy(); wrapper = mount( <Chip classes={{}} onClick={onClickSpy} onDelete={onDeleteSpy} onKeyDown={onKeyDownSpy} onKeyUp={onKeyUpSpy} label={<input className="child-input" />} />, ); }); afterEach(() => { onClickSpy.resetHistory(); onDeleteSpy.resetHistory(); }); it('should not call onDelete for child event', () => { wrapper.find('.child-input').simulate('keyDown', { keyCode: keycode('backspace') }); assert.strictEqual(onDeleteSpy.callCount, 0); }); it('should not call onClick for child event when `space` is pressed', () => { wrapper.find('.child-input').simulate('keyDown', { keyCode: keycode('space') }); assert.strictEqual(onClickSpy.callCount, 0); }); it('should not call onClick for child event when `enter` is pressed', () => { wrapper.find('.child-input').simulate('keyDown', { keyCode: keycode('enter') }); assert.strictEqual(onClickSpy.callCount, 0); }); it('should call handlers for child event', () => { onKeyDownSpy.resetHistory(); wrapper.find('.child-input').simulate('keyDown', { keyCode: keycode('p') }); assert.strictEqual(onKeyDownSpy.callCount, 1); onKeyUpSpy.resetHistory(); wrapper.find('.child-input').simulate('keyUp', { keyCode: keycode('p') }); assert.strictEqual(onKeyUpSpy.callCount, 1); }); }); }); describe('prop: icon', () => { it('should render the icon', () => { const wrapper = shallow(<Chip icon={<span />} />); assert.strictEqual( wrapper .find('span') .first() .hasClass(classes.icon), true, ); }); }); });