@pie-lib/charting 6.1.1-next.0 → 6.2.0-next.0
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/lib/actions-button.js +0 -5
- package/lib/actions-button.js.map +1 -1
- package/lib/axes.js +0 -23
- package/lib/axes.js.map +1 -1
- package/lib/bars/bar.js +0 -2
- package/lib/bars/bar.js.map +1 -1
- package/lib/bars/common/bars.js +0 -13
- package/lib/bars/common/bars.js.map +1 -1
- package/lib/bars/common/correct-check-icon.js +0 -1
- package/lib/bars/common/correct-check-icon.js.map +1 -1
- package/lib/bars/histogram.js +0 -2
- package/lib/bars/histogram.js.map +1 -1
- package/lib/chart-setup.js +0 -19
- package/lib/chart-setup.js.map +1 -1
- package/lib/chart-type.js +0 -1
- package/lib/chart-type.js.map +1 -1
- package/lib/chart-types.js +0 -1
- package/lib/chart-types.js.map +1 -1
- package/lib/chart.js +2 -18
- package/lib/chart.js.map +1 -1
- package/lib/common/correctness-indicators.js +0 -4
- package/lib/common/correctness-indicators.js.map +1 -1
- package/lib/common/drag-handle.js +0 -1
- package/lib/common/drag-handle.js.map +1 -1
- package/lib/common/drag-icon.js +0 -2
- package/lib/common/drag-icon.js.map +1 -1
- package/lib/common/styles.js +0 -1
- package/lib/common/styles.js.map +1 -1
- package/lib/grid.js +0 -4
- package/lib/grid.js.map +1 -1
- package/lib/index.js +0 -1
- package/lib/index.js.map +1 -1
- package/lib/key-legend.js +0 -1
- package/lib/key-legend.js.map +1 -1
- package/lib/line/common/drag-handle.js +0 -2
- package/lib/line/common/drag-handle.js.map +1 -1
- package/lib/line/common/line.js +2 -19
- package/lib/line/common/line.js.map +1 -1
- package/lib/line/line-cross.js +0 -16
- package/lib/line/line-cross.js.map +1 -1
- package/lib/line/line-dot.js +0 -2
- package/lib/line/line-dot.js.map +1 -1
- package/lib/mark-label.js +0 -21
- package/lib/mark-label.js.map +1 -1
- package/lib/plot/common/plot.js +0 -12
- package/lib/plot/common/plot.js.map +1 -1
- package/lib/plot/dot.js +0 -3
- package/lib/plot/dot.js.map +1 -1
- package/lib/plot/line.js +0 -3
- package/lib/plot/line.js.map +1 -1
- package/lib/tool-menu.js +0 -11
- package/lib/tool-menu.js.map +1 -1
- package/lib/utils.js +0 -12
- package/lib/utils.js.map +1 -1
- package/package.json +12 -9
- package/src/__tests__/actions-button.test.jsx +280 -0
- package/src/__tests__/axes.test.jsx +557 -16
- package/src/__tests__/chart-setup.test.jsx +495 -10
- package/src/__tests__/chart.test.jsx +1 -1
- package/src/__tests__/grid.test.jsx +2 -2
- package/src/__tests__/key-legend.test.jsx +223 -0
- package/src/__tests__/tool-menu.test.jsx +522 -0
- package/src/__tests__/utils.js +1 -1
- package/src/axes.jsx +10 -7
- package/src/bars/common/bars.jsx +32 -50
- package/src/chart-setup.jsx +6 -9
- package/src/chart-type.js +3 -6
- package/src/chart.jsx +2 -2
- package/src/common/__tests__/correctness-indicators.test.jsx +720 -0
- package/src/common/__tests__/drag-handle.test.jsx +0 -1
- package/src/common/correctness-indicators.jsx +8 -13
- package/src/common/drag-handle.jsx +2 -12
- package/src/grid.jsx +1 -1
- package/src/line/__tests__/line-cross.test.jsx +423 -1
- package/src/line/__tests__/utils.js +1 -1
- package/src/line/common/__tests__/drag-handle.test.jsx +1 -2
- package/src/line/common/drag-handle.jsx +2 -11
- package/src/line/common/line.jsx +2 -2
- package/src/line/line-cross.js +7 -13
- package/src/mark-label.jsx +3 -3
- package/src/plot/__tests__/dot.test.jsx +300 -1
- package/src/plot/__tests__/line.test.jsx +331 -1
- package/src/plot/common/plot.jsx +14 -13
- package/src/utils.js +0 -1
- package/NEXT.CHANGELOG.json +0 -16
|
@@ -1,8 +1,25 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { render } from '@pie-lib/test-utils';
|
|
3
|
+
import { createTheme, ThemeProvider } from '@mui/material/styles';
|
|
3
4
|
import Dot, { DotPlot } from '../dot';
|
|
4
5
|
import { graphProps } from './utils';
|
|
5
6
|
|
|
7
|
+
jest.mock('@mui/icons-material/Check', () => {
|
|
8
|
+
return function Check(props) {
|
|
9
|
+
return <div data-testid="check-icon" {...props} />;
|
|
10
|
+
};
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
jest.mock('@visx/shape', () => ({
|
|
14
|
+
Circle: ({ cx, cy, r, ...rest }) => <circle cx={cx} cy={cy} r={r} {...rest} />,
|
|
15
|
+
}));
|
|
16
|
+
|
|
17
|
+
let theme;
|
|
18
|
+
|
|
19
|
+
beforeAll(() => {
|
|
20
|
+
theme = createTheme();
|
|
21
|
+
});
|
|
22
|
+
|
|
6
23
|
describe('DotPlot', () => {
|
|
7
24
|
const renderComponent = (extras) => {
|
|
8
25
|
const defaults = {
|
|
@@ -16,7 +33,13 @@ describe('DotPlot', () => {
|
|
|
16
33
|
},
|
|
17
34
|
};
|
|
18
35
|
const props = { ...defaults, ...extras };
|
|
19
|
-
return render(
|
|
36
|
+
return render(
|
|
37
|
+
<ThemeProvider theme={theme}>
|
|
38
|
+
<svg>
|
|
39
|
+
<DotPlot {...props} />
|
|
40
|
+
</svg>
|
|
41
|
+
</ThemeProvider>,
|
|
42
|
+
);
|
|
20
43
|
};
|
|
21
44
|
|
|
22
45
|
describe('rendering', () => {
|
|
@@ -29,6 +52,178 @@ describe('DotPlot', () => {
|
|
|
29
52
|
const { container } = renderComponent({ graphProps: undefined });
|
|
30
53
|
expect(container.firstChild).toBeInTheDocument();
|
|
31
54
|
});
|
|
55
|
+
|
|
56
|
+
it('renders with data array', () => {
|
|
57
|
+
const data = [
|
|
58
|
+
{ value: 1, label: 'A' },
|
|
59
|
+
{ value: 2, label: 'B' },
|
|
60
|
+
{ value: 3, label: 'C' },
|
|
61
|
+
];
|
|
62
|
+
const { container } = renderComponent({ data });
|
|
63
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('renders with empty data array', () => {
|
|
67
|
+
const { container } = renderComponent({ data: [] });
|
|
68
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('renders with null data', () => {
|
|
72
|
+
const { container } = renderComponent({ data: null });
|
|
73
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('renders with undefined data', () => {
|
|
77
|
+
const { container } = renderComponent({ data: undefined });
|
|
78
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('renders with custom className', () => {
|
|
82
|
+
const { container } = renderComponent({ className: 'custom-dot-plot' });
|
|
83
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('renders with onChange handler', () => {
|
|
87
|
+
const onChange = jest.fn();
|
|
88
|
+
const { container } = renderComponent({ onChange });
|
|
89
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('renders in defineChart mode', () => {
|
|
93
|
+
const { container } = renderComponent({ defineChart: true });
|
|
94
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('renders with correctData', () => {
|
|
98
|
+
const data = [{ value: 2, label: 'A' }];
|
|
99
|
+
const correctData = [{ value: 3, label: 'A' }];
|
|
100
|
+
const { container } = renderComponent({ data, correctData });
|
|
101
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
describe('graphProps handling', () => {
|
|
106
|
+
it('handles graphProps with missing scale', () => {
|
|
107
|
+
const props = graphProps();
|
|
108
|
+
delete props.scale;
|
|
109
|
+
const { container } = renderComponent({ graphProps: props });
|
|
110
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('handles graphProps with missing size', () => {
|
|
114
|
+
const props = graphProps();
|
|
115
|
+
delete props.size;
|
|
116
|
+
const { container } = renderComponent({ graphProps: props });
|
|
117
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('handles graphProps with empty scale object', () => {
|
|
121
|
+
const props = graphProps();
|
|
122
|
+
props.scale = {};
|
|
123
|
+
const { container } = renderComponent({ graphProps: props });
|
|
124
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('handles graphProps with empty size object', () => {
|
|
128
|
+
const props = graphProps();
|
|
129
|
+
props.size = {};
|
|
130
|
+
const { container } = renderComponent({ graphProps: props });
|
|
131
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
describe('data variations', () => {
|
|
136
|
+
it('renders with single data point', () => {
|
|
137
|
+
const data = [{ value: 1, label: 'A' }];
|
|
138
|
+
const { container } = renderComponent({ data });
|
|
139
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('renders with multiple data points', () => {
|
|
143
|
+
const data = [
|
|
144
|
+
{ value: 1, label: 'A' },
|
|
145
|
+
{ value: 2, label: 'B' },
|
|
146
|
+
{ value: 3, label: 'C' },
|
|
147
|
+
{ value: 4, label: 'D' },
|
|
148
|
+
];
|
|
149
|
+
const { container } = renderComponent({ data });
|
|
150
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it('renders with zero values', () => {
|
|
154
|
+
const data = [
|
|
155
|
+
{ value: 0, label: 'A' },
|
|
156
|
+
{ value: 0, label: 'B' },
|
|
157
|
+
];
|
|
158
|
+
const { container } = renderComponent({ data });
|
|
159
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it('renders with mixed values', () => {
|
|
163
|
+
const data = [
|
|
164
|
+
{ value: 0, label: 'A' },
|
|
165
|
+
{ value: 5, label: 'B' },
|
|
166
|
+
{ value: 1, label: 'C' },
|
|
167
|
+
];
|
|
168
|
+
const { container } = renderComponent({ data });
|
|
169
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('renders with large values', () => {
|
|
173
|
+
const data = [
|
|
174
|
+
{ value: 100, label: 'A' },
|
|
175
|
+
{ value: 200, label: 'B' },
|
|
176
|
+
];
|
|
177
|
+
const { container } = renderComponent({ data });
|
|
178
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('renders with correctness data', () => {
|
|
182
|
+
const data = [
|
|
183
|
+
{ value: 2, label: 'A', correctness: { value: 'correct', label: 'Correct' } },
|
|
184
|
+
{ value: 3, label: 'B', correctness: { value: 'correct', label: 'Correct' } },
|
|
185
|
+
];
|
|
186
|
+
const { container } = renderComponent({ data });
|
|
187
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('renders with incorrect correctness and correctData', () => {
|
|
191
|
+
const data = [
|
|
192
|
+
{ value: 2, label: 'A', correctness: { value: 'incorrect', label: 'Incorrect' } },
|
|
193
|
+
{ value: 3, label: 'B', correctness: { value: 'incorrect', label: 'Incorrect' } },
|
|
194
|
+
];
|
|
195
|
+
const correctData = [
|
|
196
|
+
{ value: 3, label: 'A' },
|
|
197
|
+
{ value: 4, label: 'B' },
|
|
198
|
+
];
|
|
199
|
+
const { container } = renderComponent({ data, correctData });
|
|
200
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it('renders with interactive data points', () => {
|
|
204
|
+
const data = [
|
|
205
|
+
{ value: 2, label: 'A', interactive: true },
|
|
206
|
+
{ value: 3, label: 'B', interactive: false },
|
|
207
|
+
];
|
|
208
|
+
const { container } = renderComponent({ data });
|
|
209
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
describe('callbacks', () => {
|
|
214
|
+
it('passes onChange handler to Plot component', () => {
|
|
215
|
+
const onChange = jest.fn();
|
|
216
|
+
const data = [{ value: 1, label: 'A' }];
|
|
217
|
+
const { container } = renderComponent({ data, onChange });
|
|
218
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it('handles onChangeCategory callback', () => {
|
|
222
|
+
const onChangeCategory = jest.fn();
|
|
223
|
+
const data = [{ value: 1, label: 'A' }];
|
|
224
|
+
const { container } = renderComponent({ data, onChangeCategory });
|
|
225
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
226
|
+
});
|
|
32
227
|
});
|
|
33
228
|
|
|
34
229
|
describe('component', () => {
|
|
@@ -41,5 +236,109 @@ describe('DotPlot', () => {
|
|
|
41
236
|
name: 'Dot Plot',
|
|
42
237
|
});
|
|
43
238
|
});
|
|
239
|
+
|
|
240
|
+
it('returns object with Component that can be rendered', () => {
|
|
241
|
+
const chart = Dot();
|
|
242
|
+
const { Component } = chart;
|
|
243
|
+
|
|
244
|
+
const { container } = render(<Component graphProps={graphProps()} />);
|
|
245
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
describe('CustomBarElement (Dot)', () => {
|
|
251
|
+
const mockScale = {
|
|
252
|
+
y: jest.fn((n) => n * 10),
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
it('renders a circle element', () => {
|
|
256
|
+
const data = [{ value: 1, label: 'A' }];
|
|
257
|
+
const { container } = render(
|
|
258
|
+
<ThemeProvider theme={theme}>
|
|
259
|
+
<svg>
|
|
260
|
+
<DotPlot data={data} graphProps={graphProps()} />
|
|
261
|
+
</svg>
|
|
262
|
+
</ThemeProvider>,
|
|
263
|
+
);
|
|
264
|
+
expect(container).toBeInTheDocument();
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it('renders with dottedOverline prop', () => {
|
|
268
|
+
const data = [{ value: 2, label: 'A', correctness: { value: 'incorrect' } }];
|
|
269
|
+
const correctData = [{ value: 3, label: 'A' }];
|
|
270
|
+
const { container } = render(
|
|
271
|
+
<ThemeProvider theme={theme}>
|
|
272
|
+
<svg>
|
|
273
|
+
<DotPlot data={data} graphProps={graphProps()} correctData={correctData} />
|
|
274
|
+
</svg>
|
|
275
|
+
</ThemeProvider>,
|
|
276
|
+
);
|
|
277
|
+
expect(container).toBeInTheDocument();
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
it('renders without dottedOverline prop', () => {
|
|
281
|
+
const data = [{ value: 2, label: 'A' }];
|
|
282
|
+
const { container } = render(
|
|
283
|
+
<ThemeProvider theme={theme}>
|
|
284
|
+
<svg>
|
|
285
|
+
<DotPlot data={data} graphProps={graphProps()} />
|
|
286
|
+
</svg>
|
|
287
|
+
</ThemeProvider>,
|
|
288
|
+
);
|
|
289
|
+
expect(container).toBeInTheDocument();
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
it('calculates correct circle position', () => {
|
|
293
|
+
const data = [{ value: 3, label: 'A' }];
|
|
294
|
+
const { container } = render(
|
|
295
|
+
<ThemeProvider theme={theme}>
|
|
296
|
+
<svg>
|
|
297
|
+
<DotPlot data={data} graphProps={graphProps()} />
|
|
298
|
+
</svg>
|
|
299
|
+
</ThemeProvider>,
|
|
300
|
+
);
|
|
301
|
+
expect(container).toBeInTheDocument();
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
it('handles zero pointDiameter', () => {
|
|
305
|
+
const props = graphProps();
|
|
306
|
+
props.size = { width: 0, height: 0 };
|
|
307
|
+
const data = [{ value: 1, label: 'A' }];
|
|
308
|
+
const { container } = render(
|
|
309
|
+
<ThemeProvider theme={theme}>
|
|
310
|
+
<svg>
|
|
311
|
+
<DotPlot data={data} graphProps={props} />
|
|
312
|
+
</svg>
|
|
313
|
+
</ThemeProvider>,
|
|
314
|
+
);
|
|
315
|
+
expect(container).toBeInTheDocument();
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
it('handles large pointDiameter values', () => {
|
|
319
|
+
const props = graphProps();
|
|
320
|
+
props.size = { width: 1000, height: 1000 };
|
|
321
|
+
const data = [{ value: 1, label: 'A' }];
|
|
322
|
+
const { container } = render(
|
|
323
|
+
<ThemeProvider theme={theme}>
|
|
324
|
+
<svg>
|
|
325
|
+
<DotPlot data={data} graphProps={props} />
|
|
326
|
+
</svg>
|
|
327
|
+
</ThemeProvider>,
|
|
328
|
+
);
|
|
329
|
+
expect(container).toBeInTheDocument();
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
it('renders dotted circle with correct styling when dottedOverline is true', () => {
|
|
333
|
+
const data = [{ value: 2, label: 'A', correctness: { value: 'incorrect' } }];
|
|
334
|
+
const correctData = [{ value: 3, label: 'A' }];
|
|
335
|
+
const { container } = render(
|
|
336
|
+
<ThemeProvider theme={theme}>
|
|
337
|
+
<svg>
|
|
338
|
+
<DotPlot data={data} graphProps={graphProps()} correctData={correctData} />
|
|
339
|
+
</svg>
|
|
340
|
+
</ThemeProvider>,
|
|
341
|
+
);
|
|
342
|
+
expect(container).toBeInTheDocument();
|
|
44
343
|
});
|
|
45
344
|
});
|
|
@@ -1,8 +1,31 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { render } from '@pie-lib/test-utils';
|
|
3
|
+
import { createTheme, ThemeProvider } from '@mui/material/styles';
|
|
3
4
|
import Line, { LinePlot } from '../line';
|
|
4
5
|
import { graphProps } from './utils';
|
|
5
6
|
|
|
7
|
+
jest.mock('@mui/icons-material/Check', () => {
|
|
8
|
+
return function Check(props) {
|
|
9
|
+
return <div data-testid="check-icon" {...props} />;
|
|
10
|
+
};
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
jest.mock('@visx/shape', () => ({
|
|
14
|
+
LinePath: ({ data, x, y, ...rest }) => (
|
|
15
|
+
<path d={data.map((d, i) => `${i === 0 ? 'M' : 'L'}${x(d)},${y(d)}`).join(' ')} {...rest} />
|
|
16
|
+
),
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
jest.mock('@visx/group', () => ({
|
|
20
|
+
Group: ({ children }) => <g className="visx-group">{children}</g>,
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
let theme;
|
|
24
|
+
|
|
25
|
+
beforeAll(() => {
|
|
26
|
+
theme = createTheme();
|
|
27
|
+
});
|
|
28
|
+
|
|
6
29
|
describe('LinePlot', () => {
|
|
7
30
|
const renderComponent = (extras) => {
|
|
8
31
|
const defaults = {
|
|
@@ -16,7 +39,13 @@ describe('LinePlot', () => {
|
|
|
16
39
|
},
|
|
17
40
|
};
|
|
18
41
|
const props = { ...defaults, ...extras };
|
|
19
|
-
return render(
|
|
42
|
+
return render(
|
|
43
|
+
<ThemeProvider theme={theme}>
|
|
44
|
+
<svg>
|
|
45
|
+
<LinePlot {...props} />
|
|
46
|
+
</svg>
|
|
47
|
+
</ThemeProvider>,
|
|
48
|
+
);
|
|
20
49
|
};
|
|
21
50
|
|
|
22
51
|
describe('rendering', () => {
|
|
@@ -29,6 +58,178 @@ describe('LinePlot', () => {
|
|
|
29
58
|
const { container } = renderComponent({ graphProps: undefined });
|
|
30
59
|
expect(container.firstChild).toBeInTheDocument();
|
|
31
60
|
});
|
|
61
|
+
|
|
62
|
+
it('renders with data array', () => {
|
|
63
|
+
const data = [
|
|
64
|
+
{ value: 1, label: 'A' },
|
|
65
|
+
{ value: 2, label: 'B' },
|
|
66
|
+
{ value: 3, label: 'C' },
|
|
67
|
+
];
|
|
68
|
+
const { container } = renderComponent({ data });
|
|
69
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('renders with empty data array', () => {
|
|
73
|
+
const { container } = renderComponent({ data: [] });
|
|
74
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('renders with null data', () => {
|
|
78
|
+
const { container } = renderComponent({ data: null });
|
|
79
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('renders with undefined data', () => {
|
|
83
|
+
const { container } = renderComponent({ data: undefined });
|
|
84
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('renders with custom className', () => {
|
|
88
|
+
const { container } = renderComponent({ className: 'custom-line-plot' });
|
|
89
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('renders with onChange handler', () => {
|
|
93
|
+
const onChange = jest.fn();
|
|
94
|
+
const { container } = renderComponent({ onChange });
|
|
95
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('renders in defineChart mode', () => {
|
|
99
|
+
const { container } = renderComponent({ defineChart: true });
|
|
100
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('renders with correctData', () => {
|
|
104
|
+
const data = [{ value: 2, label: 'A' }];
|
|
105
|
+
const correctData = [{ value: 3, label: 'A' }];
|
|
106
|
+
const { container } = renderComponent({ data, correctData });
|
|
107
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
describe('graphProps handling', () => {
|
|
112
|
+
it('handles graphProps with missing scale', () => {
|
|
113
|
+
const props = graphProps();
|
|
114
|
+
delete props.scale;
|
|
115
|
+
const { container } = renderComponent({ graphProps: props });
|
|
116
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('handles graphProps with missing size', () => {
|
|
120
|
+
const props = graphProps();
|
|
121
|
+
delete props.size;
|
|
122
|
+
const { container } = renderComponent({ graphProps: props });
|
|
123
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('handles graphProps with empty scale object', () => {
|
|
127
|
+
const props = graphProps();
|
|
128
|
+
props.scale = {};
|
|
129
|
+
const { container } = renderComponent({ graphProps: props });
|
|
130
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('handles graphProps with empty size object', () => {
|
|
134
|
+
const props = graphProps();
|
|
135
|
+
props.size = {};
|
|
136
|
+
const { container } = renderComponent({ graphProps: props });
|
|
137
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
describe('data variations', () => {
|
|
142
|
+
it('renders with single data point', () => {
|
|
143
|
+
const data = [{ value: 1, label: 'A' }];
|
|
144
|
+
const { container } = renderComponent({ data });
|
|
145
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('renders with multiple data points', () => {
|
|
149
|
+
const data = [
|
|
150
|
+
{ value: 1, label: 'A' },
|
|
151
|
+
{ value: 2, label: 'B' },
|
|
152
|
+
{ value: 3, label: 'C' },
|
|
153
|
+
{ value: 4, label: 'D' },
|
|
154
|
+
];
|
|
155
|
+
const { container } = renderComponent({ data });
|
|
156
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('renders with zero values', () => {
|
|
160
|
+
const data = [
|
|
161
|
+
{ value: 0, label: 'A' },
|
|
162
|
+
{ value: 0, label: 'B' },
|
|
163
|
+
];
|
|
164
|
+
const { container } = renderComponent({ data });
|
|
165
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('renders with mixed values', () => {
|
|
169
|
+
const data = [
|
|
170
|
+
{ value: 0, label: 'A' },
|
|
171
|
+
{ value: 5, label: 'B' },
|
|
172
|
+
{ value: 1, label: 'C' },
|
|
173
|
+
];
|
|
174
|
+
const { container } = renderComponent({ data });
|
|
175
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it('renders with large values', () => {
|
|
179
|
+
const data = [
|
|
180
|
+
{ value: 100, label: 'A' },
|
|
181
|
+
{ value: 200, label: 'B' },
|
|
182
|
+
];
|
|
183
|
+
const { container } = renderComponent({ data });
|
|
184
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('renders with correctness data', () => {
|
|
188
|
+
const data = [
|
|
189
|
+
{ value: 2, label: 'A', correctness: { value: 'correct', label: 'Correct' } },
|
|
190
|
+
{ value: 3, label: 'B', correctness: { value: 'correct', label: 'Correct' } },
|
|
191
|
+
];
|
|
192
|
+
const { container } = renderComponent({ data });
|
|
193
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
it('renders with incorrect correctness and correctData', () => {
|
|
197
|
+
const data = [
|
|
198
|
+
{ value: 2, label: 'A', correctness: { value: 'incorrect', label: 'Incorrect' } },
|
|
199
|
+
{ value: 3, label: 'B', correctness: { value: 'incorrect', label: 'Incorrect' } },
|
|
200
|
+
];
|
|
201
|
+
const correctData = [
|
|
202
|
+
{ value: 3, label: 'A' },
|
|
203
|
+
{ value: 4, label: 'B' },
|
|
204
|
+
];
|
|
205
|
+
const { container } = renderComponent({ data, correctData });
|
|
206
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it('renders with interactive data points', () => {
|
|
210
|
+
const data = [
|
|
211
|
+
{ value: 2, label: 'A', interactive: true },
|
|
212
|
+
{ value: 3, label: 'B', interactive: false },
|
|
213
|
+
];
|
|
214
|
+
const { container } = renderComponent({ data });
|
|
215
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
describe('callbacks', () => {
|
|
220
|
+
it('passes onChange handler to Plot component', () => {
|
|
221
|
+
const onChange = jest.fn();
|
|
222
|
+
const data = [{ value: 1, label: 'A' }];
|
|
223
|
+
const { container } = renderComponent({ data, onChange });
|
|
224
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it('handles onChangeCategory callback', () => {
|
|
228
|
+
const onChangeCategory = jest.fn();
|
|
229
|
+
const data = [{ value: 1, label: 'A' }];
|
|
230
|
+
const { container } = renderComponent({ data, onChangeCategory });
|
|
231
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
232
|
+
});
|
|
32
233
|
});
|
|
33
234
|
|
|
34
235
|
describe('component', () => {
|
|
@@ -41,5 +242,134 @@ describe('LinePlot', () => {
|
|
|
41
242
|
name: 'Line Plot',
|
|
42
243
|
});
|
|
43
244
|
});
|
|
245
|
+
|
|
246
|
+
it('returns object with Component that can be rendered', () => {
|
|
247
|
+
const chart = Line();
|
|
248
|
+
const { Component } = chart;
|
|
249
|
+
|
|
250
|
+
const { container } = render(<Component graphProps={graphProps()} />);
|
|
251
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
describe('CustomBarElement (Line)', () => {
|
|
257
|
+
const renderLinePlot = (props) =>
|
|
258
|
+
render(
|
|
259
|
+
<ThemeProvider theme={theme}>
|
|
260
|
+
<svg>
|
|
261
|
+
<LinePlot {...props} />
|
|
262
|
+
</svg>
|
|
263
|
+
</ThemeProvider>,
|
|
264
|
+
);
|
|
265
|
+
|
|
266
|
+
it('renders line elements', () => {
|
|
267
|
+
const data = [{ value: 1, label: 'A' }];
|
|
268
|
+
const { container } = renderLinePlot({
|
|
269
|
+
data,
|
|
270
|
+
graphProps: graphProps(),
|
|
271
|
+
});
|
|
272
|
+
expect(container).toBeInTheDocument();
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
it('renders with dottedOverline prop', () => {
|
|
276
|
+
const data = [{ value: 2, label: 'A', correctness: { value: 'incorrect' } }];
|
|
277
|
+
const correctData = [{ value: 3, label: 'A' }];
|
|
278
|
+
const { container } = renderLinePlot({
|
|
279
|
+
data,
|
|
280
|
+
graphProps: graphProps(),
|
|
281
|
+
correctData,
|
|
282
|
+
});
|
|
283
|
+
expect(container).toBeInTheDocument();
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
it('renders without dottedOverline prop', () => {
|
|
287
|
+
const data = [{ value: 2, label: 'A' }];
|
|
288
|
+
const { container } = renderLinePlot({
|
|
289
|
+
data,
|
|
290
|
+
graphProps: graphProps(),
|
|
291
|
+
});
|
|
292
|
+
expect(container).toBeInTheDocument();
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it('renders two LinePath elements for X shape when not dotted', () => {
|
|
296
|
+
const data = [{ value: 3, label: 'A' }];
|
|
297
|
+
const { container } = renderLinePlot({
|
|
298
|
+
data,
|
|
299
|
+
graphProps: graphProps(),
|
|
300
|
+
});
|
|
301
|
+
expect(container).toBeInTheDocument();
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
it('renders rect with dashed stroke when dottedOverline is true', () => {
|
|
305
|
+
const data = [{ value: 2, label: 'A', correctness: { value: 'incorrect' } }];
|
|
306
|
+
const correctData = [{ value: 3, label: 'A' }];
|
|
307
|
+
const { container } = renderLinePlot({
|
|
308
|
+
data,
|
|
309
|
+
graphProps: graphProps(),
|
|
310
|
+
correctData,
|
|
311
|
+
});
|
|
312
|
+
expect(container).toBeInTheDocument();
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
it('calculates correct line positions', () => {
|
|
316
|
+
const data = [{ value: 2, label: 'A' }];
|
|
317
|
+
const { container } = renderLinePlot({
|
|
318
|
+
data,
|
|
319
|
+
graphProps: graphProps(),
|
|
320
|
+
});
|
|
321
|
+
expect(container).toBeInTheDocument();
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
it('handles zero pointDiameter', () => {
|
|
325
|
+
const props = graphProps();
|
|
326
|
+
props.size = { width: 0, height: 0 };
|
|
327
|
+
const data = [{ value: 1, label: 'A' }];
|
|
328
|
+
const { container } = renderLinePlot({
|
|
329
|
+
data,
|
|
330
|
+
graphProps: props,
|
|
331
|
+
});
|
|
332
|
+
expect(container).toBeInTheDocument();
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
it('handles large pointDiameter values', () => {
|
|
336
|
+
const props = graphProps();
|
|
337
|
+
props.size = { width: 1000, height: 1000 };
|
|
338
|
+
const data = [{ value: 1, label: 'A' }];
|
|
339
|
+
const { container } = renderLinePlot({
|
|
340
|
+
data,
|
|
341
|
+
graphProps: props,
|
|
342
|
+
});
|
|
343
|
+
expect(container).toBeInTheDocument();
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
it('applies correct strokeWidth based on pointDiameter', () => {
|
|
347
|
+
const data = [{ value: 2, label: 'A' }];
|
|
348
|
+
const { container } = renderLinePlot({
|
|
349
|
+
data,
|
|
350
|
+
graphProps: graphProps(),
|
|
351
|
+
});
|
|
352
|
+
// strokeWidth should be pointDiameter / 5
|
|
353
|
+
expect(container).toBeInTheDocument();
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
it('renders Group component wrapping LinePaths', () => {
|
|
357
|
+
const data = [{ value: 1, label: 'A' }];
|
|
358
|
+
const { container } = renderLinePlot({
|
|
359
|
+
data,
|
|
360
|
+
graphProps: graphProps(),
|
|
361
|
+
});
|
|
362
|
+
expect(container).toBeInTheDocument();
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
it('handles rect with extra padding when dotted', () => {
|
|
366
|
+
const data = [{ value: 2, label: 'A', correctness: { value: 'incorrect' } }];
|
|
367
|
+
const correctData = [{ value: 3, label: 'A' }];
|
|
368
|
+
const { container } = renderLinePlot({
|
|
369
|
+
data,
|
|
370
|
+
graphProps: graphProps(),
|
|
371
|
+
correctData,
|
|
372
|
+
});
|
|
373
|
+
expect(container).toBeInTheDocument();
|
|
44
374
|
});
|
|
45
375
|
});
|