@inglorious/charts 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +9 -0
- package/README.md +554 -0
- package/package.json +64 -0
- package/src/base.css +86 -0
- package/src/cartesian/area.js +392 -0
- package/src/cartesian/area.test.js +366 -0
- package/src/cartesian/bar.js +445 -0
- package/src/cartesian/bar.test.js +346 -0
- package/src/cartesian/line.js +823 -0
- package/src/cartesian/line.test.js +177 -0
- package/src/chart.test.js +444 -0
- package/src/component/brush.js +264 -0
- package/src/component/empty-state.js +33 -0
- package/src/component/empty-state.test.js +81 -0
- package/src/component/grid.js +123 -0
- package/src/component/grid.test.js +123 -0
- package/src/component/legend.js +76 -0
- package/src/component/legend.test.js +103 -0
- package/src/component/tooltip.js +65 -0
- package/src/component/tooltip.test.js +96 -0
- package/src/component/x-axis.js +212 -0
- package/src/component/x-axis.test.js +148 -0
- package/src/component/y-axis.js +77 -0
- package/src/component/y-axis.test.js +107 -0
- package/src/handlers.js +150 -0
- package/src/index.js +264 -0
- package/src/polar/donut.js +181 -0
- package/src/polar/donut.test.js +152 -0
- package/src/polar/pie.js +758 -0
- package/src/polar/pie.test.js +268 -0
- package/src/shape/curve.js +55 -0
- package/src/shape/dot.js +104 -0
- package/src/shape/rectangle.js +46 -0
- package/src/shape/sector.js +58 -0
- package/src/template.js +25 -0
- package/src/theme.css +90 -0
- package/src/utils/cartesian-layout.js +164 -0
- package/src/utils/chart-utils.js +30 -0
- package/src/utils/colors.js +77 -0
- package/src/utils/data-utils.js +155 -0
- package/src/utils/data-utils.test.js +210 -0
- package/src/utils/extract-data-keys.js +22 -0
- package/src/utils/padding.js +16 -0
- package/src/utils/paths.js +279 -0
- package/src/utils/process-declarative-child.js +46 -0
- package/src/utils/scales.js +250 -0
- package/src/utils/shared-context.js +166 -0
- package/src/utils/shared-context.test.js +237 -0
- package/src/utils/tooltip-handlers.js +129 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vitest-environment jsdom
|
|
3
|
+
*/
|
|
4
|
+
import { render } from "@inglorious/web/test"
|
|
5
|
+
import { beforeEach, describe, expect, it, vi } from "vitest"
|
|
6
|
+
|
|
7
|
+
import { line } from "./line.js"
|
|
8
|
+
|
|
9
|
+
describe("line", () => {
|
|
10
|
+
let entity
|
|
11
|
+
let api
|
|
12
|
+
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
entity = {
|
|
15
|
+
id: "test-line",
|
|
16
|
+
type: "line",
|
|
17
|
+
data: [
|
|
18
|
+
{ name: "Jan", value: 100 },
|
|
19
|
+
{ name: "Feb", value: 200 },
|
|
20
|
+
{ name: "Mar", value: 150 },
|
|
21
|
+
],
|
|
22
|
+
width: 800,
|
|
23
|
+
height: 400,
|
|
24
|
+
padding: { top: 20, right: 50, bottom: 30, left: 50 },
|
|
25
|
+
colors: ["#3b82f6", "#ef4444", "#10b981"],
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
api = {
|
|
29
|
+
getEntity: vi.fn((id) => (id === "test-line" ? entity : null)),
|
|
30
|
+
getType: vi.fn((type) => {
|
|
31
|
+
if (type === "line") return line
|
|
32
|
+
return null
|
|
33
|
+
}),
|
|
34
|
+
notify: vi.fn(),
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
describe("render", () => {
|
|
39
|
+
it("should render line chart with data", () => {
|
|
40
|
+
const result = line.render(entity, api)
|
|
41
|
+
const container = document.createElement("div")
|
|
42
|
+
render(result, container)
|
|
43
|
+
|
|
44
|
+
const svg = container.querySelector("svg")
|
|
45
|
+
expect(svg).toBeTruthy()
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it("should handle empty data gracefully", () => {
|
|
49
|
+
entity.data = []
|
|
50
|
+
|
|
51
|
+
const result = line.render(entity, api)
|
|
52
|
+
expect(result).toBeDefined()
|
|
53
|
+
// render may return empty template or handle empty state internally
|
|
54
|
+
})
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
describe("renderLineChart (composition mode)", () => {
|
|
58
|
+
it("should render line chart with children", () => {
|
|
59
|
+
const children = [() => null, () => null, () => null, () => null]
|
|
60
|
+
|
|
61
|
+
const result = line.renderLineChart(entity, { children, config: {} }, api)
|
|
62
|
+
const container = document.createElement("div")
|
|
63
|
+
render(result, container)
|
|
64
|
+
|
|
65
|
+
const chart = container.querySelector(".iw-chart")
|
|
66
|
+
expect(chart).toBeTruthy()
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it("should use config.data to override entity.data", () => {
|
|
70
|
+
const configData = [
|
|
71
|
+
{ name: "Apr", value: 300 },
|
|
72
|
+
{ name: "May", value: 400 },
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
const children = []
|
|
76
|
+
const result = line.renderLineChart(
|
|
77
|
+
entity,
|
|
78
|
+
{ children, config: { data: configData } },
|
|
79
|
+
api,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
// The context should use configData, not entity.data
|
|
83
|
+
expect(result).toBeDefined()
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
it("should use config dimensions if provided", () => {
|
|
87
|
+
const children = []
|
|
88
|
+
const result = line.renderLineChart(
|
|
89
|
+
entity,
|
|
90
|
+
{
|
|
91
|
+
children,
|
|
92
|
+
config: {
|
|
93
|
+
width: 1000,
|
|
94
|
+
height: 500,
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
api,
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
expect(result).toBeDefined()
|
|
101
|
+
})
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
describe("renderLine", () => {
|
|
105
|
+
it("should render line with dataKey when context is provided", () => {
|
|
106
|
+
const context = {
|
|
107
|
+
xScale: (x) => x * 100,
|
|
108
|
+
yScale: (y) => 400 - y * 2,
|
|
109
|
+
dimensions: {
|
|
110
|
+
width: 800,
|
|
111
|
+
height: 400,
|
|
112
|
+
padding: { top: 20, right: 50, bottom: 30, left: 50 },
|
|
113
|
+
},
|
|
114
|
+
entity,
|
|
115
|
+
api,
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const lineFn = line.renderLine(
|
|
119
|
+
entity,
|
|
120
|
+
{ config: { dataKey: "value" } },
|
|
121
|
+
api,
|
|
122
|
+
)
|
|
123
|
+
const result = lineFn(context)
|
|
124
|
+
const container = document.createElement("div")
|
|
125
|
+
render(result, container)
|
|
126
|
+
|
|
127
|
+
const path = container.querySelector("path")
|
|
128
|
+
expect(path).toBeTruthy()
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
it("should render dots when showDots is true", () => {
|
|
132
|
+
const context = {
|
|
133
|
+
xScale: (x) => x * 100,
|
|
134
|
+
yScale: (y) => 400 - y * 2,
|
|
135
|
+
dimensions: {
|
|
136
|
+
width: 800,
|
|
137
|
+
height: 400,
|
|
138
|
+
padding: { top: 20, right: 50, bottom: 30, left: 50 },
|
|
139
|
+
},
|
|
140
|
+
entity,
|
|
141
|
+
api,
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const lineFn = line.renderLine(
|
|
145
|
+
entity,
|
|
146
|
+
{ config: { dataKey: "value", showDots: true } },
|
|
147
|
+
api,
|
|
148
|
+
)
|
|
149
|
+
const result = lineFn(context)
|
|
150
|
+
const container = document.createElement("div")
|
|
151
|
+
render(result, container)
|
|
152
|
+
|
|
153
|
+
const dots = container.querySelectorAll("circle")
|
|
154
|
+
expect(dots.length).toBeGreaterThan(0)
|
|
155
|
+
})
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
describe("renderXAxis", () => {
|
|
159
|
+
it("should return template result", () => {
|
|
160
|
+
const result = line.renderXAxis(
|
|
161
|
+
entity,
|
|
162
|
+
{ config: { dataKey: "value" } },
|
|
163
|
+
api,
|
|
164
|
+
)
|
|
165
|
+
expect(result).toBeDefined()
|
|
166
|
+
// renderXAxis returns svg template, which may be empty if context is missing
|
|
167
|
+
})
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
describe("renderYAxis", () => {
|
|
171
|
+
it("should return template result", () => {
|
|
172
|
+
const result = line.renderYAxis(entity, { config: {} }, api)
|
|
173
|
+
expect(result).toBeDefined()
|
|
174
|
+
// renderYAxis returns svg template, which may be empty if context is missing
|
|
175
|
+
})
|
|
176
|
+
})
|
|
177
|
+
})
|
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vitest-environment jsdom
|
|
3
|
+
*/
|
|
4
|
+
import { describe, expect, it, vi } from "vitest"
|
|
5
|
+
|
|
6
|
+
import { chart } from "./index.js"
|
|
7
|
+
import {
|
|
8
|
+
areaChart,
|
|
9
|
+
barChart,
|
|
10
|
+
donutChart,
|
|
11
|
+
lineChart,
|
|
12
|
+
pieChart,
|
|
13
|
+
} from "./utils/chart-utils.js"
|
|
14
|
+
|
|
15
|
+
const sampleBarData = [
|
|
16
|
+
{ label: "Jan", value: 100 },
|
|
17
|
+
{ label: "Feb", value: 150 },
|
|
18
|
+
{ label: "Mar", value: 120 },
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
const sampleLineData = [
|
|
22
|
+
{ x: 0, y: 50 },
|
|
23
|
+
{ x: 1, y: 150 },
|
|
24
|
+
{ x: 2, y: 120 },
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
const samplePieData = [
|
|
28
|
+
{ label: "Category A", value: 20 },
|
|
29
|
+
{ label: "Category B", value: 35 },
|
|
30
|
+
{ label: "Category C", value: 15 },
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
describe("chart", () => {
|
|
34
|
+
describe("logic", () => {
|
|
35
|
+
describe("create()", () => {
|
|
36
|
+
it("should initialize with default state", () => {
|
|
37
|
+
const entity = {
|
|
38
|
+
id: "test-chart",
|
|
39
|
+
type: "bar",
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
chart.create(entity)
|
|
43
|
+
|
|
44
|
+
expect(entity.width).toBe(800)
|
|
45
|
+
expect(entity.height).toBe(400)
|
|
46
|
+
expect(entity.padding).toBeDefined()
|
|
47
|
+
expect(entity.data).toEqual([])
|
|
48
|
+
expect(entity.colors).toEqual([
|
|
49
|
+
"#3b82f6",
|
|
50
|
+
"#ef4444",
|
|
51
|
+
"#10b981",
|
|
52
|
+
"#f59e0b",
|
|
53
|
+
"#8b5cf6",
|
|
54
|
+
])
|
|
55
|
+
expect(entity.showLegend).toBe(true)
|
|
56
|
+
expect(entity.showGrid).toBe(true)
|
|
57
|
+
expect(entity.showTooltip).toBe(true)
|
|
58
|
+
expect(entity.tooltip).toBe(null)
|
|
59
|
+
expect(entity.tooltipX).toBe(0)
|
|
60
|
+
expect(entity.tooltipY).toBe(0)
|
|
61
|
+
expect(entity.labelPosition).toBe("outside")
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
it("should preserve existing values", () => {
|
|
65
|
+
const entity = {
|
|
66
|
+
id: "test-chart",
|
|
67
|
+
type: "bar",
|
|
68
|
+
width: 1000,
|
|
69
|
+
height: 500,
|
|
70
|
+
data: sampleBarData,
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
chart.create(entity)
|
|
74
|
+
|
|
75
|
+
expect(entity.width).toBe(1000)
|
|
76
|
+
expect(entity.height).toBe(500)
|
|
77
|
+
expect(entity.data).toEqual(sampleBarData)
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
it("should detect time axis type from dates", () => {
|
|
81
|
+
const entity = {
|
|
82
|
+
id: "test-chart",
|
|
83
|
+
type: "line",
|
|
84
|
+
data: [{ date: "2024-01-01", value: 100 }],
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
chart.create(entity)
|
|
88
|
+
|
|
89
|
+
expect(entity.xAxisType).toBe("time")
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
it("should default to linear axis type without dates", () => {
|
|
93
|
+
const entity = {
|
|
94
|
+
id: "test-chart",
|
|
95
|
+
type: "line",
|
|
96
|
+
data: sampleLineData,
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
chart.create(entity)
|
|
100
|
+
|
|
101
|
+
expect(entity.xAxisType).toBe("linear")
|
|
102
|
+
})
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
describe("dataUpdate()", () => {
|
|
106
|
+
it("should update chart data", () => {
|
|
107
|
+
const entity = {
|
|
108
|
+
id: "test-chart",
|
|
109
|
+
type: "bar",
|
|
110
|
+
data: sampleBarData,
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
chart.create(entity)
|
|
114
|
+
const newData = [{ label: "Apr", value: 200 }]
|
|
115
|
+
chart.dataUpdate(entity, newData)
|
|
116
|
+
|
|
117
|
+
expect(entity.data).toEqual(newData)
|
|
118
|
+
})
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
describe("sizeUpdate()", () => {
|
|
122
|
+
it("should update width and height", () => {
|
|
123
|
+
const entity = {
|
|
124
|
+
id: "test-chart",
|
|
125
|
+
type: "bar",
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
chart.create(entity)
|
|
129
|
+
chart.sizeUpdate(entity, 1200, 600)
|
|
130
|
+
|
|
131
|
+
expect(entity.width).toBe(1200)
|
|
132
|
+
expect(entity.height).toBe(600)
|
|
133
|
+
expect(entity.padding).toBeDefined()
|
|
134
|
+
})
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
describe("tooltipShow()", () => {
|
|
138
|
+
it("should set tooltip data and position", () => {
|
|
139
|
+
const entity = {
|
|
140
|
+
id: "test-chart",
|
|
141
|
+
type: "bar",
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
chart.create(entity)
|
|
145
|
+
chart.tooltipShow(entity, {
|
|
146
|
+
label: "Jan",
|
|
147
|
+
value: 100,
|
|
148
|
+
color: "#3b82f6",
|
|
149
|
+
x: 100,
|
|
150
|
+
y: 200,
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
expect(entity.tooltip).toEqual({
|
|
154
|
+
label: "Jan",
|
|
155
|
+
value: 100,
|
|
156
|
+
color: "#3b82f6",
|
|
157
|
+
})
|
|
158
|
+
expect(entity.tooltipX).toBe(100)
|
|
159
|
+
expect(entity.tooltipY).toBe(200)
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
it("should set tooltip with percentage", () => {
|
|
163
|
+
const entity = {
|
|
164
|
+
id: "test-chart",
|
|
165
|
+
type: "pie",
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
chart.create(entity)
|
|
169
|
+
chart.tooltipShow(entity, {
|
|
170
|
+
label: "Category A",
|
|
171
|
+
value: 20,
|
|
172
|
+
percentage: 25,
|
|
173
|
+
color: "#3b82f6",
|
|
174
|
+
x: 150,
|
|
175
|
+
y: 250,
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
expect(entity.tooltip).toEqual({
|
|
179
|
+
label: "Category A",
|
|
180
|
+
value: 20,
|
|
181
|
+
percentage: 25,
|
|
182
|
+
color: "#3b82f6",
|
|
183
|
+
})
|
|
184
|
+
})
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
describe("tooltipHide()", () => {
|
|
188
|
+
it("should clear tooltip", () => {
|
|
189
|
+
const entity = {
|
|
190
|
+
id: "test-chart",
|
|
191
|
+
type: "bar",
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
chart.create(entity)
|
|
195
|
+
chart.tooltipShow(entity, {
|
|
196
|
+
label: "Jan",
|
|
197
|
+
value: 100,
|
|
198
|
+
color: "#3b82f6",
|
|
199
|
+
x: 100,
|
|
200
|
+
y: 200,
|
|
201
|
+
})
|
|
202
|
+
chart.tooltipHide(entity)
|
|
203
|
+
|
|
204
|
+
expect(entity.tooltip).toBe(null)
|
|
205
|
+
})
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
describe("tooltipMove()", () => {
|
|
209
|
+
it("should update tooltip position", () => {
|
|
210
|
+
const entity = {
|
|
211
|
+
id: "test-chart",
|
|
212
|
+
type: "bar",
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
chart.create(entity)
|
|
216
|
+
chart.tooltipShow(entity, {
|
|
217
|
+
label: "Jan",
|
|
218
|
+
value: 100,
|
|
219
|
+
color: "#3b82f6",
|
|
220
|
+
x: 100,
|
|
221
|
+
y: 200,
|
|
222
|
+
})
|
|
223
|
+
chart.tooltipMove(entity, { x: 150, y: 250 })
|
|
224
|
+
|
|
225
|
+
expect(entity.tooltipX).toBe(150)
|
|
226
|
+
expect(entity.tooltipY).toBe(250)
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
it("should not update position if tooltip is not shown", () => {
|
|
230
|
+
const entity = {
|
|
231
|
+
id: "test-chart",
|
|
232
|
+
type: "bar",
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
chart.create(entity)
|
|
236
|
+
chart.tooltipMove(entity, { x: 150, y: 250 })
|
|
237
|
+
|
|
238
|
+
expect(entity.tooltipX).toBe(0)
|
|
239
|
+
expect(entity.tooltipY).toBe(0)
|
|
240
|
+
})
|
|
241
|
+
})
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
describe("rendering", () => {
|
|
245
|
+
describe("render()", () => {
|
|
246
|
+
it("should render chart using api.getType", () => {
|
|
247
|
+
const entity = {
|
|
248
|
+
id: "test-chart",
|
|
249
|
+
type: "bar",
|
|
250
|
+
data: sampleBarData,
|
|
251
|
+
width: 800,
|
|
252
|
+
height: 400,
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
chart.create(entity)
|
|
256
|
+
|
|
257
|
+
const mockApi = {
|
|
258
|
+
getType: vi.fn(() => barChart),
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const result = chart.render(entity, mockApi)
|
|
262
|
+
|
|
263
|
+
expect(mockApi.getType).toHaveBeenCalledWith("bar")
|
|
264
|
+
expect(result).toBeDefined()
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
it("should return error message for unknown chart type", () => {
|
|
268
|
+
const entity = {
|
|
269
|
+
id: "test-chart",
|
|
270
|
+
type: "unknown",
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
chart.create(entity)
|
|
274
|
+
|
|
275
|
+
const mockApi = {
|
|
276
|
+
getType: vi.fn(() => null),
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const result = chart.render(entity, mockApi)
|
|
280
|
+
|
|
281
|
+
expect(mockApi.getType).toHaveBeenCalledWith("unknown")
|
|
282
|
+
expect(result).toBeDefined()
|
|
283
|
+
})
|
|
284
|
+
})
|
|
285
|
+
})
|
|
286
|
+
|
|
287
|
+
describe("chart types", () => {
|
|
288
|
+
describe("barChart", () => {
|
|
289
|
+
it("should have create, render, and render methods", () => {
|
|
290
|
+
expect(barChart.create).toBeDefined()
|
|
291
|
+
expect(barChart.render).toBeDefined()
|
|
292
|
+
expect(barChart.render).toBeDefined()
|
|
293
|
+
})
|
|
294
|
+
|
|
295
|
+
it("should render chart with data", () => {
|
|
296
|
+
const entity = {
|
|
297
|
+
id: "test-bar",
|
|
298
|
+
type: "bar",
|
|
299
|
+
data: sampleBarData,
|
|
300
|
+
width: 800,
|
|
301
|
+
height: 400,
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
barChart.create(entity)
|
|
305
|
+
const mockApi = {
|
|
306
|
+
getType: vi.fn((type) => {
|
|
307
|
+
if (type === "bar") return barChart
|
|
308
|
+
return null
|
|
309
|
+
}),
|
|
310
|
+
notify: vi.fn(),
|
|
311
|
+
}
|
|
312
|
+
const result = barChart.render(entity, mockApi)
|
|
313
|
+
|
|
314
|
+
expect(result).toBeDefined()
|
|
315
|
+
})
|
|
316
|
+
|
|
317
|
+
it("should render empty state when no data", () => {
|
|
318
|
+
const entity = {
|
|
319
|
+
id: "test-bar",
|
|
320
|
+
type: "bar",
|
|
321
|
+
data: [],
|
|
322
|
+
width: 800,
|
|
323
|
+
height: 400,
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
barChart.create(entity)
|
|
327
|
+
const mockApi = {
|
|
328
|
+
getType: vi.fn((type) => {
|
|
329
|
+
if (type === "bar") return barChart
|
|
330
|
+
return null
|
|
331
|
+
}),
|
|
332
|
+
notify: vi.fn(),
|
|
333
|
+
}
|
|
334
|
+
const result = barChart.render(entity, mockApi)
|
|
335
|
+
|
|
336
|
+
expect(result).toBeDefined()
|
|
337
|
+
})
|
|
338
|
+
})
|
|
339
|
+
|
|
340
|
+
describe("lineChart", () => {
|
|
341
|
+
it("should have create, render, and render methods", () => {
|
|
342
|
+
expect(lineChart.create).toBeDefined()
|
|
343
|
+
expect(lineChart.render).toBeDefined()
|
|
344
|
+
expect(lineChart.render).toBeDefined()
|
|
345
|
+
})
|
|
346
|
+
|
|
347
|
+
it("should render chart with data", () => {
|
|
348
|
+
const entity = {
|
|
349
|
+
id: "test-line",
|
|
350
|
+
type: "line",
|
|
351
|
+
data: sampleLineData,
|
|
352
|
+
width: 800,
|
|
353
|
+
height: 400,
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
lineChart.create(entity)
|
|
357
|
+
const mockApi = {
|
|
358
|
+
getType: vi.fn((type) => {
|
|
359
|
+
if (type === "line") return lineChart
|
|
360
|
+
return null
|
|
361
|
+
}),
|
|
362
|
+
notify: vi.fn(),
|
|
363
|
+
}
|
|
364
|
+
const result = lineChart.render(entity, mockApi)
|
|
365
|
+
|
|
366
|
+
expect(result).toBeDefined()
|
|
367
|
+
})
|
|
368
|
+
})
|
|
369
|
+
|
|
370
|
+
describe("areaChart", () => {
|
|
371
|
+
it("should have render method", () => {
|
|
372
|
+
expect(areaChart.render).toBeDefined()
|
|
373
|
+
})
|
|
374
|
+
|
|
375
|
+
it("should render chart with data", () => {
|
|
376
|
+
const entity = {
|
|
377
|
+
id: "test-area",
|
|
378
|
+
type: "area",
|
|
379
|
+
data: sampleLineData,
|
|
380
|
+
width: 800,
|
|
381
|
+
height: 400,
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
chart.create(entity)
|
|
385
|
+
const mockApi = {
|
|
386
|
+
getType: vi.fn((type) => {
|
|
387
|
+
if (type === "area") return areaChart
|
|
388
|
+
return null
|
|
389
|
+
}),
|
|
390
|
+
notify: vi.fn(),
|
|
391
|
+
}
|
|
392
|
+
const result = areaChart.render(entity, mockApi)
|
|
393
|
+
|
|
394
|
+
expect(result).toBeDefined()
|
|
395
|
+
})
|
|
396
|
+
})
|
|
397
|
+
|
|
398
|
+
describe("pieChart", () => {
|
|
399
|
+
it("should have create, render, and render methods", () => {
|
|
400
|
+
expect(pieChart.create).toBeDefined()
|
|
401
|
+
expect(pieChart.render).toBeDefined()
|
|
402
|
+
expect(pieChart.render).toBeDefined()
|
|
403
|
+
})
|
|
404
|
+
|
|
405
|
+
it("should render chart with data", () => {
|
|
406
|
+
const entity = {
|
|
407
|
+
id: "test-pie",
|
|
408
|
+
type: "pie",
|
|
409
|
+
data: samplePieData,
|
|
410
|
+
width: 800,
|
|
411
|
+
height: 400,
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
pieChart.create(entity)
|
|
415
|
+
const result = pieChart.render(entity, {})
|
|
416
|
+
|
|
417
|
+
expect(result).toBeDefined()
|
|
418
|
+
})
|
|
419
|
+
})
|
|
420
|
+
|
|
421
|
+
describe("donutChart", () => {
|
|
422
|
+
it("should have create, render, and render methods", () => {
|
|
423
|
+
expect(donutChart.create).toBeDefined()
|
|
424
|
+
expect(donutChart.render).toBeDefined()
|
|
425
|
+
expect(donutChart.render).toBeDefined()
|
|
426
|
+
})
|
|
427
|
+
|
|
428
|
+
it("should render chart with data", () => {
|
|
429
|
+
const entity = {
|
|
430
|
+
id: "test-donut",
|
|
431
|
+
type: "donut",
|
|
432
|
+
data: samplePieData,
|
|
433
|
+
width: 400,
|
|
434
|
+
height: 400,
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
donutChart.create(entity)
|
|
438
|
+
const result = donutChart.render(entity, {})
|
|
439
|
+
|
|
440
|
+
expect(result).toBeDefined()
|
|
441
|
+
})
|
|
442
|
+
})
|
|
443
|
+
})
|
|
444
|
+
})
|