@pie-lib/charting 7.0.13 → 7.1.0-beta

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.
Files changed (63) hide show
  1. package/CHANGELOG.md +0 -44
  2. package/lib/__tests__/actions-button.test.js +332 -0
  3. package/lib/__tests__/actions-button.test.js.map +1 -0
  4. package/lib/__tests__/axes.test.js +746 -0
  5. package/lib/__tests__/axes.test.js.map +1 -0
  6. package/lib/__tests__/chart-setup.test.js +796 -0
  7. package/lib/__tests__/chart-setup.test.js.map +1 -0
  8. package/lib/__tests__/chart-type.test.js +25 -0
  9. package/lib/__tests__/chart-type.test.js.map +1 -0
  10. package/lib/__tests__/chart.test.js +103 -0
  11. package/lib/__tests__/chart.test.js.map +1 -0
  12. package/lib/__tests__/grid.test.js +39 -0
  13. package/lib/__tests__/grid.test.js.map +1 -0
  14. package/lib/__tests__/key-legend.test.js +235 -0
  15. package/lib/__tests__/key-legend.test.js.map +1 -0
  16. package/lib/__tests__/mark-label.test.js +46 -0
  17. package/lib/__tests__/mark-label.test.js.map +1 -0
  18. package/lib/__tests__/tool-menu.test.js +627 -0
  19. package/lib/__tests__/tool-menu.test.js.map +1 -0
  20. package/lib/__tests__/utils.js +56 -0
  21. package/lib/__tests__/utils.js.map +1 -0
  22. package/lib/__tests__/utils.test.js +186 -0
  23. package/lib/__tests__/utils.test.js.map +1 -0
  24. package/lib/bars/__tests__/bar.test.js +53 -0
  25. package/lib/bars/__tests__/bar.test.js.map +1 -0
  26. package/lib/bars/__tests__/histogram.test.js +53 -0
  27. package/lib/bars/__tests__/histogram.test.js.map +1 -0
  28. package/lib/bars/__tests__/utils.js +50 -0
  29. package/lib/bars/__tests__/utils.js.map +1 -0
  30. package/lib/bars/common/__tests__/bars.test.js +76 -0
  31. package/lib/bars/common/__tests__/bars.test.js.map +1 -0
  32. package/lib/bars/common/__tests__/utils.js +50 -0
  33. package/lib/bars/common/__tests__/utils.js.map +1 -0
  34. package/lib/common/__tests__/correctness-indicators.test.js +887 -0
  35. package/lib/common/__tests__/correctness-indicators.test.js.map +1 -0
  36. package/lib/common/__tests__/drag-handle.test.js +73 -0
  37. package/lib/common/__tests__/drag-handle.test.js.map +1 -0
  38. package/lib/common/__tests__/utils.js +50 -0
  39. package/lib/common/__tests__/utils.js.map +1 -0
  40. package/lib/line/__tests__/line-cross.test.js +617 -0
  41. package/lib/line/__tests__/line-cross.test.js.map +1 -0
  42. package/lib/line/__tests__/line-dot.test.js +47 -0
  43. package/lib/line/__tests__/line-dot.test.js.map +1 -0
  44. package/lib/line/__tests__/utils.js +56 -0
  45. package/lib/line/__tests__/utils.js.map +1 -0
  46. package/lib/line/common/__tests__/drag-handle.test.js +73 -0
  47. package/lib/line/common/__tests__/drag-handle.test.js.map +1 -0
  48. package/lib/line/common/__tests__/line.test.js +92 -0
  49. package/lib/line/common/__tests__/line.test.js.map +1 -0
  50. package/lib/line/common/__tests__/utils.js +50 -0
  51. package/lib/line/common/__tests__/utils.js.map +1 -0
  52. package/lib/plot/__tests__/dot.test.js +513 -0
  53. package/lib/plot/__tests__/dot.test.js.map +1 -0
  54. package/lib/plot/__tests__/line.test.js +566 -0
  55. package/lib/plot/__tests__/line.test.js.map +1 -0
  56. package/lib/plot/__tests__/utils.js +50 -0
  57. package/lib/plot/__tests__/utils.js.map +1 -0
  58. package/lib/plot/common/__tests__/plot.test.js +79 -0
  59. package/lib/plot/common/__tests__/plot.test.js.map +1 -0
  60. package/lib/plot/common/__tests__/utils.js +50 -0
  61. package/lib/plot/common/__tests__/utils.js.map +1 -0
  62. package/package.json +5 -5
  63. package/LICENSE.md +0 -5
