Browse Source

Adding mocha specs

v1-dev
Ændrew Rininsland 8 years ago
parent
commit
a21b0b0030
No known key found for this signature in database
GPG Key ID: ADBCD4C867F9B2DA
  1. 1
      .eslintrc
  2. 21
      karma.conf.js
  3. 45
      npm-debug.log
  4. 1
      package.json
  5. 10
      spec-mocha/.eslintrc
  6. 55
      spec-mocha/api.axis-spec.js
  7. 166
      spec-mocha/api.data-spec.js
  8. 443
      spec-mocha/api.focus-spec.js
  9. 121
      spec-mocha/api.grid-spec.js
  10. 123
      spec-mocha/api.load-spec.js
  11. 252
      spec-mocha/api.region-spec.js
  12. 117
      spec-mocha/api.zoom-spec.js
  13. 161
      spec-mocha/arc-spec.js
  14. 842
      spec-mocha/axis-spec.js
  15. 47
      spec-mocha/c3-helper.js
  16. 12
      spec-mocha/c3-spec.js
  17. 63
      spec-mocha/class-spec.js
  18. 160
      spec-mocha/core-spec.js
  19. 1310
      spec-mocha/data-spec.js
  20. 135
      spec-mocha/domain-spec.js
  21. 367
      spec-mocha/grid-spec.js
  22. 118
      spec-mocha/interaction-spec.js
  23. 280
      spec-mocha/legend-spec.js
  24. 183
      spec-mocha/shape.bar-spec.js
  25. 172
      spec-mocha/shape.line-spec.js
  26. 50
      spec-mocha/svg-helper.js
  27. 100
      spec-mocha/title-spec.js
  28. 124
      spec-mocha/tooltip-spec.js
  29. 139
      spec-mocha/type-spec.js
  30. 69
      spec-mocha/zoom-spec.js
  31. 8
      spec/c3-helper.js

1
.eslintrc

@ -4,6 +4,7 @@
"browser": true,
"node": true
},
"root": true,
"rules": {
"indent": ["error", 4],
"no-var": "error",

21
karma.conf.js

@ -1,8 +1,6 @@
// Karma configuration
// Generated on Wed Sep 30 2015 22:01:48 GMT+0900 (KST)
const babel = require('rollup-plugin-babel');
module.exports = function(config) {
config.set({
@ -17,6 +15,9 @@ module.exports = function(config) {
// list of files / patterns to load in the browser
files: [
'node_modules/d3/d3.min.js',
'c3.js',
'c3.css',
'spec/*-helper.js',
'spec/*-spec.js'
],
@ -30,22 +31,10 @@ module.exports = function(config) {
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'spec/*.js': ['rollup', 'coverage']
'c3.js': ['coverage']
},
rollupPreprocessor: {
// rollup settings. See Rollup documentation
plugins: [
babel({
exclude: 'node_modules/**'
})
],
// will help to prevent conflicts between different tests entries
format: 'iife',
sourceMap: 'inline'
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
@ -67,7 +56,7 @@ module.exports = function(config) {
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_ERROR,
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes

45
npm-debug.log

@ -1,45 +0,0 @@
0 info it worked if it ends with ok
1 verbose cli [ '/usr/local/bin/node', '/usr/local/bin/npm', 'run', 'test' ]
2 info using npm@3.10.3
3 info using node@v6.5.0
4 verbose run-script [ 'pretest', 'test', 'posttest' ]
5 info lifecycle c3@0.4.11~pretest: c3@0.4.11
6 silly lifecycle c3@0.4.11~pretest: no script for pretest, continuing
7 info lifecycle c3@0.4.11~test: c3@0.4.11
8 verbose lifecycle c3@0.4.11~test: unsafe-perm in lifecycle true
9 verbose lifecycle c3@0.4.11~test: PATH: /usr/local/lib/node_modules/npm/bin/node-gyp-bin:/Users/aendrew/Sites/c3/node_modules/.bin:/usr/local/bin:/Users/aendrew/.rvm/gems/ruby-2.0.0-p353/bin:/Users/aendrew/.rvm/gems/ruby-2.0.0-p353@global/bin:/Users/aendrew/.rvm/rubies/ruby-2.0.0-p353/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/usr/local/MacGPG2/bin:/Users/aendrew/bin:/Users/aendrew/.rvm/gems/ruby-2.0.0-p353/bin:/Users/aendrew/.rvm/gems/ruby-2.0.0-p353@global/bin:/Users/aendrew/.rvm/rubies/ruby-2.0.0-p353/bin:/Users/aendrew/.composer/vendor/bin:/Users/aendrew/local/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/Users/aendrew/.rvm/bin:/Users/aendrew/.rvm/bin
10 verbose lifecycle c3@0.4.11~test: CWD: /Users/aendrew/Sites/c3
11 silly lifecycle c3@0.4.11~test: Args: [ '-c', 'karma start karma.conf.js' ]
12 silly lifecycle c3@0.4.11~test: Returned: code: 1 signal: null
13 info lifecycle c3@0.4.11~test: Failed to exec test script
14 verbose stack Error: c3@0.4.11 test: `karma start karma.conf.js`
14 verbose stack Exit status 1
14 verbose stack at EventEmitter.<anonymous> (/usr/local/lib/node_modules/npm/lib/utils/lifecycle.js:242:16)
14 verbose stack at emitTwo (events.js:106:13)
14 verbose stack at EventEmitter.emit (events.js:191:7)
14 verbose stack at ChildProcess.<anonymous> (/usr/local/lib/node_modules/npm/lib/utils/spawn.js:40:14)
14 verbose stack at emitTwo (events.js:106:13)
14 verbose stack at ChildProcess.emit (events.js:191:7)
14 verbose stack at maybeClose (internal/child_process.js:877:16)
14 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:226:5)
15 verbose pkgid c3@0.4.11
16 verbose cwd /Users/aendrew/Sites/c3
17 error Darwin 15.3.0
18 error argv "/usr/local/bin/node" "/usr/local/bin/npm" "run" "test"
19 error node v6.5.0
20 error npm v3.10.3
21 error code ELIFECYCLE
22 error c3@0.4.11 test: `karma start karma.conf.js`
22 error Exit status 1
23 error Failed at the c3@0.4.11 test script 'karma start karma.conf.js'.
23 error Make sure you have the latest version of node.js and npm installed.
23 error If you do, this is most likely a problem with the c3 package,
23 error not with npm itself.
23 error Tell the author that this fails on your system:
23 error karma start karma.conf.js
23 error You can get information on how to open an issue for this project with:
23 error npm bugs c3
23 error Or if that isn't available, you can get their info via:
23 error npm owner ls c3
23 error There is likely additional logging output above.
24 verbose exit [ 1, true ]

1
package.json

@ -28,6 +28,7 @@
"devDependencies": {
"babel-plugin-external-helpers": "^6.8.0",
"babel-preset-es2015": "^6.14.0",
"chai-color-helpers": "github:aendrew/chai-color-helpers",
"codecov.io": "^0.1.6",
"eslint": "^3.5.0",
"eslint-config-airbnb-base": "^7.1.0",

10
spec-mocha/.eslintrc

@ -0,0 +1,10 @@
{
"env": {
"mocha": true,
"node": true
},
"rules": {
"prefer-arrow-callback": 0,
"no-var": 0,
},
}

55
spec-mocha/api.axis-spec.js

@ -0,0 +1,55 @@
var expect = require('chai').expect;
describe('c3 api axis', function () {
var chart, args;
beforeEach(function (done) {
chart = window.initChart(chart, args, done);
});
describe('axis.labels', function () {
it('should update args', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100],
['data2', 50, 20, 10]
],
axes: {
data1: 'y',
data2: 'y2'
}
},
axis: {
y: {
label: 'Y Axis Label'
},
y2: {
show: true,
label: 'Y2 Axis Label'
}
}
};
expect(true).to.be.ok;
});
it('should update y axis label', function () {
chart.axis.labels({y: 'New Y Axis Label'});
var label = d3.select('.c3-axis-y-label');
expect(label.text()).to.equal('New Y Axis Label');
expect(label.attr('dx')).to.equal('-0.5em');
expect(label.attr('dy')).to.equal('1.2em');
});
it('should update y axis label', function () {
chart.axis.labels({y2: 'New Y2 Axis Label'});
var label = d3.select('.c3-axis-y2-label');
expect(label.text()).to.equal('New Y2 Axis Label');
expect(label.attr('dx')).to.equal('-0.5em');
expect(label.attr('dy')).to.equal('-0.5em');
});
});
});

166
spec-mocha/api.data-spec.js

@ -0,0 +1,166 @@
var chai = require('chai');
var chaiColors = require('chai-color-helpers');
var expect = chai.expect;
chai.use(chaiColors);
describe('c3 api data', function () {
var chart;
var args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 5000, 2000, 1000, 4000, 1500, 2500]
],
names: {
data1: 'Data Name 1',
data2: 'Data Name 2'
},
colors: {
data1: '#FF0000',
data2: '#00FF00'
},
axes: {
data1: 'y',
data2: 'y2'
}
},
axis: {
y2: {
show: true
}
}
};
beforeEach(function (done) {
chart = window.initChart(chart, args, done);
});
describe('data()', function () {
it('should return all of data if no argument given', function () {
var results = chart.data(),
expected = ['data1', 'data2'];
results.forEach(function (result, i) {
expect(result.id).to.equal(expected[i]);
});
});
it('should return specifid data if string argument given', function () {
var results = chart.data('data1');
expect(results.length).to.equal(1);
expect(results[0].id).to.equal('data1');
});
it('should return specifid data if array argument given', function () {
var results = chart.data(['data1', 'data2']);
expect(results.length).to.equal(2);
expect(results[0].id).to.equal('data1');
expect(results[1].id).to.equal('data2');
});
});
describe('data.shown()', function () {
it('should return only shown targets', function () {
var results;
chart.hide('data1');
results = chart.data.shown();
expect(results.length).to.equal(1);
expect(results[0].id).to.equal('data2');
});
});
describe('data.values()', function () {
it('should return values for specified target', function () {
var values = chart.data.values('data1'),
expectedValues = [30, 200, 100, 400, 150, 250];
expect(values.length).to.equal(6);
values.forEach(function (v, i) {
expect(v).to.equal(expectedValues[i]);
});
});
it('should return null when no args', function () {
var values = chart.data.values();
expect(values).to.be.null;
});
});
describe('data.names()', function () {
it('should return data.names specified as argument', function () {
var results = chart.data.names();
expect(results.data1).to.equal('Data Name 1');
expect(results.data2).to.equal('Data Name 2');
});
it('should return data.names specified as api', function () {
var results = chart.data.names({
data1: 'New Data Name 1',
data2: 'New Data Name 2'
});
expect(results.data1).to.equal('New Data Name 1');
expect(results.data2).to.equal('New Data Name 2');
});
it('should set data.names specified as api', function () {
expect(d3.select('.c3-legend-item-data1 text').text()).to.equal("New Data Name 1");
expect(d3.select('.c3-legend-item-data2 text').text()).to.equal("New Data Name 2");
});
});
describe('data.colors()', function () {
it('should return data.colors specified as argument', function () {
var results = chart.data.colors();
expect(results.data1).to.be.color('#FF0000');
expect(results.data2).to.be.color('#00FF00');
});
it('should return data.colors specified as api', function () {
var results = chart.data.colors({
data1: '#00FF00',
data2: '#FF0000'
});
expect(results.data1).to.be.color('#00FF00');
expect(results.data2).to.be.color('#FF0000');
});
it('should set data.colors specified as api', function () {
expect(d3.select('.c3-line-data1').style('stroke')).to.be.color("#00ff00");
expect(d3.select('.c3-line-data2').style('stroke')).to.be.color("#ff0000");
expect(d3.select('.c3-legend-item-data1 .c3-legend-item-tile').style('stroke')).to.be.color("#00ff00");
expect(d3.select('.c3-legend-item-data2 .c3-legend-item-tile').style('stroke')).to.be.color("#ff0000");
});
});
describe('data.axes()', function () {
it('should return data.axes specified as argument', function () {
var results = chart.data.axes();
expect(results.data1).to.equal('y');
expect(results.data2).to.equal('y2');
expect(d3.select('.c3-axis-y g.tick text').text()).to.equal('0');
expect(d3.select('.c3-axis-y2 g.tick text').text()).to.equal('1000');
});
it('should return data.axes specified as api', function () {
var results = chart.data.axes({
data1: 'y2',
data2: 'y'
});
expect(results.data1).to.equal('y2');
expect(results.data2).to.equal('y');
expect(d3.select('.c3-axis-y g.tick text').text()).to.equal('1000');
expect(d3.select('.c3-axis-y2 g.tick text').text()).to.equal('0');
});
});
});

443
spec-mocha/api.focus-spec.js

