Since I'm trying to use your Highcharts package, I'm facing an issue when unit testing the component that use Highcharts function.
Here is my context:
I have a component (the only one) that use Highcharts. In the Web client, When I run unit test on this component, chart function legendItemClick not getting covered.
Code below are the Javascript transpilled code. Here is my original typescript file:
let dsCapacityChartOptions = {
chart: {
type: 'pie',
spacing: [0, 10, 2, 10],
margin: [-10, 0, 30, 0]
},
title: {
text: ''
},
credits: {
enabled: false
},
plotOptions: {
pie: {
shadow: false,
colors: ['#3E7BBF', '#CBCBCB', '#92B2D9'],
point: {
events: {
legendItemClick: function () {
return false;
}
}
}
},
series: {
states: {
hover: {
enabled: false
},
inactive: {
opacity: 1
}
}
}
},
tooltip: {
outside: true,
style: {
color: '#000000',
opacity: 1,
fontSize: '12px',
fontFamily: 'Metropolis,Avenir Next,Helvetica Neue,Arial,sans-serif'
},
formatter:
function () {
return '<b>' + this.point.x + '</b>: ' + this.point.formattedCapacity + " (" + this.percentage.toFixed(2) + "%)";
}
},
series: [{
type: 'pie',
name: this.labelsObj["vsc.portlet.dsCapacity.label"],
size: '80%',
innerSize: '70%',
showInLegend: true,
dataLabels: {
enabled: false
},
data: []
}],
legend: {
labelFormatter: function () {
return this.x + ": " + this.formattedCapacity;
},
align: 'center',
layout: 'vertical',
itemStyle: {
color: '#454545',
fontWeight: '500',
fontSize: '12px',
fontFamily: 'Metropolis,Avenir Next,Helvetica Neue,Arial,sans-serif'
},
itemHoverStyle: {
color: '#454545',
cursor: 'default'
}
},
exporting: { enabled: false }
};
Here is what I'm doing to make the unit tests works-
it('should call legendItemClick', () => {
let spy = spyOn(component.dsCapacityChartOptions.plotOptions.pie.point.events, 'legendItemClick')
component.dsCapacityChartOptions.plotOptions.pie.point.events.legendItemClick();
expect(spy).toHaveBeenCalledTimes(1);
})
Highcharts function not covered with unit tests with Karma + Jasmine
Please find below snippet of code coverage-
Code coverage
Your unit test doesn't make sense. You explicitly invoke a function and test if it was really called. In your case, legendItemClick returns a value, hence you should check the result of the call. There's no need to use a spy.
The test would then look simple as follows:
it('#legendItemClick should return false', () => {
const result = component.dsCapacityChartOptions.plotOptions.pie.point.events.legendItemClick();
expect(result).toBe(false);
})
Related
I want to align xaxis line and axis labels at position (0,0) when data contains negative values.
ex. consider this fiddle example where negative values bar goes down and xaxis is set at (0,0)
http://jsfiddle.net/13d54mp8/2/
var YTD = 'YTD';
var yr1 = 'Year 1';
var yr3 = '*3 Year';
var yr5 = '*5 Year';
var sinceIN = '* Since Inception (5/31/2012)';
$(function() {
var chart;
$(document).ready(function() {
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'column',
events: {
load: function() {
var xx = (-1) * (this.yAxis[0].translate(0, false, false));
this.xAxis[0].axisGroup.translate(0, xx);
this.xAxis[0].labelGroup.translate(0, xx);
}
}
},
title: {
text: 'Report Title',
style: {
fontSize: '18px',
color: '#1D5293',
fontWeight: 'bold'
},
},
subtitle: {
text: '(As of 6/30/2012)',
style: {
fontSize: '18px',
color: '#1D5293'
},
y: 40
},
xAxis: {
categories: [YTD, yr1, yr3, yr5, sinceIN],
lineColor: '#C1BADB',
tickWidth: 2,
},
yAxis: {
title: {
text: ''
},
lineColor: '#C1BADB',
lineWidth: 1,
labels: {
formatter: function() {
return this.value + '%';
}
},
gridLineWidth: 0,
tickWidth: 2
},
tooltip: {
enabled: true,
formatter: function() {
return this.series.name + ': ' + this.y + '%';
},
},
credits: {
enabled: false
},
series: [{
name: 'XXX Company Ltd. (Net)',
data: [3.02, -0.61, 2.03, 1.51, 5.35],
dataLabels: {
enabled: true,
color: '#333',
formatter: function() {
return this.y + '%'
}
},
color: '#1D5293'
},
{
name: 'XXX Relative Return Index (Gross)**',
data: [2.45, 0.85, 4.11, 0.73, 3.56],
dataLabels: {
enabled: true,
color: '#333',
formatter: function() {
return this.y + '%'
}
},
color: '#9E9E9E'
}
],
legend: {
layout: 'vertical',
align: 'top',
verticalAlign: 'top',
x: 50,
y: 65,
borderWidth: 0,
margin: 30
},
});
});
});
Now I want to make work the same use case for inverted column chart where xaxis is on top and yaxis is at right side. check fiddle - http://jsfiddle.net/fa2e80qu/3/
var YTD = 'YTD'
var yr1 = 'Year 1'
var yr3 = '*3 Year'
var yr5 = '*5 Year'
var yr7 = '*7 Year'
var yr9 = '*9 Year'
var sinceIN = '* Since '
$(function() {
var chart;
$(document).ready(function() {
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'column',
events: {
load: function() {
var xx = (0.34)* (this.yAxis[0].translate(0, false, false));
this.xAxis[0].axisGroup.translate(0, xx);
this.xAxis[0].labelGroup.translate(0, xx);
}
}
},
title: {
text: 'Report Title',
style: {
fontSize: '18px',
color: '#1D5293',
fontWeight: 'bold'
},
},
subtitle: {
text: '(As of 6/30/2012)',
style: {
fontSize: '18px',
color: '#1D5293'
},
y: 40
},
xAxis: {
categories: [YTD, yr1, yr3, yr5, yr7,yr9, sinceIN],
lineColor: '#C1BADB',
tickWidth: 2,
opposite:true
},
yAxis: {
opposite:true,
reversed:true,
title: {
text: ''
},
lineColor: '#C1BADB',
lineWidth: 1,
labels: {
formatter: function() {
return this.value + '%';
}
},
gridLineWidth: 0,
tickWidth: 2
},
tooltip: {
enabled: true,
formatter: function() {
return this.series.name + ': ' + this.y + '%';
},
},
credits: {
enabled: false
},
series: [
{
name: 'XXX Company Ltd. (Net)',
data: [3.02, -0.61, 2.03, 1.51, 5.35, -0.50,2.5],
dataLabels: {
enabled: true,
color: '#333',
formatter: function() {
return this.y + '%'
}
},
color: '#1D5293'},
{
name: 'XXX Relative Return Index (Gross)**',
data: [2.45, 0.85, 4.11, 0.73, 3.56,-0.5,1.6],
dataLabels: {
enabled: true,
color: '#333',
formatter: function() {
return this.y + '%'
}
},
color: '#9E9E9E'}
],
legend: {
enabled:false,
layout: 'vertical',
align: 'top',
verticalAlign: 'top',
x: 50,
y: 65,
borderWidth: 0,
margin: 30
},
});
});
});
Expected behavior is to have xaxis line and labels aligns properly at position (0,0)
You can use the toPixels method:
chart: {
...,
events: {
load: function() {
var xx = this.yAxis[0].toPixels(0) - this.plotTop;
this.xAxis[0].axisGroup.translate(0, xx);
this.xAxis[0].labelGroup.translate(0, xx);
}
}
}
Live demo: http://jsfiddle.net/BlackLabel/07rej16z/
API Reference: https://api.highcharts.com/class-reference/Highcharts.Axis#toPixels
In an Angular 4 project I am using the angular2-highcharts library to create a stacked bar chart. The following object is the configuration I have so far.
{
title: { text: '' },
xAxis: {
categories: [''],
crosshair: true,
visible: false
},
yAxis: {
min: 0,
max: 100,
title: {
text: ''
},
labels: {
enabled: true
},
visible: false
},
chart: {
type: 'bar',
backgroundColor: 'rgba(255, 255, 255, 0.1)'
},
legend: {
enabled: false
},
plotOptions: {
column: {
pointPadding: 0,
borderWidth: 0,
stacking: 'normal',
dataLabels: {
enabled: true,
formatter: function() {
return this.point.y + '%';
},
inside: true
},
enableMouseTracking: false,
},
series: {
stacking: 'normal',
dataLabels: {
enabled: true,
formatter: function () {
if (this.point.y) {
return this.point.y + '%';
}
return '';
},
style: { fontSize: '10px' },
padding: 10
},
borderWidth: 0
}
},
series: [{
name: 'Pending',
data: ...,
color: '#ff4233'
}, {
name: 'Executed',
data: ...,
color: '#34d788'
}, {
name: 'Cancelled',
data: ...,
color: '#8f8c87'
}]
}
and this produces this visual result ->
I need to transform this into ->
As you see in the desired result the chart has more height and also its edges are round. That I don't know how to do.
Have you tried to use rounded-corners plugin? With it you can use following properties:
borderRadiusTopLeft, borderRadiusTopRight, borderRadiusBottomRight and borderRadiusBottomLeft
Plugin Reference:
https://github.com/highcharts/rounded-corners
Example:
http://jsfiddle.net/3Lhzx8ao/
I've have had some problems with the highmaps library since a while back. I got reports from users that a map displaying statistics was not rendering sometimes.
When looking at the problem, I noticed that the map rendered quite inconsistently, sometimes perfect, but quite often - not at all.
When consulting the documentation at highcharts docs I realised that the example on jsfiddle suffers from the exact same problem. Sometimes the map simply does not render. I made a screen recording to show the problem.
This problem occurs in chrome and ff, I have not tried other browsers.
This is my code for the map, it's a part of a Angular app.
function createChart() {
chart = new Highcharts.Map({
chart: {
renderTo: 'mapContainer'
},
title: {
text: '',
},
credits: {
enabled: false
},
legend: {
layout: 'horizontal',
borderWidth: 0,
backgroundColor: 'rgba(255,255,255,0.85)',
floating: false,
verticalAlign: 'bottom',
horizontalAlign: 'center',
},
colorAxis: {
maxColor: '#7b9b00',
minColor: '#d7e241',
type: 'linear',
allowDecimals: false,
marker: {
color: 'black'
},
minPadding: 0.005
},
tooltip: {
formatter: function() {
return '<b>' + this.point.name + '</b><br>' +
'Asset Hits: ' + this.point.options.hits + '<br>' +
'Total Volume: ' + this.point.options.volume + '<br>';
},
style: {
fontSize: '12px',
fontFamily: 'Helvetica, Arial, sans-serif'
}
},
series: [{
mapData: Highcharts.maps['custom/world'],
name: 'countries',
showInLegend: false,
borderWidth: 0.2,
states: {
hover: {
borderWidth: 1
}
}
}]
});
}
scope.$on('geoData', function(event, data) {
var validData = function (data) {
var equal = _.isEqual(data, cachedData);
if (!equal && data.length > 1) {
return data;
}
};
if (validData) {
if (!chart) {
createChart();
}
updateSeries(data);
}
cachedData = data;
}, true);
function updateSeries(data) {
if (chart !== undefined) {
if (chart.series.length > 1) {
chart.series[1].remove();
}
}
chart.addSeries({
data: data,
title: 'Performance by Country',
mapData: Highcharts.maps['custom/world'],
joinBy: ['hc-key', 'countryiso'],
name: 'countries',
borderWidth: 0.2,
borderColor: 'black',
states: {
hover: {
borderWidth: 1,
color: '#7b9b00'
}
}
});
}
}
};
}
Video displaying the issue:
Link to video
I used Highchart to draw some charts in my page. And i was setting some properties for my charts. I see that for download and save charts in some type, Highchart used exporting. But properties of saved charts are not same of original chart.
for example my original chart is this:
My code is:
Highcharts.setOptions({ colors: color_items_array, locale: getPersianLocal()});
var chart;
$(document).ready(function() {
chart = new Highcharts.Chart({
exporting: {
allowHTML:true ,
chartOptions: {
xAxis: {
labels: {
align: 'top',
}
},
},
buttons: {
contextButton: {
menuItems: [{
textKey: 'printChart',
onclick: function () {
this.print();
}
}, {
separator: true
}, {
textKey: 'downloadPNG',
onclick: function () {
this.exportChart();
}
}, {
textKey: 'downloadJPEG',
onclick: function () {
this.exportChart({
type: 'image/jpeg'
});
}
}, {
textKey: 'downloadPDF',
onclick: function () {
this.exportChart({
type: 'application/pdf'
});
}
}, {
textKey: 'downloadSVG',
onclick: function () {
this.exportChart({
type: 'image/svg+xml'
});
}
}, {
separator: true
},{
text: 'Clinet side export to PNG',
onclick: function () {
this.exportChartLocal();
}
}, {
text: 'Clinet side export to SVG',
onclick: function () {
this.exportChartLocal({
type: 'image/svg+xml'
});
}
}]
}
}
},
chart: {
renderTo: conta,
type: type,
marginRight: 130,
marginBottom: 120
},
title: {
text: X_title,
x: -20 //center
},
subtitle: {
text: '',
x: -20
},
// plotOptions: {
// column: {
// minPointLength: 20
// }
//},
xAxis: {
min:0,
max:maxVariable,
labels: {
//rotation: rotlab,
align: 'top',
// align: 'center',
autoRotation: [-45],
autoRotationLimit: 100
},
categories: xAxisLabel
},
yAxis: yAxisVariale,
plotOptions: {
series: {
dataLabels: {
enabled: dataLabelvariable,
// y: -5,
inside:false,
crop :false,
overflow :'none',
style: {
fontWeight: 'bold'
},
formatter: function() {
return Highcharts.localizationNumber(this.y);
},
useHTML: true
}
}
},
tooltip: {
crosshairs: [true, true],
shared: true,
useHTML: true,
formatter: function() {
var s = [];
s.push('<table><tr><td style="text-align:right;" colspan="3"><b>' +
this.x + '</b></td></tr>');
$.each(this.points, function(i, point) {
s.push('<tr><td style="text-align: right;">'+
'<b><span style="color:'+point.series.color +'">\u25CF</span></b>'+
'</td>'+
'<td style="text-align: right;"><b>'+point.series.name +' : </b></td>'+
'<td><b>' + Highcharts.localizationNumber(point.y)+'</b></td>'+
'</tr>');
});
s.push('<tr><td style="text-align:right;" colspan="3"><b>تعداد خبر : ' +
Highcharts.localizationNumber(this.points[0].point.NumberNews) + '</b></td></tr></table>');
return s.join('');
}
},
legend: {
labelFormatter: function() {
return '<b>'+this.name+'</b>';
},
borderWidth: 1,
useHTML: true,
borderColor: '#C98657',
backgroundColor: '#FCFFC5'
},
series: seris_column2,
scrollbar: {
enabled: scrbal,
barBackgroundColor: 'gray',
barBorderRadius: 7,
barBorderWidth: 0,
buttonBackgroundColor: 'gray',
buttonBorderWidth: 0,
buttonArrowColor: 'yellow',
buttonBorderRadius: 7,
rifleColor: 'yellow',
trackBackgroundColor: 'white',
trackBorderWidth: 1,
trackBorderColor: 'silver',
trackBorderRadius: 7
}
});
});
My main problems are:
1) change font and size of strings(labels and titles ,..)
2) overlap of legent strings
3) when xaxis labels turn -45, labels go up.(for another example..)
I used :
exporting: {
allowHTML:true ,
chartOptions: {
xAxis: {
labels: {
align: 'top',
}
},
}
But didn't change any thing...
How can i do?
Thanks
I'm working with the highcharts stacked bar and want to remove some space between the bars so I can make room for some text I am rendering.
I've tried pointPadding and groupPadding but those are not working. I've tried minPadding/maxPadding on the xAxis and that did not do anything as well.
Seems the only way get rid of that space is to change the width of the whole chart which is what I really don't want.
Here is my fiddle:
http://jsfiddle.net/nick1572/dfcysj39/
$("#profit-chart").highcharts({
lang: {
thousandsSep: ","
},
chart: {
type: "column",
style: {
fontFamily: "Open Sans, sans-serif"
}
},
legend: {
enabled: false
},
title: {
text: ""
},
xAxis: {
//minPadding: 20, Not working here
//maxPadding:1, Not working here either
categories: [ "other business", "somekind of business profit" ],
labels: {
style: {
color: "#333333",
fontSize: "15px"
}
}
},
yAxis: {
gridLineDashStyle: "longdash",
title: {
text: "Dollars"
},
labels: {
enabled: true,
formatter: function() {
return "$" + Highcharts.numberFormat(this.value, 0, "", ",");
}
}
},
tooltip: {
enabled: false
},
plotOptions: {
column: {
stacking: "normal",
dataLabels: {
enabled: true,
color: "white",
inside: true,
useHTML: true,
style: {
fontSize: "18px",
fontWeight: "600"
}
}
},
series: {
//pointPadding: 0,
//groupPadding: 0, this does not work
animation: {
complete: function() {
}
},
pointWidth: 145
}
},
series: [ {
color: "#327631",
data: [ 0, 850 ],
stack: "female",
dataLabels: {
enabled: true,
formatter: function() {
if (0 != this.y) return "$" + Highcharts.numberFormat(this.y, 0);
else return null;
}
}
}, {
color: "#ADC9AD ",
data: [ 10000, 10000 ],
stack: "female",
dataLabels: {
enabled: true,
formatter: function() {
return "$" + Highcharts.numberFormat(this.y, 0);
}
}
}]
},
function (chart) { // on complete
chart.renderer.text('<span class="bracketed">}</span> <em>Profit</em>', 870, 85)
.css({
color: 'green',
fontSize: '24px',
x: 200
})
.add();
});//End HighCharts Call
Thanks in advance!
it seems that the point width setting is conflicting with the groupPadding and pointPadding .. if you remove the pointWidth: 145 in the series and add groupPadding and pointPadding to the column you will get the gap removed. on the flipside however the bars will take up the entire available width of your chart.
column: {
stacking: "normal",
groupPadding: 0,//add here
pointPadding: 0,//add here
...
}
http://jsfiddle.net/dfcysj39/9/
Ok so I think this may solve my problem at this point. Not sure if its the right way but it works. The pointPadding and groupPadding partially worked for this particular problem. I thank you Birgit for taking the time to respond!!!
What I did to solve this is explicitly put a spacingRight on the chart to give the plot area more space w/o making the bars wider. I did go back and add some pointPadding to make the cols a little wider for aesthetics. This allowed for the rendered text to show.
http://jsfiddle.net/nick1572/dfcysj39/
$("#profit-chart").highcharts({
lang: {
thousandsSep: ","
},
chart: {
spacingRight: 220,
type: "column",
width: 1200,
style: {
fontFamily: "Open Sans, sans-serif"
}
},
legend: {
enabled: false
},
title: {
text: ""
},
xAxis: {
//minPadding: 20, Not working here
//maxPadding:1, Not working here either
categories: [ "other business", "somekind of business profit" ],
labels: {
style: {
color: "#333333",
fontSize: "15px"
}
}
},
yAxis: {
gridLineDashStyle: "longdash",
title: {
text: "Dollars"
},
labels: {
enabled: true,
formatter: function() {
return "$" + Highcharts.numberFormat(this.value, 0, "", ",");
}
}
},
tooltip: {
enabled: false
},
plotOptions: {
column: {
stacking: "normal",
dataLabels: {
enabled: true,
color: "white",
inside: true,
useHTML: true,
style: {
fontSize: "18px",
fontWeight: "600"
}
}
},
series: {
pointPadding: 0.05,
//groupPadding: 0, this does not work
animation: {
complete: function() {
}
}//,
//pointWidth: 145
}
},
series: [ {
color: "#327631",
data: [ 0, 850 ],
stack: "female",
dataLabels: {
enabled: true,
formatter: function() {
if (0 != this.y) return "$" + Highcharts.numberFormat(this.y, 0);
else return null;
}
}
}, {
color: "#ADC9AD ",
data: [ 10000, 10000 ],
stack: "female",
dataLabels: {
enabled: true,
formatter: function() {
return "$" + Highcharts.numberFormat(this.y, 0);
}
}
}]
},
function (chart) { // on complete
chart.renderer.text('<span class="bracketed">}</span> <em>Profit</em>', 900, 84)
.css({
color: 'green',
fontSize: '24px',
x: 200
})
.add();
});//End HighCharts Call