import { d3, c3, initChart } from './c3-helper' describe('c3 chart axis', function() { 'use strict' var chart var args: any = { data: { columns: [ ['data1', 30, 200, 100, 400, 150, 250], ['data2', 50, 20, 10, 40, 15, 25], ['data3', 150, 120, 110, 140, 115, 125] ] }, axis: { y: { tick: { values: null, count: undefined } }, y2: { tick: { values: null, count: undefined } } } } beforeEach(function(done) { chart = initChart(chart, args, done) }) describe('axis.y.tick.count', function() { describe('with only 1 tick on y axis', function() { beforeAll(function() { args.axis.y.tick.count = 1 }) it('should have only 1 tick on y axis', function() { var ticksSize = d3 .select('.c3-axis-y') .selectAll('g.tick') .size() expect(ticksSize).toBe(1) }) }) describe('with 2 ticks on y axis', function() { beforeAll(function() { args.axis.y.tick.count = 2 }) it('should have 2 ticks on y axis', function() { var ticksSize = d3 .select('.c3-axis-y') .selectAll('g.tick') .size() expect(ticksSize).toBe(2) }) }) describe('with 3 ticks on y axis', function() { beforeAll(function() { args.axis.y.tick.count = 3 }) it('should have 3 ticks on y axis', function() { var ticksSize = d3 .select('.c3-axis-y') .selectAll('g.tick') .size() expect(ticksSize).toBe(3) }) }) }) describe('axis.y.tick.values', function() { var values = [100, 500] describe('with only 2 ticks on y axis', function() { beforeAll(function() { args.axis.y.tick.values = values }) it('should have only 2 tick on y axis', function() { var ticksSize = d3 .select('.c3-axis-y') .selectAll('g.tick') .size() expect(ticksSize).toBe(2) }) it('should have specified tick texts', function() { d3.select('.c3-axis-y') .selectAll('g.tick') .each(function(d, i) { var text = d3 .select(this) .select('text') .text() expect(+text).toBe(values[i]) }) }) }) }) describe('axis x timeseries with seconds', function() { beforeAll(function() { args = { data: { type: 'line', columns: [ ['epoch', 1401879600000, 1401883200000, 1401886800000], ['y', 1955, 2419, 2262] ], xs: { y: 'epoch' } }, axis: { x: { type: 'timeseries', min: new Date(1401879600000), max: new Date(1401969600000), localtime: false } } } }) it('should have 3 ticks on x axis', function() { var ticksSize = d3 .select('.c3-axis-x') .selectAll('g.tick') .size() expect(ticksSize).toBe(3) }) it('should have specified 1 hour intervals', function() { var prevValue d3.select('.c3-axis-x') .selectAll('g.tick') .each(function(d: any, i) { if (i !== 0) { var result = d - prevValue expect(result).toEqual(3600000) // expressed in milliseconds } prevValue = d }) }) describe('changing min x time and columns', function() { beforeAll(function() { args.axis.x.min = new Date(1401876000000) args.axis.x.max = new Date(1401876075000) args.data.columns = [ [ 'epoch', 1401876000000, 1401876015000, 1401876030000, 1401876045000, 1401876060000, 1401876075000 ], ['y', 1968, 1800, 1955, 2419, 2262, 1940] ] }) it('should have 6 ticks on x axis', function() { var ticksSize = d3 .select('.c3-axis-x') .selectAll('g.tick') .size() expect(ticksSize).toBe(6) // the count starts at initial value and increments by the set interval }) it('should have specified 15 seconds intervals', function() { var prevValue d3.select('.c3-axis-x') .selectAll('g.tick') .each(function(d: any, i) { if (i !== 0) { var result = d - prevValue expect(result).toEqual(15000) // expressed in milliseconds } prevValue = d }) }) describe('with axis.x.time.format %Y-%m-%d %H:%M:%S', function() { beforeAll(function() { args.axis.x.tick = { format: '%M:%S' // https://github.com/mbostock/d3/wiki/Time-Formatting#wiki-format } }) var textDates = ['00:00', '00:15', '00:30', '00:45', '01:00', '01:15'] it('should format x ticks as dates with time', function() { var ticks = d3 .select('.c3-axis-x') .selectAll('g.tick') .selectAll('tspan') .each(function(d: any) { expect(d.splitted).toEqual(textDates[d.index]) }) expect(ticks.size()).toBe(6) }) }) }) }) describe('axis x timeseries with iso dates', function() { beforeAll(function() { args = { data: { type: 'line', columns: [ ['epoch', 1527811200000, 1527897600000, 1527984000000], ['y', 1955, 2419, 2262] ], xs: { y: 'epoch' } }, axis: { x: { type: 'timeseries', min: new Date('2018-06-01'), max: new Date('2018-06-03'), localtime: false, tick: { format: '%Y-%m-%dT%H:%M:%S' // https://github.com/mbostock/d3/wiki/Time-Formatting#wiki-format } } } } }) var textDates = [ '2018-06-01T00:00:00', '2018-06-02T00:00:00', '2018-06-03T00:00:00' ] it('should format x ticks as dates', function() { var ticks = d3 .select('.c3-axis-x') .selectAll('g.tick') .selectAll('tspan') .each(function(d: any) { expect(d.splitted).toEqual(textDates[d.index]) }) expect(ticks.size()).toBe(3) }) }) describe('axis y timeseries', function() { beforeAll(function() { args = { data: { columns: [['times', 60000, 120000, 180000, 240000]] }, axis: { y: { type: 'timeseries', tick: { time: {} } } } } }) it('should have 7 ticks on y axis', function() { var ticksSize = d3 .select('.c3-axis-y') .selectAll('g.tick') .size() expect(ticksSize).toBe(7) // the count starts at initial value and increments by the set interval }) it('should have specified 30 second intervals', function() { var prevValue d3.select('.c3-axis-y') .selectAll('g.tick') .each(function(d: any, i) { if (i !== 0) { var result = d - prevValue expect(result).toEqual(30000) // expressed in milliseconds } prevValue = d }) }) describe('with axis.y.time', function() { beforeAll(function() { args.axis.y.tick.time = { type: d3.timeSecond, interval: 60 } }) it('should have 4 ticks on y axis', function() { var ticksSize = d3 .select('.c3-axis-y') .selectAll('g.tick') .size() expect(ticksSize).toBe(4) // the count starts at initial value and increments by the set interval }) it('should have specified 60 second intervals', function() { var prevValue d3.select('.c3-axis-y') .selectAll('g.tick') .each(function(d: any, i) { if (i !== 0) { var result = d - prevValue expect(result).toEqual(60000) // expressed in milliseconds } prevValue = d }) }) }) }) describe('axis.y.type', function() { describe('type=log', function() { beforeAll(function() { args = { data: { columns: [ ['linear', 318, 37, 0, 4, 0, 1], ['log', 318, 37, 0, 4, 0, 1] ], type: 'bar', axes: { log: 'y', linear: 'y2' }, labels: true }, axis: { y: { type: 'log' }, y2: { show: true } } } }) it('should have bars from y bigger than y2', function() { expect( (d3.select('.c3-bars-log .c3-bar-5').node() as any).getBBox().height ).toBeGreaterThan( (d3.select('.c3-bars-linear .c3-bar-5').node() as any).getBBox() .height ) }) it('should not have truncated data label', () => { const text = d3.select('.c3-texts-log .c3-text-0').node() as any expect(text).not.toBeUndefined() const bbox = text.getBBox() expect(Math.abs(bbox.y) - bbox.height).toBeGreaterThan(0) }) }) }) describe('axis.x.tick.values', function() { describe('formatted correctly when negative', function() { var xValues = [-3.3, -2.2, -1.1, 1.1, 2.2, 3.3] beforeEach(function() { args.data = { x: 'x', columns: [ ['x'].concat(xValues as any), ['data1', 30, 200, 100, 400, 150, 250] ] } }) it('should not generate whole number for negative values', function() { var tickValues = [] d3.select('.c3-axis-x') .selectAll('g.tick') .selectAll('tspan') .each(function(d: any, i) { expect(tickValues.push(parseFloat(d.splitted)) === xValues[i]) }) }) }) describe('function is provided', function() { var tickGenerator = function() { var values = [] for (var i = 0; i <= 300; i += 50) { values.push(i) } return values } beforeEach(function() { args.axis.x = { tick: { values: tickGenerator } } chart = c3.generate(args) ;(window as any).generatedTicks = tickGenerator() // This should be removed from window }) it('should use function to generate ticks', function() { d3.select('.c3-axis-x') .selectAll('g.tick') .each(function(d, i) { var tick = d3 .select(this) .select('text') .text() expect(+tick).toBe((window as any).generatedTicks[i]) }) }) }) }) describe('axis.x.tick.width', function() { describe('indexed x axis and y/y2 axis', function() { describe('not rotated', function() { beforeAll(function() { args = { data: { columns: [ ['data1', 30, 200, 100, 400, 150, 250], ['data2', 50, 20, 10, 40, 15, 25] ], axes: { data2: 'y2' } }, axis: { y2: { show: true } } } }) it('should construct indexed x axis properly', function() { var ticks = chart.internal.main .select('.c3-axis-x') .selectAll('g.tick'), expectedX = '0', expectedDy = '.71em' expect(ticks.size()).toBe(6) ticks.each(function(d, i) { var tspans = d3.select(this).selectAll('tspan') expect(tspans.size()).toBe(1) tspans.each(function() { var tspan = d3.select(this) expect(tspan.text()).toBe(i + '') expect(tspan.attr('x')).toBe(expectedX) expect(tspan.attr('dy')).toBe(expectedDy) }) }) }) describe('should set axis.x.tick.format', function() { beforeAll(function() { args.axis.x = { tick: { format: function() { return 'very long tick text on x axis' } } } }) it('should split x axis tick text to multiple lines', function() { var ticks = chart.internal.main .select('.c3-axis-x') .selectAll('g.tick'), expectedTexts = ['very long tick text', 'on x axis'], expectedX = '0' expect(ticks.size()).toBe(6) ticks.each(function() { var tspans = d3.select(this).selectAll('tspan') expect(tspans.size()).toBe(2) tspans.each(function(d, i) { var tspan = d3.select(this) expect(tspan.text()).toBe(expectedTexts[i]) expect(tspan.attr('x')).toBe(expectedX) if (i === 0) { expect(tspan.attr('dy')).toBe('.71em') } else { expect(tspan.attr('dy')).toBeGreaterThan(8) } }) }) }) it('should construct y axis properly', function() { var ticks = chart.internal.main .select('.c3-axis-y') .selectAll('g.tick'), expectedX = '-9', expectedDy = '3' expect(ticks.size()).toBe(9) ticks.each(function(d) { var tspans = d3.select(this).selectAll('tspan') expect(tspans.size()).toBe(1) tspans.each(function() { var tspan = d3.select(this) expect(tspan.text()).toBe(d + '') expect(tspan.attr('x')).toBe(expectedX) expect(tspan.attr('dy')).toBe(expectedDy) }) }) }) it('should construct y2 axis properly', function() { var ticks = chart.internal.main .select('.c3-axis-y2') .selectAll('g.tick'), expectedX = '9', expectedDy = '3' expect(ticks.size()).toBe(9) ticks.each(function(d) { var tspans = d3.select(this).selectAll('tspan') expect(tspans.size()).toBe(1) tspans.each(function() { var tspan = d3.select(this) expect(tspan.text()).toBe(d + '') expect(tspan.attr('x')).toBe(expectedX) expect(tspan.attr('dy')).toBe(expectedDy) }) }) }) }) describe('should set big values in y', function() { beforeAll(function() { args.data.columns = [ ['data1', 3000000000000000, 200, 100, 400, 150, 250], ['data2', 50, 20, 10, 40, 15, 25] ] }) it('should not split y axis tick text to multiple lines', function() { var ticks = chart.internal.main .select('.c3-axis-y2') .selectAll('g.tick') ticks.each(function() { var tspans = d3.select(this).selectAll('tspan') expect(tspans.size()).toBe(1) }) }) }) }) describe('rotated', function() { beforeAll(function() { args.axis.rotated = true }) it('should split x axis tick text to multiple lines', function() { var ticks = chart.internal.main .select('.c3-axis-x') .selectAll('g.tick'), expectedTexts = ['very long tick text on', 'x axis'], expectedX = '-9' expect(ticks.size()).toBe(6) ticks.each(function() { var tspans = d3.select(this).selectAll('tspan') expect(tspans.size()).toBe(2) tspans.each(function(d, i) { var tspan = d3.select(this) expect(tspan.text()).toBe(expectedTexts[i]) expect(tspan.attr('x')).toBe(expectedX) if (i === 0) { expect(tspan.attr('dy')).toBeLessThan(0) } else { expect(tspan.attr('dy')).toBeGreaterThan(9) } }) }) }) it('should not split y axis tick text to multiple lines', function() { var ticks = chart.internal.main .select('.c3-axis-y') .selectAll('g.tick'), expectedTexts = [ '0', '500000000000000', '1000000000000000', '1500000000000000', '2000000000000000', '2500000000000000', '3000000000000000' ], expectedX = '0', expectedDy = '.71em' expect(ticks.size()).toBe(7) ticks.each(function(d, i) { var tspans = d3.select(this).selectAll('tspan') expect(tspans.size()).toBe(1) tspans.each(function() { var tspan = d3.select(this) expect(tspan.text()).toBe(expectedTexts[i]) expect(tspan.attr('x')).toBe(expectedX) expect(tspan.attr('dy')).toBe(expectedDy) }) }) }) }) }) describe('category axis', function() { describe('not rotated', function() { beforeAll(function() { args = { data: { x: 'x', columns: [ [ 'x', 'this is a very long tick text on category axis', 'cat1', 'cat2', 'cat3', 'cat4', 'cat5' ], ['data1', 30, 200, 100, 400, 150, 250], ['data2', 50, 20, 10, 40, 15, 25] ] }, axis: { x: { type: 'category' } } } }) it('should locate ticks properly', function() { var ticks = chart.internal.main .select('.c3-axis-x') .selectAll('g.tick') ticks.each(function(d, i) { var tspans = d3.select(this).selectAll('tspan'), expectedX = '0', expectedDy = '.71em' if (i > 0) { // i === 0 should be checked in next test expect(tspans.size()).toBe(1) tspans.each(function() { var tspan = d3.select(this) expect(tspan.attr('x')).toBe(expectedX) expect(tspan.attr('dy')).toBe(expectedDy) }) } }) }) xit('should split tick text properly', function() { var tick = chart.internal.main.select('.c3-axis-x').select('g.tick'), tspans = tick.selectAll('tspan'), expectedTickTexts = [ 'this is a very long', 'tick text on category', 'axis' ], expectedX = '0' expect(tspans.size()).toBe(3) tspans.each(function(d, i) { var tspan = d3.select(this) expect(tspan.text()).toBe(expectedTickTexts[i]) expect(tspan.attr('x')).toBe(expectedX) // unable to define pricise number because it differs depends on environment.. if (i === 0) { expect(tspan.attr('dy')).toBe('.71em') } else { expect(tspan.attr('dy')).toBeGreaterThan(8) } }) }) }) describe('rotated', function() { beforeAll(function() { args.axis.rotated = true }) it('should locate ticks on rotated axis properly', function() { var ticks = chart.internal.main .select('.c3-axis-x') .selectAll('g.tick') ticks.each(function(d, i) { var tspans = d3.select(this).selectAll('tspan'), expectedX = '-9', expectedDy = '3' if (i > 0) { // i === 0 should be checked in next test expect(tspans.size()).toBe(1) tspans.each(function() { var tspan = d3.select(this) expect(tspan.attr('x')).toBe(expectedX) expect(tspan.attr('dy')).toBe(expectedDy) }) } }) }) it('should split tick text on rotated axis properly', function() { var tick = chart.internal.main.select('.c3-axis-x').select('g.tick'), tspans = tick.selectAll('tspan'), expectedTickTexts = [ 'this is a very long', 'tick text on category', 'axis' ], expectedX = '-9' expect(tspans.size()).toBe(3) tspans.each(function(d, i) { var tspan = d3.select(this) expect(tspan.text()).toBe(expectedTickTexts[i]) expect(tspan.attr('x')).toBe(expectedX) // unable to define pricise number because it differs depends on environment.. if (i === 0) { expect(tspan.attr('dy')).toBeLessThan(0) } else { expect(tspan.attr('dy')).toBeGreaterThan(8) } }) }) }) describe('option used', function() { describe('as null', function() { beforeAll(function() { //'without split ticks', args.axis.x.tick = { multiline: false } }) it('should split x tick', function() { var tick = chart.internal.main .select('.c3-axis-x') .select('g.tick'), tspans = tick.selectAll('tspan') expect(tspans.size()).toBe(1) }) }) describe('as value', function() { beforeAll(function() { // 'without split ticks', args.axis.x.tick = { width: 150 } }) it('should split x tick to 2 lines properly', function() { var tick = chart.internal.main .select('.c3-axis-x') .select('g.tick'), tspans = tick.selectAll('tspan'), expectedTickTexts = [ 'this is a very long tick text on', 'category axis' ], expectedX = '-9' expect(tspans.size()).toBe(2) tspans.each(function(d, i) { var tspan = d3.select(this) expect(tspan.text()).toBe(expectedTickTexts[i]) expect(tspan.attr('x')).toBe(expectedX) // unable to define pricise number because it differs depends on environment.. if (i === 0) { expect(tspan.attr('dy')).toBeLessThan(0) } else { expect(tspan.attr('dy')).toBeGreaterThan(8) } }) }) }) describe('with multilineMax', function() { beforeAll(function() { args.axis.x.tick = { multiline: true, multilineMax: 2 } }) it('should ellipsify x tick properly', function() { var tick = chart.internal.main.select('.c3-axis-x').select('g.tick') var tspans = tick.selectAll('tspan') var expectedTickText = [ 'this is a very long', 'tick text on categ...' ] expect(tspans.size()).toBe(2) tspans.each(function(d, i) { var tspan = d3.select(this) expect(tspan.text()).toBe(expectedTickText[i]) }) }) }) }) }) describe('with axis.x.tick.format', function() { beforeAll(function() { // 'with axis.x.tick.format', args.axis.x.tick.format = function() { return ['this is a very long tick text', 'on category axis'] } }) it('should have multiline tick text', function() { var tick = chart.internal.main.select('.c3-axis-x').select('g.tick'), tspans = tick.selectAll('tspan'), expectedTickTexts = [ 'this is a very long tick text', 'on category axis' ] expect(tspans.size()).toBe(2) tspans.each(function(d, i) { var tspan = d3.select(this) expect(tspan.text()).toBe(expectedTickTexts[i]) }) }) }) }) describe('axis.x.tick.rotate', function() { describe('not rotated', function() { beforeAll(function() { args = { data: { x: 'x', columns: [ [ 'x', 'category 1', 'category 2', 'category 3', 'category 4', 'category 5', 'category 6' ], ['data1', 30, 200, 100, 400, 150, 250], ['data2', 50, 20, 10, 40, 15, 25] ] }, axis: { x: { type: 'category', tick: { rotate: 60 } } } } }) it('should rotate tick texts', function() { chart.internal.main.selectAll('.c3-axis-x g.tick').each(function() { var tick = d3.select(this), text = tick.select('text'), tspan = text.select('tspan') expect(text.attr('transform')).toBe('rotate(60)') expect(text.attr('y')).toBe('1.5') expect(tspan.attr('dx')).toBe('6.928203230275509') }) }) it('should have automatically calculated x axis height', function() { var box = chart.internal.main .select('.c3-axis-x') .node() .getBoundingClientRect(), height = chart.internal.getHorizontalAxisHeight('x') expect(box.height).toBeGreaterThan(50) expect(height).toBeCloseTo(76, -1.3) // @TODO make this test better }) }) }) describe('axis.y.tick.rotate', function() { describe('not rotated', function() { beforeAll(function() { args = { data: { columns: [ ['data1', 30, 200, 100, 400, 150, 250, 100, 600], ['data2', 50, 20, 10, 40, 15, 25] ] }, axis: { rotated: true, y: { tick: { rotate: 45 } } } } }) it('should rotate tick texts', function() { chart.internal.main.selectAll('.c3-axis-y g.tick').each(function() { var tick = d3.select(this), text = tick.select('text'), tspan = text.select('tspan') expect(text.attr('transform')).toBe('rotate(45)') expect(text.attr('y')).toBe('4') expect(tspan.attr('dx')).toBeCloseTo(5.6, 0) }) }) it('should have automatically calculated y axis width', function() { var box = chart.internal.main .select('.c3-axis-y') .node() .getBoundingClientRect() expect(box.width).toBeCloseTo(590, 1) }) }) }) describe('axis.x.tick.fit', function() { describe('axis.x.tick.fit = true', function() { beforeAll(function() { // 'should set args for indexed data', args = { data: { columns: [ ['data1', 30, 200, 100, 400, 150, 250], ['data2', 50, 20, 10, 40, 15, 25], ['data3', 150, 120, 110, 140, 115, 125] ] } } }) it('should show fitted ticks on indexed data', function() { var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick') expect(ticks.size()).toBe(6) }) describe('should set args for x-based data', function() { beforeAll(function() { args = { data: { x: 'x', columns: [ ['x', 10, 20, 100, 110, 200, 1000], ['data1', 30, 200, 100, 400, 150, 250], ['data2', 50, 20, 10, 40, 15, 25], ['data3', 150, 120, 110, 140, 115, 125] ] } } }) it('should show fitted ticks on indexed data', function() { var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick') expect(ticks.size()).toBe(6) }) it('should show fitted ticks after hide and show', function() { chart.hide() chart.show() var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick') expect(ticks.size()).toBe(6) }) }) }) describe('axis.x.tick.fit = false', function() { describe('should set args for indexed data', function() { beforeAll(function() { args = { data: { columns: [ ['data1', 30, 200, 100, 400, 150, 250], ['data2', 50, 20, 10, 40, 15, 25], ['data3', 150, 120, 110, 140, 115, 125] ] }, axis: { x: { tick: { fit: false } } } } }) it('should show fitted ticks on indexed data', function() { var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick') expect(ticks.size()).toBe(11) }) }) describe('should set args for x-based data', function() { beforeAll(function() { args.data = { x: 'x', columns: [ ['x', 10, 20, 100, 110, 200, 1000], ['data1', 30, 200, 100, 400, 150, 250], ['data2', 50, 20, 10, 40, 15, 25], ['data3', 150, 120, 110, 140, 115, 125] ] } }) it('should show fitted ticks on indexed data', function() { var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick') expect(ticks.size()).toBe(10) }) it('should show fitted ticks after hide and show', function() { chart.hide() chart.show() var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick') expect(ticks.size()).toBe(10) }) }) }) }) describe('axis.y.inner', function() { beforeAll(function() { args = { data: { columns: [ ['data1', 30, 200, 100, 400, 150, 250], ['data2', 50, 20, 10, 40, 15, 25] ] }, axis: { y: { inner: false } } } }) it('should not have inner y axis', function() { var paddingLeft = chart.internal.getCurrentPaddingLeft(), tickTexts = chart.internal.main.selectAll('.c3-axis-y g.tick text') expect(paddingLeft).toBeGreaterThan(19) tickTexts.each(function() { expect(+d3.select(this).attr('x')).toBeLessThan(0) }) }) describe('with inner y axis', function() { beforeAll(function() { args.axis.y.inner = true }) it('should have inner y axis', function() { var paddingLeft = chart.internal.getCurrentPaddingLeft(), tickTexts = chart.internal.main.selectAll('.c3-axis-y g.tick text') expect(paddingLeft).toBe(1) tickTexts.each(function() { expect(+d3.select(this).attr('x')).toBeGreaterThan(0) }) }) }) }) describe('axis.y2.inner', function() { beforeAll(function() { args = { data: { columns: [ ['data1', 30, 200, 100, 400, 150, 250], ['data2', 50, 20, 10, 40, 15, 25] ] }, axis: { y2: { show: true, inner: false } } } }) it('should not have inner y axis', function() { var paddingRight = chart.internal.getCurrentPaddingRight(), tickTexts = chart.internal.main.selectAll('.c3-axis-2y g.tick text') expect(paddingRight).toBeGreaterThan(19) tickTexts.each(function() { expect(+d3.select(this).attr('x')).toBeGreaterThan(0) }) }) describe('with inner y axis', function() { beforeAll(function() { args.axis.y2.inner = true }) it('should have inner y axis', function() { var paddingRight = chart.internal.getCurrentPaddingRight(), tickTexts = chart.internal.main.selectAll('.c3-axis-2y g.tick text') expect(paddingRight).toBe(2) tickTexts.each(function() { expect(+d3.select(this).attr('x')).toBeLessThan(0) }) }) }) }) describe('axis.x.label', function() { beforeAll(function() { args = { data: { columns: [ ['somewhat long 1', 30, 200, 100, 400, 150, 250], ['somewhat long 2', 50, 20, 10, 40, 15, 25] ] }, axis: { x: { show: true, label: { text: 'Label of X axis' } } } } }) it('renders label text properly', () => { expect(d3.select('.c3-axis-x-label').text()).toEqual('Label of X axis') }) describe('outer label position', function() { beforeAll(function() { args.axis.x.label.position = 'outer-center' }) it('renders position properly', () => { const label = d3.select('.c3-axis-x-label') expect(label.attr('dy')).toEqual('30') }) describe('with rotated tick', function() { beforeAll(function() { args.axis.x.tick = { rotate: 90 } }) it('renders position properly', () => { const label = d3.select('.c3-axis-x-label') expect(label.attr('dy')).toBeGreaterThan(30) }) }) }) describe('inner label position', function() { beforeAll(function() { args.axis.x.label.position = 'inner-center' }) it('renders position properly', () => { const label = d3.select('.c3-axis-x-label') expect(label.attr('dy')).toEqual('-0.5em') }) describe('with rotated tick', function() { beforeAll(function() { args.axis.x.tick = { rotate: 90 } }) it('renders position properly', () => { const label = d3.select('.c3-axis-x-label') expect(label.attr('dy')).toEqual('-0.5em') }) }) }) }) })