Merge pull request #1938 from nnnick/testing_improvements

Testing improvements
This commit is contained in:
Evert Timberg 2016-01-27 18:04:22 -05:00
commit 212b6d3992
22 changed files with 3323 additions and 92 deletions

View File

@ -2,7 +2,7 @@
<html>
<head>
<title>Bar Chart</title>
<title>Bubble Chart</title>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="../Chart.js"></script>
<style type="text/css">

View File

@ -5,41 +5,6 @@
var Chart = root.Chart;
var helpers = Chart.helpers;
var defaultConfig = {
hover: {
mode: 'single',
},
scales: {
xAxes: [{
type: "linear", // bubble should probably use a linear scale by default
position: "bottom",
id: "x-axis-0", // need an ID so datasets can reference the scale
}],
yAxes: [{
type: "linear",
position: "left",
id: "y-axis-0",
}],
},
tooltips: {
callbacks: {
title: function(tooltipItems, data) {
// Title doesn't make sense for scatter since we format the data as a point
return '';
},
label: function(tooltipItem, data) {
return '(' + tooltipItem.xLabel + ', ' + tooltipItem.yLabel + ')';
}
}
},
};
// Register the default config for this type
Chart.defaults.bubble = defaultConfig;
Chart.Bubble = function(context, config) {
config.type = 'bubble';
return new Chart(context, config);

View File

@ -25,8 +25,17 @@
},
tooltips: {
template: "(<%= value.x %>, <%= value.y %>, <%= value.r %>)",
multiTemplate: "<%if (datasetLabel){%><%=datasetLabel%>: <%}%>(<%= value.x %>, <%= value.y %>, <%= value.r %>)",
callbacks: {
title: function(tooltipItems, data) {
// Title doesn't make sense for scatter since we format the data as a point
return '';
},
label: function(tooltipItem, data) {
var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || '';
var dataPoint = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
return datasetLabel + ': (' + dataPoint.x + ', ' + dataPoint.y + ', ' + dataPoint.r + ')';
}
}
},
};

View File

@ -223,8 +223,6 @@
} else {
return yScale.getPixelForValue(sumPos + value);
}
return yScale.getPixelForValue(value);
}
return yScale.getPixelForValue(value);

View File

@ -156,7 +156,6 @@
endAngle: this.chart.options.animateRotate ? Math.PI * -0.5 : endAngle,
backgroundColor: arc.custom && arc.custom.backgroundColor ? arc.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().backgroundColor, index, this.chart.options.elements.arc.backgroundColor),
hoverBackgroundColor: arc.custom && arc.custom.hoverBackgroundColor ? arc.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().hoverBackgroundColor, index, this.chart.options.elements.arc.hoverBackgroundColor),
borderWidth: arc.custom && arc.custom.borderWidth ? arc.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.arc.borderWidth),
borderColor: arc.custom && arc.custom.borderColor ? arc.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().borderColor, index, this.chart.options.elements.arc.borderColor),
@ -180,7 +179,6 @@
endAngle: endAngle,
backgroundColor: arc.custom && arc.custom.backgroundColor ? arc.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().backgroundColor, index, this.chart.options.elements.arc.backgroundColor),
hoverBackgroundColor: arc.custom && arc.custom.hoverBackgroundColor ? arc.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().hoverBackgroundColor, index, this.chart.options.elements.arc.hoverBackgroundColor),
borderWidth: arc.custom && arc.custom.borderWidth ? arc.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.arc.borderWidth),
borderColor: arc.custom && arc.custom.borderColor ? arc.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().borderColor, index, this.chart.options.elements.arc.borderColor),
@ -204,7 +202,7 @@
arc._model.backgroundColor = arc.custom && arc.custom.hoverBackgroundColor ? arc.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.color(arc._model.backgroundColor).saturate(0.5).darken(0.1).rgbString());
arc._model.borderColor = arc.custom && arc.custom.hoverBorderColor ? arc.custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.color(arc._model.borderColor).saturate(0.5).darken(0.1).rgbString());
arc._model.borderWidth = arc.custom && arc.custom.hoverBorderWidth ? arc.custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, arc._model.borderWidth);
arc._model.borderWidth = arc.custom && arc.custom.hoverBorderWidth ? arc.custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.hoverBorderWidth, index, arc._model.borderWidth);
},
removeHoverStyle: function(arc) {

View File

@ -88,11 +88,15 @@
// Model
_model: {
// Appearance
tension: helpers.getValueOrDefault(this.getDataset().tension, this.chart.options.elements.line.tension),
backgroundColor: this.getDataset().backgroundColor || this.chart.options.elements.line.backgroundColor,
borderWidth: this.getDataset().borderWidth || this.chart.options.elements.line.borderWidth,
borderColor: this.getDataset().borderColor || this.chart.options.elements.line.borderColor,
fill: this.getDataset().fill !== undefined ? this.getDataset().fill : this.chart.options.elements.line.fill, // use the value from the this.getDataset() if it was provided. else fall back to the default
tension: line.custom && line.custom.tension ? line.custom.tension : helpers.getValueOrDefault(this.getDataset().tension, this.chart.options.elements.line.tension),
backgroundColor: line.custom && line.custom.backgroundColor ? line.custom.backgroundColor : (this.getDataset().backgroundColor || this.chart.options.elements.line.backgroundColor),
borderWidth: line.custom && line.custom.borderWidth ? line.custom.borderWidth : (this.getDataset().borderWidth || this.chart.options.elements.line.borderWidth),
borderColor: line.custom && line.custom.borderColor ? line.custom.borderColor : (this.getDataset().borderColor || this.chart.options.elements.line.borderColor),
fill: line.custom && line.custom.fill ? line.custom.fill : (this.getDataset().fill !== undefined ? this.getDataset().fill : this.chart.options.elements.line.fill),
borderCapStyle: line.custom && line.custom.borderCapStyle ? line.custom.borderCapStyle : (this.getDataset().borderCapStyle || this.chart.options.elements.line.borderCapStyle),
borderDash: line.custom && line.custom.borderDash ? line.custom.borderDash : (this.getDataset().borderDash || this.chart.options.elements.line.borderDash),
borderDashOffset: line.custom && line.custom.borderDashOffset ? line.custom.borderDashOffset : (this.getDataset().borderDashOffset || this.chart.options.elements.line.borderDashOffset),
borderJoinStyle: line.custom && line.custom.borderJoinStyle ? line.custom.borderJoinStyle : (this.getDataset().borderJoinStyle || this.chart.options.elements.line.borderJoinStyle),
// Scale
scaleTop: scale.top,
@ -128,10 +132,11 @@
// Appearance
tension: point.custom && point.custom.tension ? point.custom.tension : helpers.getValueOrDefault(this.getDataset().tension, this.chart.options.elements.line.tension),
radius: point.custom && point.custom.radius ? point.custom.pointRadius : helpers.getValueAtIndexOrDefault(this.getDataset().pointRadius, index, this.chart.options.elements.point.radius),
radius: point.custom && point.custom.radius ? point.custom.radius : helpers.getValueAtIndexOrDefault(this.getDataset().pointRadius, index, this.chart.options.elements.point.radius),
backgroundColor: point.custom && point.custom.backgroundColor ? point.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().pointBackgroundColor, index, this.chart.options.elements.point.backgroundColor),
borderColor: point.custom && point.custom.borderColor ? point.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().pointBorderColor, index, this.chart.options.elements.point.borderColor),
borderWidth: point.custom && point.custom.borderWidth ? point.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().pointBorderWidth, index, this.chart.options.elements.point.borderWidth),
pointStyle: point.custom && point.custom.pointStyle ? point.custom.pointStyle : helpers.getValueAtIndexOrDefault(this.getDataset().pointStyle, index, this.chart.options.elements.point.pointStyle),
// Tooltip
hitRadius: point.custom && point.custom.hitRadius ? point.custom.hitRadius : helpers.getValueAtIndexOrDefault(this.getDataset().hitRadius, index, this.chart.options.elements.point.hitRadius),
@ -183,10 +188,10 @@
var dataset = this.chart.data.datasets[point._datasetIndex];
var index = point._index;
point._model.radius = point.custom && point.custom.radius ? point.custom.radius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius);
point._model.radius = point.custom && point.custom.hoverRadius ? point.custom.hoverRadius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius);
point._model.backgroundColor = point.custom && point.custom.hoverBackgroundColor ? point.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.color(point._model.backgroundColor).saturate(0.5).darken(0.1).rgbString());
point._model.borderColor = point.custom && point.custom.hoverBorderColor ? point.custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.color(point._model.borderColor).saturate(0.5).darken(0.1).rgbString());
point._model.borderWidth = point.custom && point.custom.hoverBorderWidth ? point.custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, point._model.borderWidth);
point._model.borderWidth = point.custom && point.custom.hoverBorderWidth ? point.custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, point._model.borderWidth);
},
removeHoverStyle: function(point) {

View File

@ -265,10 +265,22 @@
return !isNaN(parseFloat(n)) && isFinite(n);
};
helpers.max = function(array) {
return Math.max.apply(Math, array);
return array.reduce(function(max, value) {
if (!isNaN(value)) {
return Math.max(max, value);
} else {
return max;
}
}, Number.NEGATIVE_INFINITY);
};
helpers.min = function(array) {
return Math.min.apply(Math, array);
return array.reduce(function(min, value) {
if (!isNaN(value)) {
return Math.min(min, value);
} else {
return min;
}
}, Number.POSITIVE_INFINITY);
};
helpers.sign = function(x) {
if (Math.sign) {

View File

@ -43,6 +43,8 @@
if (this.options.stacked) {
var valuesPerType = {};
var hasPositiveValues = false;
var hasNegativeValues = false;
helpers.each(this.chart.data.datasets, function(dataset) {
if (valuesPerType[dataset.type] === undefined) {
@ -71,8 +73,10 @@
positiveValues[index] = 100;
} else {
if (value < 0) {
hasNegativeValues = true;
negativeValues[index] += value;
} else {
hasPositiveValues = true;
positiveValues[index] += value;
}
}
@ -81,9 +85,9 @@
}, this);
helpers.each(valuesPerType, function(valuesForType) {
var values = valuesForType.positiveValues.concat(valuesForType.negativeValues);
var values = hasPositiveValues ? hasNegativeValues ? valuesForType.positiveValues.concat(valuesForType.negativeValues) : valuesForType.positiveValues : valuesForType.negativeValues;
var minVal = helpers.min(values);
var maxVal = helpers.max(values);
var maxVal = helpers.max(values)
this.min = this.min === null ? minVal : Math.min(this.min, minVal);
this.max = this.max === null ? maxVal : Math.max(this.max, maxVal);
}, this);

View File

@ -172,7 +172,7 @@
} else {
var innerWidth = this.width - (this.paddingLeft + this.paddingRight);
pixel = this.left + (innerWidth / range * (helpers.log10(newVal) - helpers.log10(this.start)));
return pixel + this.paddingLeft;
pixel += this.paddingLeft;
}
} else {
// Bottom - top since pixels increase downard on a screen
@ -180,10 +180,11 @@
pixel = this.top + this.paddingTop;
} else {
var innerHeight = this.height - (this.paddingTop + this.paddingBottom);
return (this.bottom - this.paddingBottom) - (innerHeight / range * (helpers.log10(newVal) - helpers.log10(this.start)));
pixel = (this.bottom - this.paddingBottom) - (innerHeight / range * (helpers.log10(newVal) - helpers.log10(this.start)));
}
}
return pixel;
},
});

View File

