axis-spec.ts 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210
  1. import { d3, c3, initChart } from './c3-helper'
  2. describe('c3 chart axis', function() {
  3. 'use strict'
  4. var chart
  5. var args: any = {
  6. data: {
  7. columns: [
  8. ['data1', 30, 200, 100, 400, 150, 250],
  9. ['data2', 50, 20, 10, 40, 15, 25],
  10. ['data3', 150, 120, 110, 140, 115, 125]
  11. ]
  12. },
  13. axis: {
  14. y: {
  15. tick: {
  16. values: null,
  17. count: undefined
  18. }
  19. },
  20. y2: {
  21. tick: {
  22. values: null,
  23. count: undefined
  24. }
  25. }
  26. }
  27. }
  28. beforeEach(function(done) {
  29. chart = initChart(chart, args, done)
  30. })
  31. describe('axis.y.tick.count', function() {
  32. describe('with only 1 tick on y axis', function() {
  33. beforeAll(function() {
  34. args.axis.y.tick.count = 1
  35. })
  36. it('should have only 1 tick on y axis', function() {
  37. var ticksSize = d3
  38. .select('.c3-axis-y')
  39. .selectAll('g.tick')
  40. .size()
  41. expect(ticksSize).toBe(1)
  42. })
  43. })
  44. describe('with 2 ticks on y axis', function() {
  45. beforeAll(function() {
  46. args.axis.y.tick.count = 2
  47. })
  48. it('should have 2 ticks on y axis', function() {
  49. var ticksSize = d3
  50. .select('.c3-axis-y')
  51. .selectAll('g.tick')
  52. .size()
  53. expect(ticksSize).toBe(2)
  54. })
  55. })
  56. describe('with 3 ticks on y axis', function() {
  57. beforeAll(function() {
  58. args.axis.y.tick.count = 3
  59. })
  60. it('should have 3 ticks on y axis', function() {
  61. var ticksSize = d3
  62. .select('.c3-axis-y')
  63. .selectAll('g.tick')
  64. .size()
  65. expect(ticksSize).toBe(3)
  66. })
  67. })
  68. })
  69. describe('axis.y.tick.values', function() {
  70. var values = [100, 500]
  71. describe('with only 2 ticks on y axis', function() {
  72. beforeAll(function() {
  73. args.axis.y.tick.values = values
  74. })
  75. it('should have only 2 tick on y axis', function() {
  76. var ticksSize = d3
  77. .select('.c3-axis-y')
  78. .selectAll('g.tick')
  79. .size()
  80. expect(ticksSize).toBe(2)
  81. })
  82. it('should have specified tick texts', function() {
  83. d3.select('.c3-axis-y')
  84. .selectAll('g.tick')
  85. .each(function(d, i) {
  86. var text = d3
  87. .select(this)
  88. .select('text')
  89. .text()
  90. expect(+text).toBe(values[i])
  91. })
  92. })
  93. })
  94. })
  95. describe('axis x timeseries with seconds', function() {
  96. beforeAll(function() {
  97. args = {
  98. data: {
  99. type: 'line',
  100. columns: [
  101. ['epoch', 1401879600000, 1401883200000, 1401886800000],
  102. ['y', 1955, 2419, 2262]
  103. ],
  104. xs: {
  105. y: 'epoch'
  106. }
  107. },
  108. axis: {
  109. x: {
  110. type: 'timeseries',
  111. min: new Date(1401879600000),
  112. max: new Date(1401969600000),
  113. localtime: false
  114. }
  115. }
  116. }
  117. })
  118. it('should have 3 ticks on x axis', function() {
  119. var ticksSize = d3
  120. .select('.c3-axis-x')
  121. .selectAll('g.tick')
  122. .size()
  123. expect(ticksSize).toBe(3)
  124. })
  125. it('should have specified 1 hour intervals', function() {
  126. var prevValue
  127. d3.select('.c3-axis-x')
  128. .selectAll('g.tick')
  129. .each(function(d: any, i) {
  130. if (i !== 0) {
  131. var result = d - prevValue
  132. expect(result).toEqual(3600000) // expressed in milliseconds
  133. }
  134. prevValue = d
  135. })
  136. })
  137. describe('changing min x time and columns', function() {
  138. beforeAll(function() {
  139. args.axis.x.min = new Date(1401876000000)
  140. args.axis.x.max = new Date(1401876075000)
  141. args.data.columns = [
  142. [
  143. 'epoch',
  144. 1401876000000,
  145. 1401876015000,
  146. 1401876030000,
  147. 1401876045000,
  148. 1401876060000,
  149. 1401876075000
  150. ],
  151. ['y', 1968, 1800, 1955, 2419, 2262, 1940]
  152. ]
  153. })
  154. it('should have 6 ticks on x axis', function() {
  155. var ticksSize = d3
  156. .select('.c3-axis-x')
  157. .selectAll('g.tick')
  158. .size()
  159. expect(ticksSize).toBe(6) // the count starts at initial value and increments by the set interval
  160. })
  161. it('should have specified 15 seconds intervals', function() {
  162. var prevValue
  163. d3.select('.c3-axis-x')
  164. .selectAll('g.tick')
  165. .each(function(d: any, i) {
  166. if (i !== 0) {
  167. var result = d - prevValue
  168. expect(result).toEqual(15000) // expressed in milliseconds
  169. }
  170. prevValue = d
  171. })
  172. })
  173. describe('with axis.x.time.format %Y-%m-%d %H:%M:%S', function() {
  174. beforeAll(function() {
  175. args.axis.x.tick = {
  176. format: '%M:%S' // https://github.com/mbostock/d3/wiki/Time-Formatting#wiki-format
  177. }
  178. })
  179. var textDates = ['00:00', '00:15', '00:30', '00:45', '01:00', '01:15']
  180. it('should format x ticks as dates with time', function() {
  181. var ticks = d3
  182. .select('.c3-axis-x')
  183. .selectAll('g.tick')
  184. .selectAll('tspan')
  185. .each(function(d: any) {
  186. expect(d.splitted).toEqual(textDates[d.index])
  187. })
  188. expect(ticks.size()).toBe(6)
  189. })
  190. })
  191. })
  192. })
  193. describe('axis x timeseries with iso dates', function() {
  194. beforeAll(function() {
  195. args = {
  196. data: {
  197. type: 'line',
  198. columns: [
  199. ['epoch', 1527811200000, 1527897600000, 1527984000000],
  200. ['y', 1955, 2419, 2262]
  201. ],
  202. xs: {
  203. y: 'epoch'
  204. }
  205. },
  206. axis: {
  207. x: {
  208. type: 'timeseries',
  209. min: new Date('2018-06-01'),
  210. max: new Date('2018-06-03'),
  211. localtime: false,
  212. tick: {
  213. format: '%Y-%m-%dT%H:%M:%S' // https://github.com/mbostock/d3/wiki/Time-Formatting#wiki-format
  214. }
  215. }
  216. }
  217. }
  218. })
  219. var textDates = [
  220. '2018-06-01T00:00:00',
  221. '2018-06-02T00:00:00',
  222. '2018-06-03T00:00:00'
  223. ]
  224. it('should format x ticks as dates', function() {
  225. var ticks = d3
  226. .select('.c3-axis-x')
  227. .selectAll('g.tick')
  228. .selectAll('tspan')
  229. .each(function(d: any) {
  230. expect(d.splitted).toEqual(textDates[d.index])
  231. })
  232. expect(ticks.size()).toBe(3)
  233. })
  234. })
  235. describe('axis y timeseries', function() {
  236. beforeAll(function() {
  237. args = {
  238. data: {
  239. columns: [['times', 60000, 120000, 180000, 240000]]
  240. },
  241. axis: {
  242. y: {
  243. type: 'timeseries',
  244. tick: {
  245. time: {}
  246. }
  247. }
  248. }
  249. }
  250. })
  251. it('should have 7 ticks on y axis', function() {
  252. var ticksSize = d3
  253. .select('.c3-axis-y')
  254. .selectAll('g.tick')
  255. .size()
  256. expect(ticksSize).toBe(7) // the count starts at initial value and increments by the set interval
  257. })
  258. it('should have specified 30 second intervals', function() {
  259. var prevValue
  260. d3.select('.c3-axis-y')
  261. .selectAll('g.tick')
  262. .each(function(d: any, i) {
  263. if (i !== 0) {
  264. var result = d - prevValue
  265. expect(result).toEqual(30000) // expressed in milliseconds
  266. }
  267. prevValue = d
  268. })
  269. })
  270. describe('with axis.y.time', function() {
  271. beforeAll(function() {
  272. args.axis.y.tick.time = {
  273. type: d3.timeSecond,
  274. interval: 60
  275. }
  276. })
  277. it('should have 4 ticks on y axis', function() {
  278. var ticksSize = d3
  279. .select('.c3-axis-y')
  280. .selectAll('g.tick')
  281. .size()
  282. expect(ticksSize).toBe(4) // the count starts at initial value and increments by the set interval
  283. })
  284. it('should have specified 60 second intervals', function() {
  285. var prevValue
  286. d3.select('.c3-axis-y')
  287. .selectAll('g.tick')
  288. .each(function(d: any, i) {
  289. if (i !== 0) {
  290. var result = d - prevValue
  291. expect(result).toEqual(60000) // expressed in milliseconds
  292. }
  293. prevValue = d
  294. })
  295. })
  296. })
  297. })
  298. describe('axis.y.type', function() {
  299. describe('type=log', function() {
  300. beforeAll(function() {
  301. args = {
  302. data: {
  303. columns: [
  304. ['linear', 318, 37, 0, 4, 0, 1],
  305. ['log', 318, 37, 0, 4, 0, 1]
  306. ],
  307. type: 'bar',
  308. axes: {
  309. log: 'y',
  310. linear: 'y2'
  311. },
  312. labels: true
  313. },
  314. axis: {
  315. y: {
  316. type: 'log'
  317. },
  318. y2: {
  319. show: true
  320. }
  321. }
  322. }
  323. })
  324. it('should have bars from y bigger than y2', function() {
  325. expect(
  326. (d3.select('.c3-bars-log .c3-bar-5').node() as any).getBBox().height
  327. ).toBeGreaterThan(
  328. (d3.select('.c3-bars-linear .c3-bar-5').node() as any).getBBox()
  329. .height
  330. )
  331. })
  332. it('should not have truncated data label', () => {
  333. const text = d3.select('.c3-texts-log .c3-text-0').node() as any
  334. expect(text).not.toBeUndefined()
  335. const bbox = text.getBBox()
  336. expect(Math.abs(bbox.y) - bbox.height).toBeGreaterThan(0)
  337. })
  338. })
  339. })
  340. describe('axis.x.tick.values', function() {
  341. describe('formatted correctly when negative', function() {
  342. var xValues = [-3.3, -2.2, -1.1, 1.1, 2.2, 3.3]
  343. beforeEach(function() {
  344. args.data = {
  345. x: 'x',
  346. columns: [
  347. ['x'].concat(xValues as any),
  348. ['data1', 30, 200, 100, 400, 150, 250]
  349. ]
  350. }
  351. })
  352. it('should not generate whole number for negative values', function() {
  353. var tickValues = []
  354. d3.select('.c3-axis-x')
  355. .selectAll('g.tick')
  356. .selectAll('tspan')
  357. .each(function(d: any, i) {
  358. expect(tickValues.push(parseFloat(d.splitted)) === xValues[i])
  359. })
  360. })
  361. })
  362. describe('function is provided', function() {
  363. var tickGenerator = function() {
  364. var values = []
  365. for (var i = 0; i <= 300; i += 50) {
  366. values.push(i)
  367. }
  368. return values
  369. }
  370. beforeEach(function() {
  371. args.axis.x = {
  372. tick: {
  373. values: tickGenerator
  374. }
  375. }
  376. chart = c3.generate(args)
  377. ;(window as any).generatedTicks = tickGenerator() // This should be removed from window
  378. })
  379. it('should use function to generate ticks', function() {
  380. d3.select('.c3-axis-x')
  381. .selectAll('g.tick')
  382. .each(function(d, i) {
  383. var tick = d3
  384. .select(this)
  385. .select('text')
  386. .text()
  387. expect(+tick).toBe((window as any).generatedTicks[i])
  388. })
  389. })
  390. })
  391. })
  392. describe('axis.x.tick.width', function() {
  393. describe('indexed x axis and y/y2 axis', function() {
  394. describe('not rotated', function() {
  395. beforeAll(function() {
  396. args = {
  397. data: {
  398. columns: [
  399. ['data1', 30, 200, 100, 400, 150, 250],
  400. ['data2', 50, 20, 10, 40, 15, 25]
  401. ],
  402. axes: {
  403. data2: 'y2'
  404. }
  405. },
  406. axis: {
  407. y2: {
  408. show: true
  409. }
  410. }
  411. }
  412. })
  413. it('should construct indexed x axis properly', function() {
  414. var ticks = chart.internal.main
  415. .select('.c3-axis-x')
  416. .selectAll('g.tick'),
  417. expectedX = '0',
  418. expectedDy = '.71em'
  419. expect(ticks.size()).toBe(6)
  420. ticks.each(function(d, i) {
  421. var tspans = d3.select(this).selectAll('tspan')
  422. expect(tspans.size()).toBe(1)
  423. tspans.each(function() {
  424. var tspan = d3.select(this)
  425. expect(tspan.text()).toBe(i + '')
  426. expect(tspan.attr('x')).toBe(expectedX)
  427. expect(tspan.attr('dy')).toBe(expectedDy)
  428. })
  429. })
  430. })
  431. describe('should set axis.x.tick.format', function() {
  432. beforeAll(function() {
  433. args.axis.x = {
  434. tick: {
  435. format: function() {
  436. return 'very long tick text on x axis'
  437. }
  438. }
  439. }
  440. })
  441. it('should split x axis tick text to multiple lines', function() {
  442. var ticks = chart.internal.main
  443. .select('.c3-axis-x')
  444. .selectAll('g.tick'),
  445. expectedTexts = ['very long tick text', 'on x axis'],
  446. expectedX = '0'
  447. expect(ticks.size()).toBe(6)
  448. ticks.each(function() {
  449. var tspans = d3.select(this).selectAll('tspan')
  450. expect(tspans.size()).toBe(2)
  451. tspans.each(function(d, i) {
  452. var tspan = d3.select(this)
  453. expect(tspan.text()).toBe(expectedTexts[i])
  454. expect(tspan.attr('x')).toBe(expectedX)
  455. if (i === 0) {
  456. expect(tspan.attr('dy')).toBe('.71em')
  457. } else {
  458. expect(tspan.attr('dy')).toBeGreaterThan(8)
  459. }
  460. })
  461. })
  462. })
  463. it('should construct y axis properly', function() {
  464. var ticks = chart.internal.main
  465. .select('.c3-axis-y')
  466. .selectAll('g.tick'),
  467. expectedX = '-9',
  468. expectedDy = '3'
  469. expect(ticks.size()).toBe(9)
  470. ticks.each(function(d) {
  471. var tspans = d3.select(this).selectAll('tspan')
  472. expect(tspans.size()).toBe(1)
  473. tspans.each(function() {
  474. var tspan = d3.select(this)
  475. expect(tspan.text()).toBe(d + '')
  476. expect(tspan.attr('x')).toBe(expectedX)
  477. expect(tspan.attr('dy')).toBe(expectedDy)
  478. })
  479. })
  480. })
  481. it('should construct y2 axis properly', function() {
  482. var ticks = chart.internal.main
  483. .select('.c3-axis-y2')
  484. .selectAll('g.tick'),
  485. expectedX = '9',
  486. expectedDy = '3'
  487. expect(ticks.size()).toBe(9)
  488. ticks.each(function(d) {
  489. var tspans = d3.select(this).selectAll('tspan')
  490. expect(tspans.size()).toBe(1)
  491. tspans.each(function() {
  492. var tspan = d3.select(this)
  493. expect(tspan.text()).toBe(d + '')
  494. expect(tspan.attr('x')).toBe(expectedX)
  495. expect(tspan.attr('dy')).toBe(expectedDy)
  496. })
  497. })
  498. })
  499. })
  500. describe('should set big values in y', function() {
  501. beforeAll(function() {
  502. args.data.columns = [
  503. ['data1', 3000000000000000, 200, 100, 400, 150, 250],
  504. ['data2', 50, 20, 10, 40, 15, 25]
  505. ]
  506. })
  507. it('should not split y axis tick text to multiple lines', function() {
  508. var ticks = chart.internal.main
  509. .select('.c3-axis-y2')
  510. .selectAll('g.tick')
  511. ticks.each(function() {
  512. var tspans = d3.select(this).selectAll('tspan')
  513. expect(tspans.size()).toBe(1)
  514. })
  515. })
  516. })
  517. })
  518. describe('rotated', function() {
  519. beforeAll(function() {
  520. args.axis.rotated = true
  521. })
  522. it('should split x axis tick text to multiple lines', function() {
  523. var ticks = chart.internal.main
  524. .select('.c3-axis-x')
  525. .selectAll('g.tick'),
  526. expectedTexts = ['very long tick text on', 'x axis'],
  527. expectedX = '-9'
  528. expect(ticks.size()).toBe(6)
  529. ticks.each(function() {
  530. var tspans = d3.select(this).selectAll('tspan')
  531. expect(tspans.size()).toBe(2)
  532. tspans.each(function(d, i) {
  533. var tspan = d3.select(this)
  534. expect(tspan.text()).toBe(expectedTexts[i])
  535. expect(tspan.attr('x')).toBe(expectedX)
  536. if (i === 0) {
  537. expect(tspan.attr('dy')).toBeLessThan(0)
  538. } else {
  539. expect(tspan.attr('dy')).toBeGreaterThan(9)
  540. }
  541. })
  542. })
  543. })
  544. it('should not split y axis tick text to multiple lines', function() {
  545. var ticks = chart.internal.main
  546. .select('.c3-axis-y')
  547. .selectAll('g.tick'),
  548. expectedTexts = [
  549. '0',
  550. '500000000000000',
  551. '1000000000000000',
  552. '1500000000000000',
  553. '2000000000000000',
  554. '2500000000000000',
  555. '3000000000000000'
  556. ],
  557. expectedX = '0',
  558. expectedDy = '.71em'
  559. expect(ticks.size()).toBe(7)
  560. ticks.each(function(d, i) {
  561. var tspans = d3.select(this).selectAll('tspan')
  562. expect(tspans.size()).toBe(1)
  563. tspans.each(function() {
  564. var tspan = d3.select(this)
  565. expect(tspan.text()).toBe(expectedTexts[i])
  566. expect(tspan.attr('x')).toBe(expectedX)
  567. expect(tspan.attr('dy')).toBe(expectedDy)
  568. })
  569. })
  570. })
  571. })
  572. })
  573. describe('category axis', function() {
  574. describe('not rotated', function() {
  575. beforeAll(function() {
  576. args = {
  577. data: {
  578. x: 'x',
  579. columns: [
  580. [
  581. 'x',
  582. 'this is a very long tick text on category axis',
  583. 'cat1',
  584. 'cat2',
  585. 'cat3',
  586. 'cat4',
  587. 'cat5'
  588. ],
  589. ['data1', 30, 200, 100, 400, 150, 250],
  590. ['data2', 50, 20, 10, 40, 15, 25]
  591. ]
  592. },
  593. axis: {
  594. x: {
  595. type: 'category'
  596. }
  597. }
  598. }
  599. })
  600. it('should locate ticks properly', function() {
  601. var ticks = chart.internal.main
  602. .select('.c3-axis-x')
  603. .selectAll('g.tick')
  604. ticks.each(function(d, i) {
  605. var tspans = d3.select(this).selectAll('tspan'),
  606. expectedX = '0',
  607. expectedDy = '.71em'
  608. if (i > 0) {
  609. // i === 0 should be checked in next test
  610. expect(tspans.size()).toBe(1)
  611. tspans.each(function() {
  612. var tspan = d3.select(this)
  613. expect(tspan.attr('x')).toBe(expectedX)
  614. expect(tspan.attr('dy')).toBe(expectedDy)
  615. })
  616. }
  617. })
  618. })
  619. xit('should split tick text properly', function() {
  620. var tick = chart.internal.main.select('.c3-axis-x').select('g.tick'),
  621. tspans = tick.selectAll('tspan'),
  622. expectedTickTexts = [
  623. 'this is a very long',
  624. 'tick text on category',
  625. 'axis'
  626. ],
  627. expectedX = '0'
  628. expect(tspans.size()).toBe(3)
  629. tspans.each(function(d, i) {
  630. var tspan = d3.select(this)
  631. expect(tspan.text()).toBe(expectedTickTexts[i])
  632. expect(tspan.attr('x')).toBe(expectedX)
  633. // unable to define pricise number because it differs depends on environment..
  634. if (i === 0) {
  635. expect(tspan.attr('dy')).toBe('.71em')
  636. } else {
  637. expect(tspan.attr('dy')).toBeGreaterThan(8)
  638. }
  639. })
  640. })
  641. })
  642. describe('rotated', function() {
  643. beforeAll(function() {
  644. args.axis.rotated = true
  645. })
  646. it('should locate ticks on rotated axis properly', function() {
  647. var ticks = chart.internal.main
  648. .select('.c3-axis-x')
  649. .selectAll('g.tick')
  650. ticks.each(function(d, i) {
  651. var tspans = d3.select(this).selectAll('tspan'),
  652. expectedX = '-9',
  653. expectedDy = '3'
  654. if (i > 0) {
  655. // i === 0 should be checked in next test
  656. expect(tspans.size()).toBe(1)
  657. tspans.each(function() {
  658. var tspan = d3.select(this)
  659. expect(tspan.attr('x')).toBe(expectedX)
  660. expect(tspan.attr('dy')).toBe(expectedDy)
  661. })
  662. }
  663. })
  664. })
  665. it('should split tick text on rotated axis properly', function() {
  666. var tick = chart.internal.main.select('.c3-axis-x').select('g.tick'),
  667. tspans = tick.selectAll('tspan'),
  668. expectedTickTexts = [
  669. 'this is a very long',
  670. 'tick text on category',
  671. 'axis'
  672. ],
  673. expectedX = '-9'
  674. expect(tspans.size()).toBe(3)
  675. tspans.each(function(d, i) {
  676. var tspan = d3.select(this)
  677. expect(tspan.text()).toBe(expectedTickTexts[i])
  678. expect(tspan.attr('x')).toBe(expectedX)
  679. // unable to define pricise number because it differs depends on environment..
  680. if (i === 0) {
  681. expect(tspan.attr('dy')).toBeLessThan(0)
  682. } else {
  683. expect(tspan.attr('dy')).toBeGreaterThan(8)
  684. }
  685. })
  686. })
  687. })
  688. describe('option used', function() {
  689. describe('as null', function() {
  690. beforeAll(function() {
  691. //'without split ticks',
  692. args.axis.x.tick = {
  693. multiline: false
  694. }
  695. })
  696. it('should split x tick', function() {
  697. var tick = chart.internal.main
  698. .select('.c3-axis-x')
  699. .select('g.tick'),
  700. tspans = tick.selectAll('tspan')
  701. expect(tspans.size()).toBe(1)
  702. })
  703. })
  704. describe('as value', function() {
  705. beforeAll(function() {
  706. // 'without split ticks',
  707. args.axis.x.tick = {
  708. width: 150
  709. }
  710. })
  711. it('should split x tick to 2 lines properly', function() {
  712. var tick = chart.internal.main
  713. .select('.c3-axis-x')
  714. .select('g.tick'),
  715. tspans = tick.selectAll('tspan'),
  716. expectedTickTexts = [
  717. 'this is a very long tick text on',
  718. 'category axis'
  719. ],
  720. expectedX = '-9'
  721. expect(tspans.size()).toBe(2)
  722. tspans.each(function(d, i) {
  723. var tspan = d3.select(this)
  724. expect(tspan.text()).toBe(expectedTickTexts[i])
  725. expect(tspan.attr('x')).toBe(expectedX)
  726. // unable to define pricise number because it differs depends on environment..
  727. if (i === 0) {
  728. expect(tspan.attr('dy')).toBeLessThan(0)
  729. } else {
  730. expect(tspan.attr('dy')).toBeGreaterThan(8)
  731. }
  732. })
  733. })
  734. })
  735. describe('with multilineMax', function() {
  736. beforeAll(function() {
  737. args.axis.x.tick = {
  738. multiline: true,
  739. multilineMax: 2
  740. }
  741. })
  742. it('should ellipsify x tick properly', function() {
  743. var tick = chart.internal.main.select('.c3-axis-x').select('g.tick')
  744. var tspans = tick.selectAll('tspan')
  745. var expectedTickText = [
  746. 'this is a very long',
  747. 'tick text on categ...'
  748. ]
  749. expect(tspans.size()).toBe(2)
  750. tspans.each(function(d, i) {
  751. var tspan = d3.select(this)
  752. expect(tspan.text()).toBe(expectedTickText[i])
  753. })
  754. })
  755. })
  756. })
  757. })
  758. describe('with axis.x.tick.format', function() {
  759. beforeAll(function() {
  760. // 'with axis.x.tick.format',
  761. args.axis.x.tick.format = function() {
  762. return ['this is a very long tick text', 'on category axis']
  763. }
  764. })
  765. it('should have multiline tick text', function() {
  766. var tick = chart.internal.main.select('.c3-axis-x').select('g.tick'),
  767. tspans = tick.selectAll('tspan'),
  768. expectedTickTexts = [
  769. 'this is a very long tick text',
  770. 'on category axis'
  771. ]
  772. expect(tspans.size()).toBe(2)
  773. tspans.each(function(d, i) {
  774. var tspan = d3.select(this)
  775. expect(tspan.text()).toBe(expectedTickTexts[i])
  776. })
  777. })
  778. })
  779. })
  780. describe('axis.x.tick.rotate', function() {
  781. describe('not rotated', function() {
  782. beforeAll(function() {
  783. args = {
  784. data: {
  785. x: 'x',
  786. columns: [
  787. [
  788. 'x',
  789. 'category 1',
  790. 'category 2',
  791. 'category 3',
  792. 'category 4',
  793. 'category 5',
  794. 'category 6'
  795. ],
  796. ['data1', 30, 200, 100, 400, 150, 250],
  797. ['data2', 50, 20, 10, 40, 15, 25]
  798. ]
  799. },
  800. axis: {
  801. x: {
  802. type: 'category',
  803. tick: {
  804. rotate: 60
  805. }
  806. }
  807. }
  808. }
  809. })
  810. it('should rotate tick texts', function() {
  811. chart.internal.main.selectAll('.c3-axis-x g.tick').each(function() {
  812. var tick = d3.select(this),
  813. text = tick.select('text'),
  814. tspan = text.select('tspan')
  815. expect(text.attr('transform')).toBe('rotate(60)')
  816. expect(text.attr('y')).toBe('1.5')
  817. expect(tspan.attr('dx')).toBe('6.928203230275509')
  818. })
  819. })
  820. it('should have automatically calculated x axis height', function() {
  821. var box = chart.internal.main
  822. .select('.c3-axis-x')
  823. .node()
  824. .getBoundingClientRect(),
  825. height = chart.internal.getHorizontalAxisHeight('x')
  826. expect(box.height).toBeGreaterThan(50)
  827. expect(height).toBeCloseTo(76, -1.3) // @TODO make this test better
  828. })
  829. })
  830. })
  831. describe('axis.y.tick.rotate', function() {
  832. describe('not rotated', function() {
  833. beforeAll(function() {
  834. args = {
  835. data: {
  836. columns: [
  837. ['data1', 30, 200, 100, 400, 150, 250, 100, 600],
  838. ['data2', 50, 20, 10, 40, 15, 25]
  839. ]
  840. },
  841. axis: {
  842. rotated: true,
  843. y: {
  844. tick: {
  845. rotate: 45
  846. }
  847. }
  848. }
  849. }
  850. })
  851. it('should rotate tick texts', function() {
  852. chart.internal.main.selectAll('.c3-axis-y g.tick').each(function() {
  853. var tick = d3.select(this),
  854. text = tick.select('text'),
  855. tspan = text.select('tspan')
  856. expect(text.attr('transform')).toBe('rotate(45)')
  857. expect(text.attr('y')).toBe('4')
  858. expect(tspan.attr('dx')).toBeCloseTo(5.6, 0)
  859. })
  860. })
  861. it('should have automatically calculated y axis width', function() {
  862. var box = chart.internal.main
  863. .select('.c3-axis-y')
  864. .node()
  865. .getBoundingClientRect()
  866. expect(box.width).toBeCloseTo(590, 1)
  867. })
  868. })
  869. })
  870. describe('axis.x.tick.fit', function() {
  871. describe('axis.x.tick.fit = true', function() {
  872. beforeAll(function() {
  873. // 'should set args for indexed data',
  874. args = {
  875. data: {
  876. columns: [
  877. ['data1', 30, 200, 100, 400, 150, 250],
  878. ['data2', 50, 20, 10, 40, 15, 25],
  879. ['data3', 150, 120, 110, 140, 115, 125]
  880. ]
  881. }
  882. }
  883. })
  884. it('should show fitted ticks on indexed data', function() {
  885. var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick')
  886. expect(ticks.size()).toBe(6)
  887. })
  888. describe('should set args for x-based data', function() {
  889. beforeAll(function() {
  890. args = {
  891. data: {
  892. x: 'x',
  893. columns: [
  894. ['x', 10, 20, 100, 110, 200, 1000],
  895. ['data1', 30, 200, 100, 400, 150, 250],
  896. ['data2', 50, 20, 10, 40, 15, 25],
  897. ['data3', 150, 120, 110, 140, 115, 125]
  898. ]
  899. }
  900. }
  901. })
  902. it('should show fitted ticks on indexed data', function() {
  903. var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick')
  904. expect(ticks.size()).toBe(6)
  905. })
  906. it('should show fitted ticks after hide and show', function() {
  907. chart.hide()
  908. chart.show()
  909. var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick')
  910. expect(ticks.size()).toBe(6)
  911. })
  912. })
  913. })
  914. describe('axis.x.tick.fit = false', function() {
  915. describe('should set args for indexed data', function() {
  916. beforeAll(function() {
  917. args = {
  918. data: {
  919. columns: [
  920. ['data1', 30, 200, 100, 400, 150, 250],
  921. ['data2', 50, 20, 10, 40, 15, 25],
  922. ['data3', 150, 120, 110, 140, 115, 125]
  923. ]
  924. },
  925. axis: {
  926. x: {
  927. tick: {
  928. fit: false
  929. }
  930. }
  931. }
  932. }
  933. })
  934. it('should show fitted ticks on indexed data', function() {
  935. var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick')
  936. expect(ticks.size()).toBe(11)
  937. })
  938. })
  939. describe('should set args for x-based data', function() {
  940. beforeAll(function() {
  941. args.data = {
  942. x: 'x',
  943. columns: [
  944. ['x', 10, 20, 100, 110, 200, 1000],
  945. ['data1', 30, 200, 100, 400, 150, 250],
  946. ['data2', 50, 20, 10, 40, 15, 25],
  947. ['data3', 150, 120, 110, 140, 115, 125]
  948. ]
  949. }
  950. })
  951. it('should show fitted ticks on indexed data', function() {
  952. var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick')
  953. expect(ticks.size()).toBe(10)
  954. })
  955. it('should show fitted ticks after hide and show', function() {
  956. chart.hide()
  957. chart.show()
  958. var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick')
  959. expect(ticks.size()).toBe(10)
  960. })
  961. })
  962. })
  963. })
  964. describe('axis.y.inner', function() {
  965. beforeAll(function() {
  966. args = {
  967. data: {
  968. columns: [
  969. ['data1', 30, 200, 100, 400, 150, 250],
  970. ['data2', 50, 20, 10, 40, 15, 25]
  971. ]
  972. },
  973. axis: {
  974. y: {
  975. inner: false
  976. }
  977. }
  978. }
  979. })
  980. it('should not have inner y axis', function() {
  981. var paddingLeft = chart.internal.getCurrentPaddingLeft(),
  982. tickTexts = chart.internal.main.selectAll('.c3-axis-y g.tick text')
  983. expect(paddingLeft).toBeGreaterThan(19)
  984. tickTexts.each(function() {
  985. expect(+d3.select(this).attr('x')).toBeLessThan(0)
  986. })
  987. })
  988. describe('with inner y axis', function() {
  989. beforeAll(function() {
  990. args.axis.y.inner = true
  991. })
  992. it('should have inner y axis', function() {
  993. var paddingLeft = chart.internal.getCurrentPaddingLeft(),
  994. tickTexts = chart.internal.main.selectAll('.c3-axis-y g.tick text')
  995. expect(paddingLeft).toBe(1)
  996. tickTexts.each(function() {
  997. expect(+d3.select(this).attr('x')).toBeGreaterThan(0)
  998. })
  999. })
  1000. })
  1001. })
  1002. describe('axis.y2.inner', function() {
  1003. beforeAll(function() {
  1004. args = {
  1005. data: {
  1006. columns: [
  1007. ['data1', 30, 200, 100, 400, 150, 250],
  1008. ['data2', 50, 20, 10, 40, 15, 25]
  1009. ]
  1010. },
  1011. axis: {
  1012. y2: {
  1013. show: true,
  1014. inner: false
  1015. }
  1016. }
  1017. }
  1018. })
  1019. it('should not have inner y axis', function() {
  1020. var paddingRight = chart.internal.getCurrentPaddingRight(),
  1021. tickTexts = chart.internal.main.selectAll('.c3-axis-2y g.tick text')
  1022. expect(paddingRight).toBeGreaterThan(19)
  1023. tickTexts.each(function() {
  1024. expect(+d3.select(this).attr('x')).toBeGreaterThan(0)
  1025. })
  1026. })
  1027. describe('with inner y axis', function() {
  1028. beforeAll(function() {
  1029. args.axis.y2.inner = true
  1030. })
  1031. it('should have inner y axis', function() {
  1032. var paddingRight = chart.internal.getCurrentPaddingRight(),
  1033. tickTexts = chart.internal.main.selectAll('.c3-axis-2y g.tick text')
  1034. expect(paddingRight).toBe(2)
  1035. tickTexts.each(function() {
  1036. expect(+d3.select(this).attr('x')).toBeLessThan(0)
  1037. })
  1038. })
  1039. })
  1040. })
  1041. describe('axis.x.label', function() {
  1042. beforeAll(function() {
  1043. args = {
  1044. data: {
  1045. columns: [
  1046. ['somewhat long 1', 30, 200, 100, 400, 150, 250],
  1047. ['somewhat long 2', 50, 20, 10, 40, 15, 25]
  1048. ]
  1049. },
  1050. axis: {
  1051. x: {
  1052. show: true,
  1053. label: {
  1054. text: 'Label of X axis'
  1055. }
  1056. }
  1057. }
  1058. }
  1059. })
  1060. it('renders label text properly', () => {
  1061. expect(d3.select('.c3-axis-x-label').text()).toEqual('Label of X axis')
  1062. })
  1063. describe('outer label position', function() {
  1064. beforeAll(function() {
  1065. args.axis.x.label.position = 'outer-center'
  1066. })
  1067. it('renders position properly', () => {
  1068. const label = d3.select('.c3-axis-x-label')
  1069. expect(label.attr('dy')).toEqual('30')
  1070. })
  1071. describe('with rotated tick', function() {
  1072. beforeAll(function() {
  1073. args.axis.x.tick = {
  1074. rotate: 90
  1075. }
  1076. })
  1077. it('renders position properly', () => {
  1078. const label = d3.select('.c3-axis-x-label')
  1079. expect(label.attr('dy')).toBeGreaterThan(30)
  1080. })
  1081. })
  1082. })
  1083. describe('inner label position', function() {
  1084. beforeAll(function() {
  1085. args.axis.x.label.position = 'inner-center'
  1086. })
  1087. it('renders position properly', () => {
  1088. const label = d3.select('.c3-axis-x-label')
  1089. expect(label.attr('dy')).toEqual('-0.5em')
  1090. })
  1091. describe('with rotated tick', function() {
  1092. beforeAll(function() {
  1093. args.axis.x.tick = {
  1094. rotate: 90
  1095. }
  1096. })
  1097. it('renders position properly', () => {
  1098. const label = d3.select('.c3-axis-x-label')
  1099. expect(label.attr('dy')).toEqual('-0.5em')
  1100. })
  1101. })
  1102. })
  1103. })
  1104. })