@ -0,0 +1,443 @@
var expect = require('chai').expect;
describe('c3 api focus', function () {
var chart;
var args = {
data: {
columns: [
['data1', 30, 200, 100, 400],
['data2', 1000, 800, 500, 2000],
['data3', 5000, 2000, 1000, 4000]
]
}
};
beforeEach(function (done) {
chart = window.initChart(chart, args, done);
});
describe('focus', function () {
it('should focus all targets', function (done) {
var main = chart.internal.main,
legend = chart.internal.legend;
chart.focus();
setTimeout(function () {
var targets = main.select('.c3-chart-line.c3-target'),
legendItems = legend.select('.c3-legend-item');
targets.each(function () {
var line = d3.select(this);
expect(line.classed('c3-focused')).to.be.ok;
});
legendItems.each(function () {
var item = d3.select(this);
expect(item.classed('c3-legend-item-focused')).to.be.ok;
});
done();
}, 1000);
});
it('should focus one target', function (done) {
var main = chart.internal.main,
legend = chart.internal.legend;
chart.focus('data2');
setTimeout(function () {
var targets = {
data1: main.select('.c3-chart-line.c3-target.c3-target-data1'),
data2: main.select('.c3-chart-line.c3-target.c3-target-data2'),
data3: main.select('.c3-chart-line.c3-target.c3-target-data3')
},
legendItems = {
data1: legend.select('.c3-legend-item-data1'),
data2: legend.select('.c3-legend-item-data2'),
data3: legend.select('.c3-legend-item-data3')
};
expect(targets.data1.classed('c3-focused')).to.not.be.ok;
expect(targets.data2.classed('c3-focused')).to.be.ok;
expect(targets.data3.classed('c3-focused')).to.not.be.ok;
expect(legendItems.data1.classed('c3-legend-item-focused')).to.not.be.ok;
expect(legendItems.data2.classed('c3-legend-item-focused')).to.be.ok;
expect(legendItems.data3.classed('c3-legend-item-focused')).to.not.be.ok;
done();
}, 1000);
});
it('should focus multiple targets', function (done) {
var main = chart.internal.main,
legend = chart.internal.legend;
chart.focus(['data1', 'data2']);
setTimeout(function () {
var targets = {
data1: main.select('.c3-chart-line.c3-target.c3-target-data1'),
data2: main.select('.c3-chart-line.c3-target.c3-target-data2'),
data3: main.select('.c3-chart-line.c3-target.c3-target-data3')
},
legendItems = {
data1: legend.select('.c3-legend-item-data1'),
data2: legend.select('.c3-legend-item-data2'),
data3: legend.select('.c3-legend-item-data3')
};
expect(targets.data1.classed('c3-focused')).to.be.ok;
expect(targets.data2.classed('c3-focused')).to.be.ok;
expect(targets.data3.classed('c3-focused')).to.not.be.ok;
expect(legendItems.data1.classed('c3-legend-item-focused')).to.be.ok;
expect(legendItems.data2.classed('c3-legend-item-focused')).to.be.ok;
expect(legendItems.data3.classed('c3-legend-item-focused')).to.not.be.ok;
done();
}, 1000);
});
});
describe('defocus', function () {
it('should defocus all targets', function (done) {
var main = chart.internal.main,
legend = chart.internal.legend;
chart.defocus();
setTimeout(function () {
var targets = main.select('.c3-chart-line.c3-target'),
legendItems = legend.select('.c3-legend-item');
targets.each(function () {
var line = d3.select(this);
expect(line.classed('c3-focused')).to.not.be.ok;
expect(line.classed('c3-defocused')).to.be.ok;
});
legendItems.each(function () {
var item = d3.select(this);
expect(item.classed('c3-legend-item-focused')).to.not.be.ok;
expect(+item.style('opacity')).to.be.closeTo(0.3);
});
done();
}, 1000);
});
it('should defocus one target', function (done) {
var main = chart.internal.main,
legend = chart.internal.legend;
chart.defocus('data2');
setTimeout(function () {
var targets = {
data1: main.select('.c3-chart-line.c3-target.c3-target-data1'),
data2: main.select('.c3-chart-line.c3-target.c3-target-data2'),
data3: main.select('.c3-chart-line.c3-target.c3-target-data3')
},
legendItems = {
data1: legend.select('.c3-legend-item-data1'),
data2: legend.select('.c3-legend-item-data2'),
data3: legend.select('.c3-legend-item-data3')
};
expect(targets.data1.classed('c3-defocused')).to.not.be.ok;
expect(targets.data2.classed('c3-defocused')).to.be.ok;
expect(targets.data3.classed('c3-defocused')).to.not.be.ok;
expect(legendItems.data1.classed('c3-legend-item-focused')).to.not.be.ok;
expect(legendItems.data2.classed('c3-legend-item-focused')).to.not.be.ok;
expect(legendItems.data3.classed('c3-legend-item-focused')).to.not.be.ok;
expect(+legendItems.data1.style('opacity')).to.be.closeTo(1);
expect(+legendItems.data2.style('opacity')).to.be.closeTo(0.3);
expect(+legendItems.data3.style('opacity')).to.be.closeTo(1);
done();
}, 1000);
});
it('should defocus multiple targets', function (done) {
var main = chart.internal.main,
legend = chart.internal.legend;
chart.defocus(['data1', 'data2']);
setTimeout(function () {
var targets = {
data1: main.select('.c3-chart-line.c3-target.c3-target-data1'),
data2: main.select('.c3-chart-line.c3-target.c3-target-data2'),
data3: main.select('.c3-chart-line.c3-target.c3-target-data3')
},
legendItems = {
data1: legend.select('.c3-legend-item-data1'),
data2: legend.select('.c3-legend-item-data2'),
data3: legend.select('.c3-legend-item-data3')
};
expect(targets.data1.classed('c3-defocused')).to.be.ok;
expect(targets.data2.classed('c3-defocused')).to.be.ok;
expect(targets.data3.classed('c3-defocused')).to.not.be.ok;
expect(legendItems.data1.classed('c3-legend-item-focused')).to.not.be.ok;
expect(legendItems.data2.classed('c3-legend-item-focused')).to.not.be.ok;
expect(legendItems.data3.classed('c3-legend-item-focused')).to.not.be.ok;
expect(+legendItems.data1.style('opacity')).to.be.closeTo(0.3);
expect(+legendItems.data2.style('opacity')).to.be.closeTo(0.3);
expect(+legendItems.data3.style('opacity')).to.be.closeTo(1);
done();
}, 1000);
});
it('should defocus multiple targets after focused', function (done) {
var main = chart.internal.main,
legend = chart.internal.legend;
chart.focus();
setTimeout(function () {
chart.defocus(['data1', 'data2']);
setTimeout(function () {
var targets = {
data1: main.select('.c3-chart-line.c3-target.c3-target-data1'),
data2: main.select('.c3-chart-line.c3-target.c3-target-data2'),
data3: main.select('.c3-chart-line.c3-target.c3-target-data3')
},
legendItems = {
data1: legend.select('.c3-legend-item-data1'),
data2: legend.select('.c3-legend-item-data2'),
data3: legend.select('.c3-legend-item-data3')
};
expect(targets.data1.classed('c3-defocused')).to.be.ok;
expect(targets.data2.classed('c3-defocused')).to.be.ok;
expect(targets.data3.classed('c3-defocused')).to.not.be.ok;
expect(legendItems.data1.classed('c3-legend-item-focused')).to.not.be.ok;
expect(legendItems.data2.classed('c3-legend-item-focused')).to.not.be.ok;
expect(legendItems.data3.classed('c3-legend-item-focused')).to.be.ok;
expect(+legendItems.data1.style('opacity')).to.be.closeTo(0.3);
expect(+legendItems.data2.style('opacity')).to.be.closeTo(0.3);
expect(+legendItems.data3.style('opacity')).to.be.closeTo(1);
done();
}, 1000);
}, 1000);
});
});
describe('revert', function () {
it('should revert all targets after focus', function (done) {
var main = chart.internal.main,
legend = chart.internal.legend;
chart.focus();
setTimeout(function () {
chart.revert();
setTimeout(function () {
var targets = main.select('.c3-chart-line.c3-target'),
legendItems = legend.select('.c3-legend-item');
targets.each(function () {
var line = d3.select(this);
expect(line.classed('c3-focused')).to.not.be.ok;
});
legendItems.each(function () {
var item = d3.select(this);
expect(item.classed('c3-legend-item-focused')).to.not.be.ok;
expect(+item.style('opacity')).to.be.closeTo(1);
});
done();
}, 1000);
}, 1000);
});
it('should revert all targets after defocus', function (done) {
var main = chart.internal.main,
legend = chart.internal.legend;
chart.defocus();
setTimeout(function () {
chart.revert();
setTimeout(function () {
var targets = main.select('.c3-chart-line.c3-target'),
legendItems = legend.select('.c3-legend-item');
targets.each(function () {
var line = d3.select(this);
expect(line.classed('c3-defocused')).to.not.be.ok;
});
legendItems.each(function () {
var item = d3.select(this);
expect(item.classed('c3-legend-item-focused')).to.not.be.ok;
expect(+item.style('opacity')).to.be.closeTo(1);
});
done();
}, 1000);
}, 1000);
});
it('should revert one target after focus', function (done) {
var main = chart.internal.main,
legend = chart.internal.legend;
chart.focus();
setTimeout(function () {
chart.revert('data2');
setTimeout(function () {
var targets = {
data1: main.select('.c3-chart-line.c3-target.c3-target-data1'),
data2: main.select('.c3-chart-line.c3-target.c3-target-data2'),
data3: main.select('.c3-chart-line.c3-target.c3-target-data3')
},
legendItems = {
data1: legend.select('.c3-legend-item-data1'),
data2: legend.select('.c3-legend-item-data2'),
data3: legend.select('.c3-legend-item-data3')
};
expect(targets.data1.classed('c3-focused')).to.be.ok;
expect(targets.data2.classed('c3-focused')).to.not.be.ok;
expect(targets.data3.classed('c3-focused')).to.be.ok;
expect(+legendItems.data1.style('opacity')).to.be.closeTo(1);
expect(+legendItems.data2.style('opacity')).to.be.closeTo(1);
expect(+legendItems.data3.style('opacity')).to.be.closeTo(1);
expect(legendItems.data1.classed('c3-legend-item-focused')).to.be.ok;
expect(legendItems.data2.classed('c3-legend-item-focused')).to.not.be.ok;
expect(legendItems.data3.classed('c3-legend-item-focused')).to.be.ok;
done();
}, 1000);
}, 1000);
});
it('should revert one target after defocus', function (done) {
var main = chart.internal.main,
legend = chart.internal.legend;
chart.defocus();
setTimeout(function () {
chart.revert('data2');
setTimeout(function () {
var targets = {
data1: main.select('.c3-chart-line.c3-target.c3-target-data1'),
data2: main.select('.c3-chart-line.c3-target.c3-target-data2'),
data3: main.select('.c3-chart-line.c3-target.c3-target-data3')
},
legendItems = {
data1: legend.select('.c3-legend-item-data1'),
data2: legend.select('.c3-legend-item-data2'),
data3: legend.select('.c3-legend-item-data3')
};
expect(targets.data1.classed('c3-defocused')).to.be.ok;
expect(targets.data2.classed('c3-defocused')).to.not.be.ok;
expect(targets.data3.classed('c3-defocused')).to.be.ok;
expect(+legendItems.data1.style('opacity')).to.be.closeTo(0.3);
expect(+legendItems.data2.style('opacity')).to.be.closeTo(1);
expect(+legendItems.data3.style('opacity')).to.be.closeTo(0.3);
expect(legendItems.data1.classed('c3-legend-item-focused')).to.not.be.ok;
expect(legendItems.data2.classed('c3-legend-item-focused')).to.not.be.ok;
expect(legendItems.data3.classed('c3-legend-item-focused')).to.not.be.ok;
done();
}, 1000);
}, 1000);
});
it('should focus multiple targets after focus', function (done) {
var main = chart.internal.main,
legend = chart.internal.legend;
chart.focus();
setTimeout(function () {
chart.revert(['data1', 'data2']);
setTimeout(function () {
var targets = {
data1: main.select('.c3-chart-line.c3-target.c3-target-data1'),
data2: main.select('.c3-chart-line.c3-target.c3-target-data2'),
data3: main.select('.c3-chart-line.c3-target.c3-target-data3')
},
legendItems = {
data1: legend.select('.c3-legend-item-data1'),
data2: legend.select('.c3-legend-item-data2'),
data3: legend.select('.c3-legend-item-data3')
};
expect(targets.data1.classed('c3-focused')).to.not.be.ok;
expect(targets.data2.classed('c3-focused')).to.not.be.ok;
expect(targets.data3.classed('c3-focused')).to.be.ok;
expect(+legendItems.data1.style('opacity')).to.be.closeTo(1);
expect(+legendItems.data2.style('opacity')).to.be.closeTo(1);
expect(+legendItems.data3.style('opacity')).to.be.closeTo(1);
expect(legendItems.data1.classed('c3-legend-item-focused')).to.not.be.ok;
expect(legendItems.data2.classed('c3-legend-item-focused')).to.not.be.ok;
expect(legendItems.data3.classed('c3-legend-item-focused')).to.be.ok;
done();
}, 1000);
}, 1000);
});
it('should focus multiple targets after defocus', function (done) {
var main = chart.internal.main,
legend = chart.internal.legend;
chart.defocus();
setTimeout(function () {
chart.revert(['data1', 'data2']);
setTimeout(function () {
var targets = {
data1: main.select('.c3-chart-line.c3-target.c3-target-data1'),
data2: main.select('.c3-chart-line.c3-target.c3-target-data2'),
data3: main.select('.c3-chart-line.c3-target.c3-target-data3')
},
legendItems = {
data1: legend.select('.c3-legend-item-data1'),
data2: legend.select('.c3-legend-item-data2'),
data3: legend.select('.c3-legend-item-data3')
};
expect(targets.data1.classed('c3-defocused')).to.not.be.ok;
expect(targets.data2.classed('c3-defocused')).to.not.be.ok;
expect(targets.data3.classed('c3-defocused')).to.be.ok;
expect(+legendItems.data1.style('opacity')).to.be.closeTo(1);
expect(+legendItems.data2.style('opacity')).to.be.closeTo(1);
expect(+legendItems.data3.style('opacity')).to.be.closeTo(0.3);
expect(legendItems.data1.classed('c3-legend-item-focused')).to.not.be.ok;
expect(legendItems.data2.classed('c3-legend-item-focused')).to.not.be.ok;
expect(legendItems.data3.classed('c3-legend-item-focused')).to.not.be.ok;
done();
}, 1000);
}, 1000);
});
});
describe('when legend.show = false', function () {
it('should update args to hide legend', function () {
args.legend = {
show: false
};
expect(true).to.be.ok;
});
it('should focus all targets without showing legend', function (done) {
var main = chart.internal.main,
legend = chart.internal.legend;
chart.focus();
setTimeout(function () {
var targets = main.select('.c3-chart-line.c3-target'),
legendItems = legend.select('.c3-legend-item');
targets.each(function () {
var line = d3.select(this);
expect(line.classed('c3-focused')).to.be.ok;
});
expect(legendItems.size()).to.be.closeTo(0);
done();
}, 1000);
});
it('should defocus all targets without showing legend', function (done) {
var main = chart.internal.main,
legend = chart.internal.legend;
chart.defocus();
setTimeout(function () {
var targets = main.select('.c3-chart-line.c3-target'),
legendItems = legend.select('.c3-legend-item');
targets.each(function () {
var line = d3.select(this);
expect(line.classed('c3-defocused')).to.be.ok;
});
expect(legendItems.size()).to.be.closeTo(0);
done();
}, 1000);
});
it('should revert all targets after focus', function (done) {
var main = chart.internal.main,
legend = chart.internal.legend;
chart.focus();
setTimeout(function () {
chart.revert();
setTimeout(function () {
var targets = main.select('.c3-chart-line.c3-target'),
legendItems = legend.select('.c3-legend-item');
targets.each(function () {
var line = d3.select(this);
expect(line.classed('c3-focused')).to.not.be.ok;
});
expect(legendItems.size()).to.be.closeTo(0);
done();
}, 1000);
}, 1000);
});
});
});