@ -185,9 +185,6 @@
getLabelForIndex: function(index, datasetIndex) {
return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);
},
getCircumference: function() {
return ((Math.PI * 2) / this.getValueCount());
},
fit: function() {
/*
* Right, this is really confusing and there is a lot of maths going on here

View File

@ -86,17 +86,8 @@
scaleLabelMoments.push(labelMoment);
}, this);
if (this.options.time.min) {
this.firstTick = this.parseTime(this.options.time.min);
} else {
this.firstTick = moment.min.call(this, scaleLabelMoments);
}
if (this.options.time.max) {
this.lastTick = this.parseTime(this.options.time.max);
} else {
this.lastTick = moment.max.call(this, scaleLabelMoments);
}
this.firstTick = moment.min.call(this, scaleLabelMoments);
this.lastTick = moment.max.call(this, scaleLabelMoments);
} else {
this.firstTick = null;
this.lastTick = null;
@ -125,6 +116,15 @@
this.labelMoments.push(momentsForDataset);
}, this);
// Set these after we've done all the data
if (this.options.time.min) {
this.firstTick = this.parseTime(this.options.time.min);
}
if (this.options.time.max) {
this.lastTick = this.parseTime(this.options.time.max);
}
// We will modify these, so clone for later
this.firstTick = (this.firstTick || moment()).clone();
this.lastTick = (this.lastTick || moment()).clone();
@ -141,7 +141,7 @@
this.tickRange = Math.ceil(this.lastTick.diff(this.firstTick, this.tickUnit, true));
} else {
// Determine the smallest needed unit of the time
var innerWidth = this.width - (this.paddingLeft + this.paddingRight);
var innerWidth = this.isHorizontal() ? this.width - (this.paddingLeft + this.paddingRight) : this.height - (this.paddingTop + this.paddingBottom);
var labelCapacity = innerWidth / (this.options.ticks.fontSize + 10);
var buffer = this.options.time.round ? 0 : 2;
@ -156,7 +156,6 @@
// While we aren't ideal and we don't have units left
while (unitDefinitionIndex < time.units.length) {
// Can we scale this unit. If `false` we can scale infinitely
//var canScaleUnit = ;
this.unitScale = 1;
if (helpers.isArray(unitDefinition.steps) && Math.ceil(this.tickRange / labelCapacity) < helpers.max(unitDefinition.steps)) {
@ -185,8 +184,21 @@
}
}
this.firstTick.startOf(this.tickUnit);
this.lastTick.endOf(this.tickUnit);
var roundedStart;
// Only round the first tick if we have no hard minimum
if (!this.options.time.min) {
this.firstTick.startOf(this.tickUnit);
roundedStart = this.firstTick;
} else {
roundedStart = this.firstTick.clone().startOf(this.tickUnit);
}
// Only round the last tick if we have no hard maximum
if (!this.options.time.max) {
this.lastTick.endOf(this.tickUnit);
}
this.smallestLabelSeparation = this.width;
helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {
@ -200,18 +212,24 @@
this.displayFormat = this.options.time.displayFormat;
}
// first tick. will have been rounded correctly if options.time.min is not specified
this.ticks.push(this.firstTick.clone());
// For every unit in between the first and last moment, create a moment and add it to the ticks tick
for (var i = 0; i <= this.tickRange; ++i) {
for (var i = 1; i < this.tickRange; ++i) {
if (i % this.unitScale === 0) {
this.ticks.push(this.firstTick.clone().add(i, this.tickUnit));
} else if (i === this.tickRange) {
// Expand out the last one if not an exact multiple
this.tickRange = Math.ceil(this.tickRange / this.unitScale) * this.unitScale;
this.ticks.push(this.firstTick.clone().add(this.tickRange, this.tickUnit));
this.lastTick = this.ticks[this.ticks.length - 1].clone();
break;
this.ticks.push(roundedStart.clone().add(i, this.tickUnit));
}
}
// Always show the right tick
if (this.options.time.max) {
this.ticks.push(this.lastTick.clone());
} else {
this.tickRange = Math.ceil(this.tickRange / this.unitScale) * this.unitScale;
this.ticks.push(this.firstTick.clone().add(this.tickRange, this.tickUnit));
this.lastTick = this.ticks[this.ticks.length - 1].clone();
}
},
// Get tooltip label
getLabelForIndex: function(index, datasetIndex) {

View File

@ -378,6 +378,152 @@ describe('Bar controller tests', function() {
expect(bar2._model.y).toBe(37);
});
it('should update elements when the scales are stacked', function() {
var data = {
datasets: [{
data: [10, -10, 10, -10],
label: 'dataset1',
xAxisID: 'firstXScaleID',
yAxisID: 'firstYScaleID',
bar: true
}, {
data: [10, 15, 0, -4],
label: 'dataset2',
xAxisID: 'firstXScaleID',
yAxisID: 'firstYScaleID',
bar: true
}],
labels: ['label1', 'label2', 'label3', 'label4']
};
var mockContext = window.createMockContext();
var VerticalScaleConstructor = Chart.scaleService.getScaleConstructor('linear');
var verticalScaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear'));
verticalScaleConfig = Chart.helpers.scaleMerge(verticalScaleConfig, Chart.defaults.bar.scales.yAxes[0]);
verticalScaleConfig.stacked = true;
var yScale = new VerticalScaleConstructor({
ctx: mockContext,
options: verticalScaleConfig,
chart: {
data: data
},
id: 'firstYScaleID'
});
// Update ticks & set physical dimensions
var verticalSize = yScale.update(50, 200);
yScale.top = 0;
yScale.left = 0;
yScale.right = verticalSize.width;
yScale.bottom = verticalSize.height;
var HorizontalScaleConstructor = Chart.scaleService.getScaleConstructor('category');
var horizontalScaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('category'));
horizontalScaleConfig = Chart.helpers.scaleMerge(horizontalScaleConfig, Chart.defaults.bar.scales.xAxes[0]);
horizontalScaleConfig.stacked = true;
var xScale = new HorizontalScaleConstructor({
ctx: mockContext,
options: horizontalScaleConfig,
chart: {
data: data
},
id: 'firstXScaleID'
});
// Update ticks & set physical dimensions
var horizontalSize = xScale.update(200, 50);
xScale.left = yScale.right;
xScale.top = yScale.bottom;
xScale.right = horizontalSize.width + xScale.left;
xScale.bottom = horizontalSize.height + xScale.top;
var chart = {
data: data,
config: {
type: 'bar'
},
options: {
elements: {
rectangle: {
backgroundColor: 'rgb(255, 0, 0)',
borderColor: 'rgb(0, 0, 255)',
borderWidth: 2,
}
},
scales: {
xAxes: [{
id: 'firstXScaleID'
}],
yAxes: [{
id: 'firstYScaleID'
}]
}
},
scales: {
firstXScaleID: xScale,
firstYScaleID: yScale,
}
};
var controller0 = new Chart.controllers.bar(chart, 0);
var controller1 = new Chart.controllers.bar(chart, 1);
controller0.buildOrUpdateElements();
controller0.update();
controller1.buildOrUpdateElements();
controller1.update();
expect(chart.data.datasets[0].metaData[0]._model).toEqual(jasmine.objectContaining({
x: 106,
y: 60,
base: 113,
width: 30.400000000000002
}));
expect(chart.data.datasets[0].metaData[1]._model).toEqual(jasmine.objectContaining({
x: 144,
y: 167,
base: 113,
width: 30.400000000000002
}));
expect(chart.data.datasets[0].metaData[2]._model).toEqual(jasmine.objectContaining({
x: 183,
y: 60,
base: 113,
width: 30.400000000000002
}));
expect(chart.data.datasets[0].metaData[3]._model).toEqual(jasmine.objectContaining({
x: 222,
y: 167,
base: 113,
width: 30.400000000000002
}));
expect(chart.data.datasets[1].metaData[0]._model).toEqual(jasmine.objectContaining({
x: 106,
y: 6,
base: 60,
width: 30.400000000000002
}));
expect(chart.data.datasets[1].metaData[1]._model).toEqual(jasmine.objectContaining({
x: 144,
y: 33,
base: 113,
width: 30.400000000000002
}));
expect(chart.data.datasets[1].metaData[2]._model).toEqual(jasmine.objectContaining({
x: 183,
y: 60,
base: 60,
width: 30.400000000000002
}));
expect(chart.data.datasets[1].metaData[3]._model).toEqual(jasmine.objectContaining({
x: 222,
y: 189,
base: 167,
width: 30.400000000000002
}));
});
it ('should draw all bars', function() {
var data = {
datasets: [{}, {

View File

@ -0,0 +1,836 @@
// Test the bubble controller
describe('Bubble controller tests', function() {
it('Should be constructed', function() {
var chart = {
data: {
datasets: [{
xAxisID: 'myXAxis',
yAxisID: 'myYAxis',
data: []
}]
}
};
var controller = new Chart.controllers.bubble(chart, 0);
expect(controller).not.toBe(undefined);
expect(controller.index).toBe(0);
expect(chart.data.datasets[0].metaData).toEqual([]);
controller.updateIndex(1);
expect(controller.index).toBe(1);
});
it('Should use the first scale IDs if the dataset does not specify them', function() {
var chart = {
data: {
datasets: [{
data: []
}]
},
options: {
scales: {
xAxes: [{
id: 'firstXScaleID'
}],
yAxes: [{
id: 'firstYScaleID'
}]
}
}
};
var controller = new Chart.controllers.bubble(chart, 0);
expect(chart.data.datasets[0].xAxisID).toBe('firstXScaleID');
expect(chart.data.datasets[0].yAxisID).toBe('firstYScaleID');
});
it('Should create point elements for each data item during initialization', function() {
var chart = {
data: {
datasets: [{
data: [10, 15, 0, -4]
}]
},
config: {
type: 'bubble'
},
options: {
scales: {
xAxes: [{
id: 'firstXScaleID'
}],
yAxes: [{
id: 'firstYScaleID'
}]
}
}
};
var controller = new Chart.controllers.bubble(chart, 0);
expect(chart.data.datasets[0].metaData.length).toBe(4); // 4 points created
expect(chart.data.datasets[0].metaData[0] instanceof Chart.elements.Point).toBe(true);
expect(chart.data.datasets[0].metaData[1] instanceof Chart.elements.Point).toBe(true);
expect(chart.data.datasets[0].metaData[2] instanceof Chart.elements.Point).toBe(true);
expect(chart.data.datasets[0].metaData[3] instanceof Chart.elements.Point).toBe(true);
});
it('should draw all elements', function() {
var chart = {
data: {
datasets: [{
data: [10, 15, 0, -4]
}]
},
config: {
type: 'bubble'
},
options: {
showLines: true,
scales: {
xAxes: [{
id: 'firstXScaleID'
}],
yAxes: [{
id: 'firstYScaleID'
}]
}
}
};
var controller = new Chart.controllers.bubble(chart, 0);
spyOn(chart.data.datasets[0].metaData[0], 'draw');
spyOn(chart.data.datasets[0].metaData[1], 'draw');
spyOn(chart.data.datasets[0].metaData[2], 'draw');
spyOn(chart.data.datasets[0].metaData[3], 'draw');
controller.draw();
expect(chart.data.datasets[0].metaData[0].draw.calls.count()).toBe(1);
expect(chart.data.datasets[0].metaData[1].draw.calls.count()).toBe(1);
expect(chart.data.datasets[0].metaData[2].draw.calls.count()).toBe(1);
expect(chart.data.datasets[0].metaData[3].draw.calls.count()).toBe(1);
});
it('should update elements', function() {
var data = {
datasets: [{
data: [{
x: 10,
y: 10,
r: 5
}, {
x: -15,
y: -10,
r: 1
}, {
x: 0,
y: -9,
r: 2
}, {
x: -4,
y: 10,
r: 1
}],
label: 'dataset2',
xAxisID: 'firstXScaleID',
yAxisID: 'firstYScaleID'
}],
labels: ['label1', 'label2', 'label3', 'label4']
};
var mockContext = window.createMockContext();
var VerticalScaleConstructor = Chart.scaleService.getScaleConstructor('linear');
var verticalScaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear'));
verticalScaleConfig = Chart.helpers.scaleMerge(verticalScaleConfig, Chart.defaults.bubble.scales.yAxes[0]);
var yScale = new VerticalScaleConstructor({
ctx: mockContext,
options: verticalScaleConfig,
chart: {
data: data
},
id: 'firstYScaleID'
});
// Update ticks & set physical dimensions
var verticalSize = yScale.update(50, 200);
yScale.top = 0;
yScale.left = 0;
yScale.right = verticalSize.width;
yScale.bottom = verticalSize.height;
var HorizontalScaleConstructor = Chart.scaleService.getScaleConstructor('linear');
var horizontalScaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear'));
horizontalScaleConfig = Chart.helpers.scaleMerge(horizontalScaleConfig, Chart.defaults.bubble.scales.xAxes[0]);
horizontalScaleConfig.position = 'bottom';
var xScale = new HorizontalScaleConstructor({
ctx: mockContext,
options: horizontalScaleConfig,
chart: {
data: data
},
id: 'firstXScaleID'
});
// Update ticks & set physical dimensions
var horizontalSize = xScale.update(200, 50);
xScale.left = yScale.right;
xScale.top = yScale.bottom;
xScale.right = horizontalSize.width + xScale.left;
xScale.bottom = horizontalSize.height + xScale.top;
var chart = {
chartArea: {
bottom: 200,
left: xScale.left,
right: xScale.left + 200,
top: 0
},
data: data,
config: {
type: 'bubble'
},
options: {
showLines: true,
elements: {
line: {
backgroundColor: 'rgb(255, 0, 0)',
borderCapStyle: 'round',
borderColor: 'rgb(0, 255, 0)',
borderDash: [],
borderDashOffset: 0.1,
borderJoinStyle: 'bevel',
borderWidth: 1.2,
fill: true,
tension: 0.1,
},
point: {
backgroundColor: Chart.defaults.global.defaultColor,
borderWidth: 1,
borderColor: Chart.defaults.global.defaultColor,
hitRadius: 1,
hoverRadius: 4,
hoverBorderWidth: 1,
radius: 3,
pointStyle: 'circle'
}
},
scales: {
xAxes: [{
id: 'firstXScaleID'
}],
yAxes: [{
id: 'firstYScaleID'
}]
}
},
scales: {
firstXScaleID: xScale,
firstYScaleID: yScale,
}
};
var controller = new Chart.controllers.bubble(chart, 0);
controller.update();
expect(chart.data.datasets[0].metaData[0]._model).toEqual({
backgroundColor: Chart.defaults.global.defaultColor,
borderWidth: 1,
borderColor: Chart.defaults.global.defaultColor,
hitRadius: 1,
radius: 5,
skip: false,
// Point
x: 195,
y: 6,
});
expect(chart.data.datasets[0].metaData[1]._model).toEqual({
backgroundColor: Chart.defaults.global.defaultColor,
borderWidth: 1,
borderColor: Chart.defaults.global.defaultColor,
hitRadius: 1,
radius: 1,
skip: false,
// Point
x: 89,
y: 194,
});
expect(chart.data.datasets[0].metaData[2]._model).toEqual({
backgroundColor: Chart.defaults.global.defaultColor,
borderWidth: 1,
borderColor: Chart.defaults.global.defaultColor,
hitRadius: 1,
radius: 2,
skip: false,
// Point
x: 153,
y: 185,
});
expect(chart.data.datasets[0].metaData[3]._model).toEqual({
backgroundColor: Chart.defaults.global.defaultColor,
borderWidth: 1,
borderColor: Chart.defaults.global.defaultColor,
hitRadius: 1,
radius: 1,
skip: false,
// Point
x: 136,
y: 6,
});
// Use dataset level styles for lines & points
chart.data.datasets[0].backgroundColor = 'rgb(98, 98, 98)';
chart.data.datasets[0].borderColor = 'rgb(8, 8, 8)';
chart.data.datasets[0].borderWidth = 0.55;
// point styles
chart.data.datasets[0].radius = 22;
chart.data.datasets[0].hitRadius = 3.3;
controller.update();
expect(chart.data.datasets[0].metaData[0]._model).toEqual({
backgroundColor: 'rgb(98, 98, 98)',
borderWidth: 0.55,
borderColor: 'rgb(8, 8, 8)',
hitRadius: 3.3,
radius: 5,
skip: false,
// Point
x: 195,
y: 6,
});
expect(chart.data.datasets[0].metaData[1]._model).toEqual({
backgroundColor: 'rgb(98, 98, 98)',
borderWidth: 0.55,
borderColor: 'rgb(8, 8, 8)',
hitRadius: 3.3,
radius: 1,
skip: false,
// Point
x: 89,
y: 194,
});
expect(chart.data.datasets[0].metaData[2]._model).toEqual({
backgroundColor: 'rgb(98, 98, 98)',
borderWidth: 0.55,
borderColor: 'rgb(8, 8, 8)',
hitRadius: 3.3,
radius: 2,
skip: false,
// Point
x: 153,
y: 185,
});
expect(chart.data.datasets[0].metaData[3]._model).toEqual({
backgroundColor: 'rgb(98, 98, 98)',
borderWidth: 0.55,
borderColor: 'rgb(8, 8, 8)',
hitRadius: 3.3,
radius: 1,
skip: false,
// Point
x: 136,
y: 6,
});
// point styles
chart.data.datasets[0].metaData[0].custom = {
radius: 2.2,
backgroundColor: 'rgb(0, 1, 3)',
borderColor: 'rgb(4, 6, 8)',
borderWidth: 0.787,
tension: 0.15,
skip: true,
hitRadius: 5,
};
controller.update();
expect(chart.data.datasets[0].metaData[0]._model).toEqual({
backgroundColor: 'rgb(0, 1, 3)',
borderWidth: 0.787,
borderColor: 'rgb(4, 6, 8)',
hitRadius: 5,
radius: 2.2,
skip: true,
// Point
x: 195,
y: 6,
});
});
it('should handle number of data point changes in update', function() {
var data = {
datasets: [{
data: [{
x: 10,
y: 10,
r: 5
}, {
x: -15,
y: -10,
r: 1
}, {
x: 0,
y: -9,
r: 2
}, {
x: -4,
y: 10,
r: 1
}],
label: 'dataset2',
xAxisID: 'firstXScaleID',
yAxisID: 'firstYScaleID'
}],
labels: ['label1', 'label2', 'label3', 'label4']
};
var mockContext = window.createMockContext();
var VerticalScaleConstructor = Chart.scaleService.getScaleConstructor('linear');
var verticalScaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear'));
verticalScaleConfig = Chart.helpers.scaleMerge(verticalScaleConfig, Chart.defaults.bubble.scales.yAxes[0]);
var yScale = new VerticalScaleConstructor({
ctx: mockContext,
options: verticalScaleConfig,
chart: {
data: data
},
id: 'firstYScaleID'
});
// Update ticks & set physical dimensions
var verticalSize = yScale.update(50, 200);
yScale.top = 0;
yScale.left = 0;
yScale.right = verticalSize.width;
yScale.bottom = verticalSize.height;
var HorizontalScaleConstructor = Chart.scaleService.getScaleConstructor('linear');
var horizontalScaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear'));
horizontalScaleConfig = Chart.helpers.scaleMerge(horizontalScaleConfig, Chart.defaults.bubble.scales.xAxes[0]);
var xScale = new HorizontalScaleConstructor({
ctx: mockContext,
options: horizontalScaleConfig,
chart: {
data: data
},
id: 'firstXScaleID'
});
// Update ticks & set physical dimensions
var horizontalSize = xScale.update(200, 50);
xScale.left = yScale.right;
xScale.top = yScale.bottom;
xScale.right = horizontalSize.width + xScale.left;
xScale.bottom = horizontalSize.height + xScale.top;
var chart = {
chartArea: {
bottom: 200,
left: xScale.left,
right: 200,
top: 0
},
data: data,
config: {
type: 'line'
},
options: {
elements: {
line: {
backgroundColor: 'rgb(255, 0, 0)',
borderColor: 'rgb(0, 255, 0)',
borderWidth: 1.2,
},
point: {
backgroundColor: Chart.defaults.global.defaultColor,
borderWidth: 1,
borderColor: Chart.defaults.global.defaultColor,
hitRadius: 1,
hoverRadius: 4,
hoverBorderWidth: 1,
radius: 3,
}
},
scales: {
xAxes: [{
id: 'firstXScaleID'
}],
yAxes: [{
id: 'firstYScaleID'
}]
}
},
scales: {
firstXScaleID: xScale,
firstYScaleID: yScale,
}
};
var controller = new Chart.controllers.bubble(chart, 0);
chart.data.datasets[0].data = [{
x: 1,
y: 1,
r: 10
}, {
x: 10,
y: 5,
r: 2
}]; // remove 2 items
controller.buildOrUpdateElements();
controller.update();
expect(chart.data.datasets[0].metaData[0] instanceof Chart.elements.Point).toBe(true);
expect(chart.data.datasets[0].metaData[1] instanceof Chart.elements.Point).toBe(true);
chart.data.datasets[0].data = [{
x: 10,
y: 10,
r: 5
}, {
x: -15,
y: -10,
r: 1
}, {
x: 0,
y: -9,
r: 2
}, {
x: -4,
y: 10,
r: 1
}, {
x: -5,
y: 0,
r: 3
}]; // add 3 items
controller.buildOrUpdateElements();
controller.update();
expect(chart.data.datasets[0].metaData[0] instanceof Chart.elements.Point).toBe(true);
expect(chart.data.datasets[0].metaData[1] instanceof Chart.elements.Point).toBe(true);
expect(chart.data.datasets[0].metaData[2] instanceof Chart.elements.Point).toBe(true);
expect(chart.data.datasets[0].metaData[3] instanceof Chart.elements.Point).toBe(true);
expect(chart.data.datasets[0].metaData[4] instanceof Chart.elements.Point).toBe(true);
});
it('should set hover styles', function() {
var data = {
datasets: [{
data: [{
x: 10,
y: 10,
r: 5
}, {
x: -15,
y: -10,
r: 1
}, {
x: 0,
y: -9,
r: 2
}, {
x: -4,
y: 10,
r: 1
}],
label: 'dataset2',
xAxisID: 'firstXScaleID',
yAxisID: 'firstYScaleID'
}],
labels: ['label1', 'label2', 'label3', 'label4']
};
var mockContext = window.createMockContext();
var VerticalScaleConstructor = Chart.scaleService.getScaleConstructor('linear');
var verticalScaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear'));
verticalScaleConfig = Chart.helpers.scaleMerge(verticalScaleConfig, Chart.defaults.bubble.scales.yAxes[0]);
var yScale = new VerticalScaleConstructor({
ctx: mockContext,
options: verticalScaleConfig,
chart: {
data: data
},
id: 'firstYScaleID'
});
// Update ticks & set physical dimensions
var verticalSize = yScale.update(50, 200);
yScale.top = 0;
yScale.left = 0;
yScale.right = verticalSize.width;
yScale.bottom = verticalSize.height;
var HorizontalScaleConstructor = Chart.scaleService.getScaleConstructor('linear');
var horizontalScaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear'));
horizontalScaleConfig = Chart.helpers.scaleMerge(horizontalScaleConfig, Chart.defaults.bubble.scales.xAxes[0]);
var xScale = new HorizontalScaleConstructor({
ctx: mockContext,
options: horizontalScaleConfig,
chart: {
data: data
},
id: 'firstXScaleID'
});
// Update ticks & set physical dimensions
var horizontalSize = xScale.update(200, 50);
xScale.left = yScale.right;
xScale.top = yScale.bottom;
xScale.right = horizontalSize.width + xScale.left;
xScale.bottom = horizontalSize.height + xScale.top;
var chart = {
chartArea: {
bottom: 200,
left: xScale.left,
right: 200,
top: 0
},
data: data,
config: {
type: 'line'
},
options: {
elements: {
line: {
backgroundColor: 'rgb(255, 0, 0)',
borderColor: 'rgb(0, 255, 0)',
borderWidth: 1.2,
},
point: {
backgroundColor: 'rgb(255, 255, 0)',
borderWidth: 1,
borderColor: 'rgb(255, 255, 255)',
hitRadius: 1,
hoverRadius: 4,
hoverBorderWidth: 1,
radius: 3,
}
},
scales: {
xAxes: [{
id: 'firstXScaleID'
}],
yAxes: [{
id: 'firstYScaleID'
}]
}
},
scales: {
firstXScaleID: xScale,
firstYScaleID: yScale,
}
};
var controller = new Chart.controllers.bubble(chart, 0);
controller.update();
var point = chart.data.datasets[0].metaData[0];
controller.setHoverStyle(point);
expect(point._model.backgroundColor).toBe('rgb(229, 230, 0)');
expect(point._model.borderColor).toBe('rgb(230, 230, 230)');
expect(point._model.borderWidth).toBe(1);
expect(point._model.radius).toBe(9);
// Can set hover style per dataset
chart.data.datasets[0].hoverRadius = 3.3;
chart.data.datasets[0].hoverBackgroundColor = 'rgb(77, 79, 81)';
chart.data.datasets[0].hoverBorderColor = 'rgb(123, 125, 127)';
chart.data.datasets[0].hoverBorderWidth = 2.1;
controller.setHoverStyle(point);
expect(point._model.backgroundColor).toBe('rgb(77, 79, 81)');
expect(point._model.borderColor).toBe('rgb(123, 125, 127)');
expect(point._model.borderWidth).toBe(2.1);
expect(point._model.radius).toBe(8.3);
// Custom style
point.custom = {
hoverRadius: 4.4,
hoverBorderWidth: 5.5,
hoverBackgroundColor: 'rgb(0, 0, 0)',
hoverBorderColor: 'rgb(10, 10, 10)'
};
controller.setHoverStyle(point);
expect(point._model.backgroundColor).toBe('rgb(0, 0, 0)');
expect(point._model.borderColor).toBe('rgb(10, 10, 10)');
expect(point._model.borderWidth).toBe(5.5);
expect(point._model.radius).toBe(4.4);
});
it('should remove hover styles', function() {
var data = {
datasets: [{
data: [{
x: 10,
y: 10,
r: 5
}, {
x: -15,
y: -10,
r: 1
}, {
x: 0,
y: -9,
r: 2
}, {
x: -4,
y: 10,
r: 1
}],
label: 'dataset2',
xAxisID: 'firstXScaleID',
yAxisID: 'firstYScaleID'
}],
labels: ['label1', 'label2', 'label3', 'label4']
};
var mockContext = window.createMockContext();
var VerticalScaleConstructor = Chart.scaleService.getScaleConstructor('linear');
var verticalScaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear'));
verticalScaleConfig = Chart.helpers.scaleMerge(verticalScaleConfig, Chart.defaults.bubble.scales.yAxes[0]);
var yScale = new VerticalScaleConstructor({
ctx: mockContext,
options: verticalScaleConfig,
chart: {
data: data
},
id: 'firstYScaleID'
});
// Update ticks & set physical dimensions
var verticalSize = yScale.update(50, 200);
yScale.top = 0;
yScale.left = 0;
yScale.right = verticalSize.width;
yScale.bottom = verticalSize.height;
var HorizontalScaleConstructor = Chart.scaleService.getScaleConstructor('linear');
var horizontalScaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear'));
horizontalScaleConfig = Chart.helpers.scaleMerge(horizontalScaleConfig, Chart.defaults.bubble.scales.xAxes[0]);
var xScale = new HorizontalScaleConstructor({
ctx: mockContext,
options: horizontalScaleConfig,
chart: {
data: data
},
id: 'firstXScaleID'
});
// Update ticks & set physical dimensions
var horizontalSize = xScale.update(200, 50);
xScale.left = yScale.right;
xScale.top = yScale.bottom;
xScale.right = horizontalSize.width + xScale.left;
xScale.bottom = horizontalSize.height + xScale.top;
var chart = {
chartArea: {
bottom: 200,
left: xScale.left,
right: 200,
top: 0
},
data: data,
config: {
type: 'line'
},
options: {
elements: {
line: {
backgroundColor: 'rgb(255, 0, 0)',
borderColor: 'rgb(0, 255, 0)',
borderWidth: 1.2,
fill: true,
tension: 0.1,
},
point: {
backgroundColor: 'rgb(255, 255, 0)',
borderWidth: 1,
borderColor: 'rgb(255, 255, 255)',
hitRadius: 1,
hoverRadius: 4,
hoverBorderWidth: 1,
radius: 3,
}
},
scales: {
xAxes: [{
id: 'firstXScaleID'
}],
yAxes: [{
id: 'firstYScaleID'
}]
}
},
scales: {
firstXScaleID: xScale,
firstYScaleID: yScale,
}
};
var controller = new Chart.controllers.bubble(chart, 0);
controller.update();
var point = chart.data.datasets[0].metaData[0];
chart.options.elements.point.backgroundColor = 'rgb(45, 46, 47)';
chart.options.elements.point.borderColor = 'rgb(50, 51, 52)';
chart.options.elements.point.borderWidth = 10.1;
chart.options.elements.point.radius = 1.01;
controller.removeHoverStyle(point);
expect(point._model.backgroundColor).toBe('rgb(45, 46, 47)');
expect(point._model.borderColor).toBe('rgb(50, 51, 52)');
expect(point._model.borderWidth).toBe(10.1);
expect(point._model.radius).toBe(5);
// Can set hover style per dataset
chart.data.datasets[0].radius = 3.3;
chart.data.datasets[0].backgroundColor = 'rgb(77, 79, 81)';
chart.data.datasets[0].borderColor = 'rgb(123, 125, 127)';
chart.data.datasets[0].borderWidth = 2.1;
controller.removeHoverStyle(point);
expect(point._model.backgroundColor).toBe('rgb(77, 79, 81)');
expect(point._model.borderColor).toBe('rgb(123, 125, 127)');
expect(point._model.borderWidth).toBe(2.1);
expect(point._model.radius).toBe(5);
// Custom style
point.custom = {
radius: 4.4,
borderWidth: 5.5,
backgroundColor: 'rgb(0, 0, 0)',
borderColor: 'rgb(10, 10, 10)'
};
controller.removeHoverStyle(point);
expect(point._model.backgroundColor).toBe('rgb(0, 0, 0)');
expect(point._model.borderColor).toBe('rgb(10, 10, 10)');
expect(point._model.borderWidth).toBe(5.5);
expect(point._model.radius).toBe(4.4);
});
});

View File

@ -544,6 +544,381 @@ describe('Line controller tests', function() {
});
});
it('should update elements when the y scale is stacked', function() {
var data = {
datasets: [{
data: [10, 15, -4, -4],
label: 'dataset2',
xAxisID: 'firstXScaleID',
yAxisID: 'firstYScaleID',
type: 'line'
}, {
data: [20, 20, 30, -30],
label: 'dataset1',
xAxisID: 'firstXScaleID',
yAxisID: 'firstYScaleID',
type: 'line'
}],
labels: ['label1', 'label2', 'label3', 'label4']
};
var mockContext = window.createMockContext();
var VerticalScaleConstructor = Chart.scaleService.getScaleConstructor('linear');
var verticalScaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear'));
verticalScaleConfig = Chart.helpers.scaleMerge(verticalScaleConfig, Chart.defaults.line.scales.yAxes[0]);
verticalScaleConfig.stacked = true;
var yScale = new VerticalScaleConstructor({
ctx: mockContext,
options: verticalScaleConfig,
chart: {
data: data
},
id: 'firstYScaleID'
});
// Update ticks & set physical dimensions
var verticalSize = yScale.update(50, 200);
yScale.top = 0;
yScale.left = 0;
yScale.right = verticalSize.width;
yScale.bottom = verticalSize.height;
var HorizontalScaleConstructor = Chart.scaleService.getScaleConstructor('category');
var horizontalScaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('category'));
horizontalScaleConfig = Chart.helpers.scaleMerge(horizontalScaleConfig, Chart.defaults.line.scales.xAxes[0]);
var xScale = new HorizontalScaleConstructor({
ctx: mockContext,
options: horizontalScaleConfig,
chart: {
data: data
},
id: 'firstXScaleID'
});
// Update ticks & set physical dimensions
var horizontalSize = xScale.update(200, 50);
xScale.left = yScale.right;
xScale.top = yScale.bottom;
xScale.right = horizontalSize.width + xScale.left;
xScale.bottom = horizontalSize.height + xScale.top;
var chart = {
chartArea: {
bottom: 200,
left: xScale.left,
right: xScale.left + 200,
top: 0
},
data: data,
config: {
type: 'line'
},
options: {
showLines: true,
elements: {
line: {
backgroundColor: 'rgb(255, 0, 0)',
borderCapStyle: 'round',
borderColor: 'rgb(0, 255, 0)',
borderDash: [],
borderDashOffset: 0.1,
borderJoinStyle: 'bevel',
borderWidth: 1.2,
fill: true,
tension: 0,
},
point: {
backgroundColor: Chart.defaults.global.defaultColor,
borderWidth: 1,
borderColor: Chart.defaults.global.defaultColor,
hitRadius: 1,
hoverRadius: 4,
hoverBorderWidth: 1,
radius: 3,
pointStyle: 'circle'
}
},
scales: {
xAxes: [{
id: 'firstXScaleID'
}],
yAxes: [{
id: 'firstYScaleID'
}]
}
},
scales: {
firstXScaleID: xScale,
firstYScaleID: yScale,
}
};
var controller = new Chart.controllers.line(chart, 0);
controller.update();
// Line element
expect(chart.data.datasets[0].metaDataset._model).toEqual(jasmine.objectContaining({
scaleTop: 0,
scaleBottom: 200,
scaleZero: 100,
}));
expect(chart.data.datasets[0].metaData[0]._model).toEqual(jasmine.objectContaining({
// Point
x: 91,
y: 30,
}));
expect(chart.data.datasets[0].metaData[1]._model).toEqual(jasmine.objectContaining({
// Point
x: 141,
y: 18,
}));
expect(chart.data.datasets[0].metaData[2]._model).toEqual(jasmine.objectContaining({
// Point
x: 192,
y: 109,
}));
expect(chart.data.datasets[0].metaData[3]._model).toEqual(jasmine.objectContaining({
// Point
x: 242,
y: 180,
}));
});
it('should find the correct scale zero when the data is all positive', function() {
var data = {
datasets: [{
data: [10, 15, 20, 20],
label: 'dataset2',
xAxisID: 'firstXScaleID',
yAxisID: 'firstYScaleID',
type: 'line'
}],
labels: ['label1', 'label2', 'label3', 'label4']
};
var mockContext = window.createMockContext();
var VerticalScaleConstructor = Chart.scaleService.getScaleConstructor('linear');
var verticalScaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear'));
verticalScaleConfig = Chart.helpers.scaleMerge(verticalScaleConfig, Chart.defaults.line.scales.yAxes[0]);
verticalScaleConfig.stacked = true;
var yScale = new VerticalScaleConstructor({
ctx: mockContext,
options: verticalScaleConfig,
chart: {
data: data
},
id: 'firstYScaleID'
});
// Update ticks & set physical dimensions
var verticalSize = yScale.update(50, 200);
yScale.top = 0;
yScale.left = 0;
yScale.right = verticalSize.width;
yScale.bottom = verticalSize.height;
var HorizontalScaleConstructor = Chart.scaleService.getScaleConstructor('category');
var horizontalScaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('category'));
horizontalScaleConfig = Chart.helpers.scaleMerge(horizontalScaleConfig, Chart.defaults.line.scales.xAxes[0]);
var xScale = new HorizontalScaleConstructor({
ctx: mockContext,
options: horizontalScaleConfig,
chart: {
data: data
},
id: 'firstXScaleID'
});
// Update ticks & set physical dimensions
var horizontalSize = xScale.update(200, 50);
xScale.left = yScale.right;
xScale.top = yScale.bottom;
xScale.right = horizontalSize.width + xScale.left;
xScale.bottom = horizontalSize.height + xScale.top;
var chart = {
chartArea: {
bottom: 200,
left: xScale.left,
right: xScale.left + 200,
top: 0
},
data: data,
config: {
type: 'line'
},
options: {
showLines: true,
elements: {
line: {
backgroundColor: 'rgb(255, 0, 0)',
borderCapStyle: 'round',
borderColor: 'rgb(0, 255, 0)',
borderDash: [],
borderDashOffset: 0.1,
borderJoinStyle: 'bevel',
borderWidth: 1.2,
fill: true,
tension: 0,
},
point: {
backgroundColor: Chart.defaults.global.defaultColor,
borderWidth: 1,
borderColor: Chart.defaults.global.defaultColor,
hitRadius: 1,
hoverRadius: 4,
hoverBorderWidth: 1,
radius: 3,
pointStyle: 'circle'
}
},
scales: {
xAxes: [{
id: 'firstXScaleID'
}],
yAxes: [{
id: 'firstYScaleID'
}]
}
},
scales: {
firstXScaleID: xScale,
firstYScaleID: yScale,
}
};
var controller = new Chart.controllers.line(chart, 0);
controller.update();
// Line element
expect(chart.data.datasets[0].metaDataset._model).toEqual(jasmine.objectContaining({
scaleTop: 0,
scaleBottom: 200,
scaleZero: 194, // yScale.min is the 0 point
}));
});
it('should find the correct scale zero when the data is all negative', function() {
var data = {
datasets: [{
data: [-10, -15, -20, -20],
label: 'dataset2',
xAxisID: 'firstXScaleID',
yAxisID: 'firstYScaleID',
type: 'line'
}],
labels: ['label1', 'label2', 'label3', 'label4']
};
var mockContext = window.createMockContext();
var VerticalScaleConstructor = Chart.scaleService.getScaleConstructor('linear');
var verticalScaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear'));
verticalScaleConfig = Chart.helpers.scaleMerge(verticalScaleConfig, Chart.defaults.line.scales.yAxes[0]);
verticalScaleConfig.stacked = true;
var yScale = new VerticalScaleConstructor({
ctx: mockContext,
options: verticalScaleConfig,
chart: {
data: data
},
id: 'firstYScaleID'
});
// Update ticks & set physical dimensions
var verticalSize = yScale.update(50, 200);
yScale.top = 0;
yScale.left = 0;
yScale.right = verticalSize.width;
yScale.bottom = verticalSize.height;
var HorizontalScaleConstructor = Chart.scaleService.getScaleConstructor('category');
var horizontalScaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('category'));
horizontalScaleConfig = Chart.helpers.scaleMerge(horizontalScaleConfig, Chart.defaults.line.scales.xAxes[0]);
var xScale = new HorizontalScaleConstructor({
ctx: mockContext,
options: horizontalScaleConfig,
chart: {
data: data
},
id: 'firstXScaleID'
});
// Update ticks & set physical dimensions
var horizontalSize = xScale.update(200, 50);
xScale.left = yScale.right;
xScale.top = yScale.bottom;
xScale.right = horizontalSize.width + xScale.left;
xScale.bottom = horizontalSize.height + xScale.top;
var chart = {
chartArea: {
bottom: 200,
left: xScale.left,
right: xScale.left + 200,
top: 0
},
data: data,
config: {
type: 'line'
},
options: {
showLines: true,
elements: {
line: {
backgroundColor: 'rgb(255, 0, 0)',
borderCapStyle: 'round',
borderColor: 'rgb(0, 255, 0)',
borderDash: [],
borderDashOffset: 0.1,
borderJoinStyle: 'bevel',
borderWidth: 1.2,
fill: true,
tension: 0,
},
point: {
backgroundColor: Chart.defaults.global.defaultColor,
borderWidth: 1,
borderColor: Chart.defaults.global.defaultColor,
hitRadius: 1,
hoverRadius: 4,
hoverBorderWidth: 1,
radius: 3,
pointStyle: 'circle'
}
},
scales: {
xAxes: [{
id: 'firstXScaleID'
}],
yAxes: [{
id: 'firstYScaleID'
}]
}
},
scales: {
firstXScaleID: xScale,
firstYScaleID: yScale,
}
};
var controller = new Chart.controllers.line(chart, 0);
controller.update();
// Line element
expect(chart.data.datasets[0].metaDataset._model).toEqual(jasmine.objectContaining({
scaleTop: 0,
scaleBottom: 200,
scaleZero: 6, // yScale.max is the zero point
}));
});
it ('should fall back to the line styles for points', function() {
var data = {
datasets: [{

View File

@ -0,0 +1,508 @@
// Test the polar area controller
describe('Polar area controller tests', function() {
it('Should be constructed', function() {
var chart = {
data: {
datasets: [{
data: []
}]
}
};
var controller = new Chart.controllers.polarArea(chart, 0);
expect(controller).not.toBe(undefined);
expect(controller.index).toBe(0);
expect(chart.data.datasets[0].metaData).toEqual([]);
controller.updateIndex(1);
expect(controller.index).toBe(1);
});
it('Should create arc elements for each data item during initialization', function() {
var chart = {
data: {
datasets: [{
data: [10, 15, 0, -4]
}]
},
config: {
type: 'polarArea'
},
options: {
}
};
var controller = new Chart.controllers.polarArea(chart, 0);
expect(chart.data.datasets[0].metaData.length).toBe(4); // 4 arcs created
expect(chart.data.datasets[0].metaData[0] instanceof Chart.elements.Arc).toBe(true);
expect(chart.data.datasets[0].metaData[1] instanceof Chart.elements.Arc).toBe(true);
expect(chart.data.datasets[0].metaData[2] instanceof Chart.elements.Arc).toBe(true);
expect(chart.data.datasets[0].metaData[3] instanceof Chart.elements.Arc).toBe(true);
});
it('should draw all elements', function() {
var chart = {
data: {
datasets: [{
data: [10, 15, 0, -4]
}]
},
config: {
type: 'polarArea'
},
options: {
}
};
var controller = new Chart.controllers.polarArea(chart, 0);
spyOn(chart.data.datasets[0].metaData[0], 'draw');
spyOn(chart.data.datasets[0].metaData[1], 'draw');
spyOn(chart.data.datasets[0].metaData[2], 'draw');
spyOn(chart.data.datasets[0].metaData[3], 'draw');
controller.draw();
expect(chart.data.datasets[0].metaData[0].draw.calls.count()).toBe(1);
expect(chart.data.datasets[0].metaData[1].draw.calls.count()).toBe(1);
expect(chart.data.datasets[0].metaData[2].draw.calls.count()).toBe(1);
expect(chart.data.datasets[0].metaData[3].draw.calls.count()).toBe(1);
});
it('should update elements', function() {
var data = {
datasets: [{
data: [10, 15, 0, -4],
label: 'dataset2',
}],
labels: ['label1', 'label2', 'label3', 'label4']
};
var mockContext = window.createMockContext();
var ScaleConstructor = Chart.scaleService.getScaleConstructor('radialLinear');
var scaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('radialLinear'));
scaleConfig = Chart.helpers.scaleMerge(scaleConfig, Chart.defaults.polarArea.scale);
var scale = new ScaleConstructor({
ctx: mockContext,
options: scaleConfig,
chart: {
data: data
},
});
// Update ticks & set physical dimensions
scale.update(300, 300);
scale.top = 0;
scale.left = 0;
scale.right = 300;
scale.bottom = 300;
var chart = {
chartArea: {
bottom: 300,
left: 0,
right: 300,
top: 0
},
data: data,
config: {
type: 'line'
},
options: {
showLines: true,
elements: {
arc: {
backgroundColor: 'rgb(255, 0, 0)',
borderColor: 'rgb(0, 255, 0)',
borderWidth: 1.2,
},
},
},
scale: scale
};
var controller = new Chart.controllers.polarArea(chart, 0);
controller.update();
expect(chart.data.datasets[0].metaData[0]._model).toEqual({
x: 150,
y: 150,
innerRadius: 0,
outerRadius: 59.5,
startAngle: -0.5 * Math.PI,
endAngle: 0,
backgroundColor: 'rgb(255, 0, 0)',
borderColor: 'rgb(0, 255, 0)',
borderWidth: 1.2,
label: 'label1'
});
expect(chart.data.datasets[0].metaData[1]._model).toEqual({
x: 150,
y: 150,
innerRadius: 0,
outerRadius: 80.75,
startAngle: 0,
endAngle: 0.5 * Math.PI,
backgroundColor: 'rgb(255, 0, 0)',
borderColor: 'rgb(0, 255, 0)',
borderWidth: 1.2,
label: 'label2'
});
expect(chart.data.datasets[0].metaData[2]._model).toEqual({
x: 150,
y: 150,
innerRadius: 0,
outerRadius: 17,
startAngle: 0.5 * Math.PI,
endAngle: Math.PI,
backgroundColor: 'rgb(255, 0, 0)',
borderColor: 'rgb(0, 255, 0)',
borderWidth: 1.2,
label: 'label3'
});
expect(chart.data.datasets[0].metaData[3]._model).toEqual({
x: 150,
y: 150,
innerRadius: 0,
outerRadius: 0,
startAngle: Math.PI,
endAngle: 1.5 * Math.PI,
backgroundColor: 'rgb(255, 0, 0)',
borderColor: 'rgb(0, 255, 0)',
borderWidth: 1.2,
label: 'label4'
});
// arc styles
chart.data.datasets[0].backgroundColor = 'rgb(128, 129, 130)';
chart.data.datasets[0].borderColor = 'rgb(56, 57, 58)';
chart.data.datasets[0].borderWidth = 1.123;
controller.update();
expect(chart.data.datasets[0].metaData[0]._model).toEqual({
x: 150,
y: 150,
innerRadius: 0,
outerRadius: 59.5,
startAngle: -0.5 * Math.PI,
endAngle: 0,
backgroundColor: 'rgb(128, 129, 130)',
borderWidth: 1.123,
borderColor: 'rgb(56, 57, 58)',
label: 'label1'
});
expect(chart.data.datasets[0].metaData[1]._model).toEqual({
x: 150,
y: 150,
innerRadius: 0,
outerRadius: 80.75,
startAngle: 0,
endAngle: 0.5 * Math.PI,
backgroundColor: 'rgb(128, 129, 130)',
borderWidth: 1.123,
borderColor: 'rgb(56, 57, 58)',
label: 'label2'
});
expect(chart.data.datasets[0].metaData[2]._model).toEqual({
x: 150,
y: 150,
innerRadius: 0,
outerRadius: 17,
startAngle: 0.5 * Math.PI,
endAngle: Math.PI,
backgroundColor: 'rgb(128, 129, 130)',
borderWidth: 1.123,
borderColor: 'rgb(56, 57, 58)',
label: 'label3'
});
expect(chart.data.datasets[0].metaData[3]._model).toEqual({
x: 150,
y: 150,
innerRadius: 0,
outerRadius: 0,
startAngle: Math.PI,
endAngle: 1.5 * Math.PI,
backgroundColor: 'rgb(128, 129, 130)',
borderWidth: 1.123,
borderColor: 'rgb(56, 57, 58)',
label: 'label4'
});
// arc styles
chart.data.datasets[0].metaData[0].custom = {
backgroundColor: 'rgb(0, 1, 3)',
borderColor: 'rgb(4, 6, 8)',
borderWidth: 0.787,
};
controller.update();
expect(chart.data.datasets[0].metaData[0]._model).toEqual({
x: 150,
y: 150,
innerRadius: 0,
outerRadius: 59.5,
startAngle: -0.5 * Math.PI,
endAngle: 0,
backgroundColor: 'rgb(0, 1, 3)',
borderWidth: 0.787,
borderColor: 'rgb(4, 6, 8)',
label: 'label1'
});
});
it('should handle number of data point changes in update', function() {
var data = {
datasets: [{
data: [10, 15, 0, -4],
label: 'dataset2',
}],
labels: ['label1', 'label2', 'label3', 'label4']
};
var mockContext = window.createMockContext();
var ScaleConstructor = Chart.scaleService.getScaleConstructor('radialLinear');
var scaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('radialLinear'));
scaleConfig = Chart.helpers.scaleMerge(scaleConfig, Chart.defaults.polarArea.scale);
var scale = new ScaleConstructor({
ctx: mockContext,
options: scaleConfig,
chart: {
data: data
},
});
// Update ticks & set physical dimensions
scale.update(300, 300);
scale.top = 0;
scale.left = 0;
scale.right = 300;
scale.bottom = 300;
var chart = {
chartArea: {
bottom: 300,
left: 0,
right: 300,
top: 0
},
data: data,
config: {
type: 'line'
},
options: {
showLines: true,
elements: {
arc: {
backgroundColor: 'rgb(255, 0, 0)',
borderColor: 'rgb(0, 255, 0)',
borderWidth: 1.2,
},
},
},
scale: scale
};
var controller = new Chart.controllers.polarArea(chart, 0);
controller.update();
expect(chart.data.datasets[0].metaData.length).toBe(4);
chart.data.datasets[0].data = [1, 2]; // remove 2 items
controller.buildOrUpdateElements();
controller.update();
expect(chart.data.datasets[0].metaData.length).toBe(2);
expect(chart.data.datasets[0].metaData[0] instanceof Chart.elements.Arc).toBe(true);
expect(chart.data.datasets[0].metaData[1] instanceof Chart.elements.Arc).toBe(true);
chart.data.datasets[0].data = [1, 2, 3, 4, 5]; // add 3 items
controller.buildOrUpdateElements();
controller.update();
expect(chart.data.datasets[0].metaData.length).toBe(5);
expect(chart.data.datasets[0].metaData[0] instanceof Chart.elements.Arc).toBe(true);
expect(chart.data.datasets[0].metaData[1] instanceof Chart.elements.Arc).toBe(true);
expect(chart.data.datasets[0].metaData[2] instanceof Chart.elements.Arc).toBe(true);
expect(chart.data.datasets[0].metaData[3] instanceof Chart.elements.Arc).toBe(true);
expect(chart.data.datasets[0].metaData[4] instanceof Chart.elements.Arc).toBe(true);
});
it('should set arc hover styles', function() {
var data = {
datasets: [{
data: [10, 15, 0, -4],
label: 'dataset2',
}],
labels: ['label1', 'label2', 'label3', 'label4']
};
var mockContext = window.createMockContext();
var ScaleConstructor = Chart.scaleService.getScaleConstructor('radialLinear');
var scaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('radialLinear'));
scaleConfig = Chart.helpers.scaleMerge(scaleConfig, Chart.defaults.polarArea.scale);
var scale = new ScaleConstructor({
ctx: mockContext,
options: scaleConfig,
chart: {
data: data
},
});
// Update ticks & set physical dimensions
scale.update(300, 300);
scale.top = 0;
scale.left = 0;
scale.right = 300;
scale.bottom = 300;
var chart = {
chartArea: {
bottom: 300,
left: 0,
right: 300,
top: 0
},
data: data,
config: {
type: 'line'
},
options: {
showLines: true,
elements: {
arc: {
backgroundColor: 'rgb(255, 0, 0)',
borderColor: 'rgb(0, 255, 0)',
borderWidth: 1.2,
},
},
},
scale: scale
};
var controller = new Chart.controllers.polarArea(chart, 0);
controller.update();
var arc = chart.data.datasets[0].metaData[0];
controller.setHoverStyle(arc);
expect(arc._model.backgroundColor).toBe('rgb(230, 0, 0)');
expect(arc._model.borderColor).toBe('rgb(0, 230, 0)');
expect(arc._model.borderWidth).toBe(1.2);
// Can set hover style per dataset
chart.data.datasets[0].hoverBackgroundColor = 'rgb(77, 79, 81)';
chart.data.datasets[0].hoverBorderColor = 'rgb(123, 125, 127)';
chart.data.datasets[0].hoverBorderWidth = 2.1;
controller.setHoverStyle(arc);
expect(arc._model.backgroundColor).toBe('rgb(77, 79, 81)');
expect(arc._model.borderColor).toBe('rgb(123, 125, 127)');
expect(arc._model.borderWidth).toBe(2.1);
// Custom style
arc.custom = {
hoverBorderWidth: 5.5,
hoverBackgroundColor: 'rgb(0, 0, 0)',
hoverBorderColor: 'rgb(10, 10, 10)'
};
controller.setHoverStyle(arc);
expect(arc._model.backgroundColor).toBe('rgb(0, 0, 0)');
expect(arc._model.borderColor).toBe('rgb(10, 10, 10)');
expect(arc._model.borderWidth).toBe(5.5);
});
it('should remove hover styles', function() {
var data = {
datasets: [{
data: [10, 15, 0, -4],
label: 'dataset2',
}],
labels: ['label1', 'label2', 'label3', 'label4']
};
var mockContext = window.createMockContext();
var ScaleConstructor = Chart.scaleService.getScaleConstructor('radialLinear');
var scaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('radialLinear'));
scaleConfig = Chart.helpers.scaleMerge(scaleConfig, Chart.defaults.polarArea.scale);
var scale = new ScaleConstructor({
ctx: mockContext,
options: scaleConfig,
chart: {
data: data
},
});
// Update ticks & set physical dimensions
scale.update(300, 300);
scale.top = 0;
scale.left = 0;
scale.right = 300;
scale.bottom = 300;
var chart = {
chartArea: {
bottom: 300,
left: 0,
right: 300,
top: 0
},
data: data,
config: {
type: 'line'
},
options: {
showLines: true,
elements: {
arc: {
backgroundColor: 'rgb(255, 0, 0)',
borderColor: 'rgb(0, 255, 0)',
borderWidth: 1.2,
},
},
},
scale: scale
};
var controller = new Chart.controllers.polarArea(chart, 0);
controller.update();
var arc = chart.data.datasets[0].metaData[0];
chart.options.elements.arc.backgroundColor = 'rgb(45, 46, 47)';
chart.options.elements.arc.borderColor = 'rgb(50, 51, 52)';
chart.options.elements.arc.borderWidth = 10.1;
controller.removeHoverStyle(arc);
expect(arc._model.backgroundColor).toBe('rgb(45, 46, 47)');
expect(arc._model.borderColor).toBe('rgb(50, 51, 52)');
expect(arc._model.borderWidth).toBe(10.1);
// Can set hover style per dataset
chart.data.datasets[0].backgroundColor = 'rgb(77, 79, 81)';
chart.data.datasets[0].borderColor = 'rgb(123, 125, 127)';
chart.data.datasets[0].borderWidth = 2.1;
controller.removeHoverStyle(arc);
expect(arc._model.backgroundColor).toBe('rgb(77, 79, 81)');
expect(arc._model.borderColor).toBe('rgb(123, 125, 127)');
expect(arc._model.borderWidth).toBe(2.1);
// Custom style
arc.custom = {
borderWidth: 5.5,
backgroundColor: 'rgb(0, 0, 0)',
borderColor: 'rgb(10, 10, 10)'
};
controller.removeHoverStyle(arc);
expect(arc._model.backgroundColor).toBe('rgb(0, 0, 0)');
expect(arc._model.borderColor).toBe('rgb(10, 10, 10)');
expect(arc._model.borderWidth).toBe(5.5);
});
});

View File

@ -0,0 +1,747 @@
// Test the polar area controller
describe('Radar controller tests', function() {
it('Should be constructed', function() {
var chart = {
data: {
datasets: [{
data: []
}]
}
};
var controller = new Chart.controllers.radar(chart, 0);
expect(controller).not.toBe(undefined);
expect(controller.index).toBe(0);
expect(chart.data.datasets[0].metaData).toEqual([]);
controller.updateIndex(1);
expect(controller.index).toBe(1);
});
it('Should create arc elements for each data item during initialization', function() {
var chart = {
data: {
datasets: [{
data: [10, 15, 0, -4]
}],
labels: ['label1', 'label2', 'label3', 'label4']
},
config: {
type: 'radar'
},
options: {
}
};
var controller = new Chart.controllers.radar(chart, 0);
// Line element
expect(chart.data.datasets[0].metaDataset instanceof Chart.elements.Line).toBe(true);
expect(chart.data.datasets[0].metaData.length).toBe(4); // 4 points created
expect(chart.data.datasets[0].metaData[0] instanceof Chart.elements.Point).toBe(true);
expect(chart.data.datasets[0].metaData[1] instanceof Chart.elements.Point).toBe(true);
expect(chart.data.datasets[0].metaData[2] instanceof Chart.elements.Point).toBe(true);
expect(chart.data.datasets[0].metaData[3] instanceof Chart.elements.Point).toBe(true);
});
it('should draw all elements', function() {
var chart = {
data: {
datasets: [{
data: [10, 15, 0, -4]
}]
},
config: {
type: 'radar'
},
options: {
}
};
var controller = new Chart.controllers.radar(chart, 0);
spyOn(chart.data.datasets[0].metaDataset, 'draw');
spyOn(chart.data.datasets[0].metaData[0], 'draw');
spyOn(chart.data.datasets[0].metaData[1], 'draw');
spyOn(chart.data.datasets[0].metaData[2], 'draw');
spyOn(chart.data.datasets[0].metaData[3], 'draw');
controller.draw();
expect(chart.data.datasets[0].metaDataset.draw.calls.count()).toBe(1);
expect(chart.data.datasets[0].metaData[0].draw.calls.count()).toBe(1);
expect(chart.data.datasets[0].metaData[1].draw.calls.count()).toBe(1);
expect(chart.data.datasets[0].metaData[2].draw.calls.count()).toBe(1);
expect(chart.data.datasets[0].metaData[3].draw.calls.count()).toBe(1);
});
it('should update elements', function() {
var data = {
datasets: [{
data: [10, 15, 0, -4],
label: 'dataset2'
}],
labels: ['label1', 'label2', 'label3', 'label4']
};
var mockContext = window.createMockContext();
var ScaleConstructor = Chart.scaleService.getScaleConstructor('radialLinear');
var scaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('radialLinear'));
scaleConfig = Chart.helpers.scaleMerge(scaleConfig, Chart.defaults.radar.scale);
var scale = new ScaleConstructor({
ctx: mockContext,
options: scaleConfig,
chart: {
data: data
},
});
// Update ticks & set physical dimensions
scale.top = 0;
scale.left = 0;
scale.right = 300;
scale.bottom = 300;
scale.update(300, 300);
var chart = {
chartArea: {
bottom: 300,
left: 0,
right: 300,
top: 0
},
data: data,
config: {
type: 'radar'
},
options: {
showLines: true,
elements: {
line: {
backgroundColor: 'rgb(255, 0, 0)',
borderCapStyle: 'round',
borderColor: 'rgb(0, 255, 0)',
borderDash: [],
borderDashOffset: 0.1,
borderJoinStyle: 'bevel',
borderWidth: 1.2,
fill: true,
tension: 0.1,
},
point: {
backgroundColor: Chart.defaults.global.defaultColor,
borderWidth: 1,
borderColor: Chart.defaults.global.defaultColor,
hitRadius: 1,
hoverRadius: 4,
hoverBorderWidth: 1,
radius: 3,
pointStyle: 'circle'
}
}
},
scale: scale
};
var controller = new Chart.controllers.radar(chart, 0);
controller.update();
// Line element
expect(chart.data.datasets[0].metaDataset._model).toEqual({
backgroundColor: 'rgb(255, 0, 0)',
borderCapStyle: 'round',
borderColor: 'rgb(0, 255, 0)',
borderDash: [],
borderDashOffset: 0.1,
borderJoinStyle: 'bevel',
borderWidth: 1.2,
fill: true,
tension: 0.1,
scaleTop: 0,
scaleBottom: 300,
scaleZero: {
x: 150,
y: 133
},
});
expect(chart.data.datasets[0].metaData[0]._model).toEqual({
backgroundColor: Chart.defaults.global.defaultColor,
borderWidth: 1,
borderColor: Chart.defaults.global.defaultColor,
hitRadius: 1,
radius: 3,
pointStyle: 'circle',
skip: false,
tension: 0.1,
// Point
x: 150,
y: 91,
// Control points
controlPointPreviousX: 146.99829997808834,
controlPointPreviousY: 91,
controlPointNextX: 155.09829997808833,
controlPointNextY: 91,
});
expect(chart.data.datasets[0].metaData[1]._model).toEqual({
backgroundColor: Chart.defaults.global.defaultColor,
borderWidth: 1,
borderColor: Chart.defaults.global.defaultColor,
hitRadius: 1,
radius: 3,
pointStyle: 'circle',
skip: false,
tension: 0.1,
// Point
x: 231,
y: 150,
// Control points
controlPointPreviousX: 231,
controlPointPreviousY: 145.8377025234528,
controlPointNextX: 231,
controlPointNextY: 153.4377025234528,
});
expect(chart.data.datasets[0].metaData[2]._model).toEqual({
backgroundColor: Chart.defaults.global.defaultColor,
borderWidth: 1,
borderColor: Chart.defaults.global.defaultColor,
hitRadius: 1,
radius: 3,
pointStyle: 'circle',
skip: false,
tension: 0.1,
// Point
x: 150,
y: 167,
// Control points
controlPointPreviousX: 156.7197526476963,
controlPointPreviousY: 167,
controlPointNextX: 148.61975264769632,
controlPointNextY: 167,
});
expect(chart.data.datasets[0].metaData[3]._model).toEqual({
backgroundColor: Chart.defaults.global.defaultColor,
borderWidth: 1,
borderColor: Chart.defaults.global.defaultColor,
hitRadius: 1,
radius: 3,
pointStyle: 'circle',
skip: false,
tension: 0.1,
// Point
x: 150,
y: 150,
// Control points
controlPointPreviousX: 150,
controlPointPreviousY: 151.7,
controlPointNextX: 150,
controlPointNextY: 144.1,
});
// Use dataset level styles for lines & points
chart.data.datasets[0].tension = 0;
chart.data.datasets[0].backgroundColor = 'rgb(98, 98, 98)';
chart.data.datasets[0].borderColor = 'rgb(8, 8, 8)';
chart.data.datasets[0].borderWidth = 0.55;
chart.data.datasets[0].borderCapStyle = 'butt';
chart.data.datasets[0].borderDash = [2, 3];
chart.data.datasets[0].borderDashOffset = 7;
chart.data.datasets[0].borderJoinStyle = 'miter';
chart.data.datasets[0].fill = false;
// point styles
chart.data.datasets[0].pointRadius = 22;
chart.data.datasets[0].hitRadius = 3.3;
chart.data.datasets[0].pointBackgroundColor = 'rgb(128, 129, 130)';
chart.data.datasets[0].pointBorderColor = 'rgb(56, 57, 58)';
chart.data.datasets[0].pointBorderWidth = 1.123;
controller.update();
expect(chart.data.datasets[0].metaDataset._model).toEqual({
backgroundColor: 'rgb(98, 98, 98)',
borderCapStyle: 'butt',
borderColor: 'rgb(8, 8, 8)',
borderDash: [2, 3],
borderDashOffset: 7,
borderJoinStyle: 'miter',
borderWidth: 0.55,
fill: false,
tension: 0,
scaleTop: 0,
scaleBottom: 300,
scaleZero: {
x: 150,
y: 133
}
});
expect(chart.data.datasets[0].metaData[0]._model).toEqual({
backgroundColor: 'rgb(128, 129, 130)',
borderWidth: 1.123,
borderColor: 'rgb(56, 57, 58)',
hitRadius: 3.3,
radius: 22,
pointStyle: 'circle',
skip: false,
tension: 0,
// Point
x: 150,
y: 91,
// Control points
controlPointPreviousX: 150,
controlPointPreviousY: 91,
controlPointNextX: 150,
controlPointNextY: 91,
});
expect(chart.data.datasets[0].metaData[1]._model).toEqual({
backgroundColor: 'rgb(128, 129, 130)',
borderWidth: 1.123,
borderColor: 'rgb(56, 57, 58)',
hitRadius: 3.3,
radius: 22,
pointStyle: 'circle',
skip: false,
tension: 0,
// Point
x: 231,
y: 150,
// Control points
controlPointPreviousX: 231,
controlPointPreviousY: 150,
controlPointNextX: 231,
controlPointNextY: 150,
});
expect(chart.data.datasets[0].metaData[2]._model).toEqual({
backgroundColor: 'rgb(128, 129, 130)',
borderWidth: 1.123,
borderColor: 'rgb(56, 57, 58)',
hitRadius: 3.3,
radius: 22,
pointStyle: 'circle',
skip: false,
tension: 0,
// Point
x: 150,
y: 167,
// Control points
controlPointPreviousX: 150,
controlPointPreviousY: 167,
controlPointNextX: 150,
controlPointNextY: 167,
});
expect(chart.data.datasets[0].metaData[3]._model).toEqual({
backgroundColor: 'rgb(128, 129, 130)',
borderWidth: 1.123,
borderColor: 'rgb(56, 57, 58)',
hitRadius: 3.3,
radius: 22,
pointStyle: 'circle',
skip: false,
tension: 0,
// Point
x: 150,
y: 150,
// Control points
controlPointPreviousX: 150,
controlPointPreviousY: 150,
controlPointNextX: 150,
controlPointNextY: 150,
});
// Use custom styles for lines & first point
chart.data.datasets[0].metaDataset.custom = {
tension: 0.25,
backgroundColor: 'rgb(55, 55, 54)',
borderColor: 'rgb(8, 7, 6)',
borderWidth: 0.3,
borderCapStyle: 'square',
borderDash: [4, 3],
borderDashOffset: 4.4,
borderJoinStyle: 'round',
fill: true,
};
// point styles
chart.data.datasets[0].metaData[0].custom = {
radius: 2.2,
backgroundColor: 'rgb(0, 1, 3)',
borderColor: 'rgb(4, 6, 8)',
borderWidth: 0.787,
tension: 0.15,
skip: true,
hitRadius: 5,
};
controller.update();
expect(chart.data.datasets[0].metaDataset._model).toEqual({
backgroundColor: 'rgb(55, 55, 54)',
borderCapStyle: 'square',
borderColor: 'rgb(8, 7, 6)',
borderDash: [4, 3],
borderDashOffset: 4.4,
borderJoinStyle: 'round',
borderWidth: 0.3,
fill: true,
tension: 0.25,
scaleTop: 0,
scaleBottom: 300,
scaleZero: {
x: 150,
y: 133
},
});
expect(chart.data.datasets[0].metaData[0]._model).toEqual({
backgroundColor: 'rgb(0, 1, 3)',
borderWidth: 0.787,
borderColor: 'rgb(4, 6, 8)',
hitRadius: 5,
radius: 2.2,
pointStyle: 'circle',
skip: true,
tension: 0.15,
// Point
x: 150,
y: 91,
// Control points
controlPointPreviousX: 145.4974499671325,
controlPointPreviousY: 91,
controlPointNextX: 157.6474499671325,
controlPointNextY: 91,
});
});
it('should handle number of data point changes in update', function() {
var data = {
datasets: [{
data: [10, 15, 0, -4],
label: 'dataset2',
}],
labels: ['label1', 'label2', 'label3', 'label4']
};
var mockContext = window.createMockContext();
var ScaleConstructor = Chart.scaleService.getScaleConstructor('radialLinear');
var scaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('radialLinear'));
scaleConfig = Chart.helpers.scaleMerge(scaleConfig, Chart.defaults.radar.scale);
var scale = new ScaleConstructor({
ctx: mockContext,
options: scaleConfig,
chart: {
data: data
},
});
// Update ticks & set physical dimensions
scale.top = 0;
scale.left = 0;
scale.right = 300;
scale.bottom = 300;
scale.update(300, 300);
var chart = {
chartArea: {
bottom: 300,
left: 0,
right: 300,
top: 0
},
data: data,
config: {
type: 'radar'
},
options: {
elements: {
line: {
backgroundColor: 'rgb(255, 0, 0)',
borderCapStyle: 'round',
borderColor: 'rgb(0, 255, 0)',
borderDash: [],
borderDashOffset: 0.1,
borderJoinStyle: 'bevel',
borderWidth: 1.2,
fill: true,
tension: 0.1,
},
point: {
backgroundColor: Chart.defaults.global.defaultColor,
borderWidth: 1,
borderColor: Chart.defaults.global.defaultColor,
hitRadius: 1,
hoverRadius: 4,
hoverBorderWidth: 1,
radius: 3,
}
},
},
scale: scale
};
var controller = new Chart.controllers.radar(chart, 0);
controller.update();
expect(chart.data.datasets[0].metaData.length).toBe(4);
chart.data.datasets[0].data = [1, 2]; // remove 2 items
controller.buildOrUpdateElements();
controller.update();
expect(chart.data.datasets[0].metaData.length).toBe(2);
expect(chart.data.datasets[0].metaData[0] instanceof Chart.elements.Point).toBe(true);
expect(chart.data.datasets[0].metaData[1] instanceof Chart.elements.Point).toBe(true);
chart.data.datasets[0].data = [1, 2, 3, 4, 5]; // add 3 items
controller.buildOrUpdateElements();
controller.update();
expect(chart.data.datasets[0].metaData.length).toBe(5);
expect(chart.data.datasets[0].metaData[0] instanceof Chart.elements.Point).toBe(true);
expect(chart.data.datasets[0].metaData[1] instanceof Chart.elements.Point).toBe(true);
expect(chart.data.datasets[0].metaData[2] instanceof Chart.elements.Point).toBe(true);
expect(chart.data.datasets[0].metaData[3] instanceof Chart.elements.Point).toBe(true);
expect(chart.data.datasets[0].metaData[4] instanceof Chart.elements.Point).toBe(true);
});
it('should set point hover styles', function() {
var data = {
datasets: [{
data: [10, 15, 0, -4],
label: 'dataset2',
}],
labels: ['label1', 'label2', 'label3', 'label4']
};
var mockContext = window.createMockContext();
var ScaleConstructor = Chart.scaleService.getScaleConstructor('radialLinear');
var scaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('radialLinear'));
scaleConfig = Chart.helpers.scaleMerge(scaleConfig, Chart.defaults.radar.scale);
var scale = new ScaleConstructor({
ctx: mockContext,
options: scaleConfig,
chart: {
data: data
},
});
// Update ticks & set physical dimensions
scale.top = 0;
scale.left = 0;
scale.right = 300;
scale.bottom = 300;
scale.update(300, 300);
var chart = {
chartArea: {
bottom: 300,
left: 0,
right: 300,
top: 0
},
data: data,
config: {
type: 'radar'
},
options: {
elements: {
line: {
backgroundColor: 'rgb(255, 0, 0)',
borderCapStyle: 'round',
borderColor: 'rgb(0, 255, 0)',
borderDash: [],
borderDashOffset: 0.1,
borderJoinStyle: 'bevel',
borderWidth: 1.2,
fill: true,
skipNull: true,
tension: 0.1,
},
point: {
backgroundColor: 'rgb(255, 255, 0)',
borderWidth: 1,
borderColor: 'rgb(255, 255, 255)',
hitRadius: 1,
hoverRadius: 4,
hoverBorderWidth: 1,
radius: 3,
}
}
},
scale: scale
};
var controller = new Chart.controllers.radar(chart, 0);
controller.update();
var point = chart.data.datasets[0].metaData[0];
controller.setHoverStyle(point);
expect(point._model.backgroundColor).toBe('rgb(229, 230, 0)');
expect(point._model.borderColor).toBe('rgb(230, 230, 230)');
expect(point._model.borderWidth).toBe(1);
expect(point._model.radius).toBe(4);
// Can set hover style per dataset
chart.data.datasets[0].pointHoverRadius = 3.3;
chart.data.datasets[0].pointHoverBackgroundColor = 'rgb(77, 79, 81)';
chart.data.datasets[0].pointHoverBorderColor = 'rgb(123, 125, 127)';
chart.data.datasets[0].pointHoverBorderWidth = 2.1;
controller.setHoverStyle(point);
expect(point._model.backgroundColor).toBe('rgb(77, 79, 81)');
expect(point._model.borderColor).toBe('rgb(123, 125, 127)');
expect(point._model.borderWidth).toBe(2.1);
expect(point._model.radius).toBe(3.3);
// Custom style
point.custom = {
hoverRadius: 4.4,
hoverBorderWidth: 5.5,
hoverBackgroundColor: 'rgb(0, 0, 0)',
hoverBorderColor: 'rgb(10, 10, 10)'
};
controller.setHoverStyle(point);
expect(point._model.backgroundColor).toBe('rgb(0, 0, 0)');
expect(point._model.borderColor).toBe('rgb(10, 10, 10)');
expect(point._model.borderWidth).toBe(5.5);
expect(point._model.radius).toBe(4.4);
});
it('should remove hover styles', function() {
var data = {
datasets: [{
data: [10, 15, 0, -4],
label: 'dataset2',
}],
labels: ['label1', 'label2', 'label3', 'label4']
};
var mockContext = window.createMockContext();
var ScaleConstructor = Chart.scaleService.getScaleConstructor('radialLinear');
var scaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('radialLinear'));
scaleConfig = Chart.helpers.scaleMerge(scaleConfig, Chart.defaults.radar.scale);
var scale = new ScaleConstructor({
ctx: mockContext,
options: scaleConfig,
chart: {
data: data
},
});
// Update ticks & set physical dimensions
scale.top = 0;
scale.left = 0;
scale.right = 300;
scale.bottom = 300;
scale.update(300, 300);
var chart = {
chartArea: {
bottom: 300,
left: 0,
right: 300,
top: 0
},
data: data,
config: {
type: 'radar'
},
options: {
elements: {
line: {
backgroundColor: 'rgb(255, 0, 0)',
borderCapStyle: 'round',
borderColor: 'rgb(0, 255, 0)',
borderDash: [],
borderDashOffset: 0.1,
borderJoinStyle: 'bevel',
borderWidth: 1.2,
fill: true,
skipNull: true,
tension: 0.1,
},
point: {
backgroundColor: 'rgb(255, 255, 0)',
borderWidth: 1,
borderColor: 'rgb(255, 255, 255)',
hitRadius: 1,
hoverRadius: 4,
hoverBorderWidth: 1,
radius: 3,
}
}
},
scale: scale
};
var controller = new Chart.controllers.radar(chart, 0);
controller.update();
var point = chart.data.datasets[0].metaData[0];
chart.options.elements.point.backgroundColor = 'rgb(45, 46, 47)';
chart.options.elements.point.borderColor = 'rgb(50, 51, 52)';
chart.options.elements.point.borderWidth = 10.1;
chart.options.elements.point.radius = 1.01;
controller.removeHoverStyle(point);
expect(point._model.backgroundColor).toBe('rgb(45, 46, 47)');
expect(point._model.borderColor).toBe('rgb(50, 51, 52)');
expect(point._model.borderWidth).toBe(10.1);
expect(point._model.radius).toBe(1.01);
// Can set hover style per dataset
chart.data.datasets[0].radius = 3.3;
chart.data.datasets[0].pointBackgroundColor = 'rgb(77, 79, 81)';
chart.data.datasets[0].pointBorderColor = 'rgb(123, 125, 127)';
chart.data.datasets[0].pointBorderWidth = 2.1;
controller.removeHoverStyle(point);
expect(point._model.backgroundColor).toBe('rgb(77, 79, 81)');
expect(point._model.borderColor).toBe('rgb(123, 125, 127)');
expect(point._model.borderWidth).toBe(2.1);
expect(point._model.radius).toBe(3.3);
// Custom style
point.custom = {
radius: 4.4,
borderWidth: 5.5,
backgroundColor: 'rgb(0, 0, 0)',
borderColor: 'rgb(10, 10, 10)'
};
controller.removeHoverStyle(point);
expect(point._model.backgroundColor).toBe('rgb(0, 0, 0)');
expect(point._model.borderColor).toBe('rgb(10, 10, 10)');
expect(point._model.borderWidth).toBe(5.5);
expect(point._model.radius).toBe(4.4);
});
});

257
test/defaultConfig.tests.js Normal file
View File

@ -0,0 +1,257 @@
// Test the bubble chart default config
describe("Test the bubble chart default config", function() {
it('should reutrn correct tooltip strings', function() {
var config = Chart.defaults.bubble;
// Title is always blank
expect(config.tooltips.callbacks.title()).toBe('');
// Item label
var data = {
datasets: [{
label: 'My dataset',
data: [{
x: 10,
y: 12,
r: 5
}]
}]
};
var tooltipItem = {
datasetIndex: 0,
index: 0
};
expect(config.tooltips.callbacks.label(tooltipItem, data)).toBe('My dataset: (10, 12, 5)');
});
});
describe('Test the doughnut chart default config', function() {
it('should return correct tooltip strings', function() {
var config = Chart.defaults.doughnut;
// Title is always blank
expect(config.tooltips.callbacks.title()).toBe('');
// Item label
var data = {
labels: ['label1', 'label2', 'label3'],
datasets: [{
data: [10, 20, 30],
}]
};
var tooltipItem = {
datasetIndex: 0,
index: 1
};
expect(config.tooltips.callbacks.label(tooltipItem, data)).toBe('label2: 20');
});
it('should return the correct html legend', function() {
var config = Chart.defaults.doughnut;
var chart = {
id: 'mychart',
data: {
labels: ['label1', 'label2'],
datasets: [{
data: [10, 20],
backgroundColor: ['red', 'green']
}]
}
};
var expectedLegend = '<ul class="mychart-legend"><li><span style="background-color:red">label1</span></li><li><span style="background-color:green">label2</span></li></ul>';
expect(config.legendCallback(chart)).toBe(expectedLegend);
});
it('should return correct legend label objects', function() {
var config = Chart.defaults.doughnut;
var data = {
labels: ['label1', 'label2', 'label3'],
datasets: [{
data: [10, 20, NaN],
backgroundColor: ['red', 'green', 'blue']
}]
};
var expected = [{
text: 'label1',
fillStyle: 'red',
hidden: false,
index: 0
}, {
text: 'label2',
fillStyle: 'green',
hidden: false,
index: 1
}, {
text: 'label3',
fillStyle: 'blue',
hidden: true,
index: 2
}];
expect(config.legend.labels.generateLabels(data)).toEqual(expected);
});
it('should hide the correct arc when a legend item is clicked', function() {
var config = Chart.defaults.doughnut;
var legendItem = {
text: 'label1',
fillStyle: 'red',
hidden: false,
index: 0
};
var chart = {
data: {
labels: ['label1', 'label2', 'label3'],
datasets: [{
data: [10, 20, NaN],
backgroundColor: ['red', 'green', 'blue']
}]
},
update: function() {}
};
spyOn(chart, 'update');
var scope = {
chart: chart
};
config.legend.onClick.call(scope, null, legendItem);
expect(chart.data.datasets[0].metaHiddenData).toEqual([10]);
expect(chart.data.datasets[0].data).toEqual([NaN, 20, NaN]);
expect(chart.update).toHaveBeenCalled();
config.legend.onClick.call(scope, null, legendItem);
expect(chart.data.datasets[0].data).toEqual([10, 20, NaN]);
// Should not toggle index 2 since there was never data for it
legendItem.index = 2;
config.legend.onClick.call(scope, null, legendItem);
expect(chart.data.datasets[0].data).toEqual([10, 20, NaN]);
});
});
describe('Test the polar area chart default config', function() {
it('should return correct tooltip strings', function() {
var config = Chart.defaults.polarArea;
// Title is always blank
expect(config.tooltips.callbacks.title()).toBe('');
// Item label
var data = {
labels: ['label1', 'label2', 'label3'],
datasets: [{
data: [10, 20, 30],
}]
};
var tooltipItem = {
datasetIndex: 0,
index: 1,
yLabel: 20
};
expect(config.tooltips.callbacks.label(tooltipItem, data)).toBe('label2: 20');
});
it('should return the correct html legend', function() {
var config = Chart.defaults.polarArea;
var chart = {
id: 'mychart',
data: {
labels: ['label1', 'label2'],
datasets: [{
data: [10, 20],
backgroundColor: ['red', 'green']
}]
}
};
var expectedLegend = '<ul class="mychart-legend"><li><span style="background-color:red">label1</span></li><li><span style="background-color:green">label2</span></li></ul>';
expect(config.legendCallback(chart)).toBe(expectedLegend);
});
it('should return correct legend label objects', function() {
var config = Chart.defaults.polarArea;
var data = {
labels: ['label1', 'label2', 'label3'],
datasets: [{
data: [10, 20, NaN],
backgroundColor: ['red', 'green', 'blue']
}]
};
var expected = [{
text: 'label1',
fillStyle: 'red',
hidden: false,
index: 0
}, {
text: 'label2',
fillStyle: 'green',
hidden: false,
index: 1
}, {
text: 'label3',
fillStyle: 'blue',
hidden: true,
index: 2
}];
expect(config.legend.labels.generateLabels(data)).toEqual(expected);
});
it('should hide the correct arc when a legend item is clicked', function() {
var config = Chart.defaults.polarArea;
var legendItem = {
text: 'label1',
fillStyle: 'red',
hidden: false,
index: 0
};
var chart = {
data: {
labels: ['label1', 'label2', 'label3'],
datasets: [{
data: [10, 20, NaN],
backgroundColor: ['red', 'green', 'blue']
}]
},
update: function() {}
};
spyOn(chart, 'update');
var scope = {
chart: chart
};
config.legend.onClick.call(scope, null, legendItem);
expect(chart.data.datasets[0].metaHiddenData).toEqual([10]);
expect(chart.data.datasets[0].data).toEqual([NaN, 20, NaN]);
expect(chart.update).toHaveBeenCalled();
config.legend.onClick.call(scope, null, legendItem);
expect(chart.data.datasets[0].data).toEqual([10, 20, NaN]);
// Should not toggle index 2 since there was never data for it
legendItem.index = 2;
config.legend.onClick.call(scope, null, legendItem);
expect(chart.data.datasets[0].data).toEqual([10, 20, NaN]);
});
});

View File

@ -78,6 +78,33 @@ describe('Category scale tests', function() {
expect(scale.ticks).toEqual(mockData.labels);
});
it ('should get the correct label for the index', function() {
var scaleID = 'myScale';
var mockData = {
datasets: [{
yAxisID: scaleID,
data: [10, 5, 0, 25, 78]
}],
labels: ['tick1', 'tick2', 'tick3', 'tick4', 'tick5']
};
var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('category'));
var Constructor = Chart.scaleService.getScaleConstructor('category');
var scale = new Constructor({
ctx: {},
options: config,
chart: {
data: mockData
},
id: scaleID
});
scale.buildTicks();
expect(scale.getLabelForIndex(1)).toBe('tick2');
});
it ('Should get the correct pixel for a value when horizontal', function() {
var scaleID = 'myScale';

View File

@ -169,6 +169,48 @@ describe('Linear Scale', function() {
expect(scale.max).toBe(80);
});
it('Should correctly determine the max & min data values ignoring data that is NaN', function() {
var scaleID = 'myScale';
var mockData = {
datasets: [{
yAxisID: scaleID,
data: [null, 90, NaN, undefined, 45, 30]
}]
};
var options = Chart.scaleService.getScaleDefaults('linear');
var Constructor = Chart.scaleService.getScaleConstructor('linear');
var scale = new Constructor({
ctx: {},
options: options, // use default config for scale
chart: {
data: mockData
},
id: scaleID
});
expect(scale).not.toEqual(undefined); // must construct
expect(scale.min).toBe(undefined); // not yet set
expect(scale.max).toBe(undefined);
// Set arbitrary width and height for now
scale.width = 50;
scale.height = 400;
scale.determineDataLimits();
scale.buildTicks();
expect(scale.min).toBe(30);
expect(scale.max).toBe(90);
// Scale is now stacked
options.stacked = true;
scale.determineDataLimits();
expect(scale.min).toBe(30);
expect(scale.max).toBe(90);
});
it('Should correctly determine the max & min for scatter data', function() {
var scaleID = 'myScale';
@ -233,6 +275,50 @@ describe('Linear Scale', function() {
expect(horizontalScale.max).toBe(100);
});
it('Should correctly get the label for the given index', function() {
var scaleID = 'myScale';
var mockData = {
datasets: [{
xAxisID: scaleID, // for the horizontal scale
yAxisID: scaleID,
data: [{
x: 10,
y: 100
}, {
x: -10,
y: 0
}, {
x: 0,
y: 0
}, {
x: 99,
y: 7
}]
}]
};
var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear'));
var Constructor = Chart.scaleService.getScaleConstructor('linear');
var scale = new Constructor({
ctx: {},
options: config,
chart: {
data: mockData
},
id: scaleID
});
// Set arbitrary width and height for now
scale.width = 50;
scale.height = 400;
scale.determineDataLimits();
scale.buildTicks();
expect(scale.getLabelForIndex(3, 0)).toBe(7)
});
it('Should correctly determine the min and max data values when stacked mode is turned on', function() {
var scaleID = 'myScale';

View File

@ -159,6 +159,45 @@ describe('Logarithmic Scale tests', function() {
expect(scale.max).toBe(5000);
});
it('Should correctly determine the max & min data values when there is NaN data', function() {
var scaleID = 'myScale';
var mockData = {
datasets: [{
yAxisID: scaleID,
data: [undefined, 10, null, 5, 5000, NaN, 78, 450]
}]
};
var mockContext = window.createMockContext();
var options = Chart.scaleService.getScaleDefaults('logarithmic');
var Constructor = Chart.scaleService.getScaleConstructor('logarithmic');
var scale = new Constructor({
ctx: mockContext,
options: options, // use default config for scale
chart: {
data: mockData
},
id: scaleID
});
expect(scale).not.toEqual(undefined); // must construct
expect(scale.min).toBe(undefined); // not yet set
expect(scale.max).toBe(undefined);
scale.update(400, 400);
expect(scale.min).toBe(1);
expect(scale.max).toBe(5000);
// Turn on stacked mode since it uses it's own
options.stacked = true;
scale.update(400, 400);
expect(scale.min).toBe(1);
expect(scale.max).toBe(5000);
});
it('Should correctly determine the max & min for scatter data', function() {
var scaleID = 'myScale';
@ -495,6 +534,38 @@ describe('Logarithmic Scale tests', function() {
expect(scale.ticks).toEqual(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16']);
});
it('Should correctly get the correct label for a data item', function() {
var scaleID = 'myScale';
var mockData = {
datasets: [{
yAxisID: scaleID,
data: [10, 5, 5000, 78, 450]
}, {
yAxisID: 'second scale',
data: [1, 1000, 10, 100],
}, {
yAxisID: scaleID,
data: [150]
}]
};
var mockContext = window.createMockContext();
var Constructor = Chart.scaleService.getScaleConstructor('logarithmic');
var scale = new Constructor({
ctx: mockContext,
options: Chart.scaleService.getScaleDefaults('logarithmic'), // use default config for scale
chart: {
data: mockData,
},
id: scaleID
});
scale.update(400, 400);
expect(scale.getLabelForIndex(0, 2)).toBe(150);
});
it('Should get the correct pixel value for a point', function() {
var scaleID = 'myScale';
@ -533,6 +604,7 @@ describe('Logarithmic Scale tests', function() {
expect(verticalScale.getPixelForValue(80, 0, 0)).toBe(5); // top + paddingTop
expect(verticalScale.getPixelForValue(1, 0, 0)).toBe(105); // bottom - paddingBottom
expect(verticalScale.getPixelForValue(10, 0, 0)).toBeCloseTo(52.4, 1e-4); // halfway
expect(verticalScale.getPixelForValue(0, 0, 0)).toBe(5); // 0 is invalid. force it on top
var horizontalConfig = Chart.helpers.clone(config);
horizontalConfig.position = 'bottom';
@ -560,5 +632,6 @@ describe('Logarithmic Scale tests', function() {
expect(horizontalScale.getPixelForValue(80, 0, 0)).toBe(105); // right - paddingRight
expect(horizontalScale.getPixelForValue(1, 0, 0)).toBe(5); // left + paddingLeft
expect(horizontalScale.getPixelForValue(10, 0, 0)).toBeCloseTo(57.5, 1e-4); // halfway
expect(horizontalScale.getPixelForValue(0, 0, 0)).toBe(5); // 0 is invalid, put it on the left.
});
});

View File

@ -163,6 +163,33 @@ describe('Test the radial linear scale', function() {
expect(scale.max).toBe(200);
});
it('Should correctly determine the max & min data values when there is NaN data', function() {
var scaleID = 'myScale';
var mockData = {
datasets: [{
yAxisID: scaleID,
data: [50, 60, NaN, 70, null, undefined]
}],
labels: ['lablel1', 'label2', 'label3', 'label4', 'label5', 'label6']
};
var mockContext = window.createMockContext();
var Constructor = Chart.scaleService.getScaleConstructor('radialLinear');
var scale = new Constructor({
ctx: mockContext,
options: Chart.scaleService.getScaleDefaults('radialLinear'), // use default config for scale
chart: {
data: mockData
},
id: scaleID,
});
scale.update(200, 300);
expect(scale.min).toBe(50);
expect(scale.max).toBe(70);
});
it('Should ensure that the scale has a max and min that are not equal', function() {
var scaleID = 'myScale';
@ -427,6 +454,38 @@ describe('Test the radial linear scale', function() {
expect(scale.yCenter).toBe(155);
});
it('should correctly get the label for a given data index', function() {
var scaleID = 'myScale';
var mockData = {
datasets: [{
yAxisID: scaleID,
data: [10, 5, 0, 25, 78]
}],
labels: ['point1', 'point2', 'point3', 'point4', 'point5'] // used in radar charts which use the same scales
};
var mockContext = window.createMockContext();
var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('radialLinear'));
var Constructor = Chart.scaleService.getScaleConstructor('radialLinear');
var scale = new Constructor({
ctx: mockContext,
options: config,
chart: {
data: mockData
},
id: scaleID,
});
scale.left = 10;
scale.right = 210;
scale.top = 5;
scale.bottom = 305;
scale.update(200, 300);
expect(scale.getLabelForIndex(1, 0)).toBe(5);
});
it('should get the correct distance from the center point', function() {
var scaleID = 'myScale';

View File

@ -125,6 +125,57 @@ describe('Time scale tests', function() {
expect(scale.ticks).toEqual(['Jan 1, 2015', 'Jan 3, 2015', 'Jan 5, 2015', 'Jan 7, 2015', 'Jan 9, 2015', 'Jan 11, 2015', 'Jan 13, 2015']);
});
it('should build ticks when the data is xy points', function() {
// Helper to build date objects
function newDateFromRef(days) {
return moment('01/01/2015 12:00', 'DD/MM/YYYY HH:mm').add(days, 'd').toDate();
}
var scaleID = 'myScale';
var mockData = {
datasets: [{
data: [{
x: newDateFromRef(0),
y: 1
}, {
x: newDateFromRef(1),
y: 10
}, {
x: newDateFromRef(2),
y: 0
}, {
x: newDateFromRef(4),
y: 5
}, {
x: newDateFromRef(6),
y: 77
}, {
x: newDateFromRef(7),
y: 9
}, {
x: newDateFromRef(9),
y: 5
}], // days
}]
};
var mockContext = window.createMockContext();
var Constructor = Chart.scaleService.getScaleConstructor('time');
var scale = new Constructor({
ctx: mockContext,
options: Chart.scaleService.getScaleDefaults('time'), // use default config for scale
chart: {
data: mockData
},
id: scaleID
});
scale.update(400, 50);
// Counts down because the lines are drawn top to bottom
expect(scale.ticks).toEqual(['Jan 1, 2015', 'Jan 3, 2015', 'Jan 5, 2015', 'Jan 7, 2015', 'Jan 9, 2015', 'Jan 11, 2015', 'Jan 13, 2015']);
});
it('should build ticks using the config unit', function() {
var scaleID = 'myScale';
@ -133,7 +184,7 @@ describe('Time scale tests', function() {
};
var mockContext = window.createMockContext();
var config = Chart.scaleService.getScaleDefaults('time');
var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('time'));
config.time.unit = 'hour';
var Constructor = Chart.scaleService.getScaleConstructor('time');
var scale = new Constructor({
@ -158,7 +209,7 @@ describe('Time scale tests', function() {
};
var mockContext = window.createMockContext();
var config = Chart.scaleService.getScaleDefaults('time');
var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('time'));
config.time.unit = 'week';
config.time.round = 'week';
var Constructor = Chart.scaleService.getScaleConstructor('time');
@ -176,6 +227,31 @@ describe('Time scale tests', function() {
expect(scale.ticks).toEqual(['Dec 28, 2014', 'Jan 4, 2015', 'Jan 11, 2015', 'Jan 18, 2015', 'Jan 25, 2015', 'Feb 1, 2015', 'Feb 8, 2015', 'Feb 15, 2015']);
});
it('Should use the min and max options', function() {
var scaleID = 'myScale';
var mockData = {
labels: ["2015-01-01T20:00:00", "2015-01-02T20:00:00", "2015-01-03T20:00:00"], // days
};
var mockContext = window.createMockContext();
var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('time'));
config.time.min = "2015-01-01T04:00:00";
config.time.max = "2015-01-05T06:00:00"
var Constructor = Chart.scaleService.getScaleConstructor('time');
var scale = new Constructor({
ctx: mockContext,
options: config, // use default config for scale
chart: {
data: mockData
},
id: scaleID
});
scale.update(400, 50);
expect(scale.ticks).toEqual(['Jan 1, 4AM', 'Jan 1, 4PM', 'Jan 2, 4AM', 'Jan 2, 4PM', 'Jan 3, 4AM', 'Jan 3, 4PM', 'Jan 4, 4AM', 'Jan 4, 4PM', 'Jan 5, 4AM', 'Jan 5, 6AM']);
});
it('should get the correct pixel for a value', function() {
var scaleID = 'myScale';
@ -197,20 +273,19 @@ describe('Time scale tests', function() {
id: scaleID
});
//scale.buildTicks();
scale.update(400, 50);
expect(scale.width).toBe(400);
expect(scale.height).toBe(28);
expect(scale.height).toBe(50);
scale.left = 0;
scale.right = 400;
scale.top = 10;
scale.bottom = 38;
expect(scale.getPixelForValue('', 0, 0)).toBe(63);
expect(scale.getPixelForValue('', 6, 0)).toBe(342);
expect(scale.getPixelForValue('', 0, 0)).toBe(128);
expect(scale.getPixelForValue('', 6, 0)).toBe(380);
var verticalScaleConfig = Chart.scaleService.getScaleDefaults('time');
var verticalScaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('time'));
verticalScaleConfig.position = "left";
var verticalScale = new Constructor({
@ -229,7 +304,42 @@ describe('Time scale tests', function() {
verticalScale.right = 50;
verticalScale.bottom = 400;
expect(verticalScale.getPixelForValue('', 0, 0)).toBe(6);
expect(verticalScale.getPixelForValue('', 6, 0)).toBe(394);
expect(verticalScale.getPixelForValue('', 0, 0)).toBe(38);
expect(verticalScale.getPixelForValue('', 6, 0)).toBe(375);
});
it('should get the correct label for a data value', function() {
var scaleID = 'myScale';
var mockData = {
labels: ["2015-01-01T20:00:00", "2015-01-02T21:00:00", "2015-01-03T22:00:00", "2015-01-05T23:00:00", "2015-01-07T03:00", "2015-01-08T10:00", "2015-01-10T12:00"], // days
datasets: [{
data: [],
}]
};
var mockContext = window.createMockContext();
var Constructor = Chart.scaleService.getScaleConstructor('time');
var scale = new Constructor({
ctx: mockContext,
options: Chart.scaleService.getScaleDefaults('time'), // use default config for scale
chart: {
data: mockData
},
id: scaleID
});
scale.update(400, 50);
expect(scale.width).toBe(400);
expect(scale.height).toBe(50);
scale.left = 0;
scale.right = 400;
scale.top = 10;
scale.bottom = 38;
expect(scale.getLabelForIndex(0, 0)).toBe('2015-01-01T20:00:00');
expect(scale.getLabelForIndex(6, 0)).toBe('2015-01-10T12:00');
});
});