Skip to content

Commit

Permalink
more tests for bar/bar chart
Browse files Browse the repository at this point in the history
  • Loading branch information
Dan Delany committed Nov 15, 2017
1 parent 9cb9539 commit d0c6710
Show file tree
Hide file tree
Showing 2 changed files with 288 additions and 0 deletions.
202 changes: 202 additions & 0 deletions tests/jsdom/spec/Bar.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
import React from 'react';
import * as d3 from 'd3';
import _ from 'lodash';
import chai from 'chai';
import {mount, shallow} from 'enzyme';
import sinon from 'sinon';
import sinonChai from 'sinon-chai';
chai.use(sinonChai);
const {expect} = chai;

import {Bar} from '../../../src/index.js';

function expectProps(el, expectedProps) {
const props = el.props();
_.forEach(expectedProps, (expectedValue, key) => {
expect(props[key]).to.equal(expectedValue);
});
}

describe('Bar', () => {
it('renders a basic vertical bar correctly', () => {
const bar = shallow(
<Bar
scale={{
x: d3.scalePoint().domain(['a', 'b', 'c']).range([0, 100]),
y: d3.scaleLinear().domain([0, 1]).range([100, 0]),
}}
xValue={'b'}
yValue={0.25}
yEndValue={0.75}
thickness={20}
/>
);

const rect = bar.find('rect');
expect(rect).to.have.length(1);

const rectProps = rect.props();
expect(rectProps.className).to.include('chart-bar');
expect(rectProps.className).to.include('chart-bar-vertical');
expect(rectProps.x).to.equal(50 - (20 / 2));
expect(rectProps.y).to.equal(25);
expect(rectProps.height).to.equal(50);
expect(rectProps.width).to.equal(20);
});

it('renders a basic horizontal bar correctly', () => {
const bar = shallow(
<Bar
scale={{
x: d3.scaleLinear().domain([0, 1]).range([0, 100]),
y: d3.scalePoint().domain(['a', 'b', 'c']).range([100, 0]),
}}
xValue={.1}
xEndValue={.7}
yValue={'b'}
thickness={20}
/>
);

const rect = bar.find('rect');
expect(rect).to.have.length(1);

const rectProps = rect.props();
expect(rectProps.className).to.include('chart-bar');
expect(rectProps.className).to.include('chart-bar-horizontal');
expect(rectProps.x).to.equal(10);
expect(rectProps.y).to.equal(50 - (20 / 2));
expect(rectProps.height).to.equal(20);
expect(rectProps.width).to.equal(60);
});

it('has a thickness prop which controls the thickness of the bar', () => {
const verticalBarProps = {
scale: {
x: d3.scalePoint().domain(['a', 'b', 'c']).range([0, 100]),
y: d3.scaleLinear().domain([0, 1]).range([100, 0]),
},
xValue: 'a',
yValue: 0,
yEndValue: 1,
thickness: 10
};

const verticalBar = shallow(<Bar {...verticalBarProps} />);
expect(verticalBar.find('rect')).to.have.length(1);
expect(verticalBar.find('rect').props().width).to.equal(10);

const thickVerticalBar = shallow(<Bar {...verticalBarProps} thickness={40} />);
expect(thickVerticalBar.find('rect')).to.have.length(1);
expect(thickVerticalBar.find('rect').props().width).to.equal(40);

const horizontalBarProps = {
scale: {
x: d3.scaleLinear().domain([0, 1]).range([0, 100]),
y: d3.scalePoint().domain(['a', 'b', 'c']).range([100, 0]),
},
xValue: .2,
xEndValue: .9,
yValue: 'c',
thickness: 12
};

const horizontalBar = shallow(<Bar {...horizontalBarProps} />);
expect(horizontalBar.find('rect')).to.have.length(1);
expect(horizontalBar.find('rect').props().height).to.equal(12);

const thickHorizontalBar = shallow(<Bar {...horizontalBarProps} thickness={56} />);
expect(thickHorizontalBar.find('rect')).to.have.length(1);
expect(thickHorizontalBar.find('rect').props().height).to.equal(56);
});

it("passes className and style props through to the bar's rectangle element", () => {
const verticalBarProps = {
scale: {
x: d3.scalePoint().domain(['a', 'b', 'c']).range([0, 100]),
y: d3.scaleLinear().domain([0, 1]).range([100, 0]),
},
xValue: 'a',
yValue: 0,
yEndValue: 1,
className: 'foo-bar-test-class',
style: {fill: 'thistle'}
};

const verticalBar = shallow(<Bar {...verticalBarProps} />);
const rect = verticalBar.find('rect');
expect(rect).to.have.length(1);
expect(rect.props().className).to.include('foo-bar-test-class');
expect(rect.props().style).to.deep.equal(verticalBarProps.style);
});

it("attaches onMouseMove, onMouseEnter and onMouseLeave handlers to the bar's rectangle", () => {
const barProps = {
scale: {
x: d3.scalePoint().domain(['a', 'b', 'c']).range([0, 100]),
y: d3.scaleLinear().domain([0, 1]).range([100, 0]),
},
xValue: 'a',
yValue: 0,
yEndValue: 1,
onMouseMove: sinon.spy(),
onMouseEnter: sinon.spy(),
onMouseLeave: sinon.spy()
};

const bar = mount(<Bar {...barProps} />);
const rect = bar.find('rect');

expect(barProps.onMouseEnter).not.to.have.been.called;
rect.simulate('mouseenter');
expect(barProps.onMouseEnter).to.have.been.calledOnce;

expect(barProps.onMouseMove).not.to.have.been.called;
rect.simulate('mousemove');
expect(barProps.onMouseMove).to.have.been.calledOnce;

expect(barProps.onMouseLeave).not.to.have.been.called;
rect.simulate('mouseleave');
expect(barProps.onMouseLeave).to.have.been.calledOnce;
});

it("throws an error if x/y scale(s) are missing or invalid", () => {
const barProps = {xValue: 'a', yValue: 0, yEndValue: 1};
const xScale = d3.scalePoint().domain(['a', 'b', 'c']).range([0, 100]);
const yScale = d3.scaleLinear().domain([0, 1]).range([100, 0]);

// throw if no scale prop passed
expect(() => { shallow(<Bar {...barProps}/>); }).to.throw(Error);
// throw if one scale is missing
expect(() => {
shallow(<Bar {...{...barProps, scale: {x: xScale}}}/>);
}).to.throw(Error);
// throw if one scale is invalid
expect(() => {
shallow(<Bar {...{...barProps, scale: {x: 'bad', y: yScale}}}/>);
}).to.throw(Error);
// don't throw if both are provided
expect(() => {
shallow(<Bar {...{...barProps, scale: {x: xScale, y: yScale}}}/>);
}).not.to.throw(Error);
});

it("throws an error if exactly ONE of xEndValue OR yEndValue are not provided", () => {
const barProps = {
scale: {
x: d3.scalePoint().domain(['a', 'b', 'c']).range([0, 100]),
y: d3.scaleLinear().domain([0, 1]).range([100, 0]),
},
xValue: 'a',
yValue: 0
};

// throw if neither xEndValue or yEndValue passed
expect(() => { shallow(<Bar {...barProps}/>); }).to.throw(Error);
// throw if both xEndValue and yEndValue passed
expect(() => { shallow(<Bar {...{...barProps, xEndValue: 'b', yEndValue: 1}}/>); }).to.throw(Error);
// OK if one or other is passed
expect(() => { shallow(<Bar {...{...barProps, xEndValue: 'b'}}/>); }).not.to.throw(Error);
expect(() => { shallow(<Bar {...{...barProps, yEndValue: 1}}/>); }).not.to.throw(Error);
})
});
86 changes: 86 additions & 0 deletions tests/jsdom/spec/BarChart.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import React from 'react';
import * as d3 from 'd3';
import _ from 'lodash';
import {expect} from 'chai';
import {mount, shallow} from 'enzyme';