121
spec-mocha/api.grid-spec.js

@ -0,0 +1,121 @@
var expect = require('chai').expect;
describe('c3 api grid', function () {
var chart, args;
beforeEach(function (done) {
chart = window.initChart(chart, args, done);
});
describe('ygrid.add and ygrid.remove', function () {
it('should update args', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250]
]
}
};
expect(true).to.be.ok;
});
it('should update y grids', function (done) {
var main = chart.internal.main,
expectedGrids = [
{
value: 100,
text: 'Pressure Low'
},
{
value: 200,
text: 'Pressure High'
}
],
grids;
// Call ygrids.add
chart.ygrids.add(expectedGrids);
setTimeout(function () {
grids = main.selectAll('.c3-ygrid-line');
expect(grids.size()).to.equal(expectedGrids.length);
grids.each(function (d, i) {
var y = +d3.select(this).select('line').attr('y1'),
text = d3.select(this).select('text').text(),
expectedY = Math.round(chart.internal.y(expectedGrids[i].value)),
expectedText = expectedGrids[i].text;
expect(y).to.equal(expectedY);
expect(text).to.equal(expectedText);
});
// Call ygrids.remove
chart.ygrids.remove(expectedGrids);
setTimeout(function () {
grids = main.selectAll('.c3-ygrid-line');
expect(grids.size()).to.equal(0);
}, 500);
}, 500);
setTimeout(function () {
done();
}, 1200);
});
it("should update x ygrids even if it's zoomed", function (done) {
var main = chart.internal.main,
expectedGrids = [
{
value: 0,
text: 'Pressure Low'
},
{
value: 1,
text: 'Pressure High'
}
],
grids, domain;
chart.zoom([0, 2]);
setTimeout(function () {
// Call xgrids
chart.xgrids(expectedGrids);
setTimeout(function () {
grids = main.selectAll('.c3-xgrid-line');
expect(grids.size()).to.equal(expectedGrids.length);
grids.each(function (d, i) {
var x = +d3.select(this).select('line').attr('x1'),
text = d3.select(this).select('text').text(),
expectedX = Math.round(chart.internal.x(expectedGrids[i].value)),
expectedText = expectedGrids[i].text;
expect(x).to.equal(expectedX);
expect(text).to.equal(expectedText);
});
// check if it was not rescaled
domain = chart.internal.y.domain();
expect(domain[0]).to.be.below(0);
expect(domain[1]).to.be.above(400);
// Call xgrids.remove
chart.xgrids.remove(expectedGrids);
setTimeout(function () {
grids = main.selectAll('.c3-xgrid-line');
expect(grids.size()).to.equal(0);
}, 500); // for xgrids.remove()
}, 500); // for xgrids()
}, 500); // for zoom
setTimeout(function () {
done();
}, 1700);
});
});
});

123
spec-mocha/api.load-spec.js

@ -0,0 +1,123 @@
var expect = require('chai').expect;
describe('c3 api load', function () {
var chart, args;
beforeEach(function (done) {
chart = window.initChart(chart, args, done);
});
describe('indexed data', function () {
describe('as column', function () {
it('should update args', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 5000, 2000, 1000, 4000, 1500, 2500]
]
}
};
expect(true).to.be.ok;
});
it('should load additional data', function (done) {
var main = chart.internal.main,
legend = chart.internal.legend;
chart.load({
columns: [
['data3', 800, 500, 900, 500, 1000, 700]
]
});
setTimeout(function () {
var target = main.select('.c3-chart-line.c3-target.c3-target-data3'),
legendItem = legend.select('.c3-legend-item.c3-legend-item-data3');
expect(target.size()).to.equal(1);
expect(legendItem.size()).to.equal(1);
done();
}, 500);
});
});
});
describe('category data', function () {
it('should update arg to category data', function () {
args = {
data: {
x: 'x',
columns: [
['x', 'cat1', 'cat2', 'cat3', 'cat4', 'cat5', 'cat6'],
['data1', 30, 200, 100, 400, 150, 250],
['data2', 5000, 2000, 1000, 4000, 1500, 2500]
]
},
axis: {
x: {
type: 'category'
}
}
};
expect(true).to.be.ok;
});
describe('as column', function () {
it('should load additional data', function (done) {
var main = chart.internal.main,
legend = chart.internal.legend;
chart.load({
columns: [
['data3', 800, 500, 900, 500, 1000, 700]
]
});
setTimeout(function () {
var target = main.select('.c3-chart-line.c3-target.c3-target-data3'),
legendItem = legend.select('.c3-legend-item.c3-legend-item-data3'),
tickTexts = main.selectAll('.c3-axis-x g.tick text'),
expected = ['cat1', 'cat2', 'cat3', 'cat4', 'cat5', 'cat6'];
expect(target.size()).to.equal(1);
expect(legendItem.size()).to.equal(1);
tickTexts.each(function (d, i) {
var text = d3.select(this).select('tspan').text();
expect(text).to.equal(expected[i]);
});
done();
}, 500);
});
it('should load additional data', function (done) {
var main = chart.internal.main,
legend = chart.internal.legend;
chart.load({
columns: [
['x', 'new1', 'new2', 'new3', 'new4', 'new5', 'new6'],
['data3', 800, 500, 900, 500, 1000, 700]
]
});
setTimeout(function () {
var target = main.select('.c3-chart-line.c3-target.c3-target-data3'),
legendItem = legend.select('.c3-legend-item.c3-legend-item-data3'),
tickTexts = main.selectAll('.c3-axis-x g.tick text'),
expected = ['new1', 'new2', 'new3', 'new4', 'new5', 'new6'];
expect(target.size()).to.equal(1);
expect(legendItem.size()).to.equal(1);
tickTexts.each(function (d, i) {
var text = d3.select(this).select('tspan').text();
expect(text).to.equal(expected[i]);
});
done();
}, 500);
});
});
});
});

252
spec-mocha/api.region-spec.js

@ -0,0 +1,252 @@
var expect = require('chai').expect;
describe('c3 api region', function () {
var chart, args;
beforeEach(function (done) {
chart = window.initChart(chart, args, done);
});
describe('api.region', function () {
it('should update args', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
]
},
regions: [
{
axis: 'y',
start: 300,
end: 400,
class: 'green',
},
{
axis: 'y',
start: 0,
end: 100,
class: 'green',
}
]
};
expect(true).to.be.ok;
});
it('should update regions', function (done) {
var main = chart.internal.main,
expectedRegions = [
{
axis: 'y',
start: 250,
end: 350,
class: 'red'
},
{
axis: 'y',
start: 25,
end: 75,
class: 'red'
}
],
regions;
// Call regions API
chart.regions(expectedRegions);
setTimeout(function () {
regions = main.selectAll('.c3-region');
expect(regions.size()).to.equal(expectedRegions.length);
regions.each(function (d, i) {
var region = d3.select(this),
rect = region.select('rect'),
y = +rect.attr('y'),
height = +rect.attr('height'),
expectedClass = 'red',
unexpectedClass = 'green',
expectedStart = Math.round(chart.internal.y(expectedRegions[i].start)),
expectedEnd = Math.round(chart.internal.y(expectedRegions[i].end)),
expectedY = expectedEnd,
expectedHeight = expectedStart - expectedEnd;
expect(y).to.be.closeTo(expectedY, -1);
expect(height).to.be.closeTo(expectedHeight, -1);
expect(region.classed(expectedClass)).to.be.ok;
expect(region.classed(unexpectedClass)).to.not.be.ok;
});
}, 500);
setTimeout(function () {
done();
}, 1000);
});
});
describe('api.region.add', function () {
it('should update args', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
]
},
regions: [
{
axis: 'y',
start: 300,
end: 400,
class: 'green',
},
{
axis: 'y',
start: 0,
end: 100,
class: 'green',
}
]
};
expect(true).to.be.ok;
});
it('should add regions', function (done) {
var main = chart.internal.main,
expectedRegions = [
{
axis: 'y',
start: 300,
end: 400,
class: 'green',
},
{
axis: 'y',
start: 0,
end: 100,
class: 'green',
},
{
axis: 'y',
start: 250,
end: 350,
class: 'red'
},
{
axis: 'y',
start: 25,
end: 75,
class: 'red'
}
],
expectedClasses = [
'green',
'green',
'red',
'red',
],
regions;
// Call regions API
chart.regions(expectedRegions);
setTimeout(function () {
regions = main.selectAll('.c3-region');
expect(regions.size()).to.equal(expectedRegions.length);
regions.each(function (d, i) {
var region = d3.select(this),
rect = region.select('rect'),
y = +rect.attr('y'),
height = +rect.attr('height'),
expectedClass = expectedClasses[i],
expectedStart = Math.round(chart.internal.y(expectedRegions[i].start)),
expectedEnd = Math.round(chart.internal.y(expectedRegions[i].end)),
expectedY = expectedEnd,
expectedHeight = expectedStart - expectedEnd;
expect(y).to.be.closeTo(expectedY, -1);
expect(height).to.be.closeTo(expectedHeight, -1);
expect(region.classed(expectedClass)).to.be.ok;
});
}, 500);
setTimeout(function () {
done();
}, 1000);
});
});
describe('api.region.remove', function () {
it('should update args', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
]
},
regions: [
{
axis: 'y',
start: 300,
end: 400,
class: 'green',
},
{
axis: 'y',
start: 0,
end: 100,
class: 'green',
},
{
axis: 'y',
start: 250,
end: 350,
class: 'red'
},
]
};
expect(true).to.be.ok;
});
it('should remove regions', function (done) {
var main = chart.internal.main,
expectedRegions = [
{
axis: 'y',
start: 250,
end: 350,
class: 'red'
},
],
expectedClasses = ['red'],
regions;
// Call regions API
chart.regions(expectedRegions);
setTimeout(function () {
regions = main.selectAll('.c3-region');
expect(regions.size()).to.equal(expectedRegions.length);
regions.each(function (d, i) {
var region = d3.select(this),
rect = region.select('rect'),
y = +rect.attr('y'),
height = +rect.attr('height'),
expectedClass = expectedClasses[i],
expectedStart = Math.round(chart.internal.y(expectedRegions[i].start)),
expectedEnd = Math.round(chart.internal.y(expectedRegions[i].end)),
expectedY = expectedEnd,
expectedHeight = expectedStart - expectedEnd;
expect(y).to.be.closeTo(expectedY, -1);
expect(height).to.be.closeTo(expectedHeight, -1);
expect(region.classed(expectedClass)).to.be.ok;
});
}, 500);
setTimeout(function () {
done();
}, 1000);
});
});
});

117
spec-mocha/api.zoom-spec.js

@ -0,0 +1,117 @@
var expect = require('chai').expect;
describe('c3 api zoom', function () {
var chart, args;
beforeEach(function (done) {
chart = window.initChart(chart, args, done);
});
describe('zoom', function () {
it('should update args', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25],
['data3', 150, 120, 110, 140, 115, 125]
]
},
zoom: {
enabled: true
}
};
expect(true).to.be.ok;
});
it('should be zoomed properly', function () {
var target = [3, 5], domain;
chart.zoom(target);
domain = chart.internal.x.domain();
expect(domain[0]).to.equal(target[0]);
expect(domain[1]).to.equal(target[1]);
});
it('should be zoomed properly again', function () {
var target = [1, 4], domain;
chart.zoom(target);
domain = chart.internal.x.domain();
expect(domain[0]).to.equal(target[0]);
expect(domain[1]).to.equal(target[1]);
});
it('should load timeseries data', function () {
args = {
data: {
x: 'date',
columns: [
['date', '2014-01-01', '2014-01-02', '2014-08-01', '2014-10-19'],
['data1', 30, 200, 100, 400]
]
},
axis: {
x: {
type: 'timeseries'
}
},
zoom: {
enabled: true
}
};
expect(true).to.be.ok;
});
it('should be zoomed properly', function () {
var target = [new Date(2014, 7, 1), new Date(2014, 8, 1)], domain;
chart.zoom(target);
domain = chart.internal.x.domain();
expect(+domain[0]).to.equal(+target[0]);
expect(+domain[1]).to.equal(+target[1]);
});
it('should be zoomed properly', function () {
var target = ['2014-08-01', '2014-09-01'], domain;
chart.zoom(target);
domain = chart.internal.x.domain();
expect(+domain[0]).to.equal(+chart.internal.parseDate(target[0]));
expect(+domain[1]).to.equal(+chart.internal.parseDate(target[1]));
});
});
describe('unzoom', function () {
it('should load indexed data', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250]
]
},
zoom: {
enabled: true
}
};
expect(true).to.be.ok;
});
it('should be unzoomed properly', function () {
var target = [1, 4], orginal = chart.internal.x.domain(), domain;
chart.zoom(target);
domain = chart.internal.x.domain();
expect(domain[0]).to.equal(target[0]);
expect(domain[1]).to.equal(target[1]);
chart.unzoom();
domain = chart.internal.x.domain();
expect(domain[0]).to.equal(orginal[0]);
expect(domain[1]).to.equal(orginal[1]);
});
});
});

161
spec-mocha/arc-spec.js

