Skip to content

Commit 7c1d39b

Browse files
committedJan 1, 2022
feat(chord): init unit tests
1 parent 73467c9 commit 7c1d39b

File tree

5 files changed

+232
-4
lines changed

5 files changed

+232
-4
lines changed
 

‎packages/chord/src/ChordArc.tsx

+5-4
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export const ChordArc = memo(
4040
return (event: MouseEvent) => {
4141
setCurrent(arc)
4242
showTooltipFromEvent(createElement(tooltip, { arc }), event)
43-
onMouseEnter && onMouseEnter(arc, event)
43+
onMouseEnter?.(arc, event)
4444
}
4545
}, [isInteractive, showTooltipFromEvent, tooltip, arc, onMouseEnter])
4646

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

5050
return (event: MouseEvent) => {
5151
showTooltipFromEvent(createElement(tooltip, { arc }), event)
52-
onMouseMove && onMouseMove(arc, event)
52+
onMouseMove?.(arc, event)
5353
}
5454
}, [isInteractive, showTooltipFromEvent, tooltip, arc, onMouseMove])
5555

@@ -59,18 +59,19 @@ export const ChordArc = memo(
5959
return (event: MouseEvent) => {
6060
setCurrent(null)
6161
hideTooltip()
62-
onMouseLeave && onMouseLeave(arc, event)
62+
onMouseLeave?.(arc, event)
6363
}
6464
}, [isInteractive, hideTooltip, arc, onMouseLeave])
6565

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

69-
return (event: MouseEvent) => onClick(arc, event)
69+
return (event: MouseEvent) => onClick?.(arc, event)
7070
}, [isInteractive, arc, onClick])
7171

