From 212a51083f290aaa7770b7762ea8ee0992b24b5f Mon Sep 17 00:00:00 2001 From: vicanso Date: Mon, 20 Jun 2022 23:23:21 +0800 Subject: [PATCH] test: add test for charts --- chart_option.go | 12 +- echarts_test.go | 263 ++++++++++++++++++++++++++++++++++++++++++++ grid_test.go | 69 ++++++++++++ legend_test.go | 5 +- line_chart_test.go | 219 ++++++++++++++++++++++++++++++++++++ mark_line.go | 7 +- mark_line_test.go | 89 +++++++++++++++ mark_point_test.go | 92 ++++++++++++++++ pie_chart_test.go | 100 +++++++++++++++++ radar_chart.go | 14 +++ radar_chart_test.go | 109 ++++++++++++++++++ 11 files changed, 963 insertions(+), 16 deletions(-) create mode 100644 echarts_test.go create mode 100644 grid_test.go create mode 100644 line_chart_test.go create mode 100644 mark_line_test.go create mode 100644 mark_point_test.go create mode 100644 pie_chart_test.go create mode 100644 radar_chart_test.go diff --git a/chart_option.go b/chart_option.go index 643c4e7..db2f57b 100644 --- a/chart_option.go +++ b/chart_option.go @@ -201,17 +201,7 @@ func ChildOptionFunc(child ...ChartOption) OptionFunc { // RadarIndicatorOptionFunc set radar indicator of chart func RadarIndicatorOptionFunc(names []string, values []float64) OptionFunc { return func(opt *ChartOption) { - if len(names) != len(values) { - return - } - indicators := make([]RadarIndicator, len(names)) - for index, name := range names { - indicators[index] = RadarIndicator{ - Name: name, - Max: values[index], - } - } - opt.RadarIndicators = indicators + opt.RadarIndicators = NewRadarIndicators(names, values) } } diff --git a/echarts_test.go b/echarts_test.go new file mode 100644 index 0000000..1ed14d3 --- /dev/null +++ b/echarts_test.go @@ -0,0 +1,263 @@ +// 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 ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestConvertToArray(t *testing.T) { + assert := assert.New(t) + + assert.Equal([]byte(`[1]`), convertToArray([]byte("1"))) + assert.Equal([]byte(`[1]`), convertToArray([]byte("[1]"))) +} + +func TestEChartsPosition(t *testing.T) { + assert := assert.New(t) + var p EChartsPosition + err := p.UnmarshalJSON([]byte("1")) + assert.Nil(err) + assert.Equal(EChartsPosition("1"), p) + err = p.UnmarshalJSON([]byte(`"left"`)) + assert.Nil(err) + assert.Equal(EChartsPosition("left"), p) +} + +func TestEChartsSeriesDataValue(t *testing.T) { + assert := assert.New(t) + + es := EChartsSeriesDataValue{} + err := es.UnmarshalJSON([]byte(`[1, 2]`)) + assert.Nil(err) + assert.Equal(EChartsSeriesDataValue{ + values: []float64{ + 1, + 2, + }, + }, es) + assert.Equal(1.0, es.First()) +} + +func TestEChartsSeriesData(t *testing.T) { + assert := assert.New(t) + es := EChartsSeriesData{} + err := es.UnmarshalJSON([]byte("1.1")) + assert.Nil(err) + assert.Equal(EChartsSeriesDataValue{ + values: []float64{ + 1.1, + }, + }, es.Value) + + err = es.UnmarshalJSON([]byte(`{"value":200,"itemStyle":{"color":"#a90000"}}`)) + assert.Nil(err) + assert.Nil(err) + assert.Equal(EChartsSeriesData{ + Value: EChartsSeriesDataValue{ + values: []float64{ + 200.0, + }, + }, + ItemStyle: EChartStyle{ + Color: "#a90000", + }, + }, es) +} + +func TestEChartsXAxis(t *testing.T) { + assert := assert.New(t) + ex := EChartsXAxis{} + err := ex.UnmarshalJSON([]byte(`{"boundaryGap": true, "splitNumber": 5, "data": ["a", "b"], "type": "value"}`)) + assert.Nil(err) + + assert.Equal(EChartsXAxis{ + Data: []EChartsXAxisData{ + { + BoundaryGap: TrueFlag(), + SplitNumber: 5, + Data: []string{ + "a", + "b", + }, + Type: "value", + }, + }, + }, ex) +} + +func TestEChartsOption(t *testing.T) { + assert := assert.New(t) + + opt := EChartsOption{} + err := json.Unmarshal([]byte(`{ + "title": { + "text": "Rainfall vs Evaporation", + "subtext": "Fake Data" + }, + "tooltip": { + "trigger": "axis" + }, + "legend": { + "data": [ + "Rainfall", + "Evaporation" + ] + }, + "toolbox": { + "show": true, + "feature": { + "dataView": { + "show": true, + "readOnly": false + }, + "magicType": { + "show": true, + "type": [ + "line", + "bar" + ] + }, + "restore": { + "show": true + }, + "saveAsImage": { + "show": true + } + } + }, + "calculable": true, + "xAxis": [ + { + "type": "category", + "data": [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec" + ] + } + ], + "yAxis": [ + { + "type": "value" + } + ], + "series": [ + { + "name": "Rainfall", + "type": "bar", + "data": [ + 2, + 4.9, + 7, + 23.2, + 25.6, + 76.7, + 135.6, + 162.2, + 32.6, + 20, + 6.4, + 3.3 + ], + "markPoint": { + "data": [ + { + "type": "max", + "name": "Max" + }, + { + "type": "min", + "name": "Min" + } + ] + }, + "markLine": { + "data": [ + { + "type": "average", + "name": "Avg" + } + ] + } + }, + { + "name": "Evaporation", + "type": "bar", + "data": [ + 2.6, + 5.9, + 9, + 26.4, + 28.7, + 70.7, + 175.6, + 182.2, + 48.7, + 18.8, + 6, + 2.3 + ], + "markPoint": { + "data": [ + { + "name": "Max", + "value": 182.2, + "xAxis": 7, + "yAxis": 183 + }, + { + "name": "Min", + "value": 2.3, + "xAxis": 11, + "yAxis": 3 + } + ] + }, + "markLine": { + "data": [ + { + "type": "average", + "name": "Avg" + } + ] + } + } + ] + }`), &opt) + + assert.Nil(err) + assert.NotEmpty(opt.Series) +} diff --git a/grid_test.go b/grid_test.go new file mode 100644 index 0000000..f6880dc --- /dev/null +++ b/grid_test.go @@ -0,0 +1,69 @@ +// 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 ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/wcharczuk/go-chart/v2/drawing" +) + +func TestGrid(t *testing.T) { + assert := assert.New(t) + + tests := []struct { + render func(*Painter) ([]byte, error) + result string + }{ + { + render: func(p *Painter) ([]byte, error) { + _, err := NewGridPainter(p, GridPainterOption{ + StrokeColor: drawing.ColorBlack, + Column: 6, + Row: 6, + IgnoreFirstRow: true, + IgnoreLastRow: true, + IgnoreFirstColumn: true, + IgnoreLastColumn: true, + }).Render() + if err != nil { + return nil, err + } + return p.Bytes() + }, + result: "\\n", + }, + } + for _, tt := range tests { + p, err := NewPainter(PainterOptions{ + Type: ChartOutputSVG, + Width: 600, + Height: 400, + }, PainterThemeOption(defaultTheme)) + assert.Nil(err) + data, err := tt.render(p) + assert.Nil(err) + assert.Equal(tt.result, string(data)) + } +} diff --git a/legend_test.go b/legend_test.go index e10b538..9078006 100644 --- a/legend_test.go +++ b/legend_test.go @@ -89,10 +89,7 @@ func TestNewLegend(t *testing.T) { result: "\\nOneTwoThree", }, } - for index, tt := range tests { - if index != 0 { - continue - } + for _, tt := range tests { p, err := NewPainter(PainterOptions{ Type: ChartOutputSVG, Width: 600, diff --git a/line_chart_test.go b/line_chart_test.go new file mode 100644 index 0000000..856cdf3 --- /dev/null +++ b/line_chart_test.go @@ -0,0 +1,219 @@ +// 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 ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestLineChart(t *testing.T) { + assert := assert.New(t) + + tests := []struct { + render func(*Painter) ([]byte, error) + result string + }{ + { + render: func(p *Painter) ([]byte, error) { + values := [][]float64{ + { + 120, + 132, + 101, + 134, + 90, + 230, + 210, + }, + { + 220, + 182, + 191, + 234, + 290, + 330, + 310, + }, + { + 150, + 232, + 201, + 154, + 190, + 330, + 410, + }, + { + 320, + 332, + 301, + 334, + 390, + 330, + 320, + }, + { + 820, + 932, + 901, + 934, + 1290, + 1330, + 1320, + }, + } + _, err := NewLineChart(p, LineChartOption{ + Title: TitleOption{ + Text: "Line", + }, + Padding: Box{ + Top: 10, + Right: 10, + Bottom: 10, + Left: 10, + }, + XAxis: NewXAxisOption([]string{ + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat", + "Sun", + }), + Legend: NewLegendOption([]string{ + "Email", + "Union Ads", + "Video Ads", + "Direct", + "Search Engine", + }, PositionCenter), + SeriesList: NewSeriesListDataFromValues(values), + }).Render() + if err != nil { + return nil, err + } + return p.Bytes() + }, + result: "\\nEmailUnion AdsVideo AdsDirectSearch EngineLine1.44k1.2k9607204802400MonTueWedThuFriSatSun", + }, + { + render: func(p *Painter) ([]byte, error) { + values := [][]float64{ + { + 120, + 132, + 101, + 134, + 90, + 230, + 210, + }, + { + 220, + 182, + 191, + 234, + 290, + 330, + 310, + }, + { + 150, + 232, + 201, + 154, + 190, + 330, + 410, + }, + { + 320, + 332, + 301, + 334, + 390, + 330, + 320, + }, + { + 820, + 932, + 901, + 934, + 1290, + 1330, + 1320, + }, + } + _, err := NewLineChart(p, LineChartOption{ + Title: TitleOption{ + Text: "Line", + }, + Padding: Box{ + Top: 10, + Right: 10, + Bottom: 10, + Left: 10, + }, + XAxis: NewXAxisOption([]string{ + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat", + "Sun", + }, FalseFlag()), + Legend: NewLegendOption([]string{ + "Email", + "Union Ads", + "Video Ads", + "Direct", + "Search Engine", + }, PositionCenter), + SeriesList: NewSeriesListDataFromValues(values), + }).Render() + if err != nil { + return nil, err + } + return p.Bytes() + }, + result: "\\nEmailUnion AdsVideo AdsDirectSearch EngineLine1.44k1.2k9607204802400MonTueWedThuFriSatSun", + }, + } + + for _, tt := range tests { + p, err := NewPainter(PainterOptions{ + Type: ChartOutputSVG, + Width: 600, + Height: 400, + }, PainterThemeOption(defaultTheme)) + assert.Nil(err) + data, err := tt.render(p) + assert.Nil(err) + assert.Equal(tt.result, string(data)) + } +} diff --git a/mark_line.go b/mark_line.go index 00a37f2..a0efcfb 100644 --- a/mark_line.go +++ b/mark_line.go @@ -24,6 +24,7 @@ package charts import ( "github.com/golang/freetype/truetype" + "github.com/wcharczuk/go-chart/v2" ) func NewMarkLine(markLineTypes ...string) SeriesMarkLine { @@ -70,6 +71,10 @@ func (m *markLinePainter) Render() (Box, error) { if len(s.MarkLine.Data) == 0 { continue } + font := opt.Font + if font == nil { + font, _ = chart.GetDefaultFont() + } summary := s.Summary() for _, markLine := range s.MarkLine.Data { // 由于mark line会修改style,因此每次重新设置 @@ -82,7 +87,7 @@ func (m *markLinePainter) Render() (Box, error) { 2, }, }).OverrideTextStyle(Style{ - Font: opt.Font, + Font: font, FontColor: opt.FontColor, FontSize: labelFontSize, }) diff --git a/mark_line_test.go b/mark_line_test.go new file mode 100644 index 0000000..84152ce --- /dev/null +++ b/mark_line_test.go @@ -0,0 +1,89 @@ +// 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 ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/wcharczuk/go-chart/v2/drawing" +) + +func TestMarkLine(t *testing.T) { + assert := assert.New(t) + + tests := []struct { + render func(*Painter) ([]byte, error) + result string + }{ + { + render: func(p *Painter) ([]byte, error) { + markLine := NewMarkLinePainter(p) + series := NewSeriesFromValues([]float64{ + 1, + 2, + 3, + }) + series.MarkLine = NewMarkLine( + SeriesMarkDataTypeMax, + SeriesMarkDataTypeAverage, + SeriesMarkDataTypeMin, + ) + markLine.Add(markLineRenderOption{ + FillColor: drawing.ColorBlack, + FontColor: drawing.ColorBlack, + StrokeColor: drawing.ColorBlack, + Series: series, + Range: NewRange(AxisRangeOption{ + Min: 0, + Max: 5, + Size: p.Height(), + DivideCount: 6, + }), + }) + _, err := markLine.Render() + if err != nil { + return nil, err + } + return p.Bytes() + }, + result: "\\n321", + }, + } + 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)) + } +} diff --git a/mark_point_test.go b/mark_point_test.go new file mode 100644 index 0000000..1a810cf --- /dev/null +++ b/mark_point_test.go @@ -0,0 +1,92 @@ +// 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 ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/wcharczuk/go-chart/v2/drawing" +) + +func TestMarkPoint(t *testing.T) { + assert := assert.New(t) + + tests := []struct { + render func(*Painter) ([]byte, error) + result string + }{ + { + render: func(p *Painter) ([]byte, error) { + series := NewSeriesFromValues([]float64{ + 1, + 2, + 3, + }) + series.MarkPoint = NewMarkPoint(SeriesMarkDataTypeMax) + markPoint := NewMarkPointPainter(p) + markPoint.Add(markPointRenderOption{ + FillColor: drawing.ColorBlack, + Series: series, + Points: []Point{ + { + X: 10, + Y: 10, + }, + { + X: 30, + Y: 30, + }, + { + X: 50, + Y: 50, + }, + }, + }) + _, err := markPoint.Render() + if err != nil { + return nil, err + } + return p.Bytes() + }, + result: "\\n3", + }, + } + + 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)) + } +} diff --git a/pie_chart_test.go b/pie_chart_test.go new file mode 100644 index 0000000..c373a7e --- /dev/null +++ b/pie_chart_test.go @@ -0,0 +1,100 @@ +// 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 ( + "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)) + } +} diff --git a/radar_chart.go b/radar_chart.go index 610d5f7..5b8aa85 100644 --- a/radar_chart.go +++ b/radar_chart.go @@ -62,6 +62,20 @@ type RadarChartOption struct { backgroundIsFilled bool } +func NewRadarIndicators(names []string, values []float64) []RadarIndicator { + if len(names) != len(values) { + return nil + } + indicators := make([]RadarIndicator, len(names)) + for index, name := range names { + indicators[index] = RadarIndicator{ + Name: name, + Max: values[index], + } + } + return indicators +} + func NewRadarChart(p *Painter, opt RadarChartOption) *radarChart { if opt.Theme == nil { opt.Theme = defaultTheme diff --git a/radar_chart_test.go b/radar_chart_test.go new file mode 100644 index 0000000..baf616d --- /dev/null +++ b/radar_chart_test.go @@ -0,0 +1,109 @@ +// 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 ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestRadarChart(t *testing.T) { + assert := assert.New(t) + + tests := []struct { + render func(*Painter) ([]byte, error) + result string + }{ + { + render: func(p *Painter) ([]byte, error) { + values := [][]float64{ + { + 4200, + 3000, + 20000, + 35000, + 50000, + 18000, + }, + { + 5000, + 14000, + 28000, + 26000, + 42000, + 21000, + }, + } + _, err := NewRadarChart(p, RadarChartOption{ + SeriesList: NewSeriesListDataFromValues(values, ChartTypeRadar), + Title: TitleOption{ + Text: "Basic Radar Chart", + }, + Legend: NewLegendOption([]string{ + "Allocated Budget", + "Actual Spending", + }), + RadarIndicators: NewRadarIndicators([]string{ + "Sales", + "Administration", + "Information Technology", + "Customer Support", + "Development", + "Marketing", + }, []float64{ + 6500, + 16000, + 30000, + 38000, + 52000, + 25000, + }), + }).Render() + if err != nil { + return nil, err + } + return p.Bytes() + }, + result: "\\nAllocated BudgetActual SpendingBasic Radar ChartSalesAdministrationInformation TechnologyCustomer SupportDevelopmentMarketing", + }, + } + 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) + fmt.Println(string(data)) + assert.Equal(tt.result, string(data)) + } +}