@ -0,0 +1,161 @@
var expect = require('chai').expect;
describe('c3 chart arc', function () {
var chart, args;
beforeEach(function (done) {
chart = window.initChart(chart, args, done);
});
describe('show pie chart', function () {
it('should update args to have pie chart', function () {
args = {
data: {
columns: [
['data1', 30],
['data2', 150],
['data3', 120]
],
type: 'pie'
}
};
expect(true).to.be.ok;
});
it('should have correct classes', function () {
var chartArc = d3.select('.c3-chart-arcs'),
arcs = {
data1: chartArc.select('.c3-chart-arc.c3-target.c3-target-data1')
.select('g.c3-shapes.c3-shapes-data1.c3-arcs.c3-arcs-data1')
.select('path.c3-shape.c3-shape.c3-arc.c3-arc-data1'),
data2: chartArc.select('.c3-chart-arc.c3-target.c3-target-data2')
.select('g.c3-shapes.c3-shapes-data2.c3-arcs.c3-arcs-data2')
.select('path.c3-shape.c3-shape.c3-arc.c3-arc-data2'),
data3: chartArc.select('.c3-chart-arc.c3-target.c3-target-data3')
.select('g.c3-shapes.c3-shapes-data3.c3-arcs.c3-arcs-data3')
.select('path.c3-shape.c3-shape.c3-arc.c3-arc-data3')
};
expect(arcs.data1.size()).to.equal(1);
expect(arcs.data2.size()).to.equal(1);
expect(arcs.data3.size()).to.equal(1);
});
it('should have correct d', function () {
expect(d3.select('.c3-arc-data1').attr('d')).toMatch(/M-124\..+,-171\..+A211\..+,211\..+ 0 0,1 -3\..+,-211\..+L0,0Z/);
expect(d3.select('.c3-arc-data2').attr('d')).toMatch(/M1\..+,-211\..+A211\..+,211\..+ 0 0,1 1\..+,211\..+L0,0Z/);
expect(d3.select('.c3-arc-data3').attr('d')).toMatch(/M1\..+,211\..+A211\..+,211\..+ 0 0,1 -124\..+,-171\..+L0,0Z/);
});
it('should set args with data id that can be converted to a color', function () {
args.data.columns = [
['black', 30],
['data2', 150],
['data3', 120]
];
expect(true).to.be.ok;
});
it('should have correct d even if data id can be converted to a color', function (done) {
setTimeout(function () {
expect(d3.select('.c3-arc-black').attr('d')).toMatch(/M-124\..+,-171\..+A211\..+,211\..+ 0 0,1 -3\..+,-211\..+L0,0Z/);
done();
}, 500);
});
it('should update args to have empty pie chart', function () {
args = {
data: {
columns: [
['data1', null],
['data2', null],
['data3', null]
],
type: 'pie'
}
};
expect(true).to.be.ok;
});
it('should have correct d attribute', function () {
var chartArc = d3.select('.c3-chart-arcs'),
arcs = {
data1: chartArc.select('.c3-chart-arc.c3-target.c3-target-data1')
.select('g.c3-shapes.c3-shapes-data1.c3-arcs.c3-arcs-data1')
.select('path.c3-shape.c3-shape.c3-arc.c3-arc-data1'),
data2: chartArc.select('.c3-chart-arc.c3-target.c3-target-data2')
.select('g.c3-shapes.c3-shapes-data2.c3-arcs.c3-arcs-data2')
.select('path.c3-shape.c3-shape.c3-arc.c3-arc-data2'),
data3: chartArc.select('.c3-chart-arc.c3-target.c3-target-data3')
.select('g.c3-shapes.c3-shapes-data3.c3-arcs.c3-arcs-data3')
.select('path.c3-shape.c3-shape.c3-arc.c3-arc-data3')
};
expect(arcs.data1.attr('d').indexOf('NaN')).to.equal(-1);
expect(arcs.data2.attr('d').indexOf('NaN')).to.equal(-1);
expect(arcs.data3.attr('d').indexOf('NaN')).to.equal(-1);
});
});
describe('show gauge', function () {
it('should update args to have a 180 degree gauge', function () {
args = {
gauge: {
width: 10,
max: 10,
expand: true
},
data: {
columns: [
['data', 8]
],
type: 'gauge'
}
};
expect(true).to.be.ok;
});
it('should have correct d for Pi radian gauge', function () {
var chartArc = d3.select('.c3-chart-arcs'),
data = chartArc.select('.c3-chart-arc.c3-target.c3-target-data')
.select('g.c3-shapes.c3-shapes-data.c3-arcs.c3-arcs-data')
.select('path.c3-shape.c3-shape.c3-arc.c3-arc-data');
expect(data.attr('d')).toMatch(/M-304,-3\..+A304,304 0 0,1 245\..+,-178\..+L237\..+,-172\..+A294,294 0 0,0 -294,-3\..+Z/);
});
it('should update args to have a 2 Pi radian gauge that starts at Pi/2', function() {
args = {
gauge: {
width: 10,
max: 10,
expand: true,
fullCircle: true
},
data: {
columns: [
['data', 8]
],
type: 'gauge',
fullCircle: true,
startingAngle: Math.PI/2
}
};
expect(true).to.be.ok;
});
it('should have correct d for 2 Pi radian gauge starting at Pi/2', function() {
var chartArc = d3.select('.c3-chart-arcs'),
data = chartArc.select('.c3-chart-arc.c3-target.c3-target-data')
.select('g.c3-shapes.c3-shapes-data.c3-arcs.c3-arcs-data')
.select('path.c3-shape.c3-shape.c3-arc.c3-arc-data');
// This test has bee updated to make tests pass. @TODO double-check this test is accurate.
expect(data.attr('d')).toMatch(/M-221.*?,-2\..+A221.*?,221.*? 0 1,1 -68.*?,210.*?L-65.*?,201.*?A211.*?,211.*? 0 1,0 -211.*?,-2.*?Z/);
});
});
});

842
spec-mocha/axis-spec.js

