Skip to content

Commit

Permalink
feat(chord): init unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
plouc committed Jan 1, 2022
1 parent 73467c9 commit 7c1d39b
Show file tree
Hide file tree
Showing 5 changed files with 232 additions and 4 deletions.
9 changes: 5 additions & 4 deletions packages/chord/src/ChordArc.tsx
Expand Up @@ -40,7 +40,7 @@ export const ChordArc = memo(
return (event: MouseEvent) => {
setCurrent(arc)
showTooltipFromEvent(createElement(tooltip, { arc }), event)
onMouseEnter && onMouseEnter(arc, event)
onMouseEnter?.(arc, event)
}
}, [isInteractive, showTooltipFromEvent, tooltip, arc, onMouseEnter])

Expand All @@ -49,7 +49,7 @@ export const ChordArc = memo(

return (event: MouseEvent) => {
showTooltipFromEvent(createElement(tooltip, { arc }), event)
onMouseMove && onMouseMove(arc, event)
onMouseMove?.(arc, event)
}
}, [isInteractive, showTooltipFromEvent, tooltip, arc, onMouseMove])

Expand All @@ -59,18 +59,19 @@ export const ChordArc = memo(
return (event: MouseEvent) => {
setCurrent(null)
hideTooltip()
onMouseLeave && onMouseLeave(arc, event)
onMouseLeave?.(arc, event)
}
}, [isInteractive, hideTooltip, arc, onMouseLeave])

const handleClick = useMemo(() => {
if (!isInteractive || !onClick) return undefined

return (event: MouseEvent) => onClick(arc, event)
return (event: MouseEvent) => onClick?.(arc, event)
}, [isInteractive, arc, onClick])

