/*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 = ''; 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 = '
' + '
'; 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('dataset override', function () { it('overrides the datasets for complex charts', function () { var datasets; var markup = ''; 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 = ''; 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 = '
' + '
'; 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 = '
' + '
'; 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 = '
' + '
'; 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 = '
' + '
'; 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 = '
' + '
'; 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); ChartJsProvider.setOptions({responsive: true}); expect(ChartJs.getOptions().responsive).to.equal(true); expect(ChartJs.getOptions('Line').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); }); ['labels', 'colors', 'series', 'options'].forEach(function (attr) { it('re-creates the chart on ' + attr + ' changes', function () { var markup = '
' + '
'; 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 = '
' + '
'; 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); }); }); }); });