UNPKG

react-conventions

Version:

An open source set of React components that implement Ambassador's Design and UX patterns.

345 lines (245 loc) 13.4 kB
import React from 'react' import { shallow, mount } from 'enzyme' import InlineEdit from '../src/components/InlineEdit/InlineEdit' import Icon from '../src/components/Icon/Icon' describe('InlineEdit', () => { it('should render a span and buttons', () => { const wrapper = shallow(<InlineEdit name='test' value='test value' isEditing={true} />) expect(wrapper.hasClass('readonly')).to.be.false expect(wrapper.find('.inline-text-wrapper')).to.have.length(1) expect(wrapper.find('.inline-text-wrapper-hover')).to.have.length(0) expect(wrapper.find(Icon)).to.have.length(2) expect(wrapper.find('.inline-button-wrapper').at(0).childAt(0).hasClass('save-button')).to.be.true expect(wrapper.find('.inline-button-wrapper').at(0).childAt(1).hasClass('cancel-button')).to.be.true expect(wrapper.find('.copy-icon')).to.have.length(0) expect(wrapper.find('.inline-icon')).to.have.length(0) expect(wrapper.find('.inline-label')).to.have.length(0) expect(wrapper.find('Tooltip')).to.have.length(0) }) it('should not render buttons', () => { const wrapper = shallow(<InlineEdit name='test' value='test value' />) expect(wrapper.find('.inline-text-wrapper-hover')).to.have.length(1) expect(wrapper.find(Icon)).to.have.length(0) }) it('should trigger the callback function', () => { const changeCallback = sinon.spy() const wrapper = mount(<InlineEdit name='test' isEditing={true} changeCallback={changeCallback} value='testValue' />) const trigger = wrapper.find('.inline-button-wrapper').at(0).childAt(0) wrapper.find('.inline-text-overflow-wrapper').at(0).childAt(0).node.innerHTML = 'test value' trigger.simulate('click') expect(changeCallback.calledWithExactly({ target: { name: 'test', value: 'test value' }})).to.be.true }) it('should not trigger the callback if the edit was canceled', () => { const changeCallback = sinon.spy() const wrapper = mount(<InlineEdit name='test' isEditing={true} value='test value' changeCallback={changeCallback} />) const trigger = wrapper.find('.inline-button-wrapper').at(0).childAt(1) trigger.simulate('click') expect(changeCallback.called).to.be.false }) it('should not trigger the callback if the value hasn\'t changed', () => { const changeCallback = sinon.spy() const wrapper = mount(<InlineEdit name='test' isEditing={true} value='test value' changeCallback={changeCallback} />) const trigger = wrapper.find('.inline-button-wrapper').at(0).childAt(0) trigger.simulate('click') expect(changeCallback.called).to.be.false }) it('should show the placeholder when the value is empty', () => { const wrapper = mount(<InlineEdit name='test' value='' />) expect(wrapper.find('.placeholder')).to.have.length(1) expect(wrapper.childAt(0).childAt(0).text()).to.equal('Click to edit') wrapper.setProps({ isEditing: true }) expect(wrapper.childAt(0).childAt(0).text()).to.equal('') }) it('should show the placeholder when the value is null', () => { const value = null const wrapper = mount(<InlineEdit name='test' value={value} />) expect(wrapper.find('.placeholder')).to.have.length(1) expect(wrapper.childAt(0).childAt(0).text()).to.equal('Click to edit') wrapper.setProps({ isEditing: true }) expect(wrapper.childAt(0).childAt(0).text()).to.equal('') }) it('should be readonly', () => { const spy = sinon.spy() const wrapper = mount(<InlineEdit name='test' changeCallback={spy} value='test value' readonly />) const editTrigger = wrapper.childAt(0) expect(wrapper.find('.readonly')).to.have.length(1) editTrigger.simulate('click') expect(spy.called).to.be.false }) it('should have a loader', () => { const wrapper = mount(<InlineEdit name='test' value='test value' />) expect(wrapper.find('Spinner').at(0).props().loading).to.be.false wrapper.setProps({ loading: true }) expect(wrapper.find('Spinner').at(0).props().loading).to.be.true }) it('should have an error', () => { const wrapper = mount(<InlineEdit name='test' value='test value' />) expect(wrapper.state().error).to.equal('') wrapper.setProps({ error: 'This is an error' }) expect(wrapper.find('.error')).to.have.length(1) expect(wrapper.state().error).to.equal('This is an error') expect(wrapper.state().isEditing).to.be.true expect(wrapper.find('.error-text')).to.have.length(1) expect(wrapper.find('.error-text').at(0).text()).to.equal('This is an error') }) it('should revert back to the previously saved value if there is an error and the change is canceled', () => { const changeCallback = sinon.spy() const wrapper = mount(<InlineEdit name='test' isEditing={true} changeCallback={changeCallback} value='testValue' />) wrapper.find('.inline-text-wrapper').at(0).node.innerHTML = 'test value' let saveTrigger = wrapper.find('.inline-button-wrapper').at(0).childAt(0) saveTrigger.simulate('click') expect(wrapper.state().value).to.equal('test value') wrapper.setProps({ error: 'This is an error' }) expect(wrapper.state().error).to.equal('This is an error') expect(wrapper.state().isEditing).to.be.true saveTrigger = wrapper.find('.inline-button-wrapper').at(0).childAt(0) saveTrigger.simulate('click') expect(wrapper.state().error).to.equal('This is an error') expect(wrapper.state().isEditing).to.be.true const cancelTrigger = wrapper.find('.inline-button-wrapper').at(0).childAt(1) cancelTrigger.simulate('click') expect(wrapper.state().error).to.equal('') expect(wrapper.state().isEditing).to.be.false expect(wrapper.state().value).to.equal('testValue') }) it('should trigger the callback function if there was an error and the change was canceled', () => { const changeCallback = sinon.spy() const wrapper = mount(<InlineEdit name='test' isEditing={true} changeCallback={changeCallback} value='testValue' />) wrapper.find('.inline-text-wrapper').at(0).node.innerHTML = 'test value' let saveTrigger = wrapper.find('.inline-button-wrapper').at(0).childAt(0) saveTrigger.simulate('click') expect(changeCallback.calledWithExactly({ target: { name: 'test', value: 'test value' }})).to.be.true wrapper.setProps({ error: 'This is an error' }) expect(wrapper.state().error).to.equal('This is an error') expect(wrapper.state().isEditing).to.be.true const cancelTrigger = wrapper.find('.inline-button-wrapper').at(0).childAt(1) cancelTrigger.simulate('click') expect(changeCallback.calledWithExactly({ target: { name: 'test', value: 'testValue', canceled: true }})).to.be.true }) it('should have a copy to clipboard icon', (done) => { const wrapper = mount(<InlineEdit name='test' value='test value' copyToClipboard />) expect(wrapper.find('.copy-icon')).to.have.length(1) expect(wrapper.find('.copy-icon').at(0).find('Icon')).to.have.length(1) expect(wrapper.find('.copy-icon').hasClass('copied')).to.be.false wrapper.instance().handleCopy() expect(wrapper.find('.copy-icon').at(0).find('Icon')).to.have.length(0) expect(wrapper.find('.copy-icon').hasClass('copied')).to.be.true expect(wrapper.find('.copy-icon').at(0).text()).to.equal('copied!') setTimeout(() => { expect(wrapper.find('.copy-icon').at(0).find('Icon')).to.have.length(1) expect(wrapper.find('.copy-icon').hasClass('copied')).to.be.false done() }, 1900) }) it('should have an inline icon and label', () => { const wrapper = mount(<InlineEdit name='test' value='test value' label='Email' icon='icon-mail-1' />) expect(wrapper.find('.inline-icon')).to.have.length(1) expect(wrapper.find('.inline-label')).to.have.length(1) }) it('should set max-width for the edit component', () => { let wrapper = mount(<InlineEdit name='test' value='test value' />) expect(wrapper.state().inlineEditMaxWidth).to.equal('calc(100% - 0px)') wrapper = mount(<InlineEdit name='test' value='test value' label='Email' icon='icon-mail-1' />) expect(wrapper.state().inlineEditMaxWidth).to.not.equal('calc(100% - 0px)') }) it('should have a tooltip', () => { const wrapper = mount(<InlineEdit name='test' value='test value' tooltipText='test tooltip' tooltipPlacement='top' tooltipClass='test-class' />) expect(wrapper.find('Tooltip')).to.have.length(1) expect(wrapper.find('Tooltip').props().content).to.equal('test tooltip') expect(wrapper.find('Tooltip').props().tooltipPlacement).to.equal('top') expect(wrapper.find('Tooltip').props().optClass).to.equal('test-class') }) it('should attach key listeners', () => { const wrapper = mount(<InlineEdit name='test' value='test value' />) const addEventListenerSpy = sinon.spy(wrapper.instance()._textValue, 'addEventListener') wrapper.instance().attachKeyListeners() expect(addEventListenerSpy.calledWithExactly('keypress', wrapper.instance().handleKeyPress)).to.be.true expect(addEventListenerSpy.calledWithExactly('keyup', wrapper.instance().handleKeyUp)).to.be.true }) it('should handle keyPress events', () => { const wrapper = shallow(<InlineEdit name='test' value='test value' />) const saveStub = sinon.stub(wrapper.instance(), 'handleSave') let event = { keyCode: 13, preventDefault: sinon.spy() } wrapper.instance().handleKeyPress(event) expect(event.preventDefault.called).to.be.true expect(saveStub.calledOnce).to.be.true event = { which: 13, preventDefault: sinon.spy() } wrapper.instance().handleKeyPress(event) expect(event.preventDefault.called).to.be.true expect(saveStub.calledTwice).to.be.true event = { keyCode: 40, preventDefault: sinon.spy() } wrapper.instance().handleKeyPress(event) expect(event.preventDefault.called).to.be.false expect(saveStub.calledThrice).to.be.false }) it('should handle keyUp events', () => { const wrapper = shallow(<InlineEdit name='test' value='test value' />) const cancelStub = sinon.stub(wrapper.instance(), 'handleCancel') let event = { keyCode: 27, preventDefault: sinon.spy() } wrapper.instance().handleKeyUp(event) expect(event.preventDefault.called).to.be.true expect(cancelStub.calledOnce).to.be.true event = { which: 27, preventDefault: sinon.spy() } wrapper.instance().handleKeyUp(event) expect(event.preventDefault.called).to.be.true expect(cancelStub.calledTwice).to.be.true event = { keyCode: 40, preventDefault: sinon.spy() } wrapper.instance().handleKeyUp(event) expect(event.preventDefault.called).to.be.false expect(cancelStub.calledThrice).to.be.false }) it('should render a select field', () => { const options = [ { label: 'Item 1', value: 'item_1' }, { label: 'Item 2', value: 'item_2' }, { label: 'Item 3', value: 'item_3' }, { label: 'Item 4', value: 'item_4' } ] const wrapper = shallow(<InlineEdit name='test' value='item_3' type='select' options={options} />) expect(wrapper.find('SelectField')).to.have.length(1) expect(wrapper.find('SelectField').at(0).props().value).to.equal('item_3') expect(wrapper.find('SelectField').at(0).props().options).to.deep.equal(options) }) it('should update the state when an item is selected', () => { const options = [ { label: 'Item 1', value: 'item_1' }, { label: 'Item 2', value: 'item_2' }, { label: 'Item 3', value: 'item_3' }, { label: 'Item 4', value: 'item_4' } ] const wrapper = shallow(<InlineEdit name='test' value='item_3' type='select' options={options} />) expect(wrapper.state().value).to.equal('item_3') wrapper.instance().handleSave({ target: { value: 'item_1' } }) expect(wrapper.state().value).to.equal('item_1') }) it('should trigger the change callback when an item is selected', () => { const changeCallback = sinon.spy() const options = [ { label: 'Item 1', value: 'item_1' }, { label: 'Item 2', value: 'item_2' }, { label: 'Item 3', value: 'item_3' }, { label: 'Item 4', value: 'item_4' } ] const wrapper = shallow(<InlineEdit name='test' value='item_3' type='select' options={options} changeCallback={changeCallback} />) expect(wrapper.state().value).to.equal('item_3') wrapper.instance().handleSave({ target: { value: 'item_1' } }) expect(wrapper.state().value).to.equal('item_1') expect(changeCallback.calledWithExactly({ target: { name: 'test', value: 'item_1' } })).to.be.true wrapper.instance().handleSave({ target: { value: 'item_1' } }) expect(changeCallback.calledTwice).to.be.false }) it('should set classes on the select field', () => { const options = [ { label: 'Item 1', value: 'item_1' }, { label: 'Item 2', value: 'item_2' }, { label: 'Item 3', value: 'item_3' }, { label: 'Item 4', value: 'item_4' } ] let wrapper = shallow(<InlineEdit name='test' value='item_3' type='select' options={options} />) let field = wrapper.instance().getSelect() expect(field.props.optClass).to.equal('inline-edit-select') wrapper = shallow(<InlineEdit name='test' value='item_3' type='select' options={options} loading={true} />) field = wrapper.instance().getSelect() expect(field.props.optClass).to.equal('inline-edit-select loading') }) })