return (
<animated.path
data-testid={`arc.${arc.id}`}
d={computeArcPath({
startAngle: animatedProps.startAngle,
endAngle: animatedProps.endAngle,
Expand Down
1 change: 1 addition & 0 deletions packages/chord/src/ChordLabels.tsx
Expand Up @@ -96,6 +96,7 @@ export const ChordLabels = memo(({ arcs, radius, rotation, color }: ChordLabelsP
{transition((transitionProps, label) => (
<animated.text
key={label.id}
data-testid={`label.${label.id}`}
style={{
...theme.labels.text,
pointerEvents: 'none',
Expand Down
1 change: 1 addition & 0 deletions packages/chord/src/ChordRibbon.tsx
Expand Up @@ -79,6 +79,7 @@ export const ChordRibbon = memo(

return (
<animated.path
data-testid={`ribbon.${ribbon.source.id}.${ribbon.target.id}`}
d={computeRibbonPath({
sourceStartAngle: animatedProps.sourceStartAngle,
sourceEndAngle: animatedProps.sourceEndAngle,
Expand Down
2 changes: 2 additions & 0 deletions packages/chord/tests/.eslintrc.yml
@@ -0,0 +1,2 @@
env:
jest: true
223 changes: 223 additions & 0 deletions packages/chord/tests/Chord.test.tsx
@@ -0,0 +1,223 @@
import { mount } from 'enzyme'
// @ts-ignore
import { Chord } from '../src'

const sampleData = {
data: [
[0, 1, 0, 1],
[1, 0, 1, 0],
[0, 1, 0, 1],
[1, 0, 1, 0],
],
keys: ['A', 'B', 'C', 'D'],
}

const baseProps = {
...sampleData,
width: 600,
height: 600,
animate: false,
}

it('basic chord diagram', () => {
const wrapper = mount(<Chord {...baseProps} />)

sampleData.keys.forEach(key => {
const arc = wrapper.find(`path[data-testid='arc.${key}']`)
expect(arc.exists()).toBeTruthy()
})

expect(wrapper.find(`path[data-testid^='ribbon.']`)).toHaveLength(4)
})

describe('labels', () => {
it('enabled by default', () => {
const wrapper = mount(<Chord {...baseProps} />)

sampleData.keys.forEach(key => {
const label = wrapper.find(`text[data-testid='label.${key}']`)
expect(label.exists()).toBeTruthy()
expect(label.text()).toEqual(key)
})
})

it('disabled', () => {
const wrapper = mount(<Chord {...baseProps} enableLabel={false} />)

sampleData.keys.forEach(key => {
const label = wrapper.find(`text[data-testid='label.${key}']`)
expect(label.exists()).toBeFalsy()
})
})

it('customize label', () => {
const wrapper = mount(<Chord {...baseProps} label={arc => `custom: ${arc.id}`} />)

sampleData.keys.forEach(key => {
const label = wrapper.find(`text[data-testid='label.${key}']`)
expect(label.exists()).toBeTruthy()
expect(label.text()).toEqual(`custom: ${key}`)
})
})

it('static text color', () => {
const color = 'rgba(255, 0, 0, 1)'
const wrapper = mount(<Chord {...baseProps} labelTextColor={color} />)

sampleData.keys.forEach(key => {
const label = wrapper.find(`text[data-testid='label.${key}']`)
expect(label.exists()).toBeTruthy()
expect(label.prop('style').fill).toEqual(color)
})
})

it('text color from arcs', () => {
const colors = [
'rgba(255, 0, 0, 1)',
'rgba(0, 255, 0, 1)',
'rgba(0, 0, 255, 1)',
'rgba(255, 0, 255, 1)',
]
const wrapper = mount(
<Chord
{...baseProps}
colors={colors}
labelTextColor={{
from: 'color',
}}
/>
)

sampleData.keys.forEach((key, index) => {
const label = wrapper.find(`text[data-testid='label.${key}']`)
expect(label.exists()).toBeTruthy()
expect(label.prop('style').fill).toEqual(colors[index])
})
})
})

describe('interactivity', () => {
describe('arcs', () => {
it('onMouseEnter', () => {
const onMouseEnter = jest.fn()
const wrapper = mount(<Chord {...baseProps} onArcMouseEnter={onMouseEnter} />)

sampleData.keys.forEach(key => {
wrapper.find(`path[data-testid='arc.${key}']`).simulate('mouseenter')

expect(onMouseEnter).toHaveBeenCalledTimes(1)
const [datum] = onMouseEnter.mock.calls[0]
expect(datum.id).toEqual(key)

onMouseEnter.mockClear()
})
})

it('onMouseMove', () => {
const onMouseMove = jest.fn()
const wrapper = mount(<Chord {...baseProps} onArcMouseMove={onMouseMove} />)

sampleData.keys.forEach(key => {
wrapper.find(`path[data-testid='arc.${key}']`).simulate('mousemove')

expect(onMouseMove).toHaveBeenCalledTimes(1)
const [datum] = onMouseMove.mock.calls[0]
expect(datum.id).toEqual(key)

onMouseMove.mockClear()
})
})

it('onMouseLeave', () => {
const onMouseLeave = jest.fn()
const wrapper = mount(<Chord {...baseProps} onArcMouseLeave={onMouseLeave} />)

sampleData.keys.forEach(key => {
wrapper.find(`path[data-testid='arc.${key}']`).simulate('mouseleave')

expect(onMouseLeave).toHaveBeenCalledTimes(1)
const [datum] = onMouseLeave.mock.calls[0]
expect(datum.id).toEqual(key)

onMouseLeave.mockClear()
})
})

it('onClick', () => {
const onClick = jest.fn()
const wrapper = mount(<Chord {...baseProps} onArcClick={onClick} />)

sampleData.keys.forEach(key => {
wrapper.find(`path[data-testid='arc.${key}']`).simulate('click')

expect(onClick).toHaveBeenCalledTimes(1)
const [datum] = onClick.mock.calls[0]
expect(datum.id).toEqual(key)

onClick.mockClear()
})
})
})

describe('ribbons', () => {
it('onMouseEnter', () => {
const onMouseEnter = jest.fn()
const wrapper = mount(<Chord {...baseProps} onRibbonMouseEnter={onMouseEnter} />)

wrapper.find(`path[data-testid^='ribbon.']`).forEach(ribbon => {
ribbon.simulate('mouseenter')

expect(onMouseEnter).toHaveBeenCalledTimes(1)
const [datum] = onMouseEnter.mock.calls[0]
expect(datum.id).toEqual(ribbon.prop('data-testid').slice(7))

onMouseEnter.mockClear()
})
})

it('onMouseMove', () => {
const onMouseMove = jest.fn()
const wrapper = mount(<Chord {...baseProps} onRibbonMouseMove={onMouseMove} />)

wrapper.find(`path[data-testid^='ribbon.']`).forEach(ribbon => {
ribbon.simulate('mousemove')

expect(onMouseMove).toHaveBeenCalledTimes(1)
const [datum] = onMouseMove.mock.calls[0]
expect(datum.id).toEqual(ribbon.prop('data-testid').slice(7))

onMouseMove.mockClear()
})
})

it('onMouseLeave', () => {
const onMouseLeave = jest.fn()
const wrapper = mount(<Chord {...baseProps} onRibbonMouseLeave={onMouseLeave} />)

wrapper.find(`path[data-testid^='ribbon.']`).forEach(ribbon => {
ribbon.simulate('mouseleave')

expect(onMouseLeave).toHaveBeenCalledTimes(1)
const [datum] = onMouseLeave.mock.calls[0]
expect(datum.id).toEqual(ribbon.prop('data-testid').slice(7))

onMouseLeave.mockClear()
})
})

it('onClick', () => {
const onClick = jest.fn()
const wrapper = mount(<Chord {...baseProps} onRibbonClick={onClick} />)

wrapper.find(`path[data-testid^='ribbon.']`).forEach(ribbon => {
ribbon.simulate('click')

expect(onClick).toHaveBeenCalledTimes(1)
const [datum] = onClick.mock.calls[0]
expect(datum.id).toEqual(ribbon.prop('data-testid').slice(7))

onClick.mockClear()
})
})
})
})

0 comments on commit 7c1d39b

Please sign in to comment.