@ -0,0 +1,842 @@
var expect = require('chai').expect;
describe('c3 chart axis', function () {
var chart;
var args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25],
['data3', 150, 120, 110, 140, 115, 125]
]
},
axis: {
y: {
tick: {
values: null,
count: undefined
}
},
y2: {
tick: {
values: null,
count: undefined
}
}
}
};
beforeEach(function (done) {
chart = window.initChart(chart, args, done);
});
describe('axis.y.tick.count', function () {
it('should update args to have only 1 tick on y axis', function () {
args.axis.y.tick.count = 1;
expect(true).to.be.ok;
});
it('should have only 1 tick on y axis', function () {
var ticksSize = d3.select('.c3-axis-y').selectAll('g.tick').size();
expect(ticksSize).to.equal(1);
});
it('should update args to have 2 ticks on y axis', function () {
args.axis.y.tick.count = 2;
expect(true).to.be.ok;
});
it('should have 2 ticks on y axis', function () {
var ticksSize = d3.select('.c3-axis-y').selectAll('g.tick').size();
expect(ticksSize).to.equal(2);
});
it('should update args to have 3 ticks on y axis', function () {
args.axis.y.tick.count = 3;
expect(true).to.be.ok;
});
it('should have 3 ticks on y axis', function () {
var ticksSize = d3.select('.c3-axis-y').selectAll('g.tick').size();
expect(ticksSize).to.equal(3);
});
});
describe('axis.y.tick.values', function () {
var values = [100, 500];
it('should update args to have only 2 ticks on y axis', function () {
args.axis.y.tick.values = values;
expect(true).to.be.ok;
});
it('should have only 2 tick on y axis', function () {
var ticksSize = d3.select('.c3-axis-y').selectAll('g.tick').size();
expect(ticksSize).to.equal(2);
});
it('should have specified tick texts', function () {
d3.select('.c3-axis-y').selectAll('g.tick').each(function (d, i) {
var text = d3.select(this).select('text').text();
expect(+text).to.equal(values[i]);
});
});
});
describe('axis y timeseries', function () {
it('should update args', function () {
args = {
data: {
columns: [
["times", 60000, 120000, 180000, 240000]
]
},
axis: {
y: {
type : 'timeseries',
tick: {
time: {
}
}
}
}
};
expect(true).to.be.ok;
});
it('should have 7 ticks on y axis', function () {
var ticksSize = d3.select('.c3-axis-y').selectAll('g.tick').size();
expect(ticksSize).to.equal(7); // the count starts at initial value and increments by the set interval
});
it('should have specified 30 second intervals', function () {
var prevValue;
d3.select('.c3-axis-y').selectAll('g.tick').each(function (d, i) {
if (i !== 0) {
var result = d - prevValue;
expect(result).toEqual(30000); // expressed in milliseconds
}
prevValue = d;
});
});
it('should update args to set axis.y.time', function () {
args.axis.y.tick.time = {
value : 'seconds',
interval : 60
};
expect(true).to.be.ok;
});
it('should have 4 ticks on y axis', function () {
var ticksSize = d3.select('.c3-axis-y').selectAll('g.tick').size();
expect(ticksSize).to.equal(4); // the count starts at initial value and increments by the set interval
});
it('should have specified 60 second intervals', function () {
var prevValue;
d3.select('.c3-axis-y').selectAll('g.tick').each(function (d, i) {
if (i !== 0) {
var result = d - prevValue;
expect(result).toEqual(60000); // expressed in milliseconds
}
prevValue = d;
});
});
});
describe('axis.x.tick.values', function () {
describe('function is provided', function () {
var tickGenerator = function () {
var values = [];
for (var i = 0; i <= 300; i += 50) {
values.push(i);
}
return values;
};
beforeEach(function () {
args.axis.x = {
tick: {
values: tickGenerator
}
};
chart = window.c3.generate(args);
window.generatedTicks = tickGenerator();
});
it('should use function to generate ticks', function () {
d3.select('.c3-axis-x').selectAll('g.tick').each(function (d, i) {
var tick = d3.select(this).select('text').text();
expect(+tick).to.equal(window.generatedTicks[i]);
});
});
});
});
describe('axis.x.tick.width', function () {
describe('indexed x axis and y/y2 axis', function () {
describe('not rotated', function () {
it('should update args successfully', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25]
],
axes: {
data2: 'y2'
}
},
axis: {
y2: {
show: true
}
}
};
expect(true).to.be.ok;
});
it('should construct indexed x axis properly', function () {
var ticks = chart.internal.main.select('.c3-axis-x').selectAll('g.tick'),
expectedX = '0',
expectedDy = '.71em';
expect(ticks.size()).to.equal(6);
ticks.each(function (d, i) {
var tspans = d3.select(this).selectAll('tspan');
expect(tspans.size()).to.equal(1);
tspans.each(function () {
var tspan = d3.select(this);
expect(tspan.text()).to.equal(i + '');
expect(tspan.attr('x')).to.equal(expectedX);
expect(tspan.attr('dy')).to.equal(expectedDy);
});
});
});
it('should set axis.x.tick.format', function () {
args.axis.x = {
tick: {
format: function () {
return 'very long tick text on x axis';
}
}
};
expect(true).to.be.ok;
});
it('should split x axis tick text to multiple lines', function () {
var ticks = chart.internal.main.select('.c3-axis-x').selectAll('g.tick'),
expectedTexts = ['very long tick text', 'on x axis'],
expectedX = '0';
expect(ticks.size()).to.equal(6);
ticks.each(function () {
var tspans = d3.select(this).selectAll('tspan');
expect(tspans.size()).to.equal(2);
tspans.each(function (d, i) {
var tspan = d3.select(this);
expect(tspan.text()).to.equal(expectedTexts[i]);
expect(tspan.attr('x')).to.equal(expectedX);
if (i === 0) {
expect(tspan.attr('dy')).to.equal('.71em');
} else {
expect(tspan.attr('dy')).to.be.above(8);
}
});
});
});
it('should construct y axis properly', function () {
var ticks = chart.internal.main.select('.c3-axis-y').selectAll('g.tick'),
expectedX = '-9',
expectedDy = '3';
expect(ticks.size()).to.equal(9);
ticks.each(function (d) {
var tspans = d3.select(this).selectAll('tspan');
expect(tspans.size()).to.equal(1);
tspans.each(function () {
var tspan = d3.select(this);
expect(tspan.text()).to.equal(d + '');
expect(tspan.attr('x')).to.equal(expectedX);
expect(tspan.attr('dy')).to.equal(expectedDy);
});
});
});
it('should construct y2 axis properly', function () {
var ticks = chart.internal.main.select('.c3-axis-y2').selectAll('g.tick'),
expectedX = '9',
expectedDy = '3';
expect(ticks.size()).to.equal(9);
ticks.each(function (d) {
var tspans = d3.select(this).selectAll('tspan');
expect(tspans.size()).to.equal(1);
tspans.each(function () {
var tspan = d3.select(this);
expect(tspan.text()).to.equal(d + '');
expect(tspan.attr('x')).to.equal(expectedX);
expect(tspan.attr('dy')).to.equal(expectedDy);
});
});
});
it('should set big values in y', function () {
args.data.columns = [
['data1', 3000000000000000, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25]
];
expect(true).to.be.ok;
});
it('should not split y axis tick text to multiple lines', function () {
var ticks = chart.internal.main.select('.c3-axis-y2').selectAll('g.tick');
ticks.each(function () {
var tspans = d3.select(this).selectAll('tspan');
expect(tspans.size()).to.equal(1);
});
});
});
describe('rotated', function () {
it('should update args to rotate axis', function () {
args.axis.rotated = true;
expect(true).to.be.ok;
});
it('should split x axis tick text to multiple lines', function () {
var ticks = chart.internal.main.select('.c3-axis-x').selectAll('g.tick'),
expectedTexts = ['very long tick', 'text on x axis'],
expectedX = '-9';
expect(ticks.size()).to.equal(6);
ticks.each(function () {
var tspans = d3.select(this).selectAll('tspan');
expect(tspans.size()).to.equal(2);
tspans.each(function (d, i) {
var tspan = d3.select(this);
expect(tspan.text()).to.equal(expectedTexts[i]);
expect(tspan.attr('x')).to.equal(expectedX);
if (i === 0) {
expect(tspan.attr('dy')).to.be.below(0);
} else {
expect(tspan.attr('dy')).to.be.above(9);
}
});
});
});
it('should not split y axis tick text to multiple lines', function () {
var ticks = chart.internal.main.select('.c3-axis-y').selectAll('g.tick'),
expectedTexts = [
'0',
'500000000000000',
'1000000000000000',
'1500000000000000',
'2000000000000000',
'2500000000000000',
'3000000000000000'
],
expectedX = '0',
expectedDy = '.71em';
expect(ticks.size()).to.equal(7);
ticks.each(function (d, i) {
var tspans = d3.select(this).selectAll('tspan');
expect(tspans.size()).to.equal(1);
tspans.each(function () {
var tspan = d3.select(this);
expect(tspan.text()).to.equal(expectedTexts[i]);
expect(tspan.attr('x')).to.equal(expectedX);
expect(tspan.attr('dy')).to.equal(expectedDy);
});
});
});
});
});
describe('category axis', function () {
describe('not rotated', function () {
it('should update args successfully', function () {
args = {
data: {
x: 'x',
columns: [
['x', 'this is a very long tick text on category axis', 'cat1', 'cat2', 'cat3', 'cat4', 'cat5'],
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25]
]
},
axis: {
x: {
type: 'category'
}
}
};
expect(true).to.be.ok;
});
it('should locate ticks properly', function () {
var ticks = chart.internal.main.select('.c3-axis-x').selectAll('g.tick');
ticks.each(function (d, i) {
var tspans = d3.select(this).selectAll('tspan'),
expectedX = '0',
expectedDy = '.71em';
if (i > 0) { // i === 0 should be checked in next test
expect(tspans.size()).to.equal(1);
tspans.each(function () {
var tspan = d3.select(this);
expect(tspan.attr('x')).to.equal(expectedX);
expect(tspan.attr('dy')).to.equal(expectedDy);
});
}
});
});
it('should split tick text properly', function () {
var tick = chart.internal.main.select('.c3-axis-x').select('g.tick'),
tspans = tick.selectAll('tspan'),
expectedTickTexts = [
'this is a very',
'long tick text',
'on category axis'
],
expectedX = '0';
expect(tspans.size()).to.equal(3);
tspans.each(function (d, i) {
var tspan = d3.select(this);
expect(tspan.text()).to.equal(expectedTickTexts[i]);
expect(tspan.attr('x')).to.equal(expectedX);
// unable to define pricise number because it differs depends on environment..
if (i === 0) {
expect(tspan.attr('dy')).to.equal('.71em');
} else {
expect(tspan.attr('dy')).to.be.above(8);
}
});
});
});
describe('rotated', function () {
it('should update args to rotate axis', function () {
args.axis.rotated = true;
expect(true).to.be.ok;
});
it('should locate ticks on rotated axis properly', function () {
var ticks = chart.internal.main.select('.c3-axis-x').selectAll('g.tick');
ticks.each(function (d, i) {
var tspans = d3.select(this).selectAll('tspan'),
expectedX = '-9',
expectedDy = '3';
if (i > 0) { // i === 0 should be checked in next test
expect(tspans.size()).to.equal(1);
tspans.each(function () {
var tspan = d3.select(this);
expect(tspan.attr('x')).to.equal(expectedX);
expect(tspan.attr('dy')).to.equal(expectedDy);
});
}
});
});
it('should split tick text on rotated axis properly', function () {
var tick = chart.internal.main.select('.c3-axis-x').select('g.tick'),
tspans = tick.selectAll('tspan'),
expectedTickTexts = [
'this is a very',
'long tick text on',
'category axis'
],
expectedX = '-9';
expect(tspans.size()).to.equal(3);
tspans.each(function (d, i) {
var tspan = d3.select(this);
expect(tspan.text()).to.equal(expectedTickTexts[i]);
expect(tspan.attr('x')).to.equal(expectedX);
// unable to define pricise number because it differs depends on environment..
if (i === 0) {
expect(tspan.attr('dy')).to.be.below(0);
} else {
expect(tspan.attr('dy')).to.be.above(8);
}
});
});
});
describe('option used', function () {
describe('as null', function () {
it('should update args not to split ticks', function () {
args.axis.x.tick = {
multiline: false
};
expect(true).to.be.ok;
});
it('should split x tick', function () {
var tick = chart.internal.main.select('.c3-axis-x').select('g.tick'),
tspans = tick.selectAll('tspan');
expect(tspans.size()).to.equal(1);
});
});
describe('as value', function () {
it('should update args not to split ticks', function () {
args.axis.x.tick = {
width: 150
};
expect(true).to.be.ok;
});
it('should split x tick to 2 lines properly', function () {
var tick = chart.internal.main.select('.c3-axis-x').select('g.tick'),
tspans = tick.selectAll('tspan'),
expectedTickTexts = [
'this is a very long tick',
'text on category axis'
],
expectedX = '-9';
expect(tspans.size()).to.equal(2);
tspans.each(function (d, i) {
var tspan = d3.select(this);
expect(tspan.text()).to.equal(expectedTickTexts[i]);
expect(tspan.attr('x')).to.equal(expectedX);
// unable to define pricise number because it differs depends on environment..
if (i === 0) {
expect(tspan.attr('dy')).to.be.below(0);
} else {
expect(tspan.attr('dy')).to.be.above(8);
}
});
});
});
});
});
describe('with axis.x.tick.format', function () {
it('should update args to use axis.x.tick.format', function () {
args.axis.x.tick.format = function () {
return ['this is a very long tick text', 'on category axis'];
};
expect(true).to.be.ok;
});
it('should have multiline tick text', function () {
var tick = chart.internal.main.select('.c3-axis-x').select('g.tick'),
tspans = tick.selectAll('tspan'),
expectedTickTexts = ['this is a very long tick text', 'on category axis'];
expect(tspans.size()).to.equal(2);
tspans.each(function (d, i) {
var tspan = d3.select(this);
expect(tspan.text()).to.equal(expectedTickTexts[i]);
});
});
});
});
describe('axis.x.tick.rotate', function () {
describe('not rotated', function () {
it('should update args successfully', function () {
args = {
data: {
x: 'x',
columns: [
['x', 'category 1', 'category 2', 'category 3', 'category 4', 'category 5', 'category 6'],
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25]
]
},
axis: {
x: {
type: 'category',
tick: {
rotate: 60
}
}
}
};
expect(true).to.be.ok;
});
it('should rotate tick texts', function () {
chart.internal.main.selectAll('.c3-axis-x g.tick').each(function () {
var tick = d3.select(this),
text = tick.select('text'),
tspan = text.select('tspan');
expect(text.attr('transform')).to.equal('rotate(60)');
expect(text.attr('y')).to.equal('1.5');
expect(tspan.attr('dx')).to.equal('6.928203230275509');
});
});
it('should have automatically calculated x axis height', function () {
var box = chart.internal.main.select('.c3-axis-x').node().getBoundingClientRect(),
height = chart.internal.getHorizontalAxisHeight('x');
expect(box.height).to.be.above(50);
expect(height).to.be.closeTo(70, -1);
});
});
});
describe('axis.y.tick.rotate', function () {
describe('not rotated', function () {
it('should update args successfully', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250, 100, 600],
['data2', 50, 20, 10, 40, 15, 25],
]
},
axis: {
rotated: true,
y: {
tick: {
rotate: 45
}
}
}
};
expect(true).to.be.ok;
});
it('should rotate tick texts', function () {
chart.internal.main.selectAll('.c3-axis-y g.tick').each(function () {
var tick = d3.select(this),
text = tick.select('text'),
tspan = text.select('tspan');
expect(text.attr('transform')).to.equal('rotate(45)');
expect(text.attr('y')).to.equal('4');
expect(tspan.attr('dx')).to.be.closeTo('5.6', 0);
});
});
it('should have automatically calculated y axis width', function () {
var box = chart.internal.main.select('.c3-axis-y').node().getBoundingClientRect();
expect(box.width).to.be.closeTo(590, 1);
});
});
});
describe('axis.x.tick.fit', function () {
describe('axis.x.tick.fit = true', function () {
it('should set args for indexed data', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25],
['data3', 150, 120, 110, 140, 115, 125]
]
}
};
expect(true).to.be.ok;
});
it('should show fitted ticks on indexed data', function () {
var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick');
expect(ticks.size()).to.equal(6);
});
it('should set args for x-based data', function () {
args = {
data: {
x: 'x',
columns: [
['x', 10, 20, 100, 110, 200, 1000],
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25],
['data3', 150, 120, 110, 140, 115, 125]
]
}
};
expect(true).to.be.ok;
});
it('should show fitted ticks on indexed data', function () {
var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick');
expect(ticks.size()).to.equal(6);
});
it('should show fitted ticks after hide and show', function () {
chart.hide();
chart.show();
var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick');
expect(ticks.size()).to.equal(6);
});
});
describe('axis.x.tick.fit = false', function () {
it('should set args for indexed data', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25],
['data3', 150, 120, 110, 140, 115, 125]
]
},
axis: {
x: {
tick: {
fit: false
}
}
}
};
expect(true).to.be.ok;
});
it('should show fitted ticks on indexed data', function () {
var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick');
expect(ticks.size()).to.equal(11);
});
it('should set args for x-based data', function () {
args.data = {
x: 'x',
columns: [
['x', 10, 20, 100, 110, 200, 1000],
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25],
['data3', 150, 120, 110, 140, 115, 125]
]
};
expect(true).to.be.ok;
});
it('should show fitted ticks on indexed data', function () {
var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick');
expect(ticks.size()).to.equal(10);
});
it('should show fitted ticks after hide and show', function () {
chart.hide();
chart.show();
var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick');
expect(ticks.size()).to.equal(10);
});
});
});
describe('axis.y.inner', function () {
it('should update args', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25]
]
},
axis: {
y: {
inner: false
}
}
};
expect(true).to.be.ok;
});
it('should not have inner y axis', function () {
var paddingLeft = chart.internal.getCurrentPaddingLeft(),
tickTexts = chart.internal.main.selectAll('.c3-axis-y g.tick text');
expect(paddingLeft).to.be.above(19);
tickTexts.each(function () {
expect(+d3.select(this).attr('x')).to.be.below(0);
});
});
it('should update args to have inner y axis', function () {
args.axis.y.inner = true;
expect(true).to.be.ok;
});
it('should have inner y axis', function () {
var paddingLeft = chart.internal.getCurrentPaddingLeft(),
tickTexts = chart.internal.main.selectAll('.c3-axis-y g.tick text');
expect(paddingLeft).to.equal(1);
tickTexts.each(function () {
expect(+d3.select(this).attr('x')).to.be.above(0);
});
});
});
describe('axis.y2.inner', function () {
it('should update args', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25]
]
},
axis: {
y2: {
show: true,
inner: false
}
}
};
expect(true).to.be.ok;
});
it('should not have inner y axis', function () {
var paddingRight = chart.internal.getCurrentPaddingRight(),
tickTexts = chart.internal.main.selectAll('.c3-axis-2y g.tick text');
expect(paddingRight).to.be.above(19);
tickTexts.each(function () {
expect(+d3.select(this).attr('x')).to.be.above(0);
});
});
it('should update args to have inner y axis', function () {
args.axis.y2.inner = true;
expect(true).to.be.ok;
});
it('should have inner y axis', function () {
var paddingRight = chart.internal.getCurrentPaddingRight(),
tickTexts = chart.internal.main.selectAll('.c3-axis-2y g.tick text');
expect(paddingRight).to.equal(2);
tickTexts.each(function () {
expect(+d3.select(this).attr('x')).to.be.below(0);
});
});
});
});

47
spec-mocha/c3-helper.js

@ -0,0 +1,47 @@
function initDom() {
var div = document.createElement('div');
div.id = 'chart';
div.style.width = '640px';
div.style.height = '480px';
document.body.appendChild(div);
document.body.style.margin = '0px';
}
typeof initDom !== 'undefined';
function setMouseEvent(chart, name, x, y, element) {
var paddingLeft = chart.internal.main.node().transform.baseVal.getItem(0).matrix.e,
event = document.createEvent("MouseEvents");
event.initMouseEvent(name, true, true, window,
0, 0, 0, x + paddingLeft, y + 5,
false, false, false, false, 0, null);
chart.internal.d3.event = event;
if (element) { element.dispatchEvent(event); }
}
typeof setMouseEvent !== 'undefined';
function initChart(chart, args, done) {
if (typeof chart === 'undefined') {
window.initDom();
}
if (args) {
chart = window.c3.generate(args);
window.d3 = chart.internal.d3;
window.d3.select('.jasmine_html-reporter')
.style('position', 'absolute')
.style('width', '640px')
.style('right', 0);
}
window.setTimeout(function () {
done();
}, 10);
return chart;
}
typeof initChart !== 'undefined';

12
spec-mocha/c3-spec.js

@ -0,0 +1,12 @@
var expect = require('chai').expect;
describe('c3', function () {
var c3 = window.c3;
it('exists', function () {
expect(c3).not.to.be.null;
expect(typeof c3).to.equal('object');
});
});

63
spec-mocha/class-spec.js

@ -0,0 +1,63 @@
var expect = require('chai').expect;
describe('c3 chart class', function () {
var chart;
var args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2 prefix', 50, 20, 10, 40, 15, 25],
['data3 мужчины', 150, 120, 110, 140, 115, 125]
]
}
};
beforeEach(function (done) {
chart = window.initChart(chart, args, done);
});
describe('internal.getTargetSelectorSuffix', function () {
it('should not replace any characters', function () {
var input = 'data1',
expected = '-' + input,
suffix = chart.internal.getTargetSelectorSuffix(input);
expect(suffix).to.equal(expected);
});
it('should replace space to "-"', function () {
var input = 'data1 suffix',
expected = '-data1-suffix',
suffix = chart.internal.getTargetSelectorSuffix(input);
expect(suffix).to.equal(expected);
});
it('should replace space to "-" with multibyte characters', function () {
var input = 'data1 suffix 日本語',
expected = '-data1-suffix-日本語',
suffix = chart.internal.getTargetSelectorSuffix(input);
expect(suffix).to.equal(expected);
});
it('should replace special charactors to "-"', function () {
var input = 'data1 !@#$%^&*()_=+,.<>"\':;[]/|?~`{}\\',
expected = '-data1--------------------------------',
suffix = chart.internal.getTargetSelectorSuffix(input);
expect(suffix).to.equal(expected);
});
});
describe('multibyte characters on chart', function () {
it('should replace space to "-" with multibyte characters', function () {
var selector = '.c3-target-data3-мужчины';
expect(chart.internal.main.select(selector).size()).to.equal(1);
});
});
});

160
spec-mocha/core-spec.js

