@pie-lib/charting 7.0.22-beta.6 → 7.0.22-beta.8

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 (61) hide show
  1. package/lib/__tests__/actions-button.test.js +332 -0
  2. package/lib/__tests__/axes.test.js +746 -0
  3. package/lib/__tests__/chart-setup.test.js +796 -0
  4. package/lib/__tests__/chart-type.test.js +25 -0
  5. package/lib/__tests__/chart.test.js +103 -0
  6. package/lib/__tests__/grid.test.js +39 -0
  7. package/lib/__tests__/key-legend.test.js +235 -0
  8. package/lib/__tests__/mark-label.test.js +46 -0
  9. package/lib/__tests__/tool-menu.test.js +627 -0
  10. package/lib/__tests__/utils.js +56 -0
  11. package/lib/__tests__/utils.test.js +186 -0
  12. package/lib/bars/__tests__/bar.test.js +53 -0
  13. package/lib/bars/__tests__/histogram.test.js +53 -0
  14. package/lib/bars/__tests__/utils.js +50 -0
  15. package/lib/bars/common/__tests__/bars.test.js +76 -0
  16. package/lib/bars/common/__tests__/utils.js +50 -0
  17. package/lib/common/__tests__/correctness-indicators.test.js +887 -0
  18. package/lib/common/__tests__/drag-handle.test.js +73 -0
  19. package/lib/common/__tests__/utils.js +50 -0
  20. package/lib/line/__tests__/line-cross.test.js +617 -0
  21. package/lib/line/__tests__/line-dot.test.js +47 -0
  22. package/lib/line/__tests__/utils.js +56 -0
  23. package/lib/line/common/__tests__/drag-handle.test.js +73 -0
  24. package/lib/line/common/__tests__/line.test.js +92 -0
  25. package/lib/line/common/__tests__/utils.js +50 -0
  26. package/lib/plot/__tests__/dot.test.js +513 -0
  27. package/lib/plot/__tests__/line.test.js +566 -0
  28. package/lib/plot/__tests__/utils.js +50 -0
  29. package/lib/plot/common/__tests__/plot.test.js +79 -0
  30. package/lib/plot/common/__tests__/utils.js +50 -0
  31. package/package.json +2 -2
  32. package/src/__tests__/actions-button.test.jsx +280 -0
  33. package/src/__tests__/axes.test.jsx +667 -0
  34. package/src/__tests__/chart-setup.test.jsx +532 -0
  35. package/src/__tests__/chart-type.test.jsx +23 -0
  36. package/src/__tests__/chart.test.jsx +86 -0
  37. package/src/__tests__/grid.test.jsx +37 -0
  38. package/src/__tests__/key-legend.test.jsx +223 -0
  39. package/src/__tests__/mark-label.test.jsx +33 -0
  40. package/src/__tests__/tool-menu.test.jsx +522 -0
  41. package/src/__tests__/utils.js +36 -0
  42. package/src/__tests__/utils.test.js +100 -0
  43. package/src/bars/__tests__/bar.test.jsx +45 -0
  44. package/src/bars/__tests__/histogram.test.jsx +45 -0
  45. package/src/bars/__tests__/utils.js +30 -0
  46. package/src/bars/common/__tests__/bars.test.jsx +68 -0
  47. package/src/bars/common/__tests__/utils.js +30 -0
  48. package/src/common/__tests__/correctness-indicators.test.jsx +720 -0
  49. package/src/common/__tests__/drag-handle.test.jsx +58 -0
  50. package/src/common/__tests__/utils.js +30 -0
  51. package/src/line/__tests__/line-cross.test.jsx +463 -0
  52. package/src/line/__tests__/line-dot.test.jsx +41 -0
  53. package/src/line/__tests__/utils.js +36 -0
  54. package/src/line/common/__tests__/drag-handle.test.jsx +62 -0
  55. package/src/line/common/__tests__/line.test.jsx +79 -0
  56. package/src/line/common/__tests__/utils.js +30 -0
  57. package/src/plot/__tests__/dot.test.jsx +344 -0
  58. package/src/plot/__tests__/line.test.jsx +375 -0
  59. package/src/plot/__tests__/utils.js +30 -0
  60. package/src/plot/common/__tests__/plot.test.jsx +69 -0
  61. package/src/plot/common/__tests__/utils.js +30 -0
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.scaleMock = exports.graphProps = void 0;
7
+ var scaleMock = exports.scaleMock = function scaleMock() {
8
+ var fn = jest.fn(function (n) {
9
+ return n;
10
+ });
11
+ fn.invert = jest.fn(function (n) {
12
+ return n;
13
+ });
14
+ return fn;
15
+ };
16
+ var graphProps = exports.graphProps = function graphProps() {
17
+ var dmin = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
18
+ var dmax = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
19
+ var rmin = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
20
+ var rmax = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1;
21
+ return {
22
+ scale: {
23
+ x: scaleMock(),
24
+ y: scaleMock()
25
+ },
26
+ snap: {
27
+ x: jest.fn(function (n) {
28
+ return n;
29
+ }),
30
+ y: jest.fn(function (n) {
31
+ return n;
32
+ })
33
+ },
34
+ domain: {
35
+ min: dmin,
36
+ max: dmax,
37
+ step: 1
38
+ },
39
+ range: {
40
+ min: rmin,
41
+ max: rmax,
42
+ step: 1
43
+ },
44
+ size: {
45
+ width: 400,
46
+ height: 400
47
+ }
48
+ };
49
+ };
50
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJzY2FsZU1vY2siLCJleHBvcnRzIiwiZm4iLCJqZXN0IiwibiIsImludmVydCIsImdyYXBoUHJvcHMiLCJkbWluIiwiYXJndW1lbnRzIiwibGVuZ3RoIiwidW5kZWZpbmVkIiwiZG1heCIsInJtaW4iLCJybWF4Iiwic2NhbGUiLCJ4IiwieSIsInNuYXAiLCJkb21haW4iLCJtaW4iLCJtYXgiLCJzdGVwIiwicmFuZ2UiLCJzaXplIiwid2lkdGgiLCJoZWlnaHQiXSwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcGxvdC9fX3Rlc3RzX18vdXRpbHMuanMiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGNvbnN0IHNjYWxlTW9jayA9ICgpID0+IHtcbiAgY29uc3QgZm4gPSBqZXN0LmZuKChuKSA9PiBuKTtcbiAgZm4uaW52ZXJ0ID0gamVzdC5mbigobikgPT4gbik7XG4gIHJldHVybiBmbjtcbn07XG5cbmV4cG9ydCBjb25zdCBncmFwaFByb3BzID0gKGRtaW4gPSAwLCBkbWF4ID0gMSwgcm1pbiA9IDAsIHJtYXggPSAxKSA9PiAoe1xuICBzY2FsZToge1xuICAgIHg6IHNjYWxlTW9jaygpLFxuICAgIHk6IHNjYWxlTW9jaygpLFxuICB9LFxuICBzbmFwOiB7XG4gICAgeDogamVzdC5mbigobikgPT4gbiksXG4gICAgeTogamVzdC5mbigobikgPT4gbiksXG4gIH0sXG4gIGRvbWFpbjoge1xuICAgIG1pbjogZG1pbixcbiAgICBtYXg6IGRtYXgsXG4gICAgc3RlcDogMSxcbiAgfSxcbiAgcmFuZ2U6IHtcbiAgICBtaW46IHJtaW4sXG4gICAgbWF4OiBybWF4LFxuICAgIHN0ZXA6IDEsXG4gIH0sXG4gIHNpemU6IHtcbiAgICB3aWR0aDogNDAwLFxuICAgIGhlaWdodDogNDAwLFxuICB9LFxufSk7XG4iXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFPLElBQU1BLFNBQVMsR0FBQUMsT0FBQSxDQUFBRCxTQUFBLEdBQUcsU0FBWkEsU0FBU0EsQ0FBQSxFQUFTO0VBQzdCLElBQU1FLEVBQUUsR0FBR0MsSUFBSSxDQUFDRCxFQUFFLENBQUMsVUFBQ0UsQ0FBQztJQUFBLE9BQUtBLENBQUM7RUFBQSxFQUFDO0VBQzVCRixFQUFFLENBQUNHLE1BQU0sR0FBR0YsSUFBSSxDQUFDRCxFQUFFLENBQUMsVUFBQ0UsQ0FBQztJQUFBLE9BQUtBLENBQUM7RUFBQSxFQUFDO0VBQzdCLE9BQU9GLEVBQUU7QUFDWCxDQUFDO0FBRU0sSUFBTUksVUFBVSxHQUFBTCxPQUFBLENBQUFLLFVBQUEsR0FBRyxTQUFiQSxVQUFVQSxDQUFBO0VBQUEsSUFBSUMsSUFBSSxHQUFBQyxTQUFBLENBQUFDLE1BQUEsUUFBQUQsU0FBQSxRQUFBRSxTQUFBLEdBQUFGLFNBQUEsTUFBRyxDQUFDO0VBQUEsSUFBRUcsSUFBSSxHQUFBSCxTQUFBLENBQUFDLE1BQUEsUUFBQUQsU0FBQSxRQUFBRSxTQUFBLEdBQUFGLFNBQUEsTUFBRyxDQUFDO0VBQUEsSUFBRUksSUFBSSxHQUFBSixTQUFBLENBQUFDLE1BQUEsUUFBQUQsU0FBQSxRQUFBRSxTQUFBLEdBQUFGLFNBQUEsTUFBRyxDQUFDO0VBQUEsSUFBRUssSUFBSSxHQUFBTCxTQUFBLENBQUFDLE1BQUEsUUFBQUQsU0FBQSxRQUFBRSxTQUFBLEdBQUFGLFNBQUEsTUFBRyxDQUFDO0VBQUEsT0FBTTtJQUNyRU0sS0FBSyxFQUFFO01BQ0xDLENBQUMsRUFBRWYsU0FBUyxDQUFDLENBQUM7TUFDZGdCLENBQUMsRUFBRWhCLFNBQVMsQ0FBQztJQUNmLENBQUM7SUFDRGlCLElBQUksRUFBRTtNQUNKRixDQUFDLEVBQUVaLElBQUksQ0FBQ0QsRUFBRSxDQUFDLFVBQUNFLENBQUM7UUFBQSxPQUFLQSxDQUFDO01BQUEsRUFBQztNQUNwQlksQ0FBQyxFQUFFYixJQUFJLENBQUNELEVBQUUsQ0FBQyxVQUFDRSxDQUFDO1FBQUEsT0FBS0EsQ0FBQztNQUFBO0lBQ3JCLENBQUM7SUFDRGMsTUFBTSxFQUFFO01BQ05DLEdBQUcsRUFBRVosSUFBSTtNQUNUYSxHQUFHLEVBQUVULElBQUk7TUFDVFUsSUFBSSxFQUFFO0lBQ1IsQ0FBQztJQUNEQyxLQUFLLEVBQUU7TUFDTEgsR0FBRyxFQUFFUCxJQUFJO01BQ1RRLEdBQUcsRUFBRVAsSUFBSTtNQUNUUSxJQUFJLEVBQUU7SUFDUixDQUFDO0lBQ0RFLElBQUksRUFBRTtNQUNKQyxLQUFLLEVBQUUsR0FBRztNQUNWQyxNQUFNLEVBQUU7SUFDVjtFQUNGLENBQUM7QUFBQSxDQUFDIiwiaWdub3JlTGlzdCI6W119
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _typeof = require("@babel/runtime/helpers/typeof");
5
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
6
+ var _react = require("@testing-library/react");
7
+ var _react2 = _interopRequireDefault(require("react"));
8
+ var _plot = _interopRequireWildcard(require("../plot"));
9
+ var _utils = require("./utils");
10
+ 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); }
11
+ 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; }
12
+ 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; }
13
+ describe('Plot', function () {
14
+ var xBand = function xBand() {};
15
+ xBand.bandwidth = function () {};
16
+ var onChange = jest.fn();
17
+ var renderComponent = function renderComponent(extras) {
18
+ var defaults = {
19
+ classes: {},
20
+ className: 'className',
21
+ graphProps: (0, _utils.graphProps)(),
22
+ xBand: xBand,
23
+ onChange: onChange,
24
+ data: [{
25
+ value: 0,
26
+ label: '0'
27
+ }]
28
+ };
29
+ var props = _objectSpread(_objectSpread({}, defaults), extras);
30
+ return (0, _react.render)(/*#__PURE__*/_react2["default"].createElement(_plot["default"], props));
31
+ };
32
+ describe('rendering', function () {
33
+ it('renders without crashing', function () {
34
+ var _renderComponent = renderComponent(),
35
+ container = _renderComponent.container;
36
+ expect(container.firstChild).toBeInTheDocument();
37
+ });
38
+ });
39
+ });
40
+ describe('RawPlot', function () {
41
+ var xBand = function xBand() {};
42
+ xBand.bandwidth = function () {};
43
+ var onChangeCategory = jest.fn();
44
+ var renderComponent = function renderComponent(extras) {
45
+ var defaults = {
46
+ classes: {},
47
+ className: 'className',
48
+ graphProps: (0, _utils.graphProps)(),
49
+ xBand: xBand,
50
+ onChangeCategory: onChangeCategory,
51
+ data: [],
52
+ label: 'label',
53
+ CustomBarElement: function CustomBarElement() {
54
+ return /*#__PURE__*/_react2["default"].createElement("div", null);
55
+ }
56
+ };
57
+ var props = _objectSpread(_objectSpread({}, defaults), extras);
58
+ return (0, _react.render)(/*#__PURE__*/_react2["default"].createElement(_plot.RawPlot, props));
59
+ };
60
+ describe('rendering', function () {
61
+ it('renders without crashing', function () {
62
+ var _renderComponent2 = renderComponent(),
63
+ container = _renderComponent2.container;
64
+ expect(container.firstChild).toBeInTheDocument();
65
+ });
66
+ });
67
+ describe('functionality', function () {
68
+ it('calls onChangeCategory when drag completes with a value', function () {
69
+ var _renderComponent3 = renderComponent(),
70
+ container = _renderComponent3.container;
71
+ // Testing drag functionality requires interaction - the component should
72
+ // call onChangeCategory when a drag operation completes with a new value
73
+ // This would typically be tested through user interactions rather than
74
+ // directly calling instance methods
75
+ expect(container.firstChild).toBeInTheDocument();
76
+ });
77
+ });
78
+ });
79
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJyZXF1aXJlIiwiX3JlYWN0MiIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJfcGxvdCIsIl9pbnRlcm9wUmVxdWlyZVdpbGRjYXJkIiwiX3V0aWxzIiwiZSIsInQiLCJXZWFrTWFwIiwiciIsIm4iLCJfX2VzTW9kdWxlIiwibyIsImkiLCJmIiwiX19wcm90b19fIiwiX3R5cGVvZiIsImhhcyIsImdldCIsInNldCIsIl90IiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJvd25LZXlzIiwia2V5cyIsImdldE93blByb3BlcnR5U3ltYm9scyIsImZpbHRlciIsImVudW1lcmFibGUiLCJwdXNoIiwiYXBwbHkiLCJfb2JqZWN0U3ByZWFkIiwiYXJndW1lbnRzIiwibGVuZ3RoIiwiZm9yRWFjaCIsIl9kZWZpbmVQcm9wZXJ0eTIiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JzIiwiZGVmaW5lUHJvcGVydGllcyIsImRlc2NyaWJlIiwieEJhbmQiLCJiYW5kd2lkdGgiLCJvbkNoYW5nZSIsImplc3QiLCJmbiIsInJlbmRlckNvbXBvbmVudCIsImV4dHJhcyIsImRlZmF1bHRzIiwiY2xhc3NlcyIsImNsYXNzTmFtZSIsImdyYXBoUHJvcHMiLCJkYXRhIiwidmFsdWUiLCJsYWJlbCIsInByb3BzIiwicmVuZGVyIiwiY3JlYXRlRWxlbWVudCIsIml0IiwiX3JlbmRlckNvbXBvbmVudCIsImNvbnRhaW5lciIsImV4cGVjdCIsImZpcnN0Q2hpbGQiLCJ0b0JlSW5UaGVEb2N1bWVudCIsIm9uQ2hhbmdlQ2F0ZWdvcnkiLCJDdXN0b21CYXJFbGVtZW50IiwiUmF3UGxvdCIsIl9yZW5kZXJDb21wb25lbnQyIiwiX3JlbmRlckNvbXBvbmVudDMiXSwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvcGxvdC9jb21tb24vX190ZXN0c19fL3Bsb3QudGVzdC5qc3giXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgcmVuZGVyIH0gZnJvbSAnQHRlc3RpbmctbGlicmFyeS9yZWFjdCc7XG5pbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnO1xuaW1wb3J0IFBsb3QsIHsgUmF3UGxvdCB9IGZyb20gJy4uL3Bsb3QnO1xuaW1wb3J0IHsgZ3JhcGhQcm9wcyB9IGZyb20gJy4vdXRpbHMnO1xuXG5kZXNjcmliZSgnUGxvdCcsICgpID0+IHtcbiAgY29uc3QgeEJhbmQgPSAoKSA9PiB7fTtcbiAgeEJhbmQuYmFuZHdpZHRoID0gKCkgPT4ge307XG4gIGNvbnN0IG9uQ2hhbmdlID0gamVzdC5mbigpO1xuXG4gIGNvbnN0IHJlbmRlckNvbXBvbmVudCA9IChleHRyYXMpID0+IHtcbiAgICBjb25zdCBkZWZhdWx0cyA9IHtcbiAgICAgIGNsYXNzZXM6IHt9LFxuICAgICAgY2xhc3NOYW1lOiAnY2xhc3NOYW1lJyxcbiAgICAgIGdyYXBoUHJvcHM6IGdyYXBoUHJvcHMoKSxcbiAgICAgIHhCYW5kLFxuICAgICAgb25DaGFuZ2UsXG4gICAgICBkYXRhOiBbeyB2YWx1ZTogMCwgbGFiZWw6ICcwJyB9XSxcbiAgICB9O1xuICAgIGNvbnN0IHByb3BzID0geyAuLi5kZWZhdWx0cywgLi4uZXh0cmFzIH07XG4gICAgcmV0dXJuIHJlbmRlcig8UGxvdCB7Li4ucHJvcHN9IC8+KTtcbiAgfTtcblxuICBkZXNjcmliZSgncmVuZGVyaW5nJywgKCkgPT4ge1xuICAgIGl0KCdyZW5kZXJzIHdpdGhvdXQgY3Jhc2hpbmcnLCAoKSA9PiB7XG4gICAgICBjb25zdCB7IGNvbnRhaW5lciB9ID0gcmVuZGVyQ29tcG9uZW50KCk7XG4gICAgICBleHBlY3QoY29udGFpbmVyLmZpcnN0Q2hpbGQpLnRvQmVJblRoZURvY3VtZW50KCk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKCdSYXdQbG90JywgKCkgPT4ge1xuICBjb25zdCB4QmFuZCA9ICgpID0+IHt9O1xuICB4QmFuZC5iYW5kd2lkdGggPSAoKSA9PiB7fTtcbiAgY29uc3Qgb25DaGFuZ2VDYXRlZ29yeSA9IGplc3QuZm4oKTtcblxuICBjb25zdCByZW5kZXJDb21wb25lbnQgPSAoZXh0cmFzKSA9PiB7XG4gICAgY29uc3QgZGVmYXVsdHMgPSB7XG4gICAgICBjbGFzc2VzOiB7fSxcbiAgICAgIGNsYXNzTmFtZTogJ2NsYXNzTmFtZScsXG4gICAgICBncmFwaFByb3BzOiBncmFwaFByb3BzKCksXG4gICAgICB4QmFuZCxcbiAgICAgIG9uQ2hhbmdlQ2F0ZWdvcnksXG4gICAgICBkYXRhOiBbXSxcbiAgICAgIGxhYmVsOiAnbGFiZWwnLFxuICAgICAgQ3VzdG9tQmFyRWxlbWVudDogKCkgPT4gPGRpdiAvPixcbiAgICB9O1xuICAgIGNvbnN0IHByb3BzID0geyAuLi5kZWZhdWx0cywgLi4uZXh0cmFzIH07XG4gICAgcmV0dXJuIHJlbmRlcig8UmF3UGxvdCB7Li4ucHJvcHN9IC8+KTtcbiAgfTtcblxuICBkZXNjcmliZSgncmVuZGVyaW5nJywgKCkgPT4ge1xuICAgIGl0KCdyZW5kZXJzIHdpdGhvdXQgY3Jhc2hpbmcnLCAoKSA9PiB7XG4gICAgICBjb25zdCB7IGNvbnRhaW5lciB9ID0gcmVuZGVyQ29tcG9uZW50KCk7XG4gICAgICBleHBlY3QoY29udGFpbmVyLmZpcnN0Q2hpbGQpLnRvQmVJblRoZURvY3VtZW50KCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdmdW5jdGlvbmFsaXR5JywgKCkgPT4ge1xuICAgIGl0KCdjYWxscyBvbkNoYW5nZUNhdGVnb3J5IHdoZW4gZHJhZyBjb21wbGV0ZXMgd2l0aCBhIHZhbHVlJywgKCkgPT4ge1xuICAgICAgY29uc3QgeyBjb250YWluZXIgfSA9IHJlbmRlckNvbXBvbmVudCgpO1xuICAgICAgLy8gVGVzdGluZyBkcmFnIGZ1bmN0aW9uYWxpdHkgcmVxdWlyZXMgaW50ZXJhY3Rpb24gLSB0aGUgY29tcG9uZW50IHNob3VsZFxuICAgICAgLy8gY2FsbCBvbkNoYW5nZUNhdGVnb3J5IHdoZW4gYSBkcmFnIG9wZXJhdGlvbiBjb21wbGV0ZXMgd2l0aCBhIG5ldyB2YWx1ZVxuICAgICAgLy8gVGhpcyB3b3VsZCB0eXBpY2FsbHkgYmUgdGVzdGVkIHRocm91Z2ggdXNlciBpbnRlcmFjdGlvbnMgcmF0aGVyIHRoYW5cbiAgICAgIC8vIGRpcmVjdGx5IGNhbGxpbmcgaW5zdGFuY2UgbWV0aG9kc1xuICAgICAgZXhwZWN0KGNvbnRhaW5lci5maXJzdENoaWxkKS50b0JlSW5UaGVEb2N1bWVudCgpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl0sIm1hcHBpbmdzIjoiOzs7OztBQUFBLElBQUFBLE1BQUEsR0FBQUMsT0FBQTtBQUNBLElBQUFDLE9BQUEsR0FBQUMsc0JBQUEsQ0FBQUYsT0FBQTtBQUNBLElBQUFHLEtBQUEsR0FBQUMsdUJBQUEsQ0FBQUosT0FBQTtBQUNBLElBQUFLLE1BQUEsR0FBQUwsT0FBQTtBQUFxQyxTQUFBSSx3QkFBQUUsQ0FBQSxFQUFBQyxDQUFBLDZCQUFBQyxPQUFBLE1BQUFDLENBQUEsT0FBQUQsT0FBQSxJQUFBRSxDQUFBLE9BQUFGLE9BQUEsWUFBQUosdUJBQUEsWUFBQUEsd0JBQUFFLENBQUEsRUFBQUMsQ0FBQSxTQUFBQSxDQUFBLElBQUFELENBQUEsSUFBQUEsQ0FBQSxDQUFBSyxVQUFBLFNBQUFMLENBQUEsTUFBQU0sQ0FBQSxFQUFBQyxDQUFBLEVBQUFDLENBQUEsS0FBQUMsU0FBQSxtQkFBQVQsQ0FBQSxpQkFBQUEsQ0FBQSxnQkFBQVUsT0FBQSxDQUFBVixDQUFBLDBCQUFBQSxDQUFBLFNBQUFRLENBQUEsTUFBQUYsQ0FBQSxHQUFBTCxDQUFBLEdBQUFHLENBQUEsR0FBQUQsQ0FBQSxRQUFBRyxDQUFBLENBQUFLLEdBQUEsQ0FBQVgsQ0FBQSxVQUFBTSxDQUFBLENBQUFNLEdBQUEsQ0FBQVosQ0FBQSxHQUFBTSxDQUFBLENBQUFPLEdBQUEsQ0FBQWIsQ0FBQSxFQUFBUSxDQUFBLGNBQUFNLEVBQUEsSUFBQWQsQ0FBQSxnQkFBQWMsRUFBQSxPQUFBQyxj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
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.scaleMock = exports.graphProps = void 0;
7
+ var scaleMock = exports.scaleMock = function scaleMock() {
8
+ var fn = jest.fn(function (n) {
9
+ return n;
10
+ });
11
+ fn.invert = jest.fn(function (n) {
12
+ return n;
13
+ });
14
+ return fn;
15
+ };
16
+ var graphProps = exports.graphProps = function graphProps() {
17
+ var dmin = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
18
+ var dmax = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
19
+ var rmin = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
20
+ var rmax = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1;
21
+ return {
22
+ scale: {
23
+ x: scaleMock(),
24
+ y: scaleMock()
25
+ },
26
+ snap: {
27
+ x: jest.fn(function (n) {
28
+ return n;
29
+ }),
30
+ y: jest.fn(function (n) {
31
+ return n;
32
+ })
33
+ },
34
+ domain: {
35
+ min: dmin,
36
+ max: dmax,
37
+ step: 1
38
+ },
39
+ range: {
40
+ min: rmin,
41
+ max: rmax,
42
+ step: 1
43
+ },
44
+ size: {
45
+ width: 400,
46
+ height: 400
47
+ }
48
+ };
49
+ };
50
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJzY2FsZU1vY2siLCJleHBvcnRzIiwiZm4iLCJqZXN0IiwibiIsImludmVydCIsImdyYXBoUHJvcHMiLCJkbWluIiwiYXJndW1lbnRzIiwibGVuZ3RoIiwidW5kZWZpbmVkIiwiZG1heCIsInJtaW4iLCJybWF4Iiwic2NhbGUiLCJ4IiwieSIsInNuYXAiLCJkb21haW4iLCJtaW4iLCJtYXgiLCJzdGVwIiwicmFuZ2UiLCJzaXplIiwid2lkdGgiLCJoZWlnaHQiXSwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvcGxvdC9jb21tb24vX190ZXN0c19fL3V0aWxzLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBjb25zdCBzY2FsZU1vY2sgPSAoKSA9PiB7XG4gIGNvbnN0IGZuID0gamVzdC5mbigobikgPT4gbik7XG4gIGZuLmludmVydCA9IGplc3QuZm4oKG4pID0+IG4pO1xuICByZXR1cm4gZm47XG59O1xuXG5leHBvcnQgY29uc3QgZ3JhcGhQcm9wcyA9IChkbWluID0gMCwgZG1heCA9IDEsIHJtaW4gPSAwLCBybWF4ID0gMSkgPT4gKHtcbiAgc2NhbGU6IHtcbiAgICB4OiBzY2FsZU1vY2soKSxcbiAgICB5OiBzY2FsZU1vY2soKSxcbiAgfSxcbiAgc25hcDoge1xuICAgIHg6IGplc3QuZm4oKG4pID0+IG4pLFxuICAgIHk6IGplc3QuZm4oKG4pID0+IG4pLFxuICB9LFxuICBkb21haW46IHtcbiAgICBtaW46IGRtaW4sXG4gICAgbWF4OiBkbWF4LFxuICAgIHN0ZXA6IDEsXG4gIH0sXG4gIHJhbmdlOiB7XG4gICAgbWluOiBybWluLFxuICAgIG1heDogcm1heCxcbiAgICBzdGVwOiAxLFxuICB9LFxuICBzaXplOiB7XG4gICAgd2lkdGg6IDQwMCxcbiAgICBoZWlnaHQ6IDQwMCxcbiAgfSxcbn0pO1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBTyxJQUFNQSxTQUFTLEdBQUFDLE9BQUEsQ0FBQUQsU0FBQSxHQUFHLFNBQVpBLFNBQVNBLENBQUEsRUFBUztFQUM3QixJQUFNRSxFQUFFLEdBQUdDLElBQUksQ0FBQ0QsRUFBRSxDQUFDLFVBQUNFLENBQUM7SUFBQSxPQUFLQSxDQUFDO0VBQUEsRUFBQztFQUM1QkYsRUFBRSxDQUFDRyxNQUFNLEdBQUdGLElBQUksQ0FBQ0QsRUFBRSxDQUFDLFVBQUNFLENBQUM7SUFBQSxPQUFLQSxDQUFDO0VBQUEsRUFBQztFQUM3QixPQUFPRixFQUFFO0FBQ1gsQ0FBQztBQUVNLElBQU1JLFVBQVUsR0FBQUwsT0FBQSxDQUFBSyxVQUFBLEdBQUcsU0FBYkEsVUFBVUEsQ0FBQTtFQUFBLElBQUlDLElBQUksR0FBQUMsU0FBQSxDQUFBQyxNQUFBLFFBQUFELFNBQUEsUUFBQUUsU0FBQSxHQUFBRixTQUFBLE1BQUcsQ0FBQztFQUFBLElBQUVHLElBQUksR0FBQUgsU0FBQSxDQUFBQyxNQUFBLFFBQUFELFNBQUEsUUFBQUUsU0FBQSxHQUFBRixTQUFBLE1BQUcsQ0FBQztFQUFBLElBQUVJLElBQUksR0FBQUosU0FBQSxDQUFBQyxNQUFBLFFBQUFELFNBQUEsUUFBQUUsU0FBQSxHQUFBRixTQUFBLE1BQUcsQ0FBQztFQUFBLElBQUVLLElBQUksR0FBQUwsU0FBQSxDQUFBQyxNQUFBLFFBQUFELFNBQUEsUUFBQUUsU0FBQSxHQUFBRixTQUFBLE1BQUcsQ0FBQztFQUFBLE9BQU07SUFDckVNLEtBQUssRUFBRTtNQUNMQyxDQUFDLEVBQUVmLFNBQVMsQ0FBQyxDQUFDO01BQ2RnQixDQUFDLEVBQUVoQixTQUFTLENBQUM7SUFDZixDQUFDO0lBQ0RpQixJQUFJLEVBQUU7TUFDSkYsQ0FBQyxFQUFFWixJQUFJLENBQUNELEVBQUUsQ0FBQyxVQUFDRSxDQUFDO1FBQUEsT0FBS0EsQ0FBQztNQUFBLEVBQUM7TUFDcEJZLENBQUMsRUFBRWIsSUFBSSxDQUFDRCxFQUFFLENBQUMsVUFBQ0UsQ0FBQztRQUFBLE9BQUtBLENBQUM7TUFBQTtJQUNyQixDQUFDO0lBQ0RjLE1BQU0sRUFBRTtNQUNOQyxHQUFHLEVBQUVaLElBQUk7TUFDVGEsR0FBRyxFQUFFVCxJQUFJO01BQ1RVLElBQUksRUFBRTtJQUNSLENBQUM7SUFDREMsS0FBSyxFQUFFO01BQ0xILEdBQUcsRUFBRVAsSUFBSTtNQUNUUSxHQUFHLEVBQUVQLElBQUk7TUFDVFEsSUFBSSxFQUFFO0lBQ1IsQ0FBQztJQUNERSxJQUFJLEVBQUU7TUFDSkMsS0FBSyxFQUFFLEdBQUc7TUFDVkMsTUFBTSxFQUFFO0lBQ1Y7RUFDRixDQUFDO0FBQUEsQ0FBQyIsImlnbm9yZUxpc3QiOltdfQ==
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "7.0.22-beta.6",
6
+ "version": "7.0.22-beta.8",
7
7
  "description": "charting",