import {XYPlot, BarChart, RangeBarChart} from '../../../src/index.js';

function expectProps(el, expectedProps) {
const props = el.props();
_.forEach(expectedProps, (expectedValue, key) => {
expect(props[key]).to.equal(expectedValue);
});
}

describe('BarChart', () => {
it('passes most props through to RangeBarChart', () => {
// bar chart is just a simple wrapper around RangeBarChart, most props are passed through
const props = {
scale: {
x: d3.scalePoint().domain(['a', 'b', 'c']).range([0, 100]),
y: d3.scaleLinear().domain([0, 1]).range([100, 0]),
},
data: [['a', 0.25], ['b', .5], ['c', .67]],
getX: 0,
getY: 1,
barThickness: 13,
horizontal: false,
barClassName: 'test-bar-class-name',
barStyle: {fill: "red"},
getClass: () => 'test',
onMouseEnterBar: () => 'onMouseEnterBar',
onMouseMoveBar: () => 'onMouseMoveBar',
onMouseLeaveBar: () => 'onMouseLeaveBar'
};

const chart = mount(<BarChart {...props} />);
const rangeBarChart = chart.find(RangeBarChart);
// all props should be passed through as-is *except* getY
expectProps(rangeBarChart, _.omit(props, ['getY']));

// vertical bar chart - getY is passed to RangeBarChart as getYEnd
expect(rangeBarChart.props().getYEnd).to.equal(props.getY);

// check that correct props are passed through in horizontal case\
const horizontalProps = {...props, horizontal: true}
});

it('renders a bar chart with categorical X data & numerical Y data', () => {
// make simple bar chart with 3 datapoints to make sure it renders correctly
// this is more of an integration test/sanity check;
// most tests for render correctness are in RangeBarChart and Bar specs

const props = {
scale: {
x: d3.scalePoint().domain(['a', 'b', 'c']).range([0, 100]),
y: d3.scaleLinear().domain([0, 1]).range([100, 0]),
},
data: [['a', 0.25], ['b', .5], ['c', .67]],
getX: 0,
getY: 1,
barThickness: 10
};

const chart = mount(<BarChart {...props} />);
const group = chart.find('g');
const bars = chart.find('rect');
expect(group).to.have.length(1);
expect(bars).to.have.length(3);

expect(bars.at(0).props().x).to.equal(0 - (props.barThickness / 2));
expect(bars.at(0).props().y).to.equal(75);
expect(bars.at(0).props().width).to.equal(props.barThickness);
expect(bars.at(0).props().height).to.equal(25);

expect(bars.at(1).props().x).to.equal(50 - (props.barThickness / 2));
expect(bars.at(1).props().y).to.equal(50);
expect(bars.at(1).props().width).to.equal(props.barThickness);
expect(bars.at(1).props().height).to.equal(50);

expect(bars.at(2).props().x).to.equal(100 - (props.barThickness / 2));
expect(bars.at(2).props().y).to.equal(33);
expect(bars.at(2).props().width).to.equal(props.barThickness);
expect(bars.at(2).props().height).to.equal(67);
});
});

0 comments on commit d0c6710

Please sign in to comment.