@ -0,0 +1,160 @@
var expect = require('chai').expect;
describe('c3 chart', function () {
var chart;
var args = {
svg: {
classname: 'customclass'
},
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25],
['data3', 150, 120, 110, 140, 115, 125]
]
}
};
beforeEach(function (done) {
chart = window.initChart(chart, args, done);
});
describe('init', function () {
it('should be created', function () {
var svg = d3.select('#chart svg');
expect(svg).not.to.be.null;
});
it('should set 3rd party property to Function', function () {
Function.prototype.$extIsFunction = true;
expect(true).to.be.ok;
});
it('should be created even if 3rd party property has been set', function () {
var svg = d3.select('#chart svg');
expect(svg).not.to.be.null;
});
it('should be created with a custom class', function () {
var svg = d3.select('#chart svg');
expect(svg.attr('class')).not.to.be.null;
expect(svg.attr('class')).to.equal('customclass');
});
});
describe('size', function () {
it('should have same width', function () {
var svg = d3.select('#chart svg');
expect(+svg.attr('width')).to.equal(640);
});
it('should have same height', function () {
var svg = d3.select('#chart svg');
expect(+svg.attr('height')).to.equal(480);
});
});
describe('bindto', function () {
describe('selector', function () {
it('update args', function () {
d3.select('#chart').html('');
args.bindto = '#chart';
expect(true).to.be.ok;
});
it('should be created', function () {
var svg = d3.select('#chart svg');
expect(svg.size()).to.equal(1);
});
});
describe('d3.selection object', function () {
it('update args', function () {
d3.select('#chart').html('');
args.bindto = d3.select('#chart');
expect(true).to.be.ok;
});
it('should be created', function () {
var svg = d3.select('#chart svg');
expect(svg.size()).to.equal(1);
});
});
describe('null', function () {
it('update args', function () {
d3.select('#chart').html('');
args.bindto = null;
expect(true).to.be.ok;
});
it('should not be created', function () {
var svg = d3.select('#chart svg');
expect(svg.size()).to.equal(0);
});
});
describe('empty string', function () {
it('update args', function () {
d3.select('#chart').html('');
args.bindto = '';
expect(true).to.be.ok;
});
it('should not be created', function () {
var svg = d3.select('#chart svg');
expect(svg.size()).to.equal(0);
});
});
});
describe('empty data', function () {
it('should upaate args for empty data', function () {
args = {
data: {
columns: [
['data1'],
['data2']
]
}
};
expect(true).to.be.ok;
});
it('should generate a chart', function () {
var ticks = chart.internal.main.select('.c3-axis-x').selectAll('g.tick');
expect(ticks.size()).to.equal(0);
});
it('should upaate args for empty data', function () {
args = {
data: {
x: 'x',
columns: [
['x'],
['data1'],
['data2']
]
},
axis: {
x: {
type: 'timeseries'
}
}
};
expect(true).to.be.ok;
});
it('should generate a chart', function () {
var ticks = chart.internal.main.select('.c3-axis-x').selectAll('g.tick');
expect(ticks.size()).to.equal(0);
});
});
});

1310
spec-mocha/data-spec.js

File diff suppressed because it is too large Load Diff

135
spec-mocha/domain-spec.js

@ -0,0 +1,135 @@
var expect = require('chai').expect;
describe('c3 chart domain', function () {
var chart;
var args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25]
]
},
axis: {
y: {},
y2: {}
}
};
beforeEach(function (done) {
chart = window.initChart(chart, args, done);
});
describe('axis.y.min', function () {
it('should change axis.y.min to -100', function () {
args.axis.y.min = -100;
expect(true).to.be.ok;
});
it('should be set properly when smaller than max of data', function () {
var domain = chart.internal.y.domain();
expect(domain[0]).to.equal(-150);
expect(domain[1]).to.equal(450);
});
it('should change axis.y.min to 500', function () {
args.axis.y.min = 500;
expect(true).to.be.ok;
});
it('should be set properly when bigger than max of data', function () {
var domain = chart.internal.y.domain();
expect(domain[0]).to.equal(499);
expect(domain[1]).to.equal(511);
});
it('should change axis.y.min to undefined', function () {
args.axis.y.min = undefined;
expect(true).to.be.ok;
});
});
describe('axis.y.max', function () {
it('should change axis.y.max to 1000', function () {
args.axis.y.max = 1000;
expect(true).to.be.ok;
});
it('should be set properly when bigger than min of data', function () {
var domain = chart.internal.y.domain();
expect(domain[0]).to.equal(-89);
expect(domain[1]).to.equal(1099);
});
it('should change axis.y.max to 0', function () {
args.axis.y.max = 0;
expect(true).to.be.ok;
});
it('should be set properly when smaller than min of data', function () {
var domain = chart.internal.y.domain();
expect(domain[0]).to.equal(-11);
expect(domain[1]).to.equal(1);
});
});
describe('axis.y.padding', function () {
it('should change axis.y.max to 1000', function () {
args = {
data: {
columns: [
['data1', 10, 20, 10, 40, 15, 25],
['data2', 50, 40, 30, 45, 25, 45]
]
},
axis: {
y: {
padding: 200,
}
}
};
expect(true).to.be.ok;
});
it('should be set properly when bigger than min of data', function () {
var domain = chart.internal.y.domain();
expect(domain[0]).to.be.closeTo(-9, -1);
expect(domain[1]).to.be.closeTo(69, -1);
});
it('should change axis.y.max to 1000 with top/bottom padding', function () {
args = {
data: {
columns: [
['data1', 10, 20, 10, 40, 15, 25],
['data2', 50, 40, 30, 45, 25, 45]
]
},
axis: {
y: {
padding: {
top: 200,
bottom: 200
}
}
}
};
expect(true).to.be.ok;
});
it('should be set properly when bigger than min of data', function () {
var domain = chart.internal.y.domain();
expect(domain[0]).to.be.closeTo(-9, -1);
expect(domain[1]).to.be.closeTo(69, -1);
});
});
});

367
spec-mocha/grid-spec.js

@ -0,0 +1,367 @@
var expect = require('chai').expect;
describe('c3 chart grid', function () {
var chart, args;
beforeEach(function (done) {
chart = window.initChart(chart, args, done);
});
describe('y grid show', function () {
it('should update args', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250]
]
},
axis: {
y: {
tick: {
}
}
},
grid: {
y: {
show: false
}
}
};
expect(true).to.be.ok;
});
it('should not show y grids', function () {
expect(chart.internal.main.select('.c3-ygrids').size()).to.equal(0);
});
it('should update args to show y grids', function () {
args.grid.y.show = true;
expect(true).to.be.ok;
});
it('should show y grids', function () {
var ygrids = chart.internal.main.select('.c3-ygrids');
expect(ygrids.size()).to.equal(1);
expect(ygrids.selectAll('.c3-ygrid').size()).to.equal(9);
});
it('should update args to show only 3 y grids', function () {
args.grid.y.ticks = 3;
expect(true).to.be.ok;
});
it('should show only 3 y grids', function () {
var ygrids = chart.internal.main.select('.c3-ygrids');
expect(ygrids.size()).to.equal(1);
expect(ygrids.selectAll('.c3-ygrid').size()).to.equal(3);
});
it('should update args to show y grids depending on y axis ticks', function () {
args.axis.y.tick.count = 5;
expect(true).to.be.ok;
});
it('should show grids depending on y axis ticks', function () {
var ygrids = chart.internal.main.select('.c3-ygrids'),
expectedYs = [];
ygrids.selectAll('.c3-ygrid').each(function (d, i) {
expectedYs[i] = +d3.select(this).attr('y1');
});
expect(ygrids.size()).to.equal(1);
expect(ygrids.selectAll('.c3-ygrid').size()).to.equal(5);
chart.internal.main.select('.c3-axis-y').selectAll('.tick').each(function (d, i) {
var t = d3.transform(d3.select(this).attr('transform'));
expect(t.translate[1]).to.equal(expectedYs[i]);
});
});
});
describe('y grid lines', function () {
describe('position', function () {
it('should update args', function () {
args = {
data: {
columns: [
['data1', 10, 200, 100, 400, 150, 250]
]
},
grid: {
y: {
lines: [
{value: 30, text: 'Label 30', position: 'start'},
{value: 145, text: 'Label 145', position: 'middle'},
{value: 225, text: 'Label 225'}
]
}
}
};
expect(true).to.be.ok;
});
it('should show 3 grid lines', function () {
expect(chart.internal.main.selectAll('.c3-ygrid-lines .c3-ygrid-line').size()).to.equal(3);
});
it('should locate grid lines properly', function () {
var lines = chart.internal.main.selectAll('.c3-ygrid-lines .c3-ygrid-line'),
expectedY1s = [373, 268, 196];
lines.each(function (d, i) {
var y1 = d3.select(this).select('line').attr('y1');
expect(y1).to.be.closeTo(expectedY1s[i], -2);
});
});
it('should locate grid texts properly', function () {
var lines = chart.internal.main.selectAll('.c3-ygrid-lines .c3-ygrid-line'),
expectedPositions = ['start', 'middle', 'end'],
expectedDxs = [4, 0, -4];
lines.each(function (d, i) {
var text = d3.select(this).select('text'),
textAnchor = text.attr('text-anchor'),
dx = text.attr('dx');
expect(textAnchor).to.equal(expectedPositions[i]);
expect(+dx).to.equal(expectedDxs[i]);
});
});
it('should update args', function () {
args = {
data: {
columns: [
['data1', 10, 200, 100, 400, 150, 250]
]
},
axis: {
rotated: true
},
grid: {
y: {
lines: [
{value: 30, text: 'Label 30', position: 'start'},
{value: 145, text: 'Label 145', position: 'middle'},
{value: 225, text: 'Label 225'}
]
}
}
};
expect(true).to.be.ok;
});
it('should show 3 grid lines', function () {
expect(chart.internal.main.selectAll('.c3-ygrid-lines .c3-ygrid-line').size()).to.equal(3);
});
it('should locate grid lines properly', function () {
var lines = chart.internal.main.selectAll('.c3-ygrid-lines .c3-ygrid-line'),
expectedX1s = [75, 220, 321];
lines.each(function (d, i) {
var x1 = d3.select(this).select('line').attr('x1');
expect(x1).to.be.closeTo(expectedX1s[i], -2);
});
});
it('should locate grid texts properly', function () {
var lines = chart.internal.main.selectAll('.c3-ygrid-lines .c3-ygrid-line'),
expectedPositions = ['start', 'middle', 'end'],
expectedDxs = [4, 0, -4];
lines.each(function (d, i) {
var text = d3.select(this).select('text'),
textAnchor = text.attr('text-anchor'),
dx = text.attr('dx');
expect(textAnchor).to.equal(expectedPositions[i]);
expect(+dx).to.equal(expectedDxs[i]);
});
});
});
});
describe('x grid lines', function () {
describe('position', function () {
it('should have correct height', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400],
]
},
grid: {
x: {
lines: [
{value: 1, text: 'Label 1', position: 'start'},
{value: 2, text: 'Label 2', position: 'middle'},
{value: 3, text: 'Label 3'},
]
}
},
};
expect(true).to.be.ok;
});
it('should show 3 grid lines', function () {
expect(chart.internal.main.selectAll('.c3-xgrid-lines .c3-xgrid-line').size()).to.equal(3);
});
it('should locate grid lines properly', function () {
var lines = chart.internal.main.selectAll('.c3-xgrid-lines .c3-xgrid-line'),
expectedX1s = [202, 397, 593];
lines.each(function (d, i) {
var x1 = d3.select(this).select('line').attr('x1');
expect(x1).to.be.closeTo(expectedX1s[i], -2);
});
});
it('should locate grid texts properly', function () {
var lines = chart.internal.main.selectAll('.c3-xgrid-lines .c3-xgrid-line'),
expectedPositions = ['start', 'middle', 'end'],
expectedDxs = [4, 0, -4];
lines.each(function (d, i) {
var text = d3.select(this).select('text'),
textAnchor = text.attr('text-anchor'),
dx = text.attr('dx');
expect(textAnchor).to.equal(expectedPositions[i]);
expect(+dx).to.equal(expectedDxs[i]);
});
});
it('should update args', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400],
]
},
axis: {
rotated: true
},
grid: {
x: {
lines: [
{value: 1, text: 'Label 1', position: 'start'},
{value: 2, text: 'Label 2', position: 'middle'},
{value: 3, text: 'Label 3'},
]
}
},
};
expect(true).to.be.ok;
});
it('should show 3 grid lines', function () {
expect(chart.internal.main.selectAll('.c3-xgrid-lines .c3-xgrid-line').size()).to.equal(3);
});
it('should locate grid lines properly', function () {
var lines = chart.internal.main.selectAll('.c3-xgrid-lines .c3-xgrid-line'),
expectedY1s = [144, 283, 421];
lines.each(function (d, i) {
var y1 = d3.select(this).select('line').attr('y1');
expect(y1).to.be.closeTo(expectedY1s[i], -2);
});
});
it('should locate grid texts properly', function () {
var lines = chart.internal.main.selectAll('.c3-xgrid-lines .c3-xgrid-line'),
expectedPositions = ['start', 'middle', 'end'],
expectedDxs = [4, 0, -4];
lines.each(function (d, i) {
var text = d3.select(this).select('text'),
textAnchor = text.attr('text-anchor'),
dx = text.attr('dx');
expect(textAnchor).to.equal(expectedPositions[i]);
expect(+dx).to.equal(expectedDxs[i]);
});
});
});
describe('with padding.top', function () {
it('should have correct height', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400],
]
},
grid: {
x: {
lines: [
{value: 3, text: 'Label 3'}
]
}
},
padding: {
top: 50
}
};
expect(true).to.be.ok;
});
it('should show x grid lines', function () {
var lines = chart.internal.main.select('.c3-xgrid-lines .c3-xgrid-line'),
expectedX1 = 593,
expectedText = ['Label 3'];
lines.each(function (id, i) {
var line = d3.select(this),
l = line.select('line'),
t = line.select('text');
expect(+l.attr('x1')).to.be.closeTo(expectedX1, -2);
expect(t.text()).to.equal(expectedText[i]);
});
});
});
describe('on category axis', function () {
it('should update args', function () {
args = {
data: {
x: 'x',
columns: [
['x', 'a', 'b', 'c', 'd'],
['data1', 30, 200, 100, 400],
]
},
axis: {
x: {
type: 'category'
}
},
grid: {
x: {
lines: [
{value: 3, text: 'Label 3'},
{value: 'a', text: 'Label a'}
]
}
}
};
expect(true).to.be.ok;
});
it('should show x grid lines', function () {
var lines = chart.internal.main.selectAll('.c3-xgrid-lines .c3-xgrid-line'),
expectedX1 = [515, 74],
expectedText = ['Label 3', 'Label a'];
lines.each(function (id, i) {
var line = d3.select(this),
l = line.select('line'),
t = line.select('text');
expect(+l.attr('x1')).to.be.closeTo(expectedX1[i], -2);
expect(t.text()).to.equal(expectedText[i]);
});
});
});
});
});

118
spec-mocha/interaction-spec.js

