From 8e9de00529b00a3811b09d969a4b7bc87ca8be16 Mon Sep 17 00:00:00 2001 From: Evert Timberg Date: Sun, 30 Aug 2015 14:56:48 -0400 Subject: [PATCH] Doughnut controller tests --- src/controllers/controller.doughnut.js | 28 +- test/controller.doughnut.tests.js | 429 +++++++++++++++++++++++++ 2 files changed, 448 insertions(+), 9 deletions(-) create mode 100644 test/controller.doughnut.tests.js diff --git a/src/controllers/controller.doughnut.js b/src/controllers/controller.doughnut.js index 8b161c29a..2513a0689 100644 --- a/src/controllers/controller.doughnut.js +++ b/src/controllers/controller.doughnut.js @@ -49,10 +49,6 @@ return this.chart.data.datasets[this.index]; }, - getScaleForId: function(scaleID) { - return this.chart.scales[scaleID]; - }, - addElements: function() { this.getDataset().metaData = this.getDataset().metaData || []; helpers.each(this.getDataset().data, function(value, index) { @@ -71,7 +67,9 @@ _index: index, }); - this.getDataset().backgroundColor.splice(index, 0, colorForNewElement); + if (colorForNewElement && helpers.isArray(this.getDataset().backgroundColor)) { + this.getDataset().backgroundColor.splice(index, 0, colorForNewElement); + } // Reset the point this.updateElement(arc, index, true); @@ -92,7 +90,6 @@ this.chart.innerRadius = this.chart.options.cutoutPercentage ? (this.chart.outerRadius / 100) * (this.chart.options.cutoutPercentage) : 1; this.chart.radiusLength = (this.chart.outerRadius - this.chart.innerRadius) / this.chart.data.datasets.length; - this.getDataset().total = 0; helpers.each(this.getDataset().data, function(value) { this.getDataset().total += Math.abs(value); @@ -101,6 +98,21 @@ this.outerRadius = this.chart.outerRadius - (this.chart.radiusLength * this.index); this.innerRadius = this.outerRadius - this.chart.radiusLength; + // Make sure we have metaData for each data point + var numData = this.getDataset().data.length; + var numArcs = this.getDataset().metaData.length; + + // Make sure that we handle number of datapoints changing + if (numData < numArcs) { + // Remove excess bars for data points that have been removed + this.getDataset().metaData.splice(numData, numArcs - numData) + } else if (numData > numArcs) { + // Add new elements + for (var index = numArcs; index < numData; ++index) { + this.addElementAndReset(index); + } + } + helpers.each(this.getDataset().metaData, function(arc, index) { this.updateElement(arc, index, reset); }, this); @@ -165,15 +177,13 @@ }, this); }, - - setHoverStyle: function(arc) { var dataset = this.chart.data.datasets[arc._datasetIndex]; var index = arc._index; 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) { diff --git a/test/controller.doughnut.tests.js b/test/controller.doughnut.tests.js new file mode 100644 index 000000000..cef606263 --- /dev/null +++ b/test/controller.doughnut.tests.js @@ -0,0 +1,429 @@ +// Test the bar controller +describe('Doughnut controller tests', function() { + it('Should be constructed', function() { + var chart = { + data: { + datasets: [{ + data: [] + }] + } + }; + + var controller = new Chart.controllers.doughnut(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: 'doughnut' + }, + options: { + } + }; + + var controller = new Chart.controllers.doughnut(chart, 0); + + expect(chart.data.datasets[0].metaData.length).toBe(4); // 4 rectangles 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 remove elements', function() { + var chart = { + data: { + datasets: [{ + data: [10, 15, 0, 4] + }] + }, + config: { + type: 'doughnut' + }, + options: { + } + }; + + var controller = new Chart.controllers.doughnut(chart, 0); + controller.removeElement(1); + expect(chart.data.datasets[0].metaData.length).toBe(3); + }); + + it ('Should reset and update elements', function() { + var chart = { + chart: { + width: 100, + height: 200, + }, + data: { + datasets: [{ + data: [10, 15, 0, 4] + }, { + data: [1] + }], + labels: ['label0', 'label1', 'label2', 'label3'] + }, + config: { + type: 'doughnut' + }, + options: { + animation: { + animateRotate: false, + animateScale: false + }, + cutoutPercentage: 50, + elements: { + arc: { + backgroundColor: 'rgb(255, 0, 0)', + borderColor: 'rgb(0, 0, 255)', + borderWidth: 2, + hoverBackgroundColor: 'rgb(255, 255, 255)' + } + } + } + }; + + var controller = new Chart.controllers.doughnut(chart, 0); + controller.reset(); // reset first + + expect(chart.data.datasets[0].metaData[0]._model).toEqual({ + x: 50, + y: 100, + startAngle: Math.PI * -0.5, + circumference: 2.166614539857563, + outerRadius: 49, + innerRadius: 36.75, + }); + + expect(chart.data.datasets[0].metaData[1]._model).toEqual({ + x: 50, + y: 100, + startAngle: Math.PI * -0.5, + circumference: 3.2499218097863447, + outerRadius: 49, + innerRadius: 36.75, + }); + + expect(chart.data.datasets[0].metaData[2]._model).toEqual({ + x: 50, + y: 100, + startAngle: Math.PI * -0.5, + circumference: 0, + outerRadius: 49, + innerRadius: 36.75, + }); + + expect(chart.data.datasets[0].metaData[3]._model).toEqual({ + x: 50, + y: 100, + startAngle: Math.PI * -0.5, + circumference: 0.8666458159430251, + outerRadius: 49, + innerRadius: 36.75, + }); + + controller.update(); + + expect(chart.data.datasets[0].metaData[0]._model).toEqual({ + x: 50, + y: 100, + startAngle: Math.PI * -0.5, + endAngle: 0.5958182130626666, + circumference: 2.166614539857563, + outerRadius: 49, + innerRadius: 36.75, + + backgroundColor: 'rgb(255, 0, 0)', + borderColor: 'rgb(0, 0, 255)', + borderWidth: 2, + hoverBackgroundColor: 'rgb(255, 255, 255)', + + label: 'label0', + }); + + expect(chart.data.datasets[0].metaData[1]._model).toEqual({ + x: 50, + y: 100, + startAngle: 0.5958182130626666, + endAngle: 3.8457400228490113, + circumference: 3.2499218097863447, + outerRadius: 49, + innerRadius: 36.75, + + backgroundColor: 'rgb(255, 0, 0)', + borderColor: 'rgb(0, 0, 255)', + borderWidth: 2, + hoverBackgroundColor: 'rgb(255, 255, 255)', + + label: 'label1' + }); + + expect(chart.data.datasets[0].metaData[2]._model).toEqual({ + x: 50, + y: 100, + startAngle: 3.8457400228490113, + endAngle: 3.8457400228490113, + circumference: 0, + outerRadius: 49, + innerRadius: 36.75, + + backgroundColor: 'rgb(255, 0, 0)', + borderColor: 'rgb(0, 0, 255)', + borderWidth: 2, + hoverBackgroundColor: 'rgb(255, 255, 255)', + + label: 'label2' + }); + + expect(chart.data.datasets[0].metaData[3]._model).toEqual({ + x: 50, + y: 100, + startAngle: 3.8457400228490113, + endAngle: 4.712385838792036, + circumference: 0.8666458159430251, + outerRadius: 49, + innerRadius: 36.75, + + backgroundColor: 'rgb(255, 0, 0)', + borderColor: 'rgb(0, 0, 255)', + borderWidth: 2, + hoverBackgroundColor: 'rgb(255, 255, 255)', + + label: 'label3' + }); + + // Change the amount of data and ensure that arcs are updated accordingly + chart.data.datasets[0].data = [1, 2]; // remove 2 elements from dataset 0 + 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); + + // Add data + chart.data.datasets[0].data = [1, 2, 3, 4]; + controller.update(); + + expect(chart.data.datasets[0].metaData.length).toBe(4); + 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 arcs', function() { + var chart = { + chart: { + width: 100, + height: 200, + }, + data: { + datasets: [{ + data: [10, 15, 0, 4] + }], + labels: ['label0', 'label1', 'label2', 'label3'] + }, + config: { + type: 'doughnut' + }, + options: { + animation: { + animateRotate: false, + animateScale: false + }, + cutoutPercentage: 50, + elements: { + arc: { + backgroundColor: 'rgb(255, 0, 0)', + borderColor: 'rgb(0, 0, 255)', + borderWidth: 2, + hoverBackgroundColor: 'rgb(255, 255, 255)' + } + } + } + }; + + var controller = new Chart.controllers.doughnut(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 set the hover style of an arc', function() { + var chart = { + chart: { + width: 100, + height: 200, + }, + data: { + datasets: [{ + data: [10, 15, 0, 4] + }], + labels: ['label0', 'label1', 'label2', 'label3'] + }, + config: { + type: 'doughnut' + }, + options: { + animation: { + animateRotate: false, + animateScale: false + }, + cutoutPercentage: 50, + elements: { + arc: { + backgroundColor: 'rgb(255, 0, 0)', + borderColor: 'rgb(0, 0, 255)', + borderWidth: 2, + } + } + } + }; + + var controller = new Chart.controllers.doughnut(chart, 0); + controller.reset(); // reset first + 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, 0, 230)'); + expect(arc._model.borderWidth).toBe(2); + + // Set a dataset style to take precedence + chart.data.datasets[0].hoverBackgroundColor = 'rgb(9, 9, 9)'; + chart.data.datasets[0].hoverBorderColor = 'rgb(18, 18, 18)'; + chart.data.datasets[0].hoverBorderWidth = 1.56; + + controller.setHoverStyle(arc); + + expect(arc._model.backgroundColor).toBe('rgb(9, 9, 9)'); + expect(arc._model.borderColor).toBe('rgb(18, 18, 18)'); + expect(arc._model.borderWidth).toBe(1.56); + + // Dataset styles can be an array + chart.data.datasets[0].hoverBackgroundColor = ['rgb(255, 255, 255)', 'rgb(9, 9, 9)']; + chart.data.datasets[0].hoverBorderColor = ['rgb(18, 18, 18)']; + chart.data.datasets[0].hoverBorderWidth = [0.1, 1.56]; + + controller.setHoverStyle(arc); + + expect(arc._model.backgroundColor).toBe('rgb(255, 255, 255)'); + expect(arc._model.borderColor).toBe('rgb(18, 18, 18)'); + expect(arc._model.borderWidth).toBe(0.1); + + // Element custom styles also work + arc.custom = { + hoverBackgroundColor: 'rgb(7, 7, 7)', + hoverBorderColor: 'rgb(17, 17, 17)', + hoverBorderWidth: 3.14159, + }; + + controller.setHoverStyle(arc); + + expect(arc._model.backgroundColor).toBe('rgb(7, 7, 7)'); + expect(arc._model.borderColor).toBe('rgb(17, 17, 17)'); + expect(arc._model.borderWidth).toBe(3.14159); + }); + + it ('should unset the hover style of an arc', function() { + var chart = { + chart: { + width: 100, + height: 200, + }, + data: { + datasets: [{ + data: [10, 15, 0, 4] + }], + labels: ['label0', 'label1', 'label2', 'label3'] + }, + config: { + type: 'doughnut' + }, + options: { + animation: { + animateRotate: false, + animateScale: false + }, + cutoutPercentage: 50, + elements: { + arc: { + backgroundColor: 'rgb(255, 0, 0)', + borderColor: 'rgb(0, 0, 255)', + borderWidth: 2, + } + } + } + }; + + var controller = new Chart.controllers.doughnut(chart, 0); + controller.reset(); // reset first + controller.update(); + + var arc = chart.data.datasets[0].metaData[0]; + + controller.removeHoverStyle(arc); + + expect(arc._model.backgroundColor).toBe('rgb(255, 0, 0)'); + expect(arc._model.borderColor).toBe('rgb(0, 0, 255)'); + expect(arc._model.borderWidth).toBe(2); + + // Set a dataset style to take precedence + chart.data.datasets[0].backgroundColor = 'rgb(9, 9, 9)'; + chart.data.datasets[0].borderColor = 'rgb(18, 18, 18)'; + chart.data.datasets[0].borderWidth = 1.56; + + controller.removeHoverStyle(arc); + + expect(arc._model.backgroundColor).toBe('rgb(9, 9, 9)'); + expect(arc._model.borderColor).toBe('rgb(18, 18, 18)'); + expect(arc._model.borderWidth).toBe(1.56); + + // Dataset styles can be an array + chart.data.datasets[0].backgroundColor = ['rgb(255, 255, 255)', 'rgb(9, 9, 9)']; + chart.data.datasets[0].borderColor = ['rgb(18, 18, 18)']; + chart.data.datasets[0].borderWidth = [0.1, 1.56]; + + controller.removeHoverStyle(arc); + + expect(arc._model.backgroundColor).toBe('rgb(255, 255, 255)'); + expect(arc._model.borderColor).toBe('rgb(18, 18, 18)'); + expect(arc._model.borderWidth).toBe(0.1); + + // Element custom styles also work + arc.custom = { + backgroundColor: 'rgb(7, 7, 7)', + borderColor: 'rgb(17, 17, 17)', + borderWidth: 3.14159, + }; + + controller.removeHoverStyle(arc); + + expect(arc._model.backgroundColor).toBe('rgb(7, 7, 7)'); + expect(arc._model.borderColor).toBe('rgb(17, 17, 17)'); + expect(arc._model.borderWidth).toBe(3.14159); + }); +}); \ No newline at end of file