describe('Linear Scale', function() {
var chartInstance;
beforeEach(function() {
window.addDefaultMatchers(jasmine);
});
afterEach(function() {
if (chartInstance)
{
releaseChart(chartInstance);
}
});
it('Should register the constructor with the scale service', function() {
var Constructor = Chart.scaleService.getScaleConstructor('linear');
expect(Constructor).not.toBe(undefined);
expect(typeof Constructor).toBe('function');
});
it('Should have the correct default config', function() {
var defaultConfig = Chart.scaleService.getScaleDefaults('linear');
expect(defaultConfig).toEqual({
display: true,
gridLines: {
color: "rgba(0, 0, 0, 0.1)",
drawBorder: true,
drawOnChartArea: true,
drawTicks: true, // draw ticks extending towards the label
tickMarkLength: 10,
lineWidth: 1,
offsetGridLines: false,
display: true,
zeroLineColor: "rgba(0,0,0,0.25)",
zeroLineWidth: 1,
},
position: "left",
scaleLabel: {
labelString: '',
display: false,
},
ticks: {
beginAtZero: false,
minRotation: 0,
maxRotation: 50,
mirror: false,
padding: 10,
reverse: false,
display: true,
callback: defaultConfig.ticks.callback, // make this work nicer, then check below
autoSkip: true,
autoSkipPadding: 0,
labelOffset: 0
}
});
expect(defaultConfig.ticks.callback).toEqual(jasmine.any(Function));
});
it('Should correctly determine the max & min data values', function() {
chartInstance = window.acquireChart({
type: 'bar',
data: {
datasets: [{
yAxisID: 'yScale0',
data: [10, 5, 0, -5, 78, -100]
}, {
yAxisID: 'yScale1',
data: [-1000, 1000],
}, {
yAxisID: 'yScale0',
data: [150]
}],
labels: ['a', 'b', 'c', 'd', 'e', 'f']
},
options: {
scales: {
yAxes: [{
id: 'yScale0',
type: 'linear'
}, {
id: 'yScale1',
type: 'linear'
}]
}
}
});
expect(chartInstance.scales.yScale0).not.toEqual(undefined); // must construct
expect(chartInstance.scales.yScale0.min).toBe(-100);
expect(chartInstance.scales.yScale0.max).toBe(150);
});
it('Should correctly determine the max & min of string data values', function() {
chartInstance = window.acquireChart({
type: 'bar',
data: {
datasets: [{
yAxisID: 'yScale0',
data: ['10', '5', '0', '-5', '78', '-100']
}, {
yAxisID: 'yScale1',
data: ['-1000', '1000'],
}, {
yAxisID: 'yScale0',
data: ['150']
}],
labels: ['a', 'b', 'c', 'd', 'e', 'f']
},
options: {
scales: {
yAxes: [{
id: 'yScale0',
type: 'linear'
}, {
id: 'yScale1',
type: 'linear'
}]
}
}
});
expect(chartInstance.scales.yScale0).not.toEqual(undefined); // must construct
expect(chartInstance.scales.yScale0.min).toBe(-100);
expect(chartInstance.scales.yScale0.max).toBe(150);
});
it('Should correctly determine the max & min data values ignoring hidden datasets', function() {
chartInstance = window.acquireChart({
type: 'bar',
data: {
datasets: [{
yAxisID: 'yScale0',
data: ['10', '5', '0', '-5', '78', '-100']
}, {
yAxisID: 'yScale1',
data: ['-1000', '1000'],
}, {
yAxisID: 'yScale0',
data: ['150'],
hidden: true
}],
labels: ['a', 'b', 'c', 'd', 'e', 'f']
},
options: {
scales: {
yAxes: [{
id: 'yScale0',
type: 'linear'
}, {
id: 'yScale1',
type: 'linear'
}]
}
}
});
expect(chartInstance.scales.yScale0).not.toEqual(undefined); // must construct
expect(chartInstance.scales.yScale0.min).toBe(-100);
expect(chartInstance.scales.yScale0.max).toBe(80);
});
it('Should correctly determine the max & min data values ignoring data that is NaN', function() {
chartInstance = window.acquireChart({
type: 'bar',
data: {
datasets: [{
yAxisID: 'yScale0',
data: [null, 90, NaN, undefined, 45, 30]
}],
labels: ['a', 'b', 'c', 'd', 'e', 'f']
},
options: {
scales: {
yAxes: [{
id: 'yScale0',
type: 'linear'
}]
}
}
});
expect(chartInstance.scales.yScale0.min).toBe(30);
expect(chartInstance.scales.yScale0.max).toBe(90);
// Scale is now stacked
chartInstance.scales.yScale0.options.stacked = true;
chartInstance.update();
expect(chartInstance.scales.yScale0.min).toBe(0);
expect(chartInstance.scales.yScale0.max).toBe(90);
});
it('Should correctly determine the max & min for scatter data', function() {
chartInstance = window.acquireChart({
type: 'line',
data: {
datasets: [{
xAxisID: 'xScale0',
yAxisID: 'yScale0',
data: [{
x: 10,
y: 100
}, {
x: -10,
y: 0
}, {
x: 0,
y: 0
}, {
x: 99,
y: 7
}]
}],
},
options: {
scales: {
xAxes: [{
id: 'xScale0',
type: 'linear',
position: 'bottom'
}],
yAxes: [{
id: 'yScale0',
type: 'linear'
}]
}
}
});
chartInstance.update();
expect(chartInstance.scales.xScale0.min).toBe(-20);
expect(chartInstance.scales.xScale0.max).toBe(100);
expect(chartInstance.scales.yScale0.min).toBe(0);
expect(chartInstance.scales.yScale0.max).toBe(100);
});
it('Should correctly get the label for the given index', function() {
chartInstance = window.acquireChart({
type: 'line',
data: {
datasets: [{
xAxisID: 'xScale0',
yAxisID: 'yScale0',
data: [{
x: 10,
y: 100
}, {
x: -10,
y: 0
}, {
x: 0,
y: 0
}, {
x: 99,
y: 7
}]
}],
},
options: {
scales: {
xAxes: [{
id: 'xScale0',
type: 'linear',
position: 'bottom'
}],
yAxes: [{
id: 'yScale0',
type: 'linear'
}]
}
}
});
chartInstance.update();
expect(chartInstance.scales.yScale0.getLabelForIndex(3, 0)).toBe(7);
});
it('Should correctly determine the min and max data values when stacked mode is turned on', function() {
chartInstance = window.acquireChart({
type: 'line',
data: {
datasets: [{
yAxisID: 'yScale0',
data: [10, 5, 0, -5, 78, -100],
type: 'bar'
}, {
yAxisID: 'yScale1',
data: [-1000, 1000],
}, {
yAxisID: 'yScale0',
data: [150, 0, 0, -100, -10, 9],
type: 'bar'
}, {
yAxisID: 'yScale0',
data: [10, 10, 10, 10, 10, 10],
type: 'line'
}],
labels: ['a', 'b', 'c', 'd', 'e', 'f']
},
options: {
scales: {
yAxes: [{
id: 'yScale0',
type: 'linear',
stacked: true
}, {
id: 'yScale1',
type: 'linear'
}]
}
}
});
chartInstance.update();
expect(chartInstance.scales.yScale0.min).toBe(-150);
expect(chartInstance.scales.yScale0.max).toBe(200);
});
it('Should correctly determine the min and max data values when stacked mode is turned on and there are hidden datasets', function() {
chartInstance = window.acquireChart({
type: 'bar',
data: {
datasets: [{
yAxisID: 'yScale0',
data: [10, 5, 0, -5, 78, -100],
}, {
yAxisID: 'yScale1',
data: [-1000, 1000],
}, {
yAxisID: 'yScale0',
data: [150, 0, 0, -100, -10, 9],
}, {
yAxisID: 'yScale0',
data: [10, 20, 30, 40, 50, 60],
hidden: true
}],
labels: ['a', 'b', 'c', 'd', 'e', 'f']
},
options: {
scales: {
yAxes: [{
id: 'yScale0',
type: 'linear',
stacked: true
}, {
id: 'yScale1',
type: 'linear'
}]
}
}
});
chartInstance.update();
expect(chartInstance.scales.yScale0.min).toBe(-150);
expect(chartInstance.scales.yScale0.max).toBe(200);
});
it('Should correctly determine the min and max data values when stacked mode is turned on there are multiple types of datasets', function() {
chartInstance = window.acquireChart({
type: 'bar',
data: {
datasets: [{
yAxisID: 'yScale0',
type: 'bar',
data: [10, 5, 0, -5, 78, -100]
}, {
type: 'line',
data: [10, 10, 10, 10, 10, 10],
}, {
type: 'bar',
data: [150, 0, 0, -100, -10, 9]
}],
labels: ['a', 'b', 'c', 'd', 'e', 'f']
},
options: {
scales: {
yAxes: [{
id: 'yScale0',
type: 'linear',
stacked: true
}]
}
}
});
chartInstance.scales.yScale0.determineDataLimits();
expect(chartInstance.scales.yScale0.min).toBe(-105);
expect(chartInstance.scales.yScale0.max).toBe(160);
});
it('Should ensure that the scale has a max and min that are not equal', function() {
chartInstance = window.acquireChart({
type: 'bar',
data: {
datasets: [],
labels: ['a', 'b', 'c', 'd', 'e', 'f']
},
options: {
scales: {
yAxes: [{
id: 'yScale0',
type: 'linear'
}]
}
}
});
expect(chartInstance.scales.yScale0).not.toEqual(undefined); // must construct
expect(chartInstance.scales.yScale0.min).toBe(-1);
expect(chartInstance.scales.yScale0.max).toBe(1);
});
it('Should ensure that the scale has a max and min that are not equal when beginAtZero is set', function() {
chartInstance = window.acquireChart({
type: 'bar',
data: {
datasets: [],
labels: ['a', 'b', 'c', 'd', 'e', 'f']
},
options: {
scales: {
yAxes: [{
id: 'yScale0',
type: 'linear',
ticks: {
beginAtZero: true
}
}]
}
}
});
expect(chartInstance.scales.yScale0).not.toEqual(undefined); // must construct
expect(chartInstance.scales.yScale0.min).toBe(0);
expect(chartInstance.scales.yScale0.max).toBe(1);
});
it('Should use the suggestedMin and suggestedMax options', function() {
chartInstance = window.acquireChart({
type: 'bar',
data: {
datasets: [{
yAxisID: 'yScale0',
data: [1, 1, 1, 2, 1, 0]
}],
labels: ['a', 'b', 'c', 'd', 'e', 'f']
},
options: {
scales: {
yAxes: [{
id: 'yScale0',
type: 'linear',
ticks: {
suggestedMax: 10,
suggestedMin: -10
}
}]
}
}
});
expect(chartInstance.scales.yScale0).not.toEqual(undefined); // must construct
expect(chartInstance.scales.yScale0.min).toBe(-10);
expect(chartInstance.scales.yScale0.max).toBe(10);
});
it('Should use the min and max options', function() {
chartInstance = window.acquireChart({
type: 'bar',
data: {
datasets: [{
yAxisID: 'yScale0',
data: [1, 1, 1, 2, 1, 0]
}],
labels: ['a', 'b', 'c', 'd', 'e', 'f']
},
options: {
scales: {
yAxes: [{
id: 'yScale0',
type: 'linear',
ticks: {
max: 1010,
min: -1010
}
}]
}
}
});
expect(chartInstance.scales.yScale0).not.toEqual(undefined); // must construct
expect(chartInstance.scales.yScale0.min).toBe(-1010);
expect(chartInstance.scales.yScale0.max).toBe(1010);
expect(chartInstance.scales.yScale0.ticks[0]).toBe('1010');
expect(chartInstance.scales.yScale0.ticks[chartInstance.scales.yScale0.ticks.length - 1]).toBe('-1010');
});
it('should forcibly include 0 in the range if the beginAtZero option is used', function() {
chartInstance = window.acquireChart({
type: 'bar',
data: {
datasets: [{
yAxisID: 'yScale0',
data: [20, 30, 40, 50]
}],
labels: ['a', 'b', 'c', 'd']
},
options: {
scales: {
yAxes: [{
id: 'yScale0',
type: 'linear',
}]
}
}
});
expect(chartInstance.scales.yScale0).not.toEqual(undefined); // must construct
expect(chartInstance.scales.yScale0.ticks).toEqual(['50', '45', '40', '35', '30', '25', '20']);
chartInstance.scales.yScale0.options.ticks.beginAtZero = true;
chartInstance.update();
expect(chartInstance.scales.yScale0.ticks).toEqual(['50', '45', '40', '35', '30', '25', '20', '15', '10', '5', '0']);
chartInstance.data.datasets[0].data = [-20, -30, -40, -50];
chartInstance.update();
expect(chartInstance.scales.yScale0.ticks).toEqual(['0', '-5', '-10', '-15', '-20', '-25', '-30', '-35', '-40', '-45', '-50']);
chartInstance.scales.yScale0.options.ticks.beginAtZero = false;
chartInstance.update();
expect(chartInstance.scales.yScale0.ticks).toEqual(['-20', '-25', '-30', '-35', '-40', '-45', '-50']);
});
it('Should generate tick marks in the correct order in reversed mode', function() {
chartInstance = window.acquireChart({
type: 'bar',
data: {
datasets: [{
yAxisID: 'yScale0',
data: [10, 5, 0, 25, 78]
}],
labels: ['a', 'b', 'c', 'd']
},
options: {
scales: {
yAxes: [{
id: 'yScale0',
type: 'linear',
ticks: {
reverse: true
}
}]
}
}
});
expect(chartInstance.scales.yScale0.ticks).toEqual(['0', '10', '20', '30', '40', '50', '60', '70', '80']);
expect(chartInstance.scales.yScale0.start).toBe(80);
expect(chartInstance.scales.yScale0.end).toBe(0);
});
it('should use the correct number of decimal places in the default format function', function() {
chartInstance = window.acquireChart({
type: 'bar',
data: {
datasets: [{
yAxisID: 'yScale0',
data: [0.06, 0.005, 0, 0.025, 0.0078]
}],
labels: ['a', 'b', 'c', 'd']
},
options: {
scales: {
yAxes: [{
id: 'yScale0',
type: 'linear',
}]
}
}
});
expect(chartInstance.scales.yScale0.ticks).toEqual(['0.06', '0.05', '0.04', '0.03', '0.02', '0.01', '0']);
});
it('Should build labels using the user supplied callback', function() {
chartInstance = window.acquireChart({
type: 'bar',
data: {
datasets: [{
yAxisID: 'yScale0',
data: [10, 5, 0, 25, 78]
}],
labels: ['a', 'b', 'c', 'd']
},
options: {
scales: {
yAxes: [{
id: 'yScale0',
type: 'linear',
ticks: {
callback: function(value, index) {
return index.toString();
}
}
}]
}
}
});
// Just the index
expect(chartInstance.scales.yScale0.ticks).toEqual(['0', '1', '2', '3', '4', '5', '6', '7', '8']);
});
it('Should get the correct pixel value for a point', function() {
chartInstance = window.acquireChart({
type: 'line',
data: {
datasets: [{
xAxisID: 'xScale0',
yAxisID: 'yScale0',
data: []
}],
},
options: {
scales: {
xAxes: [{
id: 'xScale0',
type: 'linear',
position: 'bottom'
}],
yAxes: [{
id: 'yScale0',
type: 'linear'
}]
}
}
});
var xScale = chartInstance.scales.xScale0;
expect(xScale.getPixelForValue(1, 0, 0)).toBeCloseToPixel(501); // right - paddingRight
expect(xScale.getPixelForValue(-1, 0, 0)).toBeCloseToPixel(41); // left + paddingLeft
expect(xScale.getPixelForValue(0, 0, 0)).toBeCloseToPixel(271); // halfway*/
expect(xScale.getValueForPixel(501)).toBeCloseTo(1, 1e-2);
expect(xScale.getValueForPixel(41)).toBeCloseTo(-1, 1e-2);
expect(xScale.getValueForPixel(271)).toBeCloseTo(0, 1e-2);
var yScale = chartInstance.scales.yScale0;
expect(yScale.getPixelForValue(1, 0, 0)).toBeCloseToPixel(32); // right - paddingRight
expect(yScale.getPixelForValue(-1, 0, 0)).toBeCloseToPixel(484); // left + paddingLeft
expect(yScale.getPixelForValue(0, 0, 0)).toBeCloseToPixel(258); // halfway*/
expect(yScale.getValueForPixel(32)).toBe(1);
expect(yScale.getValueForPixel(484)).toBe(-1);
expect(yScale.getValueForPixel(258)).toBe(0);
});
it('should fit correctly', function() {
chartInstance = window.acquireChart({
type: 'line',
data: {
datasets: [{
xAxisID: 'xScale0',
yAxisID: 'yScale0',
data: [{
x: 10,
y: 100
}, {
x: -10,
y: 0
}, {
x: 0,
y: 0
}, {
x: 99,
y: 7
}]
}],
},
options: {
scales: {
xAxes: [{
id: 'xScale0',
type: 'linear',
position: 'bottom'
}],
yAxes: [{
id: 'yScale0',
type: 'linear'
}]
}
}
});
var xScale = chartInstance.scales.xScale0;
expect(xScale.paddingTop).toBeCloseToPixel(0);
expect(xScale.paddingBottom).toBeCloseToPixel(0);
expect(xScale.paddingLeft).toBeCloseToPixel(0);
expect(xScale.paddingRight).toBeCloseToPixel(13.5);
expect(xScale.width).toBeCloseToPixel(471);
expect(xScale.height).toBeCloseToPixel(28);
var yScale = chartInstance.scales.yScale0;
expect(yScale.paddingTop).toBeCloseToPixel(0);
expect(yScale.paddingBottom).toBeCloseToPixel(0);
expect(yScale.paddingLeft).toBeCloseToPixel(0);
expect(yScale.paddingRight).toBeCloseToPixel(0);
expect(yScale.width).toBeCloseToPixel(41);
expect(yScale.height).toBeCloseToPixel(452);
// Extra size when scale label showing
xScale.options.scaleLabel.display = true;
yScale.options.scaleLabel.display = true;
chartInstance.update();
expect(xScale.paddingTop).toBeCloseToPixel(0);
expect(xScale.paddingBottom).toBeCloseToPixel(0);
expect(xScale.paddingLeft).toBeCloseToPixel(0);
expect(xScale.paddingRight).toBeCloseToPixel(13.5);
expect(xScale.width).toBeCloseToPixel(453);
expect(xScale.height).toBeCloseToPixel(46);
expect(yScale.paddingTop).toBeCloseToPixel(0);
expect(yScale.paddingBottom).toBeCloseToPixel(0);
expect(yScale.paddingLeft).toBeCloseToPixel(0);
expect(yScale.paddingRight).toBeCloseToPixel(0);
expect(yScale.width).toBeCloseToPixel(59);
expect(yScale.height).toBeCloseToPixel(434);
});
});
|