// MIT License // Copyright (c) 2022 Tree Xie // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. package charts import ( "strconv" "testing" "github.com/stretchr/testify/assert" ) func TestPieChart(t *testing.T) { assert := assert.New(t) tests := []struct { render func(*Painter) ([]byte, error) result string }{ { render: func(p *Painter) ([]byte, error) { values := []float64{ 1048, 735, 580, 484, 300, } _, err := NewPieChart(p, PieChartOption{ SeriesList: NewPieSeriesList(values, PieSeriesOption{ Label: SeriesLabel{ Show: true, }, }), Title: TitleOption{ Text: "Rainfall vs Evaporation", Subtext: "Fake Data", Left: PositionCenter, }, Padding: Box{ Top: 20, Right: 20, Bottom: 20, Left: 20, }, Legend: LegendOption{ Orient: OrientVertical, Data: []string{ "Search Engine", "Direct", "Email", "Union Ads", "Video Ads", }, Left: PositionLeft, }, }).Render() if err != nil { return nil, err } return p.Bytes() }, result: "\\nSearch EngineDirectEmailUnion AdsVideo AdsRainfall vs EvaporationFake DataSearch Engine: 33.3%Direct: 23.35%Email: 18.43%Union Ads: 15.37%Video Ads: 9.53%", }, } for _, tt := range tests { p, err := NewPainter(PainterOptions{ Type: ChartOutputSVG, Width: 600, Height: 400, }, PainterThemeOption(defaultTheme)) assert.Nil(err) data, err := tt.render(p.Child(PainterPaddingOption(Box{ Left: 20, Top: 20, Right: 20, Bottom: 20, }))) assert.Nil(err) assert.Equal(tt.result, string(data)) } } func TestPieChartWithLabelsValuesSortedDescending(t *testing.T) { assert := assert.New(t) tests := []struct { render func(*Painter) ([]byte, error) result string }{ { render: func(p *Painter) ([]byte, error) { values := []float64{ 84358845, 68070697, 58850717, 48059777, 36753736, 19051562, 17947406, 11754004, 10827529, 10521556, 10467366, 10394055, 9597085, 9104772, 6447710, 5932654, 5563970, 5428792, 5194336, 3850894, 2857279, 2116792, 1883008, 1373101, 920701, 660809, 542051, } _, err := NewPieChart(p, PieChartOption{ SeriesList: NewPieSeriesList(values, PieSeriesOption{ Label: SeriesLabel{ Show: true, Formatter: "{b} ({c} ≅ {d})", }, Radius: "200", }), Title: TitleOption{ Text: "European Union member states by population", Left: PositionRight, }, Padding: Box{ Top: 20, Right: 20, Bottom: 20, Left: 20, }, Legend: LegendOption{ Data: []string{ "Germany", "France", "Italy", "Spain", "Poland", "Romania", "Netherlands", "Belgium", "Czech Republic", "Sweden", "Portugal", "Greece", "Hungary", "Austria", "Bulgaria", "Denmark", "Finland", "Slovakia", "Ireland", "Croatia", "Lithuania", "Slovenia", "Latvia", "Estonia", "Cyprus", "Luxembourg", "Malta", }, Show: FalseFlag(), }, }).Render() if err != nil { return nil, err } return p.Bytes() }, result: "\\nEuropean Union member states by populationFrance (68070697 ≅ 15.17%)Germany (84358845 ≅ 18.8%)Italy (58850717 ≅ 13.12%)Spain (48059777 ≅ 10.71%)Belgium (11754004 ≅ 2.62%)Netherlands (17947406 ≅ 4%)Romania (19051562 ≅ 4.24%)Poland (36753736 ≅ 8.19%)Czech Republic (10827529 ≅ 2.41%)Sweden (10521556 ≅ 2.34%)Portugal (10467366 ≅ 2.33%)Greece (10394055 ≅ 2.31%)Hungary (9597085 ≅ 2.13%)Austria (9104772 ≅ 2.02%)Bulgaria (6447710 ≅ 1.43%)Denmark (5932654 ≅ 1.32%)Finland (5563970 ≅ 1.24%)Slovakia (5428792 ≅ 1.21%)Ireland (5194336 ≅ 1.15%)Croatia (3850894 ≅ 0.85%)Lithuania (2857279 ≅ 0.63%)Slovenia (2116792 ≅ 0.47%)Latvia (1883008 ≅ 0.41%)Estonia (1373101 ≅ 0.3%)Cyprus (920701 ≅ 0.2%)Luxembourg (660809 ≅ 0.14%)Malta (542051 ≅ 0.12%)", }, } for _, tt := range tests { p, err := NewPainter(PainterOptions{ Type: ChartOutputSVG, Width: 1000, Height: 800, }, PainterThemeOption(defaultTheme)) assert.Nil(err) data, err := tt.render(p.Child(PainterPaddingOption(Box{ Left: 20, Top: 20, Right: 20, Bottom: 20, }))) assert.Nil(err) assert.Equal(tt.result, string(data)) } } func TestPieChartWithLabelsValuesUnsorted(t *testing.T) { assert := assert.New(t) tests := []struct { render func(*Painter) ([]byte, error) result string }{ { render: func(p *Painter) ([]byte, error) { values := []float64{ 9104772, 11754004, 6447710, 3850894, 920701, 10827529, 5932654, 1373101, 5563970, 68070697, 84358845, 10394055, 9597085, 5194336, 58850717, 1883008, 2857279, 660809, 542051, 17947406, 36753736, 10467366, 19051562, 5428792, 2116792, 48059777, 10521556, } _, err := NewPieChart(p, PieChartOption{ SeriesList: NewPieSeriesList(values, PieSeriesOption{ Label: SeriesLabel{ Show: true, Formatter: "{b} ({c} ≅ {d})", }, Radius: "200", }), Title: TitleOption{ Text: "European Union member states by population", Left: PositionRight, }, Padding: Box{ Top: 20, Right: 20, Bottom: 20, Left: 20, }, Legend: LegendOption{ Data: []string{ "Austria", "Belgium", "Bulgaria", "Croatia", "Cyprus", "Czech Republic", "Denmark", "Estonia", "Finland", "France", "Germany", "Greece", "Hungary", "Ireland", "Italy", "Latvia", "Lithuania", "Luxembourg", "Malta", "Netherlands", "Poland", "Portugal", "Romania", "Slovakia", "Slovenia", "Spain", "Sweden", }, Show: FalseFlag(), }, }).Render() if err != nil { return nil, err } return p.Bytes() }, result: "\\nEuropean Union member states by populationFrance (68070697 ≅ 15.17%)Finland (5563970 ≅ 1.24%)Estonia (1373101 ≅ 0.3%)Denmark (5932654 ≅ 1.32%)Czech Republic (10827529 ≅ 2.41%)Cyprus (920701 ≅ 0.2%)Croatia (3850894 ≅ 0.85%)Bulgaria (6447710 ≅ 1.43%)Belgium (11754004 ≅ 2.62%)Austria (9104772 ≅ 2.02%)Germany (84358845 ≅ 18.8%)Greece (10394055 ≅ 2.31%)Hungary (9597085 ≅ 2.13%)Poland (36753736 ≅ 8.19%)Netherlands (17947406 ≅ 4%)Malta (542051 ≅ 0.12%)Luxembourg (660809 ≅ 0.14%)Lithuania (2857279 ≅ 0.63%)Latvia (1883008 ≅ 0.41%)Italy (58850717 ≅ 13.12%)Ireland (5194336 ≅ 1.15%)Portugal (10467366 ≅ 2.33%)Romania (19051562 ≅ 4.24%)Slovakia (5428792 ≅ 1.21%)Slovenia (2116792 ≅ 0.47%)Spain (48059777 ≅ 10.71%)Sweden (10521556 ≅ 2.34%)", }, } for _, tt := range tests { p, err := NewPainter(PainterOptions{ Type: ChartOutputSVG, Width: 1000, Height: 800, }, PainterThemeOption(defaultTheme)) assert.Nil(err) data, err := tt.render(p.Child(PainterPaddingOption(Box{ Left: 20, Top: 20, Right: 20, Bottom: 20, }))) assert.Nil(err) assert.Equal(tt.result, string(data)) } } func TestPieChartWith100Labels(t *testing.T) { assert := assert.New(t) tests := []struct { render func(*Painter) ([]byte, error) result string }{ { render: func(p *Painter) ([]byte, error) { var values []float64 var labels []string for i := 1; i <= 100; i++ { values = append(values, float64(1)) labels = append(labels, "Label "+strconv.Itoa(i)) } _, err := NewPieChart(p, PieChartOption{ SeriesList: NewPieSeriesList(values, PieSeriesOption{ Label: SeriesLabel{ Show: true, }, Radius: "200", }), Title: TitleOption{ Text: "Test with 100 labels", Left: PositionRight, }, Padding: Box{ Top: 20, Right: 20, Bottom: 20, Left: 20, }, Legend: LegendOption{ Data: labels, Show: FalseFlag(), }, }).Render() if err != nil { return nil, err } return p.Bytes() }, result: "\\nTest with 100 labelsLabel 25: 1%Label 24: 1%Label 23: 1%Label 22: 1%Label 21: 1%Label 20: 1%Label 19: 1%Label 18: 1%Label 17: 1%Label 16: 1%Label 15: 1%Label 14: 1%Label 13: 1%Label 12: 1%Label 11: 1%Label 10: 1%Label 9: 1%Label 8: 1%Label 7: 1%Label 6: 1%Label 5: 1%Label 4: 1%Label 3: 1%Label 2: 1%Label 1: 1%Label 26: 1%Label 27: 1%Label 28: 1%Label 29: 1%Label 30: 1%Label 31: 1%Label 32: 1%Label 33: 1%Label 34: 1%Label 35: 1%Label 36: 1%Label 37: 1%Label 38: 1%Label 39: 1%Label 40: 1%Label 41: 1%Label 42: 1%Label 43: 1%Label 44: 1%Label 45: 1%Label 46: 1%Label 47: 1%Label 48: 1%Label 49: 1%Label 50: 1%Label 75: 1%Label 74: 1%Label 73: 1%Label 72: 1%Label 71: 1%Label 70: 1%Label 69: 1%Label 68: 1%Label 67: 1%Label 66: 1%Label 65: 1%Label 64: 1%Label 63: 1%Label 62: 1%Label 61: 1%Label 60: 1%Label 59: 1%Label 58: 1%Label 57: 1%Label 56: 1%Label 55: 1%Label 54: 1%Label 53: 1%Label 52: 1%Label 51: 1%Label 76: 1%Label 77: 1%Label 78: 1%Label 79: 1%Label 80: 1%Label 81: 1%Label 82: 1%Label 83: 1%Label 84: 1%Label 85: 1%Label 86: 1%Label 87: 1%Label 88: 1%Label 89: 1%Label 90: 1%Label 91: 1%Label 92: 1%Label 93: 1%Label 94: 1%Label 95: 1%Label 96: 1%Label 97: 1%Label 98: 1%Label 99: 1%Label 100: 1%", }, } for _, tt := range tests { p, err := NewPainter(PainterOptions{ Type: ChartOutputSVG, Width: 1000, Height: 900, }, PainterThemeOption(defaultTheme)) assert.Nil(err) data, err := tt.render(p.Child(PainterPaddingOption(Box{ Left: 20, Top: 20, Right: 20, Bottom: 20, }))) assert.Nil(err) assert.Equal(tt.result, string(data)) } }