UNPKG

react-d3-dag

Version:

React component to create interactive D3 directed acyclic graphs (DAGs)

188 lines (163 loc) 7.19 kB
import React from 'react'; import { shallow, mount } from 'enzyme'; import Link from '../index.tsx'; describe('<Link />', () => { const linkData = { source: { data: { __rd3dag: {} }, x: 123, y: 321, }, target: { data: { __rd3dag: {} }, x: 456, y: 654, }, }; const mockProps = { linkData, pathFunc: 'diagonal', orientation: 'horizontal', transitionDuration: 500, onClick: () => {}, onMouseOver: () => {}, onMouseOut: () => {}, }; const pathFuncs = { testPathFunc: (d, orientation) => orientation && `M${d.source.y},${d.source.x}V${d.target.x}H${d.target.y}`, }; jest.spyOn(Link.prototype, 'drawPath'); jest.spyOn(Link.prototype, 'drawDiagonalPath'); jest.spyOn(Link.prototype, 'drawElbowPath'); jest.spyOn(Link.prototype, 'drawStraightPath'); jest.spyOn(Link.prototype, 'drawStepPath'); jest.spyOn(Link.prototype, 'applyOpacity'); jest.spyOn(pathFuncs, 'testPathFunc'); // Clear method spies on prototype after each test afterEach(() => jest.clearAllMocks()); it('binds IDs of source & target nodes to data-source-id/data-target-id', () => { linkData.source.data.__rd3dag.id = 1; linkData.target.data.__rd3dag.id = 2; const renderedComponent = shallow(<Link {...mockProps} />); expect(renderedComponent.find('path').prop('data-source-id')).toBe( linkData.source.data.__rd3dag.id ); expect(renderedComponent.find('path').prop('data-target-id')).toBe( linkData.target.data.__rd3dag.id ); delete linkData.source.id; delete linkData.target.id; }); describe('handling classNames', () => { it('applies the expected internal className', () => { const renderedComponent = shallow(<Link {...mockProps} />); expect(renderedComponent.prop('className')).toBe('rd3dag-link'); }); it('applies any additional classNames returned by `pathClassFunc` if defined', () => { const fixture = 'additionalPathClassName'; const renderedComponent = shallow(<Link {...mockProps} pathClassFunc={() => fixture} />); expect(renderedComponent.prop('className')).toBe(['rd3dag-link', fixture].join(' ')); }); }); describe('drawing paths', () => { it('calls the appropriate path func based on `props.pathFunc`', () => { const diagonalComponent = shallow(<Link {...mockProps} />); const elbowComponent = shallow(<Link {...mockProps} pathFunc="elbow" />); const straightComponent = shallow(<Link {...mockProps} pathFunc="straight" />); const stepComponent = shallow(<Link {...mockProps} pathFunc="step" />); shallow(<Link {...mockProps} pathFunc={pathFuncs.testPathFunc} />); expect(diagonalComponent.instance().drawDiagonalPath).toHaveBeenCalled(); expect(elbowComponent.instance().drawElbowPath).toHaveBeenCalled(); expect(straightComponent.instance().drawStraightPath).toHaveBeenCalled(); expect(stepComponent.instance().drawStepPath).toHaveBeenCalled(); expect(pathFuncs.testPathFunc).toHaveBeenCalled(); expect(Link.prototype.drawPath).toHaveBeenCalledTimes(5); }); it('returns an appropriate elbowPath according to `props.orientation`', () => { expect(Link.prototype.drawElbowPath(linkData, 'horizontal')).toBe( `M${linkData.source.y},${linkData.source.x}V${linkData.target.x}H${linkData.target.y}` ); expect(Link.prototype.drawElbowPath(linkData, 'vertical')).toBe( `M${linkData.source.x},${linkData.source.y}V${linkData.target.y}H${linkData.target.x}` ); }); it('returns an appropriate diagonal according to `props.orientation`', () => { const ymean = (linkData.target.y + linkData.source.y) / 2; expect(Link.prototype.drawDiagonalPath(linkData, 'horizontal')).toBe( `M${linkData.source.y},${linkData.source.x}` + `C${ymean},${linkData.source.x},${ymean},${linkData.target.x},` + `${linkData.target.y},${linkData.target.x}` ); expect(Link.prototype.drawDiagonalPath(linkData, 'vertical')).toBe( `M${linkData.source.x},${linkData.source.y}` + `C${linkData.source.x},${ymean},${linkData.target.x},${ymean},` + `${linkData.target.x},${linkData.target.y}` ); }); it('returns an appropriate straightPath according to `props.orientation`', () => { expect(Link.prototype.drawStraightPath(linkData, 'horizontal')).toBe( `M${linkData.source.y},${linkData.source.x}L${linkData.target.y},${linkData.target.x}` ); expect(Link.prototype.drawStraightPath(linkData, 'vertical')).toBe( `M${linkData.source.x},${linkData.source.y}L${linkData.target.x},${linkData.target.y}` ); }); it('return an appropriate stepPath according to `props.orientation`', () => { const { source, target } = linkData; const deltaY = target.y - source.y; expect(Link.prototype.drawStepPath(linkData, 'horizontal')).toBe( `M${source.y},${source.x} H${source.y + deltaY / 2} V${target.x} H${target.y}` ); expect(Link.prototype.drawStepPath(linkData, 'vertical')).toBe( `M${source.x},${source.y} V${source.y + deltaY / 2} H${target.x} V${target.y}` ); }); }); it('fades in once it has been mounted', () => { const fixture = 1; const renderedComponent = mount(<Link {...mockProps} />); expect(renderedComponent.instance().applyOpacity).toHaveBeenCalledWith( fixture, mockProps.transitionDuration ); }); describe('Events', () => { it('handles onClick events and passes its nodeId & event object to onClick handler', () => { const onClickSpy = jest.fn(); const mockEvt = { mock: 'event' }; const renderedComponent = shallow(<Link {...mockProps} onClick={onClickSpy} />); renderedComponent.simulate('click', mockEvt); expect(onClickSpy).toHaveBeenCalledTimes(1); expect(onClickSpy).toHaveBeenCalledWith( linkData.source, linkData.target, expect.objectContaining(mockEvt) ); }); it('handles onMouseOver events and passes its nodeId & event object to onMouseOver handler', () => { const onMouseOverSpy = jest.fn(); const mockEvt = { mock: 'event' }; const renderedComponent = shallow(<Link {...mockProps} onMouseOver={onMouseOverSpy} />); renderedComponent.simulate('mouseover', mockEvt); expect(onMouseOverSpy).toHaveBeenCalledTimes(1); expect(onMouseOverSpy).toHaveBeenCalledWith( linkData.source, linkData.target, expect.objectContaining(mockEvt) ); }); it('handles onMouseOut events and passes its nodeId & event object to onMouseOut handler', () => { const onMouseOutSpy = jest.fn(); const mockEvt = { mock: 'event' }; const renderedComponent = shallow(<Link {...mockProps} onMouseOut={onMouseOutSpy} />); renderedComponent.simulate('mouseout', mockEvt); expect(onMouseOutSpy).toHaveBeenCalledTimes(1); expect(onMouseOutSpy).toHaveBeenCalledWith( linkData.source, linkData.target, expect.objectContaining(mockEvt) ); }); }); });