@ -0,0 +1,118 @@
var expect = require('chai').expect;
describe('c3 chart interaction', function () {
var chart, args;
beforeEach(function (done) {
chart = window.initChart(chart, args, done);
});
describe('generate event rects', function () {
describe('custom x', function () {
it('should generate bar chart', function () {
args = {
data: {
x: 'x',
columns: [
['x', 0, 1000, 3000, 10000],
['data', 10, 10, 10, 10]
],
type: 'bar'
}
};
expect(true).to.be.ok;
});
it('should have 4 event rects properly', function () {
var lefts = [78, 138, 205.5, 407.5],
widths = [60, 67.5, 202, 194];
d3.selectAll('.c3-event-rect').each(function (d, i) {
var box = d3.select(this).node().getBoundingClientRect();
expect(box.left).to.be.closeTo(lefts[i], -2);
expect(box.width).to.be.closeTo(widths[i], -2);
});
});
it('should generate bar chart with only one data', function () {
args = {
data: {
x: 'x',
columns: [
['x', 0],
['data', 10]
],
type: 'bar'
}
};
expect(true).to.be.ok;
});
it('should have 1 event rects properly', function () {
var eventRects = d3.selectAll('.c3-event-rect');
expect(eventRects.size()).to.equal(1);
eventRects.each(function () {
var box = d3.select(this).node().getBoundingClientRect();
expect(box.left).to.be.closeTo(40.5, -2);
expect(box.width).to.be.closeTo(598, -2);
});
});
});
describe('timeseries', function () {
it('should generate line chart with timeseries', function () {
args = {
data: {
x: 'x',
columns: [
['x', '20140101', '20140201', '20140210', '20140301'],
['data', 10, 10, 10, 10]
]
}
};
expect(true).to.be.ok;
});
it('should have 4 event rects properly', function () {
var lefts = [43.5, 193, 353, 500],
widths = [149.5, 160, 147, 136];
d3.selectAll('.c3-event-rect').each(function (d, i) {
var box = d3.select(this).node().getBoundingClientRect();
expect(box.left).to.be.closeTo(lefts[i], -2);
expect(box.width).to.be.closeTo(widths[i], -2);
});
});
it('should generate line chart with only 1 data timeseries', function () {
args = {
data: {
x: 'x',
columns: [
['x', '20140101'],
['data', 10]
]
}
};
expect(true).to.be.ok;
});
it('should have 1 event rects properly', function () {
var eventRects = d3.selectAll('.c3-event-rect');
expect(eventRects.size()).to.equal(1);
eventRects.each(function () {
var box = d3.select(this).node().getBoundingClientRect();
expect(box.left).to.be.closeTo(40.5, -2);
expect(box.width).to.be.closeTo(598, -2);
});
});
});
});
});

280
spec-mocha/legend-spec.js

@ -0,0 +1,280 @@
var expect = require('chai').expect;
describe('c3 chart legend', function () {
var chart, args;
beforeEach(function (done) {
chart = window.initChart(chart, args, done);
});
describe('legend when multiple charts rendered', function () {
it('should update args', function () {
args = {
data: {
columns: [
['data1', 30],
['data2', 50],
['data3', 100]
]
}
};
expect(true).to.be.ok;
});
it('should update args with long data names', function () {
args = {
data: {
columns: [
['long data name 1', 30],
['long data name 2', 50],
['long data name 3', 50],
]
}
};
expect(true).to.be.ok;
});
it('should have properly computed legend width', function () {
var expectedLeft = [148, 226, 384],
expectedWidth = [118, 118, 108];
d3.selectAll('.c3-legend-item').each(function (d, i) {
var rect = d3.select(this).node().getBoundingClientRect();
expect(rect.left).to.be.closeTo(expectedLeft[i], -2);
expect(rect.width).to.be.closeTo(expectedWidth[i], -2);
});
});
});
describe('legend position', function () {
it('should update args', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25]
]
}
};
expect(true).to.be.ok;
});
it('should be located on the center of chart', function () {
var box = chart.internal.legend.node().getBoundingClientRect();
expect(box.left + box.right).to.equal(640);
});
});
describe('legend as inset', function () {
it('should change the legend to "inset" successfully', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25]
]
},
legend: {
position: 'inset',
inset: {
step: null
}
}
};
expect(true).to.be.ok;
});
it('should be positioned properly', function () {
var box = d3.select('.c3-legend-background').node().getBoundingClientRect();
expect(box.top).to.equal(5.5);
expect(box.left).to.be.above(30);
});
it('should have automatically calculated height', function () {
var box = d3.select('.c3-legend-background').node().getBoundingClientRect();
expect(box.height).to.equal(48);
});
it('should change the legend step to 1 successfully', function () {
args.legend.inset.step = 1;
expect(true).to.be.ok;
});
it('should have automatically calculated height', function () {
var box = d3.select('.c3-legend-background').node().getBoundingClientRect();
expect(box.height).to.equal(28);
});
it('should change the legend step to 2 successfully', function () {
args.legend.inset.step = 2;
expect(true).to.be.ok;
});
it('should have automatically calculated height', function () {
var box = d3.select('.c3-legend-background').node().getBoundingClientRect();
expect(box.height).to.equal(48);
});
it('should update args to have only one series', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
]
},
legend: {
position: 'inset'
}
};
expect(true).to.be.ok;
});
it('should locate legend properly', function () {
var box = d3.select('.c3-legend-background').node().getBoundingClientRect();
expect(box.height).to.equal(28);
expect(box.width).to.be.above(64);
});
});
describe('legend.hide', function () {
it('should update args', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 130, 100, 200, 100, 250, 150]
]
},
legend: {
hide: true
}
};
expect(true).to.be.ok;
});
it('should not show legends', function () {
d3.selectAll('.c3-legend-item').each(function () {
expect(d3.select(this).style('visibility')).to.equal('hidden');
});
});
it('should update args', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 130, 100, 200, 100, 250, 150]
]
},
legend: {
hide: 'data2'
}
};
expect(true).to.be.ok;
});
it('should not show legends', function () {
expect(d3.select('.c3-legend-item-data1').style('visibility')).to.equal('visible');
expect(d3.select('.c3-legend-item-data2').style('visibility')).to.equal('hidden');
});
});
describe('legend.show', function () {
it('should update args', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 130, 100, 200, 100, 250, 150]
]
},
legend: {
show: false
}
};
expect(true).to.be.ok;
});
it('should not initially have rendered any legend items', function () {
expect(d3.selectAll('.c3-legend-item').empty()).to.equal(true);
});
it('allows us to show the legend on showLegend call', function () {
chart.legend.show();
d3.selectAll('.c3-legend-item').each(function () {
expect(d3.select(this).style('visibility')).to.equal('visible');
// This selects all the children, but we expect it to be empty
expect(d3.select(this).selectAll("*").length).not.toEqual(0);
});
});
});
describe('custom legend size', function() {
it('should update args', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 130, 100, 200, 100, 250, 150]
]
},
legend: {
item: {
tile: {
width: 15,
height: 2
}
}
}
};
expect(true).to.be.ok;
});
it('renders the legend item with the correct width and height', function () {
d3.selectAll('.c3-legend-item-tile').each(function () {
expect(d3.select(this).style('stroke-width')).to.equal(args.legend.item.tile.height + 'px');
var tileWidth = d3.select(this).attr('x2') - d3.select(this).attr('x1');
expect(tileWidth).to.equal(args.legend.item.tile.width);
});
});
});
describe('custom legend padding', function() {
it('should update args', function () {
args = {
data: {
columns: [
['padded1', 30, 200, 100, 400, 150, 250],
['padded2', 130, 100, 200, 100, 250, 150]
]
},
legend: {
padding: 10
}
};
expect(true).to.be.ok;
});
it('renders the correct amount of padding on the legend element', function () {
d3.selectAll('.c3-legend-item-padded1 .c3-legend-item-tile, .c3-legend-item-padded2 .c3-legend-item-tile').each(function (el, index) {
var itemWidth = d3.select(this).node().parentNode.getBBox().width,
textBoxWidth = d3.select(d3.select(this).node().parentNode).select('text').node().getBBox().width,
tileWidth = 15, // default value is 10, plus 5 more for padding
expectedWidth = textBoxWidth + tileWidth + (index ? 0 : 10) + args.legend.padding;
expect(itemWidth).to.equal(expectedWidth);
});
});
});
});

183
spec-mocha/shape.bar-spec.js

@ -0,0 +1,183 @@
var expect = require('chai').expect;
var setMouseEvent = window.setMouseEvent;
describe('c3 chart shape bar', function () {
var chart, args;
beforeEach(function (done) {
chart = window.initChart(chart, args, done);
});
describe('with groups', function () {
describe('with indexed data', function () {
it('should update args', function () {
args = {
data: {
columns: [
['data1', 30, 200, -100, 400, -150, 250],
['data2', 50, 20, 10, 40, 15, 25],
],
groups: [
['data1', 'data2'],
],
type: 'bar'
},
};
expect(true).to.be.ok;
});
it('should be stacked', function () {
var expectedBottom = [275, 293, 365, 281, 395, 290];
chart.internal.main.selectAll('.c3-bars-data1 .c3-bar').each(function (d, i) {
var rect = d3.select(this).node().getBoundingClientRect();
expect(rect.bottom).to.be.closeTo(expectedBottom[i], -1);
});
});
});
describe('with timeseries data', function () {
it('should update args', function () {
args = {
data: {
x: 'date',
columns: [
['date', '2012-12-24', '2012-12-25', '2012-12-26', '2012-12-27', '2012-12-28', '2012-12-29'],
['data1', 30, 200, -100, 400, -150, 250],
['data2', 50, 20, 10, 40, 15, 25],
],
groups: [
['data1', 'data2'],
],
type: 'bar'
},
axis: {
x: {
type: 'timeseries',
}
}
};
expect(true).to.be.ok;
});
it('should be stacked', function () {
var expectedBottom = [275, 293, 365, 281, 395, 290];
chart.internal.main.selectAll('.c3-bars-data1 .c3-bar').each(function (d, i) {
var rect = d3.select(this).node().getBoundingClientRect();
expect(rect.bottom).to.be.closeTo(expectedBottom[i], -1);
});
});
});
describe('with category data', function () {
it('should update args', function () {
args = {
data: {
x: 'date',
columns: [
['date', '2012-12-24', '2012-12-25', '2012-12-26', '2012-12-27', '2012-12-28', '2012-12-29'],
['data1', 30, 200, -100, 400, -150, 250],
['data2', 50, 20, 10, 40, 15, 25],
],
groups: [
['data1', 'data2'],
],
type: 'bar'
},
axis: {
x: {
type: 'category',
}
}
};
expect(true).to.be.ok;
});
it('should be stacked', function () {
var expectedBottom = [275, 293, 365, 281, 395, 290];
chart.internal.main.selectAll('.c3-bars-data1 .c3-bar').each(function (d, i) {
var rect = d3.select(this).node().getBoundingClientRect();
expect(rect.bottom).to.be.closeTo(expectedBottom[i], -1);
});
});
});
});
describe('internal.isWithinBar', function () {
describe('with normal axis', function () {
it('should update args', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, -150, 250],
['data2', 50, 20, 10, 40, 15, 25],
['data3', -150, 120, 110, 140, 115, 125]
],
type: 'bar'
},
axis: {
rotated: false
}
};
expect(true).to.be.ok;
});
it('should not be within bar', function () {
var bar = d3.select('.c3-target-data1 .c3-bar-0').node();
setMouseEvent(chart, 'click', 0, 0);
expect(chart.internal.isWithinBar(bar)).to.not.be.ok;
});
it('should be within bar', function () {
var bar = d3.select('.c3-target-data1 .c3-bar-0').node();
setMouseEvent(chart, 'click', 31, 280);
expect(chart.internal.isWithinBar(bar)).to.be.ok;
});
it('should not be within bar of negative value', function () {
var bar = d3.select('.c3-target-data3 .c3-bar-0').node();
setMouseEvent(chart, 'click', 68, 280);
expect(chart.internal.isWithinBar(bar)).to.not.be.ok;
});
it('should be within bar of negative value', function () {
var bar = d3.select('.c3-target-data3 .c3-bar-0').node();
setMouseEvent(chart, 'click', 68, 350);
expect(chart.internal.isWithinBar(bar)).to.be.ok;
});
});
describe('with rotated axis', function () {
it('should change the chart as axis rotated', function () {
args.axis.rotated = true;
expect(true).to.be.ok;
});
it('should not be within bar', function () {
var bar = d3.select('.c3-target-data1 .c3-bar-0').node();
setMouseEvent(chart, 'click', 0, 0);
expect(chart.internal.isWithinBar(bar)).to.not.be.ok;
});
it('should be within bar', function () {
var bar = d3.select('.c3-target-data1 .c3-bar-0').node();
setMouseEvent(chart, 'click', 190, 20);
expect(chart.internal.isWithinBar(bar)).to.be.ok;
});
it('should be within bar of negative value', function () {
var bar = d3.select('.c3-target-data3 .c3-bar-0').node();
setMouseEvent(chart, 'click', 68, 50);
expect(chart.internal.isWithinBar(bar)).to.be.ok;
});
});
});
});

172
spec-mocha/shape.line-spec.js

