mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-08-18 07:49:26 +02:00
Compare commits
25 Commits
mermaid@11
...
xychart
Author | SHA1 | Date | |
---|---|---|---|
![]() |
4f9cf4f9fc | ||
![]() |
90be8dedf6 | ||
![]() |
f1490ff679 | ||
![]() |
25160d9688 | ||
![]() |
533a921ef5 | ||
![]() |
3bef03f568 | ||
![]() |
737f4f0cf3 | ||
![]() |
71e5a2b3a3 | ||
![]() |
54f1435839 | ||
![]() |
48a20c5cb8 | ||
![]() |
5f4f1cc08d | ||
![]() |
da0a4ae37d | ||
![]() |
2972012059 | ||
![]() |
cf641ba4fd | ||
![]() |
39e5064019 | ||
![]() |
7830d0c4bf | ||
![]() |
60d34bdc72 | ||
![]() |
3262a06a8e | ||
![]() |
506314598e | ||
![]() |
25a9479acf | ||
![]() |
1273f440a8 | ||
![]() |
e1d085925e | ||
![]() |
39d175314c | ||
![]() |
17426f0a97 | ||
![]() |
a36fa7cd2f |
@@ -1,18 +1,19 @@
|
|||||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
||||||
|
|
||||||
describe('XY Chart', () => {
|
describe('XY Chart', () => {
|
||||||
it('should render the simplest possible chart', () => {
|
describe('single dataset', () => {
|
||||||
imgSnapshotTest(
|
it('should render the simplest possible chart', () => {
|
||||||
`
|
imgSnapshotTest(
|
||||||
|
`
|
||||||
xychart-beta
|
xychart-beta
|
||||||
line [10, 30, 20]
|
line [10, 30, 20]
|
||||||
`,
|
`,
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('Should render a complete chart', () => {
|
it('Should render a complete chart', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
xychart-beta
|
xychart-beta
|
||||||
title "Sales Revenue"
|
title "Sales Revenue"
|
||||||
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
||||||
@@ -20,82 +21,68 @@ describe('XY Chart', () => {
|
|||||||
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||||
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||||
`,
|
`,
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('Should render a chart without title', () => {
|
it('Should render a chart without title', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
xychart-beta
|
xychart-beta
|
||||||
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
||||||
y-axis "Revenue (in $)" 4000 --> 11000
|
y-axis "Revenue (in $)" 4000 --> 11000
|
||||||
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||||
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||||
`,
|
`,
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('y-axis title not required', () => {
|
it('y-axis title not required', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
xychart-beta
|
xychart-beta
|
||||||
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
||||||
y-axis 4000 --> 11000
|
y-axis 4000 --> 11000
|
||||||
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||||
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||||
`,
|
`,
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('Should render a chart without y-axis with different range', () => {
|
it('Should render a chart without y-axis with different range', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
xychart-beta
|
xychart-beta
|
||||||
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
||||||
bar [5000, 6000, 7500, 8200, 9500, 10500, 14000, 3200, 9200, 9900, 3400, 6000]
|
bar [5000, 6000, 7500, 8200, 9500, 10500, 14000, 3200, 9200, 9900, 3400, 6000]
|
||||||
line [2000, 7000, 6500, 9200, 9500, 7500, 11000, 10200, 3200, 8500, 7000, 8800]
|
line [2000, 7000, 6500, 9200, 9500, 7500, 11000, 10200, 3200, 8500, 7000, 8800]
|
||||||
`,
|
`,
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('x axis title not required', () => {
|
it('x axis title not required', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
xychart-beta
|
xychart-beta
|
||||||
x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
||||||
bar [5000, 6000, 7500, 8200, 9500, 10500, 14000, 3200, 9200, 9900, 3400, 6000]
|
bar [5000, 6000, 7500, 8200, 9500, 10500, 14000, 3200, 9200, 9900, 3400, 6000]
|
||||||
line [2000, 7000, 6500, 9200, 9500, 7500, 11000, 10200, 3200, 8500, 7000, 8800]
|
line [2000, 7000, 6500, 9200, 9500, 7500, 11000, 10200, 3200, 8500, 7000, 8800]
|
||||||
`,
|
`,
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('Multiple plots can be rendered', () => {
|
it('Decimals and negative numbers are supported', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
xychart-beta
|
|
||||||
line [23, 46, 77, 34]
|
|
||||||
line [45, 32, 33, 12]
|
|
||||||
bar [87, 54, 99, 85]
|
|
||||||
line [78, 88, 22, 4]
|
|
||||||
line [22, 29, 75, 33]
|
|
||||||
bar [52, 96, 35, 10]
|
|
||||||
`,
|
|
||||||
{}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
it('Decimals and negative numbers are supported', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`
|
|
||||||
xychart-beta
|
xychart-beta
|
||||||
y-axis -2.4 --> 3.5
|
y-axis -2.4 --> 3.5
|
||||||
line [+1.3, .6, 2.4, -.34]
|
line [+1.3, .6, 2.4, -.34]
|
||||||
`,
|
`,
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('Render spark line with "plotReservedSpacePercent"', () => {
|
it('Render spark line with "plotReservedSpacePercent"', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
---
|
---
|
||||||
config:
|
config:
|
||||||
theme: dark
|
theme: dark
|
||||||
@@ -107,12 +94,12 @@ describe('XY Chart', () => {
|
|||||||
xychart-beta
|
xychart-beta
|
||||||
line [5000, 9000, 7500, 6200, 9500, 5500, 11000, 8200, 9200, 9500, 7000, 8800]
|
line [5000, 9000, 7500, 6200, 9500, 5500, 11000, 8200, 9200, 9500, 7000, 8800]
|
||||||
`,
|
`,
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('Render spark bar without displaying other property', () => {
|
it('Render spark bar without displaying other property', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
---
|
---
|
||||||
config:
|
config:
|
||||||
theme: dark
|
theme: dark
|
||||||
@@ -133,12 +120,12 @@ describe('XY Chart', () => {
|
|||||||
xychart-beta
|
xychart-beta
|
||||||
bar [5000, 9000, 7500, 6200, 9500, 5500, 11000, 8200, 9200, 9500, 7000, 8800]
|
bar [5000, 9000, 7500, 6200, 9500, 5500, 11000, 8200, 9200, 9500, 7000, 8800]
|
||||||
`,
|
`,
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('Should use all the config from directive', () => {
|
it('Should use all the config from directive', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
%%{init: {"xyChart": {"width": 1000, "height": 600, "titlePadding": 5, "titleFontSize": 10, "xAxis": {"labelFontSize": "20", "labelPadding": 10, "titleFontSize": 30, "titlePadding": 20, "tickLength": 10, "tickWidth": 5}, "yAxis": {"labelFontSize": "20", "labelPadding": 10, "titleFontSize": 30, "titlePadding": 20, "tickLength": 10, "tickWidth": 5}, "plotBorderWidth": 5, "chartOrientation": "horizontal", "plotReservedSpacePercent": 60 }}}%%
|
%%{init: {"xyChart": {"width": 1000, "height": 600, "titlePadding": 5, "titleFontSize": 10, "xAxis": {"labelFontSize": "20", "labelPadding": 10, "titleFontSize": 30, "titlePadding": 20, "tickLength": 10, "tickWidth": 5}, "yAxis": {"labelFontSize": "20", "labelPadding": 10, "titleFontSize": 30, "titlePadding": 20, "tickLength": 10, "tickWidth": 5}, "plotBorderWidth": 5, "chartOrientation": "horizontal", "plotReservedSpacePercent": 60 }}}%%
|
||||||
xychart-beta
|
xychart-beta
|
||||||
title "Sales Revenue"
|
title "Sales Revenue"
|
||||||
@@ -147,12 +134,12 @@ describe('XY Chart', () => {
|
|||||||
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||||
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||||
`,
|
`,
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('Should use all the config from yaml', () => {
|
it('Should use all the config from yaml', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
---
|
---
|
||||||
config:
|
config:
|
||||||
theme: forest
|
theme: forest
|
||||||
@@ -187,12 +174,12 @@ describe('XY Chart', () => {
|
|||||||
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||||
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||||
`,
|
`,
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('Render with show axis title false', () => {
|
it('Render with show axis title false', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
---
|
---
|
||||||
config:
|
config:
|
||||||
xyChart:
|
xyChart:
|
||||||
@@ -208,12 +195,12 @@ describe('XY Chart', () => {
|
|||||||
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||||
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||||
`,
|
`,
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('Render with show axis label false', () => {
|
it('Render with show axis label false', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
---
|
---
|
||||||
config:
|
config:
|
||||||
xyChart:
|
xyChart:
|
||||||
@@ -229,12 +216,12 @@ describe('XY Chart', () => {
|
|||||||
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||||
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||||
`,
|
`,
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('Render with show axis tick false', () => {
|
it('Render with show axis tick false', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
---
|
---
|
||||||
config:
|
config:
|
||||||
xyChart:
|
xyChart:
|
||||||
@@ -250,12 +237,12 @@ describe('XY Chart', () => {
|
|||||||
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||||
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||||
`,
|
`,
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('Render with show axis line false', () => {
|
it('Render with show axis line false', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
---
|
---
|
||||||
config:
|
config:
|
||||||
xyChart:
|
xyChart:
|
||||||
@@ -271,12 +258,12 @@ describe('XY Chart', () => {
|
|||||||
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||||
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||||
`,
|
`,
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('Render all the theme color', () => {
|
it('Render all the theme color', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
---
|
---
|
||||||
config:
|
config:
|
||||||
themeVariables:
|
themeVariables:
|
||||||
@@ -300,19 +287,110 @@ describe('XY Chart', () => {
|
|||||||
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||||
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||||
`,
|
`,
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
it('should use the correct distances between data points', () => {
|
|
||||||
imgSnapshotTest(
|
describe('multiple datasets', () => {
|
||||||
`
|
describe('vertical', () => {
|
||||||
|
it('should render bar diagram for 3 datasets', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`
|
||||||
xychart-beta
|
xychart-beta
|
||||||
x-axis 0 --> 2
|
title "Basic xychart with multiple datasets"
|
||||||
line [0, 1, 0, 1]
|
x-axis "Relevant categories" [category1, "category 2", category3, category4]
|
||||||
bar [1, 0, 1, 0]
|
y-axis Animals 0 --> 160
|
||||||
|
bar "dogs" [0, 20, 40, 30]
|
||||||
|
bar "cats" [20, 40, 0, 30]
|
||||||
|
bar "birds" [30, 60, 50, 30]
|
||||||
`,
|
`,
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
cy.get('svg');
|
cy.get('svg');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render line diagram for 3 datasets', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`
|
||||||
|
xychart-beta
|
||||||
|
title "Basic xychart with multiple datasets"
|
||||||
|
x-axis "Relevant categories" [category1, "category 2", category3, category4]
|
||||||
|
y-axis Animals 0 --> 160
|
||||||
|
line "dogs" [0, 20, 40, 30]
|
||||||
|
line "cats" [20, 40, 0, 30]
|
||||||
|
line "birds" [30, 60, 50, 30]
|
||||||
|
`,
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
cy.get('svg');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render a mix of multiple bar and line plots', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`
|
||||||
|
xychart-beta
|
||||||
|
line [23, 46, 77, 34]
|
||||||
|
line [45, 32, 33, 12]
|
||||||
|
bar [87, 54, 99, 85]
|
||||||
|
line [78, 88, 22, 4]
|
||||||
|
line [22, 29, 75, 33]
|
||||||
|
bar [52, 96, 35, 10]
|
||||||
|
`,
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
cy.get('svg');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('horizontal', () => {
|
||||||
|
it('should render bar diagram for 3 datasets', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`
|
||||||
|
xychart-beta horizontal
|
||||||
|
title "Basic xychart with multiple datasets"
|
||||||
|
x-axis "Relevant categories" [category1, "category 2", category3, category4]
|
||||||
|
y-axis Animals 0 --> 160
|
||||||
|
bar "dogs" [0, 20, 40, 30]
|
||||||
|
bar "cats" [20, 40, 0, 30]
|
||||||
|
bar "birds" [30, 60, 50, 30]
|
||||||
|
`,
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
cy.get('svg');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render line diagram for 3 datasets', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`
|
||||||
|
xychart-beta horizontal
|
||||||
|
title "Basic xychart with multiple datasets"
|
||||||
|
x-axis "Relevant categories" [category1, "category 2", category3, category4]
|
||||||
|
y-axis Animals 0 --> 160
|
||||||
|
line "dogs" [0, 20, 40, 30]
|
||||||
|
line "cats" [20, 40, 0, 30]
|
||||||
|
line "birds" [30, 60, 50, 30]
|
||||||
|
`,
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
cy.get('svg');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render a mix of multiple bar and line plots', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`
|
||||||
|
xychart-beta horizontal
|
||||||
|
line [23, 46, 77, 34]
|
||||||
|
line [45, 32, 33, 12]
|
||||||
|
bar [87, 54, 99, 85]
|
||||||
|
line [78, 88, 22, 4]
|
||||||
|
line [22, 29, 75, 33]
|
||||||
|
bar [52, 96, 35, 10]
|
||||||
|
`,
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
cy.get('svg');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -52,7 +52,7 @@
|
|||||||
line [+1.3, .6, 2.4, -.34]
|
line [+1.3, .6, 2.4, -.34]
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<h1>XY Charts Bar with multiple category</h1>
|
<h1>XY Charts bar with single dataset</h1>
|
||||||
<pre class="mermaid">
|
<pre class="mermaid">
|
||||||
xychart-beta
|
xychart-beta
|
||||||
title "Basic xychart with many categories"
|
title "Basic xychart with many categories"
|
||||||
@@ -61,7 +61,28 @@
|
|||||||
bar "sample bar" [52, 96, 35, 10, 87, 34, 67, 99]
|
bar "sample bar" [52, 96, 35, 10, 87, 34, 67, 99]
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<h1>XY Charts line with multiple category</h1>
|
<h1>XY Charts bar with multiple datasets</h1>
|
||||||
|
<pre class="mermaid">
|
||||||
|
xychart-beta
|
||||||
|
title "Basic xychart with multiple datasets"
|
||||||
|
x-axis "Relevant categories" [category1, "category 2", category3, category4]
|
||||||
|
bar "dogs" [0, 60, 40, 30]
|
||||||
|
bar "cats" [20, 40, 50, 30]
|
||||||
|
bar "birds" [30, 60, 50, 30]
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h1>XY Charts bar horizontal with multiple datasets</h1>
|
||||||
|
<pre class="mermaid">
|
||||||
|
xychart-beta horizontal
|
||||||
|
title "Basic xychart with multiple datasets"
|
||||||
|
x-axis "Relevant categories" [category1, "category 2", category3, category4]
|
||||||
|
y-axis Animals 0 --> 160
|
||||||
|
bar "dogs" [0, 60, 40, 30]
|
||||||
|
bar "cats" [20, 40, 50, 30]
|
||||||
|
bar "birds" [30, 60, 50, 30]
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h1>XY Charts line single dataset</h1>
|
||||||
<pre class="mermaid">
|
<pre class="mermaid">
|
||||||
xychart-beta
|
xychart-beta
|
||||||
title "Line chart with many category"
|
title "Line chart with many category"
|
||||||
@@ -70,7 +91,7 @@
|
|||||||
line "sample line" [52, 96, 35, 10, 87, 34, 67, 99]
|
line "sample line" [52, 96, 35, 10, 87, 34, 67, 99]
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<h1>XY Charts category with large text</h1>
|
<h1>XY Charts bar with large text</h1>
|
||||||
<pre class="mermaid">
|
<pre class="mermaid">
|
||||||
xychart-beta
|
xychart-beta
|
||||||
title "Basic xychart with many categories with category overlap"
|
title "Basic xychart with many categories with category overlap"
|
||||||
|
@@ -6,12 +6,54 @@
|
|||||||
|
|
||||||
# XY Chart
|
# XY Chart
|
||||||
|
|
||||||
> In the context of mermaid-js, the XY chart is a comprehensive charting module that encompasses various types of charts that utilize both x-axis and y-axis for data representation. Presently, it includes two fundamental chart types: the bar chart and the line chart. These charts are designed to visually display and analyze data that involve two numerical variables.
|
> In the context of mermaid-js, the XY chart is a comprehensive charting module that encompasses various types of charts that utilize both x-axis and y-axis for data representation. Presently, it includes two fundamental chart types: the bar chart and the line chart. These charts are designed to display one or more datasets containing categories of data.
|
||||||
|
|
||||||
> It's important to note that while the current implementation of mermaid-js includes these two chart types, the framework is designed to be dynamic and adaptable. Therefore, it has the capacity for expansion and the inclusion of additional chart types in the future. This means that users can expect an evolving suite of charting options within the XY chart module, catering to various data visualization needs as new chart types are introduced over time.
|
> It's important to note that while the current implementation of mermaid-js includes these two chart types, the framework is designed to be dynamic and adaptable. Therefore, it has the capacity for expansion and the inclusion of additional chart types in the future. This means that users can expect an evolving suite of charting options within the XY chart module, catering to various data visualization needs as new chart types are introduced over time.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
|
### bar chart displaying single dataset
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
xychart-beta
|
||||||
|
title "Sales Revenue"
|
||||||
|
x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
||||||
|
y-axis "Revenue (in $)" 4000 --> 11000
|
||||||
|
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||||
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
xychart-beta
|
||||||
|
title "Sales Revenue"
|
||||||
|
x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
||||||
|
y-axis "Revenue (in $)" 4000 --> 11000
|
||||||
|
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||||
|
```
|
||||||
|
|
||||||
|
### bar chart displaying 3 datasets
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
xychart-beta
|
||||||
|
title "Basic xychart with multiple datasets"
|
||||||
|
x-axis "Relevant categories" [category1, "category 2", category3, category4]
|
||||||
|
y-axis Animals 0 --> 160
|
||||||
|
bar "dogs" [40, 20, 40, 30]
|
||||||
|
bar "cats" [20, 40, 50, 30]
|
||||||
|
bar "birds" [30, 60, 50, 30]
|
||||||
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
xychart-beta
|
||||||
|
title "Basic xychart with multiple datasets"
|
||||||
|
x-axis "Relevant categories" [category1, "category 2", category3, category4]
|
||||||
|
y-axis Animals 0 --> 160
|
||||||
|
bar "dogs" [40, 20, 40, 30]
|
||||||
|
bar "cats" [20, 40, 50, 30]
|
||||||
|
bar "birds" [30, 60, 50, 30]
|
||||||
|
```
|
||||||
|
|
||||||
|
### combined bar/line chart displaying 2 datasets
|
||||||
|
|
||||||
```mermaid-example
|
```mermaid-example
|
||||||
xychart-beta
|
xychart-beta
|
||||||
title "Sales Revenue"
|
title "Sales Revenue"
|
||||||
|
@@ -0,0 +1,5 @@
|
|||||||
|
/*eslint-disable no-restricted-syntax */
|
||||||
|
export enum PlotType {
|
||||||
|
BAR = 'bar',
|
||||||
|
LINE = 'line',
|
||||||
|
}
|
@@ -3,7 +3,7 @@ import type { Axis } from '../axis/index.js';
|
|||||||
|
|
||||||
export class BarPlot {
|
export class BarPlot {
|
||||||
constructor(
|
constructor(
|
||||||
private barData: BarPlotData,
|
private barData: BarPlotData[],
|
||||||
private boundingRect: BoundingRect,
|
private boundingRect: BoundingRect,
|
||||||
private xAxis: Axis,
|
private xAxis: Axis,
|
||||||
private yAxis: Axis,
|
private yAxis: Axis,
|
||||||
@@ -12,49 +12,85 @@ export class BarPlot {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
getDrawableElement(): DrawableElem[] {
|
getDrawableElement(): DrawableElem[] {
|
||||||
const finalData: [number, number][] = this.barData.data.map((d) => [
|
const offset = new Array(this.barData[0].data.length).fill(0);
|
||||||
this.xAxis.getScaleValue(d[0]),
|
const enlarge = new Array(this.barData[0].data.length).fill(0);
|
||||||
this.yAxis.getScaleValue(d[1]),
|
return this.barData.map((barData, dataIndex) => {
|
||||||
]);
|
const finalData: [number, number][] = barData.data.map((d) => [
|
||||||
|
this.xAxis.getScaleValue(d[0]),
|
||||||
|
this.yAxis.getScaleValue(d[1]),
|
||||||
|
]);
|
||||||
|
|
||||||
const barPaddingPercent = 0.05;
|
const barPaddingPercent = 0.05;
|
||||||
|
|
||||||
const barWidth =
|
const barWidth =
|
||||||
Math.min(this.xAxis.getAxisOuterPadding() * 2, this.xAxis.getTickDistance()) *
|
Math.min(this.xAxis.getAxisOuterPadding() * 2, this.xAxis.getTickDistance()) *
|
||||||
(1 - barPaddingPercent);
|
(1 - barPaddingPercent);
|
||||||
const barWidthHalf = barWidth / 2;
|
const barWidthHalf = barWidth / 2;
|
||||||
|
|
||||||
if (this.orientation === 'horizontal') {
|
if (this.orientation === 'horizontal') {
|
||||||
return [
|
return {
|
||||||
{
|
groupTexts: ['plot', `bar-plot-${this.plotIndex}-${dataIndex}`],
|
||||||
groupTexts: ['plot', `bar-plot-${this.plotIndex}`],
|
|
||||||
type: 'rect',
|
type: 'rect',
|
||||||
data: finalData.map((data) => ({
|
data: finalData.map((data, index) => {
|
||||||
x: this.boundingRect.x,
|
const adjustForAxisOuterPadding = dataIndex > 0 ? this.yAxis.getAxisOuterPadding() : 0;
|
||||||
y: data[0] - barWidthHalf,
|
let x = offset[index] + this.boundingRect.x;
|
||||||
height: barWidth,
|
let width = data[1] - this.boundingRect.x - adjustForAxisOuterPadding;
|
||||||
width: data[1] - this.boundingRect.x,
|
if (enlarge[index] > 0) {
|
||||||
fill: this.barData.fill,
|
x -= enlarge[index];
|
||||||
strokeWidth: 0,
|
width += enlarge[index];
|
||||||
strokeFill: this.barData.fill,
|
enlarge[index] = 0;
|
||||||
})),
|
offset[index] -= adjustForAxisOuterPadding;
|
||||||
},
|
}
|
||||||
];
|
offset[index] += width;
|
||||||
}
|
if (barData.data[index][1] === 0 && enlarge[index] === 0) {
|
||||||
return [
|
enlarge[index] = width;
|
||||||
{
|
}
|
||||||
groupTexts: ['plot', `bar-plot-${this.plotIndex}`],
|
if (barData.data[index][1] === 0) {
|
||||||
|
width = 0;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
x,
|
||||||
|
y: data[0] - barWidthHalf,
|
||||||
|
height: barWidth,
|
||||||
|
width,
|
||||||
|
fill: barData.fill,
|
||||||
|
strokeWidth: 0,
|
||||||
|
strokeFill: barData.fill,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
groupTexts: ['plot', `bar-plot-${this.plotIndex}-${dataIndex}`],
|
||||||
type: 'rect',
|
type: 'rect',
|
||||||
data: finalData.map((data) => ({
|
data: finalData.map((data, index) => {
|
||||||
x: data[0] - barWidthHalf,
|
const adjustForAxisOuterPadding = dataIndex > 0 ? this.yAxis.getAxisOuterPadding() : 0;
|
||||||
y: data[1],
|
const y = data[1] - offset[index] + adjustForAxisOuterPadding;
|
||||||
width: barWidth,
|
let height =
|
||||||
height: this.boundingRect.y + this.boundingRect.height - data[1],
|
this.boundingRect.y + this.boundingRect.height - data[1] - adjustForAxisOuterPadding;
|
||||||
fill: this.barData.fill,
|
if (enlarge[index] > 0) {
|
||||||
strokeWidth: 0,
|
height += enlarge[index];
|
||||||
strokeFill: this.barData.fill,
|
enlarge[index] = 0;
|
||||||
})),
|
offset[index] -= adjustForAxisOuterPadding;
|
||||||
},
|
}
|
||||||
];
|
offset[index] += height;
|
||||||
|
if (barData.data[index][1] === 0 && enlarge[index] === 0) {
|
||||||
|
enlarge[index] = height;
|
||||||
|
}
|
||||||
|
if (barData.data[index][1] === 0) {
|
||||||
|
height = 0;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
x: data[0] - barWidthHalf,
|
||||||
|
y,
|
||||||
|
width: barWidth,
|
||||||
|
height,
|
||||||
|
fill: barData.fill,
|
||||||
|
strokeWidth: 0,
|
||||||
|
strokeFill: barData.fill,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,11 +6,14 @@ import type {
|
|||||||
Point,
|
Point,
|
||||||
XYChartThemeConfig,
|
XYChartThemeConfig,
|
||||||
XYChartConfig,
|
XYChartConfig,
|
||||||
|
BarPlotData,
|
||||||
|
LinePlotData,
|
||||||
} from '../../interfaces.js';
|
} from '../../interfaces.js';
|
||||||
import type { Axis } from '../axis/index.js';
|
import type { Axis } from '../axis/index.js';
|
||||||
import type { ChartComponent } from '../../interfaces.js';
|
import type { ChartComponent } from '../../interfaces.js';
|
||||||
import { LinePlot } from './linePlot.js';
|
import { LinePlot } from './linePlot.js';
|
||||||
import { BarPlot } from './barPlot.js';
|
import { BarPlot } from './barPlot.js';
|
||||||
|
import { PlotType } from './PlotType.js';
|
||||||
|
|
||||||
export interface Plot extends ChartComponent {
|
export interface Plot extends ChartComponent {
|
||||||
setAxes(xAxis: Axis, yAxis: Axis): void;
|
setAxes(xAxis: Axis, yAxis: Axis): void;
|
||||||
@@ -55,34 +58,35 @@ export class BasePlot implements Plot {
|
|||||||
throw Error('Axes must be passed to render Plots');
|
throw Error('Axes must be passed to render Plots');
|
||||||
}
|
}
|
||||||
const drawableElem: DrawableElem[] = [];
|
const drawableElem: DrawableElem[] = [];
|
||||||
for (const [i, plot] of this.chartData.plots.entries()) {
|
const linePlots = this.chartData.plots.filter(
|
||||||
switch (plot.type) {
|
(plot) => plot.type === PlotType.LINE
|
||||||
case 'line':
|
) as LinePlotData[];
|
||||||
{
|
const barPlots = this.chartData.plots.filter(
|
||||||
const linePlot = new LinePlot(
|
(plot) => plot.type === PlotType.BAR
|
||||||
plot,
|
) as BarPlotData[];
|
||||||
this.xAxis,
|
|
||||||
this.yAxis,
|
let plotIndex = 0;
|
||||||
this.chartConfig.chartOrientation,
|
if (linePlots.length) {
|
||||||
i
|
const linePlot = new LinePlot(
|
||||||
);
|
linePlots,
|
||||||
drawableElem.push(...linePlot.getDrawableElement());
|
this.xAxis,
|
||||||
}
|
this.yAxis,
|
||||||
break;
|
this.chartConfig.chartOrientation,
|
||||||
case 'bar':
|
plotIndex
|
||||||
{
|
);
|
||||||
const barPlot = new BarPlot(
|
drawableElem.push(...linePlot.getDrawableElement());
|
||||||
plot,
|
}
|
||||||
this.boundingRect,
|
if (barPlots.length) {
|
||||||
this.xAxis,
|
const barPlot = new BarPlot(
|
||||||
this.yAxis,
|
barPlots,
|
||||||
this.chartConfig.chartOrientation,
|
this.boundingRect,
|
||||||
i
|
this.xAxis,
|
||||||
);
|
this.yAxis,
|
||||||
drawableElem.push(...barPlot.getDrawableElement());
|
this.chartConfig.chartOrientation,
|
||||||
}
|
plotIndex
|
||||||
break;
|
);
|
||||||
}
|
drawableElem.push(...barPlot.getDrawableElement());
|
||||||
|
plotIndex++;
|
||||||
}
|
}
|
||||||
return drawableElem;
|
return drawableElem;
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,7 @@ import type { Axis } from '../axis/index.js';
|
|||||||
|
|
||||||
export class LinePlot {
|
export class LinePlot {
|
||||||
constructor(
|
constructor(
|
||||||
private plotData: LinePlotData,
|
private plotData: LinePlotData[],
|
||||||
private xAxis: Axis,
|
private xAxis: Axis,
|
||||||
private yAxis: Axis,
|
private yAxis: Axis,
|
||||||
private orientation: XYChartConfig['chartOrientation'],
|
private orientation: XYChartConfig['chartOrientation'],
|
||||||
@@ -12,36 +12,40 @@ export class LinePlot {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
getDrawableElement(): DrawableElem[] {
|
getDrawableElement(): DrawableElem[] {
|
||||||
const finalData: [number, number][] = this.plotData.data.map((d) => [
|
const drawables: DrawableElem[] = [];
|
||||||
this.xAxis.getScaleValue(d[0]),
|
this.plotData.forEach((plotData, dataIndex) => {
|
||||||
this.yAxis.getScaleValue(d[1]),
|
|
||||||
]);
|
|
||||||
|
|
||||||
let path: string | null;
|
|
||||||
if (this.orientation === 'horizontal') {
|
|
||||||
path = line()
|
|
||||||
.y((d) => d[0])
|
|
||||||
.x((d) => d[1])(finalData);
|
|
||||||
} else {
|
|
||||||
path = line()
|
|
||||||
.x((d) => d[0])
|
|
||||||
.y((d) => d[1])(finalData);
|
|
||||||
}
|
|
||||||
if (!path) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
return [
|
|
||||||
{
|
{
|
||||||
groupTexts: ['plot', `line-plot-${this.plotIndex}`],
|
const finalData: [number, number][] = plotData.data.map((d) => [
|
||||||
type: 'path',
|
this.xAxis.getScaleValue(d[0]),
|
||||||
data: [
|
this.yAxis.getScaleValue(d[1]),
|
||||||
{
|
]);
|
||||||
path,
|
|
||||||
strokeFill: this.plotData.strokeFill,
|
let path: string | null;
|
||||||
strokeWidth: this.plotData.strokeWidth,
|
if (this.orientation === 'horizontal') {
|
||||||
},
|
path = line()
|
||||||
],
|
.y((d) => d[0])
|
||||||
},
|
.x((d) => d[1])(finalData);
|
||||||
];
|
} else {
|
||||||
|
path = line()
|
||||||
|
.x((d) => d[0])
|
||||||
|
.y((d) => d[1])(finalData);
|
||||||
|
}
|
||||||
|
if (!path) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
drawables.push({
|
||||||
|
groupTexts: ['plot', `line-plot-${this.plotIndex}-${dataIndex}`],
|
||||||
|
type: 'path',
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
path,
|
||||||
|
strokeFill: plotData.strokeFill,
|
||||||
|
strokeWidth: plotData.strokeWidth,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return drawables;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
import { PlotType } from './components/plot/PlotType.js';
|
||||||
|
|
||||||
export interface XYChartAxisThemeConfig {
|
export interface XYChartAxisThemeConfig {
|
||||||
titleColor: string;
|
titleColor: string;
|
||||||
labelColor: string;
|
labelColor: string;
|
||||||
@@ -28,14 +30,14 @@ export interface ChartComponent {
|
|||||||
export type SimplePlotDataType = [string, number][];
|
export type SimplePlotDataType = [string, number][];
|
||||||
|
|
||||||
export interface LinePlotData {
|
export interface LinePlotData {
|
||||||
type: 'line';
|
type: PlotType.LINE;
|
||||||
strokeFill: string;
|
strokeFill: string;
|
||||||
strokeWidth: number;
|
strokeWidth: number;
|
||||||
data: SimplePlotDataType;
|
data: SimplePlotDataType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BarPlotData {
|
export interface BarPlotData {
|
||||||
type: 'bar';
|
type: PlotType.BAR;
|
||||||
fill: string;
|
fill: string;
|
||||||
data: SimplePlotDataType;
|
data: SimplePlotDataType;
|
||||||
}
|
}
|
||||||
@@ -43,7 +45,7 @@ export interface BarPlotData {
|
|||||||
export type PlotData = LinePlotData | BarPlotData;
|
export type PlotData = LinePlotData | BarPlotData;
|
||||||
|
|
||||||
export function isBarPlot(data: PlotData): data is BarPlotData {
|
export function isBarPlot(data: PlotData): data is BarPlotData {
|
||||||
return data.type === 'bar';
|
return data.type === PlotType.BAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BandAxisDataType {
|
export interface BandAxisDataType {
|
||||||
|
@@ -33,384 +33,388 @@ describe('Testing xychart jison file', () => {
|
|||||||
clearMocks();
|
clearMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw error if xychart-beta text is not there', () => {
|
describe('single dataset', () => {
|
||||||
const str = 'xychart-beta-1';
|
it('should throw error if xychart-beta text is not there', () => {
|
||||||
expect(parserFnConstructor(str)).toThrow();
|
const str = 'xychart-beta-1';
|
||||||
});
|
expect(parserFnConstructor(str)).toThrow();
|
||||||
|
|
||||||
it('should not throw error if only xychart is there', () => {
|
|
||||||
const str = 'xychart-beta';
|
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('parse title of the chart within "', () => {
|
|
||||||
const str = 'xychart-beta \n title "This is a title"';
|
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
|
||||||
expect(mockDB.setDiagramTitle).toHaveBeenCalledWith('This is a title');
|
|
||||||
});
|
|
||||||
it('parse title of the chart without "', () => {
|
|
||||||
const str = 'xychart-beta \n title oneLinertitle';
|
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
|
||||||
expect(mockDB.setDiagramTitle).toHaveBeenCalledWith('oneLinertitle');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('parse chart orientation', () => {
|
|
||||||
const str = 'xychart-beta vertical';
|
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
|
||||||
expect(mockDB.setOrientation).toHaveBeenCalledWith('vertical');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('parse chart orientation with spaces', () => {
|
|
||||||
let str = 'xychart-beta horizontal ';
|
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
|
||||||
expect(mockDB.setOrientation).toHaveBeenCalledWith('horizontal');
|
|
||||||
|
|
||||||
str = 'xychart-beta abc';
|
|
||||||
expect(parserFnConstructor(str)).toThrow();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('parse x-axis', () => {
|
|
||||||
const str = 'xychart-beta \nx-axis xAxisName\n';
|
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
|
||||||
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({
|
|
||||||
text: 'xAxisName',
|
|
||||||
type: 'text',
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it('parse x-axis with axis name without "', () => {
|
it('should not throw error if only xychart is there', () => {
|
||||||
const str = 'xychart-beta \nx-axis xAxisName \n';
|
const str = 'xychart-beta';
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({
|
|
||||||
text: 'xAxisName',
|
|
||||||
type: 'text',
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it('parse x-axis with axis name with "', () => {
|
it('parse title of the chart within "', () => {
|
||||||
const str = 'xychart-beta \n x-axis "xAxisName has space"\n';
|
const str = 'xychart-beta \n title "This is a title"';
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({
|
expect(mockDB.setDiagramTitle).toHaveBeenCalledWith('This is a title');
|
||||||
text: 'xAxisName has space',
|
});
|
||||||
type: 'text',
|
it('parse title of the chart without "', () => {
|
||||||
|
const str = 'xychart-beta \n title oneLinertitle';
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
expect(mockDB.setDiagramTitle).toHaveBeenCalledWith('oneLinertitle');
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it('parse x-axis with axis name with " with spaces', () => {
|
it('parse chart orientation', () => {
|
||||||
const str = 'xychart-beta \n x-axis " xAxisName has space " \n';
|
const str = 'xychart-beta vertical';
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({
|
expect(mockDB.setOrientation).toHaveBeenCalledWith('vertical');
|
||||||
text: ' xAxisName has space ',
|
|
||||||
type: 'text',
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it('parse x-axis with axis name and range data', () => {
|
it('parse chart orientation with spaces', () => {
|
||||||
const str = 'xychart-beta \nx-axis xAxisName 45.5 --> 33 \n';
|
let str = 'xychart-beta horizontal ';
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({
|
expect(mockDB.setOrientation).toHaveBeenCalledWith('horizontal');
|
||||||
text: 'xAxisName',
|
|
||||||
type: 'text',
|
|
||||||
});
|
|
||||||
expect(mockDB.setXAxisRangeData).toHaveBeenCalledWith(45.5, 33);
|
|
||||||
});
|
|
||||||
it('parse x-axis throw error for invalid range data', () => {
|
|
||||||
const str = 'xychart-beta \nx-axis xAxisName aaa --> 33 \n';
|
|
||||||
expect(parserFnConstructor(str)).toThrow();
|
|
||||||
});
|
|
||||||
it('parse x-axis with axis name and range data with only decimal part', () => {
|
|
||||||
const str = 'xychart-beta \nx-axis xAxisName 45.5 --> .34 \n';
|
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
|
||||||
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({
|
|
||||||
text: 'xAxisName',
|
|
||||||
type: 'text',
|
|
||||||
});
|
|
||||||
expect(mockDB.setXAxisRangeData).toHaveBeenCalledWith(45.5, 0.34);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('parse x-axis without axisname and range data', () => {
|
str = 'xychart-beta abc';
|
||||||
const str = 'xychart-beta \nx-axis 45.5 --> 1.34 \n';
|
expect(parserFnConstructor(str)).toThrow();
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
|
||||||
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({
|
|
||||||
text: '',
|
|
||||||
type: 'text',
|
|
||||||
});
|
});
|
||||||
expect(mockDB.setXAxisRangeData).toHaveBeenCalledWith(45.5, 1.34);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('parse x-axis with axis name and category data', () => {
|
it('parse x-axis', () => {
|
||||||
const str = 'xychart-beta \nx-axis xAxisName [ "cat1" , cat2a ] \n ';
|
const str = 'xychart-beta \nx-axis xAxisName\n';
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({
|
||||||
text: 'xAxisName',
|
text: 'xAxisName',
|
||||||
type: 'text',
|
|
||||||
});
|
|
||||||
expect(mockDB.setXAxisBand).toHaveBeenCalledWith([
|
|
||||||
{
|
|
||||||
text: 'cat1',
|
|
||||||
type: 'text',
|
type: 'text',
|
||||||
},
|
});
|
||||||
{ text: 'cat2a', type: 'text' },
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('parse x-axis without axisname and category data', () => {
|
|
||||||
const str = 'xychart-beta \nx-axis [ "cat1" , cat2a ] \n ';
|
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
|
||||||
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({
|
|
||||||
text: '',
|
|
||||||
type: 'text',
|
|
||||||
});
|
});
|
||||||
expect(mockDB.setXAxisBand).toHaveBeenCalledWith([
|
|
||||||
{
|
it('parse x-axis with axis name without "', () => {
|
||||||
text: 'cat1',
|
const str = 'xychart-beta \nx-axis xAxisName \n';
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({
|
||||||
|
text: 'xAxisName',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
},
|
});
|
||||||
{ text: 'cat2a', type: 'text' },
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('parse x-axis throw error if unbalanced bracket', () => {
|
|
||||||
let str = 'xychart-beta \nx-axis xAxisName [ "cat1" [ cat2a ] \n ';
|
|
||||||
expect(parserFnConstructor(str)).toThrow();
|
|
||||||
str = 'xychart-beta \nx-axis xAxisName [ "cat1" , cat2a ] ] \n ';
|
|
||||||
expect(parserFnConstructor(str)).toThrow();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('parse x-axis complete variant 1', () => {
|
|
||||||
const str = `xychart-beta \n x-axis "this is x axis" [category1, "category 2", category3]\n`;
|
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
|
||||||
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'this is x axis', type: 'text' });
|
|
||||||
expect(mockDB.setXAxisBand).toHaveBeenCalledWith([
|
|
||||||
{ text: 'category1', type: 'text' },
|
|
||||||
{ text: 'category 2', type: 'text' },
|
|
||||||
{ text: 'category3', type: 'text' },
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('parse x-axis complete variant 2', () => {
|
|
||||||
const str =
|
|
||||||
'xychart-beta \nx-axis xAxisName [ "cat1 with space" , cat2 , cat3] \n ';
|
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
|
||||||
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' });
|
|
||||||
expect(mockDB.setXAxisBand).toHaveBeenCalledWith([
|
|
||||||
{ text: 'cat1 with space', type: 'text' },
|
|
||||||
{ text: 'cat2', type: 'text' },
|
|
||||||
{ text: 'cat3', type: 'text' },
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('parse x-axis complete variant 3', () => {
|
|
||||||
const str =
|
|
||||||
'xychart-beta \nx-axis xAxisName [ "cat1 with space" , cat2 asdf , cat3] \n ';
|
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
|
||||||
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' });
|
|
||||||
expect(mockDB.setXAxisBand).toHaveBeenCalledWith([
|
|
||||||
{ text: 'cat1 with space', type: 'text' },
|
|
||||||
{ text: 'cat2asdf', type: 'text' },
|
|
||||||
{ text: 'cat3', type: 'text' },
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('parse y-axis with axis name', () => {
|
|
||||||
const str = 'xychart-beta \ny-axis yAxisName\n';
|
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
|
||||||
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' });
|
|
||||||
});
|
|
||||||
it('parse y-axis with axis name with spaces', () => {
|
|
||||||
const str = 'xychart-beta \ny-axis yAxisName \n';
|
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
|
||||||
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' });
|
|
||||||
});
|
|
||||||
it('parse y-axis with axis name with "', () => {
|
|
||||||
const str = 'xychart-beta \n y-axis "yAxisName has space"\n';
|
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
|
||||||
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({
|
|
||||||
text: 'yAxisName has space',
|
|
||||||
type: 'text',
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
it('parse y-axis with axis name with " and spaces', () => {
|
it('parse x-axis with axis name with "', () => {
|
||||||
const str = 'xychart-beta \n y-axis " yAxisName has space " \n';
|
const str = 'xychart-beta \n x-axis "xAxisName has space"\n';
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({
|
||||||
text: ' yAxisName has space ',
|
text: 'xAxisName has space',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
it('parse y-axis with axis name with range data', () => {
|
it('parse x-axis with axis name with " with spaces', () => {
|
||||||
const str = 'xychart-beta \ny-axis yAxisName 45.5 --> 33 \n';
|
const str = 'xychart-beta \n x-axis " xAxisName has space " \n';
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' });
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({
|
||||||
expect(mockDB.setYAxisRangeData).toHaveBeenCalledWith(45.5, 33);
|
text: ' xAxisName has space ',
|
||||||
});
|
type: 'text',
|
||||||
it('parse y-axis without axisname with range data', () => {
|
});
|
||||||
const str = 'xychart-beta \ny-axis 45.5 --> 33 \n';
|
});
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
|
||||||
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: '', type: 'text' });
|
it('parse x-axis with axis name and range data', () => {
|
||||||
expect(mockDB.setYAxisRangeData).toHaveBeenCalledWith(45.5, 33);
|
const str = 'xychart-beta \nx-axis xAxisName 45.5 --> 33 \n';
|
||||||
});
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
it('parse y-axis with axis name with range data with only decimal part', () => {
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({
|
||||||
const str = 'xychart-beta \ny-axis yAxisName 45.5 --> .33 \n';
|
text: 'xAxisName',
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
type: 'text',
|
||||||
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' });
|
});
|
||||||
expect(mockDB.setYAxisRangeData).toHaveBeenCalledWith(45.5, 0.33);
|
expect(mockDB.setXAxisRangeData).toHaveBeenCalledWith(45.5, 33);
|
||||||
});
|
});
|
||||||
it('parse y-axis throw error for invalid number in range data', () => {
|
it('parse x-axis throw error for invalid range data', () => {
|
||||||
const str = 'xychart-beta \ny-axis yAxisName 45.5 --> abc \n';
|
const str = 'xychart-beta \nx-axis xAxisName aaa --> 33 \n';
|
||||||
expect(parserFnConstructor(str)).toThrow();
|
expect(parserFnConstructor(str)).toThrow();
|
||||||
});
|
});
|
||||||
it('parse y-axis throws error if range data is passed', () => {
|
it('parse x-axis with axis name and range data with only decimal part', () => {
|
||||||
const str = 'xychart-beta \ny-axis yAxisName [ 45.3, 33 ] \n';
|
const str = 'xychart-beta \nx-axis xAxisName 45.5 --> .34 \n';
|
||||||
expect(parserFnConstructor(str)).toThrow();
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
});
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({
|
||||||
it('parse both axis at once', () => {
|
text: 'xAxisName',
|
||||||
const str = 'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n';
|
type: 'text',
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
});
|
||||||
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' });
|
expect(mockDB.setXAxisRangeData).toHaveBeenCalledWith(45.5, 0.34);
|
||||||
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' });
|
});
|
||||||
});
|
|
||||||
it('parse line Data', () => {
|
it('parse x-axis without axisname and range data', () => {
|
||||||
const str = 'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n line lineTitle [23, 45, 56.6]';
|
const str = 'xychart-beta \nx-axis 45.5 --> 1.34 \n';
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
expect(mockDB.setLineData).toHaveBeenCalledWith(
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({
|
||||||
{ text: 'lineTitle', type: 'text' },
|
text: '',
|
||||||
[23, 45, 56.6]
|
type: 'text',
|
||||||
);
|
});
|
||||||
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' });
|
expect(mockDB.setXAxisRangeData).toHaveBeenCalledWith(45.5, 1.34);
|
||||||
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' });
|
});
|
||||||
});
|
|
||||||
it('parse line Data with spaces and +,- symbols', () => {
|
it('parse x-axis with axis name and category data', () => {
|
||||||
const str =
|
const str = 'xychart-beta \nx-axis xAxisName [ "cat1" , cat2a ] \n ';
|
||||||
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n line "lineTitle with space" [ +23 , -45 , 56.6 ] ';
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({
|
||||||
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' });
|
text: 'xAxisName',
|
||||||
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' });
|
type: 'text',
|
||||||
expect(mockDB.setLineData).toHaveBeenCalledWith(
|
});
|
||||||
{ text: 'lineTitle with space', type: 'text' },
|
expect(mockDB.setXAxisBand).toHaveBeenCalledWith([
|
||||||
[23, -45, 56.6]
|
{
|
||||||
);
|
text: 'cat1',
|
||||||
});
|
type: 'text',
|
||||||
it('parse line Data without title', () => {
|
},
|
||||||
const str =
|
{ text: 'cat2a', type: 'text' },
|
||||||
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n line [ +23 , -45 , 56.6 , .33] ';
|
]);
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
});
|
||||||
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' });
|
|
||||||
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' });
|
it('parse x-axis without axisname and category data', () => {
|
||||||
expect(mockDB.setLineData).toHaveBeenCalledWith(
|
const str = 'xychart-beta \nx-axis [ "cat1" , cat2a ] \n ';
|
||||||
{ text: '', type: 'text' },
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
[23, -45, 56.6, 0.33]
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({
|
||||||
);
|
text: '',
|
||||||
});
|
type: 'text',
|
||||||
it('parse line Data throws error unbalanced brackets', () => {
|
});
|
||||||
let str =
|
expect(mockDB.setXAxisBand).toHaveBeenCalledWith([
|
||||||
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n line "lineTitle with space" [ +23 [ -45 , 56.6 ] ';
|
{
|
||||||
expect(parserFnConstructor(str)).toThrow();
|
text: 'cat1',
|
||||||
str =
|
type: 'text',
|
||||||
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n line "lineTitle with space" [ +23 , -45 ] 56.6 ] ';
|
},
|
||||||
expect(parserFnConstructor(str)).toThrow();
|
{ text: 'cat2a', type: 'text' },
|
||||||
});
|
]);
|
||||||
it('parse line Data throws error if data is not provided', () => {
|
});
|
||||||
const str = 'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n line "lineTitle with space" ';
|
|
||||||
expect(parserFnConstructor(str)).toThrow();
|
it('parse x-axis throw error if unbalanced bracket', () => {
|
||||||
});
|
let str = 'xychart-beta \nx-axis xAxisName [ "cat1" [ cat2a ] \n ';
|
||||||
it('parse line Data throws error if data is empty', () => {
|
expect(parserFnConstructor(str)).toThrow();
|
||||||
const str =
|
str = 'xychart-beta \nx-axis xAxisName [ "cat1" , cat2a ] ] \n ';
|
||||||
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n line "lineTitle with space" [ ] ';
|
expect(parserFnConstructor(str)).toThrow();
|
||||||
expect(parserFnConstructor(str)).toThrow();
|
});
|
||||||
});
|
|
||||||
it('parse line Data throws error if , is not in proper', () => {
|
it('parse x-axis complete variant 1', () => {
|
||||||
const str =
|
const str = `xychart-beta \n x-axis "this is x axis" [category1, "category 2", category3]\n`;
|
||||||
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n line "lineTitle with space" [ +23 , , -45 , 56.6 ] ';
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
expect(parserFnConstructor(str)).toThrow();
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'this is x axis', type: 'text' });
|
||||||
});
|
expect(mockDB.setXAxisBand).toHaveBeenCalledWith([
|
||||||
it('parse line Data throws error if not number', () => {
|
{ text: 'category1', type: 'text' },
|
||||||
const str =
|
{ text: 'category 2', type: 'text' },
|
||||||
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n line "lineTitle with space" [ +23 , -4aa5 , 56.6 ] ';
|
{ text: 'category3', type: 'text' },
|
||||||
expect(parserFnConstructor(str)).toThrow();
|
]);
|
||||||
});
|
});
|
||||||
it('parse bar Data', () => {
|
|
||||||
const str =
|
it('parse x-axis complete variant 2', () => {
|
||||||
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n bar barTitle [23, 45, 56.6, .22]';
|
const str =
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
'xychart-beta \nx-axis xAxisName [ "cat1 with space" , cat2 , cat3] \n ';
|
||||||
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' });
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' });
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' });
|
||||||
expect(mockDB.setBarData).toHaveBeenCalledWith(
|
expect(mockDB.setXAxisBand).toHaveBeenCalledWith([
|
||||||
{ text: 'barTitle', type: 'text' },
|
{ text: 'cat1 with space', type: 'text' },
|
||||||
[23, 45, 56.6, 0.22]
|
{ text: 'cat2', type: 'text' },
|
||||||
);
|
{ text: 'cat3', type: 'text' },
|
||||||
});
|
]);
|
||||||
it('parse bar Data spaces and +,- symbol', () => {
|
});
|
||||||
const str =
|
|
||||||
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n bar "barTitle with space" [ +23 , -45 , 56.6 ] ';
|
it('parse x-axis complete variant 3', () => {
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
const str =
|
||||||
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' });
|
'xychart-beta \nx-axis xAxisName [ "cat1 with space" , cat2 asdf , cat3] \n ';
|
||||||
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' });
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
expect(mockDB.setBarData).toHaveBeenCalledWith(
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' });
|
||||||
{ text: 'barTitle with space', type: 'text' },
|
expect(mockDB.setXAxisBand).toHaveBeenCalledWith([
|
||||||
[23, -45, 56.6]
|
{ text: 'cat1 with space', type: 'text' },
|
||||||
);
|
{ text: 'cat2asdf', type: 'text' },
|
||||||
});
|
{ text: 'cat3', type: 'text' },
|
||||||
it('parse bar Data without plot title', () => {
|
]);
|
||||||
const str =
|
});
|
||||||
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n bar [ +23 , -45 , 56.6 ] ';
|
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
it('parse y-axis with axis name', () => {
|
||||||
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' });
|
const str = 'xychart-beta \ny-axis yAxisName\n';
|
||||||
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' });
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
expect(mockDB.setBarData).toHaveBeenCalledWith({ text: '', type: 'text' }, [23, -45, 56.6]);
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' });
|
||||||
});
|
});
|
||||||
it('parse bar should throw for unbalanced brackets', () => {
|
it('parse y-axis with axis name with spaces', () => {
|
||||||
let str =
|
const str = 'xychart-beta \ny-axis yAxisName \n';
|
||||||
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n bar "barTitle with space" [ +23 [ -45 , 56.6 ] ';
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
expect(parserFnConstructor(str)).toThrow();
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' });
|
||||||
str =
|
});
|
||||||
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n bar "barTitle with space" [ +23 , -45 ] 56.6 ] ';
|
it('parse y-axis with axis name with "', () => {
|
||||||
expect(parserFnConstructor(str)).toThrow();
|
const str = 'xychart-beta \n y-axis "yAxisName has space"\n';
|
||||||
});
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
it('parse bar should throw error if data is not provided', () => {
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({
|
||||||
const str = 'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n bar "barTitle with space" ';
|
text: 'yAxisName has space',
|
||||||
expect(parserFnConstructor(str)).toThrow();
|
type: 'text',
|
||||||
});
|
});
|
||||||
it('parse bar should throw error if data is empty', () => {
|
});
|
||||||
const str =
|
it('parse y-axis with axis name with " and spaces', () => {
|
||||||
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n bar "barTitle with space" [ ] ';
|
const str = 'xychart-beta \n y-axis " yAxisName has space " \n';
|
||||||
expect(parserFnConstructor(str)).toThrow();
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
});
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({
|
||||||
it('parse bar should throw error if comma is not proper', () => {
|
text: ' yAxisName has space ',
|
||||||
const str =
|
type: 'text',
|
||||||
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n bar "barTitle with space" [ +23 , , -45 , 56.6 ] ';
|
});
|
||||||
expect(parserFnConstructor(str)).toThrow();
|
});
|
||||||
});
|
it('parse y-axis with axis name with range data', () => {
|
||||||
it('parse bar should throw error if number is not passed', () => {
|
const str = 'xychart-beta \ny-axis yAxisName 45.5 --> 33 \n';
|
||||||
const str =
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n bar "barTitle with space" [ +23 , -4aa5 , 56.6 ] ';
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' });
|
||||||
expect(parserFnConstructor(str)).toThrow();
|
expect(mockDB.setYAxisRangeData).toHaveBeenCalledWith(45.5, 33);
|
||||||
});
|
});
|
||||||
it('parse multiple bar and line variant 1', () => {
|
it('parse y-axis without axisname with range data', () => {
|
||||||
const str =
|
const str = 'xychart-beta \ny-axis 45.5 --> 33 \n';
|
||||||
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n bar barTitle1 [23, 45, 56.6] \n line lineTitle1 [11, 45.5, 67, 23] \n bar barTitle2 [13, 42, 56.89] \n line lineTitle2 [45, 99, 012]';
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: '', type: 'text' });
|
||||||
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' });
|
expect(mockDB.setYAxisRangeData).toHaveBeenCalledWith(45.5, 33);
|
||||||
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' });
|
});
|
||||||
expect(mockDB.setBarData).toHaveBeenCalledWith(
|
it('parse y-axis with axis name with range data with only decimal part', () => {
|
||||||
{ text: 'barTitle1', type: 'text' },
|
const str = 'xychart-beta \ny-axis yAxisName 45.5 --> .33 \n';
|
||||||
[23, 45, 56.6]
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
);
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' });
|
||||||
expect(mockDB.setBarData).toHaveBeenCalledWith(
|
expect(mockDB.setYAxisRangeData).toHaveBeenCalledWith(45.5, 0.33);
|
||||||
{ text: 'barTitle2', type: 'text' },
|
});
|
||||||
[13, 42, 56.89]
|
it('parse y-axis throw error for invalid number in range data', () => {
|
||||||
);
|
const str = 'xychart-beta \ny-axis yAxisName 45.5 --> abc \n';
|
||||||
expect(mockDB.setLineData).toHaveBeenCalledWith(
|
expect(parserFnConstructor(str)).toThrow();
|
||||||
{ text: 'lineTitle1', type: 'text' },
|
});
|
||||||
[11, 45.5, 67, 23]
|
it('parse y-axis throws error if range data is passed', () => {
|
||||||
);
|
const str = 'xychart-beta \ny-axis yAxisName [ 45.3, 33 ] \n';
|
||||||
expect(mockDB.setLineData).toHaveBeenCalledWith(
|
expect(parserFnConstructor(str)).toThrow();
|
||||||
{ text: 'lineTitle2', type: 'text' },
|
});
|
||||||
[45, 99, 12]
|
it('parse both axis at once', () => {
|
||||||
);
|
const str = 'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n';
|
||||||
});
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
it('parse multiple bar and line variant 2', () => {
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' });
|
||||||
const str = `
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' });
|
||||||
|
});
|
||||||
|
it('parse line Data', () => {
|
||||||
|
const str =
|
||||||
|
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n line lineTitle [23, 45, 56.6]';
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
expect(mockDB.setLineData).toHaveBeenCalledWith(
|
||||||
|
{ text: 'lineTitle', type: 'text' },
|
||||||
|
[23, 45, 56.6]
|
||||||
|
);
|
||||||
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' });
|
||||||
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' });
|
||||||
|
});
|
||||||
|
it('parse line Data with spaces and +,- symbols', () => {
|
||||||
|
const str =
|
||||||
|
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n line "lineTitle with space" [ +23 , -45 , 56.6 ] ';
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' });
|
||||||
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' });
|
||||||
|
expect(mockDB.setLineData).toHaveBeenCalledWith(
|
||||||
|
{ text: 'lineTitle with space', type: 'text' },
|
||||||
|
[23, -45, 56.6]
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('parse line Data without title', () => {
|
||||||
|
const str =
|
||||||
|
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n line [ +23 , -45 , 56.6 , .33] ';
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' });
|
||||||
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' });
|
||||||
|
expect(mockDB.setLineData).toHaveBeenCalledWith(
|
||||||
|
{ text: '', type: 'text' },
|
||||||
|
[23, -45, 56.6, 0.33]
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('parse line Data throws error unbalanced brackets', () => {
|
||||||
|
let str =
|
||||||
|
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n line "lineTitle with space" [ +23 [ -45 , 56.6 ] ';
|
||||||
|
expect(parserFnConstructor(str)).toThrow();
|
||||||
|
str =
|
||||||
|
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n line "lineTitle with space" [ +23 , -45 ] 56.6 ] ';
|
||||||
|
expect(parserFnConstructor(str)).toThrow();
|
||||||
|
});
|
||||||
|
it('parse line Data throws error if data is not provided', () => {
|
||||||
|
const str =
|
||||||
|
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n line "lineTitle with space" ';
|
||||||
|
expect(parserFnConstructor(str)).toThrow();
|
||||||
|
});
|
||||||
|
it('parse line Data throws error if data is empty', () => {
|
||||||
|
const str =
|
||||||
|
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n line "lineTitle with space" [ ] ';
|
||||||
|
expect(parserFnConstructor(str)).toThrow();
|
||||||
|
});
|
||||||
|
it('parse line Data throws error if , is not in proper', () => {
|
||||||
|
const str =
|
||||||
|
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n line "lineTitle with space" [ +23 , , -45 , 56.6 ] ';
|
||||||
|
expect(parserFnConstructor(str)).toThrow();
|
||||||
|
});
|
||||||
|
it('parse line Data throws error if not number', () => {
|
||||||
|
const str =
|
||||||
|
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n line "lineTitle with space" [ +23 , -4aa5 , 56.6 ] ';
|
||||||
|
expect(parserFnConstructor(str)).toThrow();
|
||||||
|
});
|
||||||
|
it('parse bar Data', () => {
|
||||||
|
const str =
|
||||||
|
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n bar barTitle [23, 45, 56.6, .22]';
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' });
|
||||||
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' });
|
||||||
|
expect(mockDB.setBarData).toHaveBeenCalledWith(
|
||||||
|
{ text: 'barTitle', type: 'text' },
|
||||||
|
[23, 45, 56.6, 0.22]
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('parse bar Data spaces and +,- symbol', () => {
|
||||||
|
const str =
|
||||||
|
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n bar "barTitle with space" [ +23 , -45 , 56.6 ] ';
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' });
|
||||||
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' });
|
||||||
|
expect(mockDB.setBarData).toHaveBeenCalledWith(
|
||||||
|
{ text: 'barTitle with space', type: 'text' },
|
||||||
|
[23, -45, 56.6]
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('parse bar Data without plot title', () => {
|
||||||
|
const str =
|
||||||
|
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n bar [ +23 , -45 , 56.6 ] ';
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' });
|
||||||
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' });
|
||||||
|
expect(mockDB.setBarData).toHaveBeenCalledWith({ text: '', type: 'text' }, [23, -45, 56.6]);
|
||||||
|
});
|
||||||
|
it('parse bar should throw for unbalanced brackets', () => {
|
||||||
|
let str =
|
||||||
|
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n bar "barTitle with space" [ +23 [ -45 , 56.6 ] ';
|
||||||
|
expect(parserFnConstructor(str)).toThrow();
|
||||||
|
str =
|
||||||
|
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n bar "barTitle with space" [ +23 , -45 ] 56.6 ] ';
|
||||||
|
expect(parserFnConstructor(str)).toThrow();
|
||||||
|
});
|
||||||
|
it('parse bar should throw error if data is not provided', () => {
|
||||||
|
const str =
|
||||||
|
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n bar "barTitle with space" ';
|
||||||
|
expect(parserFnConstructor(str)).toThrow();
|
||||||
|
});
|
||||||
|
it('parse bar should throw error if data is empty', () => {
|
||||||
|
const str =
|
||||||
|
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n bar "barTitle with space" [ ] ';
|
||||||
|
expect(parserFnConstructor(str)).toThrow();
|
||||||
|
});
|
||||||
|
it('parse bar should throw error if comma is not proper', () => {
|
||||||
|
const str =
|
||||||
|
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n bar "barTitle with space" [ +23 , , -45 , 56.6 ] ';
|
||||||
|
expect(parserFnConstructor(str)).toThrow();
|
||||||
|
});
|
||||||
|
it('parse bar should throw error if number is not passed', () => {
|
||||||
|
const str =
|
||||||
|
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n bar "barTitle with space" [ +23 , -4aa5 , 56.6 ] ';
|
||||||
|
expect(parserFnConstructor(str)).toThrow();
|
||||||
|
});
|
||||||
|
it('parse multiple bar and line variant 1', () => {
|
||||||
|
const str =
|
||||||
|
'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n bar barTitle1 [23, 45, 56.6] \n line lineTitle1 [11, 45.5, 67, 23] \n bar barTitle2 [13, 42, 56.89] \n line lineTitle2 [45, 99, 012]';
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' });
|
||||||
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' });
|
||||||
|
expect(mockDB.setBarData).toHaveBeenCalledWith(
|
||||||
|
{ text: 'barTitle1', type: 'text' },
|
||||||
|
[23, 45, 56.6]
|
||||||
|
);
|
||||||
|
expect(mockDB.setBarData).toHaveBeenCalledWith(
|
||||||
|
{ text: 'barTitle2', type: 'text' },
|
||||||
|
[13, 42, 56.89]
|
||||||
|
);
|
||||||
|
expect(mockDB.setLineData).toHaveBeenCalledWith(
|
||||||
|
{ text: 'lineTitle1', type: 'text' },
|
||||||
|
[11, 45.5, 67, 23]
|
||||||
|
);
|
||||||
|
expect(mockDB.setLineData).toHaveBeenCalledWith(
|
||||||
|
{ text: 'lineTitle2', type: 'text' },
|
||||||
|
[45, 99, 12]
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('parse multiple bar and line variant 2', () => {
|
||||||
|
const str = `
|
||||||
xychart-beta horizontal
|
xychart-beta horizontal
|
||||||
title Basic xychart
|
title Basic xychart
|
||||||
x-axis "this is x axis" [category1, "category 2", category3]
|
x-axis "this is x axis" [category1, "category 2", category3]
|
||||||
@@ -419,30 +423,81 @@ describe('Testing xychart jison file', () => {
|
|||||||
line lineTitle1 [11, 45.5, 67, 23]
|
line lineTitle1 [11, 45.5, 67, 23]
|
||||||
bar barTitle2 [13, 42, 56.89]
|
bar barTitle2 [13, 42, 56.89]
|
||||||
line lineTitle2 [45, 99, 012]`;
|
line lineTitle2 [45, 99, 012]`;
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yaxisText', type: 'text' });
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yaxisText', type: 'text' });
|
||||||
expect(mockDB.setYAxisRangeData).toHaveBeenCalledWith(10, 150);
|
expect(mockDB.setYAxisRangeData).toHaveBeenCalledWith(10, 150);
|
||||||
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'this is x axis', type: 'text' });
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'this is x axis', type: 'text' });
|
||||||
expect(mockDB.setXAxisBand).toHaveBeenCalledWith([
|
expect(mockDB.setXAxisBand).toHaveBeenCalledWith([
|
||||||
{ text: 'category1', type: 'text' },
|
{ text: 'category1', type: 'text' },
|
||||||
{ text: 'category 2', type: 'text' },
|
{ text: 'category 2', type: 'text' },
|
||||||
{ text: 'category3', type: 'text' },
|
{ text: 'category3', type: 'text' },
|
||||||
]);
|
]);
|
||||||
expect(mockDB.setBarData).toHaveBeenCalledWith(
|
expect(mockDB.setBarData).toHaveBeenCalledWith(
|
||||||
{ text: 'barTitle1', type: 'text' },
|
{ text: 'barTitle1', type: 'text' },
|
||||||
[23, 45, 56.6]
|
[23, 45, 56.6]
|
||||||
);
|
);
|
||||||
expect(mockDB.setBarData).toHaveBeenCalledWith(
|
expect(mockDB.setBarData).toHaveBeenCalledWith(
|
||||||
{ text: 'barTitle2', type: 'text' },
|
{ text: 'barTitle2', type: 'text' },
|
||||||
[13, 42, 56.89]
|
[13, 42, 56.89]
|
||||||
);
|
);
|
||||||
expect(mockDB.setLineData).toHaveBeenCalledWith(
|
expect(mockDB.setLineData).toHaveBeenCalledWith(
|
||||||
{ text: 'lineTitle1', type: 'text' },
|
{ text: 'lineTitle1', type: 'text' },
|
||||||
[11, 45.5, 67, 23]
|
[11, 45.5, 67, 23]
|
||||||
);
|
);
|
||||||
expect(mockDB.setLineData).toHaveBeenCalledWith(
|
expect(mockDB.setLineData).toHaveBeenCalledWith(
|
||||||
{ text: 'lineTitle2', type: 'text' },
|
{ text: 'lineTitle2', type: 'text' },
|
||||||
[45, 99, 12]
|
[45, 99, 12]
|
||||||
);
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('multiple datasets', () => {
|
||||||
|
it('parse 2 datasets', () => {
|
||||||
|
const str = `xychart-beta
|
||||||
|
x-axis xAxisName
|
||||||
|
y-axis yAxisName
|
||||||
|
bar "barTitle1" [23, 45, 56.6]
|
||||||
|
bar "barTitle2" [13, 42, 56.89]`;
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' });
|
||||||
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' });
|
||||||
|
expect(mockDB.setBarData).toHaveBeenNthCalledWith(
|
||||||
|
1,
|
||||||
|
{ text: 'barTitle1', type: 'text' },
|
||||||
|
[23, 45, 56.6]
|
||||||
|
);
|
||||||
|
expect(mockDB.setBarData).toHaveBeenNthCalledWith(
|
||||||
|
2,
|
||||||
|
{ text: 'barTitle2', type: 'text' },
|
||||||
|
[13, 42, 56.89]
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('parse 3 datasets', () => {
|
||||||
|
const str = `xychart-beta
|
||||||
|
x-axis xAxisName
|
||||||
|
y-axis yAxisName
|
||||||
|
bar "barTitle1" [23, 45, 56.6]
|
||||||
|
bar "barTitle2" [13, 42, 56.89]
|
||||||
|
bar "barTitle3" [18, 37, 56.1]`;
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' });
|
||||||
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' });
|
||||||
|
expect(mockDB.setBarData).toHaveBeenNthCalledWith(
|
||||||
|
1,
|
||||||
|
{ text: 'barTitle1', type: 'text' },
|
||||||
|
[23, 45, 56.6]
|
||||||
|
);
|
||||||
|
expect(mockDB.setBarData).toHaveBeenNthCalledWith(
|
||||||
|
2,
|
||||||
|
{ text: 'barTitle2', type: 'text' },
|
||||||
|
[13, 42, 56.89]
|
||||||
|
);
|
||||||
|
expect(mockDB.setBarData).toHaveBeenNthCalledWith(
|
||||||
|
3,
|
||||||
|
{ text: 'barTitle3', type: 'text' },
|
||||||
|
[18, 37, 56.1]
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -22,6 +22,7 @@ import type {
|
|||||||
} from './chartBuilder/interfaces.js';
|
} from './chartBuilder/interfaces.js';
|
||||||
import { isBandAxisData, isLinearAxisData } from './chartBuilder/interfaces.js';
|
import { isBandAxisData, isLinearAxisData } from './chartBuilder/interfaces.js';
|
||||||
import type { Group } from '../../diagram-api/types.js';
|
import type { Group } from '../../diagram-api/types.js';
|
||||||
|
import { PlotType } from './chartBuilder/components/plot/PlotType.js';
|
||||||
|
|
||||||
let plotIndex = 0;
|
let plotIndex = 0;
|
||||||
|
|
||||||
@@ -34,6 +35,8 @@ let plotColorPalette = xyChartThemeConfig.plotColorPalette.split(',').map((color
|
|||||||
let hasSetXAxis = false;
|
let hasSetXAxis = false;
|
||||||
let hasSetYAxis = false;
|
let hasSetYAxis = false;
|
||||||
|
|
||||||
|
let dataSets: number[][] = [];
|
||||||
|
|
||||||
interface NormalTextType {
|
interface NormalTextType {
|
||||||
type: 'text';
|
type: 'text';
|
||||||
text: string;
|
text: string;
|
||||||
@@ -57,7 +60,7 @@ function getChartDefaultData(): XYChartData {
|
|||||||
yAxis: {
|
yAxis: {
|
||||||
type: 'linear',
|
type: 'linear',
|
||||||
title: '',
|
title: '',
|
||||||
min: Infinity,
|
min: 0,
|
||||||
max: -Infinity,
|
max: -Infinity,
|
||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
@@ -109,20 +112,26 @@ function setYAxisRangeData(min: number, max: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// this function does not set `hasSetYAxis` as there can be multiple data so we should calculate the range accordingly
|
// this function does not set `hasSetYAxis` as there can be multiple data so we should calculate the range accordingly
|
||||||
function setYAxisRangeFromPlotData(data: number[]) {
|
function setYAxisRangeFromPlotData(data: number[], plotType: PlotType) {
|
||||||
const minValue = Math.min(...data);
|
const sum = new Array(data.length).fill(0);
|
||||||
const maxValue = Math.max(...data);
|
if (plotType === PlotType.BAR) {
|
||||||
const prevMinValue = isLinearAxisData(xyChartData.yAxis) ? xyChartData.yAxis.min : Infinity;
|
dataSets.push(data);
|
||||||
const prevMaxValue = isLinearAxisData(xyChartData.yAxis) ? xyChartData.yAxis.max : -Infinity;
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
for (const entry of dataSets) {
|
||||||
|
sum[i] += entry[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
xyChartData.yAxis = {
|
xyChartData.yAxis = {
|
||||||
type: 'linear',
|
type: 'linear',
|
||||||
title: xyChartData.yAxis.title,
|
title: xyChartData.yAxis.title,
|
||||||
min: Math.min(prevMinValue, minValue),
|
min: isLinearAxisData(xyChartData.yAxis) ? xyChartData.yAxis.min : Math.min(...sum),
|
||||||
max: Math.max(prevMaxValue, maxValue),
|
max: Math.max(...sum),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function transformDataWithoutCategory(data: number[]): SimplePlotDataType {
|
function transformDataWithoutCategory(data: number[], plotType: PlotType): SimplePlotDataType {
|
||||||
let retData: SimplePlotDataType = [];
|
let retData: SimplePlotDataType = [];
|
||||||
if (data.length === 0) {
|
if (data.length === 0) {
|
||||||
return retData;
|
return retData;
|
||||||
@@ -133,11 +142,11 @@ function transformDataWithoutCategory(data: number[]): SimplePlotDataType {
|
|||||||
setXAxisRangeData(Math.min(prevMinValue, 1), Math.max(prevMaxValue, data.length));
|
setXAxisRangeData(Math.min(prevMinValue, 1), Math.max(prevMaxValue, data.length));
|
||||||
}
|
}
|
||||||
if (!hasSetYAxis) {
|
if (!hasSetYAxis) {
|
||||||
setYAxisRangeFromPlotData(data);
|
setYAxisRangeFromPlotData(data, plotType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isBandAxisData(xyChartData.xAxis)) {
|
if (isBandAxisData(xyChartData.xAxis)) {
|
||||||
retData = xyChartData.xAxis.categories.map((c, i) => [c, data[i]]);
|
retData = xyChartData.xAxis.categories.map((c, i) => [c, data[i] ?? 0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLinearAxisData(xyChartData.xAxis)) {
|
if (isLinearAxisData(xyChartData.xAxis)) {
|
||||||
@@ -148,7 +157,7 @@ function transformDataWithoutCategory(data: number[]): SimplePlotDataType {
|
|||||||
for (let i = min; i <= max; i += step) {
|
for (let i = min; i <= max; i += step) {
|
||||||
categories.push(`${i}`);
|
categories.push(`${i}`);
|
||||||
}
|
}
|
||||||
retData = categories.map((c, i) => [c, data[i]]);
|
retData = categories.map((c, i) => [c, data[i] ?? 0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return retData;
|
return retData;
|
||||||
@@ -159,9 +168,9 @@ function getPlotColorFromPalette(plotIndex: number): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setLineData(title: NormalTextType, data: number[]) {
|
function setLineData(title: NormalTextType, data: number[]) {
|
||||||
const plotData = transformDataWithoutCategory(data);
|
const plotData = transformDataWithoutCategory(data, PlotType.LINE);
|
||||||
xyChartData.plots.push({
|
xyChartData.plots.push({
|
||||||
type: 'line',
|
type: PlotType.LINE,
|
||||||
strokeFill: getPlotColorFromPalette(plotIndex),
|
strokeFill: getPlotColorFromPalette(plotIndex),
|
||||||
strokeWidth: 2,
|
strokeWidth: 2,
|
||||||
data: plotData,
|
data: plotData,
|
||||||
@@ -170,9 +179,9 @@ function setLineData(title: NormalTextType, data: number[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setBarData(title: NormalTextType, data: number[]) {
|
function setBarData(title: NormalTextType, data: number[]) {
|
||||||
const plotData = transformDataWithoutCategory(data);
|
const plotData = transformDataWithoutCategory(data, PlotType.BAR);
|
||||||
xyChartData.plots.push({
|
xyChartData.plots.push({
|
||||||
type: 'bar',
|
type: PlotType.BAR,
|
||||||
fill: getPlotColorFromPalette(plotIndex),
|
fill: getPlotColorFromPalette(plotIndex),
|
||||||
data: plotData,
|
data: plotData,
|
||||||
});
|
});
|
||||||
@@ -204,6 +213,7 @@ const clear = function () {
|
|||||||
plotColorPalette = xyChartThemeConfig.plotColorPalette.split(',').map((color) => color.trim());
|
plotColorPalette = xyChartThemeConfig.plotColorPalette.split(',').map((color) => color.trim());
|
||||||
hasSetXAxis = false;
|
hasSetXAxis = false;
|
||||||
hasSetYAxis = false;
|
hasSetYAxis = false;
|
||||||
|
dataSets = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@@ -1,11 +1,35 @@
|
|||||||
# XY Chart
|
# XY Chart
|
||||||
|
|
||||||
> In the context of mermaid-js, the XY chart is a comprehensive charting module that encompasses various types of charts that utilize both x-axis and y-axis for data representation. Presently, it includes two fundamental chart types: the bar chart and the line chart. These charts are designed to visually display and analyze data that involve two numerical variables.
|
> In the context of mermaid-js, the XY chart is a comprehensive charting module that encompasses various types of charts that utilize both x-axis and y-axis for data representation. Presently, it includes two fundamental chart types: the bar chart and the line chart. These charts are designed to display one or more datasets containing categories of data.
|
||||||
|
|
||||||
> It's important to note that while the current implementation of mermaid-js includes these two chart types, the framework is designed to be dynamic and adaptable. Therefore, it has the capacity for expansion and the inclusion of additional chart types in the future. This means that users can expect an evolving suite of charting options within the XY chart module, catering to various data visualization needs as new chart types are introduced over time.
|
> It's important to note that while the current implementation of mermaid-js includes these two chart types, the framework is designed to be dynamic and adaptable. Therefore, it has the capacity for expansion and the inclusion of additional chart types in the future. This means that users can expect an evolving suite of charting options within the XY chart module, catering to various data visualization needs as new chart types are introduced over time.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
|
### bar chart displaying single dataset
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
xychart-beta
|
||||||
|
title "Sales Revenue"
|
||||||
|
x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
||||||
|
y-axis "Revenue (in $)" 4000 --> 11000
|
||||||
|
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||||
|
```
|
||||||
|
|
||||||
|
### bar chart displaying 3 datasets
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
xychart-beta
|
||||||
|
title "Basic xychart with multiple datasets"
|
||||||
|
x-axis "Relevant categories" [category1, "category 2", category3, category4]
|
||||||
|
y-axis Animals 0 --> 160
|
||||||
|
bar "dogs" [40, 20, 40, 30]
|
||||||
|
bar "cats" [20, 40, 50, 30]
|
||||||
|
bar "birds" [30, 60, 50, 30]
|
||||||
|
```
|
||||||
|
|
||||||
|
### combined bar/line chart displaying 2 datasets
|
||||||
|
|
||||||
```mermaid-example
|
```mermaid-example
|
||||||
xychart-beta
|
xychart-beta
|
||||||
title "Sales Revenue"
|
title "Sales Revenue"
|
||||||
|
Reference in New Issue
Block a user