react-conventions
Version:
An open source set of React components that implement Ambassador's Design and UX patterns.
193 lines (152 loc) • 7.03 kB
JavaScript
import React from 'react'
import { shallow, mount } from 'enzyme'
import TestBackend from 'react-dnd-test-backend'
import { DragDropContext } from 'react-dnd'
import TestUtils from 'react-addons-test-utils'
import SortableItem from '../src/components/SortableList/SortableItem'
import SortableListWrapped, { SortableList } from '../src/components/SortableList/SortableList'
let Component = React.Component
describe('SortableList', () => {
let wrapper
const items = [
{
value: 'email',
text: 'Email',
active: false
}, {
value: 'push_notification',
text: 'Push Notification',
active: true
}, {
value: 'web',
text: 'Web',
active: false
}, {
value: 'sms',
text: 'SMS',
active: false
}
]
/**
* Wraps a component into a DragDropContext that uses the TestBackend.
*/
function wrapInTestContext(DecoratedComponent) {
return DragDropContext(TestBackend)(
class TestContextContainer extends Component {
render() {
return <DecoratedComponent {...this.props} />
}
}
)
}
it('should render itself', () => {
wrapper = mount(<SortableListWrapped items={items} />)
expect(wrapper.find('SortableList')).to.have.length(1)
expect(wrapper.find('SortableItem')).to.have.length(4)
expect(wrapper.childAt(0).childAt(0).props().value).to.be.equal('email')
expect(wrapper.childAt(0).childAt(0).props().text).to.be.equal('Email')
expect(wrapper.childAt(0).childAt(1).props().value).to.be.equal('push_notification')
expect(wrapper.childAt(0).childAt(1).props().text).to.be.equal('Push Notification')
expect(wrapper.childAt(0).childAt(2).props().value).to.be.equal('web')
expect(wrapper.childAt(0).childAt(2).props().text).to.be.equal('Web')
expect(wrapper.childAt(0).childAt(3).props().value).to.be.equal('sms')
expect(wrapper.childAt(0).childAt(3).props().text).to.be.equal('SMS')
})
it('should update state when an item is toggled', () => {
wrapper = mount(<SortableListWrapped items={items} />)
expect(wrapper.childAt(0).childAt(0).props().active).to.be.false
expect(wrapper.childAt(0).childAt(1).props().active).to.be.true
expect(wrapper.childAt(0).childAt(2).props().active).to.be.false
expect(wrapper.childAt(0).childAt(3).props().active).to.be.false
wrapper.childAt(0).childAt(0).childAt(2).childAt(0).simulate('click')
expect(wrapper.childAt(0).childAt(0).props().active).to.be.true
expect(wrapper.childAt(0).childAt(1).props().active).to.be.true
expect(wrapper.childAt(0).childAt(2).props().active).to.be.false
expect(wrapper.childAt(0).childAt(3).props().active).to.be.false
wrapper.childAt(0).childAt(0).childAt(2).childAt(0).simulate('click')
expect(wrapper.childAt(0).childAt(0).props().active).to.be.false
expect(wrapper.childAt(0).childAt(1).props().active).to.be.true
expect(wrapper.childAt(0).childAt(2).props().active).to.be.false
expect(wrapper.childAt(0).childAt(3).props().active).to.be.false
})
it('should trigger a callback when an item is toggled', () => {
let sortableItems = items
const changeCallback = function(event) {
sortableItems = event.target.value
}
wrapper = mount(<SortableListWrapped items={items} changeCallback={changeCallback} />)
expect(sortableItems[0].active).to.be.false
expect(sortableItems[1].active).to.be.true
expect(sortableItems[2].active).to.be.false
expect(sortableItems[3].active).to.be.false
wrapper.childAt(0).childAt(0).childAt(2).childAt(0).simulate('click')
expect(sortableItems[0].active).to.be.true
expect(sortableItems[1].active).to.be.true
expect(sortableItems[2].active).to.be.false
expect(sortableItems[3].active).to.be.false
wrapper.childAt(0).childAt(0).childAt(2).childAt(0).simulate('click')
expect(sortableItems[0].active).to.be.false
expect(sortableItems[1].active).to.be.true
expect(sortableItems[2].active).to.be.false
expect(sortableItems[3].active).to.be.false
})
it('should update the state when props change', () => {
wrapper = mount(<SortableListWrapped items={items} />)
expect(wrapper.find('SortableItem')).to.have.length(4)
wrapper.setProps({ items: [{ value: 'email', text: 'Email', active: false }, { value: 'push_notification', text: 'Push Notification', active: true }, { value: 'web', text: 'Web', active: false }] })
wrapper.update()
expect(wrapper.find('SortableItem')).to.have.length(3)
})
it('should remove event listener when the component is unmounted', () => {
const spy = sinon.spy(window, 'removeEventListener')
wrapper = mount(<SortableListWrapped items={items} />)
wrapper.unmount()
expect(spy.called).to.be.true
})
it('should reorder items when dragging', () => {
let sortableItems = items
const changeCallback = (event) => {
sortableItems = event.target.value
}
expect(sortableItems[0].value).to.equal('email')
expect(sortableItems[1].value).to.equal('push_notification')
expect(sortableItems[2].value).to.equal('web')
expect(sortableItems[3].value).to.equal('sms')
const SortableListContext = wrapInTestContext(SortableList)
const root = TestUtils.renderIntoDocument(<SortableListWrapped items={items} changeCallback={changeCallback} />)
// Obtain a reference to the backend
const backend = root.getManager().getBackend()
const registry = root.getManager().getRegistry()
// Find the drag source ID and use it to simulate the dragging operation
const allItems = TestUtils.scryRenderedComponentsWithType(root, SortableItem)
const source = allItems[0]
const target = allItems[1]
const sourceId = source.getDecoratedComponentInstance().getHandlerId()
const targetId = target.getHandlerId()
backend.actions.beginDrag([sourceId])
backend.actions.hover([targetId])
backend.actions.drop()
backend.actions.endDrag()
expect(sortableItems[0].value).to.equal('push_notification')
expect(sortableItems[1].value).to.equal('email')
expect(sortableItems[2].value).to.equal('web')
expect(sortableItems[3].value).to.equal('sms')
})
it('should set state and trigger callback when dragging starts', () => {
const onDragStartSpy = sinon.spy()
wrapper = shallow(<SortableList items={items} onDragStart={onDragStartSpy} />)
expect(wrapper.state().dragging).to.be.false
wrapper.instance().onDragStart()
expect(wrapper.state().dragging).to.be.true
expect(onDragStartSpy.called).to.be.true
})
it('should set state and trigger callback when dragging stops', () => {
const onDragStopSpy = sinon.spy()
wrapper = shallow(<SortableList items={items} onDragStop={onDragStopSpy} />)
wrapper.setState({ dragging: true })
expect(wrapper.state().dragging).to.be.true
wrapper.instance().onDragStop()
expect(wrapper.state().dragging).to.be.false
expect(onDragStopSpy.called).to.be.true
})
})