@@ -0,0 +1,796 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _typeof = require("@babel/runtime/helpers/typeof");
5
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
6
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
7
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
8
+ var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
9
+ var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
10
+ var _react = _interopRequireDefault(require("react"));
11
+ var _react2 = require("@testing-library/react");
12
+ var _styles = require("@mui/material/styles");
13
+ var _chartSetup = _interopRequireWildcard(require("../chart-setup"));
14
+ var _excluded = ["label", "value", "onChange"];
15
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
16
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
17
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
18
+ jest.mock('../chart-type', function () {
19
+ return function ChartType(_ref) {
20
+ var value = _ref.value,
21
+ onChange = _ref.onChange;
22
+ return /*#__PURE__*/_react["default"].createElement("select", {
23
+ "data-testid": "chart-type-select",
24
+ value: value,
25
+ onChange: onChange
26
+ }, /*#__PURE__*/_react["default"].createElement("option", {
27
+ value: "bar"
28
+ }, "Bar"), /*#__PURE__*/_react["default"].createElement("option", {
29
+ value: "line"
30
+ }, "Line"), /*#__PURE__*/_react["default"].createElement("option", {
31
+ value: "linePlot"
32
+ }, "Line Plot"), /*#__PURE__*/_react["default"].createElement("option", {
33
+ value: "dotPlot"
34
+ }, "Dot Plot"));
35
+ };
36
+ });
37
+ jest.mock('@pie-lib/config-ui', function () {
38
+ return {
39
+ NumberTextFieldCustom: function NumberTextFieldCustom(_ref2) {
40
+ var label = _ref2.label,
41
+ value = _ref2.value,
42
+ _onChange = _ref2.onChange,
43
+ props = (0, _objectWithoutProperties2["default"])(_ref2, _excluded);
44
+ return /*#__PURE__*/_react["default"].createElement("input", (0, _extends2["default"])({
45
+ "data-testid": "number-field-".concat(label.toLowerCase().replace(/\s+/g, '-')),
46
+ type: "number",
47
+ value: value,
48
+ onChange: function onChange(e) {
49
+ return _onChange(e, parseFloat(e.target.value) || 0);
50
+ },
51
+ "aria-label": label
52
+ }, props));
53
+ },
54
+ AlertDialog: function AlertDialog(_ref3) {
55
+ var open = _ref3.open,
56
+ title = _ref3.title,
57
+ text = _ref3.text,
58
+ onClose = _ref3.onClose,
59
+ onConfirm = _ref3.onConfirm;
60
+ return open ? /*#__PURE__*/_react["default"].createElement("div", {
61
+ "data-testid": "alert-dialog"
62
+ }, /*#__PURE__*/_react["default"].createElement("h2", null, title), /*#__PURE__*/_react["default"].createElement("p", null, text), /*#__PURE__*/_react["default"].createElement("button", {
63
+ "data-testid": "alert-cancel",
64
+ onClick: onClose
65
+ }, "Cancel"), /*#__PURE__*/_react["default"].createElement("button", {
66
+ "data-testid": "alert-confirm",
67
+ onClick: onConfirm
68
+ }, "Confirm")) : null;
69
+ }
70
+ };
71
+ });
72
+ var theme;
73
+ beforeAll(function () {
74
+ theme = (0, _styles.createTheme)();
75
+ });
76
+ describe('resetValues', function () {
77
+ var data;
78
+ var range;
79
+ var model;
80
+ var onChange;
81
+ beforeEach(function () {
82
+ range = {
83
+ min: 0,
84
+ max: 10,
85
+ step: 1
86
+ };
87
+ data = [{
88
+ value: 2
89
+ }, {
90
+ value: 11
91
+ }, {
92
+ value: 5.5
93
+ }, {
94
+ value: 2.0000000001
95
+ }, {
96
+ value: 2.9999999999
97
+ }];
98
+ model = {
99
+ someField: 'someValue',
100
+ data: data
101
+ };
102
+ onChange = jest.fn();
103
+ });
104
+ it('should reset values greater than range.max to zero', function () {
105
+ (0, _chartSetup.resetValues)(data, true, range, onChange, model);
106
+ expect(data[1].value).toBe(0);
107
+ });
108
+ it('should reset values that are not multiples of range.step to zero', function () {
109
+ (0, _chartSetup.resetValues)(data, true, range, onChange, model);
110
+ expect(data[2].value).toBe(0);
111
+ });
112
+ it('should not reset values that are within range and multiples of range.step', function () {
113
+ (0, _chartSetup.resetValues)(data, true, range, onChange, model);
114
+ expect(data[0].value).toBe(2);
115
+ });
116
+ it('should not reset floating point values that are close to multiples of range.step', function () {
117
+ (0, _chartSetup.resetValues)(data, true, range, onChange, model);
118
+ expect(data[3].value).toBe(2.0000000001);
119
+ expect(data[4].value).toBe(2.9999999999);
120
+ });
121
+ it('should not call onChange when updateModel is false', function () {
122
+ (0, _chartSetup.resetValues)(data, false, range, onChange, model);
123
+ expect(onChange).not.toHaveBeenCalled();
124
+ });
125
+ it('should handle null or undefined data array', function () {
126
+ expect(function () {
127
+ return (0, _chartSetup.resetValues)(null, true, range, onChange, model);
128
+ }).not.toThrow();
129
+ expect(function () {
130
+ return (0, _chartSetup.resetValues)(undefined, true, range, onChange, model);
131
+ }).not.toThrow();
132
+ });
133
+ it('should handle empty data array', function () {
134
+ (0, _chartSetup.resetValues)([], true, range, onChange, model);
135
+ expect(onChange).toHaveBeenCalledWith(_objectSpread(_objectSpread({}, model), {}, {
136
+ data: []
137
+ }));
138
+ });
139
+ it('should reset multiple invalid values', function () {
140
+ var multiData = [{
141
+ value: 11
142
+ }, {
143
+ value: 12
144
+ }, {
145
+ value: 5.5
146
+ }, {
147
+ value: 3.7
148
+ }];
149
+ (0, _chartSetup.resetValues)(multiData, true, range, onChange, _objectSpread(_objectSpread({}, model), {}, {
150
+ data: multiData
151
+ }));
152
+ expect(multiData.every(function (d) {
153
+ return d.value === 0;
154
+ })).toBe(true);
155
+ });
156
+ it('should handle decimal step values', function () {
157
+ var decimalRange = {
158
+ min: 0,
159
+ max: 10,
160
+ step: 0.5
161
+ };
162
+ var decimalData = [{
163
+ value: 1.5
164
+ }, {
165
+ value: 2.3
166
+ }, {
167
+ value: 3.0
168
+ }];
169
+ (0, _chartSetup.resetValues)(decimalData, true, decimalRange, onChange, model);
170
+ expect(decimalData[0].value).toBe(1.5);
171
+ expect(decimalData[1].value).toBe(0);
172
+ expect(decimalData[2].value).toBe(3.0);
173
+ });
174
+ });
175
+ describe('ConfigureChartPanel', function () {
176
+ var defaultModel = {
177
+ chartType: 'bar',
178
+ range: {
179
+ min: 0,
180
+ max: 10,
181
+ step: 1,
182
+ labelStep: 1
183
+ },
184
+ graph: {
185
+ width: 400,
186
+ height: 500
187
+ },
188
+ data: [{
189
+ value: 5
190
+ }],
191
+ correctAnswer: {
192
+ data: [{
193
+ value: 3
194
+ }]
195
+ },
196
+ changeInteractiveEnabled: true,
197
+ changeEditableEnabled: true
198
+ };
199
+ var defaultProps = {
200
+ model: defaultModel,
201
+ onChange: jest.fn(),
202
+ chartDimensions: {
203
+ showInConfigPanel: true,
204
+ width: {
205
+ min: 50,
206
+ max: 700,
207
+ step: 20
208
+ },
209
+ height: {
210
+ min: 400,
211
+ max: 700,
212
+ step: 20
213
+ }
214
+ },
215
+ gridValues: {
216
+ range: {
217
+ min: 0,
218
+ max: 10000
219
+ }
220
+ },
221
+ labelValues: {
222
+ range: {
223
+ min: 0,
224
+ max: 10000
225
+ }
226
+ },
227
+ studentNewCategoryDefaultLabel: {
228
+ label: 'Category'
229
+ },
230
+ availableChartTypes: {},
231
+ chartTypeLabel: 'Chart Type'
232
+ };
233
+ beforeEach(function () {
234
+ jest.clearAllMocks();
235
+ });
236
+ var renderComponent = function renderComponent() {
237
+ var extras = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
238
+ var props = _objectSpread(_objectSpread({}, defaultProps), extras);
239
+ return (0, _react2.render)(/*#__PURE__*/_react["default"].createElement(_styles.ThemeProvider, {
240
+ theme: theme
241
+ }, /*#__PURE__*/_react["default"].createElement(_chartSetup["default"], props)));
242
+ };
243
+ describe('rendering', function () {
244
+ it('should render without crashing', function () {
245
+ var _renderComponent = renderComponent(),
246
+ container = _renderComponent.container;
247
+ expect(container).toBeInTheDocument();
248
+ });
249
+ it('should render "Configure Chart" title', function () {
250
+ var _renderComponent2 = renderComponent(),
251
+ getByText = _renderComponent2.getByText;
252
+ expect(getByText('Configure Chart')).toBeInTheDocument();
253
+ });
254
+ it('should render chart type selector', function () {
255
+ var _renderComponent3 = renderComponent(),
256
+ getByTestId = _renderComponent3.getByTestId;
257
+ expect(getByTestId('chart-type-select')).toBeInTheDocument();
258
+ });
259
+ it('should render max value field', function () {
260
+ var _renderComponent4 = renderComponent(),
261
+ getByLabelText = _renderComponent4.getByLabelText;
262
+ expect(getByLabelText('Max Value')).toBeInTheDocument();
263
+ });
264
+ it('should render grid interval field for non-plot charts', function () {
265
+ var _renderComponent5 = renderComponent({
266
+ model: _objectSpread(_objectSpread({}, defaultModel), {}, {
267
+ chartType: 'bar'
268
+ })
269
+ }),
270
+ getByLabelText = _renderComponent5.getByLabelText;
271
+ expect(getByLabelText('Grid Interval')).toBeInTheDocument();
272
+ });
273
+ it('should render label interval field for non-plot charts', function () {
274
+ var _renderComponent6 = renderComponent({
275
+ model: _objectSpread(_objectSpread({}, defaultModel), {}, {
276
+ chartType: 'bar'
277
+ })
278
+ }),
279
+ getByLabelText = _renderComponent6.getByLabelText;
280
+ expect(getByLabelText('Label Interval')).toBeInTheDocument();
281
+ });
282
+ it('should not render step config for plot charts', function () {
283
+ var _renderComponent7 = renderComponent({
284
+ model: _objectSpread(_objectSpread({}, defaultModel), {}, {
285
+ chartType: 'linePlot'
286
+ })
287
+ }),
288
+ queryByLabelText = _renderComponent7.queryByLabelText;
289
+ expect(queryByLabelText('Grid Interval')).not.toBeInTheDocument();
290
+ expect(queryByLabelText('Label Interval')).not.toBeInTheDocument();
291
+ });
292
+ it('should render dimensions section when showInConfigPanel is true', function () {
293
+ var _renderComponent8 = renderComponent({
294
+ chartDimensions: {
295
+ showInConfigPanel: true,
296
+ width: {
297
+ min: 50,
298
+ max: 700,
299
+ step: 20
300
+ },
301
+ height: {
302
+ min: 400,
303
+ max: 700,
304
+ step: 20
305
+ }
306
+ }
307
+ }),
308
+ getByText = _renderComponent8.getByText;
309
+ expect(getByText('Dimensions(px)')).toBeInTheDocument();
310
+ });
311
+ it('should not render dimensions section when showInConfigPanel is false', function () {
312
+ var _renderComponent9 = renderComponent({
313
+ chartDimensions: {
314
+ showInConfigPanel: false,
315
+ width: {
316
+ min: 50,
317
+ max: 700,
318
+ step: 20
319
+ },
320
+ height: {
321
+ min: 400,
322
+ max: 700,
323
+ step: 20
324
+ }
325
+ }
326
+ }),
327
+ queryByText = _renderComponent9.queryByText;
328
+ expect(queryByText('Dimensions(px)')).not.toBeInTheDocument();
329
+ });
330
+ it('should render width field when dimensions are shown', function () {
331
+ var _renderComponent0 = renderComponent(),
332
+ getByLabelText = _renderComponent0.getByLabelText;
333
+ expect(getByLabelText('Width')).toBeInTheDocument();
334
+ });
335
+ it('should render height field when dimensions are shown', function () {
336
+ var _renderComponent1 = renderComponent(),
337
+ getByLabelText = _renderComponent1.getByLabelText;
338
+ expect(getByLabelText('Height')).toBeInTheDocument();
339
+ });
340
+ it('should display width constraints', function () {
341
+ var _renderComponent10 = renderComponent(),
342
+ getByText = _renderComponent10.getByText;
343
+ expect(getByText('Min 50, Max 700')).toBeInTheDocument();
344
+ });
345
+ it('should display height constraints', function () {
346
+ var _renderComponent11 = renderComponent(),
347
+ getAllByText = _renderComponent11.getAllByText;
348
+ var constraints = getAllByText('Min 400, Max 700');
349
+ expect(constraints.length).toBeGreaterThan(0);
350
+ });
351
+ });
352
+ describe('chart type changes', function () {
353
+ it('should call onChange when chart type is changed to non-plot', function () {
354
+ var onChange = jest.fn();
355
+ var _renderComponent12 = renderComponent({
356
+ onChange: onChange
357
+ }),
358
+ getByTestId = _renderComponent12.getByTestId;
359
+ _react2.fireEvent.change(getByTestId('chart-type-select'), {
360
+ target: {
361
+ value: 'line'
362
+ }
363
+ });
364
+ expect(onChange).toHaveBeenCalled();
365
+ });
366
+ it('should show warning when switching to plot with invalid config', /*#__PURE__*/(0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee() {
367
+ var _renderComponent13, getByTestId, getByText;
368
+ return _regenerator["default"].wrap(function (_context) {
369
+ while (1) switch (_context.prev = _context.next) {
370
+ case 0:
371
+ _renderComponent13 = renderComponent({
372
+ model: _objectSpread(_objectSpread({}, defaultModel), {}, {
373
+ range: {
374
+ max: 20,
375
+ step: 2,
376
+ labelStep: 2
377
+ }
378
+ })
379
+ }), getByTestId = _renderComponent13.getByTestId, getByText = _renderComponent13.getByText;
380
+ _react2.fireEvent.change(getByTestId('chart-type-select'), {
381
+ target: {
382
+ value: 'linePlot'
383
+ }
384
+ });
385
+ _context.next = 1;
386
+ return (0, _react2.waitFor)(function () {
387
+ expect(getByText('Warning')).toBeInTheDocument();
388
+ });
389
+ case 1:
390
+ case "end":
391
+ return _context.stop();
392
+ }
393
+ }, _callee);
394
+ })));
395
+ it('should allow switching to plot with valid config', function () {
396
+ var onChange = jest.fn();
397
+ var _renderComponent14 = renderComponent({
398
+ onChange: onChange,
399
+ model: _objectSpread(_objectSpread({}, defaultModel), {}, {
400
+ range: {
401
+ max: 10,
402
+ step: 1,
403
+ labelStep: 1
404
+ }
405
+ })
406
+ }),
407
+ getByTestId = _renderComponent14.getByTestId;
408
+ _react2.fireEvent.change(getByTestId('chart-type-select'), {
409
+ target: {
410
+ value: 'dotPlot'
411
+ }
412
+ });
413
+ expect(onChange).toHaveBeenCalledWith(expect.objectContaining({
414
+ chartType: 'dotPlot'
415
+ }));
416
+ });
417
+ });
418
+ describe('range changes', function () {
419
+ it('should update max value', function () {
420
+ var onChange = jest.fn();
421
+ var _renderComponent15 = renderComponent({
422
+ onChange: onChange
423
+ }),
424
+ getByLabelText = _renderComponent15.getByLabelText;
425
+ var maxInput = getByLabelText('Max Value');
426
+ _react2.fireEvent.change(maxInput, {
427
+ target: {
428
+ value: '15'
429
+ }
430
+ });
431
+ expect(onChange).toHaveBeenCalled();
432
+ });
433
+ it('should update step value', function () {
434
+ var onChange = jest.fn();
435
+ var _renderComponent16 = renderComponent({
436
+ onChange: onChange
437
+ }),
438
+ getByLabelText = _renderComponent16.getByLabelText;
439
+ var stepInput = getByLabelText('Grid Interval');
440
+ _react2.fireEvent.change(stepInput, {
441
+ target: {
442
+ value: '2'
443
+ }
444
+ });
445
+ expect(onChange).toHaveBeenCalled();
446
+ });
447
+ it('should update label step value', function () {
448
+ var onChange = jest.fn();
449
+ var _renderComponent17 = renderComponent({
450
+ onChange: onChange
451
+ }),
452
+ getByLabelText = _renderComponent17.getByLabelText;
453
+ var labelStepInput = getByLabelText('Label Interval');
454
+ _react2.fireEvent.change(labelStepInput, {
455
+ target: {
456
+ value: '2'
457
+ }
458
+ });
459
+ expect(onChange).toHaveBeenCalled();
460
+ });
461
+ it('should show alert when changing max causes data to be out of range', /*#__PURE__*/(0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee2() {
462
+ var onChange, _renderComponent18, getByLabelText, queryByTestId, maxInput;
463
+ return _regenerator["default"].wrap(function (_context2) {
464
+ while (1) switch (_context2.prev = _context2.next) {
465
+ case 0:
466
+ onChange = jest.fn();
467
+ _renderComponent18 = renderComponent({
468
+ onChange: onChange,
469
+ model: _objectSpread(_objectSpread({}, defaultModel), {}, {
470
+ range: {
471
+ min: 0,
472
+ max: 10,
473
+ step: 1,
474
+ labelStep: 1
475
+ },
476
+ data: [{
477
+ value: 8
478
+ }],
479
+ correctAnswer: {
480
+ data: []
481
+ }
482
+ })
483
+ }), getByLabelText = _renderComponent18.getByLabelText, queryByTestId = _renderComponent18.queryByTestId;
484
+ maxInput = getByLabelText('Max Value');
485
+ _react2.fireEvent.change(maxInput, {
486
+ target: {
487
+ value: '5'
488
+ }
489
+ });
490
+ _context2.next = 1;
491
+ return (0, _react2.waitFor)(function () {
492
+ expect(onChange).toHaveBeenCalled();
493
+ });
494
+ case 1:
495
+ case "end":
496
+ return _context2.stop();
497
+ }
498
+ }, _callee2);
499
+ })));
500
+ it('should show alert when changing step causes data to be out of range', /*#__PURE__*/(0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee3() {
501
+ var onChange, _renderComponent19, getByLabelText, stepInput;
502
+ return _regenerator["default"].wrap(function (_context3) {
503
+ while (1) switch (_context3.prev = _context3.next) {
504
+ case 0:
505
+ onChange = jest.fn();
506
+ _renderComponent19 = renderComponent({
507
+ onChange: onChange,
508
+ model: _objectSpread(_objectSpread({}, defaultModel), {}, {
509
+ range: {
510
+ min: 0,
511
+ max: 10,
512
+ step: 1,
513
+ labelStep: 1
514
+ },
515
+ data: [{
516
+ value: 5
517
+ }],
518
+ correctAnswer: {
519
+ data: []
520
+ }
521
+ })
522
+ }), getByLabelText = _renderComponent19.getByLabelText;
523
+ stepInput = getByLabelText('Grid Interval');
524
+ _react2.fireEvent.change(stepInput, {
525
+ target: {
526
+ value: '3'
527
+ }
528
+ });
529
+ _context3.next = 1;
530
+ return (0, _react2.waitFor)(function () {
531
+ expect(onChange).toHaveBeenCalled();
532
+ });
533
+ case 1:
534
+ case "end":
535
+ return _context3.stop();
536
+ }
537
+ }, _callee3);
538
+ })));
539
+ });
540
+ describe('dimensions changes', function () {
541
+ it('should update width', function () {
542
+ var onChange = jest.fn();
543
+ var _renderComponent20 = renderComponent({
544
+ onChange: onChange
545
+ }),
546
+ getByLabelText = _renderComponent20.getByLabelText;
547
+ var widthInput = getByLabelText('Width');
548
+ _react2.fireEvent.change(widthInput, {
549
+ target: {
550
+ value: '500'
551
+ }
552
+ });
553
+ expect(onChange).toHaveBeenCalledWith(expect.objectContaining({
554
+ graph: expect.objectContaining({
555
+ width: 500
556
+ })
557
+ }));
558
+ });
559
+ it('should update height', function () {
560
+ var onChange = jest.fn();
561
+ var _renderComponent21 = renderComponent({
562
+ onChange: onChange
563
+ }),
564
+ getByLabelText = _renderComponent21.getByLabelText;
565
+ var heightInput = getByLabelText('Height');
566
+ _react2.fireEvent.change(heightInput, {
567
+ target: {
568
+ value: '600'
569
+ }
570
+ });
571
+ expect(onChange).toHaveBeenCalledWith(expect.objectContaining({
572
+ graph: expect.objectContaining({
573
+ height: 600
574
+ })
575
+ }));
576
+ });
577
+ });
578
+ describe('alert dialog', function () {
579
+ it('should reset range on cancel', /*#__PURE__*/(0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee4() {
580
+ var onChange, _renderComponent22, getByLabelText, queryByTestId, maxInput, event;
581
+ return _regenerator["default"].wrap(function (_context4) {
582
+ while (1) switch (_context4.prev = _context4.next) {
583
+ case 0:
584
+ onChange = jest.fn();
585
+ _renderComponent22 = renderComponent({
586
+ onChange: onChange,
587
+ model: _objectSpread(_objectSpread({}, defaultModel), {}, {
588
+ range: {
589
+ min: 0,
590
+ max: 10,
591
+ step: 1,
592
+ labelStep: 1
593
+ },
594
+ data: [{
595
+ value: 8
596
+ }],
597
+ correctAnswer: {
598
+ data: []
599
+ }
600
+ })
601
+ }), getByLabelText = _renderComponent22.getByLabelText, queryByTestId = _renderComponent22.queryByTestId;
602
+ maxInput = getByLabelText('Max Value');
603
+ event = {
604
+ target: maxInput
605
+ };
606
+ _react2.fireEvent.change(maxInput, {
607
+ target: {
608
+ value: '5'
609
+ }
610
+ });
611
+ _context4.next = 1;
612
+ return (0, _react2.waitFor)(function () {
613
+ var dialog = queryByTestId('alert-dialog');
614
+ if (dialog) {
615
+ _react2.fireEvent.click(queryByTestId('alert-cancel'));
616
+ }
617
+ }, {
618
+ timeout: 100
619
+ })["catch"](function () {});
620
+ case 1:
621
+ expect(onChange).toHaveBeenCalled();
622
+ case 2:
623
+ case "end":
624
+ return _context4.stop();
625
+ }
626
+ }, _callee4);
627
+ })));
628
+ it('should apply changes and reset data on confirm', /*#__PURE__*/(0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee5() {
629
+ var onChange, _renderComponent23, getByLabelText, queryByTestId, maxInput;
630
+ return _regenerator["default"].wrap(function (_context5) {
631
+ while (1) switch (_context5.prev = _context5.next) {
632
+ case 0:
633
+ onChange = jest.fn();
634
+ _renderComponent23 = renderComponent({
635
+ onChange: onChange,
636
+ model: _objectSpread(_objectSpread({}, defaultModel), {}, {
637
+ range: {
638
+ min: 0,
639
+ max: 10,
640
+ step: 1,
641
+ labelStep: 1
642
+ },
643
+ data: [{
644
+ value: 8
645
+ }],
646
+ correctAnswer: {
647
+ data: []
648
+ }
649
+ })
650
+ }), getByLabelText = _renderComponent23.getByLabelText, queryByTestId = _renderComponent23.queryByTestId;
651
+ maxInput = getByLabelText('Max Value');
652
+ _react2.fireEvent.change(maxInput, {
653
+ target: {
654
+ value: '5'
655
+ }
656
+ });
657
+ _context5.next = 1;
658
+ return (0, _react2.waitFor)(function () {
659
+ var dialog = queryByTestId('alert-dialog');
660
+ if (dialog) {
661
+ _react2.fireEvent.click(queryByTestId('alert-confirm'));
662
+ }
663
+ }, {
664
+ timeout: 100
665
+ })["catch"](function () {});
666
+ case 1:
667
+ expect(onChange).toHaveBeenCalled();
668
+ case 2:
669
+ case "end":
670
+ return _context5.stop();
671
+ }
672
+ }, _callee5);
673
+ })));
674
+ });
675
+ describe('edge cases', function () {
676
+ it('should handle missing chartDimensions', function () {
677
+ var _renderComponent24 = renderComponent({
678
+ chartDimensions: undefined
679
+ }),
680
+ container = _renderComponent24.container;
681
+ expect(container).toBeInTheDocument();
682
+ });
683
+ it('should handle missing gridValues', function () {
684
+ var _renderComponent25 = renderComponent({
685
+ gridValues: undefined
686
+ }),
687
+ container = _renderComponent25.container;
688
+ expect(container).toBeInTheDocument();
689
+ });
690
+ it('should handle missing labelValues', function () {
691
+ var _renderComponent26 = renderComponent({
692
+ labelValues: undefined
693
+ }),
694
+ container = _renderComponent26.container;
695
+ expect(container).toBeInTheDocument();
696
+ });
697
+ it('should handle empty model data', function () {
698
+ var _renderComponent27 = renderComponent({
699
+ model: _objectSpread(_objectSpread({}, defaultModel), {}, {
700
+ data: [],
701
+ correctAnswer: {
702
+ data: []
703
+ }
704
+ })
705
+ }),
706
+ container = _renderComponent27.container;
707
+ expect(container).toBeInTheDocument();
708
+ });
709
+ it('should handle empty range object', function () {
710
+ var _renderComponent28 = renderComponent({
711
+ model: _objectSpread(_objectSpread({}, defaultModel), {}, {
712
+ range: {}
713
+ })
714
+ }),
715
+ container = _renderComponent28.container;
716
+ expect(container).toBeInTheDocument();
717
+ });
718
+ it('should apply width constraints correctly', function () {
719
+ var _renderComponent29 = renderComponent({
720
+ chartDimensions: {
721
+ showInConfigPanel: true,
722
+ width: {
723
+ min: 100,
724
+ max: 600,
725
+ step: 50
726
+ },
727
+ height: {
728
+ min: 400,
729
+ max: 700,
730
+ step: 20
731
+ }
732
+ }
733
+ }),
734
+ container = _renderComponent29.container;
735
+ expect(container).toBeInTheDocument();
736
+ });
737
+ it('should apply height constraints correctly', function () {
738
+ var _renderComponent30 = renderComponent({
739
+ chartDimensions: {
740
+ showInConfigPanel: true,
741
+ width: {
742
+ min: 50,
743
+ max: 700,
744
+ step: 20
745
+ },
746
+ height: {
747
+ min: 450,
748
+ max: 650,
749
+ step: 30
750
+ }
751
+ }
752
+ }),
753
+ container = _renderComponent30.container;
754
+ expect(container).toBeInTheDocument();
755
+ });
756
+ it('should handle very small step values', function () {
757
+ var _renderComponent31 = renderComponent({
758
+ chartDimensions: {
759
+ showInConfigPanel: true,
760
+ width: {
761
+ min: 50,
762
+ max: 700,
763
+ step: 0.5
764
+ },
765
+ height: {
766
+ min: 400,
767
+ max: 700,
768
+ step: 0.5
769
+ }
770
+ }
771
+ }),
772
+ container = _renderComponent31.container;
773
+ expect(container).toBeInTheDocument();
774
+ });
775
+ });
776
+ describe('useEffect lifecycle', function () {
777
+ it('should call onChange on mount', function () {
778
+ var onChange = jest.fn();
779
+ renderComponent({
780
+ onChange: onChange
781
+ });
782
+ expect(onChange).toHaveBeenCalled();
783
+ });
784
+ it('should set category default label on mount', function () {
785
+ var onChange = jest.fn();
786
+ renderComponent({
787
+ onChange: onChange,
788
+ studentNewCategoryDefaultLabel: {
789
+ label: 'Test Category'
790
+ }
791
+ });
792
+ expect(onChange).toHaveBeenCalled();
793
+ });
794
+ });
795
+ });
796
+ //# sourceMappingURL=chart-setup.test.js.map