diff --git a/. npmignore b/. npmignore index 722aced..90f603c 100644 --- a/. npmignore +++ b/. npmignore @@ -4,4 +4,5 @@ npm-debug.log # OS generated files Thumbs.db -.DS_Store \ No newline at end of file +.DS_Store +coverage \ No newline at end of file diff --git a/.gitignore b/.gitignore index 722aced..5486f90 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ npm-debug.log # OS generated files Thumbs.db -.DS_Store \ No newline at end of file +.DS_Store +coverage diff --git a/README.md b/README.md index 7397edd..d9d27a9 100644 --- a/README.md +++ b/README.md @@ -87,18 +87,18 @@ all chaining function use ase json... bottom: 40, left: 55 }, - x: function (d) { return d.x; }, - y: function (d) { return d.y; }, + x: (d) => { return d.x; }, + y: (d) => { return d.y; }, xScale: d3.time.scale(), xAxis: { ticks: d3.time.months, - tickFormat: function (d) { + tickFormat: (d) => { return d3.time.format('%b')(new Date(d)); } }, yAxis: { axisLabel: 'Gross volume', - tickFormat: function (d) { + tickFormat: (d) => { if (d == null) { return 0; } diff --git a/dist/angular2-nvd3/angular2-nvd3.module.js b/dist/angular2-nvd3/angular2-nvd3.module.js index 9efa7f7..d6f9b24 100644 --- a/dist/angular2-nvd3/angular2-nvd3.module.js +++ b/dist/angular2-nvd3/angular2-nvd3.module.js @@ -5,9 +5,6 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; -var __metadata = (this && this.__metadata) || function (k, v) { - if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); -}; var core_1 = require("@angular/core"); var angular2_nvd3_component_1 = require("./angular2-nvd3.component"); var angular2_nvd3_directive_1 = require("./angular2-nvd3.directive"); @@ -26,7 +23,6 @@ NvD3Module = __decorate([ angular2_nvd3_component_1.NvD3Component, angular2_nvd3_directive_1.NvD3Directive ] - }), - __metadata("design:paramtypes", []) + }) ], NvD3Module); exports.NvD3Module = NvD3Module; diff --git a/dist/test/angular2-nvd3.component.spec.d.ts b/dist/test/angular2-nvd3.component.spec.d.ts new file mode 100644 index 0000000..e69de29 diff --git a/dist/test/angular2-nvd3.component.spec.js b/dist/test/angular2-nvd3.component.spec.js new file mode 100644 index 0000000..56daa11 --- /dev/null +++ b/dist/test/angular2-nvd3.component.spec.js @@ -0,0 +1,33 @@ +"use strict"; +var testing_1 = require("@angular/core/testing"); +var angular2_nvd3_component_1 = require("../angular2-nvd3/angular2-nvd3.component"); +var sample_data_1 = require("./sample-data"); +sample_data_1.SampleData.chartTypes.forEach(function (type) { + describe("tasks:NvD3Component " + type, function () { + var component; + var fixture; + var componentElement; + beforeEach(function () { + testing_1.TestBed.configureTestingModule({ + declarations: [angular2_nvd3_component_1.NvD3Component], + }); + fixture = testing_1.TestBed.createComponent(angular2_nvd3_component_1.NvD3Component); + component = fixture.componentInstance; + component.options = sample_data_1.SampleData.allOptions[type]; + component.data = sample_data_1.SampleData.allData[type]; + fixture.detectChanges(); + componentElement = fixture.nativeElement; + }); + it("should have svg", function () { + expect(componentElement.querySelectorAll('svg').length).toBe(1); + }); + it('should svg have class nvd3-svg', function () { + var gElement = componentElement.querySelector('svg'); + expect(gElement.classList).toContain('nvd3-svg'); + }); + it("should g have class nv-" + type, function () { + var gElement = componentElement.querySelector('g'); + expect(gElement.className.baseVal).toContain(sample_data_1.SampleData.chartClassExpected[type]); + }); + }); +}); diff --git a/dist/test/sample-data.d.ts b/dist/test/sample-data.d.ts new file mode 100644 index 0000000..88b0d2a --- /dev/null +++ b/dist/test/sample-data.d.ts @@ -0,0 +1,320 @@ +export declare namespace SampleData { + const chartTypes: string[]; + const allOptions: { + lineChart: { + chart: { + type: string; + height: number; + x: (d: any) => any; + y: (d: any) => any; + }; + }; + discreteBarChart: { + chart: { + type: string; + height: number; + x: (d: any) => any; + y: (d: any) => any; + }; + }; + pieChart: { + chart: { + type: string; + height: number; + x: (d: any) => any; + y: (d: any) => any; + }; + }; + scatterChart: { + chart: { + type: string; + height: number; + }; + }; + multiBarChart: { + chart: { + type: string; + height: number; + stacked: boolean; + }; + }; + candlestickBarChart: { + chart: { + type: string; + height: number; + x: (d: any) => any; + y: (d: any) => any; + }; + }; + ohlcBarChart: { + chart: { + type: string; + height: number; + x: (d: any) => any; + y: (d: any) => any; + }; + }; + boxPlotChart: { + chart: { + type: string; + height: number; + x: (d: any) => any; + }; + }; + multiChart: { + chart: { + type: string; + height: number; + }; + }; + sunburstChart: { + chart: { + type: string; + height: number; + }; + }; + stackedAreaChart: { + chart: { + type: string; + height: number; + x: (d: any) => any; + y: (d: any) => any; + }; + }; + multiBarHorizontalChart: { + chart: { + type: string; + height: number; + x: (d: any) => any; + y: (d: any) => any; + }; + }; + cumulativeLineChart: { + chart: { + type: string; + height: number; + x: (d: any) => any; + y: (d: any) => number; + average: (d: any) => number; + }; + }; + historicalBarChart: { + chart: { + type: string; + height: number; + x: (d: any) => any; + y: (d: any) => number; + }; + }; + parallelCoordinates: { + chart: { + type: string; + height: number; + dimensionData: string[]; + }; + }; + sparklinePlus: { + chart: { + type: string; + height: number; + x: (d: any, i: any) => any; + }; + }; + bulletChart: { + chart: { + type: string; + height: number; + }; + }; + linePlusBarWithFocusChart: { + chart: { + type: string; + height: number; + color: string[]; + x: (d: any, i: any) => any; + }; + }; + forceDirectedGraph: { + chart: { + type: string; + }; + }; + }; + const allData: { + lineChart: { + key: string; + values: { + x: number; + y: number; + }[]; + }[]; + discreteBarChart: { + key: string; + values: { + 'label': string; + 'value': number; + }[]; + }[]; + pieChart: { + key: string; + y: number; + }[]; + scatterChart: { + key: string; + values: { + x: number; + y: number; + }[]; + }[]; + multiBarChart: { + key: string; + values: { + x: number; + y: number; + }[]; + }[]; + candlestickBarChart: { + values: { + 'date': number; + 'open': number; + 'high': number; + 'low': number; + 'close': number; + 'volume': number; + 'adjusted': number; + }[]; + }[]; + ohlcBarChart: { + values: { + 'date': number; + 'open': number; + 'high': number; + 'low': number; + 'close': number; + 'volume': number; + 'adjusted': number; + }[]; + }[]; + boxPlotChart: { + label: string; + values: { + Q1: number; + Q2: number; + Q3: number; + whisker_low: number; + whisker_high: number; + outliers: number[]; + }; + }[]; + multiChart: { + key: string; + type: string; + yAxis: number; + values: { + x: number; + y: number; + }[]; + }[]; + sunburstChart: { + 'name': string; + 'children': { + 'name': string; + 'children': { + 'name': string; + 'children': { + 'name': string; + 'size': number; + }[]; + }[]; + }[]; + }[]; + stackedAreaChart: { + 'key': string; + 'values': number[][]; + }[]; + multiBarHorizontalChart: { + 'key': string; + 'values': { + 'label': string; + 'value': number; + }[]; + }[]; + cumulativeLineChart: { + key: string; + values: number[][]; + mean: number; + }[]; + historicalBarChart: { + 'key': string; + 'bar': boolean; + 'values': number[][]; + }[]; + parallelCoordinates: { + 'name': string; + 'economy (mpg)': string; + 'cylinders': string; + 'displacement (cc)': string; + 'power (hp)': string; + 'weight (lb)': string; + '0-60 mph (s)': string; + 'year': string; + }[]; + sparklinePlus: { + x: number; + y: number; + }[]; + bulletChart: { + 'title': string; + 'subtitle': string; + 'ranges': number[]; + 'measures': number[]; + 'markers': number[]; + }; + linePlusBarWithFocusChart: ({ + 'key': string; + 'bar': boolean; + 'values': { + x: number; + y: number; + }[]; + } | { + 'key': string; + 'values': { + x: number; + y: number; + }[]; + })[]; + forceDirectedGraph: { + 'nodes': { + 'name': string; + 'group': number; + }[]; + 'links': { + 'source': number; + 'target': number; + 'value': number; + }[]; + }; + }; + const chartClassExpected: { + lineChart: string; + discreteBarChart: string; + pieChart: string; + scatterChart: string; + multiBarChart: string; + multiBarHorizontalChart: string; + candlestickBarChart: string; + ohlcBarChart: string; + boxPlotChart: string; + multiChart: string; + sunburstChart: string; + stackedAreaChart: string; + cumulativeLineChart: string; + historicalBarChart: string; + parallelCoordinates: string; + sparklinePlus: string; + bulletChart: string; + linePlusBarWithFocusChart: string; + forceDirectedGraph: string; + }; +} diff --git a/dist/test/sample-data.js b/dist/test/sample-data.js new file mode 100644 index 0000000..8b8a329 --- /dev/null +++ b/dist/test/sample-data.js @@ -0,0 +1,441 @@ +"use strict"; +var SampleData; +(function (SampleData) { + SampleData.chartTypes = [ + 'lineChart', + 'discreteBarChart', + 'pieChart', + 'scatterChart', + 'multiBarChart', + 'multiBarHorizontalChart', + 'candlestickBarChart', + 'ohlcBarChart', + 'boxPlotChart', + 'multiChart', + 'sunburstChart', + 'stackedAreaChart', + 'cumulativeLineChart', + 'historicalBarChart', + 'parallelCoordinates', + 'sparklinePlus', + 'bulletChart', + 'linePlusBarWithFocusChart', + 'forceDirectedGraph' + ]; + SampleData.allOptions = { + lineChart: { + chart: { + type: 'lineChart', + height: 450, + x: function (d) { return d.x; }, + y: function (d) { return d.y; } + } + }, + discreteBarChart: { + chart: { + type: 'discreteBarChart', + height: 450, + x: function (d) { return d.label; }, + y: function (d) { return d.value; } + } + }, + pieChart: { + chart: { + type: 'pieChart', + height: 500, + x: function (d) { return d.key; }, + y: function (d) { return d.y; } + } + }, + scatterChart: { + chart: { + type: 'scatterChart', + height: 450 + } + }, + multiBarChart: { + chart: { + type: 'multiBarChart', + height: 450, + stacked: true + } + }, + candlestickBarChart: { + chart: { + type: 'candlestickBarChart', + height: 450, + x: function (d) { return d['date']; }, + y: function (d) { return d['close']; } + } + }, + ohlcBarChart: { + chart: { + type: 'ohlcBarChart', + height: 450, + x: function (d) { return d['date']; }, + y: function (d) { return d['close']; } + } + }, + boxPlotChart: { + chart: { + type: 'boxPlotChart', + height: 450, + x: function (d) { return d.label; } + } + }, + multiChart: { + chart: { + type: 'multiChart', + height: 450 + } + }, + sunburstChart: { + chart: { + type: 'sunburstChart', + height: 450 + } + }, + stackedAreaChart: { + chart: { + type: 'stackedAreaChart', + height: 450, + x: function (d) { return d[0]; }, + y: function (d) { return d[1]; } + } + }, + multiBarHorizontalChart: { + chart: { + type: 'multiBarHorizontalChart', + height: 450, + x: function (d) { return d.label; }, + y: function (d) { return d.value; } + } + }, + cumulativeLineChart: { + chart: { + type: 'cumulativeLineChart', + height: 450, + x: function (d) { return d[0]; }, + y: function (d) { return d[1] / 100; }, + average: function (d) { return d.mean / 100; } + } + }, + historicalBarChart: { + chart: { + type: 'historicalBarChart', + height: 450, + x: function (d) { return d[0]; }, + y: function (d) { return d[1] / 100000; } + } + }, + parallelCoordinates: { + chart: { + type: 'parallelCoordinates', + height: 450, + dimensionData: [ + 'economy (mpg)', + 'cylinders', + 'displacement (cc)', + 'power (hp)', + 'weight (lb)', + '0-60 mph (s)', + 'year' + ] + } + }, + sparklinePlus: { + chart: { + type: 'sparklinePlus', + height: 450, + x: function (d, i) { return i; } + } + }, + bulletChart: { + chart: { + type: 'bulletChart', + height: 450 + } + }, + linePlusBarWithFocusChart: { + chart: { + type: 'linePlusBarChart', + height: 500, + color: ['#2ca02c', 'darkred'], + x: function (d, i) { return i; } + } + }, + forceDirectedGraph: { + chart: { + type: 'forceDirectedGraph' + } + } + }; + SampleData.allData = { + lineChart: [ + { key: 'key1', values: [{ x: 0, y: 0 }, { x: 1, y: 1 }] }, + { key: 'key2', values: [{ x: 1, y: 1 }, { x: 0, y: 0 }] } + ], + discreteBarChart: [ + { + key: 'Cumulative Return', + values: [ + { 'label': 'A', 'value': 10 }, + { 'label': 'B', 'value': 20 } + ] + } + ], + pieChart: [ + { key: 'One', y: 5 }, + { key: 'Two', y: 2 } + ], + scatterChart: [ + { key: 'key1', values: [{ x: 0, y: 0 }, { x: 1, y: 1 }] }, + { key: 'key2', values: [{ x: 1, y: 1 }, { x: 0, y: 0 }] } + ], + multiBarChart: [ + { + key: 'Sent', + values: [{ x: 0, y: 1 }, { x: 1, y: 2 }] + }, + { + key: 'Received', + values: [{ x: 0, y: 2 }, { x: 1, y: 3 }] + }, + { + key: 'Spam', + values: [{ x: 0, y: 3 }, { x: 1, y: 5 }] + } + ], + candlestickBarChart: [{ + values: [ + { 'date': 15854, 'open': 165.42, 'high': 165.8, 'low': 164.34, 'close': 165.22, 'volume': 160363400, 'adjusted': 164.35 }, + { 'date': 15855, 'open': 165.35, 'high': 166.59, 'low': 165.22, 'close': 165.83, 'volume': 107793800, 'adjusted': 164.96 } + ] + } + ], + ohlcBarChart: [{ + values: [ + { 'date': 15707, 'open': 145.11, 'high': 146.15, 'low': 144.73, 'close': 146.06, 'volume': 192059000, 'adjusted': 144.65 }, + { 'date': 15708, 'open': 145.99, 'high': 146.37, 'low': 145.34, 'close': 145.73, 'volume': 144761800, 'adjusted': 144.32 }, + ] + } + ], + boxPlotChart: [ + { + label: 'Sample A', + values: { + Q1: 180, + Q2: 200, + Q3: 250, + whisker_low: 115, + whisker_high: 400, + outliers: [50, 100, 425] + } + } + ], + multiChart: [ + { + key: 'Stream1', + type: 'area', + yAxis: 1, + values: [{ x: 0, y: 1 }, { x: 1, y: 2 }] + }, + { + key: 'Stream2', + type: 'area', + yAxis: 1, + values: [{ x: 0, y: 2 }, { x: 1, y: 3 }] + }, + { + key: 'Stream3', + type: 'line', + yAxis: 1, + values: [{ x: 0, y: 3 }, { x: 1, y: 5 }] + }, + { + key: 'Stream4', + type: 'line', + yAxis: 2, + values: [{ x: 0, y: 3 }, { x: 1, y: 5 }] + }, + { + key: 'Stream4', + type: 'bar', + yAxis: 2, + values: [{ x: 0, y: 3 }, { x: 1, y: 5 }] + } + ], + sunburstChart: [{ + 'name': 'flare', + 'children': [ + { + 'name': 'analytics', + 'children': [ + { + 'name': 'cluster', + 'children': [ + { 'name': 'AgglomerativeCluster', 'size': 3938 }, + { 'name': 'CommunityStructure', 'size': 3812 }, + { 'name': 'HierarchicalCluster', 'size': 6714 }, + { 'name': 'MergeEdge', 'size': 743 } + ] + }, + { + 'name': 'graph', + 'children': [ + { 'name': 'BetweennessCentrality', 'size': 3534 }, + { 'name': 'LinkDistance', 'size': 5731 }, + { 'name': 'MaxFlowMinCut', 'size': 7840 }, + { 'name': 'ShortestPaths', 'size': 5914 }, + { 'name': 'SpanningTree', 'size': 3416 } + ] + }, + { + 'name': 'optimization', + 'children': [ + { 'name': 'AspectRatioBanker', 'size': 7074 } + ] + } + ] + } + ] + }], + stackedAreaChart: [ + { + 'key': 'North America', + 'values': [[1025409600000, 23.041422681023], [1028088000000, 19.854291255832]] + }, + { + 'key': 'Africa', + 'values': [[1025409600000, 7.9356392949025], [1028088000000, 7.4514668527298]] + } + ], + multiBarHorizontalChart: [ + { + 'key': 'Series1', + 'values': [ + { + 'label': 'Group A', + 'value': -1.8746444827653 + }, + { + 'label': 'Group B', + 'value': -8.0961543492239 + } + ] + }, + { + 'key': 'Series2', + 'values': [ + { + 'label': 'Group A', + 'value': 25.307646510375 + }, + { + 'label': 'Group B', + 'value': 16.756779544553 + } + ] + } + ], + cumulativeLineChart: [ + { + key: 'Long', + values: [[1083297600000, -2.974623048543], [1085976000000, -1.7740300785979]], + mean: 250 + }, + { + key: 'Short', + values: [[1083297600000, -0.77078283705125], [1085976000000, -1.8356366650335]], + mean: -60 + } + ], + historicalBarChart: [ + { + 'key': 'Quantity', + 'bar': true, + 'values': [[1136005200000, 1271000.0], [1138683600000, 1271000.0], [1141102800000, 1271000.0]] + } + ], + parallelCoordinates: [ + { + 'name': 'AMC Ambassador Brougham', + 'economy (mpg)': '13', + 'cylinders': '8', + 'displacement (cc)': '360', + 'power (hp)': '175', + 'weight (lb)': '3821', + '0-60 mph (s)': '11', + 'year': '73' + }, + { + 'name': 'AMC Ambassador DPL', + 'economy (mpg)': '15', + 'cylinders': '8', + 'displacement (cc)': '390', + 'power (hp)': '190', + 'weight (lb)': '3850', + '0-60 mph (s)': '8.5', + 'year': '70' + } + ], + sparklinePlus: [{ x: 1083297600000, y: 2.974623048543 }, { x: 1085976000000, y: 1.7740300785979 }], + bulletChart: { + 'title': 'Revenue', + 'subtitle': 'US$, in thousands', + 'ranges': [150, 225, 300], + 'measures': [220], + 'markers': [250] + }, + linePlusBarWithFocusChart: [ + { + 'key': 'Quantity', + 'bar': true, + 'values': [{ x: 1083297600000, y: 2.974623048543 }, { x: 1085976000000, y: 1.7740300785979 }] + }, + { + 'key': 'Price', + 'values': [{ x: 1083297600000, y: 2.974623048543 }, { x: 1085976000000, y: 1.7740300785979 }] + } + ], + forceDirectedGraph: { + 'nodes': [ + { 'name': 'Myriel', 'group': 1 }, + { 'name': 'Napoleon', 'group': 1 }, + { 'name': 'Labarre', 'group': 2 }, + { 'name': 'Valjean', 'group': 2 }, + { 'name': 'Marguerite', 'group': 3 }, + { 'name': 'Mme.deR', 'group': 3 } + ], + 'links': [ + { 'source': 1, 'target': 0, 'value': 1 }, + { 'source': 2, 'target': 0, 'value': 8 }, + { 'source': 3, 'target': 1, 'value': 10 }, + { 'source': 3, 'target': 2, 'value': 6 }, + { 'source': 4, 'target': 0, 'value': 1 }, + { 'source': 5, 'target': 3, 'value': 1 } + ] + } + }; + SampleData.chartClassExpected = { + lineChart: 'nv-lineChart', + discreteBarChart: 'nv-discreteBarWithAxes', + pieChart: 'nv-pieChart', + scatterChart: 'nv-scatterChart', + multiBarChart: 'nv-multiBarWithLegend', + multiBarHorizontalChart: 'nv-multiBarHorizontalChart', + candlestickBarChart: 'nv-historicalBarChart', + ohlcBarChart: 'nv-historicalBarChar', + boxPlotChart: 'nv-boxPlotWithAxes', + multiChart: 'multiChart', + sunburstChart: 'nv-sunburst', + stackedAreaChart: 'nv-stackedAreaChart', + cumulativeLineChart: 'nv-cumulativeLine', + historicalBarChart: 'nv-historicalBarChart', + parallelCoordinates: 'nv-parallelCoordinates', + sparklinePlus: 'nv-sparklineplus', + bulletChart: 'nv-bulletChart', + linePlusBarWithFocusChart: 'nv-linePlusBar', + forceDirectedGraph: 'nv-force-node' + }; +})(SampleData = exports.SampleData || (exports.SampleData = {})); diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 0000000..5819ffc --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,34 @@ +// Karma configuration file, see link for more information +// https://karma-runner.github.io/0.13/config/configuration-file.html +var webpackConfig = require('./webpack.config'); + +module.exports = function (config) { + config.set({ + basePath: '', + frameworks: ['jasmine'], + plugins: [ + require('karma-jasmine'), + require('karma-webpack'), + require('karma-phantomjs-launcher') + ], + files: [ + 'src/test/test.ts' + ], + exclude: [], + preprocessors: { + 'src/test/test.ts': ['webpack'] + }, + webpack: { + module: webpackConfig.module, + resolve: webpackConfig.resolve + }, + reporters: ['progress'], + port: 9876, + colors: true, + logLevel: config.LOG_INFO, + autoWatch: true, + browsers: ['PhantomJS'], + singleRun: false, + concurrency: Infinity + }) +}; diff --git a/package.json b/package.json index ff9379c..dc9be0a 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,9 @@ "test": "test" }, "scripts": { + "prepublish": "npm run compile", "pretest": "npm run compile", - "test": "npm run test:lint", + "test": "npm run test:lint && karma start karma.conf.js", "compile": "rm -rf dist && tsc", "test:lint": "tslint -c tslint.json 'src/angular2-nvd3/angular2-nvd3.*.ts'" }, @@ -44,10 +45,20 @@ "@angular/core": "^2.4.1", "@angular/platform-browser": "^2.4.1", "@angular/platform-browser-dynamic": "^2.4.1", + "@types/jasmine": "^2.5.40", + "core-js": "^2.4.1", + "jasmine": "^2.5.2", + "karma": "^0.12.37", + "karma-jasmine": "^1.1.0", + "karma-phantomjs-launcher": "^1.0.2", + "karma-webpack": "~1.6.0", + "phantomjs-prebuilt": "^2.1.14", "reflect-metadata": "^0.1.9", "rxjs": "^5.0.2", + "ts-loader": "^1.3.3", "tslint": "^4.2.0", "typescript": "^2.1.4", + "webpack": "^1.14.0", "zone.js": "^0.7.4" }, "main": "dist/angular2-nvd3/angular2-nvd3.module.js", diff --git a/src/test/angular2-nvd3.component.spec.ts b/src/test/angular2-nvd3.component.spec.ts new file mode 100644 index 0000000..e2a8e40 --- /dev/null +++ b/src/test/angular2-nvd3.component.spec.ts @@ -0,0 +1,47 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { NvD3Component } from '../angular2-nvd3/angular2-nvd3.component'; +import { By } from '@angular/platform-browser'; +import { DebugElement } from '@angular/core'; +import { SampleData } from './sample-data'; + +SampleData.chartTypes.forEach((type) => { + + describe(`tasks:NvD3Component ${type}`, () => { + + let component: NvD3Component; + let fixture: ComponentFixture; + let componentElement: Element; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [NvD3Component], // declare the test component + }); + + fixture = TestBed.createComponent(NvD3Component); + component = fixture.componentInstance; // NvD3Component test instance + + // pretend that it was wired to something + component.options = SampleData.allOptions[type]; + component.data = SampleData.allData[type]; + // trigger initial data binding + fixture.detectChanges(); + + componentElement = fixture.nativeElement; + }); + + it(`should have svg`, () => { + expect(componentElement.querySelectorAll('svg').length).toBe(1); + }); + + it('should svg have class nvd3-svg', () => { + let gElement = componentElement.querySelector('svg'); + expect(gElement.classList).toContain('nvd3-svg'); + }); + + it(`should g have class nv-${type}`, () => { + let gElement = componentElement.querySelector('g'); + expect(gElement.className.baseVal).toContain(SampleData.chartClassExpected[type]); + }); + }); + +}); \ No newline at end of file diff --git a/src/test/angular2-nvd3.directive.spec.ts b/src/test/angular2-nvd3.directive.spec.ts new file mode 100644 index 0000000..664bb42 --- /dev/null +++ b/src/test/angular2-nvd3.directive.spec.ts @@ -0,0 +1,48 @@ +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { NvD3Directive } from '../angular2-nvd3/angular2-nvd3.directive'; +import { TestComponent } from './test.component'; +import { By } from '@angular/platform-browser'; +import { DebugElement } from '@angular/core'; +import { SampleData } from './sample-data'; + +SampleData.chartTypes.forEach((type) => { + describe(`tasks:NvD3Directive ${type}`, () => { + let component: TestComponent; + let fixture: ComponentFixture; + let componentElement: Element; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ TestComponent, NvD3Directive ], // declare the test component + schemas: [ NO_ERRORS_SCHEMA ] + }); + + fixture = TestBed.createComponent(TestComponent); + component = fixture.componentInstance; // NvD3Directive test instance + + // pretend that it was wired to something + component.options = SampleData.allOptions[type]; + component.data = SampleData.allData[type]; + // trigger initial data binding + fixture.detectChanges(); + + componentElement = fixture.nativeElement; + }); + + it(`should have svg`, () => { + expect(componentElement.querySelectorAll('svg').length).toBe(1); + }); + + it('should svg have class nvd3-svg', () => { + let gElement = componentElement.querySelector('svg'); + expect(gElement.classList).toContain('nvd3-svg'); + }); + + it(`should g have class nv-${type}`, () => { + let gElement = componentElement.querySelector('g'); + expect(gElement.className.baseVal).toContain(SampleData.chartClassExpected[type]); + }); + }); + +}); \ No newline at end of file diff --git a/src/test/polyfills.ts b/src/test/polyfills.ts new file mode 100644 index 0000000..864e319 --- /dev/null +++ b/src/test/polyfills.ts @@ -0,0 +1,19 @@ +// Polyfills + +import 'core-js/es6/symbol'; +import 'core-js/es6/object'; +import 'core-js/es6/function'; +import 'core-js/es6/parse-int'; +import 'core-js/es6/parse-float'; +import 'core-js/es6/number'; +import 'core-js/es6/math'; +import 'core-js/es6/string'; +import 'core-js/es6/date'; +import 'core-js/es6/array'; +import 'core-js/es6/regexp'; +import 'core-js/es6/map'; +import 'core-js/es6/set'; +import 'core-js/es6/reflect'; + +import 'core-js/es7/reflect'; +import 'zone.js/dist/zone'; diff --git a/src/test/sample-data.ts b/src/test/sample-data.ts new file mode 100644 index 0000000..87dede5 --- /dev/null +++ b/src/test/sample-data.ts @@ -0,0 +1,447 @@ +import * as d3 from 'd3'; + +export namespace SampleData { + export const chartTypes = [ + 'lineChart', + 'discreteBarChart', + 'pieChart', + 'scatterChart', + 'multiBarChart', + 'multiBarHorizontalChart', + 'candlestickBarChart', + 'ohlcBarChart', + 'boxPlotChart', + 'multiChart', + 'sunburstChart', + 'stackedAreaChart', + 'cumulativeLineChart', + 'historicalBarChart', + 'parallelCoordinates', + 'sparklinePlus', + 'bulletChart', + 'linePlusBarWithFocusChart', + 'forceDirectedGraph' + ]; + export const allOptions = { + lineChart: { + chart: { + type: 'lineChart', + height: 450, + x: function (d) { return d.x; }, + y: function (d) { return d.y; } + } + }, + discreteBarChart: { + chart: { + type: 'discreteBarChart', + height: 450, + x: function (d) { return d.label; }, + y: function (d) { return d.value; } + } + }, + pieChart: { + chart: { + type: 'pieChart', + height: 500, + x: function (d) { return d.key; }, + y: function (d) { return d.y; } + } + }, + scatterChart: { + chart: { + type: 'scatterChart', + height: 450 + } + }, + multiBarChart: { + chart: { + type: 'multiBarChart', + height: 450, + stacked: true + } + }, + candlestickBarChart: { + chart: { + type: 'candlestickBarChart', + height: 450, + x: function (d) { return d['date']; }, + y: function (d) { return d['close']; } + } + }, + ohlcBarChart: { + chart: { + type: 'ohlcBarChart', + height: 450, + x: function (d) { return d['date']; }, + y: function (d) { return d['close']; } + } + }, + boxPlotChart: { + chart: { + type: 'boxPlotChart', + height: 450, + x: function (d) { return d.label; } + } + }, + multiChart: { + chart: { + type: 'multiChart', + height: 450 + } + }, + sunburstChart: { + chart: { + type: 'sunburstChart', + height: 450 + } + }, + stackedAreaChart: { + chart: { + type: 'stackedAreaChart', + height: 450, + x: function (d) { return d[0]; }, + y: function (d) { return d[1]; } + } + }, + multiBarHorizontalChart: { + chart: { + type: 'multiBarHorizontalChart', + height: 450, + x: function (d) { return d.label; }, + y: function (d) { return d.value; } + } + }, + + cumulativeLineChart: { + chart: { + type: 'cumulativeLineChart', + height: 450, + x: function (d) { return d[0]; }, + y: function (d) { return d[1] / 100; }, + average: function (d) { return d.mean / 100; } + } + }, + historicalBarChart: { + chart: { + type: 'historicalBarChart', + height: 450, + x: function (d) { return d[0]; }, + y: function (d) { return d[1] / 100000; } + } + }, + parallelCoordinates: { + chart: { + type: 'parallelCoordinates', + height: 450, + dimensionData: [ + 'economy (mpg)', + 'cylinders', + 'displacement (cc)', + 'power (hp)', + 'weight (lb)', + '0-60 mph (s)', + 'year' + ] + } + }, + sparklinePlus: { + chart: { + type: 'sparklinePlus', + height: 450, + x: function (d, i) { return i; } + } + }, + bulletChart: { + chart: { + type: 'bulletChart', + height: 450 + } + }, + linePlusBarWithFocusChart: { + chart: { + type: 'linePlusBarChart', + height: 500, + color: ['#2ca02c', 'darkred'], + x: function (d, i) { return i; } + } + }, + forceDirectedGraph: { + chart: { + type: 'forceDirectedGraph' + } + } + }; + + export const allData = { + lineChart: [ + { key: 'key1', values: [{ x: 0, y: 0 }, { x: 1, y: 1 }] }, + { key: 'key2', values: [{ x: 1, y: 1 }, { x: 0, y: 0 }] } + ], + discreteBarChart: [ + { + key: 'Cumulative Return', + values: [ + { 'label': 'A', 'value': 10 }, + { 'label': 'B', 'value': 20 } + ] + } + ], + pieChart: [ + { key: 'One', y: 5 }, + { key: 'Two', y: 2 } + ], + scatterChart: [ + { key: 'key1', values: [{ x: 0, y: 0 }, { x: 1, y: 1 }] }, + { key: 'key2', values: [{ x: 1, y: 1 }, { x: 0, y: 0 }] } + ], + multiBarChart: [ + { + key: 'Sent', + values: [{ x: 0, y: 1 }, { x: 1, y: 2 }] + }, + { + key: 'Received', + values: [{ x: 0, y: 2 }, { x: 1, y: 3 }] + }, + { + key: 'Spam', + values: [{ x: 0, y: 3 }, { x: 1, y: 5 }] + } + ], + candlestickBarChart: [{ + values: [ + { 'date': 15854, 'open': 165.42, 'high': 165.8, 'low': 164.34, 'close': 165.22, 'volume': 160363400, 'adjusted': 164.35 }, + { 'date': 15855, 'open': 165.35, 'high': 166.59, 'low': 165.22, 'close': 165.83, 'volume': 107793800, 'adjusted': 164.96 } + ] + } + ], + ohlcBarChart: [{ + values: [ + { 'date': 15707, 'open': 145.11, 'high': 146.15, 'low': 144.73, 'close': 146.06, 'volume': 192059000, 'adjusted': 144.65 }, + { 'date': 15708, 'open': 145.99, 'high': 146.37, 'low': 145.34, 'close': 145.73, 'volume': 144761800, 'adjusted': 144.32 }, + ] + } + ], + boxPlotChart: [ + { + label: 'Sample A', + values: { + Q1: 180, + Q2: 200, + Q3: 250, + whisker_low: 115, + whisker_high: 400, + outliers: [50, 100, 425] + } + } + ], + multiChart: [ + { + key: 'Stream1', + type: 'area', + yAxis: 1, + values: [{ x: 0, y: 1 }, { x: 1, y: 2 }] + }, + { + key: 'Stream2', + type: 'area', + yAxis: 1, + values: [{ x: 0, y: 2 }, { x: 1, y: 3 }] + }, + { + key: 'Stream3', + type: 'line', + yAxis: 1, + values: [{ x: 0, y: 3 }, { x: 1, y: 5 }] + }, + { + key: 'Stream4', + type: 'line', + yAxis: 2, + values: [{ x: 0, y: 3 }, { x: 1, y: 5 }] + }, + { + key: 'Stream4', + type: 'bar', + yAxis: 2, + values: [{ x: 0, y: 3 }, { x: 1, y: 5 }] + } + ], + sunburstChart: [{ + 'name': 'flare', + 'children': [ + { + 'name': 'analytics', + 'children': [ + { + 'name': 'cluster', + 'children': [ + { 'name': 'AgglomerativeCluster', 'size': 3938 }, + { 'name': 'CommunityStructure', 'size': 3812 }, + { 'name': 'HierarchicalCluster', 'size': 6714 }, + { 'name': 'MergeEdge', 'size': 743 } + ] + }, + { + 'name': 'graph', + 'children': [ + { 'name': 'BetweennessCentrality', 'size': 3534 }, + { 'name': 'LinkDistance', 'size': 5731 }, + { 'name': 'MaxFlowMinCut', 'size': 7840 }, + { 'name': 'ShortestPaths', 'size': 5914 }, + { 'name': 'SpanningTree', 'size': 3416 } + ] + }, + { + 'name': 'optimization', + 'children': [ + { 'name': 'AspectRatioBanker', 'size': 7074 } + ] + } + ] + } + ] + }], + stackedAreaChart: [ + { + 'key': 'North America', + 'values': [[1025409600000, 23.041422681023], [1028088000000, 19.854291255832]] + }, + { + 'key': 'Africa', + 'values': [[1025409600000, 7.9356392949025], [1028088000000, 7.4514668527298]] + } + ], + multiBarHorizontalChart: [ + { + 'key': 'Series1', + 'values': [ + { + 'label': 'Group A', + 'value': -1.8746444827653 + }, + { + 'label': 'Group B', + 'value': -8.0961543492239 + } + ] + }, + { + 'key': 'Series2', + 'values': [ + { + 'label': 'Group A', + 'value': 25.307646510375 + }, + { + 'label': 'Group B', + 'value': 16.756779544553 + } + ] + } + ], + + cumulativeLineChart: [ + { + key: 'Long', + values: [[1083297600000, -2.974623048543], [1085976000000, -1.7740300785979]] + , + mean: 250 + }, + { + key: 'Short', + values: [[1083297600000, -0.77078283705125], [1085976000000, -1.8356366650335]] + , + mean: -60 + } + ], + historicalBarChart: [ + { + 'key': 'Quantity', + 'bar': true, + 'values': [[1136005200000, 1271000.0], [1138683600000, 1271000.0], [1141102800000, 1271000.0]] + } + ], + parallelCoordinates: [ + { + 'name': 'AMC Ambassador Brougham', + 'economy (mpg)': '13', + 'cylinders': '8', + 'displacement (cc)': '360', + 'power (hp)': '175', + 'weight (lb)': '3821', + '0-60 mph (s)': '11', + 'year': '73' + }, + { + 'name': 'AMC Ambassador DPL', + 'economy (mpg)': '15', + 'cylinders': '8', + 'displacement (cc)': '390', + 'power (hp)': '190', + 'weight (lb)': '3850', + '0-60 mph (s)': '8.5', + 'year': '70' + } + ], + sparklinePlus: [{ x: 1083297600000, y: 2.974623048543 }, { x: 1085976000000, y: 1.7740300785979 }], + bulletChart: { + 'title': 'Revenue', + 'subtitle': 'US$, in thousands', + 'ranges': [150, 225, 300], + 'measures': [220], + 'markers': [250] + }, + linePlusBarWithFocusChart: [ + { + 'key': 'Quantity', + 'bar': true, + 'values': [{ x: 1083297600000, y: 2.974623048543 }, { x: 1085976000000, y: 1.7740300785979 }] + }, + { + 'key': 'Price', + 'values': [{ x: 1083297600000, y: 2.974623048543 }, { x: 1085976000000, y: 1.7740300785979 }] + } + ], + forceDirectedGraph: { + 'nodes': [ + { 'name': 'Myriel', 'group': 1 }, + { 'name': 'Napoleon', 'group': 1 }, + { 'name': 'Labarre', 'group': 2 }, + { 'name': 'Valjean', 'group': 2 }, + { 'name': 'Marguerite', 'group': 3 }, + { 'name': 'Mme.deR', 'group': 3 } + ], + 'links': [ + { 'source': 1, 'target': 0, 'value': 1 }, + { 'source': 2, 'target': 0, 'value': 8 }, + { 'source': 3, 'target': 1, 'value': 10 }, + { 'source': 3, 'target': 2, 'value': 6 }, + { 'source': 4, 'target': 0, 'value': 1 }, + { 'source': 5, 'target': 3, 'value': 1 } + ] + } + }; + + export const chartClassExpected = { + lineChart: 'nv-lineChart', + discreteBarChart: 'nv-discreteBarWithAxes', + pieChart: 'nv-pieChart', + scatterChart: 'nv-scatterChart', + multiBarChart: 'nv-multiBarWithLegend', + multiBarHorizontalChart: 'nv-multiBarHorizontalChart', + candlestickBarChart: 'nv-historicalBarChart', + ohlcBarChart: 'nv-historicalBarChar', + boxPlotChart: 'nv-boxPlotWithAxes', + multiChart: 'multiChart', + sunburstChart: 'nv-sunburst', + stackedAreaChart: 'nv-stackedAreaChart', + cumulativeLineChart: 'nv-cumulativeLine', + historicalBarChart: 'nv-historicalBarChart', + parallelCoordinates: 'nv-parallelCoordinates', + sparklinePlus: 'nv-sparklineplus', + bulletChart: 'nv-bulletChart', + linePlusBarWithFocusChart: 'nv-linePlusBar', + forceDirectedGraph: 'nv-force-node' + }; +} diff --git a/src/test/test.component.ts b/src/test/test.component.ts new file mode 100644 index 0000000..e7d086e --- /dev/null +++ b/src/test/test.component.ts @@ -0,0 +1,8 @@ +import { Component, DebugElement } from '@angular/core'; + +@Component({ template: `
` }) +/** experimanetalDecorator */ +export class TestComponent { + public options: any; + public data: any; +} diff --git a/src/test/test.ts b/src/test/test.ts new file mode 100644 index 0000000..0c1e929 --- /dev/null +++ b/src/test/test.ts @@ -0,0 +1,32 @@ +import './polyfills.ts'; + +import 'zone.js/dist/long-stack-trace-zone'; +import 'zone.js/dist/proxy.js'; +import 'zone.js/dist/sync-test'; +import 'zone.js/dist/jasmine-patch'; +import 'zone.js/dist/async-test'; +import 'zone.js/dist/fake-async-test'; +import { getTestBed } from '@angular/core/testing'; +import { + BrowserDynamicTestingModule, + platformBrowserDynamicTesting +} from '@angular/platform-browser-dynamic/testing'; + +// Unfortunately there's no typing for the `__karma__` variable. Just declare it as any. +declare var __karma__: any; +declare var require: any; + +// Prevent Karma from running prematurely. +__karma__.loaded = function () {}; + +// First, initialize the Angular testing environment. +getTestBed().initTestEnvironment( + BrowserDynamicTestingModule, + platformBrowserDynamicTesting() +); +// Then we find all the tests. +let context = require.context('./', true, /\.spec\.ts$/); +// And load the modules. +context.keys().map(context); +// Finally, start Karma to run the tests. +__karma__.start(); \ No newline at end of file diff --git a/test/angular2-nvd3.spec.ts b/test/angular2-nvd3.spec.ts deleted file mode 100644 index 0ffdd02..0000000 --- a/test/angular2-nvd3.spec.ts +++ /dev/null @@ -1 +0,0 @@ -// TODO \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index b69568f..fac2c08 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,6 +19,7 @@ "files": [ "src/angular2-nvd3/angular2-nvd3.component.ts", "src/angular2-nvd3/angular2-nvd3.directive.ts", - "src/angular2-nvd3/angular2-nvd3.module.ts" + "src/angular2-nvd3/angular2-nvd3.module.ts", + "src/test/angular2-nvd3.component.spec.ts" ] } \ No newline at end of file diff --git a/tslint.json b/tslint.json index be9a920..580480b 100644 --- a/tslint.json +++ b/tslint.json @@ -20,7 +20,7 @@ ], "quotemark": [ true, - "double" + "single" ], "semicolon": [ true, diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..e207768 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,14 @@ +module.exports = { + resolve: { + extensions: ['.ts', '.js', '.tsx', '.jsx', ''] + }, + module: { + loaders: [ + { + test: /\.tsx?$/, + exclude: /node_modules/, + loader: 'ts-loader' + } + ] + } +};