8
8
  "keywords": [
9
9
  "react",
@@ -23,7 +23,7 @@
23
23
  "@mui/icons-material": "^7.3.4",
24
24
  "@mui/material": "^7.3.4",
25
25
  "@pie-lib/math-rendering": "^5.0.2",
26
- "@pie-lib/plot": "^4.0.22-beta.6",
26
+ "@pie-lib/plot": "^4.0.22-beta.8",
27
27
  "@pie-lib/render-ui": "^6.1.0",
28
28
  "@pie-lib/translator": "^4.0.2",
29
29
  "@visx/axis": "^3.0.0",
@@ -0,0 +1,280 @@
1
+ import React from 'react';
2
+ import { fireEvent, render } from '@testing-library/react';
3
+ import { createTheme, ThemeProvider } from '@mui/material/styles';
4
+ import { ActionsButton } from '../actions-button';
5
+
6
+ jest.mock('@pie-lib/translator', () => ({
7
+ __esModule: true,
8
+ default: {
9
+ translator: {
10
+ t: jest.fn((key) => {
11
+ const translations = {
12
+ 'charting.add': 'Add Category',
13
+ 'charting.delete': 'Delete',
14
+ 'charting.newLabel': 'New Category',
15
+ };
16
+ return translations[key] || key;
17
+ }),
18
+ },
19
+ },
20
+ }));
21
+
22
+ let theme;
23
+
24
+ beforeAll(() => {
25
+ theme = createTheme();
26
+ });
27
+
28
+ describe('ActionsButton', () => {
29
+ const addCategory = jest.fn();
30
+ const deleteCategory = jest.fn();
31
+
32
+ beforeEach(() => {
33
+ jest.clearAllMocks();
34
+ });
35
+
36
+ const renderComponent = (extras = {}) => {
37
+ const defaults = {
38
+ addCategory,
39
+ deleteCategory,
40
+ categories: [],
41
+ language: 'en',
42
+ };
43
+ const props = { ...defaults, ...extras };
44
+ return render(
45
+ <ThemeProvider theme={theme}>
46
+ <ActionsButton {...props} />
47
+ </ThemeProvider>,
48
+ );
49
+ };
50
+
51
+ describe('rendering', () => {
52
+ it('renders without crashing', () => {
53
+ const { container } = renderComponent();
54
+ expect(container).toBeInTheDocument();
55
+ });
56
+
57
+ it('renders Actions button', () => {
58
+ const { getByText } = renderComponent();
59
+ expect(getByText('Actions')).toBeInTheDocument();
60
+ });
61
+
62
+ it('renders with custom language', () => {
63
+ const { container } = renderComponent({ language: 'es' });
64
+ expect(container).toBeInTheDocument();
65
+ });
66
+
67
+ it('renders with empty categories', () => {
68
+ const { container } = renderComponent({ categories: [] });
69
+ expect(container).toBeInTheDocument();
70
+ });
71
+
72
+ it('renders with multiple categories', () => {
73
+ const categories = [
74
+ { label: 'A', deletable: true },
75
+ { label: 'B', deletable: true },
76
+ { label: 'C', deletable: false },
77
+ ];
78
+ const { container } = renderComponent({ categories });
79
+ expect(container).toBeInTheDocument();
80
+ });
81
+ });
82
+
83
+ describe('popover interactions', () => {
84
+ it('opens popover when Actions button is clicked', () => {
85
+ const { getByText } = renderComponent();
86
+ const actionsButton = getByText('Actions');
87
+
88
+ fireEvent.click(actionsButton);
89
+
90
+ expect(getByText(/Add Category/i)).toBeInTheDocument();
91
+ });
92
+
93
+ it('closes popover when clicking outside', () => {
94
+ const { getByText } = renderComponent();
95
+ const actionsButton = getByText('Actions');
96
+
97
+ fireEvent.click(actionsButton);
98
+ expect(getByText(/Add Category/i)).toBeInTheDocument();
99
+
100
+ const backdrop = document.querySelector('.MuiPopover-root');
101
+ if (backdrop) {
102
+ fireEvent.click(backdrop);
103
+ }
104
+ });
105
+
106
+ it('has correct accessibility attributes', () => {
107
+ const { getByText } = renderComponent();
108
+ const actionsButton = getByText('Actions');
109
+
110
+ expect(actionsButton).toHaveAttribute('role', 'button');
111
+ expect(actionsButton).toHaveAttribute('tabIndex', '0');
112
+ });
113
+ });
114
+
115
+ describe('add category functionality', () => {
116
+ it('calls addCategory when add button is clicked', () => {
117
+ const { getByText } = renderComponent();
118
+
119
+ fireEvent.click(getByText('Actions'));
120
+ fireEvent.click(getByText(/Add Category/i));
121
+
122
+ expect(addCategory).toHaveBeenCalledTimes(1);
123
+ });
124
+
125
+ it('closes popover after adding category', () => {
126
+ const { getByText } = renderComponent();
127
+
128
+ fireEvent.click(getByText('Actions'));
129
+ fireEvent.click(getByText(/Add Category/i));
130
+
131
+ expect(addCategory).toHaveBeenCalled();
132
+ });
133
+ });
134
+
135
+ describe('delete category functionality', () => {
136
+ it('shows delete buttons for deletable categories', () => {
137
+ const categories = [
138
+ { label: 'Category A', deletable: true },
139
+ { label: 'Category B', deletable: true },
140
+ ];
141
+ const { getByText } = renderComponent({ categories });
142
+
143
+ fireEvent.click(getByText('Actions'));
144
+
145
+ expect(getByText(/Delete <Category A>/i)).toBeInTheDocument();
146
+ expect(getByText(/Delete <Category B>/i)).toBeInTheDocument();
147
+ });
148
+
149
+ it('does not show delete button for non-deletable categories', () => {
150
+ const categories = [{ label: 'Category A', deletable: false }];
151
+ const { getByText, queryByText } = renderComponent({ categories });
152
+
153
+ fireEvent.click(getByText('Actions'));
154
+
155
+ expect(queryByText(/Delete <Category A>/i)).not.toBeInTheDocument();
156
+ });
157
+
158
+ it('does not show delete button for categories with correctness', () => {
159
+ const categories = [{ label: 'Category A', deletable: true, correctness: { value: 'correct' } }];
160
+ const { getByText, queryByText } = renderComponent({ categories });
161
+
162
+ fireEvent.click(getByText('Actions'));
163
+
164
+ expect(queryByText(/Delete <Category A>/i)).not.toBeInTheDocument();
165
+ });
166
+
167
+ it('calls deleteCategory with correct index', () => {
168
+ const categories = [
169
+ { label: 'Category A', deletable: true },
170
+ { label: 'Category B', deletable: true },
171
+ ];
172
+ const { getByText } = renderComponent({ categories });
173
+
174
+ fireEvent.click(getByText('Actions'));
175
+ fireEvent.click(getByText(/Delete <Category B>/i));
176
+
177
+ expect(deleteCategory).toHaveBeenCalledWith(1);
178
+ });
179
+
180
+ it('closes popover after deleting category', () => {
181
+ const categories = [{ label: 'Category A', deletable: true }];
182
+ const { getByText } = renderComponent({ categories });
183
+
184
+ fireEvent.click(getByText('Actions'));
185
+ fireEvent.click(getByText(/Delete <Category A>/i));
186
+
187
+ expect(deleteCategory).toHaveBeenCalled();
188
+ });
189
+
190
+ it('shows "New Category" for categories without label', () => {
191
+ const categories = [{ label: '', deletable: true }];
192
+ const { getByText } = renderComponent({ categories });
193
+
194
+ fireEvent.click(getByText('Actions'));
195
+
196
+ expect(getByText(/Delete <New Category>/i)).toBeInTheDocument();
197
+ });
198
+
199
+ it('handles deletion of multiple categories', () => {
200
+ const categories = [
201
+ { label: 'A', deletable: true },
202
+ { label: 'B', deletable: true },
203
+ { label: 'C', deletable: true },
204
+ ];
205
+ const { getByText } = renderComponent({ categories });
206
+
207
+ fireEvent.click(getByText('Actions'));
208
+
209
+ expect(getByText(/Delete <A>/i)).toBeInTheDocument();
210
+ expect(getByText(/Delete <B>/i)).toBeInTheDocument();
211
+ expect(getByText(/Delete <C>/i)).toBeInTheDocument();
212
+ });
213
+ });
214
+
215
+ describe('componentWillUnmount', () => {
216
+ it('cleans up state on unmount', () => {
217
+ const { unmount, getByText } = renderComponent();
218
+
219
+ fireEvent.click(getByText('Actions'));
220
+ unmount();
221
+
222
+ // Should not throw error
223
+ expect(true).toBe(true);
224
+ });
225
+ });
226
+
227
+ describe('edge cases', () => {
228
+ it('handles empty categories array', () => {
229
+ const { container } = renderComponent({ categories: [] });
230
+ expect(container).toBeInTheDocument();
231
+ });
232
+
233
+ it('handles undefined language', () => {
234
+ const { container } = renderComponent({ language: undefined });
235
+ expect(container).toBeInTheDocument();
236
+ });
237
+
238
+ it('handles mixed deletable and correctness states', () => {
239
+ const categories = [
240
+ { label: 'A', deletable: true },
241
+ { label: 'B', deletable: false },
242
+ { label: 'C', deletable: true, correctness: { value: 'correct' } },
243
+ { label: 'D', deletable: true },
244
+ ];
245
+ const { getByText } = renderComponent({ categories });
246
+
247
+ fireEvent.click(getByText('Actions'));
248
+
249
+ expect(getByText(/Delete <A>/i)).toBeInTheDocument();
250
+ expect(getByText(/Delete <D>/i)).toBeInTheDocument();
251
+ });
252
+
253
+ it('handles categories with special characters in labels', () => {
254
+ const categories = [{ label: '<>&"\'', deletable: true }];
255
+ const { getByText } = renderComponent({ categories });
256
+
257
+ fireEvent.click(getByText('Actions'));
258
+
259
+ expect(getByText(/Delete </i)).toBeInTheDocument();
260
+ });
261
+
262
+ it('handles very long category labels', () => {
263
+ const categories = [{ label: 'A'.repeat(100), deletable: true }];
264
+ const { container } = renderComponent({ categories });
265
+ expect(container).toBeInTheDocument();
266
+ });
267
+ });
268
+
269
+ describe('popover positioning', () => {
270
+ it('has correct anchor origin', () => {
271
+ const { getByText, queryByText } = renderComponent();
272
+
273
+ expect(queryByText(/\+ Add Category/i)).not.toBeInTheDocument();
274
+
275
+ fireEvent.click(getByText('Actions'));
276
+
277
+ expect(getByText(/\+ Add Category/i)).toBeInTheDocument();
278
+ });
279
+ });
280
+ });