@ -0,0 +1,172 @@
var expect = require('chai').expect;
describe('c3 chart shape line', function () {
var chart, args;
beforeEach(function (done) {
chart = window.initChart(chart, args, done);
});
var parseSvgPath = window.parseSvgPath;
describe('shape-rendering for line chart', function () {
it('should update args', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, -150, 250],
['data2', 50, 20, 10, 40, 15, 25],
['data3', -150, 120, 110, 140, 115, 125]
],
type: 'line'
}
};
expect(true).to.be.ok;
});
it("Should render the lines correctly", function(done) {
setTimeout(function () {
var target = chart.internal.main.select('.c3-chart-line.c3-target-data1');
var commands = parseSvgPath( target.select('.c3-line-data1').attr('d'));
expect(commands.length).to.equal(6);
done();
}, 500);
});
it("should not have shape-rendering when it's line chart", function () {
d3.selectAll('.c3-line').each(function () {
var style = d3.select(this).style('shape-rendering');
expect(style).to.equal('auto');
});
});
it('should change to step chart', function () {
args.data.type = 'step';
expect(true).to.be.ok;
});
it("should have shape-rendering = crispedges when it's step chart", function () {
d3.selectAll('.c3-line').each(function () {
var style = d3.select(this).style('shape-rendering').toLowerCase();
expect(style).to.equal('crispedges');
});
});
it('should change to spline chart', function () {
args.data.type = 'spline';
expect(true).to.be.ok;
});
it('should use cardinal interpolation by default', function () {
expect(chart.internal.config.spline_interpolation_type).to.equal('cardinal');
});
});
describe('point.show option', function () {
it('should change args to include null data', function () {
args = {
data: {
columns: [
['data1', 30, null, 100, 400, -150, 250],
['data2', 50, 20, 10, 40, 15, 25],
['data3', -150, 120, 110, 140, 115, 125]
],
type: 'line'
}
};
expect(true).to.be.ok;
});
it('should not show the circle for null', function (done) {
setTimeout(function () {
var target = chart.internal.main.select('.c3-chart-line.c3-target-data1');
expect(+target.select('.c3-circle-0').style('opacity')).to.equal(1);
expect(+target.select('.c3-circle-1').style('opacity')).to.equal(0);
expect(+target.select('.c3-circle-2').style('opacity')).to.equal(1);
done();
}, 500);
});
it('should not draw a line segment for null data', function(done) {
setTimeout(function () {
var target = chart.internal.main.select('.c3-chart-line.c3-target-data1');
var commands = parseSvgPath( target.select('.c3-line-data1').attr('d'));
var segments = 0;
for(var i = 0; i < commands.length; i++) {
(commands[i].command === 'L') ? segments++ : null;
}
expect(segments).to.equal(3);
done();
}, 500);
});
// it('should change args to include null data on scatter plot', function () {
// args = {
// data: {
// columns: [
// ['data1', 30, null, 100, 400, -150, 250],
// ['data2', 50, 20, 10, 40, 15, 25],
// ['data3', -150, 120, 110, 140, 115, 125]
// ],
// type: 'scatter'
// }
// };
// expect(true).to.be.ok;
// });
// it('should not show the circle for null', function (done) {
// setTimeout(function () {
// var target = chart.internal.main.select('.c3-chart-line.c3-target-data1');
// expect(+target.select('.c3-circle-0').style('opacity')).to.equal(0.5);
// expect(+target.select('.c3-circle-1').style('opacity')).to.equal(0);
// expect(+target.select('.c3-circle-2').style('opacity')).to.equal(0.5);
// done();
// }, 500);
// });
});
describe('spline.interpolation option', function () {
it('should update args', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, -150, 250],
['data2', 50, 20, 10, 40, 15, 25],
['data3', -150, 120, 110, 140, 115, 125]
],
type: 'spline'
},
spline: {
interpolation: {
type: 'monotone'
}
}
};
expect(true).to.be.ok;
});
it('should update interpolation function', function() {
expect(chart.internal.getInterpolate(chart.data()[0])).to.equal('monotone');
});
it('should not use a non-valid interpolation', function () {
args.spline.interpolation.type = 'foo';
expect(true).to.be.ok;
});
it('should use cardinal interpolation when given option is not valid', function() {
expect(chart.internal.getInterpolate(chart.data()[0])).to.equal('cardinal');
});
});
});

50
spec-mocha/svg-helper.js

@ -0,0 +1,50 @@
/**
* Parse the d property of an SVG path into an array of drawing commands.
* @param {String} d SvgPath d attribute.]
* @return {Array} an array of drawing commands.
*/
function parseSvgPath(d) { //jshint ignore:line
var commands = [];
var commandTokens = ['M','L','I','H','V','C','S','Q','T','A'];
var command;
var in_x = false;
var in_y = false;
var x = '';
var y = '';
for(var i = 0; i <= d.length; i++) {
if (commandTokens.indexOf(d[i]) !== -1) {
if (in_x || in_y) {
commands.push({command: command, x: x, y: y});
x = '';
y = '';
}
command = d[i];
in_x = true;
in_y = false;
}
else {
if (d[i] === ',') {
if (in_y) {
commands.push({command: command, x: x, y: y});
x = '';
y = '';
}
in_x = !in_x;
in_y = !in_y;
}
else if (in_x) {
x += d[i];
}
else if (in_y) {
y += d[i];
}
}
}
if (d[i] !== ',' && in_y) {
commands.push({command: command, x: x, y: y});
}
return commands;
}

100
spec-mocha/title-spec.js

@ -0,0 +1,100 @@
var expect = require('chai').expect;
describe('c3 chart title', function () {
var chart, config;
describe('when given a title config option', function () {
describe('with no padding and no position', function () {
beforeEach(function(done) {
config = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250]
]
},
title: {
text: 'new title'
}
};
chart = window.initChart(chart, config, done);
});
it('renders the title at the default config position', function () {
var titleEl = d3.select(".c3-title");
expect(+titleEl.attr("x")).to.be.closeTo(294, -2);
expect(+titleEl.attr("y")).toEqual(titleEl.node().getBBox().height);
});
it('renders the title text', function () {
var titleEl = d3.select(".c3-title");
expect(titleEl.node().textContent).toEqual('new title');
});
});
describe('with padding', function () {
var config, getConfig = function (titlePosition) {
return {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250]
]
},
title: {
text: 'positioned title',
padding: {
top: 20,
right: 30,
bottom: 40,
left: 50
},
position: titlePosition
}
};
};
describe('and position center', function () {
beforeEach(function(done) {
config = getConfig('top-center');
chart = window.initChart(chart, config, done);
});
it('renders the title at the default config position', function () {
var titleEl = d3.select(".c3-title");
expect(+titleEl.attr("x")).to.be.closeTo(275, -2);
expect(+titleEl.attr("y")).to.be.closeTo(34, -1);
});
it('adds the correct amount of padding to fit the title', function() {
expect(chart.internal.getCurrentPaddingTop()).toEqual(
config.title.padding.top + d3.select('.c3-title').node().getBBox().height + config.title.padding.bottom
);
});
});
describe('and position left', function () {
beforeEach(function(done) {
config = getConfig('top-left');
chart = window.initChart(chart, config, done);
});
it('renders the title at the default config position', function () {
var titleEl = d3.select(".c3-title");
expect(+titleEl.attr("x")).to.be.closeTo(50, -1);
expect(+titleEl.attr("y")).to.be.closeTo(34, -1);
});
});
describe('and position right', function () {
beforeEach(function(done) {
config = getConfig('top-right');
chart = window.initChart(chart, config, done);
});
it('renders the title at the default config position', function () {
var titleEl = d3.select(".c3-title");
expect(+titleEl.attr("x")).to.be.closeTo(520, -2);
expect(+titleEl.attr("y")).to.be.closeTo(34, -1);
});
});
});
});
});

124
spec-mocha/tooltip-spec.js

@ -0,0 +1,124 @@
var expect = require('chai').expect;
describe('c3 chart tooltip', function () {
var chart;
var tooltipConfiguration;
var args = function () {
return {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25],
['data3', 150, 120, 110, 140, 115, 125]
],
},
tooltip: tooltipConfiguration
};
};
beforeEach(function (done) {
chart = window.initChart(chart, args(), done);
});
describe('tooltip position', function () {
beforeAll(function () {
tooltipConfiguration = {};
});
describe('without left margin', function () {
it('should show tooltip on proper position', function () {
var eventRect = d3.select('.c3-event-rect-2').node();
window.setMouseEvent(chart, 'mousemove', 100, 100, eventRect);
var tooltipContainer = d3.select('.c3-tooltip-container'),
top = Math.floor(+tooltipContainer.style('top').replace(/px/, '')),
left = Math.floor(+tooltipContainer.style('left').replace(/px/, '')),
topExpected = 115,
leftExpected = 280;
expect(top).to.equal(topExpected);
expect(left).to.be.above(leftExpected);
});
});
describe('with left margin', function () {
it('should set left margin', function () {
d3.select('#chart').style('margin-left', '300px');
expect(true).to.be.ok;
});
it('should show tooltip on proper position', function () {
var eventRect = d3.select('.c3-event-rect-2').node();
window.setMouseEvent(chart, 'mousemove', 100, 100, eventRect);
var tooltipContainer = d3.select('.c3-tooltip-container'),
top = Math.floor(+tooltipContainer.style('top').replace(/px/, '')),
left = Math.floor(+tooltipContainer.style('left').replace(/px/, '')),
topExpected = 115,
leftExpected = 280;
expect(top).to.equal(topExpected);
expect(left).to.be.above(leftExpected);
});
});
});
describe('tooltip positionFunction', function () {
var topExpected = 37, leftExpected = 79;
beforeAll(function () {
tooltipConfiguration = {
position: function (data, width, height, element) {
expect(data.length).to.equal(args().data.columns.length);
expect(data[0]).toEqual(jasmine.objectContaining({
index: 2,
value: 100,
id: 'data1'
}));
expect(width).to.be.above(0);
expect(height).to.be.above(0);
expect(element).to.equal(d3.select('.c3-event-rect-2').node());
return {top: topExpected, left: leftExpected};
}
};
});
it('should be set to the coordinate where the function returned', function () {
var eventRect = d3.select('.c3-event-rect-2').node();
window.setMouseEvent(chart, 'mousemove', 100, 100, eventRect);
var tooltipContainer = d3.select('.c3-tooltip-container'),
top = Math.floor(+tooltipContainer.style('top').replace(/px/, '')),
left = Math.floor(+tooltipContainer.style('left').replace(/px/, ''));
expect(top).to.equal(topExpected);
expect(left).to.equal(leftExpected);
});
});
describe('tooltip getTooltipContent', function () {
beforeAll(function () {
tooltipConfiguration = {
data_order: 'desc'
};
});
it('should sort values desc', function () {
var eventRect = d3.select('.c3-event-rect-2').node();
window.setMouseEvent(chart, 'mousemove', 100, 100, eventRect);
var tooltipTable = d3.select('.c3-tooltip')[0];
var expected = ["", "c3-tooltip-name--data3",
"c3-tooltip-name--data1", "c3-tooltip-name--data2"];
var i;
for (i = 0; i < tooltipTable[0].rows.length; i++) {
expect(tooltipTable[0].rows[i].className).to.equal(expected[i]);
}
});
});
});

139
spec-mocha/type-spec.js

@ -0,0 +1,139 @@
var expect = require('chai').expect;
describe('c3 chart types', function () {
var chart, args;
beforeEach(function (done) {
chart = window.initChart(chart, args, done);
});
describe('internal.hasArcType', function () {
describe('with data', function () {
it('should update args', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25],
['data3', 150, 120, 110, 140, 115, 125]
],
type: 'pie'
}
};
expect(true).to.be.ok;
});
it('should return true', function () {
expect(chart.internal.hasArcType()).to.be.ok;
});
it('should change chart type to "bar"', function () {
args.data.type = 'bar';
expect(true).to.be.ok;
});
it('should return false', function () {
expect(chart.internal.hasArcType()).to.not.be.ok;
});
});
describe('with empty data', function () {
it('should update args to have empty data', function () {
args = {
data: {
columns: [],
type: 'pie'
}
};
expect(true).to.be.ok;
});
it('should return true', function () {
expect(chart.internal.hasArcType()).to.be.ok;
});
it('should change chart type to "bar"', function () {
args.data.type = 'bar';
expect(true).to.be.ok;
});
it('should return false', function () {
expect(chart.internal.hasArcType()).to.not.be.ok;
});
});
});
describe('internal.hasType', function () {
it('should update args', function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25],
['data3', 150, 120, 110, 140, 115, 125]
],
type: 'pie'
}
};
expect(true).to.be.ok;
});
it('should return true for "pie" type', function () {
expect(chart.internal.hasType('pie')).to.be.ok;
});
it('should return false for "line" type', function () {
expect(chart.internal.hasType('line')).to.not.be.ok;
});
it('should return false for "bar" type', function () {
expect(chart.internal.hasType('bar')).to.not.be.ok;
});
it('should unload successfully', function () {
chart.unload([]);
expect(true).to.be.ok;
});
it('should return true for "pie" type even if no data', function () {
expect(chart.internal.hasType('pie')).to.be.ok;
});
it('should return false for "line" type even if no data', function () {
expect(chart.internal.hasType('line')).to.not.be.ok;
});
it('should return false for "bar" type even if no data', function () {
expect(chart.internal.hasType('bar')).to.not.be.ok;
});
it('should change chart type to "bar" successfully', function () {
args.data.type = 'bar';
expect(true).to.be.ok;
});
it('should return false for "pie" type even if no data', function () {
expect(chart.internal.hasType('pie')).to.not.be.ok;
});
it('should return false for "line" type even if no data', function () {
expect(chart.internal.hasType('line')).to.not.be.ok;
});
it('should return true for "bar" type even if no data', function () {
expect(chart.internal.hasType('bar')).to.be.ok;
});
});
});

69
spec-mocha/zoom-spec.js

@ -0,0 +1,69 @@
var expect = require('chai').expect;
describe('c3 chart zoom', function () {
var chart;
var args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 3150, 250],
['data2', 50, 20, 10, 40, 15, 6025]
]
},
axis: {
x: {
extent: [1, 2]
}
},
zoom: {
enable: true
},
subchart: {
show: true
}
};
beforeEach(function (done) {
chart = window.initChart(chart, args, done);
});
describe('default extent', function () {
describe('main chart domain', function () {
it('should have original y domain', function () {
var yDomain = chart.internal.y.domain(),
expectedYDomain = [-591.5, 6626.5];
expect(yDomain[0]).to.equal(expectedYDomain[0]);
expect(yDomain[1]).to.equal(expectedYDomain[1]);
});
});
describe('main chart domain', function () {
it('should have original y domain in subchart', function () {
var yDomain = chart.internal.y.domain(),
subYDomain = chart.internal.subY.domain();
expect(subYDomain[0]).to.equal(yDomain[0]);
expect(subYDomain[1]).to.equal(yDomain[1]);
});
});
describe('main chart domain', function () {
it('should have specified brush extent', function () {
var brushExtent = chart.internal.brush.extent(),
expectedBrushExtent = [1, 2];
expect(brushExtent[0]).to.equal(expectedBrushExtent[0]);
expect(brushExtent[1]).to.equal(expectedBrushExtent[1]);
});
});
});
});

8
spec/c3-helper.js

@ -1,5 +1,3 @@
import * as c3 from '../src/index';
function initDom() {
'use strict';
@ -32,9 +30,9 @@ function initChart(chart, args, done) {
window.initDom();
}
if (args) {
chart = c3.generate(args);
const d3 = chart.internal.d3;
d3.select('.jasmine_html-reporter')
chart = window.c3.generate(args);
window.d3 = chart.internal.d3;
window.d3.select('.jasmine_html-reporter')
.style('position', 'absolute')
.style('width', '640px')
.style('right', 0);

Loading…
Cancel
Save