test/test.unit.js
/*jshint mocha:true*/
/*global module:true*/
/*global inject:true*/
/*global expect:true*/
/*global sinon:true*/
describe('Unit testing', function () {
'use strict';
var $compile, scope, sandbox, ChartJs, ChartJsProvider;
beforeEach(module('chart.js', function (_ChartJsProvider_) {
ChartJsProvider = _ChartJsProvider_;
ChartJsProvider.setOptions({ env: 'test', responsive: false });
}));
beforeEach(inject(function (_$compile_, _$rootScope_, _ChartJs_) {
// The injector unwraps the underscores (_) from around the parameter names when matching
$compile = _$compile_;
scope = _$rootScope_;
ChartJs = _ChartJs_;
sandbox = sinon.sandbox.create();
}));
afterEach(function () {
sandbox.restore();
});
describe('base', function () {
describe('chart types', function () {
['line', 'bar', 'horizontalBar', 'radar', 'pie', 'doughnut', 'polarArea', 'bubble'].forEach(function (type) {
it('creates a ' + type + ' chart using the directive', function () {
var markup = '<canvas class="chart chart-' +
(type === 'polarArea' ? 'polar-area' : type === 'horizontalBar' ? 'horizontal-bar' : type) +
'" chart-data="data" chart-labels="labels"></canvas>';
if (['line', 'bar', 'horizontalBar', 'radar'].indexOf(type) > - 1) {
scope.labels = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
scope.data = [
[65, 59, 80, 81, 56, 55, 40],
[28, 48, 40, 19, 86, 27, 90]
];
} else {
scope.labels = ['Downloads', 'In store', 'Mail orders'];
scope.data = [300, 500, 100];
}
var spyChart = sandbox.spy(ChartJs, 'Chart');
scope.$on('chart-create', function (evt, chart) {
expect(chart).to.be.an.instanceOf(Chart.Controller);
});
$compile(markup)(scope);
scope.$digest();
expect(spyChart).to.have.been.calledWithNew;
expect(spyChart).to.have.been.calledWithExactly(
sinon.match.any,
sinon.match({ type: type, data: sinon.match.object, options: sinon.match.object })
);
});
it('creates a ' + type + ' chart using the "chart-type" attribute', function () {
var markup = '<div style="width: 250px; height:120px">' +
'<canvas class="chart chart-base" chart-data="data" chart-labels="labels" ' +
'chart-type="type"></canvas></div>';
scope.type = type;
if (['line', 'bar', 'horizontalBar', 'radar'].indexOf(type) > - 1) {
scope.labels = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
scope.data = [
[65, 59, 80, 81, 56, 55, 40],
[28, 48, 40, 19, 86, 27, 90]
];
} else {
scope.labels = ['Downloads', 'In store', 'Mail orders'];
scope.data = [300, 500, 100];
}
var spyChart = sandbox.spy(ChartJs, 'Chart');
scope.$on('chart-create', function (evt, chart) {
expect(chart).to.be.an.instanceOf(Chart.Controller);
});
$compile(markup)(scope);
scope.$digest();
expect(spyChart).to.have.been.calledWithNew;
expect(spyChart).to.have.been.calledWithExactly(
sinon.match.any,
sinon.match({ type: type, data: sinon.match.object, options: sinon.match.object })
);
});
});
});
describe('colors', function(){
it('sets the chart colors when Hex colors, RGB colors, RGBA colors, or objects are used', function (){
var datasets;
var markup = '<canvas class="chart chart-pie" chart-data="data" chart-labels="labels" chart-colors="colors"></canvas>';
scope.colors = [
{
backgroundColor: 'rgba(159,204,0,0.2)',
pointBackgroundColor: 'rgba(159,204,0,1)',
pointHoverBackgroundColor: 'rgba(159,204,0,0.8)',
borderColor: 'rgba(159,204,0,1)',
pointBorderColor: '#fff',
pointHoverBorderColor: 'rgba(159,204,0,1)'
},'rgba(250,109,33,0.5)','#9a9a9a','rgb(233,177,69)'
];
scope.labels = ['Green', 'Peach', 'Grey', 'Orange'];
scope.data = [300, 500, 100, 150];
scope.$on('chart-create', function (evt, chart) {
datasets = chart.chart.config.data.datasets;
});
$compile(markup)(scope);
scope.$digest();
expect(datasets[0].backgroundColor[0]).to.equal('rgba(159,204,0,1)');
expect(datasets[0].backgroundColor[1]).to.equal('rgba(250,109,33,0.5)');
expect(datasets[0].backgroundColor[2]).to.equal('rgba(154,154,154,1)');
expect(datasets[0].backgroundColor[3]).to.equal('rgba(233,177,69,1)');
});
});
describe('dataset override', function () {
it('overrides the datasets for complex charts', function () {
var datasets;
var markup = '<canvas class="chart chart-bar" chart-data="data" chart-labels="labels" ' +
'chart-dataset-override="datasetOverride"></canvas>';
scope.labels = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
scope.data = [
[65, -59, 80, 81, -56, 55, -40],
[28, 48, -40, 19, 86, 27, 90]
];
scope.datasetOverride = [
{
label: 'Bar chart',
borderWidth: 1,
type: 'bar'
},
{
label: 'Line chart',
borderWidth: 3,
type: 'line'
}
];
scope.$on('chart-create', function (evt, chart) {
datasets = chart.chart.config.data.datasets;
});
$compile(markup)(scope);
scope.$digest();
expect(datasets[0].label).to.equal('Bar chart');
expect(datasets[1].label).to.equal('Line chart');
expect(datasets[0].borderWidth).to.equal(1);
expect(datasets[1].borderWidth).to.equal(3);
expect(datasets[0].type).to.equal('bar');
expect(datasets[1].type).to.equal('line');
});
it('overrides the dataset for simple charts', function () {
var datasets;
var markup = '<canvas class="chart chart-doughnut" chart-data="data" chart-labels="labels" ' +
'chart-colors="colors" chart-dataset-override="datasetOverride"></canvas>';
scope.colors = ['#45b7cd', '#ff6384', '#ff8e72'];
scope.labels = ['Download Sales', 'In-Store Sales', 'Mail-Order Sales'];
scope.data = [350, 450, 100];
scope.datasetOverride = {
hoverBackgroundColor: ['#45b7cd', '#ff6384', '#ff8e72'],
hoverBorderColor: ['#45b7cd', '#ff6384', '#ff8e72']
};
scope.$on('chart-create', function (evt, chart) {
datasets = chart.chart.config.data.datasets;
});
$compile(markup)(scope);
scope.$digest();
expect(datasets[0].hoverBackgroundColor).to.deep.equal(['#45b7cd', '#ff6384', '#ff8e72']);
expect(datasets[0].hoverBorderColor).to.deep.equal(['#45b7cd', '#ff6384', '#ff8e72']);
});
});
});
describe('lifecycle', function () {
it('watches the attributes of the chart', function () {
var markup = '<div style="width: 250px; height:120px">' +
'<canvas class="chart chart-line" chart-data="data" chart-labels="labels" chart-type="type"></canvas></div>';
scope.labels = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
scope.data = [
[65, 59, 80, 81, 56, 55, 40],
[28, 48, 40, 19, 86, 27, 90]
];
var spy = sandbox.spy(scope, '$watch');
$compile(markup)(scope);
// cannot get a hold of the child scope as it isn't created yet
// so cannot be more precise on expectations
expect(spy.calledThrice).to.be.true;
});
it('creates the chart only once', function () {
var markup = '<div style="width: 250px; height:120px">' +
'<canvas class="chart chart-line" chart-data="data" chart-labels="labels" ' +
'chart-series="series"></canvas></div>';
var count = 0;
scope.labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
scope.series = ['Series A', 'Series B'];
scope.data = [
[65, 59, 80, 81, 56, 55, 40],
[28, 48, 40, 19, 86, 27, 90]
];
scope.$on('chart-create', function () {
count++;
});
$compile(markup)(scope);
scope.$digest();
expect(count).to.equal(1);
});
it('updates the chart', function () {
var markup = '<div style="width: 250px; height:120px">' +
'<canvas class="chart chart-line" chart-data="data" chart-labels="labels" ' +
'chart-series="series"></canvas></div>';
var count = 0;
scope.labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
scope.series = ['Series A', 'Series B'];
scope.data = [
[65, 59, 80, 81, 56, 55, 40],
[28, 48, 40, 19, 86, 27, 90]
];
scope.$on('chart-update', function () {
count++;
});
$compile(markup)(scope);
scope.$digest();
scope.data = [
[28, 48, 40, 19, 86, 27, 90],
[65, 59, 80, 81, 56, 55, 40]
];
scope.$digest();
expect(count).to.equal(1);
});
it('destroy the chart if all data is removed', function () {
var markup = '<div style="width: 250px; height:120px">' +
'<canvas class="chart chart-line" chart-data="data" chart-labels="labels"></canvas></div>';
var countCreate = 0, countUpdate = 0, countDestroy = 0;
scope.labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
scope.data = [
[65, 59, 80, 81, 56, 55, 40],
[28, 48, 40, 19, 86, 27, 90]
];
scope.$on('chart-create', function () {
countCreate++;
});
scope.$on('chart-update', function () {
countUpdate++;
});
scope.$on('chart-destroy', function() {
countDestroy++;
});
$compile(markup)(scope);
scope.$digest();
scope.data = [];
scope.$digest();
expect(countCreate).to.equal(1);
expect(countUpdate).to.equal(0);
expect(countDestroy).to.equal(1);
});
it('re-create the chart if data added or removed', function () {
var markup = '<div style="width: 250px; height:120px">' +
'<canvas class="chart chart-line" chart-data="data" chart-labels="labels" ' +
'chart-series="series"></canvas></div>';
var countCreate = 0, countUpdate = 0, countDestroy = 0;
scope.labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
scope.data = [
[65, 59, 80, 81, 56, 55, 40],
[28, 48, 40, 19, 86, 27, 90]
];
scope.$on('chart-create', function () {
countCreate++;
});
scope.$on('chart-update', function () {
countUpdate++;
});
scope.$on('chart-destroy', function() {
countDestroy++;
});
$compile(markup)(scope);
scope.$digest();
scope.data = [
[28, 48, 40, 19, 86, 27, 90],
[65, 59, 80, 81, 56, 55, 40],
[65, 59, 80, 81, 56, 55, 40]
];
scope.$digest();
expect(countCreate).to.equal(2);
expect(countUpdate).to.equal(0);
expect(countDestroy).to.equal(1);
});
it('should allow to set a configuration', function () {
ChartJsProvider.setOptions({responsive: false});
expect(ChartJs.getOptions().responsive).to.equal(false);
expect(ChartJs.getOptions('Line').responsive).to.equal(false);
expect(ChartJsProvider.$get().Chart.defaults.responsive).to.equal(false);
ChartJsProvider.setOptions({responsive: true});
expect(ChartJs.getOptions().responsive).to.equal(true);
expect(ChartJs.getOptions('Line').responsive).to.equal(true);
expect(ChartJsProvider.$get().Chart.defaults.responsive).to.equal(true);
});
it('should allow to set a configuration for a chart type', function () {
ChartJsProvider.setOptions('Line', {responsive: false});
expect(ChartJs.getOptions('Line').responsive).to.equal(false);
ChartJsProvider.setOptions('Line', {responsive: true});
expect(ChartJs.getOptions('Line').responsive).to.equal(true);
ChartJsProvider.setOptions('Line', {responsive: true});
expect(ChartJsProvider.$get().Chart.defaults.Line.responsive).to.equal(true);
});
['labels', 'colors', 'series', 'options'].forEach(function (attr) {
it('re-creates the chart on ' + attr + ' changes', function () {
var markup = '<div style="width: 250px; height:120px">' +
'<canvas class="chart chart-line" chart-data="data" chart-labels="labels" chart-series="series" ' +
'chart-colors="colors" chart-options="options"></canvas></div>';
var count = 0;
scope.options = { scaleShowVerticalLines: false };
scope.labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
scope.series = ['Series A', 'Series B'];
scope.colors = ['#45b7cd', '#ff6384'];
scope.data = [
[65, 59, 80, 81, 56, 55, 40],
[28, 48, 40, 19, 86, 27, 90]
];
scope.$on('chart-create', function () {
count++;
});
$compile(markup)(scope);
scope.$digest();
switch (attr) {
case 'labels':
scope.labels = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
break;
case 'colors':
scope.colors = ['#ff6384', '#ff8e72'];
break;
case 'series':
scope.series = ['Series C', 'Series D'];
break;
case 'options':
scope.options = { scaleShowVerticalLines: true };
break;
}
scope.$digest();
expect(count).to.equal(2);
});
});
['labels', 'colors', 'series', 'options'].forEach(function (attr) {
it('does not re-create the chart on ' + attr + ' not changed', function () {
var markup = '<div style="width: 250px; height:120px">' +
'<canvas class="chart chart-line" chart-data="data" chart-labels="labels" chart-series="series" ' +
'chart-colors="colors" chart-options="options"></canvas></div>';
var count = 0;
scope.options = { scaleShowVerticalLines: false };
scope.labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
scope.series = ['Series A', 'Series B'];
scope.colors = ['#45b7cd', '#ff6384'];
scope.data = [
[65, 59, 80, 81, 56, 55, 40],
[28, 48, 40, 19, 86, 27, 90]
];
scope.$on('chart-create', function () {
count++;
});
$compile(markup)(scope);
scope.$digest();
switch (attr) {
case 'labels':
scope.labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
break;
case 'colors':
scope.colors = ['#45b7cd', '#ff6384'];
break;
case 'series':
scope.series = ['Series A', 'Series B'];
break;
case 'options':
scope.options = { scaleShowVerticalLines: false };
break;
}
scope.$digest();
expect(count).to.equal(1);
});
});
});
});