arc-spec.ts 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. import { d3, initChart } from './c3-helper'
  2. describe('c3 chart arc', function() {
  3. 'use strict'
  4. var chart, args
  5. beforeEach(function(done) {
  6. chart = initChart(chart, args, done)
  7. })
  8. describe('unloads correctly', function() {
  9. beforeAll(function() {
  10. args = {
  11. data: {
  12. columns: [
  13. ['data1', 30],
  14. ['data2', 150],
  15. ['data3', 120]
  16. ],
  17. type: 'pie'
  18. },
  19. transition: {
  20. duration: 500
  21. }
  22. }
  23. })
  24. it('unloads without error', function(done) {
  25. chart.load({
  26. columns: [['data2', 30, 20, 50, 40, 60, 50]]
  27. })
  28. setTimeout(function() {
  29. chart.destroy()
  30. }, 200)
  31. setTimeout(function() {
  32. expect(chart.internal.config).toBeNull()
  33. done()
  34. }, 501)
  35. })
  36. })
  37. describe('show pie chart', function() {
  38. beforeAll(function() {
  39. args = {
  40. data: {
  41. columns: [
  42. ['data1', 30],
  43. ['data2', 150],
  44. ['data3', 120]
  45. ],
  46. type: 'pie'
  47. }
  48. }
  49. })
  50. it('should have correct classes', function() {
  51. var chartArc = d3.select('.c3-chart-arcs'),
  52. arcs = {
  53. data1: chartArc
  54. .select('.c3-chart-arc.c3-target.c3-target-data1')
  55. .select('g.c3-shapes.c3-shapes-data1.c3-arcs.c3-arcs-data1')
  56. .select('path.c3-shape.c3-shape.c3-arc.c3-arc-data1'),
  57. data2: chartArc
  58. .select('.c3-chart-arc.c3-target.c3-target-data2')
  59. .select('g.c3-shapes.c3-shapes-data2.c3-arcs.c3-arcs-data2')
  60. .select('path.c3-shape.c3-shape.c3-arc.c3-arc-data2'),
  61. data3: chartArc
  62. .select('.c3-chart-arc.c3-target.c3-target-data3')
  63. .select('g.c3-shapes.c3-shapes-data3.c3-arcs.c3-arcs-data3')
  64. .select('path.c3-shape.c3-shape.c3-arc.c3-arc-data3')
  65. }
  66. expect(arcs.data1.size()).toBe(1)
  67. expect(arcs.data2.size()).toBe(1)
  68. expect(arcs.data3.size()).toBe(1)
  69. })
  70. it('should have correct d', function() {
  71. expect(d3.select('.c3-arc-data1').attr('d')).toMatch(
  72. /M-124\..+,-171\..+A211\..+,211\..+,0,0,1,-3\..+,-211\..+L0,0Z/
  73. )
  74. expect(d3.select('.c3-arc-data2').attr('d')).toMatch(
  75. /M1\..+,-211\..+211\..+,211\..+,0,0,1,1\..+,211\..+L0,0Z/
  76. )
  77. expect(d3.select('.c3-arc-data3').attr('d')).toMatch(
  78. /M1\..+,211\..+211\..+,211\..+,0,0,1,-124\..+,-171\..+L0,0Z/
  79. )
  80. })
  81. describe('with data id that can be converted to a color', function() {
  82. beforeAll(function() {
  83. args.data.columns = [
  84. ['black', 30],
  85. ['data2', 150],
  86. ['data3', 120]
  87. ]
  88. })
  89. it('should have correct d even if data id can be converted to a color', function(done) {
  90. setTimeout(function() {
  91. expect(d3.select('.c3-arc-black').attr('d')).toMatch(
  92. /M-124\..+,-171\..+A211\..+,211\..+,0,0,1,-3\..+,-211\..+L0,0Z/
  93. )
  94. done()
  95. }, 500)
  96. })
  97. describe('with empty pie chart', function() {
  98. beforeAll(function() {
  99. args = {
  100. data: {
  101. columns: [
  102. ['data1', null],
  103. ['data2', null],
  104. ['data3', null]
  105. ],
  106. type: 'pie'
  107. }
  108. }
  109. })
  110. it('should have correct d attribute', function() {
  111. var chartArc = d3.select('.c3-chart-arcs'),
  112. arcs = {
  113. data1: chartArc
  114. .select('.c3-chart-arc.c3-target.c3-target-data1')
  115. .select('g.c3-shapes.c3-shapes-data1.c3-arcs.c3-arcs-data1')
  116. .select('path.c3-shape.c3-shape.c3-arc.c3-arc-data1'),
  117. data2: chartArc
  118. .select('.c3-chart-arc.c3-target.c3-target-data2')
  119. .select('g.c3-shapes.c3-shapes-data2.c3-arcs.c3-arcs-data2')
  120. .select('path.c3-shape.c3-shape.c3-arc.c3-arc-data2'),
  121. data3: chartArc
  122. .select('.c3-chart-arc.c3-target.c3-target-data3')
  123. .select('g.c3-shapes.c3-shapes-data3.c3-arcs.c3-arcs-data3')
  124. .select('path.c3-shape.c3-shape.c3-arc.c3-arc-data3')
  125. }
  126. expect(arcs.data1.attr('d').indexOf('NaN')).toBe(-1)
  127. expect(arcs.data2.attr('d').indexOf('NaN')).toBe(-1)
  128. expect(arcs.data3.attr('d').indexOf('NaN')).toBe(-1)
  129. })
  130. })
  131. })
  132. })
  133. describe('sort pie chart', function() {
  134. var createPie = function(order) {
  135. return {
  136. data: {
  137. order: order,
  138. columns: [
  139. ['data1', 30],
  140. ['data2', 150],
  141. ['data3', 120]
  142. ],
  143. type: 'pie'
  144. }
  145. }
  146. }
  147. var collectArcs = function() {
  148. return d3
  149. .selectAll('.c3-arc')
  150. .data()
  151. .sort(function(a: any, b: any) {
  152. return a.startAngle - b.startAngle
  153. })
  154. .map(function(item: any) {
  155. return item.data.id
  156. })
  157. }
  158. it('should update data_order to desc', function() {
  159. args = createPie('desc')
  160. expect(true).toBeTruthy()
  161. })
  162. it('it should have descending ordering', function() {
  163. expect(collectArcs()).toEqual(['data2', 'data3', 'data1'])
  164. })
  165. it('should update data_order to asc', function() {
  166. args = createPie('asc')
  167. expect(true).toBeTruthy()
  168. })
  169. it('it should have ascending ordering', function() {
  170. expect(collectArcs()).toEqual(['data1', 'data3', 'data2'])
  171. })
  172. it('should update data_order to NULL', function() {
  173. args = createPie(null)
  174. expect(true).toBeTruthy()
  175. })
  176. it('it should have no ordering', function() {
  177. expect(collectArcs()).toEqual(['data1', 'data2', 'data3'])
  178. })
  179. it('should update data_order to Array', function() {
  180. args = createPie(['data3', 'data2', 'data1'])
  181. expect(true).toBeTruthy()
  182. })
  183. it('it should have array specified ordering', function() {
  184. expect(collectArcs()).toEqual(['data3', 'data2', 'data1'])
  185. })
  186. it('should update data_order to Function', function() {
  187. var names = ['data2', 'data1', 'data3']
  188. args = createPie(function(a, b) {
  189. return names.indexOf(a.id) - names.indexOf(b.id)
  190. })
  191. expect(true).toBeTruthy()
  192. })
  193. it('it should have array specified ordering', function() {
  194. expect(collectArcs()).toEqual(['data2', 'data1', 'data3'])
  195. })
  196. })
  197. describe('config donut chart', function() {
  198. beforeAll(function() {
  199. args = {
  200. data: {
  201. columns: [
  202. ['data1', 30],
  203. ['data2', 150],
  204. ['data3', 120]
  205. ],
  206. type: 'donut'
  207. },
  208. donut: {
  209. padAngle: 0.05
  210. }
  211. }
  212. })
  213. it('can configure padAngle', function() {
  214. expect(chart.internal.pie.padAngle()()).toBe(0.05)
  215. })
  216. })
  217. describe('config pie chart', function() {
  218. beforeAll(function() {
  219. args = {
  220. data: {
  221. columns: [
  222. ['data1', 30],
  223. ['data2', 150],
  224. ['data3', 120]
  225. ],
  226. type: 'pie'
  227. },
  228. pie: {
  229. padAngle: 0.05
  230. }
  231. }
  232. })
  233. it('can configure padAngle', function() {
  234. expect(chart.internal.pie.padAngle()()).toBe(0.05)
  235. })
  236. })
  237. describe('show gauge', function() {
  238. describe('with a 180 degree gauge', function() {
  239. beforeAll(function() {
  240. args = {
  241. gauge: {
  242. width: 10,
  243. max: 10,
  244. expand: true
  245. },
  246. data: {
  247. columns: [['data', 8]],
  248. type: 'gauge'
  249. }
  250. }
  251. })
  252. it('should have correct d for Pi radian gauge', function() {
  253. var chartArc = d3.select('.c3-chart-arcs'),
  254. data = chartArc
  255. .select('.c3-chart-arc.c3-target.c3-target-data')
  256. .select('g.c3-shapes.c3-shapes-data.c3-arcs.c3-arcs-data')
  257. .select('path.c3-shape.c3-shape.c3-arc.c3-arc-data')
  258. expect(data.attr('d')).toMatch(
  259. /-258.4,-3\..+A258.4,258.4,0,0,1,209\..+,-151\..+L200\..+,-146\..+A248.39999999999998,248.39999999999998,0,0,0,-248.39999999999998,-3\..+Z/
  260. )
  261. })
  262. })
  263. describe('with a 2 Pi radian gauge that starts at Pi/2', function() {
  264. beforeAll(function() {
  265. args = {
  266. gauge: {
  267. width: 10,
  268. max: 10,
  269. expand: true,
  270. fullCircle: true,
  271. startingAngle: Math.PI / 2
  272. },
  273. data: {
  274. columns: [['data', 8]],
  275. type: 'gauge'
  276. }
  277. }
  278. })
  279. it('should have correct d for 2 Pi radian gauge starting at Pi/2', function() {
  280. var chartArc = d3.select('.c3-chart-arcs'),
  281. data = chartArc
  282. .select('.c3-chart-arc.c3-target.c3-target-data')
  283. .select('g.c3-shapes.c3-shapes-data.c3-arcs.c3-arcs-data')
  284. .select('path.c3-shape.c3-shape.c3-arc.c3-arc-data')
  285. expect(data.attr('d')).toMatch(/^M180/)
  286. })
  287. describe('with labels use custom text', function() {
  288. beforeAll(function() {
  289. args = {
  290. gauge: {
  291. width: 10,
  292. max: 100,
  293. expand: true,
  294. label: {
  295. extents: function(value, isMax) {
  296. if (isMax) {
  297. return 'Max: ' + value + '%'
  298. }
  299. return 'Min: ' + value + '%'
  300. }
  301. }
  302. },
  303. data: {
  304. columns: [['data', 8]],
  305. type: 'gauge'
  306. }
  307. }
  308. })
  309. it('should show custom min/max guage labels', function() {
  310. var chartArc = d3.select('.c3-chart-arcs'),
  311. min = chartArc.select('.c3-chart-arcs-gauge-min'),
  312. max = chartArc.select('.c3-chart-arcs-gauge-max')
  313. expect(min.text()).toMatch('Min: 0%')
  314. expect(max.text()).toMatch('Max: 100%')
  315. })
  316. })
  317. })
  318. describe('with more than one data_column ', function() {
  319. beforeAll(function() {
  320. args = {
  321. data: {
  322. columns: [
  323. ['padded1', 100],
  324. ['padded2', 90],
  325. ['padded3', 50],
  326. ['padded4', 20]
  327. ],
  328. type: 'gauge'
  329. },
  330. color: {
  331. pattern: ['#FF0000', '#F97600', '#F6C600', '#60B044'],
  332. threshold: {
  333. values: [30, 80, 95]
  334. }
  335. }
  336. }
  337. })
  338. var arcColor = [
  339. 'rgb(96, 176, 68)',
  340. 'rgb(246, 198, 0)',
  341. 'rgb(249, 118, 0)',
  342. 'rgb(255, 0, 0)'
  343. ]
  344. describe('should contain arcs ', function() {
  345. it('each data_column should have one arc', function() {
  346. chart.internal.main
  347. .selectAll('.c3-chart-arc .c3-arc')
  348. .each(function(d, i) {
  349. expect(
  350. d3.select(this).classed('c3-arc-' + args.data.columns[i][0])
  351. ).toBeTruthy()
  352. })
  353. })
  354. it('each arc should have the color from color_pattern if color_treshold is given ', function() {
  355. chart.internal.main
  356. .selectAll('.c3-chart-arc .c3-arc')
  357. .each(function(d, i) {
  358. expect(d3.select(this).style('fill')).toBe(arcColor[i])
  359. })
  360. })
  361. })
  362. describe('should contain backgrounds ', function() {
  363. it('each data_column should have one background', function() {
  364. chart.internal.main
  365. .selectAll('.c3-chart-arcs path.c3-chart-arcs-background')
  366. .each(function(d, i) {
  367. expect(
  368. d3.select(this).classed('c3-chart-arcs-background-' + i)
  369. ).toBeTruthy()
  370. })
  371. })
  372. it('each background should have tbe same color', function() {
  373. chart.internal.main
  374. .selectAll('.c3-chart-arcs path.c3-chart-arcs-background')
  375. .each(function() {
  376. expect(d3.select(this).style('fill')).toBe('rgb(224, 224, 224)')
  377. })
  378. })
  379. })
  380. describe('should contain labels', function() {
  381. it('each data_column should have a label', function() {
  382. chart.internal.main
  383. .selectAll('.c3-chart-arc .c3-gauge-value')
  384. .each(function(d, i) {
  385. expect(d3.select(this).text()).toBe(
  386. chart.internal.defaultArcValueFormat(
  387. null,
  388. args.data.columns[i][1] / 100
  389. )
  390. )
  391. })
  392. })
  393. it('each label should have the same color', function() {
  394. chart.internal.main
  395. .selectAll('.c3-chart-arc .c3-gauge-value')
  396. .each(function() {
  397. expect(d3.select(this).style('fill')).toBe('rgb(0, 0, 0)')
  398. })
  399. })
  400. it('if only one data_column is visible the label should have "" for transform', function(done) {
  401. var textBeforeHide = chart.internal.main.select(
  402. '.c3-chart-arc.c3-target.c3-target-padded4 text'
  403. )
  404. expect(textBeforeHide.attr('transform')).not.toBe('')
  405. chart.hide(['padded1', 'padded2', 'padded3'])
  406. setTimeout(function() {
  407. var textAfterHide = chart.internal.main.select(
  408. '.c3-chart-arc.c3-target.c3-target-padded4 text'
  409. )
  410. expect(textAfterHide.attr('transform')).toBe('')
  411. done()
  412. }, 1000)
  413. })
  414. })
  415. describe('should contain labellines', function() {
  416. it('each data_column should have a labelline', function() {
  417. chart.internal.main
  418. .selectAll('.c3-chart-arc .c3-arc-label-line')
  419. .each(function(d, i) {
  420. expect(
  421. d3.select(this).classed('c3-target-' + args.data.columns[i][0])
  422. ).toBeTruthy()
  423. })
  424. })
  425. it('each labelline should have the color from color_pattern if color_treshold is given', function() {
  426. chart.internal.main
  427. .selectAll('.c3-chart-arc .c3-arc-label-line')
  428. .each(function(d, i) {
  429. expect(d3.select(this).style('fill')).toBe(arcColor[i])
  430. })
  431. })
  432. })
  433. })
  434. describe('with more than one data value ', function() {
  435. beforeAll(function() {
  436. args = {
  437. data: {
  438. columns: [
  439. ['padded1', 40, 60],
  440. ['padded2', 100, -10],
  441. ['padded3', 0, 50],
  442. ['padded4', 20, 0]
  443. ],
  444. type: 'gauge'
  445. },
  446. color: {
  447. pattern: ['#FF0000', '#F97600', '#F6C600', '#60B044'],
  448. threshold: {
  449. values: [30, 80, 95]
  450. }
  451. }
  452. }
  453. })
  454. var arcColor = [
  455. 'rgb(96, 176, 68)',
  456. 'rgb(246, 198, 0)',
  457. 'rgb(249, 118, 0)',
  458. 'rgb(255, 0, 0)'
  459. ]
  460. describe('should contain arcs ', function() {
  461. it('each data_column should have one arc', function() {
  462. chart.internal.main
  463. .selectAll('.c3-chart-arc .c3-arc')
  464. .each(function(d, i) {
  465. expect(
  466. d3.select(this).classed('c3-arc-' + args.data.columns[i][0])
  467. ).toBeTruthy()
  468. })
  469. })
  470. it('each arc should have the color from color_pattern if color_treshold is given ', function() {
  471. chart.internal.main
  472. .selectAll('.c3-chart-arc .c3-arc')
  473. .each(function(d, i) {
  474. expect(d3.select(this).style('fill')).toBe(arcColor[i])
  475. })
  476. })
  477. })
  478. })
  479. })
  480. })