7272
return (
7373
<animated.path
74+
data-testid={`arc.${arc.id}`}
7475
d={computeArcPath({
7576
startAngle: animatedProps.startAngle,
7677
endAngle: animatedProps.endAngle,

‎packages/chord/src/ChordLabels.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ export const ChordLabels = memo(({ arcs, radius, rotation, color }: ChordLabelsP
9696
{transition((transitionProps, label) => (
9797
<animated.text
9898
key={label.id}
99+
data-testid={`label.${label.id}`}
99100
style={{
100101
...theme.labels.text,
101102
pointerEvents: 'none',

‎packages/chord/src/ChordRibbon.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ export const ChordRibbon = memo(
7979

8080
return (
8181
<animated.path
82+
data-testid={`ribbon.${ribbon.source.id}.${ribbon.target.id}`}
8283
d={computeRibbonPath({
8384
sourceStartAngle: animatedProps.sourceStartAngle,
8485
sourceEndAngle: animatedProps.sourceEndAngle,

‎packages/chord/tests/.eslintrc.yml

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
env:
2+
jest: true

‎packages/chord/tests/Chord.test.tsx

+223
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
import { mount } from 'enzyme'
2+
// @ts-ignore
3+
import { Chord } from '../src'
4+
5+
const sampleData = {
6+
data: [
7+
[0, 1, 0, 1],
8+
[1, 0, 1, 0],
9+
[0, 1, 0, 1],
10+
[1, 0, 1, 0],
11+
],
12+
keys: ['A', 'B', 'C', 'D'],
13+
}
14+
15+
const baseProps = {
16+
...sampleData,
17+
width: 600,
18+
height: 600,
19+
animate: false,
20+
}
21+
22+
it('basic chord diagram', () => {
23+
const wrapper = mount(<Chord {...baseProps} />)
24+
25+
sampleData.keys.forEach(key => {
26+
const arc = wrapper.find(`path[data-testid='arc.${key}']`)
27+
expect(arc.exists()).toBeTruthy()
28+
})
29+
30+
expect(wrapper.find(`path[data-testid^='ribbon.']`)).toHaveLength(4)
31+
})
32+
33+
describe('labels', () => {
34+
it('enabled by default', () => {
35+
const wrapper = mount(<Chord {...baseProps} />)
36+
37+
sampleData.keys.forEach(key => {
38+
const label = wrapper.find(`text[data-testid='label.${key}']`)
39+
expect(label.exists()).toBeTruthy()
40+
expect(label.text()).toEqual(key)
41+
})
42+
})
43+
44+
it('disabled', () => {
45+
const wrapper = mount(<Chord {...baseProps} enableLabel={false} />)
46+
47+
sampleData.keys.forEach(key => {
48+
const label = wrapper.find(`text[data-testid='label.${key}']`)
49+
expect(label.exists()).toBeFalsy()
50+
})
51+
})
52+
53+
it('customize label', () => {
54+
const wrapper = mount(<Chord {...baseProps} label={arc => `custom: ${arc.id}`} />)
55+
56+
sampleData.keys.forEach(key => {
57+
const label = wrapper.find(`text[data-testid='label.${key}']`)
58+
expect(label.exists()).toBeTruthy()
59+
expect(label.text()).toEqual(`custom: ${key}`)
60+
})
61+
})
62+
63+
it('static text color', () => {
64+
const color = 'rgba(255, 0, 0, 1)'
65+
const wrapper = mount(<Chord {...baseProps} labelTextColor={color} />)
66+
67+
sampleData.keys.forEach(key => {
68+
const label = wrapper.find(`text[data-testid='label.${key}']`)
69+
expect(label.exists()).toBeTruthy()
70+
expect(label.prop('style').fill).toEqual(color)
71+
})
72+
})
73+
74+
it('text color from arcs', () => {
75+
const colors = [
76+
'rgba(255, 0, 0, 1)',
77+
'rgba(0, 255, 0, 1)',
78+
'rgba(0, 0, 255, 1)',
79+
'rgba(255, 0, 255, 1)',
80+
]
81+
const wrapper = mount(
82+
<Chord
83+
{...baseProps}
84+
colors={colors}
85+
labelTextColor={{
86+
from: 'color',
87+
}}
88+
/>
89+
)
90+
91+
sampleData.keys.forEach((key, index) => {
92+
const label = wrapper.find(`text[data-testid='label.${key}']`)
93+
expect(label.exists()).toBeTruthy()
94+
expect(label.prop('style').fill).toEqual(colors[index])
95+
})
96+
})
97+
})
98+
99+
describe('interactivity', () => {
100+
describe('arcs', () => {
101+
it('onMouseEnter', () => {
102+
const onMouseEnter = jest.fn()
103+
const wrapper = mount(<Chord {...baseProps} onArcMouseEnter={onMouseEnter} />)
104+
105+
sampleData.keys.forEach(key => {
106+
wrapper.find(`path[data-testid='arc.${key}']`).simulate('mouseenter')
107+
108+
expect(onMouseEnter).toHaveBeenCalledTimes(1)
109+
const [datum] = onMouseEnter.mock.calls[0]
110+
expect(datum.id).toEqual(key)
111+
112+
onMouseEnter.mockClear()
113+
})
114+
})
115+
116+
it('onMouseMove', () => {
117+
const onMouseMove = jest.fn()
118+
const wrapper = mount(<Chord {...baseProps} onArcMouseMove={onMouseMove} />)
119+
120+
sampleData.keys.forEach(key => {
121+
wrapper.find(`path[data-testid='arc.${key}']`).simulate('mousemove')
122+
123+
expect(onMouseMove).toHaveBeenCalledTimes(1)
124+
const [datum] = onMouseMove.mock.calls[0]
125+
expect(datum.id).toEqual(key)
126+
127+
onMouseMove.mockClear()
128+
})
129+
})
130+
131+
it('onMouseLeave', () => {
132+
const onMouseLeave = jest.fn()
133+
const wrapper = mount(<Chord {...baseProps} onArcMouseLeave={onMouseLeave} />)
134+
135+
sampleData.keys.forEach(key => {
136+
wrapper.find(`path[data-testid='arc.${key}']`).simulate('mouseleave')
137+
138+
expect(onMouseLeave).toHaveBeenCalledTimes(1)
139+
const [datum] = onMouseLeave.mock.calls[0]
140+
expect(datum.id).toEqual(key)
141+
142+
onMouseLeave.mockClear()
143+
})
144+
})
145+
146+
it('onClick', () => {
147+
const onClick = jest.fn()
148+
const wrapper = mount(<Chord {...baseProps} onArcClick={onClick} />)
149+
150+
sampleData.keys.forEach(key => {
151+
wrapper.find(`path[data-testid='arc.${key}']`).simulate('click')
152+
153+
expect(onClick).toHaveBeenCalledTimes(1)
154+
const [datum] = onClick.mock.calls[0]
155+
expect(datum.id).toEqual(key)
156+
157+
onClick.mockClear()
158+
})
159+
})
160+
})
161+
162+
describe('ribbons', () => {
163+
it('onMouseEnter', () => {
164+
const onMouseEnter = jest.fn()
165+
const wrapper = mount(<Chord {...baseProps} onRibbonMouseEnter={onMouseEnter} />)
166+
167+
wrapper.find(`path[data-testid^='ribbon.']`).forEach(ribbon => {
168+
ribbon.simulate('mouseenter')
169+
170+
expect(onMouseEnter).toHaveBeenCalledTimes(1)
171+
const [datum] = onMouseEnter.mock.calls[0]
172+
expect(datum.id).toEqual(ribbon.prop('data-testid').slice(7))
173+
174+
onMouseEnter.mockClear()
175+
})
176+
})
177+
178+
it('onMouseMove', () => {
179+
const onMouseMove = jest.fn()
180+
const wrapper = mount(<Chord {...baseProps} onRibbonMouseMove={onMouseMove} />)
181+
182+
wrapper.find(`path[data-testid^='ribbon.']`).forEach(ribbon => {
183+
ribbon.simulate('mousemove')
184+
185+
expect(onMouseMove).toHaveBeenCalledTimes(1)
186+
const [datum] = onMouseMove.mock.calls[0]
187+
expect(datum.id).toEqual(ribbon.prop('data-testid').slice(7))
188+
189+
onMouseMove.mockClear()
190+
})
191+
})
192+
193+
it('onMouseLeave', () => {
194+
const onMouseLeave = jest.fn()
195+
const wrapper = mount(<Chord {...baseProps} onRibbonMouseLeave={onMouseLeave} />)
196+
197+
wrapper.find(`path[data-testid^='ribbon.']`).forEach(ribbon => {
198+
ribbon.simulate('mouseleave')
199+
200+
expect(onMouseLeave).toHaveBeenCalledTimes(1)
201+
const [datum] = onMouseLeave.mock.calls[0]
202+
expect(datum.id).toEqual(ribbon.prop('data-testid').slice(7))
203+
204+
onMouseLeave.mockClear()
205+
})
206+
})
207+
208+
it('onClick', () => {
209+
const onClick = jest.fn()
210+
const wrapper = mount(<Chord {...baseProps} onRibbonClick={onClick} />)
211+
212+
wrapper.find(`path[data-testid^='ribbon.']`).forEach(ribbon => {
213+
ribbon.simulate('click')
214+
215+
expect(onClick).toHaveBeenCalledTimes(1)
216+
const [datum] = onClick.mock.calls[0]
217+
expect(datum.id).toEqual(ribbon.prop('data-testid').slice(7))
218+
219+
onClick.mockClear()
220+
})
221+
})
222+
})
223+
})

0 commit comments

Comments
 (0)
Please sign in to comment.